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

This commit is contained in:
Dave Townsend 2011-06-10 13:10:48 -07:00
parent 77db392f64
commit bff65d76ee
5 changed files with 213 additions and 14 deletions

View File

@ -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

View File

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>addon1@tests.mozilla.org</em:id>
<em:version>1.0</em:version>
<em:name>Test 1</em:name>
<em:updateURL>http://localhost:4444/data/test_bug655254.rdf</em:updateURL>
<em:targetApplication>
<Description>
<em:id>xpcshell@tests.mozilla.org</em:id>
<em:minVersion>1</em:minVersion>
<em:maxVersion>1</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<RDF:Description about="urn:mozilla:extension:addon1@tests.mozilla.org">
<em:updates>
<RDF:Seq>
<RDF:li>
<RDF:Description>
<em:version>1</em:version>
<em:targetApplication>
<RDF:Description>
<em:id>xpcshell@tests.mozilla.org</em:id>
<em:minVersion>1</em:minVersion>
<em:maxVersion>2</em:maxVersion>
</RDF:Description>
</em:targetApplication>
</RDF:Description>
</RDF:li>
</RDF:Seq>
</em:updates>
</RDF:Description>
</RDF:RDF>

View File

@ -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);
});
}

View File

@ -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]