diff --git a/toolkit/components/extensions/Extension.jsm b/toolkit/components/extensions/Extension.jsm index 2d8bf31b4c47..1d4b732f2545 100644 --- a/toolkit/components/extensions/Extension.jsm +++ b/toolkit/components/extensions/Extension.jsm @@ -1215,12 +1215,10 @@ class MockExtension { } } -let _browserUpdated = false; - // We create one instance of this class per extension. |addonData| // comes directly from bootstrap.js when initializing. this.Extension = class extends ExtensionData { - constructor(addonData, startupReason) { + constructor(addonData) { super(addonData.resourceURI); this.uuid = UUIDMap.get(addonData.id); @@ -1232,8 +1230,6 @@ this.Extension = class extends ExtensionData { } this.addonData = addonData; - this.startupReason = startupReason; - this.id = addonData.id; this.baseURI = NetUtil.newURI(this.getURL("")).QueryInterface(Ci.nsIURL); this.principal = this.createPrincipal(); @@ -1252,14 +1248,6 @@ this.Extension = class extends ExtensionData { this.emitter = new EventEmitter(); } - static set browserUpdated(updated) { - _browserUpdated = updated; - } - - static get browserUpdated() { - return _browserUpdated; - } - /** * This code is designed to make it easy to test a WebExtension * without creating a bunch of files. Everything is contained in a diff --git a/toolkit/components/extensions/ExtensionXPCShellUtils.jsm b/toolkit/components/extensions/ExtensionXPCShellUtils.jsm index 339709a19d1c..946975663d0b 100644 --- a/toolkit/components/extensions/ExtensionXPCShellUtils.jsm +++ b/toolkit/components/extensions/ExtensionXPCShellUtils.jsm @@ -20,11 +20,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "Schemas", XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm"); -XPCOMUtils.defineLazyGetter(this, "Management", () => { - const {Management} = Cu.import("resource://gre/modules/Extension.jsm", {}); - return Management; -}); - /* exported ExtensionTestUtils */ let BASE_MANIFEST = Object.freeze({ @@ -55,8 +50,6 @@ class ExtensionWrapper { this.messageQueue = new Set(); - this.attachListeners(); - this.testScope.do_register_cleanup(() => { if (this.messageQueue.size) { let names = Array.from(this.messageQueue, ([msg]) => msg); @@ -68,6 +61,32 @@ class ExtensionWrapper { } }); + /* eslint-disable mozilla/balanced-listeners */ + extension.on("test-eq", (kind, pass, msg, expected, actual) => { + this.testScope.ok(pass, `${msg} - Expected: ${expected}, Actual: ${actual}`); + }); + extension.on("test-log", (kind, pass, msg) => { + this.testScope.do_print(msg); + }); + extension.on("test-result", (kind, pass, msg) => { + this.testScope.ok(pass, msg); + }); + extension.on("test-done", (kind, pass, msg, expected, actual) => { + this.testScope.ok(pass, msg); + this.testResolve(msg); + }); + + extension.on("test-message", (kind, msg, ...args) => { + let handler = this.messageHandler.get(msg); + if (handler) { + handler(...args); + } else { + this.messageQueue.add([msg, ...args]); + this.checkMessages(); + } + }); + /* eslint-enable mozilla/balanced-listeners */ + this.testScope.do_register_cleanup(() => { if (this.state == "pending" || this.state == "running") { this.testScope.equal(this.state, "unloaded", "Extension left running at test shutdown"); @@ -80,34 +99,6 @@ class ExtensionWrapper { this.testScope.do_print(`Extension loaded`); } - attachListeners() { - /* eslint-disable mozilla/balanced-listeners */ - this.extension.on("test-eq", (kind, pass, msg, expected, actual) => { - this.testScope.ok(pass, `${msg} - Expected: ${expected}, Actual: ${actual}`); - }); - this.extension.on("test-log", (kind, pass, msg) => { - this.testScope.do_print(msg); - }); - this.extension.on("test-result", (kind, pass, msg) => { - this.testScope.ok(pass, msg); - }); - this.extension.on("test-done", (kind, pass, msg, expected, actual) => { - this.testScope.ok(pass, msg); - this.testResolve(msg); - }); - - this.extension.on("test-message", (kind, msg, ...args) => { - let handler = this.messageHandler.get(msg); - if (handler) { - handler(...args); - } else { - this.messageQueue.add([msg, ...args]); - this.checkMessages(); - } - }); - /* eslint-enable mozilla/balanced-listeners */ - } - startup() { if (this.state != "uninitialized") { throw new Error("Extension already started"); @@ -209,6 +200,8 @@ var ExtensionTestUtils = { BASE_MANIFEST, normalizeManifest: Task.async(function* (manifest, baseManifest = BASE_MANIFEST) { + const {Management} = Cu.import("resource://gre/modules/Extension.jsm", {}); + yield Management.lazyInit(); let errors = []; diff --git a/toolkit/components/extensions/ext-backgroundPage.js b/toolkit/components/extensions/ext-backgroundPage.js index a43e5d77fa42..c1e84d66d351 100644 --- a/toolkit/components/extensions/ext-backgroundPage.js +++ b/toolkit/components/extensions/ext-backgroundPage.js @@ -101,7 +101,11 @@ BackgroundPage.prototype = { .then(addon => addon.setDebugGlobal(window)); } - this.extension.emit("startup"); + // TODO(robwu): This implementation of onStartup is wrong, see + // https://bugzil.la/1247435#c1 + if (this.extension.onStartup) { + this.extension.onStartup(); + } }), shutdown() { diff --git a/toolkit/components/extensions/ext-runtime.js b/toolkit/components/extensions/ext-runtime.js index 3bc15577bd51..352a228a0d9b 100644 --- a/toolkit/components/extensions/ext-runtime.js +++ b/toolkit/components/extensions/ext-runtime.js @@ -8,44 +8,28 @@ Cu.import("resource://gre/modules/ExtensionUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Extension", - "resource://gre/modules/Extension.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "ExtensionManagement", "resource://gre/modules/ExtensionManagement.jsm"); var { - ignoreEvent, + EventManager, SingletonEventManager, + ignoreEvent, } = ExtensionUtils; extensions.registerSchemaAPI("runtime", "addon_parent", context => { let {extension} = context; return { runtime: { - onStartup: ignoreEvent(context, "runtime.onStartup"), - - onInstalled: new SingletonEventManager(context, "runtime.onInstalled", fire => { - let listener = () => { - switch (extension.startupReason) { - case "APP_STARTUP": - if (Extension.browserUpdated) { - fire({reason: "browser_update"}); - } - break; - case "ADDON_INSTALL": - fire({reason: "install"}); - break; - case "ADDON_UPGRADE": - fire({reason: "update"}); - break; - } - }; - extension.on("startup", listener); + onStartup: new EventManager(context, "runtime.onStartup", fire => { + extension.onStartup = fire; return () => { - extension.off("startup", listener); + extension.onStartup = null; }; }).api(), + onInstalled: ignoreEvent(context, "runtime.onInstalled"), + onUpdateAvailable: new SingletonEventManager(context, "runtime.onUpdateAvailable", fire => { let instanceID = extension.addonData.instanceID; AddonManager.addUpgradeListener(instanceID, upgrade => { diff --git a/toolkit/components/extensions/schemas/runtime.json b/toolkit/components/extensions/schemas/runtime.json index c19147a46dd0..aa4198b6cf7b 100644 --- a/toolkit/components/extensions/schemas/runtime.json +++ b/toolkit/components/extensions/schemas/runtime.json @@ -122,7 +122,7 @@ { "id": "OnInstalledReason", "type": "string", - "enum": ["install", "update", "browser_update"], + "enum": ["install", "update", "chrome_update", "shared_module_update"], "allowedContexts": ["content"], "description": "The reason that this event is being dispatched." }, @@ -459,6 +459,7 @@ }, { "name": "onInstalled", + "unsupported": true, "type": "function", "description": "Fired when the extension is first installed, when the extension is updated to a new version, and when the browser is updated to a new version.", "parameters": [ @@ -473,13 +474,11 @@ "previousVersion": { "type": "string", "optional": true, - "unsupported": true, "description": "Indicates the previous version of the extension, which has just been updated. This is present only if 'reason' is 'update'." }, "id": { "type": "string", "optional": true, - "unsupported": true, "description": "Indicates the ID of the imported shared module extension which updated. This is present only if 'reason' is 'shared_module_update'." } } diff --git a/toolkit/components/extensions/test/xpcshell/head.js b/toolkit/components/extensions/test/xpcshell/head.js index 9e22be6da7cf..4c6caf950ce6 100644 --- a/toolkit/components/extensions/test/xpcshell/head.js +++ b/toolkit/components/extensions/test/xpcshell/head.js @@ -7,7 +7,6 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; Components.utils.import("resource://gre/modules/Task.jsm"); Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); Components.utils.import("resource://gre/modules/Timer.jsm"); -Components.utils.import("resource://testing-common/AddonTestUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "AppConstants", "resource://gre/modules/AppConstants.jsm"); diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_runtime_onInstalled.js b/toolkit/components/extensions/test/xpcshell/test_ext_runtime_onInstalled.js deleted file mode 100644 index b37b6a07d130..000000000000 --- a/toolkit/components/extensions/test/xpcshell/test_ext_runtime_onInstalled.js +++ /dev/null @@ -1,324 +0,0 @@ -/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* vim: set sts=2 sw=2 et tw=80: */ -"use strict"; - -XPCOMUtils.defineLazyGetter(this, "Management", () => { - const {Management} = Cu.import("resource://gre/modules/Extension.jsm", {}); - return Management; -}); - -const { - createAppInfo, - createTempWebExtensionFile, - promiseAddonByID, - promiseAddonEvent, - promiseCompleteAllInstalls, - promiseFindAddonUpdates, - promiseRestartManager, - promiseShutdownManager, - promiseStartupManager, -} = AddonTestUtils; - -AddonTestUtils.init(this); - -// Allow for unsigned addons. -AddonTestUtils.overrideCertDB(); - -createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); - -function awaitEvent(eventName) { - return new Promise(resolve => { - let listener = (_eventName, extension) => { - if (_eventName === eventName) { - Management.off(eventName, listener); - resolve(extension); - } - }; - - Management.on(eventName, listener); - }); -} - -add_task(function* test_should_fire_on_addon_update() { - const EXTENSION_ID = "test_runtime_on_installed_addon_update@tests.mozilla.org"; - - const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity"; - - // The test extension uses an insecure update url. - Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false); - - const testServer = createHttpServer(); - const port = testServer.identity.primaryPort; - - let extension = ExtensionTestUtils.loadExtension({ - useAddonManager: "permanent", - manifest: { - "version": "1.0", - "applications": { - "gecko": { - "id": EXTENSION_ID, - "update_url": `http://localhost:${port}/test_update.json`, - }, - }, - }, - background() { - browser.runtime.onUpdateAvailable.addListener(details => { - browser.test.sendMessage("reloading"); - browser.runtime.reload(); - }); - - browser.runtime.onInstalled.addListener(details => { - browser.test.sendMessage("installed", details); - }); - }, - }); - - testServer.registerPathHandler("/test_update.json", (request, response) => { - response.write(`{ - "addons": { - "${EXTENSION_ID}": { - "updates": [ - { - "version": "2.0", - "update_link": "http://localhost:${port}/addons/test_runtime_on_installed-2.0.xpi" - } - ] - } - } - }`); - }); - - let webExtensionFile = createTempWebExtensionFile({ - manifest: { - version: "2.0", - applications: { - gecko: { - id: EXTENSION_ID, - }, - }, - }, - background() { - browser.runtime.onInstalled.addListener(details => { - browser.test.sendMessage("installed", details); - }); - }, - }); - - testServer.registerFile("/addons/test_runtime_on_installed-2.0.xpi", webExtensionFile); - - yield promiseStartupManager(); - - yield extension.startup(); - let details = yield extension.awaitMessage("installed"); - equal(details.reason, "install", "runtime.onInstalled fired with the correct reason"); - - let addon = yield promiseAddonByID(EXTENSION_ID); - equal(addon.version, "1.0", "The installed addon has the correct version"); - - let update = yield promiseFindAddonUpdates(addon); - let install = update.updateAvailable; - - let promiseInstalled = promiseAddonEvent("onInstalled"); - yield promiseCompleteAllInstalls([install]); - - yield extension.awaitMessage("reloading"); - - let startupPromise = awaitEvent("ready"); - - let [updated_addon] = yield promiseInstalled; - equal(updated_addon.version, "2.0", "The updated addon has the correct version"); - - extension.extension = yield startupPromise; - extension.attachListeners(); - - details = yield extension.awaitMessage("installed"); - equal(details.reason, "update", "runtime.onInstalled fired with the correct reason"); - - yield extension.unload(); - - yield updated_addon.uninstall(); - yield promiseShutdownManager(); -}); - -add_task(function* test_should_fire_on_browser_update() { - const EXTENSION_ID = "test_runtime_on_installed_browser_update@tests.mozilla.org"; - - yield promiseStartupManager(); - - let extension = ExtensionTestUtils.loadExtension({ - useAddonManager: "permanent", - manifest: { - "version": "1.0", - "applications": { - "gecko": { - "id": EXTENSION_ID, - }, - }, - }, - background() { - let onInstalledDetails = null; - - browser.runtime.onInstalled.addListener(details => { - onInstalledDetails = details; - }); - - browser.test.onMessage.addListener(message => { - if (message == "get-on-installed-details") { - browser.test.sendMessage("on-installed-details", onInstalledDetails); - } - }); - }, - }); - - yield extension.startup(); - - extension.sendMessage("get-on-installed-details"); - let details = yield extension.awaitMessage("on-installed-details"); - equal(details.reason, "install", "runtime.onInstalled fired with the correct reason"); - - let startupPromise = awaitEvent("ready"); - yield promiseRestartManager("1"); - extension.extension = yield startupPromise; - extension.attachListeners(); - - extension.sendMessage("get-on-installed-details"); - details = yield extension.awaitMessage("on-installed-details"); - equal(details, null, "runtime.onInstalled should not have fired"); - - // Update the browser. - startupPromise = awaitEvent("ready"); - yield promiseRestartManager("2"); - extension.extension = yield startupPromise; - extension.attachListeners(); - - extension.sendMessage("get-on-installed-details"); - details = yield extension.awaitMessage("on-installed-details"); - equal(details.reason, "browser_update", "runtime.onInstalled fired with the correct reason"); - - // Restart the browser. - startupPromise = awaitEvent("ready"); - yield promiseRestartManager("2"); - extension.extension = yield startupPromise; - extension.attachListeners(); - - extension.sendMessage("get-on-installed-details"); - details = yield extension.awaitMessage("on-installed-details"); - equal(details, null, "runtime.onInstalled should not have fired"); - - // Update the browser again. - startupPromise = awaitEvent("ready"); - yield promiseRestartManager("3"); - extension.extension = yield startupPromise; - extension.attachListeners(); - - extension.sendMessage("get-on-installed-details"); - details = yield extension.awaitMessage("on-installed-details"); - equal(details.reason, "browser_update", "runtime.onInstalled fired with the correct reason"); - - yield extension.unload(); - - yield promiseShutdownManager(); -}); - -add_task(function* test_should_not_fire_on_reload() { - const EXTENSION_ID = "test_runtime_on_installed_reload@tests.mozilla.org"; - - yield promiseStartupManager(); - - let extension = ExtensionTestUtils.loadExtension({ - useAddonManager: "permanent", - manifest: { - "version": "1.0", - "applications": { - "gecko": { - "id": EXTENSION_ID, - }, - }, - }, - background() { - let onInstalledDetails = null; - - browser.runtime.onInstalled.addListener(details => { - onInstalledDetails = details; - }); - - browser.test.onMessage.addListener(message => { - if (message == "reload-extension") { - browser.runtime.reload(); - } else if (message == "get-on-installed-details") { - browser.test.sendMessage("on-installed-details", onInstalledDetails); - } - }); - }, - }); - - yield extension.startup(); - - extension.sendMessage("get-on-installed-details"); - let details = yield extension.awaitMessage("on-installed-details"); - equal(details.reason, "install", "runtime.onInstalled fired with the correct reason"); - - let startupPromise = awaitEvent("ready"); - extension.sendMessage("reload-extension"); - extension.extension = yield startupPromise; - extension.attachListeners(); - - extension.sendMessage("get-on-installed-details"); - details = yield extension.awaitMessage("on-installed-details"); - equal(details, null, "runtime.onInstalled should not have fired"); - - yield extension.unload(); - yield promiseShutdownManager(); -}); - -add_task(function* test_should_not_fire_on_restart() { - const EXTENSION_ID = "test_runtime_on_installed_restart@tests.mozilla.org"; - - yield promiseStartupManager(); - - let extension = ExtensionTestUtils.loadExtension({ - useAddonManager: "permanent", - manifest: { - "version": "1.0", - "applications": { - "gecko": { - "id": EXTENSION_ID, - }, - }, - }, - background() { - let onInstalledDetails = null; - - browser.runtime.onInstalled.addListener(details => { - onInstalledDetails = details; - }); - - browser.test.onMessage.addListener(message => { - if (message == "get-on-installed-details") { - browser.test.sendMessage("on-installed-details", onInstalledDetails); - } - }); - }, - }); - - yield extension.startup(); - - extension.sendMessage("get-on-installed-details"); - let details = yield extension.awaitMessage("on-installed-details"); - equal(details.reason, "install", "runtime.onInstalled fired with the correct reason"); - - let addon = yield promiseAddonByID(EXTENSION_ID); - addon.userDisabled = true; - - let startupPromise = awaitEvent("ready"); - addon.userDisabled = false; - extension.extension = yield startupPromise; - extension.attachListeners(); - - extension.sendMessage("get-on-installed-details"); - details = yield extension.awaitMessage("on-installed-details"); - equal(details, null, "runtime.onInstalled should not have fired"); - - yield extension.markUnloaded(); - yield promiseShutdownManager(); -}); diff --git a/toolkit/components/extensions/test/xpcshell/xpcshell.ini b/toolkit/components/extensions/test/xpcshell/xpcshell.ini index 513f55b171a4..760cca09ea03 100644 --- a/toolkit/components/extensions/test/xpcshell/xpcshell.ini +++ b/toolkit/components/extensions/test/xpcshell/xpcshell.ini @@ -46,7 +46,6 @@ skip-if = release_or_beta [test_ext_runtime_connect_no_receiver.js] [test_ext_runtime_getBrowserInfo.js] [test_ext_runtime_getPlatformInfo.js] -[test_ext_runtime_onInstalled.js] [test_ext_runtime_sendMessage.js] [test_ext_runtime_sendMessage_errors.js] [test_ext_runtime_sendMessage_no_receiver.js] diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm index 755709defbbf..07b32bff8319 100644 --- a/toolkit/mozapps/extensions/AddonManager.jsm +++ b/toolkit/mozapps/extensions/AddonManager.jsm @@ -85,8 +85,6 @@ 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"); @@ -852,8 +850,6 @@ var AddonManagerInternal = { } catch (e) { } - Extension.browserUpdated = appChanged; - let oldPlatformVersion = null; try { oldPlatformVersion = Services.prefs.getCharPref(PREF_EM_LAST_PLATFORM_VERSION); diff --git a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm b/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm index 1cfcca4cbeb5..bc5d362ba9a2 100644 --- a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm +++ b/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm @@ -1087,65 +1087,6 @@ var AddonTestUtils = { return new Promise(resolve => AddonManager.getAddonByID(id, resolve)); }, - /** - * Returns a promise that will be resolved when an add-on update check is - * complete. The value resolved will be an AddonInstall if a new version was - * found. - * - * @param {object} addon The add-on to find updates for. - * @param {integer} reason The type of update to find. - * @return {Promise} an object containing information about the update. - */ - promiseFindAddonUpdates(addon, reason = AddonManager.UPDATE_WHEN_PERIODIC_UPDATE) { - let equal = this.testScope.equal; - return new Promise((resolve, reject) => { - let result = {}; - addon.findUpdates({ - onNoCompatibilityUpdateAvailable: function(addon2) { - if ("compatibilityUpdate" in result) { - throw new Error("Saw multiple compatibility update events"); - } - equal(addon, addon2, "onNoCompatibilityUpdateAvailable"); - result.compatibilityUpdate = false; - }, - - onCompatibilityUpdateAvailable: function(addon2) { - if ("compatibilityUpdate" in result) { - throw new Error("Saw multiple compatibility update events"); - } - equal(addon, addon2, "onCompatibilityUpdateAvailable"); - result.compatibilityUpdate = true; - }, - - onNoUpdateAvailable: function(addon2) { - if ("updateAvailable" in result) { - throw new Error("Saw multiple update available events"); - } - equal(addon, addon2, "onNoUpdateAvailable"); - result.updateAvailable = false; - }, - - onUpdateAvailable: function(addon2, install) { - if ("updateAvailable" in result) { - throw new Error("Saw multiple update available events"); - } - equal(addon, addon2, "onUpdateAvailable"); - result.updateAvailable = install; - }, - - onUpdateFinished: function(addon2, error) { - equal(addon, addon2, "onUpdateFinished"); - if (error == AddonManager.UPDATE_STATUS_NO_ERROR) { - resolve(result); - } else { - result.error = error; - reject(result); - } - } - }, reason); - }); - }, - /** * A promise-based variant of AddonManager.getAddonsWithOperationsByTypes * diff --git a/toolkit/mozapps/extensions/internal/WebExtensionBootstrap.js b/toolkit/mozapps/extensions/internal/WebExtensionBootstrap.js index a920c2eae8ba..77404dd9f467 100644 --- a/toolkit/mozapps/extensions/internal/WebExtensionBootstrap.js +++ b/toolkit/mozapps/extensions/internal/WebExtensionBootstrap.js @@ -8,24 +8,13 @@ Components.utils.import("resource://gre/modules/Extension.jsm"); var extension; -const BOOTSTRAP_REASON_TO_STRING_MAP = { - 1: "APP_STARTUP", - 2: "APP_SHUTDOWN", - 3: "ADDON_ENABLE", - 4: "ADDON_DISABLE", - 5: "ADDON_INSTALL", - 6: "ADDON_UNINSTALL", - 7: "ADDON_UPGRADE", - 8: "ADDON_DOWNGRADE", -} - function install(data, reason) { } function startup(data, reason) { - extension = new Extension(data, BOOTSTRAP_REASON_TO_STRING_MAP[reason]); + extension = new Extension(data); extension.startup(); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js index 0e7f374be1a2..a9d711d60fc0 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js +++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js @@ -56,34 +56,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "MockRegistrar", XPCOMUtils.defineLazyModuleGetter(this, "MockRegistry", "resource://testing-common/MockRegistry.jsm"); -const { - awaitPromise, - createAppInfo, - createInstallRDF, - createTempWebExtensionFile, - createUpdateRDF, - getFileForAddon, - manuallyInstall, - manuallyUninstall, - promiseAddonByID, - promiseAddonEvent, - promiseAddonsByIDs, - promiseAddonsWithOperationsByTypes, - promiseCompleteAllInstalls, - promiseConsoleOutput, - promiseFindAddonUpdates, - promiseInstallAllFiles, - promiseInstallFile, - promiseRestartManager, - promiseSetExtensionModifiedTime, - promiseShutdownManager, - promiseStartupManager, - promiseWriteProxyFileToDir, - registerDirectory, - setExtensionModifiedTime, - writeFilesToZip -} = AddonTestUtils; - // WebExtension wrapper for ease of testing ExtensionTestUtils.init(this); @@ -344,6 +316,8 @@ function isNightlyChannel() { return channel != "aurora" && channel != "beta" && channel != "release" && channel != "esr"; } +var {createAppInfo} = AddonTestUtils; + /** * Tests that an add-on does appear in the crash report annotations, if * crash reporting is enabled. The test will fail if the add-on is not in the @@ -602,6 +576,11 @@ function do_check_icons(aActual, aExpected) { } } +var {promiseStartupManager} = AddonTestUtils; +var {promiseRestartManager} = AddonTestUtils; +var {promiseShutdownManager} = AddonTestUtils; +var {awaitPromise} = AddonTestUtils; + function startupManager(aAppChanged) { promiseStartupManager(aAppChanged); } @@ -644,6 +623,9 @@ function check_startup_changes(aType, aIds) { do_check_eq(JSON.stringify(ids), JSON.stringify(changes)); } +var {createUpdateRDF} = AddonTestUtils; +var {createInstallRDF} = AddonTestUtils; + /** * Writes an install.rdf manifest into a directory using the properties passed * in a JS object. The objects should contain a property for each property to @@ -753,6 +735,8 @@ function promiseWriteWebManifestForExtension(aData, aDir, aId = aData.applicatio return AddonTestUtils.promiseWriteFilesToExtension(aDir.path, aId, files); } +var {writeFilesToZip} = AddonTestUtils; + /** * Creates an XPI file for some manifest data in the temporary directory and * returns the nsIFile for it. The file will be deleted when the test completes. @@ -773,6 +757,18 @@ function createTempXPIFile(aData, aExtraFile) { return AddonTestUtils.createTempXPIFile(files); } +var {createTempWebExtensionFile} = AddonTestUtils; + +var {setExtensionModifiedTime} = AddonTestUtils; +var {promiseSetExtensionModifiedTime} = AddonTestUtils; + +var {manuallyInstall} = AddonTestUtils; +var {manuallyUninstall} = AddonTestUtils; + +var {getFileForAddon} = AddonTestUtils; + +var {registerDirectory} = AddonTestUtils; + var gExpectedEvents = {}; var gExpectedInstalls = []; var gNext = null; @@ -1023,6 +1019,10 @@ function ensure_test_completed() { do_check_eq(gExpectedInstalls.length, 0); } +var {promiseAddonEvent} = AddonTestUtils; + +var {promiseCompleteAllInstalls} = AddonTestUtils; + /** * A helper method to install an array of AddonInstall to completion and then * call a provided callback. @@ -1036,6 +1036,8 @@ function completeAllInstalls(aInstalls, aCallback) { promiseCompleteAllInstalls(aInstalls).then(aCallback); } +var {promiseInstallFile, promiseInstallAllFiles} = AddonTestUtils; + /** * A helper method to install an array of files and call a callback after the * installs are completed. @@ -1272,6 +1274,70 @@ function callback_soon(aFunction) { } } +var {promiseAddonsByIDs} = AddonTestUtils; + +var {promiseAddonByID} = AddonTestUtils; + +var {promiseAddonsWithOperationsByTypes} = AddonTestUtils; + +/** + * Returns a promise that will be resolved when an add-on update check is + * complete. The value resolved will be an AddonInstall if a new version was + * found. + */ +function promiseFindAddonUpdates(addon, reason = AddonManager.UPDATE_WHEN_PERIODIC_UPDATE) { + return new Promise((resolve, reject) => { + let result = {}; + addon.findUpdates({ + onNoCompatibilityUpdateAvailable: function(addon2) { + if ("compatibilityUpdate" in result) { + do_throw("Saw multiple compatibility update events"); + } + equal(addon, addon2, "onNoCompatibilityUpdateAvailable"); + result.compatibilityUpdate = false; + }, + + onCompatibilityUpdateAvailable: function(addon2) { + if ("compatibilityUpdate" in result) { + do_throw("Saw multiple compatibility update events"); + } + equal(addon, addon2, "onCompatibilityUpdateAvailable"); + result.compatibilityUpdate = true; + }, + + onNoUpdateAvailable: function(addon2) { + if ("updateAvailable" in result) { + do_throw("Saw multiple update available events"); + } + equal(addon, addon2, "onNoUpdateAvailable"); + result.updateAvailable = false; + }, + + onUpdateAvailable: function(addon2, install) { + if ("updateAvailable" in result) { + do_throw("Saw multiple update available events"); + } + equal(addon, addon2, "onUpdateAvailable"); + result.updateAvailable = install; + }, + + onUpdateFinished: function(addon2, error) { + equal(addon, addon2, "onUpdateFinished"); + if (error == AddonManager.UPDATE_STATUS_NO_ERROR) { + resolve(result); + } else { + result.error = error; + reject(result); + } + } + }, reason); + }); +} + +var {promiseConsoleOutput} = AddonTestUtils; + +var {promiseWriteProxyFileToDir} = AddonTestUtils; + function writeProxyFileToDir(aDir, aAddon, aId) { awaitPromise(promiseWriteProxyFileToDir(aDir, aAddon, aId));