mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 10:18:41 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			177 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 | 
						|
/* 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/. */
 | 
						|
 | 
						|
const STRING_BUNDLE_URI = "chrome://browser/locale/feeds/subscribe.properties";
 | 
						|
 | 
						|
export function WebProtocolHandlerRegistrar() {}
 | 
						|
 | 
						|
WebProtocolHandlerRegistrar.prototype = {
 | 
						|
  get stringBundle() {
 | 
						|
    let sb = Services.strings.createBundle(STRING_BUNDLE_URI);
 | 
						|
    delete WebProtocolHandlerRegistrar.prototype.stringBundle;
 | 
						|
    return (WebProtocolHandlerRegistrar.prototype.stringBundle = sb);
 | 
						|
  },
 | 
						|
 | 
						|
  _getFormattedString(key, params) {
 | 
						|
    return this.stringBundle.formatStringFromName(key, params);
 | 
						|
  },
 | 
						|
 | 
						|
  _getString(key) {
 | 
						|
    return this.stringBundle.GetStringFromName(key);
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * See nsIWebProtocolHandlerRegistrar
 | 
						|
   */
 | 
						|
  removeProtocolHandler(aProtocol, aURITemplate) {
 | 
						|
    let eps = Cc[
 | 
						|
      "@mozilla.org/uriloader/external-protocol-service;1"
 | 
						|
    ].getService(Ci.nsIExternalProtocolService);
 | 
						|
    let handlerInfo = eps.getProtocolHandlerInfo(aProtocol);
 | 
						|
    let handlers = handlerInfo.possibleApplicationHandlers;
 | 
						|
    for (let i = 0; i < handlers.length; i++) {
 | 
						|
      try {
 | 
						|
        // We only want to test web handlers
 | 
						|
        let handler = handlers.queryElementAt(i, Ci.nsIWebHandlerApp);
 | 
						|
        if (handler.uriTemplate == aURITemplate) {
 | 
						|
          handlers.removeElementAt(i);
 | 
						|
          let hs = Cc["@mozilla.org/uriloader/handler-service;1"].getService(
 | 
						|
            Ci.nsIHandlerService
 | 
						|
          );
 | 
						|
          hs.store(handlerInfo);
 | 
						|
          return;
 | 
						|
        }
 | 
						|
      } catch (e) {
 | 
						|
        /* it wasn't a web handler */
 | 
						|
      }
 | 
						|
    }
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * Determines if a web handler is already registered.
 | 
						|
   *
 | 
						|
   * @param aProtocol
 | 
						|
   *        The scheme of the web handler we are checking for.
 | 
						|
   * @param aURITemplate
 | 
						|
   *        The URI template that the handler uses to handle the protocol.
 | 
						|
   * @return true if it is already registered, false otherwise.
 | 
						|
   */
 | 
						|
  _protocolHandlerRegistered(aProtocol, aURITemplate) {
 | 
						|
    let eps = Cc[
 | 
						|
      "@mozilla.org/uriloader/external-protocol-service;1"
 | 
						|
    ].getService(Ci.nsIExternalProtocolService);
 | 
						|
    let handlerInfo = eps.getProtocolHandlerInfo(aProtocol);
 | 
						|
    let handlers = handlerInfo.possibleApplicationHandlers;
 | 
						|
    for (let i = 0; i < handlers.length; i++) {
 | 
						|
      try {
 | 
						|
        // We only want to test web handlers
 | 
						|
        let handler = handlers.queryElementAt(i, Ci.nsIWebHandlerApp);
 | 
						|
        if (handler.uriTemplate == aURITemplate) {
 | 
						|
          return true;
 | 
						|
        }
 | 
						|
      } catch (e) {
 | 
						|
        /* it wasn't a web handler */
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * See nsIWebProtocolHandlerRegistrar
 | 
						|
   */
 | 
						|
  registerProtocolHandler(
 | 
						|
    aProtocol,
 | 
						|
    aURI,
 | 
						|
    aTitle,
 | 
						|
    aDocumentURI,
 | 
						|
    aBrowserOrWindow
 | 
						|
  ) {
 | 
						|
    aProtocol = (aProtocol || "").toLowerCase();
 | 
						|
    if (!aURI || !aDocumentURI) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    let browser = aBrowserOrWindow; // This is the e10s case.
 | 
						|
    if (aBrowserOrWindow instanceof Ci.nsIDOMWindow) {
 | 
						|
      // In the non-e10s case, grab the browser off the same-process window.
 | 
						|
      let rootDocShell = aBrowserOrWindow.docShell.sameTypeRootTreeItem;
 | 
						|
      browser = rootDocShell.QueryInterface(Ci.nsIDocShell).chromeEventHandler;
 | 
						|
    }
 | 
						|
 | 
						|
    let browserWindow = browser.ownerGlobal;
 | 
						|
    try {
 | 
						|
      browserWindow.navigator.checkProtocolHandlerAllowed(
 | 
						|
        aProtocol,
 | 
						|
        aURI,
 | 
						|
        aDocumentURI
 | 
						|
      );
 | 
						|
    } catch (ex) {
 | 
						|
      // We should have already shown the user an error.
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    // If the protocol handler is already registered, just return early.
 | 
						|
    if (this._protocolHandlerRegistered(aProtocol, aURI.spec)) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    // Now Ask the user and provide the proper callback
 | 
						|
    let message = this._getFormattedString("addProtocolHandlerMessage", [
 | 
						|
      aURI.host,
 | 
						|
      aProtocol,
 | 
						|
    ]);
 | 
						|
 | 
						|
    let notificationIcon = aURI.prePath + "/favicon.ico";
 | 
						|
    let notificationValue = "Protocol Registration: " + aProtocol;
 | 
						|
    let addButton = {
 | 
						|
      label: this._getString("addProtocolHandlerAddButton"),
 | 
						|
      accessKey: this._getString("addProtocolHandlerAddButtonAccesskey"),
 | 
						|
      protocolInfo: { protocol: aProtocol, uri: aURI.spec, name: aTitle },
 | 
						|
 | 
						|
      callback(aNotification, aButtonInfo) {
 | 
						|
        let protocol = aButtonInfo.protocolInfo.protocol;
 | 
						|
        let name = aButtonInfo.protocolInfo.name;
 | 
						|
 | 
						|
        let handler = Cc[
 | 
						|
          "@mozilla.org/uriloader/web-handler-app;1"
 | 
						|
        ].createInstance(Ci.nsIWebHandlerApp);
 | 
						|
        handler.name = name;
 | 
						|
        handler.uriTemplate = aButtonInfo.protocolInfo.uri;
 | 
						|
 | 
						|
        let eps = Cc[
 | 
						|
          "@mozilla.org/uriloader/external-protocol-service;1"
 | 
						|
        ].getService(Ci.nsIExternalProtocolService);
 | 
						|
        let handlerInfo = eps.getProtocolHandlerInfo(protocol);
 | 
						|
        handlerInfo.possibleApplicationHandlers.appendElement(handler);
 | 
						|
 | 
						|
        // Since the user has agreed to add a new handler, chances are good
 | 
						|
        // that the next time they see a handler of this type, they're going
 | 
						|
        // to want to use it.  Reset the handlerInfo to ask before the next
 | 
						|
        // use.
 | 
						|
        handlerInfo.alwaysAskBeforeHandling = true;
 | 
						|
 | 
						|
        let hs = Cc["@mozilla.org/uriloader/handler-service;1"].getService(
 | 
						|
          Ci.nsIHandlerService
 | 
						|
        );
 | 
						|
        hs.store(handlerInfo);
 | 
						|
      },
 | 
						|
    };
 | 
						|
    let notificationBox = browser.getTabBrowser().getNotificationBox(browser);
 | 
						|
    notificationBox.appendNotification(
 | 
						|
      notificationValue,
 | 
						|
      {
 | 
						|
        label: message,
 | 
						|
        image: notificationIcon,
 | 
						|
        priority: notificationBox.PRIORITY_INFO_LOW,
 | 
						|
      },
 | 
						|
      [addButton]
 | 
						|
    );
 | 
						|
  },
 | 
						|
 | 
						|
  /**
 | 
						|
   * See nsISupports
 | 
						|
   */
 | 
						|
  QueryInterface: ChromeUtils.generateQI(["nsIWebProtocolHandlerRegistrar"]),
 | 
						|
};
 |