Manage your own custom protocol

Many software vendors define their own schemes for use in URLs, along with their own protocols for handling URLs containing those schemes.
With a custom scheme, vendors can create URLs that invoke their software when an end-user accesses that URL via a web browser or the operating system.

Starting with RVM v12 and Runtime v34, providers of OpenFin application platforms can define custom schemes and register protocol handlers for their applications, so that the OpenFin environment can appropriately invoke the right application for a URL containing a custom scheme.

📘

Note

The custom protocol feature is supported only on Microsoft Windows.

Because of the sensitivity of invoking applications, the ability to register a custom protocol is protected by OpenFin's API security mechanism.
As with any secured API, the following controls are in place:

  • The application provider must declare in the application manifest that it is using methods related to custom protocols.

  • The desktop owner can specify whether to allow use of the custom protocol methods in desktop owner settings.

  • If the desktop owner does not define a permission for a custom protocol method, the end-user is shown a dialog box and can choose to block or allow it.

In addition to the normal controls for secured APIs, the desktop owner settings can also specify custom protocol schemes to block or allow.

Disallowed schemes

The following schemes cannot be registered by an application provider:

  • fin, fins, or openfin, which are reserved by OpenFin

  • Any scheme that is in the URI scheme registry maintained by the Internet Assigned Number Authority (IANA), including both "Permanent" and "Provisional" schemes.

Application providers

There are several steps that an application provider must take in order to register and use a custom protocol in OpenFin.

  • Select a scheme name, avoiding the disallowed schemes.
    If you have implemented the protocol handler for use with a web browser, it might already have a scheme name.
    OpenFin requires that protocol names contain only ASCII alphanumeric characters, dashes, "-", and underscores, "_".

  • If URLs that use your scheme might contain a URL parameter, make sure that your application can handle that parameter; for a custom protocol, anything after the colon in the URL is considered the URL parameter.

  • Add code to your application to register, unregister, and check the state of your custom protocol.

  • In the application manifest, declare your use of methods related to custom protocols and, optionally, the protocols you want to register.

Methods for custom protocols

The methods related to custom protocols are the following:

  • System.registerCustomProtocol registers the specified scheme with the operating system.

  • System.unregisterCustomProtocol removes the entry for the protocol name from the registry.

  • System.getCustomProtocolState returns an object that indicates the state of the protocol.
    This method is useful for determining whether the scheme you want to register is already registered by another application.
    The return value can be one of the following:

    • If the scheme is not registered, the registration state object contains: "state": "Missing".

    • If the scheme is registered, the registration state object contains: "state": "Registered" along with "handlerManifestUrl": "HANDLER_APP_MANIFEST.json" where HANDLER_APP_MANIFEST.json is the location of the app manifest for the application that registered the scheme.

    • If a registry value exists but does not contain data in the expected format, the registration state object contains: "state": "Malformed"

Note that if you don't unregister your protocol, it remains registered, even for future instances of the RVM and your application.
Thus, OpenFin can start your application to handle a link containing your custom protocol, even when your application is not running.
It is unregistered only by explicitly calling System.unregisterCustomProtocol or by removing the application.
(Refer to Removal of a custom protocol handler application.)

Declare custom protocol methods in the application manifest

Because the custom protocol methods are secured APIs, in order to use these methods in your application, you need to add them to the "permissions" object in your application manifest.
You can either declare them with either a Boolean value, which enables the method for all protocols, or with an object that defines specific protocols that you will use.
As with other secured APIs, the location of the "permissions" object depends on the type of application: "platform" for apps that use the Platform API, or "startup_app" for those that don't.

For example, the following are settings for a platform app using a simple Boolean declaration:

/* top-level settings ... */
"platform": {
  /* other platform settings ... */
  "permissions": {
      /* other secured API namespaces ... */
      "System": {
       /* other secured System methods ... */
       "registerCustomProtocol": true,
       "unregisterCustomProtocol": true,
       "getCustomProtocolState": true
    },
  /* other platform settings ... */ 
  }
}

This example shows the settings for a non-platform app, with an object for each method:


/* top-level settings ... */
"startup_app": {
  /* other startup_app settings ... */
  "permissions": {
    /* other secured API namespaces ... */
    "System": {
      /* other secured System methods ... */
      "registerCustomProtocol": {
        "enabled": true,
        "protocols": [
          "PROTOCOL1",
          "PROTOCOL2"
          ]
      },
      "unregisterCustomProtocol": {
        "enabled": true,
        "protocols": [
          "PROTOCOL1",
          "PROTOCOL2"
        ]
      },
      "getCustomProtocolState": {
        "enabled": true,
        "protocols": [
          "PROTOCOL1",
          "PROTOCOL2",
          "PROTOCOL3",
          "PROTOCOL4"
        ]
      },
    },
  },
  /* Other startup_app settings ... */ 
}

Handle the URL parameter

