1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/mozapps/extensions/addonManager.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,214 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/** 1.9 + * This component serves as integration between the platform and AddonManager. 1.10 + * It is responsible for initializing and shutting down the AddonManager as well 1.11 + * as passing new installs from webpages to the AddonManager. 1.12 + */ 1.13 + 1.14 +"use strict"; 1.15 + 1.16 +const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; 1.17 + 1.18 +const PREF_EM_UPDATE_INTERVAL = "extensions.update.interval"; 1.19 + 1.20 +// The old XPInstall error codes 1.21 +const EXECUTION_ERROR = -203; 1.22 +const CANT_READ_ARCHIVE = -207; 1.23 +const USER_CANCELLED = -210; 1.24 +const DOWNLOAD_ERROR = -228; 1.25 +const UNSUPPORTED_TYPE = -244; 1.26 +const SUCCESS = 0; 1.27 + 1.28 +const MSG_INSTALL_ENABLED = "WebInstallerIsInstallEnabled"; 1.29 +const MSG_INSTALL_ADDONS = "WebInstallerInstallAddonsFromWebpage"; 1.30 +const MSG_INSTALL_CALLBACK = "WebInstallerInstallCallback"; 1.31 + 1.32 +const CHILD_SCRIPT = "resource://gre/modules/addons/Content.js"; 1.33 + 1.34 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.35 +Cu.import("resource://gre/modules/Services.jsm"); 1.36 + 1.37 +let gSingleton = null; 1.38 + 1.39 +let gParentMM = null; 1.40 + 1.41 + 1.42 +function amManager() { 1.43 + Cu.import("resource://gre/modules/AddonManager.jsm"); 1.44 + 1.45 + let globalMM = Cc["@mozilla.org/globalmessagemanager;1"] 1.46 + .getService(Ci.nsIMessageListenerManager); 1.47 + globalMM.loadFrameScript(CHILD_SCRIPT, true); 1.48 + 1.49 + gParentMM = Cc["@mozilla.org/parentprocessmessagemanager;1"] 1.50 + .getService(Ci.nsIMessageListenerManager); 1.51 + gParentMM.addMessageListener(MSG_INSTALL_ENABLED, this); 1.52 + gParentMM.addMessageListener(MSG_INSTALL_ADDONS, this); 1.53 +} 1.54 + 1.55 +amManager.prototype = { 1.56 + observe: function AMC_observe(aSubject, aTopic, aData) { 1.57 + if (aTopic == "addons-startup") 1.58 + AddonManagerPrivate.startup(); 1.59 + }, 1.60 + 1.61 + /** 1.62 + * @see amIAddonManager.idl 1.63 + */ 1.64 + mapURIToAddonID: function AMC_mapURIToAddonID(uri, id) { 1.65 + id.value = AddonManager.mapURIToAddonID(uri); 1.66 + return !!id.value; 1.67 + }, 1.68 + 1.69 + /** 1.70 + * @see amIWebInstaller.idl 1.71 + */ 1.72 + isInstallEnabled: function AMC_isInstallEnabled(aMimetype, aReferer) { 1.73 + return AddonManager.isInstallEnabled(aMimetype); 1.74 + }, 1.75 + 1.76 + /** 1.77 + * @see amIWebInstaller.idl 1.78 + */ 1.79 + installAddonsFromWebpage: function AMC_installAddonsFromWebpage(aMimetype, 1.80 + aWindow, 1.81 + aReferer, aUris, 1.82 + aHashes, aNames, 1.83 + aIcons, aCallback) { 1.84 + if (aUris.length == 0) 1.85 + return false; 1.86 + 1.87 + let retval = true; 1.88 + if (!AddonManager.isInstallAllowed(aMimetype, aReferer)) { 1.89 + aCallback = null; 1.90 + retval = false; 1.91 + } 1.92 + 1.93 + let loadGroup = null; 1.94 + 1.95 + try { 1.96 + loadGroup = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) 1.97 + .getInterface(Ci.nsIWebNavigation) 1.98 + .QueryInterface(Ci.nsIDocumentLoader).loadGroup; 1.99 + } 1.100 + catch (e) { 1.101 + } 1.102 + 1.103 + let installs = []; 1.104 + function buildNextInstall() { 1.105 + if (aUris.length == 0) { 1.106 + AddonManager.installAddonsFromWebpage(aMimetype, aWindow, aReferer, installs); 1.107 + return; 1.108 + } 1.109 + let uri = aUris.shift(); 1.110 + AddonManager.getInstallForURL(uri, function buildNextInstall_getInstallForURL(aInstall) { 1.111 + function callCallback(aUri, aStatus) { 1.112 + try { 1.113 + aCallback.onInstallEnded(aUri, aStatus); 1.114 + } 1.115 + catch (e) { 1.116 + Components.utils.reportError(e); 1.117 + } 1.118 + } 1.119 + 1.120 + if (aInstall) { 1.121 + installs.push(aInstall); 1.122 + if (aCallback) { 1.123 + aInstall.addListener({ 1.124 + onDownloadCancelled: function buildNextInstall_onDownloadCancelled(aInstall) { 1.125 + callCallback(uri, USER_CANCELLED); 1.126 + }, 1.127 + 1.128 + onDownloadFailed: function buildNextInstall_onDownloadFailed(aInstall) { 1.129 + if (aInstall.error == AddonManager.ERROR_CORRUPT_FILE) 1.130 + callCallback(uri, CANT_READ_ARCHIVE); 1.131 + else 1.132 + callCallback(uri, DOWNLOAD_ERROR); 1.133 + }, 1.134 + 1.135 + onInstallFailed: function buildNextInstall_onInstallFailed(aInstall) { 1.136 + callCallback(uri, EXECUTION_ERROR); 1.137 + }, 1.138 + 1.139 + onInstallEnded: function buildNextInstall_onInstallEnded(aInstall, aStatus) { 1.140 + callCallback(uri, SUCCESS); 1.141 + } 1.142 + }); 1.143 + } 1.144 + } 1.145 + else if (aCallback) { 1.146 + aCallback.onInstallEnded(uri, UNSUPPORTED_TYPE); 1.147 + } 1.148 + buildNextInstall(); 1.149 + }, aMimetype, aHashes.shift(), aNames.shift(), aIcons.shift(), null, loadGroup); 1.150 + } 1.151 + buildNextInstall(); 1.152 + 1.153 + return retval; 1.154 + }, 1.155 + 1.156 + notify: function AMC_notify(aTimer) { 1.157 + AddonManagerPrivate.backgroundUpdateCheck(); 1.158 + }, 1.159 + 1.160 + /** 1.161 + * messageManager callback function. 1.162 + * 1.163 + * Listens to requests from child processes for InstallTrigger 1.164 + * activity, and sends back callbacks. 1.165 + */ 1.166 + receiveMessage: function AMC_receiveMessage(aMessage) { 1.167 + let payload = aMessage.data; 1.168 + let referer = Services.io.newURI(payload.referer, null, null); 1.169 + 1.170 + switch (aMessage.name) { 1.171 + case MSG_INSTALL_ENABLED: 1.172 + return this.isInstallEnabled(payload.mimetype, referer); 1.173 + 1.174 + case MSG_INSTALL_ADDONS: 1.175 + let callback = null; 1.176 + if (payload.callbackID != -1) { 1.177 + callback = { 1.178 + onInstallEnded: function ITP_callback(url, status) { 1.179 + gParentMM.broadcastAsyncMessage(MSG_INSTALL_CALLBACK, { 1.180 + callbackID: payload.callbackID, 1.181 + url: url, 1.182 + status: status 1.183 + }); 1.184 + }, 1.185 + }; 1.186 + } 1.187 + 1.188 + // Should reimplement this properly with Window IDs when possible, 1.189 + // see bug 596109. 1.190 + let window = aMessage.objects.win; 1.191 + 1.192 + return this.installAddonsFromWebpage(payload.mimetype, 1.193 + window, referer, payload.uris, payload.hashes, payload.names, 1.194 + payload.icons, callback); 1.195 + } 1.196 + }, 1.197 + 1.198 + classID: Components.ID("{4399533d-08d1-458c-a87a-235f74451cfa}"), 1.199 + _xpcom_factory: { 1.200 + createInstance: function AMC_createInstance(aOuter, aIid) { 1.201 + if (aOuter != null) 1.202 + throw Components.Exception("Component does not support aggregation", 1.203 + Cr.NS_ERROR_NO_AGGREGATION); 1.204 + 1.205 + if (!gSingleton) 1.206 + gSingleton = new amManager(); 1.207 + return gSingleton.QueryInterface(aIid); 1.208 + } 1.209 + }, 1.210 + QueryInterface: XPCOMUtils.generateQI([Ci.amIAddonManager, 1.211 + Ci.amIWebInstaller, 1.212 + Ci.nsITimerCallback, 1.213 + Ci.nsIObserver, 1.214 + Ci.nsIMessageListener]) 1.215 +}; 1.216 + 1.217 +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([amManager]);