mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1209341 - allow loading unsigned restartless add-ons at runtime. r=mossop
This commit is contained in:
parent
8db12ffec2
commit
a2347b9b5b
@ -2315,6 +2315,27 @@ var AddonManagerInternal = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts installation of a temporary add-on from a local directory.
|
||||
* @param aDirectory
|
||||
* The directory of the add-on to be temporarily installed
|
||||
* @return a Promise that rejects if the add-on is not restartless
|
||||
* or an add-on with the same ID is already temporarily installed
|
||||
*/
|
||||
installTemporaryAddon: function AMI_installTemporaryAddon(aFile) {
|
||||
if (!gStarted)
|
||||
throw Components.Exception("AddonManager is not initialized",
|
||||
Cr.NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
if (!(aFile instanceof Ci.nsIFile))
|
||||
throw Components.Exception("aFile must be a nsIFile",
|
||||
Cr.NS_ERROR_INVALID_ARG);
|
||||
|
||||
return AddonManagerInternal._getProviderByName("XPIProvider")
|
||||
.installTemporaryAddon(aFile);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Gets an icon from the icon set provided by the add-on
|
||||
* that is closest to the specified size.
|
||||
@ -3026,8 +3047,10 @@ this.AddonManager = {
|
||||
SCOPE_APPLICATION: 4,
|
||||
// Installed for all users of the computer.
|
||||
SCOPE_SYSTEM: 8,
|
||||
// Installed temporarily
|
||||
SCOPE_TEMPORARY: 16,
|
||||
// The combination of all scopes.
|
||||
SCOPE_ALL: 15,
|
||||
SCOPE_ALL: 31,
|
||||
|
||||
// 1-15 are different built-in views for the add-on type
|
||||
VIEW_TYPE_LIST: "list",
|
||||
@ -3207,6 +3230,10 @@ this.AddonManager = {
|
||||
aInstalls);
|
||||
},
|
||||
|
||||
installTemporaryAddon: function AM_installTemporaryAddon(aDirectory) {
|
||||
return AddonManagerInternal.installTemporaryAddon(aDirectory);
|
||||
},
|
||||
|
||||
addManagerListener: function AM_addManagerListener(aListener) {
|
||||
AddonManagerInternal.addManagerListener(aListener);
|
||||
},
|
||||
|
@ -202,6 +202,9 @@ function loadView(aViewId) {
|
||||
}
|
||||
|
||||
function isCorrectlySigned(aAddon) {
|
||||
// temporary add-ons do not require signing
|
||||
if (aAddon.scope == AddonManager.SCOPE_TEMPORARY)
|
||||
return true;
|
||||
if (aAddon.signedState <= AddonManager.SIGNEDSTATE_MISSING)
|
||||
return false;
|
||||
if (aAddon.foreignInstall && aAddon.signedState < AddonManager.SIGNEDSTATE_SIGNED)
|
||||
|
@ -146,6 +146,7 @@ const KEY_APP_GLOBAL = "app-global";
|
||||
const KEY_APP_SYSTEM_LOCAL = "app-system-local";
|
||||
const KEY_APP_SYSTEM_SHARE = "app-system-share";
|
||||
const KEY_APP_SYSTEM_USER = "app-system-user";
|
||||
const KEY_APP_TEMPORARY = "app-temporary";
|
||||
|
||||
const NOTIFICATION_FLUSH_PERMISSIONS = "flush-pending-permissions";
|
||||
const XPI_PERMISSION = "install";
|
||||
@ -646,6 +647,12 @@ function canRunInSafeMode(aAddon) {
|
||||
// Even though the updated system add-ons aren't generally run in safe mode we
|
||||
// include them here so their uninstall functions get called when switching
|
||||
// back to the default set.
|
||||
|
||||
// TODO product should make the call about temporary add-ons running
|
||||
// in safe mode. assuming for now that they are.
|
||||
if (aAddon._installLocation.name == KEY_APP_TEMPORARY)
|
||||
return true;
|
||||
|
||||
return aAddon._installLocation.name == KEY_APP_SYSTEM_DEFAULTS ||
|
||||
aAddon._installLocation.name == KEY_APP_SYSTEM_ADDONS;
|
||||
}
|
||||
@ -666,8 +673,10 @@ function isUsableAddon(aAddon) {
|
||||
aAddon.signedState != AddonManager.SIGNEDSTATE_SYSTEM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aAddon._installLocation.name != KEY_APP_SYSTEM_DEFAULTS && mustSign(aAddon.type)) {
|
||||
// temporary and system add-ons do not require signing
|
||||
if ((aAddon._installLocation.name != KEY_APP_SYSTEM_DEFAULTS &&
|
||||
aAddon._installLocation.name != KEY_APP_TEMPORARY) &&
|
||||
mustSign(aAddon.type)) {
|
||||
if (aAddon.signedState <= AddonManager.SIGNEDSTATE_MISSING)
|
||||
return false;
|
||||
if (aAddon.foreignInstall && aAddon.signedState < AddonManager.SIGNEDSTATE_SIGNED)
|
||||
@ -2544,6 +2553,11 @@ this.XPIProvider = {
|
||||
|
||||
// These must be in order of priority, highest to lowest,
|
||||
// for processFileChanges etc. to work
|
||||
|
||||
XPIProvider.installLocations.push(TemporaryInstallLocation);
|
||||
XPIProvider.installLocationsByName[TemporaryInstallLocation.name] =
|
||||
TemporaryInstallLocation;
|
||||
|
||||
// The profile location is always enabled
|
||||
addDirectoryInstallLocation(KEY_APP_PROFILE, KEY_PROFILEDIR,
|
||||
[DIR_EXTENSIONS],
|
||||
@ -3784,6 +3798,95 @@ this.XPIProvider = {
|
||||
}, aFile);
|
||||
},
|
||||
|
||||
/**
|
||||
* Temporarily installs add-on from local directory.
|
||||
* As this is intended for development, the signature is not checked and
|
||||
* the add-on does not persist on application restart.
|
||||
*
|
||||
* @param aDirectory
|
||||
* The directory containing the unpacked add-on directory or XPI file
|
||||
*
|
||||
* @return a Promise that rejects if the add-on is not restartless
|
||||
* or an add-on with the same ID is already temporarily installed
|
||||
*/
|
||||
installTemporaryAddon: Task.async(function*
|
||||
XPI_installTemporaryAddon(aDirectory) {
|
||||
let addon = yield loadManifestFromFile(aDirectory, TemporaryInstallLocation);
|
||||
|
||||
if (!addon.bootstrap) {
|
||||
throw new Error("Only restartless (bootstrap) add-ons"
|
||||
+ " can be temporarily installed:", addon.id);
|
||||
}
|
||||
let oldAddon = yield new Promise(
|
||||
resolve => XPIDatabase.getVisibleAddonForID(addon.id, resolve));
|
||||
if (oldAddon) {
|
||||
if (oldAddon.location == KEY_APP_TEMPORARY) {
|
||||
logger.warn("temporary add-on already installed:", addon.id);
|
||||
throw new Error("Add-on with ID " + oldAddon.id + " is already"
|
||||
+ " temporarily installed");
|
||||
}
|
||||
else if (!oldAddon.bootstrap) {
|
||||
logger.warn("Non-restartless Add-on is already installed", addon.id);
|
||||
throw new Error("Non-restartless add-on with ID "
|
||||
+ oldAddon.id + " is already installed");
|
||||
}
|
||||
else {
|
||||
logger.warn("Addon with ID " + oldAddon.id + " already installed,"
|
||||
+ " older version will be disabled");
|
||||
|
||||
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;
|
||||
let uninstallReason = Services.vc.compare(oldVersion, newVersion) < 0 ?
|
||||
BOOTSTRAP_REASONS.ADDON_UPGRADE :
|
||||
BOOTSTRAP_REASONS.ADDON_DOWNGRADE;
|
||||
|
||||
if (oldAddon.active) {
|
||||
XPIProvider.callBootstrapMethod(oldAddon, existingAddon,
|
||||
"shutdown", uninstallReason,
|
||||
{ newVersion });
|
||||
}
|
||||
this.callBootstrapMethod(oldAddon, existingAddon,
|
||||
"uninstall", uninstallReason, { newVersion });
|
||||
this.unloadBootstrapScope(existingAddonID);
|
||||
flushStartupCache();
|
||||
}
|
||||
}
|
||||
|
||||
let file = addon._sourceBundle;
|
||||
|
||||
let wrapper = createWrapper(addon);
|
||||
let oldWrapper = createWrapper(oldAddon);
|
||||
XPIProvider.callBootstrapMethod(addon, file, "install",
|
||||
BOOTSTRAP_REASONS.ADDON_INSTALL);
|
||||
addon.state = AddonManager.STATE_INSTALLED;
|
||||
logger.debug("Install of temporary addon in " + aDirectory.path + " completed.");
|
||||
addon.visible = true;
|
||||
addon.enabled = true;
|
||||
addon.active = true;
|
||||
|
||||
addon = XPIDatabase.addAddonMetadata(addon, file.persistentDescriptor);
|
||||
|
||||
XPIStates.addAddon(addon);
|
||||
XPIDatabase.saveChanges();
|
||||
|
||||
// addon was modified above, create new wrapper
|
||||
wrapper = createWrapper(addon);
|
||||
|
||||
AddonManagerPrivate.callAddonListeners("onInstalling", wrapper,
|
||||
false);
|
||||
XPIProvider.callBootstrapMethod(addon, file, "startup",
|
||||
BOOTSTRAP_REASONS.ADDON_ENABLE);
|
||||
AddonManagerPrivate.callInstallListeners("onExternalInstall",
|
||||
null, wrapper, oldWrapper,
|
||||
false);
|
||||
AddonManagerPrivate.callAddonListeners("onInstalled", wrapper);
|
||||
}),
|
||||
|
||||
/**
|
||||
* Removes an AddonInstall from the list of active installs.
|
||||
*
|
||||
@ -6988,6 +7091,9 @@ function AddonWrapper(aAddon) {
|
||||
});
|
||||
|
||||
this.__defineGetter__("hidden", function AddonWrapper_hidden() {
|
||||
if (aAddon._installLocation.name == KEY_APP_TEMPORARY)
|
||||
return false;
|
||||
|
||||
return (aAddon._installLocation.name == KEY_APP_SYSTEM_DEFAULTS ||
|
||||
aAddon._installLocation.name == KEY_APP_SYSTEM_ADDONS);
|
||||
});
|
||||
@ -7818,6 +7924,21 @@ Object.assign(SystemAddonInstallLocation.prototype, {
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* An object which identifies a directory install location for temporary
|
||||
* add-ons.
|
||||
*/
|
||||
const TemporaryInstallLocation = {
|
||||
locked: false,
|
||||
name: KEY_APP_TEMPORARY,
|
||||
scope: AddonManager.SCOPE_TEMPORARY,
|
||||
getAddonLocations: () => [],
|
||||
isLinkedAddon: () => false,
|
||||
installAddon: () => {},
|
||||
uninstallAddon: (aAddon) => {},
|
||||
getStagingDir: () => {},
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
/**
|
||||
* An object that identifies a registry install location for add-ons. The location
|
||||
|
@ -323,7 +323,7 @@ function DBAddonInternal(aLoaded) {
|
||||
|
||||
if (aLoaded._installLocation) {
|
||||
this._installLocation = aLoaded._installLocation;
|
||||
this.location = aLoaded._installLocation._name;
|
||||
this.location = aLoaded._installLocation.name;
|
||||
}
|
||||
else if (aLoaded.location) {
|
||||
this._installLocation = XPIProvider.installLocationsByName[this.location];
|
||||
|
1
toolkit/mozapps/extensions/test/xpcshell/data/test_temporary/bootstrap.js
vendored
Normal file
1
toolkit/mozapps/extensions/test/xpcshell/data/test_temporary/bootstrap.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
Components.utils.import("resource://xpcshell-data/BootstrapMonitor.jsm").monitor(this);
|
445
toolkit/mozapps/extensions/test/xpcshell/test_temporary.js
Normal file
445
toolkit/mozapps/extensions/test/xpcshell/test_temporary.js
Normal file
@ -0,0 +1,445 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
const ID = "bootstrap1@tests.mozilla.org";
|
||||
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42");
|
||||
startupManager();
|
||||
|
||||
BootstrapMonitor.init();
|
||||
|
||||
// Install a temporary add-on with no existing add-on present.
|
||||
// Restart and make sure it has gone away.
|
||||
add_task(function*() {
|
||||
let extInstallCalled = false;
|
||||
AddonManager.addInstallListener({
|
||||
onExternalInstall: (aInstall) => {
|
||||
do_check_eq(aInstall.id, ID);
|
||||
do_check_eq(aInstall.version, "1.0");
|
||||
extInstallCalled = true;
|
||||
},
|
||||
});
|
||||
|
||||
let installingCalled = false;
|
||||
let installedCalled = false;
|
||||
AddonManager.addAddonListener({
|
||||
onInstalling: (aInstall) => {
|
||||
do_check_eq(aInstall.id, ID);
|
||||
do_check_eq(aInstall.version, "1.0");
|
||||
installingCalled = true;
|
||||
},
|
||||
onInstalled: (aInstall) => {
|
||||
do_check_eq(aInstall.id, ID);
|
||||
do_check_eq(aInstall.version, "1.0");
|
||||
installedCalled = true;
|
||||
},
|
||||
onInstallStarted: (aInstall) => {
|
||||
do_throw("onInstallStarted called unexpectedly");
|
||||
}
|
||||
});
|
||||
|
||||
yield AddonManager.installTemporaryAddon(do_get_addon("test_bootstrap1_1"));
|
||||
|
||||
do_check_true(extInstallCalled);
|
||||
do_check_true(installingCalled);
|
||||
do_check_true(installedCalled);
|
||||
|
||||
BootstrapMonitor.checkAddonInstalled(ID, "1.0");
|
||||
BootstrapMonitor.checkAddonStarted(ID, "1.0");
|
||||
|
||||
let addon = yield promiseAddonByID(ID);
|
||||
|
||||
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_MISSING : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
|
||||
|
||||
yield promiseRestartManager();
|
||||
|
||||
BootstrapMonitor.checkAddonNotInstalled(ID);
|
||||
BootstrapMonitor.checkAddonNotStarted(ID);
|
||||
|
||||
addon = yield promiseAddonByID(ID);
|
||||
do_check_eq(addon, null);
|
||||
|
||||
yield 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(function*() {
|
||||
yield promiseInstallAllFiles([do_get_addon("test_bootstrap1_1")], true);
|
||||
|
||||
BootstrapMonitor.checkAddonInstalled(ID, "1.0");
|
||||
BootstrapMonitor.checkAddonStarted(ID, "1.0");
|
||||
|
||||
let addon = yield promiseAddonByID(ID);
|
||||
|
||||
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_MISSING : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
|
||||
|
||||
// test that an unpacked add-on works too
|
||||
let tempdir = gTmpD.clone();
|
||||
|
||||
writeInstallRDFToDir({
|
||||
id: ID,
|
||||
version: "2.0",
|
||||
bootstrap: true,
|
||||
unpack: true,
|
||||
targetApplications: [{
|
||||
id: "xpcshell@tests.mozilla.org",
|
||||
minVersion: "1",
|
||||
maxVersion: "1"
|
||||
}],
|
||||
name: "Test Bootstrap 1 (temporary)",
|
||||
}, tempdir, "bootstrap1@tests.mozilla.org", "bootstrap.js");
|
||||
|
||||
let unpacked_addon = tempdir.clone();
|
||||
unpacked_addon.append(ID);
|
||||
do_get_file("data/test_temporary/bootstrap.js")
|
||||
.copyTo(unpacked_addon, "bootstrap.js");
|
||||
|
||||
yield AddonManager.installTemporaryAddon(unpacked_addon);
|
||||
|
||||
BootstrapMonitor.checkAddonInstalled(ID, "2.0");
|
||||
BootstrapMonitor.checkAddonStarted(ID, "2.0");
|
||||
|
||||
addon = yield 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 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_MISSING : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
|
||||
|
||||
restartManager();
|
||||
|
||||
BootstrapMonitor.checkAddonInstalled(ID, "1.0");
|
||||
BootstrapMonitor.checkAddonStarted(ID, "1.0");
|
||||
|
||||
addon = yield promiseAddonByID(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_MISSING : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
|
||||
|
||||
unpacked_addon.remove(true);
|
||||
addon.uninstall();
|
||||
|
||||
BootstrapMonitor.checkAddonNotInstalled(ID);
|
||||
BootstrapMonitor.checkAddonNotStarted(ID);
|
||||
|
||||
yield promiseRestartManager();
|
||||
});
|
||||
|
||||
// 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(function*() {
|
||||
yield promiseInstallAllFiles([do_get_addon("test_bootstrap1_1")], true);
|
||||
|
||||
BootstrapMonitor.checkAddonInstalled(ID, "1.0");
|
||||
BootstrapMonitor.checkAddonStarted(ID, "1.0");
|
||||
|
||||
let tempdir = gTmpD.clone();
|
||||
writeInstallRDFToDir({
|
||||
id: ID,
|
||||
version: "2.0",
|
||||
bootstrap: true,
|
||||
unpack: true,
|
||||
targetApplications: [{
|
||||
id: "xpcshell@tests.mozilla.org",
|
||||
minVersion: "1",
|
||||
maxVersion: "1"
|
||||
}],
|
||||
name: "Test Bootstrap 1 (temporary)",
|
||||
}, tempdir);
|
||||
|
||||
let unpacked_addon = tempdir.clone();
|
||||
unpacked_addon.append(ID);
|
||||
|
||||
let extInstallCalled = false;
|
||||
AddonManager.addInstallListener({
|
||||
onExternalInstall: (aInstall) => {
|
||||
do_check_eq(aInstall.id, ID);
|
||||
do_check_eq(aInstall.version, "2.0");
|
||||
extInstallCalled = true;
|
||||
},
|
||||
});
|
||||
|
||||
let installingCalled = false;
|
||||
let installedCalled = false;
|
||||
AddonManager.addAddonListener({
|
||||
onInstalling: (aInstall) => {
|
||||
do_check_eq(aInstall.id, ID);
|
||||
if (!installingCalled)
|
||||
do_check_eq(aInstall.version, "2.0");
|
||||
installingCalled = true;
|
||||
},
|
||||
onInstalled: (aInstall) => {
|
||||
do_check_eq(aInstall.id, ID);
|
||||
if (!installedCalled)
|
||||
do_check_eq(aInstall.version, "2.0");
|
||||
installedCalled = true;
|
||||
},
|
||||
onInstallStarted: (aInstall) => {
|
||||
do_throw("onInstallStarted called unexpectedly");
|
||||
}
|
||||
});
|
||||
|
||||
yield AddonManager.installTemporaryAddon(unpacked_addon);
|
||||
|
||||
do_check_true(extInstallCalled);
|
||||
do_check_true(installingCalled);
|
||||
do_check_true(installedCalled);
|
||||
|
||||
let addon = yield promiseAddonByID(ID);
|
||||
|
||||
BootstrapMonitor.checkAddonNotInstalled(ID);
|
||||
BootstrapMonitor.checkAddonNotStarted(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 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_MISSING : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
|
||||
|
||||
addon.uninstall();
|
||||
|
||||
addon = yield promiseAddonByID(ID);
|
||||
|
||||
BootstrapMonitor.checkAddonInstalled(ID);
|
||||
BootstrapMonitor.checkAddonStarted(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_MISSING : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
|
||||
|
||||
unpacked_addon.remove(true);
|
||||
addon.uninstall();
|
||||
|
||||
BootstrapMonitor.checkAddonNotInstalled(ID);
|
||||
BootstrapMonitor.checkAddonNotStarted(ID);
|
||||
|
||||
yield promiseRestartManager();
|
||||
});
|
||||
|
||||
// Install a temporary add-on over the top of an existing disabled add-on.
|
||||
// After restart, the existing add-on should continue to be installed and disabled.
|
||||
add_task(function*() {
|
||||
yield promiseInstallAllFiles([do_get_addon("test_bootstrap1_1")], true);
|
||||
|
||||
BootstrapMonitor.checkAddonInstalled(ID, "1.0");
|
||||
BootstrapMonitor.checkAddonStarted(ID, "1.0");
|
||||
|
||||
let addon = yield promiseAddonByID(ID);
|
||||
|
||||
addon.userDisabled = true;
|
||||
|
||||
BootstrapMonitor.checkAddonInstalled(ID, "1.0");
|
||||
BootstrapMonitor.checkAddonNotStarted(ID);
|
||||
|
||||
let tempdir = gTmpD.clone();
|
||||
writeInstallRDFToDir({
|
||||
id: ID,
|
||||
version: "2.0",
|
||||
bootstrap: true,
|
||||
unpack: true,
|
||||
targetApplications: [{
|
||||
id: "xpcshell@tests.mozilla.org",
|
||||
minVersion: "1",
|
||||
maxVersion: "1"
|
||||
}],
|
||||
name: "Test Bootstrap 1 (temporary)",
|
||||
}, tempdir, "bootstrap1@tests.mozilla.org", "bootstrap.js");
|
||||
|
||||
let unpacked_addon = tempdir.clone();
|
||||
unpacked_addon.append(ID);
|
||||
do_get_file("data/test_temporary/bootstrap.js")
|
||||
.copyTo(unpacked_addon, "bootstrap.js");
|
||||
|
||||
let extInstallCalled = false;
|
||||
AddonManager.addInstallListener({
|
||||
onExternalInstall: (aInstall) => {
|
||||
do_check_eq(aInstall.id, ID);
|
||||
do_check_eq(aInstall.version, "2.0");
|
||||
extInstallCalled = true;
|
||||
},
|
||||
});
|
||||
|
||||
yield AddonManager.installTemporaryAddon(unpacked_addon);
|
||||
|
||||
do_check_true(extInstallCalled);
|
||||
|
||||
let tempAddon = yield promiseAddonByID(ID);
|
||||
|
||||
BootstrapMonitor.checkAddonInstalled(ID, "2.0");
|
||||
BootstrapMonitor.checkAddonStarted(ID);
|
||||
|
||||
// temporary add-on is installed and started
|
||||
do_check_neq(tempAddon, null);
|
||||
do_check_eq(tempAddon.version, "2.0");
|
||||
do_check_eq(tempAddon.name, "Test Bootstrap 1 (temporary)");
|
||||
do_check_true(tempAddon.isCompatible);
|
||||
do_check_false(tempAddon.appDisabled);
|
||||
do_check_true(tempAddon.isActive);
|
||||
do_check_eq(tempAddon.type, "extension");
|
||||
do_check_eq(tempAddon.signedState, mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_MISSING : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
|
||||
|
||||
tempAddon.uninstall();
|
||||
unpacked_addon.remove(true);
|
||||
|
||||
addon.userDisabled = false;
|
||||
addon = yield promiseAddonByID(ID);
|
||||
|
||||
BootstrapMonitor.checkAddonInstalled(ID, "1.0");
|
||||
BootstrapMonitor.checkAddonStarted(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_MISSING : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
|
||||
|
||||
addon.uninstall();
|
||||
|
||||
BootstrapMonitor.checkAddonNotInstalled(ID);
|
||||
BootstrapMonitor.checkAddonNotStarted(ID);
|
||||
|
||||
yield promiseRestartManager();
|
||||
});
|
||||
|
||||
// Installing a temporary add-on over a non-restartless add-on should fail.
|
||||
add_task(function*(){
|
||||
yield promiseInstallAllFiles([do_get_addon("test_install1")], true);
|
||||
|
||||
let non_restartless_ID = "addon1@tests.mozilla.org";
|
||||
|
||||
BootstrapMonitor.checkAddonNotInstalled(non_restartless_ID);
|
||||
BootstrapMonitor.checkAddonNotStarted(non_restartless_ID);
|
||||
|
||||
restartManager();
|
||||
|
||||
BootstrapMonitor.checkAddonNotInstalled(non_restartless_ID);
|
||||
BootstrapMonitor.checkAddonNotStarted(non_restartless_ID);
|
||||
|
||||
let addon = yield promiseAddonByID(non_restartless_ID);
|
||||
|
||||
// non-restartless add-on is installed and started
|
||||
do_check_neq(addon, null);
|
||||
do_check_eq(addon.id, non_restartless_ID);
|
||||
do_check_eq(addon.version, "1.0");
|
||||
do_check_eq(addon.name, "Test 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_MISSING : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
|
||||
|
||||
let tempdir = gTmpD.clone();
|
||||
writeInstallRDFToDir({
|
||||
id: non_restartless_ID,
|
||||
version: "2.0",
|
||||
bootstrap: true,
|
||||
unpack: true,
|
||||
targetApplications: [{
|
||||
id: "xpcshell@tests.mozilla.org",
|
||||
minVersion: "1",
|
||||
maxVersion: "1"
|
||||
}],
|
||||
name: "Test 1 (temporary)",
|
||||
}, tempdir);
|
||||
|
||||
let unpacked_addon = tempdir.clone();
|
||||
unpacked_addon.append(non_restartless_ID);
|
||||
|
||||
try {
|
||||
yield AddonManager.installTemporaryAddon(unpacked_addon);
|
||||
do_throw("Installing over a non-restartless add-on should return"
|
||||
+ " a rejected promise");
|
||||
} catch (err) {
|
||||
do_check_eq(err.message,
|
||||
"Non-restartless add-on with ID addon1@tests.mozilla.org is"
|
||||
+ " already installed");
|
||||
}
|
||||
|
||||
unpacked_addon.remove(true);
|
||||
addon.uninstall();
|
||||
|
||||
BootstrapMonitor.checkAddonNotInstalled(ID);
|
||||
BootstrapMonitor.checkAddonNotStarted(ID);
|
||||
|
||||
yield promiseRestartManager();
|
||||
});
|
||||
|
||||
// Installing a temporary add-on when there is already a temporary
|
||||
// add-on should fail.
|
||||
add_task(function*() {
|
||||
yield AddonManager.installTemporaryAddon(do_get_addon("test_bootstrap1_1"));
|
||||
|
||||
let addon = yield promiseAddonByID(ID);
|
||||
|
||||
BootstrapMonitor.checkAddonInstalled(ID, "1.0");
|
||||
BootstrapMonitor.checkAddonStarted(ID, "1.0");
|
||||
|
||||
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_MISSING : AddonManager.SIGNEDSTATE_NOT_REQUIRED);
|
||||
|
||||
try {
|
||||
yield AddonManager.installTemporaryAddon(do_get_addon("test_bootstrap1_1"));
|
||||
do_throw("Installing a temporary second temporary add-on should return"
|
||||
+ " a rejected promise");
|
||||
} catch (err) {
|
||||
do_check_eq(err.message,
|
||||
"Add-on with ID bootstrap1@tests.mozilla.org is already temporarily"
|
||||
+ " installed");
|
||||
}
|
||||
|
||||
BootstrapMonitor.checkAddonInstalled(ID, "1.0");
|
||||
BootstrapMonitor.checkAddonStarted(ID, "1.0");
|
||||
|
||||
yield promiseRestartManager();
|
||||
|
||||
BootstrapMonitor.checkAddonNotInstalled(ID);
|
||||
BootstrapMonitor.checkAddonNotStarted(ID);
|
||||
});
|
@ -29,6 +29,7 @@ skip-if = appname != "firefox"
|
||||
[test_system_reset.js]
|
||||
[test_XPIcancel.js]
|
||||
[test_XPIStates.js]
|
||||
[test_temporary.js]
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user