Bug 832408 - Notifications stick around after a failed 3rd party app update r=ferjm

This commit is contained in:
Fabrice Desré 2013-01-24 18:24:17 -08:00
parent 576471ba4f
commit 108b57be61
3 changed files with 67 additions and 29 deletions

View File

@ -60,6 +60,7 @@ this.AppsUtils = {
packageEtag: aApp.packageEtag,
manifestHash: aApp.manifestHash,
packageHash: aApp.packageHash,
staged: aApp.staged,
installerAppId: aApp.installerAppId || Ci.nsIScriptSecurityManager.NO_APP_ID,
installerIsBrowser: !!aApp.installerIsBrowser
};

View File

@ -577,10 +577,15 @@ WebappsApplication.prototype = {
this._fireEvent("downloadapplied", this._ondownloadapplied);
break;
case "downloaded":
this._manifest = msg.manifest;
// We don't update the packaged apps manifests until they
// are installed or until the update is unstaged.
if (msg.manifest) {
this._manifest = msg.manifest;
}
this._fireEvent("downloadsuccess", this._ondownloadsuccess);
break;
case "applied":
this._manifest = msg.manifest;
this._fireEvent("downloadapplied", this._ondownloadapplied);
break;
}

View File

@ -851,6 +851,7 @@ this.DOMApplicationRegistry = {
},
_writeFile: function ss_writeFile(aFile, aData, aCallbak) {
debug("Saving " + aFile.path);
// Initialize the file output stream.
let ostream = FileUtils.openSafeFileOutputStream(aFile);
@ -949,8 +950,12 @@ this.DOMApplicationRegistry = {
app.retryingDownload = !isUpdate;
// We need to get the update manifest here, not the webapp manifest.
// If this is an update, the update manifest is staged.
let file = FileUtils.getFile(DIRECTORY_NAME,
["webapps", id, "update.webapp"], true);
["webapps", id,
isUpdate ? "staged-update.webapp"
: "update.webapp"],
true);
if (!file.exists()) {
// This is a hosted app, let's check if it has an appcache
@ -1012,8 +1017,7 @@ this.DOMApplicationRegistry = {
DOMApplicationRegistry.broadcastMessage("Webapps:PackageEvent",
{ type: "downloaded",
manifestURL: aManifestURL,
app: app,
manifest: aManifest });
app: app });
if (app.installState == "pending") {
// We restarted a failed download, apply it automatically.
DOMApplicationRegistry.applyDownload(aManifestURL);
@ -1047,6 +1051,16 @@ this.DOMApplicationRegistry = {
appFile.moveTo(dir, "application.zip");
manFile.moveTo(dir, "manifest.webapp");
// Move the staged update manifest to a non staged one.
let staged = dir.clone();
staged.append("staged-update.webapp");
// If we are applying after a restarted download, we have no
// staged update manifest.
if (staged.exists()) {
staged.moveTo(dir, "update.webapp");
}
try {
tmpDir.remove(true);
} catch(e) { }
@ -1064,6 +1078,15 @@ this.DOMApplicationRegistry = {
app.downloadSize = 0;
app.installState = "installed";
app.readyToApplyDownload = false;
// Update the staged properties.
if (app.staged) {
for (let prop in app.staged) {
app[prop] = app.staged[prop];
}
delete app.staged;
}
delete app.retryingDownload;
DOMApplicationRegistry._saveApps(function() {
@ -1224,7 +1247,7 @@ this.DOMApplicationRegistry = {
// Store the new update manifest.
let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
let manFile = dir.clone();
manFile.append("update.webapp");
manFile.append("staged-update.webapp");
this._writeFile(manFile, JSON.stringify(aManifest), function() { });
let manifest = new ManifestHelper(aManifest, app.manifestURL);
@ -1408,6 +1431,7 @@ this.DOMApplicationRegistry = {
xhr.addEventListener("load", (function() {
debug("Got http status=" + xhr.status + " for " + aData.manifestURL);
let oldHash = app.manifestHash;
let isPackage = app.origin.startsWith("app://");
if (xhr.status == 200) {
let manifest = xhr.response;
@ -1425,12 +1449,19 @@ this.DOMApplicationRegistry = {
} else {
let hash = this.computeManifestHash(manifest);
debug("Manifest hash = " + hash);
app.manifestHash = hash;
if (isPackage) {
if (!app.staged) {
app.staged = { };
}
app.staged.manifestHash = hash;
app.staged.etag = xhr.getResponseHeader("Etag");
} else {
app.manifestHash = hash;
app.etag = xhr.getResponseHeader("Etag");
}
app.etag = xhr.getResponseHeader("Etag");
debug("at update got app etag=" + app.etag);
app.lastCheckedUpdate = Date.now();
if (app.origin.startsWith("app://")) {
if (isPackage) {
if (oldHash != hash) {
updatePackagedApp.call(this, manifest);
} else {
@ -1455,7 +1486,7 @@ this.DOMApplicationRegistry = {
}
} else if (xhr.status == 304) {
// The manifest has not changed.
if (app.origin.startsWith("app://")) {
if (isPackage) {
// If the app is a packaged app, we just send a 'downloadapplied'
// or downloadavailable event.
app.lastCheckedUpdate = Date.now();
@ -1944,6 +1975,11 @@ this.DOMApplicationRegistry = {
let download = AppDownloadManager.get(aApp.manifestURL);
app.downloading = false;
// To prevent repeated prompts, wait for the next checkForUpdates to
// try a new download.
app.downloadAvailable = false;
// If there were not enough storage to download the packaged app we
// won't have a record of the download details, so we just set the
// installState to 'pending'.
@ -2042,17 +2078,9 @@ this.DOMApplicationRegistry = {
.createInstance(Ci.nsISimpleStreamListener);
listener.init(bufferedOutputStream, {
onStartRequest: function(aRequest, aContext) {
// early check for ETag header
try {
requestChannel.getResponseHeader("Etag");
} catch (e) {
// in https://bugzilla.mozilla.org/show_bug.cgi?id=825218
// we might do something cleaner to have a proper user error
debug("We found no ETag Header, canceling the request");
requestChannel.cancel(Cr.NS_BINDING_ABORTED);
AppDownloadManager.remove(aApp.manifestURL);
}
// Nothing to do there anymore.
},
onStopRequest: function(aRequest, aContext, aStatusCode) {
debug("onStopRequest " + aStatusCode);
bufferedOutputStream.close();
@ -2185,17 +2213,21 @@ this.DOMApplicationRegistry = {
throw "INVALID_SECURITY_LEVEL";
}
app.appStatus = AppsUtils.getAppManifestStatus(manifest);
app.packageHash = aHash;
// Save the new Etag for the package.
try {
if (aIsUpdate) {
if (!app.staged) {
app.staged = { };
}
app.staged.packageEtag =
requestChannel.getResponseHeader("Etag");
app.staged.packageHash = aHash;
app.staged.appStatus =
AppsUtils.getAppManifestStatus(manifest);
} else {
app.packageEtag = requestChannel.getResponseHeader("Etag");
debug("Package etag=" + app.packageEtag);
} catch (e) {
// in https://bugzilla.mozilla.org/show_bug.cgi?id=825218
// we'll fail gracefully in this case
// for now, just going on
app.packageEtag = null;
debug("Can't find an etag, this should not happen");
app.packageHash = aHash;
app.appStatus = AppsUtils.getAppManifestStatus(manifest);
}
if (aOnSuccess) {