Bug 1463016: Part 5 - Add domWindow property to DocShellTreeItem and update callers to use it. r=nika
☠☠ backed out by aaee68beff80 ☠ ☠
authorKris Maglione <maglione.k@gmail.com>
Sun, 20 May 2018 18:10:16 -0700
changeset 483984 0d69b4fb1ed43751cfcbc0b4f2fe3b6a49bc0494
parent 483983 553a4074bc2d39a801eb715e891e37017a420993
child 483985 fcfb99baa0f0fb60a7c420a712c6ae7c72576871
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika
bugs1463016
milestone63.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 1463016: Part 5 - Add domWindow property to DocShellTreeItem and update callers to use it. r=nika MozReview-Commit-ID: FRRAdxLHRtG
accessible/tests/mochitest/common.js
browser/base/content/browser.js
browser/base/content/test/general/browser_bug676619.js
browser/base/content/test/general/browser_fullscreen-window-open.js
browser/components/feeds/WebContentConverter.js
browser/components/nsBrowserContentHandler.js
browser/components/search/content/searchReset.js
browser/components/search/test/browser_webapi.js
browser/components/sessionstore/ContentRestore.jsm
browser/components/sessionstore/SessionStorage.jsm
browser/components/sessionstore/content/aboutSessionRestore.js
browser/components/shell/HeadlessShell.jsm
browser/components/syncedtabs/util.js
browser/extensions/pdfjs/test/browser_pdfjs_savedialog.js
devtools/client/debugger/test/mochitest/head.js
devtools/client/framework/devtools-browser.js
devtools/client/responsive.html/utils/window.js
devtools/client/webide/modules/runtimes.js
devtools/server/actors/addon/webextension-inspected-window.js
devtools/server/actors/targets/browsing-context.js
devtools/server/actors/targets/webextension.js
devtools/server/actors/webbrowser.js
devtools/shared/security/prompt.js
docshell/base/nsDocShell.cpp
docshell/base/nsIDocShellTreeItem.idl
docshell/test/chrome/test_private_hidden_window.html
dom/base/test/chrome/file_bug549682.xul
dom/plugins/test/mochitest/test_privatemode_perwindowpb.xul
dom/security/test/general/browser_test_data_download.js
dom/security/test/general/browser_test_data_text_csv.js
dom/serviceworkers/test/test_privateBrowsing.html
dom/tests/mochitest/beacon/test_beaconCookies.html
dom/tests/mochitest/chrome/window_focus.xul
dom/tests/mochitest/localstorage/test_localStorageBasePrivateBrowsing_perwindowpb.html
dom/tests/mochitest/localstorage/test_localStorageQuotaPrivateBrowsing_perwindowpb.html
dom/url/tests/browser_download_after_revoke.js
dom/workers/test/test_sharedWorker_privateBrowsing.html
editor/spellchecker/tests/test_bug1209414.html
image/test/mochitest/test_bug1132427.html
js/xpconnect/tests/unit/test_xray_named_element_access.js
layout/forms/test/test_bug536567_perwindowpb.html
layout/tools/reftest/bootstrap.js
mobile/android/chrome/content/aboutAccounts.js
mobile/android/chrome/content/aboutAddons.js
mobile/android/chrome/content/aboutLogins.js
mobile/android/chrome/content/aboutPrivateBrowsing.js
mobile/android/components/ContentPermissionPrompt.js
mobile/android/components/extensions/ext-tabs.js
mobile/android/modules/WebrtcUI.jsm
mobile/android/modules/geckoview/GeckoViewUtils.jsm
mobile/android/tests/browser/chrome/test_awsy_lite.html
netwerk/test/browser/browser_NetUtil.js
security/manager/ssl/tests/mochitest/stricttransportsecurity/test_sts_privatebrowsing_perwindowpb.html
testing/mochitest/bootstrap.js
testing/specialpowers/content/specialpowersAPI.js
toolkit/components/browser/nsWebBrowser.cpp
toolkit/components/extensions/ExtensionContent.jsm
toolkit/components/extensions/ExtensionParent.jsm
toolkit/components/extensions/extension-process-script.js
toolkit/components/passwordmgr/test/browser/browser_passwordmgr_switchtab.js
toolkit/components/passwordmgr/test/chrome/test_privbrowsing_perwindowpb.html
toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
toolkit/components/url-classifier/tests/mochitest/test_advisory_link.html
toolkit/components/url-classifier/tests/mochitest/test_donottrack.html
toolkit/components/url-classifier/tests/mochitest/test_privatebrowsing_trackingprotection.html
toolkit/components/url-classifier/tests/mochitest/test_reporturl.html
toolkit/components/url-classifier/tests/mochitest/test_threathit_report.html
toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_bug1157081.html
toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_bug1312515.html
toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_whitelist.html
toolkit/content/aboutTelemetry.js
toolkit/modules/BrowserUtils.jsm
toolkit/modules/Finder.jsm
toolkit/modules/HiddenFrame.jsm
toolkit/modules/addons/WebNavigationContent.js
toolkit/modules/addons/WebNavigationFrames.jsm
toolkit/mozapps/downloads/nsHelperAppDlg.js
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/extensions/test/browser/head.js
toolkit/mozapps/extensions/test/xpinstall/head.js
widget/headless/tests/test_headless.js
widget/tests/test_bug593307.xul
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -852,22 +852,17 @@ function shortenString(aString, aMaxLeng
 
 // //////////////////////////////////////////////////////////////////////////////
 // General Utils
 // //////////////////////////////////////////////////////////////////////////////
 /**
  * Return main chrome window (crosses chrome boundary)
  */
 function getMainChromeWindow(aWindow) {
-  return aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                .getInterface(Ci.nsIWebNavigation)
-                .QueryInterface(Ci.nsIDocShellTreeItem)
-                .rootTreeItem
-                .QueryInterface(Ci.nsIInterfaceRequestor)
-                .getInterface(Ci.nsIDOMWindow);
+  return aWindow.document.docShell.rootTreeItem.domWindow;
 }
 
 /** Sets the test plugin(s) initially expected enabled state.
  * It will automatically be reset to it's previous value after the test
  * ends.
  * @param aNewEnabledState [in] the enabled state, e.g. SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED
  * @param aPluginName [in, optional] The name of the plugin, defaults to "Test Plug-in"
  */
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -7075,22 +7075,18 @@ var MailIntegration = {
 };
 
 function BrowserOpenAddonsMgr(aView) {
   return new Promise(resolve => {
     let emWindow;
     let browserWindow;
 
     var receivePong = function(aSubject, aTopic, aData) {
-      let browserWin = aSubject.QueryInterface(Ci.nsIInterfaceRequestor)
-                               .getInterface(Ci.nsIWebNavigation)
-                               .QueryInterface(Ci.nsIDocShellTreeItem)
-                               .rootTreeItem
-                               .QueryInterface(Ci.nsIInterfaceRequestor)
-                               .getInterface(Ci.nsIDOMWindow);
+      let browserWin = aSubject.document.docShell
+                               .rootTreeItem.domWindow;
       if (!emWindow || browserWin == window /* favor the current window */) {
         emWindow = aSubject;
         browserWindow = browserWin;
       }
     };
     Services.obs.addObserver(receivePong, "EM-pong");
     Services.obs.notifyObservers(null, "EM-ping");
     Services.obs.removeObserver(receivePong, "EM-pong");
--- a/browser/base/content/test/general/browser_bug676619.js
+++ b/browser/base/content/test/general/browser_bug676619.js
@@ -7,18 +7,17 @@ function waitForNewWindow() {
 
         function downloadOnLoad() {
           domwindow.removeEventListener("load", downloadOnLoad, true);
 
           is(domwindow.document.location.href, "chrome://mozapps/content/downloads/unknownContentType.xul", "Download page appeared");
           resolve(domwindow);
         }
 
-        var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                                  .getInterface(Ci.nsIDOMWindow);
+        var domwindow = aXULWindow.docShell.domWindow;
         domwindow.addEventListener("load", downloadOnLoad, true);
       },
       onCloseWindow: aXULWindow => {},
     };
 
     Services.wm.addListener(listener);
   });
 }
