diff options
Diffstat (limited to 'toolkit/mozapps/extensions/AddonManager.jsm')
-rw-r--r-- | toolkit/mozapps/extensions/AddonManager.jsm | 1220 |
1 files changed, 286 insertions, 934 deletions
diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm index c5cb80091..681c4240a 100644 --- a/toolkit/mozapps/extensions/AddonManager.jsm +++ b/toolkit/mozapps/extensions/AddonManager.jsm @@ -21,9 +21,6 @@ if ("@mozilla.org/xre/app-info;1" in Cc) { } } -Cu.import("resource://gre/modules/AppConstants.jsm"); - -const MOZ_COMPATIBILITY_NIGHTLY = !['aurora', 'beta', 'release', 'esr'].includes(AppConstants.MOZ_UPDATE_CHANNEL); const PREF_BLOCKLIST_PINGCOUNTVERSION = "extensions.blocklist.pingCountVersion"; const PREF_DEFAULT_PROVIDERS_ENABLED = "extensions.defaultProviders.enabled"; @@ -36,18 +33,10 @@ const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity"; const PREF_EM_UPDATE_BACKGROUND_URL = "extensions.update.background.url"; const PREF_APP_UPDATE_ENABLED = "app.update.enabled"; const PREF_APP_UPDATE_AUTO = "app.update.auto"; -const PREF_EM_HOTFIX_ID = "extensions.hotfix.id"; -const PREF_EM_HOTFIX_LASTVERSION = "extensions.hotfix.lastVersion"; -const PREF_EM_HOTFIX_URL = "extensions.hotfix.url"; -const PREF_EM_CERT_CHECKATTRIBUTES = "extensions.hotfix.cert.checkAttributes"; -const PREF_EM_HOTFIX_CERTS = "extensions.hotfix.certs."; const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS"; const PREF_SELECTED_LOCALE = "general.useragent.locale"; const UNKNOWN_XPCOM_ABI = "unknownABI"; -const PREF_MIN_WEBEXT_PLATFORM_VERSION = "extensions.webExtensionsMinPlatformVersion"; -const PREF_WEBAPI_TESTING = "extensions.webapi.testing"; - const UPDATE_REQUEST_VERSION = 2; const CATEGORY_UPDATE_PARAMS = "extension-update-params"; @@ -59,21 +48,12 @@ const FILE_BLOCKLIST = "blocklist.xml"; const BRANCH_REGEXP = /^([^\.]+\.[0-9]+[a-z]*).*/gi; const PREF_EM_CHECK_COMPATIBILITY_BASE = "extensions.checkCompatibility"; -var PREF_EM_CHECK_COMPATIBILITY = MOZ_COMPATIBILITY_NIGHTLY ? - PREF_EM_CHECK_COMPATIBILITY_BASE + ".nightly" : - undefined; +var PREF_EM_CHECK_COMPATIBILITY; const TOOLKIT_ID = "toolkit@mozilla.org"; const VALID_TYPES_REGEXP = /^[\w\-]+$/; -const WEBAPI_INSTALL_HOSTS = ["addons.mozilla.org", "testpilot.firefox.com"]; -const WEBAPI_TEST_INSTALL_HOSTS = [ - "addons.allizom.org", "addons-dev.allizom.org", - "testpilot.stage.mozaws.net", "testpilot.dev.mozaws.net", - "example.com", -]; - Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/AsyncShutdown.jsm"); @@ -84,18 +64,15 @@ XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository", "resource://gre/modules/addons/AddonRepository.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Extension", - "resource://gre/modules/Extension.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm"); -XPCOMUtils.defineLazyGetter(this, "CertUtils", function() { +XPCOMUtils.defineLazyGetter(this, "CertUtils", function certUtilsLazyGetter() { let certUtils = {}; Components.utils.import("resource://gre/modules/CertUtils.jsm", certUtils); return certUtils; }); -const INTEGER = /^[1-9]\d*$/; this.EXPORTED_SYMBOLS = [ "AddonManager", "AddonManagerPrivate" ]; @@ -111,9 +88,9 @@ Cu.import("resource://gre/modules/Log.jsm"); // Configure a logger at the parent 'addons' level to format // messages for all the modules under addons.* const PARENT_LOGGER_ID = "addons"; -var parentLogger = Log.repository.getLogger(PARENT_LOGGER_ID); +let parentLogger = Log.repository.getLogger(PARENT_LOGGER_ID); parentLogger.level = Log.Level.Warn; -var formatter = new Log.BasicFormatter(); +let formatter = new Log.BasicFormatter(); // Set parent logger (and its children) to append to // the Javascript section of the Browser Console parentLogger.addAppender(new Log.ConsoleAppender(formatter)); @@ -124,7 +101,7 @@ parentLogger.addAppender(new Log.DumpAppender(formatter)); // Create a new logger (child of 'addons' logger) // for use by the Addons Manager const LOGGER_ID = "addons.manager"; -var logger = Log.repository.getLogger(LOGGER_ID); +let logger = Log.repository.getLogger(LOGGER_ID); // Provide the ability to enable/disable logging // messages at runtime. @@ -147,13 +124,13 @@ function providerName(aProvider) { * parent 'addons' level logger accordingly. */ var PrefObserver = { - init: function() { + init: function PrefObserver_init() { Services.prefs.addObserver(PREF_LOGGING_ENABLED, this, false); Services.obs.addObserver(this, "xpcom-shutdown", false); this.observe(null, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, PREF_LOGGING_ENABLED); }, - observe: function(aSubject, aTopic, aData) { + observe: function PrefObserver_observe(aSubject, aTopic, aData) { if (aTopic == "xpcom-shutdown") { Services.prefs.removeObserver(PREF_LOGGING_ENABLED, this); Services.obs.removeObserver(this, "xpcom-shutdown"); @@ -194,19 +171,6 @@ function safeCall(aCallback, ...aArgs) { } /** - * Creates a function that will call the passed callback catching and logging - * any exceptions. - * - * @param aCallback - * The callback method to call - */ -function makeSafe(aCallback) { - return function(...aArgs) { - safeCall(aCallback, ...aArgs); - } -} - -/** * Report an exception thrown by a provider API method. */ function reportProviderError(aProvider, aMethod, aError) { @@ -258,7 +222,7 @@ function callProviderAsync(aProvider, aMethod, ...aArgs) { let callback = aArgs[aArgs.length - 1]; if (!(aMethod in aProvider)) { callback(undefined); - return undefined; + return; } try { return aProvider[aMethod].apply(aProvider, aArgs); @@ -266,31 +230,11 @@ function callProviderAsync(aProvider, aMethod, ...aArgs) { catch (e) { reportProviderError(aProvider, aMethod, e); callback(undefined); - return undefined; + return; } } /** - * Calls a method on a provider if it exists and consumes any thrown exception. - * Parameters after aMethod are passed to aProvider.aMethod() and an additional - * callback is added for the provider to return a result to. - * - * @param aProvider - * The provider to call - * @param aMethod - * The method name to call - * @return {Promise} - * @resolves The result the provider returns, or |undefined| if the provider - * does not implement the method or the method throws. - * @rejects Never - */ -function promiseCallProvider(aProvider, aMethod, ...aArgs) { - return new Promise(resolve => { - callProviderAsync(aProvider, aMethod, ...aArgs, resolve); - }); -} - -/** * Gets the currently selected locale for display. * @return the selected locale or "en-US" if none is selected */ @@ -317,28 +261,35 @@ function getLocale() { return "en-US"; } -function webAPIForAddon(addon) { - if (!addon) { - return null; - } +/** + * Previously the APIs for installing add-ons from webpages accepted nsIURI + * arguments for the installing page. They now take an nsIPrincipal but for now + * maintain backwards compatibility by converting an nsIURI to an nsIPrincipal. + * + * @param aPrincipalOrURI + * The argument passed to the API function. Can be null, an nsIURI or + * an nsIPrincipal. + * @return an nsIPrincipal. + */ +function ensurePrincipal(principalOrURI) { + if (principalOrURI instanceof Ci.nsIPrincipal) + return principalOrURI; - let result = {}; + logger.warn("Deprecated API call, please pass a non-null nsIPrincipal instead of an nsIURI"); - // By default just pass through any plain property, the webidl will - // control access. Also filter out private properties, regular Addon - // objects are okay but MockAddon used in tests has non-serializable - // private properties. - for (let prop in addon) { - if (prop[0] != "_" && typeof(addon[prop]) != "function") { - result[prop] = addon[prop]; - } + // Previously a null installing URI meant allowing the install regardless. + if (!principalOrURI) { + return Services.scriptSecurityManager.getSystemPrincipal(); } - // A few properties are computed for a nicer API - result.isEnabled = !addon.userDisabled; - result.canUninstall = Boolean(addon.permissions & AddonManager.PERM_CAN_UNINSTALL); + if (principalOrURI instanceof Ci.nsIURI) { + return Services.scriptSecurityManager.createCodebasePrincipal(principalOrURI, { + inBrowser: true + }); + } - return result; + // Just return whatever we have, the API method will log an error about it. + return principalOrURI; } /** @@ -373,7 +324,7 @@ AsyncObjectCaller.prototype = { * Passes the next object to the listener or calls noMoreObjects if there * are none left. */ - callNext: function() { + callNext: function AOC_callNext() { if (this.objects.length == 0) { this.listener.noMoreObjects(this); return; @@ -398,7 +349,7 @@ function BrowserListener(aBrowser, aInstallingPrincipal, aInstalls) { this.installCount = aInstalls.length; aBrowser.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_LOCATION); - Services.obs.addObserver(this, "message-manager-close", true); + Services.obs.addObserver(this, "message-manager-disconnect", true); for (let install of this.installs) install.addListener(this); @@ -417,7 +368,7 @@ BrowserListener.prototype = { return; this.registered = false; - Services.obs.removeObserver(this, "message-manager-close"); + Services.obs.removeObserver(this, "message-manager-disconnect"); // The browser may have already been detached if (this.browser.removeProgressListener) this.browser.removeProgressListener(this); @@ -499,7 +450,7 @@ AddonAuthor.prototype = { url: null, // Returns the author's name, defaulting to the empty string - toString: function() { + toString: function AddonAuthor_toString() { return this.name || ""; } } @@ -543,7 +494,7 @@ AddonScreenshot.prototype = { caption: null, // Returns the screenshot URL, defaulting to the empty string - toString: function() { + toString: function AddonScreenshot_toString() { return this.url || ""; } } @@ -649,9 +600,11 @@ function AddonType(aID, aLocaleURI, aLocaleKey, aViewType, aUIPriority, aFlags) this.flags = aFlags; if (aLocaleURI) { - XPCOMUtils.defineLazyGetter(this, "name", () => { + this.__defineGetter__("name", function nameGetter() { + delete this.name; let bundle = Services.strings.createBundle(aLocaleURI); - return bundle.GetStringFromName(aLocaleKey.replace("%ID%", aID)); + this.name = bundle.GetStringFromName(aLocaleKey.replace("%ID%", aID)); + return this.name; }); } else { @@ -667,12 +620,9 @@ var gCheckUpdateSecurityDefault = true; var gCheckUpdateSecurity = gCheckUpdateSecurityDefault; var gUpdateEnabled = true; var gAutoUpdateDefault = true; -var gHotfixID = null; -var gWebExtensionsMinPlatformVersion = null; var gShutdownBarrier = null; var gRepoShutdownState = ""; var gShutdownInProgress = false; -var gPluginPageListener = null; /** * This is the real manager, kept here rather than in AddonManager to keep its @@ -690,13 +640,12 @@ var AddonManagerInternal = { startupChanges: {}, // Store telemetry details per addon provider telemetryDetails: {}, - upgradeListeners: new Map(), - recordTimestamp: function(name, value) { + recordTimestamp: function AMI_recordTimestamp(name, value) { this.TelemetryTimestamps.add(name, value); }, - validateBlocklist: function() { + validateBlocklist: function AMI_validateBlocklist() { let appBlocklist = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]); // If there is no application shipped blocklist then there is nothing to do @@ -819,19 +768,11 @@ var AddonManagerInternal = { logger.debug(`Provider finished startup: ${providerName(aProvider)}`); }, - _getProviderByName(aName) { - for (let provider of this.providers) { - if (providerName(provider) == aName) - return provider; - } - return undefined; - }, - /** * Initializes the AddonManager, loading any known providers and initializing * them. */ - startup: function() { + startup: function AMI_startup() { try { if (gStarted) return; @@ -851,8 +792,6 @@ var AddonManagerInternal = { } catch (e) { } - Extension.browserUpdated = appChanged; - let oldPlatformVersion = null; try { oldPlatformVersion = Services.prefs.getCharPref(PREF_EM_LAST_PLATFORM_VERSION); @@ -870,10 +809,8 @@ var AddonManagerInternal = { this.validateBlocklist(); } - if (!MOZ_COMPATIBILITY_NIGHTLY) { - PREF_EM_CHECK_COMPATIBILITY = PREF_EM_CHECK_COMPATIBILITY_BASE + "." + - Services.appinfo.version.replace(BRANCH_REGEXP, "$1"); - } + PREF_EM_CHECK_COMPATIBILITY = PREF_EM_CHECK_COMPATIBILITY_BASE + "." + + Services.appinfo.version.replace(BRANCH_REGEXP, "$1"); try { gCheckCompatibility = Services.prefs.getBoolPref(PREF_EM_CHECK_COMPATIBILITY); @@ -888,7 +825,7 @@ var AddonManagerInternal = { try { let defaultBranch = Services.prefs.getDefaultBranch(""); gCheckUpdateSecurityDefault = defaultBranch.getBoolPref(PREF_EM_CHECK_UPDATE_SECURITY); - } catch (e) {} + } catch(e) {} try { gCheckUpdateSecurity = Services.prefs.getBoolPref(PREF_EM_CHECK_UPDATE_SECURITY); @@ -905,16 +842,6 @@ var AddonManagerInternal = { } catch (e) {} Services.prefs.addObserver(PREF_EM_AUTOUPDATE_DEFAULT, this, false); - try { - gHotfixID = Services.prefs.getCharPref(PREF_EM_HOTFIX_ID); - } catch (e) {} - Services.prefs.addObserver(PREF_EM_HOTFIX_ID, this, false); - - try { - gWebExtensionsMinPlatformVersion = Services.prefs.getCharPref(PREF_MIN_WEBEXT_PLATFORM_VERSION); - } catch (e) {} - Services.prefs.addObserver(PREF_MIN_WEBEXT_PLATFORM_VERSION, this, false); - let defaultProvidersEnabled = true; try { defaultProvidersEnabled = Services.prefs.getBoolPref(PREF_DEFAULT_PROVIDERS_ENABLED); @@ -941,7 +868,7 @@ var AddonManagerInternal = { AddonManagerPrivate.recordException("AMI", "provider " + url + " load failed", e); logger.error("Exception loading default provider \"" + url + "\"", e); } - } + }; } // Load any providers registered in the category manager @@ -982,13 +909,6 @@ var AddonManagerInternal = { delete this.startupChanges[type]; } - // Support for remote about:plugins. Note that this module isn't loaded - // at the top because Services.appinfo is defined late in tests. - let { RemotePages } = Cu.import("resource://gre/modules/RemotePageManager.jsm", {}); - - gPluginPageListener = new RemotePages("about:plugins"); - gPluginPageListener.addMessageListener("RequestPlugins", this.requestPlugins); - gStartupComplete = true; this.recordTimestamp("AMI_startup_end"); } @@ -1009,7 +929,7 @@ var AddonManagerInternal = { * @param aTypes * An optional array of add-on types */ - registerProvider: function(aProvider, aTypes) { + registerProvider: function AMI_registerProvider(aProvider, aTypes) { if (!aProvider || typeof aProvider != "object") throw Components.Exception("aProvider must be specified", Cr.NS_ERROR_INVALID_ARG); @@ -1021,26 +941,29 @@ var AddonManagerInternal = { this.pendingProviders.add(aProvider); if (aTypes) { - for (let type of aTypes) { - if (!(type.id in this.types)) { - if (!VALID_TYPES_REGEXP.test(type.id)) { - logger.warn("Ignoring invalid type " + type.id); + aTypes.forEach(function(aType) { + if (!(aType.id in this.types)) { + if (!VALID_TYPES_REGEXP.test(aType.id)) { + logger.warn("Ignoring invalid type " + aType.id); return; } - this.types[type.id] = { - type: type, + this.types[aType.id] = { + type: aType, providers: [aProvider] }; let typeListeners = this.typeListeners.slice(0); - for (let listener of typeListeners) - safeCall(() => listener.onTypeAdded(type)); + for (let listener of typeListeners) { + safeCall(function listenerSafeCall() { + listener.onTypeAdded(aType); + }); + } } else { - this.types[type.id].providers.push(aProvider); + this.types[aType.id].providers.push(aProvider); } - } + }, this); } // If we're registering after startup call this provider's startup. @@ -1058,7 +981,7 @@ var AddonManagerInternal = { * For providers that have async shutdown methods returning Promises, * the caller should wait for that Promise to resolve. */ - unregisterProvider: function(aProvider) { + unregisterProvider: function AMI_unregisterProvider(aProvider) { if (!aProvider || typeof aProvider != "object") throw Components.Exception("aProvider must be specified", Cr.NS_ERROR_INVALID_ARG); @@ -1070,14 +993,17 @@ var AddonManagerInternal = { this.pendingProviders.delete(aProvider); for (let type in this.types) { - this.types[type].providers = this.types[type].providers.filter(p => p != aProvider); + this.types[type].providers = this.types[type].providers.filter(function filterProvider(p) p != aProvider); if (this.types[type].providers.length == 0) { let oldType = this.types[type].type; delete this.types[type]; let typeListeners = this.typeListeners.slice(0); - for (let listener of typeListeners) - safeCall(() => listener.onTypeRemoved(oldType)); + for (let listener of typeListeners) { + safeCall(function listenerSafeCall() { + listener.onTypeRemoved(oldType); + }); + } } } @@ -1110,7 +1036,7 @@ var AddonManagerInternal = { * * @param aProvider Provider object to mark safe */ - markProviderSafe: function(aProvider) { + markProviderSafe: function AMI_markProviderSafe(aProvider) { if (!gStarted) { throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1140,7 +1066,7 @@ var AddonManagerInternal = { * The method name to call * @see callProvider */ - callProviders: function(aMethod, ...aArgs) { + callProviders: function AMI_callProviders(aMethod, ...aArgs) { if (!aMethod || typeof aMethod != "string") throw Components.Exception("aMethod must be a non-empty string", Cr.NS_ERROR_INVALID_ARG); @@ -1152,7 +1078,7 @@ var AddonManagerInternal = { provider[aMethod].apply(provider, aArgs); } catch (e) { - reportProviderError(provider, aMethod, e); + reportProviderError(aProvider, aMethod, e); } } }, @@ -1181,7 +1107,7 @@ var AddonManagerInternal = { * @return Promise{null} that resolves when all providers and dependent modules * have finished shutting down */ - shutdownManager: Task.async(function*() { + shutdownManager: Task.async(function* () { logger.debug("shutdown"); this.callManagerListeners("onShutdown"); @@ -1193,9 +1119,6 @@ var AddonManagerInternal = { Services.prefs.removeObserver(PREF_EM_CHECK_UPDATE_SECURITY, this); Services.prefs.removeObserver(PREF_EM_UPDATE_ENABLED, this); Services.prefs.removeObserver(PREF_EM_AUTOUPDATE_DEFAULT, this); - Services.prefs.removeObserver(PREF_EM_HOTFIX_ID, this); - gPluginPageListener.destroy(); - gPluginPageListener = null; let savedError = null; // Only shut down providers if they've been started. @@ -1203,7 +1126,7 @@ var AddonManagerInternal = { try { yield gShutdownBarrier.wait(); } - catch (err) { + catch(err) { savedError = err; logger.error("Failure during wait for shutdown barrier", err); AddonManagerPrivate.recordException("AMI", "Async shutdown of AddonManager providers", err); @@ -1216,7 +1139,7 @@ var AddonManagerInternal = { yield AddonRepository.shutdown(); gRepoShutdownState = "done"; } - catch (err) { + catch(err) { savedError = err; logger.error("Failure during AddonRepository shutdown", err); AddonManagerPrivate.recordException("AMI", "Async shutdown of AddonRepository", err); @@ -1239,36 +1162,18 @@ var AddonManagerInternal = { } }), - requestPlugins: function({ target: port }) { - // Lists all the properties that plugins.html needs - const NEEDED_PROPS = ["name", "pluginLibraries", "pluginFullpath", "version", - "isActive", "blocklistState", "description", - "pluginMimeTypes"]; - function filterProperties(plugin) { - let filtered = {}; - for (let prop of NEEDED_PROPS) { - filtered[prop] = plugin[prop]; - } - return filtered; - } - - AddonManager.getAddonsByTypes(["plugin"], function(aPlugins) { - port.sendAsyncMessage("PluginList", aPlugins.map(filterProperties)); - }); - }, - /** * Notified when a preference we're interested in has changed. * * @see nsIObserver */ - observe: function(aSubject, aTopic, aData) { + observe: function AMI_observe(aSubject, aTopic, aData) { switch (aData) { case PREF_EM_CHECK_COMPATIBILITY: { let oldValue = gCheckCompatibility; try { gCheckCompatibility = Services.prefs.getBoolPref(PREF_EM_CHECK_COMPATIBILITY); - } catch (e) { + } catch(e) { gCheckCompatibility = true; } @@ -1283,7 +1188,7 @@ var AddonManagerInternal = { let oldValue = gStrictCompatibility; try { gStrictCompatibility = Services.prefs.getBoolPref(PREF_EM_STRICT_COMPATIBILITY); - } catch (e) { + } catch(e) { gStrictCompatibility = true; } @@ -1298,7 +1203,7 @@ var AddonManagerInternal = { let oldValue = gCheckUpdateSecurity; try { gCheckUpdateSecurity = Services.prefs.getBoolPref(PREF_EM_CHECK_UPDATE_SECURITY); - } catch (e) { + } catch(e) { gCheckUpdateSecurity = true; } @@ -1313,7 +1218,7 @@ var AddonManagerInternal = { let oldValue = gUpdateEnabled; try { gUpdateEnabled = Services.prefs.getBoolPref(PREF_EM_UPDATE_ENABLED); - } catch (e) { + } catch(e) { gUpdateEnabled = true; } @@ -1324,25 +1229,13 @@ var AddonManagerInternal = { let oldValue = gAutoUpdateDefault; try { gAutoUpdateDefault = Services.prefs.getBoolPref(PREF_EM_AUTOUPDATE_DEFAULT); - } catch (e) { + } catch(e) { gAutoUpdateDefault = true; } this.callManagerListeners("onUpdateModeChanged"); break; } - case PREF_EM_HOTFIX_ID: { - try { - gHotfixID = Services.prefs.getCharPref(PREF_EM_HOTFIX_ID); - } catch (e) { - gHotfixID = null; - } - break; - } - case PREF_MIN_WEBEXT_PLATFORM_VERSION: { - gWebExtensionsMinPlatformVersion = Services.prefs.getCharPref(PREF_MIN_WEBEXT_PLATFORM_VERSION); - break; - } } }, @@ -1358,7 +1251,7 @@ var AddonManagerInternal = { * The optional application version to use for %APP_VERSION% * @return The appropriately escaped URI. */ - escapeAddonURI: function(aAddon, aUri, aAppVersion) + escapeAddonURI: function AMI_escapeAddonURI(aAddon, aUri, aAppVersion) { if (!aAddon || typeof aAddon != "object") throw Components.Exception("aAddon must be an Addon object", @@ -1403,7 +1296,7 @@ var AddonManagerInternal = { // Replace custom parameters (names of custom parameters must have at // least 3 characters to prevent lookups for something like %D0%C8) var catMan = null; - uri = uri.replace(/%(\w{3,})%/g, function(aMatch, aParam) { + uri = uri.replace(/%(\w{3,})%/g, function parameterReplace(aMatch, aParam) { if (!catMan) { catMan = Cc["@mozilla.org/categorymanager;1"]. getService(Ci.nsICategoryManager); @@ -1414,7 +1307,7 @@ var AddonManagerInternal = { var paramHandler = Cc[contractID].getService(Ci.nsIPropertyBag2); return paramHandler.getPropertyAsAString(aParam); } - catch (e) { + catch(e) { return aMatch; } }); @@ -1429,18 +1322,12 @@ var AddonManagerInternal = { * @return Promise{null} Resolves when the background update check is complete * (the resulting addon installations may still be in progress). */ - backgroundUpdateCheck: function() { + backgroundUpdateCheck: function AMI_backgroundUpdateCheck() { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); - let buPromise = Task.spawn(function*() { - let hotfixID = this.hotfixID; - - let appUpdateEnabled = Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) && - Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO); - let checkHotfix = hotfixID && appUpdateEnabled; - + let buPromise = Task.spawn(function* backgroundUpdateTask() { logger.debug("Background update check beginning"); Services.obs.notifyObservers(null, "addons-background-update-start", null); @@ -1460,15 +1347,11 @@ var AddonManagerInternal = { let updates = []; for (let addon of allAddons) { - if (addon.id == hotfixID) { - continue; - } - // Check all add-ons for updates so that any compatibility updates will // be applied updates.push(new Promise((resolve, reject) => { addon.findUpdates({ - onUpdateAvailable: function(aAddon, aInstall) { + onUpdateAvailable: function BUC_onUpdateAvailable(aAddon, aInstall) { // Start installing updates when the add-on can be updated and // background updates should be applied. logger.debug("Found update for add-on ${id}", aAddon); @@ -1476,7 +1359,7 @@ var AddonManagerInternal = { AddonManager.shouldAutoUpdate(aAddon)) { // XXX we really should resolve when this install is done, // not when update-available check completes, no? - logger.debug(`Starting upgrade install of ${aAddon.id}`); + logger.debug("Starting install of ${id}", aAddon); aInstall.install(); } }, @@ -1488,113 +1371,6 @@ var AddonManagerInternal = { yield Promise.all(updates); } - if (checkHotfix) { - var hotfixVersion = ""; - try { - hotfixVersion = Services.prefs.getCharPref(PREF_EM_HOTFIX_LASTVERSION); - } - catch (e) { } - - let url = null; - if (Services.prefs.getPrefType(PREF_EM_HOTFIX_URL) == Ci.nsIPrefBranch.PREF_STRING) - url = Services.prefs.getCharPref(PREF_EM_HOTFIX_URL); - else - url = Services.prefs.getCharPref(PREF_EM_UPDATE_BACKGROUND_URL); - - // Build the URI from a fake add-on data. - url = AddonManager.escapeAddonURI({ - id: hotfixID, - version: hotfixVersion, - userDisabled: false, - appDisabled: false - }, url); - - Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm"); - let update = null; - try { - let foundUpdates = yield new Promise((resolve, reject) => { - AddonUpdateChecker.checkForUpdates(hotfixID, null, url, { - onUpdateCheckComplete: resolve, - onUpdateCheckError: reject - }); - }); - update = AddonUpdateChecker.getNewestCompatibleUpdate(foundUpdates); - } catch (e) { - // AUC.checkForUpdates already logged the error - } - - // Check that we have a hotfix update, and it's newer than the one we already - // have installed (if any) - if (update) { - if (Services.vc.compare(hotfixVersion, update.version) < 0) { - logger.debug("Downloading hotfix version " + update.version); - let aInstall = yield new Promise((resolve, reject) => - AddonManager.getInstallForURL(update.updateURL, resolve, - "application/x-xpinstall", update.updateHash, null, - null, update.version)); - - aInstall.addListener({ - onDownloadEnded: function(aInstall) { - if (aInstall.addon.id != hotfixID) { - logger.warn("The downloaded hotfix add-on did not have the " + - "expected ID and so will not be installed."); - aInstall.cancel(); - return; - } - - // If XPIProvider has reported the hotfix as properly signed then - // there is nothing more to do here - if (aInstall.addon.signedState == AddonManager.SIGNEDSTATE_SIGNED) - return; - - try { - if (!Services.prefs.getBoolPref(PREF_EM_CERT_CHECKATTRIBUTES)) - return; - } - catch (e) { - // By default don't do certificate checks. - return; - } - - try { - CertUtils.validateCert(aInstall.certificate, - CertUtils.readCertPrefs(PREF_EM_HOTFIX_CERTS)); - } - catch (e) { - logger.warn("The hotfix add-on was not signed by the expected " + - "certificate and so will not be installed.", e); - aInstall.cancel(); - } - }, - - onInstallEnded: function(aInstall) { - // Remember the last successfully installed version. - Services.prefs.setCharPref(PREF_EM_HOTFIX_LASTVERSION, - aInstall.version); - }, - - onInstallCancelled: function(aInstall) { - // Revert to the previous version if the installation was - // cancelled. - Services.prefs.setCharPref(PREF_EM_HOTFIX_LASTVERSION, - hotfixVersion); - } - }); - - aInstall.install(); - } - } - } - - if (appUpdateEnabled) { - try { - yield AddonManagerInternal._getProviderByName("XPIProvider").updateSystemAddons(); - } - catch (e) { - logger.warn("Failed to update system addons", e); - } - } - logger.debug("Background update check complete"); Services.obs.notifyObservers(null, "addons-background-update-complete", @@ -1617,7 +1393,7 @@ var AddonManagerInternal = { * @param aID * The ID of the add-on */ - addStartupChange: function(aType, aID) { + addStartupChange: function AMI_addStartupChange(aType, aID) { if (!aType || typeof aType != "string") throw Components.Exception("aType must be a non-empty string", Cr.NS_ERROR_INVALID_ARG); @@ -1628,7 +1404,6 @@ var AddonManagerInternal = { if (gStartupComplete) return; - logger.debug("Registering startup change '" + aType + "' for " + aID); // Ensure that an ID is only listed in one type of change for (let type in this.startupChanges) @@ -1647,7 +1422,7 @@ var AddonManagerInternal = { * @param aID * The ID of the add-on */ - removeStartupChange: function(aType, aID) { + removeStartupChange: function AMI_removeStartupChange(aType, aID) { if (!aType || typeof aType != "string") throw Components.Exception("aType must be a non-empty string", Cr.NS_ERROR_INVALID_ARG); @@ -1662,7 +1437,8 @@ var AddonManagerInternal = { if (!(aType in this.startupChanges)) return; - this.startupChanges[aType] = this.startupChanges[aType].filter(aItem => aItem != aID); + this.startupChanges[aType] = this.startupChanges[aType].filter( + function filterItem(aItem) aItem != aID); }, /** @@ -1672,7 +1448,7 @@ var AddonManagerInternal = { * @param aMethod * The method on the listeners to call */ - callManagerListeners: function(aMethod, ...aArgs) { + callManagerListeners: function AMI_callManagerListeners(aMethod, ...aArgs) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1703,7 +1479,7 @@ var AddonManagerInternal = { * An optional array of extra InstallListeners to also call * @return false if any of the listeners returned false, true otherwise */ - callInstallListeners: function(aMethod, + callInstallListeners: function AMI_callInstallListeners(aMethod, aExtraListeners, ...aArgs) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", @@ -1745,7 +1521,7 @@ var AddonManagerInternal = { * @param aMethod * The method on the listeners to call */ - callAddonListeners: function(aMethod, ...aArgs) { + callAddonListeners: function AMI_callAddonListeners(aMethod, ...aArgs) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1779,7 +1555,7 @@ var AddonManagerInternal = { * A boolean indicating if the change will only take place the next * time the application is restarted */ - notifyAddonChanged: function(aID, aType, aPendingRestart) { + notifyAddonChanged: function AMI_notifyAddonChanged(aID, aType, aPendingRestart) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1816,7 +1592,7 @@ var AddonManagerInternal = { * their add-ons in response to an application change such as a blocklist * update. */ - updateAddonAppDisabledStates: function() { + updateAddonAppDisabledStates: function AMI_updateAddonAppDisabledStates() { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1831,7 +1607,7 @@ var AddonManagerInternal = { * @param aCallback * Function to call when operation is complete. */ - updateAddonRepositoryData: function(aCallback) { + updateAddonRepositoryData: function AMI_updateAddonRepositoryData(aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1841,11 +1617,11 @@ var AddonManagerInternal = { Cr.NS_ERROR_INVALID_ARG); new AsyncObjectCaller(this.providers, "updateAddonRepositoryData", { - nextObject: function(aCaller, aProvider) { + nextObject: function updateAddonRepositoryData_nextObject(aCaller, aProvider) { callProviderAsync(aProvider, "updateAddonRepositoryData", aCaller.callNext.bind(aCaller)); }, - noMoreObjects: function(aCaller) { + noMoreObjects: function updateAddonRepositoryData_noMoreObjects(aCaller) { safeCall(aCallback); // only tests should care about this Services.obs.notifyObservers(null, "TEST:addon-repository-data-updated", null); @@ -1874,7 +1650,7 @@ var AddonManagerInternal = { * An optional nsILoadGroup to associate any network requests with * @throws if the aUrl, aCallback or aMimetype arguments are not specified */ - getInstallForURL: function(aUrl, aCallback, aMimetype, + getInstallForURL: function AMI_getInstallForURL(aUrl, aCallback, aMimetype, aHash, aName, aIcons, aVersion, aBrowser) { if (!gStarted) @@ -1944,7 +1720,7 @@ var AddonManagerInternal = { * An optional mimetype hint for the add-on * @throws if the aFile or aCallback arguments are not specified */ - getInstallForFile: function(aFile, aCallback, aMimetype) { + getInstallForFile: function AMI_getInstallForFile(aFile, aCallback, aMimetype) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -1962,9 +1738,9 @@ var AddonManagerInternal = { Cr.NS_ERROR_INVALID_ARG); new AsyncObjectCaller(this.providers, "getInstallForFile", { - nextObject: function(aCaller, aProvider) { + nextObject: function getInstallForFile_nextObject(aCaller, aProvider) { callProviderAsync(aProvider, "getInstallForFile", aFile, - function(aInstall) { + function getInstallForFile_safeCall(aInstall) { if (aInstall) safeCall(aCallback, aInstall); else @@ -1972,7 +1748,7 @@ var AddonManagerInternal = { }); }, - noMoreObjects: function(aCaller) { + noMoreObjects: function getInstallForFile_noMoreObjects(aCaller) { safeCall(aCallback, null); } }); @@ -1988,7 +1764,7 @@ var AddonManagerInternal = { * A callback which will be passed an array of AddonInstalls * @throws If the aCallback argument is not specified */ - getInstallsByTypes: function(aTypes, aCallback) { + getInstallsByTypes: function AMI_getInstallsByTypes(aTypes, aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2004,9 +1780,9 @@ var AddonManagerInternal = { let installs = []; new AsyncObjectCaller(this.providers, "getInstallsByTypes", { - nextObject: function(aCaller, aProvider) { + nextObject: function getInstallsByTypes_nextObject(aCaller, aProvider) { callProviderAsync(aProvider, "getInstallsByTypes", aTypes, - function(aProviderInstalls) { + function getInstallsByTypes_safeCall(aProviderInstalls) { if (aProviderInstalls) { installs = installs.concat(aProviderInstalls); } @@ -2014,7 +1790,7 @@ var AddonManagerInternal = { }); }, - noMoreObjects: function(aCaller) { + noMoreObjects: function getInstallsByTypes_noMoreObjects(aCaller) { safeCall(aCallback, installs); } }); @@ -2026,7 +1802,7 @@ var AddonManagerInternal = { * @param aCallback * A callback which will be passed an array of AddonInstalls */ - getAllInstalls: function(aCallback) { + getAllInstalls: function AMI_getAllInstalls(aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2046,7 +1822,7 @@ var AddonManagerInternal = { * @return string containing the Addon ID or null * @see amIAddonManager.mapURIToAddonID */ - mapURIToAddonID: function(aURI) { + mapURIToAddonID: function AMI_mapURIToAddonID(aURI) { if (!(aURI instanceof Ci.nsIURI)) { throw Components.Exception("aURI is not a nsIURI", Cr.NS_ERROR_INVALID_ARG); @@ -2071,7 +1847,7 @@ var AddonManagerInternal = { * The mimetype to check * @return true if installation is enabled for the mimetype */ - isInstallEnabled: function(aMimetype) { + isInstallEnabled: function AMI_isInstallEnabled(aMimetype) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2099,7 +1875,7 @@ var AddonManagerInternal = { * The nsIPrincipal that initiated the install * @return true if the source is allowed to install this mimetype */ - isInstallAllowed: function(aMimetype, aInstallingPrincipal) { + isInstallAllowed: function AMI_isInstallAllowed(aMimetype, aInstallingPrincipal) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2134,8 +1910,10 @@ var AddonManagerInternal = { * @param aInstalls * The array of AddonInstalls to be installed */ - installAddonsFromWebpage: function(aMimetype, aBrowser, - aInstallingPrincipal, aInstalls) { + installAddonsFromWebpage: function AMI_installAddonsFromWebpage(aMimetype, + aBrowser, + aInstallingPrincipal, + aInstalls) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2158,8 +1936,9 @@ var AddonManagerInternal = { if (!("@mozilla.org/addons/web-install-listener;1" in Cc)) { logger.warn("No web installer available, cancelling all installs"); - for (let install of aInstalls) - install.cancel(); + aInstalls.forEach(function(aInstall) { + aInstall.cancel(); + }); return; } @@ -2207,14 +1986,16 @@ var AddonManagerInternal = { if (!this.isInstallAllowed(aMimetype, aInstallingPrincipal)) { if (weblistener.onWebInstallBlocked(topBrowser, aInstallingPrincipal.URI, aInstalls, aInstalls.length)) { - for (let install of aInstalls) - install.install(); + aInstalls.forEach(function(aInstall) { + aInstall.install(); + }); } } else if (weblistener.onWebInstallRequested(topBrowser, aInstallingPrincipal.URI, aInstalls, aInstalls.length)) { - for (let install of aInstalls) - install.install(); + aInstalls.forEach(function(aInstall) { + aInstall.install(); + }); } } catch (e) { @@ -2222,8 +2003,9 @@ var AddonManagerInternal = { // calling onWebInstallBlocked or onWebInstallRequested all of the // installs should get cancelled. logger.warn("Failure calling web installer", e); - for (let install of aInstalls) - install.cancel(); + aInstalls.forEach(function(aInstall) { + aInstall.cancel(); + }); } }, @@ -2233,12 +2015,12 @@ var AddonManagerInternal = { * @param aListener * The InstallListener to add */ - addInstallListener: function(aListener) { + addInstallListener: function AMI_addInstallListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be a InstallListener object", Cr.NS_ERROR_INVALID_ARG); - if (!this.installListeners.some(function(i) { + if (!this.installListeners.some(function addInstallListener_matchListener(i) { return i == aListener; })) this.installListeners.push(aListener); }, @@ -2249,7 +2031,7 @@ var AddonManagerInternal = { * @param aListener * The InstallListener to remove */ - removeInstallListener: function(aListener) { + removeInstallListener: function AMI_removeInstallListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be a InstallListener object", Cr.NS_ERROR_INVALID_ARG); @@ -2262,199 +2044,17 @@ var AddonManagerInternal = { pos++; } }, - /* - * Adds new or overrides existing UpgradeListener. - * - * @param aInstanceID - * The instance ID of an addon to register a listener for. - * @param aCallback - * The callback to invoke when updates are available for this addon. - * @throws if there is no addon matching the instanceID - */ - addUpgradeListener: function(aInstanceID, aCallback) { - if (!aInstanceID || typeof aInstanceID != "symbol") - throw Components.Exception("aInstanceID must be a symbol", - Cr.NS_ERROR_INVALID_ARG); - - if (!aCallback || typeof aCallback != "function") - throw Components.Exception("aCallback must be a function", - Cr.NS_ERROR_INVALID_ARG); - - this.getAddonByInstanceID(aInstanceID).then(wrapper => { - if (!wrapper) { - throw Error("No addon matching instanceID:", aInstanceID.toString()); - } - let addonId = wrapper.addonId(); - logger.debug(`Registering upgrade listener for ${addonId}`); - this.upgradeListeners.set(addonId, aCallback); - }); - }, - - /** - * Removes an UpgradeListener if the listener is registered. - * - * @param aInstanceID - * The instance ID of the addon to remove - */ - removeUpgradeListener: function(aInstanceID) { - if (!aInstanceID || typeof aInstanceID != "symbol") - throw Components.Exception("aInstanceID must be a symbol", - Cr.NS_ERROR_INVALID_ARG); - - this.getAddonByInstanceID(aInstanceID).then(addon => { - if (!addon) { - throw Error("No addon for instanceID:", aInstanceID.toString()); - } - if (this.upgradeListeners.has(addon.id)) { - this.upgradeListeners.delete(addon.id); - } else { - throw Error("No upgrade listener registered for addon ID:", addon.id); - } - }); - }, - - /** - * Installs a temporary add-on from a local file or directory. - * @param aFile - * An nsIFile for the file or directory of the add-on to be - * temporarily installed. - * @return a Promise that rejects if the add-on is not a valid restartless - * add-on or if the same ID is already temporarily installed. - */ - installTemporaryAddon: function(aFile) { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - - if (!(aFile instanceof Ci.nsIFile)) - throw Components.Exception("aFile must be a nsIFile", - Cr.NS_ERROR_INVALID_ARG); - - return AddonManagerInternal._getProviderByName("XPIProvider") - .installTemporaryAddon(aFile); - }, - - installAddonFromSources: function(aFile) { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - - if (!(aFile instanceof Ci.nsIFile)) - throw Components.Exception("aFile must be a nsIFile", - Cr.NS_ERROR_INVALID_ARG); - - return AddonManagerInternal._getProviderByName("XPIProvider") - .installAddonFromSources(aFile); - }, - - /** - * Returns an Addon corresponding to an instance ID. - * @param aInstanceID - * An Addon Instance ID symbol - * @return {Promise} - * @resolves The found Addon or null if no such add-on exists. - * @rejects Never - * @throws if the aInstanceID argument is not specified - * or the AddonManager is not initialized - */ - getAddonByInstanceID: function(aInstanceID) { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - - if (!aInstanceID || typeof aInstanceID != "symbol") - throw Components.Exception("aInstanceID must be a Symbol()", - Cr.NS_ERROR_INVALID_ARG); - - return AddonManagerInternal._getProviderByName("XPIProvider") - .getAddonByInstanceID(aInstanceID); - }, - - /** - * Gets an icon from the icon set provided by the add-on - * that is closest to the specified size. - * - * The optional window parameter will be used to determine - * the screen resolution and select a more appropriate icon. - * Calling this method with 48px on retina screens will try to - * match an icon of size 96px. - * - * @param aAddon - * An addon object, meaning: - * An object with either an icons property that is a key-value - * list of icon size and icon URL, or an object having an iconURL - * and icon64URL property. - * @param aSize - * Ideal icon size in pixels - * @param aWindow - * Optional window object for determining the correct scale. - * @return {String} The absolute URL of the icon or null if the addon doesn't have icons - */ - getPreferredIconURL: function(aAddon, aSize, aWindow = undefined) { - if (aWindow && aWindow.devicePixelRatio) { - aSize *= aWindow.devicePixelRatio; - } - - let icons = aAddon.icons; - - // certain addon-types only have iconURLs - if (!icons) { - icons = {}; - if (aAddon.iconURL) { - icons[32] = aAddon.iconURL; - icons[48] = aAddon.iconURL; - } - if (aAddon.icon64URL) { - icons[64] = aAddon.icon64URL; - } - } - - // quick return if the exact size was found - if (icons[aSize]) { - return icons[aSize]; - } - - let bestSize = null; - - for (let size of Object.keys(icons)) { - if (!INTEGER.test(size)) { - throw Components.Exception("Invalid icon size, must be an integer", - Cr.NS_ERROR_ILLEGAL_VALUE); - } - - size = parseInt(size, 10); - - if (!bestSize) { - bestSize = size; - continue; - } - - if (size > aSize && bestSize > aSize) { - // If both best size and current size are larger than the wanted size then choose - // the one closest to the wanted size - bestSize = Math.min(bestSize, size); - } - else { - // Otherwise choose the largest of the two so we'll prefer sizes as close to below aSize - // or above aSize - bestSize = Math.max(bestSize, size); - } - } - - return icons[bestSize] || null; - }, /** * Asynchronously gets an add-on with a specific ID. * * @param aID * The ID of the add-on to retrieve - * @return {Promise} - * @resolves The found Addon or null if no such add-on exists. - * @rejects Never - * @throws if the aID argument is not specified + * @param aCallback + * The callback to pass the retrieved add-on to + * @throws if the aID or aCallback arguments are not specified */ - getAddonByID: function(aID) { + getAddonByID: function AMI_getAddonByID(aID, aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2463,10 +2063,24 @@ var AddonManagerInternal = { throw Components.Exception("aID must be a non-empty string", Cr.NS_ERROR_INVALID_ARG); - let promises = Array.from(this.providers, - p => promiseCallProvider(p, "getAddonByID", aID)); - return Promise.all(promises).then(aAddons => { - return aAddons.find(a => !!a) || null; + if (typeof aCallback != "function") + throw Components.Exception("aCallback must be a function", + Cr.NS_ERROR_INVALID_ARG); + + new AsyncObjectCaller(this.providers, "getAddonByID", { + nextObject: function getAddonByID_nextObject(aCaller, aProvider) { + callProviderAsync(aProvider, "getAddonByID", aID, + function getAddonByID_safeCall(aAddon) { + if (aAddon) + safeCall(aCallback, aAddon); + else + aCaller.callNext(); + }); + }, + + noMoreObjects: function getAddonByID_noMoreObjects(aCaller) { + safeCall(aCallback, null); + } }); }, @@ -2479,7 +2093,7 @@ var AddonManagerInternal = { * The callback to pass the retrieved add-on to. * @throws if the aGUID or aCallback arguments are not specified */ - getAddonBySyncGUID: function(aGUID, aCallback) { + getAddonBySyncGUID: function AMI_getAddonBySyncGUID(aGUID, aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2493,9 +2107,9 @@ var AddonManagerInternal = { Cr.NS_ERROR_INVALID_ARG); new AsyncObjectCaller(this.providers, "getAddonBySyncGUID", { - nextObject: function(aCaller, aProvider) { + nextObject: function getAddonBySyncGUID_nextObject(aCaller, aProvider) { callProviderAsync(aProvider, "getAddonBySyncGUID", aGUID, - function(aAddon) { + function getAddonBySyncGUID_safeCall(aAddon) { if (aAddon) { safeCall(aCallback, aAddon); } else { @@ -2504,7 +2118,7 @@ var AddonManagerInternal = { }); }, - noMoreObjects: function(aCaller) { + noMoreObjects: function getAddonBySyncGUID_noMoreObjects(aCaller) { safeCall(aCallback, null); } }); @@ -2515,12 +2129,11 @@ var AddonManagerInternal = { * * @param aIDs * The array of IDs to retrieve - * @return {Promise} - * @resolves The array of found add-ons. - * @rejects Never - * @throws if the aIDs argument is not specified + * @param aCallback + * The callback to pass an array of Addons to + * @throws if the aID or aCallback arguments are not specified */ - getAddonsByIDs: function(aIDs) { + getAddonsByIDs: function AMI_getAddonsByIDs(aIDs, aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2529,8 +2142,25 @@ var AddonManagerInternal = { throw Components.Exception("aIDs must be an array", Cr.NS_ERROR_INVALID_ARG); - let promises = aIDs.map(a => AddonManagerInternal.getAddonByID(a)); - return Promise.all(promises); + if (typeof aCallback != "function") + throw Components.Exception("aCallback must be a function", + Cr.NS_ERROR_INVALID_ARG); + + let addons = []; + + new AsyncObjectCaller(aIDs, null, { + nextObject: function getAddonsByIDs_nextObject(aCaller, aID) { + AddonManagerInternal.getAddonByID(aID, + function getAddonsByIDs_getAddonByID(aAddon) { + addons.push(aAddon); + aCaller.callNext(); + }); + }, + + noMoreObjects: function getAddonsByIDs_noMoreObjects(aCaller) { + safeCall(aCallback, addons); + } + }); }, /** @@ -2542,7 +2172,7 @@ var AddonManagerInternal = { * The callback to pass an array of Addons to. * @throws if the aCallback argument is not specified */ - getAddonsByTypes: function(aTypes, aCallback) { + getAddonsByTypes: function AMI_getAddonsByTypes(aTypes, aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2558,9 +2188,9 @@ var AddonManagerInternal = { let addons = []; new AsyncObjectCaller(this.providers, "getAddonsByTypes", { - nextObject: function(aCaller, aProvider) { + nextObject: function getAddonsByTypes_nextObject(aCaller, aProvider) { callProviderAsync(aProvider, "getAddonsByTypes", aTypes, - function(aProviderAddons) { + function getAddonsByTypes_concatAddons(aProviderAddons) { if (aProviderAddons) { addons = addons.concat(aProviderAddons); } @@ -2568,7 +2198,7 @@ var AddonManagerInternal = { }); }, - noMoreObjects: function(aCaller) { + noMoreObjects: function getAddonsByTypes_noMoreObjects(aCaller) { safeCall(aCallback, addons); } }); @@ -2580,7 +2210,7 @@ var AddonManagerInternal = { * @param aCallback * A callback which will be passed an array of Addons */ - getAllAddons: function(aCallback) { + getAllAddons: function AMI_getAllAddons(aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2602,7 +2232,8 @@ var AddonManagerInternal = { * The callback to pass the array of Addons to * @throws if the aCallback argument is not specified */ - getAddonsWithOperationsByTypes: function(aTypes, aCallback) { + getAddonsWithOperationsByTypes: + function AMI_getAddonsWithOperationsByTypes(aTypes, aCallback) { if (!gStarted) throw Components.Exception("AddonManager is not initialized", Cr.NS_ERROR_NOT_INITIALIZED); @@ -2630,7 +2261,7 @@ var AddonManagerInternal = { }); }, - noMoreObjects: function(caller) { + noMoreObjects: function getAddonsWithOperationsByTypes_noMoreObjects(caller) { safeCall(aCallback, addons); } }); @@ -2642,12 +2273,13 @@ var AddonManagerInternal = { * @param aListener * The listener to add */ - addManagerListener: function(aListener) { + addManagerListener: function AMI_addManagerListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be an AddonManagerListener object", Cr.NS_ERROR_INVALID_ARG); - if (!this.managerListeners.some(i => i == aListener)) + if (!this.managerListeners.some(function addManagerListener_matchListener(i) { + return i == aListener; })) this.managerListeners.push(aListener); }, @@ -2657,7 +2289,7 @@ var AddonManagerInternal = { * @param aListener * The listener to remove */ - removeManagerListener: function(aListener) { + removeManagerListener: function AMI_removeManagerListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be an AddonManagerListener object", Cr.NS_ERROR_INVALID_ARG); @@ -2677,12 +2309,13 @@ var AddonManagerInternal = { * @param aListener * The AddonListener to add */ - addAddonListener: function(aListener) { + addAddonListener: function AMI_addAddonListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be an AddonListener object", Cr.NS_ERROR_INVALID_ARG); - if (!this.addonListeners.some(i => i == aListener)) + if (!this.addonListeners.some(function addAddonListener_matchListener(i) { + return i == aListener; })) this.addonListeners.push(aListener); }, @@ -2692,7 +2325,7 @@ var AddonManagerInternal = { * @param aListener * The AddonListener to remove */ - removeAddonListener: function(aListener) { + removeAddonListener: function AMI_removeAddonListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be an AddonListener object", Cr.NS_ERROR_INVALID_ARG); @@ -2712,12 +2345,13 @@ var AddonManagerInternal = { * @param aListener * The TypeListener to add */ - addTypeListener: function(aListener) { + addTypeListener: function AMI_addTypeListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be a TypeListener object", Cr.NS_ERROR_INVALID_ARG); - if (!this.typeListeners.some(i => i == aListener)) + if (!this.typeListeners.some(function addTypeListener_matchListener(i) { + return i == aListener; })) this.typeListeners.push(aListener); }, @@ -2727,7 +2361,7 @@ var AddonManagerInternal = { * @param aListener * The TypeListener to remove */ - removeTypeListener: function(aListener) { + removeTypeListener: function AMI_removeTypeListener(aListener) { if (!aListener || typeof aListener != "object") throw Components.Exception("aListener must be a TypeListener object", Cr.NS_ERROR_INVALID_ARG); @@ -2857,169 +2491,6 @@ var AddonManagerInternal = { Services.prefs.setBoolPref(PREF_EM_UPDATE_ENABLED, aValue); return aValue; }, - - get hotfixID() { - return gHotfixID; - }, - - webAPI: { - // installs maps integer ids to AddonInstall instances. - installs: new Map(), - nextInstall: 0, - - sendEvent: null, - setEventHandler(fn) { - this.sendEvent = fn; - }, - - getAddonByID(target, id) { - return new Promise(resolve => { - AddonManager.getAddonByID(id, (addon) => { - resolve(webAPIForAddon(addon)); - }); - }); - }, - - // helper to copy (and convert) the properties we care about - copyProps(install, obj) { - obj.state = AddonManager.stateToString(install.state); - obj.error = AddonManager.errorToString(install.error); - obj.progress = install.progress; - obj.maxProgress = install.maxProgress; - }, - - makeListener(id, mm) { - const events = [ - "onDownloadStarted", - "onDownloadProgress", - "onDownloadEnded", - "onDownloadCancelled", - "onDownloadFailed", - "onInstallStarted", - "onInstallEnded", - "onInstallCancelled", - "onInstallFailed", - ]; - - let listener = {}; - events.forEach(event => { - listener[event] = (install) => { - let data = {event, id}; - AddonManager.webAPI.copyProps(install, data); - this.sendEvent(mm, data); - } - }); - return listener; - }, - - forgetInstall(id) { - let info = this.installs.get(id); - if (!info) { - throw new Error(`forgetInstall cannot find ${id}`); - } - info.install.removeListener(info.listener); - this.installs.delete(id); - }, - - createInstall(target, options) { - // Throw an appropriate error if the given URL is not valid - // as an installation source. Return silently if it is okay. - function checkInstallUrl(url) { - let host = Services.io.newURI(options.url, null, null).host; - if (WEBAPI_INSTALL_HOSTS.includes(host)) { - return; - } - if (Services.prefs.getBoolPref(PREF_WEBAPI_TESTING) - && WEBAPI_TEST_INSTALL_HOSTS.includes(host)) { - return; - } - - throw new Error(`Install from ${host} not permitted`); - } - - return new Promise((resolve, reject) => { - try { - checkInstallUrl(options.url); - } catch (err) { - reject({message: err.message}); - return; - } - - let newInstall = install => { - let id = this.nextInstall++; - let listener = this.makeListener(id, target.messageManager); - install.addListener(listener); - - this.installs.set(id, {install, target, listener}); - - let result = {id}; - this.copyProps(install, result); - resolve(result); - }; - AddonManager.getInstallForURL(options.url, newInstall, "application/x-xpinstall", options.hash); - }); - }, - - addonUninstall(target, id) { - return new Promise(resolve => { - AddonManager.getAddonByID(id, addon => { - if (!addon) { - resolve(false); - } - - try { - addon.uninstall(); - resolve(true); - } catch (err) { - Cu.reportError(err); - resolve(false); - } - }); - }); - }, - - addonSetEnabled(target, id, value) { - return new Promise((resolve, reject) => { - AddonManager.getAddonByID(id, addon => { - if (!addon) { - reject({message: `No such addon ${id}`}); - } - addon.userDisabled = !value; - resolve(); - }); - }); - }, - - addonInstallDoInstall(target, id) { - let state = this.installs.get(id); - if (!state) { - return Promise.reject(`invalid id ${id}`); - } - return Promise.resolve(state.install.install()); - }, - - addonInstallCancel(target, id) { - let state = this.installs.get(id); - if (!state) { - return Promise.reject(`invalid id ${id}`); - } - return Promise.resolve(state.install.cancel()); - }, - - clearInstalls(ids) { - for (let id of ids) { - this.forgetInstall(id); - } - }, - - clearInstallsFrom(mm) { - for (let [id, info] of this.installs) { - if (info.target.messageManager == mm) { - this.forgetInstall(id); - } - } - }, - }, }; /** @@ -3029,33 +2500,29 @@ var AddonManagerInternal = { * subject to change at any time. */ this.AddonManagerPrivate = { - startup: function() { + startup: function AMP_startup() { AddonManagerInternal.startup(); }, - registerProvider: function(aProvider, aTypes) { + registerProvider: function AMP_registerProvider(aProvider, aTypes) { AddonManagerInternal.registerProvider(aProvider, aTypes); }, - unregisterProvider: function(aProvider) { + unregisterProvider: function AMP_unregisterProvider(aProvider) { AddonManagerInternal.unregisterProvider(aProvider); }, - markProviderSafe: function(aProvider) { + markProviderSafe: function AMP_markProviderSafe(aProvider) { AddonManagerInternal.markProviderSafe(aProvider); }, - backgroundUpdateCheck: function() { + backgroundUpdateCheck: function AMP_backgroundUpdateCheck() { return AddonManagerInternal.backgroundUpdateCheck(); }, backgroundUpdateTimerHandler() { // Don't call through to the real update check if no checks are enabled. - let checkHotfix = AddonManagerInternal.hotfixID && - Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) && - Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO); - - if (!AddonManagerInternal.updateEnabled && !checkHotfix) { + if (!AddonManagerInternal.updateEnabled) { logger.info("Skipping background update check"); return; } @@ -3063,32 +2530,32 @@ this.AddonManagerPrivate = { AddonManagerInternal.backgroundUpdateCheck(); }, - addStartupChange: function(aType, aID) { + addStartupChange: function AMP_addStartupChange(aType, aID) { AddonManagerInternal.addStartupChange(aType, aID); }, - removeStartupChange: function(aType, aID) { + removeStartupChange: function AMP_removeStartupChange(aType, aID) { AddonManagerInternal.removeStartupChange(aType, aID); }, - notifyAddonChanged: function(aID, aType, aPendingRestart) { + notifyAddonChanged: function AMP_notifyAddonChanged(aID, aType, aPendingRestart) { AddonManagerInternal.notifyAddonChanged(aID, aType, aPendingRestart); }, - updateAddonAppDisabledStates: function() { + updateAddonAppDisabledStates: function AMP_updateAddonAppDisabledStates() { AddonManagerInternal.updateAddonAppDisabledStates(); }, - updateAddonRepositoryData: function(aCallback) { + updateAddonRepositoryData: function AMP_updateAddonRepositoryData(aCallback) { AddonManagerInternal.updateAddonRepositoryData(aCallback); }, - callInstallListeners: function(...aArgs) { + callInstallListeners: function AMP_callInstallListeners(...aArgs) { return AddonManagerInternal.callInstallListeners.apply(AddonManagerInternal, aArgs); }, - callAddonListeners: function(...aArgs) { + callAddonListeners: function AMP_callAddonListeners(...aArgs) { AddonManagerInternal.callAddonListeners.apply(AddonManagerInternal, aArgs); }, @@ -3100,16 +2567,16 @@ this.AddonManagerPrivate = { AddonType: AddonType, - recordTimestamp: function(name, value) { + recordTimestamp: function AMP_recordTimestamp(name, value) { AddonManagerInternal.recordTimestamp(name, value); }, _simpleMeasures: {}, - recordSimpleMeasure: function(name, value) { + recordSimpleMeasure: function AMP_recordSimpleMeasure(name, value) { this._simpleMeasures[name] = value; }, - recordException: function(aModule, aContext, aException) { + recordException: function AMP_recordException(aModule, aContext, aException) { let report = { module: aModule, context: aContext @@ -3129,15 +2596,15 @@ this.AddonManagerPrivate = { this._simpleMeasures.exception = report; }, - getSimpleMeasures: function() { + getSimpleMeasures: function AMP_getSimpleMeasures() { return this._simpleMeasures; }, - getTelemetryDetails: function() { + getTelemetryDetails: function AMP_getTelemetryDetails() { return AddonManagerInternal.telemetryDetails; }, - setTelemetryDetails: function(aProvider, aDetails) { + setTelemetryDetails: function AMP_setTelemetryDetails(aProvider, aDetails) { AddonManagerInternal.telemetryDetails[aProvider] = aDetails; }, @@ -3156,7 +2623,7 @@ this.AddonManagerPrivate = { * This can be used as an implementation for Addon.findUpdates() when * no update mechanism is available. */ - callNoUpdateListeners: function(addon, listener, reason, appVersion, platformVersion) { + callNoUpdateListeners: function (addon, listener, reason, appVersion, platformVersion) { if ("onNoCompatibilityUpdateAvailable" in listener) { safeCall(listener.onNoCompatibilityUpdateAvailable.bind(listener), addon); } @@ -3167,18 +2634,6 @@ this.AddonManagerPrivate = { safeCall(listener.onUpdateFinished.bind(listener), addon); } }, - - get webExtensionsMinPlatformVersion() { - return gWebExtensionsMinPlatformVersion; - }, - - hasUpgradeListener: function(aId) { - return AddonManagerInternal.upgradeListeners.has(aId); - }, - - getUpgradeListener: function(aId) { - return AddonManagerInternal.upgradeListeners.get(aId); - }, }; /** @@ -3187,49 +2642,37 @@ this.AddonManagerPrivate = { */ this.AddonManager = { // Constants for the AddonInstall.state property - // These will show up as AddonManager.STATE_* (eg, STATE_AVAILABLE) - _states: new Map([ - // The install is available for download. - ["STATE_AVAILABLE", 0], - // The install is being downloaded. - ["STATE_DOWNLOADING", 1], - // The install is checking for compatibility information. - ["STATE_CHECKING", 2], - // The install is downloaded and ready to install. - ["STATE_DOWNLOADED", 3], - // The download failed. - ["STATE_DOWNLOAD_FAILED", 4], - // The install has been postponed. - ["STATE_POSTPONED", 5], - // The add-on is being installed. - ["STATE_INSTALLING", 6], - // The add-on has been installed. - ["STATE_INSTALLED", 7], - // The install failed. - ["STATE_INSTALL_FAILED", 8], - // The install has been cancelled. - ["STATE_CANCELLED", 9], - ]), + // The install is available for download. + STATE_AVAILABLE: 0, + // The install is being downloaded. + STATE_DOWNLOADING: 1, + // The install is checking for compatibility information. + STATE_CHECKING: 2, + // The install is downloaded and ready to install. + STATE_DOWNLOADED: 3, + // The download failed. + STATE_DOWNLOAD_FAILED: 4, + // The add-on is being installed. + STATE_INSTALLING: 5, + // The add-on has been installed. + STATE_INSTALLED: 6, + // The install failed. + STATE_INSTALL_FAILED: 7, + // The install has been cancelled. + STATE_CANCELLED: 8, // Constants representing different types of errors while downloading an // add-on. - // These will show up as AddonManager.ERROR_* (eg, ERROR_NETWORK_FAILURE) - _errors: new Map([ - // The download failed due to network problems. - ["ERROR_NETWORK_FAILURE", -1], - // The downloaded file did not match the provided hash. - ["ERROR_INCORRECT_HASH", -2], - // The downloaded file seems to be corrupted in some way. - ["ERROR_CORRUPT_FILE", -3], - // An error occured trying to write to the filesystem. - ["ERROR_FILE_ACCESS", -4], - // The add-on must be signed and isn't. - ["ERROR_SIGNEDSTATE_REQUIRED", -5], - // The downloaded add-on had a different type than expected. - ["ERROR_UNEXPECTED_ADDON_TYPE", -6], - // The addon did not have the expected ID - ["ERROR_INCORRECT_ID", -7], - ]), + // The download failed due to network problems. + ERROR_NETWORK_FAILURE: -1, + // The downloaded file did not match the provided hash. + ERROR_INCORRECT_HASH: -2, + // The downloaded file seems to be corrupted in some way. + ERROR_CORRUPT_FILE: -3, + // An error occured trying to write to the filesystem. + ERROR_FILE_ACCESS: -4, + // The downloaded file seems to be WebExtension. + ERROR_WEBEXT_FILE: -9, // These must be kept in sync with AddonUpdateChecker. // No error was encountered. @@ -3307,10 +2750,8 @@ this.AddonManager = { SCOPE_APPLICATION: 4, // Installed for all users of the computer. SCOPE_SYSTEM: 8, - // Installed temporarily - SCOPE_TEMPORARY: 16, // The combination of all scopes. - SCOPE_ALL: 31, + SCOPE_ALL: 15, // Add-on type is expected to be displayed in the UI in a list. VIEW_TYPE_LIST: "list", @@ -3348,10 +2789,6 @@ this.AddonManager = { // Same as OPTIONS_TYPE_INLINE, but no Preferences button will be shown. // Used to indicate that only non-interactive information will be shown. OPTIONS_TYPE_INLINE_INFO: 4, - // Similar to OPTIONS_TYPE_INLINE, but rather than generating inline - // options from a specially-formatted XUL file, the contents of the - // file are simply displayed in an inline <browser> element. - OPTIONS_TYPE_INLINE_BROWSER: 5, // Constants for displayed or hidden options notifications // Options notification will be displayed @@ -3379,67 +2816,30 @@ this.AddonManager = { // add-ons that were pending being enabled the last time the application ran. STARTUP_CHANGE_ENABLED: "enabled", - // Constants for Addon.signedState. Any states that should cause an add-on - // to be unusable in builds that require signing should have negative values. - // Add-on signing is not required, e.g. because the pref is disabled. - SIGNEDSTATE_NOT_REQUIRED: undefined, - // Add-on is signed but signature verification has failed. - SIGNEDSTATE_BROKEN: -2, - // Add-on may be signed but by an certificate that doesn't chain to our - // our trusted certificate. - SIGNEDSTATE_UNKNOWN: -1, - // Add-on is unsigned. - SIGNEDSTATE_MISSING: 0, - // Add-on is preliminarily reviewed. - SIGNEDSTATE_PRELIMINARY: 1, - // Add-on is fully reviewed. - SIGNEDSTATE_SIGNED: 2, - // Add-on is system add-on. - SIGNEDSTATE_SYSTEM: 3, - // Constants for the Addon.userDisabled property // Indicates that the userDisabled state of this add-on is currently // ask-to-activate. That is, it can be conditionally enabled on a // case-by-case basis. STATE_ASK_TO_ACTIVATE: "askToActivate", +#ifdef MOZ_EM_DEBUG get __AddonManagerInternal__() { - return AppConstants.DEBUG ? AddonManagerInternal : undefined; + return AddonManagerInternal; }, +#endif get isReady() { return gStartupComplete && !gShutdownInProgress; }, - init() { - this._stateToString = new Map(); - for (let [name, value] of this._states) { - this[name] = value; - this._stateToString.set(value, name); - } - this._errorToString = new Map(); - for (let [name, value] of this._errors) { - this[name] = value; - this._errorToString.set(value, name); - } - }, - - stateToString(state) { - return this._stateToString.get(state); - }, - - errorToString(err) { - return err ? this._errorToString.get(err) : null; - }, - - getInstallForURL: function(aUrl, aCallback, aMimetype, + getInstallForURL: function AM_getInstallForURL(aUrl, aCallback, aMimetype, aHash, aName, aIcons, aVersion, aBrowser) { AddonManagerInternal.getInstallForURL(aUrl, aCallback, aMimetype, aHash, aName, aIcons, aVersion, aBrowser); }, - getInstallForFile: function(aFile, aCallback, aMimetype) { + getInstallForFile: function AM_getInstallForFile(aFile, aCallback, aMimetype) { AddonManagerInternal.getInstallForFile(aFile, aCallback, aMimetype); }, @@ -3450,128 +2850,94 @@ this.AddonManager = { * The type of startup change to get * @return An array of add-on IDs */ - getStartupChanges: function(aType) { + getStartupChanges: function AM_getStartupChanges(aType) { if (!(aType in AddonManagerInternal.startupChanges)) return []; return AddonManagerInternal.startupChanges[aType].slice(0); }, - getAddonByID: function(aID, aCallback) { - if (typeof aCallback != "function") - throw Components.Exception("aCallback must be a function", - Cr.NS_ERROR_INVALID_ARG); - - AddonManagerInternal.getAddonByID(aID) - .then(makeSafe(aCallback)) - .catch(logger.error); + getAddonByID: function AM_getAddonByID(aID, aCallback) { + AddonManagerInternal.getAddonByID(aID, aCallback); }, - getAddonBySyncGUID: function(aGUID, aCallback) { + getAddonBySyncGUID: function AM_getAddonBySyncGUID(aGUID, aCallback) { AddonManagerInternal.getAddonBySyncGUID(aGUID, aCallback); }, - getAddonsByIDs: function(aIDs, aCallback) { - if (typeof aCallback != "function") - throw Components.Exception("aCallback must be a function", - Cr.NS_ERROR_INVALID_ARG); - - AddonManagerInternal.getAddonsByIDs(aIDs) - .then(makeSafe(aCallback)) - .catch(logger.error); + getAddonsByIDs: function AM_getAddonsByIDs(aIDs, aCallback) { + AddonManagerInternal.getAddonsByIDs(aIDs, aCallback); }, - getAddonsWithOperationsByTypes: function(aTypes, aCallback) { + getAddonsWithOperationsByTypes: + function AM_getAddonsWithOperationsByTypes(aTypes, aCallback) { AddonManagerInternal.getAddonsWithOperationsByTypes(aTypes, aCallback); }, - getAddonsByTypes: function(aTypes, aCallback) { + getAddonsByTypes: function AM_getAddonsByTypes(aTypes, aCallback) { AddonManagerInternal.getAddonsByTypes(aTypes, aCallback); }, - getAllAddons: function(aCallback) { + getAllAddons: function AM_getAllAddons(aCallback) { AddonManagerInternal.getAllAddons(aCallback); }, - getInstallsByTypes: function(aTypes, aCallback) { + getInstallsByTypes: function AM_getInstallsByTypes(aTypes, aCallback) { AddonManagerInternal.getInstallsByTypes(aTypes, aCallback); }, - getAllInstalls: function(aCallback) { + getAllInstalls: function AM_getAllInstalls(aCallback) { AddonManagerInternal.getAllInstalls(aCallback); }, - mapURIToAddonID: function(aURI) { + mapURIToAddonID: function AM_mapURIToAddonID(aURI) { return AddonManagerInternal.mapURIToAddonID(aURI); }, - isInstallEnabled: function(aType) { + isInstallEnabled: function AM_isInstallEnabled(aType) { return AddonManagerInternal.isInstallEnabled(aType); }, - isInstallAllowed: function(aType, aInstallingPrincipal) { - return AddonManagerInternal.isInstallAllowed(aType, aInstallingPrincipal); + isInstallAllowed: function AM_isInstallAllowed(aType, aInstallingPrincipal) { + return AddonManagerInternal.isInstallAllowed(aType, ensurePrincipal(aInstallingPrincipal)); }, - installAddonsFromWebpage: function(aType, aBrowser, aInstallingPrincipal, - aInstalls) { + installAddonsFromWebpage: function AM_installAddonsFromWebpage(aType, aBrowser, + aInstallingPrincipal, + aInstalls) { AddonManagerInternal.installAddonsFromWebpage(aType, aBrowser, - aInstallingPrincipal, + ensurePrincipal(aInstallingPrincipal), aInstalls); }, - installTemporaryAddon: function(aDirectory) { - return AddonManagerInternal.installTemporaryAddon(aDirectory); - }, - - installAddonFromSources: function(aDirectory) { - return AddonManagerInternal.installAddonFromSources(aDirectory); - }, - - getAddonByInstanceID: function(aInstanceID) { - return AddonManagerInternal.getAddonByInstanceID(aInstanceID); - }, - - addManagerListener: function(aListener) { + addManagerListener: function AM_addManagerListener(aListener) { AddonManagerInternal.addManagerListener(aListener); }, - removeManagerListener: function(aListener) { + removeManagerListener: function AM_removeManagerListener(aListener) { AddonManagerInternal.removeManagerListener(aListener); }, - addInstallListener: function(aListener) { + addInstallListener: function AM_addInstallListener(aListener) { AddonManagerInternal.addInstallListener(aListener); }, - removeInstallListener: function(aListener) { + removeInstallListener: function AM_removeInstallListener(aListener) { AddonManagerInternal.removeInstallListener(aListener); }, - getUpgradeListener: function(aId) { - return AddonManagerInternal.upgradeListeners.get(aId); - }, - - addUpgradeListener: function(aInstanceID, aCallback) { - AddonManagerInternal.addUpgradeListener(aInstanceID, aCallback); - }, - - removeUpgradeListener: function(aInstanceID) { - AddonManagerInternal.removeUpgradeListener(aInstanceID); - }, - - addAddonListener: function(aListener) { + addAddonListener: function AM_addAddonListener(aListener) { AddonManagerInternal.addAddonListener(aListener); }, - removeAddonListener: function(aListener) { + removeAddonListener: function AM_removeAddonListener(aListener) { AddonManagerInternal.removeAddonListener(aListener); }, - addTypeListener: function(aListener) { + addTypeListener: function AM_addTypeListener(aListener) { AddonManagerInternal.addTypeListener(aListener); }, - removeTypeListener: function(aListener) { + removeTypeListener: function AM_removeTypeListener(aListener) { AddonManagerInternal.removeTypeListener(aListener); }, @@ -3586,7 +2952,7 @@ this.AddonManager = { * The Addon representing the add-on * @return true if the addon should auto-update, false otherwise. */ - shouldAutoUpdate: function(aAddon) { + shouldAutoUpdate: function AM_shouldAutoUpdate(aAddon) { if (!aAddon || typeof aAddon != "object") throw Components.Exception("aAddon must be specified", Cr.NS_ERROR_INVALID_ARG); @@ -3644,29 +3010,15 @@ this.AddonManager = { AddonManagerInternal.autoUpdateDefault = aValue; }, - get hotfixID() { - return AddonManagerInternal.hotfixID; - }, - - escapeAddonURI: function(aAddon, aUri, aAppVersion) { + escapeAddonURI: function AM_escapeAddonURI(aAddon, aUri, aAppVersion) { return AddonManagerInternal.escapeAddonURI(aAddon, aUri, aAppVersion); }, - getPreferredIconURL: function(aAddon, aSize, aWindow = undefined) { - return AddonManagerInternal.getPreferredIconURL(aAddon, aSize, aWindow); - }, - - get webAPI() { - return AddonManagerInternal.webAPI; - }, - get shutdown() { return gShutdownBarrier.client; }, }; -this.AddonManager.init(); - // load the timestamps module into AddonManagerInternal Cu.import("resource://gre/modules/TelemetryTimestamps.jsm", AddonManagerInternal); Object.freeze(AddonManagerInternal); |