Merge inbound to mozilla-central r=merge a=merge
authorTiberius Oros <toros@mozilla.com>
Fri, 24 Nov 2017 00:28:29 +0200
changeset 702882 3f5d48c08903475b5f556f3d5906773978b30489
parent 702877 b705100d6ca823ddafe43ba4188dce181dcd79fd (current diff)
parent 702881 d4f80c4ba719d375e3b6d81a2fdd58007475f53c (diff)
child 702883 e83e5a736b88279a4c0a88db84149058d2fae295
child 702914 304c979214d49817cd414ed2347ba960561eed84
child 702916 4f35bcb5940d28a5fb9166f65465acb168a717de
child 702918 2424d63af20dce66a99a4b7c8416aecee3cce42c
child 702924 7cac0855a4421a46d9213a48e0969ca99f645482
child 702929 44237d734d181df91f3a5f3f3c43ad9e162c2c71
child 702936 0bbde3d72e702fe06528d7e31b2bb259c09e90dd
child 702939 ded008970206c0606bd23c0f7743cc58902f9f15
child 702952 a71b1b5284937149e7cc22c9ee16b7d3dc49e344
child 702953 e3bf6edbc94a9c9327c582511d31d21c1f7054d1
child 702962 1cfa45459df19dcadc3a2699752a57e433732456
child 702964 6b4dec6603bf33790f40da5ddd4f0ab411f3d010
child 702987 10f62a7bce04019d0b6c4a2ca113ec91d8f03d24
child 702994 b2c80e2b88b2a81075814c9e20c30963fa78595d
child 702997 bcba7165731376199cc5a1433f9923284f073f7b
child 702998 9471af6283faeeb4f81c1ba54e91f562f889cb07
child 703003 d291547bf746ca77e6737b92bee763a71d4bcfae
child 703004 59d3aca20bb5de4eb52d8bc06be0020d9341fabb
child 703005 551fae0db4c2322a812cfccd54b6c227ad6b5196
child 703012 70f1e69cca25af0b82c618df24c824c42c916e54
child 703013 ddd54c5c0756e983582a6623046e0cc8234722aa
child 703014 d8fe9228c6a1ff9d538cc7fe7469e6bb986a405f
child 703017 25266fa2b076afdecaded309234ac89cc174be48
child 703022 4e51cdeefdac112f878ac7be3217ba09c3b550a5
child 703028 f2946b1bc8fa18c4a76df80d31b6a621bc1e29cb
child 703051 cf23ff80be8335364a0e4d09399e37fb9d42afe0
child 703052 a530f27567a9deb667fe540bced40658d281dcc0
child 703053 1f6fbd7b20f1f78cd8e28625b3433f0dd35e21cc
child 703062 915c6444c476372d9e100edb37d00dc4eb2e953f
child 703063 c5ab7edfb49305ecdd982fe7840bf9d7308fc130
child 703064 5545adc8df469fc0b7a571fcc7215f51c82e77ac
child 703067 025518c20393749f9c1528fde3898512352c7f75
child 703074 e098330f9b5345db353ec6630ccdb315100ee71d
child 703079 b169aecdb7039956d625883a035cf7c55f001d86
child 703081 e51a7bda5c192d604e45389b59c44ebdf5bcbeff
child 703090 1221ac5d4523deb99df1aab4ab9b2758adf78f3b
child 703091 879a501b27400b90e68dfa2fd47f37a1562ecc4a
child 703095 a4213db42c169a856bd61d534b6a4f7b846e2d3a
child 703113 88f353b08c571d71eac3f3c0b024b54fb677cefc
child 703145 0fdc354319bc4f4d50c2145b0249ba48b28dcd87
child 703146 a63d5306da8428bd62e716e76cc03520b87582a1
child 703147 8ef3b90e0264508c70c62584ee4ce78ff3c193a7
child 703150 5d823cdd99f51de5c248bbb33842d58b59c1003f
child 703154 e78a0f9cadf16d6689d856f7c68839d91c0bb818
child 703162 5482a1a3cfee4351402acc357c30dcd92c697521
child 703182 c59ef89a762ee9b01585c3816d73054ad00e606e
child 703186 0109c10a7b5de386d8d899c9074e40f52f32fb04
child 703195 063d415939348a0fda12129b46fdbd07244bb0e0
child 703208 175e775302b4174dd9a71dfe7523dde4164de7b8
child 703382 ae300300eb89f0a05c05d4201816d22512f9f765
child 703444 f00ad029aea6b65502377832192f0a087c7a9de4
child 703573 239a6d1fd4ccf33d5e410984db48646a5d69e833
child 703591 3170001627c3ca2ed141de0250fcaf60fbaea986
child 703593 3762591d91e4d81eb4509745bb5f8a1666cecdab
child 704198 f5bab54eb81f87303aa889b7dc6ab9e251fba3d7
child 704946 6de389a4704a59bcf961e40084821022e0969a0e
child 704987 1f08c9d62e164e73630e43af3e5c2ebd2b116baf
child 704988 e6178a1549c9c3410ba6cc6ccdc3f6ec1421f186
child 706755 90ccc9b180df7223977cbe1c1790bc8a72a5cdf0
push id90623
push userbmo:giles@thaumas.net
push dateThu, 23 Nov 2017 23:00:33 +0000
reviewersmerge, merge
milestone59.0a1
Merge inbound to mozilla-central r=merge a=merge
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/nsGlobalWindow.cpp
modules/libpref/init/all.js
security/sandbox/chromium/base/numerics/safe_math_impl.h
security/sandbox/chromium/base/time/time_posix.cc
security/sandbox/chromium/sandbox/win/src/process_mitigations_test.cc
security/sandbox/modifications-to-chromium-to-reapply-after-upstream-merge.txt
security/sandbox/moz-chromium-commit-status.txt
--- a/.cron.yml
+++ b/.cron.yml
@@ -93,16 +93,28 @@ jobs:
           target-tasks-method: nightly_dmd
       run-on-projects:
           - mozilla-central
       when:
           by-project:
               mozilla-central: [{hour: 10, minute: 0}]
               # No default
 
+    - name: searchfox-index
+      job:
+          type: decision-task
+          treeherder-symbol: Searchfox
+          target-tasks-method: searchfox_index
+      run-on-projects:
+          - mozilla-central
+      when:
+          by-project:
+              mozilla-central: [{hour: 10, minute: 30}]
+              # No default
+
     - name: periodic-update
       job:
           type: decision-task
           treeherder-symbol: Nfile
           target-tasks-method: file_update
       run-on-projects:
           - mozilla-central
       when:
--- a/browser/base/content/browser-pageActions.js
+++ b/browser/base/content/browser-pageActions.js
@@ -15,17 +15,17 @@ var BrowserPageActions = {
    * The main page action panel DOM node (DOM node)
    */
   get panelNode() {
     delete this.panelNode;
     return this.panelNode = document.getElementById("pageActionPanel");
   },
 
   /**
-   * The photonmultiview node in the main page action panel (DOM node)
+   * The panelmultiview node in the main page action panel (DOM node)
    */
   get multiViewNode() {
     delete this.multiViewNode;
     return this.multiViewNode = document.getElementById("pageActionPanelMultiView");
   },
 
   /**
    * The main panelview node in the main page action panel (DOM node)
@@ -229,17 +229,17 @@ var BrowserPageActions = {
     if (this._disablePanelAnimations) {
       panelNode.setAttribute("animate", "false");
     }
 
     let panelViewNode = null;
     let iframeNode = null;
 
     if (action.subview) {
-      let multiViewNode = document.createElement("photonpanelmultiview");
+      let multiViewNode = document.createElement("panelmultiview");
       panelViewNode = this._makePanelViewNodeForAction(action, true);
       multiViewNode.appendChild(panelViewNode);
       panelNode.appendChild(multiViewNode);
     } else if (action.wantsIframe) {
       iframeNode = document.createElement("iframe");
       iframeNode.setAttribute("type", "content");
       panelNode.appendChild(iframeNode);
     }
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -66,42 +66,27 @@ toolbar[customizable="true"] {
 #toolbar-menubar[autohide="true"] {
   -moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar-menubar-autohide");
 }
 
 panelmultiview {
   -moz-binding: url("chrome://browser/content/customizableui/panelUI.xml#panelmultiview");
 }
 
-photonpanelmultiview {
-  -moz-binding: url("chrome://browser/content/customizableui/panelUI.xml#photonpanelmultiview");
-}
-
 panelview {
   -moz-binding: url("chrome://browser/content/customizableui/panelUI.xml#panelview");
   -moz-box-orient: vertical;
 }
 
 panel[hidden] panelmultiview,
-panel[hidden] photonpanelmultiview,
 panel[hidden] panelview {
   -moz-binding: none;
 }
 
-.panel-mainview {
-  transition: transform var(--panelui-subview-transition-duration);
-}
-
-panelview:not([mainview]):not([current]):not([in-transition]) {
-  transition: visibility 0s linear var(--panelui-subview-transition-duration);
-  visibility: collapse;
-}
-
-photonpanelmultiview panelview:not([current]):not([in-transition]) {
-  transition: none;
+panelview:not([current]):not([in-transition]) {
   visibility: collapse;
 }
 
 panelview[mainview] > .panel-header,
 panelview:not([title]) > .panel-header {
   display: none;
 }
 
@@ -1065,22 +1050,16 @@ html|*#gcli-output-frame,
   -moz-box-pack: center;
 }
 
 /* Translation */
 notification[value="translation"] {
   -moz-binding: url("chrome://browser/content/translation-infobar.xml#translationbar");
 }
 
-/** See bug 872317 for why the following rule is necessary. */
-
-#downloads-button {
-  -moz-binding: url("chrome://browser/content/downloads/download.xml#download-toolbarbutton");
-}
-
 /*** Visibility of downloads indicator controls ***/
 
 /* Bug 924050: If we've loaded the indicator, for now we hide it in the menu panel,
    and just show the icon. This is a hack to side-step very weird layout bugs that
    seem to be caused by the indicator stack interacting with the menu panel. */
 #downloads-button[indicator]:not([cui-areatype="menu-panel"]) > .toolbarbutton-badge-stack > image.toolbarbutton-icon,
 #downloads-button[indicator][cui-areatype="menu-panel"] > #downloads-indicator-anchor {
   display: none;
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -412,25 +412,25 @@
            photon="true"
            position="bottomcenter topright"
            tabspecific="true"
            noautofocus="true"
            copyURL-title="&pageAction.copyLink.label;"
            emailLink-title="&emailPageCmd.label;"
            sendToDevice-title="&pageAction.sendTabToDevice.label;"
            sendToDevice-notReadyTitle="&sendToDevice.syncNotReady.label;">
-      <photonpanelmultiview id="pageActionPanelMultiView"
-                            mainViewId="pageActionPanelMainView"
-                            viewCacheId="appMenu-viewCache">
+      <panelmultiview id="pageActionPanelMultiView"
+                      mainViewId="pageActionPanelMainView"
+                      viewCacheId="appMenu-viewCache">
         <panelview id="pageActionPanelMainView"
                    context="pageActionContextMenu"
                    class="PanelUI-subView">
           <vbox class="panel-subview-body"/>
         </panelview>
-      </photonpanelmultiview>
+      </panelmultiview>
     </panel>
     <panel id="pageActionFeedback"
            role="alert"
            type="arrow"
            hidden="true"
            flip="slide"
            position="bottomcenter topright"
            tabspecific="true"
--- a/browser/components/controlcenter/content/panel.inc.xul
+++ b/browser/components/controlcenter/content/panel.inc.xul
@@ -11,18 +11,18 @@
        onpopuphidden="gIdentityHandler.onPopupHidden(event);"
        orient="vertical">
 
   <broadcasterset>
     <broadcaster id="identity-popup-mcb-learn-more" class="text-link plain" value="&identity.learnMore;"/>
     <broadcaster id="identity-popup-insecure-login-forms-learn-more" class="text-link plain" value="&identity.learnMore;"/>
   </broadcasterset>
 
-  <photonpanelmultiview id="identity-popup-multiView"
-                        mainViewId="identity-popup-mainView">
+  <panelmultiview id="identity-popup-multiView"
+                  mainViewId="identity-popup-mainView">
     <panelview id="identity-popup-mainView"
                descriptionheightworkaround="true">
       <!-- Security Section -->
       <hbox id="identity-popup-security" class="identity-popup-section">
         <vbox class="identity-popup-security-content" flex="1">
           <label class="plain">
             <label class="identity-popup-headline identity-popup-host"></label>
             <label class="identity-popup-headline identity-popup-hostless" crop="end"/>
@@ -179,10 +179,10 @@
 
       <vbox id="identity-popup-securityView-footer">
         <!-- More Security Information -->
         <button label="&identity.moreInfoLinkText2;"
                 oncommand="gIdentityHandler.handleMoreInfoClick(event);"/>
       </vbox>
 
     </panelview>
-  </photonpanelmultiview>
+  </panelmultiview>
 </panel>
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -1615,17 +1615,17 @@ var CustomizableUIInternal = {
     } else if (aWidget.type == "view") {
       let ownerWindow = aNode.ownerGlobal;
       let area = this.getPlacementOfWidget(aNode.id).area;
       let areaType = CustomizableUI.getAreaType(area);
       let anchor = aNode;
       if (areaType != CustomizableUI.TYPE_MENU_PANEL) {
         let wrapper = this.wrapWidget(aWidget.id).forWindow(ownerWindow);
 
-        let hasMultiView = !!aNode.closest("photonpanelmultiview,panelmultiview");
+        let hasMultiView = !!aNode.closest("panelmultiview");
         if (wrapper && !hasMultiView && wrapper.anchor) {
           this.hidePanelForNode(aNode);
           anchor = wrapper.anchor;
         }
       }
 
       ownerWindow.PanelUI.showSubView(aWidget.viewId, anchor, aEvent);
     }
@@ -1799,23 +1799,19 @@ var CustomizableUIInternal = {
       target = target.parentNode;
     }
     if (closemenu == "none" || widgetType == "view") {
       return;
     }
 
     if (closemenu == "single") {
       let panel = this._getPanelForNode(target);
-      let multiview = panel.querySelector("photonpanelmultiview,panelmultiview");
+      let multiview = panel.querySelector("panelmultiview");
       if (multiview.showingSubView) {
-        if (multiview.instance.panelViews) {
-          multiview.goBack();
-        } else {
-          multiview.showMainView();
-        }
+        multiview.goBack();
         return;
       }
     }
 
     // If we get here, we can actually hide the popup:
     this.hidePanelForNode(aEvent.target);
   },
 
@@ -4298,25 +4294,20 @@ OverflowableToolbar.prototype = {
 
   show(aEvent) {
     if (this._panel.state == "open") {
       return Promise.resolve();
     }
     return new Promise(resolve => {
       let doc = this._panel.ownerDocument;
       this._panel.hidden = false;
-      let photonView = this._panel.querySelector("photonpanelmultiview");
-      let contextMenu;
-      if (photonView) {
-        let mainViewId = photonView.getAttribute("mainViewId");
-        let mainView = doc.getElementById(mainViewId);
-        contextMenu = doc.getElementById(mainView.getAttribute("context"));
-      } else {
-        contextMenu = doc.getElementById(this._panel.getAttribute("context"));
-      }
+      let multiview = this._panel.querySelector("panelmultiview");
+      let mainViewId = multiview.getAttribute("mainViewId");
+      let mainView = doc.getElementById(mainViewId);
+      let contextMenu = doc.getElementById(mainView.getAttribute("context"));
       gELS.addSystemEventListener(contextMenu, "command", this, true);
       let anchor = doc.getAnonymousElementByAttribute(this._chevron, "class", "toolbarbutton-icon");
       // Ensure we update the gEditUIVisible flag when opening the popup, in
       // case the edit controls are in it.
       this._panel.addEventListener("popupshowing", () => doc.defaultView.updateEditUIVisibility(), {once: true});
       this._panel.openPopup(anchor || this._chevron, { triggerEvent: aEvent });
       this._chevron.open = true;
 
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -161,17 +161,17 @@ this.PanelMultiView = class {
     return this.node.ownerGlobal;
   }
 
   get _panel() {
     return this.node.parentNode;
   }
 
   get showingSubView() {
-    return this.node.getAttribute("viewtype") == "subview";
+    return this._showingSubView;
   }
   get _mainViewId() {
     return this.node.getAttribute("mainViewId");
   }
   set _mainViewId(val) {
     this.node.setAttribute("mainViewId", val);
     return val;
   }
@@ -196,21 +196,16 @@ this.PanelMultiView = class {
    *                   that this instance should be ready to be thrown away at
    *                   any time.
    */
   get _ephemeral() {
     return this.node.hasAttribute("ephemeral");
   }
 
   get panelViews() {
-    // If there's a dedicated subViews container, we're not in the right binding
-    // to use SlidingPanelViews.
-    if (this._subViews)
-      return null;
-
     if (this._panelViews)
       return this._panelViews;
 
     this._panelViews = new SlidingPanelViews();
     this._panelViews.push(...this.node.getElementsByTagName("panelview"));
     return this._panelViews;
   }
   get _dwu() {
@@ -229,24 +224,20 @@ this.PanelMultiView = class {
    * @return {panelview} the currently visible subview OR the subview that is
    *                     about to be shown whilst a 'ViewShowing' event is being
    *                     dispatched.
    */
   get current() {
     return this._viewShowing || this._currentSubView;
   }
   get _currentSubView() {
-    return this.panelViews ? this.panelViews.currentView : this.__currentSubView;
+    return this.panelViews.currentView;
   }
   set _currentSubView(panel) {
-    if (this.panelViews)
-      this.panelViews.currentView = panel;
-    else
-      this.__currentSubView = panel;
-    return panel;
+    this.panelViews.currentView = panel;
   }
   /**
    * @return {Promise} showSubView() returns a promise, which is kept here for
    *                   random access.
    */
   get currentShowPromise() {
     return this._currentShowPromise || Promise.resolve();
   }
@@ -263,62 +254,46 @@ this.PanelMultiView = class {
 
   constructor(xulNode, testMode = false) {
     this.node = xulNode;
     // If `testMode` is `true`, the consumer is only interested in accessing the
     // methods of this instance. (E.g. in unit tests.)
     if (testMode)
       return;
 
-    this._currentSubView = this._anchorElement = this._subViewObserver = null;
+    this._currentSubView = this._subViewObserver = null;
     this._mainViewHeight = 0;
-    this.__transitioning = this._ignoreMutations = false;
+    this.__transitioning = this._ignoreMutations = this._showingSubView = false;
 
     const {document, window} = this;
 
-    this._clickCapturer =
-      document.getAnonymousElementByAttribute(this.node, "anonid", "clickCapturer");
     this._viewContainer =
       document.getAnonymousElementByAttribute(this.node, "anonid", "viewContainer");
-    this._mainViewContainer =
-      document.getAnonymousElementByAttribute(this.node, "anonid", "mainViewContainer");
-    this._subViews =
-      document.getAnonymousElementByAttribute(this.node, "anonid", "subViews");
     this._viewStack =
       document.getAnonymousElementByAttribute(this.node, "anonid", "viewStack");
     this._offscreenViewStack =
       document.getAnonymousElementByAttribute(this.node, "anonid", "offscreenViewStack");
 
     XPCOMUtils.defineLazyGetter(this, "_panelViewCache", () => {
       let viewCacheId = this.node.getAttribute("viewCacheId");
       return viewCacheId ? document.getElementById(viewCacheId) : null;
     });
 
     this._panel.addEventListener("popupshowing", this);
     this._panel.addEventListener("popuppositioned", this);
     this._panel.addEventListener("popuphidden", this);
     this._panel.addEventListener("popupshown", this);
-    if (this.panelViews) {
-      let cs = window.getComputedStyle(document.documentElement);
-      // Set CSS-determined attributes now to prevent a layout flush when we do
-      // it when transitioning between panels.
-      this._dir = cs.direction;
-      this.setMainView(this.panelViews.currentView);
-      this.showMainView();
-    } else {
-      this._clickCapturer.addEventListener("click", this);
+    let cs = window.getComputedStyle(document.documentElement);
+    // Set CSS-determined attributes now to prevent a layout flush when we do
+    // it when transitioning between panels.
+    this._dir = cs.direction;
+    this.setMainView(this.panelViews.currentView);
+    this.showMainView();
 
-      this._mainViewContainer.setAttribute("panelid", this._panel.id);
-
-      if (this._mainView) {
-        this.setMainView(this._mainView);
-      }
-    }
-
-    this.node.setAttribute("viewtype", "main");
+    this._showingSubView = false;
 
     // Proxy these public properties and methods, as used elsewhere by various
     // parts of the browser, to this instance.
     ["_mainView", "ignoreMutations", "showingSubView",
      "_panelViews"].forEach(property => {
       Object.defineProperty(this.node, property, {
         enumerable: true,
         get: () => this[property],
@@ -349,34 +324,27 @@ this.PanelMultiView = class {
     if (this._ephemeral)
       this.hideAllViewsExcept(null);
     let mainView = this._mainView;
     if (mainView) {
       if (this._panelViewCache)
         this._panelViewCache.appendChild(mainView);
       mainView.removeAttribute("mainview");
     }
-    if (this._subViews)
-      this._moveOutKids(this._subViews);
 
-    if (this.panelViews) {
-      this._moveOutKids(this._viewStack);
-      this.panelViews.clear();
-    } else {
-      this._clickCapturer.removeEventListener("click", this);
-    }
+    this._moveOutKids(this._viewStack);
+    this.panelViews.clear();
     this._panel.removeEventListener("mousemove", this);
     this._panel.removeEventListener("popupshowing", this);
     this._panel.removeEventListener("popuppositioned", this);
     this._panel.removeEventListener("popupshown", this);
     this._panel.removeEventListener("popuphidden", this);
     this.window.removeEventListener("keydown", this);
-    this.node = this._clickCapturer = this._viewContainer = this._mainViewContainer =
-      this._subViews = this._viewStack = this.__dwu = this._panelViewCache =
-        this._transitionDetails = null;
+    this.node = this._viewContainer = this._viewStack = this.__dwu =
+      this._panelViewCache = this._transitionDetails = null;
   }
 
   /**
    * Remove any child subviews into the panelViewCache, to ensure
    * they remain usable even if this panelmultiview instance is removed
    * from the DOM.
    * @param viewNodeContainer the container from which to remove subviews
    */
@@ -390,23 +358,19 @@ this.PanelMultiView = class {
     for (let subview of subviews) {
       // XBL lists the 'children' XBL element explicitly. :-(
       if (subview.nodeName != "children")
         this._panelViewCache.appendChild(subview);
     }
   }
 
   _placeSubView(viewNode) {
-    if (this.panelViews) {
-      this._viewStack.appendChild(viewNode);
-      if (!this.panelViews.includes(viewNode))
-        this.panelViews.push(viewNode);
-    } else {
-      this._subViews.appendChild(viewNode);
-    }
+    this._viewStack.appendChild(viewNode);
+    if (!this.panelViews.includes(viewNode))
+      this.panelViews.push(viewNode);
   }
 
   goBack(target) {
     let [current, previous] = this.panelViews.back();
     return this.showSubView(current, target, previous);
   }
 
   /**
@@ -420,52 +384,33 @@ this.PanelMultiView = class {
     return view.id != this._mainViewId;
   }
 
   setMainView(aNewMainView) {
     if (!aNewMainView)
       return;
 
     if (this._mainView) {
-      if (!this.panelViews)
-        this._subViews.appendChild(this._mainView);
       this._mainView.removeAttribute("mainview");
     }
     this._mainViewId = aNewMainView.id;
     aNewMainView.setAttribute("mainview", "true");
-    if (this.panelViews) {
-      // If the new main view is not yet in the zeroth position, make sure it's
-      // inserted there.
-      if (aNewMainView.parentNode != this._viewStack && this._viewStack.firstChild != aNewMainView) {
-        this._viewStack.insertBefore(aNewMainView, this._viewStack.firstChild);
-      }
-    } else {
-      this._mainViewContainer.appendChild(aNewMainView);
+    // If the new main view is not yet in the zeroth position, make sure it's
+    // inserted there.
+    if (aNewMainView.parentNode != this._viewStack &&
+        this._viewStack.firstChild != aNewMainView) {
+      this._viewStack.insertBefore(aNewMainView, this._viewStack.firstChild);
     }
   }
 
   showMainView() {
     if (!this._mainViewId)
       return Promise.resolve();
 
-    if (this.panelViews)
-      return this.showSubView(this._mainView);
-
-    if (this.showingSubView) {
-      let viewNode = this._currentSubView;
-      this._dispatchViewEvent(viewNode, "ViewHiding");
-      this._transitionHeight(() => {
-        viewNode.removeAttribute("current");
-        this._currentSubView = null;
-        this.node.setAttribute("viewtype", "main");
-      });
-    }
-
-    this._shiftMainView();
-    return Promise.resolve();
+    return this.showSubView(this._mainView);
   }
 
   /**
    * Ensures that all the panelviews, that are currently part of this instance,
    * are hidden, except one specifically.
    *
    * @param {panelview} [theOne] The panelview DOM node to ensure is visible.
    *                             Optional.
@@ -486,17 +431,17 @@ this.PanelMultiView = class {
       return;
 
     this._currentSubView = theOne;
     if (!theOne.hasAttribute("current")) {
       theOne.setAttribute("current", true);
       this.descriptionHeightWorkaround(theOne);
       this._dispatchViewEvent(theOne, "ViewShown");
     }
-    this.node.setAttribute("viewtype", (theOne.id == this._mainViewId) ? "main" : "subview");
+    this._showingSubView = theOne.id != this._mainViewId;
   }
 
   showSubView(aViewId, aAnchor, aPreviousView) {
     this._currentShowPromise = (async () => {
       // Support passing in the node directly.
       let viewNode = typeof aViewId == "string" ? this.node.querySelector("#" + aViewId) : aViewId;
       if (!viewNode) {
         viewNode = this.document.getElementById(aViewId);
@@ -512,54 +457,49 @@ this.PanelMultiView = class {
       let reverse = !!aPreviousView;
       let previousViewNode = aPreviousView || this._currentSubView;
       // If the panelview to show is the same as the previous one, the 'ViewShowing'
       // event has already been dispatched. Don't do it twice.
       let showingSameView = viewNode == previousViewNode;
       let playTransition = (!!previousViewNode && !showingSameView && this._panel.state == "open");
       let isMainView = viewNode.id == this._mainViewId;
 
-      let dwu, previousRect;
-      if (playTransition || this.panelViews) {
-        dwu = this._dwu;
-        previousRect = previousViewNode.__lastKnownBoundingRect =
+      let dwu = this._dwu;
+      let previousRect = previousViewNode.__lastKnownBoundingRect =
           dwu.getBoundsWithoutFlushing(previousViewNode);
-        if (this.panelViews) {
-          // Cache the measures that have the same caching lifetime as the width
-          // or height of the main view, i.e. whilst the panel is shown and/ or
-          // visible.
-          if (!this._mainViewWidth) {
-            this._mainViewWidth = previousRect.width;
-            let top = dwu.getBoundsWithoutFlushing(previousViewNode.firstChild || previousViewNode).top;
-            let bottom = dwu.getBoundsWithoutFlushing(previousViewNode.lastChild || previousViewNode).bottom;
-            this._viewVerticalPadding = previousRect.height - (bottom - top);
-          }
-          if (!this._mainViewHeight) {
-            this._mainViewHeight = previousRect.height;
-            this._viewContainer.style.minHeight = this._mainViewHeight + "px";
-          }
-        }
+      // Cache the measures that have the same caching lifetime as the width
+      // or height of the main view, i.e. whilst the panel is shown and/ or
+      // visible.
+      if (!this._mainViewWidth) {
+        this._mainViewWidth = previousRect.width;
+        let top = dwu.getBoundsWithoutFlushing(previousViewNode.firstChild || previousViewNode).top;
+        let bottom = dwu.getBoundsWithoutFlushing(previousViewNode.lastChild || previousViewNode).bottom;
+        this._viewVerticalPadding = previousRect.height - (bottom - top);
+      }
+      if (!this._mainViewHeight) {
+        this._mainViewHeight = previousRect.height;
+        this._viewContainer.style.minHeight = this._mainViewHeight + "px";
       }
 
       this._viewShowing = viewNode;
       // Because the 'mainview' attribute may be out-of-sync, due to view node
       // reparenting in combination with ephemeral PanelMultiView instances,
       // this is the best place to correct it (just before showing).
       if (isMainView)
         viewNode.setAttribute("mainview", true);
       else
         viewNode.removeAttribute("mainview");
 
       // Make sure that new panels always have a title set.
-      if (this.panelViews && aAnchor) {
+      if (aAnchor) {
         if (!viewNode.hasAttribute("title"))
           viewNode.setAttribute("title", aAnchor.getAttribute("label"));
         viewNode.classList.add("PanelUI-subView");
       }
-      if (this.panelViews && !isMainView && this._mainViewWidth)
+      if (!isMainView && this._mainViewWidth)
         viewNode.style.maxWidth = viewNode.style.minWidth = this._mainViewWidth + "px";
 
       if (!showingSameView || !viewNode.hasAttribute("current")) {
         // Emit the ViewShowing event so that the widget definition has a chance
         // to lazily populate the subview with things or perhaps even cancel this
         // whole operation.
         let detail = {
           blockers: new Set(),
@@ -579,41 +519,24 @@ this.PanelMultiView = class {
         }
 
         if (cancel) {
           this._viewShowing = null;
           return;
         }
       }
 
-      // Now we have to transition the panel.
-      if (this.panelViews) {
-        // If we've got an older transition still running, make sure to clean it up.
-        await this._cleanupTransitionPhase();
-        if (playTransition) {
-          await this._transitionViews(previousViewNode, viewNode, reverse, previousRect, aAnchor);
-          this._updateKeyboardFocus(viewNode);
-        } else {
-          this.hideAllViewsExcept(viewNode);
-        }
+      // Now we have to transition the panel. If we've got an older transition
+      // still running, make sure to clean it up.
+      await this._cleanupTransitionPhase();
+      if (playTransition) {
+        await this._transitionViews(previousViewNode, viewNode, reverse, previousRect, aAnchor);
+        this._updateKeyboardFocus(viewNode);
       } else {
-        this._currentSubView = viewNode;
-        this._transitionHeight(() => {
-          viewNode.setAttribute("current", true);
-          if (viewNode.id == this._mainViewId) {
-            this.node.setAttribute("viewtype", "main");
-          } else {
-            this.node.setAttribute("viewtype", "subview");
-          }
-          // Now that the subview is visible, we can check the height of the
-          // description elements it contains.
-          this.descriptionHeightWorkaround(viewNode);
-          this._dispatchViewEvent(viewNode, "ViewShown");
-        });
-        this._shiftMainView(aAnchor);
+        this.hideAllViewsExcept(viewNode);
       }
     })().catch(e => Cu.reportError(e));
     return this._currentShowPromise;
   }
 
   /**
    * Apply a transition to 'slide' from the currently active view to the next
    * one.
@@ -896,133 +819,22 @@ this.PanelMultiView = class {
     // due to small rounding errors. So, we just use a value that makes
     // sense for all platforms. If the arrow visuals change significantly,
     // this value will be easy to adjust.
     const EXTRA_MARGIN_PX = 20;
     maxHeight -= EXTRA_MARGIN_PX;
     return maxHeight;
   }
 
-  /**
-   * Applies the height transition for which <panelmultiview> is designed.
-   *
-   * The height transition involves two elements, the viewContainer and its only
-   * immediate child the viewStack. In order for this to work correctly, the
-   * viewContainer must have "overflow: hidden;" and the two elements must have
-   * no margins or padding. This means that the height of the viewStack is never
-   * limited by the viewContainer, but when the height of the container is not
-   * constrained it matches the height of the viewStack.
-   *
-   * @param changeFn
-   *        This synchronous function is called to make the DOM changes
-   *        that will result in a new height of the viewStack.
-   */
-  _transitionHeight(changeFn) {
-    if (this._panel.state != "open") {
-      changeFn();
-      return;
-    }
-
-    // Lock the dimensions of the window that hosts the popup panel. This
-    // in turn constrains the height of the viewContainer.
-    let rect = this._panel.popupBoxObject.getOuterScreenRect();
-    this._panel.setAttribute("width", rect.width);
-    this._panel.setAttribute("height", rect.height);
-
-    // Read the current height of the viewStack. If we are in the middle
-    // of a transition, this is the actual height of the element at this
-    // point in time.
-    let oldHeight = this._dwu.getBoundsWithoutFlushing(this._viewStack).height;
-
-    // Make the necessary DOM changes, and remove the "height" property of the
-    // viewStack to ensure that we read its final value even if we are in the
-    // middle of a transition. To avoid flickering, we have to prevent the panel
-    // from being painted in this temporary state, which requires a synchronous
-    // layout when reading the new height.
-    this._viewStack.style.removeProperty("height");
-    changeFn();
-    let newHeight = this._viewStack.getBoundingClientRect().height;
-
-    // Now we can allow the popup panel to resize again. This must occur
-    // in the same tick as the code below, but we can do this before
-    // setting the starting height in case the transition is not needed.
-    this._panel.removeAttribute("width");
-    this._panel.removeAttribute("height");
-
-    if (oldHeight != newHeight) {
-      // Height transitions can only occur between two numeric values, and
-      // cannot start if the height is not set. In case a transition is
-      // needed, we have to set the height to the old value, then force a
-      // synchronous layout so the panel won't resize unexpectedly.
-      this._viewStack.style.height = oldHeight + "px";
-      this._viewStack.getBoundingClientRect().height;
-
-      // We can now set the new height to start the transition, but
-      // before doing that we set up a listener to reset the height to
-      // "auto" at the end, so that DOM changes made after the
-      // transition ends are still reflected by the height of the panel.
-      let onTransitionEnd = event => {
-        if (event.target != this._viewStack) {
-          return;
-        }
-        this._viewStack.removeEventListener("transitionend", onTransitionEnd);
-        this._viewStack.style.removeProperty("height");
-      };
-      this._viewStack.addEventListener("transitionend", onTransitionEnd);
-      this._viewStack.style.height = newHeight + "px";
-    }
-  }
-
-  _shiftMainView(aAnchor) {
-    if (aAnchor) {
-      // We need to find the edge of the anchor, relative to the main panel.
-      // Then we need to add half the width of the anchor. This is the target
-      // that we need to transition to.
-      let anchorRect = aAnchor.getBoundingClientRect();
-      let mainViewRect = this._mainViewContainer.getBoundingClientRect();
-      let center = aAnchor.clientWidth / 2;
-      let direction = aAnchor.ownerGlobal.getComputedStyle(aAnchor).direction;
-      let edge;
-      if (direction == "ltr") {
-        edge = anchorRect.left - mainViewRect.left;
-      } else {
-        edge = mainViewRect.right - anchorRect.right;
-      }
-
-      // If the anchor is an element on the far end of the mainView we
-      // don't want to shift the mainView too far, we would reveal empty
-      // space otherwise.
-      let cstyle = this.window.getComputedStyle(this.document.documentElement);
-      let exitSubViewGutterWidth =
-        cstyle.getPropertyValue("--panel-ui-exit-subview-gutter-width");
-      let maxShift = mainViewRect.width - parseInt(exitSubViewGutterWidth);
-      let target = Math.min(maxShift, edge + center);
-
-      let neg = direction == "ltr" ? "-" : "";
-      this._mainViewContainer.style.transform = `translateX(${neg}${target}px)`;
-      aAnchor.setAttribute("panel-multiview-anchor", true);
-    } else {
-      this._mainViewContainer.style.transform = "";
-      if (this.anchorElement)
-        this.anchorElement.removeAttribute("panel-multiview-anchor");
-    }
-    this.anchorElement = aAnchor;
-  }
-
   handleEvent(aEvent) {
     if (aEvent.type.startsWith("popup") && aEvent.target != this._panel) {
       // Shouldn't act on e.g. context menus being shown from within the panel.
       return;
     }
     switch (aEvent.type) {
-      case "click":
-        if (aEvent.originalTarget == this._clickCapturer) {
-          this.showMainView();
-        }
-        break;
       case "keydown":
         this._keyNavigation(aEvent);
         break;
       case "mousemove":
         this._resetKeyNavigation();
         break;
       case "popupshowing": {
         this.node.setAttribute("panelopen", "true");
@@ -1055,37 +867,35 @@ this.PanelMultiView = class {
         break;
       case "popuphidden": {
         // WebExtensions consumers can hide the popup from viewshowing, or
         // mid-transition, which disrupts our state:
         this._viewShowing = null;
         this._transitioning = false;
         this.node.removeAttribute("panelopen");
         this.showMainView();
-        if (this.panelViews) {
-          for (let panelView of this._viewStack.children) {
-            if (panelView.nodeName != "children") {
-              panelView.__lastKnownBoundingRect = null;
-              panelView.style.removeProperty("min-width");
-              panelView.style.removeProperty("max-width");
-            }
+        for (let panelView of this._viewStack.children) {
+          if (panelView.nodeName != "children") {
+            panelView.__lastKnownBoundingRect = null;
+            panelView.style.removeProperty("min-width");
+            panelView.style.removeProperty("max-width");
           }
-          this.window.removeEventListener("keydown", this);
-          this._panel.removeEventListener("mousemove", this);
-          this._resetKeyNavigation();
+        }
+        this.window.removeEventListener("keydown", this);
+        this._panel.removeEventListener("mousemove", this);
+        this._resetKeyNavigation();
 
-          // Clear the main view size caches. The dimensions could be different
-          // when the popup is opened again, e.g. through touch mode sizing.
-          this._mainViewHeight = 0;
-          this._mainViewWidth = 0;
-          this._viewContainer.style.removeProperty("min-height");
-          this._viewStack.style.removeProperty("max-height");
-          this._viewContainer.style.removeProperty("min-width");
-          this._viewContainer.style.removeProperty("max-width");
-        }
+        // Clear the main view size caches. The dimensions could be different
+        // when the popup is opened again, e.g. through touch mode sizing.
+        this._mainViewHeight = 0;
+        this._mainViewWidth = 0;
+        this._viewContainer.style.removeProperty("min-height");
+        this._viewStack.style.removeProperty("max-height");
+        this._viewContainer.style.removeProperty("min-width");
+        this._viewContainer.style.removeProperty("max-width");
 
         this._dispatchViewEvent(this.node, "PanelMultiViewHidden");
         break;
       }
     }
   }
 
   /**
--- a/browser/components/customizableui/content/panelUI.css
+++ b/browser/components/customizableui/content/panelUI.css
@@ -1,59 +1,35 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-.panel-viewstack[viewtype="main"] > .panel-clickcapturer {
-  pointer-events: none;
-}
-
 .panel-viewcontainer {
   overflow: hidden;
 }
 
 .panel-viewstack {
+  overflow: visible;
   transition: height var(--panelui-subview-transition-duration);
 }
 
-.panel-subviews {
-  -moz-stack-sizing: ignore-horizontal;
-  transform: translateX(0);
-}
-
-.panel-viewstack[viewtype="main"] > .panel-subviews {
-  -moz-stack-sizing: ignore;
-}
-
-.panel-subviews[panelopen] {
-  transition: transform var(--panelui-subview-transition-duration);
-}
-
-.panel-viewcontainer[panelopen]:-moz-any(:not([viewtype="main"]),[transitioning]) {
+.panel-viewcontainer[panelopen] {
   transition-property: height;
   transition-timing-function: var(--animation-easing-function);
   transition-duration: var(--panelui-subview-transition-duration);
   will-change: height;
 }
 
-/* START photon adjustments */
-
-photonpanelmultiview > .panel-viewcontainer > .panel-viewstack {
-  overflow: visible;
-}
-
-photonpanelmultiview[transitioning] {
+panelmultiview[transitioning] {
   pointer-events: none;
 }
 
 .panel-viewcontainer.offscreen {
   position: absolute;
   top: 100000px;
   left: 100000px;
 }
 
 .panel-viewcontainer.offscreen,
 .panel-viewcontainer.offscreen > .panel-viewstack {
   margin: 0;
   padding: 0;
 }
-
-/* END photon adjustments */
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -4,32 +4,32 @@
 
 <panel id="widget-overflow"
        role="group"
        type="arrow"
        noautofocus="true"
        position="bottomcenter topright"
        photon="true"
        hidden="true">
-  <photonpanelmultiview mainViewId="widget-overflow-mainView" disablekeynav="true">
+  <panelmultiview mainViewId="widget-overflow-mainView" disablekeynav="true">
     <panelview id="widget-overflow-mainView"
                context="toolbar-context-menu">
       <vbox class="panel-subview-body">
         <vbox id="widget-overflow-list" class="widget-overflow-list"
               overflowfortoolbar="nav-bar"/>
         <toolbarseparator id="widget-overflow-fixed-separator" hidden="true"/>
         <vbox id="widget-overflow-fixed-list" class="widget-overflow-list" hidden="true" />
       </vbox>
       <toolbarbutton command="cmd_CustomizeToolbars"
                       id="overflowMenu-customize-button"
                       class="subviewbutton panel-subview-footer"
                       accesskey="&overflowCustomizeToolbar.accesskey;"
                       label="&overflowCustomizeToolbar.label;"/>
     </panelview>
-  </photonpanelmultiview>
+  </panelmultiview>
   <!-- This menu is here because not having it in the menu in which it's used flickers
        when hover styles overlap. See https://bugzilla.mozilla.org/show_bug.cgi?id=1378427 .
        -->
   <menupopup id="customizationPanelItemContextMenu"
              onpopupshowing="gCustomizeMode.onPanelContextMenuShowing(event)">
     <menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
               id="customizationPanelItemContextMenuPin"
               accesskey="&customizeMenu.pinToOverflowMenu.accesskey;"
@@ -159,18 +159,18 @@
 <panel id="appMenu-popup"
        class="cui-widget-panel"
        role="group"
        type="arrow"
        hidden="true"
        flip="slide"
        position="bottomcenter topright"
        noautofocus="true">
-  <photonpanelmultiview id="appMenu-multiView" mainViewId="appMenu-mainView"
-                        viewCacheId="appMenu-viewCache">
+  <panelmultiview id="appMenu-multiView" mainViewId="appMenu-mainView"
+                  viewCacheId="appMenu-viewCache">
     <panelview id="appMenu-mainView" class="PanelUI-subView"
                descriptionheightworkaround="true">
       <vbox class="panel-subview-body">
         <vbox id="appMenu-addon-banners"/>
         <toolbarbutton class="panel-banner-item"
                        label-update-available="&updateAvailable.panelUI.label;"
                        label-update-manual="&updateManual.panelUI.label;"
                        label-update-restart="&updateRestart.panelUI.label2;"
@@ -662,17 +662,17 @@
                        placesanonid="view-toolbar"
                        toolbarId="PersonalToolbar"
                        type="checkbox"
                        oncommand="onViewToolbarCommand(event)"
                        label="&viewBookmarksToolbar.label;"
                        label-checked="&hideBookmarksToolbar.label;"/>
       </vbox>
     </panelview>
-  </photonpanelmultiview>
+  </panelmultiview>
 </panel>
 
 <panel id="downloads-button-autohide-panel"
        role="group"
        type="arrow"
        hidden="true"
        onpopupshown="gCustomizeMode._downloadPanelAutoHideTimeout = setTimeout(() => event.target.hidePopup(), 4000);"
        onmouseover="clearTimeout(gCustomizeMode._downloadPanelAutoHideTimeout);"
--- a/browser/components/customizableui/content/panelUI.js
+++ b/browser/components/customizableui/content/panelUI.js
@@ -394,17 +394,17 @@ const PanelUI = {
 
     if (!aAnchor) {
       Cu.reportError("Expected an anchor when opening subview with id: " + aViewId);
       return;
     }
 
     this.ensureLibraryInitialized(viewNode);
 
-    let container = aAnchor.closest("panelmultiview,photonpanelmultiview");
+    let container = aAnchor.closest("panelmultiview");
     if (container) {
       container.showSubView(aViewId, aAnchor);
     } else if (!aAnchor.open) {
       aAnchor.open = true;
 
       let tempPanel = document.createElement("panel");
       tempPanel.setAttribute("type", "arrow");
       tempPanel.setAttribute("id", "customizationui-widget-panel");
@@ -429,17 +429,17 @@ const PanelUI = {
       if (oldMultiView && oldMultiView.current == viewNode) {
         await oldMultiView.showMainView();
       }
 
       let viewShown = false;
       let listener = () => viewShown = true;
       viewNode.addEventListener("ViewShown", listener, {once: true});
 
-      let multiView = document.createElement("photonpanelmultiview");
+      let multiView = document.createElement("panelmultiview");
       multiView.setAttribute("id", "customizationui-widget-multiview");
       multiView.setAttribute("viewCacheId", "appMenu-viewCache");
       multiView.setAttribute("mainViewId", viewNode.id);
       multiView.setAttribute("ephemeral", true);
       document.getElementById("appMenu-viewCache").appendChild(viewNode);
       tempPanel.appendChild(multiView);
       viewNode.classList.add("cui-widget-panelview");
 
--- a/browser/components/customizableui/content/panelUI.xml
+++ b/browser/components/customizableui/content/panelUI.xml
@@ -13,62 +13,37 @@
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
           xmlns:xbl="http://www.mozilla.org/xbl">
 
   <binding id="panelmultiview">
     <resources>
       <stylesheet src="chrome://browser/content/customizableui/panelUI.css"/>
     </resources>
     <content>
-      <xul:vbox anonid="viewContainer" class="panel-viewcontainer" xbl:inherits="panelopen,viewtype,transitioning">
-        <xul:stack anonid="viewStack" xbl:inherits="viewtype,transitioning" class="panel-viewstack">
-          <xul:vbox anonid="mainViewContainer" class="panel-mainview" xbl:inherits="viewtype"/>
-
-          <!-- Used to capture click events over the PanelUI-mainView if we're in
-               subview mode. That way, any click on the PanelUI-mainView causes us
-               to revert to the mainView mode, whereupon PanelUI-click-capture then
-               allows click events to go through it. -->
-          <xul:vbox anonid="clickCapturer" class="panel-clickcapturer"/>
-
-          <!-- We manually set display: none (via a CSS attribute selector) on the
-               subviews that are not being displayed. We're using this over a deck
-               because a deck assumes the size of its largest child, regardless of
-               whether or not it is shown. That's not good for our case, since we
-               want to allow each subview to be uniquely sized. -->
-          <xul:vbox anonid="subViews" class="panel-subviews" xbl:inherits="panelopen">
-            <children includes="panelview"/>
-          </xul:vbox>
-        </xul:stack>
-      </xul:vbox>
+      <xul:box anonid="viewContainer" class="panel-viewcontainer" xbl:inherits="panelopen,transitioning">
+        <xul:box anonid="viewStack" xbl:inherits="transitioning" class="panel-viewstack">
+          <children includes="panelview"/>
+        </xul:box>
+      </xul:box>
+      <xul:box class="panel-viewcontainer offscreen">
+        <xul:box anonid="offscreenViewStack" class="panel-viewstack"/>
+      </xul:box>
     </content>
     <implementation>
       <constructor><![CDATA[
         const {PanelMultiView} = Components.utils.import("resource:///modules/PanelMultiView.jsm", {});
         this.instance = new PanelMultiView(this);
       ]]></constructor>
 
       <destructor><![CDATA[
         this.instance.destructor();
       ]]></destructor>
     </implementation>
   </binding>
 
-  <binding id="photonpanelmultiview" extends="chrome://browser/content/customizableui/panelUI.xml#panelmultiview">
-    <content>
-      <xul:box anonid="viewContainer" class="panel-viewcontainer" xbl:inherits="panelopen,transitioning">
-        <xul:box anonid="viewStack" xbl:inherits="transitioning" class="panel-viewstack">
-          <children includes="panelview"/>
-        </xul:box>
-      </xul:box>
-      <xul:box class="panel-viewcontainer offscreen">
-        <xul:box anonid="offscreenViewStack" class="panel-viewstack"/>
-      </xul:box>
-    </content>
-  </binding>
-
   <binding id="panelview">
     <content>
       <xul:box class="panel-header" anonid="header">
         <xul:toolbarbutton anonid="back"
                            class="subviewbutton subviewbutton-iconic subviewbutton-back"
                            closemenu="none"
                            tabindex="0"
                            tooltip="&backCmd.label;"
--- a/browser/components/customizableui/test/browser_967000_button_charEncoding.js
+++ b/browser/components/customizableui/test/browser_967000_button_charEncoding.js
@@ -41,17 +41,17 @@ add_task(async function() {
 
   let pinnedEncodings = document.getElementById("PanelUI-characterEncodingView-pinned");
   let charsetsList = document.getElementById("PanelUI-characterEncodingView-charsets");
   ok(pinnedEncodings, "Pinned charsets are available");
   ok(charsetsList, "Charsets list is available");
 
   let checkedButtons = characterEncodingView.querySelectorAll("toolbarbutton[checked='true']");
   is(checkedButtons.length, 2, "There should be 2 checked items (1 charset, 1 detector).");
-  is(checkedButtons[0].getAttribute("label"), "Unicode", "The unicode encoding is correctly selected");
+  is(checkedButtons[0].getAttribute("label"), "Western", "The western encoding is correctly selected");
   is(characterEncodingView.querySelectorAll("#PanelUI-characterEncodingView-autodetect toolbarbutton[checked='true']").length,
      1,
      "There should be 1 checked detector.");
 
   panelHidePromise = promiseOverflowHidden(window);
   document.getElementById("nav-bar").overflowable._panel.hidePopup();
   await panelHidePromise;
   info("Panel hidden");
--- a/browser/components/customizableui/test/browser_987640_charEncoding.js
+++ b/browser/components/customizableui/test/browser_987640_charEncoding.js
@@ -21,42 +21,44 @@ add_task(async function() {
   let charEncodingButton = document.getElementById("characterencoding-button");
   let characterEncodingView = document.getElementById("PanelUI-characterEncodingView");
   let subviewShownPromise = subviewShown(characterEncodingView);
   charEncodingButton.click();
   await subviewShownPromise;
 
   let checkedButtons = characterEncodingView.querySelectorAll("toolbarbutton[checked='true']");
   let initialEncoding = checkedButtons[0];
-  is(initialEncoding.getAttribute("label"), "Unicode", "The unicode encoding is initially selected");
+  is(initialEncoding.getAttribute("label"), "Western", "The western encoding is initially selected");
 
   // change the encoding
   let encodings = characterEncodingView.querySelectorAll("toolbarbutton");
   let newEncoding = encodings[0].hasAttribute("checked") ? encodings[1] : encodings[0];
-  let tabLoadPromise = promiseTabLoadEvent(gBrowser.selectedTab, TEST_PAGE);
+  let browserStopPromise = BrowserTestUtils.browserStopped(gBrowser, TEST_PAGE);
   newEncoding.click();
-  await tabLoadPromise;
+  await browserStopPromise;
+  is(gBrowser.selectedBrowser.characterSet, "UTF-8", "The encoding should be changed to UTF-8");
+  ok(!gBrowser.selectedBrowser.mayEnableCharacterEncodingMenu, "The encoding menu should be disabled");
 
   // check that the new encodng is applied
   await document.getElementById("nav-bar").overflowable.show();
   charEncodingButton.click();
   checkedButtons = characterEncodingView.querySelectorAll("toolbarbutton[checked='true']");
   let selectedEncodingName = checkedButtons[0].getAttribute("label");
-  ok(selectedEncodingName != "Unicode", "The encoding was changed to " + selectedEncodingName);
+  ok(selectedEncodingName == "Unicode", "The encoding was changed to " + selectedEncodingName);
 
-  // reset the initial encoding
+  CustomizableUI.removeWidgetFromArea("characterencoding-button");
+  CustomizableUI.addWidgetToArea("characterencoding-button",
+                                  CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
+  await waitForOverflowButtonShown();
   await document.getElementById("nav-bar").overflowable.show();
-  charEncodingButton.click();
-  tabLoadPromise = promiseTabLoadEvent(gBrowser.selectedTab, TEST_PAGE);
-  initialEncoding.click();
-  await tabLoadPromise;
-  await document.getElementById("nav-bar").overflowable.show();
-  charEncodingButton.click();
-  checkedButtons = characterEncodingView.querySelectorAll("toolbarbutton[checked='true']");
-  is(checkedButtons[0].getAttribute("label"), "Unicode", "The encoding was reset to Unicode");
+  charEncodingButton = document.getElementById("characterencoding-button");
+
+  // check the encoding menu again
+  is(charEncodingButton.getAttribute("disabled"), "true", "We should disable the encoding menu");
+
   await BrowserTestUtils.removeTab(newTab);
 });
 
 add_task(async function asyncCleanup() {
   // reset the panel to the default state
   await resetCustomization();
   ok(CustomizableUI.inDefaultState, "The UI is in default state again.");
 });
--- a/browser/components/customizableui/test/browser_overflow_use_subviews.js
+++ b/browser/components/customizableui/test/browser_overflow_use_subviews.js
@@ -34,17 +34,17 @@ add_task(async function check_developer_
   chevron.click();
   await shownPanelPromise;
 
   let developerView = document.getElementById("PanelUI-developer");
   let button = document.getElementById("developer-button");
   let subviewShownPromise = subviewShown(developerView);
   button.click();
   await subviewShownPromise;
-  let hasSubviews = !!kOverflowPanel.querySelector("photonpanelmultiview,panelmultiview");
+  let hasSubviews = !!kOverflowPanel.querySelector("panelmultiview");
   let expectedPanel = hasSubviews ? kOverflowPanel : document.getElementById("customizationui-widget-panel");
   is(developerView.closest("panel"), expectedPanel, "Should be inside the panel");
   expectedPanel.hidePopup();
   await Promise.resolve(); // wait for popup to hide fully.
   await stopOverflowing();
 });
 
 /**
--- a/browser/components/customizableui/test/support/test_967000_charEncoding_page.html
+++ b/browser/components/customizableui/test/support/test_967000_charEncoding_page.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
   <head>
-    <meta charset="utf-8">
+    <meta charset="iso-8859-1">
     <title>Test page</title>
   </head>
 
   <body>
   This is a test page
   </body>
 </html>
--- a/browser/components/downloads/content/download.xml
+++ b/browser/components/downloads/content/download.xml
@@ -105,31 +105,16 @@
                     oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_chooseOpen');"/>
         <xul:button class="downloadButton downloadShowBlockedInfo"
                     tooltiptext="&cmd.chooseUnblock.label;"
                     oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_showBlockedInfo');"/>
       </xul:stack>
     </content>
   </binding>
 
-  <binding id="download-toolbarbutton"
-           extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-badged">
-    <content>
-      <xul:stack class="toolbarbutton-badge-stack">
-        <children />
-        <xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label,consumeanchor"/>
-        <xul:label class="toolbarbutton-badge" xbl:inherits="value=badge" top="0" end="0" crop="none"/>
-      </xul:stack>
-      <xul:label class="toolbarbutton-text" crop="right" flex="1"
-                 xbl:inherits="value=label,accesskey,crop,wrap"/>
-      <xul:label class="toolbarbutton-multiline-text" flex="1"
-                 xbl:inherits="xbl:text=label,accesskey,wrap"/>
-    </content>
-  </binding>
-
   <binding id="download-subview-toolbarbutton"
            extends="chrome://global/content/bindings/button.xml#menu-button-base">
     <content>
       <children includes="observes|template|menupopup|panel|tooltip"/>
       <xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label,consumeanchor"/>
       <xul:vbox class="toolbarbutton-text" flex="1">
         <xul:label crop="end" xbl:inherits="value=label,accesskey,crop,wrap"/>
         <xul:label class="status-text status-full" crop="end" xbl:inherits="value=fullStatus"/>
--- a/browser/components/downloads/content/downloads.css
+++ b/browser/components/downloads/content/downloads.css
@@ -193,18 +193,17 @@ richlistitem.download button {
 #downloadsPanel-mainView .download-state[state="8"] .downloadRetry,
 #downloadsPanel-mainView .download-state[state="8"] .downloadShow {
   display: none;
 }
 
 /* Make the panel wide enough to show the download list items without improperly
    truncating them. */
 #downloadsPanel-multiView > .panel-viewcontainer,
-#downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack,
-#downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack > .panel-mainview {
+#downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack {
   max-width: unset;
 }
 
 /* Show the "show blocked info" button. */
 #downloadsPanel-mainView .download-state[state="8"] .downloadShowBlockedInfo {
   display: inline;
 }
 
--- a/browser/components/downloads/content/downloadsOverlay.xul
+++ b/browser/components/downloads/content/downloadsOverlay.xul
@@ -104,18 +104,18 @@
         <menuitem command="downloadsCmd_clearList"
                   label="&cmd.clearList2.label;"
                   accesskey="&cmd.clearList2.accesskey;"/>
         <menuitem command="downloadsCmd_clearDownloads"
                   hidden="true"
                   label="&cmd.clearDownloads.label;"/>
       </menupopup>
 
-      <photonpanelmultiview id="downloadsPanel-multiView"
-                            mainViewId="downloadsPanel-mainView">
+      <panelmultiview id="downloadsPanel-multiView"
+                      mainViewId="downloadsPanel-mainView">
 
         <panelview id="downloadsPanel-mainView">
           <vbox class="panel-view-body-unscrollable">
             <richlistbox id="downloadsListBox"
                          context="downloadsContextMenu"
                          onmouseover="DownloadsView.onDownloadMouseOver(event);"
                          onmouseout="DownloadsView.onDownloadMouseOut(event);"
                          oncontextmenu="DownloadsView.onDownloadContextMenu(event);"
@@ -202,13 +202,13 @@
             </toolbaritem>
           </vbox>
           <toolbarbutton id="PanelUI-downloadsMore"
                          class="panel-subview-footer subviewbutton"
                          label="&downloadsHistory.label;"
                          oncommand="BrowserDownloadsUI(); CustomizableUI.hidePanelForNode(this);"/>
         </panelview>
 
-      </photonpanelmultiview>
+      </panelmultiview>
 
     </panel>
   </popupset>
 </overlay>
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -2199,17 +2199,17 @@ BrowserGlue.prototype = {
         if (currentEngine._loadPath.startsWith("[https]")) {
           Services.prefs.setCharPref("browser.search.reset.status", "pending");
         } else {
           // Can't call resetToOriginalDefaultEngine because it doesn't
           // unhide the engine.
           let defaultEngine = Services.search.originalDefaultEngine;
           defaultEngine.hidden = false;
           Services.search.currentEngine = defaultEngine;
-          Services.prefs.setIntPref("browser.search.reset.status", "silent");
+          Services.prefs.setCharPref("browser.search.reset.status", "silent");
         }
       });
     }
 
     // Update the migration version.
     Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
   },
 
--- a/browser/components/search/content/searchReset.xhtml
+++ b/browser/components/search/content/searchReset.xhtml
@@ -36,17 +36,17 @@
       <div class="title">
         <h1 class="title-text">&searchreset.pageTitle;</h1>
       </div>
 
       <div class="description">
         <p>&searchreset.pageInfo1;</p>
         <p>&searchreset.selector.label;<span id="defaultEngine"/></p>
 
-        <p>&searchreset.beforelink.pageInfo2;<a id="linkSettingsPage" href="about:preferences">&searchreset.link.pageInfo2;</a>&searchreset.afterlink.pageInfo2;</p>
+        <p>&searchreset.beforelink.pageInfo2;<a id="linkSettingsPage" href="about:preferences#search">&searchreset.link.pageInfo2;</a>&searchreset.afterlink.pageInfo2;</p>
       </div>
 
       <div class="button-container">
         <xul:button id="searchResetKeepCurrent"
                     label="&searchreset.noChangeButton;"
                     accesskey="&searchreset.noChangeButton.access;"
                     oncommand="keepCurrentEngine();"/>
         <xul:button class="primary"
--- a/browser/components/search/test/browser_aboutSearchReset.js
+++ b/browser/components/search/test/browser_aboutSearchReset.js
@@ -110,17 +110,17 @@ var gTests = [
 },
 
 {
   desc: "Click the settings link.",
   async run() {
     Services.prefs.setCharPref(kStatusPref, "pending");
     let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser,
                                                      false,
-                                                     "about:preferences");
+                                                     "about:preferences#search");
     // eslint-disable-next-line mozilla/no-cpows-in-tests
     gBrowser.contentDocument.getElementById("linkSettingsPage").click();
     await loadPromise;
 
     checkTelemetryRecords(TELEMETRY_RESULT_ENUM.OPENED_SETTINGS);
     is(Services.prefs.getCharPref(kStatusPref), "customized");
   }
 },
--- a/browser/components/sessionstore/test/browser.ini
+++ b/browser/components/sessionstore/test/browser.ini
@@ -214,17 +214,17 @@ skip-if = true # Needs to be rewritten a
 [browser_687710_2.js]
 [browser_694378.js]
 [browser_701377.js]
 [browser_705597.js]
 [browser_707862.js]
 [browser_739531.js]
 [browser_739805.js]
 [browser_819510_perwindowpb.js]
-skip-if = (os == 'win' && bits == 64) || (os == "mac") # Win: Bug 1284312, Mac: Bug 1341980
+skip-if = (os == 'win' && bits == 64) || (os == "mac") || (os == "linux") # Win: Bug 1284312, Mac: Bug 1341980, Linux: bug 1381451
 [browser_not_collect_when_idle.js]
 
 # Disabled for frequent intermittent failures
 [browser_464620_a.js]
 skip-if = true
 [browser_464620_b.js]
 skip-if = true
 
new file mode 100644
--- /dev/null
+++ b/browser/config/mozconfigs/linux64/debug-searchfox-clang
@@ -0,0 +1,25 @@
+MOZ_AUTOMATION_BUILD_SYMBOLS=0
+MOZ_AUTOMATION_PACKAGE_TESTS=0
+MOZ_AUTOMATION_L10N_CHECK=0
+
+. "$topsrcdir/build/mozconfig.common"
+
+ac_add_options --enable-debug
+ac_add_options --enable-dmd
+
+. $topsrcdir/build/mozconfig.stylo
+
+# Use Clang as specified in manifest
+export CC="$topsrcdir/clang/bin/clang"
+export CXX="$topsrcdir/clang/bin/clang++"
+
+# Add the static checker
+ac_add_options --enable-clang-plugin
+ac_add_options --enable-mozsearch-plugin
+
+. "$topsrcdir/build/unix/mozconfig.stdcxx"
+
+export PKG_CONFIG_LIBDIR=/usr/lib64/pkgconfig:/usr/share/pkgconfig
+. $topsrcdir/build/unix/mozconfig.gtk
+
+. "$topsrcdir/build/mozconfig.common.override"
new file mode 100644
--- /dev/null
+++ b/browser/config/mozconfigs/macosx64/debug-searchfox
@@ -0,0 +1,13 @@
+MOZ_AUTOMATION_BUILD_SYMBOLS=0
+MOZ_AUTOMATION_PACKAGE_TESTS=0
+MOZ_AUTOMATION_L10N_CHECK=0
+
+. $topsrcdir/build/macosx/mozconfig.common
+
+ac_add_options --enable-debug
+ac_add_options --enable-dmd
+
+ac_add_options --enable-clang-plugin
+ac_add_options --enable-mozsearch-plugin
+
+. "$topsrcdir/build/mozconfig.common.override"
new file mode 100644
--- /dev/null
+++ b/browser/config/mozconfigs/win32/debug-searchfox
@@ -0,0 +1,17 @@
+MOZ_AUTOMATION_BUILD_SYMBOLS=0
+MOZ_AUTOMATION_PACKAGE_TESTS=0
+MOZ_AUTOMATION_L10N_CHECK=0
+
+. "$topsrcdir/build/mozconfig.win-common"
+. "$topsrcdir/browser/config/mozconfigs/common"
+
+ac_add_options --enable-optimize
+ac_add_options --enable-debug
+
+ac_add_options --enable-clang-plugin
+ac_add_options --enable-mozsearch-plugin
+
+. $topsrcdir/build/win32/mozconfig.vs-latest
+
+. "$topsrcdir/build/mozconfig.common.override"
+. "$topsrcdir/build/mozconfig.clang-cl"
--- a/browser/themes/linux/customizableui/panelUI.css
+++ b/browser/themes/linux/customizableui/panelUI.css
@@ -1,18 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 %include ../../shared/customizableui/panelUI.inc.css
 
-.panel-subviews {
-  background-color: var(--arrowpanel-background);
-}
-
 #BMB_bookmarksPopup > menuitem[type="checkbox"] {
   -moz-appearance: none !important; /* important, to override toolkit rule */
 }
 
 #BMB_bookmarksPopup menupopup {
   -moz-appearance: none;
   background: var(--arrowpanel-background);
   color: var(--arrowpanel-color);
--- a/browser/themes/osx/controlcenter/panel.css
+++ b/browser/themes/osx/controlcenter/panel.css
@@ -5,25 +5,16 @@
 %include ../shared.inc
 %include ../../shared/controlcenter/panel.inc.css
 
 .identity-popup-expander:-moz-focusring,
 .identity-popup-permission-remove-button:-moz-focusring {
   box-shadow: var(--focus-ring-box-shadow);
 }
 
-#identity-popup-multiView > .panel-viewcontainer > .panel-viewstack > .panel-subviews {
-  border-bottom-right-radius: 3.5px;
-}
-
-#identity-popup-multiView > .panel-viewcontainer > .panel-viewstack > .panel-subviews:-moz-locale-dir(rtl) {
-  border-bottom-right-radius: 0;
-  border-bottom-left-radius: 3.5px;
-}
-
 #tracking-action-block,
 #tracking-action-unblock,
 #tracking-action-unblock-private,
 #identity-popup-securityView-body > button {
   @hudButton@
   min-height: 30px;
 }
 
--- a/browser/themes/osx/customizableui/panelUI.css
+++ b/browser/themes/osx/customizableui/panelUI.css
@@ -1,31 +1,27 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 %include ../../shared/customizableui/panelUI.inc.css
 
-.panel-subviews {
-  background-color: hsla(0,0%,100%,.97);
-}
-
 .restoreallitem > .toolbarbutton-icon {
   display: none;
 }
 
 .subviewbutton {
   padding-inline-start: 18px;
 }
 
 .subviewbutton.download {
   padding-inline-start: 14px;
 }
 
-photonpanelmultiview .toolbaritem-combined-buttons > spacer {
+panelmultiview .toolbaritem-combined-buttons > spacer {
   width: 42px; /* 18px toolbarbutton padding + 16px icon + 8px label padding start */
 }
 
 #appMenu-addon-banners > .addon-banner-item,
 #appMenu-mainView > .panel-subview-body > .panel-banner-item {
   padding-inline-start: 18px;
 }
 
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -63,30 +63,16 @@
   fill-opacity: .6;
 }
 
 #identity-popup-mainView {
   min-width: 30em;
   max-width: 30em;
 }
 
-#identity-popup-multiView > .panel-viewcontainer > .panel-viewstack[viewtype="main"] > .panel-subviews {
-  transform: translateX(100%);
-  box-shadow: none;
-}
-
-#identity-popup-multiView > .panel-viewcontainer > .panel-viewstack[viewtype="main"] > .panel-subviews:-moz-locale-dir(rtl) {
-  transform: translateX(-100%);
-}
-
-#identity-popup-multiView > .panel-viewcontainer > .panel-viewstack > .panel-subviews {
-  background: var(--arrowpanel-background);
-  padding: 0;
-}
-
 .identity-popup-section:not(:first-child) {
   border-top: 1px solid var(--panel-separator-color);
 }
 
 .identity-popup-security-content,
 #identity-popup-permissions-content,
 #tracking-protection-content {
   background-repeat: no-repeat;
@@ -159,17 +145,17 @@
 .identity-popup-headline {
   margin: 3px 0 4px;
   font-size: 150%;
 }
 
 .identity-popup-host {
   word-wrap: break-word;
   /* 1em + 2em + 24px is .identity-popup-security-content padding
-   * 30em is .panel-mainview width */
+   * 30em is the panel width */
   max-width: calc(30rem - 3rem - 24px - @identityPopupExpanderWidth@);
 }
 
 .identity-popup-warning-gray {
   padding-inline-start: 24px;
   background: url(chrome://browser/skin/controlcenter/warning-gray.svg) no-repeat 0 50%;
 }
 
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -17,17 +17,16 @@
 %define menuStateHover :not(:-moz-any([disabled],:active))[_moz-menuactive]
 %define buttonStateActive :not([disabled]):-moz-any([open],:hover:active)
 %define menuStateActive :not([disabled])[_moz-menuactive]:active
 %define menuStateMenuActive :not([disabled])[_moz-menuactive]
 %define inAnyPanel :-moz-any(:not([cui-areatype="toolbar"]), [overflowedItem=true])
 %define panelPaletteIconSize 16px
 
 :root {
-  --panel-ui-exit-subview-gutter-width: 38px;
   --appmenu-yellow-warning-border-color: hsl(45, 100%, 77%);
   --appmenu-yellow-warning-color: #FFEFBF;
   --appmenu-yellow-warning-hover-color: #FFE8A2;
   --appmenu-yellow-warning-active-color: #FFE38F;
 }
 
 :root:not([uidensity=compact]):not([chromehidden~="toolbar"]) #PanelUI-button {
   margin-inline-start: 3px;
@@ -109,36 +108,21 @@
   filter: none;
 }
 
 #PanelUI-menu-button[badge-status="addon-alert"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
   height: 13px;
   background: #FFBF00 url(chrome://browser/skin/update-badge-failed.svg) no-repeat center;
 }
 
-.panel-subviews {
-  padding: 4px;
-  background-clip: padding-box;
-  border-left: 1px solid var(--arrowpanel-border-color);
-  box-shadow: 0 3px 5px hsla(210,4%,10%,.1),
-              0 0 7px hsla(210,4%,10%,.1);
-  margin-inline-start: var(--panel-ui-exit-subview-gutter-width);
-}
-
-.panel-viewstack[viewtype="main"] > .panel-subviews {
-  transform: translateX(@menuPanelWidth@);
-}
-
-.panel-viewstack[viewtype="main"] > .panel-subviews:-moz-locale-dir(rtl) {
-  transform: translateX(-@menuPanelWidth@);
-}
-
 panelview {
   -moz-box-orient: vertical;
   -moz-box-flex: 1;
+  background: var(--arrowpanel-background);
+  padding: 0;
 }
 
 /* This section is to anchor all the drop down panels at the same height, shift the
   panel`s top margin according to its positioning and the uidensity of the window. */
 #downloadsPanel,
 #widget-overflow,
 #appMenu-popup,
 #customizationui-widget-panel {
@@ -195,16 +179,17 @@ panelview {
 :root[uidensity=touch] #PersonalToolbar #BMB_bookmarksPopup {
   margin-top: -5px;
 }
 
 .panel-subview-body {
   overflow-y: auto;
   overflow-x: hidden;
   -moz-box-flex: 1;
+  padding: 6px 0;
 }
 
 .panel-view-body-unscrollable {
   overflow: hidden;
   -moz-box-flex: 1;
 }
 
 .subviewbutton.panel-subview-footer {
@@ -237,18 +222,17 @@ panel[photon] > .panel-arrowcontainer > 
   padding: 0;
 }
 
 #wrapper-edit-controls:-moz-any([place="palette"],[place="panel"]) > #edit-controls,
 #wrapper-zoom-controls:-moz-any([place="palette"],[place="panel"]) > #zoom-controls {
   margin-inline-start: 0;
 }
 
-#BMB_bookmarksPopup,
-.panel-mainview {
+#BMB_bookmarksPopup {
   max-width: @standaloneSubviewWidth@;
 }
 
 #pageActionFeedback > .panel-arrowcontainer > .panel-arrowbox {
   /* Don't display the arrow but keep the popup at the same vertical
      offset as other arrow panels. */
   visibility: hidden;
 }
@@ -318,21 +302,16 @@ panel[photon] > .panel-arrowcontainer > 
               opacity 60ms linear;
 }
 
 #pageActionFeedbackAnimatableBox[animate] + #pageActionFeedbackMessage {
   transform: scale(1);
   opacity: 1;
 }
 
-/* Give WebExtension stand-alone panels extra width for Chrome compatibility */
-.cui-widget-panel[viewId^=PanelUI-webext-] .panel-mainview {
-  max-width: 800px;
-}
-
 .cui-widget-panel[viewId^=PanelUI-webext-] > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 0;
 }
 
 panelview[id^=PanelUI-webext-] {
   overflow: hidden;
 }
 
@@ -342,28 +321,21 @@ panelview:not([mainview]) .toolbarbutton
   text-align: start;
   display: -moz-box;
 }
 
 .cui-widget-panel > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 4px 0;
 }
 
-/* START photonpanelview adjustments */
-
 #appMenu-popup > .panel-arrowcontainer > .panel-arrowcontent,
 panel[photon] > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 0;
 }
 
-photonpanelmultiview panelview {
-  background: var(--arrowpanel-background);
-  padding: 0;
-}
-
 #appMenu-popup panelview,
 #customizationui-widget-multiview panelview:not([extension]) {
   min-width: @menuPanelWidth@;
   max-width: 35em;
 }
 
 #customizationui-widget-multiview #appMenu-libraryView,
 #pageActionPanel panelview,
@@ -372,22 +344,16 @@ photonpanelmultiview panelview {
   max-width: @wideMenuPanelWidth@;
 }
 
 /* Add 2 * 16px extra width for touch mode button padding. */
 #appMenu-popup[touchmode] panelview {
   min-width: calc(@menuPanelWidth@ + 32px);
 }
 
-photonpanelmultiview .panel-subview-body {
-  padding: 6px 0;
-}
-
-/* END photonpanelview adjustments */
-
 .cui-widget-panel.cui-widget-panelWithFooter > .panel-arrowcontainer > .panel-arrowcontent {
   padding-bottom: 0;
 }
 
 .toolbaritem-combined-buttons@inAnyPanel@ > toolbarbutton > .toolbarbutton-icon {
   min-width: 0;
   min-height: 0;
   margin: 0;
@@ -456,17 +422,18 @@ toolbarbutton[constrain-size="true"][cui
   display: none;
 }
 
 .addon-banner-item::after,
 .panel-banner-item::after {
   content: "";
   width: 16px;
   height: 16px;
-  margin-inline-end: 16.5px;
+  margin-inline-start: 10px;
+  margin-inline-end: 12px;
   display: -moz-box;
 }
 
 .addon-banner-item {
   background-color: var(--appmenu-yellow-warning-color);
   /* Force border to override `.addon-banner-item` selector below */
   border-top: 1px solid var(--appmenu-yellow-warning-border-color) !important;
   display: flex;
@@ -899,61 +866,45 @@ panelview .toolbarbutton-1,
 }
 
 /* This is a <label> but it should fit in with the menu font- and colorwise. */
 #PanelUI-characterEncodingView-autodetect-label {
   font: menu;
   color: inherit;
 }
 
-/* START photon adjustments */
-
 .subviewbutton[checked="true"] {
-  background: url(chrome://browser/skin/check.svg) center left 7px / 11px 11px no-repeat transparent;
+  list-style-image: url(chrome://browser/skin/check.svg);
   fill: currentColor;
 }
 
-.subviewbutton[checked="true"]:-moz-locale-dir(rtl) {
-  background-position: center right 7px;
-}
-
-photonpanelmultiview .subviewbutton[checked="true"] {
-  background: none;
-  list-style-image: url(chrome://browser/skin/check.svg);
-}
-
-photonpanelmultiview .subviewbutton > .menu-iconic-left {
-  -moz-appearance: none;
-  margin-inline-end: 0;
-}
-
 #appMenu-popup .toolbaritem-combined-buttons {
   -moz-box-align: center;
   -moz-box-orient: horizontal;
   border: 0;
   border-radius: 0;
   margin-inline-end: 8px;
 }
 
-photonpanelmultiview .toolbaritem-combined-buttons > label {
+panelmultiview .toolbaritem-combined-buttons > label {
   -moz-box-flex: 1;
   font: menu;
   margin: 0;
 }
 
-photonpanelmultiview .toolbaritem-combined-buttons > spacer.before-label {
+panelmultiview .toolbaritem-combined-buttons > spacer.before-label {
   width: 36px; /* 12px toolbarbutton padding + 16px icon + 8px label padding start */
 }
 
-photonpanelmultiview .toolbaritem-combined-buttons > spacer.after-label {
+panelmultiview .toolbaritem-combined-buttons > spacer.after-label {
   -moz-box-flex: 1;
   width: 20px; /* a little bigger than the width of the scrollbar */
 }
 
-photonpanelmultiview .PanelUI-subView .toolbaritem-combined-buttons > .subviewbutton {
+.PanelUI-subView .toolbaritem-combined-buttons > .subviewbutton {
   -moz-box-flex: 0;
   height: auto;
   margin-inline-start: 18px;
   min-width: auto;
   padding: 4px;
 }
 
 #appMenu-zoom-controls > .subviewbutton {
@@ -970,54 +921,43 @@ photonpanelmultiview .PanelUI-subView .t
   text-align: center;
 }
 
 .toolbaritem-combined-buttons > toolbarseparator[orient="vertical"] + .subviewbutton,
 #appMenu-zoom-controls > toolbarseparator[orient="vertical"] + .subviewbutton {
   margin-inline-start: 0;
 }
 
-photonpanelmultiview .PanelUI-subView .toolbaritem-combined-buttons >
-  .subviewbutton-iconic > .toolbarbutton-text,
-photonpanelmultiview .PanelUI-subView .toolbaritem-combined-buttons >
-  .subviewbutton:not(.subviewbutton-iconic) > .toolbarbutton-icon {
+.PanelUI-subView .toolbaritem-combined-buttons > .subviewbutton-iconic > .toolbarbutton-text,
+.PanelUI-subView .toolbaritem-combined-buttons > .subviewbutton:not(.subviewbutton-iconic) > .toolbarbutton-icon {
   display: none;
 }
 
 /* Using this selector, because this way the hover and active selectors will apply properly. */
-photonpanelmultiview .PanelUI-subView .toolbaritem-combined-buttons >
-  .subviewbutton:not(.subviewbutton-iconic) {
+.PanelUI-subView .toolbaritem-combined-buttons > .subviewbutton:not(.subviewbutton-iconic) {
   background-color: #f9f9f9;
   border: 1px solid #e1e1e1;
   border-radius: 10000px;
   padding: 1px 8px;
 }
 
-photonpanelmultiview .toolbaritem-combined-buttons > .subviewbutton:not(.subviewbutton-iconic) > .toolbarbutton-text {
+.toolbaritem-combined-buttons > .subviewbutton:not(.subviewbutton-iconic) > .toolbarbutton-text {
   font-size: 1em;
   padding-inline-start: 0;
 }
 
-photonpanelmultiview .addon-banner-item::after,
-photonpanelmultiview .panel-banner-item::after {
-  margin-inline-end: 12px;
-  margin-inline-start: 10px;
-}
-
-photonpanelmultiview .subview-subheader {
+.subview-subheader {
   color: GrayText;
 }
 
-photonpanelmultiview .subview-subheader,
-photonpanelmultiview .panel-subview-footer {
+.subview-subheader,
+.panel-subview-footer {
   font: menu;
 }
 
-/* END photon adjustments */
-
 panelview .toolbarbutton-1 {
   margin-top: 6px;
 }
 
 panelview .toolbarbutton-1@buttonStateHover@,
 toolbarbutton.subviewbutton@buttonStateHover@,
 menu.subviewbutton@menuStateHover@,
 menuitem.subviewbutton@menuStateHover@,
@@ -1103,22 +1043,26 @@ menuitem.panel-subview-footer@menuStateA
   -moz-appearance: none;
   min-height: 0;
   border-top: 1px solid var(--panel-separator-color);
   border-bottom: none;
   margin: 6px 0;
   padding: 0;
 }
 
-.PanelUI-subView menuseparator,
-.PanelUI-subView toolbarseparator {
+.PanelUI-subView menuseparator {
   margin-inline-start: -5px;
   margin-inline-end: -4px;
 }
 
+.PanelUI-subView toolbarseparator {
+  margin-inline-start: 0;
+  margin-inline-end: 0;
+}
+
 .PanelUI-subView menuseparator.small-separator,
 .PanelUI-subView toolbarseparator.small-separator {
   margin-left: 5px;
   margin-right: 5px;
 }
 
 .cui-widget-panelview menuseparator.small-separator {
   margin-left: 10px;
@@ -1235,17 +1179,16 @@ toolbarpaletteitem[place=panel] > .toolb
 .toolbaritem-combined-buttons@inAnyPanel@:hover > separator {
   margin: 0;
 }
 
 #widget-overflow > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 0;
 }
 
-.cui-widget-panelview,
 #widget-overflow-mainView .panel-subview-body {
   overflow-y: auto;
   overflow-x: hidden;
 }
 
 .widget-overflow-list {
   width: @wideMenuPanelWidth@;
 }
@@ -1288,24 +1231,23 @@ toolbarpaletteitem[place=panel] > .subvi
 
 .widget-overflow-list .toolbarbutton-1:not(.toolbarbutton-combined) > .toolbarbutton-text {
   text-align: start;
   padding-inline-start: .5em;
 }
 
 .subviewbutton > .menu-iconic-left {
   -moz-appearance: none;
-  margin-inline-end: 3px;
+  margin-inline-end: 0;
 }
 
 menuitem[checked="true"].subviewbutton > .menu-iconic-left {
   visibility: hidden;
 }
 
-.panel-mainview[panelid=customizationui-widget-panel],
 #PanelUI-panicView > .panel-subview-body,
 #PanelUI-panicView {
   overflow: visible;
 }
 
 #PanelUI-panicView.cui-widget-panelview {
   min-width: 280px;
 }
@@ -1488,18 +1430,16 @@ menuitem[checked="true"].subviewbutton >
     background-image: -moz-image-rect(url(chrome://browser/skin/panic-panel/icons@2x.png), 0, 96, 32, 64);
   }
 
   #PanelUI-panic-actionlist-newwindow {
     background-image: -moz-image-rect(url(chrome://browser/skin/panic-panel/icons@2x.png), 0, 128, 32, 96);
   }
 }
 
-/* START photon adjustments */
-
 .panel-header {
   align-items: center;
   border-bottom: 1px solid var(--panel-separator-color);
   display: flex;
   flex: 1 auto;
   height: 40px; /* fixed item height to prevent flex sizing; height + 2*4px padding */
   padding: 4px;
 }
@@ -1509,45 +1449,34 @@ menuitem[checked="true"].subviewbutton >
   font-size: 13px;
   font-weight: 500;
   margin: 0;
   /* Add the size of the back button to center properly. */
   margin-inline-end: 32px;
   text-align: center;
 }
 
-photonpanelmultiview .PanelUI-subView .panel-header > .subviewbutton-back {
+.PanelUI-subView .panel-header > .subviewbutton-back {
   -moz-context-properties: fill;
   fill: var(--arrowpanel-color);
   list-style-image: url(chrome://browser/skin/arrow-left.svg);
   padding: 8px;
 }
 
 .panel-header > .subviewbutton-back:-moz-locale-dir(rtl) {
   transform: scaleX(-1);
 }
 
 .panel-header > .subviewbutton-back > .toolbarbutton-text {
   /* !important to override .cui-widget-panel toolbarbutton:not([wrap]) > .toolbarbutton-text
    * selector further down. */
   display: none !important;
 }
 
-photonpanelmultiview .PanelUI-subView toolbarseparator {
-  margin-inline-start: 0;
-  margin-inline-end: 0;
-}
-
-/* This is explicitly overriding the overflow properties set above. */
-photonpanelmultiview .cui-widget-panelview {
-  overflow-x: visible;
-  overflow-y: visible;
-}
-
-photonpanelmultiview #panelMenu_pocket {
+#panelMenu_pocket {
   display: none;
 }
 
 .subviewbutton.download {
   -moz-box-align: start;
   min-height: 48px;
   padding-inline-start: 8px;
 }
@@ -1592,10 +1521,8 @@ photonpanelmultiview #panelMenu_pocket {
 
 .subviewbutton.download:-moz-any([openLabel],[retryLabel]) > .action-button@buttonStateHover@ {
   background-color: var(--arrowpanel-dimmed-further);
 }
 
 .subviewbutton.download:-moz-any([openLabel],[retryLabel]) > .action-button@buttonStateActive@ {
   background-color: var(--arrowpanel-dimmed-even-further);
 }
-
-/* END photon adjustments */
--- a/browser/themes/shared/downloads/downloads.inc.css
+++ b/browser/themes/shared/downloads/downloads.inc.css
@@ -10,20 +10,16 @@
 %define itemFinished @item@[state="1"]
 %define itemNotFinished @item@:not([state="1"])
 %define itemFocused #downloadsListBox:focus > @item@[selected]
 
 /*** Panel and outer controls ***/
 
 #downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent {
   overflow: hidden;
-}
-
-#downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent,
-#downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack > .panel-subviews {
   padding: 0;
 }
 
 #downloadsListBox {
   background: transparent;
   color: inherit;
   -moz-appearance: none;
   margin: 0;
--- a/browser/themes/windows/customizableui/panelUI.css
+++ b/browser/themes/windows/customizableui/panelUI.css
@@ -1,18 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 %include ../../shared/customizableui/panelUI.inc.css
 
-.panel-subviews {
-  background-color: var(--arrowpanel-background);
-}
-
 /* bookmark panel submenus */
 
 #BMB_bookmarksPopup menupopup[placespopup=true] {
   -moz-appearance: none;
   background: transparent;
   border: none;
   padding: 0;
   padding-top: 4px;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -3859,17 +3859,16 @@ nsDocShell::CanAccessItem(nsIDocShellTre
   return CanAccessItem(openerItem, aAccessingItem, false);
 }
 
 static bool
 ItemIsActive(nsIDocShellTreeItem* aItem)
 {
   if (nsCOMPtr<nsPIDOMWindowOuter> window = aItem->GetWindow()) {
     auto* win = nsGlobalWindowOuter::Cast(window);
-    MOZ_ASSERT(win->IsOuterWindow());
     if (!win->GetClosedOuter()) {
       return true;
     }
   }
 
   return false;
 }
 
--- a/dom/audiochannel/AudioChannelAgent.cpp
+++ b/dom/audiochannel/AudioChannelAgent.cpp
@@ -1,10 +1,8 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AudioChannelAgent.h"
 #include "AudioChannelService.h"
 #include "mozilla/Preferences.h"
 #include "nsContentUtils.h"
@@ -72,18 +70,16 @@ AudioChannelAgent::InitWithWeakCallback(
 {
   return InitInternal(nsPIDOMWindowInner::From(aWindow),
                       aCallback, /* useWeakRef = */ true);
 }
 
 nsresult
 AudioChannelAgent::FindCorrectWindow(nsPIDOMWindowInner* aWindow)
 {
-  MOZ_ASSERT(aWindow->IsInnerWindow());
-
   mWindow = aWindow->GetScriptableTop();
   if (NS_WARN_IF(!mWindow)) {
     return NS_OK;
   }
 
   // From here we do an hack for nested iframes.
   // The system app doesn't have access to the nested iframe objects so it
   // cannot control the volume of the agents running in nested apps. What we do
@@ -137,17 +133,16 @@ nsresult
 AudioChannelAgent::InitInternal(nsPIDOMWindowInner* aWindow,
                                 nsIAudioChannelAgentCallback *aCallback,
                                 bool aUseWeakRef)
 {
   if (NS_WARN_IF(!aWindow)) {
     return NS_ERROR_FAILURE;
   }
 
-  MOZ_ASSERT(aWindow->IsInnerWindow());
   mInnerWindowID = aWindow->WindowID();
 
   nsresult rv = FindCorrectWindow(aWindow);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (aUseWeakRef) {
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -340,22 +340,20 @@ AudioChannelService::UnregisterAudioChan
   // released in their callback.
   RefPtr<AudioChannelAgent> kungFuDeathGrip(aAgent);
   winData->RemoveAgent(aAgent);
 }
 
 AudioPlaybackConfig
 AudioChannelService::GetMediaConfig(nsPIDOMWindowOuter* aWindow) const
 {
-  MOZ_ASSERT(!aWindow || aWindow->IsOuterWindow());
-
   AudioPlaybackConfig config(1.0, false,
                              nsISuspendedTypes::NONE_SUSPENDED);
 
-  if (!aWindow || !aWindow->IsOuterWindow()) {
+  if (!aWindow) {
     config.SetConfig(0.0, true,
                      nsISuspendedTypes::SUSPENDED_BLOCK);
     return config;
   }
 
   AudioChannelWindow* winData = nullptr;
   nsCOMPtr<nsPIDOMWindowOuter> window = aWindow;
 
@@ -447,17 +445,16 @@ AudioChannelService::Observe(nsISupports
   return NS_OK;
 }
 
 void
 AudioChannelService::RefreshAgents(nsPIDOMWindowOuter* aWindow,
                                    const std::function<void(AudioChannelAgent*)>& aFunc)
 {
   MOZ_ASSERT(aWindow);
-  MOZ_ASSERT(aWindow->IsOuterWindow());
 
   nsCOMPtr<nsPIDOMWindowOuter> topWindow = aWindow->GetScriptableTop();
   if (!topWindow) {
     return;
   }
 
   AudioChannelWindow* winData = GetWindowData(topWindow->WindowID());
   if (!winData) {
@@ -490,17 +487,16 @@ AudioChannelService::RefreshAgentsSuspen
 
 void
 AudioChannelService::SetWindowAudioCaptured(nsPIDOMWindowOuter* aWindow,
                                             uint64_t aInnerWindowID,
                                             bool aCapture)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aWindow);
-  MOZ_ASSERT(aWindow->IsOuterWindow());
 
   MOZ_LOG(GetAudioChannelLog(), LogLevel::Debug,
          ("AudioChannelService, SetWindowAudioCaptured, window = %p, "
           "aCapture = %d\n", aWindow, aCapture));
 
   nsCOMPtr<nsPIDOMWindowOuter> topWindow = aWindow->GetScriptableTop();
   if (!topWindow) {
     return;
@@ -527,17 +523,16 @@ AudioChannelService::SetWindowAudioCaptu
   }
 }
 
 AudioChannelService::AudioChannelWindow*
 AudioChannelService::GetOrCreateWindowData(nsPIDOMWindowOuter* aWindow)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aWindow);
-  MOZ_ASSERT(aWindow->IsOuterWindow());
 
   AudioChannelWindow* winData = GetWindowData(aWindow->WindowID());
   if (!winData) {
     winData = new AudioChannelWindow(aWindow->WindowID());
     mWindows.AppendElement(winData);
   }
 
   return winData;
@@ -590,17 +585,16 @@ AudioChannelService::RefreshAgentsAudioF
     }
   }
 }
 
 void
 AudioChannelService::NotifyMediaResumedFromBlock(nsPIDOMWindowOuter* aWindow)
 {
   MOZ_ASSERT(aWindow);
-  MOZ_ASSERT(aWindow->IsOuterWindow());
 
   nsCOMPtr<nsPIDOMWindowOuter> topWindow = aWindow->GetScriptableTop();
   if (!topWindow) {
     return;
   }
 
   AudioChannelWindow* winData = GetWindowData(topWindow->WindowID());
   if (!winData) {
@@ -969,17 +963,16 @@ AudioChannelService::AudioChannelWindow:
 void
 AudioChannelService::AudioChannelWindow::MaybeNotifyMediaBlockStart(AudioChannelAgent* aAgent)
 {
   nsCOMPtr<nsPIDOMWindowOuter> window = aAgent->Window();
   if (!window) {
     return;
   }
 
-  MOZ_ASSERT(window->IsOuterWindow());
   nsCOMPtr<nsPIDOMWindowInner> inner = window->GetCurrentInnerWindow();
   if (!inner) {
     return;
   }
 
   nsCOMPtr<nsIDocument> doc = inner->GetExtantDoc();
   if (!doc) {
     return;
--- a/dom/base/BarProps.cpp
+++ b/dom/base/BarProps.cpp
@@ -16,17 +16,16 @@ namespace mozilla {
 namespace dom {
 
 //
 //  Basic (virtual) BarProp class implementation
 //
 BarProp::BarProp(nsGlobalWindowInner* aWindow)
   : mDOMWindow(aWindow)
 {
-  MOZ_ASSERT(aWindow->IsInnerWindow());
 }
 
 BarProp::~BarProp()
 {
 }
 
 nsPIDOMWindowInner*
 BarProp::GetParentObject() const
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -219,17 +219,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 CustomElementRegistry::CustomElementRegistry(nsPIDOMWindowInner* aWindow)
  : mWindow(aWindow)
  , mIsCustomDefinitionRunning(false)
 {
   MOZ_ASSERT(aWindow);
-  MOZ_ASSERT(aWindow->IsInnerWindow());
   MOZ_ALWAYS_TRUE(mConstructors.init());
 
   mozilla::HoldJSObjects(this);
 }
 
 CustomElementRegistry::~CustomElementRegistry()
 {
   mozilla::DropJSObjects(this);
--- a/dom/base/EventSource.cpp
+++ b/dom/base/EventSource.cpp
@@ -1960,18 +1960,17 @@ EventSource::CreateAndDispatchSimpleEven
 /* static */ already_AddRefed<EventSource>
 EventSource::Constructor(const GlobalObject& aGlobal, const nsAString& aURL,
                          const EventSourceInit& aEventSourceInitDict,
                          ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindowInner> ownerWindow =
     do_QueryInterface(aGlobal.GetAsSupports());
 
-  MOZ_ASSERT(!NS_IsMainThread() ||
-             (ownerWindow && ownerWindow->IsInnerWindow()));
+  MOZ_ASSERT(!NS_IsMainThread() || ownerWindow);
 
   RefPtr<EventSource> eventSource =
     new EventSource(ownerWindow, aEventSourceInitDict.mWithCredentials);
   RefPtr<EventSourceImpl> eventSourceImp = eventSource->mImpl;
 
   if (NS_IsMainThread()) {
     // Get principal from document and init EventSourceImpl
     nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -37,18 +37,16 @@
 #include "mozilla/dom/ScriptSettings.h"
 
 namespace mozilla {
 namespace dom {
 
 Location::Location(nsPIDOMWindowInner* aWindow, nsIDocShell *aDocShell)
   : mInnerWindow(aWindow)
 {
-  MOZ_ASSERT(mInnerWindow->IsInnerWindow());
-
   // aDocShell can be null if it gets called after nsDocShell::Destory().
   mDocShell = do_GetWeakReference(aDocShell);
 }
 
 Location::~Location()
 {
 }
 
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -163,17 +163,16 @@ Navigator::Init()
                                "dom.vibrator.max_vibrate_ms", 10000);
   Preferences::AddUintVarCache(&sMaxVibrateListLen,
                                "dom.vibrator.max_vibrate_list_len", 128);
 }
 
 Navigator::Navigator(nsPIDOMWindowInner* aWindow)
   : mWindow(aWindow)
 {
-  MOZ_ASSERT(aWindow->IsInnerWindow(), "Navigator must get an inner window!");
 }
 
 Navigator::~Navigator()
 {
   Invalidate();
 }
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Navigator)
@@ -1623,18 +1622,16 @@ Navigator::SizeOfIncludingThis(mozilla::
   // TODO: add SizeOfIncludingThis() to DesktopNotificationCenter, bug 674116.
 
   return n;
 }
 
 void
 Navigator::SetWindow(nsPIDOMWindowInner *aInnerWindow)
 {
-  NS_ASSERTION(aInnerWindow->IsInnerWindow(),
-               "Navigator must get an inner window!");
   mWindow = aInnerWindow;
 }
 
 void
 Navigator::OnNavigation()
 {
   if (!mWindow) {
     return;
@@ -1707,17 +1704,16 @@ Navigator::HasUserMediaSupport(JSContext
 }
 
 /* static */
 already_AddRefed<nsPIDOMWindowInner>
 Navigator::GetWindowFromGlobal(JSObject* aGlobal)
 {
   nsCOMPtr<nsPIDOMWindowInner> win =
     do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(aGlobal));
-  MOZ_ASSERT(!win || win->IsInnerWindow());
   return win.forget();
 }
 
 nsresult
 Navigator::GetPlatform(nsAString& aPlatform, bool aUsePrefOverriddenValue)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
--- a/dom/base/PostMessageEvent.cpp
+++ b/dom/base/PostMessageEvent.cpp
@@ -50,21 +50,16 @@ PostMessageEvent::PostMessageEvent(nsGlo
 
 PostMessageEvent::~PostMessageEvent()
 {
 }
 
 NS_IMETHODIMP
 PostMessageEvent::Run()
 {
-  MOZ_ASSERT(mTargetWindow->IsOuterWindow(),
-             "should have been passed an outer window!");
-  MOZ_ASSERT(!mSource || mSource->IsOuterWindow(),
-             "should have been passed an outer window!");
-
   // Note: We don't init this AutoJSAPI with targetWindow, because we do not
   // want exceptions during message deserialization to trigger error events on
   // targetWindow.
   AutoJSAPI jsapi;
   jsapi.Init();
   JSContext* cx = jsapi.cx();
 
   // The document is just used for the principal mismatch error message below.
@@ -77,18 +72,16 @@ PostMessageEvent::Run()
   // that's probably better than crashing.
 
   RefPtr<nsGlobalWindowInner> targetWindow;
   if (mTargetWindow->IsClosedOrClosing() ||
       !(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) ||
       targetWindow->IsClosedOrClosing())
     return NS_OK;
 
-  MOZ_ASSERT(targetWindow->IsInnerWindow(),
-             "we ordered an inner window!");
   JSAutoCompartment ac(cx, targetWindow->GetWrapper());
 
   // Ensure that any origin which might have been provided is the origin of this
   // window's document.  Note that we do this *now* instead of when postMessage
   // is called because the target window might have been navigated to a
   // different location between then and now.  If this check happened when
   // postMessage was called, it would be fairly easy for a malicious webpage to
   // intercept messages intended for another site by carefully timing navigation
--- a/dom/base/TimeoutManager.cpp
+++ b/dom/base/TimeoutManager.cpp
@@ -405,18 +405,16 @@ TimeoutManager::TimeoutManager(nsGlobalW
     mRunningTimeout(nullptr),
     mIdleCallbackTimeoutCounter(1),
     mLastBudgetUpdate(TimeStamp::Now()),
     mExecutionBudget(GetMaxBudget(mWindow.IsBackgroundInternal())),
     mThrottleTimeouts(false),
     mThrottleTrackingTimeouts(false),
     mBudgetThrottleTimeouts(false)
 {
-  MOZ_DIAGNOSTIC_ASSERT(aWindow.IsInnerWindow());
-
   MOZ_LOG(gLog, LogLevel::Debug,
           ("TimeoutManager %p created, tracking bucketing %s\n",
            this, gAnnotateTrackingChannels ? "enabled" : "disabled"));
 }
 
 TimeoutManager::~TimeoutManager()
 {
   MOZ_DIAGNOSTIC_ASSERT(mWindow.AsInner()->InnerObjectsFreed());
@@ -582,27 +580,27 @@ TimeoutManager::SetTimeout(nsITimeoutHan
   if (!mWindow.IsSuspended()) {
     nsresult rv = MaybeSchedule(timeout->When(), now);
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
 
   if (gRunningTimeoutDepth == 0 &&
-      mWindow.GetPopupControlState() < openBlocked) {
+      nsContentUtils::GetPopupControlState() < openBlocked) {
     // This timeout is *not* set from another timeout and it's set
     // while popups are enabled. Propagate the state to the timeout if
     // its delay (interval) is equal to or less than what
     // "dom.disable_open_click_delay" is set to (in ms).
 
     // This is checking |interval|, not realInterval, on purpose,
     // because our lower bound for |realInterval| could be pretty high
     // in some cases.
     if (interval <= gDisableOpenClickDelay) {
-      timeout->mPopupState = mWindow.GetPopupControlState();
+      timeout->mPopupState = nsContentUtils::GetPopupControlState();
     }
   }
 
   Timeouts::SortBy sort(mWindow.IsFrozen() ? Timeouts::SortBy::TimeRemaining
                                            : Timeouts::SortBy::TimeWhen);
   if (timeout->mIsTracking) {
     mTrackingTimeouts.Insert(timeout, sort);
   } else {
@@ -1192,17 +1190,16 @@ namespace {
 
 class ThrottleTimeoutsCallback final : public nsITimerCallback
                                      , public nsINamed
 {
 public:
   explicit ThrottleTimeoutsCallback(nsGlobalWindowInner* aWindow)
     : mWindow(aWindow)
   {
-    MOZ_DIAGNOSTIC_ASSERT(aWindow->IsInnerWindow());
   }
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
 
   NS_IMETHOD GetName(nsACString& aName) override
   {
     aName.AssignLiteral("ThrottleTimeoutsCallback");
new file mode 100644
--- /dev/null
+++ b/dom/base/WindowDestroyedEvent.cpp
@@ -0,0 +1,138 @@
+#include "WindowDestroyedEvent.h"
+
+#include "nsJSUtils.h"
+#include "jsapi.h"              // for JSAutoRequest
+#include "jswrapper.h"
+#include "nsIPrincipal.h"
+#include "nsISupportsPrimitives.h"
+#include "nsIAppStartup.h"
+#include "nsToolkitCompsCID.h"
+#include "nsCOMPtr.h"
+
+namespace mozilla {
+
+// Try to match compartments that are not web content by matching compartments
+// with principals that are either the system principal or an expanded principal.
+// This may not return true for all non-web-content compartments.
+struct BrowserCompartmentMatcher : public js::CompartmentFilter {
+  bool match(JSCompartment* aC) const override
+  {
+    nsCOMPtr<nsIPrincipal> pc = nsJSPrincipals::get(JS_GetCompartmentPrincipals(aC));
+    return nsContentUtils::IsSystemOrExpandedPrincipal(pc);
+  }
+};
+
+WindowDestroyedEvent::WindowDestroyedEvent(nsGlobalWindowInner* aWindow,
+                                           uint64_t aID, const char* aTopic)
+  : mozilla::Runnable("WindowDestroyedEvent")
+  , mID(aID)
+  , mPhase(Phase::Destroying)
+  , mTopic(aTopic)
+  , mIsInnerWindow(true)
+{
+  mWindow = do_GetWeakReference(aWindow);
+}
+
+WindowDestroyedEvent::WindowDestroyedEvent(nsGlobalWindowOuter* aWindow,
+                                           uint64_t aID, const char* aTopic)
+  : mozilla::Runnable("WindowDestroyedEvent")
+  , mID(aID)
+  , mPhase(Phase::Destroying)
+  , mTopic(aTopic)
+  , mIsInnerWindow(false)
+{
+  mWindow = do_GetWeakReference(aWindow);
+}
+
+NS_IMETHODIMP
+WindowDestroyedEvent::Run()
+{
+  AUTO_PROFILER_LABEL("WindowDestroyedEvent::Run", OTHER);
+
+  nsCOMPtr<nsIObserverService> observerService =
+    services::GetObserverService();
+  if (!observerService) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsISupportsPRUint64> wrapper =
+    do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID);
+  if (wrapper) {
+    wrapper->SetData(mID);
+    observerService->NotifyObservers(wrapper, mTopic.get(), nullptr);
+  }
+
+  switch (mPhase) {
+    case Phase::Destroying:
+    {
+      bool skipNukeCrossCompartment = false;
+#ifndef DEBUG
+      nsCOMPtr<nsIAppStartup> appStartup =
+        do_GetService(NS_APPSTARTUP_CONTRACTID);
+
+      if (appStartup) {
+        appStartup->GetShuttingDown(&skipNukeCrossCompartment);
+      }
+#endif
+
+      if (!skipNukeCrossCompartment) {
+        // The compartment nuking phase might be too expensive, so do that
+        // part off of idle dispatch.
+
+        // For the compartment nuking phase, we dispatch either an
+        // inner-window-nuked or an outer-window-nuked notification.
+        // This will allow tests to wait for compartment nuking to happen.
+        if (mTopic.EqualsLiteral("inner-window-destroyed")) {
+          mTopic.AssignLiteral("inner-window-nuked");
+        } else if (mTopic.EqualsLiteral("outer-window-destroyed")) {
+          mTopic.AssignLiteral("outer-window-nuked");
+        }
+        mPhase = Phase::Nuking;
+
+        nsCOMPtr<nsIRunnable> copy(this);
+        NS_IdleDispatchToCurrentThread(copy.forget(), 1000);
+      }
+    }
+    break;
+
+    case Phase::Nuking:
+    {
+      nsCOMPtr<nsISupports> window = do_QueryReferent(mWindow);
+      if (window) {
+        nsGlobalWindowInner* currentInner;
+        if (mIsInnerWindow) {
+          currentInner = nsGlobalWindowInner::FromSupports(window);
+        } else {
+          nsGlobalWindowOuter* outer = nsGlobalWindowOuter::FromSupports(window);
+          currentInner = outer->GetCurrentInnerWindowInternal();
+        }
+        NS_ENSURE_TRUE(currentInner, NS_OK);
+
+        AutoSafeJSContext cx;
+        JS::Rooted<JSObject*> obj(cx, currentInner->FastGetGlobalJSObject());
+        if (obj && !js::IsSystemCompartment(js::GetObjectCompartment(obj))) {
+          JSCompartment* cpt = js::GetObjectCompartment(obj);
+          nsCOMPtr<nsIPrincipal> pc = nsJSPrincipals::get(JS_GetCompartmentPrincipals(cpt));
+
+          if (BasePrincipal::Cast(pc)->AddonPolicy()) {
+            // We want to nuke all references to the add-on compartment.
+            xpc::NukeAllWrappersForCompartment(cx, cpt,
+                                               mIsInnerWindow ? js::DontNukeWindowReferences
+                                                              : js::NukeWindowReferences);
+          } else {
+            // We only want to nuke wrappers for the chrome->content case
+            js::NukeCrossCompartmentWrappers(cx, BrowserCompartmentMatcher(), cpt,
+                                             mIsInnerWindow ? js::DontNukeWindowReferences
+                                                            : js::NukeWindowReferences,
+                                             js::NukeIncomingReferences);
+          }
+        }
+      }
+    }
+    break;
+  }
+
+  return NS_OK;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/base/WindowDestroyedEvent.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WindowDestroyedEvent_h
+#define WindowDestroyedEvent_h
+
+#include "nsGlobalWindow.h"
+#include "nsThreadUtils.h"
+#include "nsWeakPtr.h"
+#include "nsString.h"
+
+namespace mozilla {
+
+class WindowDestroyedEvent final : public Runnable
+{
+public:
+  WindowDestroyedEvent(nsGlobalWindowInner* aWindow,
+                       uint64_t aID, const char* aTopic);
+  WindowDestroyedEvent(nsGlobalWindowOuter* aWindow,
+                       uint64_t aID, const char* aTopic);
+
+  enum class Phase
+  {
+    Destroying,
+    Nuking
+  };
+
+  NS_IMETHOD Run() override;
+
+private:
+  uint64_t mID;
+  Phase mPhase;
+  nsCString mTopic;
+  nsWeakPtr mWindow;
+  bool mIsInnerWindow;
+};
+
+} // namespace mozilla
+
+#endif // defined(WindowDestroyedEvent_h)
--- a/dom/base/WindowOrientationObserver.cpp
+++ b/dom/base/WindowOrientationObserver.cpp
@@ -16,17 +16,17 @@ using namespace mozilla::dom;
  * and window.onorientationchange. This class is defined in its own file
  * because Hal.h pulls in windows.h and can't be included from
  * nsGlobalWindow.cpp
  */
 WindowOrientationObserver::WindowOrientationObserver(
   nsGlobalWindowInner* aGlobalWindow)
   : mWindow(aGlobalWindow)
 {
-  MOZ_ASSERT(aGlobalWindow && aGlobalWindow->IsInnerWindow());
+  MOZ_ASSERT(aGlobalWindow);
   hal::RegisterScreenConfigurationObserver(this);
 
   hal::ScreenConfiguration config;
   hal::GetCurrentScreenConfiguration(&config);
   mAngle = config.angle();
 }
 
 WindowOrientationObserver::~WindowOrientationObserver()
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -358,16 +358,17 @@ UNIFIED_SOURCES += [
     'ThirdPartyUtil.cpp',
     'Timeout.cpp',
     'TimeoutBudgetManager.cpp',
     'TimeoutExecutor.cpp',
     'TimeoutHandler.cpp',
     'TimeoutManager.cpp',
     'TreeWalker.cpp',
     'WebKitCSSMatrix.cpp',
+    'WindowDestroyedEvent.cpp',
     'WindowNamedPropertiesHandler.cpp',
     'WindowOrientationObserver.cpp',
     'XPathGenerator.cpp',
 ]
 
 if CONFIG['MOZ_WEBRTC']:
     UNIFIED_SOURCES += [
         'nsDOMDataChannel.cpp',
@@ -383,21 +384,19 @@ SOURCES += [
     # Several conflicts with other bindings.
     'DOMIntersectionObserver.cpp',
     # Because of OS X headers.
     'nsContentUtils.cpp',
     # this file doesn't like windows.h
     'nsDOMWindowUtils.cpp',
     # Conflicts with windows.h's definition of SendMessage.
     'nsFrameMessageManager.cpp',
-    # This file has a #error "Never include windows.h in this file!"
-    'nsGlobalWindow.cpp',
-    # These files are included by nsGlobalWindow.cpp
-    # 'nsGlobalWindowInner.cpp',
-    # 'nsGlobalWindowOuter.cpp',
+    # These files have a #error "Never include windows.h in this file!"
+    'nsGlobalWindowInner.cpp',
+    'nsGlobalWindowOuter.cpp',
     # Conflicts with windows.h's definition of LoadImage.
     'nsImageLoadingContent.cpp',
     # Because of OS X headers.
     'nsObjectLoadingContent.cpp',
     # nsPluginArray.cpp includes npapi.h indirectly, and that includes a lot of system headers
     'nsPluginArray.cpp',
 ]
 
--- a/dom/base/nsContentPermissionHelper.cpp
+++ b/dom/base/nsContentPermissionHelper.cpp
@@ -359,17 +359,16 @@ nsContentPermissionUtils::CreateContentP
 
   return parent;
 }
 
 /* static */ nsresult
 nsContentPermissionUtils::AskPermission(nsIContentPermissionRequest* aRequest,
                                         nsPIDOMWindowInner* aWindow)
 {
-  MOZ_ASSERT(!aWindow || aWindow->IsInnerWindow());
   NS_ENSURE_STATE(aWindow && aWindow->IsCurrentInnerWindow());
 
   // for content process
   if (XRE_IsContentProcess()) {
 
     RefPtr<RemotePermissionRequest> req =
       new RemotePermissionRequest(aRequest, aWindow);
 
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -338,16 +338,21 @@ bool nsContentUtils::sFragmentParsingAct
 #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
 bool nsContentUtils::sDOMWindowDumpEnabled;
 #endif
 
 bool nsContentUtils::sDoNotTrackEnabled = false;
 
 mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump");
 
+PopupControlState nsContentUtils::sPopupControlState = openAbused;
+
+int32_t nsContentUtils::sInnerOrOuterWindowCount = 0;
+uint32_t nsContentUtils::sInnerOrOuterWindowSerialCounter = 0;
+
 // Subset of http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name
 enum AutocompleteUnsupportedFieldName : uint8_t
 {
   #define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
     eAutocompleteUnsupportedFieldName_##name_,
   #include "AutocompleteFieldList.h"
   #undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
 };
@@ -9012,18 +9017,16 @@ nsContentUtils::IsNonSubresourceRequest(
   return type == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
          type == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
 }
 
 // static, public
 nsContentUtils::StorageAccess
 nsContentUtils::StorageAllowedForWindow(nsPIDOMWindowInner* aWindow)
 {
-  MOZ_ASSERT(aWindow->IsInnerWindow());
-
   if (nsIDocument* document = aWindow->GetExtantDoc()) {
     nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal();
     return InternalStorageAllowedForPrincipal(principal, aWindow);
   }
 
   return StorageAccess::eDeny;
 }
 
@@ -9102,17 +9105,16 @@ nsContentUtils::GetCookieBehaviorForPrin
 }
 
 // static, private
 nsContentUtils::StorageAccess
 nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
                                                    nsPIDOMWindowInner* aWindow)
 {
   MOZ_ASSERT(aPrincipal);
-  MOZ_ASSERT(!aWindow || aWindow->IsInnerWindow());
 
   StorageAccess access = StorageAccess::eAllow;
 
   // We don't allow storage on the null principal, in general. Even if the
   // calling context is chrome.
   if (aPrincipal->GetIsNullPrincipal()) {
     return StorageAccess::eDeny;
   }
@@ -10969,8 +10971,49 @@ nsContentUtils::DevToolsEnabled(JSContex
 
   workers::WorkerPrivate* workerPrivate = workers::GetWorkerPrivateFromContext(aCx);
   if (!workerPrivate) {
     return false;
   }
 
   return workerPrivate->DevToolsEnabled();
 }
+
+/* static */ bool
+nsContentUtils::ContentIsLink(nsIContent* aContent)
+{
+  return aContent && (aContent->IsHTMLElement(nsGkAtoms::a) ||
+                      aContent->AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::type,
+                                            nsGkAtoms::simple, eCaseMatters));
+}
+
+/* static */ already_AddRefed<EventTarget>
+nsContentUtils::TryGetTabChildGlobalAsEventTarget(nsISupports* aFrom)
+{
+  nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner = do_QueryInterface(aFrom);
+  if (!frameLoaderOwner) {
+    return nullptr;
+  }
+
+  RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
+  if (!frameLoader) {
+    return nullptr;
+  }
+
+  nsCOMPtr<EventTarget> target = frameLoader->GetTabChildGlobalAsEventTarget();
+  return target.forget();
+}
+
+/* static */ uint32_t
+nsContentUtils::InnerOrOuterWindowCreated()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  ++sInnerOrOuterWindowCount;
+  return ++sInnerOrOuterWindowSerialCounter;
+}
+
+/* static */ void
+nsContentUtils::InnerOrOuterWindowDestroyed()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(sInnerOrOuterWindowCount > 0);
+  --sInnerOrOuterWindowCount;
+}
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -3238,16 +3238,48 @@ public:
    * Returns true if the passed-in mesasge is a pending InputEvent.
    *
    * @param aMsg  The message to check
    */
   static bool IsMessageInputEvent(const IPC::Message& aMsg);
 
   static void AsyncPrecreateStringBundles();
 
+  static bool ContentIsLink(nsIContent* aContent);
+
+  static already_AddRefed<mozilla::dom::EventTarget>
+  TryGetTabChildGlobalAsEventTarget(nsISupports* aFrom);
+
+  static PopupControlState
+  PushPopupControlState(PopupControlState aState, bool aForce)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    PopupControlState old = sPopupControlState;
+    if (aState < old || aForce) {
+      sPopupControlState = aState;
+    }
+    return old;
+  }
+
+  static void
+  PopPopupControlState(PopupControlState aState)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    sPopupControlState = aState;
+  }
+
+  static PopupControlState GetPopupControlState() { return sPopupControlState; }
+
+  // Get a serial number for a newly created inner or outer window.
+  static uint32_t InnerOrOuterWindowCreated();
+  // Record that an inner or outer window has been destroyed.
+  static void InnerOrOuterWindowDestroyed();
+  // Get the current number of inner or outer windows.
+  static int32_t GetCurrentInnerOrOuterWindowCount() { return sInnerOrOuterWindowCount; }
+
 private:
   static bool InitializeEventTable();
 
   static nsresult EnsureStringBundle(PropertiesFile aFile);
 
   static bool CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
                                 nsIPrincipal* aPrincipal);
 
@@ -3426,16 +3458,21 @@ private:
   // bytecode out of the nsCacheInfoChannel.
   static nsCString* sJSBytecodeMimeType;
 
 #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
   static bool sDOMWindowDumpEnabled;
 #endif
   static bool sDoNotTrackEnabled;
   static mozilla::LazyLogModule sDOMDumpLog;
+
+  static PopupControlState sPopupControlState;
+
+  static int32_t sInnerOrOuterWindowCount;
+  static uint32_t sInnerOrOuterWindowSerialCounter;
 };
 
 /* static */ inline
 nsContentPolicyType
 nsContentUtils::InternalContentPolicyTypeToExternal(nsContentPolicyType aType)
 {
   switch (aType) {
   case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -224,17 +224,16 @@ FindObjectClass(JSContext* cx, JSObject*
   sObjectClass = js::GetObjectJSClass(obj);
 }
 
 // Helper to handle torn-down inner windows.
 static inline nsresult
 SetParentToWindow(nsGlobalWindowInner *win, JSObject **parent)
 {
   MOZ_ASSERT(win);
-  MOZ_ASSERT(win->IsInnerWindow());
   *parent = win->FastGetGlobalJSObject();
 
   if (MOZ_UNLIKELY(!*parent)) {
     // The inner window has been torn down. The scope is dying, so don't create
     // any new wrappers.
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
@@ -1024,22 +1023,23 @@ nsDOMConstructor::Create(const char16_t*
   // Prevent creating a constructor if aOwner is inner window which doesn't have
   // an outer window. If the outer window doesn't have an inner window or the
   // caller can't access the outer window's current inner window then try to use
   // the owner (so long as it is, in fact, an inner window). If that doesn't
   // work then prevent creation also.
   nsPIDOMWindowOuter* outerWindow = aOwner->GetOuterWindow();
   nsPIDOMWindowInner* currentInner =
     outerWindow ? outerWindow->GetCurrentInnerWindow() : aOwner;
-  if (!currentInner ||
-      (aOwner != currentInner &&
-       !nsContentUtils::CanCallerAccess(currentInner) &&
-       !(currentInner = aOwner)->IsInnerWindow())) {
+  if (!currentInner) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
+  if (aOwner != currentInner &&
+      !nsContentUtils::CanCallerAccess(currentInner)) {
+    currentInner = aOwner;
+  }
 
   bool constructable = aNameStruct && IsConstructable(aNameStruct);
 
   *aResult = new nsDOMConstructor(aName, constructable, currentInner);
   NS_ADDREF(*aResult);
   return NS_OK;
 }
 
--- a/dom/base/nsDOMMutationObserver.cpp
+++ b/dom/base/nsDOMMutationObserver.cpp
@@ -811,17 +811,16 @@ nsDOMMutationObserver::Constructor(const
                                    mozilla::dom::MutationCallback& aCb,
                                    mozilla::ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
   if (!window) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
-  MOZ_ASSERT(window->IsInnerWindow());
   bool isChrome = nsContentUtils::IsChromeDoc(window->GetExtantDoc());
   RefPtr<nsDOMMutationObserver> observer =
     new nsDOMMutationObserver(window.forget(), aCb, isChrome);
   return observer.forget();
 }
 
 
 bool
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -207,17 +207,16 @@ NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(nsDOMWindowUtils)
 NS_IMPL_RELEASE(nsDOMWindowUtils)
 
 nsDOMWindowUtils::nsDOMWindowUtils(nsGlobalWindowOuter *aWindow)
 {
   nsCOMPtr<nsISupports> supports = do_QueryObject(aWindow);
   mWindow = do_GetWeakReference(supports);
-  NS_ASSERTION(aWindow->IsOuterWindow(), "How did that happen?");
 }
 
 nsDOMWindowUtils::~nsDOMWindowUtils()
 {
   OldWindowSize::GetAndRemove(mWindow);
 }
 
 nsIPresShell*
@@ -2385,28 +2384,26 @@ nsDOMWindowUtils::SetDesktopModeViewport
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetOuterWindowID(uint64_t *aWindowID)
 {
   nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
   NS_ENSURE_STATE(window);
 
-  NS_ASSERTION(window->IsOuterWindow(), "How did that happen?");
   *aWindowID = window->WindowID();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetCurrentInnerWindowID(uint64_t *aWindowID)
 {
   nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
   NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE);
 
-  NS_ASSERTION(window->IsOuterWindow(), "How did that happen?");
   nsGlobalWindowInner* inner =
     nsGlobalWindowOuter::Cast(window)->GetCurrentInnerWindowInternal();
   if (!inner) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   *aWindowID = inner->WindowID();
   return NS_OK;
 }
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1533,16 +1533,17 @@ nsIDocument::nsIDocument()
     mDidFireDOMContentLoaded(true),
     mHasScrollLinkedEffect(false),
     mFrameRequestCallbacksScheduled(false),
     mIsTopLevelContentDocument(false),
     mIsContentDocument(false),
     mDidCallBeginLoad(false),
     mBufferingCSPViolations(false),
     mAllowPaymentRequest(false),
+    mEncodingMenuDisabled(false),
     mIsScopedStyleEnabled(eScopedStyle_Unknown),
     mCompatMode(eCompatibility_FullStandards),
     mReadyState(ReadyState::READYSTATE_UNINITIALIZED),
     mStyleBackendType(StyleBackendType::None),
 #ifdef MOZILLA_INTERNAL_API
     mVisibilityState(dom::VisibilityState::Hidden),
 #else
     mDummy(0),
@@ -5058,24 +5059,16 @@ nsISupports*
 nsIDocument::GetContainer() const
 {
   return static_cast<nsIDocShell*>(mDocumentContainer);
 }
 
 void
 nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
 {
-#ifdef DEBUG
-  {
-    nsCOMPtr<nsPIDOMWindowInner> win(do_QueryInterface(aScriptGlobalObject));
-
-    NS_ASSERTION(!win || win->IsInnerWindow(),
-                 "Script global object must be an inner window!");
-  }
-#endif
   MOZ_ASSERT(aScriptGlobalObject || !mAnimationController ||
              mAnimationController->IsPausedByType(
                nsSMILTimeContainer::PAUSE_PAGEHIDE |
                nsSMILTimeContainer::PAUSE_BEGIN),
              "Clearing window pointer while animations are unpaused");
 
   if (mScriptGlobalObject && !aScriptGlobalObject) {
     // We're detaching from the window.  We need to grab a pointer to
@@ -10884,17 +10877,16 @@ nsIDocument::CreateTouch(nsGlobalWindowI
                          int32_t aIdentifier,
                          int32_t aPageX, int32_t aPageY,
                          int32_t aScreenX, int32_t aScreenY,
                          int32_t aClientX, int32_t aClientY,
                          int32_t aRadiusX, int32_t aRadiusY,
                          float aRotationAngle,
                          float aForce)
 {
-  MOZ_ASSERT_IF(aView, aView->IsInnerWindow());
   RefPtr<Touch> touch = new Touch(aTarget,
                                   aIdentifier,
                                   aPageX, aPageY,
                                   aScreenX, aScreenY,
                                   aClientX, aClientY,
                                   aRadiusX, aRadiusY,
                                   aRotationAngle,
                                   aForce);
@@ -14375,17 +14367,16 @@ nsIDocument::ClearStaleServoData()
 Selection*
 nsIDocument::GetSelection(ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindowInner> window = GetInnerWindow();
   if (!window) {
     return nullptr;
   }
 
-  NS_ASSERTION(window->IsInnerWindow(), "Should have inner window here!");
   if (!window->IsCurrentInnerWindow()) {
     return nullptr;
   }
 
   return nsGlobalWindowInner::Cast(window)->GetSelection(aRv);
 }
 
 void
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -1033,17 +1033,16 @@ nsFocusManager::WindowHidden(mozIDOMWind
     docShellBeingHidden->IsBeingDestroyed(&beingDestroyed);
   }
   if (beingDestroyed) {
     // There is usually no need to do anything if a toplevel window is going
     // away, as we assume that WindowLowered will be called. However, this may
     // not happen if nsIAppStartup::eForceQuit is used to quit, and can cause
     // a leak. So if the active window is being destroyed, call WindowLowered
     // directly.
-    NS_ASSERTION(mFocusedWindow->IsOuterWindow(), "outer window expected");
     if (mActiveWindow == mFocusedWindow || mActiveWindow == window)
       WindowLowered(mActiveWindow);
     else
       ClearFocus(mActiveWindow);
     return NS_OK;
   }
 
   // if the window being hidden is an ancestor of the focused window, adjust
deleted file mode 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ /dev/null
@@ -1,832 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsGlobalWindow.h"
-
-#include <algorithm>
-
-#include "mozilla/MemoryReporting.h"
-
-// Local Includes
-#include "Navigator.h"
-#include "nsContentSecurityManager.h"
-#include "nsScreen.h"
-#include "nsHistory.h"
-#include "nsDOMNavigationTiming.h"
-#include "nsIDOMStorageManager.h"
-#include "mozilla/dom/LocalStorage.h"
-#include "mozilla/dom/Storage.h"
-#include "mozilla/dom/IdleRequest.h"
-#include "mozilla/dom/Performance.h"
-#include "mozilla/dom/StorageEvent.h"
-#include "mozilla/dom/StorageEventBinding.h"
-#include "mozilla/dom/StorageNotifierService.h"
-#include "mozilla/dom/StorageUtils.h"
-#include "mozilla/dom/Timeout.h"
-#include "mozilla/dom/TimeoutHandler.h"
-#include "mozilla/dom/TimeoutManager.h"
-#include "mozilla/IntegerPrintfMacros.h"
-#if defined(MOZ_WIDGET_ANDROID)
-#include "mozilla/dom/WindowOrientationObserver.h"
-#endif
-#include "nsDOMOfflineResourceList.h"
-#include "nsError.h"
-#include "nsIIdleService.h"
-#include "nsISizeOfEventTarget.h"
-#include "nsDOMJSUtils.h"
-#include "nsArrayUtils.h"
-#include "nsIDOMWindowCollection.h"
-#include "nsDOMWindowList.h"
-#include "mozilla/dom/WakeLock.h"
-#include "mozilla/dom/power/PowerManagerService.h"
-#include "nsIDocShellTreeOwner.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsIPermissionManager.h"
-#include "nsIScriptContext.h"
-#include "nsIScriptTimeoutHandler.h"
-#include "nsITimeoutHandler.h"
-#include "nsIController.h"
-#include "nsScriptNameSpaceManager.h"
-#include "nsISlowScriptDebug.h"
-#include "nsWindowMemoryReporter.h"
-#include "nsWindowSizes.h"
-#include "WindowNamedPropertiesHandler.h"
-#include "nsFrameSelection.h"
-#include "nsNetUtil.h"
-#include "nsVariant.h"
-#include "nsPrintfCString.h"
-#include "mozilla/intl/LocaleService.h"
-
-// Helper Classes
-#include "nsJSUtils.h"
-#include "jsapi.h"              // for JSAutoRequest
-#include "jswrapper.h"
-#include "nsCharSeparatedTokenizer.h"
-#include "nsReadableUtils.h"
-#include "nsDOMClassInfo.h"
-#include "nsJSEnvironment.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/Likely.h"
-#include "mozilla/Sprintf.h"
-#include "mozilla/Unused.h"
-
-// Other Classes
-#include "mozilla/dom/BarProps.h"
-#include "nsContentCID.h"
-#include "nsLayoutStatics.h"
-#include "nsCCUncollectableMarker.h"
-#include "mozilla/dom/workers/Workers.h"
-#include "mozilla/dom/ToJSValue.h"
-#include "nsJSPrincipals.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/Debug.h"
-#include "mozilla/EventListenerManager.h"
-#include "mozilla/EventStates.h"
-#include "mozilla/MouseEvents.h"
-#include "mozilla/ProcessHangMonitor.h"
-#include "mozilla/ThrottledEventQueue.h"
-#include "AudioChannelService.h"
-#include "nsAboutProtocolUtils.h"
-#include "nsCharTraits.h" // NS_IS_HIGH/LOW_SURROGATE
-#include "PostMessageEvent.h"
-#include "mozilla/dom/DocGroup.h"
-#include "mozilla/dom/TabGroup.h"
-
-// Interfaces Needed
-#include "nsIFrame.h"
-#include "nsCanvasFrame.h"
-#include "nsIWidget.h"
-#include "nsIWidgetListener.h"
-#include "nsIBaseWindow.h"
-#include "nsIDeviceSensors.h"
-#include "nsIContent.h"
-#include "nsIDocShell.h"
-#include "nsIDocCharset.h"
-#include "nsIDocument.h"
-#include "Crypto.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMElement.h"
-#include "nsIDOMEvent.h"
-#include "nsIDOMOfflineResourceList.h"
-#include "nsDOMString.h"
-#include "nsIEmbeddingSiteWindow.h"
-#include "nsThreadUtils.h"
-#include "nsILoadContext.h"
-#include "nsIPresShell.h"
-#include "nsIScrollableFrame.h"
-#include "nsView.h"
-#include "nsViewManager.h"
-#include "nsISelectionController.h"
-#include "nsISelection.h"
-#include "nsIPrompt.h"
-#include "nsIPromptService.h"
-#include "nsIPromptFactory.h"
-#include "nsIAddonPolicyService.h"
-#include "nsIWritablePropertyBag2.h"
-#include "nsIWebNavigation.h"
-#include "nsIWebBrowserChrome.h"
-#include "nsIWebBrowserFind.h"  // For window.find()
-#include "nsIWindowMediator.h"  // For window.find()
-#include "nsComputedDOMStyle.h"
-#include "nsDOMCID.h"
-#include "nsDOMWindowUtils.h"
-#include "nsIWindowWatcher.h"
-#include "nsPIWindowWatcher.h"
-#include "nsIContentViewer.h"
-#include "nsIScriptError.h"
-#include "nsIControllers.h"
-#include "nsIControllerContext.h"
-#include "nsGlobalWindowCommands.h"
-#include "nsQueryObject.h"
-#include "nsContentUtils.h"
-#include "nsCSSProps.h"
-#include "nsIDOMFileList.h"
-#include "nsIURIFixup.h"
-#ifndef DEBUG
-#include "nsIAppStartup.h"
-#include "nsToolkitCompsCID.h"
-#endif
-#include "nsCDefaultURIFixup.h"
-#include "mozilla/EventDispatcher.h"
-#include "mozilla/EventStateManager.h"
-#include "nsIObserverService.h"
-#include "nsFocusManager.h"
-#include "nsIXULWindow.h"
-#include "nsITimedChannel.h"
-#include "nsServiceManagerUtils.h"
-#ifdef MOZ_XUL
-#include "nsIDOMXULControlElement.h"
-#include "nsMenuPopupFrame.h"
-#endif
-#include "mozilla/dom/CustomEvent.h"
-#include "nsIJARChannel.h"
-#include "nsIScreenManager.h"
-#include "nsIEffectiveTLDService.h"
-
-#include "xpcprivate.h"
-
-#ifdef NS_PRINTING
-#include "nsIPrintSettings.h"
-#include "nsIPrintSettingsService.h"
-#include "nsIWebBrowserPrint.h"
-#endif
-
-#include "nsWindowRoot.h"
-#include "nsNetCID.h"
-#include "nsIArray.h"
-
-// XXX An unfortunate dependency exists here (two XUL files).
-#include "nsIDOMXULDocument.h"
-#include "nsIDOMXULCommandDispatcher.h"
-
-#include "nsBindingManager.h"
-#include "nsXBLService.h"
-
-// used for popup blocking, needs to be converted to something
-// belonging to the back-end like nsIContentPolicy
-#include "nsIPopupWindowManager.h"
-
-#include "nsIDragService.h"
-#include "mozilla/dom/Element.h"
-#include "mozilla/dom/Selection.h"
-#include "nsFrameLoader.h"
-#include "nsISupportsPrimitives.h"
-#include "nsXPCOMCID.h"
-#include "mozilla/Logging.h"
-#include "prenv.h"
-
-#include "mozilla/dom/IDBFactory.h"
-#include "mozilla/dom/MessageChannel.h"
-#include "mozilla/dom/Promise.h"
-
-#include "mozilla/dom/Gamepad.h"
-#include "mozilla/dom/GamepadManager.h"
-
-#include "gfxVR.h"
-#include "mozilla/dom/VRDisplay.h"
-#include "mozilla/dom/VRDisplayEvent.h"
-#include "mozilla/dom/VRDisplayEventBinding.h"
-#include "mozilla/dom/VREventObserver.h"
-
-#include "nsRefreshDriver.h"
-#include "Layers.h"
-
-#include "mozilla/AddonPathService.h"
-#include "mozilla/BasePrincipal.h"
-#include "mozilla/Services.h"
-#include "mozilla/Telemetry.h"
-#include "mozilla/dom/Location.h"
-#include "nsHTMLDocument.h"
-#include "nsWrapperCacheInlines.h"
-#include "mozilla/DOMEventTargetHelper.h"
-#include "prrng.h"
-#include "nsSandboxFlags.h"
-#include "TimeChangeObserver.h"
-#include "mozilla/dom/AudioContext.h"
-#include "mozilla/dom/BrowserElementDictionariesBinding.h"
-#include "mozilla/dom/cache/CacheStorage.h"
-#include "mozilla/dom/Console.h"
-#include "mozilla/dom/Fetch.h"
-#include "mozilla/dom/FunctionBinding.h"
-#include "mozilla/dom/HashChangeEvent.h"
-#include "mozilla/dom/IntlUtils.h"
-#include "mozilla/dom/MozSelfSupportBinding.h"
-#include "mozilla/dom/PopStateEvent.h"
-#include "mozilla/dom/PopupBlockedEvent.h"
-#include "mozilla/dom/PrimitiveConversions.h"
-#include "mozilla/dom/WindowBinding.h"
-#include "nsITabChild.h"
-#include "mozilla/dom/MediaQueryList.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/NavigatorBinding.h"
-#include "mozilla/dom/ImageBitmap.h"
-#include "mozilla/dom/ImageBitmapBinding.h"
-#include "mozilla/dom/ServiceWorkerRegistration.h"
-#include "mozilla/dom/U2F.h"
-#include "mozilla/dom/WebIDLGlobalNameHash.h"
-#include "mozilla/dom/Worklet.h"
-#ifdef HAVE_SIDEBAR
-#include "mozilla/dom/ExternalBinding.h"
-#endif
-
-#ifdef MOZ_WEBSPEECH
-#include "mozilla/dom/SpeechSynthesis.h"
-#endif
-
-// Apple system headers seem to have a check() macro.  <sigh>
-#ifdef check
-class nsIScriptTimeoutHandler;
-#undef check
-#endif // check
-#include "AccessCheck.h"
-
-#ifdef ANDROID
-#include <android/log.h>
-#endif
-
-#ifdef XP_WIN
-#include <process.h>
-#define getpid _getpid
-#else
-#include <unistd.h> // for getpid()
-#endif
-
-static const char kStorageEnabled[] = "dom.storage.enabled";
-
-using namespace mozilla;
-using namespace mozilla::dom;
-using namespace mozilla::dom::ipc;
-using mozilla::BasePrincipal;
-using mozilla::OriginAttributes;
-using mozilla::TimeStamp;
-using mozilla::TimeDuration;
-using mozilla::dom::cache::CacheStorage;
-
-static LazyLogModule gDOMLeakPRLog("DOMLeak");
-
-static int32_t              gRefCnt                           = 0;
-static int32_t              gOpenPopupSpamCount               = 0;
-static PopupControlState    gPopupControlState                = openAbused;
-static bool                 gMouseDown                        = false;
-static bool                 gDragServiceDisabled              = false;
-static FILE                *gDumpFile                         = nullptr;
-static uint32_t             gSerialCounter                    = 0;
-static bool                 gIdleObserversAPIFuzzTimeDisabled = false;
-
-#ifdef DEBUG_jst
-int32_t gTimeoutCnt                                    = 0;
-#endif
-
-#if defined(DEBUG_bryner) || defined(DEBUG_chb)
-#define DEBUG_PAGE_CACHE
-#endif
-
-#define DOM_TOUCH_LISTENER_ADDED "dom-touch-listener-added"
-
-#define MEMORY_PRESSURE_OBSERVER_TOPIC "memory-pressure"
-
-// The interval at which we execute idle callbacks
-static uint32_t gThrottledIdlePeriodLength;
-
-#define DEFAULT_THROTTLED_IDLE_PERIOD_LENGTH 10000
-
-// CIDs
-static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
-
-#define NETWORK_UPLOAD_EVENT_NAME     NS_LITERAL_STRING("moznetworkupload")
-#define NETWORK_DOWNLOAD_EVENT_NAME   NS_LITERAL_STRING("moznetworkdownload")
-
-namespace mozilla {
-namespace dom {
-extern uint64_t
-NextWindowID();
-} // namespace dom
-} // namespace mozilla
-
-template<class T>
-nsPIDOMWindow<T>::nsPIDOMWindow(nsPIDOMWindowOuter *aOuterWindow)
-: mFrameElement(nullptr), mDocShell(nullptr), mModalStateDepth(0),
-  mMutationBits(0), mActivePeerConnections(0), mIsDocumentLoaded(false),
-  mIsHandlingResizeEvent(false), mIsInnerWindow(aOuterWindow != nullptr),
-  mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false),
-  mMayHaveSelectionChangeEventListener(false),
-  mMayHaveMouseEnterLeaveEventListener(false),
-  mMayHavePointerEnterLeaveEventListener(false),
-  mInnerObjectsFreed(false),
-  mIsActive(false), mIsBackground(false),
-  mMediaSuspend(
-    Preferences::GetBool("media.block-autoplay-until-in-foreground", true) &&
-    Preferences::GetBool("media.autoplay.enabled", true) ?
-      nsISuspendedTypes::SUSPENDED_BLOCK : nsISuspendedTypes::NONE_SUSPENDED),
-  mAudioMuted(false), mAudioVolume(1.0), mAudioCaptured(false),
-  mDesktopModeViewport(false), mIsRootOuterWindow(false), mInnerWindow(nullptr),
-  mOuterWindow(aOuterWindow),
-  // Make sure no actual window ends up with mWindowID == 0
-  mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
-  mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false),
-  mLargeAllocStatus(LargeAllocStatus::NONE),
-  mHasTriedToCacheTopInnerWindow(false),
-  mNumOfIndexedDBDatabases(0),
-  mNumOfOpenWebSockets(0)
-{
-  if (aOuterWindow) {
-    mTimeoutManager =
-      MakeUnique<mozilla::dom::TimeoutManager>(*nsGlobalWindowInner::Cast(AsInner()));
-  }
-}
-
-template<class T>
-nsPIDOMWindow<T>::~nsPIDOMWindow() {}
-
-PopupControlState
-PushPopupControlState(PopupControlState aState, bool aForce)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  PopupControlState oldState = gPopupControlState;
-
-  if (aState < gPopupControlState || aForce) {
-    gPopupControlState = aState;
-  }
-
-  return oldState;
-}
-
-void
-PopPopupControlState(PopupControlState aState)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  gPopupControlState = aState;
-}
-
-// We need certain special behavior for remote XUL whitelisted domains, but we
-// don't want that behavior to take effect in automation, because we whitelist
-// all the mochitest domains. So we need to check a pref here.
-static bool
-TreatAsRemoteXUL(nsIPrincipal* aPrincipal)
-{
-  MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(aPrincipal));
-  return nsContentUtils::AllowXULXBLForPrincipal(aPrincipal) &&
-         !Preferences::GetBool("dom.use_xbl_scopes_for_remote_xul", false);
-}
-
-static bool
-EnablePrivilege(JSContext* cx, unsigned argc, JS::Value* vp)
-{
-  Telemetry::Accumulate(Telemetry::ENABLE_PRIVILEGE_EVER_CALLED, true);
-  return xpc::EnableUniversalXPConnect(cx);
-}
-
-static const JSFunctionSpec EnablePrivilegeSpec[] = {
-  JS_FN("enablePrivilege", EnablePrivilege, 1, 0),
-  JS_FS_END
-};
-
-static bool
-InitializeLegacyNetscapeObject(JSContext* aCx, JS::Handle<JSObject*> aGlobal)
-{
-  JSAutoCompartment ac(aCx, aGlobal);
-
-  // Note: MathJax depends on window.netscape being exposed. See bug 791526.
-  JS::Rooted<JSObject*> obj(aCx);
-  obj = JS_DefineObject(aCx, aGlobal, "netscape", nullptr);
-  NS_ENSURE_TRUE(obj, false);
-
-  obj = JS_DefineObject(aCx, obj, "security", nullptr);
-  NS_ENSURE_TRUE(obj, false);
-
-  // We hide enablePrivilege behind a pref because it has been altered in a
-  // way that makes it fundamentally insecure to use in production. Mozilla
-  // uses this pref during automated testing to support legacy test code that
-  // uses enablePrivilege. If you're not doing test automation, you _must_ not
-  // flip this pref, or you will be exposing all your users to security
-  // vulnerabilities.
-  if (!xpc::IsInAutomation()) {
-    return true;
-  }
-
-  /* Define PrivilegeManager object with the necessary "static" methods. */
-  obj = JS_DefineObject(aCx, obj, "PrivilegeManager", nullptr);
-  NS_ENSURE_TRUE(obj, false);
-
-  return JS_DefineFunctions(aCx, obj, EnablePrivilegeSpec);
-}
-
-static JS::CompartmentCreationOptions&
-SelectZoneGroup(nsGlobalWindowInner* aNewInner,
-                JS::CompartmentCreationOptions& aOptions)
-{
-  JS::CompartmentCreationOptions options;
-
-  if (aNewInner->GetOuterWindow()) {
-    nsGlobalWindowOuter *top = aNewInner->GetTopInternal();
-
-    // If we have a top-level window, use its zone (and zone group).
-    if (top && top->GetGlobalJSObject()) {
-      return aOptions.setExistingZone(top->GetGlobalJSObject());
-    }
-  }
-
-  // If we're in the parent process, don't bother with zone groups.
-  if (XRE_IsParentProcess()) {
-    return aOptions.setNewZoneInSystemZoneGroup();
-  }
-
-  // Otherwise, find a zone group from the TabGroup. Typically we only have to
-  // go through one iteration of this loop.
-  RefPtr<TabGroup> tabGroup = aNewInner->TabGroup();
-  for (nsPIDOMWindowOuter* outer : tabGroup->GetWindows()) {
-    nsGlobalWindowOuter* window = nsGlobalWindowOuter::Cast(outer);
-    if (JSObject* global = window->GetGlobalJSObject()) {
-      return aOptions.setNewZoneInExistingZoneGroup(global);
-    }
-  }
-
-  return aOptions.setNewZoneInNewZoneGroup();
-}
-
-/**
- * Create a new global object that will be used for an inner window.
- * Return the native global and an nsISupports 'holder' that can be used
- * to manage the lifetime of it.
- */
-static nsresult
-CreateNativeGlobalForInner(JSContext* aCx,
-                           nsGlobalWindowInner* aNewInner,
-                           nsIURI* aURI,
-                           nsIPrincipal* aPrincipal,
-                           JS::MutableHandle<JSObject*> aGlobal,
-                           bool aIsSecureContext)
-{
-  MOZ_ASSERT(aCx);
-  MOZ_ASSERT(aNewInner);
-  MOZ_ASSERT(aNewInner->IsInnerWindow());
-  MOZ_ASSERT(aPrincipal);
-
-  // DOMWindow with nsEP is not supported, we have to make sure
-  // no one creates one accidentally.
-  nsCOMPtr<nsIExpandedPrincipal> nsEP = do_QueryInterface(aPrincipal);
-  MOZ_RELEASE_ASSERT(!nsEP, "DOMWindow with nsEP is not supported");
-
-  JS::CompartmentOptions options;
-
-  SelectZoneGroup(aNewInner, options.creationOptions());
-
-  // Sometimes add-ons load their own XUL windows, either as separate top-level
-  // windows or inside a browser element. In such cases we want to tag the
-  // window's compartment with the add-on ID. See bug 1092156.
-  if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
-    options.creationOptions().setAddonId(MapURIToAddonID(aURI));
-  }
-
-  options.creationOptions().setSecureContext(aIsSecureContext);
-
-  xpc::InitGlobalObjectOptions(options, aPrincipal);
-
-  // Determine if we need the Components object.
-  bool needComponents = nsContentUtils::IsSystemPrincipal(aPrincipal) ||
-                        TreatAsRemoteXUL(aPrincipal);
-  uint32_t flags = needComponents ? 0 : xpc::OMIT_COMPONENTS_OBJECT;
-  flags |= xpc::DONT_FIRE_ONNEWGLOBALHOOK;
-
-  if (!WindowBinding::Wrap(aCx, aNewInner, aNewInner, options,
-                           nsJSPrincipals::get(aPrincipal), false, aGlobal) ||
-      !xpc::InitGlobalObject(aCx, aGlobal, flags)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  MOZ_ASSERT(aNewInner->GetWrapperPreserveColor() == aGlobal);
-
-  // Set the location information for the new global, so that tools like
-  // about:memory may use that information
-  xpc::SetLocationForGlobal(aGlobal, aURI);
-
-  if (!InitializeLegacyNetscapeObject(aCx, aGlobal)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  return NS_OK;
-}
-
-static
-already_AddRefed<EventTarget>
-TryGetTabChildGlobalAsEventTarget(nsISupports *aFrom)
-{
-  nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner = do_QueryInterface(aFrom);
-  if (!frameLoaderOwner) {
-    return nullptr;
-  }
-
-  RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
-  if (!frameLoader) {
-    return nullptr;
-  }
-
-  nsCOMPtr<EventTarget> target = frameLoader->GetTabChildGlobalAsEventTarget();
-  return target.forget();
-}
-
-template <class T>
-nsIURI*
-nsPIDOMWindow<T>::GetDocumentURI() const
-{
-  return mDoc ? mDoc->GetDocumentURI() : mDocumentURI.get();
-}
-
-template <class T>
-nsIURI*
-nsPIDOMWindow<T>::GetDocBaseURI() const
-{
-  return mDoc ? mDoc->GetDocBaseURI() : mDocBaseURI.get();
-}
-
-template <class T>
-void
-nsPIDOMWindow<T>::MaybeCreateDoc()
-{
-  MOZ_ASSERT(!mDoc);
-  if (nsIDocShell* docShell = GetDocShell()) {
-    // Note that |document| here is the same thing as our mDoc, but we
-    // don't have to explicitly set the member variable because the docshell
-    // has already called SetNewDocument().
-    nsCOMPtr<nsIDocument> document = docShell->GetDocument();
-    Unused << document;
-  }
-}
-
-// Try to match compartments that are not web content by matching compartments
-// with principals that are either the system principal or an expanded principal.
-// This may not return true for all non-web-content compartments.
-struct BrowserCompartmentMatcher : public js::CompartmentFilter {
-  bool match(JSCompartment* aC) const override
-    {
-      nsCOMPtr<nsIPrincipal> pc = nsJSPrincipals::get(JS_GetCompartmentPrincipals(aC));
-      return nsContentUtils::IsSystemOrExpandedPrincipal(pc);
-    }
-};
-
-class WindowDestroyedEvent final : public Runnable
-{
-public:
-  WindowDestroyedEvent(nsGlobalWindowInner* aWindow, uint64_t aID, const char* aTopic)
-    : mozilla::Runnable("WindowDestroyedEvent")
-    , mID(aID)
-    , mPhase(Phase::Destroying)
-    , mTopic(aTopic)
-    , mIsInnerWindow(true)
-  {
-    mWindow = do_GetWeakReference(aWindow);
-  }
-  WindowDestroyedEvent(nsGlobalWindowOuter* aWindow, uint64_t aID, const char* aTopic)
-    : mozilla::Runnable("WindowDestroyedEvent")
-    , mID(aID)
-    , mPhase(Phase::Destroying)
-    , mTopic(aTopic)
-    , mIsInnerWindow(false)
-  {
-    mWindow = do_GetWeakReference(aWindow);
-  }
-
-  enum class Phase
-  {
-    Destroying,
-    Nuking
-  };
-
-  NS_IMETHOD Run() override
-  {
-    AUTO_PROFILER_LABEL("WindowDestroyedEvent::Run", OTHER);
-
-    nsCOMPtr<nsIObserverService> observerService =
-      services::GetObserverService();
-    if (!observerService) {
-      return NS_OK;
-    }
-
-    nsCOMPtr<nsISupportsPRUint64> wrapper =
-      do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID);
-    if (wrapper) {
-      wrapper->SetData(mID);
-      observerService->NotifyObservers(wrapper, mTopic.get(), nullptr);
-    }
-
-    switch (mPhase) {
-      case Phase::Destroying:
-      {
-        bool skipNukeCrossCompartment = false;
-#ifndef DEBUG
-        nsCOMPtr<nsIAppStartup> appStartup =
-          do_GetService(NS_APPSTARTUP_CONTRACTID);
-
-        if (appStartup) {
-          appStartup->GetShuttingDown(&skipNukeCrossCompartment);
-        }
-#endif
-
-        if (!skipNukeCrossCompartment) {
-          // The compartment nuking phase might be too expensive, so do that
-          // part off of idle dispatch.
-
-          // For the compartment nuking phase, we dispatch either an
-          // inner-window-nuked or an outer-window-nuked notification.
-          // This will allow tests to wait for compartment nuking to happen.
-          if (mTopic.EqualsLiteral("inner-window-destroyed")) {
-            mTopic.AssignLiteral("inner-window-nuked");
-          } else if (mTopic.EqualsLiteral("outer-window-destroyed")) {
-            mTopic.AssignLiteral("outer-window-nuked");
-          }
-          mPhase = Phase::Nuking;
-
-          nsCOMPtr<nsIRunnable> copy(this);
-          NS_IdleDispatchToCurrentThread(copy.forget(), 1000);
-        }
-      }
-      break;
-
-      case Phase::Nuking:
-      {
-        nsCOMPtr<nsISupports> window = do_QueryReferent(mWindow);
-        if (window) {
-          nsGlobalWindowInner* currentInner;
-          if (mIsInnerWindow) {
-            currentInner = nsGlobalWindowInner::FromSupports(window);
-          } else {
-            nsGlobalWindowOuter* outer = nsGlobalWindowOuter::FromSupports(window);
-            currentInner = outer->GetCurrentInnerWindowInternal();
-          }
-          NS_ENSURE_TRUE(currentInner, NS_OK);
-
-          AutoSafeJSContext cx;
-          JS::Rooted<JSObject*> obj(cx, currentInner->FastGetGlobalJSObject());
-          if (obj && !js::IsSystemCompartment(js::GetObjectCompartment(obj))) {
-            JSCompartment* cpt = js::GetObjectCompartment(obj);
-            nsCOMPtr<nsIPrincipal> pc = nsJSPrincipals::get(JS_GetCompartmentPrincipals(cpt));
-
-            if (BasePrincipal::Cast(pc)->AddonPolicy()) {
-              // We want to nuke all references to the add-on compartment.
-              xpc::NukeAllWrappersForCompartment(cx, cpt,
-                                                 mIsInnerWindow ? js::DontNukeWindowReferences
-                                                                : js::NukeWindowReferences);
-            } else {
-              // We only want to nuke wrappers for the chrome->content case
-              js::NukeCrossCompartmentWrappers(cx, BrowserCompartmentMatcher(), cpt,
-                                               mIsInnerWindow ? js::DontNukeWindowReferences
-                                                              : js::NukeWindowReferences,
-                                               js::NukeIncomingReferences);
-            }
-          }
-        }
-      }
-      break;
-    }
-
-    return NS_OK;
-  }
-
-private:
-  uint64_t mID;
-  Phase mPhase;
-  nsCString mTopic;
-  nsWeakPtr mWindow;
-  bool mIsInnerWindow;
-};
-
-class ChildCommandDispatcher : public Runnable
-{
-public:
-  ChildCommandDispatcher(nsPIWindowRoot* aRoot,
-                         nsITabChild* aTabChild,
-                         const nsAString& aAction)
-    : mozilla::Runnable("ChildCommandDispatcher")
-    , mRoot(aRoot)
-    , mTabChild(aTabChild)
-    , mAction(aAction)
-  {
-  }
-
-  NS_IMETHOD Run() override
-  {
-    nsTArray<nsCString> enabledCommands, disabledCommands;
-    mRoot->GetEnabledDisabledCommands(enabledCommands, disabledCommands);
-    if (enabledCommands.Length() || disabledCommands.Length()) {
-      mTabChild->EnableDisableCommands(mAction, enabledCommands, disabledCommands);
-    }
-
-    return NS_OK;
-  }
-
-private:
-  nsCOMPtr<nsPIWindowRoot>             mRoot;
-  nsCOMPtr<nsITabChild>                mTabChild;
-  nsString                             mAction;
-};
-
-class CommandDispatcher : public Runnable
-{
-public:
-  CommandDispatcher(nsIDOMXULCommandDispatcher* aDispatcher,
-                    const nsAString& aAction)
-    : mozilla::Runnable("CommandDispatcher")
-    , mDispatcher(aDispatcher)
-    , mAction(aAction)
-  {
-  }
-
-  NS_IMETHOD Run() override
-  {
-    return mDispatcher->UpdateCommands(mAction);
-  }
-
-  nsCOMPtr<nsIDOMXULCommandDispatcher> mDispatcher;
-  nsString                             mAction;
-};
-
-static bool IsLink(nsIContent* aContent)
-{
-  return aContent && (aContent->IsHTMLElement(nsGkAtoms::a) ||
-                      aContent->AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::type,
-                                            nsGkAtoms::simple, eCaseMatters));
-}
-
-static bool ShouldShowFocusRingIfFocusedByMouse(nsIContent* aNode)
-{
-  if (!aNode) {
-    return true;
-  }
-  return !IsLink(aNode) &&
-    !aNode->IsAnyOfHTMLElements(nsGkAtoms::video, nsGkAtoms::audio);
-}
-
-static bool
-IsInterval(const Optional<int32_t>& aTimeout, int32_t& aResultTimeout)
-{
-  if (aTimeout.WasPassed()) {
-    aResultTimeout = aTimeout.Value();
-    return true;
-  }
-
-  // If no interval was specified, treat this like a timeout, to avoid setting
-  // an interval of 0 milliseconds.
-  aResultTimeout = 0;
-  return false;
-}
-
-template<typename T>
-mozilla::dom::DocGroup*
-nsPIDOMWindow<T>::GetDocGroup() const
-{
-  nsIDocument* doc = GetExtantDoc();
-  if (doc) {
-    return doc->GetDocGroup();
-  }
-  return nullptr;
-}
-
-static void
-EnsurePrefCaches()
-{
-  static bool sFirstTime = true;
-  if (sFirstTime) {
-    TimeoutManager::Initialize();
-    Preferences::AddBoolVarCache(&gIdleObserversAPIFuzzTimeDisabled,
-                                 "dom.idle-observers-api.fuzz_time.disabled",
-                                 false);
-
-    Preferences::AddUintVarCache(&gThrottledIdlePeriodLength,
-                                 "dom.idle_period.throttled_length",
-                                 DEFAULT_THROTTLED_IDLE_PERIOD_LENGTH);
-    sFirstTime = false;
-  }
-}
-
-// Include the implementations for the inner and outer windows respectively.
-#include "nsGlobalWindowOuter.cpp"
-#include "nsGlobalWindowInner.cpp"
-
-template class nsPIDOMWindow<mozIDOMWindowProxy>;
-template class nsPIDOMWindow<mozIDOMWindow>;
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -2,34 +2,16 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsGlobalWindow_h___
 #define nsGlobalWindow_h___
 
-// XXX(nika): Figure out where to put this?
-#define DEFAULT_HOME_PAGE "www.mozilla.org"
-#define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
-
-// Amount of time allowed between alert/prompt/confirm before enabling
-// the stop dialog checkbox.
-#define DEFAULT_SUCCESSIVE_DIALOG_TIME_LIMIT 3 // 3 sec
-
-// Maximum number of successive dialogs before we prompt users to disable
-// dialogs for this window.
-#define MAX_SUCCESSIVE_DIALOG_COUNT 5
-
-// Idle fuzz time upper limit
-#define MAX_IDLE_FUZZ_TIME_MS 90000
-
-// Min idle notification time in seconds.
-#define MIN_IDLE_NOTIFICATION_TIME_S 1
-
 // NOTE: This is so that I can rewrite the includes in a separate patch.
 // Specificially I don't think I want to change this until I've moved everything
 // to mozilla/dom/Window.h and mozilla/dom/WindowProxy.h.
 
 #include "nsGlobalWindowInner.h"
 #include "nsGlobalWindowOuter.h"
 
 #endif /* nsGlobalWindow_h___ */
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -1,63 +1,363 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "nsGlobalWindow.h"
+
+#include <algorithm>
+
+#include "mozilla/MemoryReporting.h"
+
+// Local Includes
+#include "Navigator.h"
+#include "nsContentSecurityManager.h"
+#include "nsScreen.h"
+#include "nsHistory.h"
+#include "nsDOMNavigationTiming.h"
+#include "nsIDOMStorageManager.h"
+#include "mozilla/dom/LocalStorage.h"
+#include "mozilla/dom/Storage.h"
+#include "mozilla/dom/IdleRequest.h"
+#include "mozilla/dom/Performance.h"
+#include "mozilla/dom/StorageEvent.h"
+#include "mozilla/dom/StorageEventBinding.h"
+#include "mozilla/dom/StorageNotifierService.h"
+#include "mozilla/dom/StorageUtils.h"
+#include "mozilla/dom/Timeout.h"
+#include "mozilla/dom/TimeoutHandler.h"
+#include "mozilla/dom/TimeoutManager.h"
+#include "mozilla/IntegerPrintfMacros.h"
+#if defined(MOZ_WIDGET_ANDROID)
+#include "mozilla/dom/WindowOrientationObserver.h"
+#endif
+#include "nsDOMOfflineResourceList.h"
+#include "nsError.h"
+#include "nsIIdleService.h"
+#include "nsISizeOfEventTarget.h"
+#include "nsDOMJSUtils.h"
+#include "nsArrayUtils.h"
+#include "nsIDOMWindowCollection.h"
+#include "nsDOMWindowList.h"
+#include "mozilla/dom/WakeLock.h"
+#include "mozilla/dom/power/PowerManagerService.h"
+#include "nsIDocShellTreeOwner.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsIPermissionManager.h"
+#include "nsIScriptContext.h"
+#include "nsIScriptTimeoutHandler.h"
+#include "nsITimeoutHandler.h"
+#include "nsIController.h"
+#include "nsScriptNameSpaceManager.h"
+#include "nsISlowScriptDebug.h"
+#include "nsWindowMemoryReporter.h"
+#include "nsWindowSizes.h"
+#include "WindowNamedPropertiesHandler.h"
+#include "nsFrameSelection.h"
+#include "nsNetUtil.h"
+#include "nsVariant.h"
+#include "nsPrintfCString.h"
+#include "mozilla/intl/LocaleService.h"
+#include "WindowDestroyedEvent.h"
+
+// Helper Classes
+#include "nsJSUtils.h"
+#include "jsapi.h"              // for JSAutoRequest
+#include "jswrapper.h"
+#include "nsCharSeparatedTokenizer.h"
+#include "nsReadableUtils.h"
+#include "nsDOMClassInfo.h"
+#include "nsJSEnvironment.h"
+#include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/Likely.h"
+#include "mozilla/Sprintf.h"
+#include "mozilla/Unused.h"
+
+// Other Classes
+#include "mozilla/dom/BarProps.h"
+#include "nsContentCID.h"
+#include "nsLayoutStatics.h"
+#include "nsCCUncollectableMarker.h"
+#include "mozilla/dom/workers/Workers.h"
+#include "mozilla/dom/ToJSValue.h"
+#include "nsJSPrincipals.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Debug.h"
+#include "mozilla/EventListenerManager.h"
+#include "mozilla/EventStates.h"
+#include "mozilla/MouseEvents.h"
+#include "mozilla/ProcessHangMonitor.h"
+#include "mozilla/ThrottledEventQueue.h"
+#include "AudioChannelService.h"
+#include "nsAboutProtocolUtils.h"
+#include "nsCharTraits.h" // NS_IS_HIGH/LOW_SURROGATE
+#include "PostMessageEvent.h"
+#include "mozilla/dom/DocGroup.h"
+#include "mozilla/dom/TabGroup.h"
+
+// Interfaces Needed
+#include "nsIFrame.h"
+#include "nsCanvasFrame.h"
+#include "nsIWidget.h"
+#include "nsIWidgetListener.h"
+#include "nsIBaseWindow.h"
+#include "nsIDeviceSensors.h"
+#include "nsIContent.h"
+#include "nsIDocShell.h"
+#include "nsIDocCharset.h"
+#include "nsIDocument.h"
+#include "Crypto.h"
+#include "nsIDOMDocument.h"
+#include "nsIDOMElement.h"
+#include "nsIDOMEvent.h"
+#include "nsIDOMOfflineResourceList.h"
+#include "nsDOMString.h"
+#include "nsIEmbeddingSiteWindow.h"
+#include "nsThreadUtils.h"
+#include "nsILoadContext.h"
+#include "nsIPresShell.h"
+#include "nsIScrollableFrame.h"
+#include "nsView.h"
+#include "nsViewManager.h"
+#include "nsISelectionController.h"
+#include "nsISelection.h"
+#include "nsIPrompt.h"
+#include "nsIPromptService.h"
+#include "nsIPromptFactory.h"
+#include "nsIAddonPolicyService.h"
+#include "nsIWritablePropertyBag2.h"
+#include "nsIWebNavigation.h"
+#include "nsIWebBrowserChrome.h"
+#include "nsIWebBrowserFind.h"  // For window.find()
+#include "nsIWindowMediator.h"  // For window.find()
+#include "nsComputedDOMStyle.h"
+#include "nsDOMCID.h"
+#include "nsDOMWindowUtils.h"
+#include "nsIWindowWatcher.h"
+#include "nsPIWindowWatcher.h"
+#include "nsIContentViewer.h"
+#include "nsIScriptError.h"
+#include "nsIControllers.h"
+#include "nsIControllerContext.h"
+#include "nsGlobalWindowCommands.h"
+#include "nsQueryObject.h"
+#include "nsContentUtils.h"
+#include "nsCSSProps.h"
+#include "nsIDOMFileList.h"
+#include "nsIURIFixup.h"
+#ifndef DEBUG
+#include "nsIAppStartup.h"
+#include "nsToolkitCompsCID.h"
+#endif
+#include "nsCDefaultURIFixup.h"
+#include "mozilla/EventDispatcher.h"
+#include "mozilla/EventStateManager.h"
+#include "nsIObserverService.h"
+#include "nsFocusManager.h"
+#include "nsIXULWindow.h"
+#include "nsITimedChannel.h"
+#include "nsServiceManagerUtils.h"
+#ifdef MOZ_XUL
+#include "nsIDOMXULControlElement.h"
+#include "nsMenuPopupFrame.h"
+#endif
+#include "mozilla/dom/CustomEvent.h"
+#include "nsIJARChannel.h"
+#include "nsIScreenManager.h"
+#include "nsIEffectiveTLDService.h"
+
+#include "xpcprivate.h"
+
+#ifdef NS_PRINTING
+#include "nsIPrintSettings.h"
+#include "nsIPrintSettingsService.h"
+#include "nsIWebBrowserPrint.h"
+#endif
+
+#include "nsWindowRoot.h"
+#include "nsNetCID.h"
+#include "nsIArray.h"
+
+// XXX An unfortunate dependency exists here (two XUL files).
+#include "nsIDOMXULDocument.h"
+#include "nsIDOMXULCommandDispatcher.h"
+
+#include "nsBindingManager.h"
+#include "nsXBLService.h"
+
+// used for popup blocking, needs to be converted to something
+// belonging to the back-end like nsIContentPolicy
+#include "nsIPopupWindowManager.h"
+
+#include "nsIDragService.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/Selection.h"
+#include "nsFrameLoader.h"
+#include "nsISupportsPrimitives.h"
+#include "nsXPCOMCID.h"
+#include "mozilla/Logging.h"
+#include "prenv.h"
+
+#include "mozilla/dom/IDBFactory.h"
+#include "mozilla/dom/MessageChannel.h"
+#include "mozilla/dom/Promise.h"
+
+#include "mozilla/dom/Gamepad.h"
+#include "mozilla/dom/GamepadManager.h"
+
+#include "gfxVR.h"
+#include "mozilla/dom/VRDisplay.h"
+#include "mozilla/dom/VRDisplayEvent.h"
+#include "mozilla/dom/VRDisplayEventBinding.h"
+#include "mozilla/dom/VREventObserver.h"
+
+#include "nsRefreshDriver.h"
+#include "Layers.h"
+
+#include "mozilla/AddonPathService.h"
+#include "mozilla/BasePrincipal.h"
+#include "mozilla/Services.h"
+#include "mozilla/Telemetry.h"
+#include "mozilla/dom/Location.h"
+#include "nsHTMLDocument.h"
+#include "nsWrapperCacheInlines.h"
+#include "mozilla/DOMEventTargetHelper.h"
+#include "prrng.h"
+#include "nsSandboxFlags.h"
+#include "TimeChangeObserver.h"
+#include "mozilla/dom/AudioContext.h"
+#include "mozilla/dom/BrowserElementDictionariesBinding.h"
+#include "mozilla/dom/cache/CacheStorage.h"
+#include "mozilla/dom/Console.h"
+#include "mozilla/dom/Fetch.h"
+#include "mozilla/dom/FunctionBinding.h"
+#include "mozilla/dom/HashChangeEvent.h"
+#include "mozilla/dom/IntlUtils.h"
+#include "mozilla/dom/MozSelfSupportBinding.h"
+#include "mozilla/dom/PopStateEvent.h"
+#include "mozilla/dom/PopupBlockedEvent.h"
+#include "mozilla/dom/PrimitiveConversions.h"
+#include "mozilla/dom/WindowBinding.h"
+#include "nsITabChild.h"
+#include "mozilla/dom/MediaQueryList.h"
+#include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/dom/NavigatorBinding.h"
+#include "mozilla/dom/ImageBitmap.h"
+#include "mozilla/dom/ImageBitmapBinding.h"
+#include "mozilla/dom/ServiceWorkerRegistration.h"
+#include "mozilla/dom/U2F.h"
+#include "mozilla/dom/WebIDLGlobalNameHash.h"
+#include "mozilla/dom/Worklet.h"
+#ifdef HAVE_SIDEBAR
+#include "mozilla/dom/ExternalBinding.h"
+#endif
+
+#ifdef MOZ_WEBSPEECH
+#include "mozilla/dom/SpeechSynthesis.h"
+#endif
+
 #include "mozilla/dom/ClientManager.h"
 #include "mozilla/dom/ClientSource.h"
 
+// Apple system headers seem to have a check() macro.  <sigh>
+#ifdef check
+class nsIScriptTimeoutHandler;
+#undef check
+#endif // check
+#include "AccessCheck.h"
+
+#ifdef ANDROID
+#include <android/log.h>
+#endif
+
+#ifdef XP_WIN
+#include <process.h>
+#define getpid _getpid
+#else
+#include <unistd.h> // for getpid()
+#endif
+
+using namespace mozilla;
+using namespace mozilla::dom;
+using namespace mozilla::dom::ipc;
+using mozilla::TimeStamp;
+using mozilla::TimeDuration;
+using mozilla::dom::cache::CacheStorage;
+
 #define FORWARD_TO_OUTER(method, args, err_rval)                        \
   PR_BEGIN_MACRO                                                        \
-  MOZ_RELEASE_ASSERT(IsInnerWindow());                                  \
   nsGlobalWindowOuter *outer = GetOuterWindowInternal();                \
   if (!HasActiveDocument()) {                                           \
     NS_WARNING(outer ?                                                  \
                "Inner window does not have active document." :          \
                "No outer window available!");                           \
     return err_rval;                                                    \
   }                                                                     \
   return outer->method args;                                            \
   PR_END_MACRO
 
 #define FORWARD_TO_OUTER_OR_THROW(method, args, errorresult, err_rval)  \
   PR_BEGIN_MACRO                                                        \
-  MOZ_RELEASE_ASSERT(IsInnerWindow());                                  \
   nsGlobalWindowOuter *outer = GetOuterWindowInternal();                \
   if (MOZ_LIKELY(HasActiveDocument())) {                                \
     return outer->method args;                                          \
   }                                                                     \
   if (!outer) {                                                         \
     NS_WARNING("No outer window available!");                           \
     errorresult.Throw(NS_ERROR_NOT_INITIALIZED);                        \
   } else {                                                              \
     errorresult.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO);              \
   }                                                                     \
   return err_rval;                                                      \
   PR_END_MACRO
 
 #define FORWARD_TO_OUTER_VOID(method, args)                             \
   PR_BEGIN_MACRO                                                        \
-  MOZ_RELEASE_ASSERT(IsInnerWindow());                                  \
   nsGlobalWindowOuter *outer = GetOuterWindowInternal();                \
   if (!HasActiveDocument()) {                                           \
     NS_WARNING(outer ?                                                  \
                "Inner window does not have active document." :          \
                "No outer window available!");                           \
     return;                                                             \
   }                                                                     \
   outer->method args;                                                   \
   return;                                                               \
   PR_END_MACRO
 
+#define DOM_TOUCH_LISTENER_ADDED "dom-touch-listener-added"
+#define MEMORY_PRESSURE_OBSERVER_TOPIC "memory-pressure"
+
+// Amount of time allowed between alert/prompt/confirm before enabling
+// the stop dialog checkbox.
+#define DEFAULT_SUCCESSIVE_DIALOG_TIME_LIMIT 3 // 3 sec
+
+// Maximum number of successive dialogs before we prompt users to disable
+// dialogs for this window.
+#define MAX_SUCCESSIVE_DIALOG_COUNT 5
+
+// Idle fuzz time upper limit
+#define MAX_IDLE_FUZZ_TIME_MS 90000
+
+// Min idle notification time in seconds.
+#define MIN_IDLE_NOTIFICATION_TIME_S 1
+
+static LazyLogModule gDOMLeakPRLogInner("DOMLeakInner");
+
+static bool                 gIdleObserversAPIFuzzTimeDisabled = false;
+static FILE                *gDumpFile                         = nullptr;
 
 nsGlobalWindowInner::InnerWindowByIdTable *nsGlobalWindowInner::sInnerWindowsById = nullptr;
 
+bool nsGlobalWindowInner::sDragServiceDisabled = false;
+bool nsGlobalWindowInner::sMouseDown = false;
+
 /**
  * An indirect observer object that means we don't have to implement nsIObserver
  * on nsGlobalWindow, where any script could see it.
  */
 class nsGlobalWindowObserver final : public nsIObserver
                                    , public nsIInterfaceRequestor
                                    , public StorageNotificationObserver
 {
@@ -155,17 +455,16 @@ class IdleRequestExecutor final : public
 {
 public:
   explicit IdleRequestExecutor(nsGlobalWindowInner* aWindow)
     : mDispatched(false)
     , mDeadline(TimeStamp::Now())
     , mWindow(aWindow)
   {
     MOZ_DIAGNOSTIC_ASSERT(mWindow);
-    MOZ_DIAGNOSTIC_ASSERT(mWindow->IsInnerWindow());
 
     mIdlePeriodLimit = { mDeadline, mWindow->LastIdleRequestHandle() };
     mDelayedExecutorDispatcher = new IdleRequestExecutorTimeoutHandler(this);
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IdleRequestExecutor, nsIRunnable)
 
@@ -497,17 +796,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
 NS_INTERFACE_MAP_END_INHERITING(TimeoutHandler)
 
 uint32_t
 nsGlobalWindowInner::RequestIdleCallback(JSContext* aCx,
                                          IdleRequestCallback& aCallback,
                                          const IdleRequestOptions& aOptions,
                                          ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
   AssertIsOnMainThread();
 
   uint32_t handle = mIdleRequestCallbackCounter++;
 
   RefPtr<IdleRequest> request =
     new IdleRequest(&aCallback, handle);
 
   if (aOptions.mTimeout.WasPassed()) {
@@ -533,18 +831,16 @@ nsGlobalWindowInner::RequestIdleCallback
   }
 
   return handle;
 }
 
 void
 nsGlobalWindowInner::CancelIdleCallback(uint32_t aHandle)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   for (IdleRequest* r : mIdleRequestCallbacks) {
     if (r->Handle() == aHandle) {
       RemoveIdleCallback(r);
       break;
     }
   }
 }
 
@@ -573,74 +869,58 @@ nsGlobalWindowInner::IsBackgroundInterna
 //*****************************************************************************
 
 nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter *aOuterWindow)
   : nsPIDOMWindowInner(aOuterWindow->AsOuter()),
     mIdleFuzzFactor(0),
     mIdleCallbackIndex(-1),
     mCurrentlyIdle(false),
     mAddActiveEventFuzzTime(true),
-    mFullScreen(false),
-    mFullscreenMode(false),
-    mIsClosed(false),
-    mInClose(false),
-    mHavePendingClose(false),
-    mHadOriginalOpener(false),
-    mOriginalOpenerWasSecureContext(false),
-    mIsPopupSpam(false),
-    mBlockScriptedClosingFlag(false),
+    mIsSecureContextIfOpenerIgnored(false),
     mWasOffline(false),
     mHasHadSlowScript(false),
     mNotifyIdleObserversIdleOnThaw(false),
     mNotifyIdleObserversActiveOnThaw(false),
-    mCreatingInnerWindow(false),
     mIsChrome(false),
     mCleanMessageManager(false),
     mNeedsFocus(true),
     mHasFocus(false),
     mShowFocusRingForContent(false),
     mFocusByKeyOccurred(false),
     mHasGamepad(false),
     mHasVREvents(false),
     mHasVRDisplayActivateEvents(false),
     mHasSeenGamepadInput(false),
-    mNotifiedIDDestroyed(false),
-    mAllowScriptsToClose(false),
-    mTopLevelOuterContentWindow(false),
     mSuspendDepth(0),
     mFreezeDepth(0),
     mFocusMethod(0),
     mSerial(0),
     mIdleRequestCallbackCounter(1),
     mIdleRequestExecutor(nullptr),
-#ifdef DEBUG
-    mSetOpenerWindowCalled(false),
-#endif
     mCleanedUp(false),
     mDialogAbuseCount(0),
     mAreDialogsEnabled(true),
-#ifdef DEBUG
-    mIsValidatingTabGroup(false),
-#endif
     mCanSkipCCGeneration(0),
-    mAutoActivateVRDisplayID(0),
     mBeforeUnloadListenerCount(0)
 {
   AssertIsOnMainThread();
 
   nsLayoutStatics::AddRef();
 
   // Initialize the PRCList (this).
   PR_INIT_CLIST(this);
 
   if (aOuterWindow) {
     // |this| is an inner window, add this inner window to the outer
     // window list of inners.
     PR_INSERT_AFTER(this, aOuterWindow);
 
+    mTimeoutManager =
+      MakeUnique<mozilla::dom::TimeoutManager>(*nsGlobalWindowInner::Cast(AsInner()));
+
     mObserver = new nsGlobalWindowObserver(this);
     if (mObserver) {
       nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
       if (os) {
         // Watch for online/offline status changes so we can fire events. Use
         // a strong reference.
         os->AddObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
                         false);
@@ -669,45 +949,50 @@ nsGlobalWindowInner::nsGlobalWindowInner
       mTabChild = docShell->GetTabChild();
     }
   }
 
   // We could have failed the first time through trying
   // to create the entropy collector, so we should
   // try to get one until we succeed.
 
-  gRefCnt++;
-
-  EnsurePrefCaches();
+  mSerial = nsContentUtils::InnerOrOuterWindowCreated();
+
+  static bool sFirstTime = true;
+  if (sFirstTime) {
+    sFirstTime = false;
+    TimeoutManager::Initialize();
+    Preferences::AddBoolVarCache(&gIdleObserversAPIFuzzTimeDisabled,
+                                 "dom.idle-observers-api.fuzz_time.disabled",
+                                 false);
+  }
 
   if (gDumpFile == nullptr) {
     nsAutoCString fname;
     Preferences::GetCString("browser.dom.window.dump.file", fname);
     if (!fname.IsEmpty()) {
       // If this fails to open, Dump() knows to just go to stdout on null.
       gDumpFile = fopen(fname.get(), "wb+");
     } else {
       gDumpFile = stdout;
     }
   }
 
-  mSerial = ++gSerialCounter;
-
 #ifdef DEBUG
   if (!PR_GetEnv("MOZ_QUIET")) {
     printf_stderr("++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n",
-                  gRefCnt,
+                  nsContentUtils::GetCurrentInnerOrOuterWindowCount(),
                   static_cast<void*>(ToCanonicalSupports(this)),
                   getpid(),
-                  gSerialCounter,
+                  mSerial,
                   static_cast<void*>(ToCanonicalSupports(aOuterWindow)));
   }
 #endif
 
-  MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug,
+  MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
           ("DOMWINDOW %p created outer=%p", this, aOuterWindow));
 
   // Add ourselves to the inner windows list.
   MOZ_ASSERT(sInnerWindowsById, "Inner Windows hash table must be created!");
   MOZ_ASSERT(!sInnerWindowsById->Get(mWindowID),
              "This window shouldn't be in the hash table yet!");
   // We seem to see crashes in release builds because of null |sInnerWindowsById|.
   if (sInnerWindowsById) {
@@ -727,17 +1012,17 @@ nsGlobalWindowInner::AssertIsOnMainThrea
 #endif // DEBUG
 
 /* static */
 void
 nsGlobalWindowInner::Init()
 {
   AssertIsOnMainThread();
 
-  NS_ASSERTION(gDOMLeakPRLog, "gDOMLeakPRLog should have been initialized!");
+  NS_ASSERTION(gDOMLeakPRLogInner, "gDOMLeakPRLogInner should have been initialized!");
 
   sInnerWindowsById = new InnerWindowByIdTable();
 }
 
 nsGlobalWindowInner::~nsGlobalWindowInner()
 {
   AssertIsOnMainThread();
 
@@ -758,43 +1043,43 @@ nsGlobalWindowInner::~nsGlobalWindowInne
   DisconnectEventTargetObjects();
 
   if (sInnerWindowsById) {
     MOZ_ASSERT(sInnerWindowsById->Get(mWindowID),
                 "This window should be in the hash table");
     sInnerWindowsById->Remove(mWindowID);
   }
 
-  --gRefCnt;
+  nsContentUtils::InnerOrOuterWindowDestroyed();
 
 #ifdef DEBUG
   if (!PR_GetEnv("MOZ_QUIET")) {
     nsAutoCString url;
     if (mLastOpenedURI) {
       url = mLastOpenedURI->GetSpecOrDefault();
 
       // Data URLs can be very long, so truncate to avoid flooding the log.
       const uint32_t maxURLLength = 1000;
       if (url.Length() > maxURLLength) {
         url.Truncate(maxURLLength);
       }
     }
 
     nsGlobalWindowOuter* outer = nsGlobalWindowOuter::Cast(mOuterWindow);
     printf_stderr("--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = %s]\n",
-                  gRefCnt,
+                  nsContentUtils::GetCurrentInnerOrOuterWindowCount(),
                   static_cast<void*>(ToCanonicalSupports(this)),
                   getpid(),
                   mSerial,
                   static_cast<void*>(ToCanonicalSupports(outer)),
                   url.get());
   }
 #endif
 
-  MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug, ("DOMWINDOW %p destroyed", this));
+  MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug, ("DOMWINDOW %p destroyed", this));
 
   Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,
                         mMutationBits ? 1 : 0);
 
   if (mListenerManager) {
     mListenerManager->Disconnect();
     mListenerManager = nullptr;
   }
@@ -824,24 +1109,22 @@ nsGlobalWindowInner::~nsGlobalWindowInne
     ac->RemoveWindowAsListener(this);
 
   nsLayoutStatics::Release();
 }
 
 void
 nsGlobalWindowInner::AddEventTargetObject(DOMEventTargetHelper* aObject)
 {
-  MOZ_ASSERT(IsInnerWindow());
   mEventTargetObjects.PutEntry(aObject);
 }
 
 void
 nsGlobalWindowInner::RemoveEventTargetObject(DOMEventTargetHelper* aObject)
 {
-  MOZ_ASSERT(IsInnerWindow());
   mEventTargetObjects.RemoveEntry(aObject);
 }
 
 void
 nsGlobalWindowInner::DisconnectEventTargetObjects()
 {
   for (auto iter = mEventTargetObjects.ConstIter(); !iter.Done();
        iter.Next()) {
@@ -852,17 +1135,21 @@ nsGlobalWindowInner::DisconnectEventTarg
 }
 
 // static
 void
 nsGlobalWindowInner::ShutDown()
 {
   AssertIsOnMainThread();
 
-  // nsGlobalWindowOuter::ShutDown() handles closing gDumpFile.
+  if (gDumpFile && gDumpFile != stdout) {
+    fclose(gDumpFile);
+  }
+  gDumpFile = nullptr;
+
   delete sInnerWindowsById;
   sInnerWindowsById = nullptr;
 }
 
 // static
 void
 nsGlobalWindowInner::CleanupCachedXBLHandlers()
 {
@@ -916,18 +1203,16 @@ nsGlobalWindowInner::CleanUp()
   mMenubar = nullptr;
   mToolbar = nullptr;
   mLocationbar = nullptr;
   mPersonalbar = nullptr;
   mStatusbar = nullptr;
   mScrollbars = nullptr;
   mHistory = nullptr;
   mCustomElements = nullptr;
-  mFrames = nullptr;
-  mWindowUtils = nullptr;
   mApplicationCache = nullptr;
   mIndexedDB = nullptr;
 
   mConsole = nullptr;
 
   mAudioWorklet = nullptr;
   mPaintWorklet = nullptr;
 
@@ -940,22 +1225,16 @@ nsGlobalWindowInner::CleanUp()
 #ifdef MOZ_WEBSPEECH
   mSpeechSynthesis = nullptr;
 #endif
 
 #if defined(MOZ_WIDGET_ANDROID)
   mOrientationChangeObserver = nullptr;
 #endif
 
-  ClearControllers();
-
-  mOpener = nullptr;             // Forces Release
-  if (mContext) {
-    mContext = nullptr;            // Forces Release
-  }
   mChromeEventHandler = nullptr; // Forces Release
   mParentTarget = nullptr;
 
   DisableGamepadUpdates();
   mHasGamepad = false;
   DisableVRUpdates();
   mHasVREvents = false;
   mHasVRDisplayActivateEvents = false;
@@ -964,18 +1243,16 @@ nsGlobalWindowInner::CleanUp()
   if (mCleanMessageManager) {
     MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned");
     if (mChromeFields.mMessageManager) {
       static_cast<nsFrameMessageManager*>(
         mChromeFields.mMessageManager.get())->Disconnect();
     }
   }
 
-  mArguments = nullptr;
-
   CleanupCachedXBLHandlers();
 
   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
     mAudioContexts[i]->Shutdown();
   }
   mAudioContexts.Clear();
 
   if (mIdleTimer) {
@@ -984,40 +1261,18 @@ nsGlobalWindowInner::CleanUp()
   }
 
   mServiceWorkerRegistrationTable.Clear();
 
   mIntlUtils = nullptr;
 }
 
 void
-nsGlobalWindowInner::ClearControllers()
-{
-  if (mControllers) {
-    uint32_t count;
-    mControllers->GetControllerCount(&count);
-
-    while (count--) {
-      nsCOMPtr<nsIController> controller;
-      mControllers->GetControllerAt(count, getter_AddRefs(controller));
-
-      nsCOMPtr<nsIControllerContext> context = do_QueryInterface(controller);
-      if (context)
-        context->SetCommandContext(nullptr);
-    }
-
-    mControllers = nullptr;
-  }
-}
-
-void
 nsGlobalWindowInner::FreeInnerObjects()
 {
-  NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
-
   // Make sure that this is called before we null out the document and
   // other members that the window destroyed observers could
   // re-create.
   NotifyDOMWindowDestroyed(this);
   if (auto* reporter = nsWindowMemoryReporter::Get()) {
     reporter->ObserveDOMWindowDetached(this);
   }
 
@@ -1126,17 +1381,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)
   if (aIID.Equals(NS_GET_IID(nsPIDOMWindowInner))) {
     foundInterface = static_cast<nsPIDOMWindowInner*>(this);
   } else
-  if (aIID.Equals(NS_GET_IID(mozIDOMWindow)) && IsInnerWindow()) {
+  if (aIID.Equals(NS_GET_IID(mozIDOMWindow))) {
     foundInterface = static_cast<mozIDOMWindow*>(this);
   } else
   if (aIID.Equals(NS_GET_IID(nsIDOMChromeWindow)) && IsChromeWindow()) {
     foundInterface = static_cast<nsIDOMChromeWindow*>(this);
   } else
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
 NS_INTERFACE_MAP_END
@@ -1180,28 +1435,23 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalW
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowInner)
   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
     char name[512];
     nsAutoCString uri;
     if (tmp->mDoc && tmp->mDoc->GetDocumentURI()) {
       uri = tmp->mDoc->GetDocumentURI()->GetSpecOrDefault();
     }
-    SprintfLiteral(name, "nsGlobalWindowInner # %" PRIu64 " %s %s", tmp->mWindowID,
-                   tmp->IsInnerWindow() ? "inner" : "outer", uri.get());
+    SprintfLiteral(name, "nsGlobalWindowInner # %" PRIu64 " inner %s", tmp->mWindowID,
+                   uri.get());
     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
   } else {
     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindowInner, tmp->mRefCnt.get())
   }
 
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
-
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArguments)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReturnValue)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerRegistrationTable)
 
 #ifdef MOZ_WEBSPEECH
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSpeechSynthesis)
@@ -1221,17 +1471,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHistory)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCustomElements)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStorage)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStorage)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mApplicationCache)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuspendedDoc)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChild)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleService)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleRequestExecutor)
   for (IdleRequest* request : tmp->mIdleRequestCallbacks) {
@@ -1243,17 +1492,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepads)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDisplays)
 
   // Traverse stuff from nsPIDOMWindow
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedNode)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMenubar)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mToolbar)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocationbar)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPersonalbar)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusbar)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScrollbars)
@@ -1261,34 +1509,25 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mU2F)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioWorklet)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaintWorklet)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExternal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMozSelfSupport)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils)
 
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)
-
   tmp->TraverseHostObjectURIs(cb);
 
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mBrowserDOMWindow)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mMessageManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mGroupMessageManagers)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mOpenerForInitialContentBrowser)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)
   tmp->CleanupCachedXBLHandlers();
 
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
-
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mArguments)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mReturnValue)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mServiceWorkerRegistrationTable)
 
 #ifdef MOZ_WEBSPEECH
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSpeechSynthesis)
@@ -1312,33 +1551,31 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mHistory)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCustomElements)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStorage)
   if (tmp->mApplicationCache) {
     static_cast<nsDOMOfflineResourceList*>(tmp->mApplicationCache.get())->Disconnect();
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplicationCache)
   }
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuspendedDoc)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChild)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleService)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleObservers)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mGamepads)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDisplays)
 
   // Unlink stuff from nsPIDOMWindow
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFocusedNode)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMenubar)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mToolbar)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocationbar)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPersonalbar)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusbar)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mScrollbars)
@@ -1346,35 +1583,31 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mU2F)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioWorklet)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaintWorklet)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mExternal)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMozSelfSupport)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntlUtils)
 
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)
-
   tmp->UnlinkHostObjectURIs();
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)
   tmp->DisableIdleCallbackRequests();
 
   tmp->mClientSource.reset();
 
   if (tmp->IsChromeWindow()) {
-    NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mBrowserDOMWindow)
     if (tmp->mChromeFields.mMessageManager) {
       static_cast<nsFrameMessageManager*>(
         tmp->mChromeFields.mMessageManager.get())->Disconnect();
       NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mMessageManager)
     }
     tmp->DisconnectAndClearGroupMessageManagers();
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mGroupMessageManagers)
-    NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mOpenerForInitialContentBrowser)
   }
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 #ifdef DEBUG
 void
 nsGlobalWindowInner::RiskyUnlink()
@@ -1441,40 +1674,20 @@ nsGlobalWindowInner::GetGlobalJSObject()
 }
 
 void
 nsGlobalWindowInner::TraceGlobalJSObject(JSTracer* aTrc)
 {
   TraceWrapper(aTrc, "active window global");
 }
 
-void
-nsGlobalWindowInner::SetInitialPrincipalToSubject()
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-PopupControlState
-nsGlobalWindowInner::PushPopupControlState(PopupControlState aState,
-                                           bool aForce) const
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-void
-nsGlobalWindowInner::PopPopupControlState(PopupControlState aState) const
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
 PopupControlState
 nsGlobalWindowInner::GetPopupControlState() const
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  return gPopupControlState;
+  return nsContentUtils::GetPopupControlState();
 }
 
 nsresult
 nsGlobalWindowInner::SetNewDocument(nsIDocument* aDocument,
                                     nsISupports* aState,
                                     bool aForceReuseInnerWindow)
 {
   NS_PRECONDITION(mDocumentPrincipal == nullptr,
@@ -1493,22 +1706,21 @@ nsGlobalWindowInner::SetNewDocument(nsID
 
   return GetOuterWindowInternal()->SetNewDocument(aDocument, aState,
                                                   aForceReuseInnerWindow);
 }
 
 void
 nsGlobalWindowInner::InnerSetNewDocument(JSContext* aCx, nsIDocument* aDocument)
 {
-  NS_PRECONDITION(IsInnerWindow(), "Must only be called on inner windows");
   MOZ_ASSERT(aDocument);
 
-  if (MOZ_LOG_TEST(gDOMLeakPRLog, LogLevel::Debug)) {
+  if (MOZ_LOG_TEST(gDOMLeakPRLogInner, LogLevel::Debug)) {
     nsIURI *uri = aDocument->GetDocumentURI();
-    MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug,
+    MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
             ("DOMWINDOW %p SetNewDocument %s",
              this, uri ? uri->GetSpecOrDefault().get() : ""));
   }
 
   mDoc = aDocument;
   ClearDocumentDependentSlots(aCx);
   mFocusedNode = nullptr;
   mLocalStorage = nullptr;
@@ -1616,28 +1828,30 @@ nsGlobalWindowInner::UpdateParentTarget(
 
   // Try to get our frame element's tab child global (its in-process message
   // manager).  If that fails, fall back to the chrome event handler's tab
   // child global, and if it doesn't have one, just use the chrome event
   // handler itself.
 
   nsCOMPtr<Element> frameElement = GetOuterWindow()->GetFrameElementInternal();
   nsCOMPtr<EventTarget> eventTarget =
-    TryGetTabChildGlobalAsEventTarget(frameElement);
+    nsContentUtils::TryGetTabChildGlobalAsEventTarget(frameElement);
 
   if (!eventTarget) {
     nsGlobalWindowOuter* topWin = GetScriptableTopInternal();
     if (topWin) {
       frameElement = topWin->AsOuter()->GetFrameElementInternal();
-      eventTarget = TryGetTabChildGlobalAsEventTarget(frameElement);
+      eventTarget =
+        nsContentUtils::TryGetTabChildGlobalAsEventTarget(frameElement);
     }
   }
 
   if (!eventTarget) {
-    eventTarget = TryGetTabChildGlobalAsEventTarget(mChromeEventHandler);
+    eventTarget =
+      nsContentUtils::TryGetTabChildGlobalAsEventTarget(mChromeEventHandler);
   }
 
   if (!eventTarget) {
     eventTarget = mChromeEventHandler;
   }
 
   mParentTarget = eventTarget;
 }
@@ -1658,40 +1872,38 @@ nsresult
 nsGlobalWindowInner::WillHandleEvent(EventChainPostVisitor& aVisitor)
 {
   return NS_OK;
 }
 
 nsresult
 nsGlobalWindowInner::GetEventTargetParent(EventChainPreVisitor& aVisitor)
 {
-  NS_PRECONDITION(IsInnerWindow(),
-                  "GetEventTargetParent is used on outer window!?");
   EventMessage msg = aVisitor.mEvent->mMessage;
 
   aVisitor.mCanHandle = true;
   aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
   if (msg == eResize && aVisitor.mEvent->IsTrusted()) {
     // QIing to window so that we can keep the old behavior also in case
     // a child window is handling resize.
     nsCOMPtr<nsPIDOMWindowInner> window =
       do_QueryInterface(aVisitor.mEvent->mOriginalTarget);
     if (window) {
       mIsHandlingResizeEvent = true;
     }
   } else if (msg == eMouseDown && aVisitor.mEvent->IsTrusted()) {
-    gMouseDown = true;
+    sMouseDown = true;
   } else if ((msg == eMouseUp || msg == eDragEnd) &&
              aVisitor.mEvent->IsTrusted()) {
-    gMouseDown = false;
-    if (gDragServiceDisabled) {
+    sMouseDown = false;
+    if (sDragServiceDisabled) {
       nsCOMPtr<nsIDragService> ds =
         do_GetService("@mozilla.org/widget/dragservice;1");
       if (ds) {
-        gDragServiceDisabled = false;
+        sDragServiceDisabled = false;
         ds->Unsuppress();
       }
     }
   }
 
   aVisitor.mParentTarget = GetParentTarget();
 
   // Handle 'active' event.
@@ -1703,17 +1915,16 @@ nsGlobalWindowInner::GetEventTargetParen
   }
 
   return NS_OK;
 }
 
 bool
 nsGlobalWindowInner::DialogsAreBeingAbused()
 {
-  MOZ_ASSERT(IsInnerWindow());
   NS_ASSERTION(GetScriptableTopInternal() &&
                GetScriptableTopInternal()->GetCurrentInnerWindowInternal() == this,
                "DialogsAreBeingAbused called with invalid window");
 
   if (mLastDialogQuitTime.IsNull() ||
       nsContentUtils::IsCallerChrome()) {
     return false;
   }
@@ -1744,18 +1955,16 @@ void
 nsGlobalWindowInner::EnableDialogs()
 {
   FORWARD_TO_OUTER_VOID(EnableDialogs, ());
 }
 
 nsresult
 nsGlobalWindowInner::PostHandleEvent(EventChainPostVisitor& aVisitor)
 {
-  NS_PRECONDITION(IsInnerWindow(), "PostHandleEvent is used on outer window!?");
-
   // Return early if there is nothing to do.
   switch (aVisitor.mEvent->mMessage) {
     case eResize:
     case eUnload:
     case eLoad:
       break;
     default:
       return NS_OK;
@@ -1839,26 +2048,18 @@ nsGlobalWindowInner::PostHandleEvent(Eve
                                 VRDisplayEventReason::Navigation);
     }
   }
 
   return NS_OK;
 }
 
 nsresult
-nsGlobalWindowInner::SetArguments(nsIArray *aArguments)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-nsresult
 nsGlobalWindowInner::DefineArgumentsProperty(nsIArray *aArguments)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   nsIScriptContext *ctx = GetOuterWindowInternal()->mContext;
   NS_ENSURE_TRUE(aArguments && ctx, NS_ERROR_NOT_INITIALIZED);
 
   JS::Rooted<JSObject*> obj(RootingCx(), GetWrapperPreserveColor());
   return ctx->SetProperty(obj, "arguments", aArguments);
 }
 
 //*****************************************************************************
@@ -1895,50 +2096,42 @@ nsGlobalWindowInner::GetPrincipal()
 
 //*****************************************************************************
 // nsGlobalWindowInner::nsIDOMWindow
 //*****************************************************************************
 
 bool
 nsPIDOMWindowInner::AddAudioContext(AudioContext* aAudioContext)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   mAudioContexts.AppendElement(aAudioContext);
 
   // Return true if the context should be muted and false if not.
   nsIDocShell* docShell = GetDocShell();
   return docShell && !docShell->GetAllowMedia() && !aAudioContext->IsOffline();
 }
 
 void
 nsPIDOMWindowInner::RemoveAudioContext(AudioContext* aAudioContext)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   mAudioContexts.RemoveElement(aAudioContext);
 }
 
 void
 nsPIDOMWindowInner::MuteAudioContexts()
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
     if (!mAudioContexts[i]->IsOffline()) {
       mAudioContexts[i]->Mute();
     }
   }
 }
 
 void
 nsPIDOMWindowInner::UnmuteAudioContexts()
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
     if (!mAudioContexts[i]->IsOffline()) {
       mAudioContexts[i]->Unmute();
     }
   }
 }
 
 nsGlobalWindowInner*
@@ -1951,36 +2144,32 @@ nsGlobalWindowInner*
 nsGlobalWindowInner::Self()
 {
   return this;
 }
 
 Navigator*
 nsGlobalWindowInner::Navigator()
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mNavigator) {
     mNavigator = new mozilla::dom::Navigator(this);
   }
 
   return mNavigator;
 }
 
 nsIDOMNavigator*
 nsGlobalWindowInner::GetNavigator()
 {
   return Navigator();
 }
 
 nsScreen*
 nsGlobalWindowInner::GetScreen(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mScreen) {
     mScreen = nsScreen::Create(this);
     if (!mScreen) {
       aError.Throw(NS_ERROR_UNEXPECTED);
       return nullptr;
     }
   }
 
@@ -1994,50 +2183,43 @@ nsGlobalWindowInner::GetScreen()
   nsIDOMScreen* screen = GetScreen(dummy);
   dummy.SuppressException();
   return screen;
 }
 
 nsHistory*
 nsGlobalWindowInner::GetHistory(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mHistory) {
     mHistory = new nsHistory(this);
   }
 
   return mHistory;
 }
 
 CustomElementRegistry*
 nsGlobalWindowInner::CustomElements()
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mCustomElements) {
     mCustomElements = new CustomElementRegistry(this);
   }
 
   return mCustomElements;
 }
 
 Performance*
 nsPIDOMWindowInner::GetPerformance()
 {
-  MOZ_ASSERT(IsInnerWindow());
   CreatePerformanceObjectIfNeeded();
   return mPerformance;
 }
 
 void
 nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded()
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   if (mPerformance || !mDoc) {
     return;
   }
   RefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
   nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
   bool timingEnabled = false;
   if (!timedChannel ||
       !NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled)) ||
@@ -2095,49 +2277,46 @@ Maybe<ClientInfo>
 nsPIDOMWindowInner::GetClientInfo() const
 {
   return Move(nsGlobalWindowInner::Cast(this)->GetClientInfo());
 }
 
 void
 nsGlobalWindowInner::UpdateTopInnerWindow()
 {
-  if (!IsInnerWindow() || IsTopInnerWindow() || !mTopInnerWindow) {
+  if (IsTopInnerWindow() || !mTopInnerWindow) {
     return;
   }
 
   mTopInnerWindow->UpdateWebSocketCount(-(int32_t)mNumOfOpenWebSockets);
 }
 
 void
 nsPIDOMWindowInner::AddPeerConnection()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(IsInnerWindow());
   mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections++
                   : mActivePeerConnections++;
 }
 
 void
 nsPIDOMWindowInner::RemovePeerConnection()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(IsInnerWindow());
   MOZ_ASSERT(mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections
                              : mActivePeerConnections);
 
   mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections--
                   : mActivePeerConnections--;
 }
 
 bool
 nsPIDOMWindowInner::HasActivePeerConnections()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(IsInnerWindow());
   return mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections
                          : mActivePeerConnections;
 }
 
 bool
 nsPIDOMWindowInner::IsPlayingAudio()
 {
   for (uint32_t i = 0; i < mAudioContexts.Length(); i++) {
@@ -2263,55 +2442,48 @@ nsPIDOMWindowInner::HasOpenWebSockets() 
 
   return mNumOfOpenWebSockets ||
          (mTopInnerWindow && mTopInnerWindow->mNumOfOpenWebSockets);
 }
 
 bool
 nsPIDOMWindowInner::GetAudioCaptured() const
 {
-  MOZ_ASSERT(IsInnerWindow());
   return mAudioCaptured;
 }
 
 nsresult
 nsPIDOMWindowInner::SetAudioCapture(bool aCapture)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   mAudioCaptured = aCapture;
 
   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
   if (service) {
     service->SetWindowAudioCaptured(GetOuterWindow(), mWindowID, aCapture);
   }
 
   return NS_OK;
 }
 
 // nsISpeechSynthesisGetter
 
 #ifdef MOZ_WEBSPEECH
 SpeechSynthesis*
 nsGlobalWindowInner::GetSpeechSynthesis(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mSpeechSynthesis) {
     mSpeechSynthesis = new SpeechSynthesis(this);
   }
 
   return mSpeechSynthesis;
 }
 
 bool
 nsGlobalWindowInner::HasActiveSpeechSynthesis()
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   if (mSpeechSynthesis) {
     return !mSpeechSynthesis->HasEmptyQueue();
   }
 
   return false;
 }
 
 #endif
@@ -2341,163 +2513,116 @@ nsGlobalWindowInner::GetScriptableParent
  */
 nsPIDOMWindowOuter*
 nsGlobalWindowInner::GetScriptableParentOrNull()
 {
   FORWARD_TO_OUTER(GetScriptableParentOrNull, (), nullptr);
 }
 
 /**
- * nsPIDOMWindow::GetParent (when called from C++) is just a wrapper around
- * GetRealParent.
- */
-already_AddRefed<nsPIDOMWindowOuter>
-nsGlobalWindowInner::GetParent()
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-/**
  * GetScriptableTop is called when script reads window.top.
  *
  * In contrast to GetRealTop, GetScriptableTop respects <iframe mozbrowser>
  * boundaries.  If we encounter a window owned by an <iframe mozbrowser> while
  * walking up the window hierarchy, we'll stop and return that window.
  */
 nsPIDOMWindowOuter*
 nsGlobalWindowInner::GetScriptableTop()
 {
   FORWARD_TO_OUTER(GetScriptableTop, (), nullptr);
 }
 
-already_AddRefed<nsPIDOMWindowOuter>
-nsGlobalWindowInner::GetTop()
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
 void
 nsGlobalWindowInner::GetContent(JSContext* aCx,
                                 JS::MutableHandle<JSObject*> aRetval,
                                 CallerType aCallerType,
                                 ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(GetContentOuter,
                             (aCx, aRetval, aCallerType, aError), aError, );
 }
 
 MozSelfSupport*
 nsGlobalWindowInner::GetMozSelfSupport(ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   if (mMozSelfSupport) {
     return mMozSelfSupport;
   }
 
   // We're called from JS and want to use out existing JSContext (and,
   // importantly, its compartment!) here.
   AutoJSContext cx;
   GlobalObject global(cx, FastGetGlobalJSObject());
   mMozSelfSupport = MozSelfSupport::Constructor(global, cx, aError);
   return mMozSelfSupport;
 }
 
-nsresult
-nsGlobalWindowInner::GetPrompter(nsIPrompt** aPrompt)
-{
-  nsGlobalWindowOuter* outer = GetOuterWindowInternal();
-  if (!outer) {
-    NS_WARNING("No outer window available!");
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  return outer->GetPrompter(aPrompt);
-}
-
 BarProp*
 nsGlobalWindowInner::GetMenubar(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mMenubar) {
     mMenubar = new MenubarProp(this);
   }
 
   return mMenubar;
 }
 
 BarProp*
 nsGlobalWindowInner::GetToolbar(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mToolbar) {
     mToolbar = new ToolbarProp(this);
   }
 
   return mToolbar;
 }
 
 BarProp*
 nsGlobalWindowInner::GetLocationbar(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mLocationbar) {
     mLocationbar = new LocationbarProp(this);
   }
   return mLocationbar;
 }
 
 BarProp*
 nsGlobalWindowInner::GetPersonalbar(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mPersonalbar) {
     mPersonalbar = new PersonalbarProp(this);
   }
   return mPersonalbar;
 }
 
 BarProp*
 nsGlobalWindowInner::GetStatusbar(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mStatusbar) {
     mStatusbar = new StatusbarProp(this);
   }
   return mStatusbar;
 }
 
 BarProp*
 nsGlobalWindowInner::GetScrollbars(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mScrollbars) {
     mScrollbars = new ScrollbarsProp(this);
   }
 
   return mScrollbars;
 }
 
 bool
 nsGlobalWindowInner::GetClosed(ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(GetClosedOuter, (), aError, false);
 }
 
-bool
-nsGlobalWindowInner::Closed()
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
 already_AddRefed<nsIDOMWindowCollection>
 nsGlobalWindowInner::GetFrames()
 {
   FORWARD_TO_OUTER(GetFrames, (), nullptr);
 }
 
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindowInner::IndexedGetter(uint32_t aIndex)
@@ -2505,18 +2630,16 @@ nsGlobalWindowInner::IndexedGetter(uint3
   FORWARD_TO_OUTER(IndexedGetterOuter, (aIndex), nullptr);
 }
 
 bool
 nsGlobalWindowInner::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
                                JS::Handle<jsid> aId,
                                JS::MutableHandle<JS::PropertyDescriptor> aDesc)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   // Note: Keep this in sync with MayResolve.
 
   // Note: The infallibleInit call in GlobalResolve depends on this check.
   if (!JSID_IS_STRING(aId)) {
     return true;
   }
 
   bool found;
@@ -2586,17 +2709,16 @@ nsGlobalWindowInner::GetOwnPropertyNames
     // ResolvePrototype and using the resulting descriptot to define the
     // property.  ResolvePrototype always passes 0 to the FillPropertyDescriptor
     // for the property attributes, so all those are non-enumerable as well.
     //
     // So in the aEnumerableOnly case we have nothing to do.
     return;
   }
 
-  MOZ_ASSERT(IsInnerWindow());
   // "Components" is marked as enumerable but only resolved on demand :-/.
   //aNames.AppendElement(NS_LITERAL_STRING("Components"));
 
   nsScriptNameSpaceManager* nameSpaceManager = GetNameSpaceManager();
   if (nameSpaceManager) {
     JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
 
     // There are actually two ways we can get called here: For normal
@@ -2649,18 +2771,16 @@ nsGlobalWindowInner::IsRequestIdleCallba
   // The requestIdleCallback should always be enabled for system code.
   return nsContentUtils::RequestIdleCallbackEnabled() ||
          nsContentUtils::IsSystemCaller(aCx);
 }
 
 nsIDOMOfflineResourceList*
 nsGlobalWindowInner::GetApplicationCache(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mApplicationCache) {
     nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(GetDocShell()));
     if (!webNav || !mDoc) {
       aError.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
     nsCOMPtr<nsIURI> uri;
@@ -2692,30 +2812,26 @@ nsGlobalWindowInner::GetApplicationCache
     GetApplicationCache(dummy);
   dummy.SuppressException();
   return applicationCache.forget();
 }
 
 Crypto*
 nsGlobalWindowInner::GetCrypto(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mCrypto) {
     mCrypto = new Crypto();
     mCrypto->Init(this);
   }
   return mCrypto;
 }
 
 mozilla::dom::U2F*
 nsGlobalWindowInner::GetU2f(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mU2F) {
     RefPtr<U2F> u2f = new U2F(this);
     u2f->Init(aError);
     if (NS_WARN_IF(aError.Failed())) {
       return nullptr;
     }
 
     mU2F = u2f;
@@ -2744,33 +2860,25 @@ nsGlobalWindowInner::GetOpenerWindow(Err
 {
   FORWARD_TO_OUTER_OR_THROW(GetOpenerWindowOuter, (), aError, nullptr);
 }
 
 void
 nsGlobalWindowInner::GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
                                ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpenerWindow(aError);
   if (aError.Failed() || !opener) {
     aRetval.setNull();
     return;
   }
 
   aError = nsContentUtils::WrapNative(aCx, opener, aRetval);
 }
 
-already_AddRefed<nsPIDOMWindowOuter>
-nsGlobalWindowInner::GetOpener()
-{
-  FORWARD_TO_OUTER(GetOpener, (), nullptr);
-}
-
 void
 nsGlobalWindowInner::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
                                ErrorResult& aError)
 {
   // Check if we were called from a privileged chrome script.  If not, and if
   // aOpener is not null, just define aOpener on our inner window's JS object,
   // wrapped into the current compartment so that for Xrays we define on the
   // Xray expando object, but don't set it on the outer window, so that it'll
@@ -3045,36 +3153,32 @@ nsGlobalWindowInner::GetMozPaintCount(Er
 {
   FORWARD_TO_OUTER_OR_THROW(GetMozPaintCountOuter, (), aError, 0);
 }
 
 int32_t
 nsGlobalWindowInner::RequestAnimationFrame(FrameRequestCallback& aCallback,
                                            ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mDoc) {
     return 0;
   }
 
   if (GetWrapperPreserveColor()) {
     js::NotifyAnimationActivity(GetWrapperPreserveColor());
   }
 
   int32_t handle;
   aError = mDoc->ScheduleFrameRequestCallback(aCallback, &handle);
   return handle;
 }
 
 void
 nsGlobalWindowInner::CancelAnimationFrame(int32_t aHandle, ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mDoc) {
     return;
   }
 
   mDoc->CancelFrameRequestCallback(aHandle);
 }
 
 already_AddRefed<MediaQueryList>
@@ -3137,38 +3241,34 @@ nsGlobalWindowInner::SetScreenY(JSContex
 {
   SetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::SetScreenY,
                             aValue, "screenY", aCallerType, aError);
 }
 
 int32_t
 nsGlobalWindowInner::GetScrollMinX(ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
   FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideLeft), aError, 0);
 }
 
 int32_t
 nsGlobalWindowInner::GetScrollMinY(ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
   FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideTop), aError, 0);
 }
 
 int32_t
 nsGlobalWindowInner::GetScrollMaxX(ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
   FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideRight), aError, 0);
 }
 
 int32_t
 nsGlobalWindowInner::GetScrollMaxY(ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
   FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideBottom), aError, 0);
 }
 
 double
 nsGlobalWindowInner::GetScrollX(ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(GetScrollXOuter, (), aError, 0);
 }
@@ -3195,27 +3295,19 @@ nsPIDOMWindowOuter*
 nsGlobalWindowInner::GetChildWindow(const nsAString& aName)
 {
   if (GetOuterWindowInternal()) {
     return GetOuterWindowInternal()->GetChildWindow(aName);
   }
   return nullptr;
 }
 
-bool
-nsGlobalWindowInner::DispatchCustomEvent(const nsAString& aEventName)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
 void
 nsGlobalWindowInner::RefreshCompartmentPrincipal()
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   JS_SetCompartmentPrincipals(js::GetObjectCompartment(GetWrapperPreserveColor()),
                               nsJSPrincipals::get(mDoc->NodePrincipal()));
 }
 
 already_AddRefed<nsIWidget>
 nsGlobalWindowInner::GetMainWidget()
 {
   FORWARD_TO_OUTER(GetMainWidget, (), nullptr);
@@ -3231,41 +3323,16 @@ nsGlobalWindowInner::GetNearestWidget() 
 }
 
 void
 nsGlobalWindowInner::SetFullScreen(bool aFullScreen, mozilla::ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(SetFullScreenOuter, (aFullScreen, aError), aError, /* void */);
 }
 
-nsresult
-nsGlobalWindowInner::SetFullScreen(bool aFullScreen)
-{
-  FORWARD_TO_OUTER(SetFullScreen, (aFullScreen), NS_ERROR_NOT_INITIALIZED);
-}
-
-nsresult
-nsGlobalWindowInner::SetFullscreenInternal(FullscreenReason aReason,
-                                           bool aFullScreen)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-/* virtual */ void
-nsGlobalWindowInner::FullscreenWillChange(bool aIsFullscreen)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-/* virtual */ void
-nsGlobalWindowInner::FinishFullscreenChange(bool aIsFullscreen)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
 bool
 nsGlobalWindowInner::GetFullScreen(ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(GetFullScreenOuter, (), aError, false);
 }
 
 bool
 nsGlobalWindowInner::GetFullScreen()
@@ -3309,17 +3376,16 @@ nsGlobalWindowInner::Dump(const nsAStrin
     free(cstr);
   }
 }
 
 void
 nsGlobalWindowInner::Alert(nsIPrincipal& aSubjectPrincipal,
                            ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
   Alert(EmptyString(), aSubjectPrincipal, aError);
 }
 
 void
 nsGlobalWindowInner::Alert(const nsAString& aMessage,
                            nsIPrincipal& aSubjectPrincipal,
                            ErrorResult& aError)
 {
@@ -3431,22 +3497,16 @@ nsGlobalWindowInner::MoveTo(int32_t aXPo
 void
 nsGlobalWindowInner::MoveBy(int32_t aXDif, int32_t aYDif,
                             CallerType aCallerType, ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(MoveByOuter,
                             (aXDif, aYDif, aCallerType, aError), aError, );
 }
 
-nsresult
-nsGlobalWindowInner::MoveBy(int32_t aXDif, int32_t aYDif)
-{
-  FORWARD_TO_OUTER(MoveBy, (aXDif, aYDif), NS_ERROR_UNEXPECTED);
-}
-
 void
 nsGlobalWindowInner::ResizeTo(int32_t aWidth, int32_t aHeight,
                               CallerType aCallerType, ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(ResizeToOuter,
                             (aWidth, aHeight, aCallerType, aError), aError, );
 }
 
@@ -3464,23 +3524,21 @@ nsGlobalWindowInner::SizeToContent(Calle
 {
   FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter, (aCallerType, aError),
                             aError, );
 }
 
 already_AddRefed<nsPIWindowRoot>
 nsGlobalWindowInner::GetTopWindowRoot()
 {
-  nsPIDOMWindowOuter* piWin = GetPrivateRoot();
-  if (!piWin) {
+  nsGlobalWindowOuter* outer = GetOuterWindowInternal();
+  if (!outer) {
     return nullptr;
   }
-
-  nsCOMPtr<nsPIWindowRoot> window = do_QueryInterface(piWin->GetChromeEventHandler());
-  return window.forget();
+  return outer->GetTopWindowRoot();
 }
 
 void
 nsGlobalWindowInner::Scroll(double aXScroll, double aYScroll)
 {
   // Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
   auto scrollPos = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),
                                          mozilla::ToZeroIfNonfinite(aYScroll));
@@ -3605,18 +3663,16 @@ nsGlobalWindowInner::ScrollBy(const Scro
     ScrollTo(scrollPos, aOptions);
   }
 }
 
 void
 nsGlobalWindowInner::ScrollByLines(int32_t numLines,
                                    const ScrollOptions& aOptions)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   FlushPendingNotifications(FlushType::Layout);
   nsIScrollableFrame *sf = GetScrollFrame();
   if (sf) {
     // It seems like it would make more sense for ScrollByLines to use
     // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
     // Perhaps Web content does too.
     bool smoothScroll = sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);
 
@@ -3626,18 +3682,16 @@ nsGlobalWindowInner::ScrollByLines(int32
                    : nsIScrollableFrame::INSTANT);
   }
 }
 
 void
 nsGlobalWindowInner::ScrollByPages(int32_t numPages,
                                    const ScrollOptions& aOptions)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   FlushPendingNotifications(FlushType::Layout);
   nsIScrollableFrame *sf = GetScrollFrame();
   if (sf) {
     // It seems like it would make more sense for ScrollByPages to use
     // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
     // Perhaps Web content does too.
     bool smoothScroll = sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);
 
@@ -3646,40 +3700,34 @@ nsGlobalWindowInner::ScrollByPages(int32
                    ? nsIScrollableFrame::SMOOTH_MSD
                    : nsIScrollableFrame::INSTANT);
   }
 }
 
 void
 nsGlobalWindowInner::MozScrollSnap()
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   FlushPendingNotifications(FlushType::Layout);
   nsIScrollableFrame *sf = GetScrollFrame();
   if (sf) {
     sf->ScrollSnap();
   }
 }
 
 void
 nsGlobalWindowInner::ClearTimeout(int32_t aHandle)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (aHandle > 0) {
     mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
   }
 }
 
 void
 nsGlobalWindowInner::ClearInterval(int32_t aHandle)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (aHandle > 0) {
     mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
   }
 }
 
 void
 nsGlobalWindowInner::SetResizable(bool aResizable) const
 {
@@ -3697,64 +3745,24 @@ nsGlobalWindowInner::CaptureEvents()
 void
 nsGlobalWindowInner::ReleaseEvents()
 {
   if (mDoc) {
     mDoc->WarnOnceAbout(nsIDocument::eUseOfReleaseEvents);
   }
 }
 
-void
-nsGlobalWindowInner::FirePopupBlockedEvent(nsIDocument* aDoc,
-                                           nsIURI* aPopupURI,
-                                           const nsAString& aPopupWindowName,
-                                           const nsAString& aPopupWindowFeatures)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindowInner::Open(const nsAString& aUrl, const nsAString& aName,
                           const nsAString& aOptions, ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(OpenOuter, (aUrl, aName, aOptions, aError), aError,
                             nullptr);
 }
 
-nsresult
-nsGlobalWindowInner::Open(const nsAString& aUrl, const nsAString& aName,
-                          const nsAString& aOptions, nsIDocShellLoadInfo* aLoadInfo,
-                          bool aForceNoOpener, nsPIDOMWindowOuter **_retval)
-{
-  FORWARD_TO_OUTER(Open, (aUrl, aName, aOptions, aLoadInfo, aForceNoOpener,
-                          _retval),
-                   NS_ERROR_NOT_INITIALIZED);
-}
-
-// like Open, but attaches to the new window any extra parameters past
-// [features] as a JS property named "arguments"
-nsresult
-nsGlobalWindowInner::OpenDialog(const nsAString& aUrl, const nsAString& aName,
-                                const nsAString& aOptions,
-                                nsISupports* aExtraArgument,
-                                nsPIDOMWindowOuter** _retval)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-// Like Open, but passes aNavigate=false.
-/* virtual */ nsresult
-nsGlobalWindowInner::OpenNoNavigate(const nsAString& aUrl,
-                                    const nsAString& aName,
-                                    const nsAString& aOptions,
-                                    nsPIDOMWindowOuter **_retval)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindowInner::OpenDialog(JSContext* aCx, const nsAString& aUrl,
                                 const nsAString& aName, const nsAString& aOptions,
                                 const Sequence<JS::Value>& aExtraArgument,
                                 ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(OpenDialogOuter,
                             (aCx, aUrl, aName, aOptions, aExtraArgument, aError),
@@ -3829,58 +3837,34 @@ nsGlobalWindowInner::PostMessageMoz(JSCo
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   PostMessageMoz(aCx, aMessage, aTargetOrigin, transferArray,
                  aSubjectPrincipal, aRv);
 }
 
-bool
-nsGlobalWindowInner::CanClose()
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
 void
 nsGlobalWindowInner::Close(ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(CloseOuter, (nsContentUtils::IsCallerChrome()), aError, );
 }
 
 nsresult
 nsGlobalWindowInner::Close()
 {
   FORWARD_TO_OUTER(Close, (), NS_ERROR_UNEXPECTED);
 }
 
 void
-nsGlobalWindowInner::ForceClose()
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-void
 nsGlobalWindowInner::ReallyCloseWindow()
 {
   FORWARD_TO_OUTER_VOID(ReallyCloseWindow, ());
 }
 
-void
-nsGlobalWindowInner::EnterModalState()
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-void
-nsGlobalWindowInner::LeaveModalState()
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
 bool
 nsGlobalWindowInner::IsInModalState()
 {
   FORWARD_TO_OUTER(IsInModalState, (), false);
 }
 
 // static
 void
@@ -3895,20 +3879,17 @@ nsGlobalWindowInner::NotifyDOMWindowDest
   }
 }
 
 void
 nsGlobalWindowInner::NotifyWindowIDDestroyed(const char* aTopic)
 {
   nsCOMPtr<nsIRunnable> runnable =
     new WindowDestroyedEvent(this, mWindowID, aTopic);
-  nsresult rv = Dispatch(TaskCategory::Other, runnable.forget());
-  if (NS_SUCCEEDED(rv)) {
-    mNotifiedIDDestroyed = true;
-  }
+  Dispatch(TaskCategory::Other, runnable.forget());
 }
 
 // static
 void
 nsGlobalWindowInner::NotifyDOMWindowFrozen(nsGlobalWindowInner* aWindow)
 {
   if (aWindow) {
     nsCOMPtr<nsIObserverService> observerService =
@@ -4123,54 +4104,45 @@ nsGlobalWindowInner::UpdateCommands(cons
 }
 
 Selection*
 nsGlobalWindowInner::GetSelection(ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(GetSelectionOuter, (), aError, nullptr);
 }
 
-already_AddRefed<nsISelection>
-nsGlobalWindowInner::GetSelection()
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
 bool
 nsGlobalWindowInner::Find(const nsAString& aString, bool aCaseSensitive,
                           bool aBackwards, bool aWrapAround, bool aWholeWord,
                           bool aSearchInFrames, bool aShowDialog,
                           ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(FindOuter,
                             (aString, aCaseSensitive, aBackwards, aWrapAround,
                              aWholeWord, aSearchInFrames, aShowDialog, aError),
                             aError, false);
 }
 
 void
 nsGlobalWindowInner::GetOrigin(nsAString& aOrigin)
 {
-  MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow());
   nsContentUtils::GetUTFOrigin(GetPrincipal(), aOrigin);
 }
 
 void
 nsGlobalWindowInner::Atob(const nsAString& aAsciiBase64String,
                           nsAString& aBinaryData, ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
   aError = nsContentUtils::Atob(aAsciiBase64String, aBinaryData);
 }
 
 void
 nsGlobalWindowInner::Btoa(const nsAString& aBinaryData,
                           nsAString& aAsciiBase64String, ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
   aError = nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
 }
 
 //*****************************************************************************
 // nsGlobalWindowInner::nsIDOMEventTarget
 //*****************************************************************************
 
 nsPIDOMWindowOuter*
@@ -4324,53 +4296,33 @@ nsGlobalWindowInner::GetPrivateRoot()
     return nullptr;
   }
   return outer->GetPrivateRoot();
 }
 
 Location*
 nsGlobalWindowInner::GetLocation()
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mLocation) {
     mLocation = new dom::Location(this, GetDocShell());
   }
 
   return mLocation;
 }
 
-void
-nsGlobalWindowInner::ActivateOrDeactivate(bool aActivate)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-void
-nsGlobalWindowInner::SetActive(bool aActive)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
 bool
 nsGlobalWindowInner::IsTopLevelWindowActive()
 {
   if (GetOuterWindowInternal()) {
     return GetOuterWindowInternal()->IsTopLevelWindowActive();
   }
   return false;
 }
 
 void
-nsGlobalWindowInner::SetIsBackground(bool aIsBackground)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-void
 nsGlobalWindowInner::MaybeUpdateTouchState()
 {
   if (mMayHaveTouchEventListener) {
     nsCOMPtr<nsIObserverService> observerService =
       services::GetObserverService();
 
     if (observerService) {
       observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
@@ -4378,71 +4330,67 @@ nsGlobalWindowInner::MaybeUpdateTouchSta
                                        nullptr);
     }
   }
 }
 
 void
 nsGlobalWindowInner::EnableGamepadUpdates()
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   if (mHasGamepad) {
     RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
     if (gamepadManager) {
       gamepadManager->AddListener(this);
     }
   }
 }
 
 void
 nsGlobalWindowInner::DisableGamepadUpdates()
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   if (mHasGamepad) {
     RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
     if (gamepadManager) {
       gamepadManager->RemoveListener(this);
     }
   }
 }
 
 void
 nsGlobalWindowInner::EnableVRUpdates()
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   if (mHasVREvents && !mVREventObserver) {
     mVREventObserver = new VREventObserver(this);
   }
 }
 
 void
 nsGlobalWindowInner::DisableVRUpdates()
 {
-  MOZ_ASSERT(IsInnerWindow());
   if (mVREventObserver) {
     mVREventObserver->DisconnectFromOwner();
     mVREventObserver = nullptr;
   }
 }
 
 void
 nsGlobalWindowInner::ResetVRTelemetry(bool aUpdate)
 {
   if (mVREventObserver) {
     mVREventObserver->UpdateSpentTimeIn2DTelemetry(aUpdate);
   }
 }
 
-void
-nsGlobalWindowInner::SetChromeEventHandler(EventTarget* aChromeEventHandler)
-{
-  MOZ_CRASH("Virtual outer window only function");
+static bool ShouldShowFocusRingIfFocusedByMouse(nsIContent* aNode)
+{
+  if (!aNode) {
+    return true;
+  }
+  return !nsContentUtils::ContentIsLink(aNode) &&
+    !aNode->IsAnyOfHTMLElements(nsGkAtoms::video, nsGkAtoms::audio);
 }
 
 void
 nsGlobalWindowInner::SetFocusedNode(nsIContent* aNode,
                                     uint32_t aFocusMethod,
                                     bool aNeedsFocus)
 {
   if (aNode && aNode->GetComposedDoc() != mDoc) {
@@ -4497,23 +4445,16 @@ nsGlobalWindowInner::ShouldShowFocusRing
   if (mShowFocusRingForContent || mFocusByKeyOccurred) {
     return true;
   }
 
   nsCOMPtr<nsPIWindowRoot> root = GetTopWindowRoot();
   return root ? root->ShowFocusRings() : false;
 }
 
-void
-nsGlobalWindowInner::SetKeyboardIndicators(UIStateChangeType aShowAccelerators,
-                                           UIStateChangeType aShowFocusRings)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
 bool
 nsGlobalWindowInner::TakeFocus(bool aFocus, uint32_t aFocusMethod)
 {
   if (mCleanedUp) {
     return false;
   }
 
   if (aFocus)
@@ -4570,17 +4511,16 @@ class HashchangeCallback : public Runnab
 public:
   HashchangeCallback(const nsAString& aOldURL,
                      const nsAString& aNewURL,
                      nsGlobalWindowInner* aWindow)
     : mozilla::Runnable("HashchangeCallback")
     , mWindow(aWindow)
   {
     MOZ_ASSERT(mWindow);
-    MOZ_ASSERT(mWindow->IsInnerWindow());
     mOldURL.Assign(aOldURL);
     mNewURL.Assign(aNewURL);
   }
 
   NS_IMETHOD Run() override
   {
     NS_PRECONDITION(NS_IsMainThread(), "Should be called on the main thread.");
     return mWindow->FireHashchange(mOldURL, mNewURL);
@@ -4590,18 +4530,16 @@ private:
   nsString mOldURL;
   nsString mNewURL;
   RefPtr<nsGlobalWindowInner> mWindow;
 };
 
 nsresult
 nsGlobalWindowInner::DispatchAsyncHashchange(nsIURI *aOldURI, nsIURI *aNewURI)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   // Make sure that aOldURI and aNewURI are identical up to the '#', and that
   // their hashes are different.
   bool equal = false;
   NS_ENSURE_STATE(NS_SUCCEEDED(aOldURI->EqualsExceptRef(aNewURI, &equal)) && equal);
   nsAutoCString oldHash, newHash;
   bool oldHasHash, newHasHash;
   NS_ENSURE_STATE(NS_SUCCEEDED(aOldURI->GetRef(oldHash)) &&
                   NS_SUCCEEDED(aNewURI->GetRef(newHash)) &&
@@ -4622,18 +4560,16 @@ nsGlobalWindowInner::DispatchAsyncHashch
     new HashchangeCallback(oldWideSpec, newWideSpec, this);
   return Dispatch(TaskCategory::Other, callback.forget());
 }
 
 nsresult
 nsGlobalWindowInner::FireHashchange(const nsAString &aOldURL,
                                     const nsAString &aNewURL)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   // Don't do anything if the window is frozen.
   if (IsFrozen()) {
     return NS_OK;
   }
 
   // Get a presentation shell for use in creating the hashchange event.
   NS_ENSURE_STATE(IsCurrentInnerWindow());
 
@@ -4657,17 +4593,16 @@ nsGlobalWindowInner::FireHashchange(cons
 
   bool dummy;
   return DispatchEvent(event, &dummy);
 }
 
 nsresult
 nsGlobalWindowInner::DispatchSyncPopState()
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
   NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
                "Must be safe to run script here.");
 
   nsresult rv = NS_OK;
 
   // Bail if the window is frozen.
   if (IsFrozen()) {
     return NS_OK;
@@ -4732,18 +4667,16 @@ FindCanvasFrame(nsIFrame* aFrame)
     return nullptr;
 }
 
 //-------------------------------------------------------
 // Tells the HTMLFrame/CanvasFrame that is now has focus
 void
 nsGlobalWindowInner::UpdateCanvasFocus(bool aFocusChanged, nsIContent* aNewContent)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   // this is called from the inner window so use GetDocShell
   nsIDocShell* docShell = GetDocShell();
   if (!docShell)
     return;
 
   bool editable;
   docShell->GetEditable(&editable);
   if (editable)
@@ -4777,37 +4710,33 @@ nsGlobalWindowInner::UpdateCanvasFocus(b
       }
   }
 }
 
 already_AddRefed<nsICSSDeclaration>
 nsGlobalWindowInner::GetComputedStyle(Element& aElt, const nsAString& aPseudoElt,
                                       ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
   return GetComputedStyleHelper(aElt, aPseudoElt, false, aError);
 }
 
 already_AddRefed<nsICSSDeclaration>
 nsGlobalWindowInner::GetDefaultComputedStyle(Element& aElt,
                                              const nsAString& aPseudoElt,
                                              ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
   return GetComputedStyleHelper(aElt, aPseudoElt, true, aError);
 }
 
 nsresult
 nsGlobalWindowInner::GetComputedStyleHelper(nsIDOMElement* aElt,
                                             const nsAString& aPseudoElt,
                                             bool aDefaultStylesOnly,
                                             nsIDOMCSSStyleDeclaration** aReturn)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   NS_ENSURE_ARG_POINTER(aReturn);
   *aReturn = nullptr;
 
   nsCOMPtr<dom::Element> element = do_QueryInterface(aElt);
   if (!element) {
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
 
@@ -4828,27 +4757,25 @@ nsGlobalWindowInner::GetComputedStyleHel
   FORWARD_TO_OUTER_OR_THROW(GetComputedStyleHelperOuter,
                             (aElt, aPseudoElt, aDefaultStylesOnly),
                             aError, nullptr);
 }
 
 Storage*
 nsGlobalWindowInner::GetSessionStorage(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   nsIPrincipal *principal = GetPrincipal();
   nsIDocShell* docShell = GetDocShell();
 
-  if (!principal || !docShell || !Preferences::GetBool(kStorageEnabled)) {
+  if (!principal || !docShell || !Storage::StoragePrefIsEnabled()) {
     return nullptr;
   }
 
   if (mSessionStorage) {
-    MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug,
+    MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
             ("nsGlobalWindowInner %p has %p sessionStorage", this, mSessionStorage.get()));
     bool canAccess = principal->Subsumes(mSessionStorage->Principal());
     NS_ASSERTION(canAccess,
                  "This window owned sessionStorage "
                  "that could not be accessed!");
     if (!canAccess) {
       mSessionStorage = nullptr;
     }
@@ -4889,37 +4816,35 @@ nsGlobalWindowInner::GetSessionStorage(E
                                            getter_AddRefs(storage));
     if (aError.Failed()) {
       return nullptr;
     }
 
     mSessionStorage = static_cast<Storage*>(storage.get());
     MOZ_ASSERT(mSessionStorage);
 
-    MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug,
+    MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
             ("nsGlobalWindowInner %p tried to get a new sessionStorage %p", this, mSessionStorage.get()));
 
     if (!mSessionStorage) {
       aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
       return nullptr;
     }
   }
 
-  MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug,
+  MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
           ("nsGlobalWindowInner %p returns %p sessionStorage", this, mSessionStorage.get()));
 
   return mSessionStorage;
 }
 
 Storage*
 nsGlobalWindowInner::GetLocalStorage(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
-  if (!Preferences::GetBool(kStorageEnabled)) {
+  if (!Storage::StoragePrefIsEnabled()) {
     return nullptr;
   }
 
   if (!mLocalStorage) {
     if (nsContentUtils::StorageAllowedForWindow(this) ==
           nsContentUtils::StorageAccess::eDeny) {
       aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
       return nullptr;
@@ -4959,17 +4884,16 @@ nsGlobalWindowInner::GetLocalStorage(Err
   }
 
   return mLocalStorage;
 }
 
 IDBFactory*
 nsGlobalWindowInner::GetIndexedDB(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
   if (!mIndexedDB) {
     // This may keep mIndexedDB null without setting an error.
     aError = IDBFactory::CreateForWindow(this,
                                          getter_AddRefs(mIndexedDB));
   }
 
   return mIndexedDB;
 }
@@ -4991,25 +4915,22 @@ nsGlobalWindowInner::GetInterface(const 
   return rv;
 }
 
 void
 nsGlobalWindowInner::GetInterface(JSContext* aCx, nsIJSID* aIID,
                                   JS::MutableHandle<JS::Value> aRetval,
                                   ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
   dom::GetInterface(aCx, this, aIID, aRetval, aError);
 }
 
 already_AddRefed<CacheStorage>
 nsGlobalWindowInner::GetCaches(ErrorResult& aRv)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   if (!mCacheStorage) {
     bool forceTrustedOrigin =
       GetOuterWindow()->GetServiceWorkersTestingEnabled();
 
     nsContentUtils::StorageAccess access =
       nsContentUtils::StorageAllowedForWindow(this);
 
     // We don't block the cache API when being told to only allow storage for the
@@ -5112,17 +5033,16 @@ private:
   // If false then call on active
   bool mCallOnidle;
 };
 
 void
 nsGlobalWindowInner::NotifyIdleObserver(IdleObserverHolder* aIdleObserverHolder,
                                         bool aCallOnidle)
 {
-  MOZ_ASSERT(IsInnerWindow());
   MOZ_ASSERT(aIdleObserverHolder);
   aIdleObserverHolder->mPrevNotificationIdle = aCallOnidle;
 
   nsCOMPtr<nsIRunnable> caller =
     new NotifyIdleObserverRunnable(aIdleObserverHolder->mIdleObserver,
                                    aIdleObserverHolder->mTimeInS,
                                    aCallOnidle, this);
   if (NS_FAILED(Dispatch(TaskCategory::Other, caller.forget()))) {
@@ -5163,31 +5083,29 @@ IdleObserverTimerCallback(nsITimer* aTim
     static_cast<nsGlobalWindowInner*>(aClosure);
   MOZ_ASSERT(idleWindow, "Idle window has not been instantiated.");
   idleWindow->HandleIdleObserverCallback();
 }
 
 void
 nsGlobalWindowInner::HandleIdleObserverCallback()
 {
-  MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
   MOZ_ASSERT(static_cast<uint32_t>(mIdleCallbackIndex) < mIdleObservers.Length(),
                                   "Idle callback index exceeds array bounds!");
   IdleObserverHolder& idleObserver = mIdleObservers.ElementAt(mIdleCallbackIndex);
   NotifyIdleObserver(&idleObserver, true);
   mIdleCallbackIndex++;
   if (NS_FAILED(ScheduleNextIdleObserverCallback())) {
     NS_WARNING("Failed to set next idle observer callback.");
   }
 }
 
 nsresult
 nsGlobalWindowInner::ScheduleNextIdleObserverCallback()
 {
-  MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
   MOZ_ASSERT(mIdleService, "No idle service!");
 
   if (mIdleCallbackIndex < 0 ||
       static_cast<uint32_t>(mIdleCallbackIndex) >= mIdleObservers.Length()) {
     return NS_OK;
   }
 
   IdleObserverHolder& idleObserver =
@@ -5212,18 +5130,16 @@ nsGlobalWindowInner::ScheduleNextIdleObs
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 uint32_t
 nsGlobalWindowInner::GetFuzzTimeMS()
 {
-  MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
-
   if (gIdleObserversAPIFuzzTimeDisabled) {
     return 0;
   }
 
   uint32_t randNum = MAX_IDLE_FUZZ_TIME_MS;
   size_t nbytes = PR_GetRandomNoise(&randNum, sizeof(randNum));
   if (nbytes != sizeof(randNum)) {
     NS_WARNING("PR_GetRandomNoise(...) Not implemented or no available noise!");
@@ -5235,18 +5151,16 @@ nsGlobalWindowInner::GetFuzzTimeMS()
   }
 
   return randNum;
 }
 
 nsresult
 nsGlobalWindowInner::ScheduleActiveTimerCallback()
 {
-  MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
-
   if (!mAddActiveEventFuzzTime) {
     return HandleIdleActiveEvent();
   }
 
   MOZ_ASSERT(mIdleTimer);
   mIdleTimer->Cancel();
 
   uint32_t fuzzFactorInMS = GetFuzzTimeMS();
@@ -5258,18 +5172,16 @@ nsGlobalWindowInner::ScheduleActiveTimer
     "nsGlobalWindowInner::ScheduleActiveTimerCallback");
   NS_ENSURE_SUCCESS(rv, rv);
   return NS_OK;
 }
 
 nsresult
 nsGlobalWindowInner::HandleIdleActiveEvent()
 {
-  MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
-
   if (mCurrentlyIdle) {
     mIdleCallbackIndex = 0;
     mIdleFuzzFactor = GetFuzzTimeMS();
     nsresult rv = ScheduleNextIdleObserverCallback();
     NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
   }
 
@@ -5285,18 +5197,16 @@ nsGlobalWindowInner::HandleIdleActiveEve
   }
 
   return NS_OK;
 }
 
 nsGlobalWindowInner::SlowScriptResponse
 nsGlobalWindowInner::ShowSlowScriptDialog(const nsString& aAddonId)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   nsresult rv;
   AutoJSContext cx;
 
   if (Preferences::GetBool("dom.always_stop_slow_scripts")) {
     return KillSlowScript;
   }
 
   // If it isn't safe to run script, then it isn't safe to bring up the prompt
@@ -5520,17 +5430,16 @@ nsGlobalWindowInner::ShowSlowScriptDialo
   if (checkboxValue && isAddonScript)
     return KillScriptGlobal;
   return KillSlowScript;
 }
 
 uint32_t
 nsGlobalWindowInner::FindInsertionIndex(IdleObserverHolder* aIdleObserver)
 {
-  MOZ_ASSERT(IsInnerWindow());
   MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
 
   uint32_t i = 0;
   nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
   while (iter.HasMore()) {
     IdleObserverHolder& idleObserver = iter.GetNext();
     if (idleObserver.mTimeInS > aIdleObserver->mTimeInS) {
       break;
@@ -5540,18 +5449,16 @@ nsGlobalWindowInner::FindInsertionIndex(
   }
 
   return i;
 }
 
 nsresult
 nsGlobalWindowInner::RegisterIdleObserver(nsIIdleObserver* aIdleObserver)
 {
-  MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
-
   nsresult rv;
   if (mIdleObservers.IsEmpty()) {
     mIdleService = do_GetService("@mozilla.org/widget/idleservice;1", &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = mIdleService->AddIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -5612,17 +5519,16 @@ nsGlobalWindowInner::RegisterIdleObserve
   }
   return NS_OK;
 }
 
 nsresult
 nsGlobalWindowInner::FindIndexOfElementToRemove(nsIIdleObserver* aIdleObserver,
                                                 int32_t* aRemoveElementIndex)
 {
-  MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
   MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
 
   *aRemoveElementIndex = 0;
   if (mIdleObservers.IsEmpty()) {
     return NS_ERROR_FAILURE;
   }
 
   uint32_t aIdleObserverTimeInS;
@@ -5641,18 +5547,16 @@ nsGlobalWindowInner::FindIndexOfElementT
   }
   return static_cast<uint32_t>(*aRemoveElementIndex) >= mIdleObservers.Length() ?
     NS_ERROR_FAILURE : NS_OK;
 }
 
 nsresult
 nsGlobalWindowInner::UnregisterIdleObserver(nsIIdleObserver* aIdleObserver)
 {
-  MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
-
   int32_t removeElementIndex;
   nsresult rv = FindIndexOfElementToRemove(aIdleObserver, &removeElementIndex);
   if (NS_FAILED(rv)) {
     NS_WARNING("Idle observer not found in list of idle observers. No idle observer removed.");
     return NS_OK;
   }
   mIdleObservers.RemoveElementAt(removeElementIndex);
 
@@ -5731,17 +5635,16 @@ nsGlobalWindowInner::Observe(nsISupports
   }
 
   if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_ACTIVE)) {
     mCurrentlyIdle = false;
     if (IsFrozen()) {
       mNotifyIdleObserversActiveOnThaw = true;
       mNotifyIdleObserversIdleOnThaw = false;
     } else if (IsCurrentInnerWindow()) {
-      MOZ_ASSERT(IsInnerWindow());
       ScheduleActiveTimerCallback();
     }
     return NS_OK;
   }
 
   if (!nsCRT::strcmp(aTopic, "offline-cache-update-added")) {
     if (mApplicationCache)
       return NS_OK;
@@ -5754,17 +5657,16 @@ nsGlobalWindowInner::Observe(nsISupports
     if (observer)
       observer->Observe(aSubject, aTopic, aData);
 
     return NS_OK;
   }
 
   if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
     MOZ_ASSERT(!NS_strcmp(aData, u"intl.accept_languages"));
-    MOZ_ASSERT(IsInnerWindow());
 
     // The user preferred languages have changed, we need to fire an event on
     // Window object and invalidate the cache for navigator.languages. It is
     // done for every change which can be a waste of cycles but those should be
     // fairly rare.
     // We MUST invalidate navigator.languages before sending the event in the
     // very likely situation where an event handler will try to read its value.
 
@@ -5803,17 +5705,17 @@ nsGlobalWindowInner::ObserveStorageNotif
   if (aPrivateBrowsing != IsPrivateBrowsing()) {
     return;
   }
 
   // LocalStorage can only exist on an inner window, and we don't want to
   // generate events on frozen or otherwise-navigated-away from windows.
   // (Actually, this code used to try and buffer events for frozen windows,
   // but it never worked, so we've removed it.  See bug 1285898.)
-  if (!IsInnerWindow() || !IsCurrentInnerWindow() || IsFrozen()) {
+  if (!IsCurrentInnerWindow() || IsFrozen()) {
     return;
   }
 
   nsIPrincipal *principal = GetPrincipal();
   if (!principal) {
     return;
   }
 
@@ -5837,17 +5739,17 @@ nsGlobalWindowInner::ObserveStorageNotif
     }
 
     if (!check) {
       // This storage event is not coming from our storage or is coming
       // from a different docshell, i.e. it is a clone, ignore this event.
       return;
     }
 
-    MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug,
+    MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
             ("nsGlobalWindowInner %p with sessionStorage %p passing event from %p",
              this, mSessionStorage.get(), changingStorage.get()));
 
     fireMozStorageChanged = mSessionStorage == changingStorage;
     if (fireMozStorageChanged) {
       eventType.AssignLiteral("MozSessionStorageChanged");
     }
   }
@@ -5885,18 +5787,16 @@ nsGlobalWindowInner::ObserveStorageNotif
   DispatchEvent(clonedEvent, &defaultActionEnabled);
 }
 
 already_AddRefed<StorageEvent>
 nsGlobalWindowInner::CloneStorageEvent(const nsAString& aType,
                                        const RefPtr<StorageEvent>& aEvent,
                                        ErrorResult& aRv)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   StorageEventInit dict;
 
   dict.mBubbles = aEvent->Bubbles();
   dict.mCancelable = aEvent->Cancelable();
   aEvent->GetKey(dict.mKey);
   aEvent->GetOldValue(dict.mOldValue);
   aEvent->GetNewValue(dict.mNewValue);
   aEvent->GetUrl(dict.mUrl);
@@ -5937,17 +5837,16 @@ nsGlobalWindowInner::CloneStorageEvent(c
   RefPtr<StorageEvent> event = StorageEvent::Constructor(this, aType, dict);
   return event.forget();
 }
 
 void
 nsGlobalWindowInner::Suspend()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow());
 
   // We can only safely suspend windows that are the current inner window.  If
   // its not the current inner, then we are in one of two different cases.
   // Either we are in the bfcache or we are doomed window that is going away.
   // When a window becomes inactive we purposely avoid placing already suspended
   // windows into the bfcache.  It only expects windows suspended due to the
   // Freeze() method which occurs while the window is still the current inner.
   // So we must not call Suspend() on bfcache windows at this point or this
@@ -5986,17 +5885,16 @@ nsGlobalWindowInner::Suspend()
     RefPtr<Promise> d = mAudioContexts[i]->Suspend(dummy);
   }
 }
 
 void
 nsGlobalWindowInner::Resume()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow());
 
   // We can only safely resume a window if its the current inner window.  If
   // its not the current inner, then we are in one of two different cases.
   // Either we are in the bfcache or we are doomed window that is going away.
   // If a window is suspended when it becomes inactive we purposely do not
   // put it in the bfcache, so Resume should never be needed in that case.
   // If the window is doomed then there is no point in resuming it.
   if (!IsCurrentInnerWindow()) {
@@ -6054,17 +5952,16 @@ nsGlobalWindowInner::Freeze()
   Suspend();
   FreezeInternal();
 }
 
 void
 nsGlobalWindowInner::FreezeInternal()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow());
   MOZ_DIAGNOSTIC_ASSERT(IsCurrentInnerWindow());
   MOZ_DIAGNOSTIC_ASSERT(IsSuspended());
 
   CallOnChildren(&nsGlobalWindowInner::FreezeInternal);
 
   mFreezeDepth += 1;
   MOZ_ASSERT(mSuspendDepth >= mFreezeDepth);
   if (mFreezeDepth != 1) {
@@ -6073,34 +5970,31 @@ nsGlobalWindowInner::FreezeInternal()
 
   mozilla::dom::workers::FreezeWorkersForWindow(this);
 
   mTimeoutManager->Freeze();
   if (mClientSource) {
     mClientSource->Freeze();
   }
 
-  if (IsInnerWindow()) {
-    NotifyDOMWindowFrozen(this);
-  }
+  NotifyDOMWindowFrozen(this);
 }
 
 void
 nsGlobalWindowInner::Thaw()
 {
   MOZ_ASSERT(NS_IsMainThread());
   ThawInternal();
   Resume();
 }
 
 void
 nsGlobalWindowInner::ThawInternal()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow());
   MOZ_DIAGNOSTIC_ASSERT(IsCurrentInnerWindow());
   MOZ_DIAGNOSTIC_ASSERT(IsSuspended());
 
   CallOnChildren(&nsGlobalWindowInner::ThawInternal);
 
   MOZ_ASSERT(mFreezeDepth != 0);
   mFreezeDepth -= 1;
   MOZ_ASSERT(mSuspendDepth >= mFreezeDepth);
@@ -6110,36 +6004,33 @@ nsGlobalWindowInner::ThawInternal()
 
   if (mClientSource) {
     mClientSource->Thaw();
   }
   mTimeoutManager->Thaw();
 
   mozilla::dom::workers::ThawWorkersForWindow(this);
 
-  if (IsInnerWindow()) {
-    NotifyDOMWindowThawed(this);
-  }
+  NotifyDOMWindowThawed(this);
 }
 
 bool
 nsGlobalWindowInner::IsFrozen() const
 {
   MOZ_ASSERT(NS_IsMainThread());
   bool frozen = mFreezeDepth != 0;
   MOZ_ASSERT_IF(frozen, IsSuspended());
   return frozen;
 }
 
 void
 nsGlobalWindowInner::SyncStateFromParentWindow()
 {
   // This method should only be called on an inner window that has been
   // assigned to an outer window already.
-  MOZ_ASSERT(IsInnerWindow());
   MOZ_ASSERT(IsCurrentInnerWindow());
   nsPIDOMWindowOuter* outer = GetOuterWindow();
   MOZ_ASSERT(outer);
 
   // Attempt to find our parent windows.
   nsCOMPtr<Element> frame = outer->GetFrameElementInternal();
   nsPIDOMWindowOuter* parentOuter = frame ? frame->OwnerDoc()->GetWindow()
                                           : nullptr;
@@ -6174,17 +6065,16 @@ nsGlobalWindowInner::SyncStateFromParent
   }
 }
 
 template<typename Method>
 void
 nsGlobalWindowInner::CallOnChildren(Method aMethod)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(IsInnerWindow());
   MOZ_ASSERT(IsCurrentInnerWindow());
 
   nsCOMPtr<nsIDocShell> docShell = GetDocShell();
   if (!docShell) {
     return;
   }
 
   int32_t childCount = 0;
@@ -6310,16 +6200,30 @@ int32_t
 nsGlobalWindowInner::SetTimeout(JSContext* aCx, const nsAString& aHandler,
                                 int32_t aTimeout,
                                 const Sequence<JS::Value>& /* unused */,
                                 ErrorResult& aError)
 {
   return SetTimeoutOrInterval(aCx, aHandler, aTimeout, false, aError);
 }
 
+static bool
+IsInterval(const Optional<int32_t>& aTimeout, int32_t& aResultTimeout)
+{
+  if (aTimeout.WasPassed()) {
+    aResultTimeout = aTimeout.Value();
+    return true;
+  }
+
+  // If no interval was specified, treat this like a timeout, to avoid setting
+  // an interval of 0 milliseconds.
+  aResultTimeout = 0;
+  return false;
+}
+
 int32_t
 nsGlobalWindowInner::SetInterval(JSContext* aCx, Function& aFunction,
                                  const Optional<int32_t>& aTimeout,
                                  const Sequence<JS::Value>& aArguments,
                                  ErrorResult& aError)
 {
   int32_t timeout;
   bool isInterval = IsInterval(aTimeout, timeout);
@@ -6394,18 +6298,16 @@ nsGlobalWindowInner::SetTimeoutOrInterva
                                       &result);
   return result;
 }
 
 bool
 nsGlobalWindowInner::RunTimeoutHandler(Timeout* aTimeout,
                                        nsIScriptContext* aScx)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   // Hold on to the timeout in case mExpr or mFunObj releases its
   // doc.
   RefPtr<Timeout> timeout = aTimeout;
   Timeout* last_running_timeout = mTimeoutManager->BeginRunningTimeout(timeout);
   timeout->mRunning = true;
 
   // Push this timeout's popup control state, which should only be
   // eabled the first time a timeout fires that was created while
@@ -6551,38 +6453,18 @@ void
 nsGlobalWindowInner::FlushPendingNotifications(FlushType aType)
 {
   if (mDoc) {
     mDoc->FlushPendingNotifications(aType);
   }
 }
 
 void
-nsGlobalWindowInner::EnsureSizeAndPositionUpToDate()
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-already_AddRefed<nsISupports>
-nsGlobalWindowInner::SaveWindowState()
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-nsresult
-nsGlobalWindowInner::RestoreWindowState(nsISupports *aState)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-void
 nsGlobalWindowInner::EnableDeviceSensor(uint32_t aType)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   bool alreadyEnabled = false;
   for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) {
     if (mEnabledSensors[i] == aType) {
       alreadyEnabled = true;
       break;
     }
   }
 
@@ -6596,18 +6478,16 @@ nsGlobalWindowInner::EnableDeviceSensor(
   if (ac) {
     ac->AddWindowListener(aType, this);
   }
 }
 
 void
 nsGlobalWindowInner::DisableDeviceSensor(uint32_t aType)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   int32_t doomedElement = -1;
   int32_t listenerCount = 0;
   for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) {
     if (mEnabledSensors[i] == aType) {
       doomedElement = i;
       listenerCount++;
     }
   }
@@ -6627,37 +6507,35 @@ nsGlobalWindowInner::DisableDeviceSensor
     ac->RemoveWindowListener(aType, this);
   }
 }
 
 #if defined(MOZ_WIDGET_ANDROID)
 void
 nsGlobalWindowInner::EnableOrientationChangeListener()
 {
-  MOZ_ASSERT(IsInnerWindow());
-  if (!nsContentUtils::ShouldResistFingerprinting(mDocShell) &&
+  // XXX: mDocShell is never set on the inner window?
+  nsIDocShell* docShell = nullptr;
+  if (!nsContentUtils::ShouldResistFingerprinting(docShell) &&
       !mOrientationChangeObserver) {
     mOrientationChangeObserver =
       MakeUnique<WindowOrientationObserver>(this);
   }
 }
 
 void
 nsGlobalWindowInner::DisableOrientationChangeListener()
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   mOrientationChangeObserver = nullptr;
 }
 #endif
 
 void
 nsGlobalWindowInner::SetHasGamepadEventListener(bool aHasGamepad/* = true*/)
 {
-  MOZ_ASSERT(IsInnerWindow());
   mHasGamepad = aHasGamepad;
   if (aHasGamepad) {
     EnableGamepadUpdates();
   }
 }
 
 
 void
@@ -6673,17 +6551,16 @@ nsGlobalWindowInner::EventListenerAdded(
 
   if (aType == nsGkAtoms::onvrdisplayactivate) {
     mHasVRDisplayActivateEvents = true;
   }
 
   if (aType == nsGkAtoms::onbeforeunload &&
       mTabChild &&
       (!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS))) {
-    MOZ_ASSERT(IsInnerWindow());
     mBeforeUnloadListenerCount++;
     MOZ_ASSERT(mBeforeUnloadListenerCount > 0);
     mTabChild->BeforeUnloadAdded();
   }
 
   // We need to initialize localStorage in order to receive notifications.
   if (aType == nsGkAtoms::onstorage) {
     ErrorResult rv;
@@ -6693,46 +6570,40 @@ nsGlobalWindowInner::EventListenerAdded(
 }
 
 void
 nsGlobalWindowInner::EventListenerRemoved(nsAtom* aType)
 {
   if (aType == nsGkAtoms::onbeforeunload &&
       mTabChild &&
       (!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS))) {
-    MOZ_ASSERT(IsInnerWindow());
     mBeforeUnloadListenerCount--;
     MOZ_ASSERT(mBeforeUnloadListenerCount >= 0);
     mTabChild->BeforeUnloadRemoved();
   }
 }
 
 void
 nsGlobalWindowInner::NotifyVREventListenerAdded()
 {
-  MOZ_ASSERT(IsInnerWindow());
   mHasVREvents = true;
   EnableVRUpdates();
 }
 
 bool
 nsGlobalWindowInner::HasUsedVR() const
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   // Returns true only if any WebVR API call or related event
   // has been used
   return mHasVREvents;
 }
 
 bool
 nsGlobalWindowInner::IsVRContentDetected() const
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   // Returns true only if the content will respond to
   // the VRDisplayActivate event.
   return mHasVRDisplayActivateEvents;
 }
 
 bool
 nsGlobalWindowInner::IsVRContentPresenting() const
 {
@@ -6805,46 +6676,43 @@ nsGlobalWindowInner::AddSizeOfIncludingT
     aWindowSizes.mDOMPerformanceResourceEntries =
       mPerformance->SizeOfResourceEntries(aWindowSizes.mState.mMallocSizeOf);
   }
 }
 
 void
 nsGlobalWindowInner::AddGamepad(uint32_t aIndex, Gamepad* aGamepad)
 {
-  MOZ_ASSERT(IsInnerWindow());
   // Create the index we will present to content based on which indices are
   // already taken, as required by the spec.
   // https://w3c.github.io/gamepad/gamepad.html#widl-Gamepad-index
   int index = 0;
   while(mGamepadIndexSet.Contains(index)) {
     ++index;
   }
   mGamepadIndexSet.Put(index);
   aGamepad->SetIndex(index);
   mGamepads.Put(aIndex, aGamepad);
 }
 
 void
 nsGlobalWindowInner::RemoveGamepad(uint32_t aIndex)
 {
-  MOZ_ASSERT(IsInnerWindow());
   RefPtr<Gamepad> gamepad;
   if (!mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
     return;
   }
   // Free up the index we were using so it can be reused
   mGamepadIndexSet.Remove(gamepad->Index());
   mGamepads.Remove(aIndex);
 }
 
 void
 nsGlobalWindowInner::GetGamepads(nsTArray<RefPtr<Gamepad> >& aGamepads)
 {
-  MOZ_ASSERT(IsInnerWindow());
   aGamepads.Clear();
 
   // navigator.getGamepads() always returns an empty array when
   // privacy.resistFingerprinting is true.
   if (nsContentUtils::ShouldResistFingerprinting()) {
     return;
   }
 
@@ -6855,56 +6723,51 @@ nsGlobalWindowInner::GetGamepads(nsTArra
     aGamepads.EnsureLengthAtLeast(gamepad->Index() + 1);
     aGamepads[gamepad->Index()] = gamepad;
   }
 }
 
 already_AddRefed<Gamepad>
 nsGlobalWindowInner::GetGamepad(uint32_t aIndex)
 {
-  MOZ_ASSERT(IsInnerWindow());
   RefPtr<Gamepad> gamepad;
 
   if (mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
     return gamepad.forget();
   }
 
   return nullptr;
 }
 
 void
 nsGlobalWindowInner::SetHasSeenGamepadInput(bool aHasSeen)
 {
-  MOZ_ASSERT(IsInnerWindow());
   mHasSeenGamepadInput = aHasSeen;
 }
 
 bool
 nsGlobalWindowInner::HasSeenGamepadInput()
 {
-  MOZ_ASSERT(IsInnerWindow());
   return mHasSeenGamepadInput;
 }
 
 void
 nsGlobalWindowInner::SyncGamepadState()
 {
-  MOZ_ASSERT(IsInnerWindow());
   if (mHasSeenGamepadInput) {
     RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
     for (auto iter = mGamepads.Iter(); !iter.Done(); iter.Next()) {
       gamepadManager->SyncGamepadState(iter.Key(), iter.UserData());
     }
   }
 }
 
 void
 nsGlobalWindowInner::StopGamepadHaptics()
 {
-  MOZ_ASSERT(IsInnerWindow());
   if (mHasSeenGamepadInput) {
     RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
     gamepadManager->StopHaptics();
   }
 }
 
 bool
 nsGlobalWindowInner::UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDevices)
@@ -6912,18 +6775,16 @@ nsGlobalWindowInner::UpdateVRDisplays(ns
   VRDisplay::UpdateVRDisplays(mVRDisplays, this);
   aDevices = mVRDisplays;
   return true;
 }
 
 void
 nsGlobalWindowInner::NotifyActiveVRDisplaysChanged()
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   if (mNavigator) {
     mNavigator->NotifyActiveVRDisplaysChanged();
   }
 }
 
 void
 nsGlobalWindowInner::DispatchVRDisplayActivate(uint32_t aDisplayID,
                                                mozilla::dom::VRDisplayEventReason aReason)
@@ -7088,17 +6949,16 @@ enum WindowState {
   STATE_MINIMIZED = 2,
   STATE_NORMAL = 3,
   STATE_FULLSCREEN = 4
 };
 
 uint16_t
 nsGlobalWindowInner::WindowState()
 {
-  MOZ_ASSERT(IsInnerWindow());
   nsCOMPtr<nsIWidget> widget = GetMainWidget();
 
   int32_t mode = widget ? widget->SizeMode() : 0;
 
   switch (mode) {
     case nsSizeMode_Minimized:
       return STATE_MINIMIZED;
     case nsSizeMode_Maximized:
@@ -7113,84 +6973,71 @@ nsGlobalWindowInner::WindowState()
   }
 
   return STATE_NORMAL;
 }
 
 bool
 nsGlobalWindowInner::IsFullyOccluded()
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   nsCOMPtr<nsIWidget> widget = GetMainWidget();
   return widget && widget->IsFullyOccluded();
 }
 
 void
 nsGlobalWindowInner::Maximize()
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   nsCOMPtr<nsIWidget> widget = GetMainWidget();
 
   if (widget) {
     widget->SetSizeMode(nsSizeMode_Maximized);
   }
 }
 
 void
 nsGlobalWindowInner::Minimize()
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   nsCOMPtr<nsIWidget> widget = GetMainWidget();
 
   if (widget) {
     widget->SetSizeMode(nsSizeMode_Minimized);
   }
 }
 
 void
 nsGlobalWindowInner::Restore()
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   nsCOMPtr<nsIWidget> widget = GetMainWidget();
 
   if (widget) {
     widget->SetSizeMode(nsSizeMode_Normal);
   }
 }
 
 void
 nsGlobalWindowInner::GetAttention(ErrorResult& aResult)
 {
-  MOZ_ASSERT(IsInnerWindow());
   return GetAttentionWithCycleCount(-1, aResult);
 }
 
 void
 nsGlobalWindowInner::GetAttentionWithCycleCount(int32_t aCycleCount,
                                                 ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   nsCOMPtr<nsIWidget> widget = GetMainWidget();
 
   if (widget) {
     aError = widget->GetAttention(aCycleCount);
   }
 }
 
 void
 nsGlobalWindowInner::BeginWindowMove(Event& aMouseDownEvent, Element* aPanel,
                                      ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   nsCOMPtr<nsIWidget> widget;
 
   // if a panel was supplied, use its widget instead.
 #ifdef MOZ_XUL
   if (aPanel) {
     nsIFrame* frame = aPanel->GetPrimaryFrame();
     if (!frame || !frame->IsMenuPopupFrame()) {
       return;
@@ -7253,17 +7100,16 @@ nsGlobalWindowInner::SetBrowserDOMWindow
 {
   FORWARD_TO_OUTER_OR_THROW(SetBrowserDOMWindowOuter, (aBrowserWindow), aError, );
 }
 
 void
 nsGlobalWindowInner::NotifyDefaultButtonLoaded(Element& aDefaultButton,
                                                ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
 #ifdef MOZ_XUL
   // Don't snap to a disabled button.
   nsCOMPtr<nsIDOMXULControlElement> xulControl =
                                       do_QueryInterface(&aDefaultButton);
   if (!xulControl) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
@@ -7310,17 +7156,16 @@ nsGlobalWindowInner::GetMessageManager(n
   NS_IF_ADDREF(*aManager = GetMessageManager(rv));
   return rv.StealNSResult();
 }
 
 nsIMessageBroadcaster*
 nsGlobalWindowInner::GetMessageManager(ErrorResult& aError)
 {
   MOZ_ASSERT(IsChromeWindow());
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
   if (!mChromeFields.mMessageManager) {
     nsCOMPtr<nsIMessageBroadcaster> globalMM =
       do_GetService("@mozilla.org/globalmessagemanager;1");
     mChromeFields.mMessageManager =
       new nsFrameMessageManager(nullptr,
                                 static_cast<nsFrameMessageManager*>(globalMM.get()),
                                 MM_CHROME | MM_BROADCASTER);
   }
@@ -7337,43 +7182,30 @@ nsGlobalWindowInner::GetGroupMessageMana
   return rv.StealNSResult();
 }
 
 nsIMessageBroadcaster*
 nsGlobalWindowInner::GetGroupMessageManager(const nsAString& aGroup,
                                             ErrorResult& aError)
 {
   MOZ_ASSERT(IsChromeWindow());
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
 
   nsCOMPtr<nsIMessageBroadcaster> messageManager =
     mChromeFields.mGroupMessageManagers.LookupForAdd(aGroup).OrInsert(
       [this, &aError] () {
         nsFrameMessageManager* parent =
           static_cast<nsFrameMessageManager*>(GetMessageManager(aError));
 
         return new nsFrameMessageManager(nullptr,
                                          parent,
                                          MM_CHROME | MM_BROADCASTER);
       });
   return messageManager;
 }
 
-nsresult
-nsGlobalWindowInner::SetOpenerForInitialContentBrowser(mozIDOMWindowProxy* aOpenerWindow)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
-nsresult
-nsGlobalWindowInner::TakeOpenerForInitialContentBrowser(mozIDOMWindowProxy** aOpenerWindow)
-{
-  MOZ_CRASH("Virtual outer window only function");
-}
-
 void
 nsGlobalWindowInner::InitWasOffline()
 {
   mWasOffline = NS_IsOffline();
 }
 
 #if defined(MOZ_WIDGET_ANDROID)
 int16_t
@@ -7382,49 +7214,41 @@ nsGlobalWindowInner::Orientation(CallerT
   return nsContentUtils::ResistFingerprinting(aCallerType) ?
            0 : WindowOrientationObserver::OrientationAngle();
 }
 #endif
 
 Console*
 nsGlobalWindowInner::GetConsole(ErrorResult& aRv)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mConsole) {
     mConsole = Console::Create(this, aRv);
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
   }
 
   return mConsole;
 }
 
 bool
 nsGlobalWindowInner::IsSecureContext() const
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   return JS_GetIsSecureContext(js::GetObjectCompartment(GetWrapperPreserveColor()));
 }
 
 bool
 nsGlobalWindowInner::IsSecureContextIfOpenerIgnored() const
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   return mIsSecureContextIfOpenerIgnored;
 }
 
 already_AddRefed<External>
 nsGlobalWindowInner::GetExternal(ErrorResult& aRv)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
 #ifdef HAVE_SIDEBAR
   if (!mExternal) {
     AutoJSContext cx;
     JS::Rooted<JSObject*> jsImplObj(cx);
     ConstructJSImplementation("@mozilla.org/sidebar;1", this, &jsImplObj, aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
@@ -7438,18 +7262,16 @@ nsGlobalWindowInner::GetExternal(ErrorRe
   return nullptr;
 #endif
 }
 
 void
 nsGlobalWindowInner::GetSidebar(OwningExternalOrWindowProxy& aResult,
                                 ErrorResult& aRv)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
 #ifdef HAVE_SIDEBAR
   // First check for a named frame named "sidebar"
   nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetChildWindow(NS_LITERAL_STRING("sidebar"));
   if (domWindow) {
     aResult.SetAsWindowProxy() = domWindow.forget();
     return;
   }
 
@@ -7460,18 +7282,16 @@ nsGlobalWindowInner::GetSidebar(OwningEx
 #else
   aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
 #endif
 }
 
 void
 nsGlobalWindowInner::ClearDocumentDependentSlots(JSContext* aCx)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   // If JSAPI OOMs here, there is basically nothing we can do to recover safely.
   if (!WindowBinding::ClearCachedDocumentValue(aCx, this) ||
       !WindowBinding::ClearCachedPerformanceValue(aCx, this)) {
     MOZ_CRASH("Unhandlable OOM while clearing document dependent slots.");
   }
 }
 
 /* static */
@@ -7508,35 +7328,31 @@ nsGlobalWindowInner::RedefineProperty(JS
 
 void
 nsGlobalWindowInner::GetReplaceableWindowCoord(JSContext* aCx,
                                                nsGlobalWindowInner::WindowCoordGetter aGetter,
                                                JS::MutableHandle<JS::Value> aRetval,
                                                CallerType aCallerType,
                                                ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   int32_t coord = (this->*aGetter)(aCallerType, aError);
   if (!aError.Failed() &&
       !ToJSValue(aCx, coord, aRetval)) {
     aError.Throw(NS_ERROR_FAILURE);
   }
 }
 
 void
 nsGlobalWindowInner::SetReplaceableWindowCoord(JSContext* aCx,
                                                nsGlobalWindowInner::WindowCoordSetter aSetter,
                                                JS::Handle<JS::Value> aValue,
                                                const char* aPropName,
                                                CallerType aCallerType,
                                                ErrorResult& aError)
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   /*
    * If caller is not chrome and the user has not explicitly exempted the site,
    * just treat this the way we would an IDL replaceable property.
    */
   nsGlobalWindowOuter* outer = GetOuterWindowInternal();
   if (!outer ||
       !outer->CanMoveResizeWindows(aCallerType) ||
       outer->IsFrame()) {
@@ -7646,18 +7462,16 @@ nsGlobalWindowInner::SetReplaceableWindo
   }
 
   (this->*aSetter)(value, aCallerType, aError);
 }
 
 void
 nsGlobalWindowInner::FireOnNewGlobalObject()
 {
-  MOZ_ASSERT(IsInnerWindow());
-
   // AutoEntryScript required to invoke debugger hook, which is a
   // Gecko-specific concept at present.
   AutoEntryScript aes(this, "nsGlobalWindowInner report new global");
   JS::Rooted<JSObject*> global(aes.cx(), GetWrapper());
   JS_FireOnNewGlobalObject(aes.cx(), global);
 }
 
 #ifdef _WINDOWS_
@@ -7709,18 +7523,16 @@ nsGlobalWindowInner::CreateImageBitmap(J
   }
   aRv.Throw(NS_ERROR_TYPE_ERR);
   return nullptr;
 }
 
 mozilla::dom::TabGroup*
 nsGlobalWindowInner::TabGroupInner()
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   // If we don't have a TabGroup yet, try to get it from the outer window and
   // cache it.
   if (!mTabGroup) {
     nsGlobalWindowOuter* outer = GetOuterWindowInternal();
     // This will never be called without either an outer window, or a cached tab group.
     // This is because of the following:
     // * This method is only called on inner windows
     // * This method is called as a document is attached to it's script global
@@ -7770,36 +7582,32 @@ nsGlobalWindowInner::AbstractMainThreadF
     return GetDocGroup()->AbstractMainThreadFor(aCategory);
   }
   return DispatcherTrait::AbstractMainThreadFor(aCategory);
 }
 
 Worklet*
 nsGlobalWindowInner::GetAudioWorklet(ErrorResult& aRv)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mAudioWorklet) {
     nsIPrincipal* principal = GetPrincipal();
     if (!principal) {
       aRv.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
     mAudioWorklet = new Worklet(this, principal, Worklet::eAudioWorklet);
   }
 
   return mAudioWorklet;
 }
 
 Worklet*
 nsGlobalWindowInner::GetPaintWorklet(ErrorResult& aRv)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mPaintWorklet) {
     nsIPrincipal* principal = GetPrincipal();
     if (!principal) {
       aRv.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
     mPaintWorklet = new Worklet(this, principal, Worklet::ePaintWorklet);
@@ -7817,18 +7625,16 @@ nsGlobalWindowInner::GetRegionalPrefsLoc
   for (const auto& loc : rpLocales) {
     aLocales.AppendElement(NS_ConvertUTF8toUTF16(loc));
   }
 }
 
 IntlUtils*
 nsGlobalWindowInner::GetIntlUtils(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsInnerWindow());
-
   if (!mIntlUtils) {
     mIntlUtils = new IntlUtils(this);
   }
 
   return mIntlUtils;
 }
 
 mozilla::dom::TabGroup*
@@ -7845,11 +7651,77 @@ nsGlobalWindowInner::Create(nsGlobalWind
     window->mIsChrome = true;
     window->mCleanMessageManager = true;
   }
 
   window->InitWasOffline();
   return window.forget();
 }
 
+nsIURI*
+nsPIDOMWindowInner::GetDocumentURI() const
+{
+  return mDoc ? mDoc->GetDocumentURI() : mDocumentURI.get();
+}
+
+nsIURI*
+nsPIDOMWindowInner::GetDocBaseURI() const
+{
+  return mDoc ? mDoc->GetDocBaseURI() : mDocBaseURI.get();
+}
+
+void
+nsPIDOMWindowInner::MaybeCreateDoc()
+{
+  // XXX: Forward to outer?
+  MOZ_ASSERT(!mDoc);
+  if (nsIDocShell* docShell = GetDocShell()) {
+    // Note that |document| here is the same thing as our mDoc, but we
+    // don't have to explicitly set the member variable because the docshell
+    // has already called SetNewDocument().
+    nsCOMPtr<nsIDocument> document = docShell->GetDocument();
+    Unused << document;
+  }
+}
+
+mozilla::dom::DocGroup*
+nsPIDOMWindowInner::GetDocGroup() const
+{
+  nsIDocument* doc = GetExtantDoc();
+  if (doc) {
+    return doc->GetDocGroup();
+  }
+  return nullptr;
+}
+
+// XXX: Can we define this in a header instead of here?
+namespace mozilla {
+namespace dom {
+extern uint64_t
+NextWindowID();
+} // namespace dom
+} // namespace mozilla
+
+nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter *aOuterWindow)
+: mMutationBits(0), mActivePeerConnections(0), mIsDocumentLoaded(false),
+  mIsHandlingResizeEvent(false),
+  mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false),
+  mMayHaveSelectionChangeEventListener(false),
+  mMayHaveMouseEnterLeaveEventListener(false),
+  mMayHavePointerEnterLeaveEventListener(false),
+  mInnerObjectsFreed(false),
+  mAudioCaptured(false),
+  mOuterWindow(aOuterWindow),
+  // Make sure no actual window ends up with mWindowID == 0
+  mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
+  mMarkedCCGeneration(0),
+  mHasTriedToCacheTopInnerWindow(false),
+  mNumOfIndexedDBDatabases(0),
+  mNumOfOpenWebSockets(0)
+{
+  MOZ_ASSERT(aOuterWindow);
+}
+
+nsPIDOMWindowInner::~nsPIDOMWindowInner() {}
+
 #undef FORWARD_TO_OUTER
 #undef FORWARD_TO_OUTER_OR_THROW
 #undef FORWARD_TO_OUTER_VOID
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -187,37 +187,27 @@ inline void
 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
                             IdleObserverHolder& aField,
                             const char* aName,
                             unsigned aFlags)
 {
   CycleCollectionNoteChild(aCallback, aField.mIdleObserver.get(), aName, aFlags);
 }
 
-// NOTE: Currently this file, despite being named mozilla/dom/Window.h, exports
-// the class nsGlobalWindowInner. It will be renamed in the future to
-// mozilla::dom::Window.
-
 //*****************************************************************************
-// nsGlobalWindow: Global Object for Scripting
+// nsGlobalWindowInner: Global Object for Scripting
 //*****************************************************************************
-// Beware that all scriptable interfaces implemented by
-// nsGlobalWindow will be reachable from JS, if you make this class
-// implement new interfaces you better know what you're
-// doing. Security wise this is very sensitive code. --
-// jst@netscape.com
 
-// nsGlobalWindow inherits PRCList for maintaining a list of all inner
-// windows still in memory for any given outer window. This list is
-// needed to ensure that mOuterWindow doesn't end up dangling. The
-// nature of PRCList means that the window itself is always in the
-// list, and an outer window's list will also contain all inner window
-// objects that are still in memory (and in reality all inner window
-// object's lists also contain its outer and all other inner windows
-// belonging to the same outer window, but that's an unimportant
+// nsGlobalWindowInner inherits PRCList for maintaining a list of all inner
+// windows still in memory for any given outer window. This list is needed to
+// ensure that mOuterWindow doesn't end up dangling. The nature of PRCList means
+// that the window itself is always in the list, and an outer window's list will
+// also contain all inner window objects that are still in memory (and in
+// reality all inner window object's lists also contain its outer and all other
+// inner windows belonging to the same outer window, but that's an unimportant
 // side effect of inheriting PRCList).
 
 class nsGlobalWindowInner : public mozilla::dom::EventTarget,
                             public nsPIDOMWindowInner,
                             private nsIDOMWindow,
                             // NOTE: This interface is private, as it's only
                             // implemented on chrome windows.
                             private nsIDOMChromeWindow,
@@ -257,18 +247,16 @@ public:
     AssertIsOnMainThread();
 
     if (!sInnerWindowsById) {
       return nullptr;
     }
 
     nsGlobalWindowInner* innerWindow =
       sInnerWindowsById->Get(aInnerWindowID);
-    MOZ_ASSERT(!innerWindow || innerWindow->IsInnerWindow(),
-                "Outer window in sInnerWindowsById?");
     return innerWindow;
   }
 
   static InnerWindowByIdTable* GetWindowsTable() {
     AssertIsOnMainThread();
 
     return sInnerWindowsById;
   }
@@ -286,17 +274,17 @@ public:
   void ReallyCloseWindow();
 
   // nsISupports
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsWrapperCache
   virtual JSObject *WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override
   {
-    return IsInnerWindow() || AsOuter()->EnsureInnerWindow() ? GetWrapper() : nullptr;
+    return GetWrapper();
   }
 
   // nsIGlobalJSObjectHolder
   virtual JSObject* GetGlobalJSObject() override;
 
   // nsIScriptGlobalObject
   JSObject *FastGetGlobalJSObject() const
   {
@@ -343,32 +331,20 @@ public:
   virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override;
 
   virtual nsIGlobalObject* GetOwnerGlobal() const override;
 
   // nsPIDOMWindow
   virtual nsPIDOMWindowOuter* GetPrivateRoot() override;
 
   // Outer windows only.
-  virtual void ActivateOrDeactivate(bool aActivate) override;
-  virtual void SetActive(bool aActive) override;
   virtual bool IsTopLevelWindowActive() override;
-  virtual void SetIsBackground(bool aIsBackground) override;
-  virtual void SetChromeEventHandler(mozilla::dom::EventTarget* aChromeEventHandler) override;
 
-  // Outer windows only.
-  virtual void SetInitialPrincipalToSubject() override;
-
-  virtual PopupControlState PushPopupControlState(PopupControlState state, bool aForce) const override;
-  virtual void PopPopupControlState(PopupControlState state) const override;
   virtual PopupControlState GetPopupControlState() const override;
 
-  virtual already_AddRefed<nsISupports> SaveWindowState() override;
-  virtual nsresult RestoreWindowState(nsISupports *aState) override;
-
   void Suspend();
   void Resume();
   virtual bool IsSuspended() const override;
   void Freeze();
   void Thaw();
   virtual bool IsFrozen() const override;
   void SyncStateFromParentWindow();
 
@@ -378,43 +354,24 @@ public:
 
   virtual nsresult SetNewDocument(nsIDocument *aDocument,
                                   nsISupports *aState,
                                   bool aForceReuseInnerWindow) override;
 
   virtual void SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
                                bool aOriginalOpener) override;
 
-  // Outer windows only.
-  virtual void EnsureSizeAndPositionUpToDate() override;
-
-  virtual void EnterModalState() override;
-  virtual void LeaveModalState() override;
-
-  // Outer windows only.
-  virtual bool CanClose() override;
-  virtual void ForceClose() override;
-
   virtual void MaybeUpdateTouchState() override;
 
-  // Outer windows only.
-  virtual bool DispatchCustomEvent(const nsAString& aEventName) override;
-
   // Inner windows only.
   void RefreshCompartmentPrincipal();
 
   // For accessing protected field mFullScreen
   friend class FullscreenTransitionTask;
 
-  // Outer windows only.
-  virtual nsresult SetFullscreenInternal(
-    FullscreenReason aReason, bool aIsFullscreen) override final;
-  virtual void FullscreenWillChange(bool aIsFullscreen) override final;
-  virtual void FinishFullscreenChange(bool aIsFullscreen) override final;
-
   // Inner windows only.
   virtual void SetHasGamepadEventListener(bool aHasGamepad = true) override;
   void NotifyVREventListenerAdded();
   bool HasUsedVR() const;
   bool IsVRContentDetected() const;
   bool IsVRContentPresenting() const;
 
   using EventTarget::EventListenerAdded;
@@ -439,17 +396,16 @@ public:
                  JS::MutableHandle<JS::PropertyDescriptor> aDesc);
   // The return value is whether DoResolve might end up resolving the given id.
   // If in doubt, return true.
   static bool MayResolve(jsid aId);
 
   void GetOwnPropertyNames(JSContext* aCx, JS::AutoIdVector& aNames,
                            bool aEnumerableOnly, mozilla::ErrorResult& aRv);
 
-  already_AddRefed<nsPIDOMWindowOuter> GetTop() override;
   nsPIDOMWindowOuter* GetScriptableTop() override;
   inline nsGlobalWindowOuter *GetTopInternal();
 
   inline nsGlobalWindowOuter* GetScriptableTopInternal();
 
   nsPIDOMWindowOuter* GetChildWindow(const nsAString& aName);
 
   // These return true if we've reached the state in this top level window
@@ -470,21 +426,16 @@ public:
   // re-enable dialogs is actually quite difficult.
   void EnableDialogs();
   void DisableDialogs();
 
   nsIScriptContext *GetContextInternal();
 
   nsGlobalWindowOuter *GetOuterWindowInternal() const;
 
-  bool IsCreatingInnerWindow() const
-  {
-    return mCreatingInnerWindow;
-  }
-
   bool IsChromeWindow() const
   {
     return mIsChrome;
   }
 
   // GetScrollFrame does not flush.  Callers should do it themselves as needed,
   // depending on which info they actually want off the scrollable frame.
   nsIScrollableFrame *GetScrollFrame();
@@ -533,58 +484,42 @@ public:
 #if defined(MOZ_WIDGET_ANDROID)
   virtual void EnableOrientationChangeListener() override;
   virtual void DisableOrientationChangeListener() override;
 #endif
 
   virtual void EnableTimeChangeNotifications() override;
   virtual void DisableTimeChangeNotifications() override;
 
-  virtual nsresult SetArguments(nsIArray* aArguments) override;
-
   bool IsClosedOrClosing() {
-    return (mIsClosed ||
-            mInClose ||
-            mHavePendingClose ||
-            mCleanedUp);
+    return mCleanedUp;
   }
 
   bool
   IsCleanedUp() const
   {
     return mCleanedUp;
   }
 
-  virtual void
-  FirePopupBlockedEvent(nsIDocument* aDoc,
-                        nsIURI* aPopupURI,
-                        const nsAString& aPopupWindowName,
-                        const nsAString& aPopupWindowFeatures) override;
-
   virtual uint32_t GetSerial() override {
     return mSerial;
   }
 
   void AddSizeOfIncludingThis(nsWindowSizes& aWindowSizes) const;
 
   // Inner windows only.
   void AddEventTargetObject(mozilla::DOMEventTargetHelper* aObject);
   void RemoveEventTargetObject(mozilla::DOMEventTargetHelper* aObject);
 
   void NotifyIdleObserver(IdleObserverHolder* aIdleObserverHolder,
                           bool aCallOnidle);
   nsresult HandleIdleActiveEvent();
   bool ContainsIdleObserver(nsIIdleObserver* aIdleObserver, uint32_t timeInS);
   void HandleIdleObserverCallback();
 
-  void AllowScriptsToClose()
-  {
-    mAllowScriptsToClose = true;
-  }
-
   enum SlowScriptResponse {
     ContinueSlowScript = 0,
     ContinueSlowScriptAndKeepNotifying,
     AlwaysContinueSlowScript,
     KillSlowScript,
     KillScriptGlobal
   };
   SlowScriptResponse ShowSlowScriptDialog(const nsString& aAddonId);
@@ -702,56 +637,46 @@ public:
   mozilla::dom::BarProp* GetScrollbars(mozilla::ErrorResult& aError);
   mozilla::dom::BarProp* GetStatusbar(mozilla::ErrorResult& aError);
   mozilla::dom::BarProp* GetToolbar(mozilla::ErrorResult& aError);
   void GetStatus(nsAString& aStatus, mozilla::ErrorResult& aError);
   void SetStatus(const nsAString& aStatus, mozilla::ErrorResult& aError);
   void Close(mozilla::ErrorResult& aError);
   nsresult Close() override;
   bool GetClosed(mozilla::ErrorResult& aError);
-  bool Closed() override;
   void Stop(mozilla::ErrorResult& aError);
   void Focus(mozilla::ErrorResult& aError);
   nsresult Focus() override;
   void Blur(mozilla::ErrorResult& aError);
   already_AddRefed<nsIDOMWindowCollection> GetFrames() override;
   already_AddRefed<nsPIDOMWindowOuter> GetFrames(mozilla::ErrorResult& aError);
   uint32_t Length();
   already_AddRefed<nsPIDOMWindowOuter> GetTop(mozilla::ErrorResult& aError);
-
-  nsresult GetPrompter(nsIPrompt** aPrompt) override;
 protected:
   explicit nsGlobalWindowInner(nsGlobalWindowOuter *aOuterWindow);
   // Initializes the mWasOffline member variable
   void InitWasOffline();
 public:
   nsPIDOMWindowOuter* GetOpenerWindow(mozilla::ErrorResult& aError);
   void GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
                  mozilla::ErrorResult& aError);
-  already_AddRefed<nsPIDOMWindowOuter> GetOpener() override;
   void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
                  mozilla::ErrorResult& aError);
   already_AddRefed<nsPIDOMWindowOuter> GetParent(mozilla::ErrorResult& aError);
-  already_AddRefed<nsPIDOMWindowOuter> GetParent() override;
   nsPIDOMWindowOuter* GetScriptableParent() override;
   nsPIDOMWindowOuter* GetScriptableParentOrNull() override;
   mozilla::dom::Element*
   GetFrameElement(nsIPrincipal& aSubjectPrincipal,
                   mozilla::ErrorResult& aError);
   already_AddRefed<nsIDOMElement> GetFrameElement() override;
   already_AddRefed<nsPIDOMWindowOuter>
   Open(const nsAString& aUrl,
        const nsAString& aName,
        const nsAString& aOptions,
        mozilla::ErrorResult& aError);
-  nsresult Open(const nsAString& aUrl, const nsAString& aName,
-                const nsAString& aOptions,
-                nsIDocShellLoadInfo* aLoadInfo,
-                bool aForceNoOpener,
-                nsPIDOMWindowOuter **_retval) override;
   mozilla::dom::Navigator* Navigator();
   nsIDOMNavigator* GetNavigator() override;
   nsIDOMOfflineResourceList* GetApplicationCache(mozilla::ErrorResult& aError);
   already_AddRefed<nsIDOMOfflineResourceList> GetApplicationCache() override;
 
 #if defined(MOZ_WIDGET_ANDROID)
   int16_t Orientation(mozilla::dom::CallerType aCallerType) const;
 #endif
@@ -831,34 +756,32 @@ public:
   void Atob(const nsAString& aAsciiBase64String, nsAString& aBinaryData,
             mozilla::ErrorResult& aError);
   void Btoa(const nsAString& aBinaryData, nsAString& aAsciiBase64String,
             mozilla::ErrorResult& aError);
   mozilla::dom::Storage* GetSessionStorage(mozilla::ErrorResult& aError);
   mozilla::dom::Storage*
   GetLocalStorage(mozilla::ErrorResult& aError);
   mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aError);
-  already_AddRefed<nsISelection> GetSelection() override;
   mozilla::dom::IDBFactory* GetIndexedDB(mozilla::ErrorResult& aError);
   already_AddRefed<nsICSSDeclaration>
     GetComputedStyle(mozilla::dom::Element& aElt, const nsAString& aPseudoElt,
                      mozilla::ErrorResult& aError) override;
   already_AddRefed<mozilla::dom::MediaQueryList> MatchMedia(
     const nsAString& aQuery,
     mozilla::dom::CallerType aCallerType,
     mozilla::ErrorResult& aError);
   nsScreen* GetScreen(mozilla::ErrorResult& aError);
   nsIDOMScreen* GetScreen() override;
   void MoveTo(int32_t aXPos, int32_t aYPos,
               mozilla::dom::CallerType aCallerType,
               mozilla::ErrorResult& aError);
   void MoveBy(int32_t aXDif, int32_t aYDif,
               mozilla::dom::CallerType aCallerType,
               mozilla::ErrorResult& aError);
-  nsresult MoveBy(int32_t aXDif, int32_t aYDif) override;
   void ResizeTo(int32_t aWidth, int32_t aHeight,
                 mozilla::dom::CallerType aCallerType,
                 mozilla::ErrorResult& aError);
   void ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
                 mozilla::dom::CallerType aCallerType,
                 mozilla::ErrorResult& aError);
   void Scroll(double aXScroll, double aYScroll);
   void Scroll(const mozilla::dom::ScrollToOptions& aOptions);
@@ -951,17 +874,16 @@ public:
                              mozilla::ErrorResult& aError);
   int32_t GetScrollMinX(mozilla::ErrorResult& aError);
   int32_t GetScrollMinY(mozilla::ErrorResult& aError);
   int32_t GetScrollMaxX(mozilla::ErrorResult& aError);
   int32_t GetScrollMaxY(mozilla::ErrorResult& aError);
   bool GetFullScreen(mozilla::ErrorResult& aError);
   bool GetFullScreen() override;
   void SetFullScreen(bool aFullScreen, mozilla::ErrorResult& aError);
-  nsresult SetFullScreen(bool aFullScreen) override;
   void Back(mozilla::ErrorResult& aError);
   void Forward(mozilla::ErrorResult& aError);
   void Home(nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& aError);
   bool Find(const nsAString& aString, bool aCaseSensitive, bool aBackwards,
             bool aWrapAround, bool aWholeWord, bool aSearchInFrames,
             bool aShowDialog, mozilla::ErrorResult& aError);
   uint64_t GetMozPaintCount(mozilla::ErrorResult& aError);
 
@@ -971,20 +893,16 @@ public:
 
   already_AddRefed<nsPIDOMWindowOuter>
   OpenDialog(JSContext* aCx,
              const nsAString& aUrl,
              const nsAString& aName,
              const nsAString& aOptions,
              const mozilla::dom::Sequence<JS::Value>& aExtraArgument,
              mozilla::ErrorResult& aError);
-  nsresult OpenDialog(const nsAString& aUrl, const nsAString& aName,
-                      const nsAString& aOptions,
-                      nsISupports* aExtraArgument,
-                      nsPIDOMWindowOuter** _retval) override;
   nsresult UpdateCommands(const nsAString& anAction, nsISelection* aSel, int16_t aReason) override;
 
   void GetContent(JSContext* aCx,
                   JS::MutableHandle<JSObject*> aRetval,
                   mozilla::dom::CallerType aCallerType,
                   mozilla::ErrorResult& aError);
 
   already_AddRefed<mozilla::dom::Promise>
@@ -1152,19 +1070,16 @@ protected:
   RefPtr<mozilla::dom::WakeLock> mWakeLock;
 
   friend class HashchangeCallback;
   friend class mozilla::dom::BarProp;
 
   // Object Management
   virtual ~nsGlobalWindowInner();
   void CleanUp();
-  void ClearControllers();
-
-  inline void MaybeClearInnerWindow(nsGlobalWindowInner* aExpectedInner);
 
   void FreeInnerObjects();
   nsGlobalWindowInner *CallerInnerWindow();
 
   // Only to be called on an inner window.
   // aDocument must not be null.
   void InnerSetNewDocument(JSContext* aCx, nsIDocument* aDocument);
 
@@ -1176,26 +1091,16 @@ protected:
 
   // Get the parent, returns null if this is a toplevel window
   nsPIDOMWindowOuter* GetParentInternal();
 
 public:
   // popup tracking
   bool IsPopupSpamWindow();
 
-protected:
-  // Window Control Functions
-
-  // Outer windows only.
-  virtual nsresult
-  OpenNoNavigate(const nsAString& aUrl,
-                 const nsAString& aName,
-                 const nsAString& aOptions,
-                 nsPIDOMWindowOuter** _retval) override;
-
 private:
   template<typename Method>
   void CallOnChildren(Method aMethod);
 
   void FreezeInternal();
   void ThawInternal();
 
 public:
@@ -1251,19 +1156,16 @@ public:
   virtual void SetFocusedNode(nsIContent* aNode,
                               uint32_t aFocusMethod = 0,
                               bool aNeedsFocus = false) override;
 
   virtual uint32_t GetFocusMethod() override;
 
   virtual bool ShouldShowFocusRing() override;
 
-  virtual void SetKeyboardIndicators(UIStateChangeType aShowAccelerators,
-                                     UIStateChangeType aShowFocusRings) override;
-
   // Inner windows only.
   void UpdateCanvasFocus(bool aFocusChanged, nsIContent* aNewContent);
 
 public:
   virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() override;
 
 protected:
   static void NotifyDOMWindowDestroyed(nsGlobalWindowInner* aWindow);
@@ -1305,20 +1207,17 @@ protected:
                       mozilla::ErrorResult& aError);
 
 private:
   // Fire the JS engine's onNewGlobalObject hook.  Only used on inner windows.
   void FireOnNewGlobalObject();
 
   void DisconnectEventTargetObjects();
 
-  // nsPIDOMWindow<T> should be able to see these helper methods.
-  friend class nsPIDOMWindow<mozIDOMWindowProxy>;
-  friend class nsPIDOMWindow<mozIDOMWindow>;
-  friend class nsPIDOMWindow<nsISupports>;
+  // nsPIDOMWindow{Inner,Outer} should be able to see these helper methods.
   friend class nsPIDOMWindowInner;
   friend class nsPIDOMWindowOuter;
 
   mozilla::dom::TabGroup* TabGroupInner();
 
   bool IsBackgroundInternal() const;
 
   // NOTE: Chrome Only
@@ -1355,50 +1254,30 @@ public:
   void ResumeIdleRequests();
 
   typedef mozilla::LinkedList<mozilla::dom::IdleRequest> IdleRequests;
   void InsertIdleCallback(mozilla::dom::IdleRequest* aRequest);
 
   void RemoveIdleCallback(mozilla::dom::IdleRequest* aRequest);
 
 protected:
-  // These members are only used on outer window objects. Make sure
-  // you never set any of these on an inner object!
-  bool                          mFullScreen : 1;
-  bool                          mFullscreenMode : 1;
-  bool                          mIsClosed : 1;
-  bool                          mInClose : 1;
-  // mHavePendingClose means we've got a termination function set to
-  // close us when the JS stops executing or that we have a close
-  // event posted.  If this is set, just ignore window.close() calls.
-  bool                          mHavePendingClose : 1;
-  bool                          mHadOriginalOpener : 1;
-  bool                          mOriginalOpenerWasSecureContext : 1;
   bool                          mIsSecureContextIfOpenerIgnored : 1;
-  bool                          mIsPopupSpam : 1;
-
-  // Indicates whether scripts are allowed to close this window.
-  bool                          mBlockScriptedClosingFlag : 1;
 
   // Window offline status. Checked to see if we need to fire offline event
   bool                          mWasOffline : 1;
 
   // Represents whether the inner window's page has had a slow script notice.
   // Only used by inner windows; will always be false for outer windows.
   // This is used to implement Telemetry measures such as SLOW_SCRIPT_PAGE_COUNT.
   bool                          mHasHadSlowScript : 1;
 
   // Track what sorts of events we need to fire when thawed
   bool                          mNotifyIdleObserversIdleOnThaw : 1;
   bool                          mNotifyIdleObserversActiveOnThaw : 1;
 
-  // Indicates whether we're in the middle of creating an initializing
-  // a new inner window object.
-  bool                          mCreatingInnerWindow : 1;
-
   // Fast way to tell if this is a chrome window (without having to QI).
   bool                          mIsChrome : 1;
 
   // Hack to indicate whether a chrome window needs its message manager
   // to be disconnected, since clean up code is shared in the global
   // window superclass.
   bool                          mCleanMessageManager : 1;
 
@@ -1410,63 +1289,39 @@ protected:
   // when true, show focus rings for the current focused content only.
   // This will be reset when another element is focused
   bool                   mShowFocusRingForContent : 1;
 
   // true if tab navigation has occurred for this window. Focus rings
   // should be displayed.
   bool                   mFocusByKeyOccurred : 1;
 
-  // Inner windows only.
   // Indicates whether this window wants gamepad input events
   bool                   mHasGamepad : 1;
 
-  // Inner windows only.
   // Indicates whether this window wants VR events
   bool                   mHasVREvents : 1;
 
-  // Inner windows only.
   // Indicates whether this window wants VRDisplayActivate events
   bool                   mHasVRDisplayActivateEvents : 1;
   nsCheapSet<nsUint32HashKey> mGamepadIndexSet;
   nsRefPtrHashtable<nsUint32HashKey, mozilla::dom::Gamepad> mGamepads;
   bool mHasSeenGamepadInput;
 
-  // whether we've sent the destroy notification for our window id
-  bool                   mNotifiedIDDestroyed : 1;
-  // whether scripts may close the window,
-  // even if "dom.allow_scripts_to_close_windows" is false.
-  bool                   mAllowScriptsToClose : 1;
-
-  bool mTopLevelOuterContentWindow : 1;
-
-  nsCOMPtr<nsIScriptContext>    mContext;
-  nsWeakPtr                     mOpener;
-  nsCOMPtr<nsIControllers>      mControllers;
-
-  // For |window.arguments|, via |openDialog|.
-  nsCOMPtr<nsIArray>            mArguments;
-
-  // Only used in the outer.
-  RefPtr<DialogValueHolder> mReturnValue;
-
   RefPtr<mozilla::dom::Navigator> mNavigator;
   RefPtr<nsScreen>            mScreen;
-  RefPtr<nsDOMWindowList>     mFrames;
-  // All BarProps are inner window only.
+
   RefPtr<mozilla::dom::BarProp> mMenubar;
   RefPtr<mozilla::dom::BarProp> mToolbar;
   RefPtr<mozilla::dom::BarProp> mLocationbar;
   RefPtr<mozilla::dom::BarProp> mPersonalbar;
   RefPtr<mozilla::dom::BarProp> mStatusbar;
   RefPtr<mozilla::dom::BarProp> mScrollbars;
-  RefPtr<nsDOMWindowUtils>      mWindowUtils;
-  nsString                      mStatus;
-  nsString                      mDefaultStatus;
-  RefPtr<nsGlobalWindowObserver> mObserver; // Inner windows only.
+
+  RefPtr<nsGlobalWindowObserver> mObserver;
   RefPtr<mozilla::dom::Crypto>  mCrypto;
   RefPtr<mozilla::dom::U2F> mU2F;
   RefPtr<mozilla::dom::cache::CacheStorage> mCacheStorage;
   RefPtr<mozilla::dom::Console> mConsole;
   RefPtr<mozilla::dom::Worklet> mAudioWorklet;
   RefPtr<mozilla::dom::Worklet> mPaintWorklet;
   // We need to store an nsISupports pointer to this object because the
   // mozilla::dom::External class doesn't exist on b2g and using the type
@@ -1474,23 +1329,21 @@ protected:
   // it wouldn't see the ~External function's declaration.
   nsCOMPtr<nsISupports>         mExternal;
 
   RefPtr<mozilla::dom::MozSelfSupport> mMozSelfSupport;
 
   RefPtr<mozilla::dom::Storage> mLocalStorage;
   RefPtr<mozilla::dom::Storage> mSessionStorage;
 
-  // These member variable are used only on inner windows.
   RefPtr<mozilla::EventListenerManager> mListenerManager;
   RefPtr<mozilla::dom::Location> mLocation;
   RefPtr<nsHistory>           mHistory;
   RefPtr<mozilla::dom::CustomElementRegistry> mCustomElements;
 
-  // These member variables are used on both inner and the outer windows.
   nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
   // mTabChild is only ever populated in the content process.
   nsCOMPtr<nsITabChild>  mTabChild;
 
   uint32_t mSuspendDepth;
   uint32_t mFreezeDepth;
 
   // the method that was used to focus mFocusedNode
@@ -1499,35 +1352,26 @@ protected:
   uint32_t mSerial;
 
   // The current idle request callback handle
   uint32_t mIdleRequestCallbackCounter;
   IdleRequests mIdleRequestCallbacks;
   RefPtr<IdleRequestExecutor> mIdleRequestExecutor;
 
 #ifdef DEBUG
-  bool mSetOpenerWindowCalled;
   nsCOMPtr<nsIURI> mLastOpenedURI;
 #endif
 
   bool mCleanedUp;
 
   nsCOMPtr<nsIDOMOfflineResourceList> mApplicationCache;
 
   using XBLPrototypeHandlerTable = nsJSThingHashtable<nsPtrHashKey<nsXBLPrototypeHandler>, JSObject*>;
   mozilla::UniquePtr<XBLPrototypeHandlerTable> mCachedXBLPrototypeHandlers;
 
-  // mSuspendedDoc is only set on outer windows. It's useful when we get matched
-  // EnterModalState/LeaveModalState calls, in which case the outer window is
-  // responsible for unsuspending events on the document. If we don't (for
-  // example, if the outer window is closed before the LeaveModalState call),
-  // then the inner window whose mDoc is our mSuspendedDoc is responsible for
-  // unsuspending it.
-  nsCOMPtr<nsIDocument> mSuspendedDoc;
-
   RefPtr<mozilla::dom::IDBFactory> mIndexedDB;
 
   // This counts the number of windows that have been opened in rapid succession
   // (i.e. within dom.successive_dialog_time_limit of each other). It is reset
   // to 0 once a dialog is opened after dom.successive_dialog_time_limit seconds
   // have elapsed without any other dialogs.
   uint32_t                      mDialogAbuseCount;
 
@@ -1545,63 +1389,51 @@ protected:
 
   nsTArray<uint32_t> mEnabledSensors;
 
 #if defined(MOZ_WIDGET_ANDROID)
   mozilla::UniquePtr<mozilla::dom::WindowOrientationObserver> mOrientationChangeObserver;
 #endif
 
 #ifdef MOZ_WEBSPEECH
-  // mSpeechSynthesis is only used on inner windows.
   RefPtr<mozilla::dom::SpeechSynthesis> mSpeechSynthesis;
 #endif
 
-#ifdef DEBUG
-  // This member is used in the debug only assertions in TabGroup()
-  // to catch cyclic parent/opener trees and not overflow the stack.
-  bool mIsValidatingTabGroup;
-#endif
-
   // This is the CC generation the last time we called CanSkip.
   uint32_t mCanSkipCCGeneration;
 
   // The VR Displays for this window
   nsTArray<RefPtr<mozilla::dom::VRDisplay>> mVRDisplays;
 
   RefPtr<mozilla::dom::VREventObserver> mVREventObserver;
 
-  // When non-zero, the document should receive a vrdisplayactivate event
-  // after loading.  The value is the ID of the VRDisplay that content should
-  // begin presentation on.
-  uint32_t mAutoActivateVRDisplayID; // Outer windows only
-  int64_t mBeforeUnloadListenerCount; // Inner windows only
+  int64_t mBeforeUnloadListenerCount;
 
   RefPtr<mozilla::dom::IntlUtils> mIntlUtils;
 
   mozilla::UniquePtr<mozilla::dom::ClientSource> mClientSource;
 
   static InnerWindowByIdTable* sInnerWindowsById;
 
   // Members in the mChromeFields member should only be used in chrome windows.
   // All accesses to this field should be guarded by a check of mIsChrome.
   struct ChromeFields {
     ChromeFields()
       : mGroupMessageManagers(1)
     {}
 
-    nsCOMPtr<nsIBrowserDOMWindow> mBrowserDOMWindow;
     nsCOMPtr<nsIMessageBroadcaster> mMessageManager;
     nsInterfaceHashtable<nsStringHashKey, nsIMessageBroadcaster> mGroupMessageManagers;
-    // A weak pointer to the nsPresShell that we are doing fullscreen for.
-    // The pointer being set indicates we've set the IsInFullscreenChange
-    // flag on this pres shell.
-    nsWeakPtr mFullscreenPresShell;
-    nsCOMPtr<mozIDOMWindowProxy> mOpenerForInitialContentBrowser;
   } mChromeFields;
 
+  // These fields are used by the inner and outer windows to prevent
+  // programatically moving the window while the mouse is down.
+  static bool sMouseDown;
+  static bool sDragServiceDisabled;
+
   friend class nsDOMScriptableHelper;
   friend class nsDOMWindowUtils;
   friend class mozilla::dom::PostMessageEvent;
   friend class DesktopNotification;
   friend class mozilla::dom::TimeoutManager;
   friend class IdleRequestExecutor;
   friend class nsGlobalWindowOuter;
 };
@@ -1647,42 +1479,34 @@ nsGlobalWindowInner::GetScriptableTopInt
 
 inline nsIScriptContext*
 nsGlobalWindowInner::GetContextInternal()
 {
   if (mOuterWindow) {
     return GetOuterWindowInternal()->mContext;
   }
 
-  return mContext;
+  return nullptr;
 }
 
 inline nsGlobalWindowOuter*
 nsGlobalWindowInner::GetOuterWindowInternal() const
 {
   return nsGlobalWindowOuter::Cast(GetOuterWindow());
 }
 
 inline bool
 nsGlobalWindowInner::IsPopupSpamWindow()
 {
-  if (IsInnerWindow() && !mOuterWindow) {
+  if (!mOuterWindow) {
     return false;
   }
 
   return GetOuterWindowInternal()->mIsPopupSpam;
 }
 
 inline bool
 nsGlobalWindowInner::IsFrame()
 {
   return GetParentInternal() != nullptr;
 }
 
-inline void
-nsGlobalWindowInner::MaybeClearInnerWindow(nsGlobalWindowInner* aExpectedInner)
-{
-  if(mInnerWindow == aExpectedInner->AsInner()) {
-    mInnerWindow = nullptr;
-  }
-}
-
 #endif /* nsGlobalWindowInner_h___ */
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -1,119 +1,340 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "nsGlobalWindow.h"
+
+#include <algorithm>
+
+#include "mozilla/MemoryReporting.h"
+
+// Local Includes
+#include "Navigator.h"
+#include "nsContentSecurityManager.h"
+#include "nsScreen.h"
+#include "nsHistory.h"
+#include "nsDOMNavigationTiming.h"
+#include "nsIDOMStorageManager.h"
+#include "mozilla/dom/LocalStorage.h"
+#include "mozilla/dom/Storage.h"
+#include "mozilla/dom/IdleRequest.h"
+#include "mozilla/dom/Performance.h"
+#include "mozilla/dom/StorageEvent.h"
+#include "mozilla/dom/StorageEventBinding.h"
+#include "mozilla/dom/StorageNotifierService.h"
+#include "mozilla/dom/StorageUtils.h"
+#include "mozilla/dom/Timeout.h"
+#include "mozilla/dom/TimeoutHandler.h"
+#include "mozilla/dom/TimeoutManager.h"
+#include "mozilla/IntegerPrintfMacros.h"
+#if defined(MOZ_WIDGET_ANDROID)
+#include "mozilla/dom/WindowOrientationObserver.h"
+#endif
+#include "nsDOMOfflineResourceList.h"
+#include "nsError.h"
+#include "nsIIdleService.h"
+#include "nsISizeOfEventTarget.h"
+#include "nsDOMJSUtils.h"
+#include "nsArrayUtils.h"
+#include "nsIDOMWindowCollection.h"
+#include "nsDOMWindowList.h"
+#include "mozilla/dom/WakeLock.h"
+#include "mozilla/dom/power/PowerManagerService.h"
+#include "nsIDocShellTreeOwner.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsIPermissionManager.h"
+#include "nsIScriptContext.h"
+#include "nsIScriptTimeoutHandler.h"
+#include "nsITimeoutHandler.h"
+#include "nsIController.h"
+#include "nsScriptNameSpaceManager.h"
+#include "nsISlowScriptDebug.h"
+#include "nsWindowMemoryReporter.h"
+#include "nsWindowSizes.h"
+#include "WindowNamedPropertiesHandler.h"
+#include "nsFrameSelection.h"
+#include "nsNetUtil.h"
+#include "nsVariant.h"
+#include "nsPrintfCString.h"
+#include "mozilla/intl/LocaleService.h"
+#include "WindowDestroyedEvent.h"
+
+// Helper Classes
+#include "nsJSUtils.h"
+#include "jsapi.h"              // for JSAutoRequest
+#include "jswrapper.h"
+#include "nsCharSeparatedTokenizer.h"
+#include "nsReadableUtils.h"
+#include "nsDOMClassInfo.h"
+#include "nsJSEnvironment.h"
+#include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/Likely.h"
+#include "mozilla/Sprintf.h"
+#include "mozilla/Unused.h"
+
+// Other Classes
+#include "mozilla/dom/BarProps.h"
+#include "nsContentCID.h"
+#include "nsLayoutStatics.h"
+#include "nsCCUncollectableMarker.h"
+#include "mozilla/dom/workers/Workers.h"
+#include "mozilla/dom/ToJSValue.h"
+#include "nsJSPrincipals.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Debug.h"
+#include "mozilla/EventListenerManager.h"
+#include "mozilla/EventStates.h"
+#include "mozilla/MouseEvents.h"
+#include "mozilla/ProcessHangMonitor.h"
+#include "mozilla/ThrottledEventQueue.h"
+#include "AudioChannelService.h"
+#include "nsAboutProtocolUtils.h"
+#include "nsCharTraits.h" // NS_IS_HIGH/LOW_SURROGATE
+#include "PostMessageEvent.h"
+#include "mozilla/dom/DocGroup.h"
+#include "mozilla/dom/TabGroup.h"
+
+// Interfaces Needed
+#include "nsIFrame.h"
+#include "nsCanvasFrame.h"
+#include "nsIWidget.h"
+#include "nsIWidgetListener.h"
+#include "nsIBaseWindow.h"
+#include "nsIDeviceSensors.h"
+#include "nsIContent.h"
+#include "nsIDocShell.h"
+#include "nsIDocCharset.h"
+#include "nsIDocument.h"
+#include "Crypto.h"
+#include "nsIDOMDocument.h"
+#include "nsIDOMElement.h"
+#include "nsIDOMEvent.h"
+#include "nsIDOMOfflineResourceList.h"
+#include "nsDOMString.h"
+#include "nsIEmbeddingSiteWindow.h"
+#include "nsThreadUtils.h"
+#include "nsILoadContext.h"
+#include "nsIPresShell.h"
+#include "nsIScrollableFrame.h"
+#include "nsView.h"
+#include "nsViewManager.h"
+#include "nsISelectionController.h"
+#include "nsISelection.h"
+#include "nsIPrompt.h"
+#include "nsIPromptService.h"
+#include "nsIPromptFactory.h"
+#include "nsIAddonPolicyService.h"
+#include "nsIWritablePropertyBag2.h"
+#include "nsIWebNavigation.h"
+#include "nsIWebBrowserChrome.h"
+#include "nsIWebBrowserFind.h"  // For window.find()
+#include "nsIWindowMediator.h"  // For window.find()
+#include "nsComputedDOMStyle.h"
+#include "nsDOMCID.h"
+#include "nsDOMWindowUtils.h"
+#include "nsIWindowWatcher.h"
+#include "nsPIWindowWatcher.h"
+#include "nsIContentViewer.h"
+#include "nsIScriptError.h"
+#include "nsIControllers.h"
+#include "nsIControllerContext.h"
+#include "nsGlobalWindowCommands.h"
+#include "nsQueryObject.h"
+#include "nsContentUtils.h"
+#include "nsCSSProps.h"
+#include "nsIDOMFileList.h"
+#include "nsIURIFixup.h"
+#ifndef DEBUG
+#include "nsIAppStartup.h"
+#include "nsToolkitCompsCID.h"
+#endif
+#include "nsCDefaultURIFixup.h"
+#include "mozilla/EventDispatcher.h"
+#include "mozilla/EventStateManager.h"
+#include "nsIObserverService.h"
+#include "nsFocusManager.h"
+#include "nsIXULWindow.h"
+#include "nsITimedChannel.h"
+#include "nsServiceManagerUtils.h"
+#ifdef MOZ_XUL
+#include "nsIDOMXULControlElement.h"
+#include "nsMenuPopupFrame.h"
+#endif
+#include "mozilla/dom/CustomEvent.h"
+#include "nsIJARChannel.h"
+#include "nsIScreenManager.h"
+#include "nsIEffectiveTLDService.h"
+
+#include "xpcprivate.h"
+
+#ifdef NS_PRINTING
+#include "nsIPrintSettings.h"
+#include "nsIPrintSettingsService.h"
+#include "nsIWebBrowserPrint.h"
+#endif
+
+#include "nsWindowRoot.h"
+#include "nsNetCID.h"
+#include "nsIArray.h"
+
+// XXX An unfortunate dependency exists here (two XUL files).
+#include "nsIDOMXULDocument.h"
+#include "nsIDOMXULCommandDispatcher.h"
+
+#include "nsBindingManager.h"
+#include "nsXBLService.h"
+
+// used for popup blocking, needs to be converted to something
+// belonging to the back-end like nsIContentPolicy
+#include "nsIPopupWindowManager.h"
+
+#include "nsIDragService.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/Selection.h"
+#include "nsFrameLoader.h"
+#include "nsISupportsPrimitives.h"
+#include "nsXPCOMCID.h"
+#include "mozilla/Logging.h"
+#include "prenv.h"
+
+#include "mozilla/dom/IDBFactory.h"
+#include "mozilla/dom/MessageChannel.h"
+#include "mozilla/dom/Promise.h"
+
+#include "mozilla/dom/Gamepad.h"
+#include "mozilla/dom/GamepadManager.h"
+
+#include "gfxVR.h"
+#include "mozilla/dom/VRDisplay.h"
+#include "mozilla/dom/VRDisplayEvent.h"
+#include "mozilla/dom/VRDisplayEventBinding.h"
+#include "mozilla/dom/VREventObserver.h"
+
+#include "nsRefreshDriver.h"
+#include "Layers.h"
+
+#include "mozilla/AddonPathService.h"
+#include "mozilla/BasePrincipal.h"
+#include "mozilla/Services.h"
+#include "mozilla/Telemetry.h"
+#include "mozilla/dom/Location.h"
+#include "nsHTMLDocument.h"
+#include "nsWrapperCacheInlines.h"
+#include "mozilla/DOMEventTargetHelper.h"
+#include "prrng.h"
+#include "nsSandboxFlags.h"
+#include "TimeChangeObserver.h"
+#include "mozilla/dom/AudioContext.h"
+#include "mozilla/dom/BrowserElementDictionariesBinding.h"
+#include "mozilla/dom/cache/CacheStorage.h"
+#include "mozilla/dom/Console.h"
+#include "mozilla/dom/Fetch.h"
+#include "mozilla/dom/FunctionBinding.h"
+#include "mozilla/dom/HashChangeEvent.h"
+#include "mozilla/dom/IntlUtils.h"
+#include "mozilla/dom/MozSelfSupportBinding.h"
+#include "mozilla/dom/PopStateEvent.h"
+#include "mozilla/dom/PopupBlockedEvent.h"
+#include "mozilla/dom/PrimitiveConversions.h"
+#include "mozilla/dom/WindowBinding.h"
+#include "nsITabChild.h"
+#include "mozilla/dom/MediaQueryList.h"
+#include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/dom/NavigatorBinding.h"
+#include "mozilla/dom/ImageBitmap.h"
+#include "mozilla/dom/ImageBitmapBinding.h"
+#include "mozilla/dom/ServiceWorkerRegistration.h"
+#include "mozilla/dom/U2F.h"
+#include "mozilla/dom/WebIDLGlobalNameHash.h"
+#include "mozilla/dom/Worklet.h"
+#ifdef HAVE_SIDEBAR
+#include "mozilla/dom/ExternalBinding.h"
+#endif
+
+#ifdef MOZ_WEBSPEECH
+#include "mozilla/dom/SpeechSynthesis.h"
+#endif
+
+// Apple system headers seem to have a check() macro.  <sigh>
+#ifdef check
+class nsIScriptTimeoutHandler;
+#undef check
+#endif // check
+#include "AccessCheck.h"
+
+#ifdef ANDROID
+#include <android/log.h>
+#endif
+
+#ifdef XP_WIN
+#include <process.h>
+#define getpid _getpid
+#else
+#include <unistd.h> // for getpid()
+#endif
+
+using namespace mozilla;
+using namespace mozilla::dom;
+using namespace mozilla::dom::ipc;
+using mozilla::BasePrincipal;
+using mozilla::OriginAttributes;
+using mozilla::TimeStamp;
+
 #define FORWARD_TO_INNER(method, args, err_rval)                        \
   PR_BEGIN_MACRO                                                        \
-  MOZ_RELEASE_ASSERT(IsOuterWindow());                                  \
   if (!mInnerWindow) {                                                  \
     NS_WARNING("No inner window available!");                           \
     return err_rval;                                                    \
   }                                                                     \
   return GetCurrentInnerWindowInternal()->method args;                  \
   PR_END_MACRO
 
 #define FORWARD_TO_INNER_VOID(method, args)                             \
   PR_BEGIN_MACRO                                                        \
-  MOZ_RELEASE_ASSERT(IsOuterWindow());                                  \
   if (!mInnerWindow) {                                                  \
     NS_WARNING("No inner window available!");                           \
     return;                                                             \
   }                                                                     \
   GetCurrentInnerWindowInternal()->method args;                         \
   return;                                                               \
   PR_END_MACRO
 
 // Same as FORWARD_TO_INNER, but this will create a fresh inner if an
 // inner doesn't already exists.
 #define FORWARD_TO_INNER_CREATE(method, args, err_rval)                 \
   PR_BEGIN_MACRO                                                        \
-  MOZ_RELEASE_ASSERT(IsOuterWindow());                                  \
   if (!mInnerWindow) {                                                  \
     if (mIsClosed) {                                                    \
       return err_rval;                                                  \
     }                                                                   \
     nsCOMPtr<nsIDocument> kungFuDeathGrip = GetDoc();                   \
     ::mozilla::Unused << kungFuDeathGrip;                               \
     if (!mInnerWindow) {                                                \
       return err_rval;                                                  \
     }                                                                   \
   }                                                                     \
   return GetCurrentInnerWindowInternal()->method args;                  \
   PR_END_MACRO
 
+#define DEFAULT_HOME_PAGE "www.mozilla.org"
+#define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
+
+static LazyLogModule gDOMLeakPRLogOuter("DOMLeakOuter");
+
+static int32_t              gOpenPopupSpamCount               = 0;
+
 nsGlobalWindowOuter::OuterWindowByIdTable *nsGlobalWindowOuter::sOuterWindowsById = nullptr;
 
-static already_AddRefed<nsIVariant>
-CreateVoidVariant()
-{
-  RefPtr<nsVariantCC> writable = new nsVariantCC();
-  writable->SetAsVoid();
-  return writable.forget();
-}
-
-nsresult
-DialogValueHolder::Get(nsIPrincipal* aSubject, nsIVariant** aResult)
-{
-  nsCOMPtr<nsIVariant> result;
-  if (aSubject->SubsumesConsideringDomain(mOrigin)) {
-    result = mValue;
-  } else {
-    result = CreateVoidVariant();
-  }
-  result.forget(aResult);
-  return NS_OK;
-}
-
-void
-DialogValueHolder::Get(JSContext* aCx, JS::Handle<JSObject*> aScope,
-                       nsIPrincipal* aSubject,
-                       JS::MutableHandle<JS::Value> aResult,
-                       mozilla::ErrorResult& aError)
-{
-  if (aSubject->Subsumes(mOrigin)) {
-    aError = nsContentUtils::XPConnect()->VariantToJS(aCx, aScope,
-                                                      mValue, aResult);
-  } else {
-    aResult.setUndefined();
-  }
-}
-void
-nsGlobalWindowOuter::RemoveIdleCallback(mozilla::dom::IdleRequest* aRequest)
-{
-  AssertIsOnMainThread();
-
-  if (aRequest->HasTimeout()) {
-    mTimeoutManager->ClearTimeout(aRequest->GetTimeoutHandle(),
-                                  Timeout::Reason::eIdleCallbackTimeout);
-  }
-
-  aRequest->removeFrom(mIdleRequestCallbacks);
-  aRequest->Release();
-}
-
-nsresult
-nsGlobalWindowOuter::RunIdleRequest(IdleRequest* aRequest,
-                                    DOMHighResTimeStamp aDeadline,
-                                    bool aDidTimeout)
-{
-  AssertIsOnMainThread();
-  RefPtr<IdleRequest> request(aRequest);
-  RemoveIdleCallback(request);
-  return request->IdleRun(AsInner(), aDeadline, aDidTimeout);
-}
-
-bool
-nsGlobalWindowOuter::IsBackgroundInternal() const
-{
-  return !mOuterWindow || mOuterWindow->IsBackground();
-}
+// CIDs
+static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
 
 /* static */
 nsPIDOMWindowOuter*
 nsPIDOMWindowOuter::GetFromCurrentInner(nsPIDOMWindowInner* aInner)
 {
   if (!aInner) {
     return nullptr;
   }
@@ -121,26 +342,16 @@ nsPIDOMWindowOuter::GetFromCurrentInner(
   nsPIDOMWindowOuter* outer = aInner->GetOuterWindow();
   if (!outer || outer->GetCurrentInnerWindow() != aInner) {
     return nullptr;
   }
 
   return outer;
 }
 
-// DialogValueHolder CC goop.
-NS_IMPL_CYCLE_COLLECTION(DialogValueHolder, mValue)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DialogValueHolder)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(DialogValueHolder)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(DialogValueHolder)
-
 //*****************************************************************************
 // nsOuterWindowProxy: Outer Window Proxy
 //*****************************************************************************
 
 class nsOuterWindowProxy : public js::Wrapper
 {
 public:
   constexpr nsOuterWindowProxy() : js::Wrapper(0) { }
@@ -214,17 +425,16 @@ public:
 
   static const nsOuterWindowProxy singleton;
 
 protected:
   static nsGlobalWindowOuter* GetOuterWindow(JSObject *proxy)
   {
     nsGlobalWindowOuter* outerWindow = nsGlobalWindowOuter::FromSupports(
       static_cast<nsISupports*>(js::GetProxyReservedSlot(proxy, 0).toPrivate()));
-    MOZ_ASSERT_IF(outerWindow, outerWindow->IsOuterWindow());
     return outerWindow;
   }
 
   // False return value means we threw an exception.  True return value
   // but false "found" means we didn't have a subframe at that index.
   bool GetSubframeWindow(JSContext *cx, JS::Handle<JSObject*> proxy,
                          JS::Handle<jsid> id,
                          JS::MutableHandle<JS::Value> vp,
@@ -533,17 +743,16 @@ nsOuterWindowProxy::GetSubframeWindow(JS
                                       JS::Handle<jsid> id) const
 {
   uint32_t index = GetArrayIndexFromId(cx, id);
   if (!IsArrayIndex(index)) {
     return nullptr;
   }
 
   nsGlobalWindowOuter* win = GetOuterWindow(proxy);
-  MOZ_ASSERT(win->IsOuterWindow());
   return win->IndexedGetterOuter(index);
 }
 
 bool
 nsOuterWindowProxy::AppendIndexedPropertyNames(JSContext *cx, JSObject *proxy,
                                                JS::AutoIdVector &props) const
 {
   uint32_t length = GetOuterWindow(proxy)->Length();
@@ -627,51 +836,30 @@ nsGlobalWindowOuter::nsGlobalWindowOuter
     mIsClosed(false),
     mInClose(false),
     mHavePendingClose(false),
     mHadOriginalOpener(false),
     mOriginalOpenerWasSecureContext(false),
     mIsPopupSpam(false),
     mBlockScriptedClosingFlag(false),
     mWasOffline(false),
-    mHasHadSlowScript(false),
-    mNotifyIdleObserversIdleOnThaw(false),
-    mNotifyIdleObserversActiveOnThaw(false),
     mCreatingInnerWindow(false),
     mIsChrome(false),
-    mCleanMessageManager(false),
-    mNeedsFocus(true),
-    mHasFocus(false),
-    mShowFocusRingForContent(false),
-    mFocusByKeyOccurred(false),
-    mHasGamepad(false),
-    mHasVREvents(false),
-    mHasVRDisplayActivateEvents(false),
-    mHasSeenGamepadInput(false),
-    mNotifiedIDDestroyed(false),
     mAllowScriptsToClose(false),
     mTopLevelOuterContentWindow(false),
-    mSuspendDepth(0),
-    mFreezeDepth(0),
-    mFocusMethod(0),
     mSerial(0),
-    mIdleRequestCallbackCounter(1),
-    mIdleRequestExecutor(nullptr),
 #ifdef DEBUG
     mSetOpenerWindowCalled(false),
 #endif
     mCleanedUp(false),
-    mDialogAbuseCount(0),
-    mAreDialogsEnabled(true),
 #ifdef DEBUG
     mIsValidatingTabGroup(false),
 #endif
     mCanSkipCCGeneration(0),
-    mAutoActivateVRDisplayID(0),
-    mBeforeUnloadListenerCount(0)
+    mAutoActivateVRDisplayID(0)
 {
   AssertIsOnMainThread();
 
   nsLayoutStatics::AddRef();
 
   // Initialize the PRCList (this).
   PR_INIT_CLIST(this);
 
@@ -685,45 +873,30 @@ nsGlobalWindowOuter::nsGlobalWindowOuter
       mTabChild = docShell->GetTabChild();
     }
   }
 
   // We could have failed the first time through trying
   // to create the entropy collector, so we should
   // try to get one until we succeed.
 
-  gRefCnt++;
-
-  EnsurePrefCaches();
-
-  if (gDumpFile == nullptr) {
-    nsAutoCString fname;
-    Preferences::GetCString("browser.dom.window.dump.file", fname);
-    if (!fname.IsEmpty()) {
-      // If this fails to open, Dump() knows to just go to stdout on null.
-      gDumpFile = fopen(fname.get(), "wb+");
-    } else {
-      gDumpFile = stdout;
-    }
-  }
-
-  mSerial = ++gSerialCounter;
+  mSerial = nsContentUtils::InnerOrOuterWindowCreated();
 
 #ifdef DEBUG
   if (!PR_GetEnv("MOZ_QUIET")) {
     printf_stderr("++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n",
-                  gRefCnt,
+                  nsContentUtils::GetCurrentInnerOrOuterWindowCount(),
                   static_cast<void*>(ToCanonicalSupports(this)),
                   getpid(),
-                  gSerialCounter,
+                  mSerial,
                   nullptr);
   }
 #endif
 
-  MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug,
+  MOZ_LOG(gDOMLeakPRLogOuter, LogLevel::Debug,
           ("DOMWINDOW %p created outer=nullptr", this));
 
   // Add ourselves to the outer windows list.
   MOZ_ASSERT(sOuterWindowsById, "Outer Windows hash table must be created!");
 
   // |this| is an outer window, add to the outer windows list.
   MOZ_ASSERT(!sOuterWindowsById->Get(mWindowID),
              "This window shouldn't be in the hash table yet!");
@@ -745,72 +918,57 @@ nsGlobalWindowOuter::AssertIsOnMainThrea
 #endif // DEBUG
 
 /* static */
 void
 nsGlobalWindowOuter::Init()
 {
   AssertIsOnMainThread();
 
-  NS_ASSERTION(gDOMLeakPRLog, "gDOMLeakPRLog should have been initialized!");
+  NS_ASSERTION(gDOMLeakPRLogOuter, "gDOMLeakPRLogOuter should have been initialized!");
 
   sOuterWindowsById = new OuterWindowByIdTable();
 }
 
 nsGlobalWindowOuter::~nsGlobalWindowOuter()
 {
   AssertIsOnMainThread();
 
-  if (IsChromeWindow()) {
-    MOZ_ASSERT(mCleanMessageManager,
-              "chrome windows may always disconnect the msg manager");
-
-    DisconnectAndClearGroupMessageManagers();
-
-    if (mChromeFields.mMessageManager) {
-      static_cast<nsFrameMessageManager *>(
-        mChromeFields.mMessageManager.get())->Disconnect();
-    }
-
-    mCleanMessageManager = false;
-  }
-
   if (sOuterWindowsById) {
     MOZ_ASSERT(sOuterWindowsById->Get(mWindowID),
                 "This window should be in the hash table");
     sOuterWindowsById->Remove(mWindowID);
   }
 
-  --gRefCnt;
+  nsContentUtils::InnerOrOuterWindowDestroyed();
 
 #ifdef DEBUG
   if (!PR_GetEnv("MOZ_QUIET")) {
     nsAutoCString url;
     if (mLastOpenedURI) {
       url = mLastOpenedURI->GetSpecOrDefault();
 
       // Data URLs can be very long, so truncate to avoid flooding the log.
       const uint32_t maxURLLength = 1000;
       if (url.Length() > maxURLLength) {
         url.Truncate(maxURLLength);
       }
     }
 
-    nsGlobalWindowOuter* outer = nsGlobalWindowOuter::Cast(mOuterWindow);
     printf_stderr("--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = %s]\n",
-                  gRefCnt,
+                  nsContentUtils::GetCurrentInnerOrOuterWindowCount(),
                   static_cast<void*>(ToCanonicalSupports(this)),
                   getpid(),
                   mSerial,
-                  static_cast<void*>(ToCanonicalSupports(outer)),
+                  nullptr,
                   url.get());
   }
 #endif
 
-  MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug, ("DOMWINDOW %p destroyed", this));
+  MOZ_LOG(gDOMLeakPRLogOuter, LogLevel::Debug, ("DOMWINDOW %p destroyed", this));
 
   JSObject *proxy = GetWrapperMaybeDead();
   if (proxy) {
     js::SetProxyReservedSlot(proxy, 0, js::PrivateValue(nullptr));
   }
 
   // An outer window is destroyed with inner windows still possibly
   // alive, iterate through the inner windows and null out their
@@ -844,160 +1002,82 @@ nsGlobalWindowOuter::~nsGlobalWindowOute
 }
 
 // static
 void
 nsGlobalWindowOuter::ShutDown()
 {
   AssertIsOnMainThread();
 
-  if (gDumpFile && gDumpFile != stdout) {
-    fclose(gDumpFile);
-  }
-  gDumpFile = nullptr;
-
   delete sOuterWindowsById;
   sOuterWindowsById = nullptr;
 }
 
-// static
-void
-nsGlobalWindowOuter::CleanupCachedXBLHandlers()
-{
-  if (mCachedXBLPrototypeHandlers &&
-      mCachedXBLPrototypeHandlers->Count() > 0) {
-    mCachedXBLPrototypeHandlers->Clear();
-  }
-}
-
 void
 nsGlobalWindowOuter::MaybeForgiveSpamCount()
 {
   if (IsPopupSpamWindow()) {
     SetIsPopupSpamWindow(false);
   }
 }
 
 void
 nsGlobalWindowOuter::SetIsPopupSpamWindow(bool aIsPopupSpam)
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   mIsPopupSpam = aIsPopupSpam;
   if (aIsPopupSpam) {
     ++gOpenPopupSpamCount;
   } else {
     --gOpenPopupSpamCount;
     NS_ASSERTION(gOpenPopupSpamCount >= 0,
                  "Unbalanced decrement of gOpenPopupSpamCount");
   }
 }
 
 void
 nsGlobalWindowOuter::DropOuterWindowDocs()
 {
-  MOZ_ASSERT(IsOuterWindow());
   MOZ_ASSERT_IF(mDoc, !mDoc->EventHandlingSuppressed());
   mDoc = nullptr;
   mSuspendedDoc = nullptr;
 }
 
 void
 nsGlobalWindowOuter::CleanUp()
 {
   // Guarantee idempotence.
   if (mCleanedUp)
     return;
   mCleanedUp = true;
 
   StartDying();
 
-  MOZ_RELEASE_ASSERT(!mObserver, "mObserver should only be set on the inner window");
-
-  if (mNavigator) {
-    mNavigator->Invalidate();
-    mNavigator = nullptr;
-  }
-
-  mScreen = nullptr;
-  mMenubar = nullptr;
-  mToolbar = nullptr;
-  mLocationbar = nullptr;
-  mPersonalbar = nullptr;
-  mStatusbar = nullptr;
-  mScrollbars = nullptr;
-  mHistory = nullptr;
-  mCustomElements = nullptr;
   mFrames = nullptr;
   mWindowUtils = nullptr;
-  mApplicationCache = nullptr;
-  mIndexedDB = nullptr;
-
-  mConsole = nullptr;
-
-  mAudioWorklet = nullptr;
-  mPaintWorklet = nullptr;
-
-  mExternal = nullptr;
-
-  mMozSelfSupport = nullptr;
-
-  mPerformance = nullptr;
-
-#ifdef MOZ_WEBSPEECH
-  mSpeechSynthesis = nullptr;
-#endif
-
-#if defined(MOZ_WIDGET_ANDROID)
-  mOrientationChangeObserver = nullptr;
-#endif
 
   ClearControllers();
 
   mOpener = nullptr;             // Forces Release
   if (mContext) {
     mContext = nullptr;            // Forces Release
   }
   mChromeEventHandler = nullptr; // Forces Release
   mParentTarget = nullptr;
 
   nsGlobalWindowInner* inner = GetCurrentInnerWindowInternal();
   if (inner) {
     inner->CleanUp();
   }
 
-  MOZ_ASSERT(!mHasGamepad);
-  MOZ_ASSERT(!mHasVREvents);
-  MOZ_ASSERT(!mHasVRDisplayActivateEvents);
-
-  if (mCleanMessageManager) {
-    MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned");
-    if (mChromeFields.mMessageManager) {
-      static_cast<nsFrameMessageManager*>(
-        mChromeFields.mMessageManager.get())->Disconnect();
-    }
-  }
-
   mArguments = nullptr;
 
-  CleanupCachedXBLHandlers();
-
-  for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
-    mAudioContexts[i]->Shutdown();
-  }
-  mAudioContexts.Clear();
-
   if (mIdleTimer) {
     mIdleTimer->Cancel();
     mIdleTimer = nullptr;
   }
-
-  mServiceWorkerRegistrationTable.Clear();
-
-  mIntlUtils = nullptr;
 }
 
 void
 nsGlobalWindowOuter::ClearControllers()
 {
   if (mControllers) {
     uint32_t count;
     mControllers->GetControllerCount(&count);
@@ -1028,17 +1108,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)
   if (aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter))) {
     foundInterface = static_cast<nsPIDOMWindowOuter*>(this);
   } else
-  if (aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)) && IsOuterWindow()) {
+  if (aIID.Equals(NS_GET_IID(mozIDOMWindowProxy))) {
     foundInterface = static_cast<mozIDOMWindowProxy*>(this);
   } else
   if (aIID.Equals(NS_GET_IID(nsIDOMChromeWindow)) && IsChromeWindow()) {
     foundInterface = static_cast<nsIDOMChromeWindow*>(this);
   } else
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
 NS_INTERFACE_MAP_END
@@ -1048,29 +1128,19 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobal
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGlobalWindowOuter)
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindowOuter)
   if (tmp->IsBlackForCC(false)) {
     if (nsCCUncollectableMarker::InGeneration(tmp->mCanSkipCCGeneration)) {
       return true;
     }
     tmp->mCanSkipCCGeneration = nsCCUncollectableMarker::sGeneration;
-    if (tmp->mCachedXBLPrototypeHandlers) {
-      for (auto iter = tmp->mCachedXBLPrototypeHandlers->Iter();
-           !iter.Done();
-           iter.Next()) {
-        iter.Data().exposeToActiveJS();
-      }
-    }
     if (EventListenerManager* elm = tmp->GetExistingListenerManager()) {
       elm->MarkForCC();
     }
-    if (tmp->mTimeoutManager) {
-      tmp->mTimeoutManager->UnmarkGrayTimers();
-    }
     return true;
   }
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGlobalWindowOuter)
   return tmp->IsBlackForCC(true);
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
 
@@ -1082,212 +1152,82 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalW
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowOuter)
   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
     char name[512];
     nsAutoCString uri;
     if (tmp->mDoc && tmp->mDoc->GetDocumentURI()) {
       uri = tmp->mDoc->GetDocumentURI()->GetSpecOrDefault();
     }
-    SprintfLiteral(name, "nsGlobalWindowOuter # %" PRIu64 " %s %s", tmp->mWindowID,
-                   tmp->IsInnerWindow() ? "inner" : "outer", uri.get());
+    SprintfLiteral(name, "nsGlobalWindowOuter # %" PRIu64 " outer %s", tmp->mWindowID,
+                   uri.get());
     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
   } else {
     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindowOuter, tmp->mRefCnt.get())
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArguments)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReturnValue)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
-
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
-
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerRegistrationTable)
-
-#ifdef MOZ_WEBSPEECH
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSpeechSynthesis)
-#endif
-
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOuterWindow)
-
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTopInnerWindow)
-
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)
-
-  if (tmp->mTimeoutManager) {
-    tmp->mTimeoutManager->ForEachUnorderedTimeout([&cb](Timeout* timeout) {
-      cb.NoteNativeChild(timeout, NS_CYCLE_COLLECTION_PARTICIPANT(Timeout));
-    });
-  }
-
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHistory)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCustomElements)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStorage)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStorage)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mApplicationCache)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuspendedDoc)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChild)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleService)
 
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleRequestExecutor)
-  for (IdleRequest* request : tmp->mIdleRequestCallbacks) {
-    cb.NoteNativeChild(request, NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest));
-  }
-
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleObservers)
 
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepads)
-
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDisplays)
-
   // Traverse stuff from nsPIDOMWindow
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameElement)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedNode)
-
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMenubar)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mToolbar)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocationbar)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPersonalbar)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusbar)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScrollbars)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mU2F)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioWorklet)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaintWorklet)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExternal)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMozSelfSupport)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOpenerForInitialContentBrowser)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)
 
   tmp->TraverseHostObjectURIs(cb);
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mBrowserDOMWindow)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mMessageManager)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mGroupMessageManagers)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mOpenerForInitialContentBrowser)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowOuter)
-  tmp->CleanupCachedXBLHandlers();
-
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mArguments)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mReturnValue)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
-
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
-
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mServiceWorkerRegistrationTable)
-
-#ifdef MOZ_WEBSPEECH
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mSpeechSynthesis)
-#endif
-
-  if (tmp->mListenerManager) {
-    tmp->mListenerManager->Disconnect();
-    NS_IMPL_CYCLE_COLLECTION_UNLINK(mListenerManager)
-  }
-
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mTopInnerWindow)
-
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mHistory)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCustomElements)
+
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStorage)
-  if (tmp->mApplicationCache) {
-    static_cast<nsDOMOfflineResourceList*>(tmp->mApplicationCache.get())->Disconnect();
-    NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplicationCache)
-  }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuspendedDoc)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChild)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleService)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleObservers)
 
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mGamepads)
-
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDisplays)
-
   // Unlink stuff from nsPIDOMWindow
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameElement)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mFocusedNode)
-
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mMenubar)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mToolbar)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocationbar)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPersonalbar)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusbar)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mScrollbars)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mU2F)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioWorklet)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaintWorklet)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mExternal)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mMozSelfSupport)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntlUtils)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mOpenerForInitialContentBrowser)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)
 
   tmp->UnlinkHostObjectURIs();
 
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)
-
   if (tmp->IsChromeWindow()) {
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mBrowserDOMWindow)
-    if (tmp->mChromeFields.mMessageManager) {
-      static_cast<nsFrameMessageManager*>(
-        tmp->mChromeFields.mMessageManager.get())->Disconnect();
-      NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mMessageManager)
-    }
-    tmp->DisconnectAndClearGroupMessageManagers();
-    NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mGroupMessageManagers)
-    NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mOpenerForInitialContentBrowser)
   }
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-#ifdef DEBUG
-void
-nsGlobalWindowOuter::RiskyUnlink()
-{
-  NS_CYCLE_COLLECTION_INNERNAME.Unlink(this);
-}
-#endif
-
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindowOuter)
-  if (tmp->mCachedXBLPrototypeHandlers) {
-    for (auto iter = tmp->mCachedXBLPrototypeHandlers->Iter();
-         !iter.Done();
-         iter.Next()) {
-      aCallbacks.Trace(&iter.Data(), "Cached XBL prototype handler", aClosure);
-    }
-  }
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 bool
 nsGlobalWindowOuter::IsBlackForCC(bool aTracingNeeded)
 {
   if (!nsCCUncollectableMarker::sGeneration) {
     return false;
@@ -1346,18 +1286,16 @@ void
 nsGlobalWindowOuter::TraceGlobalJSObject(JSTracer* aTrc)
 {
   TraceWrapper(aTrc, "active window global");
 }
 
 bool
 nsGlobalWindowOuter::WouldReuseInnerWindow(nsIDocument* aNewDocument)
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   // We reuse the inner window when:
   // a. We are currently at our original document.
   // b. At least one of the following conditions are true:
   // -- The new document is the same as the old document. This means that we're
   //    getting called from document.open().
   // -- The new document has the same origin as what we have loaded right now.
 
   if (!mDoc || !aNewDocument) {
@@ -1392,18 +1330,16 @@ nsGlobalWindowOuter::WouldReuseInnerWind
   }
 
   return false;
 }
 
 void
 nsGlobalWindowOuter::SetInitialPrincipalToSubject()
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   // First, grab the subject principal.
   nsCOMPtr<nsIPrincipal> newWindowPrincipal = nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
 
   // We should never create windows with an expanded principal.
   // If we have a system principal, make sure we're not using it for a content
   // docshell.
   // NOTE: Please keep this logic in sync with nsWebShellWindow::Initialize().
   if (nsContentUtils::IsExpandedPrincipal(newWindowPrincipal) ||
@@ -1446,30 +1382,29 @@ nsGlobalWindowOuter::SetInitialPrincipal
     shell->Initialize(r.Width(), r.Height());
   }
 }
 
 PopupControlState
 nsGlobalWindowOuter::PushPopupControlState(PopupControlState aState,
                                            bool aForce) const
 {
-  return ::PushPopupControlState(aState, aForce);
+  return nsContentUtils::PushPopupControlState(aState, aForce);
 }
 
 void
 nsGlobalWindowOuter::PopPopupControlState(PopupControlState aState) const
 {
-  ::PopPopupControlState(aState);
+  nsContentUtils::PopPopupControlState(aState);
 }
 
 PopupControlState
 nsGlobalWindowOuter::GetPopupControlState() const
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  return gPopupControlState;
+  return nsContentUtils::GetPopupControlState();
 }
 
 #define WINDOWSTATEHOLDER_IID \
 {0x0b917c3e, 0xbd50, 0x4683, {0xaf, 0xc9, 0xc7, 0x81, 0x07, 0xae, 0x33, 0x26}}
 
 class WindowStateHolder final : public nsISupports
 {
 public:
@@ -1497,17 +1432,16 @@ protected:
 
 NS_DEFINE_STATIC_IID_ACCESSOR(WindowStateHolder, WINDOWSTATEHOLDER_IID)
 
 WindowStateHolder::WindowStateHolder(nsGlobalWindowInner* aWindow)
   : mInnerWindow(aWindow),
     mInnerWindowReflector(RootingCx(), aWindow->GetWrapper())
 {
   NS_PRECONDITION(aWindow, "null window");
-  NS_PRECONDITION(aWindow->IsInnerWindow(), "Saving an outer window");
 
   aWindow->Suspend();
 
   // When a global goes into the bfcache, we disable script.
   xpc::Scriptability::Get(mInnerWindowReflector).SetDocShellAllowsScript(false);
 }
 
 WindowStateHolder::~WindowStateHolder()
@@ -1522,18 +1456,16 @@ WindowStateHolder::~WindowStateHolder()
   }
 }
 
 NS_IMPL_ISUPPORTS(WindowStateHolder, WindowStateHolder)
 
 bool
 nsGlobalWindowOuter::ComputeIsSecureContext(nsIDocument* aDocument, SecureContextFlags aFlags)
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
   if (nsContentUtils::IsSystemPrincipal(principal)) {
     return true;
   }
 
   // Implement https://w3c.github.io/webappsec-secure-contexts/#settings-object
   // With some modifications to allow for aFlags.
 
@@ -1603,27 +1535,173 @@ nsGlobalWindowOuter::ComputeIsSecureCont
     if (isTrustworthyOrigin) {
       return true;
     }
   }
 
   return false;
 }
 
+// We need certain special behavior for remote XUL whitelisted domains, but we
+// don't want that behavior to take effect in automation, because we whitelist
+// all the mochitest domains. So we need to check a pref here.
+static bool
+TreatAsRemoteXUL(nsIPrincipal* aPrincipal)
+{
+  MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(aPrincipal));
+  return nsContentUtils::AllowXULXBLForPrincipal(aPrincipal) &&
+    !Preferences::GetBool("dom.use_xbl_scopes_for_remote_xul", false);
+}
+
+static bool
+EnablePrivilege(JSContext* cx, unsigned argc, JS::Value* vp)
+{
+  Telemetry::Accumulate(Telemetry::ENABLE_PRIVILEGE_EVER_CALLED, true);
+  return xpc::EnableUniversalXPConnect(cx);
+}
+
+static const JSFunctionSpec EnablePrivilegeSpec[] = {
+  JS_FN("enablePrivilege", EnablePrivilege, 1, 0),
+  JS_FS_END
+};
+
+static bool
+InitializeLegacyNetscapeObject(JSContext* aCx, JS::Handle<JSObject*> aGlobal)
+{
+  JSAutoCompartment ac(aCx, aGlobal);
+
+  // Note: MathJax depends on window.netscape being exposed. See bug 791526.
+  JS::Rooted<JSObject*> obj(aCx);
+  obj = JS_DefineObject(aCx, aGlobal, "netscape", nullptr);
+  NS_ENSURE_TRUE(obj, false);
+
+  obj = JS_DefineObject(aCx, obj, "security", nullptr);
+  NS_ENSURE_TRUE(obj, false);
+
+  // We hide enablePrivilege behind a pref because it has been altered in a
+  // way that makes it fundamentally insecure to use in production. Mozilla
+  // uses this pref during automated testing to support legacy test code that
+  // uses enablePrivilege. If you're not doing test automation, you _must_ not
+  // flip this pref, or you will be exposing all your users to security
+  // vulnerabilities.
+  if (!xpc::IsInAutomation()) {
+    return true;
+  }
+
+  /* Define PrivilegeManager object with the necessary "static" methods. */
+  obj = JS_DefineObject(aCx, obj, "PrivilegeManager", nullptr);
+  NS_ENSURE_TRUE(obj, false);
+
+  return JS_DefineFunctions(aCx, obj, EnablePrivilegeSpec);
+}
+
+static JS::CompartmentCreationOptions&
+SelectZoneGroup(nsGlobalWindowInner* aNewInner,
+                JS::CompartmentCreationOptions& aOptions)
+{
+  JS::CompartmentCreationOptions options;
+
+  if (aNewInner->GetOuterWindow()) {
+    nsGlobalWindowOuter *top = aNewInner->GetTopInternal();
+
+    // If we have a top-level window, use its zone (and zone group).
+    if (top && top->GetGlobalJSObject()) {
+      return aOptions.setExistingZone(top->GetGlobalJSObject());
+    }
+  }
+
+  // If we're in the parent process, don't bother with zone groups.
+  if (XRE_IsParentProcess()) {
+    return aOptions.setNewZoneInSystemZoneGroup();
+  }
+
+  // Otherwise, find a zone group from the TabGroup. Typically we only have to
+  // go through one iteration of this loop.
+  RefPtr<TabGroup> tabGroup = aNewInner->TabGroup();
+  for (nsPIDOMWindowOuter* outer : tabGroup->GetWindows()) {
+    nsGlobalWindowOuter* window = nsGlobalWindowOuter::Cast(outer);
+    if (JSObject* global = window->GetGlobalJSObject()) {
+      return aOptions.setNewZoneInExistingZoneGroup(global);
+    }
+  }
+
+  return aOptions.setNewZoneInNewZoneGroup();
+}
+
+/**
+ * Create a new global object that will be used for an inner window.
+ * Return the native global and an nsISupports 'holder' that can be used
+ * to manage the lifetime of it.
+ */
+static nsresult
+CreateNativeGlobalForInner(JSContext* aCx,
+                           nsGlobalWindowInner* aNewInner,
+                           nsIURI* aURI,
+                           nsIPrincipal* aPrincipal,
+                           JS::MutableHandle<JSObject*> aGlobal,
+                           bool aIsSecureContext)
+{
+  MOZ_ASSERT(aCx);
+  MOZ_ASSERT(aNewInner);
+  MOZ_ASSERT(aPrincipal);
+
+  // DOMWindow with nsEP is not supported, we have to make sure
+  // no one creates one accidentally.
+  nsCOMPtr<nsIExpandedPrincipal> nsEP = do_QueryInterface(aPrincipal);
+  MOZ_RELEASE_ASSERT(!nsEP, "DOMWindow with nsEP is not supported");
+
+  JS::CompartmentOptions options;
+
+  SelectZoneGroup(aNewInner, options.creationOptions());
+
+  // Sometimes add-ons load their own XUL windows, either as separate top-level
+  // windows or inside a browser element. In such cases we want to tag the
+  // window's compartment with the add-on ID. See bug 1092156.
+  if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
+    options.creationOptions().setAddonId(MapURIToAddonID(aURI));
+  }
+
+  options.creationOptions().setSecureContext(aIsSecureContext);
+
+  xpc::InitGlobalObjectOptions(options, aPrincipal);
+
+  // Determine if we need the Components object.
+  bool needComponents = nsContentUtils::IsSystemPrincipal(aPrincipal) ||
+                        TreatAsRemoteXUL(aPrincipal);
+  uint32_t flags = needComponents ? 0 : xpc::OMIT_COMPONENTS_OBJECT;
+  flags |= xpc::DONT_FIRE_ONNEWGLOBALHOOK;
+
+  if (!WindowBinding::Wrap(aCx, aNewInner, aNewInner, options,
+                           nsJSPrincipals::get(aPrincipal), false, aGlobal) ||
+      !xpc::InitGlobalObject(aCx, aGlobal, flags)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  MOZ_ASSERT(aNewInner->GetWrapperPreserveColor() == aGlobal);
+
+  // Set the location information for the new global, so that tools like
+  // about:memory may use that information
+  xpc::SetLocationForGlobal(aGlobal, aURI);
+
+  if (!InitializeLegacyNetscapeObject(aCx, aGlobal)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
 nsresult
 nsGlobalWindowOuter::SetNewDocument(nsIDocument* aDocument,
                                     nsISupports* aState,
                                     bool aForceReuseInnerWindow)
 {
   NS_PRECONDITION(mDocumentPrincipal == nullptr,
                   "mDocumentPrincipal prematurely set!");
   MOZ_ASSERT(aDocument);
 
-  NS_PRECONDITION(IsOuterWindow(), "Must only be called on outer windows");
-
   // Bail out early if we're in process of closing down the window.
   NS_ENSURE_STATE(!mCleanedUp);
 
   NS_ASSERTION(!GetCurrentInnerWindow() ||
                GetCurrentInnerWindow()->GetExtantDoc() == mDoc,
                "Uh, mDoc doesn't match the current inner window "
                "document!");
 
@@ -2011,19 +2089,17 @@ nsGlobalWindowOuter::SetNewDocument(nsID
   mLargeAllocStatus = LargeAllocStatus::NONE;
 
   return NS_OK;
 }
 
 void
 nsGlobalWindowOuter::PreloadLocalStorage()
 {
-  MOZ_ASSERT(IsOuterWindow());
-
-  if (!Preferences::GetBool(kStorageEnabled)) {
+  if (!Storage::StoragePrefIsEnabled()) {
     return;
   }
 
   if (IsChromeWindow()) {
     return;
   }
 
   nsIPrincipal* principal = GetPrincipal();
@@ -2048,18 +2124,16 @@ nsGlobalWindowOuter::PreloadLocalStorage
       mLocalStorage = static_cast<Storage*>(storage.get());
     }
   }
 }
 
 void
 nsGlobalWindowOuter::DispatchDOMWindowCreated()
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   if (!mDoc) {
     return;
   }
 
   // Fire DOMWindowCreated at chrome event listeners
   nsContentUtils::DispatchChromeEvent(mDoc, mDoc, NS_LITERAL_STRING("DOMWindowCreated"),
                                       true /* bubbles */,
                                       false /* not cancellable */);
@@ -2087,34 +2161,31 @@ void
 nsGlobalWindowOuter::ClearStatus()
 {
   SetStatusOuter(EmptyString());
 }
 
 void
 nsGlobalWindowOuter::SetDocShell(nsIDocShell* aDocShell)
 {
-  NS_ASSERTION(IsOuterWindow(), "Uh, SetDocShell() called on inner window!");
   MOZ_ASSERT(aDocShell);
 
   if (aDocShell == mDocShell) {
     return;
   }
 
   mDocShell = aDocShell; // Weak Reference
 
   nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetScriptableParentOrNull();
   MOZ_RELEASE_ASSERT(!parentWindow || !mTabGroup ||
                      mTabGroup == nsGlobalWindowOuter::Cast(parentWindow)->mTabGroup);
 
   mTopLevelOuterContentWindow =
     !mIsChrome && GetScriptableTopInternal() == this;
 
-  NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
-
   if (mFrames) {
     mFrames->SetDocShell(aDocShell);
   }
 
   // Get our enclosing chrome shell and retrieve its global window impl, so
   // that we can do some forwarding to the chrome document.
   nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
   mDocShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
@@ -2139,33 +2210,30 @@ nsGlobalWindowOuter::SetDocShell(nsIDocS
   bool docShellActive;
   mDocShell->GetIsActive(&docShellActive);
   SetIsBackgroundInternal(!docShellActive);
 }
 
 void
 nsGlobalWindowOuter::DetachFromDocShell()
 {
-  NS_ASSERTION(IsOuterWindow(), "Uh, DetachFromDocShell() called on inner window!");
-
   // DetachFromDocShell means the window is being torn down. Drop our
   // reference to the script context, allowing it to be deleted
   // later. Meanwhile, keep our weak reference to the script object
   // so that it can be retrieved later (until it is finalized by the JS GC).
 
   // Call FreeInnerObjects on all inner windows, not just the current
   // one, since some could be held by WindowStateHolder objects that
   // are GC-owned.
   RefPtr<nsGlobalWindowInner> inner;
   for (PRCList* node = PR_LIST_HEAD(this);
        node != this;
        node = PR_NEXT_LINK(inner)) {
     // This cast is safe because `node != this`. Non-this nodes are inner windows.
     inner = static_cast<nsGlobalWindowInner*>(node);
-    MOZ_ASSERT(inner->IsInnerWindow());
     MOZ_ASSERT(!inner->mOuterWindow || inner->mOuterWindow == this);
     inner->FreeInnerObjects();
   }
 
   // Don't report that we were detached to the nsWindowMemoryReporter, as it
   // only tracks inner windows.
 
   NotifyWindowIDDestroyed("outer-window-destroyed");
@@ -2177,17 +2245,16 @@ nsGlobalWindowOuter::DetachFromDocShell(
 
     // Remember the document's principal and URI.
     mDocumentPrincipal = mDoc->NodePrincipal();
     mDocumentURI = mDoc->GetDocumentURI();
     mDocBaseURI = mDoc->GetDocBaseURI();
 
     // Release our document reference
     DropOuterWindowDocs();
-    mFocusedNode = nullptr;
   }
 
   ClearControllers();
 
   mChromeEventHandler = nullptr; // force release now
 
   if (mContext) {
     // When we're about to destroy a top level content window
@@ -2196,18 +2263,16 @@ nsGlobalWindowOuter::DetachFromDocShell(
     nsJSContext::PokeGC(JS::gcreason::SET_DOC_SHELL,
                         (mTopLevelOuterContentWindow || mIsChrome) ?
                           nullptr : GetWrapperPreserveColor());
     mContext = nullptr;
   }
 
   mDocShell = nullptr; // Weak Reference
 
-  NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
-
   if (mFrames) {
     mFrames->SetDocShell(nullptr);
   }
 
   MaybeForgiveSpamCount();
   CleanUp();
 }
 
@@ -2261,28 +2326,30 @@ nsGlobalWindowOuter::UpdateParentTarget(
 
   // Try to get our frame element's tab child global (its in-process message
   // manager).  If that fails, fall back to the chrome event handler's tab
   // child global, and if it doesn't have one, just use the chrome event
   // handler itself.
 
   nsCOMPtr<Element> frameElement = GetOuterWindow()->GetFrameElementInternal();
   nsCOMPtr<EventTarget> eventTarget =
-    TryGetTabChildGlobalAsEventTarget(frameElement);
+    nsContentUtils::TryGetTabChildGlobalAsEventTarget(frameElement);
 
   if (!eventTarget) {
     nsGlobalWindowOuter* topWin = GetScriptableTopInternal();
     if (topWin) {
       frameElement = topWin->GetFrameElementInternal();
-      eventTarget = TryGetTabChildGlobalAsEventTarget(frameElement);
+      eventTarget =
+        nsContentUtils::TryGetTabChildGlobalAsEventTarget(frameElement);
     }
   }
 
   if (!eventTarget) {
-    eventTarget = TryGetTabChildGlobalAsEventTarget(mChromeEventHandler);
+    eventTarget =
+      nsContentUtils::TryGetTabChildGlobalAsEventTarget(mChromeEventHandler);
   }
 
   if (!eventTarget) {
     eventTarget = mChromeEventHandler;
   }
 
   mParentTarget = eventTarget;
 }
@@ -2303,24 +2370,22 @@ nsresult
 nsGlobalWindowOuter::WillHandleEvent(EventChainPostVisitor& aVisitor)
 {
   return NS_OK;
 }
 
 nsresult
 nsGlobalWindowOuter::GetEventTargetParent(EventChainPreVisitor& aVisitor)
 {
-  MOZ_CRASH("Virtual inner window only function");
+  MOZ_CRASH("The outer window should not be part of an event path");
 }
 
 bool
 nsGlobalWindowOuter::ShouldPromptToBlockDialogs()
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   nsGlobalWindowOuter *topWindowOuter = GetScriptableTopInternal();
   if (!topWindowOuter) {
     NS_ASSERTION(!mDocShell, "ShouldPromptToBlockDialogs() called without a top window?");
     return true;
   }
 
   nsGlobalWindowInner* topWindow = topWindowOuter->GetCurrentInnerWindowInternal();
   if (!topWindow) {
@@ -2328,18 +2393,16 @@ nsGlobalWindowOuter::ShouldPromptToBlock
   }
 
   return topWindow->DialogsAreBeingAbused();
 }
 
 bool
 nsGlobalWindowOuter::AreDialogsEnabled()
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   nsGlobalWindowOuter *topWindowOuter = GetScriptableTopInternal();
   if (!topWindowOuter) {
     NS_ERROR("AreDialogsEnabled() called without a top window?");
     return false;
   }
 
   // TODO: Warn if no top window?
   nsGlobalWindowInner* topWindow = topWindowOuter->GetCurrentInnerWindowInternal();
@@ -2370,18 +2433,16 @@ nsGlobalWindowOuter::AreDialogsEnabled()
   }
 
   return topWindow->mAreDialogsEnabled;
 }
 
 bool
 nsGlobalWindowOuter::ConfirmDialogIfNeeded()
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   NS_ENSURE_TRUE(mDocShell, false);
   nsCOMPtr<nsIPromptService> promptSvc =
     do_GetService("@mozilla.org/embedcomp/prompt-service;1");
 
   if (!promptSvc) {
     return true;
   }
 
@@ -2435,32 +2496,30 @@ nsGlobalWindowOuter::EnableDialogs()
   if (topWindow) {
     topWindow->mAreDialogsEnabled = true;
   }
 }
 
 nsresult
 nsGlobalWindowOuter::PostHandleEvent(EventChainPostVisitor& aVisitor)
 {
-  MOZ_CRASH("Virtual inner window only function");
+  MOZ_CRASH("The outer window should not be part of an event path");
 }
 
 void
 nsGlobalWindowOuter::PoisonOuterWindowProxy(JSObject *aObject)
 {
-  MOZ_ASSERT(IsOuterWindow());
   if (aObject == GetWrapperMaybeDead()) {
     PoisonWrapper();
   }
 }
 
 nsresult
 nsGlobalWindowOuter::SetArguments(nsIArray *aArguments)
 {
-  MOZ_ASSERT(IsOuterWindow());
   nsresult rv;
 
   // Historically, we've used the same machinery to handle openDialog arguments
   // (exposed via window.arguments) and showModalDialog arguments (exposed via
   // window.dialogArguments), even though the former is XUL-only and uses an XPCOM
   // array while the latter is web-exposed and uses an arbitrary JS value.
   // Moreover, per-spec |dialogArguments| is a property of the browsing context
   // (outer), whereas |arguments| lives on the inner.
@@ -2514,17 +2573,16 @@ nsGlobalWindowOuter::GetPrincipal()
 //*****************************************************************************
 // nsGlobalWindowOuter::nsIDOMWindow
 //*****************************************************************************
 
 void
 nsPIDOMWindowOuter::SetInitialKeyboardIndicators(
   UIStateChangeType aShowAccelerators, UIStateChangeType aShowFocusRings)
 {
-  MOZ_ASSERT(IsOuterWindow());
   MOZ_ASSERT(!GetCurrentInnerWindow());
 
   nsPIDOMWindowOuter* piWin = GetPrivateRoot();
   if (!piWin) {
     return;
   }
 
   MOZ_ASSERT(piWin == this);
@@ -2545,45 +2603,37 @@ nsPIDOMWindowOuter::SetInitialKeyboardIn
   nsContentUtils::SetKeyboardIndicatorsOnRemoteChildren(GetOuterWindow(),
                                                         aShowAccelerators,
                                                         aShowFocusRings);
 }
 
 Element*
 nsPIDOMWindowOuter::GetFrameElementInternal() const
 {
-  MOZ_ASSERT(IsOuterWindow());
   return mFrameElement;
 }
 
 void
 nsPIDOMWindowOuter::SetFrameElementInternal(Element* aFrameElement)
 {
-  MOZ_ASSERT(IsOuterWindow());
   mFrameElement = aFrameElement;
 }
 
 nsIDOMNavigator*
 nsGlobalWindowOuter::GetNavigator()
 {
   FORWARD_TO_INNER(GetNavigator, (), nullptr);
 }
 
 nsIDOMScreen*
 nsGlobalWindowOuter::GetScreen()
 {
   FORWARD_TO_INNER(GetScreen, (), nullptr);
 }
 
-CustomElementRegistry*
-nsGlobalWindowOuter::CustomElements()
-{
-  MOZ_CRASH("Virtual inner window only function");
-}
-
 void
 nsPIDOMWindowOuter::MaybeActiveMediaComponents()
 {
   if (mMediaSuspend != nsISuspendedTypes::SUSPENDED_BLOCK) {
     return;
   }
 
   MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
@@ -2709,18 +2759,16 @@ nsPIDOMWindowOuter::GetServiceWorkersTes
     return false;
   }
   return topWindow->mServiceWorkersTestingEnabled;
 }
 
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindowOuter::GetParentOuter()
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   if (!mDocShell) {
     return nullptr;
   }
 
   nsCOMPtr<nsPIDOMWindowOuter> parent;
   if (mDocShell->GetIsMozBrowser()) {
     parent = this;
   } else {
@@ -2757,18 +2805,16 @@ nsGlobalWindowOuter::GetScriptableParent
 
 /**
  * nsPIDOMWindow::GetParent (when called from C++) is just a wrapper around
  * GetRealParent.
  */
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindowOuter::GetParent()
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   if (!mDocShell) {
     return nullptr;
   }
 
   nsCOMPtr<nsIDocShell> parent;
   mDocShell->GetSameTypeParentIgnoreBrowserBoundaries(getter_AddRefs(parent));
 
   if (parent) {
@@ -2828,30 +2874,27 @@ nsGlobalWindowOuter::GetScriptableTop()
   nsCOMPtr<nsPIDOMWindowOuter> window;
   GetTopImpl(this, getter_AddRefs(window), /* aScriptable = */ true);
   return window.get();
 }
 
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindowOuter::GetTop()
 {
-  MOZ_ASSERT(IsOuterWindow());
   nsCOMPtr<nsPIDOMWindowOuter> window;
   GetTopImpl(this, getter_AddRefs(window), /* aScriptable = */ false);
   return window.forget();
 }
 
 void
 nsGlobalWindowOuter::GetContentOuter(JSContext* aCx,
                                      JS::MutableHandle<JSObject*> aRetval,
                                      CallerType aCallerType,
                                      ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   nsCOMPtr<nsPIDOMWindowOuter> content =
     GetContentInternal(aError, aCallerType);
   if (aError.Failed()) {
     return;
   }
 
   if (content) {
     JS::Rooted<JS::Value> val(aCx);
@@ -2865,18 +2908,16 @@ nsGlobalWindowOuter::GetContentOuter(JSC
   }
 
   aRetval.set(nullptr);
 }
 
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindowOuter::GetContentInternal(ErrorResult& aError, CallerType aCallerType)
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   // First check for a named frame named "content"
   nsCOMPtr<nsPIDOMWindowOuter> domWindow =
     GetChildWindow(NS_LITERAL_STRING("content"));
   if (domWindow) {
     return domWindow.forget();
   }
 
   // If we're contained in <iframe mozbrowser>, then GetContent is the same as
@@ -2935,35 +2976,29 @@ nsGlobalWindowOuter::GetPrompter(nsIProm
 
   prompter.forget(aPrompt);
   return NS_OK;
 }
 
 bool
 nsGlobalWindowOuter::GetClosedOuter()
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   // If someone called close(), or if we don't have a docshell, we're closed.
   return mIsClosed || !mDocShell;
 }
 
 bool
 nsGlobalWindowOuter::Closed()
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   return GetClosedOuter();
 }
 
 nsDOMWindowList*
 nsGlobalWindowOuter::GetWindowList()
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   if (!mFrames && mDocShell) {
     mFrames = new nsDOMWindowList(mDocShell);
   }
 
   return mFrames;
 }
 
 already_AddRefed<nsIDOMWindowCollection>
@@ -2971,35 +3006,25 @@ nsGlobalWindowOuter::GetFrames()
 {
   nsCOMPtr<nsIDOMWindowCollection> frames = GetWindowList();
   return frames.forget();
 }
 
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindowOuter::IndexedGetterOuter(uint32_t aIndex)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   nsDOMWindowList* windows = GetWindowList();
   NS_ENSURE_TRUE(windows, nullptr);
 
   return windows->IndexedGetter(aIndex);
 }
 
-already_AddRefed<nsIDOMOfflineResourceList>
-nsGlobalWindowOuter::GetApplicationCache()
-{
-  FORWARD_TO_INNER(GetApplicationCache, (), nullptr);
-}
-
 nsIControllers*
 nsGlobalWindowOuter::GetControllersOuter(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   if (!mControllers) {
     nsresult rv;
     mControllers = do_CreateInstance(kXULControllersCID, &rv);
     if (NS_FAILED(rv)) {
       aError.Throw(rv);
       return nullptr;
     }
 
@@ -3063,18 +3088,16 @@ nsGlobalWindowOuter::GetSanitizedOpener(
   }
 
   return nullptr;
 }
 
 nsPIDOMWindowOuter*
 nsGlobalWindowOuter::GetOpenerWindowOuter()
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   nsCOMPtr<nsPIDOMWindowOuter> opener = do_QueryReferent(mOpener);
 
   if (!opener) {
     return nullptr;
   }
 
   // First, check if we were called from a privileged chrome script
   if (nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
@@ -3094,26 +3117,22 @@ nsGlobalWindowOuter::GetOpener()
 {
   nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpenerWindowOuter();
   return opener.forget();
 }
 
 void
 nsGlobalWindowOuter::GetStatusOuter(nsAString& aStatus)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   aStatus = mStatus;
 }
 
 void
 nsGlobalWindowOuter::SetStatusOuter(const nsAString& aStatus)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   mStatus = aStatus;
 
   /*
    * If caller is not chrome and dom.disable_window_status_change is true,
    * prevent propagating window.status to the UI by exiting early
    */
 
   if (!CanSetProperty("dom.disable_window_status_change")) {
@@ -3125,28 +3144,24 @@ nsGlobalWindowOuter::SetStatusOuter(cons
     browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT,
                              PromiseFlatString(aStatus).get());
   }
 }
 
 void
 nsGlobalWindowOuter::GetNameOuter(nsAString& aName)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   if (mDocShell) {
     mDocShell->GetName(aName);
   }
 }
 
 void
 nsGlobalWindowOuter::SetNameOuter(const nsAString& aName, mozilla::ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   if (mDocShell) {
     aError = mDocShell->SetName(aName);
   }
 }
 
 // Helper functions used by many methods below.
 int32_t
 nsGlobalWindowOuter::DevToCSSIntPixels(int32_t px)
@@ -3206,18 +3221,16 @@ nsGlobalWindowOuter::CSSToDevIntPixels(n
   return nsIntSize(
     presContext->CSSPixelsToDevPixels(px.width),
     presContext->CSSPixelsToDevPixels(px.height));
 }
 
 nsresult
 nsGlobalWindowOuter::GetInnerSize(CSSIntSize& aSize)
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   EnsureSizeAndPositionUpToDate();
 
   NS_ENSURE_STATE(mDocShell);
 
   RefPtr<nsPresContext> presContext;
   mDocShell->GetPresContext(getter_AddRefs(presContext));
   RefPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
 
@@ -3245,36 +3258,32 @@ nsGlobalWindowOuter::GetInnerSize(CSSInt
       presContext->GetVisibleArea().Size());
   }
   return NS_OK;
 }
 
 int32_t
 nsGlobalWindowOuter::GetInnerWidthOuter(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   CSSIntSize size;
   aError = GetInnerSize(size);
   return size.width;
 }
 
 nsresult
 nsGlobalWindowOuter::GetInnerWidth(int32_t* aInnerWidth)
 {
   FORWARD_TO_INNER(GetInnerWidth, (aInnerWidth), NS_ERROR_UNEXPECTED);
 }
 
 void
 nsGlobalWindowOuter::SetInnerWidthOuter(int32_t aInnerWidth,
                                         CallerType aCallerType,
                                         ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   if (!mDocShell) {
     aError.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
 
   CheckSecurityWidthAndHeight(&aInnerWidth, nullptr, aCallerType);
 
   RefPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
@@ -3299,36 +3308,32 @@ nsGlobalWindowOuter::SetInnerWidthOuter(
   nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
   docShellAsWin->GetSize(&unused, &height);
   aError = SetDocShellWidthAndHeight(CSSToDevIntPixels(aInnerWidth), height);
 }
 
 int32_t
 nsGlobalWindowOuter::GetInnerHeightOuter(ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   CSSIntSize size;
   aError = GetInnerSize(size);
   return size.height;
 }
 
 nsresult
 nsGlobalWindowOuter::GetInnerHeight(int32_t* aInnerHeight)
 {
   FORWARD_TO_INNER(GetInnerHeight, (aInnerHeight), NS_ERROR_UNEXPECTED);
 }
 
 void
 nsGlobalWindowOuter::SetInnerHeightOuter(int32_t aInnerHeight,
                                          CallerType aCallerType,
                                          ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   if (!mDocShell) {
     aError.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
 
   RefPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
 
   if (presShell && presShell->GetIsViewportOverridden())
@@ -3352,18 +3357,16 @@ nsGlobalWindowOuter::SetInnerHeightOuter
   docShellAsWin->GetSize(&width, &height);
   CheckSecurityWidthAndHeight(nullptr, &aInnerHeight, aCallerType);
   aError = SetDocShellWidthAndHeight(width, CSSToDevIntPixels(aInnerHeight));
 }
 
 nsIntSize
 nsGlobalWindowOuter::GetOuterSize(CallerType aCallerType, ErrorResult& aError)
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   if (nsContentUtils::ResistFingerprinting(aCallerType)) {
     CSSIntSize size;
     aError = GetInnerSize(size);
     return nsIntSize(size.width, size.height);
   }
 
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
   if (!treeOwnerAsWin) {
@@ -3378,33 +3381,29 @@ nsGlobalWindowOuter::GetOuterSize(Caller
   }
 
   return DevToCSSIntPixels(sizeDevPixels);
 }
 
 int32_t
 nsGlobalWindowOuter::GetOuterWidthOuter(CallerType aCallerType, ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
   return GetOuterSize(aCallerType, aError).width;
 }
 
 int32_t
 nsGlobalWindowOuter::GetOuterHeightOuter(CallerType aCallerType, ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
   return GetOuterSize(aCallerType, aError).height;
 }
 
 void
 nsGlobalWindowOuter::SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
                                   CallerType aCallerType, ErrorResult& aError)
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
   if (!treeOwnerAsWin) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   CheckSecurityWidthAndHeight(aIsWidth ? &aLengthCSSPixels : nullptr,
                               aIsWidth ? nullptr : &aLengthCSSPixels,
@@ -3427,36 +3426,30 @@ nsGlobalWindowOuter::SetOuterSize(int32_
   CheckForDPIChange();
 }
 
 void
 nsGlobalWindowOuter::SetOuterWidthOuter(int32_t aOuterWidth,
                                         CallerType aCallerType,
                                         ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   SetOuterSize(aOuterWidth, true, aCallerType, aError);
 }
 
 void
 nsGlobalWindowOuter::SetOuterHeightOuter(int32_t aOuterHeight,
                                          CallerType aCallerType,
                                          ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   SetOuterSize(aOuterHeight, false, aCallerType, aError);
 }
 
 CSSIntPoint
 nsGlobalWindowOuter::GetScreenXY(CallerType aCallerType, ErrorResult& aError)
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   // When resisting fingerprinting, always return (0,0)
   if (nsContentUtils::ResistFingerprinting(aCallerType)) {
     return CSSIntPoint(0, 0);
   }
 
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
   if (!treeOwnerAsWin) {
     aError.Throw(NS_ERROR_FAILURE);
@@ -3493,26 +3486,22 @@ nsGlobalWindowOuter::GetScreenXY(CallerT
   cssPt.y += screenRectDesk.y;
 
   return CSSIntPoint(NSToIntRound(cssPt.x), NSToIntRound(cssPt.y));
 }
 
 int32_t
 nsGlobalWindowOuter::GetScreenXOuter(CallerType aCallerType, ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   return GetScreenXY(aCallerType, aError).x;
 }
 
 nsRect
 nsGlobalWindowOuter::GetInnerScreenRect()
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   if (!mDocShell) {
     return nsRect();
   }
 
   EnsureSizeAndPositionUpToDate();
 
   if (!mDocShell) {
     return nsRect();
@@ -3528,46 +3517,40 @@ nsGlobalWindowOuter::GetInnerScreenRect(
   }
 
   return rootFrame->GetScreenRectInAppUnits();
 }
 
 float
 nsGlobalWindowOuter::GetMozInnerScreenXOuter(CallerType aCallerType)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   // When resisting fingerprinting, always return 0.
   if (nsContentUtils::ResistFingerprinting(aCallerType)) {
     return 0.0;
   }
 
   nsRect r = GetInnerScreenRect();
   return nsPresContext::AppUnitsToFloatCSSPixels(r.x);
 }
 
 float
 nsGlobalWindowOuter::GetMozInnerScreenYOuter(CallerType aCallerType)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   // Return 0 to prevent fingerprinting.
   if (nsContentUtils::ResistFingerprinting(aCallerType)) {
     return 0.0;
   }
 
   nsRect r = GetInnerScreenRect();
   return nsPresContext::AppUnitsToFloatCSSPixels(r.y);
 }
 
 double
 nsGlobalWindowOuter::GetDevicePixelRatioOuter(CallerType aCallerType)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   if (!mDocShell) {
     return 1.0;
   }
 
   RefPtr<nsPresContext> presContext;
   mDocShell->GetPresContext(getter_AddRefs(presContext));
   if (!presContext) {
     return 1.0;
@@ -3591,46 +3574,40 @@ float
 nsPIDOMWindowOuter::GetDevicePixelRatio(CallerType aCallerType)
 {
   return nsGlobalWindowOuter::Cast(this)->GetDevicePixelRatioOuter(aCallerType);
 }
 
 uint64_t
 nsGlobalWindowOuter::GetMozPaintCountOuter()
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   if (!mDocShell) {
     return 0;
   }
 
   nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
   return presShell ? presShell->GetPaintCount() : 0;
 }
 
 already_AddRefed<MediaQueryList>
 nsGlobalWindowOuter::MatchMediaOuter(const nsAString& aMediaQueryList,
                                      CallerType aCallerType)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   if (!mDoc) {
     return nullptr;
   }
 
   return mDoc->MatchMedia(aMediaQueryList, aCallerType);
 }
 
 void
 nsGlobalWindowOuter::SetScreenXOuter(int32_t aScreenX,
                                      CallerType aCallerType,
                                      ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
   if (!treeOwnerAsWin) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   int32_t x, y;
   aError = treeOwnerAsWin->GetPosition(&x, &y);
@@ -3644,29 +3621,25 @@ nsGlobalWindowOuter::SetScreenXOuter(int
   aError = treeOwnerAsWin->SetPosition(x, y);
 
   CheckForDPIChange();
 }
 
 int32_t
 nsGlobalWindowOuter::GetScreenYOuter(CallerType aCallerType, ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   return GetScreenXY(aCallerType, aError).y;
 }
 
 
 void
 nsGlobalWindowOuter::SetScreenYOuter(int32_t aScreenY,
                                      CallerType aCallerType,
                                      ErrorResult& aError)
 {
-  MOZ_RELEASE_ASSERT(IsOuterWindow());
-
   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
   if (!treeOwnerAsWin) {
     aError.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   int32_t x, y;
   aError = treeOwnerAsWin->GetPosition(&x, &y);
@@ -3683,18 +3656,16 @@ nsGlobalWindowOuter::SetScreenYOuter(int
 }
 
 // NOTE: Arguments to this function should have values scaled to
 // CSS pixels, not device pixels.
 void
 nsGlobalWindowOuter::CheckSecurityWidthAndHeight(int32_t* aWidth, int32_t* aHeight,
                                                  CallerType aCallerType)
 {
-  MOZ_ASSERT(IsOuterWindow());
-
 #ifdef MOZ_XUL
   if (aCallerType != CallerType::System) {
     // if attempting to resize the window, hide any open popups
     nsContentUtils::HidePopupsInDocument(mDoc);
   }
 #endif
 
   // This one is easy. Just ensure the variable is greater than 100;
@@ -3712,54 +3683,48 @@ nsGlobalWindowOuter::CheckSecurityWidthA
     }
   }
 }
 
 // NOTE: Arguments to this function should have values in device pixels
 nsresult
 nsGlobalWindowOuter::SetDocShellWidthAndHeight(int32_t aInnerWidth, int32_t aInnerHeight)
 {
-  MOZ_ASSERT(IsOuterWindow());
-
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
   mDocShell->GetTreeOwner(getter_AddRefs(treeOwner));
   NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
 
   NS_ENSURE_SUCCESS(treeOwner->SizeShellTo(mDocShell, aInnerWidth, aInnerHeight),
                     NS_ERROR_FAILURE);
 
   return NS_OK;
 }
 
 // NOTE: Argume