Bug 1448221: Part 1 - Remove support for operations requiring restart. r?aswan
MozReview-Commit-ID: EJDAAXCpViY
--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -1706,143 +1706,135 @@ class AddonInstall {
aInstall.addon.id == this.addon.id) {
logger.debug("Cancelling previous pending install of " + aInstall.addon.id);
aInstall.cancel();
}
}
let isUpgrade = this.existingAddon &&
this.existingAddon._installLocation == this.installLocation;
- let requiresRestart = XPIProvider.installRequiresRestart(this.addon);
logger.debug("Starting install of " + this.addon.id + " from " + this.sourceURI.spec);
AddonManagerPrivate.callAddonListeners("onInstalling",
this.addon.wrapper,
- requiresRestart);
+ false);
let stagedAddon = this.installLocation.getStagingDir();
(async () => {
await this.installLocation.requestStagingDir();
// remove any previously staged files
await this.unstageInstall(stagedAddon);
stagedAddon.append(`${this.addon.id}.xpi`);
- await this.stageInstall(requiresRestart, stagedAddon, isUpgrade);
+ await this.stageInstall(false, stagedAddon, isUpgrade);
- if (requiresRestart) {
- this.state = AddonManager.STATE_INSTALLED;
- AddonManagerPrivate.callInstallListeners("onInstallEnded",
- this.listeners, this.wrapper,
- this.addon.wrapper);
- } else {
- // The install is completed so it should be removed from the active list
- XPIProvider.removeActiveInstall(this);
+ // The install is completed so it should be removed from the active list
+ XPIProvider.removeActiveInstall(this);
- // Deactivate and remove the old add-on as necessary
- let reason = BOOTSTRAP_REASONS.ADDON_INSTALL;
- let callUpdate = false;
- if (this.existingAddon) {
- if (Services.vc.compare(this.existingAddon.version, this.addon.version) < 0)
- reason = BOOTSTRAP_REASONS.ADDON_UPGRADE;
- else
- reason = BOOTSTRAP_REASONS.ADDON_DOWNGRADE;
-
- callUpdate = isWebExtension(this.addon.type) && isWebExtension(this.existingAddon.type);
+ // Deactivate and remove the old add-on as necessary
+ let reason = BOOTSTRAP_REASONS.ADDON_INSTALL;
+ let callUpdate = false;
+ if (this.existingAddon) {
+ if (Services.vc.compare(this.existingAddon.version, this.addon.version) < 0)
+ reason = BOOTSTRAP_REASONS.ADDON_UPGRADE;
+ else
+ reason = BOOTSTRAP_REASONS.ADDON_DOWNGRADE;
- if (this.existingAddon.bootstrap) {
- let file = this.existingAddon._sourceBundle;
- if (this.existingAddon.active) {
- XPIProvider.callBootstrapMethod(this.existingAddon, file,
- "shutdown", reason,
- { newVersion: this.addon.version });
- }
+ callUpdate = isWebExtension(this.addon.type) && isWebExtension(this.existingAddon.type);
- if (!callUpdate) {
- XPIProvider.callBootstrapMethod(this.existingAddon, file,
- "uninstall", reason,
- { newVersion: this.addon.version });
- }
- XPIProvider.unloadBootstrapScope(this.existingAddon.id);
- flushChromeCaches();
+ if (this.existingAddon.bootstrap) {
+ let file = this.existingAddon._sourceBundle;
+ if (this.existingAddon.active) {
+ XPIProvider.callBootstrapMethod(this.existingAddon, file,
+ "shutdown", reason,
+ { newVersion: this.addon.version });
}
- if (!isUpgrade && this.existingAddon.active) {
- XPIDatabase.updateAddonActive(this.existingAddon, false);
+ if (!callUpdate) {
+ XPIProvider.callBootstrapMethod(this.existingAddon, file,
+ "uninstall", reason,
+ { newVersion: this.addon.version });
}
+ XPIProvider.unloadBootstrapScope(this.existingAddon.id);
+ flushChromeCaches();
}
- // Install the new add-on into its final location
- let existingAddonID = this.existingAddon ? this.existingAddon.id : null;
- let file = this.installLocation.installAddon({
- id: this.addon.id,
- source: stagedAddon,
- existingAddonID
- });
+ if (!isUpgrade && this.existingAddon.active) {
+ XPIDatabase.updateAddonActive(this.existingAddon, false);
+ }
+ }
- // Update the metadata in the database
- this.addon._sourceBundle = file;
- this.addon.visible = true;
+ // Install the new add-on into its final location
+ let existingAddonID = this.existingAddon ? this.existingAddon.id : null;
+ let file = this.installLocation.installAddon({
+ id: this.addon.id,
+ source: stagedAddon,
+ existingAddonID
+ });
+
+ // Update the metadata in the database
+ this.addon._sourceBundle = file;
+ this.addon.visible = true;
- if (isUpgrade) {
- this.addon = XPIDatabase.updateAddonMetadata(this.existingAddon, this.addon,
- file.path);
- let state = XPIStates.getAddon(this.installLocation.name, this.addon.id);
- if (state) {
- state.syncWithDB(this.addon, true);
- } else {
- logger.warn("Unexpected missing XPI state for add-on ${id}", this.addon);
- }
+ if (isUpgrade) {
+ this.addon = XPIDatabase.updateAddonMetadata(this.existingAddon, this.addon,
+ file.path);
+ let state = XPIStates.getAddon(this.installLocation.name, this.addon.id);
+ if (state) {
+ state.syncWithDB(this.addon, true);
} else {
- this.addon.active = (this.addon.visible && !this.addon.disabled);
- this.addon = XPIDatabase.addAddonMetadata(this.addon, file.path);
- XPIStates.addAddon(this.addon);
- this.addon.installDate = this.addon.updateDate;
- XPIDatabase.saveChanges();
+ logger.warn("Unexpected missing XPI state for add-on ${id}", this.addon);
}
- XPIStates.save();
+ } else {
+ this.addon.active = (this.addon.visible && !this.addon.disabled);
+ this.addon = XPIDatabase.addAddonMetadata(this.addon, file.path);
+ XPIStates.addAddon(this.addon);
+ this.addon.installDate = this.addon.updateDate;
+ XPIDatabase.saveChanges();
+ }
+ XPIStates.save();
- let extraParams = {};
- if (this.existingAddon) {
- extraParams.oldVersion = this.existingAddon.version;
- }
+ let extraParams = {};
+ if (this.existingAddon) {
+ extraParams.oldVersion = this.existingAddon.version;
+ }
- if (this.addon.bootstrap) {
- let method = callUpdate ? "update" : "install";
- XPIProvider.callBootstrapMethod(this.addon, file, method,
- reason, extraParams);
- }
+ if (this.addon.bootstrap) {
+ let method = callUpdate ? "update" : "install";
+ XPIProvider.callBootstrapMethod(this.addon, file, method,
+ reason, extraParams);
+ }
- AddonManagerPrivate.callAddonListeners("onInstalled",
+ AddonManagerPrivate.callAddonListeners("onInstalled",
+ this.addon.wrapper);
+
+ logger.debug("Install of " + this.sourceURI.spec + " completed.");
+ this.state = AddonManager.STATE_INSTALLED;
+ AddonManagerPrivate.callInstallListeners("onInstallEnded",
+ this.listeners, this.wrapper,
this.addon.wrapper);
- logger.debug("Install of " + this.sourceURI.spec + " completed.");
- this.state = AddonManager.STATE_INSTALLED;
- AddonManagerPrivate.callInstallListeners("onInstallEnded",
- this.listeners, this.wrapper,
- this.addon.wrapper);
+ if (this.addon.bootstrap) {
+ if (this.addon.active) {
+ XPIProvider.callBootstrapMethod(this.addon, file, "startup",
+ reason, extraParams);
+ } else {
+ // XXX this makes it dangerous to do some things in onInstallEnded
+ // listeners because important cleanup hasn't been done yet
+ XPIProvider.unloadBootstrapScope(this.addon.id);
+ }
+ }
+ recordAddonTelemetry(this.addon);
- if (this.addon.bootstrap) {
- if (this.addon.active) {
- XPIProvider.callBootstrapMethod(this.addon, file, "startup",
- reason, extraParams);
- } else {
- // XXX this makes it dangerous to do some things in onInstallEnded
- // listeners because important cleanup hasn't been done yet
- XPIProvider.unloadBootstrapScope(this.addon.id);
- }
- }
- recordAddonTelemetry(this.addon);
-
- // Notify providers that a new theme has been enabled.
- if (isTheme(this.addon.type) && this.addon.active)
- AddonManagerPrivate.notifyAddonChanged(this.addon.id, this.addon.type, requiresRestart);
- }
+ // Notify providers that a new theme has been enabled.
+ if (isTheme(this.addon.type) && this.addon.active)
+ AddonManagerPrivate.notifyAddonChanged(this.addon.id, this.addon.type);
})().catch((e) => {
logger.warn(`Failed to install ${this.file.path} from ${this.sourceURI.spec} to ${stagedAddon.path}`, e);
if (stagedAddon.exists())
recursiveRemove(stagedAddon);
this.state = AddonManager.STATE_INSTALL_FAILED;
this.error = AddonManager.ERROR_FILE_ACCESS;
XPIProvider.removeActiveInstall(this);
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -3751,21 +3751,18 @@ var XPIProvider = {
/**
* Called when a new add-on has been enabled when only one add-on of that type
* can be enabled.
*
* @param aId
* The ID of the newly enabled add-on
* @param aType
* The type of the newly enabled add-on
- * @param aPendingRestart
- * true if the newly enabled add-on will only become enabled after a
- * restart
*/
- addonChanged(aId, aType, aPendingRestart) {
+ addonChanged(aId, aType) {
// We only care about themes in this provider
if (!isTheme(aType))
return;
if (!aId) {
// Fallback to the default theme when no theme was enabled
this.enableDefaultTheme();
return;
@@ -3777,48 +3774,38 @@ var XPIProvider = {
let newSkin = this.defaultSkin;
let addons = XPIDatabase.getAddonsByType("theme", "webextension-theme");
for (let theme of addons) {
if (!theme.visible)
return;
let isChangedAddon = (theme.id == aId);
if (isWebExtension(theme.type)) {
if (!isChangedAddon)
- this.updateAddonDisabledState(theme, true, undefined, aPendingRestart);
+ this.updateAddonDisabledState(theme, true, undefined);
} else if (isChangedAddon) {
newSkin = theme.internalName;
} else if (!theme.userDisabled && !theme.pendingUninstall) {
previousTheme = theme;
}
}
- if (aPendingRestart) {
- Services.prefs.setBoolPref(PREF_SKIN_SWITCHPENDING, true);
- Services.prefs.setCharPref(PREF_SKIN_TO_SELECT, newSkin);
- } else if (newSkin == this.currentSkin) {
- try {
- Services.prefs.clearUserPref(PREF_SKIN_SWITCHPENDING);
- } catch (e) { }
- try {
- Services.prefs.clearUserPref(PREF_SKIN_TO_SELECT);
- } catch (e) { }
- } else {
+ if (newSkin != this.currentSkin) {
Services.prefs.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, newSkin);
this.currentSkin = newSkin;
}
this.selectedSkin = newSkin;
// Flush the preferences to disk so they don't get out of sync with the
// database
Services.prefs.savePrefFile(null);
// Mark the previous theme as disabled. This won't cause recursion since
// only enabled calls notifyAddonChanged.
if (previousTheme)
- this.updateAddonDisabledState(previousTheme, true, undefined, aPendingRestart);
+ this.updateAddonDisabledState(previousTheme, true, undefined);
},
/**
* Update the appDisabled property for all add-ons.
*/
updateAddonAppDisabledStates() {
let addons = XPIDatabase.getAddons();
for (let addon of addons) {
@@ -3930,166 +3917,16 @@ var XPIProvider = {
case PREF_ALLOW_LEGACY:
this.updateAddonAppDisabledStates();
break;
}
}
},
/**
- * Tests whether enabling an add-on will require a restart.
- *
- * @param aAddon
- * The add-on to test
- * @return true if the operation requires a restart
- */
- enableRequiresRestart(aAddon) {
- // If the platform couldn't have activated extensions then we can make
- // changes without any restart.
- if (!this.extensionsActive)
- return false;
-
- // If the application is in safe mode then any change can be made without
- // restarting
- if (Services.appinfo.inSafeMode)
- return false;
-
- // Anything that is active is already enabled
- if (aAddon.active)
- return false;
-
- if (isTheme(aAddon.type)) {
- if (isWebExtension(aAddon.type)) {
- // Enabling a WebExtension type theme requires a restart ONLY when the
- // theme-to-be-disabled requires a restart.
- let theme = XPIDatabase.getVisibleAddonForInternalName(this.currentSkin);
- return !theme || this.disableRequiresRestart(theme);
- }
-
- // If the theme is already the theme in use then no restart is necessary.
- // This covers the case where the default theme is in use but a
- // lightweight theme is considered active.
- return aAddon.internalName != this.currentSkin;
- }
-
- return !aAddon.bootstrap;
- },
-
- /**
- * Tests whether disabling an add-on will require a restart.
- *
- * @param aAddon
- * The add-on to test
- * @return true if the operation requires a restart
- */
- disableRequiresRestart(aAddon) {
- // If the platform couldn't have activated up extensions then we can make
- // changes without any restart.
- if (!this.extensionsActive)
- return false;
-
- // If the application is in safe mode then any change can be made without
- // restarting
- if (Services.appinfo.inSafeMode)
- return false;
-
- // Anything that isn't active is already disabled
- if (!aAddon.active)
- return false;
-
- if (aAddon.type == "theme") {
- // Non-default themes always require a restart to disable since it will
- // be switching from one theme to another or to the default theme and a
- // lightweight theme.
- if (aAddon.internalName != this.defaultSkin)
- return true;
-
- // The default theme requires a restart to disable if we are in the
- // process of switching to a different theme. Note that this makes the
- // disabled flag of operationsRequiringRestart incorrect for the default
- // theme (it will be false most of the time). Bug 520124 would be required
- // to fix it. For the UI this isn't a problem since we never try to
- // disable or uninstall the default theme.
- return this.selectedSkin != this.currentSkin;
- }
-
- return !aAddon.bootstrap;
- },
-
- /**
- * Tests whether installing an add-on will require a restart.
- *
- * @param aAddon
- * The add-on to test
- * @return true if the operation requires a restart
- */
- installRequiresRestart(aAddon) {
- // If the platform couldn't have activated up extensions then we can make
- // changes without any restart.
- if (!this.extensionsActive)
- return false;
-
- // If the application is in safe mode then any change can be made without
- // restarting
- if (Services.appinfo.inSafeMode)
- return false;
-
- // Add-ons that are already installed don't require a restart to install.
- // This wouldn't normally be called for an already installed add-on (except
- // for forming the operationsRequiringRestart flags) so is really here as
- // a safety measure.
- if (aAddon.inDatabase)
- return false;
-
- // If we have an AddonInstall for this add-on then we can see if there is
- // an existing installed add-on with the same ID
- if ("_install" in aAddon && aAddon._install) {
- // If there is an existing installed add-on and uninstalling it would
- // require a restart then installing the update will also require a
- // restart
- let existingAddon = aAddon._install.existingAddon;
- if (existingAddon && this.uninstallRequiresRestart(existingAddon))
- return true;
- }
-
- // If the add-on is not going to be active after installation then it
- // doesn't require a restart to install.
- if (aAddon.disabled)
- return false;
-
- // Themes will require a restart (even if dynamic switching is enabled due
- // to some caching issues) and non-bootstrapped add-ons will require a
- // restart
- return aAddon.type == "theme" || !aAddon.bootstrap;
- },
-
- /**
- * Tests whether uninstalling an add-on will require a restart.
- *
- * @param aAddon
- * The add-on to test
- * @return true if the operation requires a restart
- */
- uninstallRequiresRestart(aAddon) {
- // If the platform couldn't have activated up extensions then we can make
- // changes without any restart.
- if (!this.extensionsActive)
- return false;
-
- // If the application is in safe mode then any change can be made without
- // restarting
- if (Services.appinfo.inSafeMode)
- return false;
-
- // If the add-on can be disabled without a restart then it can also be
- // uninstalled without a restart
- return this.disableRequiresRestart(aAddon);
- },
-
- /**
* Loads a bootstrapped add-on's bootstrap.js into a sandbox and the reason
* values as constants in the scope. This will also add information about the
* add-on to the bootstrappedAddons dictionary and notify the crash reporter
* that new add-ons have been loaded.
*
* @param aId
* The add-on's ID
* @param aFile
@@ -4341,26 +4178,23 @@ var XPIProvider = {
* @param aAddon
* The DBAddonInternal to update
* @param aUserDisabled
* Value for the userDisabled property. If undefined the value will
* not change
* @param aSoftDisabled
* Value for the softDisabled property. If undefined the value will
* not change. If true this will force userDisabled to be true
- * @param aPendingRestart
- * If the addon is updated whilst the disabled state of another non-
- * restartless addon is also set, we need to carry that forward.
* @return a tri-state indicating the action taken for the add-on:
* - undefined: The add-on did not change state
* - true: The add-on because disabled
* - false: The add-on became enabled
* @throws if addon is not a DBAddonInternal
*/
- updateAddonDisabledState(aAddon, aUserDisabled, aSoftDisabled, aPendingRestart = false) {
+ updateAddonDisabledState(aAddon, aUserDisabled, aSoftDisabled) {
if (!(aAddon.inDatabase))
throw new Error("Can only update addon states for installed addons.");
if (aUserDisabled !== undefined && aSoftDisabled !== undefined) {
throw new Error("Cannot change userDisabled and softDisabled at the " +
"same time");
}
if (aUserDisabled === undefined) {
@@ -4422,48 +4256,42 @@ var XPIProvider = {
logger.warn("No XPIState for ${id} in ${location}", aAddon);
}
// Have we just gone back to the current state?
if (isDisabled != aAddon.active) {
AddonManagerPrivate.callAddonListeners("onOperationCancelled", wrapper);
} else {
if (isDisabled) {
- var needsRestart = aPendingRestart || this.disableRequiresRestart(aAddon);
- AddonManagerPrivate.callAddonListeners("onDisabling", wrapper,
- needsRestart);
+ AddonManagerPrivate.callAddonListeners("onDisabling", wrapper, false);
} else {
- needsRestart = this.enableRequiresRestart(aAddon);
- AddonManagerPrivate.callAddonListeners("onEnabling", wrapper,
- needsRestart);
+ AddonManagerPrivate.callAddonListeners("onEnabling", wrapper, false);
}
- if (!needsRestart) {
- XPIDatabase.updateAddonActive(aAddon, !isDisabled);
-
- if (isDisabled) {
- if (aAddon.bootstrap && this.activeAddons.has(aAddon.id)) {
- this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "shutdown",
- BOOTSTRAP_REASONS.ADDON_DISABLE);
- this.unloadBootstrapScope(aAddon.id);
- }
- AddonManagerPrivate.callAddonListeners("onDisabled", wrapper);
- } else {
- if (aAddon.bootstrap) {
- this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "startup",
- BOOTSTRAP_REASONS.ADDON_ENABLE);
- }
- AddonManagerPrivate.callAddonListeners("onEnabled", wrapper);
+ XPIDatabase.updateAddonActive(aAddon, !isDisabled);
+
+ if (isDisabled) {
+ if (aAddon.bootstrap && this.activeAddons.has(aAddon.id)) {
+ this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "shutdown",
+ BOOTSTRAP_REASONS.ADDON_DISABLE);
+ this.unloadBootstrapScope(aAddon.id);
}
+ AddonManagerPrivate.callAddonListeners("onDisabled", wrapper);
+ } else {
+ if (aAddon.bootstrap) {
+ this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "startup",
+ BOOTSTRAP_REASONS.ADDON_ENABLE);
+ }
+ AddonManagerPrivate.callAddonListeners("onEnabled", wrapper);
}
}
// Notify any other providers that a new theme has been enabled
if (isTheme(aAddon.type) && !isDisabled) {
- AddonManagerPrivate.notifyAddonChanged(aAddon.id, aAddon.type, needsRestart);
+ AddonManagerPrivate.notifyAddonChanged(aAddon.id, aAddon.type);
if (xpiState) {
xpiState.syncWithDB(aAddon);
XPIStates.save();
}
}
return isDisabled;
@@ -4471,36 +4299,33 @@ var XPIProvider = {
/**
* Uninstalls an add-on, immediately if possible or marks it as pending
* uninstall if not.
*
* @param aAddon
* The DBAddonInternal to uninstall
* @param aForcePending
- * Force this addon into the pending uninstall state, even if
- * it isn't marked as requiring a restart (used e.g. while the
- * add-on manager is open and offering an "undo" button)
+ * Force this addon into the pending uninstall state (used
+ * e.g. while the add-on manager is open and offering an
+ * "undo" button)
* @throws if the addon cannot be uninstalled because it is in an install
* location that does not allow it
*/
uninstallAddon(aAddon, aForcePending) {
if (!(aAddon.inDatabase))
throw new Error("Cannot uninstall addon " + aAddon.id + " because it is not installed");
if (aAddon._installLocation.locked)
throw new Error("Cannot uninstall addon " + aAddon.id
+ " from locked install location " + aAddon._installLocation.name);
- // Inactive add-ons don't require a restart to uninstall
- let requiresRestart = this.uninstallRequiresRestart(aAddon);
-
// if makePending is true, we don't actually apply the uninstall,
// we just mark the addon as having a pending uninstall
- let makePending = aForcePending || requiresRestart;
+ let makePending = aForcePending;
if (makePending && aAddon.pendingUninstall)
throw new Error("Add-on is already marked to be uninstalled");
aAddon._hasResourceCache.clear();
if (aAddon._updateCheck) {
logger.debug("Cancel in-progress update check for " + aAddon.id);
@@ -4536,22 +4361,18 @@ var XPIProvider = {
// If the add-on is not visible then there is no need to notify listeners.
if (!aAddon.visible)
return;
let wrapper = aAddon.wrapper;
// If the add-on wasn't already pending uninstall then notify listeners.
if (!wasPending) {
- // Passing makePending as the requiresRestart parameter is a little
- // strange as in some cases this operation can complete without a restart
- // so really this is now saying that the uninstall isn't going to happen
- // immediately but will happen later.
AddonManagerPrivate.callAddonListeners("onUninstalling", wrapper,
- makePending);
+ !!makePending);
}
let reason = BOOTSTRAP_REASONS.ADDON_UNINSTALL;
let callUpdate = false;
let existingAddon = XPIStates.findAddon(aAddon.id, loc =>
loc.name != aAddon._installLocation.name);
if (existingAddon) {
reason = newVersionReason(aAddon.version, existingAddon.version);
@@ -4580,48 +4401,46 @@ var XPIProvider = {
if (existingAddon) {
XPIDatabase.getAddonInLocation(aAddon.id, existingAddon.location.name, existing => {
XPIDatabase.makeAddonVisible(existing);
let wrappedAddon = existing.wrapper;
AddonManagerPrivate.callAddonListeners("onInstalling", wrappedAddon, false);
- if (!existing.disabled && !XPIProvider.enableRequiresRestart(existing)) {
+ if (!existing.disabled) {
XPIDatabase.updateAddonActive(existing, true);
}
if (aAddon.bootstrap) {
let method = callUpdate ? "update" : "install";
XPIProvider.callBootstrapMethod(existing, existing._sourceBundle,
method, reason);
if (existing.active) {
XPIProvider.callBootstrapMethod(existing, existing._sourceBundle,
"startup", reason);
} else {
XPIProvider.unloadBootstrapScope(existing.id);
}
}
- // We always send onInstalled even if a restart is required to enable
- // the revealed add-on
AddonManagerPrivate.callAddonListeners("onInstalled", wrappedAddon);
});
}
- } else if (aAddon.bootstrap && aAddon.active && !this.disableRequiresRestart(aAddon)) {
+ } else if (aAddon.bootstrap && aAddon.active) {
this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "shutdown", reason);
XPIStates.disableAddon(aAddon.id);
this.unloadBootstrapScope(aAddon.id);
XPIDatabase.updateAddonActive(aAddon, false);
}
// Notify any other providers that a new theme has been enabled
if (isTheme(aAddon.type) && aAddon.active)
- AddonManagerPrivate.notifyAddonChanged(null, aAddon.type, requiresRestart);
+ AddonManagerPrivate.notifyAddonChanged(null, aAddon.type);
},
/**
* Cancels the pending uninstall of an add-on.
*
* @param aAddon
* The DBAddonInternal to cancel uninstall for
*/
@@ -4645,17 +4464,17 @@ var XPIProvider = {
XPIStates.save();
Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, true);
// TODO hide hidden add-ons (bug 557710)
let wrapper = aAddon.wrapper;
AddonManagerPrivate.callAddonListeners("onOperationCancelled", wrapper);
- if (aAddon.bootstrap && !aAddon.disabled && !this.enableRequiresRestart(aAddon)) {
+ if (aAddon.bootstrap && !aAddon.disabled) {
this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "startup",
BOOTSTRAP_REASONS.ADDON_INSTALL);
XPIDatabase.updateAddonActive(aAddon, true);
}
// Notify any other providers that this theme is now enabled again.
if (isTheme(aAddon.type) && aAddon.active)
AddonManagerPrivate.notifyAddonChanged(aAddon.id, aAddon.type, false);
@@ -5356,28 +5175,17 @@ AddonWrapper.prototype = {
if (addon.pendingUpgrade)
pending |= AddonManager.PENDING_UPGRADE;
return pending;
},
get operationsRequiringRestart() {
- let addon = addonFor(this);
- let ops = 0;
- if (XPIProvider.installRequiresRestart(addon))
- ops |= AddonManager.OP_NEEDS_RESTART_INSTALL;
- if (XPIProvider.uninstallRequiresRestart(addon))
- ops |= AddonManager.OP_NEEDS_RESTART_UNINSTALL;
- if (XPIProvider.enableRequiresRestart(addon))
- ops |= AddonManager.OP_NEEDS_RESTART_ENABLE;
- if (XPIProvider.disableRequiresRestart(addon))
- ops |= AddonManager.OP_NEEDS_RESTART_DISABLE;
-
- return ops;
+ return 0;
},
get isDebuggable() {
return this.isActive && addonFor(this).bootstrap;
},
get permissions() {
return addonFor(this).permissions();
@@ -6415,21 +6223,16 @@ class SystemAddonInstallLocation extends
}
isValidAddon(aAddon) {
if (aAddon.appDisabled) {
logger.warn(`System add-on ${aAddon.id} isn't compatible with the application.`);
return false;
}
- if (!aAddon.bootstrap) {
- logger.warn(`System add-on ${aAddon.id} isn't restartless.`);
- return false;
- }
-
return true;
}
/**
* Tests whether the loaded add-on information matches what is expected.
*/
isValid(aAddons) {
for (let id of Object.keys(this._addonSet.addons)) {
--- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
@@ -178,29 +178,16 @@ function DBAddonInternal(aLoaded) {
this._key = this.location + ":" + this.id;
if (!aLoaded._sourceBundle) {
throw new Error("Expected passed argument to contain a path");
}
this._sourceBundle = aLoaded._sourceBundle;
-
- XPCOMUtils.defineLazyGetter(this, "pendingUpgrade", function() {
- for (let install of XPIProvider.installs) {
- if (install.state == AddonManager.STATE_INSTALLED &&
- !(install.addon.inDatabase) &&
- install.addon.id == this.id &&
- install.installLocation == this._installLocation) {
- delete this.pendingUpgrade;
- return this.pendingUpgrade = install.addon;
- }
- }
- return null;
- });
}
DBAddonInternal.prototype = Object.create(AddonInternal.prototype);
Object.assign(DBAddonInternal.prototype, {
applyCompatibilityUpdate(aUpdate, aSyncCompatibility) {
let wasCompatible = this.isCompatible;
this.targetApplications.forEach(function(aTargetApp) {
@@ -826,20 +813,17 @@ this.XPIDatabase = {
* @param aTypes
* The types of add-ons to retrieve or null to get all types
* @param aCallback
* A callback to pass the array of DBAddonInternal to
*/
getVisibleAddonsWithPendingOperations(aTypes, aCallback) {
this.getAddonList(
aAddon => (aAddon.visible &&
- (aAddon.pendingUninstall ||
- // Logic here is tricky. If we're active but disabled,
- // we're pending disable; !active && !disabled, we're pending enable
- (aAddon.active == aAddon.disabled)) &&
+ aAddon.pendingUninstall &&
(!aTypes || (aTypes.length == 0) || (aTypes.indexOf(aAddon.type) > -1))),
aCallback);
},
/**
* Asynchronously get an add-on by its Sync GUID.
*
* @param aGUID
@@ -1165,17 +1149,17 @@ this.XPIDatabaseReconcile = {
if (aNewAddon.id != aId) {
throw new Error("Invalid addon ID: expected addon ID " + aId +
", found " + aNewAddon.id + " in manifest");
}
} catch (e) {
logger.warn("addMetadata: Add-on " + aId + " is invalid", e);
// Remove the invalid add-on from the install location if the install
- // location isn't locked, no restart will be necessary
+ // location isn't locked
if (aInstallLocation.isLinkedAddon(aId))
logger.warn("Not uninstalling invalid item because it is a proxy file");
else if (aInstallLocation.locked)
logger.warn("Could not uninstall invalid item from locked install location");
else
aInstallLocation.uninstallAddon(aId);
return null;
}
@@ -1223,19 +1207,18 @@ this.XPIDatabaseReconcile = {
*/
removeMetadata(aOldAddon) {
// This add-on has disappeared
logger.debug("Add-on " + aOldAddon.id + " removed from " + aOldAddon.location);
XPIDatabase.removeAddonMetadata(aOldAddon);
},
/**
- * Updates an add-on's metadata and determines if a restart of the
- * application is necessary. This is called when either the add-on's
- * install directory path or last modified time has changed.
+ * Updates an add-on's metadata and determines. This is called when either the
+ * add-on's install directory path or last modified time has changed.
*
* @param aInstallLocation
* The install location containing the add-on
* @param aOldAddon
* The AddonInternal as it appeared the last time the application
* ran
* @param aAddonState
* The new state of the add-on
@@ -1248,22 +1231,16 @@ this.XPIDatabaseReconcile = {
logger.debug("Add-on " + aOldAddon.id + " modified in " + aInstallLocation.name);
try {
// If there isn't an updated install manifest for this add-on then load it.
if (!aNewAddon) {
let file = new nsIFile(aAddonState.path);
aNewAddon = syncLoadManifestFromFile(file, aInstallLocation);
- // Carry over any pendingUninstall state to add-ons modified directly
- // in the profile. This is important when the attempt to remove the
- // add-on in processPendingFileChanges failed and caused an mtime
- // change to the add-ons files.
- aNewAddon.pendingUninstall = aOldAddon.pendingUninstall;
-
aNewAddon.updateBlocklistState({oldAddon: aOldAddon});
}
// The ID in the manifest that was loaded must match the ID of the old
// add-on.
if (aNewAddon.id != aOldAddon.id)
throw new Error("Incorrect id in install manifest for existing add-on " + aOldAddon.id);
} catch (e) {