toolkit/mozapps/extensions/amInstallTrigger.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 "use strict";
michael@0 6
michael@0 7 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
michael@0 8
michael@0 9 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 10 Cu.import("resource://gre/modules/Services.jsm");
michael@0 11 Cu.import("resource://gre/modules/Preferences.jsm");
michael@0 12 Cu.import("resource://gre/modules/Log.jsm");
michael@0 13
michael@0 14 const XPINSTALL_MIMETYPE = "application/x-xpinstall";
michael@0 15
michael@0 16 const MSG_INSTALL_ENABLED = "WebInstallerIsInstallEnabled";
michael@0 17 const MSG_INSTALL_ADDONS = "WebInstallerInstallAddonsFromWebpage";
michael@0 18 const MSG_INSTALL_CALLBACK = "WebInstallerInstallCallback";
michael@0 19
michael@0 20
michael@0 21 let log = Log.repository.getLogger("AddonManager.InstallTrigger");
michael@0 22 log.level = Log.Level[Preferences.get("extensions.logging.enabled", false) ? "Warn" : "Trace"];
michael@0 23
michael@0 24 function CallbackObject(id, callback, urls, mediator) {
michael@0 25 this.id = id;
michael@0 26 this.callback = callback;
michael@0 27 this.urls = new Set(urls);
michael@0 28 this.callCallback = function(url, status) {
michael@0 29 try {
michael@0 30 this.callback(url, status);
michael@0 31 }
michael@0 32 catch (e) {
michael@0 33 log.warn("InstallTrigger callback threw an exception: " + e);
michael@0 34 }
michael@0 35
michael@0 36 this.urls.delete(url);
michael@0 37 if (this.urls.size == 0)
michael@0 38 mediator._callbacks.delete(id);
michael@0 39 };
michael@0 40 }
michael@0 41
michael@0 42 function RemoteMediator(windowID) {
michael@0 43 this._windowID = windowID;
michael@0 44 this._lastCallbackID = 0;
michael@0 45 this._callbacks = new Map();
michael@0 46 this.mm = Cc["@mozilla.org/childprocessmessagemanager;1"]
michael@0 47 .getService(Ci.nsISyncMessageSender);
michael@0 48 this.mm.addWeakMessageListener(MSG_INSTALL_CALLBACK, this);
michael@0 49 }
michael@0 50
michael@0 51 RemoteMediator.prototype = {
michael@0 52 receiveMessage: function(message) {
michael@0 53 if (message.name == MSG_INSTALL_CALLBACK) {
michael@0 54 let payload = message.data;
michael@0 55 let callbackHandler = this._callbacks.get(payload.callbackID);
michael@0 56 if (callbackHandler) {
michael@0 57 callbackHandler.callCallback(payload.url, payload.status);
michael@0 58 }
michael@0 59 }
michael@0 60 },
michael@0 61
michael@0 62 enabled: function(url) {
michael@0 63 let params = {
michael@0 64 referer: url,
michael@0 65 mimetype: XPINSTALL_MIMETYPE
michael@0 66 };
michael@0 67 return this.mm.sendSyncMessage(MSG_INSTALL_ENABLED, params)[0];
michael@0 68 },
michael@0 69
michael@0 70 install: function(installs, referer, callback, window) {
michael@0 71 let callbackID = this._addCallback(callback, installs.uris);
michael@0 72
michael@0 73 installs.mimetype = XPINSTALL_MIMETYPE;
michael@0 74 installs.referer = referer;
michael@0 75 installs.callbackID = callbackID;
michael@0 76
michael@0 77 return this.mm.sendSyncMessage(MSG_INSTALL_ADDONS, installs, {win: window})[0];
michael@0 78 },
michael@0 79
michael@0 80 _addCallback: function(callback, urls) {
michael@0 81 if (!callback || typeof callback != "function")
michael@0 82 return -1;
michael@0 83
michael@0 84 let callbackID = this._windowID + "-" + ++this._lastCallbackID;
michael@0 85 let callbackObject = new CallbackObject(callbackID, callback, urls, this);
michael@0 86 this._callbacks.set(callbackID, callbackObject);
michael@0 87 return callbackID;
michael@0 88 },
michael@0 89
michael@0 90 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference])
michael@0 91 };
michael@0 92
michael@0 93
michael@0 94 function InstallTrigger() {
michael@0 95 }
michael@0 96
michael@0 97 InstallTrigger.prototype = {
michael@0 98 // Here be magic. We've declared ourselves as providing the
michael@0 99 // nsIDOMGlobalPropertyInitializer interface, and are registered in the
michael@0 100 // "JavaScript-global-property" category in the XPCOM category manager. This
michael@0 101 // means that for newly created windows, XPCOM will createinstance this
michael@0 102 // object, and then call init, passing in the window for which we need to
michael@0 103 // provide an instance. We then initialize ourselves and return the webidl
michael@0 104 // version of this object using the webidl-provided _create method, which
michael@0 105 // XPCOM will then duly expose as a property value on the window. All this
michael@0 106 // indirection is necessary because webidl does not (yet) support statics
michael@0 107 // (bug 863952). See bug 926712 for more details about this implementation.
michael@0 108 init: function(window) {
michael@0 109 this._window = window;
michael@0 110 this._principal = window.document.nodePrincipal;
michael@0 111 this._url = window.document.documentURIObject;
michael@0 112
michael@0 113 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
michael@0 114 let utils = window.getInterface(Components.interfaces.nsIDOMWindowUtils);
michael@0 115 this._mediator = new RemoteMediator(utils.currentInnerWindowID);
michael@0 116
michael@0 117 return window.InstallTriggerImpl._create(window, this);
michael@0 118 },
michael@0 119
michael@0 120 enabled: function() {
michael@0 121 return this._mediator.enabled(this._url.spec);
michael@0 122 },
michael@0 123
michael@0 124 updateEnabled: function() {
michael@0 125 return this.enabled();
michael@0 126 },
michael@0 127
michael@0 128 install: function(installs, callback) {
michael@0 129 let installData = {
michael@0 130 uris: [],
michael@0 131 hashes: [],
michael@0 132 names: [],
michael@0 133 icons: [],
michael@0 134 };
michael@0 135
michael@0 136 for (let name of Object.keys(installs)) {
michael@0 137 let item = installs[name];
michael@0 138 if (typeof item === "string") {
michael@0 139 item = { URL: item };
michael@0 140 }
michael@0 141 if (!item.URL) {
michael@0 142 throw new this._window.DOMError("Error", "Missing URL property for '" + name + "'");
michael@0 143 }
michael@0 144
michael@0 145 let url = this._resolveURL(item.URL);
michael@0 146 if (!this._checkLoadURIFromScript(url)) {
michael@0 147 throw new this._window.DOMError("SecurityError", "Insufficient permissions to install: " + url.spec);
michael@0 148 }
michael@0 149
michael@0 150 let iconUrl = null;
michael@0 151 if (item.IconURL) {
michael@0 152 iconUrl = this._resolveURL(item.IconURL);
michael@0 153 if (!this._checkLoadURIFromScript(iconUrl)) {
michael@0 154 iconUrl = null; // If page can't load the icon, just ignore it
michael@0 155 }
michael@0 156 }
michael@0 157
michael@0 158 installData.uris.push(url.spec);
michael@0 159 installData.hashes.push(item.Hash || null);
michael@0 160 installData.names.push(name);
michael@0 161 installData.icons.push(iconUrl ? iconUrl.spec : null);
michael@0 162 }
michael@0 163
michael@0 164 return this._mediator.install(installData, this._url.spec, callback, this._window);
michael@0 165 },
michael@0 166
michael@0 167 startSoftwareUpdate: function(url, flags) {
michael@0 168 let filename = Services.io.newURI(url, null, null)
michael@0 169 .QueryInterface(Ci.nsIURL)
michael@0 170 .filename;
michael@0 171 let args = {};
michael@0 172 args[filename] = { "URL": url };
michael@0 173 return this.install(args);
michael@0 174 },
michael@0 175
michael@0 176 installChrome: function(type, url, skin) {
michael@0 177 return this.startSoftwareUpdate(url);
michael@0 178 },
michael@0 179
michael@0 180 _resolveURL: function (url) {
michael@0 181 return Services.io.newURI(url, null, this._url);
michael@0 182 },
michael@0 183
michael@0 184 _checkLoadURIFromScript: function(uri) {
michael@0 185 let secman = Services.scriptSecurityManager;
michael@0 186 try {
michael@0 187 secman.checkLoadURIWithPrincipal(this._principal,
michael@0 188 uri,
michael@0 189 secman.DISALLOW_INHERIT_PRINCIPAL);
michael@0 190 return true;
michael@0 191 }
michael@0 192 catch(e) {
michael@0 193 return false;
michael@0 194 }
michael@0 195 },
michael@0 196
michael@0 197 classID: Components.ID("{9df8ef2b-94da-45c9-ab9f-132eb55fddf1}"),
michael@0 198 contractID: "@mozilla.org/addons/installtrigger;1",
michael@0 199 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIDOMGlobalPropertyInitializer])
michael@0 200 };
michael@0 201
michael@0 202
michael@0 203
michael@0 204 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([InstallTrigger]);

mercurial