Bug 1463291: Move docShell getter from Document to Window. r=bz
authorKris Maglione <maglione.k@gmail.com>
Mon, 21 May 2018 16:58:23 -0700
changeset 428891 544320932f97d62f477bedd6296690fb164b846f
parent 428890 60c1c783f5e100e1e43b09be2f11b4d1d0b82bdf
child 428892 0462ba95cb8464436526a35551170f3252451c22
push id34350
push userncsoregi@mozilla.com
push dateSun, 29 Jul 2018 09:46:15 +0000
treeherdermozilla-central@0be4463d2915 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1463291
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 1463291: Move docShell getter from Document to Window. r=bz DocShells are associated with outer DOM Windows, rather than Documents, so having the getter on the document is a bit odd to begin with. But it's also considerably less convenient, since most of the times when we want a docShell from JS, we're dealing most directly with a window, and have to detour through the document to get it. MozReview-Commit-ID: LUj1H9nG3QL
accessible/tests/mochitest/common.js
browser/base/content/browser.js
browser/base/content/test/about/browser_aboutCertError.js
browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
browser/base/content/test/general/browser_e10s_about_page_triggeringprincipal.js
browser/base/content/test/static/browser_parsable_css.js
browser/components/customizableui/test/browser_panelUINotifications_fullscreen_noAutoHideToolbar.js
browser/components/extensions/parent/ext-browser.js
browser/components/feeds/WebContentConverter.js
browser/components/nsBrowserContentHandler.js
browser/components/privatebrowsing/test/browser/browser_oa_private_browsing_window.js
browser/components/search/content/searchReset.js
browser/components/sessionstore/content/aboutSessionRestore.js
browser/components/syncedtabs/util.js
browser/modules/ClickEventHandler.jsm
browser/modules/ExtensionsUI.jsm
browser/modules/NetErrorContent.jsm
browser/modules/PageStyleHandler.jsm
browser/modules/test/browser/contentSearch.js
devtools/client/debugger/test/mochitest/head.js
devtools/client/framework/devtools-browser.js
devtools/client/jsonview/test/browser_json_refresh.js
devtools/client/responsive.html/utils/window.js
devtools/client/webconsole/test/fixtures/stub-generators/head.js
devtools/server/actors/targets/webextension.js
devtools/shared/webconsole/test/test_cached_messages.html
docshell/test/chrome/test_docRedirect.xul
docshell/test/chrome/test_private_hidden_window.html
docshell/test/navigation/file_triggeringprincipal_subframe_nav.html
docshell/test/navigation/test_triggeringprincipal_iframe_iframe_window_open.html
docshell/test/navigation/test_triggeringprincipal_parent_iframe_window_open.html
docshell/test/navigation/test_triggeringprincipal_window_open.html
docshell/test/test_forceinheritprincipal_overrule_owner.html
dom/base/test/chrome/cpows_parent.xul
dom/base/test/test_bug513194.html
dom/html/test/browser_fullscreen-api-keys.js
dom/html/test/browser_fullscreen-contextmenu-esc.js
dom/plugins/test/mochitest/test_privatemode_perwindowpb.xul
dom/serviceworkers/test/fetch/hsts/realindex.html
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/webidl/Document.webidl
dom/webidl/Window.webidl
dom/workers/test/test_sharedWorker_privateBrowsing.html
editor/spellchecker/tests/test_bug1209414.html
image/test/mochitest/test_bug1132427.html
layout/base/tests/chrome/printpreview_bug396024_helper.xul
layout/base/tests/chrome/printpreview_bug482976_helper.xul
layout/base/tests/chrome/printpreview_helper.xul
layout/base/tests/chrome/test_bug420499.xul
layout/forms/test/test_bug536567_perwindowpb.html
layout/style/test/test_bug413958.html
layout/style/test/test_css_parse_error_smoketest.html
layout/style/test/test_parser_diagnostics_unprintables.html
layout/tools/reftest/manifest.jsm
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/ContentDispatchChooser.js
mobile/android/components/ContentPermissionPrompt.js
mobile/android/components/extensions/ext-tabs.js
mobile/android/modules/WebrtcUI.jsm
netwerk/test/browser/browser_about_cache.js
security/manager/ssl/tests/mochitest/stricttransportsecurity/test_sts_privatebrowsing_perwindowpb.html
testing/specialpowers/content/specialpowersAPI.js
toolkit/components/extensions/ExtensionCommon.jsm
toolkit/components/extensions/ExtensionPageChild.jsm
toolkit/components/extensions/ExtensionParent.jsm
toolkit/components/extensions/extension-process-script.js
toolkit/components/extensions/parent/ext-tabs-base.js
toolkit/components/passwordmgr/test/chrome/test_privbrowsing_perwindowpb.html
toolkit/components/search/nsSearchService.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/content/tests/browser/browser_saveImageURL.js
toolkit/modules/WebChannelContent.jsm
toolkit/mozapps/extensions/content/extensions.js
widget/tests/test_bug593307.xul
widget/tests/test_bug760802.xul
widget/tests/test_taskbar_progress.xul
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -852,17 +852,17 @@ function shortenString(aString, aMaxLeng
 
 // //////////////////////////////////////////////////////////////////////////////
 // General Utils
 // //////////////////////////////////////////////////////////////////////////////
 /**
  * Return main chrome window (crosses chrome boundary)
  */
 function getMainChromeWindow(aWindow) {
-  return aWindow.document.docShell.rootTreeItem.domWindow;
+  return aWindow.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,18 +7075,17 @@ var MailIntegration = {
 };
 
 function BrowserOpenAddonsMgr(aView) {
   return new Promise(resolve => {
     let emWindow;
     let browserWindow;
 
     var receivePong = function(aSubject, aTopic, aData) {
-      let browserWin = aSubject.document.docShell
-                               .rootTreeItem.domWindow;
+      let browserWin = aSubject.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/about/browser_aboutCertError.js
+++ b/browser/base/content/test/about/browser_aboutCertError.js
@@ -297,26 +297,27 @@ add_task(async function checkAdvancedDet
       let el = doc.getElementById("errorCode");
       return { textContent: el.textContent, tagName: el.tagName };
     });
     is(message.textContent, "SEC_ERROR_EXPIRED_CERTIFICATE",
        "Correct error message found");
     is(message.tagName, "a", "Error message is a link");
 
     message = await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
-      let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
+      let win = frame ? content.document.querySelector("iframe").contentWindow : content;
+      let doc = win.document;
 
       let errorCode = doc.getElementById("errorCode");
       errorCode.click();
       let div = doc.getElementById("certificateErrorDebugInformation");
       let text = doc.getElementById("certificateErrorText");
 
       let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
                        .getService(Ci.nsISerializationHelper);
-      let serializable =  doc.docShell.failedChannel.securityInfo
+      let serializable =  win.docShell.failedChannel.securityInfo
                                       .QueryInterface(Ci.nsITransportSecurityInfo)
                                       .QueryInterface(Ci.nsISerializable);
       let serializedSecurityInfo = serhelper.serializeToString(serializable);
       return {
         divDisplay: content.getComputedStyle(div).display,
         text: text.textContent,
         securityInfoAsString: serializedSecurityInfo
       };
@@ -383,26 +384,27 @@ add_task(async function checkAdvancedDet
        "Correct error message found");
     is(message.ecTagName, "a", "Error message is a link");
     const url = badStsUri.prePath.slice(badStsUri.prePath.indexOf(".") + 1);
     is(message.cdlTextContent, url,
        "Correct cert_domain_link contents found");
     is(message.cdlTagName, "a", "cert_domain_link is a link");
 
     message = await ContentTask.spawn(browser, {frame: useFrame}, async function({frame}) {
-      let doc = frame ? content.document.querySelector("iframe").contentDocument : content.document;
+      let win = frame ? content.document.querySelector("iframe").contentWindow : content;
+      let doc = win.document;
 
       let errorCode = doc.getElementById("errorCode");
       errorCode.click();
       let div = doc.getElementById("certificateErrorDebugInformation");
       let text = doc.getElementById("certificateErrorText");
 
       let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
                        .getService(Ci.nsISerializationHelper);
-      let serializable =  doc.docShell.failedChannel.securityInfo
+      let serializable =  win.docShell.failedChannel.securityInfo
                                       .QueryInterface(Ci.nsITransportSecurityInfo)
                                       .QueryInterface(Ci.nsISerializable);
       let serializedSecurityInfo = serhelper.serializeToString(serializable);
       return {
         divDisplay: content.getComputedStyle(div).display,
         text: text.textContent,
         securityInfoAsString: serializedSecurityInfo
       };
--- a/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
+++ b/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
@@ -23,18 +23,17 @@ function frameScript() {
   });
   content.document.addEventListener("fullscreenchange", () => {
     sendAsyncMessage("Test:FullscreenChanged", {
       inDOMFullscreen: !!content.document.fullscreenElement,
       inFullscreen: content.fullScreen
     });
   });
   function waitUntilActive() {
-    let doc = content.document;
-    if (doc.docShell.isActive && doc.hasFocus()) {
+    if (docShell.isActive && content.document.hasFocus()) {
       sendAsyncMessage("Test:Activated");
     } else {
       setTimeout(waitUntilActive, 10);
     }
   }
   waitUntilActive();
 }
 
--- a/browser/base/content/test/general/browser_e10s_about_page_triggeringprincipal.js
+++ b/browser/base/content/test/general/browser_e10s_about_page_triggeringprincipal.js
@@ -16,17 +16,17 @@ add_task(async function test_principal_c
   await kAboutPagesRegistered;
   await BrowserTestUtils.withNewTab("about:test-about-principal-parent", async function(browser) {
     let loadPromise = BrowserTestUtils.browserLoaded(browser, false, "about:test-about-principal-child");
     let myLink = browser.contentDocument.getElementById("aboutchildprincipal");
     myLink.click();
     await loadPromise;
 
     await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
-      let channel = content.document.docShell.currentDocumentChannel;
+      let channel = content.docShell.currentDocumentChannel;
       is(channel.originalURI.asciiSpec,
          "about:test-about-principal-child",
          "sanity check - make sure we test the principal for the correct URI");
 
       let triggeringPrincipal = channel.loadInfo.triggeringPrincipal;
       ok(Services.scriptSecurityManager.isSystemPrincipal(triggeringPrincipal),
          "loading about: from privileged page must have a triggering of System");
 
@@ -52,17 +52,17 @@ add_task(async function test_principal_c
     // simulate ctrl+click
     BrowserTestUtils.synthesizeMouseAtCenter("#aboutchildprincipal",
                                              { ctrlKey: true, metaKey: true },
                                              gBrowser.selectedBrowser);
     let tab = await loadPromise;
     gBrowser.selectTabAtIndex(2);
 
     await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
-      let channel = content.document.docShell.currentDocumentChannel;
+      let channel = content.docShell.currentDocumentChannel;
       is(channel.originalURI.asciiSpec,
          "about:test-about-principal-child",
          "sanity check - make sure we test the principal for the correct URI");
 
       let triggeringPrincipal = channel.loadInfo.triggeringPrincipal;
       ok(Services.scriptSecurityManager.isSystemPrincipal(triggeringPrincipal),
          "loading about: from privileged page must have a triggering of System");
 
@@ -97,17 +97,17 @@ add_task(async function test_principal_r
     BrowserTestUtils.synthesizeMouseAtCenter("#aboutchildprincipal",
                                              { type: "contextmenu", button: 2 },
                                              gBrowser.selectedBrowser);
 
     let tab = await loadPromise;
     gBrowser.selectTabAtIndex(2);
 
     await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
-      let channel = content.document.docShell.currentDocumentChannel;
+      let channel = content.docShell.currentDocumentChannel;
       is(channel.originalURI.asciiSpec,
          "about:test-about-principal-child",
          "sanity check - make sure we test the principal for the correct URI");
 
       let triggeringPrincipal = channel.loadInfo.triggeringPrincipal;
       ok(Services.scriptSecurityManager.isSystemPrincipal(triggeringPrincipal),
          "loading about: from privileged page must have a triggering of System");
 
--- a/browser/base/content/test/static/browser_parsable_css.js
+++ b/browser/base/content/test/static/browser_parsable_css.js
@@ -351,17 +351,17 @@ add_task(async function checkAllTheCSS()
   let hiddenFrame = new HiddenFrame();
   let win = await hiddenFrame.get();
   let iframe = win.document.createElementNS("http://www.w3.org/1999/xhtml", "html:iframe");
   win.document.documentElement.appendChild(iframe);
   let iframeLoaded = BrowserTestUtils.waitForEvent(iframe, "load", true);
   iframe.contentWindow.location = testFile;
   await iframeLoaded;
   let doc = iframe.contentWindow.document;
-  doc.docShell.cssErrorReportingEnabled = true;
+  iframe.contentWindow.docShell.cssErrorReportingEnabled = true;
 
   // Parse and remove all manifests from the list.
   // NOTE that this must be done before filtering out devtools paths
   // so that all chrome paths can be recorded.
   let manifestURIs = [];
   uris = uris.filter(uri => {
     if (uri.pathQueryRef.endsWith(".manifest")) {
       manifestURIs.push(uri);
--- a/browser/components/customizableui/test/browser_panelUINotifications_fullscreen_noAutoHideToolbar.js
+++ b/browser/components/customizableui/test/browser_panelUINotifications_fullscreen_noAutoHideToolbar.js
@@ -5,17 +5,17 @@ ChromeUtils.import("resource://gre/modul
 function waitForDocshellActivated() {
   return ContentTask.spawn(gBrowser.selectedBrowser, null, async function() {
     // Setting docshell activated/deactivated will trigger visibility state
     // changes to relevant state ("visible" or "hidden"). AFAIK, there is no
     // such event notifying docshell is being activated, so I use
     // "visibilitychange" event rather than polling the docShell.isActive.
     await ContentTaskUtils.waitForEvent(content.document, "visibilitychange",
                                         true /* capture */, (aEvent) => {
-      return content.document.docShell.isActive;
+      return content.docShell.isActive;
     });
   });
 }
 
 function waitForFullscreen() {
   return Promise.all([
     BrowserTestUtils.waitForEvent(window, "fullscreen"),
     // In the platforms that support reporting occlusion state (e.g. Mac),
--- a/browser/components/extensions/parent/ext-browser.js
+++ b/browser/components/extensions/parent/ext-browser.js
@@ -607,17 +607,17 @@ class TabTracker extends TabTrackerBase 
 
   getBrowserData(browser) {
     let {gBrowser} = browser.ownerGlobal;
     // Some non-browser windows have gBrowser but not getTabForBrowser!
     if (!gBrowser || !gBrowser.getTabForBrowser) {
       if (browser.ownerDocument.documentURI === "about:addons") {
         // When we're loaded into a <browser> inside about:addons, we need to go up
         // one more level.
-        browser = browser.ownerDocument.docShell.chromeEventHandler;
+        browser = browser.ownerGlobal.docShell.chromeEventHandler;
 
         ({gBrowser} = browser.ownerGlobal);
       } else {
         return {
           tabId: -1,
           windowId: -1,
         };
       }
--- a/browser/components/feeds/WebContentConverter.js
+++ b/browser/components/feeds/WebContentConverter.js
@@ -282,17 +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.document.docShell.rootTreeItem.domWindow
+    return aContentWindow.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,17 +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 bwin = navWin.document.docShell.rootTreeItem.domWindow;
+  var bwin = navWin.docShell.rootTreeItem.domWindow;
   bwin.openURI(uri, null, location,
                Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL, triggeringPrincipal);
 }
 
 function nsDefaultCommandLineHandler() {
 }
 
 nsDefaultCommandLineHandler.prototype = {
--- a/browser/components/privatebrowsing/test/browser/browser_oa_private_browsing_window.js
+++ b/browser/components/privatebrowsing/test/browser/browser_oa_private_browsing_window.js
@@ -16,17 +16,17 @@ add_task(async function test_principal_r
     });
     BrowserTestUtils.synthesizeMouseAtCenter("#checkPrincipalOA",
                                              { type: "contextmenu", button: 2 },
                                              gBrowser.selectedBrowser);
     let privateWin = await promiseNewWindow;
 
     await ContentTask.spawn(privateWin.gBrowser.selectedBrowser, {DUMMY_PAGE, TEST_PAGE}, async function({DUMMY_PAGE, TEST_PAGE}) { // eslint-disable-line
 
-      let channel = content.document.docShell.currentDocumentChannel;
+      let channel = content.docShell.currentDocumentChannel;
       is(channel.URI.spec, DUMMY_PAGE,
          "sanity check to ensure we check principal for right URI");
 
       let triggeringPrincipal = channel.loadInfo.triggeringPrincipal;
       ok(triggeringPrincipal.isCodebasePrincipal,
          "sanity check to ensure principal is a codebasePrincipal");
       is(triggeringPrincipal.URI.spec, TEST_PAGE,
          "test page must be the triggering page");
--- a/browser/components/search/content/searchReset.js
+++ b/browser/components/search/content/searchReset.js
@@ -41,17 +41,17 @@ function doSearch() {
     }
   }
 
   let engine = Services.search.currentEngine;
   let submission = engine.getSubmission(queryString, null, purpose);
 
   window.removeEventListener("unload", recordPageClosed);
 
-  let win = window.document.docShell.rootTreeItem.domWindow;
+  let win = window.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/sessionstore/content/aboutSessionRestore.js
+++ b/browser/components/sessionstore/content/aboutSessionRestore.js
@@ -220,17 +220,17 @@ function onListKeyDown(aEvent) {
       restoreSingleTab(ix, aEvent.shiftKey);
     break;
   }
 }
 
 // Helper functions
 
 function getBrowserWindow() {
-  return window.document.docShell.rootTreeItem.domWindow;
+  return window.docShell.rootTreeItem.domWindow;
 }
 
 function toggleRowChecked(aIx) {
   function isChecked(aItem) {
     return aItem.checked;
   }
 
   var item = gTreeData[aIx];
--- a/browser/components/syncedtabs/util.js
+++ b/browser/components/syncedtabs/util.js
@@ -5,11 +5,11 @@
 "use strict";
 
 var EXPORTED_SYMBOLS = [
   "getChromeWindow"
 ];
 
 // Get the chrome (ie, browser) window hosting this content.
 function getChromeWindow(window) {
-  return window.document.docShell.rootTreeItem.domWindow
+  return window.docShell.rootTreeItem.domWindow
          .wrappedJSObject;
 }
--- a/browser/modules/ClickEventHandler.jsm
+++ b/browser/modules/ClickEventHandler.jsm
@@ -84,17 +84,17 @@ class ClickEventHandler {
         json.title = node.getAttribute("title");
       }
       json.noReferrer = BrowserUtils.linkHasNoReferrer(node);
 
       // Check if the link needs to be opened with mixed content allowed.
       // Only when the owner doc has |mixedContentChannel| and the same origin
       // should we allow mixed content.
       json.allowMixedContent = false;
-      let docshell = ownerDoc.docShell;
+      let docshell = ownerDoc.defaultView.docShell;
       if (this.mm.docShell.mixedContentChannel) {
         const sm = Services.scriptSecurityManager;
         try {
           let targetURI = Services.io.newURI(href);
           sm.checkSameOriginURI(docshell.mixedContentChannel.URI, targetURI, false);
           json.allowMixedContent = true;
         } catch (e) {}
       }
--- a/browser/modules/ExtensionsUI.jsm
+++ b/browser/modules/ExtensionsUI.jsm
@@ -22,18 +22,18 @@ XPCOMUtils.defineLazyPreferenceGetter(th
 const DEFAULT_EXTENSION_ICON = "chrome://mozapps/skin/extensions/extensionGeneric.svg";
 
 const BROWSER_PROPERTIES = "chrome://browser/locale/browser.properties";
 const BRAND_PROPERTIES = "chrome://branding/locale/brand.properties";
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 
 function getTabBrowser(browser) {
-  while (browser.ownerDocument.docShell.itemType !== Ci.nsIDocShell.typeChrome) {
-    browser = browser.ownerDocument.docShell.chromeEventHandler;
+  while (browser.ownerGlobal.docShell.itemType !== Ci.nsIDocShell.typeChrome) {
+    browser = browser.ownerGlobal.docShell.chromeEventHandler;
   }
   return {browser, window: browser.ownerGlobal};
 }
 
 var ExtensionsUI = {
   sideloaded: new Set(),
   updates: new Set(),
   sideloadListener: null,
@@ -101,17 +101,17 @@ var ExtensionsUI = {
       AppMenuNotifications.showBadgeOnlyNotification("addon-alert");
     }
     this.emit("change");
   },
 
   showAddonsManager(browser, strings, icon, histkey) {
     let global = browser.selectedBrowser.ownerGlobal;
     return global.BrowserOpenAddonsMgr("addons://list/extension").then(aomWin => {
-      let aomBrowser = aomWin.document.docShell.chromeEventHandler;
+      let aomBrowser = aomWin.docShell.chromeEventHandler;
       return this.showPermissionsPrompt(aomBrowser, strings, icon, histkey);
     });
   },
 
   showSideloaded(browser, addon) {
     addon.markAsSeen();
     this.sideloaded.delete(addon);
     this._updateNotifications();
--- a/browser/modules/NetErrorContent.jsm
+++ b/browser/modules/NetErrorContent.jsm
@@ -547,17 +547,17 @@ var NetErrorContent = {
     let hideAddExceptionButton = false;
 
     if (this.isAboutCertError(win.document)) {
       this.onCertError(global, originalTarget, win);
       hideAddExceptionButton =
         Services.prefs.getBoolPref("security.certerror.hideAddException", false);
     }
     if (this.isAboutNetError(win.document)) {
-      let docShell = win.document.docShell;
+      let docShell = win.docShell;
       if (docShell) {
         let {securityInfo} = docShell.failedChannel;
         // We don't have a securityInfo when this is for example a DNS error.
         if (securityInfo) {
           securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
           let msg = this._getErrorMessageFromCode(securityInfo,
                                                   win.document);
           let id = win.document.getElementById("errorShortDescText");
@@ -592,30 +592,30 @@ var NetErrorContent = {
   onSetAutomatic(global, evt) {
     global.sendAsyncMessage("Browser:SetSSLErrorReportAuto", {
       automatic: evt.detail
     });
 
     // If we're enabling reports, send a report for this failure.
     if (evt.detail) {
       let win = evt.originalTarget.ownerGlobal;
-      let docShell = win.document.docShell;
+      let docShell = win.docShell;
 
       let {securityInfo} = docShell.failedChannel;
       securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
       let {host, port} = win.document.mozDocumentURIIfNotForErrorPages;
 
       let errorReporter = Cc["@mozilla.org/securityreporter;1"]
                             .getService(Ci.nsISecurityReporter);
       errorReporter.reportTLSError(securityInfo, host, port);
     }
   },
 
   onCertError(global, targetElement, win) {
-    let docShell = win.document.docShell;
+    let docShell = win.docShell;
     global.sendAsyncMessage("Browser:CertExceptionError", {
       frameId: WebNavigationFrames.getFrameId(win),
       location: win.document.location.href,
       elementId: targetElement.getAttribute("id"),
       isTopFrame: (win.parent === win),
       securityInfoAsString: getSerializedSecurityInfo(docShell),
     });
   },
--- a/browser/modules/PageStyleHandler.jsm
+++ b/browser/modules/PageStyleHandler.jsm
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var EXPORTED_SYMBOLS = ["PageStyleHandler"];
 
 var PageStyleHandler = {
   getViewer(content) {
-    return content.document.docShell.contentViewer;
+    return content.docShell.contentViewer;
   },
 
   sendStyleSheetInfo(mm) {
     let content = mm.content;
     let filteredStyleSheets = this._filterStyleSheets(this.getAllStyleSheets(content), content);
 
     mm.sendAsyncMessage("PageStyle:StyleSheets", {
       filteredStyleSheets,
@@ -45,17 +45,17 @@ var PageStyleHandler = {
   },
 
   handleEvent(event) {
     let win = event.target.ownerGlobal;
     if (win != win.top) {
       return;
     }
 
-    let mm = win.document.docShell
+    let mm = win.docShell
                 .QueryInterface(Ci.nsIInterfaceRequestor)
                 .getInterface(Ci.nsIContentFrameMessageManager);
     this.sendStyleSheetInfo(mm);
   },
 
   _stylesheetSwitchAll(frameset, title) {
     if (!title || this._stylesheetInFrame(frameset, title)) {
       this._stylesheetSwitchFrame(frameset, title);
--- a/browser/modules/test/browser/contentSearch.js
+++ b/browser/modules/test/browser/contentSearch.js
@@ -47,18 +47,18 @@ addMessageListener(TEST_MSG, msg => {
 
 // We need to keep a reference to the listener as webProgress records a weak
 // reference, hence we need to stop garbage collection cleaning it up before the
 // test is completed.
 var webProgressListener;
 
 function waitForLoadAndStopIt(expectedURL) {
   return new Promise(resolve => {
-    let webProgress = content.document.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
-                                               .getInterface(Ci.nsIWebProgress);
+    let webProgress = content.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
+                                      .getInterface(Ci.nsIWebProgress);
     webProgressListener = {
       onStateChange(webProg, req, flags, status) {
         if (req instanceof Ci.nsIChannel) {
           let url = req.originalURI.spec;
           dump("waitForLoadAndStopIt: onStateChange " + url + "\n");
           let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
                          Ci.nsIWebProgressListener.STATE_START;
           if ((flags & docStart) && webProg.isTopLevel && url == expectedURL) {
--- a/devtools/client/debugger/test/mochitest/head.js
+++ b/devtools/client/debugger/test/mochitest/head.js
@@ -70,17 +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.document.docShell.rootTreeItem.domWindow;
+  return aWindow.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,18 +514,17 @@ 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.document.docShell.rootTreeItem.domWindow
-                                 .QueryInterface(Ci.nsIDOMChromeWindow);
+      const chromeWindow = window.docShell.rootTreeItem.domWindow;
 
       let setupFinished = false;
       slowScriptDebugHandler(chromeWindow.gBrowser.selectedTab,
         () => {
           setupFinished = true;
         });
 
       // Don't return from the interrupt handler until the debugger is brought
--- a/devtools/client/jsonview/test/browser_json_refresh.js
+++ b/devtools/client/jsonview/test/browser_json_refresh.js
@@ -13,17 +13,17 @@ add_task(async function() {
   // generate file:// URI for JSON file and load in new tab
   const dir = getChromeDir(getResolvedURI(gTestPath));
   dir.append(TEST_JSON_FILE);
   const uri = Services.io.newFileURI(dir);
   const tab = await addJsonViewTab(uri.spec);
 
   // perform sanity checks for URI and pricnipals in loadInfo
   await ContentTask.spawn(tab.linkedBrowser, {TEST_JSON_FILE}, async function ({TEST_JSON_FILE}) { // eslint-disable-line
-    const channel = content.document.docShell.currentDocumentChannel;
+    const channel = content.docShell.currentDocumentChannel;
     const channelURI = channel.URI.spec;
     ok(channelURI.startsWith("file://") && channelURI.includes(TEST_JSON_FILE),
        "sanity: correct channel uri");
     const contentPolicyType = channel.loadInfo.externalContentPolicyType;
     is(contentPolicyType, Ci.nsIContentPolicy.TYPE_DOCUMENT,
        "sanity: correct contentPolicyType");
 
     const loadingPrincipal = channel.loadInfo.loadingPrincipal;
@@ -39,17 +39,17 @@ add_task(async function() {
 
   // reload the tab
   const loaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   tab.linkedBrowser.reload();
   await loaded;
 
   // check principals in loadInfo are still correct
   await ContentTask.spawn(tab.linkedBrowser, {TEST_JSON_FILE}, async function ({TEST_JSON_FILE}) { // eslint-disable-line
-    const channel = content.document.docShell.currentDocumentChannel;
+    const channel = content.docShell.currentDocumentChannel;
     const channelURI = channel.URI.spec;
     ok(channelURI.startsWith("file://") && channelURI.includes(TEST_JSON_FILE),
        "reloaded: correct channel uri");
     const contentPolicyType = channel.loadInfo.externalContentPolicyType;
     is(contentPolicyType, Ci.nsIContentPolicy.TYPE_DOCUMENT,
        "reloaded: correct contentPolicyType");
 
     const loadingPrincipal = channel.loadInfo.loadingPrincipal;
--- a/devtools/client/responsive.html/utils/window.js
+++ b/devtools/client/responsive.html/utils/window.js
@@ -5,17 +5,17 @@
 "use strict";
 
 const Services = require("Services");
 
 /**
  * Returns the `nsIDOMWindow` toplevel window for any child/inner window
  */
 function getToplevelWindow(window) {
-  return window.document.docShell.rootTreeItem.domWindow;
+  return window.docShell.rootTreeItem.domWindow;
 }
 exports.getToplevelWindow = getToplevelWindow;
 
 function getDOMWindowUtils(window) {
   return window.windowUtils;
 }
 exports.getDOMWindowUtils = getDOMWindowUtils;
 
--- a/devtools/client/webconsole/test/fixtures/stub-generators/head.js
+++ b/devtools/client/webconsole/test/fixtures/stub-generators/head.js
@@ -368,17 +368,17 @@ async function generateCssMessageStubs()
         resolve();
       });
     });
 
     await ContentTask.spawn(
       gBrowser.selectedBrowser,
       [key, code],
       function([subKey, subCode]) {
-        content.document.docShell.cssErrorReportingEnabled = true;
+        content.docShell.cssErrorReportingEnabled = true;
         const style = content.document.createElement("style");
         // eslint-disable-next-line no-unsanitized/property
         style.innerHTML = subCode;
         content.document.body.appendChild(style);
       }
     );
 
     await received;
--- a/devtools/server/actors/targets/webextension.js
+++ b/devtools/server/actors/targets/webextension.js
@@ -295,17 +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 rootWin = window.document.docShell.sameTypeRootTreeItem.domWindow;
+  const rootWin = window.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/shared/webconsole/test/test_cached_messages.html
+++ b/devtools/shared/webconsole/test/test_cached_messages.html
@@ -7,17 +7,17 @@
   <script type="text/javascript" src="common.js"></script>
   <!-- Any copyright is dedicated to the Public Domain.
      - http://creativecommons.org/publicdomain/zero/1.0/ -->
 </head>
 <body>
 <p>Test for cached messages</p>
 
 <script class="testbody" type="application/javascript">
-document.docShell.cssErrorReportingEnabled = true;
+window.docShell.cssErrorReportingEnabled = true;
 var ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"]
                           .getService(Ci.nsIConsoleAPIStorage);
 let expectedConsoleCalls = [];
 let expectedPageErrors = [];
 
 function doPageErrors() {
   Services.console.reset();
 
--- a/docshell/test/chrome/test_docRedirect.xul
+++ b/docshell/test/chrome/test_docRedirect.xul
@@ -66,17 +66,17 @@ https://bugzilla.mozilla.org/show_bug.cg
           iid.equals(Ci.nsISupportsWeakReference))
         return this;
       throw Cr.NS_ERROR_NO_INTERFACE;
     }
   }
 
   var webNav = Cc["@mozilla.org/appshell/appShellService;1"].
       getService(Ci.nsIAppShellService).createWindowlessBrowser(true);
-  var docShell = webNav.QueryInterface(Ci.nsIInterfaceRequestor).
+  let docShell = webNav.QueryInterface(Ci.nsIInterfaceRequestor).
       getInterface(Ci.nsIDocShell);
   docShell.createAboutBlankContentViewer(
       Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal));
 
   progressListener.add(docShell, function(success) {
     webNav.close();
     SimpleTest.is(success, true, "Received document redirect event");
     SimpleTest.finish();
--- a/docshell/test/chrome/test_private_hidden_window.html
+++ b/docshell/test/chrome/test_private_hidden_window.html
@@ -13,17 +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.document.docShell.rootTreeItem.domWindow;
+var mainWindow = window.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/docshell/test/navigation/file_triggeringprincipal_subframe_nav.html
+++ b/docshell/test/navigation/file_triggeringprincipal_subframe_nav.html
@@ -3,17 +3,17 @@
 <head><meta charset="utf-8"></head>
 <body onload="checkResults()">
 <b>Sub Frame 2 Navigated</b><br/>
 
 <script type='application/javascript'>
   function checkResults() {
   	// query the uri of the loadingPrincipal and the TriggeringPrincipal and pass
   	// that information on to the parent for verification.
-    var channel = SpecialPowers.wrap(document).docShell.currentDocumentChannel;
+    var channel = SpecialPowers.wrap(window).docShell.currentDocumentChannel;
     var triggeringPrincipalURI = channel.loadInfo.triggeringPrincipal.URI.asciiSpec;
     var loadingPrincipalURI = channel.loadInfo.loadingPrincipal.URI.asciiSpec;
     var referrerURI = document.referrer;
     window.parent.parent.postMessage({triggeringPrincipalURI,
     	                              loadingPrincipalURI,
     	                              referrerURI}, '*');
   }
 </script>
--- a/docshell/test/navigation/test_triggeringprincipal_iframe_iframe_window_open.html
+++ b/docshell/test/navigation/test_triggeringprincipal_iframe_iframe_window_open.html
@@ -46,17 +46,17 @@ const TRIGGERING_PRINCIPAL_URI =
 const LOADING_PRINCIPAL_URI =
   "http://mochi.test:8888/tests/docshell/test/navigation/test_triggeringprincipal_iframe_iframe_window_open.html";
 
 var frameA = document.getElementById("framea");
 
 function checkResults() {
   frameA.removeEventListener('load', checkResults);
 
-  var channel = SpecialPowers.wrap(frameA.contentDocument).docShell.currentDocumentChannel;
+  var channel = SpecialPowers.wrap(frameA.contentWindow).docShell.currentDocumentChannel;
   var triggeringPrincipal = channel.loadInfo.triggeringPrincipal.URI.asciiSpec;
   var loadingPrincipal = channel.loadInfo.loadingPrincipal.URI.asciiSpec;
 
   is(triggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
     "TriggeringPrincipal for targeted window.open() should be the iframe triggering the load");
 
   is(frameA.contentDocument.referrer, TRIGGERING_PRINCIPAL_URI,
     "Referrer for targeted window.open() should be the principal of the iframe triggering the load");
--- a/docshell/test/navigation/test_triggeringprincipal_parent_iframe_window_open.html
+++ b/docshell/test/navigation/test_triggeringprincipal_parent_iframe_window_open.html
@@ -32,17 +32,17 @@ const TRIGGERING_PRINCIPAL_URI =
 
 const LOADING_PRINCIPAL_URI = TRIGGERING_PRINCIPAL_URI;
 
 var testframe = document.getElementById("testframe");
 
 function checkResults() {
   testframe.removeEventListener('load', checkResults);
 
-  var channel = SpecialPowers.wrap(testframe.contentDocument).docShell.currentDocumentChannel;
+  var channel = SpecialPowers.wrap(testframe.contentWindow).docShell.currentDocumentChannel;
   var triggeringPrincipal = channel.loadInfo.triggeringPrincipal.URI.asciiSpec;
   var loadingPrincipal = channel.loadInfo.loadingPrincipal.URI.asciiSpec;
 
   is(triggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
     "TriggeringPrincipal for targeted window.open() should be the principal of the document");
 
   is(testframe.contentDocument.referrer, TRIGGERING_PRINCIPAL_URI,
     "Referrer for targeted window.open() should be the principal of the document");
--- a/docshell/test/navigation/test_triggeringprincipal_window_open.html
+++ b/docshell/test/navigation/test_triggeringprincipal_window_open.html
@@ -30,17 +30,17 @@ function checkFinish() {
     SimpleTest.finish();
   }
 }
 
 // ----------------------------------------------------------------------------
 // Test 1: window.open(http:)
 var httpWin = window.open("file_triggeringprincipal_window_open.html", "_blank", "width=10,height=10");
 httpWin.onload = function() {
-  var httpChannel = SpecialPowers.wrap(httpWin.document).docShell.currentDocumentChannel;
+  var httpChannel = SpecialPowers.wrap(httpWin).docShell.currentDocumentChannel;
   var httpTriggeringPrincipal = httpChannel.loadInfo.triggeringPrincipal.URI.asciiSpec;
   var httpLoadingPrincipal = httpChannel.loadInfo.loadingPrincipal;
 
   is(httpTriggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
      "TriggeringPrincipal for window.open(http:) should be the principal of the document");
 
   is(httpWin.document.referrer, TRIGGERING_PRINCIPAL_URI,
      "Referrer for window.open(http:) should be the principal of the document");
@@ -51,17 +51,17 @@ httpWin.onload = function() {
   httpWin.close();
   checkFinish();
 }
 
 // ----------------------------------------------------------------------------
 // Test 2: window.open(javascript:)
 var jsWin = window.open("javascript:'<html><body>js</body></html>';", "_blank", "width=10,height=10");
 jsWin.onload = function() {
-  var jsChannel = SpecialPowers.wrap(jsWin.document).docShell.currentDocumentChannel;
+  var jsChannel = SpecialPowers.wrap(jsWin).docShell.currentDocumentChannel;
   var jsTriggeringPrincipal = jsChannel.loadInfo.triggeringPrincipal.URI.asciiSpec;
   var jsLoadingPrincipal = jsChannel.loadInfo.loadingPrincipal;
 
   is(jsTriggeringPrincipal, TRIGGERING_PRINCIPAL_URI,
      "TriggeringPrincipal for window.open(javascript:) should be the principal of the document");
 
   is(jsWin.document.referrer, "",
      "Referrer for window.open(javascript:) should be empty");
--- a/docshell/test/test_forceinheritprincipal_overrule_owner.html
+++ b/docshell/test/test_forceinheritprincipal_overrule_owner.html
@@ -3,17 +3,17 @@
 <head>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
 
 <script type="text/javascript">
 
-var channel = SpecialPowers.wrap(document).docShell.currentDocumentChannel;
+var channel = SpecialPowers.wrap(window).docShell.currentDocumentChannel;
 var loadInfo = channel.loadInfo;
 
 // 1) perform some sanity checks
 var triggeringPrincipal = channel.loadInfo.triggeringPrincipal.URI.asciiSpec;
 var loadingPrincipal = channel.loadInfo.loadingPrincipal.URI.asciiSpec;
 var principalToInherit = channel.loadInfo.principalToInherit.URI.asciiSpec;
 
 ok(triggeringPrincipal.startsWith("http://mochi.test:8888/"),
--- a/dom/base/test/chrome/cpows_parent.xul
+++ b/dom/base/test/chrome/cpows_parent.xul
@@ -242,17 +242,17 @@
         // alive as long as we have a reference to the first CPOW (so as long
         // as it's detectable).
         is(savedElement.isEqualNode, savedElement.isEqualNode, "webidl function identity works");
 
         // We want to test what happens when a CPOW is passed through XPConnect
         // as an XPCOM interface.  But elements are losing all their XPCOM
         // interfaces, so let's use an object that will likely stay an XPCOM
         // one.
-        let docshell = savedElement.ownerDocument.docShell;
+        let docshell = savedElement.ownerGlobal.docShell;
         ok(docshell, "We should have a docshell here!");
 
         let secureUI = Cc['@mozilla.org/secure_browser_ui;1']
                          .createInstance(Ci.nsISecureBrowserUI);
 
         try {
           secureUI.setDocShell(docshell);
           ok(false, "expected exception passing CPOW to C++");
--- a/dom/base/test/test_bug513194.html
+++ b/dom/base/test/test_bug513194.html
@@ -12,17 +12,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body>
 <a target="_blank"
    href="https://bugzilla.mozilla.org/show_bug.cgi?id=631615"
    >Mozilla Bug 513194</a>
 <script>
 // The use of document.write is deliberate.  We are testing for the
 // HTML parser to call the CSS parser once and only once when it
 // encounters a new <style> element.
-SpecialPowers.wrap(document).docShell.cssErrorReportingEnabled = true;
+SpecialPowers.wrap(window).docShell.cssErrorReportingEnabled = true;
 SimpleTest.runTestExpectingConsoleMessages(
   function () { document.write("<style>qux { foo : bar; }<\/style>") },
   [{ errorMessage: /Unknown property/ }]
 );
 </script>
 </body>
 </html>
 
--- a/dom/html/test/browser_fullscreen-api-keys.js
+++ b/dom/html/test/browser_fullscreen-api-keys.js
@@ -33,17 +33,17 @@ function frameScript() {
       keyCode: evt.keyCode
     });
   }
   doc.addEventListener("keydown", keyHandler, true);
   doc.addEventListener("keyup", keyHandler, true);
   doc.addEventListener("keypress", keyHandler, true);
 
   function waitUntilActive() {
-    if (doc.docShell.isActive && doc.hasFocus()) {
+    if (docShell.isActive && doc.hasFocus()) {
       sendAsyncMessage("Test:Activated");
     } else {
       setTimeout(waitUntilActive, 10);
     }
   }
   waitUntilActive();
 }
 
--- a/dom/html/test/browser_fullscreen-contextmenu-esc.js
+++ b/dom/html/test/browser_fullscreen-contextmenu-esc.js
@@ -8,18 +8,17 @@ function frameScript() {
     sendAsyncMessage("Test:FullscreenChanged",
                      !!content.document.fullscreenElement);
   });
   addMessageListener("Test:QueryFullscreenState", () => {
     sendAsyncMessage("Test:FullscreenState",
                      !!content.document.fullscreenElement);
   });
   function waitUntilActive() {
-    let doc = content.document;
-    if (doc.docShell.isActive && doc.hasFocus()) {
+    if (docShell.isActive && content.document.hasFocus()) {
       sendAsyncMessage("Test:Activated");
     } else {
       setTimeout(waitUntilActive, 10);
     }
   }
   waitUntilActive();
 }
 
--- a/dom/plugins/test/mochitest/test_privatemode_perwindowpb.xul
+++ b/dom/plugins/test/mochitest/test_privatemode_perwindowpb.xul
@@ -46,17 +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.document.docShell.rootTreeItem.domWindow;
+  var mainWindow = window.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/serviceworkers/test/fetch/hsts/realindex.html
+++ b/dom/serviceworkers/test/fetch/hsts/realindex.html
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
 <script>
-  var securityInfoPresent = !!SpecialPowers.wrap(document).docShell.currentDocumentChannel.securityInfo;
+  var securityInfoPresent = !!SpecialPowers.wrap(window).docShell.currentDocumentChannel.securityInfo;
   window.parent.postMessage({status: "protocol",
                              data: location.protocol,
                              securityInfoPresent: securityInfoPresent},
                             "*");
 </script>
--- a/dom/serviceworkers/test/test_privateBrowsing.html
+++ b/dom/serviceworkers/test/test_privateBrowsing.html
@@ -29,17 +29,17 @@ function testOnWindow(aIsPrivate, aCallb
 
     if (!aIsPrivate) {
       win.gBrowser.loadURI(contentPage);
     }
   }, {capture: true, once: true});
 }
 
 function setupWindow() {
-  mainWindow = window.document.docShell.rootTreeItem.domWindow;
+  mainWindow = window.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,17 +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.document.docShell.rootTreeItem.domWindow;
+  var mainWindow = window.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,17 +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.document.docShell.rootTreeItem.domWindow;
+  return win.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,17 +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.document.docShell.rootTreeItem.domWindow;
+  mainWindow = window.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,17 +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.document.docShell.rootTreeItem.domWindow;
+  var mainWindow = window.docShell.rootTreeItem.domWindow;
 
   mainWindow.openWebLinkIn(CONTENT_PAGE, "window", {
                                   private: aIsPrivate });
   whenDelayedStartupFinished(callback);
 };
 </script>
 </head>
 <body onload="startTest();">
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -378,18 +378,16 @@ partial interface Document {
   [NewObject, Func="nsGenericHTMLElement::TouchEventsEnabled"]
   TouchList createTouchList();
   [NewObject, Func="nsGenericHTMLElement::TouchEventsEnabled"]
   TouchList createTouchList(sequence<Touch> touches);
 
   [ChromeOnly]
   attribute boolean styleSheetChangeEventsEnabled;
 
-  [ChromeOnly] readonly attribute nsIDocShell? docShell;
-
   [ChromeOnly] readonly attribute DOMString contentLanguage;
 
   [ChromeOnly] readonly attribute nsILoadGroup? documentLoadGroup;
 
   // Blocks the initial document parser until the given promise is settled.
   [ChromeOnly, Throws]
   Promise<any> blockParsing(Promise<any> promise,
                             optional BlockParsingOptions options);
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -250,16 +250,18 @@ partial interface Window {
    */
   [Throws, NeedsCallerType] void sizeToContent();
 
   // XXX Shouldn't this be in nsIDOMChromeWindow?
   [ChromeOnly, Replaceable, Throws] readonly attribute XULControllers controllers;
 
   [ChromeOnly, Throws] readonly attribute Element? realFrameElement;
 
+  [ChromeOnly] readonly attribute nsIDocShell? docShell;
+
   [Throws, NeedsCallerType]
   readonly attribute float mozInnerScreenX;
   [Throws, NeedsCallerType]
   readonly attribute float mozInnerScreenY;
   [Replaceable, Throws, NeedsCallerType]
   readonly attribute double devicePixelRatio;
 
   /* The maximum offset that the window can be scrolled to
--- a/dom/workers/test/test_sharedWorker_privateBrowsing.html
+++ b/dom/workers/test/test_sharedWorker_privateBrowsing.html
@@ -27,17 +27,17 @@ function testOnWindow(aIsPrivate, aCallb
 
     if (!aIsPrivate) {
       win.gBrowser.loadURI(contentPage);
     }
   }, {capture: true, once: true});
 }
 
 function setupWindow() {
-  mainWindow = window.document.docShell.rootTreeItem.domWindow;
+  mainWindow = window.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,17 +38,17 @@ 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.docShell
+    var chromeWin = browserElement.ownerGlobal.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)
--- a/image/test/mochitest/test_bug1132427.html
+++ b/image/test/mochitest/test_bug1132427.html
@@ -48,17 +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).document.docShell.rootTreeItem.domWindow;
+  var chromewin = SpecialPowers.wrap(win).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/layout/base/tests/chrome/printpreview_bug396024_helper.xul
+++ b/layout/base/tests/chrome/printpreview_bug396024_helper.xul
@@ -12,17 +12,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <script type="application/javascript">
 <![CDATA[
 var is = window.opener.wrappedJSObject.is;
 var ok = window.opener.wrappedJSObject.ok;
 var todo = window.opener.wrappedJSObject.todo;
 var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
 var gWbp;
 function printpreview() {
-  gWbp = window.frames[1].document.docShell.printPreview;
+  gWbp = window.frames[1].docShell.printPreview;
   var listener = {
     onLocationChange: function(webProgress, request, location, flags) { },
     onProgressChange: function(webProgress, request, curSelfProgress, 
                                maxSelfProgress, curTotalProgress,
                                maxTotalProgress) { },
     onSecurityChange: function(webProgress, request, state) { },
     onStateChange: function(webProgress, request, stateFlags, status) { },
     onStatusChange: function(webProgress, request, status, message) { },
@@ -38,17 +38,17 @@ function printpreview() {
   prefs.setBoolPref('print.show_print_progress', false);
   //XXX I would have thought this would work, instead I'm forced to use prefs service
   gWbp.globalPrintSettings.showPrintProgress = false; 
   gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
   prefs.clearUserPref('print.show_print_progress');
 }
 
 function exitprintpreview() {
-  window.frames[1].document.docShell.printPreview.exitPrintPreview();
+  window.frames[1].docShell.printPreview.exitPrintPreview();
 }
 
 function finish() {
   SimpleTest.finish();
   window.close();
 }
 
 function run()
@@ -84,17 +84,17 @@ function run2() {
     document.getElementById("i").removeEventListener("load", arguments.callee, true);
     setTimeout(run3, 0);
   };
   document.getElementById("i").addEventListener("load", loadhandler, true);
   window.frames[0].location.reload();
 }
 
 function run3() {
-  gWbp = window.frames[1].document.docShell.printPreview;
+  gWbp = window.frames[1].docShell.printPreview;
   ok(gWbp.doingPrintPreview, "Should be doing print preview");
   exitprintpreview();
   setTimeout(run4, 0);
 }
 
 function run4() {
   var i = document.getElementById("i");
   i.remove();
@@ -103,17 +103,17 @@ function run4() {
     setTimeout(run5, 0);
   };
   i.addEventListener("load", loadhandler, true);
   document.documentElement.getBoundingClientRect();
   document.documentElement.appendChild(i);
 }
 
 function run5() {
-  gWbp = window.frames[0].document.docShell.printPreview;
+  gWbp = window.frames[0].docShell.printPreview;
   ok(!gWbp.doingPrintPreview, "Should not be doing print preview anymore2");
 
   //XXX this shouldn't be necessary, see bug 405555
   printpreview();
   exitprintpreview();
   finish(); //should not have crashed after all of this
 }
 ]]></script>
--- a/layout/base/tests/chrome/printpreview_bug482976_helper.xul
+++ b/layout/base/tests/chrome/printpreview_bug482976_helper.xul
@@ -12,17 +12,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 <script type="application/javascript">
 <![CDATA[
 var is = window.opener.wrappedJSObject.is;
 var ok = window.opener.wrappedJSObject.ok;
 var todo = window.opener.wrappedJSObject.todo;
 var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
 var gWbp;
 function printpreview() {
-  gWbp = window.frames[1].document.docShell.printPreview;
+  gWbp = window.frames[1].docShell.printPreview;
   var listener = {
     onLocationChange: function(webProgress, request, location, flags) { },
     onProgressChange: function(webProgress, request, curSelfProgress, 
                                maxSelfProgress, curTotalProgress,
                                maxTotalProgress) { },
     onSecurityChange: function(webProgress, request, state) { },
     onStateChange: function(webProgress, request, stateFlags, status) { },
     onStatusChange: function(webProgress, request, status, message) { },
@@ -38,17 +38,17 @@ function printpreview() {
   prefs.setBoolPref('print.show_print_progress', false);
   //XXX I would have thought this would work, instead I'm forced to use prefs service
   gWbp.globalPrintSettings.showPrintProgress = false; 
   gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
   prefs.clearUserPref('print.show_print_progress');
 }
 
 function exitprintpreview() {
-  window.frames[1].document.docShell.printPreview.exitPrintPreview();
+  window.frames[1].docShell.printPreview.exitPrintPreview();
 }
 
 function finish() {
   SimpleTest.finish();
   window.close();
 }
 
 function run1()
--- a/layout/base/tests/chrome/printpreview_helper.xul
+++ b/layout/base/tests/chrome/printpreview_helper.xul
@@ -19,17 +19,17 @@ var ctx2;
 var counter = 0;
 
 var file = Cc["@mozilla.org/file/directory_service;1"]
              .getService(Ci.nsIProperties)
              .get("TmpD", Ci.nsIFile);
 filePath = file.path;
 
 function printpreview() {
-  gWbp = window.frames[1].document.docShell.printPreview;
+  gWbp = window.frames[1].docShell.printPreview;
   var listener = {
     onLocationChange: function(webProgress, request, location, flags) { },
     onProgressChange: function(webProgress, request, curSelfProgress, 
                                maxSelfProgress, curTotalProgress,
                                maxTotalProgress) { },
     onSecurityChange: function(webProgress, request, state) { },
     onStateChange: function(webProgress, request, stateFlags, status) { },
     onStatusChange: function(webProgress, request, status, message) { },
@@ -55,17 +55,17 @@ function printpreview() {
   is(before, 1, "Should have called beforeprint listener!");
   is(after, 1, "Should have called afterprint listener!");
   window.frames[0].removeEventListener("beforeprint", beforeprint, true);
   window.frames[0].removeEventListener("afterprint", afterprint, true);
   prefs.clearUserPref('print.show_print_progress');
 }
 
 function exitprintpreview() {
-  window.frames[1].document.docShell.printPreview.exitPrintPreview();
+  window.frames[1].docShell.printPreview.exitPrintPreview();
 }
 
 function finish() {
   SimpleTest.finish();
   window.close();
 }
 
 function runTests()
--- a/layout/base/tests/chrome/test_bug420499.xul
+++ b/layout/base/tests/chrome/test_bug420499.xul
@@ -55,17 +55,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
     
     /** Test for Bug 420499 **/
     SimpleTest.waitForExplicitFinish();
 
     function getSelectionController() {
-      return document.docShell
+      return window.docShell
         .QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(Ci.nsISelectionDisplay)
         .QueryInterface(Ci.nsISelectionController);
     }
 
     function isCaretVisible() {
       window.QueryInterface(Ci.nsIInterfaceRequestor);
       var docShell = window.QueryInterface(Ci.nsIInterfaceRequestor)
--- a/layout/forms/test/test_bug536567_perwindowpb.html
+++ b/layout/forms/test/test_bug536567_perwindowpb.html
@@ -124,17 +124,17 @@ function endTest() {
   }
 
   normalWindow.close();
   privateWindow.close();
   MockFilePicker.cleanup();
   SimpleTest.finish();
 }
 
-var mainWindow = window.document.docShell.rootTreeItem.domWindow;
+var mainWindow = window.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/style/test/test_bug413958.html
+++ b/layout/style/test/test_bug413958.html
@@ -15,17 +15,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       href="https://bugzilla.mozilla.org/show_bug.cgi?id=413958"
       >Mozilla Bug 413958</a>. All text below should be black on white.</p>
 <p>Sheet: <span id="s1">1</span>
           <span id="s2">2</span>
           <span id="s3">3</span>.
    Style attr: <span id="setStyle">4</span>.
    Properties: <span id="setStyleProp" style="">5</span>.</p>
 <script>
-SpecialPowers.wrap(document).docShell.cssErrorReportingEnabled = true;
+SpecialPowers.wrap(window).docShell.cssErrorReportingEnabled = true;
 
 var tests = [
   function() {
     var s = document.createTextNode(
 "#s1{nosuchprop:auto; color:black}\n"+
 "#s2{nosuchprop:auto; color:black}invalid?sel{}#s3{color:black}"),
         e = document.createElement("style");
     e.appendChild(s);
--- a/layout/style/test/test_css_parse_error_smoketest.html
+++ b/layout/style/test/test_css_parse_error_smoketest.html
@@ -4,17 +4,17 @@
   <meta charset="utf-8">
   <title>Test for CSS parser reporting parsing errors with expected precision</title>
   <script src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" href="/tests/SimpleTest/test.css">
 </head>
 <body>
 <style id="testbench"></style>
 <script>
-  SpecialPowers.wrap(document).docShell.cssErrorReportingEnabled = true;
+  SpecialPowers.wrap(window).docShell.cssErrorReportingEnabled = true;
   var tests = [
     { css: "@unknown {}", error: "Unrecognized at-rule or error parsing at-rule ‘@unknown’." },
 
     { css: "x { color: invalid; }", error: "Expected color but found ‘invalid’.  Error in parsing value for ‘color’.  Declaration dropped." },
 
     { css: "x { filter: alpha(foo); }", error: "Expected ‘none’, URL, or filter function but found ‘alpha(’.  Error in parsing value for ‘filter’.  Declaration dropped." },
     { css: "x { filter: 5; }", error: "Expected ‘none’, URL, or filter function but found ‘5’.  Error in parsing value for ‘filter’.  Declaration dropped." },
 
--- a/layout/style/test/test_parser_diagnostics_unprintables.html
+++ b/layout/style/test/test_parser_diagnostics_unprintables.html
@@ -13,17 +13,17 @@
 >Mozilla Bug 229827</a>
 <style id="testbench"></style>
 <script type="application/javascript">
 // This test has intimate knowledge of how to get the CSS parser to
 // emit diagnostics that contain text under control of the user.
 // That's not the point of the test, though; the point is only that
 // *that text* is properly escaped.
 
-SpecialPowers.wrap(document).docShell.cssErrorReportingEnabled = true;
+SpecialPowers.wrap(window).docShell.cssErrorReportingEnabled = true;
 
 // There is one "pattern" for each code path through the error reporter
 // that might need to escape some kind of user-supplied text.
 // Each "pattern" is tested once with each of the "substitution"s below:
 // <t>, <i>, and <s> are replaced by the t:, i:, and s: fields of
 // each substitution object in turn.
 let patterns = [
   // REPORT_UNEXPECTED_P (only ever used in contexts where identifier-like
--- a/layout/tools/reftest/manifest.jsm
+++ b/layout/tools/reftest/manifest.jsm
@@ -522,17 +522,17 @@ sandbox.compareRetainedDisplayLists = g.
         getIntPref:  function(p) { return prefs.getIntPref(p); }
     }, sandbox, { cloneFunctions: true });
 
     // Tests shouldn't care about this except for when they need to
     // crash the content process
     sandbox.browserIsRemote = g.browserIsRemote;
 
     try {
-        sandbox.asyncPan = g.containingWindow.document.docShell.asyncPanZoomEnabled;
+        sandbox.asyncPan = g.containingWindow.docShell.asyncPanZoomEnabled;
     } catch (e) {
         sandbox.asyncPan = false;
     }
 
     // Graphics features
     sandbox.usesRepeatResampling = sandbox.d2d;
 
     // Running in a test-verify session?
--- a/mobile/android/chrome/content/aboutAccounts.js
+++ b/mobile/android/chrome/content/aboutAccounts.js
@@ -299,17 +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
-        .document.docShell.rootTreeItem.domWindow
+        .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,17 +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.document.docShell.rootTreeItem.domWindow
+  return window.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,17 +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.document.docShell.rootTreeItem.domWindow
+  window.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,17 +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.document.docShell.rootTreeItem.domWindow
+  window.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/ContentDispatchChooser.js
+++ b/mobile/android/components/ContentDispatchChooser.js
@@ -81,17 +81,17 @@ ContentDispatchChooser.prototype =
         }
 
         // We couldn't open this. If this was from a click, it's likely that we just
         // want this to fail silently. If the user entered this on the address bar, though,
         // we want to show the neterror page.
         let dwu = window.windowUtils;
         let millis = dwu.millisSinceLastUserInput;
         if (millis < 0 || millis >= 1000) {
-          window.document.docShell.displayLoadError(Cr.NS_ERROR_UNKNOWN_PROTOCOL, aURI, null);
+          window.docShell.displayLoadError(Cr.NS_ERROR_UNKNOWN_PROTOCOL, aURI, null);
         } else {
           this._closeBlankWindow(window);
         }
       });
     }
   },
 };
 
--- a/mobile/android/components/ContentPermissionPrompt.js
+++ b/mobile/android/components/ContentPermissionPrompt.js
@@ -46,17 +46,17 @@ ContentPermissionPrompt.prototype = {
       callback(/* allow */ false);
       return true;
     }
 
     return false;
   },
 
   getChromeWindow: function getChromeWindow(aWindow) {
-     let chromeWin = aWindow.document.docShell.rootTreeItem.domWindow
+     let chromeWin = aWindow.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,17 +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.document.docShell.rootTreeItem.domWindow;
+  return window.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,17 +278,17 @@ var WebrtcUI = {
     } else {
       message = Strings.browser.GetStringFromName("getUserMedia.blockedCameraAndMicrophoneAccess");
     }
 
     DoorHanger.show(aWindow, message, "webrtc-blocked");
   },
 
   getChromeWindow: function getChromeWindow(aWindow) {
-     let chromeWin = aWindow.document.docShell.rootTreeItem.domWindow
+     let chromeWin = aWindow.docShell.rootTreeItem.domWindow
                             .QueryInterface(Ci.nsIDOMChromeWindow);
      return chromeWin;
   },
 
   prompt: function prompt(aContentWindow, aCallID, aAudioRequested,
                           aVideoRequested, aDevices) {
     let audioDevices = [];
     let videoDevices = [];
--- a/netwerk/test/browser/browser_about_cache.js
+++ b/netwerk/test/browser/browser_about_cache.js
@@ -17,17 +17,17 @@ add_task(async function() {
     // Can't easily use searchParms and new URL() because it's an about: URI...
     return uri.startsWith("about:cache?") && uri.includes("storage=disk");
   };
   let diskPageLoaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, expectedPageCheck);
   await ContentTask.spawn(tab.linkedBrowser, null, function() {
     ok(!content.document.nodePrincipal.isSystemPrincipal,
        "about:cache should not have system principal");
     let principalURI = content.document.nodePrincipal.URI;
-    let channel = content.document.docShell.currentDocumentChannel;
+    let channel = content.docShell.currentDocumentChannel;
     ok(!channel.loadInfo.loadingPrincipal, "Loading principal should be null.");
     is(principalURI && principalURI.spec, content.document.location.href, "Principal matches location");
     let links = [... content.document.querySelectorAll("a[href*=disk]")];
     is(links.length, 1, "Should have 1 link to the disk entries");
     links[0].click();
   });
   await diskPageLoaded;
   info("about:cache disk subpage loaded");
@@ -38,34 +38,34 @@ add_task(async function() {
   };
   let triggeringURISpec = tab.linkedBrowser.currentURI.spec;
   let entryLoaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, expectedPageCheck);
   await ContentTask.spawn(tab.linkedBrowser, kTestPage, function(kTestPage) {
     ok(!content.document.nodePrincipal.isSystemPrincipal,
        "about:cache with query params should still not have system principal");
     let principalURI = content.document.nodePrincipal.URI;
     is(principalURI && principalURI.spec, content.document.location.href, "Principal matches location");
-    let channel = content.document.docShell.currentDocumentChannel;
+    let channel = content.docShell.currentDocumentChannel;
     principalURI = channel.loadInfo.triggeringPrincipal.URI;
     is(principalURI && principalURI.spec, "about:cache", "Triggering principal matches previous location");
     ok(!channel.loadInfo.loadingPrincipal, "Loading principal should be null.");
     let links = [... content.document.querySelectorAll("a[href*='" + kTestPage + "']")];
     is(links.length, 1, "Should have 1 link to the entry for " + kTestPage);
     links[0].click();
   });
   await entryLoaded;
   info("about:cache entry loaded");
 
 
   await ContentTask.spawn(tab.linkedBrowser, triggeringURISpec, function(triggeringURISpec) {
     ok(!content.document.nodePrincipal.isSystemPrincipal,
        "about:cache-entry should also not have system principal");
     let principalURI = content.document.nodePrincipal.URI;
     is(principalURI && principalURI.spec, content.document.location.href, "Principal matches location");
-    let channel = content.document.docShell.currentDocumentChannel;
+    let channel = content.docShell.currentDocumentChannel;
     principalURI = channel.loadInfo.triggeringPrincipal.URI;
     is(principalURI && principalURI.spec, triggeringURISpec, "Triggering principal matches previous location");
     ok(!channel.loadInfo.loadingPrincipal, "Loading principal should be null.");
     ok(content.document.querySelectorAll("th").length,
        "Should have several table headers with data.");
   });
   BrowserTestUtils.removeTab(tab);
 });
--- 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,17 +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.document.docShell.rootTreeItem.domWindow;
+  var mainWindow = window.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/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -1410,17 +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.document.docShell.rootTreeItem.domWindow
+    return window.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/extensions/ExtensionCommon.jsm
+++ b/toolkit/components/extensions/ExtensionCommon.jsm
@@ -363,18 +363,17 @@ class BaseContext {
     this.incognito = null;
     this.messageManager = null;
     this.docShell = null;
     this.contentWindow = null;
     this.innerWindowID = 0;
   }
 
   setContentWindow(contentWindow) {
-    let {document} = contentWindow;
-    let {docShell} = document;
+    let {document, docShell} = contentWindow;
 
     this.innerWindowID = getInnerWindowID(contentWindow);
     this.messageManager = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                                   .getInterface(Ci.nsIContentFrameMessageManager);
 
     if (this.incognito == null) {
       this.incognito = PrivateBrowsingUtils.isContentWindowPrivate(contentWindow);
     }
--- a/toolkit/components/extensions/ExtensionPageChild.jsm
+++ b/toolkit/components/extensions/ExtensionPageChild.jsm
@@ -394,17 +394,17 @@ ExtensionPageChild = {
     let context = this.extensionContexts.get(windowId);
     if (context) {
       if (context.extension !== extension) {
         throw new Error("A different extension context already exists for this frame");
       }
       throw new Error("An extension context was already initialized for this frame");
     }
 
-    let mm = contentWindow.document.docShell
+    let mm = contentWindow.docShell
                           .QueryInterface(Ci.nsIInterfaceRequestor)
                           .getInterface(Ci.nsIContentFrameMessageManager);
 
     let {viewType, tabId, devtoolsToolboxInfo} = getFrameData(mm) || {};
 
     let uri = contentWindow.document.documentURIObject;
 
     if (devtoolsToolboxInfo) {
--- a/toolkit/components/extensions/ExtensionParent.jsm
+++ b/toolkit/components/extensions/ExtensionParent.jsm
@@ -656,17 +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.domWindow;
+    return win.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
@@ -84,17 +84,17 @@ var extensions = new DefaultWeakMap(poli
 });
 
 var contentScripts = new DefaultWeakMap(matcher => {
   return new ExtensionContent.Script(extensions.get(matcher.extension),
                                      matcher);
 });
 
 function getMessageManager(window) {
-  let docShell = window.document.docShell.QueryInterface(Ci.nsIInterfaceRequestor);
+  let docShell = window.docShell.QueryInterface(Ci.nsIInterfaceRequestor);
   try {
     return docShell.getInterface(Ci.nsIContentFrameMessageManager);
   } catch (e) {
     // Some windows don't support this interface (hidden window).
     return null;
   }
 }
 
--- a/toolkit/components/extensions/parent/ext-tabs-base.js
+++ b/toolkit/components/extensions/parent/ext-tabs-base.js
@@ -783,17 +783,17 @@ class WindowBase {
   }
 
   /**
    * @property {nsIXULWindow} xulWindow
    *        The nsIXULWindow object for this browser window.
    *        @readonly
    */
   get xulWindow() {
-    return this.window.document.docShell.treeOwner
+    return this.window.docShell.treeOwner
                .QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIXULWindow);
   }
 
   /**
    * Returns true if this window is the current window for the given extension
    * context, false otherwise.
    *
--- a/toolkit/components/passwordmgr/test/chrome/test_privbrowsing_perwindowpb.html
+++ b/toolkit/components/passwordmgr/test/chrome/test_privbrowsing_perwindowpb.html
@@ -189,17 +189,17 @@ function checkTest() {
       break;
 
     default:
       ok(false, "Unexpected call to checkTest for test #" + testNum);
 
   }
 }
 
-var mainWindow = window.document.docShell.rootTreeItem.domWindow;
+var mainWindow = window.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/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -2454,19 +2454,17 @@ Engine.prototype = {
                            .QueryInterface(Ci.nsILoadContext);
 
     // Using the codebase principal which is constructed by the search URI
     // and given originAttributes. If originAttributes are not given, we
     // fallback to use the docShell's originAttributes.
     let attrs = options.originAttributes;
 
     if (!attrs) {
-      attrs = options.window.document
-                            .docShell
-                            .getOriginAttributes();
+      attrs = options.window.docShell.getOriginAttributes();
     }
 
     let principal = Services.scriptSecurityManager
                             .createCodebasePrincipal(searchURI, attrs);
 
     connector.speculativeConnect2(searchURI, principal, callbacks);
 
     if (this.supportsResponseType(URLTYPE_SUGGEST_JSON)) {
--- a/toolkit/components/url-classifier/tests/mochitest/test_advisory_link.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_advisory_link.html
@@ -15,17 +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.document.docShell.rootTreeItem.domWindow;
+var mainWindow = window.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,17 +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.document.docShell.rootTreeItem.domWindow;
+var mainWindow = window.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,17 +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.document.docShell.rootTreeItem.domWindow;
+var mainWindow = window.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,17 +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.document.docShell.rootTreeItem.domWindow;
+var mainWindow = window.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,17 +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.document.docShell.rootTreeItem.domWindow;
+var mainWindow = window.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 =
@@ -187,17 +187,17 @@ function testOnWindow(aTestData) {
   return new Promise(resolve => {
     let win = mainWindow.OpenBrowserWindow();
 
     (async function() {
       await new Promise(rs => whenDelayedStartupFinished(win, rs));
 
       let expected;
       let browser = win.gBrowser.selectedBrowser;
-      let wp = win.gBrowser.contentDocument.docShell.QueryInterface(Ci.nsIWebProgress);
+      let wp = win.gBrowser.contentWindow.docShell.QueryInterface(Ci.nsIWebProgress);
       let progressListener = {
         onSecurityChange(aWebProgress, aRequest, aState) {
           expected = aTestData.reportUrl;
         },
         QueryInterface: ChromeUtils.generateQI(["nsISupportsWeakReference"])
       };
       wp.addProgressListener(progressListener, wp.NOTIFY_SECURITY);
 
--- a/toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_bug1157081.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_bug1157081.html
@@ -11,17 +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.document.docShell.rootTreeItem.domWindow;
+var mainWindow = window.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,17 +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.document.docShell.rootTreeItem.domWindow;
+var mainWindow = window.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,17 +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.document.docShell.rootTreeItem.domWindow;
+var mainWindow = window.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,17 +124,17 @@ function sectionalizeObject(obj) {
   }
   return map;
 }
 
 /**
  * Obtain the main DOMWindow for the current context.
  */
 function getMainWindow() {
-  return window.document.docShell.rootTreeItem.domWindow;
+  return window.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/content/tests/browser/browser_saveImageURL.js
+++ b/toolkit/content/tests/browser/browser_saveImageURL.js
@@ -33,17 +33,17 @@ add_task(async function preferred_API() 
   }, async function(browser) {
     let url = await ContentTask.spawn(browser, null, async function() {
       let image = content.document.getElementById("image");
       return image.href;
     });
 
     saveImageURL(url, "image.jpg", null, true, false, null, null, null, null,
       false, gBrowser.contentPrincipal);
-    let channel = gBrowser.contentDocumentAsCPOW.docShell.currentDocumentChannel;
+    let channel = gBrowser.contentWindowAsCPOW.docShell.currentDocumentChannel;
     if (channel) {
       ok(true, channel.QueryInterface(Ci.nsIHttpChannelInternal)
                       .channelIsForDownload);
 
       // Throttleable is the only class flag assigned to downloads.
       ok(channel.QueryInterface(Ci.nsIClassOfService).classFlags,
          Ci.nsIClassOfService.Throttleable);
     }
@@ -69,17 +69,17 @@ add_task(async function deprecated_API()
       return image.href;
     });
 
     // Now get the document directly from content. If we run this test with
     // e10s-enabled, this will be a CPOW, which is forbidden. We'll just
     // pass the XUL document instead to test this interface.
     let doc = document;
 
-    let channel = gBrowser.contentDocumentAsCPOW.docShell.currentDocumentChannel;
+    let channel = gBrowser.contentWindowAsCPOW.docShell.currentDocumentChannel;
     if (channel) {
       ok(true, channel.QueryInterface(Ci.nsIHttpChannelInternal)
                       .channelIsForDownload);
 
       // Throttleable is the only class flag assigned to downloads.
       ok(channel.QueryInterface(Ci.nsIClassOfService).classFlags,
          Ci.nsIClassOfService.Throttleable);
     }
--- a/toolkit/modules/WebChannelContent.jsm
+++ b/toolkit/modules/WebChannelContent.jsm
@@ -7,17 +7,17 @@
 
 var EXPORTED_SYMBOLS = ["WebChannelContent"];
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 function getMessageManager(event) {
   let window = Cu.getGlobalForObject(event.target);
 
-  return window.document.docShell
+  return window.docShell
                .QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIContentFrameMessageManager);
 }
 
 var WebChannelContent = {
   // Preference containing the list (space separated) of origins that are
   // allowed to send non-string values through a WebChannel, mainly for
   // backwards compatability. See bug 1238128 for more information.
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -273,17 +273,17 @@ function isDiscoverEnabled() {
 
   return true;
 }
 
 /**
  * Obtain the main DOMWindow for the current context.
  */
 function getMainWindow() {
-  return window.document.docShell.rootTreeItem.domWindow;
+  return window.docShell.rootTreeItem.domWindow;
 }
 
 function getBrowserElement() {
   return window.QueryInterface(Ci.nsIInterfaceRequestor)
                .getInterface(Ci.nsIDocShell)
                .chromeEventHandler;
 }
 
@@ -3445,17 +3445,17 @@ var gDragDrop = {
   }
 };
 
 // Stub tabbrowser implementation for use by the tab-modal alert code
 // when an alert/prompt/confirm method is called in a WebExtensions options_ui page
 // (See Bug 1385548 for rationale).
 var gBrowser = {
   getTabModalPromptBox(browser) {
-    const parentWindow = document.docShell.chromeEventHandler.ownerGlobal;
+    const parentWindow = window.docShell.chromeEventHandler.ownerGlobal;
 
     if (parentWindow.gBrowser) {
       return parentWindow.gBrowser.getTabModalPromptBox(browser);
     }
 
     return null;
   }
 };
--- a/widget/tests/test_bug593307.xul
+++ b/widget/tests/test_bug593307.xul
@@ -24,17 +24,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 SimpleTest.waitForExplicitFinish();
 
 function finish() {
   offscreenWindow.close();
   SimpleTest.finish();
 }
 
-var mainWindow = window.document.docShell.rootTreeItem.domWindow;
+var mainWindow = window.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>
 
--- a/widget/tests/test_bug760802.xul
+++ b/widget/tests/test_bug760802.xul
@@ -53,17 +53,17 @@ function doesntThrowException(fun) {
 }
 
 var baseWindow = getBaseWindowInterface(this);
 var nativeHandle = baseWindow.nativeHandle;
 $("display").innerHTML = "found nativeHandle for this window: "+nativeHandle;
 
 var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
 var win = wm.getMostRecentWindow("navigator:browser");
-var docShell = getBaseWindowInterfaceFromDocShell(win);
+let docShell = getBaseWindowInterfaceFromDocShell(win);
 
 ok(
   shouldThrowException(function(){docShell.nativeHandle;},
               Cr.NS_ERROR_NOT_IMPLEMENTED),
   "nativeHandle should not be implemented for nsDocShell"
 );
 
 ok(typeof(nativeHandle) === "string", "nativeHandle should be a string");
--- a/widget/tests/test_taskbar_progress.xul
+++ b/widget/tests/test_taskbar_progress.xul
@@ -35,17 +35,17 @@
 
       is(taskbar.available, IsWin7OrHigher(), "Expected availability of taskbar");
       if (!taskbar.available)
         return null;
       
       // HACK from mconnor:
       var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
       let win = wm.getMostRecentWindow("navigator:browser");
-      let docShell = win.document.docShell;
+      let docShell = win.docShell;
 
       let progress = taskbar.getTaskbarProgress(docShell);
       isnot(progress, null, "Progress is not null");
 
       try {
         taskbar.getTaskbarProgress(null);
         ok(false, "Got progress for null docshell");
       } catch (e) {