Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'win' OR os == 'android'
- Manifest: toolkit/mozapps/extensions/test/xpcshell/xpcshell.toml
/* Any copyright is dedicated to the Public Domain.
*/
// This verifies that forcing undo for uninstall works
const APP_STARTUP = 1;
const APP_SHUTDOWN = 2;
const ADDON_DISABLE = 4;
const ADDON_INSTALL = 5;
const ADDON_UNINSTALL = 6;
const ADDON_UPGRADE = 7;
const ID = "undouninstall1@tests.mozilla.org";
const INCOMPAT_ID = "incompatible@tests.mozilla.org";
const profileDir = gProfD.clone();
profileDir.append("extensions");
const ADDONS = {
test_undoincompatible: {
manifest: {
name: "Incompatible Addon",
browser_specific_settings: {
gecko: {
id: "incompatible@tests.mozilla.org",
strict_min_version: "2",
strict_max_version: "2",
},
},
},
},
test_undouninstall1: {
manifest: {
name: "Test Bootstrap 1",
browser_specific_settings: {
gecko: {
id: "undouninstall1@tests.mozilla.org",
},
},
},
},
};
const XPIS = {};
BootstrapMonitor.init();
function getStartupReason(id) {
let info = BootstrapMonitor.started.get(id);
return info ? info.reason : undefined;
}
function getShutdownReason(id) {
let info = BootstrapMonitor.stopped.get(id);
return info ? info.reason : undefined;
}
function getInstallReason(id) {
let info = BootstrapMonitor.installed.get(id);
return info ? info.reason : undefined;
}
function getUninstallReason(id) {
let info = BootstrapMonitor.uninstalled.get(id);
return info ? info.reason : undefined;
}
function getShutdownNewVersion(id) {
let info = BootstrapMonitor.stopped.get(id);
return info ? info.params.newVersion : undefined;
}
// Sets up the profile by installing an add-on.
add_task(async function setup() {
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
await promiseStartupManager();
registerCleanupFunction(promiseShutdownManager);
for (let [name, files] of Object.entries(ADDONS)) {
XPIS[name] = await AddonTestUtils.createTempWebExtensionFile(files);
}
});
// Tests that an enabled restartless add-on can be uninstalled and goes away
// when the uninstall is committed
add_task(async function uninstallRestartless() {
await promiseInstallFile(XPIS.test_undouninstall1);
let a1 = await promiseAddonByID(ID);
Assert.notEqual(a1, null);
BootstrapMonitor.checkInstalled(ID, "1.0");
BootstrapMonitor.checkStarted(ID, "1.0");
Assert.equal(getInstallReason(ID), ADDON_INSTALL);
Assert.equal(getStartupReason(ID), ADDON_INSTALL);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(a1.isActive);
Assert.ok(!a1.userDisabled);
await a1.uninstall(true);
a1 = await promiseAddonByID(ID);
Assert.notEqual(a1, null);
BootstrapMonitor.checkInstalled(ID);
BootstrapMonitor.checkNotStarted(ID);
Assert.equal(getShutdownReason(ID), ADDON_UNINSTALL);
Assert.ok(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations));
Assert.ok(!a1.isActive);
Assert.ok(!a1.userDisabled);
await a1.uninstall();
a1 = await promiseAddonByID(ID);
Assert.equal(a1, null);
BootstrapMonitor.checkNotStarted(ID);
});
// Tests that an enabled restartless add-on can be uninstalled and then cancelled
add_task(async function cancelUninstallOfRestartless() {
await promiseInstallFile(XPIS.test_undouninstall1);
let a1 = await promiseAddonByID(ID);
Assert.notEqual(a1, null);
BootstrapMonitor.checkInstalled(ID, "1.0");
BootstrapMonitor.checkStarted(ID, "1.0");
Assert.equal(getInstallReason(ID), ADDON_INSTALL);
Assert.equal(getStartupReason(ID), ADDON_INSTALL);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(a1.isActive);
Assert.ok(!a1.userDisabled);
await expectEvents(
{
addonEvents: {
"undouninstall1@tests.mozilla.org": [{ event: "onUninstalling" }],
},
},
() => a1.uninstall(true)
);
a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkInstalled(ID);
BootstrapMonitor.checkNotStarted(ID);
Assert.equal(getShutdownReason(ID), ADDON_UNINSTALL);
Assert.ok(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations));
Assert.ok(!a1.isActive);
Assert.ok(!a1.userDisabled);
let promises = [
promiseAddonEvent("onOperationCancelled"),
promiseWebExtensionStartup(ID),
];
a1.cancelUninstall();
await Promise.all(promises);
BootstrapMonitor.checkInstalled(ID, "1.0");
BootstrapMonitor.checkStarted(ID, "1.0");
Assert.equal(getStartupReason(ID), ADDON_INSTALL);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(a1.isActive);
Assert.ok(!a1.userDisabled);
await promiseShutdownManager();
Assert.equal(getShutdownReason(ID), APP_SHUTDOWN);
Assert.equal(getShutdownNewVersion(ID), undefined);
await promiseStartupManager();
a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkStarted(ID, "1.0");
Assert.equal(getStartupReason(ID), APP_STARTUP);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(a1.isActive);
Assert.ok(!a1.userDisabled);
await a1.uninstall();
});
// Tests that reinstalling an enabled restartless add-on waiting to be
// uninstalled aborts the uninstall and leaves the add-on enabled
add_task(async function reinstallAddonAwaitingUninstall() {
await promiseInstallFile(XPIS.test_undouninstall1);
let a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkInstalled(ID, "1.0");
BootstrapMonitor.checkStarted(ID, "1.0");
Assert.equal(getInstallReason(ID), ADDON_INSTALL);
Assert.equal(getStartupReason(ID), ADDON_INSTALL);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(a1.isActive);
Assert.ok(!a1.userDisabled);
await expectEvents(
{
addonEvents: {
"undouninstall1@tests.mozilla.org": [{ event: "onUninstalling" }],
},
},
() => a1.uninstall(true)
);
a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkInstalled(ID);
BootstrapMonitor.checkNotStarted(ID);
Assert.equal(getShutdownReason(ID), ADDON_UNINSTALL);
Assert.ok(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations));
Assert.ok(!a1.isActive);
Assert.ok(!a1.userDisabled);
await expectEvents(
{
addonEvents: {
"undouninstall1@tests.mozilla.org": [
{ event: "onInstalling" },
{ event: "onInstalled" },
],
},
installEvents: [
{ event: "onNewInstall" },
{ event: "onInstallStarted" },
{ event: "onInstallEnded" },
],
},
() => promiseInstallFile(XPIS.test_undouninstall1)
);
a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
BootstrapMonitor.checkInstalled(ID, "1.0");
BootstrapMonitor.checkStarted(ID, "1.0");
Assert.equal(getInstallReason(ID), ADDON_UPGRADE);
Assert.equal(getStartupReason(ID), ADDON_UPGRADE);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(a1.isActive);
Assert.ok(!a1.userDisabled);
await promiseShutdownManager();
Assert.equal(getShutdownReason(ID), APP_SHUTDOWN);
await promiseStartupManager();
a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkStarted(ID, "1.0");
Assert.equal(getStartupReason(ID), APP_STARTUP);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(a1.isActive);
Assert.ok(!a1.userDisabled);
await a1.uninstall();
});
// Tests that a disabled restartless add-on can be uninstalled and goes away
// when the uninstall is committed
add_task(async function uninstallDisabledRestartless() {
await promiseInstallFile(XPIS.test_undouninstall1);
let a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkInstalled(ID, "1.0");
BootstrapMonitor.checkStarted(ID, "1.0");
Assert.equal(getInstallReason(ID), ADDON_INSTALL);
Assert.equal(getStartupReason(ID), ADDON_INSTALL);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(a1.isActive);
Assert.ok(!a1.userDisabled);
await a1.disable();
BootstrapMonitor.checkNotStarted(ID);
Assert.equal(getShutdownReason(ID), ADDON_DISABLE);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(!a1.isActive);
Assert.ok(a1.userDisabled);
await expectEvents(
{
addonEvents: {
"undouninstall1@tests.mozilla.org": [{ event: "onUninstalling" }],
},
},
() => a1.uninstall(true)
);
a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkNotStarted(ID);
Assert.ok(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations));
Assert.ok(!a1.isActive);
Assert.ok(a1.userDisabled);
// commit the uninstall
await expectEvents(
{
addonEvents: {
"undouninstall1@tests.mozilla.org": [{ event: "onUninstalled" }],
},
},
() => a1.uninstall()
);
a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.equal(a1, null);
BootstrapMonitor.checkNotStarted(ID);
BootstrapMonitor.checkNotInstalled(ID);
Assert.equal(getUninstallReason(ID), ADDON_UNINSTALL);
});
// Tests that a disabled restartless add-on can be uninstalled and then cancelled
add_task(async function cancelUninstallDisabledRestartless() {
await expectEvents(
{
addonEvents: {
"undouninstall1@tests.mozilla.org": [
{ event: "onInstalling" },
{ event: "onInstalled" },
],
},
installEvents: [
{ event: "onNewInstall" },
{ event: "onInstallStarted" },
{ event: "onInstallEnded" },
],
},
() => promiseInstallFile(XPIS.test_undouninstall1)
);
let a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkInstalled(ID, "1.0");
BootstrapMonitor.checkStarted(ID, "1.0");
Assert.equal(getInstallReason(ID), ADDON_INSTALL);
Assert.equal(getStartupReason(ID), ADDON_INSTALL);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(a1.isActive);
Assert.ok(!a1.userDisabled);
await expectEvents(
{
addonEvents: {
"undouninstall1@tests.mozilla.org": [
{ event: "onDisabling" },
{ event: "onDisabled" },
],
},
},
() => a1.disable()
);
BootstrapMonitor.checkNotStarted(ID);
Assert.equal(getShutdownReason(ID), ADDON_DISABLE);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(!a1.isActive);
Assert.ok(a1.userDisabled);
await expectEvents(
{
addonEvents: {
"undouninstall1@tests.mozilla.org": [{ event: "onUninstalling" }],
},
},
() => a1.uninstall(true)
);
a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkNotStarted(ID);
BootstrapMonitor.checkInstalled(ID);
Assert.ok(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations));
Assert.ok(!a1.isActive);
Assert.ok(a1.userDisabled);
await expectEvents(
{
addonEvents: {
"undouninstall1@tests.mozilla.org": [{ event: "onOperationCancelled" }],
},
},
async () => {
a1.cancelUninstall();
}
);
BootstrapMonitor.checkNotStarted(ID);
BootstrapMonitor.checkInstalled(ID);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(!a1.isActive);
Assert.ok(a1.userDisabled);
await promiseRestartManager();
a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkNotStarted(ID);
BootstrapMonitor.checkInstalled(ID);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(!a1.isActive);
Assert.ok(a1.userDisabled);
await a1.uninstall();
});
// Tests that reinstalling a disabled restartless add-on waiting to be
// uninstalled aborts the uninstall and leaves the add-on disabled
add_task(async function reinstallDisabledAddonAwaitingUninstall() {
await promiseInstallFile(XPIS.test_undouninstall1);
let a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkInstalled(ID, "1.0");
BootstrapMonitor.checkStarted(ID, "1.0");
Assert.equal(getInstallReason(ID), ADDON_INSTALL);
Assert.equal(getStartupReason(ID), ADDON_INSTALL);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(a1.isActive);
Assert.ok(!a1.userDisabled);
await a1.disable();
BootstrapMonitor.checkNotStarted(ID);
Assert.equal(getShutdownReason(ID), ADDON_DISABLE);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(!a1.isActive);
Assert.ok(a1.userDisabled);
await expectEvents(
{
addonEvents: {
"undouninstall1@tests.mozilla.org": [{ event: "onUninstalling" }],
},
},
() => a1.uninstall(true)
);
a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkNotStarted(ID);
Assert.ok(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations));
Assert.ok(!a1.isActive);
Assert.ok(a1.userDisabled);
await expectEvents(
{
addonEvents: {
"undouninstall1@tests.mozilla.org": [
{ event: "onInstalling" },
{ event: "onInstalled" },
],
},
installEvents: [
{ event: "onNewInstall" },
{ event: "onInstallStarted" },
{ event: "onInstallEnded" },
],
},
() => promiseInstallFile(XPIS.test_undouninstall1)
);
a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
BootstrapMonitor.checkInstalled(ID, "1.0");
BootstrapMonitor.checkNotStarted(ID, "1.0");
Assert.equal(getInstallReason(ID), ADDON_UPGRADE);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(!a1.isActive);
Assert.ok(a1.userDisabled);
await promiseRestartManager();
a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkNotStarted(ID, "1.0");
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(!a1.isActive);
Assert.ok(a1.userDisabled);
await a1.uninstall();
});
// Test that uninstalling a temporary addon can be canceled
add_task(async function cancelUninstallTemporary() {
await AddonManager.installTemporaryAddon(XPIS.test_undouninstall1);
let a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkInstalled(ID, "1.0");
BootstrapMonitor.checkStarted(ID, "1.0");
Assert.equal(getInstallReason(ID), ADDON_INSTALL);
Assert.equal(getStartupReason(ID), ADDON_INSTALL);
Assert.equal(a1.pendingOperations, AddonManager.PENDING_NONE);
Assert.ok(a1.isActive);
Assert.ok(!a1.userDisabled);
await expectEvents(
{
addonEvents: {
"undouninstall1@tests.mozilla.org": [{ event: "onUninstalling" }],
},
},
() => a1.uninstall(true)
);
BootstrapMonitor.checkNotStarted(ID, "1.0");
Assert.ok(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations));
let promises = [
promiseAddonEvent("onOperationCancelled"),
promiseWebExtensionStartup("undouninstall1@tests.mozilla.org"),
];
a1.cancelUninstall();
await Promise.all(promises);
a1 = await promiseAddonByID("undouninstall1@tests.mozilla.org");
Assert.notEqual(a1, null);
BootstrapMonitor.checkStarted(ID, "1.0");
Assert.equal(a1.pendingOperations, 0);
await promiseRestartManager();
});
// Tests that cancelling the uninstall of an incompatible restartless addon
// does not start the addon
add_task(async function cancelUninstallIncompatibleRestartless() {
await promiseInstallFile(XPIS.test_undoincompatible);
let a1 = await promiseAddonByID(INCOMPAT_ID);
Assert.notEqual(a1, null);
BootstrapMonitor.checkNotStarted(INCOMPAT_ID);
Assert.ok(!a1.isActive);
await expectEvents(
{
addonEvents: {
"incompatible@tests.mozilla.org": [{ event: "onUninstalling" }],
},
},
() => a1.uninstall(true)
);
a1 = await promiseAddonByID(INCOMPAT_ID);
Assert.notEqual(a1, null);
Assert.ok(hasFlag(AddonManager.PENDING_UNINSTALL, a1.pendingOperations));
Assert.ok(!a1.isActive);
await expectEvents(
{
addonEvents: {
"incompatible@tests.mozilla.org": [{ event: "onOperationCancelled" }],
},
},
async () => {
a1.cancelUninstall();
}
);
a1 = await promiseAddonByID(INCOMPAT_ID);
Assert.notEqual(a1, null);
BootstrapMonitor.checkNotStarted(INCOMPAT_ID);
Assert.equal(a1.pendingOperations, 0);
Assert.ok(!a1.isActive);
});