Bug 1446940 part 2. Stop getting docshells from windows via getInterface in browser. r=gijs
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 01 Aug 2018 13:07:10 -0400
changeset 429597 956c6eeca8733095d0a4fe61c57238990614926c
parent 429596 fbe5a0e5be75bc052c66623ea2346d80dc74cf1a
child 429598 d0f6f26864b7ab12902a818246f64203616a46b4
push id105943
push userbzbarsky@mozilla.com
push dateWed, 01 Aug 2018 17:07:38 +0000
treeherdermozilla-inbound@9873d9aa413f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgijs
bugs1446940
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 1446940 part 2. Stop getting docshells from windows via getInterface in browser. r=gijs
browser/base/content/browser.js
browser/base/content/content-refreshblocker.js
browser/base/content/nsContextMenu.js
browser/base/content/pageinfo/pageInfo.js
browser/base/content/tabbrowser.js
browser/base/content/test/general/browser_bug1297539.js
browser/base/content/test/performance/head.js
browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font.html
browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font2.html
browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_img.html
browser/components/customizableui/CustomizableUI.jsm
browser/components/downloads/DownloadsTaskbar.jsm
browser/components/extensions/test/browser/browser_ext_find.js
browser/components/extensions/test/browser/browser_ext_windows_create.js
browser/components/feeds/FeedWriter.js
browser/components/feeds/WebContentConverter.js
browser/components/nsBrowserContentHandler.js
browser/components/preferences/in-content/findInPage.js
browser/components/preferences/in-content/subdialogs.js
browser/components/preferences/in-content/sync.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_context_and_chromeFlags.js
browser/components/sessionstore/SessionStorage.jsm
browser/components/sessionstore/SessionStore.jsm
browser/components/sessionstore/test/browser_docshell_uuid_consistency.js
browser/extensions/formautofill/FormAutofillContent.jsm
browser/extensions/formautofill/content/FormAutofillFrameScript.js
browser/extensions/mortar/host/pdf/ppapi-content-sandbox.js
browser/extensions/pdfjs/content/PdfStreamConverter.jsm
browser/extensions/pdfjs/content/PdfjsContentUtils.jsm
browser/modules/BlockedSiteContent.jsm
browser/modules/ContentObservers.js
browser/modules/ContentWebRTC.jsm
browser/modules/FormSubmitObserver.jsm
browser/modules/LightWeightThemeWebInstallListener.jsm
browser/modules/LightweightThemeChildHelper.jsm
browser/modules/PermissionUI.jsm
browser/modules/WindowsPreviewPerTab.jsm
browser/tools/mozscreenshots/browser_boundingbox.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -232,18 +232,17 @@ XPCOMUtils.defineLazyGetter(this, "Win7F
   return null;
 });
 
 var gBrowser;
 var gLastValidURLStr = "";
 var gInPrintPreviewMode = false;
 var gContextMenu = null; // nsContextMenu instance
 var gMultiProcessBrowser =
-  window.QueryInterface(Ci.nsIInterfaceRequestor)
-        .getInterface(Ci.nsIWebNavigation)
+  window.docShell
         .QueryInterface(Ci.nsILoadContext)
         .useRemoteTabs;
 
 if (AppConstants.platform != "macosx") {
   var gEditUIVisible = true;
 }
 
 /* globals gNavToolbox, gURLBar:true */
