Loading toolkit/mozapps/extensions/AddonManager.jsm +26 −0 Original line number Diff line number Diff line Loading @@ -2246,6 +2246,28 @@ var AddonManagerInternal = { .installTemporaryAddon(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 Loading Loading @@ -3198,6 +3220,10 @@ this.AddonManager = { return AddonManagerInternal.installTemporaryAddon(aDirectory); }, getAddonByInstanceID: function(aInstanceID) { return AddonManagerInternal.getAddonByInstanceID(aInstanceID); }, addManagerListener: function(aListener) { AddonManagerInternal.addManagerListener(aListener); }, Loading toolkit/mozapps/extensions/internal/XPIProvider.jsm +34 −0 Original line number Diff line number Diff line Loading @@ -3881,6 +3881,29 @@ this.XPIProvider = { AddonManagerPrivate.callAddonListeners("onInstalled", addon.wrapper); }), /** * Returns an Addon corresponding to an instance ID. * @param aInstanceID * An Addon Instance ID * @return {Promise} * @resolves The found Addon or null if no such add-on exists. * @rejects Never * @throws if the aInstanceID argument is not specified */ getAddonByInstanceID: function(aInstanceID) { if (!aInstanceID || typeof aInstanceID != "symbol") throw Components.Exception("aInstanceID must be a Symbol()", Cr.NS_ERROR_INVALID_ARG); for (let [id, val] of this.activeAddons) { if (aInstanceID == val.instanceID) { return new Promise(resolve => this.getAddonByID(id, resolve)); } } return Promise.resolve(null); }, /** * Removes an AddonInstall from the list of active installs. * Loading Loading @@ -4451,6 +4474,8 @@ this.XPIProvider = { this.activeAddons.set(aId, { bootstrapScope: null, // a Symbol passed to this add-on, which it can use to identify itself instanceID: Symbol(aId), }); let activeAddon = this.activeAddons.get(aId); Loading Loading @@ -4598,6 +4623,15 @@ this.XPIProvider = { activeAddon = this.activeAddons.get(aAddon.id); } if (aAddon.bootstrap) { if (aMethod == "startup" || aMethod == "shutdown") { if (!aExtraParams) { aExtraParams = {}; } aExtraParams["instanceID"] = this.activeAddons.get(aAddon.id).instanceID; } } // Nothing to call for locales if (aAddon.type == "locale") return; Loading toolkit/mozapps/extensions/test/addons/test_symbol/bootstrap.js 0 → 100644 +62 −0 Original line number Diff line number Diff line Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/AddonManager.jsm"); const PASS_PREF = "symboltest.instanceid.pass"; const FAIL_BOGUS_PREF = "symboltest.instanceid.fail_bogus"; const FAIL_ID_PREF = "symboltest.instanceid.fail_bogus"; const ADDON_ID = "test_symbol@tests.mozilla.org"; function install(data, reason) {} // normally we would use BootstrapMonitor here, but we need a reference to // the symbol inside `XPIProvider.jsm`. function startup(data, reason) { Services.prefs.setBoolPref(PASS_PREF, false); Services.prefs.setBoolPref(FAIL_BOGUS_PREF, false); Services.prefs.setBoolPref(FAIL_ID_PREF, false); // test with the correct symbol if (data.hasOwnProperty("instanceID") && data.instanceID) { AddonManager.getAddonByInstanceID(data.instanceID) .then(addon => { if (addon.id == ADDON_ID) { Services.prefs.setBoolPref(PASS_PREF, true); } }).catch(err => { throw Error("no addon found for symbol"); }); } // test with a totally bogus symbol AddonManager.getAddonByInstanceID(Symbol("bad symbol")) .then(addon => { // there is no symbol by this name, so null should be returned if (addon == null) { Services.prefs.setBoolPref(FAIL_BOGUS_PREF, true); } else { throw Error("bad symbol should not match:", addon); } }).catch(err => { throw Error("promise should not have rejected: " + err); }); // try to make a matching symbol - this should fail because it's not a // reference to the same symbol stored inside the addons manager. AddonManager.getAddonByInstanceID(Symbol(ADDON_ID)) .then(addon => { // there is no symbol by this name, so null should be returned if (addon == null) { Services.prefs.setBoolPref(FAIL_ID_PREF, true); } else { throw Error("bad symbol should not match:", addon); } }).catch(err => { throw Error("promise should not have rejected: " + err); }); } function shutdown(data, reason) {} function uninstall(data, reason) {} toolkit/mozapps/extensions/test/addons/test_symbol/install.rdf 0 → 100644 +28 −0 Original line number Diff line number Diff line <?xml version="1.0"?> <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> <em:id>test_symbol@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:bootstrap>true</em:bootstrap> <!-- Front End MetaData --> <em:name>Test Symbol</em:name> <em:description>Test Description</em:description> <em:iconURL>chrome://foo/skin/icon.png</em:iconURL> <em:aboutURL>chrome://foo/content/about.xul</em:aboutURL> <em:optionsURL>chrome://foo/content/options.xul</em:optionsURL> <em:targetApplication> <Description> <em:id>xpcshell@tests.mozilla.org</em:id> <em:minVersion>1</em:minVersion> <em:maxVersion>1</em:maxVersion> </Description> </em:targetApplication> </Description> </RDF> toolkit/mozapps/extensions/test/xpcshell/test_pass_symbol.js 0 → 100644 +43 −0 Original line number Diff line number Diff line /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ const PASS_PREF = "symboltest.instanceid.pass"; const FAIL_BOGUS_PREF = "symboltest.instanceid.fail_bogus"; const FAIL_ID_PREF = "symboltest.instanceid.fail_bogus"; const ADDON_ID = "test_symbol@tests.mozilla.org"; createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); startupManager(); BootstrapMonitor.init(); // symbol is passed when add-on is installed add_task(function*() { for (let pref of [PASS_PREF, FAIL_BOGUS_PREF, FAIL_ID_PREF]) Services.prefs.clearUserPref(pref); yield promiseInstallAllFiles([do_get_addon("test_symbol")], true); let addon = yield promiseAddonByID(ADDON_ID); do_check_neq(addon, null); do_check_eq(addon.version, "1.0"); do_check_eq(addon.name, "Test Symbol"); do_check_true(addon.isCompatible); do_check_false(addon.appDisabled); do_check_true(addon.isActive); do_check_eq(addon.type, "extension"); // most of the test is in bootstrap.js in the addon because BootstrapMonitor // currently requires the objects in `data` to be serializable, and we // need a real reference to the symbol to test this. do_execute_soon(function() { // give the startup time to run do_check_true(Services.prefs.getBoolPref(PASS_PREF)); do_check_true(Services.prefs.getBoolPref(FAIL_BOGUS_PREF)); do_check_true(Services.prefs.getBoolPref(FAIL_ID_PREF)); }); yield promiseRestartManager(); }); Loading
toolkit/mozapps/extensions/AddonManager.jsm +26 −0 Original line number Diff line number Diff line Loading @@ -2246,6 +2246,28 @@ var AddonManagerInternal = { .installTemporaryAddon(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 Loading Loading @@ -3198,6 +3220,10 @@ this.AddonManager = { return AddonManagerInternal.installTemporaryAddon(aDirectory); }, getAddonByInstanceID: function(aInstanceID) { return AddonManagerInternal.getAddonByInstanceID(aInstanceID); }, addManagerListener: function(aListener) { AddonManagerInternal.addManagerListener(aListener); }, Loading
toolkit/mozapps/extensions/internal/XPIProvider.jsm +34 −0 Original line number Diff line number Diff line Loading @@ -3881,6 +3881,29 @@ this.XPIProvider = { AddonManagerPrivate.callAddonListeners("onInstalled", addon.wrapper); }), /** * Returns an Addon corresponding to an instance ID. * @param aInstanceID * An Addon Instance ID * @return {Promise} * @resolves The found Addon or null if no such add-on exists. * @rejects Never * @throws if the aInstanceID argument is not specified */ getAddonByInstanceID: function(aInstanceID) { if (!aInstanceID || typeof aInstanceID != "symbol") throw Components.Exception("aInstanceID must be a Symbol()", Cr.NS_ERROR_INVALID_ARG); for (let [id, val] of this.activeAddons) { if (aInstanceID == val.instanceID) { return new Promise(resolve => this.getAddonByID(id, resolve)); } } return Promise.resolve(null); }, /** * Removes an AddonInstall from the list of active installs. * Loading Loading @@ -4451,6 +4474,8 @@ this.XPIProvider = { this.activeAddons.set(aId, { bootstrapScope: null, // a Symbol passed to this add-on, which it can use to identify itself instanceID: Symbol(aId), }); let activeAddon = this.activeAddons.get(aId); Loading Loading @@ -4598,6 +4623,15 @@ this.XPIProvider = { activeAddon = this.activeAddons.get(aAddon.id); } if (aAddon.bootstrap) { if (aMethod == "startup" || aMethod == "shutdown") { if (!aExtraParams) { aExtraParams = {}; } aExtraParams["instanceID"] = this.activeAddons.get(aAddon.id).instanceID; } } // Nothing to call for locales if (aAddon.type == "locale") return; Loading
toolkit/mozapps/extensions/test/addons/test_symbol/bootstrap.js 0 → 100644 +62 −0 Original line number Diff line number Diff line Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/AddonManager.jsm"); const PASS_PREF = "symboltest.instanceid.pass"; const FAIL_BOGUS_PREF = "symboltest.instanceid.fail_bogus"; const FAIL_ID_PREF = "symboltest.instanceid.fail_bogus"; const ADDON_ID = "test_symbol@tests.mozilla.org"; function install(data, reason) {} // normally we would use BootstrapMonitor here, but we need a reference to // the symbol inside `XPIProvider.jsm`. function startup(data, reason) { Services.prefs.setBoolPref(PASS_PREF, false); Services.prefs.setBoolPref(FAIL_BOGUS_PREF, false); Services.prefs.setBoolPref(FAIL_ID_PREF, false); // test with the correct symbol if (data.hasOwnProperty("instanceID") && data.instanceID) { AddonManager.getAddonByInstanceID(data.instanceID) .then(addon => { if (addon.id == ADDON_ID) { Services.prefs.setBoolPref(PASS_PREF, true); } }).catch(err => { throw Error("no addon found for symbol"); }); } // test with a totally bogus symbol AddonManager.getAddonByInstanceID(Symbol("bad symbol")) .then(addon => { // there is no symbol by this name, so null should be returned if (addon == null) { Services.prefs.setBoolPref(FAIL_BOGUS_PREF, true); } else { throw Error("bad symbol should not match:", addon); } }).catch(err => { throw Error("promise should not have rejected: " + err); }); // try to make a matching symbol - this should fail because it's not a // reference to the same symbol stored inside the addons manager. AddonManager.getAddonByInstanceID(Symbol(ADDON_ID)) .then(addon => { // there is no symbol by this name, so null should be returned if (addon == null) { Services.prefs.setBoolPref(FAIL_ID_PREF, true); } else { throw Error("bad symbol should not match:", addon); } }).catch(err => { throw Error("promise should not have rejected: " + err); }); } function shutdown(data, reason) {} function uninstall(data, reason) {}
toolkit/mozapps/extensions/test/addons/test_symbol/install.rdf 0 → 100644 +28 −0 Original line number Diff line number Diff line <?xml version="1.0"?> <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> <em:id>test_symbol@tests.mozilla.org</em:id> <em:version>1.0</em:version> <em:bootstrap>true</em:bootstrap> <!-- Front End MetaData --> <em:name>Test Symbol</em:name> <em:description>Test Description</em:description> <em:iconURL>chrome://foo/skin/icon.png</em:iconURL> <em:aboutURL>chrome://foo/content/about.xul</em:aboutURL> <em:optionsURL>chrome://foo/content/options.xul</em:optionsURL> <em:targetApplication> <Description> <em:id>xpcshell@tests.mozilla.org</em:id> <em:minVersion>1</em:minVersion> <em:maxVersion>1</em:maxVersion> </Description> </em:targetApplication> </Description> </RDF>
toolkit/mozapps/extensions/test/xpcshell/test_pass_symbol.js 0 → 100644 +43 −0 Original line number Diff line number Diff line /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ const PASS_PREF = "symboltest.instanceid.pass"; const FAIL_BOGUS_PREF = "symboltest.instanceid.fail_bogus"; const FAIL_ID_PREF = "symboltest.instanceid.fail_bogus"; const ADDON_ID = "test_symbol@tests.mozilla.org"; createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); startupManager(); BootstrapMonitor.init(); // symbol is passed when add-on is installed add_task(function*() { for (let pref of [PASS_PREF, FAIL_BOGUS_PREF, FAIL_ID_PREF]) Services.prefs.clearUserPref(pref); yield promiseInstallAllFiles([do_get_addon("test_symbol")], true); let addon = yield promiseAddonByID(ADDON_ID); do_check_neq(addon, null); do_check_eq(addon.version, "1.0"); do_check_eq(addon.name, "Test Symbol"); do_check_true(addon.isCompatible); do_check_false(addon.appDisabled); do_check_true(addon.isActive); do_check_eq(addon.type, "extension"); // most of the test is in bootstrap.js in the addon because BootstrapMonitor // currently requires the objects in `data` to be serializable, and we // need a real reference to the symbol to test this. do_execute_soon(function() { // give the startup time to run do_check_true(Services.prefs.getBoolPref(PASS_PREF)); do_check_true(Services.prefs.getBoolPref(FAIL_BOGUS_PREF)); do_check_true(Services.prefs.getBoolPref(FAIL_ID_PREF)); }); yield promiseRestartManager(); });