Bug 1175794 - Use task with setTimeout and send messages to continuously update PageInfo Media tab. r=florian
authorJimmy Wang <jiwang@mozilla.com>
Thu, 13 Aug 2015 05:12:02 -0400
changeset 258169 40b5df5cdc590a00c484033dd253e2be3a76249e
parent 258168 47b1d38a23f535775a03fcdf0749e295c473e6f0
child 258170 28077c310d985f70241ab37f30e55dfbf94b1c64
push id63843
push userryanvm@gmail.com
push dateTue, 18 Aug 2015 14:58:06 +0000
treeherdermozilla-inbound@d55e24c983aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersflorian
bugs1175794
milestone43.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 1175794 - Use task with setTimeout and send messages to continuously update PageInfo Media tab. r=florian
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)) {