Does electron's registerHttpProtocol work in development?

Viewed 738

I'm trying to register a custom protocol with electron. I want it to be a redirect location that a website can use to provide an api key (like myprotocol://example/payload=api-key). I have been using electron's registerHttpProtocol and also tried electron's interceptHttpProtocol.

But, when the website tries to redirect to my protocol my electron app doesn't do anything. The website goes to myprotocol://example/payload=api-key, and registers a "page doesn't exist error"--while nothing happens in my app.

This is in a development environment. I've seen some discussion about custom protocols that assume a production environment.

Can you register a custom protocol with electron in development?

Why am I not able to intercept the website's going to the protocol I've set out?

Here's my code:

main.js:

app.whenReady().then(() => {
  protocol.registerHttpProtocol('examplep', (request, callback) => {
     console.log("examplep", request);
     callback('it-worked');
  }, (error) => {
        if (error) console.error('Failed to register protocol = ' + error)
  })

  protocol.interceptHttpProtocol("examplep", function (request, callback) {  //I've tried both registerHttp... and interceptHttp... methods, so including both here; though I think in practice only one should be required
    console.log('intercepted!' + request)
    callback(request);
  });
})

redirect url provided to website:

'http://examplep'

And I've whitelisted this url on the website itself.

I've also tried related methods registerStringProtocol, interceptStringProtocol, registerFileProtocol, and interceptFileProtocol, without success.


What am I missing?

1 Answers

Sounds like you need to support deep linking fora desktop app, which is done via a Custom URI Scheme and is registered with setAsDefaultProtocolClient.

When your Electron app starts up write this code to register the scheme, on the main side of your app:

const customScheme = 'x-mycompany-myapp';
app.setAsDefaultProtocolClient(customScheme);

The custom scheme can be tested from the command line like this, depending whether you are running macOS or Windows:

open  x-mycompany-myapp:/some/location
start x-mycompany-myapp:/some/location

A web client will just invoke a URL as in this Javascript code of mine;

The notification will be received within the main side of your app and on Windows will attempt to create a new instance of the app, in which case you need to detect this condition, process the notification then cancel the new app instance.

On MacOS it will be received within the open-url event, so you register it like this:

app.on('open-url', this._onOpenUrl);

Once the main side of the Electron app has the notification, it needs to get the URL information and forward it to the renderer process. You can use ipcMain events for this.

Finally the code for receiving the notification in running instances and starting the app from a deep link are different.

EXAMPLE APP

Since the code is a little tricky, here is some example code that may be useful, to give you something to compare against. If it helps you can also run the app by following the instructions in the blog post:

My use case is around receiving OAuth responses after signing in from the system browser. Hopefully you can borrow some ideas from it related to deep linking though.

INFO.PLIST

My understand is that in a development environment (on macOS) deep links work when the app is running, but if you stop the app and attempt a deep link it will not start the app.

You can only resolve this for a packaged app, which requires an info.plist. In my code sample the info.plist is generated from build protocol entries in the package.json file.

My code sample is packaged in a basic way by the Electron Packager, so when I run npm run pack, the app is built to a dist folder. I can then run the packaged version of the app and it gets registered with the system - as can be seen in the Default Apps tool. See screenshots in the blog post.

SECRETS

Secrets for a desktop app should be stored using operating system secure storage. There are screenshots of credential storage in the blog post.

On Electron, have a look at the keytar component - and this wrapper class of mine. I am storing tokens (strings) so you should be able to adapt the code for your API keys.

Related