Bug 819974 - [Apps] Allow to cancel hosted app download. r=fabrice, a=blocking-basecamp
authorFernando Jiménez <ferjmoreno@gmail.com>
Tue, 18 Dec 2012 22:43:13 +0100
changeset 118999 9f16f87d783a27a715b1d9dcd0ae5693278efb57
parent 118998 10b241489bb6c3c5119b362ac5040b297cbe969d
child 119000 53d60295131dba05a8db2c05bee19613f794606c
push id3016
push userryanvm@gmail.com
push dateWed, 19 Dec 2012 22:20:24 +0000
treeherdermozilla-aurora@6a56fc48ecfd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice, blocking-basecamp
bugs819974
milestone19.0a2
Bug 819974 - [Apps] Allow to cancel hosted app download. r=fabrice, a=blocking-basecamp
dom/apps/src/Webapps.jsm
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -863,25 +863,36 @@ this.DOMApplicationRegistry = {
       aMm.sendAsyncMessage("Webapps:Launch:Return:KO", aData);
       return;
     }
 
     Services.obs.notifyObservers(aMm, "webapps-launch", JSON.stringify(aData));
   },
 
   cancelDownload: function cancelDownload(aManifestURL) {
-    // We can't cancel appcache downloads for now.
-    if (!this.downloads[aManifestURL]) {
+    debug("cancelDownload " + aManifestURL);
+    let download = this.downloads[aManifestURL];
+    if (!download) {
+      debug("Could not find a download for " + aManifestURL);
       return;
     }
-    // This is a HTTP channel.
-    let download = this.downloads[aManifestURL]
-    download.channel.cancel(Cr.NS_BINDING_ABORTED);
+
+    if (download.cacheUpdate) {
+      // Cancel hosted app download.
+      try {
+        download.cacheUpdate.cancel();
+      } catch (e) { debug (e); }
+    } else if (download.channel) {
+      // Cancel packaged app download.
+      download.channel.cancel(Cr.NS_BINDING_ABORTED);
+    } else {
+      return;
+    }
+
     let app = this.webapps[download.appId];
-
     app.progress = 0;
     app.installState = download.previousState;
     app.downloading = false;
     app.downloadAvailable = false;
     app.downloadSize = 0;
     this._saveApps((function() {
       this.broadcastMessage("Webapps:PackageEvent",
                              { type: "canceled",
@@ -1033,36 +1044,52 @@ this.DOMApplicationRegistry = {
       });
     }).bind(this));
   },
 
   startOfflineCacheDownload: function startOfflineCacheDownload(aManifest, aApp,
                                                                 aProfileDir,
                                                                 aOfflineCacheObserver,
                                                                 aIsUpdate) {
-    // if the manifest has an appcache_path property, use it to populate the appcache
-    if (aManifest.appcache_path) {
-      let appcacheURI = Services.io.newURI(aManifest.fullAppcachePath(), null, null);
-      let docURI = Services.io.newURI(aManifest.fullLaunchPath(), null, null);
-      // We determine the app's 'installState' according to its previous
-      // state. Cancelled download should remain as 'pending'. Successfully
-      // installed apps should morph to 'updating'.
-      if (aIsUpdate) {
-        aApp.installState = "updating";
-      }
-      // We set the 'downloading' flag right before starting the app
-      // download/update.
-      aApp.downloading = true;
-      let cacheUpdate = aProfileDir
-        ? updateSvc.scheduleCustomProfileUpdate(appcacheURI, docURI, aProfileDir)
-        : updateSvc.scheduleAppUpdate(appcacheURI, docURI, aApp.localId, false);
-      cacheUpdate.addObserver(new AppcacheObserver(aApp), false);
-      if (aOfflineCacheObserver) {
-        cacheUpdate.addObserver(aOfflineCacheObserver, false);
-      }
+    if (!aManifest.appcache_path) {
+      return;
+    }
+
+    // If the manifest has an appcache_path property, use it to populate the
+    // appcache.
+    let appcacheURI = Services.io.newURI(aManifest.fullAppcachePath(),
+                                         null, null);
+    let docURI = Services.io.newURI(aManifest.fullLaunchPath(), null, null);
+
+    // We determine the app's 'installState' according to its previous
+    // state. Cancelled downloads should remain as 'pending'. Successfully
+    // installed apps should morph to 'updating'.
+    if (aIsUpdate) {
+      aApp.installState = "updating";
+    }
+
+    // We set the 'downloading' flag right before starting the app
+    // download/update.
+    aApp.downloading = true;
+    let cacheUpdate = aProfileDir
+      ? updateSvc.scheduleCustomProfileUpdate(appcacheURI, docURI, aProfileDir)
+      : updateSvc.scheduleAppUpdate(appcacheURI, docURI, aApp.localId, false);
+
+    // We save the download details for potential further usage like cancelling
+    // it.
+    let download = {
+      cacheUpdate: cacheUpdate,
+      appId: this._appIdForManifestURL(aApp.manifestURL),
+      previousState: aIsUpdate ? "installed" : "pending"
+    };
+    this.downloads[aApp.manifestURL] = download;
+
+    cacheUpdate.addObserver(new AppcacheObserver(aApp), false);
+    if (aOfflineCacheObserver) {
+      cacheUpdate.addObserver(aOfflineCacheObserver, false);
     }
   },
 
   checkForUpdate: function(aData, aMm) {
     debug("checkForUpdate for " + aData.manifestURL);
     let id = this._appIdForManifestURL(aData.manifestURL);
     let app = this.webapps[id];
 
@@ -1709,21 +1736,21 @@ this.DOMApplicationRegistry = {
                               app: app });
     }
 
     function download() {
       debug("About to download " + aManifest.fullPackagePath());
 
       let requestChannel = NetUtil.newChannel(aManifest.fullPackagePath())
                                   .QueryInterface(Ci.nsIHttpChannel);
-      self.downloads[aApp.manifestURL] =
-        { channel:requestChannel,
-          appId: id,
-          previousState: aIsUpdate ? "installed" : "pending"
-        };
+      self.downloads[aApp.manifestURL] = {
+        channel: requestChannel,
+        appId: id,
+        previousState: aIsUpdate ? "installed" : "pending"
+      };
 
       let lastProgressTime = 0;
       requestChannel.notificationCallbacks = {
         QueryInterface: function notifQI(aIID) {
           if (aIID.equals(Ci.nsISupports)          ||
               aIID.equals(Ci.nsIProgressEventSink) ||
               aIID.equals(Ci.nsILoadContext))
             return this;