--- a/browser/base/content/test/general/browser_fullscreen-window-open.js
+++ b/browser/base/content/test/general/browser_fullscreen-window-open.js
@@ -312,18 +312,17 @@ WindowListener.prototype = {
   test_title: null,
   test_url: null,
   callback_onSuccess: null,
   callBack_onFinalize: null,
 
   onOpenWindow(aXULWindow) {
     Services.wm.removeListener(this);
 
-    let domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindow);
+    let domwindow = aXULWindow.docShell.domWindow;
     let onLoad = aEvent => {
       is(domwindow.document.location.href, this.test_url,
         "Opened Window is expected: " + this.test_title);
       if (this.callback_onSuccess) {
         this.callback_onSuccess();
       }
 
       domwindow.removeEventListener("load", onLoad, true);
--- a/browser/components/feeds/WebContentConverter.js
+++ b/browser/components/feeds/WebContentConverter.js
@@ -282,22 +282,17 @@ WebContentConverterRegistrar.prototype =
                                        notificationBox.PRIORITY_INFO_LOW,
                                        [addButton]);
   },
 
   /**
    * Returns the browser chrome window in which the content window is in
    */
   _getBrowserWindowForContentWindow(aContentWindow) {
-    return aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIWebNavigation)
-                         .QueryInterface(Ci.nsIDocShellTreeItem)
-                         .rootTreeItem
-                         .QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIDOMWindow)
+    return aContentWindow.document.docShell.rootTreeItem.domWindow
                          .wrappedJSObject;
   },
 
   /**
    * Returns the <xul:browser> element associated with the given content
    * window.
    *
    * @param aBrowserWindow
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -665,22 +665,17 @@ function handURIToExistingBrowser(uri, l
   var allowPrivate = forcePrivate || PrivateBrowsingUtils.permanentPrivateBrowsing;
   var navWin = BrowserWindowTracker.getTopWindow({private: allowPrivate});
   if (!navWin) {
     // if we couldn't load it in an existing window, open a new one
     openBrowserWindow(cmdLine, uri.spec, null, forcePrivate);
     return;
   }
 
-  var navNav = navWin.QueryInterface(Ci.nsIInterfaceRequestor)
-                     .getInterface(Ci.nsIWebNavigation);
-  var rootItem = navNav.QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem;
-  var rootWin = rootItem.QueryInterface(Ci.nsIInterfaceRequestor)
-                        .getInterface(Ci.nsIDOMWindow);
-  var bwin = rootWin.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow;
+  var bwin = navWin.document.docShell.rootTreeItem.domWindow;
   bwin.openURI(uri, null, location,
                Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL, triggeringPrincipal);
 }
 
 function nsDefaultCommandLineHandler() {
 }
 
 nsDefaultCommandLineHandler.prototype = {
--- a/browser/components/search/content/searchReset.js
+++ b/browser/components/search/content/searchReset.js
@@ -41,22 +41,17 @@ function doSearch() {
     }
   }
 
   let engine = Services.search.currentEngine;
   let submission = engine.getSubmission(queryString, null, purpose);
 
   window.removeEventListener("unload", recordPageClosed);
 
-  let win = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                  .getInterface(Ci.nsIWebNavigation)
-                  .QueryInterface(Ci.nsIDocShellTreeItem)
-                  .rootTreeItem
-                  .QueryInterface(Ci.nsIInterfaceRequestor)
-                  .getInterface(Ci.nsIDOMWindow);
+  let win = window.document.docShell.rootTreeItem.domWindow;
   win.openTrustedLinkIn(submission.uri.spec, "current", {
     allowThirdPartyFixup: false,
     postData: submission.postData,
   });
 }
 
 function openingSettings() {
   record(TELEMETRY_RESULT_ENUM.OPENED_SETTINGS);
--- a/browser/components/search/test/browser_webapi.js
+++ b/browser/components/search/test/browser_webapi.js
@@ -12,18 +12,17 @@ function AddSearchProvider(...args) {
 }
 
 function promiseDialogOpened() {
   return new Promise((resolve, reject) => {
     Services.wm.addListener({
       onOpenWindow(xulWin) {
         Services.wm.removeListener(this);
 
-        let win = xulWin.QueryInterface(Ci.nsIInterfaceRequestor)
-                        .getInterface(Ci.nsIDOMWindow);
+        let win = xulWin.docShell.domWindow;
         waitForFocus(() => {
           if (win.location == "chrome://global/content/commonDialog.xul")
             resolve(win);
           else
             reject();
         }, win);
       }
     });
--- a/browser/components/sessionstore/ContentRestore.jsm
+++ b/browser/components/sessionstore/ContentRestore.jsm
@@ -309,18 +309,17 @@ ContentRestoreInternal.prototype = {
    */
   restoreDocument() {
     if (!this._restoringDocument) {
       return;
     }
     let {formdata, scrollPositions} = this._restoringDocument;
     this._restoringDocument = null;
 
-    let window = this.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                               .getInterface(Ci.nsIDOMWindow);
+    let window = this.docShell.domWindow;
 
     // Restore form data.
     restoreFrameTreeData(window, formdata, (frame, data) => {
       // restore() will return false, and thus abort restoration for the
       // current |frame| and its descendants, if |data.url| is given but
       // doesn't match the loaded document's URL.
       return FormData.restore(frame, data);
     });
--- a/browser/components/sessionstore/SessionStorage.jsm
+++ b/browser/components/sessionstore/SessionStorage.jsm
@@ -145,17 +145,17 @@ var SessionStorageInternal = {
         let dataPrincipal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
         principal = Services.scriptSecurityManager.createCodebasePrincipal(dataPrincipal.URI, attrs);
       } catch (e) {
         console.error(e);
         continue;
       }
 
       let storageManager = aDocShell.QueryInterface(Ci.nsIDOMStorageManager);
-      let window = aDocShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+      let window = aDocShell.domWindow;
 
       // There is no need to pass documentURI, it's only used to fill documentURI property of
       // domstorage event, which in this case has no consumer. Prevention of events in case
       // of missing documentURI will be solved in a followup bug to bug 600307.
       let storage = storageManager.createStorage(window, principal, "", aDocShell.usePrivateBrowsing);
 
       for (let key of Object.keys(data)) {
         try {
@@ -174,17 +174,17 @@ var SessionStorageInternal = {
    *        That history entry uri
    * @param aDocShell
    *        A tab's docshell (containing the sessionStorage)
    */
   _readEntry(aPrincipal, aDocShell) {
     let hostData = {};
     let storage;
 
-    let window = aDocShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+    let window = aDocShell.domWindow;
 
     try {
       let storageManager = aDocShell.QueryInterface(Ci.nsIDOMStorageManager);
       storage = storageManager.getStorage(window, aPrincipal);
       storage.length; // XXX: Bug 1232955 - storage.length can throw, catch that failure
     } catch (e) {
       // sessionStorage might throw if it's turned off, see bug 458954
       storage = null;
--- a/browser/components/sessionstore/content/aboutSessionRestore.js
+++ b/browser/components/sessionstore/content/aboutSessionRestore.js
@@ -220,19 +220,17 @@ function onListKeyDown(aEvent) {
       restoreSingleTab(ix, aEvent.shiftKey);
     break;
   }
 }
 
 // Helper functions
 
 function getBrowserWindow() {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
-               .QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem
-               .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+  return window.document.docShell.rootTreeItem.domWindow;
 }
 
 function toggleRowChecked(aIx) {
   function isChecked(aItem) {
     return aItem.checked;
   }
 
   var item = gTreeData[aIx];
--- a/browser/components/shell/HeadlessShell.jsm
+++ b/browser/components/shell/HeadlessShell.jsm
@@ -25,18 +25,17 @@ function loadContentWindow(webNavigation
         // Ignore inner-frame events
         if (progress != webProgress) {
           return;
         }
         // Ignore events that don't change the document
         if (flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
           return;
         }
-        let contentWindow = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                                    .getInterface(Ci.nsIDOMWindow);
+        let contentWindow = docShell.domWindow;
         progressListeners.delete(progressListener);
         webProgress.removeProgressListener(progressListener);
         contentWindow.addEventListener("load", (event) => {
           resolve(contentWindow);
         }, { once: true });
       },
       QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",
                                               "nsISupportsWeakReference"])
--- a/browser/components/syncedtabs/util.js
+++ b/browser/components/syncedtabs/util.js
@@ -5,17 +5,11 @@
 "use strict";
 
 var EXPORTED_SYMBOLS = [
   "getChromeWindow"
 ];
 
 // Get the chrome (ie, browser) window hosting this content.
 function getChromeWindow(window) {
-  return window
-         .QueryInterface(Ci.nsIInterfaceRequestor)
-         .getInterface(Ci.nsIWebNavigation)
-         .QueryInterface(Ci.nsIDocShellTreeItem)
-         .rootTreeItem
-         .QueryInterface(Ci.nsIInterfaceRequestor)
-         .getInterface(Ci.nsIDOMWindow)
+  return window.document.docShell.rootTreeItem.domWindow
          .wrappedJSObject;
 }
--- a/browser/extensions/pdfjs/test/browser_pdfjs_savedialog.js
+++ b/browser/extensions/pdfjs/test/browser_pdfjs_savedialog.js
@@ -42,18 +42,17 @@ function changeMimeHandler(preferredActi
 }
 
 function addWindowListener(aURL, aCallback) {
   Services.wm.addListener({
     onOpenWindow(aXULWindow) {
       info("window opened, waiting for focus");
       Services.wm.removeListener(this);
 
-      var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                                .getInterface(Ci.nsIDOMWindow);
+      var domwindow = aXULWindow.docShell.domWindow;
       waitForFocus(function() {
         is(domwindow.document.location.href, aURL, "should have seen the right window open");
         domwindow.close();
         aCallback();
       }, domwindow);
     },
     onCloseWindow(aXULWindow) { },
   });
--- a/devtools/client/debugger/test/mochitest/head.js
+++ b/devtools/client/debugger/test/mochitest/head.js
@@ -70,20 +70,17 @@ var helpersjs = testDir + "/../../../com
 Services.scriptloader.loadSubScript(helpersjs, this);
 
 function addWindow(aUrl) {
   info("Adding window: " + aUrl);
   return promise.resolve(getChromeWindow(window.open(aUrl)));
 }
 
 function getChromeWindow(aWindow) {
-  return aWindow
-    .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
-    .QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem
-    .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+  return aWindow.document.docShell.rootTreeItem.domWindow;
 }
 
 // Override addTab/removeTab as defined by shared-head, since these have
 // an extra window parameter and add a frame script
 this.addTab = function addTab(aUrl, aWindow) {
   info("Adding tab: " + aUrl);
 
   let deferred = promise.defer();
--- a/devtools/client/framework/devtools-browser.js
+++ b/devtools/client/framework/devtools-browser.js
@@ -514,23 +514,18 @@ var gDevToolsBrowser = exports.gDevTools
           default:
             throw Error("invalid thread client state in slow script debug handler: " +
                         threadClient.state);
         }
       });
     }
 
     debugService.activationHandler = function(window) {
-      const chromeWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                                .getInterface(Ci.nsIWebNavigation)
-                                .QueryInterface(Ci.nsIDocShellTreeItem)
-                                .rootTreeItem
-                                .QueryInterface(Ci.nsIInterfaceRequestor)
-                                .getInterface(Ci.nsIDOMWindow)
-                                .QueryInterface(Ci.nsIDOMChromeWindow);
+      const chromeWindow = window.document.docShell.rootTreeItem.domWindow
+                                 .QueryInterface(Ci.nsIDOMChromeWindow);
 
       let setupFinished = false;
       slowScriptDebugHandler(chromeWindow.gBrowser.selectedTab,
         () => {
           setupFinished = true;
         });
 
       // Don't return from the interrupt handler until the debugger is brought
--- a/devtools/client/responsive.html/utils/window.js
+++ b/devtools/client/responsive.html/utils/window.js
@@ -1,27 +1,21 @@
 /* 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";
 
-const { Ci } = require("chrome");
 const Services = require("Services");
 
 /**
  * Returns the `nsIDOMWindow` toplevel window for any child/inner window
  */
 function getToplevelWindow(window) {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIWebNavigation)
-               .QueryInterface(Ci.nsIDocShellTreeItem)
-               .rootTreeItem
-               .QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIDOMWindow);
+  return window.document.docShell.rootTreeItem.domWindow;
 }
 exports.getToplevelWindow = getToplevelWindow;
 
 function getDOMWindowUtils(window) {
   return window.windowUtils;
 }
 exports.getDOMWindowUtils = getDOMWindowUtils;
 
--- a/devtools/client/webide/modules/runtimes.js
+++ b/devtools/client/webide/modules/runtimes.js
@@ -1,15 +1,14 @@
 /* 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";
 
-const {Ci} = require("chrome");
 const Services = require("Services");
 const {Devices} = require("resource://devtools/shared/apps/Devices.jsm");
 const {DebuggerServer} = require("devtools/server/main");
 const discovery = require("devtools/shared/discovery/discovery");
 const EventEmitter = require("devtools/shared/event-emitter");
 const promise = require("promise");
 loader.lazyRequireGetter(this, "AuthenticationResult",
   "devtools/shared/security/auth", true);
@@ -386,18 +385,17 @@ WiFiRuntime.prototype = {
     if (authResult != AuthenticationResult.PENDING) {
       throw new Error("Expected PENDING result, got " + authResult);
     }
 
     // Listen for the window our prompt opens, so we can close it programatically
     let promptWindow;
     const windowListener = {
       onOpenWindow(xulWindow) {
-        const win = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                           .getInterface(Ci.nsIDOMWindow);
+        const win = xulWindow.docShell.domWindow;
         win.addEventListener("load", function() {
           if (win.document.documentElement.getAttribute("id") != WINDOW_ID) {
             return;
           }
           // Found the window
           promptWindow = win;
           Services.wm.removeListener(windowListener);
         }, {once: true});
--- a/devtools/server/actors/addon/webextension-inspected-window.js
+++ b/devtools/server/actors/addon/webextension-inspected-window.js
@@ -178,19 +178,17 @@ CustomizedReload.prototype = {
                                 .QueryInterface(Ci.nsIDocShell);
 
     // Keep track of the set of window objects where we are going to inject
     // the injectedScript: the top level window and all its descendant
     // that are still of type content (filtering out loaded XUL pages, if any).
     if (window == this.window) {
       this.customizedReloadWindows.add(window);
     } else if (subjectDocShell.sameTypeParent) {
-      const parentWindow = subjectDocShell.sameTypeParent
-                                        .QueryInterface(Ci.nsIInterfaceRequestor)
-                                        .getInterface(Ci.nsIDOMWindow);
+      const parentWindow = subjectDocShell.sameTypeParent.domWindow;
       if (parentWindow && this.customizedReloadWindows.has(parentWindow)) {
         this.customizedReloadWindows.add(window);
       }
     }
 
     if (this.customizedReloadWindows.has(window)) {
       const {
         apiErrorResult
--- a/devtools/server/actors/targets/browsing-context.js
+++ b/devtools/server/actors/targets/browsing-context.js
@@ -57,36 +57,34 @@ function getWindowID(window) {
 }
 
 function getDocShellChromeEventHandler(docShell) {
   let handler = docShell.chromeEventHandler;
   if (!handler) {
     try {
       // Toplevel xul window's docshell doesn't have chromeEventHandler
       // attribute. The chrome event handler is just the global window object.
-      handler = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                        .getInterface(Ci.nsIDOMWindow);
+      handler = docShell.domWindow;
     } catch (e) {
       // ignore
     }
   }
   return handler;
 }
 
 function getChildDocShells(parentDocShell) {
   const docShellsEnum = parentDocShell.getDocShellEnumerator(
     Ci.nsIDocShellTreeItem.typeAll,
     Ci.nsIDocShell.ENUMERATE_FORWARDS
   );
 
   const docShells = [];
   while (docShellsEnum.hasMoreElements()) {
     const docShell = docShellsEnum.getNext();
-    docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-            .getInterface(Ci.nsIWebProgress);
+    docShell.QueryInterface(Ci.nsIDocShell);
     docShells.push(docShell);
   }
   return docShells;
 }
 
 exports.getChildDocShells = getChildDocShells;
 
 /**
@@ -340,19 +338,17 @@ const browsingContextTargetPrototype = {
   },
 
   /**
    * Getter for the browsing context's current DOM window.
    */
   get window() {
     // On xpcshell, there is no document
     if (this.docShell) {
-      return this.docShell
-        .QueryInterface(Ci.nsIInterfaceRequestor)
-        .getInterface(Ci.nsIDOMWindow);
+      return this.docShell.domWindow;
     }
     return null;
   },
 
   get outerWindowID() {
     if (this.window) {
       return this.window.windowUtils.outerWindowID;
     }
@@ -376,18 +372,17 @@ const browsingContextTargetPrototype = {
   },
 
   /**
    * Getter for the list of all content DOM windows in the browsing context.
    * @return {Array}
    */
   get windows() {
     return this.docShells.map(docShell => {
-      return docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                     .getInterface(Ci.nsIDOMWindow);
+      return docShell.domWindow;
     });
   },
 
   /**
    * Getter for the original docShell this actor got attached to in the first
    * place.
    * Note that your actor should normally *not* rely on this top level docShell
    * if you want it to show information relative to the iframe that's currently
@@ -1483,18 +1478,17 @@ DebuggerProgressListener.prototype = {
     this._knownWindowIDs.clear();
     this._knownWindowIDs = null;
   },
 
   watch(docShell) {
     // Add the docshell to the watched set. We're actually adding the window,
     // because docShell objects are not wrappercached and would be rejected
     // by the WeakSet.
-    const docShellWindow = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                                 .getInterface(Ci.nsIDOMWindow);
+    const docShellWindow = docShell.domWindow;
     this._watchedDocShells.add(docShellWindow);
 
     const webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                               .getInterface(Ci.nsIWebProgress);
     webProgress.addProgressListener(this,
                                     Ci.nsIWebProgress.NOTIFY_STATE_WINDOW |
                                     Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
 
@@ -1506,18 +1500,17 @@ DebuggerProgressListener.prototype = {
     // Dispatch the _windowReady event on the targetActor for pre-existing windows
     for (const win of this._getWindowsInDocShell(docShell)) {
       this._targetActor._windowReady(win);
       this._knownWindowIDs.set(getWindowID(win), win);
     }
   },
 
   unwatch(docShell) {
-    const docShellWindow = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                                 .getInterface(Ci.nsIDOMWindow);
+    const docShellWindow = docShell.domWindow;
     if (!this._watchedDocShells.has(docShellWindow)) {
       return;
     }
 
     const webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                               .getInterface(Ci.nsIWebProgress);
     // During process shutdown, the docshell may already be cleaned up and throw
     try {
@@ -1534,18 +1527,17 @@ DebuggerProgressListener.prototype = {
 
     for (const win of this._getWindowsInDocShell(docShell)) {
       this._knownWindowIDs.delete(getWindowID(win));
     }
   },
 
   _getWindowsInDocShell(docShell) {
     return getChildDocShells(docShell).map(d => {
-      return d.QueryInterface(Ci.nsIInterfaceRequestor)
-              .getInterface(Ci.nsIDOMWindow);
+      return d.domWindow;
     });
   },
 
   onWindowCreated: DevToolsUtils.makeInfallible(function(evt) {
     if (!this._targetActor.attached) {
       return;
     }
 
--- a/devtools/server/actors/targets/webextension.js
+++ b/devtools/server/actors/targets/webextension.js
@@ -160,18 +160,17 @@ webExtensionTargetPrototype._createFallb
   }
 
   // Create an empty hidden window as a fallback (e.g. the background page could be
   // not defined for the target add-on or not yet when the actor instance has been
   // created).
   this.fallbackWebNav = Services.appShell.createWindowlessBrowser(true);
 
   // Save the reference to the fallback DOMWindow.
-  this.fallbackWindow = this.fallbackWebNav.QueryInterface(Ci.nsIInterfaceRequestor)
-                                           .getInterface(Ci.nsIDOMWindow);
+  this.fallbackWindow = this.fallbackWebNav.document.defaultView;
 
   // Insert the fallback doc message.
   this.fallbackWindow.document.body.innerText = FALLBACK_DOC_MESSAGE;
 };
 
 webExtensionTargetPrototype._destroyFallbackWindow = function() {
   if (this.fallbackWebNav) {
     // Explicitly close the fallback windowless browser to prevent it to leak
@@ -268,21 +267,18 @@ webExtensionTargetPrototype._docShellToW
 
   const webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                             .getInterface(Ci.nsIWebProgress);
   const window = webProgress.DOMWindow;
 
   // Collect the addonID from the document origin attributes and its sameType top level
   // frame.
   const addonID = window.document.nodePrincipal.addonId;
-  const sameTypeRootAddonID = docShell.QueryInterface(Ci.nsIDocShellTreeItem)
-                                    .sameTypeRootTreeItem
-                                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                                    .getInterface(Ci.nsIDOMWindow)
-                                    .document.nodePrincipal.addonId;
+  const sameTypeRootAddonID = docShell.sameTypeRootTreeItem.domWindow
+                                      .document.nodePrincipal.addonId;
 
   return Object.assign(baseWindowDetails, {
     addonID,
     sameTypeRootAddonID,
   });
 };
 
 /**
@@ -299,20 +295,17 @@ webExtensionTargetPrototype._docShellsTo
 };
 
 webExtensionTargetPrototype.isExtensionWindow = function(window) {
   return window.document.nodePrincipal.addonId == this.id;
 };
 
 webExtensionTargetPrototype.isExtensionWindowDescendent = function(window) {
   // Check if the source is coming from a descendant docShell of an extension window.
-  const docShell = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDocShell);
-  const rootWin = docShell.sameTypeRootTreeItem.QueryInterface(Ci.nsIInterfaceRequestor)
-                                             .getInterface(Ci.nsIDOMWindow);
+  const rootWin = window.document.docShell.sameTypeRootTreeItem.domWindow;
   return this.isExtensionWindow(rootWin);
 };
 
 /**
  * Return true if the given source is associated with this addon and should be
  * added to the visible sources (retrieved and used by the webbrowser actor module).
  */
 webExtensionTargetPrototype._allowSource = function(source) {
--- a/devtools/server/actors/webbrowser.js
+++ b/devtools/server/actors/webbrowser.js
@@ -652,18 +652,19 @@ DevToolsUtils.makeInfallible(function(wi
   window = window.QueryInterface(Ci.nsIInterfaceRequestor)
                  .getInterface(Ci.nsIDOMWindow);
 
   window.addEventListener("load", handleLoad);
 }, "BrowserTabList.prototype.onOpenWindow");
 
 BrowserTabList.prototype.onCloseWindow =
 DevToolsUtils.makeInfallible(function(window) {
-  window = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                   .getInterface(Ci.nsIDOMWindow);
+  if (window instanceof Ci.nsIXULWindow) {
+    window = window.docShell.domWindow;
+  }
 
   if (appShellDOMWindowType(window) !== DebuggerServer.chromeWindowType) {
     return;
   }
 
   /*
    * nsIWindowMediator deadlocks if you call its GetEnumerator method from
    * a nsIWindowMediatorListener's onCloseWindow hook (bug 873589), so
--- a/devtools/shared/security/prompt.js
+++ b/devtools/shared/security/prompt.js
@@ -1,17 +1,16 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* 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";
 
-var { Ci } = require("chrome");
 var Services = require("Services");
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
 loader.lazyRequireGetter(this, "AuthenticationResult",
   "devtools/shared/security/auth", true);
 
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const L10N = new LocalizationHelper("devtools/shared/locales/debugger.properties");
 
@@ -55,18 +54,17 @@ Client.defaultSendOOB = ({ authResult, o
   const msg = `${header}\n\n${hashMsg}\n${tokenMsg}`;
   const prompt = Services.prompt;
   const flags = prompt.BUTTON_POS_0 * prompt.BUTTON_TITLE_CANCEL;
 
   // Listen for the window our prompt opens, so we can close it programatically
   let promptWindow;
   const windowListener = {
     onOpenWindow(xulWindow) {
-      const win = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIDOMWindow);
+      const win = xulWindow.docShell.domWindow;
       win.addEventListener("load", function() {
         if (win.document.documentElement.getAttribute("id") != "commonDialog") {
           return;
         }
         // Found the window
         promptWindow = win;
         Services.wm.removeListener(windowListener);
       }, {once: true});
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -3959,16 +3959,29 @@ nsDocShell::GetWindow()
 {
   if (NS_FAILED(EnsureScriptEnvironment())) {
     return nullptr;
   }
   return mScriptGlobal->AsOuter();
 }
 
 NS_IMETHODIMP
+nsDocShell::GetDomWindow(mozIDOMWindowProxy** aWindow)
+{
+  NS_ENSURE_ARG_POINTER(aWindow);
+
+  nsresult rv = EnsureScriptEnvironment();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsPIDOMWindowOuter> window = mScriptGlobal->AsOuter();
+  window.forget(aWindow);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDocShell::SetDeviceSizeIsPageSize(bool aValue)
 {
   if (mDeviceSizeIsPageSize != aValue) {
     mDeviceSizeIsPageSize = aValue;
     RefPtr<nsPresContext> presContext;
     GetPresContext(getter_AddRefs(presContext));
     if (presContext) {
       presContext->MediaFeatureValuesChanged({
--- a/docshell/base/nsIDocShellTreeItem.idl
+++ b/docshell/base/nsIDocShellTreeItem.idl
@@ -1,21 +1,21 @@
 /* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * 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/. */
 
 #include "nsISupports.idl"
 
+interface mozIDOMWindowProxy;
 interface nsIDocShellTreeOwner;
 interface nsIDocument;
 interface nsPIDOMWindowOuter;
 
-
 /**
  * The nsIDocShellTreeItem supplies the methods that are required of any item
  * that wishes to be able to live within the docshell tree either as a middle
  * node or a leaf. 
  */
 
 [scriptable, uuid(9b7c586f-9214-480c-a2c4-49b526fff1a6)]
 interface nsIDocShellTreeItem : nsISupports
@@ -174,12 +174,17 @@ interface nsIDocShellTreeItem : nsISuppo
 	Note the search is depth first when recursing.
 	*/
 	nsIDocShellTreeItem findChildWithName(in AString aName,
 	                                      in boolean aRecurse,
 	                                      in boolean aSameType,
 	                                      in nsIDocShellTreeItem aRequestor,
 	                                      in nsIDocShellTreeItem aOriginalRequestor);
 
+  /**
+   * Returns the DOM outer window for the content viewer.
+   */
+  readonly attribute mozIDOMWindowProxy domWindow;
+
   [noscript,nostdcall,notxpcom] nsIDocument getDocument();
   [noscript,nostdcall,notxpcom] nsPIDOMWindowOuter getWindow();
 };
 
--- a/docshell/test/chrome/test_private_hidden_window.html
+++ b/docshell/test/chrome/test_private_hidden_window.html
@@ -13,22 +13,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <div id="content" style="display: none">
   <iframe name="target"></iframe>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 SimpleTest.waitForExplicitFinish();
-var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIWebNavigation)
-                       .QueryInterface(Ci.nsIDocShellTreeItem)
-                       .rootTreeItem
-                       .QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindow);
+var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 
 // We need to wait for the hidden window to load, but can't access
 // an event target for a regular event listener.
 var hidden = mainWindow.Services.appShell.hiddenPrivateDOMWindow;
 
 function isNotLoaded() {
   return !["complete", "interactive"].includes(hidden.document.readyState);
 }
--- a/dom/base/test/chrome/file_bug549682.xul
+++ b/dom/base/test/chrome/file_bug549682.xul
@@ -136,17 +136,18 @@ https://bugzilla.mozilla.org/show_bug.cg
       sendAsyncMessage('weak', {});\
       sendAsyncMessage('weakdone', {});", false);
   }
 
   function run() {
     var localmm = document.getElementById('ifr').messageManager;
 
     var wn = document.getElementById('ifr').contentWindow
-      .getInterface(Ci.nsIWebNavigation);
+      .getInterface(Ci.nsIWebNavigation)
+      .QueryInterface(Ci.nsIInterfaceRequestor);
     ok(wn, "Should have webnavigation");
     var cfmm = wn.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIContentFrameMessageManager);
     ok(cfmm, "Should have content messageManager");
 
     var didGetSyncMessage = false;
     function syncContinueTestFn() {
       didGetSyncMessage = true;
     }
--- a/dom/plugins/test/mochitest/test_privatemode_perwindowpb.xul
+++ b/dom/plugins/test/mochitest/test_privatemode_perwindowpb.xul
@@ -46,22 +46,17 @@ function runTestsCallback() {
   } catch (e) {
     exceptionThrown = true;
   }
   is(exceptionThrown, false, "Exception thrown getting private mode state.");
   is(state1, false, "Browser returned incorrect private mode state.");
   is(state2, false, "Browser returned incorrect private mode state.");
 
   // open a window with private mode and get the references of the elements.
-  var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIWebNavigation)
-                    .QueryInterface(Ci.nsIDocShellTreeItem)
-                    .rootTreeItem
-                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindow);
+  var mainWindow = window.document.docShell.rootTreeItem.domWindow;
   var contentPage = getRootDirectory(window.location.href) + "privatemode_perwindowpb.xul";
 
   function testOnWindow(aIsPrivate, aCallback) {
     var win = mainWindow.OpenBrowserWindow({private: aIsPrivate});
     whenDelayedStartupFinished(win, function () {
       win.addEventListener("DOMContentLoaded", function onInnerLoad() {
         if (win.content.location.href == "about:privatebrowsing") {
           win.gBrowser.loadURI(contentPage);
--- a/dom/security/test/general/browser_test_data_download.js
+++ b/dom/security/test/general/browser_test_data_download.js
@@ -4,18 +4,17 @@ const kTestPath = getRootDirectory(gTest
                   .replace("chrome://mochitests/content", "http://example.com")
 const kTestURI = kTestPath + "file_data_download.html";
 
 function addWindowListener(aURL, aCallback) {
   Services.wm.addListener({
     onOpenWindow(aXULWindow) {
       info("window opened, waiting for focus");
       Services.wm.removeListener(this);
-      var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                                .getInterface(Ci.nsIDOMWindow);
+      var domwindow = aXULWindow.docShell.domWindow;
       waitForFocus(function() {
         is(domwindow.document.location.href, aURL, "should have seen the right window open");
         aCallback(domwindow);
       }, domwindow);
     },
     onCloseWindow(aXULWindow) { },
   });
 }
--- a/dom/security/test/general/browser_test_data_text_csv.js
+++ b/dom/security/test/general/browser_test_data_text_csv.js
@@ -4,18 +4,17 @@ const kTestPath = getRootDirectory(gTest
                   .replace("chrome://mochitests/content", "http://example.com")
 const kTestURI = kTestPath + "file_data_text_csv.html";
 
 function addWindowListener(aURL, aCallback) {
   Services.wm.addListener({
     onOpenWindow(aXULWindow) {
       info("window opened, waiting for focus");
       Services.wm.removeListener(this);
-      var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                                .getInterface(Ci.nsIDOMWindow);
+      var domwindow = aXULWindow.docShell.domWindow;
       waitForFocus(function() {
         is(domwindow.document.location.href, aURL, "should have seen the right window open");
         aCallback(domwindow);
       }, domwindow);
     },
     onCloseWindow(aXULWindow) { },
   });
 }
--- a/dom/serviceworkers/test/test_privateBrowsing.html
+++ b/dom/serviceworkers/test/test_privateBrowsing.html
@@ -29,22 +29,17 @@ function testOnWindow(aIsPrivate, aCallb
 
     if (!aIsPrivate) {
       win.gBrowser.loadURI(contentPage);
     }
   }, {capture: true, once: true});
 }
 
 function setupWindow() {
-  mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                     .getInterface(Ci.nsIWebNavigation)
-                     .QueryInterface(Ci.nsIDocShellTreeItem)
-                     .rootTreeItem
-                     .QueryInterface(Ci.nsIInterfaceRequestor)
-                     .getInterface(Ci.nsIDOMWindow);
+  mainWindow = window.document.docShell.rootTreeItem.domWindow;
   runTest();
 }
 
 var wN;
 var registration;
 var wP;
 
 function testPrivateWindow() {
--- a/dom/tests/mochitest/beacon/test_beaconCookies.html
+++ b/dom/tests/mochitest/beacon/test_beaconCookies.html
@@ -30,22 +30,17 @@ function whenDelayedStartupFinished(aWin
     if (aWindow == aSubject) {
       Services.obs.removeObserver(observer, aTopic);
       setTimeout(aCallback, 0);
     }
   }, "browser-delayed-startup-finished");
 }
 
 function testOnWindow(options, callback) {
-  var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIWebNavigation)
-                         .QueryInterface(Ci.nsIDocShellTreeItem)
-                         .rootTreeItem
-                         .QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIDOMWindow);
+  var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 
   var win = mainWindow.OpenBrowserWindow(options);
   windowsToClose.push(win);
   whenDelayedStartupFinished(win, function() {
     callback(win);
   });
 };
 
--- a/dom/tests/mochitest/chrome/window_focus.xul
+++ b/dom/tests/mochitest/chrome/window_focus.xul
@@ -269,21 +269,17 @@ function checkSelection(node, testid)
   is(selection.focusNode, range.startContainer, testid + " selection focusNode");
   is(selection.focusOffset, range.startOffset, testid + " selection focusOffset");
   is(selection.anchorNode, range.endContainer, testid + " selection anchorNode");
   is(selection.anchorOffset, range.endOffset, testid + " selection anchorOffset");
 }
 
 function getTopWindow(win)
 {
-  return win.QueryInterface(Ci.nsIInterfaceRequestor).
-             getInterface(Ci.nsIWebNavigation).
-             QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem.
-             QueryInterface(Ci.nsIInterfaceRequestor).
-             getInterface(Ci.nsIDOMWindow);
+  return win.document.docShell.rootTreeItem.domWindow;
 }
 
 function mouseWillTriggerFocus(element)
 {
   if (!element) {
     return false;
   }
 
--- a/dom/tests/mochitest/localstorage/test_localStorageBasePrivateBrowsing_perwindowpb.html
+++ b/dom/tests/mochitest/localstorage/test_localStorageBasePrivateBrowsing_perwindowpb.html
@@ -10,22 +10,17 @@
 var mainWindow;
 
 var prefBranch = Cc["@mozilla.org/preferences-service;1"]
                    .getService(Ci.nsIPrefBranch);
 prefBranch.setIntPref("browser.startup.page", 0);
 prefBranch.setCharPref("browser.startup.homepage_override.mstone", "ignore");
 
 function startTest() {
-  mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                      .getInterface(Ci.nsIWebNavigation)
-                      .QueryInterface(Ci.nsIDocShellTreeItem)
-                      .rootTreeItem
-                      .QueryInterface(Ci.nsIInterfaceRequestor)
-                      .getInterface(Ci.nsIDOMWindow);
+  mainWindow = window.document.docShell.rootTreeItem.domWindow;
 
   doTest();
 }
 
 var contentPage = "http://mochi.test:8888/chrome/dom/tests/mochitest/localstorage/page_blank.html";
 
 function testOnWindow(aIsPrivate, aCallback) {
   var win = mainWindow.OpenBrowserWindow({private: aIsPrivate});
--- a/dom/tests/mochitest/localstorage/test_localStorageQuotaPrivateBrowsing_perwindowpb.html
+++ b/dom/tests/mochitest/localstorage/test_localStorageQuotaPrivateBrowsing_perwindowpb.html
@@ -156,22 +156,17 @@ function whenDelayedStartupFinished(aCal
 
     aSubject.addEventListener("DOMContentLoaded", function() {
       SimpleTest.executeSoon(function() { aCallback(aSubject); });
     }, {capture: true, once: true});
   }, "browser-delayed-startup-finished");
 }
 
 function testOnWindow(aIsPrivate, callback) {
-  var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIWebNavigation)
-                         .QueryInterface(Ci.nsIDocShellTreeItem)
-                         .rootTreeItem
-                         .QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIDOMWindow);
+  var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 
   mainWindow.openWebLinkIn(CONTENT_PAGE, "window", {
                                   private: aIsPrivate });
   whenDelayedStartupFinished(callback);
 };
 </script>
 </head>
 <body onload="startTest();">
