diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm index 00155516e4d2..8d279c15d0d1 100644 --- a/toolkit/mozapps/extensions/AddonManager.jsm +++ b/toolkit/mozapps/extensions/AddonManager.jsm @@ -277,15 +277,20 @@ var AddonManagerInternal = { Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", scope); scope.LightweightThemeManager.updateCurrentTheme(); - this.getAddonsByTypes(null, function getAddonsCallback(aAddons) { + this.getAllAddons(function getAddonsCallback(aAddons) { aAddons.forEach(function BUC_forEachCallback(aAddon) { - if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE) { - aAddon.findUpdates({ - onUpdateAvailable: function BUC_onUpdateAvailable(aAddon, aInstall) { + // Check all add-ons for updates so that any compatibility updates will + // be applied + aAddon.findUpdates({ + onUpdateAvailable: function BUC_onUpdateAvailable(aAddon, aInstall) { + // Start installing updates when the add-on can be updated and + // background updates should be applied. + if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE && + aAddon.applyBackgroundUpdates) { aInstall.install(); } - }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); - } + } + }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE); }); }); }, diff --git a/toolkit/mozapps/extensions/XPIProvider.jsm b/toolkit/mozapps/extensions/XPIProvider.jsm index eba6198b64ae..ceb2ea6174c4 100644 --- a/toolkit/mozapps/extensions/XPIProvider.jsm +++ b/toolkit/mozapps/extensions/XPIProvider.jsm @@ -402,6 +402,8 @@ function loadManifestFromRDF(aUri, aStream) { addon.userDisabled = false; addon.appDisabled = !isUsableAddon(addon); + addon.applyBackgroundUpdates = true; + return addon; } @@ -1177,8 +1179,6 @@ var XPIProvider = { // Set the additional properties on the new AddonInternal newAddon._installLocation = aInstallLocation; - newAddon.userDisabled = aOldAddon.userDisabled; - newAddon.installDate = aOldAddon.installDate; newAddon.updateDate = aAddonState.mtime; newAddon.visible = !(newAddon.id in visibleAddons); @@ -2182,7 +2182,8 @@ var XPIProvider = { const FIELDS_ADDON = "internal_id, id, location, version, type, internalName, " + "updateURL, updateKey, optionsURL, aboutURL, iconURL, " + "defaultLocale, visible, active, userDisabled, appDisabled, " + - "pendingUninstall, descriptor, installDate, updateDate"; + "pendingUninstall, descriptor, installDate, updateDate, " + + "applyBackgroundUpdates"; // A helper function to simply log any errors that occur during async statements. function asyncErrorLogger(aError) { @@ -2218,7 +2219,7 @@ var XPIDatabase = { ":updateKey, :optionsURL, :aboutURL, :iconURL, " + ":locale, :visible, :active, :userDisabled," + " :appDisabled, 0, :descriptor, :installDate, " + - ":updateDate)", + ":updateDate, :applyBackgroundUpdates)", addAddonMetadata_addon_locale: "INSERT INTO addon_locale VALUES " + "(:internal_id, :name, :locale)", addAddonMetadata_locale: "INSERT INTO locale (name, description, creator, " + @@ -2261,7 +2262,8 @@ var XPIDatabase = { "1 - appDisabled, 1 - pendingUninstall)", setAddonProperties: "UPDATE addon SET userDisabled=:userDisabled, " + "appDisabled=:appDisabled, " + - "pendingUninstall=:pendingUninstall WHERE " + + "pendingUninstall=:pendingUninstall, " + + "applyBackgroundUpdates=:applyBackgroundUpdates WHERE " + "internal_id=:internal_id", updateTargetApplications: "UPDATE targetApplication SET " + "minVersion=:minVersion, maxVersion=:maxVersion " + @@ -2430,6 +2432,7 @@ var XPIDatabase = { "userDisabled INTEGER, appDisabled INTEGER, " + "pendingUninstall INTEGER, descriptor TEXT, " + "installDate INTEGER, updateDate INTEGER, " + + "applyBackgroundUpdates INTEGER, " + "UNIQUE (id, location)"); this.connection.createTable("targetApplication", "addon_internal_id INTEGER, " + @@ -2566,7 +2569,7 @@ var XPIDatabase = { addon.installDate = aRow.installDate; addon.updateDate = aRow.updateDate; ["visible", "active", "userDisabled", "appDisabled", - "pendingUninstall"].forEach(function(aProp) { + "pendingUninstall", "applyBackgroundUpdates"].forEach(function(aProp) { addon[aProp] = aRow[aProp] != 0; }); this.addonCache[aRow.internal_id] = Components.utils.getWeakReference(addon); @@ -2716,7 +2719,7 @@ var XPIDatabase = { addon.installDate = aRow.getResultByName("installDate"); addon.updateDate = aRow.getResultByName("updateDate"); ["visible", "active", "userDisabled", "appDisabled", - "pendingUninstall"].forEach(function(aProp) { + "pendingUninstall", "applyBackgroundUpdates"].forEach(function(aProp) { addon[aProp] = aRow.getResultByName(aProp) != 0; }); this.addonCache[internal_id] = Components.utils.getWeakReference(addon); @@ -2990,7 +2993,8 @@ var XPIDatabase = { stmt.params.installDate = aAddon.installDate; stmt.params.updateDate = aAddon.updateDate; copyProperties(aAddon, PROP_METADATA, stmt.params); - ["visible", "userDisabled", "appDisabled"].forEach(function(aProp) { + ["visible", "userDisabled", "appDisabled", + "applyBackgroundUpdates"].forEach(function(aProp) { stmt.params[aProp] = aAddon[aProp] ? 1 : 0; }); stmt.params.active = (aAddon.visible && !aAddon.userDisabled && @@ -3034,6 +3038,9 @@ var XPIDatabase = { updateAddonMetadata: function XPIDB_updateAddonMetadata(aOldAddon, aNewAddon, aDescriptor) { this.removeAddonMetadata(aOldAddon); + aNewAddon.userDisabled = aOldAddon.userDisabled; + aNewAddon.installDate = aOldAddon.installDate; + aNewAddon.applyBackgroundUpdates = aOldAddon.applyBackgroundUpdates; this.addAddonMetadata(aNewAddon, aDescriptor); }, @@ -3106,29 +3113,16 @@ var XPIDatabase = { let stmt = this.getStatement("setAddonProperties"); stmt.params.internal_id = aAddon._internal_id; - if ("userDisabled" in aProperties) { - stmt.params.userDisabled = convertBoolean(aProperties.userDisabled); - aAddon.userDisabled = aProperties.userDisabled; - } - else { - stmt.params.userDisabled = convertBoolean(aAddon.userDisabled); - } - - if ("appDisabled" in aProperties) { - stmt.params.appDisabled = convertBoolean(aProperties.appDisabled); - aAddon.appDisabled = aProperties.appDisabled; - } - else { - stmt.params.appDisabled = convertBoolean(aAddon.appDisabled); - } - - if ("pendingUninstall" in aProperties) { - stmt.params.pendingUninstall = convertBoolean(aProperties.pendingUninstall); - aAddon.pendingUninstall = aProperties.pendingUninstall; - } - else { - stmt.params.pendingUninstall = convertBoolean(aAddon.pendingUninstall); - } + ["userDisabled", "appDisabled", "pendingUninstall", + "applyBackgroundUpdates"].forEach(function(aProp) { + if (aProp in aProperties) { + stmt.params[aProp] = convertBoolean(aProperties[aProp]); + aAddon[aProp] = aProperties[aProp]; + } + else { + stmt.params[aProp] = convertBoolean(aAddon[aProp]); + } + }); stmt.execute(); }, @@ -3822,7 +3816,6 @@ AddonInstall.prototype = { this.addon.updateDate = dir.lastModifiedTime; this.addon.visible = true; if (isUpgrade) { - this.addon.installDate = this.existingAddon.installDate; XPIDatabase.updateAddonMetadata(this.existingAddon, this.addon, dir.persistentDescriptor); } @@ -4314,12 +4307,13 @@ function AddonWrapper(aAddon) { return []; }); - this.__defineGetter__("updateAutomatically", function() { - return aAddon.updateAutomatically; + this.__defineGetter__("applyBackgroundUpdates", function() { + return aAddon.applyBackgroundUpdates; }); - this.__defineSetter__("updateAutomatically", function(val) { - // TODO store this in the DB (bug 557849) - aAddon.updateAutomatically = val; + this.__defineSetter__("applyBackgroundUpdates", function(val) { + XPIDatabase.setAddonProperties(aAddon, { + applyBackgroundUpdates: val + }); }); this.__defineGetter__("install", function() { diff --git a/toolkit/mozapps/extensions/test/addons/test_update8/install.rdf b/toolkit/mozapps/extensions/test/addons/test_update8/install.rdf new file mode 100644 index 000000000000..43e31af423dc --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_update8/install.rdf @@ -0,0 +1,23 @@ + + + + + + addon8@tests.mozilla.org + 2.0 + + + Test 8 + Test Description + + + + xpcshell@tests.mozilla.org + 1 + 1 + + + + + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_update.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_update.rdf index cbc3a1028531..72342eb60a69 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/data/test_update.rdf +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_update.rdf @@ -123,4 +123,24 @@ + + + + +
  • + + 2.0 + + + xpcshell@tests.mozilla.org + 1 + 1 + http://localhost:4444/addons/test_update8.xpi + + + +
  • +
    +
    +
    diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update.js b/toolkit/mozapps/extensions/test/xpcshell/test_update.js index d911fa7ed55a..e86be7c75a30 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_update.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update.js @@ -84,6 +84,8 @@ function run_test_1() { AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { do_check_neq(a1, null); do_check_eq(a1.version, "1.0"); + do_check_true(a1.applyBackgroundUpdates); + a1.applyBackgroundUpdates = false; prepare_test({}, [ "onNewInstall", @@ -147,6 +149,7 @@ function check_test_2() { do_check_neq(a1, null); do_check_eq(a1.version, "2.0"); do_check_true(isExtensionInAddonsList(profileDir, a1.id)); + do_check_false(a1.applyBackgroundUpdates); a1.uninstall(); restartManager(0); @@ -577,10 +580,22 @@ function run_test_8() { function([a1, a2, a3, a4, a5, a6]) { let count = 6; + function run_next_test() { + a1.uninstall(); + a2.uninstall(); + a3.uninstall(); + a4.uninstall(); + a5.uninstall(); + a6.uninstall(); + + restartManager(0); + run_test_9(); + } + let compatListener = { onUpdateFinished: function(addon, error) { if (--count == 0) - end_test(); + run_next_test(); } }; @@ -590,19 +605,8 @@ function run_test_8() { }, onUpdateFinished: function(addon, error) { - if (--count != 0) - return; - - a1.uninstall(); - a2.uninstall(); - a3.uninstall(); - a4.uninstall(); - a5.uninstall(); - a6.uninstall(); - - restartManager(0); - - run_test_9(); + if (--count == 0) + run_next_test(); } }; @@ -742,6 +746,90 @@ function check_test_13() { a7.uninstall(); restartManager(0); + run_test_14(); + }); +} + +// Test that background update checks doesn't update an add-on that isn't +// allowed to update automatically. +function run_test_14() { + // Have an add-on there that will be updated so we see some events from it + var dest = profileDir.clone(); + dest.append("addon1@tests.mozilla.org"); + writeInstallRDFToDir({ + id: "addon1@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 1", + }, dest); + + dest = profileDir.clone(); + dest.append("addon8@tests.mozilla.org"); + writeInstallRDFToDir({ + id: "addon8@tests.mozilla.org", + version: "1.0", + updateURL: "http://localhost:4444/data/test_update.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }], + name: "Test Addon 8", + }, dest); + restartManager(1); + + AddonManager.getAddonByID("addon8@tests.mozilla.org", function(a8) { + a8.applyBackgroundUpdates = false; + + // Note that the background check will find a new update for both add-ons + // but only start installing one of them + prepare_test({}, [ + "onNewInstall", + "onDownloadStarted", + "onNewInstall", + "onDownloadEnded" + ], continue_test_14); + + // Fake a timer event + gInternalManager.notify(null); + }); +} + +function continue_test_14(install) { + do_check_neq(install.existingAddon, null); + do_check_eq(install.existingAddon.id, "addon1@tests.mozilla.org"); + + prepare_test({ + "addon1@tests.mozilla.org": [ + "onInstalling" + ] + }, [ + "onInstallStarted", + "onInstallEnded", + ], check_test_14); +} + +function check_test_14(install) { + do_check_eq(install.existingAddon.pendingUpgrade.install, install); + + restartManager(1); + AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org", + "addon8@tests.mozilla.org"], function([a1, a8]) { + do_check_neq(a1, null); + do_check_eq(a1.version, "2.0"); + a1.uninstall(); + + do_check_neq(a8, null); + do_check_eq(a8.version, "1.0"); + a8.uninstall(); + + restartManager(0); + end_test(); }); }