Bug 401229: Reduce Extension Manager flushing during startup. r=robstrong

This commit is contained in:
Dave Townsend 2008-07-25 12:23:25 -04:00
Родитель 165dc509e0
Коммит 34e62d8180
1 изменённых файлов: 124 добавлений и 30 удалений

Просмотреть файл

@ -177,6 +177,9 @@ var gCheckCompatibility = true;
var gCheckUpdateSecurity = true;
var gLocale = "en-US";
var gFirstRun = false;
var gAllowFlush = true;
var gDSNeedsFlush = false;
var gManifestNeedsFlush = false;
/**
* Valid GUIDs fit this pattern.
@ -2661,6 +2664,25 @@ ExtensionManager.prototype = {
* Clean up on application shutdown to avoid leaks.
*/
_shutdown: function() {
if (!gAllowFlush) {
// Something went wrong and there are potentially flushes pending.
ERROR("Reached _shutdown and without clearing any pending flushes");
try {
gAllowFlush = true;
if (gManifestNeedsFlush) {
gManifestNeedsFlush = false;
this._updateManifests(false);
}
if (gDSNeedsFlush) {
gDSNeedsFlush = false;
this.datasource.Flush();
}
}
catch (e) {
ERROR("Error flushing caches: " + e);
}
}
gOS.removeObserver(this, "xpcom-shutdown");
// Release strongly held services.
@ -2733,6 +2755,9 @@ ExtensionManager.prototype = {
if (this._ensureDatasetIntegrity())
isDirty = true;
// Block attempts to flush for the entire startup
gAllowFlush = false;
// Configure any items that are being installed, uninstalled or upgraded
// by being added, removed or modified by another process. We must do this
// on every startup since there is no way we can tell if this has happened
@ -2745,20 +2770,37 @@ ExtensionManager.prototype = {
if (PendingOperations.size != 0)
isDirty = true;
var needsRestart = false;
// Extension Changes
if (isDirty) {
var needsRestart = this._finishOperations();
needsRestart = this._finishOperations();
if (forceAutoReg) {
this._extensionListChanged = true;
needsRestart = true;
}
return needsRestart;
}
this._startTimers();
// Resume flushing and perform a flush for anything that was deferred
try {
gAllowFlush = true;
if (gManifestNeedsFlush) {
gManifestNeedsFlush = false;
this._updateManifests(false);
}
if (gDSNeedsFlush) {
gDSNeedsFlush = false;
this.datasource.Flush();
}
}
catch (e) {
ERROR("Error flushing caches: " + e);
}
return false;
if (!needsRestart)
this._startTimers();
return needsRestart;
},
/**
@ -3568,6 +3610,9 @@ ExtensionManager.prototype = {
return false;
}
// Block attempts to flush for the entire startup
gAllowFlush = false;
// Version mismatch, we have to load the extensions datasource and do
// version checking. Time hit here doesn't matter since this doesn't happen
// all that often.
@ -3630,6 +3675,11 @@ ExtensionManager.prototype = {
else if (allAppManaged)
allAppManaged = false;
var properties = {
availableUpdateURL: null,
availableUpdateVersion: null
};
if (ds.getItemProperty(id, "providesUpdatesSecurely") == "false") {
/* It's possible the previous version did not understand updateKeys so
* check if we can import one for this addon from it's manifest. */
@ -3646,13 +3696,13 @@ ExtensionManager.prototype = {
// updates, satisfying its dependencies, and not being blocklisted
if (this._isUsableItem(id)) {
if (ds.getItemProperty(id, "appDisabled"))
ds.setItemProperty(id, EM_R("appDisabled"), null);
properties.appDisabled = null;
}
else if (!ds.getItemProperty(id, "appDisabled")) {
properties.appDisabled = EM_L("true");
}
else if (!ds.getItemProperty(id, "appDisabled"))
ds.setItemProperty(id, EM_R("appDisabled"), EM_L("true"));
ds.setItemProperty(id, EM_R("availableUpdateURL"), null);
ds.setItemProperty(id, EM_R("availableUpdateVersion"), null);
ds.setItemProperties(id, properties);
}
// Must clean up outside of the loop. Modifying the container while
@ -3702,6 +3752,23 @@ ExtensionManager.prototype = {
// Prevent extension update dialog from showing
gPref.setBoolPref(PREF_UPDATE_NOTIFYUSER, false);
// Re-enable flushing and flush anything that was deferred
try {
gAllowFlush = true;
if (gManifestNeedsFlush) {
gManifestNeedsFlush = false;
this._updateManifests(false);
}
if (gDSNeedsFlush) {
gDSNeedsFlush = false;
this.datasource.Flush();
}
}
catch (e) {
ERROR("Error flushing caches: " + e);
}
return true;
},
@ -3914,10 +3981,20 @@ ExtensionManager.prototype = {
* true if the application needs to restart again, false otherwise.
*/
_updateManifests: function(needsRestart) {
// Write the Startup Cache (All Items, visible or not)
StartupCache.write();
// Write the Extensions Locations Manifest (Visible, enabled items)
this._updateExtensionsManifest(needsRestart);
// During startup we block flushing until the startup operations are all
// complete to reduce file accesses that can trigger bug 431065
if (gAllowFlush) {
// Write the Startup Cache (All Items, visible or not)
StartupCache.write();
// Write the Extensions Locations Manifest (Visible, enabled items)
this._updateExtensionsManifest();
}
else {
gManifestNeedsFlush = true;
}
// Notify nsAppRunner to update the compatibility manifest on next startup
this._extensionListChanged = needsRestart;
},
/**
@ -3959,10 +4036,8 @@ ExtensionManager.prototype = {
/**
* Write the Extensions List
* @param needsRestart
* true if the application needs to restart again, false otherwise.
*/
_updateExtensionsManifest: function(needsRestart) {
_updateExtensionsManifest: function() {
// When an operation is performed that requires a component re-registration
// (extension enabled/disabled, installed, uninstalled), we must write the
// set of paths where extensions live so that the startup system can determine
@ -4004,9 +4079,6 @@ ExtensionManager.prototype = {
// Cache the enabled list for annotating the crash report subsequently
gPref.setCharPref(PREF_EM_ENABLED_ITEMS, enabledItems.join(","));
// Now refresh the compatibility manifest.
this._extensionListChanged = needsRestart;
},
/**
@ -4765,8 +4837,7 @@ ExtensionManager.prototype = {
availableUpdateHash : null,
availableUpdateVersion: null,
availableUpdateInfo : null };
for (var p in props)
ds.setItemProperty(id, EM_R(p), props[p]);
ds.setItemProperties(id, props);
ds.updateProperty(id, "availableUpdateURL");
this._setOp(id, OP_NEEDS_INSTALL);
@ -4806,8 +4877,7 @@ ExtensionManager.prototype = {
availableUpdateHash : null,
availableUpdateVersion : null,
availableUpdateInfo : null };
for (var p in props)
ds.setItemProperty(id, EM_R(p), props[p]);
ds.setItemProperties(id, props);
ds.updateProperty(id, "availableUpdateURL");
this._setOp(id, OP_NEEDS_UPGRADE);
@ -5670,10 +5740,12 @@ ExtensionManager.prototype = {
// being updated during an install.
if (!manager) {
var id = currItem.id
ds.setItemProperty(id, EM_R("availableUpdateURL"), null);
ds.setItemProperty(id, EM_R("availableUpdateHash"), null);
ds.setItemProperty(id, EM_R("availableUpdateVersion"), null);
ds.setItemProperty(id, EM_R("availableUpdateInfo"), null);
ds.setItemProperties(id, {
availableUpdateURL: null,
availableUpdateHash: null,
availableUpdateVersion: null,
availableUpdateInfo: null
});
ds.updateProperty(id, "availableUpdateURL");
ds.updateProperty(id, "updateable");
}
@ -7547,6 +7619,20 @@ ExtensionsDataSource.prototype = {
this.Flush();
},
/**
* Sets one or more properties for an item.
* @param id
* The ID of the item
* @param properties
* A JS object which maps properties to values.
*/
setItemProperties: function (id, properties) {
var item = getResourceForID(id);
for (var key in properties)
this._setProperty(this._inner, item, EM_R(key), properties[key]);
this.Flush();
},
/**
* Inserts the RDF resource for an item into a container.
* @param id
@ -8143,9 +8229,11 @@ ExtensionsDataSource.prototype = {
hash = EM_L(addon.xpiHash);
version = EM_L(addon.version);
}
this.setItemProperty(addon.id, EM_R("availableUpdateURL"), url);
this.setItemProperty(addon.id, EM_R("availableUpdateHash"), hash);
this.setItemProperty(addon.id, EM_R("availableUpdateVersion"), version);
this.setItemProperties(addon.id, {
availableUpdateURL: url,
availableUpdateHash: hash,
availableUpdateVersion: version
});
this.updateProperty(addon.id, "availableUpdateURL");
},
@ -8710,6 +8798,12 @@ ExtensionsDataSource.prototype = {
},
Flush: function() {
// For some operations we block repeated flushing until all operations
// are complete to reduce file accesses that can trigger bug 431065
if (!gAllowFlush) {
gDSNeedsFlush = true;
return;
}
if (this._inner instanceof Ci.nsIRDFRemoteDataSource)
this._inner.Flush();
},