1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 const XUL_PAGE = Services.io.newURI("chrome://global/content/win.xhtml");
7 const gAllHiddenFrames = new Set();
9 let cleanupRegistered = false;
10 function ensureCleanupRegistered() {
11 if (!cleanupRegistered) {
12 cleanupRegistered = true;
13 Services.obs.addObserver(function () {
14 for (let hiddenFrame of gAllHiddenFrames) {
15 hiddenFrame.destroy();
22 * An hidden frame object. It takes care of creating a windowless browser and
23 * passing the window containing a blank XUL <window> back.
25 export function HiddenFrame() {}
27 HiddenFrame.prototype = {
35 * Gets the |contentWindow| of the hidden frame. Creates the frame if needed.
36 * @returns Promise Returns a promise which is resolved when the hidden frame has finished
40 if (!this._deferred) {
41 this._deferred = Promise.withResolvers();
45 return this._deferred.promise;
49 * Fetch a sync ref to the window inside the frame (needed for the add-on SDK).
53 return this._browser.document.ownerGlobal;
59 this._webProgress.removeProgressListener(this._listener);
60 this._listener = null;
61 this._webProgress = null;
64 this._deferred = null;
66 gAllHiddenFrames.delete(this);
67 this._browser.close();
73 ensureCleanupRegistered();
74 let chromeFlags = Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW;
75 if (Services.appinfo.fissionAutostart) {
76 chromeFlags |= Ci.nsIWebBrowserChrome.CHROME_FISSION_WINDOW;
78 this._browser = Services.appShell.createWindowlessBrowser(
82 this._browser.QueryInterface(Ci.nsIInterfaceRequestor);
83 gAllHiddenFrames.add(this);
84 this._webProgress = this._browser.getInterface(Ci.nsIWebProgress);
86 QueryInterface: ChromeUtils.generateQI([
87 "nsIWebProgressListener",
88 "nsIWebProgressListener2",
89 "nsISupportsWeakReference",
92 this._listener.onStateChange = (wbp, request, stateFlags) => {
96 if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
97 this._webProgress.removeProgressListener(this._listener);
98 this._listener = null;
99 this._webProgress = null;
100 // Get the window reference via the document.
101 this._frame = this._browser.document.ownerGlobal;
102 this._deferred.resolve(this._frame);
105 this._webProgress.addProgressListener(
107 Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT
109 let docShell = this._browser.docShell;
110 let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
111 docShell.createAboutBlankDocumentViewer(systemPrincipal, systemPrincipal);
112 let browsingContext = this._browser.browsingContext;
113 browsingContext.useGlobalHistory = false;
114 let loadURIOptions = {
115 triggeringPrincipal: systemPrincipal,
117 this._browser.loadURI(XUL_PAGE, loadURIOptions);