--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -397,16 +397,18 @@ function loadManifestFromRDF(aUri, aStre
// Themes are disabled by default unless they are currently selected
if (addon.type == "theme")
addon.userDisabled = addon.internalName != XPIProvider.selectedSkin;
else
addon.userDisabled = false;
addon.appDisabled = !isUsableAddon(addon);
+ addon.applyBackgroundUpdates = true;
+
return addon;
}
/**
* Loads an AddonInternal object from an add-on extracted in a directory.
*
* @param aDir
* The nsIFile directory holding the add-on
@@ -1172,18 +1174,16 @@ var XPIProvider = {
return true;
}
return false;
}
// 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);
// Update the database
XPIDatabase.updateAddonMetadata(aOldAddon, newAddon, aAddonState.descriptor);
if (newAddon.visible) {
visibleAddons[newAddon.id] = newAddon;
// If the old version was active and wasn't bootstrapped or the new
@@ -2177,17 +2177,18 @@ var XPIProvider = {
if (aAddon.type == "theme" && aAddon.active)
AddonManagerPrivate.notifyAddonChanged(aAddon.id, aAddon.type, false);
}
};
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) {
ERROR("SQL error " + aError.result + ": " + aError.message);
}
var XPIDatabase = {
// true if the database connection has been opened
@@ -2213,17 +2214,17 @@ var XPIDatabase = {
_readLocaleStrings: "SELECT locale_id, type, value FROM locale_strings " +
"WHERE locale_id=:id",
addAddonMetadata_addon: "INSERT INTO addon VALUES (NULL, :id, :location, " +
":version, :type, :internalName, :updateURL, " +
":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, " +
"homepageURL) VALUES (:name, :description, " +
":creator, :homepageURL)",
addAddonMetadata_strings: "INSERT INTO locale_strings VALUES (:locale, " +
":type, :value)",
addAddonMetadata_targetApplication: "INSERT INTO targetApplication VALUES " +
@@ -2256,17 +2257,18 @@ var XPIDatabase = {
makeAddonVisible: "UPDATE addon SET visible=1 WHERE internal_id=:internal_id",
removeAddonMetadata: "DELETE FROM addon WHERE internal_id=:internal_id",
// Equates to active = visible && !userDisabled && !appDisabled && !pendingUninstall
setActiveAddons: "UPDATE addon SET active=MIN(visible, 1 - userDisabled, " +
"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 " +
"WHERE addon_internal_id=:internal_id AND id=:id",
},
/**
* Opens a new connection to the database file.
@@ -2425,16 +2427,17 @@ var XPIDatabase = {
"id TEXT, location TEXT, version TEXT, " +
"type TEXT, internalName TEXT, updateURL TEXT, " +
"updateKey TEXT, optionsURL TEXT, aboutURL TEXT, " +
"iconURL TEXT, defaultLocale INTEGER, " +
"visible INTEGER, active INTEGER, " +
"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, " +
"id TEXT, minVersion TEXT, maxVersion TEXT, " +
"UNIQUE (addon_internal_id, id)");
this.connection.createTable("addon_locale",
"addon_internal_id INTEGER, "+
"locale TEXT, locale_id INTEGER, " +
@@ -2561,17 +2564,17 @@ var XPIDatabase = {
addon._internal_id = aRow.internal_id;
addon._installLocation = XPIProvider.installLocationsByName[aRow.location];
addon._descriptor = aRow.descriptor;
copyProperties(aRow, PROP_METADATA, addon);
addon._defaultLocale = aRow.defaultLocale;
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);
return addon;
},
/**
* Asynchronously fetches additional metadata for a DBAddonInternal.
@@ -2711,17 +2714,17 @@ var XPIDatabase = {
let location = aRow.getResultByName("location");
addon._installLocation = XPIProvider.installLocationsByName[location];
addon._descriptor = aRow.getResultByName("descriptor");
copyRowProperties(aRow, PROP_METADATA, addon);
addon._defaultLocale = aRow.getResultByName("defaultLocale");
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);
return addon;
},
/**
* Synchronously reads all install locations known about by the database. This
@@ -2985,17 +2988,18 @@ var XPIDatabase = {
let stmt = this.getStatement("addAddonMetadata_addon");
stmt.params.locale = insertLocale(aAddon.defaultLocale);
stmt.params.location = aAddon._installLocation.name;
stmt.params.descriptor = aDescriptor;
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 &&
!aAddon.appDisabled) ? 1 : 0;
stmt.execute();
let internal_id = this.connection.lastInsertRowID;
stmt = this.getStatement("addAddonMetadata_addon_locale");
@@ -3029,16 +3033,19 @@ var XPIDatabase = {
* @param aNewAddon
* The new AddonInternal to add
* @param aDescriptor
* The file descriptor of the add-on's directory
*/
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);
},
/**
* Synchronously updates the target application entries for an add-on.
*
* @param aAddon
* The DBAddonInternal being updated
@@ -3101,39 +3108,26 @@ var XPIDatabase = {
setAddonProperties: function XPIDB_setAddonProperties(aAddon, aProperties) {
function convertBoolean(value) {
return value ? 1 : 0;
}
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();
},
/**
* Synchronously pdates an add-on's active flag in the database.
*
* @param aAddon
@@ -3817,17 +3811,16 @@ AddonInstall.prototype = {
// Install the new add-on into its final directory
let dir = this.installLocation.installAddon(this.addon.id, stagedAddon);
// Update the metadata in the database
this.addon._installLocation = this.installLocation;
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);
}
else {
this.addon.installDate = this.addon.updateDate;
XPIDatabase.addAddonMetadata(this.addon, dir.persistentDescriptor);
}
@@ -4309,22 +4302,23 @@ function AddonWrapper(aAddon) {
});
}, this);
this.__defineGetter__("screenshots", function() {
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() {
if (!("_install" in aAddon) || !aAddon._install)
return null;
return aAddon._install.wrapper;
});
--- a/toolkit/mozapps/extensions/test/xpcshell/test_update.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_update.js
@@ -79,16 +79,18 @@ function end_test() {
testserver.stop(do_test_finished);
}
// Verify that an update is available and can be installed.
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",
]);
a1.findUpdates({
onNoCompatibilityUpdateAvailable: function(addon) {
do_throw("Should not have seen no compatibility update");
@@ -142,16 +144,17 @@ function check_test_2() {
do_check_neq(olda1, null);
do_check_eq(olda1.version, "1.0");
restartManager(1);
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
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);
run_test_3();
});
});
}
@@ -572,42 +575,43 @@ function run_test_8() {
"addon2@tests.mozilla.org",
"addon3@tests.mozilla.org",
"addon4@tests.mozilla.org",
"addon5@tests.mozilla.org",
"addon6@tests.mozilla.org"],
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();
}
};
let updateListener = {
onUpdateAvailable: function(addon, update) {
// Dummy so the update checker knows we care about new versions
},
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();
}
};
a1.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED);
a2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_ADDON_INSTALLED);
a3.findUpdates(updateListener, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
a4.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "2");
a5.findUpdates(compatListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
@@ -737,11 +741,95 @@ function check_test_13() {
do_check_neq(a7, null);
do_check_true(a7.isActive);
do_check_true(a7.isCompatible);
do_check_false(a7.appDisabled);
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();
});
}