Bug 1175794 - Use task with setTimeout and send messages to continuously update PageInfo Media tab. r=florian, a=sledru
authorJimmy Wang <jiwang@mozilla.com>
Thu, 13 Aug 2015 05:12:02 -0400
changeset 289040 c8ca46b051f00e304016b3318da5c445db7a254c
parent 289039 1c4c3d6c5fd36a066aba81b11b01ceb58f95e461
child 289041 5a9d52dfc0646ada65dd4ec6cd6d03f3973d9414
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersflorian, sledru
bugs1175794
milestone42.0a2
Bug 1175794 - Use task with setTimeout and send messages to continuously update PageInfo Media tab. r=florian, a=sledru
browser/base/content/content.js
browser/base/content/pageinfo/pageInfo.js
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -9,16 +9,17 @@
 let {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource:///modules/ContentWebRTC.jsm");
 Cu.import("resource:///modules/ContentObservers.jsm");
 Cu.import("resource://gre/modules/InlineSpellChecker.jsm");
 Cu.import("resource://gre/modules/InlineSpellCheckerContent.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
   "resource://gre/modules/BrowserUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ContentLinkHandler",
   "resource:///modules/ContentLinkHandler.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerContent",
   "resource://gre/modules/LoginManagerContent.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "InsecurePasswordUtils",
@@ -874,18 +875,17 @@ let PageInfoListener = {
 
     let pageInfoData = {metaViewRows: this.getMetaInfo(document),
                         docInfo: this.getDocumentInfo(document),
                         feeds: this.getFeedsInfo(document, strings),
                         windowInfo: this.getWindowInfo(window)};
     sendAsyncMessage("PageInfo:data", pageInfoData);
 
     // Separate step so page info dialog isn't blank while waiting for this to finish.
-    let pageInfoMediaData = {imageViewRows: this.getMediaInfo(document, window, strings)};
-    sendAsyncMessage("PageInfo:mediaData", pageInfoMediaData);
+    this.getMediaInfo(document, window, strings);
   },
 
   getMetaInfo: function(document) {
     let metaViewRows = [];
 
     // Get the meta tags from the page.
     let metaNodes = document.getElementsByTagName("meta");
 
@@ -960,48 +960,56 @@ let PageInfoListener = {
     }
     return feeds;
   },
 
   // Only called once to get the media tab's media elements from the content page.
   getMediaInfo: function(document, window, strings)
   {
     let frameList = this.goThroughFrames(document, window);
-    return this.processFrames(document, frameList, strings);
+    Task.spawn(() => this.processFrames(document, frameList, strings));
   },
 
   goThroughFrames: function(document, window)
   {
     let frameList = [document];
     if (window && window.frames.length > 0) {
       let num = window.frames.length;
       for (let i = 0; i < num; i++) {
         // Recurse through the frames.
         frameList.concat(this.goThroughFrames(window.frames[i].document,
                                               window.frames[i]));
       }
     }
     return frameList;
   },
 
-  processFrames: function(document, frameList, strings)
+  processFrames: function*(document, frameList, strings)
   {
-    let imageViewRows = [];
+    let nodeCount = 0;
     for (let doc of frameList) {
       let iterator = doc.createTreeWalker(doc, content.NodeFilter.SHOW_ELEMENT);
 
+      // Goes through all the elements on the doc. imageViewRows takes only the media elements.
       while (iterator.nextNode()) {
         let mediaNode = this.getMediaNode(document, strings, iterator.currentNode);
 
         if (mediaNode) {
-          imageViewRows.push(mediaNode);
+          sendAsyncMessage("PageInfo:mediaData",
+                           {imageViewRow: mediaNode, isComplete: false});
+        }
+
+        if (++nodeCount % 500 == 0) {
+          // setTimeout every 500 elements so we don't keep blocking the content process.
+          yield new Promise(resolve => setTimeout(resolve, 10));
         }
       }
     }
-    return imageViewRows;
+    // Send that page info media fetching has finished.
+    sendAsyncMessage("PageInfo:mediaData", {isComplete: true});
   },
 
   getMediaNode: function(document, strings, elem)
   {
     // Check for images defined in CSS (e.g. background, borders), any node may have multiple.
     let computedStyle = elem.ownerDocument.defaultView.getComputedStyle(elem, "");
     let mediaElement = null;
 
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -359,17 +359,17 @@ function loadPageInfo(frameOuterWindowID
   gStrings["text/xml"]             = gBundle.getString("feedXML");
   gStrings["application/xml"]      = gBundle.getString("feedXML");
   gStrings["application/rdf+xml"]  = gBundle.getString("feedXML");
 
   // Look for pageInfoListener in content.js. Sends message to listener with arguments.
   mm.sendAsyncMessage("PageInfo:getData", {strings: gStrings,
                       frameOuterWindowID: frameOuterWindowID});
 
-  let pageInfoData = null;
+  let pageInfoData;
 
   // Get initial pageInfoData needed to display the general, feeds, permission and security tabs.
   mm.addMessageListener("PageInfo:data", function onmessage(message) {
     mm.removeMessageListener("PageInfo:data", onmessage);
     pageInfoData = message.data;
     let docInfo = pageInfoData.docInfo;
     let windowInfo = pageInfoData.windowInfo;
     let uri = makeURI(docInfo.documentURIObject.spec,
@@ -384,22 +384,32 @@ function loadPageInfo(frameOuterWindowID
 
     makeGeneralTab(pageInfoData.metaViewRows, docInfo);
     initFeedTab(pageInfoData.feeds);
     onLoadPermission(uri);
     securityOnLoad(uri, windowInfo);
   });
 
   // Get the media elements from content script to setup the media tab.
-  mm.addMessageListener("PageInfo:mediaData", function onmessage(message){
-    mm.removeMessageListener("PageInfo:mediaData", onmessage);
-    makeMediaTab(message.data.imageViewRows);
+  mm.addMessageListener("PageInfo:mediaData", function onmessage(message) {
+    // Page info window was closed.
+    if (window.closed) {
+      mm.removeMessageListener("PageInfo:mediaData", onmessage);
+      return;
+    }
 
-    // Loop through onFinished and execute the functions on it.
-    onFinished.forEach(function(func) { func(pageInfoData); });
+    // The page info media fetching has been completed.
+    if (message.data.isComplete) {
+      mm.removeMessageListener("PageInfo:mediaData", onmessage);
+      onFinished.forEach(function(func) { func(pageInfoData); });
+      return;
+    }
+
+    addImage(message.data.imageViewRow);
+    selectImage();
   });
 
   /* Call registered overlay init functions */
   onLoadRegistry.forEach(function(func) { func(); });
 }
 
 function resetPageInfo(args)
 {
@@ -575,28 +585,20 @@ function makeGeneralTab(metaViewRows, do
       var pageSize = cacheEntry.dataSize;
       var kbSize = formatNumber(Math.round(pageSize / 1024 * 100) / 100);
       sizeText = gBundle.getFormattedString("generalSize", [kbSize, formatNumber(pageSize)]);
     }
     setItemValue("sizetext", sizeText);
   });
 }
 
-function makeMediaTab(imageViewRows)
+function addImage(imageViewRow)
 {
-  // Call addImage passing in the image rows to add to the view on the Media Tab.
-  for (let image of imageViewRows) {
-    let [url, type, alt, elem, isBg] = image;
-    addImage(url, type, alt, elem, isBg);
-  }
-  selectImage();
-}
+  let [url, type, alt, elem, isBg] = imageViewRow;
 
-function addImage(url, type, alt, elem, isBg)
-{
   if (!url)
     return;
 
   if (!gImageHash.hasOwnProperty(url))
     gImageHash[url] = { };
   if (!gImageHash[url].hasOwnProperty(type))
     gImageHash[url][type] = { };
   if (!gImageHash[url][type].hasOwnProperty(alt)) {