From bff65d76ee10389d82c839a196264a7735760179 Mon Sep 17 00:00:00 2001 From: Dave Townsend Date: Fri, 10 Jun 2011 13:10:48 -0700 Subject: [PATCH] Bug 655254: When an add-on moves to a different directory but doesn't change in any other way we should keep updated compatibility information. r=robstrong --- toolkit/mozapps/extensions/XPIProvider.jsm | 80 +++++++++++--- .../test/addons/test_bug655254/install.rdf | 19 ++++ .../test/xpcshell/data/test_bug655254.rdf | 26 +++++ .../test/xpcshell/test_bug655254.js | 101 ++++++++++++++++++ .../extensions/test/xpcshell/xpcshell.ini | 1 + 5 files changed, 213 insertions(+), 14 deletions(-) create mode 100644 toolkit/mozapps/extensions/test/addons/test_bug655254/install.rdf create mode 100644 toolkit/mozapps/extensions/test/xpcshell/data/test_bug655254.rdf create mode 100644 toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js diff --git a/toolkit/mozapps/extensions/XPIProvider.jsm b/toolkit/mozapps/extensions/XPIProvider.jsm index ba18e019b439..1d636d8fbc76 100644 --- a/toolkit/mozapps/extensions/XPIProvider.jsm +++ b/toolkit/mozapps/extensions/XPIProvider.jsm @@ -2181,7 +2181,8 @@ var XPIProvider = { * When performing recovery after startup this will be an array of * persistent descriptors of add-ons that are known to be active, * otherwise it will be null - * @return true if a change requiring a restart was detected + * @return a boolean indicating if a change requiring flushing the caches was + * detected */ processFileChanges: function XPI_processFileChanges(aState, aManifests, aUpdateCompatibility, @@ -2205,7 +2206,7 @@ var XPIProvider = { * ran * @param aAddonState * The new state of the add-on - * @return true if restarting the application is required to complete + * @return a boolean indicating if flushing caches is required to complete * changing this add-on */ function updateMetadata(aInstallLocation, aOldAddon, aAddonState) { @@ -2276,6 +2277,37 @@ var XPIProvider = { return false; } + /** + * Updates an add-on's descriptor for when the add-on has moved in the + * filesystem but hasn't changed in any other way. + * + * @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 + * @return a boolean indicating if flushing caches is required to complete + * changing this add-on + */ + function updateDescriptor(aInstallLocation, aOldAddon, aAddonState) { + LOG("Add-on " + aOldAddon.id + " moved to " + aAddonState.descriptor); + + aOldAddon._descriptor = aAddonState.descriptor; + aOldAddon.visible = !(aOldAddon.id in visibleAddons); + + // Update the database + XPIDatabase.setAddonDescriptor(aOldAddon, aAddonState.descriptor); + if (aOldAddon.visible) { + visibleAddons[aOldAddon.id] = aOldAddon; + + return true; + } + + return false; + } + /** * Called when no change has been detected for an add-on's metadata. The * add-on may have become visible due to other add-ons being removed or @@ -2289,8 +2321,8 @@ var XPIProvider = { * ran * @param aAddonState * The new state of the add-on - * @return a boolean indicating if restarting the application is required - * to complete changing this add-on + * @return a boolean indicating if flushing caches is required to complete + * changing this add-on */ function updateVisibilityAndCompatibility(aInstallLocation, aOldAddon, aAddonState) { @@ -2399,8 +2431,8 @@ var XPIProvider = { * @param aOldAddon * The AddonInternal as it appeared the last time the application * ran - * @return a boolean indicating if restarting the application is required - * to complete changing this add-on + * @return a boolean indicating if flushing caches is required to complete + * changing this add-on */ function removeMetadata(aInstallLocation, aOldAddon) { // This add-on has disappeared @@ -2433,8 +2465,8 @@ var XPIProvider = { * @param aMigrateData * If during startup the database had to be upgraded this will * contain data that used to be held about this add-on - * @return a boolean indicating if restarting the application is required - * to complete changing this add-on + * @return a boolean indicating if flushing caches is required to complete + * changing this add-on */ function addMetadata(aInstallLocation, aId, aAddonState, aMigrateData) { LOG("New add-on " + aId + " installed in " + aInstallLocation.name); @@ -2606,17 +2638,19 @@ var XPIProvider = { XPIProvider.inactiveAddonIDs.push(aOldAddon.id); // The add-on has changed if the modification time has changed, or - // the directory it is installed in has changed or we have an - // updated manifest for it. Also reload the metadata for add-ons - // in the application directory when the application version has - // changed + // we have an updated manifest for it. Also reload the metadata for + // add-ons in the application directory when the application version + // has changed if (aOldAddon.id in aManifests[installLocation.name] || aOldAddon.updateDate != addonState.mtime || - aOldAddon._descriptor != addonState.descriptor || (aUpdateCompatibility && installLocation.name == KEY_APP_GLOBAL)) { changed = updateMetadata(installLocation, aOldAddon, addonState) || changed; } + else if (aOldAddon._descriptor != addonState.descriptor) { + changed = updateDescriptor(installLocation, aOldAddon, addonState) || + changed; + } else { changed = updateVisibilityAndCompatibility(installLocation, aOldAddon, addonState) || @@ -3882,6 +3916,8 @@ var XPIDatabase = { "pendingUninstall=:pendingUninstall, " + "applyBackgroundUpdates=:applyBackgroundUpdates WHERE " + "internal_id=:internal_id", + setAddonDescriptor: "UPDATE addon SET descriptor=:descriptor WHERE " + + "internal_id=:internal_id", updateTargetApplications: "UPDATE targetApplication SET " + "minVersion=:minVersion, maxVersion=:maxVersion " + "WHERE addon_internal_id=:internal_id AND id=:id", @@ -5129,7 +5165,23 @@ var XPIDatabase = { }, /** - * Synchronously pdates an add-on's active flag in the database. + * Synchronously sets the file descriptor for an add-on. + * + * @param aAddon + * The DBAddonInternal being updated + * @param aProperties + * A dictionary of properties to set + */ + setAddonDescriptor: function XPIDB_setAddonDescriptor(aAddon, aDescriptor) { + let stmt = this.getStatement("setAddonDescriptor"); + stmt.params.internal_id = aAddon._internal_id; + stmt.params.descriptor = aDescriptor; + + executeStatement(stmt); + }, + + /** + * Synchronously updates an add-on's active flag in the database. * * @param aAddon * The DBAddonInternal to update diff --git a/toolkit/mozapps/extensions/test/addons/test_bug655254/install.rdf b/toolkit/mozapps/extensions/test/addons/test_bug655254/install.rdf new file mode 100644 index 000000000000..2530cce4fff4 --- /dev/null +++ b/toolkit/mozapps/extensions/test/addons/test_bug655254/install.rdf @@ -0,0 +1,19 @@ + + + + + + addon1@tests.mozilla.org + 1.0 + Test 1 + http://localhost:4444/data/test_bug655254.rdf + + + xpcshell@tests.mozilla.org + 1 + 1 + + + + diff --git a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug655254.rdf b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug655254.rdf new file mode 100644 index 000000000000..9857dcb5555a --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug655254.rdf @@ -0,0 +1,26 @@ + + + + + + + + + + 1 + + + xpcshell@tests.mozilla.org + 1 + 2 + + + + + + + + + + diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js b/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js new file mode 100644 index 000000000000..7da81be7e129 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js @@ -0,0 +1,101 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that moving an extension in the filesystem without any other +// change still keeps updated compatibility information + +// The test extension uses an insecure update url. +Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false); +// Enable loading extensions from the user and system scopes +Services.prefs.setIntPref("extensions.enabledScopes", + AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_USER); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "1.9.2"); + +do_load_httpd_js(); +var testserver; + +var userDir = gProfD.clone(); +userDir.append("extensions2"); +userDir.append(gAppInfo.ID); + +var dirProvider = { + getFile: function(aProp, aPersistent) { + aPersistent.value = false; + if (aProp == "XREUSysExt") + return userDir.parent; + return null; + }, + + QueryInterface: XPCOMUtils.generateQI([AM_Ci.nsIDirectoryServiceProvider, + AM_Ci.nsISupports]) +}; +Services.dirsvc.registerProvider(dirProvider); + +var addon1 = { + id: "addon1@tests.mozilla.org", + version: "1.0", + name: "Test 1", + updateURL: "http://localhost:4444/data/test_bug655254.rdf", + targetApplications: [{ + id: "xpcshell@tests.mozilla.org", + minVersion: "1", + maxVersion: "1" + }] +}; + +// Set up the profile +function run_test() { + do_test_pending(); + + // Create and configure the HTTP server. + testserver = new nsHttpServer(); + testserver.registerDirectory("/data/", do_get_file("data")); + testserver.start(4444); + + var time = Date.now(); + var dir = writeInstallRDFForExtension(addon1, userDir); + setExtensionModifiedTime(dir, time); + + startupManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_true(a1.appDisabled); + do_check_false(a1.isActive); + do_check_false(isExtensionInAddonsList(userDir, a1.id)); + + a1.findUpdates({ + onUpdateFinished: function() { + restartManager(); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(userDir, a1.id)); + + shutdownManager(); + + userDir.parent.moveTo(gProfD, "extensions3"); + userDir = gProfD.clone(); + userDir.append("extensions3"); + userDir.append(gAppInfo.ID); + do_check_true(userDir.exists()); + + startupManager(false); + + AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) { + do_check_neq(a1, null); + do_check_false(a1.appDisabled); + do_check_true(a1.isActive); + do_check_true(isExtensionInAddonsList(userDir, a1.id)); + + testserver.stop(do_test_finished); + }); + }); + } + }, AddonManager.UPDATE_WHEN_USER_REQUESTED); + }); +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini index ec50c8810d66..c2623ef258ad 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini @@ -54,6 +54,7 @@ tail = [test_bug616841.js] [test_bug619730.js] [test_bug620837.js] +[test_bug655254.js] [test_cacheflush.js] [test_checkcompatibility.js] [test_corrupt.js]