Bug 1027458 - Correctly cleanup after canceling a mozapp download. r=fabrice, a=2.0+
authorJames Lal <james@lightsofapollo.com>
Sat, 21 Jun 2014 01:32:15 +0200
changeset 207309 8afd9789d02c049c09cbccc6fff89fe3c92931da
parent 207308 3a93fc4f02652636f11566dd5d90b289280fa00f
child 207310 f4c13377f1fe98e4feea1e95f6b85baf085d068c
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice, 2
bugs1027458
milestone32.0a2
Bug 1027458 - Correctly cleanup after canceling a mozapp download. r=fabrice, a=2.0+
dom/apps/src/Webapps.jsm
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -1308,16 +1308,22 @@ this.DOMApplicationRegistry = {
     } else if (download.channel) {
       try {
         download.channel.cancel(Cr.NS_BINDING_ABORTED);
       } catch(e) { }
     } else {
       return;
     }
 
+    // Ensure we don't send additional errors for this download
+    app.isCanceling = true;
+
+    // Ensure this app can be downloaded again after canceling
+    app.downloading = false;
+
     this._saveApps().then(() => {
       this.broadcastMessage("Webapps:UpdateState", {
         app: {
           progress: 0,
           installState: download.previousState,
           downloading: false
         },
         error: error,
@@ -1331,16 +1337,17 @@ this.DOMApplicationRegistry = {
     AppDownloadManager.remove(aManifestURL);
   },
 
   startDownload: Task.async(function*(aManifestURL) {
     debug("startDownload for " + aManifestURL);
 
     let id = this._appIdForManifestURL(aManifestURL);
     let app = this.webapps[id];
+
     if (!app) {
       debug("startDownload: No app found for " + aManifestURL);
       throw new Error("NO_SUCH_APP");
     }
 
     if (app.downloading) {
       debug("app is already downloading. Ignoring.");
       throw new Error("APP_IS_DOWNLOADING");
@@ -2763,16 +2770,24 @@ this.DOMApplicationRegistry = {
       // We determine the app's 'installState' according to its previous
       // state. Cancelled download should remain as 'pending'. Successfully
       // installed apps should morph to 'updating'.
       oldApp.installState = aIsUpdate ? "updating" : "pending";
 
       // initialize the progress to 0 right now
       oldApp.progress = 0;
 
+      // Save the current state of the app to handle cases where we may be
+      // retrying a past download.
+      yield DOMApplicationRegistry._saveApps();
+      DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
+        app: oldApp,
+        manifestURL: aNewApp.manifestURL
+      });
+
       let zipFile = yield this._getPackage(requestChannel, id, oldApp, aNewApp);
       let hash = yield this._computeFileHash(zipFile.path);
 
       let responseStatus = requestChannel.responseStatus;
       let oldPackage = (responseStatus == 304 || hash == oldApp.packageHash);
 
       if (oldPackage) {
         debug("package's etag or hash unchanged; sending 'applied' event");
@@ -4076,26 +4091,34 @@ AppcacheObserver.prototype = {
         eventType: ["downloadsuccess", "downloadapplied"],
         manifestURL: app.manifestURL
       });
     }
 
     let setError = function appObs_setError(aError) {
       debug("Offlinecache setError to " + aError);
       app.downloading = false;
+      mustSave = true;
+
+      // If we are canceling the download, we already send a DOWNLOAD_CANCELED
+      // error.
+      if (app.isCanceling) {
+        delete app.isCanceling;
+        return;
+      }
+
       DOMApplicationRegistry.broadcastMessage("Webapps:UpdateState", {
         app: app,
         error: aError,
         manifestURL: app.manifestURL
       });
       DOMApplicationRegistry.broadcastMessage("Webapps:FireEvent", {
         eventType: "downloaderror",
         manifestURL: app.manifestURL
       });
-      mustSave = true;
     }
 
     switch (aState) {
       case Ci.nsIOfflineCacheUpdateObserver.STATE_ERROR:
         aUpdate.removeObserver(this);
         AppDownloadManager.remove(app.manifestURL);
         setError("APP_CACHE_DOWNLOAD_ERROR");
         break;