Bug 1338215 - use a windowless browser for thumbnail hosting, r=markh
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Mon, 27 Feb 2017 19:58:55 +0000
changeset 374116 68763bfa6d054cd6bc63b61c3d127e721d8aaec8
parent 374115 01bc4c9ad3b50d29b61e0bbfbba2862af8cf5b81
child 374117 62736acb85d02f7fe6e8135a46646b7fa0e4703b
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmarkh
bugs1338215
milestone54.0a1
Bug 1338215 - use a windowless browser for thumbnail hosting, r=markh MozReview-Commit-ID: LWzMDHu0N8H
toolkit/components/thumbnails/BackgroundPageThumbs.jsm
toolkit/components/thumbnails/content/backgroundPageThumbs.xhtml
toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
toolkit/components/thumbnails/jar.mn
--- a/toolkit/components/thumbnails/BackgroundPageThumbs.jsm
+++ b/toolkit/components/thumbnails/BackgroundPageThumbs.jsm
@@ -155,46 +155,57 @@ const BackgroundPageThumbs = {
       // Already fully initialized.
       return true;
     if (this._startedParentWinInit)
       // Already started initializing.
       return false;
 
     this._startedParentWinInit = true;
 
-    // Create an html:iframe, stick it in the parent document, and
-    // use it to host the browser.  about:blank will not have the system
-    // principal, so it can't host, but a document with a chrome URI will.
-    let hostWindow = Services.appShell.hiddenDOMWindow;
-    let iframe = hostWindow.document.createElementNS(HTML_NS, "iframe");
-    iframe.setAttribute("src", "chrome://global/content/mozilla.xhtml");
-    let onLoad = function onLoadFn() {
-      iframe.removeEventListener("load", onLoad, true);
-      this._parentWin = iframe.contentWindow;
-      this._processCaptureQueue();
-    }.bind(this);
-    iframe.addEventListener("load", onLoad, true);
-    hostWindow.document.documentElement.appendChild(iframe);
-    this._hostIframe = iframe;
+    // Create a windowless browser and load our hosting
+    // (privileged) document in it.
+    let wlBrowser = Services.appShell.createWindowlessBrowser(true);
+    wlBrowser.QueryInterface(Ci.nsIInterfaceRequestor);
+    let webProgress = wlBrowser.getInterface(Ci.nsIWebProgress);
+    let listener = {
+      QueryInterface: XPCOMUtils.generateQI([
+        Ci.nsIWebProgressListener, Ci.nsIWebProgressListener2,
+        Ci.nsISupportsWeakReference]),
+    };
+    listener.onStateChange = (wbp, request, stateFlags, status) => {
+      if (!request) {
+        return;
+      }
+      if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
+          stateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) {
+        webProgress.removeProgressListener(listener);
+        // Get the window reference via the document.
+        this._parentWin = wlBrowser.document.defaultView;
+        this._processCaptureQueue();
+      }
+    };
+    webProgress.addProgressListener(listener, Ci.nsIWebProgress.NOTIFY_STATE_ALL);
+    wlBrowser.loadURI("chrome://global/content/backgroundPageThumbs.xhtml", 0, null, null, null);
+    this._windowlessContainer = wlBrowser;
 
     return false;
   },
 
   /**
    * Destroys the service.  Queued and pending captures will never complete, and
    * their consumer callbacks will never be called.
    */
   _destroy() {
     if (this._captureQueue)
       this._captureQueue.forEach(cap => cap.destroy());
     this._destroyBrowser();
-    if (this._hostIframe)
-      this._hostIframe.remove();
+    if (this._windowlessContainer)
+      this._windowlessContainer.close();
     delete this._captureQueue;
-    delete this._hostIframe;
+    delete this._windowlessContainer;
     delete this._startedParentWinInit;
     delete this._parentWin;
   },
 
   /**
    * Creates the thumbnail browser if it doesn't already exist.
    */
   _ensureBrowser() {
new file mode 100644
--- /dev/null
+++ b/toolkit/components/thumbnails/content/backgroundPageThumbs.xhtml
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!-- This page is used to host a (remote) browser for background page
+     thumbnailing purposes. It's always loaded as chrome:// . -->
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta charset='utf-8' />
+    <title>backgroundPageThumbs.html</title>
+  </head>
+  <body></body>
+</html>
+
--- a/toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
+++ b/toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
@@ -184,16 +184,20 @@ const backgroundPageThumbsContent = {
       failReason: reason,
     });
   },
 
   // We load about:blank to finish all captures, even canceled captures.  Two
   // reasons: GC the captured page, and ensure it can't possibly load any more
   // resources.
   _loadAboutBlank: function _loadAboutBlank() {
+    // It's possible we've been destroyed by now, if so don't do anything:
+    if (!docShell) {
+      return;
+    }
     this._webNav.loadURI("about:blank",
                          Ci.nsIWebNavigation.LOAD_FLAGS_STOP_CONTENT,
                          null, null, null);
   },
 
   QueryInterface: XPCOMUtils.generateQI([
     Ci.nsIWebProgressListener,
     Ci.nsISupportsWeakReference,
--- a/toolkit/components/thumbnails/jar.mn
+++ b/toolkit/components/thumbnails/jar.mn
@@ -1,6 +1,7 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 toolkit.jar:
+  content/global/backgroundPageThumbs.xhtml     (content/backgroundPageThumbs.xhtml)
   content/global/backgroundPageThumbsContent.js (content/backgroundPageThumbsContent.js)