Bug 1192921: Remove most assumptions that add-on IDs match filenames. r=rhelmer

Normal directory install locations expect add-ons to exist on disk with the
naming convention "<id>.xpi". Originally system add-ons were going to do
something different so I started working on this. In the end it is unnecessary
but this work did reveal some cases where _sourceBundle wasn't being updated
for add-ons and removing most of these assumptions is still valuable.

--HG--
extra : commitid : 81LpRFeugL5
extra : rebase_source : 8b532ee58e57194889fffd8d9558718e1b551bac
This commit is contained in:
Dave Townsend 2015-08-25 15:18:43 -07:00
parent 688ebef0fa
commit 4369ebf0fc
2 changed files with 36 additions and 85 deletions

View File

@ -1980,9 +1980,7 @@ this.XPIStates = {
delete oldState[location.name];
}
for (let file of addons) {
let id = location.getIDForLocation(file);
for (let [id, file] of addons) {
if (!(id in locState)) {
logger.debug("New add-on ${id} in ${location}", {id: id, location: location.name});
let xpiState = new XPIState({d: file.persistentDescriptor});
@ -2944,9 +2942,9 @@ this.XPIProvider = {
logger.debug("Processing install of " + id + " in " + aLocation.name);
if (existingAddonID in this.bootstrappedAddons) {
try {
var existingAddon = aLocation.getLocationForID(existingAddonID);
if (this.bootstrappedAddons[existingAddonID].descriptor ==
existingAddon.persistentDescriptor) {
var existingAddon = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
existingAddon.persistentDescriptor = this.bootstrappedAddons[existingAddonID].descriptor;
if (existingAddon.exists()) {
oldBootstrap = this.bootstrappedAddons[existingAddonID];
// We'll be replacing a currently active bootstrapped add-on so
@ -3103,7 +3101,7 @@ this.XPIProvider = {
// Install the add-on
try {
profileLocation.installAddon(id, entry, null, true);
addon._sourceBundle = profileLocation.installAddon(id, entry, null, true);
logger.debug("Installed distribution add-on " + id);
Services.prefs.setBoolPref(PREF_BRANCH_INSTALLED_ADDON + id, true)
@ -4240,8 +4238,7 @@ this.XPIProvider = {
XPIDatabase.updateAddonActive(aAddon, !isDisabled);
if (isDisabled) {
if (aAddon.bootstrap) {
let file = aAddon._installLocation.getLocationForID(aAddon.id);
this.callBootstrapMethod(aAddon, file, "shutdown",
this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "shutdown",
BOOTSTRAP_REASONS.ADDON_DISABLE);
this.unloadBootstrapScope(aAddon.id);
}
@ -4249,8 +4246,7 @@ this.XPIProvider = {
}
else {
if (aAddon.bootstrap) {
let file = aAddon._installLocation.getLocationForID(aAddon.id);
this.callBootstrapMethod(aAddon, file, "startup",
this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "startup",
BOOTSTRAP_REASONS.ADDON_ENABLE);
}
AddonManagerPrivate.callAddonListeners("onEnabled", wrapper);
@ -4344,12 +4340,11 @@ this.XPIProvider = {
}
if (aAddon.bootstrap) {
let file = aAddon._installLocation.getLocationForID(aAddon.id);
XPIProvider.callBootstrapMethod(aAddon, file,
XPIProvider.callBootstrapMethod(aAddon, aAddon._sourceBundle,
"install", BOOTSTRAP_REASONS.ADDON_INSTALL);
if (aAddon.active) {
XPIProvider.callBootstrapMethod(aAddon, file,
XPIProvider.callBootstrapMethod(aAddon, aAddon._sourceBundle,
"startup", BOOTSTRAP_REASONS.ADDON_INSTALL);
}
else {
@ -4371,13 +4366,12 @@ this.XPIProvider = {
if (!requiresRestart) {
if (aAddon.bootstrap) {
let file = aAddon._installLocation.getLocationForID(aAddon.id);
if (aAddon.active) {
this.callBootstrapMethod(aAddon, file, "shutdown",
this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "shutdown",
BOOTSTRAP_REASONS.ADDON_UNINSTALL);
}
this.callBootstrapMethod(aAddon, file, "uninstall",
this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "uninstall",
BOOTSTRAP_REASONS.ADDON_UNINSTALL);
this.unloadBootstrapScope(aAddon.id);
flushStartupCache();
@ -5451,8 +5445,7 @@ AddonInstall.prototype = {
reason = BOOTSTRAP_REASONS.ADDON_DOWNGRADE;
if (this.existingAddon.bootstrap) {
let file = this.existingAddon._installLocation
.getLocationForID(this.existingAddon.id);
let file = this.existingAddon._sourceBundle;
if (this.existingAddon.active) {
XPIProvider.callBootstrapMethod(this.existingAddon, file,
"shutdown", reason,
@ -6781,7 +6774,6 @@ function DirectoryInstallLocation(aName, aDirectory, aScope, aLocked) {
this._directory = aDirectory;
this._scope = aScope
this._IDToFileMap = {};
this._FileToIDMap = {};
this._linkedAddons = [];
this._stagingDirLock = 0;
@ -6797,7 +6789,6 @@ DirectoryInstallLocation.prototype = {
_name : "",
_directory : null,
_IDToFileMap : null, // mapping from add-on ID to nsIFile
_FileToIDMap : null, // mapping from add-on path to add-on ID
/**
* Reads a directory linked to in a file.
@ -6890,7 +6881,6 @@ DirectoryInstallLocation.prototype = {
}
this._IDToFileMap[id] = entry;
this._FileToIDMap[entry.path] = id;
XPIProvider._addURIMapping(id, entry);
}
},
@ -6913,9 +6903,9 @@ DirectoryInstallLocation.prototype = {
* Gets an array of nsIFiles for add-ons installed in this location.
*/
get addonLocations() {
let locations = [];
let locations = new Map();
for (let id in this._IDToFileMap) {
locations.push(this._IDToFileMap[id].clone());
locations.set(id, this._IDToFileMap[id].clone());
}
return locations;
},
@ -7120,13 +7110,11 @@ DirectoryInstallLocation.prototype = {
} catch (e) {
logger.warn("failed to set lastModifiedTime on " + newFile.path, e);
}
this._FileToIDMap[newFile.path] = aId;
this._IDToFileMap[aId] = newFile;
XPIProvider._addURIMapping(aId, newFile);
if (aExistingAddonID && aExistingAddonID != aId &&
aExistingAddonID in this._IDToFileMap) {
delete this._FileToIDMap[this._IDToFileMap[aExistingAddonID]];
delete this._IDToFileMap[aExistingAddonID];
}
@ -7157,7 +7145,6 @@ DirectoryInstallLocation.prototype = {
logger.warn("Attempted to remove " + aId + " from " +
this._name + " but it was already gone");
delete this._FileToIDMap[file.path];
delete this._IDToFileMap[aId];
return;
}
@ -7185,24 +7172,9 @@ DirectoryInstallLocation.prototype = {
}
}
delete this._FileToIDMap[file.path];
delete this._IDToFileMap[aId];
},
/**
* Gets the ID of the add-on installed in the given nsIFile.
*
* @param aFile
* The nsIFile to look in
* @return the ID
* @throws if the file does not represent an installed add-on
*/
getIDForLocation: function DirInstallLocation_getIDForLocation(aFile) {
if (aFile.path in this._FileToIDMap)
return this._FileToIDMap[aFile.path];
throw new Error("Unknown add-on location " + aFile.path);
},
/**
* Gets the directory that the add-on with the given ID is installed in.
*
@ -7248,7 +7220,6 @@ function WinRegInstallLocation(aName, aRootKey, aScope) {
this._rootKey = aRootKey;
this._scope = aScope;
this._IDToFileMap = {};
this._FileToIDMap = {};
let path = this._appKeyPath + "\\Extensions";
let key = Cc["@mozilla.org/windows-registry-key;1"].
@ -7272,7 +7243,6 @@ WinRegInstallLocation.prototype = {
_rootKey : null,
_scope : null,
_IDToFileMap : null, // mapping from ID to nsIFile
_FileToIDMap : null, // mapping from path to ID
/**
* Retrieves the path of this Application's data key in the registry.
@ -7316,7 +7286,6 @@ WinRegInstallLocation.prototype = {
}
this._IDToFileMap[id] = file;
this._FileToIDMap[file.path] = id;
XPIProvider._addURIMapping(id, file);
}
},
@ -7339,40 +7308,13 @@ WinRegInstallLocation.prototype = {
* Gets an array of nsIFiles for add-ons installed in this location.
*/
get addonLocations() {
let locations = [];
let locations = new Map();
for (let id in this._IDToFileMap) {
locations.push(this._IDToFileMap[id].clone());
locations.set(id, this._IDToFileMap[id].clone());
}
return locations;
},
/**
* Gets the ID of the add-on installed in the given nsIFile.
*
* @param aFile
* The nsIFile to look in
* @return the ID
* @throws if the file does not represent an installed add-on
*/
getIDForLocation: function RegInstallLocation_getIDForLocation(aFile) {
if (aFile.path in this._FileToIDMap)
return this._FileToIDMap[aFile.path];
throw new Error("Unknown add-on location");
},
/**
* Gets the nsIFile that the add-on with the given ID is installed in.
*
* @param aId
* The ID of the add-on
* @return the nsIFile
*/
getLocationForID: function RegInstallLocation_getLocationForID(aId) {
if (aId in this._IDToFileMap)
return this._IDToFileMap[aId].clone();
throw new Error("Unknown add-on ID");
},
/**
* @see DirectoryInstallLocation
*/

View File

@ -329,13 +329,15 @@ function DBAddonInternal(aLoaded) {
this._key = this.location + ":" + this.id;
try {
this._sourceBundle = this._installLocation.getLocationForID(this.id);
if (aLoaded._sourceBundle) {
this._sourceBundle = aLoaded._sourceBundle;
}
catch (e) {
// An exception will be thrown if the add-on appears in the database but
// not on disk. In general this should only happen during startup as
// this change is being detected.
else if (aLoaded.descriptor) {
this._sourceBundle = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
this._sourceBundle.persistentDescriptor = aLoaded.descriptor;
}
else {
throw new Error("Expected passed argument to contain a descriptor");
}
XPCOMUtils.defineLazyGetter(this, "pendingUpgrade",
@ -1595,7 +1597,8 @@ this.XPIDatabaseReconcile = {
try {
if (!aNewAddon) {
// Load the manifest from the add-on.
let file = aInstallLocation.getLocationForID(aId);
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
file.persistentDescriptor = aAddonState.descriptor;
aNewAddon = syncLoadManifestFromFile(file);
}
// The add-on in the manifest should match the add-on ID.
@ -1713,7 +1716,8 @@ this.XPIDatabaseReconcile = {
try {
// If there isn't an updated install manifest for this add-on then load it.
if (!aNewAddon) {
let file = aInstallLocation.getLocationForID(aOldAddon.id);
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
file.persistentDescriptor = aAddonState.descriptor;
aNewAddon = syncLoadManifestFromFile(file);
applyBlocklistChanges(aOldAddon, aNewAddon);
@ -1766,6 +1770,7 @@ this.XPIDatabaseReconcile = {
updateDescriptor(aInstallLocation, aOldAddon, aAddonState) {
logger.debug("Add-on " + aOldAddon.id + " moved to " + aAddonState.descriptor);
aOldAddon.descriptor = aAddonState.descriptor;
aOldAddon._sourceBundle.persistentDescriptor = aAddonState.descriptor;
return aOldAddon;
},
@ -1779,6 +1784,8 @@ this.XPIDatabaseReconcile = {
* @param aOldAddon
* The AddonInternal as it appeared the last time the application
* ran
* @param aAddonState
* The new state of the add-on
* @param aOldAppVersion
* The version of the application last run with this profile or null
* if it is a new profile or the version is unknown
@ -1788,14 +1795,15 @@ this.XPIDatabaseReconcile = {
* @return a boolean indicating if flushing caches is required to complete
* changing this add-on
*/
updateCompatibility(aInstallLocation, aOldAddon, aOldAppVersion, aOldPlatformVersion) {
updateCompatibility(aInstallLocation, aOldAddon, aAddonState, aOldAppVersion, aOldPlatformVersion) {
logger.debug("Updating compatibility for add-on " + aOldAddon.id + " in " + aInstallLocation.name);
// If updating from a version of the app that didn't support signedState
// then fetch that property now
if (aOldAddon.signedState === undefined && ADDON_SIGNING &&
SIGNED_TYPES.has(aOldAddon.type)) {
let file = aInstallLocation.getLocationForID(aOldAddon.id);
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
file.persistentDescriptor = aAddonState.descriptor;
let manifest = syncLoadManifestFromFile(file);
aOldAddon.signedState = manifest.signedState;
}
@ -1900,7 +1908,8 @@ this.XPIDatabaseReconcile = {
newAddon = this.updateDescriptor(installLocation, oldAddon, xpiState);
}
else if (aUpdateCompatibility) {
newAddon = this.updateCompatibility(installLocation, oldAddon, aOldAppVersion, aOldPlatformVersion);
newAddon = this.updateCompatibility(installLocation, oldAddon, xpiState,
aOldAppVersion, aOldPlatformVersion);
}
else {
// No change