/ src / protocol-handler-installer.js
protocol-handler-installer.js
  1  const { remote } = require('electron');
  2  
  3  const SETTING = 'core.uriHandlerRegistration';
  4  const PROMPT = 'prompt';
  5  const ALWAYS = 'always';
  6  const NEVER = 'never';
  7  
  8  module.exports = class ProtocolHandlerInstaller {
  9    isSupported() {
 10      return ['win32', 'darwin'].includes(process.platform);
 11    }
 12  
 13    isDefaultProtocolClient() {
 14      return remote.app.isDefaultProtocolClient('atom', process.execPath, [
 15        '--uri-handler',
 16        '--'
 17      ]);
 18    }
 19  
 20    setAsDefaultProtocolClient() {
 21      // This Electron API is only available on Windows and macOS. There might be some
 22      // hacks to make it work on Linux; see https://github.com/electron/electron/issues/6440
 23      return (
 24        this.isSupported() &&
 25        remote.app.setAsDefaultProtocolClient('atom', process.execPath, [
 26          '--uri-handler',
 27          '--'
 28        ])
 29      );
 30    }
 31  
 32    initialize(config, notifications) {
 33      if (!this.isSupported()) {
 34        return;
 35      }
 36  
 37      const behaviorWhenNotProtocolClient = config.get(SETTING);
 38      switch (behaviorWhenNotProtocolClient) {
 39        case PROMPT:
 40          if (!this.isDefaultProtocolClient()) {
 41            this.promptToBecomeProtocolClient(config, notifications);
 42          }
 43          break;
 44        case ALWAYS:
 45          if (!this.isDefaultProtocolClient()) {
 46            this.setAsDefaultProtocolClient();
 47          }
 48          break;
 49        case NEVER:
 50          if (process.platform === 'win32') {
 51            // Only win32 supports deregistration
 52            const Registry = require('winreg');
 53            const commandKey = new Registry({ hive: 'HKCR', key: `\\atom` });
 54            commandKey.destroy((_err, _val) => {
 55              /* no op */
 56            });
 57          }
 58          break;
 59        default:
 60        // Do nothing
 61      }
 62    }
 63  
 64    promptToBecomeProtocolClient(config, notifications) {
 65      let notification;
 66  
 67      const withSetting = (value, fn) => {
 68        return function() {
 69          config.set(SETTING, value);
 70          fn();
 71        };
 72      };
 73  
 74      const accept = () => {
 75        notification.dismiss();
 76        this.setAsDefaultProtocolClient();
 77      };
 78      const decline = () => {
 79        notification.dismiss();
 80      };
 81  
 82      notification = notifications.addInfo(
 83        'Register as default atom:// URI handler?',
 84        {
 85          dismissable: true,
 86          icon: 'link',
 87          description:
 88            'Atom is not currently set as the default handler for atom:// URIs. Would you like Atom to handle ' +
 89            'atom:// URIs?',
 90          buttons: [
 91            {
 92              text: 'Yes',
 93              className: 'btn btn-info btn-primary',
 94              onDidClick: accept
 95            },
 96            {
 97              text: 'Yes, Always',
 98              className: 'btn btn-info',
 99              onDidClick: withSetting(ALWAYS, accept)
100            },
101            {
102              text: 'No',
103              className: 'btn btn-info',
104              onDidClick: decline
105            },
106            {
107              text: 'No, Never',
108              className: 'btn btn-info',
109              onDidClick: withSetting(NEVER, decline)
110            }
111          ]
112        }
113      );
114    }
115  };