Bug 1261522 - Support reloading an add-on. r=Mossop
MozReview-Commit-ID: W8z1J4QzjE
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -7269,16 +7269,38 @@ AddonWrapper.prototype = {
addon._hasResourceCache.set(aPath, false);
return false;
}
finally {
zipReader.close();
}
},
+ reload: function() {
+ return new Promise(resolve => {
+ if (this.appDisabled) {
+ throw new Error(
+ "cannot reload add-on because it is disabled by the application");
+ }
+
+ const addon = addonFor(this);
+ const isReloadable = (!XPIProvider.enableRequiresRestart(addon) &&
+ !XPIProvider.disableRequiresRestart(addon));
+ if (!isReloadable) {
+ throw new Error(
+ "cannot reload add-on because it requires a browser restart");
+ }
+
+ this.userDisabled = true;
+ flushStartupCache();
+ this.userDisabled = false;
+ resolve();
+ });
+ },
+
/**
* Returns a URI to the selected resource or to the add-on bundle if aPath
* is null. URIs to the bundle will always be file: URIs. URIs to resources
* will be file: URIs if the add-on is unpacked or jar: URIs if the add-on is
* still an XPI file.
*
* @param aPath
* The path in the add-on to get the URI for or null to get a URI to
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/addons/test_bug1261522_app_disabled/install.rdf
@@ -0,0 +1,21 @@
+<?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>bug1261522-app-disabled@tests.mozilla.org</em:id>
+ <em:version>1.0</em:version>
+
+ <em:targetApplication>
+ <Description>
+ <em:minVersion>1</em:minVersion>
+ <em:maxVersion>2</em:maxVersion>
+ <em:strictCompatibility>true</em:strictCompatibility>
+ </Description>
+ </em:targetApplication>
+
+ <em:name>An add-on that will be app-disabled when installed</em:name>
+
+ </Description>
+</RDF>
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_reload.js
@@ -0,0 +1,74 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42");
+startupManager();
+
+function* getTestAddon(fixtureName, addonID) {
+ yield promiseInstallAllFiles([do_get_addon(fixtureName)]);
+ restartManager();
+ return promiseAddonByID(addonID);
+}
+
+function* tearDownAddon(addon) {
+ addon.uninstall();
+ yield promiseShutdownManager();
+}
+
+add_task(function* test_reloading_an_addon() {
+ const addonId = "webextension1@tests.mozilla.org";
+ const addon = yield getTestAddon("webextension_1", addonId);
+
+ const onDisabled = promiseAddonEvent("onDisabled");
+ const onEnabled = promiseAddonEvent("onEnabled");
+
+ yield addon.reload();
+
+ const [disabledAddon] = yield onDisabled;
+ do_check_eq(disabledAddon.id, addonId);
+
+ const [enabledAddon] = yield onEnabled;
+ do_check_eq(enabledAddon.id, addonId);
+
+ tearDownAddon(addon);
+});
+
+add_task(function* test_cannot_reload_addon_requiring_restart() {
+ // This is a plain install.rdf add-on without a bootstrap script.
+ const addon = yield getTestAddon("test_install1", "addon1@tests.mozilla.org");
+
+ let caughtError = null;
+ try {
+ yield addon.reload();
+ } catch (error) {
+ caughtError = error;
+ }
+
+ do_check_eq(
+ caughtError && caughtError.message,
+ "cannot reload add-on because it requires a browser restart");
+
+ tearDownAddon(addon);
+});
+
+add_task(function* test_cannot_reload_app_disabled_addon() {
+ // This add-on will be app disabled immediately.
+ const addon = yield getTestAddon(
+ "test_bug1261522_app_disabled",
+ "bug1261522-app-disabled@tests.mozilla.org");
+ do_check_eq(addon.appDisabled, true);
+
+ let caughtError = null;
+ try {
+ yield addon.reload();
+ } catch (error) {
+ caughtError = error;
+ }
+
+ do_check_eq(
+ caughtError && caughtError.message,
+ "cannot reload add-on because it is disabled by the application");
+
+ tearDownAddon(addon);
+});
--- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini
+++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini
@@ -1,14 +1,15 @@
# The file is shared between the two main xpcshell manifest files.
[DEFAULT]
skip-if = toolkit == 'android' || toolkit == 'gonk'
tags = addons
[test_AddonRepository.js]
+[test_reload.js]
# Bug 676992: test consistently hangs on Android
skip-if = os == "android"
[test_AddonRepository_cache.js]
# Bug 676992: test consistently hangs on Android
# Bug 1026805: frequent hangs on OSX 10.8
skip-if = os == "android" || os == "mac"
run-sequentially = Uses hardcoded ports in xpi files.
[test_AddonRepository_compatmode.js]
--- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
@@ -31,9 +31,10 @@ skip-if = appname != "firefox"
[test_system_reset.js]
[test_XPIcancel.js]
[test_XPIStates.js]
[test_temporary.js]
[test_proxies.js]
[test_proxy.js]
[test_pass_symbol.js]
+
[include:xpcshell-shared.ini]