Bug 1338215 - use a windowless browser for thumbnail hosting, r?markh draft
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Mon, 27 Feb 2017 19:58:55 +0000
changeset 490168 7daca7527d6e460830c1e8fdda1d71442aebed86
parent 490032 106a96755d3bcebe64bbbc3b521d65d262ba9c02
child 547193 d325b286b88573cebb02578d7240b6de67a37d24
push id47025
push usergijskruitbosch@gmail.com
push dateMon, 27 Feb 2017 20:00:01 +0000
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)