Bug 881590 - Don't cancel loads when preloading in the hiddenWindow; r=jaws
authorTim Taubert <ttaubert@mozilla.com>
Mon, 17 Jun 2013 19:46:55 +0200
changeset 136014 c36e0340d4e03bd118aa2537736ad9cc52692468
parent 136013 2b9573964077de9278ca4857503ddf1bdaeb12f0
child 136015 8f5749eb49f6254be92646605322972c20abcd45
push id24858
push userttaubert@mozilla.com
push dateSat, 22 Jun 2013 04:11:24 +0000
treeherdermozilla-central@cea75ce9a559 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs881590
milestone24.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 881590 - Don't cancel loads when preloading in the hiddenWindow; r=jaws
browser/base/content/test/newtab/browser_newtab_perwindow_private_browsing.js
browser/modules/BrowserNewTabPreloader.jsm
--- a/browser/base/content/test/newtab/browser_newtab_perwindow_private_browsing.js
+++ b/browser/base/content/test/newtab/browser_newtab_perwindow_private_browsing.js
@@ -40,19 +40,29 @@ function runTests() {
 
 var windowsToClose = [];
 function testOnWindow(options) {
   var win = OpenBrowserWindow(options);
   win.addEventListener("load", function onLoad() {
     win.removeEventListener("load", onLoad, false);
     windowsToClose.push(win);
     gWindow = win;
-    executeSoon(TestRunner.next);
+    whenDelayedStartupFinished(win, TestRunner.next);
   }, false);
 }
 
+function whenDelayedStartupFinished(win, callback) {
+  const topic = "browser-delayed-startup-finished";
+  Services.obs.addObserver(function onStartup(subject) {
+    if (win == subject) {
+      Services.obs.removeObserver(onStartup, topic);
+      executeSoon(callback);
+    }
+  }, topic, false);
+}
+
 registerCleanupFunction(function () {
   gWindow = window;
   windowsToClose.forEach(function(win) {
     win.close();
   });
 });
 
--- a/browser/modules/BrowserNewTabPreloader.jsm
+++ b/browser/modules/BrowserNewTabPreloader.jsm
@@ -7,20 +7,21 @@
 this.EXPORTED_SYMBOLS = ["BrowserNewTabPreloader"];
 
 const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Promise.jsm");
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-const XUL_PAGE = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window id='win'/>";
+const XUL_PAGE = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window%20id='win'/>";
 const NEWTAB_URL = "about:newtab";
 const PREF_BRANCH = "browser.newtab.";
 
 // The interval between swapping in a preload docShell and kicking off the
 // next preload in the background.
 const PRELOADER_INTERVAL_MS = 3000;
 // The initial delay before we start preloading our first new tab page. The
 // timer is started after the first 'browser-delayed-startup' has been sent.
@@ -285,22 +286,22 @@ let HiddenBrowsers = {
 
     return sizes;
   }
 };
 
 function HiddenBrowser(width, height) {
   this.resize(width, height);
 
-  HostFrame.get(aFrame => {
+  HostFrame.get().then(aFrame => {
     let doc = aFrame.document;
     this._browser = doc.createElementNS(XUL_NS, "browser");
     this._browser.setAttribute("type", "content");
+    this._browser.setAttribute("src", NEWTAB_URL);
     doc.getElementById("win").appendChild(this._browser);
-    this.preload();
   });
 }
 
 HiddenBrowser.prototype = {
   _width: null,
   _height: null,
   _timer: null,
 
@@ -328,26 +329,16 @@ HiddenBrowser.prototype = {
     this._timer = createTimer(this, PRELOADER_INTERVAL_MS);
 
     // Signal that we swapped docShells.
     return true;
   },
 
   observe: function () {
     this._timer = null;
-    this.preload();
-  },
-
-  preload: function () {
-    if (!this._browser) {
-      return;
-    }
-
-    // Make sure the browser has the right size.
-    this.resize(this._width, this._height);
 
     // Start pre-loading the new tab page.
     this._browser.loadURI(NEWTAB_URL);
   },
 
   resize: function (width, height) {
     if (this._browser) {
       this._browser.style.width = width + "px";
@@ -365,53 +356,61 @@ HiddenBrowser.prototype = {
     }
 
     this._timer = clearTimer(this._timer);
   }
 };
 
 let HostFrame = {
   _frame: null,
-  _loading: false,
+  _deferred: null,
 
   get hiddenDOMDocument() {
     return Services.appShell.hiddenDOMWindow.document;
   },
 
   get isReady() {
     return this.hiddenDOMDocument.readyState === "complete";
   },
 
-  get: function (callback) {
-    if (this._frame) {
-      callback(this._frame);
-    } else if (this.isReady && !this._loading) {
-      this._create(callback);
-      this._loading = true;
-    } else {
-      Services.tm.currentThread.dispatch(() => HostFrame.get(callback),
-                                         Ci.nsIThread.DISPATCH_NORMAL);
+  get: function () {
+    if (!this._deferred) {
+      this._deferred = Promise.defer();
+      this._create();
     }
+
+    return this._deferred.promise;
   },
 
   destroy: function () {
-    this._frame = null;
+    if (this._frame) {
+      if (!Cu.isDeadWrapper(this._frame)) {
+        this._frame.removeEventListener("load", this, true);
+        this._frame.remove();
+      }
+
+      this._frame = null;
+      this._deferred = null;
+    }
   },
 
-  _create: function (callback) {
-    let doc = this.hiddenDOMDocument;
-    let iframe = doc.createElementNS(HTML_NS, "iframe");
-    doc.documentElement.appendChild(iframe);
-
-    let frame = iframe.contentWindow;
-    let docShell = frame.QueryInterface(Ci.nsIInterfaceRequestor)
-                        .getInterface(Ci.nsIDocShell);
+  handleEvent: function () {
+    let contentWindow = this._frame.contentWindow;
+    if (contentWindow.location.href === XUL_PAGE) {
+      this._frame.removeEventListener("load", this, true);
+      this._deferred.resolve(contentWindow);
+    } else {
+      contentWindow.location = XUL_PAGE;
+    }
+  },
 
-    docShell.createAboutBlankContentViewer(null);
-    frame.location = XUL_PAGE;
-
-    let eventHandler = docShell.chromeEventHandler;
-    eventHandler.addEventListener("DOMContentLoaded", function onLoad() {
-      eventHandler.removeEventListener("DOMContentLoaded", onLoad, false);
-      callback(HostFrame._frame = frame);
-    }, false);
+  _create: function () {
+    if (this.isReady) {
+      let doc = this.hiddenDOMDocument;
+      this._frame = doc.createElementNS(HTML_NS, "iframe");
+      this._frame.addEventListener("load", this, true);
+      doc.documentElement.appendChild(this._frame);
+    } else {
+      let flags = Ci.nsIThread.DISPATCH_NORMAL;
+      Services.tm.currentThread.dispatch(() => this._create(), flags);
+    }
   }
 };