--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -482,16 +482,31 @@ function findMatchingStaticBlocklistItem
return item;
}
}
}
return null;
}
/**
+ * Determine the reason to pass to an extension's bootstrap methods when
+ * switch between versions.
+ *
+ * @param {string} oldVersion The version of the existing extension instance.
+ * @param {string} newVersion The version of the extension being installed.
+ *
+ * @return {BOOSTRAP_REASONS.ADDON_UPGRADE|BOOSTRAP_REASONS.ADDON_DOWNGRADE}
+ */
+function newVersionReason(oldVersion, newVersion) {
+ return Services.vc.compare(oldVersion, newVersion) <= 0 ?
+ BOOTSTRAP_REASONS.ADDON_UPGRADE :
+ BOOTSTRAP_REASONS.ADDON_DOWNGRADE;
+}
+
+/**
* Converts an iterable of addon objects into a map with the add-on's ID as key.
*/
function addonMap(addons) {
return new Map(addons.map(a => [a.id, a]));
}
/**
* Helper function that determines whether an addon of a certain type is a
@@ -1677,22 +1692,23 @@ this.XPIStates = {
let location = this.db.get(aLocation);
return location && location.get(aId);
},
/**
* Find the highest priority location of an add-on by ID and return the
* location and the XPIState.
* @param aId The add-on ID
+ * @param aLocations If specified, the locations to search
* @return {XPIState?}
*/
- findAddon(aId) {
+ findAddon(aId, aLocations = this.db.values()) {
// Fortunately the Map iterator returns in order of insertion, which is
// also our highest -> lowest priority order.
- for (let location of this.db.values()) {
+ for (let location of aLocations) {
if (location.has(aId)) {
return location.get(aId);
}
}
return undefined;
},
/**
@@ -2250,23 +2266,30 @@ this.XPIProvider = {
// pending enable)
if (!XPIProvider.activeAddons.has(addon.id))
continue;
let addonDetails = createAddonDetails(addon.id, addon);
// If the add-on was pending disable then shut it down and remove it
// from the persisted data.
+ let reason = BOOTSTRAP_REASONS.APP_SHUTDOWN;
if (addon.disable) {
- XPIProvider.callBootstrapMethod(addonDetails, addon.file, "shutdown",
- BOOTSTRAP_REASONS.ADDON_DISABLE);
- } else {
- XPIProvider.callBootstrapMethod(addonDetails, addon.file, "shutdown",
- BOOTSTRAP_REASONS.APP_SHUTDOWN);
+ reason = BOOTSTRAP_REASONS.ADDON_DISABLE;
+ } else if (addon.location.name == KEY_APP_TEMPORARY) {
+ reason = BOOTSTRAP_REASONS.ADDON_UNINSTALL;
+ let locations = Array.from(XPIStates.db.values())
+ .filter(loc => loc.name != TemporaryInstallLocation.name);
+ let existing = XPIStates.findAddon(addon.id, locations);
+ if (existing) {
+ reason = newVersionReason(addon.version, existing.version);
+ }
}
+ XPIProvider.callBootstrapMethod(addonDetails, addon.file,
+ "shutdown", reason);
}
Services.obs.removeObserver(this, "quit-application-granted");
}
}, "quit-application-granted");
// Detect final-ui-startup for telemetry reporting
Services.obs.addObserver({
observe(aSubject, aTopic, aData) {
@@ -2342,31 +2365,38 @@ this.XPIProvider = {
this.cancelAll();
// Uninstall any temporary add-ons.
let tempLocation = XPIStates.getLocation(TemporaryInstallLocation.name);
if (tempLocation) {
for (let [id, addon] of tempLocation.entries()) {
tempLocation.delete(id);
+ let reason = BOOTSTRAP_REASONS.ADDON_UNINSTALL;
+
+ let locations = Array.from(XPIStates.db.values())
+ .filter(loc => loc != tempLocation);
+ let existing = XPIStates.findAddon(id, locations);
+ if (existing) {
+ reason = newVersionReason(addon.version, existing.version);
+ }
+
this.callBootstrapMethod(createAddonDetails(id, addon),
- addon.file, "uninstall",
- BOOTSTRAP_REASONS.ADDON_UNINSTALL);
+ addon.file, "uninstall", reason);
this.unloadBootstrapScope(id);
TemporaryInstallLocation.uninstallAddon(id);
- let state = XPIStates.findAddon(id);
- if (state) {
- let newAddon = XPIDatabase.makeAddonLocationVisible(id, state.location.name);
+ if (existing) {
+ let newAddon = XPIDatabase.makeAddonLocationVisible(id, existing.location.name);
let file = new nsIFile(newAddon.path);
+ let data = {oldVersion: addon.version};
this.callBootstrapMethod(createAddonDetails(id, newAddon),
- file, "install",
- BOOTSTRAP_REASONS.ADDON_INSTALL);
+ file, "install", reason, data);
}
}
}
this.activeAddons.clear();
this.allAppGlobal = true;
// If there are pending operations then we must update the list of active
@@ -2851,19 +2881,17 @@ this.XPIProvider = {
var file = existingAddon.file;
if (file.exists()) {
oldBootstrap = existingAddon;
// We'll be replacing a currently active bootstrapped add-on so
// call its uninstall method
let newVersion = addon.version;
let oldVersion = existingAddon;
- let uninstallReason = Services.vc.compare(oldVersion, newVersion) < 0 ?
- BOOTSTRAP_REASONS.ADDON_UPGRADE :
- BOOTSTRAP_REASONS.ADDON_DOWNGRADE;
+ let uninstallReason = newVersionReason(oldVersion, newVersion);
this.callBootstrapMethod(createAddonDetails(existingAddonID, existingAddon),
file, "uninstall", uninstallReason,
{ newVersion });
this.unloadBootstrapScope(existingAddonID);
flushChromeCaches();
}
} catch (e) {
@@ -3474,21 +3502,17 @@ this.XPIProvider = {
let existingAddonID = oldAddon.id;
let existingAddon = oldAddon._sourceBundle;
// We'll be replacing a currently active bootstrapped add-on so
// call its uninstall method
let newVersion = addon.version;
let oldVersion = oldAddon.version;
- if (Services.vc.compare(newVersion, oldVersion) >= 0) {
- installReason = BOOTSTRAP_REASONS.ADDON_UPGRADE;
- } else {
- installReason = BOOTSTRAP_REASONS.ADDON_DOWNGRADE;
- }
+ installReason = newVersionReason(oldVersion, newVersion);
let uninstallReason = installReason;
extraParams.newVersion = newVersion;
extraParams.oldVersion = oldVersion;
if (oldAddon.active) {
XPIProvider.callBootstrapMethod(oldAddon, existingAddon,
"shutdown", uninstallReason,
--- a/toolkit/mozapps/extensions/test/xpcshell/test_temporary.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_temporary.js
@@ -1,12 +1,14 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
+Components.utils.import("resource://gre/modules/AppConstants.jsm");
+
const ID = "bootstrap1@tests.mozilla.org";
const sampleRDFManifest = {
id: ID,
version: "1.0",
bootstrap: true,
targetApplications: [{
id: "xpcshell@tests.mozilla.org",
minVersion: "1",
@@ -17,17 +19,19 @@ const sampleRDFManifest = {
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42");
startupManager();
BootstrapMonitor.init();
// Partial list of bootstrap reasons from XPIProvider.jsm
const BOOTSTRAP_REASONS = {
+ APP_STARTUP: 1,
ADDON_INSTALL: 5,
+ ADDON_UNINSTALL: 6,
ADDON_UPGRADE: 7,
ADDON_DOWNGRADE: 8,
};
function waitForBootstrapEvent(expectedEvent, addonId) {
return new Promise(resolve => {
const observer = {
observe: (subject, topic, data) => {
@@ -95,240 +99,266 @@ add_task(async function() {
do_check_eq(addon.version, "1.0");
do_check_eq(addon.name, "Test Bootstrap 1");
do_check_true(addon.isCompatible);
do_check_false(addon.appDisabled);
do_check_true(addon.isActive);
do_check_eq(addon.type, "extension");
do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
+ let onShutdown = waitForBootstrapEvent("shutdown", ID);
+ let onUninstall = waitForBootstrapEvent("uninstall", ID);
+
await promiseRestartManager();
+ let shutdown = await onShutdown;
+ equal(shutdown.reason, BOOTSTRAP_REASONS.ADDON_UNINSTALL);
+
+ let uninstall = await onUninstall;
+ equal(uninstall.reason, BOOTSTRAP_REASONS.ADDON_UNINSTALL);
+
BootstrapMonitor.checkAddonNotInstalled(ID);
BootstrapMonitor.checkAddonNotStarted(ID);
addon = await promiseAddonByID(ID);
do_check_eq(addon, null);
await promiseRestartManager();
});
// Install a temporary add-on over the top of an existing add-on.
// Restart and make sure the existing add-on comes back.
add_task(async function() {
- await promiseInstallAllFiles([do_get_addon("test_bootstrap1_1")], true);
+ await promiseInstallAllFiles([do_get_addon("test_bootstrap1_2")], true);
- BootstrapMonitor.checkAddonInstalled(ID, "1.0");
- BootstrapMonitor.checkAddonStarted(ID, "1.0");
+ BootstrapMonitor.checkAddonInstalled(ID, "2.0");
+ BootstrapMonitor.checkAddonStarted(ID, "2.0");
let addon = await promiseAddonByID(ID);
do_check_neq(addon, null);
- do_check_eq(addon.version, "1.0");
+ do_check_eq(addon.version, "2.0");
do_check_eq(addon.name, "Test Bootstrap 1");
do_check_true(addon.isCompatible);
do_check_false(addon.appDisabled);
do_check_true(addon.isActive);
do_check_eq(addon.type, "extension");
do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
let tempdir = gTmpD.clone();
- // test that an unpacked add-on works too
- writeInstallRDFToDir({
- id: ID,
- version: "3.0",
- bootstrap: true,
- targetApplications: [{
- id: "xpcshell@tests.mozilla.org",
- minVersion: "1",
- maxVersion: "1"
- }],
- name: "Test Bootstrap 1 (temporary)",
- }, tempdir, "bootstrap1@tests.mozilla.org", "bootstrap.js");
+ let bootstrapJS = await OS.File.read("data/test_temporary/bootstrap.js", {encoding: "utf-8"});
- let unpacked_addon = tempdir.clone();
- unpacked_addon.append(ID);
- do_get_file("data/test_temporary/bootstrap.js")
- .copyTo(unpacked_addon, "bootstrap.js");
-
- await AddonManager.installTemporaryAddon(unpacked_addon);
+ for (let newversion of ["1.0", "3.0"]) {
+ for (let packed of [false, true]) {
+ // ugh, file locking issues with xpis on windows
+ if (packed && AppConstants.platform == "win") {
+ continue;
+ }
- BootstrapMonitor.checkAddonInstalled(ID, "3.0");
- BootstrapMonitor.checkAddonStarted(ID, "3.0");
-
- addon = await promiseAddonByID(ID);
+ let files = {
+ "install.rdf": AddonTestUtils.createInstallRDF({
+ id: ID,
+ version: newversion,
+ bootstrap: true,
+ targetApplications: [{
+ id: "xpcshell@tests.mozilla.org",
+ minVersion: "1",
+ maxVersion: "1"
+ }],
+ name: "Test Bootstrap 1 (temporary)",
+ }),
+ "bootstrap.js": bootstrapJS,
+ };
- // temporary add-on is installed and started
- do_check_neq(addon, null);
- do_check_eq(addon.version, "3.0");
- do_check_eq(addon.name, "Test Bootstrap 1 (temporary)");
- do_check_true(addon.isCompatible);
- do_check_false(addon.appDisabled);
- do_check_true(addon.isActive);
- do_check_eq(addon.type, "extension");
- do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
-
- restartManager();
-
- BootstrapMonitor.checkAddonInstalled(ID, "1.0");
- BootstrapMonitor.checkAddonStarted(ID, "1.0");
-
- addon = await promiseAddonByID(ID);
+ let target;
+ if (packed) {
+ target = tempdir.clone();
+ target.append(ID);
- // existing add-on is back
- do_check_neq(addon, null);
- do_check_eq(addon.version, "1.0");
- do_check_eq(addon.name, "Test Bootstrap 1");
- do_check_true(addon.isCompatible);
- do_check_false(addon.appDisabled);
- do_check_true(addon.isActive);
- do_check_eq(addon.type, "extension");
- do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
+ await AddonTestUtils.promiseWriteFilesToDir(target.path, files);
+ } else {
+ target = tempdir.clone();
+ target.append(`${ID}.xpi`);
- unpacked_addon.remove(true);
+ await AddonTestUtils.promiseWriteFilesToZip(target.path, files);
+ }
+
+ let onShutdown = waitForBootstrapEvent("shutdown", ID);
+ let onUninstall = waitForBootstrapEvent("uninstall", ID);
+ let onInstall = waitForBootstrapEvent("install", ID);
+ let onStartup = waitForBootstrapEvent("startup", ID);
+
+ await AddonManager.installTemporaryAddon(target);
- // on Windows XPI files will be locked by the JAR cache, skip this test there.
- if (!("nsIWindowsRegKey" in Components.interfaces)) {
- // test that a packed (XPI) add-on works
- writeInstallRDFToXPI({
- id: ID,
- version: "2.0",
- bootstrap: true,
- targetApplications: [{
- id: "xpcshell@tests.mozilla.org",
- minVersion: "1",
- maxVersion: "1"
- }],
- name: "Test Bootstrap 1 (temporary)",
- }, tempdir, "bootstrap1@tests.mozilla.org");
+ let reason = Services.vc.compare(newversion, "2.0") < 0 ?
+ BOOTSTRAP_REASONS.ADDON_DOWNGRADE :
+ BOOTSTRAP_REASONS.ADDON_UPGRADE;
- let packed_addon = tempdir.clone();
- packed_addon.append(ID + ".xpi");
+ let shutdown = await onShutdown;
+ equal(shutdown.data.version, "2.0");
+ equal(shutdown.reason, reason);
- await AddonManager.installTemporaryAddon(packed_addon);
-
- addon = await promiseAddonByID(ID);
+ let uninstall = await onUninstall;
+ equal(uninstall.data.version, "2.0");
+ equal(uninstall.reason, reason);
- // temporary add-on is installed and started
- do_check_neq(addon, null);
- do_check_eq(addon.version, "2.0");
- do_check_eq(addon.name, "Test Bootstrap 1 (temporary)");
- do_check_true(addon.isCompatible);
- do_check_false(addon.appDisabled);
- do_check_true(addon.isActive);
- do_check_eq(addon.type, "extension");
- do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
-
- restartManager();
-
- BootstrapMonitor.checkAddonInstalled(ID, "1.0");
- BootstrapMonitor.checkAddonStarted(ID, "1.0");
+ let install = await onInstall;
+ equal(install.data.version, newversion);
+ equal(install.reason, reason);
+ equal(install.data.oldVersion, "2.0");
- addon = await promiseAddonByID(ID);
+ let startup = await onStartup;
+ equal(startup.data.version, newversion);
+ equal(startup.reason, reason);
+ equal(startup.data.oldVersion, "2.0");
- // existing add-on is back
- do_check_neq(addon, null);
- do_check_eq(addon.version, "1.0");
- do_check_eq(addon.name, "Test Bootstrap 1");
- do_check_true(addon.isCompatible);
- do_check_false(addon.appDisabled);
- do_check_true(addon.isActive);
- do_check_eq(addon.type, "extension");
- do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
-
- packed_addon.remove(false);
+ addon = await promiseAddonByID(ID);
- // test that a webextension works
- let webext = createTempWebExtensionFile({
- manifest: {
- version: "4.0",
- name: "Test WebExtension 1 (temporary)",
- applications: {
- gecko: {
- id: ID
- }
- }
- }
- });
+ // temporary add-on is installed and started
+ do_check_neq(addon, null);
+ do_check_eq(addon.version, newversion);
+ do_check_eq(addon.name, "Test Bootstrap 1 (temporary)");
+ do_check_true(addon.isCompatible);
+ do_check_false(addon.appDisabled);
+ do_check_true(addon.isActive);
+ do_check_eq(addon.type, "extension");
+ do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
- await Promise.all([
- AddonManager.installTemporaryAddon(webext),
- promiseWebExtensionStartup(),
- ]);
- addon = await promiseAddonByID(ID);
+ // Now restart, the temporary addon will go away which should
+ // be the opposite action (ie, if the temporary addon was an
+ // upgrade, then removing it is a downgrade and vice versa)
+ reason = reason == BOOTSTRAP_REASONS.ADDON_UPGRADE ?
+ BOOTSTRAP_REASONS.ADDON_DOWNGRADE :
+ BOOTSTRAP_REASONS.ADDON_UPGRADE;
- // temporary add-on is installed and started
- do_check_neq(addon, null);
- do_check_eq(addon.version, "4.0");
- do_check_eq(addon.name, "Test WebExtension 1 (temporary)");
- do_check_true(addon.isCompatible);
- do_check_false(addon.appDisabled);
- do_check_true(addon.isActive);
- do_check_eq(addon.type, "extension");
- do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
+ onShutdown = waitForBootstrapEvent("shutdown", ID);
+ onUninstall = waitForBootstrapEvent("uninstall", ID);
+ onInstall = waitForBootstrapEvent("install", ID);
+ onStartup = waitForBootstrapEvent("startup", ID);
+
+ await promiseRestartManager();
- // test that re-loading a webextension works, using the same filename
- webext.remove(false);
- webext = createTempWebExtensionFile({
- manifest: {
- version: "5.0",
- name: "Test WebExtension 1 (temporary)",
- applications: {
- gecko: {
- id: ID
- }
- }
- }
- });
+ shutdown = await onShutdown;
+ equal(shutdown.data.version, newversion);
+ equal(shutdown.reason, reason);
- await Promise.all([
- AddonManager.installTemporaryAddon(webext),
- promiseWebExtensionStartup(),
- ]);
- addon = await promiseAddonByID(ID);
+ uninstall = await onUninstall;
+ equal(uninstall.data.version, newversion);
+ equal(uninstall.reason, reason);
+
+ install = await onInstall;
+ equal(install.data.version, "2.0");
+ equal(install.reason, reason);
+ equal(install.data.oldVersion, newversion);
- // temporary add-on is installed and started
- do_check_neq(addon, null);
- do_check_eq(addon.version, "5.0");
- do_check_eq(addon.name, "Test WebExtension 1 (temporary)");
- do_check_true(addon.isCompatible);
- do_check_false(addon.appDisabled);
- do_check_true(addon.isActive);
- do_check_eq(addon.type, "extension");
- do_check_true(addon.isWebExtension);
- do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
+ startup = await onStartup;
+ equal(startup.data.version, "2.0");
+ // We don't actually propagate the upgrade/downgrade reason across
+ // the browser restart when a temporary addon is removed. See
+ // bug 1359558 for detailed reasoning.
+ equal(startup.reason, BOOTSTRAP_REASONS.APP_STARTUP);
- restartManager();
+ BootstrapMonitor.checkAddonInstalled(ID, "2.0");
+ BootstrapMonitor.checkAddonStarted(ID, "2.0");
+
+ addon = await promiseAddonByID(ID);
- BootstrapMonitor.checkAddonInstalled(ID, "1.0");
- BootstrapMonitor.checkAddonStarted(ID, "1.0");
-
- addon = await promiseAddonByID(ID);
+ // existing add-on is back
+ do_check_neq(addon, null);
+ do_check_eq(addon.version, "2.0");
+ do_check_eq(addon.name, "Test Bootstrap 1");
+ do_check_true(addon.isCompatible);
+ do_check_false(addon.appDisabled);
+ do_check_true(addon.isActive);
+ do_check_eq(addon.type, "extension");
+ do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
- // existing add-on is back
- do_check_neq(addon, null);
- do_check_eq(addon.version, "1.0");
- do_check_eq(addon.name, "Test Bootstrap 1");
- do_check_true(addon.isCompatible);
- do_check_false(addon.appDisabled);
- do_check_true(addon.isActive);
- do_check_eq(addon.type, "extension");
- do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
+ target.remove(true);
+ }
}
// remove original add-on
addon.uninstall();
BootstrapMonitor.checkAddonNotInstalled(ID);
BootstrapMonitor.checkAddonNotStarted(ID);
await promiseRestartManager();
});
+// Test that loading from the same path multiple times work
+add_task(async function test_samefile() {
+ // File locking issues on Windows, ugh
+ if (AppConstants.platform == "win") {
+ return;
+ }
+
+ // test that a webextension works
+ let webext = createTempWebExtensionFile({
+ manifest: {
+ version: "1.0",
+ name: "Test WebExtension 1 (temporary)",
+ applications: {
+ gecko: {
+ id: ID
+ }
+ }
+ }
+ });
+
+ await Promise.all([
+ AddonManager.installTemporaryAddon(webext),
+ promiseWebExtensionStartup(),
+ ]);
+ let addon = await promiseAddonByID(ID);
+
+ // temporary add-on is installed and started
+ do_check_neq(addon, null);
+ do_check_eq(addon.version, "1.0");
+ do_check_eq(addon.name, "Test WebExtension 1 (temporary)");
+ do_check_true(addon.isCompatible);
+ do_check_false(addon.appDisabled);
+ do_check_true(addon.isActive);
+ do_check_eq(addon.type, "extension");
+ do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
+
+ webext.remove(false);
+ webext = createTempWebExtensionFile({
+ manifest: {
+ version: "2.0",
+ name: "Test WebExtension 1 (temporary)",
+ applications: {
+ gecko: {
+ id: ID
+ }
+ }
+ }
+ });
+
+ await Promise.all([
+ AddonManager.installTemporaryAddon(webext),
+ promiseWebExtensionStartup(),
+ ]);
+ addon = await promiseAddonByID(ID);
+
+ // temporary add-on is installed and started
+ do_check_neq(addon, null);
+ do_check_eq(addon.version, "2.0");
+ do_check_eq(addon.name, "Test WebExtension 1 (temporary)");
+ do_check_true(addon.isCompatible);
+ do_check_false(addon.appDisabled);
+ do_check_true(addon.isActive);
+ do_check_eq(addon.type, "extension");
+ do_check_true(addon.isWebExtension);
+ do_check_eq(addon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
+
+ addon.uninstall();
+});
+
// Install a temporary add-on over the top of an existing add-on.
// Uninstall it and make sure the existing add-on comes back.
add_task(async function() {
await promiseInstallAllFiles([do_get_addon("test_bootstrap1_1")], true);
BootstrapMonitor.checkAddonInstalled(ID, "1.0");
BootstrapMonitor.checkAddonStarted(ID, "1.0");