Bug 1000695 - Part 1: Rewrite backgroundUpdateCheck() to Task.jsm-based async. r=Unfocused

This commit is contained in:
Irving Reid 2014-05-05 08:55:58 -04:00
parent b5f5065758
commit e8f9e05f60

View File

@ -67,6 +67,8 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/AsyncShutdown.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonRepository",
@ -1132,120 +1134,115 @@ var AddonManagerInternal = {
/**
* Performs a background update check by starting an update for all add-ons
* that can be updated.
* @return Promise{null} resolves when the background update check is complete
* (including all addon installs)
*/
backgroundUpdateCheck: function AMI_backgroundUpdateCheck() {
if (!gStarted)
throw Components.Exception("AddonManager is not initialized",
Cr.NS_ERROR_NOT_INITIALIZED);
let hotfixID = this.hotfixID;
return Task.spawn(function* backgroundUpdateTask() {
let hotfixID = this.hotfixID;
let checkHotfix = hotfixID &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO);
let checkHotfix = hotfixID &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO);
if (!this.updateEnabled && !checkHotfix)
return;
if (!this.updateEnabled && !checkHotfix)
return;
Services.obs.notifyObservers(null, "addons-background-update-start", null);
Services.obs.notifyObservers(null, "addons-background-update-start", null);
// Start this from one to ensure the whole of this function completes before
// we can send the complete notification. Some parts can in some cases
// complete synchronously before later parts have a chance to increment
// pendingUpdates.
let pendingUpdates = 1;
if (this.updateEnabled) {
let scope = {};
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", scope);
scope.LightweightThemeManager.updateCurrentTheme();
function notifyComplete() {
if (--pendingUpdates == 0) {
Services.obs.notifyObservers(null,
"addons-background-update-complete",
null);
}
}
let aAddons = yield new Promise((resolve, reject) => this.getAllAddons(resolve));
if (this.updateEnabled) {
let scope = {};
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", scope);
scope.LightweightThemeManager.updateCurrentTheme();
pendingUpdates++;
this.getAllAddons(function getAddonsCallback(aAddons) {
// If there is a known hotfix then exclude it from the list of add-ons to update.
var ids = [a.id for each (a in aAddons) if (a.id != hotfixID)];
// Repopulate repository cache first, to ensure compatibility overrides
// are up to date before checking for addon updates.
AddonRepository.backgroundUpdateCheck(
ids, function BUC_backgroundUpdateCheckCallback() {
pendingUpdates += aAddons.length;
aAddons.forEach(function BUC_forEachCallback(aAddon) {
if (aAddon.id == hotfixID) {
notifyComplete();
return;
}
yield new Promise((resolve, reject) => AddonRepository.backgroundUpdateCheck(ids, resolve));
// Check all add-ons for updates so that any compatibility updates will
// be applied
// Keep track of all the async add-on updates happening in parallel
let updates = [];
for (let aAddon of aAddons) {
if (aAddon.id == hotfixID) {
continue;
}
// Check all add-ons for updates so that any compatibility updates will
// be applied
updates.push(new Promise((resolve, reject) => {
aAddon.findUpdates({
onUpdateAvailable: function BUC_onUpdateAvailable(aAddon, aInstall) {
// Start installing updates when the add-on can be updated and
// background updates should be applied.
if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE &&
AddonManager.shouldAutoUpdate(aAddon)) {
// XXX we really should resolve when this install is done,
// not when update-available check completes, no?
aInstall.install();
}
},
onUpdateFinished: notifyComplete
onUpdateFinished: resolve
}, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
});
notifyComplete();
});
});
}
if (checkHotfix) {
var hotfixVersion = "";
try {
hotfixVersion = Services.prefs.getCharPref(PREF_EM_HOTFIX_LASTVERSION);
}));
}
yield Promise.all(updates);
}
catch (e) { }
let url = null;
if (Services.prefs.getPrefType(PREF_EM_HOTFIX_URL) == Ci.nsIPrefBranch.PREF_STRING)
url = Services.prefs.getCharPref(PREF_EM_HOTFIX_URL);
else
url = Services.prefs.getCharPref(PREF_EM_UPDATE_BACKGROUND_URL);
if (checkHotfix) {
var hotfixVersion = "";
try {
hotfixVersion = Services.prefs.getCharPref(PREF_EM_HOTFIX_LASTVERSION);
}
catch (e) { }
// Build the URI from a fake add-on data.
url = AddonManager.escapeAddonURI({
id: hotfixID,
version: hotfixVersion,
userDisabled: false,
appDisabled: false
}, url);
let url = null;
if (Services.prefs.getPrefType(PREF_EM_HOTFIX_URL) == Ci.nsIPrefBranch.PREF_STRING)
url = Services.prefs.getCharPref(PREF_EM_HOTFIX_URL);
else
url = Services.prefs.getCharPref(PREF_EM_UPDATE_BACKGROUND_URL);
pendingUpdates++;
Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm");
AddonUpdateChecker.checkForUpdates(hotfixID, null, url, {
onUpdateCheckComplete: function BUC_onUpdateCheckComplete(aUpdates) {
let update = AddonUpdateChecker.getNewestCompatibleUpdate(aUpdates);
if (!update) {
notifyComplete();
return;
}
// Build the URI from a fake add-on data.
url = AddonManager.escapeAddonURI({
id: hotfixID,
version: hotfixVersion,
userDisabled: false,
appDisabled: false
}, url);
// If the available version isn't newer than the last installed
// version then ignore it.
if (Services.vc.compare(hotfixVersion, update.version) >= 0) {
notifyComplete();
return;
}
Components.utils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm");
let update = null;
try {
let foundUpdates = yield new Promise((resolve, reject) => {
AddonUpdateChecker.checkForUpdates(hotfixID, null, url, {
onUpdateCheckComplete: resolve,
onUpdateCheckError: reject
});
});
update = AddonUpdateChecker.getNewestCompatibleUpdate(foundUpdates);
} catch (e) {
// AUC.checkForUpdates already logged the error
}
// Check that we have a hotfix update, and it's newer than the one we already
// have installed (if any)
if (update) {
if (Services.vc.compare(hotfixVersion, update.version) < 0) {
logger.debug("Downloading hotfix version " + update.version);
let aInstall = yield new Promise((resolve, reject) =>
AddonManager.getInstallForURL(update.updateURL, resolve,
"application/x-xpinstall", update.updateHash, null,
null, update.version));
logger.debug("Downloading hotfix version " + update.version);
AddonManager.getInstallForURL(update.updateURL,
function BUC_getInstallForURL(aInstall) {
aInstall.addListener({
onDownloadEnded: function BUC_onDownloadEnded(aInstall) {
try {
@ -1283,17 +1280,14 @@ var AddonManagerInternal = {
});
aInstall.install();
}
}
}
notifyComplete();
}, "application/x-xpinstall", update.updateHash, null,
null, update.version);
},
onUpdateCheckError: notifyComplete
});
}
notifyComplete();
Services.obs.notifyObservers(null,
"addons-background-update-complete",
null);
}.bind(this));
},
/**