Bug 759065 - Fall back to downloading the full update if staging the update in the background fails; r=rstrong

This commit is contained in:
Ehsan Akhgari 2012-05-29 16:20:12 -04:00
parent e2a2f37105
commit 6508c6a4a5
3 changed files with 56 additions and 21 deletions

View File

@ -482,6 +482,13 @@ appUpdater.prototype =
return;
}
this.setupDownloadingUI();
},
/**
* Switches to the UI responsible for tracking the download.
*/
setupDownloadingUI: function() {
this.downloadStatus = document.getElementById("downloadStatus");
this.downloadStatus.value =
DownloadUtils.getTransferTotal(0, this.update.selectedPatch.size);
@ -527,7 +534,7 @@ appUpdater.prototype =
let self = this;
Services.obs.addObserver(function (aSubject, aTopic, aData) {
// Update the UI when the background updater is finished
let status = update.state;
let status = aData;
if (status == "applied" || status == "applied-service" ||
status == "pending" || status == "pending-service") {
// If the update is successfully applied, or if the updater has
@ -540,6 +547,12 @@ appUpdater.prototype =
// Background update has failed, let's show the UI responsible for
// prompting the user to update manually.
self.selectPanel("downloadFailed");
} else if (status == "downloading") {
// We've fallen back to downloading the full update because the
// partial update failed to get staged in the background.
// Therefore we need to keep our observer.
self.setupDownloadingUI();
return;
}
Services.obs.removeObserver(arguments.callee, "update-staged");
}, "update-staged", false);

View File

@ -1602,6 +1602,12 @@ var gDownloadingPage = {
*/
observe: function(aSubject, aTopic, aData) {
if (aTopic == "update-staged") {
if (aData == STATE_DOWNLOADING) {
// We've fallen back to downloding the full update because the
// partial update failed to get staged in the background.
this._setStatus("downloading");
return;
}
this.cleanUp();
if (aData == STATE_APPLIED ||
aData == STATE_APPLIED_SVC ||

View File

@ -1006,6 +1006,36 @@ function handleUpdateFailure(update, errorCode) {
return false;
}
/**
* Fall back to downloading a complete update in case an update has failed.
*
* @param update the update object that has failed to apply.
*/
function handleFallbackToCompleteUpdate(update) {
cleanupActiveUpdate();
update.statusText = gUpdateBundle.GetStringFromName("patchApplyFailure");
var oldType = update.selectedPatch ? update.selectedPatch.type
: "complete";
if (update.selectedPatch && oldType == "partial" && update.patchCount == 2) {
// Partial patch application failed, try downloading the complete
// update in the background instead.
LOG("UpdateService:_postUpdateProcessing - install of partial patch " +
"failed, downloading complete patch");
var status = Cc["@mozilla.org/updates/update-service;1"].
getService(Ci.nsIApplicationUpdateService).
downloadUpdate(update, true);
if (status == STATE_NONE)
cleanupActiveUpdate();
}
else {
LOG("handleFallbackToCompleteUpdate - install of complete or " +
"only one patch offered failed.");
}
update.QueryInterface(Ci.nsIWritablePropertyBag);
update.setProperty("patchingFailed", oldType);
}
/**
* Update Patch
* @param patch
@ -1587,26 +1617,8 @@ UpdateService.prototype = {
}
// Something went wrong with the patch application process.
cleanupActiveUpdate();
handleFallbackToCompleteUpdate(update);
update.statusText = gUpdateBundle.GetStringFromName("patchApplyFailure");
var oldType = update.selectedPatch ? update.selectedPatch.type
: "complete";
if (update.selectedPatch && oldType == "partial" && update.patchCount == 2) {
// Partial patch application failed, try downloading the complete
// update in the background instead.
LOG("UpdateService:_postUpdateProcessing - install of partial patch " +
"failed, downloading complete patch");
var status = this.downloadUpdate(update, true);
if (status == STATE_NONE)
cleanupActiveUpdate();
}
else {
LOG("UpdateService:_postUpdateProcessing - install of complete or " +
"only one patch offered failed... showing error.");
}
update.QueryInterface(Ci.nsIWritablePropertyBag);
update.setProperty("patchingFailed", oldType);
prompter.showUpdateError(update);
}
},
@ -2407,7 +2419,9 @@ UpdateManager.prototype = {
update.state = ary[0];
if (update.state == STATE_FAILED && ary[1]) {
updateSucceeded = false;
handleUpdateFailure(update, ary[1]);
if (!handleUpdateFailure(update, ary[1])) {
handleFallbackToCompleteUpdate(update);
}
}
if (update.state == STATE_APPLIED && shouldUseService()) {
writeStatusFile(getUpdatesDir(), update.state = STATE_APPLIED_SVC);
@ -2425,6 +2439,8 @@ UpdateManager.prototype = {
// Send an observer notification which the update wizard uses in
// order to update its UI.
LOG("UpdateManager:refreshUpdateStatus - Notifying observers that " +
"the update was staged. state: " + update.state + ", status: " + status);
Services.obs.notifyObservers(null, "update-staged", update.state);
// Do this after *everything* else, since it will likely cause the app