@@ -1233,19 +1232,17 @@ var gBrowserInit = {
     ToolbarIconColor.init();
   },
 
   onDOMContentLoaded() {
     gBrowser = window._gBrowser;
     delete window._gBrowser;
     gBrowser.init();
 
-    window.QueryInterface(Ci.nsIInterfaceRequestor)
-          .getInterface(Ci.nsIWebNavigation)
-          .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
+    window.docShell.treeOwner
           .QueryInterface(Ci.nsIInterfaceRequestor)
           .getInterface(Ci.nsIXULWindow)
           .XULBrowserWindow = window.XULBrowserWindow;
     window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow =
       new nsBrowserAccess();
     BrowserWindowTracker.track(window);
 
     let initBrowser = gBrowser.initialBrowser;
@@ -1931,19 +1928,17 @@ var gBrowserInit = {
       WebAuthnPromptHelper.uninit();
       PanelUI.uninit();
       AutoShowBookmarksToolbar.uninit();
     }
 
     // Final window teardown, do this last.
     gBrowser.destroy();
     window.XULBrowserWindow = null;
-    window.QueryInterface(Ci.nsIInterfaceRequestor)
-          .getInterface(Ci.nsIWebNavigation)
-          .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
+    window.docShell.treeOwner
           .QueryInterface(Ci.nsIInterfaceRequestor)
           .getInterface(Ci.nsIXULWindow)
           .XULBrowserWindow = null;
     window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = null;
   },
 };
 
 function HandleAppCommandEvent(evt) {
@@ -2476,19 +2471,17 @@ function getPostDataStream(aPostDataStri
   let mimeStream = Cc["@mozilla.org/network/mime-input-stream;1"]
                      .createInstance(Ci.nsIMIMEInputStream);
   mimeStream.addHeader("Content-Type", aType);
   mimeStream.setData(dataStream);
   return mimeStream.QueryInterface(Ci.nsIInputStream);
 }
 
 function getLoadContext() {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIWebNavigation)
-               .QueryInterface(Ci.nsILoadContext);
+  return window.docShell.QueryInterface(Ci.nsILoadContext);
 }
 
 function readFromClipboard() {
   var url;
 
   try {
     // Create transferable that will transfer the text.
     var trans = Cc["@mozilla.org/widget/transferable;1"]
@@ -2548,19 +2541,17 @@ async function BrowserViewSourceOfDocume
     let doc = aArgsOrDocument;
     // Deprecated API - callers should pass args object instead.
     if (Cu.isCrossProcessWrapper(doc)) {
       throw new Error("BrowserViewSourceOfDocument cannot accept a CPOW " +
                       "as a document.");
     }
 
     let win = doc.defaultView;
-    let browser = win.getInterface(Ci.nsIWebNavigation)
-                     .QueryInterface(Ci.nsIDocShell)
-                     .chromeEventHandler;
+    let browser = win.docShell.chromeEventHandler;
     let outerWindowID = win.windowUtils.outerWindowID;
     let URL = browser.currentURI.spec;
     args = { browser, outerWindowID, URL };
   } else {
     args = aArgsOrDocument;
   }
 
   // Check if external view source is enabled.  If so, try it.  If it fails,
--- a/browser/base/content/content-refreshblocker.js
+++ b/browser/base/content/content-refreshblocker.js
@@ -155,19 +155,17 @@ var RefreshBlocker = {
     return false;
   },
 
   receiveMessage(message) {
     let data = message.data;
 
     if (message.name == "RefreshBlocker:Refresh") {
       let win = Services.wm.getOuterWindowWithId(data.outerWindowID);
-      let refreshURI = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                          .getInterface(Ci.nsIDocShell)
-                          .QueryInterface(Ci.nsIRefreshURI);
+      let refreshURI = win.docShell.QueryInterface(Ci.nsIRefreshURI);
 
       let URI = Services.io.newURI(data.URI);
 
       refreshURI.forceRefreshURI(URI, null, data.delay, true);
     }
   },
 
   QueryInterface: ChromeUtils.generateQI([Ci.nsIWebProgressListener2, Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]),
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -225,21 +225,17 @@ nsContextMenu.prototype = {
     this.targetSelectors = gContextMenuContentData
                            ? gContextMenuContentData.popupNodeSelectors
                            : [];
 
     if (this.isRemote) {
       this.browser = gContextMenuContentData.browser;
       this.selectionInfo = gContextMenuContentData.selectionInfo;
     } else {
-      this.browser = this.ownerDoc.defaultView
-                         .QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIWebNavigation)
-                         .QueryInterface(Ci.nsIDocShell)
-                         .chromeEventHandler;
+      this.browser = this.ownerDoc.defaultView.docShell.chromeEventHandler;
       this.selectionInfo = BrowserUtils.getSelectionDetails(window);
     }
 
     this.textSelected      = this.selectionInfo.text;
     this.isTextSelected    = this.textSelected.length != 0;
     this.webExtBrowserType = this.browser.getAttribute("webextension-view-type");
     this.inWebExtBrowser   = !!this.webExtBrowserType;
     this.inTabBrowser      = this.browser.ownerGlobal.gBrowser ?
@@ -255,18 +251,17 @@ nsContextMenu.prototype = {
       }
     }
 
     if (context.shouldInitInlineSpellCheckerUIWithChildren) {
       if (this.isRemote) {
         InlineSpellCheckerUI.initFromRemote(gContextMenuContentData.spellInfo);
       } else {
         var targetWin = this.ownerDoc.defaultView;
-        var editingSession = targetWin.QueryInterface(Ci.nsIInterfaceRequestor)
-                                      .getInterface(Ci.nsIWebNavigation)
+        var editingSession = targetWin.docShell
                                       .QueryInterface(Ci.nsIInterfaceRequestor)
                                       .getInterface(Ci.nsIEditingSession);
 
         InlineSpellCheckerUI.init(editingSession.getEditorForWindow(targetWin));
         InlineSpellCheckerUI.initFromEvent(document.popupRangeParent,
                                            document.popupRangeOffset);
       }
 
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -233,19 +233,17 @@ const PREFERENCES_CONTRACTID    = "@mozi
 
 // a number of services I'll need later
 // the cache services
 const nsICacheStorageService = Ci.nsICacheStorageService;
 const nsICacheStorage = Ci.nsICacheStorage;
 const cacheService = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(nsICacheStorageService);
 
 var loadContextInfo = Services.loadContextInfo.fromLoadContext(
-  window.QueryInterface(Ci.nsIInterfaceRequestor)
-        .getInterface(Ci.nsIWebNavigation)
-        .QueryInterface(Ci.nsILoadContext), false);
+  window.docShell.QueryInterface(Ci.nsILoadContext), false);
 var diskStorage = cacheService.diskCacheStorage(loadContextInfo, false);
 
 const nsICookiePermission  = Ci.nsICookiePermission;
 const nsIPermissionManager = Ci.nsIPermissionManager;
 
 const nsICertificateDialogs = Ci.nsICertificateDialogs;
 const CERTIFICATEDIALOGS_CONTRACTID = "@mozilla.org/nsCertificateDialogs;1";
 
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -653,20 +653,17 @@ window._gBrowser = {
     return this._outerWindowIDBrowserMap.get(aID);
   },
 
   _getTabForContentWindow(aWindow) {
     // When not using remote browsers, we can take a fast path by getting
     // directly from the content window to the browser without looping
     // over all browsers.
     if (!gMultiProcessBrowser) {
-      let browser = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                           .getInterface(Ci.nsIWebNavigation)
-                           .QueryInterface(Ci.nsIDocShell)
-                           .chromeEventHandler;
+      let browser = aWindow.docShell.chromeEventHandler;
       return this.getTabForBrowser(browser);
     }
 
     for (let i = 0; i < this.browsers.length; i++) {
       // NB: We use contentWindowAsCPOW so that this code works both
       // for remote browsers as well. aWindow may be a CPOW.
       if (this.browsers[i].contentWindowAsCPOW == aWindow)
         return this.tabs[i];
@@ -3063,21 +3060,17 @@ window._gBrowser = {
     // immediately without animation before the docshell swap, to avoid
     // about:blank being painted.
     let [closeWindow] = aOtherTab._endRemoveArgs;
     if (closeWindow) {
       let win = aOtherTab.ownerGlobal;
       win.windowUtils.suppressAnimation(true);
       // Only suppressing window animations isn't enough to avoid
       // an empty content area being painted.
-      let baseWin = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDocShell)
-                       .QueryInterface(Ci.nsIDocShellTreeItem)
-                       .treeOwner
-                       .QueryInterface(Ci.nsIBaseWindow);
+      let baseWin = win.docShell.treeOwner.QueryInterface(Ci.nsIBaseWindow);
       baseWin.visibility = false;
     }
 
     let modifiedAttrs = [];
     if (aOtherTab.hasAttribute("muted")) {
       aOurTab.setAttribute("muted", "true");
       aOurTab.muteReason = aOtherTab.muteReason;
       ourBrowser.mute();
--- a/browser/base/content/test/general/browser_bug1297539.js
+++ b/browser/base/content/test/general/browser_bug1297539.js
@@ -13,19 +13,17 @@
  * "pasteTransferable" runs only in the content process.
  * This doesn't test the remote case.
  *
  */
 
 "use strict";
 
 function getLoadContext() {
-  return window.QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIWebNavigation)
-               .QueryInterface(Ci.nsILoadContext);
+  return window.docShell.QueryInterface(Ci.nsILoadContext);
 }
 
 function getTransferableFromClipboard(asHTML) {
   let trans = Cc["@mozilla.org/widget/transferable;1"].
                     createInstance(Ci.nsITransferable);
   trans.init(getLoadContext());
   if (asHTML) {
     trans.addDataFlavor("text/html");
--- a/browser/base/content/test/performance/head.js
+++ b/browser/base/content/test/performance/head.js
@@ -52,20 +52,17 @@ async function recordReflows(testPromise
       // Interruptible reflows are the reflows caused by the refresh
       // driver ticking. These are fine.
     },
 
     QueryInterface: ChromeUtils.generateQI([Ci.nsIReflowObserver,
                                             Ci.nsISupportsWeakReference])
   };
 
-  let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                    .getInterface(Ci.nsIWebNavigation)
-                    .QueryInterface(Ci.nsIDocShell);
-  docShell.addWeakReflowObserver(observer);
+  win.docShell.addWeakReflowObserver(observer);
 
   let dirtyFrameFn = event => {
     if (event.type != "MozAfterPaint") {
       dirtyFrame(win);
     }
   };
   Services.els.addListenerForAllEvents(win, dirtyFrameFn, true);
 
--- a/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font.html
+++ b/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font.html
@@ -7,21 +7,17 @@
 <head>
   <meta charset="utf-8">
   <title>Test 2 for Bug 909920</title>
   <link rel="stylesheet" type="text/css" href="https://example.com/browser/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font.css" />
 <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 
 <script type="text/javascript">
   function checkLoadStates() {
-   var ui = SpecialPowers.wrap(window)
-            .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
-             .getInterface(SpecialPowers.Ci.nsIWebNavigation)
-             .QueryInterface(SpecialPowers.Ci.nsIDocShell)
-             .securityUI;
+   var ui = SpecialPowers.wrap(window).docShell.securityUI;
 
    var loadedMixedActive = ui &&
      !!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
    is(loadedMixedActive, false, "OK: Should not load mixed active content!");
 
    var blockedMixedActive = ui &&
      !!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
    is(blockedMixedActive, false, "OK: Should not block mixed active content!");
--- a/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font2.html
+++ b/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font2.html
@@ -7,21 +7,17 @@
 <head>
   <meta charset="utf-8">
   <title>Test 3 for Bug 909920</title>
   <link rel="stylesheet" type="text/css" href="https://example.com/browser/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_font2.css" />
 <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 
 <script type="text/javascript">
   function checkLoadStates() {
-   var ui = SpecialPowers.wrap(window)
-        .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
-             .getInterface(SpecialPowers.Ci.nsIWebNavigation)
-             .QueryInterface(SpecialPowers.Ci.nsIDocShell)
-             .securityUI;
+   var ui = SpecialPowers.wrap(window).docShell.securityUI;
 
    var loadedMixedActive = ui &&
      !!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
    is(loadedMixedActive, false, "OK: Should not load mixed active content!");
 
    var blockedMixedActive = ui &&
      !!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
    is(blockedMixedActive, false, "OK: Should not block mixed active content!");
--- a/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_img.html
+++ b/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_img.html
@@ -7,21 +7,17 @@
 <head>
   <meta charset="utf-8">
   <title>Test 1 for Bug 909920</title>
   <link rel="stylesheet" type="text/css" href="https://example.com/browser/browser/base/content/test/siteIdentity/test_no_mcb_on_http_site_img.css" />
 <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 
 <script type="text/javascript">
   function checkLoadStates() {
-   var ui = SpecialPowers.wrap(window)
-            .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
-             .getInterface(SpecialPowers.Ci.nsIWebNavigation)
-             .QueryInterface(SpecialPowers.Ci.nsIDocShell)
-             .securityUI;
+   var ui = SpecialPowers.wrap(window).docShell.securityUI;
 
    var loadedMixedActive = ui &&
      !!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT);
    is(loadedMixedActive, false, "OK: Should not load mixed active content!");
 
    var blockedMixedActive = ui &&
      !!(ui.state & SpecialPowers.Ci.nsIWebProgressListener.STATE_BLOCKED_MIXED_ACTIVE_CONTENT);
    is(blockedMixedActive, false, "OK: Should not block mixed active content!");
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -1709,21 +1709,18 @@ var CustomizableUIInternal = {
     // a toolbarbutton/item, or the panel:
     while (true && target) {
       // Skip out of iframes etc:
       if (target.nodeType == target.DOCUMENT_NODE) {
         if (!target.defaultView) {
           // Err, we're done.
           break;
         }
-        // Cue some voodoo
-        target = target.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
-                                   .getInterface(Ci.nsIWebNavigation)
-                                   .QueryInterface(Ci.nsIDocShell)
-                                   .chromeEventHandler;
+        // Find containing browser or iframe element in the parent doc.
+        target = target.defaultView.docShell.chromeEventHandler;
         if (!target) {
           break;
         }
       }
       let tagName = target.localName;
       inInput = tagName == "input" || tagName == "textbox";
       inItem = tagName == "toolbaritem" || tagName == "toolbarbutton";
       let isMenuItem = tagName == "menuitem";
--- a/browser/components/downloads/DownloadsTaskbar.jsm
+++ b/browser/components/downloads/DownloadsTaskbar.jsm
@@ -117,19 +117,17 @@ var DownloadsTaskbar = {
     }
   },
 
   /**
    * On Windows, attaches the taskbar indicator to the specified browser window.
    */
   _attachIndicator(aWindow) {
     // Activate the indicator on the specified window.
-    let docShell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                          .getInterface(Ci.nsIWebNavigation)
-                          .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
+    let docShell = aWindow.docShell.treeOwner
                           .QueryInterface(Ci.nsIInterfaceRequestor)
                           .getInterface(Ci.nsIXULWindow).docShell;
     this._taskbarProgress = gWinTaskbar.getTaskbarProgress(docShell);
 
     // If the DownloadSummary object has already been created, we should update
     // the state of the new indicator, otherwise it will be updated as soon as
     // the DownloadSummary view is registered.
     if (this._summary) {
--- a/browser/components/extensions/test/browser/browser_ext_find.js
+++ b/browser/components/extensions/test/browser/browser_ext_find.js
@@ -1,17 +1,15 @@
 /* global browser */
 "use strict";
 
 function frameScript() {
   function getSelectedText() {
     let frame = this.content.frames[0].frames[1];
-    let docShell = frame.QueryInterface(Ci.nsIInterfaceRequestor)
-                        .getInterface(Ci.nsIWebNavigation)
-                        .QueryInterface(Ci.nsIDocShell);
+    let docShell = frame.docShell;
     let controller = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                              .getInterface(Ci.nsISelectionDisplay)
                              .QueryInterface(Ci.nsISelectionController);
     let selection = controller.getSelection(controller.SELECTION_FIND);
     let range = selection.getRangeAt(0);
     let scope = {};
     ChromeUtils.import("resource://gre/modules/FindContent.jsm", scope);
     let highlighter = (new scope.FindContent(docShell)).highlighter;
--- a/browser/components/extensions/test/browser/browser_ext_windows_create.js
+++ b/browser/components/extensions/test/browser/browser_ext_windows_create.js
@@ -113,18 +113,17 @@ add_task(async function testWindowCreate
     }
     if (expected.hiddenChrome) {
       let chromeHidden = latestWindow.document.documentElement.getAttribute("chromehidden");
       is(chromeHidden.trim().split(/\s+/).sort().join(" "),
          expected.hiddenChrome.sort().join(" "),
          "Got expected hidden chrome");
     }
     if (expected.chromeFlags) {
-      let {chromeFlags} = latestWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                                      .getInterface(Ci.nsIDocShell)
+      let {chromeFlags} = latestWindow.docShell
                                       .treeOwner.QueryInterface(Ci.nsIInterfaceRequestor)
                                       .getInterface(Ci.nsIXULWindow);
       for (let flag of expected.chromeFlags) {
         ok(chromeFlags & Ci.nsIWebBrowserChrome[flag],
            `Expected window to have the ${flag} flag`);
       }
     }
 
--- a/browser/components/feeds/FeedWriter.js
+++ b/browser/components/feeds/FeedWriter.js
@@ -71,18 +71,17 @@ function FeedWriter() {
   this._selectedApp = undefined;
   this._selectedAppMenuItem = null;
   this._subscribeCallback = null;
   this._defaultHandlerMenuItem = null;
 
   Services.telemetry.scalarAdd("browser.feeds.preview_loaded", 1);
 
   XPCOMUtils.defineLazyGetter(this, "_mm", () =>
-    this._window.QueryInterface(Ci.nsIInterfaceRequestor).
-                 getInterface(Ci.nsIDocShell).
+    this._window.docShell.
                  QueryInterface(Ci.nsIInterfaceRequestor).
                  getInterface(Ci.nsIContentFrameMessageManager));
 }
 
 FeedWriter.prototype = {
   _getPropertyAsBag(container, property) {
     return container.fields.getProperty(property).
                      QueryInterface(Ci.nsIPropertyBag2);
@@ -705,19 +704,17 @@ FeedWriter.prototype = {
 
   /**
    * Returns the original URI object of the feed and ensures that this
    * component is only ever invoked from the preview document.
    * @param aWindow
    *        The window of the document invoking the BrowserFeedWriter
    */
   _getOriginalURI(aWindow) {
-    let docShell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                          .getInterface(Ci.nsIWebNavigation)
-                          .QueryInterface(Ci.nsIDocShell);
+    let docShell = aWindow.docShell;
     let chan = docShell.currentDocumentChannel;
 
     // We probably need to call Inherit() for this, but right now we can't call
     // it from JS.
     let attrs = docShell.getOriginAttributes();
     let ssm = Services.scriptSecurityManager;
     let nullPrincipal = ssm.createNullPrincipal(attrs);
 
--- a/browser/components/feeds/WebContentConverter.js
+++ b/browser/components/feeds/WebContentConverter.js
@@ -318,19 +318,17 @@ WebContentConverterRegistrar.prototype =
 
 function WebContentConverterRegistrarContent() {
 }
 
 WebContentConverterRegistrarContent.prototype = {
   registerProtocolHandler(aProtocol, aURIString, aTitle, aBrowserOrWindow) {
     aProtocol = (aProtocol || "").toLowerCase();
     // aBrowserOrWindow must be a window.
-    let messageManager = aBrowserOrWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                                         .getInterface(Ci.nsIWebNavigation)
-                                         .QueryInterface(Ci.nsIDocShell)
+    let messageManager = aBrowserOrWindow.docShell
                                          .QueryInterface(Ci.nsIInterfaceRequestor)
                                          .getInterface(Ci.nsITabChild)
                                          .messageManager;
 
     let uri = Utils.checkAndGetURI(aURIString, aBrowserOrWindow);
     Utils.checkProtocolHandlerAllowed(aProtocol, aURIString, aBrowserOrWindow);
 
     messageManager.sendAsyncMessage("WCCR:registerProtocolHandler",
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -205,18 +205,17 @@ function openBrowserWindow(cmdLine, urlO
   if (cmdLine.state == Ci.nsICommandLine.STATE_INITIAL_LAUNCH) {
     let win = Services.wm.getMostRecentWindow("navigator:blank");
     if (win) {
       // Remove the windowtype of our blank window so that we don't close it
       // later on when seeing cmdLine.preventDefault is true.
       win.document.documentElement.removeAttribute("windowtype");
 
       if (forcePrivate) {
-        win.QueryInterface(Ci.nsIInterfaceRequestor)
-           .getInterface(Ci.nsIWebNavigation)
+        win.docShell
            .QueryInterface(Ci.nsILoadContext)
            .usePrivateBrowsing = true;
       }
 
       win.location = chromeURL;
       win.arguments = args; // <-- needs to be a plain JS array here.
 
       return;
@@ -415,18 +414,17 @@ nsBrowserContentHandler.prototype = {
 
     // The global PB Service consumes this flag, so only eat it in per-window
     // PB builds.
     if (cmdLine.handleFlag("private", false) && PrivateBrowsingUtils.enabled) {
       PrivateBrowsingUtils.enterTemporaryAutoStartMode();
       if (cmdLine.state == Ci.nsICommandLine.STATE_INITIAL_LAUNCH) {
         let win = Services.wm.getMostRecentWindow("navigator:blank");
         if (win) {
-          win.QueryInterface(Ci.nsIInterfaceRequestor)
-             .getInterface(Ci.nsIWebNavigation)
+          win.docShell
              .QueryInterface(Ci.nsILoadContext)
              .usePrivateBrowsing = true;
         }
       }
     }
     if (cmdLine.handleFlag("setDefaultBrowser", false)) {
       ShellService.setDefaultBrowser(true, true);
     }
--- a/browser/components/preferences/in-content/findInPage.js
+++ b/browser/components/preferences/in-content/findInPage.js
@@ -180,19 +180,17 @@ var gSearchResultsPane = {
   /**
    * Get the selection instance from given window
    *
    * @param Object win
    *   The window object points to frame's window
    */
   getFindSelection(win) {
     // Yuck. See bug 138068.
-    let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                      .getInterface(Ci.nsIWebNavigation)
-                      .QueryInterface(Ci.nsIDocShell);
+    let docShell = win.docShell;
 
     let controller = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
                               .getInterface(Ci.nsISelectionDisplay)
                               .QueryInterface(Ci.nsISelectionController);
 
     let selection = controller.getSelection(Ci.nsISelectionController.SELECTION_FIND);
     selection.setColors("currentColor", "#ffe900", "currentColor", "#003eaa");
 
--- a/browser/components/preferences/in-content/subdialogs.js
+++ b/browser/components/preferences/in-content/subdialogs.js
@@ -517,20 +517,17 @@ SubDialog.prototype = {
 
   _untrapFocus() {
     this._frame.contentDocument.removeEventListener("keydown", this, true);
     this._closeButton.removeEventListener("keydown", this);
     window.removeEventListener("focus", this);
   },
 
   _getBrowser() {
-    return window.QueryInterface(Ci.nsIInterfaceRequestor)
-                 .getInterface(Ci.nsIWebNavigation)
-                 .QueryInterface(Ci.nsIDocShell)
-                 .chromeEventHandler;
+    return window.docShell.chromeEventHandler;
   },
 };
 
 var gSubDialog = {
   /**
    * New dialogs are stacked on top of the existing ones, and they are pushed
    * to the end of the _dialogs array.
    * @type {Array}
--- a/browser/components/preferences/in-content/sync.js
+++ b/browser/components/preferences/in-content/sync.js
@@ -351,20 +351,17 @@ var gSyncPane = {
       return;
     }
     win.switchToTabHavingURI(url, true, options);
   },
 
   // Replace the current tab with the specified URL.
   replaceTabWithUrl(url) {
     // Get the <browser> element hosting us.
-    let browser = window.QueryInterface(Ci.nsIInterfaceRequestor)
-      .getInterface(Ci.nsIWebNavigation)
-      .QueryInterface(Ci.nsIDocShell)
-      .chromeEventHandler;
+    let browser = window.docShell.chromeEventHandler;
     // And tell it to load our URL.
     browser.loadURI(url);
   },
 
   async signIn() {
     const url = await FxAccounts.config.promiseSignInURI(this._getEntryPoint());
     this.replaceTabWithUrl(url);
   },
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_context_and_chromeFlags.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_context_and_chromeFlags.js
@@ -7,20 +7,18 @@
  * both the window's nsILoadContext, as well as on the initial
  * browser's content docShell nsILoadContext.
  *
  * @param win (nsIDOMWindow)
  *        An nsIDOMWindow in the parent process.
  * @return Promise
  */
 function assertWindowIsPrivate(win) {
-  let winDocShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDocShell);
-  let chromeFlags = winDocShell.QueryInterface(Ci.nsIDocShellTreeItem)
-                               .treeOwner
+  let winDocShell = win.docShell;
+  let chromeFlags = winDocShell.treeOwner
                                .QueryInterface(Ci.nsIInterfaceRequestor)
                                .getInterface(Ci.nsIXULWindow)
                                .chromeFlags;
 
   if (!win.gBrowser.selectedBrowser.hasContentOpener) {
     Assert.ok(chromeFlags & Ci.nsIWebBrowserChrome.CHROME_PRIVATE_WINDOW,
               "Should have the private window chrome flag");
   }
--- a/browser/components/sessionstore/SessionStorage.jsm
+++ b/browser/components/sessionstore/SessionStorage.jsm
@@ -68,19 +68,17 @@ var SessionStorageInternal = {
    *        A tab's global, i.e. the root frame we want to collect for.
    * @return Returns a nested object that will have hosts as keys and per-origin
    *         session storage data as strings. For example:
    *         {"https://example.com^userContextId=1": {"key": "value", "my_number": "123"}}
    */
   collect(content) {
     let data = {};
     let visitedOrigins = new Set();
-    let docShell = content.QueryInterface(Ci.nsIInterfaceRequestor)
-                          .getInterface(Ci.nsIWebNavigation)
-                          .QueryInterface(Ci.nsIDocShell);
+    let docShell = content.docShell;
 
     forEachNonDynamicChildFrame(content, frame => {
       let principal = getPrincipalForFrame(docShell, frame);
       if (!principal) {
         return;
       }
 
       // Get the origin of the current history entry
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -1685,21 +1685,17 @@ var SessionStoreInternal = {
     // the user can't start changing any window state while we're waiting
     // for the flushes to finish.
     for (let window of this._browserWindows) {
       windowPromises.set(window, TabStateFlusher.flushWindow(window));
 
       // We have to wait for these messages to come up from
       // each window and each browser. In the meantime, hide
       // the windows to improve perceived shutdown speed.
-      let baseWin = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                          .getInterface(Ci.nsIDocShell)
-                          .QueryInterface(Ci.nsIDocShellTreeItem)
-                          .treeOwner
-                          .QueryInterface(Ci.nsIBaseWindow);
+      let baseWin = window.docShell.treeOwner.QueryInterface(Ci.nsIBaseWindow);
       baseWin.visibility = false;
     }
 
     progress.total = windowPromises.size;
     progress.current = 0;
 
     // We'll iterate through the Promise array, yielding each one, so as to
     // provide useful progress information to AsyncShutdown.
@@ -4468,17 +4464,17 @@ var SessionStoreInternal = {
       let docElem = aWindow.document.documentElement;
       let attr = parseInt(docElem.getAttribute(aAttribute), 10);
       if (attr) {
         if (aAttribute != "width" && aAttribute != "height") {
           return attr;
         }
         // Width and height attribute report the inner size, but we want
         // to store the outer size, so add the difference.
-        let xulWin = aWindow.getInterface(Ci.nsIDocShell)
+        let xulWin = aWindow.docShell
                             .treeOwner
                             .QueryInterface(Ci.nsIInterfaceRequestor)
                             .getInterface(Ci.nsIXULWindow);
         let diff = aAttribute == "width"
           ? xulWin.outerToInnerWidthDifferenceInCSSPixels
           : xulWin.outerToInnerHeightDifferenceInCSSPixels;
         return attr + diff;
       }
--- a/browser/components/sessionstore/test/browser_docshell_uuid_consistency.js
+++ b/browser/components/sessionstore/test/browser_docshell_uuid_consistency.js
@@ -1,47 +1,44 @@
 // First test - open a tab and duplicate it, using session restore to restore the history into the new tab.
 add_task(async function duplicateTab() {
   const TEST_URL = "data:text/html,foo";
   let tab = BrowserTestUtils.addTab(gBrowser, TEST_URL);
   await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
 
   await ContentTask.spawn(tab.linkedBrowser, null, function() {
-    let docshell = content.window.QueryInterface(Ci.nsIInterfaceRequestor)
-                                 .getInterface(Ci.nsIWebNavigation)
-                                 .QueryInterface(Ci.nsIDocShell);
+    let docshell = content.window.docShell
+                                 .QueryInterface(Ci.nsIWebNavigation);
     let shEntry = docshell.sessionHistory.legacySHistory.getEntryAtIndex(0, false);
     is(shEntry.docshellID.toString(), docshell.historyID.toString());
   });
 
   let tab2 = gBrowser.duplicateTab(tab);
   await BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
 
   await ContentTask.spawn(tab2.linkedBrowser, null, function() {
-    let docshell = content.window.QueryInterface(Ci.nsIInterfaceRequestor)
-                                 .getInterface(Ci.nsIWebNavigation)
-                                 .QueryInterface(Ci.nsIDocShell);
+    let docshell = content.window.docShell
+                                 .QueryInterface(Ci.nsIWebNavigation);
     let shEntry = docshell.sessionHistory.legacySHistory.getEntryAtIndex(0, false);
     is(shEntry.docshellID.toString(), docshell.historyID.toString());
   });
 
   BrowserTestUtils.removeTab(tab);
   BrowserTestUtils.removeTab(tab2);
 });
 
 // Second test - open a tab and navigate across processes, which triggers sessionrestore to persist history.
 add_task(async function contentToChromeNavigate() {
   const TEST_URL = "data:text/html,foo";
   let tab = BrowserTestUtils.addTab(gBrowser, TEST_URL);
   await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
 
   await ContentTask.spawn(tab.linkedBrowser, null, function() {
-    let docshell = content.window.QueryInterface(Ci.nsIInterfaceRequestor)
-                                 .getInterface(Ci.nsIWebNavigation)
-                                 .QueryInterface(Ci.nsIDocShell);
+    let docshell = content.window.docShell
+                                 .QueryInterface(Ci.nsIWebNavigation);
     let sh = docshell.sessionHistory;
     is(sh.count, 1);
     is(sh.legacySHistory.getEntryAtIndex(0, false).docshellID.toString(), docshell.historyID.toString());
   });
 
   // Force the browser to navigate to the chrome process.
   await ContentTask.spawn(tab.linkedBrowser, null, function() {
     const CHROME_URL = "about:config";
--- a/browser/extensions/formautofill/FormAutofillContent.jsm
+++ b/browser/extensions/formautofill/FormAutofillContent.jsm
@@ -261,18 +261,17 @@ let ProfileAutocomplete = {
         }
         this._fillFromAutocompleteRow(FormAutofillContent.activeInput);
         break;
       }
     }
   },
 
   _frameMMFromWindow(contentWindow) {
-    return contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                        .getInterface(Ci.nsIDocShell)
+    return contentWindow.docShell
                         .QueryInterface(Ci.nsIInterfaceRequestor)
                         .getInterface(Ci.nsIContentFrameMessageManager);
   },
 
   _getSelectedIndex(contentWindow) {
     let mm = this._frameMMFromWindow(contentWindow);
     let selectedIndexResult = mm.sendSyncMessage("FormAutoComplete:GetSelectedIndex", {});
     if (selectedIndexResult.length != 1 || !Number.isInteger(selectedIndexResult[0])) {
@@ -626,19 +625,17 @@ var FormAutofillContent = {
     if (!field || ChromeUtils.getClassName(field) !== "HTMLInputElement") {
       return;
     }
 
     formFillController.markAsAutofillField(field);
   },
 
   _messageManagerFromWindow(win) {
-    return win.QueryInterface(Ci.nsIInterfaceRequestor)
-              .getInterface(Ci.nsIWebNavigation)
-              .QueryInterface(Ci.nsIDocShell)
+    return win.docShell
               .QueryInterface(Ci.nsIInterfaceRequestor)
               .getInterface(Ci.nsIContentFrameMessageManager);
   },
 
   _onKeyDown(e) {
     delete FormAutofillContent._keyDownEnterForInput;
     let lastAutoCompleteResult = ProfileAutocomplete.lastProfileAutoCompleteResult;
     let focusedInput = FormAutofillContent.activeInput;
--- a/browser/extensions/formautofill/content/FormAutofillFrameScript.js
+++ b/browser/extensions/formautofill/content/FormAutofillFrameScript.js
@@ -83,17 +83,17 @@ var FormAutofillFrameScript = {
   },
 
   receiveMessage(message) {
     if (!FormAutofill.isAutofillEnabled) {
       return;
     }
 
     const doc = content.document;
-    const {chromeEventHandler} = doc.ownerGlobal.getInterface(Ci.nsIDocShell);
+    const {chromeEventHandler} = doc.ownerGlobal.docShell;
 
     switch (message.name) {
       case "FormAutofill:PreviewProfile": {
         FormAutofillContent.previewProfile(doc);
         break;
       }
       case "FormAutofill:ClearForm": {
         FormAutofillContent.clearForm();
--- a/browser/extensions/mortar/host/pdf/ppapi-content-sandbox.js
+++ b/browser/extensions/mortar/host/pdf/ppapi-content-sandbox.js
@@ -256,19 +256,17 @@ mm.addMessageListener("ppapipdf.js:save"
     if ("nsIPrivateBrowsingChannel" in Ci &&
         channel instanceof Ci.nsIPrivateBrowsingChannel) {
       channel.setPrivate(docIsPrivate);
     }
 
     let listener = {
       extListener: null,
       onStartRequest(aRequest, aContext) {
-        var loadContext = containerWindow
-                            .QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIWebNavigation)
+        var loadContext = containerWindow.docShell
                             .QueryInterface(Ci.nsILoadContext);
         this.extListener = extHelperAppSvc.doContent(
           "application/pdf", aRequest, loadContext, false);
         this.extListener.onStartRequest(aRequest, aContext);
       },
       onStopRequest(aRequest, aContext, aStatusCode) {
         if (this.extListener) {
           this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
--- a/browser/extensions/pdfjs/content/PdfStreamConverter.jsm
+++ b/browser/extensions/pdfjs/content/PdfStreamConverter.jsm
@@ -263,19 +263,17 @@ class ChromeActions {
       if ("nsIPrivateBrowsingChannel" in Ci &&
           channel instanceof Ci.nsIPrivateBrowsingChannel) {
         channel.setPrivate(docIsPrivate);
       }
 
       var listener = {
         extListener: null,
         onStartRequest(aRequest, aContext) {
-          var loadContext = self.domWindow
-                                .QueryInterface(Ci.nsIInterfaceRequestor)
-                                .getInterface(Ci.nsIWebNavigation)
+          var loadContext = self.domWindow.docShell
                                 .QueryInterface(Ci.nsILoadContext);
           this.extListener = extHelperAppSvc.doContent(
             (data.isAttachment ? "application/octet-stream" :
                                  "application/pdf"),
             aRequest, loadContext, false);
           this.extListener.onStartRequest(aRequest, aContext);
         },
         onStopRequest(aRequest, aContext, aStatusCode) {
@@ -409,18 +407,17 @@ class ChromeActions {
     } else {
       message = getLocalizedString(strings, "unsupported_feature");
     }
     PdfJsTelemetry.onFallback();
     PdfjsContentUtils.displayWarning(domWindow, message,
       getLocalizedString(strings, "open_with_different_viewer"),
       getLocalizedString(strings, "open_with_different_viewer", "accessKey"));
 
-    let winmm = domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIDocShell)
+    let winmm = domWindow.docShell
                          .QueryInterface(Ci.nsIInterfaceRequestor)
                          .getInterface(Ci.nsIContentFrameMessageManager);
 
     winmm.addMessageListener("PDFJS:Child:fallbackDownload",
       function fallbackDownload(msg) {
         let data = msg.data;
         sendResponse(data.download);
 
@@ -437,18 +434,17 @@ class ChromeActions {
     var result = data.result;
     var findPrevious = data.findPrevious;
     var findPreviousType = typeof findPrevious;
     if ((typeof result !== "number" || result < 0 || result > 3) ||
         (findPreviousType !== "undefined" && findPreviousType !== "boolean")) {
       return;
     }
 
-    var winmm = this.domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                              .getInterface(Ci.nsIDocShell)
+    var winmm = this.domWindow.docShell
                               .QueryInterface(Ci.nsIInterfaceRequestor)
                               .getInterface(Ci.nsIContentFrameMessageManager);
 
     winmm.sendAsyncMessage("PDFJS:Parent:updateControlState", data);
   }
 
   setPreferences(prefs, sendResponse) {
     var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + ".");
@@ -754,18 +750,17 @@ class RequestListener {
 
 /**
  * Forwards events from the eventElement to the contentWindow only if the
  * content window matches the currently selected browser window.
  */
 class FindEventManager {
   constructor(contentWindow) {
     this.contentWindow = contentWindow;
-    this.winmm = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                              .getInterface(Ci.nsIDocShell)
+    this.winmm = contentWindow.docShell
                               .QueryInterface(Ci.nsIInterfaceRequestor)
                               .getInterface(Ci.nsIContentFrameMessageManager);
   }
 
   bind() {
     var unload = (evt) => {
       this.unbind();
       this.contentWindow.removeEventListener(evt.type, unload);
--- a/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm
+++ b/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm
@@ -86,18 +86,17 @@ var PdfjsContentUtils = {
   },
 
   /*
    * Request the display of a notification warning in the associated window
    * when the renderer isn't sure a pdf displayed correctly.
    */
   displayWarning(aWindow, aMessage, aLabel, aAccessKey) {
     // the child's dom frame mm associated with the window.
-    let winmm = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDocShell)
+    let winmm = aWindow.docShell
                        .QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIContentFrameMessageManager);
     winmm.sendAsyncMessage("PDFJS:Parent:displayWarning", {
       message: aMessage,
       label: aLabel,
       accessKey: aAccessKey,
     });
   },
--- a/browser/modules/BlockedSiteContent.jsm
+++ b/browser/modules/BlockedSiteContent.jsm
@@ -127,19 +127,17 @@ var BlockedSiteContent = {
     if (/e=malwareBlocked/.test(ownerDoc.documentURI)) {
       reason = "malware";
     } else if (/e=unwantedBlocked/.test(ownerDoc.documentURI)) {
       reason = "unwanted";
     } else if (/e=harmfulBlocked/.test(ownerDoc.documentURI)) {
       reason = "harmful";
     }
 
-    let docShell = ownerDoc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
-                                       .getInterface(Ci.nsIWebNavigation)
-                                      .QueryInterface(Ci.nsIDocShell);
+    let docShell = ownerDoc.defaultView.docShell;
 
     global.sendAsyncMessage("Browser:SiteBlockedError", {
       location: ownerDoc.location.href,
       reason,
       elementId: targetElement.getAttribute("id"),
       isTopFrame: (ownerDoc.defaultView.parent === ownerDoc.defaultView),
       blockedInfo: getSiteBlockedErrorDetails(docShell),
     });
--- a/browser/modules/ContentObservers.js
+++ b/browser/modules/ContentObservers.js
@@ -32,18 +32,17 @@ var gDecoderDoctorObserver = function(su
   let win = subject.top;
   let mm = getMessageManagerForWindow(win);
   if (mm) {
     mm.sendAsyncMessage("DecoderDoctor:Notification", data);
   }
 };
 
 function getMessageManagerForWindow(aContentWindow) {
-  let ir = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                         .getInterface(Ci.nsIDocShell)
+  let ir = aContentWindow.docShell
                          .sameTypeRootTreeItem
                          .QueryInterface(Ci.nsIInterfaceRequestor);
   try {
     // If e10s is disabled, this throws NS_NOINTERFACE for closed tabs.
     return ir.getInterface(Ci.nsIContentFrameMessageManager);
   } catch (e) {
     if (e.result == Cr.NS_NOINTERFACE) {
       return null;
--- a/browser/modules/ContentWebRTC.jsm
+++ b/browser/modules/ContentWebRTC.jsm
@@ -414,27 +414,20 @@ function getTabStateForContentWindow(aCo
   return tabState;
 }
 
 function getInnerWindowIDForWindow(aContentWindow) {
   return aContentWindow.windowUtils.currentInnerWindowID;
 }
 
 function getMessageManagerForWindow(aContentWindow) {
-  aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor);
-
-  let docShell;
-  try {
-    // This throws NS_NOINTERFACE for closed tabs.
-    docShell = aContentWindow.getInterface(Ci.nsIDocShell);
-  } catch (e) {
-    if (e.result == Cr.NS_NOINTERFACE) {
-      return null;
-    }
-    throw e;
+  let docShell = aContentWindow.docShell;
+  if (!docShell) {
+    // Closed tab.
+    return null;
   }
 
   let ir = docShell.sameTypeRootTreeItem
                    .QueryInterface(Ci.nsIInterfaceRequestor);
   try {
     // This throws NS_NOINTERFACE for closed tabs (only with e10s enabled).
     return ir.getInterface(Ci.nsIContentFrameMessageManager);
   } catch (e) {
--- a/browser/modules/FormSubmitObserver.jsm
+++ b/browser/modules/FormSubmitObserver.jsm
@@ -31,20 +31,18 @@ FormSubmitObserver.prototype =
   /*
    * Public apis
    */
 
   init(aWindow, aTabChildGlobal) {
     this._content = aWindow;
     this._tab = aTabChildGlobal;
     this._mm =
-      this._content.QueryInterface(Ci.nsIInterfaceRequestor)
-                   .getInterface(Ci.nsIDocShell)
+      this._content.docShell
                    .sameTypeRootTreeItem
-                   .QueryInterface(Ci.nsIDocShell)
                    .QueryInterface(Ci.nsIInterfaceRequestor)
                    .getInterface(Ci.nsIContentFrameMessageManager);
 
     this._tab.addEventListener("pageshow", this);
     this._tab.addEventListener("unload", this);
   },
 
   uninit() {
--- a/browser/modules/LightWeightThemeWebInstallListener.jsm
+++ b/browser/modules/LightWeightThemeWebInstallListener.jsm
@@ -46,14 +46,13 @@ var LightWeightThemeWebInstallListener =
 
   _resetPreviewWindow() {
     this._previewWindow.removeEventListener("pagehide", this, true);
     this._previewWindow = null;
   }
 };
 
 function getMessageManagerForContent(content) {
-  return content.QueryInterface(Ci.nsIInterfaceRequestor)
-                .getInterface(Ci.nsIDocShell)
+  return content.docShell
                 .sameTypeRootTreeItem
                 .QueryInterface(Ci.nsIInterfaceRequestor)
                 .getInterface(Ci.nsIContentFrameMessageManager);
 }
--- a/browser/modules/LightweightThemeChildHelper.jsm
+++ b/browser/modules/LightweightThemeChildHelper.jsm
@@ -36,18 +36,17 @@ var LightweightThemeChildHelper = {
   /**
    * Update the theme data for the whole process
    * @param {Array} changedKeys The sharedData keys that were changed.
    */
   _updateProcess(changedKeys) {
     const windowEnumerator = Services.ww.getWindowEnumerator();
     while (windowEnumerator.hasMoreElements()) {
       const window = windowEnumerator.getNext().QueryInterface(Ci.nsIDOMWindow);
-      const tabChildGlobal = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                                   .getInterface(Ci.nsIDocShell)
+      const tabChildGlobal = window.docShell
                                    .sameTypeRootTreeItem
                                    .QueryInterface(Ci.nsIInterfaceRequestor)
                                    .getInterface(Ci.nsIContentFrameMessageManager);
       const {chromeOuterWindowID, content} = tabChildGlobal;
       if (changedKeys.includes(`theme/${chromeOuterWindowID}`) &&
           content && this.whitelist.has(content.document.documentURI)) {
         this.update(chromeOuterWindowID, content);
       }
--- a/browser/modules/PermissionUI.jsm
+++ b/browser/modules/PermissionUI.jsm
@@ -403,22 +403,17 @@ var PermissionPromptForRequestPrototype 
 
   get browser() {
     // In the e10s-case, the <xul:browser> will be at request.element.
     // In the single-process case, we have to use some XPCOM incantations
     // to resolve to the <xul:browser>.
     if (this.request.element) {
       return this.request.element;
     }
-    return this.request
-               .window
-               .QueryInterface(Ci.nsIInterfaceRequestor)
-               .getInterface(Ci.nsIWebNavigation)
-               .QueryInterface(Ci.nsIDocShell)
-               .chromeEventHandler;
+    return this.request.window.docShell.chromeEventHandler;
   },
 
   get principal() {
     return this.request.principal;
   },
 
   cancel() {
     this.request.cancel();
--- a/browser/modules/WindowsPreviewPerTab.jsm
+++ b/browser/modules/WindowsPreviewPerTab.jsm
@@ -424,20 +424,17 @@ TabWindow.prototype = {
     this.previews.set(tab, controller.preview);
     AeroPeek.addPreview(controller.preview);
     // updateTitleAndTooltip relies on having controller.preview which is lazily resolved.
     // Now that we've updated this.previews, it will resolve successfully.
     controller.updateTitleAndTooltip();
   },
 
   createTabPreview(controller) {
-    let docShell = this.win
-                  .QueryInterface(Ci.nsIInterfaceRequestor)
-                  .getInterface(Ci.nsIWebNavigation)
-                  .QueryInterface(Ci.nsIDocShell);
+    let docShell = this.win.docShell;
     let preview = AeroPeek.taskbar.createTaskbarTabPreview(docShell, controller);
     preview.visible = AeroPeek.enabled;
     preview.active = this.tabbrowser.selectedTab == controller.tab;
     this.onLinkIconAvailable(controller.tab.linkedBrowser,
                              controller.tab.getAttribute("image"));
     return preview;
   },
 
--- a/browser/tools/mozscreenshots/browser_boundingbox.js
+++ b/browser/tools/mozscreenshots/browser_boundingbox.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 "use strict";
 
 add_task(async function() {
-  const scale = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                      .getInterface(Ci.nsIDocShell).QueryInterface(Ci.nsIBaseWindow)
+  const scale = window.docShell
+                      .QueryInterface(Ci.nsIBaseWindow)
                       .devicePixelsPerDesktopPixel;
   let {bounds, rects} = TestRunner._findBoundingBox(["#tabbrowser-tabs"]);
   let element = document.querySelector("#tabbrowser-tabs");
   let tabBar = element.ownerDocument.getBoxObjectFor(element);
 
   // Calculate expected values
   let expectedLeft = scale * (tabBar.screenX - TestRunner.croppingPadding);
   let expectedTop = scale * (tabBar.screenY - TestRunner.croppingPadding);