Bug 815173 - The interface feels sluggish when installing a big app [r=ferjm]
authorFabrice Desré <fabrice@mozilla.com>
Thu, 13 Dec 2012 09:54:49 -0800
changeset 115947 29e9bc98ea775ffac363b77370f115184ad69d4b
parent 115946 3cfc257e29a5a3725207fbaa0bf184e3719c8b73
child 115948 ff6a7246cb9ec423dd159ca1126f555559b6bccd
push id24034
push useremorley@mozilla.com
push dateFri, 14 Dec 2012 15:28:57 +0000
treeherdermozilla-central@50d8f411d305 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersferjm
bugs815173
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 815173 - The interface feels sluggish when installing a big app [r=ferjm]
dom/apps/src/Webapps.jsm
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -19,16 +19,19 @@ Cu.import("resource://gre/modules/AppsUt
 Cu.import("resource://gre/modules/PermissionsInstaller.jsm");
 Cu.import("resource://gre/modules/OfflineCacheInstaller.jsm");
 Cu.import("resource://gre/modules/SystemMessagePermissionsChecker.jsm");
 
 function debug(aMsg) {
   //dump("-*-*- Webapps.jsm : " + aMsg + "\n");
 }
 
+// Minimum delay between two progress events while downloading, in ms.
+const MIN_PROGRESS_EVENT_DELAY = 1000;
+
 const WEBAPP_RUNTIME = Services.appinfo.ID == "webapprt@mozilla.org";
 
 XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
   Cu.import("resource://gre/modules/NetUtil.jsm");
   return NetUtil;
 });
 
 XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
@@ -1688,37 +1691,42 @@ this.DOMApplicationRegistry = {
 
       let requestChannel = NetUtil.newChannel(aManifest.fullPackagePath())
                                   .QueryInterface(Ci.nsIHttpChannel);
       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;
 
           throw Cr.NS_ERROR_NO_INTERFACE;
         },
         getInterface: function notifGI(aIID) {
           return this.QueryInterface(aIID);
         },
         onProgress: function notifProgress(aRequest, aContext,
                                            aProgress, aProgressMax) {
           debug("onProgress: " + aProgress + "/" + aProgressMax);
           app.progress = aProgress;
-          self.broadcastMessage("Webapps:PackageEvent",
-                                { type: "progress",
-                                  manifestURL: aApp.manifestURL,
-                                  progress: aProgress,
-                                  app: app });
+          let now = Date.now();
+          if (now - lastProgressTime > MIN_PROGRESS_EVENT_DELAY) {
+            self.broadcastMessage("Webapps:PackageEvent",
+                                  { type: "progress",
+                                    manifestURL: aApp.manifestURL,
+                                    app: app });
+            lastProgressTime = now;
+          }
         },
         onStatus: function notifStatus(aRequest, aContext, aStatus, aStatusArg) { },
 
         // nsILoadContext
         appId: app.installerAppId,
         isInBrowserElement: app.installerIsBrowser,
         usePrivateBrowsing: false,
         isContent: false,
@@ -2255,16 +2263,17 @@ this.DOMApplicationRegistry = {
 /**
  * Appcache download observer
  */
 let AppcacheObserver = function(aApp) {
   debug("Creating AppcacheObserver for " + aApp.origin +
         " - " + aApp.installState);
   this.app = aApp;
   this.startStatus = aApp.installState;
+  this.lastProgressTime = 0;
 };
 
 AppcacheObserver.prototype = {
   // nsIOfflineCacheUpdateObserver implementation
   updateStateChanged: function appObs_Update(aUpdate, aState) {
     let mustSave = false;
     let app = this.app;
 
@@ -2300,18 +2309,24 @@ AppcacheObserver.prototype = {
         break;
       case Ci.nsIOfflineCacheUpdateObserver.STATE_NOUPDATE:
       case Ci.nsIOfflineCacheUpdateObserver.STATE_FINISHED:
         aUpdate.removeObserver(this);
         setStatus("installed");
         break;
       case Ci.nsIOfflineCacheUpdateObserver.STATE_DOWNLOADING:
       case Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMSTARTED:
+        setStatus(this.startStatus);
+        break;
       case Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMPROGRESS:
-        setStatus(this.startStatus);
+        let now = Date.now();
+        if (now - this.lastProgressTime > MIN_PROGRESS_EVENT_DELAY) {
+          setStatus(this.startStatus);
+          this.lastProgressTime = now;
+        }
         break;
     }
 
     // Status changed, update the stored version.
     if (mustSave) {
       DOMApplicationRegistry._saveApps();
     }
   },