--- a/dom/url/tests/browser_download_after_revoke.js
+++ b/dom/url/tests/browser_download_after_revoke.js
@@ -15,18 +15,17 @@ function test () {
 
 	  is(domwindow.document.location.href, "chrome://mozapps/content/downloads/unknownContentType.xul", "Download page appeared");
 
 	  domwindow.close();
           gBrowser.removeTab(gBrowser.selectedTab);
 	  finish();
         }
 
-        var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                                  .getInterface(Ci.nsIDOMWindow);
+        var domwindow = aXULWindow.docShell.domWindow;
         domwindow.addEventListener("load", downloadOnLoad, true);
       },
       onCloseWindow: function(aXULWindow) {},
     }
 
     Services.wm.addListener(listener);
 
     info("Creating BlobURL and clicking on a HTMLAnchorElement...");
--- a/dom/workers/test/test_sharedWorker_privateBrowsing.html
+++ b/dom/workers/test/test_sharedWorker_privateBrowsing.html
@@ -27,22 +27,17 @@ function testOnWindow(aIsPrivate, aCallb
 
     if (!aIsPrivate) {
       win.gBrowser.loadURI(contentPage);
     }
   }, {capture: true, once: true});
 }
 
 function setupWindow() {
-  mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                     .getInterface(Ci.nsIWebNavigation)
-                     .QueryInterface(Ci.nsIDocShellTreeItem)
-                     .rootTreeItem
-                     .QueryInterface(Ci.nsIInterfaceRequestor)
-                     .getInterface(Ci.nsIDOMWindow);
+  mainWindow = window.document.docShell.rootTreeItem.domWindow;
   runTest();
 }
 
 var wN;
 var wP;
 
 function doTests() {
   testOnWindow(false, function(aWin) {
--- a/editor/spellchecker/tests/test_bug1209414.html
+++ b/editor/spellchecker/tests/test_bug1209414.html
@@ -38,23 +38,18 @@ var script;
 
 var onSpellCheck =
   SpecialPowers.Cu.import(
     "resource://testing-common/AsyncSpellCheckTestHelper.jsm").onSpellCheck;
 
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(function() {
   script = SpecialPowers.loadChromeScript(function() {
-    var chromeWin = browserElement.ownerDocument.defaultView
-                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIWebNavigation)
-                    .QueryInterface(Ci.nsIDocShellTreeItem)
-                    .rootTreeItem
-                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindow)
+    var chromeWin = browserElement.ownerDocument.docShell
+                    .rootTreeItem.domWindow
                     .QueryInterface(Ci.nsIDOMChromeWindow);
     var contextMenu = chromeWin.document.getElementById("contentAreaContextMenu");
     contextMenu.addEventListener("popupshown",
                                  () => sendAsyncMessage("popupshown"));
 
     var dir = Cc["@mozilla.org/file/directory_service;1"]
                 .getService(Ci.nsIProperties)
                 .get("CurWorkD", Ci.nsIFile);
--- a/image/test/mochitest/test_bug1132427.html
+++ b/image/test/mochitest/test_bug1132427.html
@@ -48,22 +48,17 @@ function checkPixel(canvas, context, x1,
 }
 
 var iterationsLeft = 10;
 
 function continueTest() {
   // we need to drawWindow the chrome window so we can get a dump of the retained widget layers
   // if we have to repaint to fulfill this drawWindow request then it will be impossible to
   // observe the bug
-  var chromewin = SpecialPowers.wrap(win).QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
-                     .getInterface(SpecialPowers.Ci.nsIWebNavigation)
-                     .QueryInterface(SpecialPowers.Ci.nsIDocShellTreeItem)
-                     .rootTreeItem
-                     .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
-                     .getInterface(SpecialPowers.Ci.nsIDOMWindow);
+  var chromewin = SpecialPowers.wrap(win).document.docShell.rootTreeItem.domWindow;
 
   var el = window.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
   el.width = chromewin.innerWidth;
   el.height = chromewin.innerHeight;
   var ctx = el.getContext("2d");
   // pass the correct flags so we don't have to flush the retained layers
   SpecialPowers.wrap(ctx).drawWindow(chromewin, 0, 0, chromewin.innerWidth, chromewin.innerHeight, "rgba(0,0,0,0)",
     ctx.DRAWWINDOW_USE_WIDGET_LAYERS | ctx.DRAWWINDOW_DRAW_VIEW | ctx.DRAWWINDOW_DRAW_CARET);
--- a/js/xpconnect/tests/unit/test_xray_named_element_access.js
+++ b/js/xpconnect/tests/unit/test_xray_named_element_access.js
@@ -7,17 +7,17 @@ ChromeUtils.import("resource://gre/modul
 add_task(async function() {
   let webnav = Services.appShell.createWindowlessBrowser(false);
 
   let docShell = webnav.QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIDocShell);
 
   docShell.createAboutBlankContentViewer(null);
 
-  let window = webnav.getInterface(Ci.nsIDOMWindow);
+  let window = webnav.document.defaultView;
   let unwrapped = Cu.waiveXrays(window);
 
   window.document.body.innerHTML = '<div id="foo"></div>';
 
   equal(window.foo, undefined, "Should not have named X-ray property access");
   equal(typeof unwrapped.foo, "object", "Should always have non-X-ray named property access");
 
   webnav.close();
--- a/layout/forms/test/test_bug536567_perwindowpb.html
+++ b/layout/forms/test/test_bug536567_perwindowpb.html
@@ -124,21 +124,17 @@ function endTest() {
   }
 
   normalWindow.close();
   privateWindow.close();
   MockFilePicker.cleanup();
   SimpleTest.finish();
 }
 
-var mainWindow =
-  window.QueryInterface(Ci.nsIInterfaceRequestor).
-    getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShellTreeItem).
-    rootTreeItem.QueryInterface(Ci.nsIInterfaceRequestor).
-    getInterface(Ci.nsIDOMWindow);
+var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 var contentPage = "http://mochi.test:8888/chrome/layout/forms/test/bug536567_iframe.html";
 
 function whenDelayedStartupFinished(aWindow, aCallback) {
   Services.obs.addObserver(function observer(aSubject, aTopic) {
     if (aWindow == aSubject) {
       Services.obs.removeObserver(observer, aTopic);
       setTimeout(aCallback, 0);
     }
--- a/layout/tools/reftest/bootstrap.js
+++ b/layout/tools/reftest/bootstrap.js
@@ -13,20 +13,20 @@ function processTerminated() {
         Services.obs.removeObserver(observe, topic);
         resolve();
       }
     }, "ipc:content-shutdown");
   });
 }
 
 var WindowListener = {
-  onOpenWindow: function(win) {
+  onOpenWindow: function(xulWin) {
     Services.wm.removeListener(WindowListener);
 
-    win = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+    let win = xulWin.docShell.domWindow;
     win.addEventListener("load", function listener() {
       // Load into any existing windows.
       let windows = Services.wm.getEnumerator("navigator:browser");
       while (windows.hasMoreElements()) {
         win = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
         break;
       }
 
--- a/mobile/android/chrome/content/aboutAccounts.js
+++ b/mobile/android/chrome/content/aboutAccounts.js
@@ -299,23 +299,17 @@ document.addEventListener("DOMContentLoa
   var buttonOpenPrefs = document.getElementById("buttonOpenPrefs");
   buttonOpenPrefs.addEventListener("click", openPrefs);
 }, {capture: true, once: true});
 
 // This window is contained in a XUL <browser> element.  Return the
 // messageManager of that <browser> element, or null.
 function getBrowserMessageManager() {
   let browser = window
-        .QueryInterface(Ci.nsIInterfaceRequestor)
-        .getInterface(Ci.nsIWebNavigation)
-        .QueryInterface(Ci.nsIDocShellTreeItem)
-        .rootTreeItem
-        .QueryInterface(Ci.nsIInterfaceRequestor)
-        .getInterface(Ci.nsIDOMWindow)
-        .QueryInterface(Ci.nsIDOMChromeWindow)
+        .document.docShell.rootTreeItem.domWindow
         .BrowserApp
         .getBrowserForDocument(document);
   if (browser) {
     return browser.messageManager;
   }
   return null;
 }
 
--- a/mobile/android/chrome/content/aboutAddons.js
+++ b/mobile/android/chrome/content/aboutAddons.js
@@ -11,22 +11,17 @@ ChromeUtils.import("resource://gre/modul
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const AMO_ICON = "chrome://browser/skin/images/amo-logo.png";
 const UPDATE_INDICATOR = "chrome://browser/skin/images/extension-update.svg";
 
 var gStringBundle = Services.strings.createBundle("chrome://browser/locale/aboutAddons.properties");
 
 XPCOMUtils.defineLazyGetter(window, "gChromeWin", function() {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor)
-           .getInterface(Ci.nsIWebNavigation)
-           .QueryInterface(Ci.nsIDocShellTreeItem)
-           .rootTreeItem
-           .QueryInterface(Ci.nsIInterfaceRequestor)
-           .getInterface(Ci.nsIDOMWindow)
+  return window.document.docShell.rootTreeItem.domWindow
            .QueryInterface(Ci.nsIDOMChromeWindow);
 });
 ChromeUtils.defineModuleGetter(window, "Preferences",
                                "resource://gre/modules/Preferences.jsm");
 
 var ContextMenus = {
   target: null,
 
--- a/mobile/android/chrome/content/aboutLogins.js
+++ b/mobile/android/chrome/content/aboutLogins.js
@@ -3,22 +3,17 @@
 * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 ChromeUtils.import("resource://services-common/utils.js"); /* global: CommonUtils */
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/TelemetryStopwatch.jsm");
 
 XPCOMUtils.defineLazyGetter(window, "gChromeWin", () =>
-  window.QueryInterface(Ci.nsIInterfaceRequestor)
-    .getInterface(Ci.nsIWebNavigation)
-    .QueryInterface(Ci.nsIDocShellTreeItem)
-    .rootTreeItem
-    .QueryInterface(Ci.nsIInterfaceRequestor)
-    .getInterface(Ci.nsIDOMWindow)
+  window.document.docShell.rootTreeItem.domWindow
     .QueryInterface(Ci.nsIDOMChromeWindow));
 
 ChromeUtils.defineModuleGetter(this, "EventDispatcher",
                                "resource://gre/modules/Messaging.jsm");
 ChromeUtils.defineModuleGetter(this, "Snackbars", "resource://gre/modules/Snackbars.jsm");
 ChromeUtils.defineModuleGetter(this, "Prompt",
                                "resource://gre/modules/Prompt.jsm");
 
--- a/mobile/android/chrome/content/aboutPrivateBrowsing.js
+++ b/mobile/android/chrome/content/aboutPrivateBrowsing.js
@@ -4,22 +4,17 @@
 
 "use strict";
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 XPCOMUtils.defineLazyGetter(window, "gChromeWin", () =>
-  window.QueryInterface(Ci.nsIInterfaceRequestor)
-    .getInterface(Ci.nsIWebNavigation)
-    .QueryInterface(Ci.nsIDocShellTreeItem)
-    .rootTreeItem
-    .QueryInterface(Ci.nsIInterfaceRequestor)
-    .getInterface(Ci.nsIDOMWindow)
+  window.document.docShell.rootTreeItem.domWindow
     .QueryInterface(Ci.nsIDOMChromeWindow));
 
 document.addEventListener("DOMContentLoaded", function() {
     let BrowserApp = window.gChromeWin.BrowserApp;
 
     if (!PrivateBrowsingUtils.isContentWindowPrivate(window)) {
       document.body.setAttribute("class", "normal");
       document.getElementById("newPrivateTabLink").addEventListener("click", function() {
--- a/mobile/android/components/ContentPermissionPrompt.js
+++ b/mobile/android/components/ContentPermissionPrompt.js
@@ -46,22 +46,17 @@ ContentPermissionPrompt.prototype = {
       callback(/* allow */ false);
       return true;
     }
 
     return false;
   },
 
   getChromeWindow: function getChromeWindow(aWindow) {
-     let chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIWebNavigation)
-                            .QueryInterface(Ci.nsIDocShellTreeItem)
-                            .rootTreeItem
-                            .QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIDOMWindow)
+     let chromeWin = aWindow.document.docShell.rootTreeItem.domWindow
                             .QueryInterface(Ci.nsIDOMChromeWindow);
      return chromeWin;
   },
 
   getChromeForRequest: function getChromeForRequest(request) {
     if (request.window) {
       let requestingWindow = request.window.top;
       return this.getChromeWindow(requestingWindow).wrappedJSObject;
--- a/mobile/android/components/extensions/ext-tabs.js
+++ b/mobile/android/components/extensions/ext-tabs.js
@@ -1,19 +1,17 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 ChromeUtils.defineModuleGetter(this, "PromiseUtils",
                                "resource://gre/modules/PromiseUtils.jsm");
 
 const getBrowserWindow = window => {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDocShell)
-               .QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem
-               .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+  return window.document.docShell.rootTreeItem.domWindow;
 };
 
 let tabListener = {
   tabReadyInitialized: false,
   tabReadyPromises: new WeakMap(),
   initializingTabs: new WeakSet(),
 
   initTabReady() {
--- a/mobile/android/modules/WebrtcUI.jsm
+++ b/mobile/android/modules/WebrtcUI.jsm
@@ -278,22 +278,17 @@ var WebrtcUI = {
     } else {
       message = Strings.browser.GetStringFromName("getUserMedia.blockedCameraAndMicrophoneAccess");
     }
 
     DoorHanger.show(aWindow, message, "webrtc-blocked");
   },
 
   getChromeWindow: function getChromeWindow(aWindow) {
-     let chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIWebNavigation)
-                            .QueryInterface(Ci.nsIDocShellTreeItem)
-                            .rootTreeItem
-                            .QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIDOMWindow)
+     let chromeWin = aWindow.document.docShell.rootTreeItem.domWindow
                             .QueryInterface(Ci.nsIDOMChromeWindow);
      return chromeWin;
   },
 
   prompt: function prompt(aContentWindow, aCallID, aAudioRequested,
                           aVideoRequested, aDevices) {
     let audioDevices = [];
     let videoDevices = [];
--- a/mobile/android/modules/geckoview/GeckoViewUtils.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewUtils.jsm
@@ -254,17 +254,17 @@ var GeckoViewUtils = {
   /**
    * Return the outermost chrome DOM window (the XUL window) for a given DOM
    * window, in the parent process.
    *
    * @param aWin a DOM window.
    */
   getChromeWindow: function(aWin) {
     const docShell = this.getRootDocShell(aWin);
-    return docShell && docShell.getInterface(Ci.nsIDOMWindow);
+    return docShell && docShell.domWindow;
   },
 
   /**
    * Return the content frame message manager (aka the frame script global
    * object) for a given DOM window, in a child process.
    *
    * @param aWin a DOM window.
    */
--- a/mobile/android/tests/browser/chrome/test_awsy_lite.html
+++ b/mobile/android/tests/browser/chrome/test_awsy_lite.html
@@ -41,18 +41,18 @@
 
   function checkpoint(aName) {
     var mrm = Cc["@mozilla.org/memory-reporter-manager;1"].getService(Ci.nsIMemoryReporterManager);
     gResults.push( { name: aName, resident: mrm.resident } );
     info(`${aName} | Resident Memory: ${mrm.resident}`);
   }
 
   var browserListener = {
-    onOpenWindow: function(aWindow) {
-        var win = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+    onOpenWindow: function(aXulWin) {
+        var win = aXulWin.docShell.domWindow;
         win.addEventListener("UIReady", function(aEvent) {
             attachTo(win);
         }, {once: true});
     },
 
     onCloseWindow: function(aWindow) {
         detachFrom(aWindow);
     },
--- a/netwerk/test/browser/browser_NetUtil.js
+++ b/netwerk/test/browser/browser_NetUtil.js
@@ -67,18 +67,17 @@ function test_asyncFetchBadCert() {
 }
 
 function WindowListener(aURL, aCallback) {
   this.callback = aCallback;
   this.url = aURL;
 }
 WindowListener.prototype = {
   onOpenWindow: function(aXULWindow) {
-    var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                              .getInterface(Ci.nsIDOMWindow);
+    var domwindow = aXULWindow.docShell.domWindow;
     var self = this;
     domwindow.addEventListener("load", function() {
       if (domwindow.document.location.href != self.url)
         return;
 
       // Allow other window load listeners to execute before passing to callback
       executeSoon(function() {
         self.callback(domwindow);
--- a/security/manager/ssl/tests/mochitest/stricttransportsecurity/test_sts_privatebrowsing_perwindowpb.html
+++ b/security/manager/ssl/tests/mochitest/stricttransportsecurity/test_sts_privatebrowsing_perwindowpb.html
@@ -24,21 +24,17 @@
   ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
   ChromeUtils.import("resource://testing-common/ContentTask.jsm");
   ChromeUtils.import("resource://gre/modules/Services.jsm");
 
   // This is how many sub-tests (testframes) in each round.
   // When the round begins, this will be initialized.
   var testsleftinround = 0;
   var currentround = "";
-  var mainWindow =
-    window.QueryInterface(Ci.nsIInterfaceRequestor).
-    getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShellTreeItem).
-    rootTreeItem.QueryInterface(Ci.nsIInterfaceRequestor).
-    getInterface(Ci.nsIDOMWindow);
+  var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 
   SpecialPowers.Services.prefs.setIntPref("browser.startup.page", 0);
 
   var testframes = {
     samedom: {
       url: `http://example.com/${STSPATH}/verify.sjs`,
       expected: {plain: "SECURE", subdom: "SECURE", nosts: "INSECURE"}
     },
--- a/testing/mochitest/bootstrap.js
+++ b/testing/mochitest/bootstrap.js
@@ -59,18 +59,18 @@ var WindowListener = {
 
   tearDownWindow(win) {
     if (win.nativeConsole) {
       win.console = win.nativeConsole;
       win.nativeConsole = undefined;
     }
   },
 
-  onOpenWindow(win) {
-    win = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+  onOpenWindow(xulWin) {
+    let win = xulWin.docShell.domWindow;
 
     win.addEventListener("load", function() {
       if (win.document.documentElement.getAttribute("windowtype") == "navigator:browser") {
         WindowListener.setupWindow(win);
       }
     }, {once: true});
   }
 };
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -1410,22 +1410,17 @@ SpecialPowersAPI.prototype = {
                  .QueryInterface(Ci.nsIDocShell);
   },
   _getMUDV(window) {
     return this._getDocShell(window).contentViewer;
   },
   // XXX: these APIs really ought to be removed, they're not e10s-safe.
   // (also they're pretty Firefox-specific)
   _getTopChromeWindow(window) {
-    return window.QueryInterface(Ci.nsIInterfaceRequestor)
-                 .getInterface(Ci.nsIWebNavigation)
-                 .QueryInterface(Ci.nsIDocShellTreeItem)
-                 .rootTreeItem
-                 .QueryInterface(Ci.nsIInterfaceRequestor)
-                 .getInterface(Ci.nsIDOMWindow)
+    return window.document.docShell.rootTreeItem.domWindow
                  .QueryInterface(Ci.nsIDOMChromeWindow);
   },
   _getAutoCompletePopup(window) {
     return this._getTopChromeWindow(window).document
                                            .getElementById("PopupAutoComplete");
   },
   addAutoCompletePopupEventListener(window, eventname, listener) {
     this._getAutoCompletePopup(window).addEventListener(eventname,
--- a/toolkit/components/browser/nsWebBrowser.cpp
+++ b/toolkit/components/browser/nsWebBrowser.cpp
@@ -548,16 +548,24 @@ nsWebBrowser::GetDocument()
 
 nsPIDOMWindowOuter*
 nsWebBrowser::GetWindow()
 {
   return mDocShell ? mDocShell->GetWindow() : nullptr;
 }
 
 NS_IMETHODIMP
+nsWebBrowser::GetDomWindow(mozIDOMWindowProxy** aWindow)
+{
+  if (!mDocShell)
+    return NS_ERROR_NOT_INITIALIZED;
+  return mDocShell->GetDomWindow(aWindow);
+}
+
+NS_IMETHODIMP
 nsWebBrowser::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner)
 {
   NS_ENSURE_ARG_POINTER(aTreeOwner);
   *aTreeOwner = nullptr;
   if (mDocShellTreeOwner) {
     if (mDocShellTreeOwner->mTreeOwner) {
       *aTreeOwner = mDocShellTreeOwner->mTreeOwner;
     } else {
--- a/toolkit/components/extensions/ExtensionContent.jsm
+++ b/toolkit/components/extensions/ExtensionContent.jsm
@@ -916,18 +916,18 @@ var ExtensionContent = {
   },
 
   // Helpers
 
   * enumerateWindows(docShell) {
     let enum_ = docShell.getDocShellEnumerator(docShell.typeContent,
                                                docShell.ENUMERATE_FORWARDS);
 
-    for (let docShell of XPCOMUtils.IterSimpleEnumerator(enum_, Ci.nsIInterfaceRequestor)) {
+    for (let docShell of XPCOMUtils.IterSimpleEnumerator(enum_, Ci.nsIDocShell)) {
       try {
-        yield docShell.getInterface(Ci.nsIDOMWindow);
+        yield docShell.domWindow;
       } catch (e) {
         // This can fail if the docShell is being destroyed, so just
         // ignore the error.
       }
     }
   },
 };
--- a/toolkit/components/extensions/ExtensionParent.jsm
+++ b/toolkit/components/extensions/ExtensionParent.jsm
@@ -656,18 +656,17 @@ class ExtensionPageContextParent extends
     this.extension.views.add(this);
 
     extension.emit("extension-proxy-context-load", this);
   }
 
   // The window that contains this context. This may change due to moving tabs.
   get xulWindow() {
     let win = this.xulBrowser.ownerGlobal;
-    return win.document.docShell.rootTreeItem
-              .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+    return win.document.docShell.rootTreeItem.domWindow;
   }
 
   get currentWindow() {
     if (this.viewType !== "background") {
       return this.xulWindow;
     }
   }
 
--- a/toolkit/components/extensions/extension-process-script.js
+++ b/toolkit/components/extensions/extension-process-script.js
@@ -278,18 +278,18 @@ DocumentManager = {
 
   // Helpers
 
   * enumerateWindows(docShell) {
     if (docShell) {
       let enum_ = docShell.getDocShellEnumerator(docShell.typeContent,
                                                  docShell.ENUMERATE_FORWARDS);
 
-      for (let docShell of XPCOMUtils.IterSimpleEnumerator(enum_, Ci.nsIInterfaceRequestor)) {
-        yield docShell.getInterface(Ci.nsIDOMWindow);
+      for (let docShell of XPCOMUtils.IterSimpleEnumerator(enum_, Ci.nsIDocShell)) {
+        yield docShell.domWindow;
       }
     } else {
       for (let global of this.globals.keys()) {
         yield* this.enumerateWindows(global.docShell);
       }
     }
   },
 };
--- a/toolkit/components/passwordmgr/test/browser/browser_passwordmgr_switchtab.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_passwordmgr_switchtab.js
@@ -6,19 +6,18 @@ const PROMPT_URL = "chrome://global/cont
 
 add_task(async function test() {
   await new Promise(resolve => {
 
   let tab = BrowserTestUtils.addTab(gBrowser);
   isnot(tab, gBrowser.selectedTab, "New tab shouldn't be selected");
 
   let listener = {
-    onOpenWindow(window) {
-      var domwindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIDOMWindow);
+    onOpenWindow(xulWin) {
+      var domwindow = xulWin.docShell.domWindow;
       waitForFocus(() => {
         is(domwindow.document.location.href, PROMPT_URL, "Should have seen a prompt window");
         is(domwindow.args.promptType, "promptUserAndPass", "Should be an authenticate prompt");
 
         is(gBrowser.selectedTab, tab, "Should have selected the new tab");
 
         domwindow.document.documentElement.cancelDialog();
       }, domwindow);
--- a/toolkit/components/passwordmgr/test/chrome/test_privbrowsing_perwindowpb.html
+++ b/toolkit/components/passwordmgr/test/chrome/test_privbrowsing_perwindowpb.html
@@ -189,22 +189,17 @@ function checkTest() {
       break;
 
     default:
       ok(false, "Unexpected call to checkTest for test #" + testNum);
 
   }
 }
 
-var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIWebNavigation)
-                    .QueryInterface(Ci.nsIDocShellTreeItem)
-                    .rootTreeItem
-                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindow);
+var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 var contentPage = "http://mochi.test:8888/chrome/toolkit/components/passwordmgr/test/chrome/privbrowsing_perwindowpb_iframe.html";
 var testWindows = [];
 
 function whenDelayedStartupFinished(aWindow, aCallback) {
   Services.obs.addObserver(function obs(aSubject, aTopic) {
     if (aWindow == aSubject) {
       Services.obs.removeObserver(obs, aTopic);
       setTimeout(aCallback, 0);
--- a/toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
+++ b/toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
@@ -178,18 +178,17 @@ const backgroundPageThumbsContent = {
       capture.canvasDrawTime = new Date() - canvasDrawDate;
 
       finalCanvas.toBlob(blob => {
         capture.imageBlob = new Blob([blob]);
         // Load about:blank to finish the capture and wait for onStateChange.
         this._loadAboutBlank();
       });
     };
-    let win = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                      .getInterface(Ci.nsIDOMWindow);
+    let win = docShell.domWindow;
     win.requestIdleCallback(() => doCapture().catch(ex => this._failCurrentCapture(ex.message)));
   },
 
   _finishCurrentCapture() {
     let capture = this._currentCapture;
     let fileReader = new FileReader();
     fileReader.onloadend = () => {
       sendAsyncMessage("BackgroundPageThumbs:didCapture", {
--- a/toolkit/components/url-classifier/tests/mochitest/test_advisory_link.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_advisory_link.html
@@ -15,22 +15,17 @@
 </div>
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://testing-common/TestUtils.jsm");
 ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
 
-var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIWebNavigation)
-                    .QueryInterface(Ci.nsIDocShellTreeItem)
-                    .rootTreeItem
-                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindow);
+var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 
 var testDatas = [
   { url: "itisaphishingsite.org/phishing.html",
     list: "mochi1-phish-simple",
     provider: "google",
   },
 
   { url: "fakeitisaphishingsite.org/phishing.html",
--- a/toolkit/components/url-classifier/tests/mochitest/test_donottrack.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_donottrack.html
@@ -9,22 +9,17 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
 
-var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIWebNavigation)
-                    .QueryInterface(Ci.nsIDocShellTreeItem)
-                    .rootTreeItem
-                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindow);
+var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 
 const tests = [
   // DNT turned on and TP turned off, DNT signal sent in both private browsing
   // and normal mode.
   {
     setting:  {dntPref: true, tpPref: false, tppbPref: false, pbMode: true},
     expected: {dnt: "1"},
   },
--- a/toolkit/components/url-classifier/tests/mochitest/test_privatebrowsing_trackingprotection.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_privatebrowsing_trackingprotection.html
@@ -11,22 +11,17 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
 
-var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIWebNavigation)
-                    .QueryInterface(Ci.nsIDocShellTreeItem)
-                    .rootTreeItem
-                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindow);
+var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 var contentPage = "http://www.itisatrap.org/tests/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedPBFrame.html";
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://testing-common/UrlClassifierTestUtils.jsm");
 ChromeUtils.import("resource://testing-common/TestUtils.jsm");
 
 function testOnWindow(aPrivate, aCallback) {
   var win = mainWindow.OpenBrowserWindow({private: aPrivate});
--- a/toolkit/components/url-classifier/tests/mochitest/test_reporturl.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_reporturl.html
@@ -16,22 +16,17 @@
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
 ChromeUtils.import("resource://testing-common/ContentTask.jsm");
 ChromeUtils.import("resource://testing-common/TestUtils.jsm");
 
-var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIWebNavigation)
-                    .QueryInterface(Ci.nsIDocShellTreeItem)
-                    .rootTreeItem
-                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindow);
+var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 const SJS = "mochi.test:8888/chrome/toolkit/components/url-classifier/tests/mochitest/report.sjs";
 const BASE_URL = "http://" + SJS + "?";
 
 var pushPrefs = (...p) => SpecialPowers.pushPrefEnv({set: p});
 
 function addUrlToDB(list, url) {
   let testData = [{ db: list, url}];
 
--- a/toolkit/components/url-classifier/tests/mochitest/test_threathit_report.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_threathit_report.html
@@ -16,22 +16,17 @@
 <pre id="test">
 
 <script src="head.js"></script>
 <script class="testbody" type="text/javascript">
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://testing-common/BrowserTestUtils.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
-var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIWebNavigation)
-                    .QueryInterface(Ci.nsIDocShellTreeItem)
-                    .rootTreeItem
-                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindow);
+var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 
 var listmanager = Cc["@mozilla.org/url-classifier/listmanager;1"].
                     getService(Ci.nsIUrlListManager);
 const SJS = "mochi.test:8888/chrome/toolkit/components/url-classifier/tests/mochitest/threathit.sjs";
 
 function hash(str) {
   function bytesFromString(str1) {
     let converter =
--- a/toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_bug1157081.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_bug1157081.html
@@ -11,22 +11,17 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
 
-var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIWebNavigation)
-                    .QueryInterface(Ci.nsIDocShellTreeItem)
-                    .rootTreeItem
-                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindow);
+var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 var contentPage = "chrome://mochitests/content/chrome/toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedPBFrame.html";
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://testing-common/UrlClassifierTestUtils.jsm");
 ChromeUtils.import("resource://testing-common/TestUtils.jsm");
 
 function testOnWindow(aCallback) {
   var win = mainWindow.OpenBrowserWindow();
--- a/toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_bug1312515.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_bug1312515.html
@@ -11,22 +11,17 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
 
-var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIWebNavigation)
-                       .QueryInterface(Ci.nsIDocShellTreeItem)
-                       .rootTreeItem
-                       .QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindow);
+var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 var contentPage = "http://www.itisatrap.org/tests/toolkit/components/url-classifier/tests/mochitest/trackingRequest.html";
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://testing-common/UrlClassifierTestUtils.jsm");
 ChromeUtils.import("resource://testing-common/TestUtils.jsm");
 
 function testOnWindow(aPrivate, aCallback) {
   var win = mainWindow.OpenBrowserWindow({private: aPrivate});
--- a/toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_whitelist.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_whitelist.html
@@ -11,22 +11,17 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script class="testbody" type="text/javascript">
 
-var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIWebNavigation)
-                    .QueryInterface(Ci.nsIDocShellTreeItem)
-                    .rootTreeItem
-                    .QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIDOMWindow);
+var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 var contentPage1 = "http://www.itisatrap.org/tests/toolkit/components/url-classifier/tests/mochitest/whitelistFrame.html";
 var contentPage2 = "http://example.com/tests/toolkit/components/url-classifier/tests/mochitest/whitelistFrame.html";
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://testing-common/UrlClassifierTestUtils.jsm");
 ChromeUtils.import("resource://testing-common/TestUtils.jsm");
 
 function testOnWindow(contentPage, aCallback) {
--- a/toolkit/content/aboutTelemetry.js
+++ b/toolkit/content/aboutTelemetry.js
@@ -124,22 +124,17 @@ function sectionalizeObject(obj) {
   }
   return map;
 }
 
 /**
  * Obtain the main DOMWindow for the current context.
  */
 function getMainWindow() {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIWebNavigation)
-               .QueryInterface(Ci.nsIDocShellTreeItem)
-               .rootTreeItem
-               .QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIDOMWindow);
+  return window.document.docShell.rootTreeItem.domWindow;
 }
 
 /**
  * Obtain the DOMWindow that can open a preferences pane.
  *
  * This is essentially "get the browser chrome window" with the added check
  * that the supposed browser chrome window is capable of opening a preferences
  * pane.
--- a/toolkit/modules/BrowserUtils.jsm
+++ b/toolkit/modules/BrowserUtils.jsm
@@ -419,19 +419,17 @@ var BrowserUtils = {
   /**
    * Retrieve the root window object (i.e. the top-most content global) for a
    * specific docShell object.
    *
    * @param  {nsIDocShell} docShell
    * @return {nsIDOMWindow}
    */
   getRootWindow(docShell) {
-    return docShell.QueryInterface(Ci.nsIDocShellTreeItem)
-      .sameTypeRootTreeItem.QueryInterface(Ci.nsIInterfaceRequestor)
-      .getInterface(Ci.nsIDOMWindow);
+    return docShell.sameTypeRootTreeItem.domWindow;
   },
 
   /**
    * Trim the selection text to a reasonable size and sanitize it to make it
    * safe for search query input.
    *
    * @param aSelection
    *        The selection text to trim.
--- a/toolkit/modules/Finder.jsm
+++ b/toolkit/modules/Finder.jsm
@@ -465,17 +465,17 @@ Finder.prototype = {
       current: 0,
       _currentFound: false
     };
   },
 
   _getWindow() {
     if (!this._docShell)
       return null;
-    return this._docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+    return this._docShell.domWindow;
   },
 
   /**
    * Get the bounding selection rect in CSS px relative to the origin of the
    * top-level content document.
    */
   _getResultRect() {
     let topWin = this._getWindow();
--- a/toolkit/modules/HiddenFrame.jsm
+++ b/toolkit/modules/HiddenFrame.jsm
@@ -54,18 +54,17 @@ HiddenFrame.prototype = {
     return this._deferred.promise;
   },
 
   /**
    * Fetch a sync ref to the window inside the frame (needed for the add-on SDK).
    */
   getWindow() {
     this.get();
-    this._browser.QueryInterface(Ci.nsIInterfaceRequestor);
-    return this._browser.getInterface(Ci.nsIDOMWindow);
+    return this._browser.document.ownerGlobal;
   },
 
 
   destroy() {
     if (this._browser) {
       if (this._listener) {
         this._webProgress.removeProgressListener(this._listener);
         this._listener = null;
--- a/toolkit/modules/addons/WebNavigationContent.js
+++ b/toolkit/modules/addons/WebNavigationContent.js
@@ -8,18 +8,17 @@ ChromeUtils.import("resource://gre/modul
 ChromeUtils.defineModuleGetter(this, "WebNavigationFrames",
                                "resource://gre/modules/WebNavigationFrames.jsm");
 
 function getDocShellOuterWindowId(docShell) {
   if (!docShell) {
     return undefined;
   }
 
-  return docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                 .getInterface(Ci.nsIDOMWindow)
+  return docShell.domWindow
                  .windowUtils
                  .outerWindowID;
 }
 
 function loadListener(event) {
   let document = event.target;
   let window = document.defaultView;
   let url = document.documentURI;
@@ -115,18 +114,17 @@ var FormSubmitListener = {
 var WebProgressListener = {
   init: function() {
     // This WeakMap (DOMWindow -> nsIURI) keeps track of the pathname and hash
     // of the previous location for all the existent docShells.
     this.previousURIMap = new WeakMap();
 
     // Populate the above previousURIMap by iterating over the docShells tree.
     for (let currentDocShell of WebNavigationFrames.iterateDocShellTree(docShell)) {
-      let win = currentDocShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                               .getInterface(Ci.nsIDOMWindow);
+      let win = currentDocShell.domWindow;
       let {currentURI} = currentDocShell.QueryInterface(Ci.nsIWebNavigation);
 
       this.previousURIMap.set(win, currentURI);
     }
 
     // This WeakSet of DOMWindows keeps track of the attempted refresh.
     this.refreshAttemptedDOMWindows = new WeakSet();
 
--- a/toolkit/modules/addons/WebNavigationFrames.jsm
+++ b/toolkit/modules/addons/WebNavigationFrames.jsm
@@ -4,27 +4,16 @@
 
 "use strict";
 
 const EXPORTED_SYMBOLS = ["WebNavigationFrames"];
 
 /* exported WebNavigationFrames */
 
 /**
- * Retrieve the DOMWindow associated to the docShell passed as parameter.
- *
- * @param    {nsIDocShell}  docShell - the docShell that we want to get the DOMWindow from.
- * @returns  {nsIDOMWindow}          - the DOMWindow associated to the docShell.
- */
-function docShellToWindow(docShell) {
-  return docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                 .getInterface(Ci.nsIDOMWindow);
-}
-
-/**
  * The FrameDetail object which represents a frame in WebExtensions APIs.
  *
  * @typedef  {Object}  FrameDetail
  * @inner
  * @property {number}  frameId        - Represents the numeric id which identify the frame in its tab.
  * @property {number}  parentFrameId  - Represents the numeric id which identify the parent frame.
  * @property {string}  url            - Represents the current location URL loaded in the frame.
  * @property {boolean} errorOccurred  - Indicates whether an error is occurred during the last load
@@ -36,17 +25,17 @@ function docShellToWindow(docShell) {
  *
  * @param   {nsIDocShell} docShell - the root docShell object
  */
 function* iterateDocShellTree(docShell) {
   let docShellsEnum = docShell.getDocShellEnumerator(
     docShell.typeContent, docShell.ENUMERATE_FORWARDS);
 
   while (docShellsEnum.hasMoreElements()) {
-    yield docShellsEnum.getNext();
+    yield docShellsEnum.getNext().QueryInterface(Ci.nsIDocShell);
   }
 }
 
 /**
  * Returns the frame ID of the given window. If the window is the
  * top-level content window, its frame ID is 0. Otherwise, its frame ID
  * is its outer window ID.
  *
@@ -76,28 +65,27 @@ function getParentFrameId(window) {
   return getFrameId(window.parent);
 }
 
 function getDocShellFrameId(docShell) {
   if (!docShell) {
     return undefined;
   }
 
-  return getFrameId(docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIDOMWindow));
+  return getFrameId(docShell.domWindow);
 }
 
 /**
  * Convert a docShell object into its internal FrameDetail representation.
  *
  * @param    {nsIDocShell} docShell - the docShell object to be converted into a FrameDetail JSON object.
  * @returns  {FrameDetail} the FrameDetail JSON object which represents the docShell.
  */
 function convertDocShellToFrameDetail(docShell) {
-  let window = docShellToWindow(docShell);
+  let window = docShell.domWindow;
 
   return {
     frameId: getFrameId(window),
     parentFrameId: getParentFrameId(window),
     url: window.location.href,
   };
 }
 
@@ -108,17 +96,17 @@ function convertDocShellToFrameDetail(do
  * @param  {number}      frameId - the frame ID of the frame to retrieve, as
  *                                 described in getFrameId.
  * @param   {nsIDocShell} rootDocShell - the root docShell object
  * @returns {nsIDocShell?} the docShell with the given frameId, or null
  *                         if no match.
  */
 function findDocShell(frameId, rootDocShell) {
   for (let docShell of iterateDocShellTree(rootDocShell)) {
-    if (frameId == getFrameId(docShellToWindow(docShell))) {
+    if (frameId == getFrameId(docShell.domWindow)) {
       return docShell;
     }
   }
 
   return null;
 }
 
 var WebNavigationFrames = {
--- a/toolkit/mozapps/downloads/nsHelperAppDlg.js
+++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js
@@ -151,20 +151,17 @@ nsUnknownContentTypeDialog.prototype = {
   // When opening from new tab, if tab closes while dialog is opening,
   // (which is a race condition on the XUL file being cached and the timer
   // in nsExternalHelperAppService), the dialog gets a blur and doesn't
   // activate the OK button.  So we wait a bit before doing opening it.
   reallyShow() {
     try {
       let ir = this.mContext.QueryInterface(Ci.nsIInterfaceRequestor);
       let docShell = ir.getInterface(Ci.nsIDocShell);
-      let rootWin = docShell.QueryInterface(Ci.nsIDocShellTreeItem)
-                                 .rootTreeItem
-                                 .QueryInterface(Ci.nsIInterfaceRequestor)
-                                 .getInterface(Ci.nsIDOMWindow);
+      let rootWin = docShell.rootTreeItem.domWindow;
       this.mDialog = Services.ww.openWindow(rootWin,
                                             "chrome://mozapps/content/downloads/unknownContentType.xul",
                                             null,
                                             "chrome,centerscreen,titlebar,dialog=yes,dependent",
                                             null);
     } catch (ex) {
       // The containing window may have gone away.  Break reference
       // cycles and stop doing the download.
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -273,22 +273,17 @@ function isDiscoverEnabled() {
 
   return true;
 }
 
 /**
  * Obtain the main DOMWindow for the current context.
  */
 function getMainWindow() {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIWebNavigation)
-               .QueryInterface(Ci.nsIDocShellTreeItem)
-               .rootTreeItem
-               .QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIDOMWindow);
+  return window.document.docShell.rootTreeItem.domWindow;
 }
 
 function getBrowserElement() {
   return window.QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIDocShell)
                .chromeEventHandler;
 }
 
@@ -1905,18 +1900,17 @@ var gHeader = {
     var docshellItem = window.QueryInterface(Ci.nsIInterfaceRequestor)
                              .getInterface(Ci.nsIWebNavigation)
                              .QueryInterface(Ci.nsIDocShellTreeItem);
 
     // If there is no outer frame then make the buttons visible
     if (docshellItem.rootTreeItem == docshellItem)
       return true;
 
-    var outerWin = docshellItem.rootTreeItem.QueryInterface(Ci.nsIInterfaceRequestor)
-                                            .getInterface(Ci.nsIDOMWindow);
+    var outerWin = docshellItem.rootTreeItem.domWindow;
     var outerDoc = outerWin.document;
     var node = outerDoc.getElementById("back-button");
     // If the outer frame has no back-button then make the buttons visible
     if (!node)
       return true;
 
     // If the back-button or any of its parents are hidden then make the buttons
     // visible
--- a/toolkit/mozapps/extensions/test/browser/head.js
+++ b/toolkit/mozapps/extensions/test/browser/head.js
@@ -449,21 +449,20 @@ function restart_manager(aManagerWindow,
 
   return close_manager(aManagerWindow)
     .then(() => open_manager(aView, aCallback, aLoadCallback));
 }
 
 function wait_for_window_open(aCallback) {
   let p = new Promise(resolve => {
     Services.wm.addListener({
-      onOpenWindow(aWindow) {
+      onOpenWindow(aXulWin) {
         Services.wm.removeListener(this);
 
-        let domwindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                               .getInterface(Ci.nsIDOMWindow);
+        let domwindow = aXulWin.docShell.domWindow;
         domwindow.addEventListener("load", function() {
           executeSoon(function() {
             resolve(domwindow);
           });
         }, {once: true});
       },
 
       onCloseWindow(aWindow) {
--- a/toolkit/mozapps/extensions/test/xpinstall/head.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/head.js
@@ -316,19 +316,18 @@ var Harness = {
       });
       this.expectingCancelled = false;
       this.endTest();
     }
   },
 
   // nsIWindowMediatorListener
 
-  onOpenWindow(window) {
-    var domwindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                          .getInterface(Ci.nsIDOMWindow);
+  onOpenWindow(xulWin) {
+    var domwindow = xulWin.docShell.domWindow;
     var self = this;
     waitForFocus(function() {
       self.windowReady(domwindow);
     }, domwindow);
   },
 
   onCloseWindow(window) {
   },
--- a/widget/headless/tests/test_headless.js
+++ b/widget/headless/tests/test_headless.js
@@ -32,18 +32,17 @@ function loadContentWindow(webNavigation
           return;
         }
         // Ignore events that don't change the document
         if (flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
           return;
         }
         let docShell = webNavigation.QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIDocShell);
-        let contentWindow = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIDOMWindow);
+        let contentWindow = docShell.domWindow;
         webProgress.removeProgressListener(progressListener);
         progressListeners.delete(progressListener);
         contentWindow.addEventListener("load", (event) => {
           resolve(contentWindow);
         }, { once: true });
       },
       QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener",
                                              "nsISupportsWeakReference"])
--- a/widget/tests/test_bug593307.xul
+++ b/widget/tests/test_bug593307.xul
@@ -24,22 +24,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 SimpleTest.waitForExplicitFinish();
 
 function finish() {
   offscreenWindow.close();
   SimpleTest.finish();
 }
 
-var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIWebNavigation)
-                       .QueryInterface(Ci.nsIDocShellTreeItem)
-                       .rootTreeItem
-                       .QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDOMWindow);
+var mainWindow = window.document.docShell.rootTreeItem.domWindow;
 
 var offscreenWindow = mainWindow.openDialog("window_bug593307_offscreen.xul", "",
                                             "dialog=no,chrome,width=200,height=200,screenX=-3000,screenY=-3000",
                                             SimpleTest, finish);
 
 ]]>
 </script>