Bug 972852 - Handle file errors and fix log messages that were causing addon manager failures. r=Mossop
--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -2079,27 +2079,33 @@ var XPIProvider = {
AddonManager.checkCompatibility);
} catch (e) { }
this.addAddonsToCrashReporter();
}
try {
AddonManagerPrivate.recordTimestamp("XPI_bootstrap_addons_begin");
for (let id in this.bootstrappedAddons) {
- let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
- file.persistentDescriptor = this.bootstrappedAddons[id].descriptor;
- let reason = BOOTSTRAP_REASONS.APP_STARTUP;
- // Eventually set INSTALLED reason when a bootstrap addon
- // is dropped in profile folder and automatically installed
- if (AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_INSTALLED)
- .indexOf(id) !== -1)
- reason = BOOTSTRAP_REASONS.ADDON_INSTALL;
- this.callBootstrapMethod(id, this.bootstrappedAddons[id].version,
- this.bootstrappedAddons[id].type, file,
- "startup", reason);
+ try {
+ let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
+ file.persistentDescriptor = this.bootstrappedAddons[id].descriptor;
+ let reason = BOOTSTRAP_REASONS.APP_STARTUP;
+ // Eventually set INSTALLED reason when a bootstrap addon
+ // is dropped in profile folder and automatically installed
+ if (AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_INSTALLED)
+ .indexOf(id) !== -1)
+ reason = BOOTSTRAP_REASONS.ADDON_INSTALL;
+ this.callBootstrapMethod(id, this.bootstrappedAddons[id].version,
+ this.bootstrappedAddons[id].type, file,
+ "startup", reason);
+ }
+ catch (e) {
+ ERROR("Failed to load bootstrap addon " + id + " from " +
+ this.bootstrappedAddons[id].descriptor, e);
+ }
}
AddonManagerPrivate.recordTimestamp("XPI_bootstrap_addons_end");
}
catch (e) {
ERROR("bootstrap startup failed", e);
AddonManagerPrivate.recordException("XPI-BOOTSTRAP", "startup failed", e);
}
@@ -2156,18 +2162,18 @@ var XPIProvider = {
this.allAppGlobal = true;
this.inactiveAddonIDs = [];
// If there are pending operations then we must update the list of active
// add-ons
if (Prefs.getBoolPref(PREF_PENDING_OPERATIONS, false)) {
XPIDatabase.updateActiveAddons();
- XPIDatabase.writeAddonsList();
- Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, false);
+ Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS,
+ !XPIDatabase.writeAddonsList());
}
this.installs = null;
this.installLocations = null;
this.installLocationsByName = null;
// This is needed to allow xpcshell tests to simulate a restart
this.extensionsActive = false;
@@ -2239,18 +2245,18 @@ var XPIProvider = {
// This *must* be modal as it has to block startup.
var features = "chrome,centerscreen,dialog,titlebar,modal";
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
ww.openWindow(null, URI_EXTENSION_UPDATE_DIALOG, "", features, variant);
}
// Ensure any changes to the add-ons list are flushed to disk
- XPIDatabase.writeAddonsList();
- Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, false);
+ Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS,
+ !XPIDatabase.writeAddonsList());
},
/**
* Persists changes to XPIProvider.bootstrappedAddons to its store (a pref).
*/
persistBootstrappedAddons: function XPI_persistBootstrappedAddons() {
Services.prefs.setCharPref(PREF_BOOTSTRAP_ADDONS,
JSON.stringify(this.bootstrappedAddons));
@@ -2415,34 +2421,34 @@ var XPIProvider = {
if (addon.unpack || Prefs.getBoolPref(PREF_XPI_UNPACK, false)) {
let targetDir = stagingDir.clone();
targetDir.append(addon.id);
try {
targetDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
}
catch (e) {
- ERROR("Failed to create staging directory for add-on " + id, e);
+ ERROR("Failed to create staging directory for add-on " + addon.id, e);
continue;
}
try {
extractFiles(stagedXPI, targetDir);
}
catch (e) {
- ERROR("Failed to extract staged XPI for add-on " + id + " in " +
+ ERROR("Failed to extract staged XPI for add-on " + addon.id + " in " +
aLocation.name, e);
}
}
else {
try {
stagedXPI.moveTo(stagingDir, addon.id + ".xpi");
}
catch (e) {
- ERROR("Failed to move staged XPI for add-on " + id + " in " +
+ ERROR("Failed to move staged XPI for add-on " + addon.id + " in " +
aLocation.name, e);
}
}
}
entries.close();
}
if (stagedXPIDir.exists()) {
@@ -2450,18 +2456,24 @@ var XPIProvider = {
recursiveRemove(stagedXPIDir);
}
catch (e) {
// Non-critical, just saves some perf on startup if we clean this up.
LOG("Error removing XPI staging dir " + stagedXPIDir.path, e);
}
}
- if (!stagingDir || !stagingDir.exists() || !stagingDir.isDirectory())
+ try {
+ if (!stagingDir || !stagingDir.exists() || !stagingDir.isDirectory())
+ return;
+ }
+ catch (e) {
+ WARN("Failed to find staging directory", e);
return;
+ }
let seenFiles = [];
// Use a snapshot of the directory contents to avoid possible issues with
// iterating over a directory while removing files from it (the YAFFS2
// embedded filesystem has this issue, see bug 772238), and to remove
// normal files before their resource forks on OSX (see bug 733436).
let stagingDirEntries = getDirectoryEntries(stagingDir, true);
for (let stageDirEntry of stagingDirEntries) {
@@ -3582,18 +3594,18 @@ var XPIProvider = {
}
}
// If the application crashed before completing any pending operations then
// we should perform them now.
if (extensionListChanged || hasPendingChanges) {
LOG("Updating database with changes to installed add-ons");
XPIDatabase.updateActiveAddons();
- XPIDatabase.writeAddonsList();
- Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, false);
+ Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS,
+ !XPIDatabase.writeAddonsList());
Services.prefs.setCharPref(PREF_BOOTSTRAP_ADDONS,
JSON.stringify(this.bootstrappedAddons));
return true;
}
LOG("No changes found");
}
catch (e) {
--- a/toolkit/mozapps/extensions/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/XPIProviderUtils.js
@@ -1404,16 +1404,17 @@ this.XPIDatabase = {
addon.active = newActive;
this.saveChanges();
}
}
},
/**
* Writes out the XPI add-ons list for the platform to read.
+ * @return true if the file was successfully updated, false otherwise
*/
writeAddonsList: function XPIDB_writeAddonsList() {
if (!this.addonDB) {
// force the DB to load
AddonManagerPrivate.recordSimpleMeasure("XPIDB_lateOpen_writeList",
XPIProvider.runPhase);
this.syncLoadDB(true);
}
@@ -1468,27 +1469,41 @@ this.XPIDatabase = {
encodeURIComponent(row.version));
}
fullCount += count;
}
if (fullCount > 0) {
LOG("Writing add-ons list");
- let addonsListTmp = FileUtils.getFile(KEY_PROFILEDIR, [FILE_XPI_ADDONS_LIST + ".tmp"],
- true);
- var fos = FileUtils.openFileOutputStream(addonsListTmp);
- fos.write(text, text.length);
- fos.close();
- addonsListTmp.moveTo(addonsListTmp.parent, FILE_XPI_ADDONS_LIST);
+ try {
+ let addonsListTmp = FileUtils.getFile(KEY_PROFILEDIR, [FILE_XPI_ADDONS_LIST + ".tmp"],
+ true);
+ var fos = FileUtils.openFileOutputStream(addonsListTmp);
+ fos.write(text, text.length);
+ fos.close();
+ addonsListTmp.moveTo(addonsListTmp.parent, FILE_XPI_ADDONS_LIST);
- Services.prefs.setCharPref(PREF_EM_ENABLED_ADDONS, enabledAddons.join(","));
+ Services.prefs.setCharPref(PREF_EM_ENABLED_ADDONS, enabledAddons.join(","));
+ }
+ catch (e) {
+ ERROR("Failed to write add-ons list to " + addonsListTmp.parent + "/" +
+ FILE_XPI_ADDONS_LIST, e);
+ return false;
+ }
}
else {
if (addonsList.exists()) {
LOG("Deleting add-ons list");
- addonsList.remove(false);
+ try {
+ addonsList.remove(false);
+ }
+ catch (e) {
+ ERROR("Failed to remove " + addonsList.path, e);
+ return false;
+ }
}
Services.prefs.clearUserPref(PREF_EM_ENABLED_ADDONS);
}
+ return true;
}
};