Bug 1128500 - Put |HiddenFrame| from CustomizationTabPreloader.jsm in HiddenFrame.jsm. r=ttaubert, a=lmandel
authorAlessio Placitelli <alessio.placitelli@gmail.com>
Wed, 04 Feb 2015 06:33:00 +0100
changeset 250108 3d6eaf96ca69
parent 250107 9fb3cc1f7ff6
child 250109 cae785163094
push id4503
push userryanvm@gmail.com
push date2015-02-27 21:34 +0000
treeherdermozilla-beta@87d76aead804 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersttaubert, lmandel
bugs1128500
milestone37.0
Bug 1128500 - Put |HiddenFrame| from CustomizationTabPreloader.jsm in HiddenFrame.jsm. r=ttaubert, a=lmandel
browser/modules/HiddenFrame.jsm
browser/modules/moz.build
new file mode 100644
--- /dev/null
+++ b/browser/modules/HiddenFrame.jsm
@@ -0,0 +1,86 @@
+/* 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/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["HiddenFrame"];
+
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/PromiseUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Timer.jsm");
+
+const HTML_NS = "http://www.w3.org/1999/xhtml";
+const XUL_PAGE = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window%20id='win'/>";
+
+/**
+ * An hidden frame object. It takes care of creating an IFRAME and attaching it the
+ * |hiddenDOMWindow|.
+ */
+function HiddenFrame() {}
+
+HiddenFrame.prototype = {
+  _frame: null,
+  _deferred: null,
+  _retryTimerId: null,
+
+  get hiddenDOMDocument() {
+    return Services.appShell.hiddenDOMWindow.document;
+  },
+
+  get isReady() {
+    return this.hiddenDOMDocument.readyState === "complete";
+  },
+
+  /**
+   * Gets the |contentWindow| of the hidden frame. Creates the frame if needed.
+   * @returns Promise Returns a promise which is resolved when the hidden frame has finished
+   *          loading.
+   */
+  get: function () {
+    if (!this._deferred) {
+      this._deferred = PromiseUtils.defer();
+      this._create();
+    }
+
+    return this._deferred.promise;
+  },
+
+  destroy: function () {
+    clearTimeout(this._retryTimerId);
+
+    if (this._frame) {
+      if (!Cu.isDeadWrapper(this._frame)) {
+        this._frame.removeEventListener("load", this, true);
+        this._frame.remove();
+      }
+
+      this._frame = null;
+      this._deferred = null;
+    }
+  },
+
+  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;
+    }
+  },
+
+  _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 {
+      // Check again if |hiddenDOMDocument| is ready as soon as possible.
+      this._retryTimerId = setTimeout(this._create.bind(this), 0);
+    }
+  }
+};
--- a/browser/modules/moz.build
+++ b/browser/modules/moz.build
@@ -18,16 +18,17 @@ EXTRA_JS_MODULES += [
     'ContentSearch.jsm',
     'ContentWebRTC.jsm',
     'CustomizationTabPreloader.jsm',
     'DirectoryLinksProvider.jsm',
     'E10SUtils.jsm',
     'Feeds.jsm',
     'FormSubmitObserver.jsm',
     'FormValidationHandler.jsm',
+    'HiddenFrame.jsm',
     'NetworkPrioritizer.jsm',
     'offlineAppCache.jsm',
     'PanelFrame.jsm',
     'RemotePrompt.jsm',
     'SitePermissions.jsm',
     'Social.jsm',
     'TabCrashReporter.jsm',
     'WebappManager.jsm',