--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -1794,33 +1794,38 @@ class AddonInstall {
this.listeners, this.wrapper,
this.addon.wrapper);
} else {
// 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);
+
if (this.existingAddon.bootstrap) {
let file = this.existingAddon._sourceBundle;
if (this.existingAddon.active) {
XPIProvider.callBootstrapMethod(this.existingAddon, file,
"shutdown", reason,
{ newVersion: this.addon.version });
}
- XPIProvider.callBootstrapMethod(this.existingAddon, file,
- "uninstall", reason,
- { newVersion: this.addon.version });
+ if (!callUpdate) {
+ XPIProvider.callBootstrapMethod(this.existingAddon, file,
+ "uninstall", reason,
+ { newVersion: this.addon.version });
+ }
XPIProvider.unloadBootstrapScope(this.existingAddon.id);
flushChromeCaches();
}
if (!isUpgrade && this.existingAddon.active) {
XPIDatabase.updateAddonActive(this.existingAddon, false);
}
}
@@ -1856,17 +1861,18 @@ class AddonInstall {
XPIStates.save();
let extraParams = {};
if (this.existingAddon) {
extraParams.oldVersion = this.existingAddon.version;
}
if (this.addon.bootstrap) {
- XPIProvider.callBootstrapMethod(this.addon, file, "install",
+ let method = callUpdate ? "update" : "install";
+ XPIProvider.callBootstrapMethod(this.addon, file, method,
reason, extraParams);
}
AddonManagerPrivate.callAddonListeners("onInstalled",
this.addon.wrapper);
logger.debug("Install of " + this.sourceURI.spec + " completed.");
this.state = AddonManager.STATE_INSTALLED;
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -2387,33 +2387,38 @@ this.XPIProvider = {
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 existing = XPIStates.findAddon(id, loc => loc != tempLocation);
+ let callUpdate = false;
if (existing) {
reason = newVersionReason(addon.version, existing.version);
+ callUpdate = (isWebExtension(addon.type) && isWebExtension(existing.type));
}
this.callBootstrapMethod(addon, addon.file, "shutdown", reason);
- this.callBootstrapMethod(addon, addon.file, "uninstall", reason);
+ if (!callUpdate) {
+ this.callBootstrapMethod(addon, addon.file, "uninstall", reason);
+ }
this.unloadBootstrapScope(id);
TemporaryInstallLocation.uninstallAddon(id);
XPIStates.removeAddon(TemporaryInstallLocation.name, id);
if (existing) {
let newAddon = XPIDatabase.makeAddonLocationVisible(id, existing.location.name);
let file = new nsIFile(newAddon.path);
let data = {oldVersion: addon.version};
- this.callBootstrapMethod(newAddon, file, "install", reason, data);
+ let method = callUpdate ? "update" : "install";
+ this.callBootstrapMethod(newAddon, file, method, reason, data);
}
}
}
},
/**
* Applies any pending theme change to the preferences.
*/
@@ -3548,16 +3553,17 @@ this.XPIProvider = {
if (!addon.bootstrap) {
throw new Error("Only restartless (bootstrap) add-ons"
+ " can be installed from sources:", addon.id);
}
let installReason = BOOTSTRAP_REASONS.ADDON_INSTALL;
let oldAddon = await new Promise(
resolve => XPIDatabase.getVisibleAddonForID(addon.id, resolve));
+ let callUpdate = false;
let extraParams = {};
extraParams.temporarilyInstalled = aInstallLocation === TemporaryInstallLocation;
if (oldAddon) {
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");
@@ -3576,34 +3582,40 @@ this.XPIProvider = {
let oldVersion = oldAddon.version;
installReason = newVersionReason(oldVersion, newVersion);
let uninstallReason = installReason;
extraParams.newVersion = newVersion;
extraParams.oldVersion = oldVersion;
+ callUpdate = isWebExtension(oldAddon.type) && isWebExtension(addon.type);
+
if (oldAddon.active) {
XPIProvider.callBootstrapMethod(oldAddon, existingAddon,
"shutdown", uninstallReason,
extraParams);
}
- this.callBootstrapMethod(oldAddon, existingAddon,
- "uninstall", uninstallReason, extraParams);
+
+ if (!callUpdate) {
+ this.callBootstrapMethod(oldAddon, existingAddon,
+ "uninstall", uninstallReason, extraParams);
+ }
this.unloadBootstrapScope(existingAddonID);
flushChromeCaches();
}
} else {
addon.installDate = Date.now();
}
let file = addon._sourceBundle;
XPIProvider._addURIMapping(addon.id, file);
- XPIProvider.callBootstrapMethod(addon, file, "install", installReason, extraParams);
+ let method = callUpdate ? "update" : "install";
+ XPIProvider.callBootstrapMethod(addon, file, method, installReason, extraParams);
addon.state = AddonManager.STATE_INSTALLED;
logger.debug("Install of temporary addon in " + aFile.path + " completed.");
addon.visible = true;
addon.enabled = true;
addon.active = true;
// WebExtension themes are installed as disabled, fix that here.
addon.userDisabled = false;
@@ -4648,31 +4660,35 @@ this.XPIProvider = {
// 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);
}
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);
+ callUpdate = isWebExtension(aAddon.type) && isWebExtension(existingAddon.type);
}
if (!makePending) {
if (aAddon.bootstrap) {
if (aAddon.active) {
this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "shutdown",
reason);
}
- this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "uninstall",
- reason);
+ if (!callUpdate) {
+ this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "uninstall",
+ reason);
+ }
XPIStates.disableAddon(aAddon.id);
this.unloadBootstrapScope(aAddon.id);
flushChromeCaches();
}
aAddon._installLocation.uninstallAddon(aAddon.id);
XPIDatabase.removeAddonMetadata(aAddon);
XPIStates.removeAddon(aAddon.location, aAddon.id);
AddonManagerPrivate.callAddonListeners("onUninstalled", wrapper);
@@ -4684,18 +4700,19 @@ this.XPIProvider = {
let wrappedAddon = existing.wrapper;
AddonManagerPrivate.callAddonListeners("onInstalling", wrappedAddon, false);
if (!existing.disabled && !XPIProvider.enableRequiresRestart(existing)) {
XPIDatabase.updateAddonActive(existing, true);
}
if (aAddon.bootstrap) {
+ let method = callUpdate ? "update" : "install";
XPIProvider.callBootstrapMethod(existing, existing._sourceBundle,
- "install", reason);
+ method, reason);
if (existing.active) {
XPIProvider.callBootstrapMethod(existing, existing._sourceBundle,
"startup", reason);
} else {
XPIProvider.unloadBootstrapScope(existing.id);
}
}