summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/parent/ext-protocolHandlers.js
blob: 099e193f0f9257f8a7f78e17e2c49b5cade279dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

XPCOMUtils.defineLazyServiceGetter(
  this,
  "handlerService",
  "@mozilla.org/uriloader/handler-service;1",
  "nsIHandlerService"
);
XPCOMUtils.defineLazyServiceGetter(
  this,
  "protocolService",
  "@mozilla.org/uriloader/external-protocol-service;1",
  "nsIExternalProtocolService"
);

const hasHandlerApp = handlerConfig => {
  let protoInfo = protocolService.getProtocolHandlerInfo(
    handlerConfig.protocol
  );
  let appHandlers = protoInfo.possibleApplicationHandlers;
  for (let i = 0; i < appHandlers.length; i++) {
    let handler = appHandlers.queryElementAt(i, Ci.nsISupports);
    if (
      handler instanceof Ci.nsIWebHandlerApp &&
      handler.uriTemplate === handlerConfig.uriTemplate
    ) {
      return true;
    }
  }
  return false;
};

this.protocolHandlers = class extends ExtensionAPI {
  onManifestEntry() {
    let { extension } = this;
    let { manifest } = extension;

    for (let handlerConfig of manifest.protocol_handlers) {
      if (hasHandlerApp(handlerConfig)) {
        continue;
      }

      let handler = Cc[
        "@mozilla.org/uriloader/web-handler-app;1"
      ].createInstance(Ci.nsIWebHandlerApp);
      handler.name = handlerConfig.name;
      handler.uriTemplate = handlerConfig.uriTemplate;

      let protoInfo = protocolService.getProtocolHandlerInfo(
        handlerConfig.protocol
      );
      let handlers = protoInfo.possibleApplicationHandlers;
      if (protoInfo.preferredApplicationHandler || handlers.length) {
        protoInfo.alwaysAskBeforeHandling = true;
      } else {
        protoInfo.preferredApplicationHandler = handler;
        protoInfo.alwaysAskBeforeHandling = false;
      }
      handlers.appendElement(handler);
      handlerService.store(protoInfo);
    }
  }

  onShutdown(isAppShutdown) {
    let { extension } = this;
    let { manifest } = extension;

    if (isAppShutdown) {
      return;
    }

    for (let handlerConfig of manifest.protocol_handlers) {
      let protoInfo = protocolService.getProtocolHandlerInfo(
        handlerConfig.protocol
      );
      let appHandlers = protoInfo.possibleApplicationHandlers;
      for (let i = 0; i < appHandlers.length; i++) {
        let handler = appHandlers.queryElementAt(i, Ci.nsISupports);
        if (
          handler instanceof Ci.nsIWebHandlerApp &&
          handler.uriTemplate === handlerConfig.uriTemplate
        ) {
          appHandlers.removeElementAt(i);
          if (protoInfo.preferredApplicationHandler === handler) {
            protoInfo.preferredApplicationHandler = null;
            protoInfo.alwaysAskBeforeHandling = true;
          }
          handlerService.store(protoInfo);
          break;
        }
      }
    }
  }
};