When your application is invoked by the RVM with a custom protocol URL, it needs to handle the URL parameter, that is, the part of the URL that is not the scheme.
This is a similar situation to when an application is invoked using the fin or fins protocols with a URL parameter.
There are two cases where an application can be invoked, and it needs to handle both of them:

  • When the application is first launched, the initial parameters are available via the initialOptions property of the object returned by Application.getInfo.

  • When the application is invoked when it is already running, the userAppConfigArgs property on the Application.RunRequestedEvent contains the parameter.

The following example shows how to access the URL parameters in both these cases.

// utility function to get the custom URL parameter (minus the scheme name)
function getParam(args) {
    return args.userAppConfigArgs.userRequestUri;
}

...

const finApp = fin.Application.getCurrentSync();

// App is already running when a run-requested event type occurs
finApp.on('run-requested', data => {
  console.log(`[run-requested] ${this.getParam(data)}`);
  });

...

// When app is first started, URL parameter is in initialOptions
const info = await finApp.getInfo();
console.log(`[start] ${this.getParam(info.initialOptions)}`);

...

Desktop owners and end-users

While the application manifest declares the methods and protocols that an application provider would like to use, the desktop owner has ultimate control over what methods and protocols are allowed to be used.
If the desktop owner does not define controls, then the end-user is prompted for whether to allow them.

Desktop owner settings

The desktop owner can control access to the protocol-related methods in the usual way for secured APIs.
In addition, the desktop owner can define protocols that are allowed or blocked from being registered on a system.

A top-level object, customProtocols, in the desktop owner settings, contains lists of blocked or allowed protocols. For example:

  • If allowList is defined, only protocols that are included in this list are allowed; any others are rejected.

  • If denyList is defined, any protocols that are included in this list are rejected.

  • If both properties are defined, only protocols included in allowList are allowed, except that protocols that are also in denyList are rejected.

End-user permission dialog box

In cases where an application declares its intention to use secured APIs, and the desktop owner application security settings do not exist or do not address those APIs, then a Review security permissions dialog is presented to the end user, requesting permission to use the APIs.
This is the standard dialog box used for all secured APIs.
It lists the APIs requested, but does not mention the requested protocol scheme or schemes.

How protocol registration works in the operating system

The System.registerCustomProtocol() method registers the specified scheme with the operating system.
In the Windows Registry, it creates a sub-key under HKEY_CURRENT_USER/Software/Classes. The name of the sub-key is based on the scheme of the protocol.

Example

Suppose you have an OpenFin-based application whose application manifest is provided at https://EXAMPLE.com/APP_NAME.json.
You want to define a custom protocol with the scheme PROTOCOL1, which invokes your OpenFin application.

Register the protocol

To register the protocol, you make the following call in the code for the application:

fin.System.registerCustomProtocol({protocolName:'PROTOCOL1'});

A sub-key called Software/Classes/PROTOCOL1 is created in Windows Registry, with a sub-key under it called /shell/open/command.
The "default" value of this key contains data that is the command to run the RVM, invoking your application's manifest, and passing the URL parameter (if any).
For the example, the default value's data is created as the following:

"C:\Users\USER\AppData\Local\OpenFin\OpenFinRVM.exe" "--config=https://EXAMPLE.com/APP_NAME.json" "--user-request-uri=%1"

The application manifest referenced is the manifest for the application that calls registerCustomProtocol.
The value of the parameter --user-request-uri is whatever follows the colon in the custom protocol URL.

User clicks a custom protocol URL

Suppose a user clicks on the following URL:
PROTOCOL1://ARG1=SOME DATA & ARG2=SOME OTHER DATA

Note that a colon (:) separates the scheme from the rest of the URL.
Double-slashes (//) after the colon are conventional, but not required.
In OpenFin's implementation, the entire URL is passed as the URL parameter.

While a URL is technically required to be URL encoded to contain only certain ASCII characters, the encoding and decoding is handled either at the operating system level or by the RVM.

🚧 Caution
Because "%1" is used in the registry data for a custom protocol handler, URLs containing a custom scheme cannot contain the (unencoded) string "%1".

The command line that is invoked, as a result of looking up the custom scheme in the registry, is the following:

"C:\Users\USER\AppData\Local\OpenFin\OpenFinRVM.exe" "--config=https://EXAMPLE.com/APP_NAME.json" --user-request-uri=PROTOCOL1://ARG1=SOME DATA & ARG2=SOME OTHER DATA"

The application can handle the URL parameter as described above.
The value of the RVM's --user-request-uri parameter is exposed as userAppConfigArgs.userRequestUri.

Removal of a protocol handler application

When an application is removed by calling the RVM with the --remove-app option, any protocols registered by that application are automatically unregistered, as long as they are still in the Registered state. If another application has attempted to register the same protocol, it is set to the Malformed state, and therefore is not removed when the application that originally registered it is removed.