Backed out 6 changesets (bug 1353867) for nsDocShell.cpp failures CLOSED TREE
authorBogdan Tara <btara@mozilla.com>
Mon, 31 Dec 2018 17:47:12 +0200
changeset 509298 cc4bb8c7fa92e8a4f44377c253160cea4ab66c97
parent 509297 19828a8dd8ae5ce8d7aa37d57ed607ee3043e49b
child 509299 9f5be1d14edcdeca0e0d0c6bee0f8b11db05add4
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1353867
milestone66.0a1
backs outaa9b106b15d93573e5125356667f3a1f474d2e5a
8c05f4d3f7ad300b5ee0ac6c78cc34b19107a4e9
00869bed41216138d967c715a8ed601cff074720
700aeb906fd206725e85311d6857f429576eb8f1
8b60851b93da2cf1f622e1bad41ba2e0527876c5
ebdf4531b3bde9d88da6a22c2df5290dda137c34
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 6 changesets (bug 1353867) for nsDocShell.cpp failures CLOSED TREE Backed out changeset aa9b106b15d9 (bug 1353867) Backed out changeset 8c05f4d3f7ad (bug 1353867) Backed out changeset 00869bed4121 (bug 1353867) Backed out changeset 700aeb906fd2 (bug 1353867) Backed out changeset 8b60851b93da (bug 1353867) Backed out changeset ebdf4531b3bd (bug 1353867)
docshell/base/BrowsingContext.cpp
docshell/base/BrowsingContext.h
docshell/base/ChromeBrowsingContext.h
docshell/base/moz.build
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
dom/base/ContentFrameMessageManager.h
dom/base/InProcessTabChildMessageManager.cpp
dom/base/InProcessTabChildMessageManager.h
dom/base/Location.h
dom/base/PostMessageEvent.cpp
dom/base/PostMessageEvent.h
dom/base/RemoteOuterWindowProxy.cpp
dom/base/WindowNamedPropertiesHandler.cpp
dom/base/WindowProxyHolder.h
dom/base/moz.build
dom/base/nsDocument.cpp
dom/base/nsFrameLoader.cpp
dom/base/nsFrameLoader.h
dom/base/nsGlobalWindowInner.cpp
dom/base/nsGlobalWindowInner.h
dom/base/nsGlobalWindowOuter.cpp
dom/base/nsGlobalWindowOuter.h
dom/base/nsIDocument.h
dom/base/nsINode.cpp
dom/base/nsINode.h
dom/base/nsObjectLoadingContent.cpp
dom/base/nsObjectLoadingContent.h
dom/base/nsPIDOMWindow.h
dom/base/nsPIDOMWindowInlines.h
dom/base/nsWindowRoot.cpp
dom/base/nsWindowRoot.h
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/bindings/Bindings.conf
dom/bindings/Codegen.py
dom/bindings/RemoteObjectProxy.cpp
dom/bindings/RemoteObjectProxy.h
dom/bindings/ToJSValue.cpp
dom/bindings/ToJSValue.h
dom/bindings/moz.build
dom/bindings/nsScriptError.cpp
dom/bindings/nsScriptError.h
dom/bindings/parser/WebIDL.py
dom/browser-element/BrowserElementParent.cpp
dom/browser-element/BrowserElementParent.h
dom/events/DOMEventTargetHelper.h
dom/events/EventTarget.cpp
dom/events/EventTarget.h
dom/events/MessageEvent.cpp
dom/events/MessageEvent.h
dom/events/UIEvent.h
dom/html/HTMLObjectElement.cpp
dom/html/HTMLObjectElement.h
dom/html/nsGenericHTMLFrameElement.cpp
dom/html/nsGenericHTMLFrameElement.h
dom/html/nsHTMLDocument.cpp
dom/html/nsHTMLDocument.h
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/smil/TimeEvent.h
dom/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
dom/webidl/Window.webidl
dom/xul/XULFrameElement.cpp
dom/xul/XULFrameElement.h
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/src/xpcpublic.h
js/xpconnect/wrappers/FilteringWrapper.cpp
js/xpconnect/wrappers/FilteringWrapper.h
js/xpconnect/wrappers/XrayWrapper.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
toolkit/components/antitracking/AntiTrackingCommon.cpp
toolkit/components/extensions/ExtensionPolicyService.cpp
toolkit/components/extensions/WebExtensionContentScript.h
toolkit/components/extensions/WebExtensionPolicy.cpp
toolkit/components/extensions/WebExtensionPolicy.h
toolkit/components/sessionstore/nsSessionStoreUtils.cpp
xpfe/appshell/nsContentTreeOwner.cpp
xpfe/appshell/nsXULWindow.cpp
--- a/docshell/base/BrowsingContext.cpp
+++ b/docshell/base/BrowsingContext.cpp
@@ -5,29 +5,24 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/BrowsingContext.h"
 
 #include "mozilla/dom/ChromeBrowsingContext.h"
 #include "mozilla/dom/BrowsingContextBinding.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
-#include "mozilla/dom/Location.h"
-#include "mozilla/dom/LocationBinding.h"
-#include "mozilla/dom/WindowBinding.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/HashTable.h"
 #include "mozilla/Logging.h"
 #include "mozilla/StaticPtr.h"
 
 #include "nsDocShell.h"
-#include "nsGlobalWindowOuter.h"
 #include "nsContentUtils.h"
-#include "nsScriptError.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 static LazyLogModule gBrowsingContextLog("BrowsingContext");
 
 static StaticAutoPtr<BrowsingContext::Children> sRootBrowsingContexts;
@@ -50,22 +45,24 @@ static void Register(BrowsingContext* aB
 
 static void Sync(BrowsingContext* aBrowsingContext) {
   if (!XRE_IsContentProcess()) {
     return;
   }
 
   auto cc = ContentChild::GetSingleton();
   MOZ_DIAGNOSTIC_ASSERT(cc);
+  nsAutoString name;
+  aBrowsingContext->GetName(name);
   RefPtr<BrowsingContext> parent = aBrowsingContext->GetParent();
   BrowsingContext* opener = aBrowsingContext->GetOpener();
   cc->SendAttachBrowsingContext(BrowsingContextId(parent ? parent->Id() : 0),
                                 BrowsingContextId(opener ? opener->Id() : 0),
                                 BrowsingContextId(aBrowsingContext->Id()),
-                                aBrowsingContext->Name());
+                                name);
 }
 
 /* static */ void BrowsingContext::Init() {
   if (!sRootBrowsingContexts) {
     sRootBrowsingContexts = new BrowsingContext::Children();
     ClearOnShutdown(&sRootBrowsingContexts);
   }
 
@@ -149,18 +146,17 @@ static void Sync(BrowsingContext* aBrows
 BrowsingContext::BrowsingContext(BrowsingContext* aParent,
                                  BrowsingContext* aOpener,
                                  const nsAString& aName,
                                  uint64_t aBrowsingContextId, Type aType)
     : mType(aType),
       mBrowsingContextId(aBrowsingContextId),
       mParent(aParent),
       mOpener(aOpener),
-      mName(aName),
-      mClosed(false) {
+      mName(aName) {
   if (mParent) {
     mBrowsingContextGroup = mParent->mBrowsingContextGroup;
   } else if (mOpener) {
     mBrowsingContextGroup = mOpener->mBrowsingContextGroup;
   } else {
     mBrowsingContextGroup = new BrowsingContextGroup();
   }
 
@@ -324,142 +320,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(BrowsingContext)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(BrowsingContext, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(BrowsingContext, Release)
 
-void BrowsingContext::Location(JSContext* aCx,
-                               JS::MutableHandle<JSObject*> aLocation,
-                               OOMReporter& aError) {}
-
-void BrowsingContext::Close(CallerType aCallerType, ErrorResult& aError) {
-  // FIXME We need to set mClosed, but only once we're sending the
-  //       DOMWindowClose event (which happens in the process where the
-  //       document for this browsing context is loaded).
-  //       See https://bugzilla.mozilla.org/show_bug.cgi?id=1516343.
-  ContentChild* cc = ContentChild::GetSingleton();
-  cc->SendWindowClose(BrowsingContextId(mBrowsingContextId),
-                      aCallerType == CallerType::System);
-}
-
-void BrowsingContext::Focus(ErrorResult& aError) {
-  ContentChild* cc = ContentChild::GetSingleton();
-  cc->SendWindowFocus(BrowsingContextId(mBrowsingContextId));
-}
-
-void BrowsingContext::Blur(ErrorResult& aError) {
-  ContentChild* cc = ContentChild::GetSingleton();
-  cc->SendWindowBlur(BrowsingContextId(mBrowsingContextId));
-}
-
-Nullable<WindowProxyHolder> BrowsingContext::GetTop(ErrorResult& aError) {
-  // We never return null or throw an error, but the implementation in
-  // nsGlobalWindow does and we need to use the same signature.
-  BrowsingContext* bc = this;
-  BrowsingContext* parent;
-  while ((parent = bc->mParent)) {
-    bc = parent;
-  }
-  return WindowProxyHolder(bc);
-}
-
-void BrowsingContext::GetOpener(JSContext* aCx,
-                                JS::MutableHandle<JS::Value> aOpener,
-                                ErrorResult& aError) const {
-  auto* opener = GetOpener();
-  if (!opener) {
-    aOpener.setNull();
-    return;
-  }
-
-  if (!ToJSValue(aCx, WindowProxyHolder(opener), aOpener)) {
-    aError.NoteJSContextException(aCx);
-  }
-}
-
-Nullable<WindowProxyHolder> BrowsingContext::GetParent(
-    ErrorResult& aError) const {
-  // We never throw an error, but the implementation in nsGlobalWindow does and
-  // we need to use the same signature.
-  if (!mParent) {
-    return nullptr;
-  }
-  return WindowProxyHolder(mParent.get());
-}
-
-void BrowsingContext::PostMessageMoz(JSContext* aCx,
-                                     JS::Handle<JS::Value> aMessage,
-                                     const nsAString& aTargetOrigin,
-                                     const Sequence<JSObject*>& aTransfer,
-                                     nsIPrincipal& aSubjectPrincipal,
-                                     ErrorResult& aError) {
-  RefPtr<BrowsingContext> sourceBc;
-  PostMessageData data;
-  data.targetOrigin() = aTargetOrigin;
-  data.subjectPrincipal() = &aSubjectPrincipal;
-  RefPtr<nsGlobalWindowInner> callerInnerWindow;
-  if (!nsGlobalWindowOuter::GatherPostMessageData(
-          aCx, aTargetOrigin, getter_AddRefs(sourceBc), data.origin(),
-          getter_AddRefs(data.targetOriginURI()),
-          getter_AddRefs(data.callerPrincipal()),
-          getter_AddRefs(callerInnerWindow),
-          getter_AddRefs(data.callerDocumentURI()), aError)) {
-    return;
-  }
-  data.source() = BrowsingContextId(sourceBc->Id());
-  data.isFromPrivateWindow() =
-      callerInnerWindow &&
-      nsScriptErrorBase::ComputeIsFromPrivateWindow(callerInnerWindow);
-
-  JS::Rooted<JS::Value> transferArray(aCx);
-  aError = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransfer,
-                                                             &transferArray);
-  if (NS_WARN_IF(aError.Failed())) {
-    return;
-  }
-
-  ipc::StructuredCloneData message;
-  message.Write(aCx, aMessage, transferArray, aError);
-  if (NS_WARN_IF(aError.Failed())) {
-    return;
-  }
-
-  ContentChild* cc = ContentChild::GetSingleton();
-  ClonedMessageData messageData;
-  if (!message.BuildClonedMessageDataForChild(cc, messageData)) {
-    aError.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  cc->SendWindowPostMessage(BrowsingContextId(mBrowsingContextId), messageData,
-                            data);
-}
-
-void BrowsingContext::PostMessageMoz(JSContext* aCx,
-                                     JS::Handle<JS::Value> aMessage,
-                                     const WindowPostMessageOptions& aOptions,
-                                     nsIPrincipal& aSubjectPrincipal,
-                                     ErrorResult& aError) {
-  PostMessageMoz(aCx, aMessage, aOptions.mTargetOrigin, aOptions.mTransfer,
-                 aSubjectPrincipal, aError);
-}
-
-already_AddRefed<BrowsingContext> BrowsingContext::FindChildWithName(
-    const nsAString& aName) {
-  // FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=1515646 will reimplement
-  //       this on top of the BC tree.
-  MOZ_ASSERT(mDocShell);
-  nsCOMPtr<nsIDocShellTreeItem> child;
-  mDocShell->FindChildWithName(aName, false, true, nullptr, nullptr,
-                               getter_AddRefs(child));
-  nsCOMPtr<nsIDocShell> childDS = do_QueryInterface(child);
-  RefPtr<BrowsingContext> bc;
-  if (childDS) {
-    childDS->GetBrowsingContext(getter_AddRefs(bc));
-  }
-  return bc.forget();
-}
-
 }  // namespace dom
 }  // namespace mozilla
--- a/docshell/base/BrowsingContext.h
+++ b/docshell/base/BrowsingContext.h
@@ -5,43 +5,32 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_BrowsingContext_h
 #define mozilla_dom_BrowsingContext_h
 
 #include "mozilla/LinkedList.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/WeakPtr.h"
-#include "mozilla/dom/BindingDeclarations.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
-#include "nsIDocShell.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
 
-class nsGlobalWindowOuter;
-class nsOuterWindowProxy;
+class nsIDocShell;
 
 namespace mozilla {
 
-class ErrorResult;
 class LogModule;
-class OOMReporter;
 
 namespace dom {
 
 class BrowsingContext;
 class ContentParent;
-template <typename>
-struct Nullable;
-template <typename T>
-class Sequence;
-struct WindowPostMessageOptions;
-class WindowProxyHolder;
 
 // List of top-level or auxiliary BrowsingContexts
 class BrowsingContextGroup : public nsTArray<WeakPtr<BrowsingContext>> {
  public:
   NS_INLINE_DECL_REFCOUNTING(BrowsingContextGroup)
  private:
   ~BrowsingContextGroup() {}
 };
@@ -86,22 +75,16 @@ class BrowsingContext : public nsWrapper
       BrowsingContext* aParent, BrowsingContext* aOpener,
       const nsAString& aName, uint64_t aId, ContentParent* aOriginProcess);
 
   // Get the DocShell for this BrowsingContext if it is in-process, or
   // null if it's not.
   nsIDocShell* GetDocShell() { return mDocShell; }
   void SetDocShell(nsIDocShell* aDocShell);
 
-  // Get the outer window object for this BrowsingContext if it is in-process
-  // and still has a docshell, or null otherwise.
-  nsPIDOMWindowOuter* GetDOMWindow() const {
-    return mDocShell ? mDocShell->GetWindow() : nullptr;
-  }
-
   // Attach the current BrowsingContext to its parent, in both the child and the
   // parent process. BrowsingContext objects are created attached by default, so
   // this method need only be called when restoring cached BrowsingContext
   // objects.
   void Attach();
 
   // Detach the current BrowsingContext from its parent, in both the
   // child and the parent process.
@@ -113,130 +96,61 @@ class BrowsingContext : public nsWrapper
 
   // Determine if the current BrowsingContext was 'cached' by the logic in
   // CacheChildren.
   bool IsCached();
 
   // TODO(farre): We should sync changes from SetName to the parent
   // process. [Bug 1490303]
   void SetName(const nsAString& aName) { mName = aName; }
-  const nsString& Name() const { return mName; }
+  void GetName(nsAString& aName) { aName = mName; }
   bool NameEquals(const nsAString& aName) { return mName.Equals(aName); }
 
   bool IsContent() const { return mType == Type::Content; }
 
   uint64_t Id() const { return mBrowsingContextId; }
 
   BrowsingContext* GetParent() { return mParent; }
 
   void GetChildren(nsTArray<RefPtr<BrowsingContext>>& aChildren);
 
-  BrowsingContext* GetOpener() const { return mOpener; }
+  BrowsingContext* GetOpener() { return mOpener; }
 
   void SetOpener(BrowsingContext* aOpener);
 
   static void GetRootBrowsingContexts(
       nsTArray<RefPtr<BrowsingContext>>& aBrowsingContexts);
 
   nsISupports* GetParentObject() const;
   JSObject* WrapObject(JSContext* aCx,
                        JS::Handle<JSObject*> aGivenProto) override;
 
-  // Return the window proxy object that corresponds to this browsing context.
-  inline JSObject* GetWindowProxy() const { return mWindowProxy; }
-  // Set the window proxy object that corresponds to this browsing context.
-  void SetWindowProxy(JS::Handle<JSObject*> aWindowProxy) {
-    mWindowProxy = aWindowProxy;
-  }
-
   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(BrowsingContext)
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(BrowsingContext)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(BrowsingContext)
 
   using Children = nsTArray<RefPtr<BrowsingContext>>;
-  const Children& GetChildren() { return mChildren; }
-
-  // Window APIs that are cross-origin-accessible (from the HTML spec).
-  BrowsingContext* Window() { return Self(); }
-  BrowsingContext* Self() { return this; }
-  void Location(JSContext* aCx, JS::MutableHandle<JSObject*> aLocation,
-                OOMReporter& aError);
-  void Close(CallerType aCallerType, ErrorResult& aError);
-  bool GetClosed(ErrorResult&) { return mClosed; }
-  void Focus(ErrorResult& aError);
-  void Blur(ErrorResult& aError);
-  BrowsingContext* GetFrames(ErrorResult& aError) { return Self(); }
-  int32_t Length() const { return mChildren.Length(); }
-  Nullable<WindowProxyHolder> GetTop(ErrorResult& aError);
-  void GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aOpener,
-                 ErrorResult& aError) const;
-  Nullable<WindowProxyHolder> GetParent(ErrorResult& aError) const;
-  void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
-                      const nsAString& aTargetOrigin,
-                      const Sequence<JSObject*>& aTransfer,
-                      nsIPrincipal& aSubjectPrincipal, ErrorResult& aError);
-  void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
-                      const WindowPostMessageOptions& aOptions,
-                      nsIPrincipal& aSubjectPrincipal, ErrorResult& aError);
-
-  already_AddRefed<BrowsingContext> FindChildWithName(const nsAString& aName);
-
-  JSObject* WrapObject(JSContext* aCx);
 
  protected:
   virtual ~BrowsingContext();
   BrowsingContext(BrowsingContext* aParent, BrowsingContext* aOpener,
                   const nsAString& aName, uint64_t aBrowsingContextId,
                   Type aType);
 
  private:
-  friend class ::nsOuterWindowProxy;
-  friend class ::nsGlobalWindowOuter;
-  // Update the window proxy object that corresponds to this browsing context.
-  // This should be called from the window proxy object's objectMoved hook, if
-  // the object mWindowProxy points to was moved by the JS GC.
-  void UpdateWindowProxy(JSObject* obj, JSObject* old) {
-    if (mWindowProxy) {
-      MOZ_ASSERT(mWindowProxy == old);
-      mWindowProxy = obj;
-    }
-  }
-  // Clear the window proxy object that corresponds to this browsing context.
-  // This should be called if the window proxy object is finalized, or it can't
-  // reach its browsing context anymore.
-  void ClearWindowProxy() { mWindowProxy = nullptr; }
-
   // Type of BrowsingContent
   const Type mType;
 
   // Unique id identifying BrowsingContext
   const uint64_t mBrowsingContextId;
 
   RefPtr<BrowsingContextGroup> mBrowsingContextGroup;
   RefPtr<BrowsingContext> mParent;
   Children mChildren;
   WeakPtr<BrowsingContext> mOpener;
   nsCOMPtr<nsIDocShell> mDocShell;
   nsString mName;
-  // This is not a strong reference, but using a JS::Heap for that should be
-  // fine. The JSObject stored in here should be a proxy with a
-  // nsOuterWindowProxy handler, which will update the pointer from its
-  // objectMoved hook and clear it from its finalize hook.
-  JS::Heap<JSObject*> mWindowProxy;
-  bool mClosed;
 };
 
-/**
- * Gets a WindowProxy object for a BrowsingContext that lives in a different
- * process (creating the object if it doesn't already exist). The WindowProxy
- * object will be in the compartment that aCx is currently in. This should only
- * be called if aContext doesn't hold a docshell, otherwise the BrowsingContext
- * lives in this process, and a same-process WindowProxy should be used (see
- * nsGlobalWindowOuter). This should only be called by bindings code, ToJSValue
- * is the right API to get a WindowProxy for a BrowsingContext.
- */
-extern bool GetRemoteOuterWindowProxy(JSContext* aCx, BrowsingContext* aContext,
-                                      JS::MutableHandle<JSObject*> aRetVal);
-
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // !defined(mozilla_dom_BrowsingContext_h)
--- a/docshell/base/ChromeBrowsingContext.h
+++ b/docshell/base/ChromeBrowsingContext.h
@@ -29,17 +29,16 @@ class ChromeBrowsingContext final : publ
   static void CleanupContexts(uint64_t aProcessId);
   static already_AddRefed<ChromeBrowsingContext> Get(uint64_t aId);
   static ChromeBrowsingContext* Cast(BrowsingContext* aContext);
   static const ChromeBrowsingContext* Cast(const BrowsingContext* aContext);
 
   bool IsOwnedByProcess(uint64_t aProcessId) const {
     return mProcessId == aProcessId;
   }
-  uint64_t OwnerProcessId() const { return mProcessId; }
 
   void GetWindowGlobals(nsTArray<RefPtr<WindowGlobalParent>>& aWindows);
 
   // Called by WindowGlobalParent to register and unregister window globals.
   void RegisterWindowGlobal(WindowGlobalParent* aGlobal);
   void UnregisterWindowGlobal(WindowGlobalParent* aGlobal);
 
   // The current active WindowGlobal.
--- a/docshell/base/moz.build
+++ b/docshell/base/moz.build
@@ -98,17 +98,16 @@ UNIFIED_SOURCES += [
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/docshell/shistory',
     '/dom/base',
-    '/dom/bindings',
     '/layout/base',
     '/layout/generic',
     '/layout/style',
     '/layout/xul',
     '/netwerk/base',
     '/netwerk/protocol/viewsource',
     '/toolkit/components/browser',
     '/toolkit/components/find',
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2304,17 +2304,17 @@ nsDocShell::NotifyScrollObservers() {
 }
 
 //*****************************************************************************
 // nsDocShell::nsIDocShellTreeItem
 //*****************************************************************************
 
 NS_IMETHODIMP
 nsDocShell::GetName(nsAString& aName) {
-  aName = mBrowsingContext->Name();
+  mBrowsingContext->GetName(aName);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::SetName(const nsAString& aName) {
   mBrowsingContext->SetName(aName);
   return NS_OK;
 }
@@ -13416,13 +13416,17 @@ nsDocShell::GetColorMatrix(uint32_t* aMa
     memcpy(*aMatrix, mColorMatrix->components, 20 * sizeof(float));
   }
 
   return NS_OK;
 }
 
 bool nsDocShell::IsForceReloading() { return IsForceReloadType(mLoadType); }
 
+BrowsingContext* nsDocShell::GetBrowsingContext() const {
+  return mBrowsingContext;
+}
+
 NS_IMETHODIMP
 nsDocShell::GetBrowsingContext(BrowsingContext** aBrowsingContext) {
   *aBrowsingContext = do_AddRef(mBrowsingContext).take();
   return NS_OK;
 }
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -378,23 +378,20 @@ class nsDocShell final : public nsDocLoa
   static nsDocShell* Cast(nsIDocShell* aDocShell) {
     return static_cast<nsDocShell*>(aDocShell);
   }
 
   // Returns true if the current load is a force reload (started by holding
   // shift while triggering reload)
   bool IsForceReloading();
 
-  mozilla::dom::BrowsingContext* GetBrowsingContext() const {
-    return mBrowsingContext;
-  }
-  mozilla::dom::BrowsingContext* GetWindowProxy() {
-    EnsureScriptEnvironment();
-    return mBrowsingContext;
-  }
+  /**
+   * Native getter for a DocShell's BrowsingContext.
+   */
+  mozilla::dom::BrowsingContext* GetBrowsingContext() const;
 
   /**
    * Loads the given URI. See comments on nsDocShellLoadState members for more
    * information on information used. aDocShell and aRequest come from
    * onLinkClickSync, which is triggered during form submission.
    */
   nsresult InternalLoad(nsDocShellLoadState* aLoadState,
                         nsIDocShell** aDocShell, nsIRequest** aRequest);
--- a/dom/base/ContentFrameMessageManager.h
+++ b/dom/base/ContentFrameMessageManager.h
@@ -10,20 +10,16 @@
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/dom/MessageManagerGlobal.h"
 #include "nsContentUtils.h"
 #include "xpcpublic.h"
 
 namespace mozilla {
 namespace dom {
 
-template <typename>
-struct Nullable;
-class WindowProxyHolder;
-
 #define NS_CONTENTFRAMEMESSAGEMANAGER_IID            \
   {                                                  \
     0x97e192a6, 0xab7a, 0x4c8f, {                    \
       0xb7, 0xdd, 0xf7, 0xec, 0x36, 0x38, 0x71, 0xb5 \
     }                                                \
   }
 
 /**
@@ -32,17 +28,18 @@ class WindowProxyHolder;
 class ContentFrameMessageManager : public DOMEventTargetHelper,
                                    public MessageManagerGlobal {
  public:
   using DOMEventTargetHelper::AddRef;
   using DOMEventTargetHelper::Release;
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_CONTENTFRAMEMESSAGEMANAGER_IID)
 
-  virtual Nullable<WindowProxyHolder> GetContent(ErrorResult& aError) = 0;
+  virtual already_AddRefed<nsPIDOMWindowOuter> GetContent(
+      ErrorResult& aError) = 0;
   virtual already_AddRefed<nsIDocShell> GetDocShell(ErrorResult& aError) = 0;
   virtual already_AddRefed<nsIEventTarget> GetTabEventTarget() = 0;
   virtual uint64_t ChromeOuterWindowID() = 0;
 
   nsFrameMessageManager* GetMessageManager() { return mMessageManager; }
   void DisconnectMessageManager() {
     mMessageManager->Disconnect();
     mMessageManager = nullptr;
--- a/dom/base/InProcessTabChildMessageManager.cpp
+++ b/dom/base/InProcessTabChildMessageManager.cpp
@@ -1,31 +1,29 @@
 /* -*- 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 "InProcessTabChildMessageManager.h"
 #include "nsContentUtils.h"
-#include "nsDocShell.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIComponentManager.h"
 #include "nsIServiceManager.h"
 #include "nsComponentManagerUtils.h"
 #include "nsFrameLoader.h"
 #include "xpcpublic.h"
 #include "nsIMozBrowserFrame.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/dom/ChromeMessageSender.h"
 #include "mozilla/dom/MessageManagerBinding.h"
 #include "mozilla/dom/SameProcessMessageQueue.h"
 #include "mozilla/dom/ScriptLoader.h"
-#include "mozilla/dom/WindowProxyHolder.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::dom::ipc;
 
 bool InProcessTabChildMessageManager::DoSendBlockingMessage(
     JSContext* aCx, const nsAString& aMessage, StructuredCloneData& aData,
     JS::Handle<JSObject*> aCpows, nsIPrincipal* aPrincipal,
@@ -73,17 +71,17 @@ nsresult InProcessTabChildMessageManager
     return rv;
   }
 
   queue->Push(ev);
   return NS_OK;
 }
 
 InProcessTabChildMessageManager::InProcessTabChildMessageManager(
-    nsDocShell* aShell, nsIContent* aOwner, nsFrameMessageManager* aChrome)
+    nsIDocShell* aShell, nsIContent* aOwner, nsFrameMessageManager* aChrome)
     : ContentFrameMessageManager(new nsFrameMessageManager(this)),
       mDocShell(aShell),
       mLoadingScript(false),
       mPreventEventsEscaping(false),
       mOwner(aOwner),
       mChromeMessageManager(aChrome) {
   mozilla::HoldJSObjects(this);
 
@@ -144,37 +142,39 @@ JSObject* InProcessTabChildMessageManage
   return ContentFrameMessageManager_Binding::Wrap(aCx, this, aGivenProto);
 }
 
 void InProcessTabChildMessageManager::CacheFrameLoader(
     nsFrameLoader* aFrameLoader) {
   mFrameLoader = aFrameLoader;
 }
 
-Nullable<WindowProxyHolder> InProcessTabChildMessageManager::GetContent(
-    ErrorResult& aError) {
-  if (!mDocShell) {
-    return nullptr;
+already_AddRefed<nsPIDOMWindowOuter>
+InProcessTabChildMessageManager::GetContent(ErrorResult& aError) {
+  nsCOMPtr<nsPIDOMWindowOuter> content;
+  if (mDocShell) {
+    content = mDocShell->GetWindow();
   }
-  return WindowProxyHolder(mDocShell->GetBrowsingContext());
+  return content.forget();
 }
 
 already_AddRefed<nsIEventTarget>
 InProcessTabChildMessageManager::GetTabEventTarget() {
   nsCOMPtr<nsIEventTarget> target = GetMainThreadEventTarget();
   return target.forget();
 }
 
 uint64_t InProcessTabChildMessageManager::ChromeOuterWindowID() {
   if (!mDocShell) {
     return 0;
   }
 
+  nsCOMPtr<nsIDocShellTreeItem> item = mDocShell;
   nsCOMPtr<nsIDocShellTreeItem> root;
-  nsresult rv = mDocShell->GetRootTreeItem(getter_AddRefs(root));
+  nsresult rv = item->GetRootTreeItem(getter_AddRefs(root));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return 0;
   }
 
   nsPIDOMWindowOuter* topWin = root->GetWindow();
   if (!topWin) {
     return 0;
   }
--- a/dom/base/InProcessTabChildMessageManager.h
+++ b/dom/base/InProcessTabChildMessageManager.h
@@ -12,17 +12,17 @@
 #include "mozilla/RefPtr.h"
 #include "mozilla/dom/ContentFrameMessageManager.h"
 #include "nsCOMPtr.h"
 #include "nsFrameMessageManager.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsIClassInfo.h"
-#include "nsDocShell.h"
+#include "nsIDocShell.h"
 #include "nsCOMArray.h"
 #include "nsIRunnable.h"
 #include "nsWeakReference.h"
 
 namespace mozilla {
 class EventChainPreVisitor;
 
 namespace dom {
@@ -37,22 +37,22 @@ class InProcessTabChildMessageManager fi
     : public ContentFrameMessageManager,
       public nsMessageManagerScriptExecutor,
       public nsIInProcessContentFrameMessageManager,
       public nsSupportsWeakReference,
       public mozilla::dom::ipc::MessageManagerCallback {
   typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData;
 
  private:
-  InProcessTabChildMessageManager(nsDocShell* aShell, nsIContent* aOwner,
+  InProcessTabChildMessageManager(nsIDocShell* aShell, nsIContent* aOwner,
                                   nsFrameMessageManager* aChrome);
 
  public:
   static already_AddRefed<InProcessTabChildMessageManager> Create(
-      nsDocShell* aShell, nsIContent* aOwner, nsFrameMessageManager* aChrome) {
+      nsIDocShell* aShell, nsIContent* aOwner, nsFrameMessageManager* aChrome) {
     RefPtr<InProcessTabChildMessageManager> mm =
         new InProcessTabChildMessageManager(aShell, aOwner, aChrome);
 
     NS_ENSURE_TRUE(mm->Init(), nullptr);
 
     return mm.forget();
   }
 
@@ -60,20 +60,22 @@ class InProcessTabChildMessageManager fi
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
       InProcessTabChildMessageManager, DOMEventTargetHelper)
 
   void MarkForCC();
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
-  Nullable<WindowProxyHolder> GetContent(ErrorResult& aError) override;
+  virtual already_AddRefed<nsPIDOMWindowOuter> GetContent(
+      ErrorResult& aError) override;
   virtual already_AddRefed<nsIDocShell> GetDocShell(
       ErrorResult& aError) override {
-    return do_AddRef(mDocShell);
+    nsCOMPtr<nsIDocShell> docShell(mDocShell);
+    return docShell.forget();
   }
   virtual already_AddRefed<nsIEventTarget> GetTabEventTarget() override;
   virtual uint64_t ChromeOuterWindowID() override;
 
   NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
 
   NS_DECL_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER
 
@@ -114,17 +116,17 @@ class InProcessTabChildMessageManager fi
     mChromeMessageManager = aParent;
   }
 
   already_AddRefed<nsFrameLoader> GetFrameLoader();
 
  protected:
   virtual ~InProcessTabChildMessageManager();
 
-  RefPtr<nsDocShell> mDocShell;
+  nsCOMPtr<nsIDocShell> mDocShell;
   bool mLoadingScript;
 
   // Is this the message manager for an in-process <iframe mozbrowser>? This
   // affects where events get sent, so it affects GetEventTargetParent.
   bool mIsBrowserFrame;
   bool mPreventEventsEscaping;
 
   // We keep a strong reference to the frameloader after we've started
--- a/dom/base/Location.h
+++ b/dom/base/Location.h
@@ -4,17 +4,16 @@
  * 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 mozilla_dom_Location_h
 #define mozilla_dom_Location_h
 
 #include "js/TypeDecls.h"
 #include "mozilla/ErrorResult.h"
-#include "mozilla/dom/BrowsingContext.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsString.h"
 #include "nsWrapperCache.h"
 
 class nsIDocShell;
 class nsIURI;
@@ -24,18 +23,16 @@ namespace mozilla {
 namespace dom {
 
 //*****************************************************************************
 // Location: Script "location" object
 //*****************************************************************************
 
 class Location final : public nsISupports, public nsWrapperCache {
  public:
-  typedef Location RemoteProxy;
-
   Location(nsPIDOMWindowInner* aWindow, nsIDocShell* aDocShell);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Location)
 
   // WebIDL API:
   void Assign(const nsAString& aUrl, nsIPrincipal& aSubjectPrincipal,
               ErrorResult& aError);
--- a/dom/base/PostMessageEvent.cpp
+++ b/dom/base/PostMessageEvent.cpp
@@ -14,61 +14,56 @@
 #include "mozilla/dom/MessageEventBinding.h"
 #include "mozilla/dom/MessagePort.h"
 #include "mozilla/dom/MessagePortBinding.h"
 #include "mozilla/dom/PMessagePort.h"
 #include "mozilla/dom/StructuredCloneTags.h"
 #include "mozilla/dom/UnionConversions.h"
 #include "mozilla/EventDispatcher.h"
 #include "nsContentUtils.h"
-#include "nsDocShell.h"
 #include "nsGlobalWindow.h"
-#include "nsIConsoleService.h"
 #include "nsIPresShell.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptError.h"
-#include "nsNetUtil.h"
 #include "nsPresContext.h"
 #include "nsQueryObject.h"
 
 namespace mozilla {
 namespace dom {
 
-PostMessageEvent::PostMessageEvent(BrowsingContext* aSource,
+PostMessageEvent::PostMessageEvent(nsGlobalWindowOuter* aSource,
                                    const nsAString& aCallerOrigin,
                                    nsGlobalWindowOuter* aTargetWindow,
                                    nsIPrincipal* aProvidedPrincipal,
-                                   const Maybe<uint64_t>& aCallerWindowID,
-                                   nsIURI* aCallerDocumentURI,
-                                   bool aIsFromPrivateWindow)
+                                   nsIDocument* aSourceDocument)
     : Runnable("dom::PostMessageEvent"),
+      StructuredCloneHolder(CloningSupported, TransferringSupported,
+                            StructuredCloneScope::SameProcessSameThread),
       mSource(aSource),
       mCallerOrigin(aCallerOrigin),
       mTargetWindow(aTargetWindow),
       mProvidedPrincipal(aProvidedPrincipal),
-      mCallerWindowID(aCallerWindowID),
-      mCallerDocumentURI(aCallerDocumentURI),
-      mIsFromPrivateWindow(aIsFromPrivateWindow) {}
+      mSourceDocument(aSourceDocument) {}
 
 PostMessageEvent::~PostMessageEvent() {}
 
 NS_IMETHODIMP
 PostMessageEvent::Run() {
   // 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 URI is just used for the principal mismatch error message
-  // below. Use a stack variable so mCallerDocumentURI is not held onto after
-  // this method finishes, regardless of the method outcome.
-  nsCOMPtr<nsIURI> callerDocumentURI;
-  callerDocumentURI.swap(mCallerDocumentURI);
+  // The document is just used for the principal mismatch error message below.
+  // Use a stack variable so mSourceDocument is not held onto after this method
+  // finishes, regardless of the method outcome.
+  nsCOMPtr<nsIDocument> sourceDocument;
+  sourceDocument.swap(mSourceDocument);
 
   // If we bailed before this point we're going to leak mMessage, but
   // that's probably better than crashing.
 
   RefPtr<nsGlobalWindowInner> targetWindow;
   if (mTargetWindow->IsClosedOrClosing() ||
       !(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) ||
       targetWindow->IsDying())
@@ -114,78 +109,44 @@ PostMessageEvent::Run() {
       nsAutoString providedOrigin, targetOrigin;
       nsresult rv = nsContentUtils::GetUTFOrigin(targetPrin, targetOrigin);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = nsContentUtils::GetUTFOrigin(mProvidedPrincipal, providedOrigin);
       NS_ENSURE_SUCCESS(rv, rv);
 
       const char16_t* params[] = {providedOrigin.get(), targetOrigin.get()};
 
-      nsAutoString errorText;
-      nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
-                                            "TargetPrincipalDoesNotMatch",
-                                            params, errorText);
-
-      nsCOMPtr<nsIScriptError> errorObject =
-          do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
-      NS_ENSURE_SUCCESS(rv, rv);
+      nsContentUtils::ReportToConsole(
+          nsIScriptError::errorFlag, NS_LITERAL_CSTRING("DOM Window"),
+          sourceDocument, nsContentUtils::eDOM_PROPERTIES,
+          "TargetPrincipalDoesNotMatch", params, ArrayLength(params));
 
-      if (mCallerWindowID.isSome()) {
-        rv = errorObject->InitWithSourceURI(
-            errorText, callerDocumentURI, EmptyString(), 0, 0,
-            nsIScriptError::errorFlag, "DOM Window", mCallerWindowID.value());
-      } else {
-        nsString uriSpec;
-        rv = NS_GetSanitizedURIStringFromURI(callerDocumentURI, uriSpec);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        rv = errorObject->Init(errorText, uriSpec, EmptyString(), 0, 0,
-                               nsIScriptError::errorFlag, "DOM Window",
-                               mIsFromPrivateWindow);
-      }
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      nsCOMPtr<nsIConsoleService> consoleService =
-          do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      return consoleService->LogMessage(errorObject);
+      return NS_OK;
     }
   }
 
   IgnoredErrorResult rv;
   JS::Rooted<JS::Value> messageData(cx);
   nsCOMPtr<mozilla::dom::EventTarget> eventTarget =
       do_QueryObject(targetWindow);
 
-  StructuredCloneHolder* holder;
-  if (mHolder.constructed<StructuredCloneHolder>()) {
-    mHolder.ref<StructuredCloneHolder>().Read(targetWindow->AsInner(), cx,
-                                              &messageData, rv);
-    holder = &mHolder.ref<StructuredCloneHolder>();
-  } else {
-    MOZ_ASSERT(mHolder.constructed<ipc::StructuredCloneData>());
-    mHolder.ref<ipc::StructuredCloneData>().Read(cx, &messageData, rv);
-    holder = &mHolder.ref<ipc::StructuredCloneData>();
-  }
+  Read(targetWindow->AsInner(), cx, &messageData, rv);
   if (NS_WARN_IF(rv.Failed())) {
     DispatchError(cx, targetWindow, eventTarget);
     return NS_OK;
   }
 
   // Create the event
   RefPtr<MessageEvent> event = new MessageEvent(eventTarget, nullptr, nullptr);
 
   Nullable<WindowProxyOrMessagePortOrServiceWorker> source;
-  if (mSource) {
-    source.SetValue().SetAsWindowProxy() = mSource;
-  }
+  source.SetValue().SetAsWindowProxy() = mSource ? mSource->AsOuter() : nullptr;
 
   Sequence<OwningNonNull<MessagePort>> ports;
-  if (!holder->TakeTransferredPortsAsSequence(ports)) {
+  if (!TakeTransferredPortsAsSequence(ports)) {
     DispatchError(cx, targetWindow, eventTarget);
     return NS_OK;
   }
 
   event->InitMessageEvent(nullptr, NS_LITERAL_STRING("message"), CanBubble::eNo,
                           Cancelable::eNo, messageData, mCallerOrigin,
                           EmptyString(), source, ports);
 
@@ -197,17 +158,17 @@ void PostMessageEvent::DispatchError(JSC
                                      nsGlobalWindowInner* aTargetWindow,
                                      mozilla::dom::EventTarget* aEventTarget) {
   RootedDictionary<MessageEventInit> init(aCx);
   init.mBubbles = false;
   init.mCancelable = false;
   init.mOrigin = mCallerOrigin;
 
   if (mSource) {
-    init.mSource.SetValue().SetAsWindowProxy() = mSource;
+    init.mSource.SetValue().SetAsWindowProxy() = mSource->AsOuter();
   }
 
   RefPtr<Event> event = MessageEvent::Constructor(
       aEventTarget, NS_LITERAL_STRING("messageerror"), init);
   Dispatch(aTargetWindow, event);
 }
 
 void PostMessageEvent::Dispatch(nsGlobalWindowInner* aTargetWindow,
--- a/dom/base/PostMessageEvent.h
+++ b/dom/base/PostMessageEvent.h
@@ -3,102 +3,54 @@
 /* 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 mozilla_dom_PostMessageEvent_h
 #define mozilla_dom_PostMessageEvent_h
 
 #include "mozilla/dom/Event.h"
-#include "mozilla/dom/ipc/StructuredCloneData.h"
 #include "mozilla/dom/StructuredCloneHolder.h"
 #include "nsCOMPtr.h"
-#include "mozilla/MaybeOneOf.h"
 #include "mozilla/RefPtr.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 
 class nsGlobalWindowOuter;
 class nsGlobalWindowInner;
 class nsIDocument;
 class nsIPrincipal;
 
 namespace mozilla {
 namespace dom {
 
-class BrowsingContext;
-
 /**
  * Class used to represent events generated by calls to Window.postMessage,
  * which asynchronously creates and dispatches events.
  */
-class PostMessageEvent final : public Runnable {
+class PostMessageEvent final : public Runnable, public StructuredCloneHolder {
  public:
   NS_DECL_NSIRUNNABLE
 
-  // aCallerWindowID should not be 0.
-  PostMessageEvent(BrowsingContext* aSource, const nsAString& aCallerOrigin,
-                   nsGlobalWindowOuter* aTargetWindow,
-                   nsIPrincipal* aProvidedPrincipal, uint64_t aCallerWindowID,
-                   nsIURI* aCallerDocumentURI)
-      : PostMessageEvent(aSource, aCallerOrigin, aTargetWindow,
-                         aProvidedPrincipal, Some(aCallerWindowID),
-                         aCallerDocumentURI, false) {}
-
-  // To be used if there is no WindowID for the PostMessage caller's window (for
-  // example because it lives in a different process).
-  PostMessageEvent(BrowsingContext* aSource, const nsAString& aCallerOrigin,
+  PostMessageEvent(nsGlobalWindowOuter* aSource, const nsAString& aCallerOrigin,
                    nsGlobalWindowOuter* aTargetWindow,
-                   nsIPrincipal* aProvidedPrincipal, nsIURI* aCallerDocumentURI,
-                   bool aIsFromPrivateWindow)
-      : PostMessageEvent(aSource, aCallerOrigin, aTargetWindow,
-                         aProvidedPrincipal, Nothing(), aCallerDocumentURI,
-                         aIsFromPrivateWindow) {}
-
-  void Write(JSContext* aCx, JS::Handle<JS::Value> aMessage,
-             JS::Handle<JS::Value> aTransfer, ErrorResult& aError) {
-    mHolder.construct<StructuredCloneHolder>(
-        StructuredCloneHolder::CloningSupported,
-        StructuredCloneHolder::TransferringSupported,
-        JS::StructuredCloneScope::SameProcessSameThread);
-    mHolder.ref<StructuredCloneHolder>().Write(aCx, aMessage, aTransfer,
-                                               JS::CloneDataPolicy(), aError);
-  }
-  void UnpackFrom(const ClonedMessageData& aMessageData) {
-    mHolder.construct<ipc::StructuredCloneData>();
-    // FIXME Want to steal!
-    //       See https://bugzilla.mozilla.org/show_bug.cgi?id=1516349.
-    mHolder.ref<ipc::StructuredCloneData>().CopyFromClonedMessageDataForChild(
-        aMessageData);
-  }
+                   nsIPrincipal* aProvidedPrincipal,
+                   nsIDocument* aSourceDocument);
 
  private:
-  PostMessageEvent(BrowsingContext* aSource, const nsAString& aCallerOrigin,
-                   nsGlobalWindowOuter* aTargetWindow,
-                   nsIPrincipal* aProvidedPrincipal,
-                   const Maybe<uint64_t>& aCallerWindowID,
-                   nsIURI* aCallerDocumentURI, bool aIsFromPrivateWindow);
   ~PostMessageEvent();
 
   void Dispatch(nsGlobalWindowInner* aTargetWindow, Event* aEvent);
 
   void DispatchError(JSContext* aCx, nsGlobalWindowInner* aTargetWindow,
                      mozilla::dom::EventTarget* aEventTarget);
 
-  RefPtr<BrowsingContext> mSource;
+  RefPtr<nsGlobalWindowOuter> mSource;
   nsString mCallerOrigin;
   RefPtr<nsGlobalWindowOuter> mTargetWindow;
   nsCOMPtr<nsIPrincipal> mProvidedPrincipal;
-  // If the postMessage call was made on a WindowProxy whose Window lives in a
-  // separate process then mHolder will contain a StructuredCloneData, else
-  // it'll contain a StructuredCloneHolder.
-  MaybeOneOf<StructuredCloneHolder, ipc::StructuredCloneData> mHolder;
-  Maybe<uint64_t> mCallerWindowID;
-  nsCOMPtr<nsIURI> mCallerDocumentURI;
-  // This is only set to a relevant value if mCallerWindowID doesn't contain a
-  // value.
-  bool mIsFromPrivateWindow;
+  nsCOMPtr<nsIDocument> mSourceDocument;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // mozilla_dom_PostMessageEvent_h
deleted file mode 100644
--- a/dom/base/RemoteOuterWindowProxy.cpp
+++ /dev/null
@@ -1,194 +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 "AccessCheck.h"
-#include "js/Proxy.h"
-#include "mozilla/dom/BrowsingContext.h"
-#include "mozilla/dom/RemoteObjectProxy.h"
-#include "mozilla/dom/WindowBinding.h"
-#include "xpcprivate.h"
-
-namespace mozilla {
-namespace dom {
-
-/**
- * RemoteOuterWindowProxy is the proxy handler for the WindowProxy objects for
- * Window objects that live in a different process.
- *
- * RemoteOuterWindowProxy holds a BrowsingContext, which is cycle collected.
- * However, RemoteOuterWindowProxy only holds BrowsingContexts that don't have a
- * reference to a docshell, so there's no need to declare the edge from
- * RemoteOuterWindowProxy to its BrowsingContext to the cycle collector.
- *
- * FIXME Verify that this is correct:
- *       https://bugzilla.mozilla.org/show_bug.cgi?id=1516350.
- */
-
-class RemoteOuterWindowProxy
-    : public RemoteObjectProxy<BrowsingContext,
-                               Window_Binding::sCrossOriginAttributes,
-                               Window_Binding::sCrossOriginMethods> {
- public:
-  constexpr RemoteOuterWindowProxy()
-      : RemoteObjectProxy(prototypes::id::Window) {}
-
-  // Standard internal methods
-  bool getOwnPropertyDescriptor(
-      JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
-      JS::MutableHandle<JS::PropertyDescriptor> aDesc) const final;
-  bool ownPropertyKeys(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                       JS::AutoIdVector& aProps) const final;
-
-  // SpiderMonkey extensions
-  bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
-                                    JS::AutoIdVector& props) const final;
-  void finalize(JSFreeOp* aFop, JSObject* aProxy) const final;
-  const char* className(JSContext* aCx,
-                        JS::Handle<JSObject*> aProxy) const final;
-};
-
-static const RemoteOuterWindowProxy sSingleton;
-
-// Give RemoteOuterWindowProxyClass 2 reserved slots, like the other wrappers,
-// so JSObject::swap can swap it with CrossCompartmentWrappers without requiring
-// malloc.
-const js::Class RemoteOuterWindowProxyClass =
-    PROXY_CLASS_DEF("Proxy", JSCLASS_HAS_RESERVED_SLOTS(2));
-
-bool GetRemoteOuterWindowProxy(JSContext* aCx, BrowsingContext* aContext,
-                               JS::MutableHandle<JSObject*> aRetVal) {
-  MOZ_ASSERT(!aContext->GetDocShell(),
-             "Why are we creating a RemoteOuterWindowProxy?");
-
-  xpc::CompartmentPrivate* priv =
-      xpc::CompartmentPrivate::Get(JS::CurrentGlobalOrNull(aCx));
-  xpc::CompartmentPrivate::RemoteProxyMap& map = priv->GetRemoteProxyMap();
-  auto result = map.lookupForAdd(aContext);
-  if (result) {
-    aRetVal.set(result->value());
-    return true;
-  }
-
-  JS::Rooted<JSObject*> obj(
-      aCx, sSingleton.CreateProxyObject(aCx, aContext,
-                                        &RemoteOuterWindowProxyClass));
-  if (!obj) {
-    return false;
-  }
-  NS_ADDREF(aContext);
-
-  if (!map.add(result, aContext, obj)) {
-    JS_ReportOutOfMemory(aCx);
-    return false;
-  }
-
-  aRetVal.set(obj);
-  return true;
-}
-
-static BrowsingContext* GetBrowsingContext(JSObject* aProxy) {
-  MOZ_ASSERT(IsRemoteObjectProxy(aProxy, prototypes::id::Window));
-  return static_cast<BrowsingContext*>(
-      RemoteObjectProxyBase::GetNative(aProxy));
-}
-
-bool WrapResult(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                BrowsingContext* aResult, unsigned attrs,
-                JS::MutableHandle<JS::PropertyDescriptor> aDesc) {
-  JS::Rooted<JS::Value> v(aCx);
-  if (!ToJSValue(aCx, WindowProxyHolder(aResult), &v)) {
-    return false;
-  }
-  aDesc.object().set(aProxy);
-  aDesc.setDataDescriptor(v, attrs);
-  return true;
-}
-
-bool RemoteOuterWindowProxy::getOwnPropertyDescriptor(
-    JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
-    JS::MutableHandle<JS::PropertyDescriptor> aDesc) const {
-  BrowsingContext* bc = GetBrowsingContext(aProxy);
-  uint32_t index = GetArrayIndexFromId(aId);
-  if (IsArrayIndex(index)) {
-    const BrowsingContext::Children& children = bc->GetChildren();
-    if (index < children.Length()) {
-      return WrapResult(aCx, aProxy, children[index],
-                        JSPROP_READONLY | JSPROP_ENUMERATE, aDesc);
-    }
-    return ReportCrossOriginDenial(aCx, aId, NS_LITERAL_CSTRING("access"));
-  }
-
-  bool ok = RemoteObjectProxy::getOwnPropertyDescriptorInternal(aCx, aProxy,
-                                                                aId, aDesc);
-  if (!ok || aDesc.object()) {
-    return ok;
-  }
-
-  if (JSID_IS_STRING(aId)) {
-    nsAutoJSString str;
-    if (!str.init(aCx, JSID_TO_STRING(aId))) {
-      return false;
-    }
-
-    for (BrowsingContext* child : bc->GetChildren()) {
-      if (child->NameEquals(str)) {
-        return WrapResult(aCx, aProxy, child, JSPROP_READONLY, aDesc);
-      }
-    }
-  }
-
-  return getOwnPropertyDescriptorTail(aCx, aProxy, aId, aDesc);
-}
-
-bool AppendIndexedPropertyNames(JSContext* aCx, BrowsingContext* aContext,
-                                JS::AutoIdVector& aIndexedProps) {
-  int32_t length = aContext->GetChildren().Length();
-  if (!aIndexedProps.reserve(aIndexedProps.length() + length)) {
-    return false;
-  }
-
-  for (int32_t i = 0; i < length; ++i) {
-    aIndexedProps.infallibleAppend(INT_TO_JSID(i));
-  }
-  return true;
-}
-
-bool RemoteOuterWindowProxy::ownPropertyKeys(JSContext* aCx,
-                                             JS::Handle<JSObject*> aProxy,
-                                             JS::AutoIdVector& aProps) const {
-  BrowsingContext* bc = GetBrowsingContext(aProxy);
-
-  // https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-ownpropertykeys:crossoriginownpropertykeys-(-o-)
-  // step 3 to 5
-  if (!AppendIndexedPropertyNames(aCx, bc, aProps)) {
-    return false;
-  }
-
-  // https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-ownpropertykeys:crossoriginownpropertykeys-(-o-)
-  // step 7
-  return RemoteObjectProxy::ownPropertyKeys(aCx, aProxy, aProps);
-}
-
-bool RemoteOuterWindowProxy::getOwnEnumerablePropertyKeys(
-    JSContext* aCx, JS::Handle<JSObject*> aProxy,
-    JS::AutoIdVector& aProps) const {
-  return AppendIndexedPropertyNames(aCx, GetBrowsingContext(aProxy), aProps);
-}
-
-void RemoteOuterWindowProxy::finalize(JSFreeOp* aFop, JSObject* aProxy) const {
-  BrowsingContext* bc = GetBrowsingContext(aProxy);
-  RefPtr<BrowsingContext> self(dont_AddRef(bc));
-}
-
-const char* RemoteOuterWindowProxy::className(
-    JSContext* aCx, JS::Handle<JSObject*> aProxy) const {
-  MOZ_ASSERT(js::IsProxy(aProxy));
-
-  return "Object";
-}
-
-}  // namespace dom
-}  // namespace mozilla
--- a/dom/base/WindowNamedPropertiesHandler.cpp
+++ b/dom/base/WindowNamedPropertiesHandler.cpp
@@ -13,25 +13,24 @@
 #include "nsHTMLDocument.h"
 #include "nsJSUtils.h"
 #include "xpcprivate.h"
 
 namespace mozilla {
 namespace dom {
 
 static bool ShouldExposeChildWindow(nsString& aNameBeingResolved,
-                                    BrowsingContext* aChild) {
-  nsPIDOMWindowOuter* child = aChild->GetDOMWindow();
-  Element* e = child->GetFrameElementInternal();
+                                    nsPIDOMWindowOuter* aChild) {
+  Element* e = aChild->GetFrameElementInternal();
   if (e && e->IsInShadowTree()) {
     return false;
   }
 
   // If we're same-origin with the child, go ahead and expose it.
-  nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(child);
+  nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aChild);
   NS_ENSURE_TRUE(sop, false);
   if (nsContentUtils::SubjectPrincipal()->Equals(sop->GetPrincipal())) {
     return true;
   }
 
   // If we're not same-origin, expose it _only_ if the name of the browsing
   // context matches the 'name' attribute of the frame element in the parent.
   // The motivations behind this heuristic are worth explaining here.
@@ -96,23 +95,23 @@ bool WindowNamedPropertiesHandler::getOw
 
   if (str.IsEmpty()) {
     return true;
   }
 
   // Grab the DOM window.
   nsGlobalWindowInner* win = xpc::WindowGlobalOrNull(aProxy);
   if (win->Length() > 0) {
-    RefPtr<BrowsingContext> child = win->GetChildWindow(str);
-    if (child && ShouldExposeChildWindow(str, child)) {
+    nsCOMPtr<nsPIDOMWindowOuter> childWin = win->GetChildWindow(str);
+    if (childWin && ShouldExposeChildWindow(str, childWin)) {
       // We found a subframe of the right name. Shadowing via |var foo| in
       // global scope is still allowed, since |var| only looks up |own|
       // properties. But unqualified shadowing will fail, per-spec.
       JS::Rooted<JS::Value> v(aCx);
-      if (!ToJSValue(aCx, WindowProxyHolder(child.forget()), &v)) {
+      if (!ToJSValue(aCx, nsGlobalWindowOuter::Cast(childWin), &v)) {
         return false;
       }
       FillPropertyDescriptor(aDesc, aProxy, 0, v);
       return true;
     }
   }
 
   // The rest of this function is for HTML documents only.
@@ -178,18 +177,18 @@ bool WindowNamedPropertiesHandler::ownPr
         // item->GetWindow().  But it's not obvious whether this does the same
         // thing as GetChildWindow() with the item's name (due to the complexity
         // of FindChildWithName).  Since GetChildWindow is what we use in
         // getOwnPropDescriptor, let's try to be consistent.
         nsString name;
         item->GetName(name);
         if (!names.Contains(name)) {
           // Make sure we really would expose it from getOwnPropDescriptor.
-          RefPtr<BrowsingContext> child = win->GetChildWindow(name);
-          if (child && ShouldExposeChildWindow(name, child)) {
+          nsCOMPtr<nsPIDOMWindowOuter> childWin = win->GetChildWindow(name);
+          if (childWin && ShouldExposeChildWindow(name, childWin)) {
             names.AppendElement(name);
           }
         }
       }
     }
   }
   if (!AppendNamedPropertyIds(aCx, aProxy, names, false, aProps)) {
     return false;
deleted file mode 100644
--- a/dom/base/WindowProxyHolder.h
+++ /dev/null
@@ -1,78 +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/. */
-
-#ifndef mozilla_dom_WindowProxyHolder_h__
-#define mozilla_dom_WindowProxyHolder_h__
-
-#include "mozilla/dom/BrowsingContext.h"
-
-struct JSContext;
-class JSObject;
-
-namespace JS {
-template <typename T>
-class MutableHandle;
-}  // namespace JS
-
-namespace mozilla {
-namespace dom {
-
-/**
- * This class is used for passing arguments and the return value for WebIDL
- * binding code that takes/returns a WindowProxy object and for WebIDL
- * unions/dictionaries that contain a WindowProxy member. It should never
- * contain null; if the value in WebIDL is nullable the binding code will use a
- * Nullable<WindowProxyHolder>.
- */
-class WindowProxyHolder {
- public:
-  WindowProxyHolder() = default;
-  explicit WindowProxyHolder(BrowsingContext* aBC) : mBrowsingContext(aBC) {
-    MOZ_ASSERT(mBrowsingContext, "Don't set WindowProxyHolder to null.");
-  }
-  explicit WindowProxyHolder(already_AddRefed<BrowsingContext>&& aBC)
-      : mBrowsingContext(std::move(aBC)) {
-    MOZ_ASSERT(mBrowsingContext, "Don't set WindowProxyHolder to null.");
-  }
-  WindowProxyHolder& operator=(BrowsingContext* aBC) {
-    mBrowsingContext = aBC;
-    MOZ_ASSERT(mBrowsingContext, "Don't set WindowProxyHolder to null.");
-    return *this;
-  }
-  WindowProxyHolder& operator=(already_AddRefed<BrowsingContext>&& aBC) {
-    mBrowsingContext = std::move(aBC);
-    MOZ_ASSERT(mBrowsingContext, "Don't set WindowProxyHolder to null.");
-    return *this;
-  }
-
-  BrowsingContext* get() const {
-    MOZ_ASSERT(mBrowsingContext, "WindowProxyHolder hasn't been initialized.");
-    return mBrowsingContext;
-  }
-
- private:
-  friend void ImplCycleCollectionUnlink(WindowProxyHolder& aProxy);
-
-  RefPtr<BrowsingContext> mBrowsingContext;
-};
-
-inline void ImplCycleCollectionTraverse(
-    nsCycleCollectionTraversalCallback& aCallback, WindowProxyHolder& aProxy,
-    const char* aName, uint32_t aFlags = 0) {
-  CycleCollectionNoteChild(aCallback, aProxy.get(), "mBrowsingContext", aFlags);
-}
-
-inline void ImplCycleCollectionUnlink(WindowProxyHolder& aProxy) {
-  aProxy.mBrowsingContext = nullptr;
-}
-
-extern bool GetRemoteOuterWindowProxy(JSContext* aCx, BrowsingContext* aContext,
-                                      JS::MutableHandle<JSObject*> aValue);
-
-}  // namespace dom
-}  // namespace mozilla
-
-#endif /* mozilla_dom_WindowProxyHolder_h__ */
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -206,17 +206,16 @@ EXPORTS.mozilla.dom += [
     'PlacesBookmark.h',
     'PlacesBookmarkAddition.h',
     'PlacesEvent.h',
     'PlacesObservers.h',
     'PlacesVisit.h',
     'PlacesWeakCallbackWrapper.h',
     'PopupBlocker.h',
     'Pose.h',
-    'PostMessageEvent.h',
     'ProcessMessageManager.h',
     'ResponsiveImageSelector.h',
     'SameProcessMessageQueue.h',
     'ScreenLuminance.h',
     'ScreenOrientation.h',
     'Selection.h',
     'ShadowRoot.h',
     'StructuredCloneBlob.h',
@@ -231,17 +230,16 @@ EXPORTS.mozilla.dom += [
     'Timeout.h',
     'TimeoutHandler.h',
     'TimeoutManager.h',
     'TreeIterator.h',
     'TreeWalker.h',
     'VisualViewport.h',
     'WebKitCSSMatrix.h',
     'WindowOrientationObserver.h',
-    'WindowProxyHolder.h',
 ]
 
 if CONFIG['FUZZING']:
     EXPORTS.mozilla.dom += [
         'FuzzingFunctions.h',
     ]
 
 UNIFIED_SOURCES += [
@@ -365,17 +363,16 @@ UNIFIED_SOURCES += [
     'nsWrapperCache.cpp',
     'nsXHTMLContentSerializer.cpp',
     'nsXMLContentSerializer.cpp',
     'ParentProcessMessageManager.cpp',
     'PopupBlocker.cpp',
     'Pose.cpp',
     'PostMessageEvent.cpp',
     'ProcessMessageManager.cpp',
-    'RemoteOuterWindowProxy.cpp',
     'ResponsiveImageSelector.cpp',
     'SameProcessMessageQueue.cpp',
     'ScreenLuminance.cpp',
     'ScreenOrientation.cpp',
     'Selection.cpp',
     'SelectionChangeEventDispatcher.cpp',
     'ShadowRoot.cpp',
     'StorageAccessPermissionRequest.cpp',
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -289,17 +289,16 @@
 #include "mozilla/RestyleManager.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "nsHTMLTags.h"
 #include "NodeUbiReporting.h"
 #include "nsICookieService.h"
 #include "mozilla/net/ChannelEventQueue.h"
 #include "mozilla/net/RequestContextService.h"
 #include "StorageAccessPermissionRequest.h"
-#include "mozilla/dom/WindowProxyHolder.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 typedef nsTArray<Link*> LinkArray;
 
 static LazyLogModule gDocumentLeakPRLog("DocumentLeak");
 static LazyLogModule gCspPRLog("CSP");
@@ -3364,24 +3363,16 @@ nsresult nsIDocument::GetSrcdocData(nsAS
     if (inStrmChan) {
       return inStrmChan->GetSrcdocData(aSrcdocData);
     }
   }
   aSrcdocData = VoidString();
   return NS_OK;
 }
 
-Nullable<WindowProxyHolder> nsIDocument::GetDefaultView() const {
-  nsPIDOMWindowOuter* win = GetWindow();
-  if (!win) {
-    return nullptr;
-  }
-  return WindowProxyHolder(win->GetBrowsingContext());
-}
-
 Element* nsIDocument::GetActiveElement() {
   // Get the focused element.
   Element* focusedElement = GetRetargetedFocusedElement();
   if (focusedElement) {
     return focusedElement;
   }
 
   // No focused element anywhere in this document.  Try to get the BODY.
@@ -5704,17 +5695,19 @@ already_AddRefed<TreeWalker> nsIDocument
 
 already_AddRefed<Location> nsIDocument::GetLocation() const {
   nsCOMPtr<nsPIDOMWindowInner> w = do_QueryInterface(mScriptGlobalObject);
 
   if (!w) {
     return nullptr;
   }
 
-  return do_AddRef(w->Location());
+  nsGlobalWindowInner* window = nsGlobalWindowInner::Cast(w);
+  RefPtr<Location> loc = window->GetLocation();
+  return loc.forget();
 }
 
 Element* nsIDocument::GetHtmlElement() const {
   Element* rootElement = GetRootElement();
   if (rootElement && rootElement->IsHTMLElement(nsGkAtoms::html))
     return rootElement;
   return nullptr;
 }
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -498,17 +498,17 @@ nsresult nsFrameLoader::CheckURILoad(nsI
 
   // Bail out if this is an infinite recursion scenario
   if (IsRemoteFrame()) {
     return NS_OK;
   }
   return CheckForRecursiveLoad(aURI);
 }
 
-nsDocShell* nsFrameLoader::GetDocShell(ErrorResult& aRv) {
+nsIDocShell* nsFrameLoader::GetDocShell(ErrorResult& aRv) {
   if (IsRemoteFrame()) {
     return nullptr;
   }
 
   // If we have an owner, make sure we have a docshell and return
   // that. If not, we're most likely in the middle of being torn down,
   // then we just return null.
   if (mOwnerContent) {
@@ -670,37 +670,41 @@ bool nsFrameLoader::Show(int32_t marginW
   NS_ASSERTION(mDocShell, "MaybeCreateDocShell succeeded, but null mDocShell");
   if (!mDocShell) {
     return false;
   }
 
   mDocShell->SetMarginWidth(marginWidth);
   mDocShell->SetMarginHeight(marginHeight);
 
-  mDocShell->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,
-                                            scrollbarPrefX);
-  mDocShell->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,
-                                            scrollbarPrefY);
+  nsCOMPtr<nsIScrollable> sc = do_QueryInterface(mDocShell);
+  if (sc) {
+    sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,
+                                       scrollbarPrefX);
+    sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,
+                                       scrollbarPrefY);
+  }
 
   nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
   if (presShell) {
     // Ensure root scroll frame is reflowed in case scroll preferences or
     // margins have changed
     nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
     if (rootScrollFrame) {
       presShell->FrameNeedsReflow(rootScrollFrame, nsIPresShell::eResize,
                                   NS_FRAME_IS_DIRTY);
     }
     return true;
   }
 
   nsView* view = frame->EnsureInnerView();
   if (!view) return false;
 
-  RefPtr<nsDocShell> baseWindow = mDocShell;
+  nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(mDocShell);
+  NS_ASSERTION(baseWindow, "Found a nsIDocShell that isn't a nsIBaseWindow.");
   baseWindow->InitWindow(nullptr, view->GetWidget(), 0, 0, size.width,
                          size.height);
   // This is kinda whacky, this "Create()" call doesn't really
   // create anything, one starts to wonder why this was named
   // "Create"...
   baseWindow->Create();
   baseWindow->SetVisibility(true);
   NS_ENSURE_TRUE(mDocShell, false);
@@ -849,17 +853,19 @@ void nsFrameLoader::Hide() {
   }
 
   if (!mDocShell) return;
 
   nsCOMPtr<nsIContentViewer> contentViewer;
   mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
   if (contentViewer) contentViewer->SetSticky(false);
 
-  RefPtr<nsDocShell> baseWin = mDocShell;
+  nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mDocShell);
+  NS_ASSERTION(baseWin,
+               "Found an nsIDocShell which doesn't implement nsIBaseWindow.");
   baseWin->SetVisibility(false);
   baseWin->SetParentWidget(nullptr);
 }
 
 void nsFrameLoader::ForceLayoutIfNecessary() {
   nsIFrame* frame = GetPrimaryFrameOfOwningContent();
   if (!frame) {
     return;
@@ -1666,18 +1672,19 @@ void nsFrameLoader::DestroyDocShell() {
   }
 
   // Fire the "unload" event if we're in-process.
   if (mChildMessageManager) {
     mChildMessageManager->FireUnloadEvent();
   }
 
   // Destroy the docshell.
-  if (mDocShell) {
-    mDocShell->Destroy();
+  nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
+  if (base_win) {
+    base_win->Destroy();
   }
   mDocShell = nullptr;
 
   if (mChildMessageManager) {
     // Stop handling events in the in-process frame script.
     mChildMessageManager->DisconnectEventListeners();
   }
 }
@@ -1965,18 +1972,18 @@ nsresult nsFrameLoader::MaybeCreateDocSh
                                  nsGkAtoms::allowscriptstoclose,
                                  nsGkAtoms::_true, eCaseMatters)) {
     nsGlobalWindowOuter::Cast(newWindow)->AllowScriptsToClose();
   }
 
   // This is kinda whacky, this call doesn't really create anything,
   // but it must be called to make sure things are properly
   // initialized.
-  RefPtr<nsDocShell> docShell = mDocShell;
-  if (NS_FAILED(docShell->Create())) {
+  nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mDocShell);
+  if (NS_FAILED(baseWin->Create())) {
     // Do not call Destroy() here. See bug 472312.
     NS_WARNING("Something wrong when creating the docshell for a frameloader!");
     return NS_ERROR_FAILURE;
   }
 
   // If we are an in-process browser, we want to set up our session history. We
   // do this by creating both the child SHistory (which is in the nsDocShell),
   // and creating the corresponding in-process ParentSHistory.
@@ -2285,17 +2292,18 @@ nsresult nsFrameLoader::UpdatePositionAn
     return NS_OK;
   }
   UpdateBaseWindowPositionAndSize(aIFrame);
   return NS_OK;
 }
 
 void nsFrameLoader::UpdateBaseWindowPositionAndSize(
     nsSubDocumentFrame* aIFrame) {
-  nsCOMPtr<nsIBaseWindow> baseWindow = GetDocShell(IgnoreErrors());
+  nsCOMPtr<nsIBaseWindow> baseWindow =
+      do_QueryInterface(GetDocShell(IgnoreErrors()));
 
   // resize the sub document
   if (baseWindow) {
     int32_t x = 0;
     int32_t y = 0;
 
     AutoWeakFrame weakFrame(aIFrame);
 
@@ -3004,17 +3012,17 @@ already_AddRefed<nsITabParent> nsFrameLo
   return do_AddRef(mRemoteBrowser);
 }
 
 already_AddRefed<nsILoadContext> nsFrameLoader::LoadContext() {
   nsCOMPtr<nsILoadContext> loadContext;
   if (IsRemoteFrame() && (mRemoteBrowser || TryRemoteBrowser())) {
     loadContext = mRemoteBrowser->GetLoadContext();
   } else {
-    loadContext = do_GetInterface(ToSupports(GetDocShell(IgnoreErrors())));
+    loadContext = do_GetInterface(GetDocShell(IgnoreErrors()));
   }
   return loadContext.forget();
 }
 
 already_AddRefed<BrowsingContext> nsFrameLoader::GetBrowsingContext() {
   RefPtr<BrowsingContext> browsingContext;
   if (IsRemoteFrame() && (mRemoteBrowser || TryRemoteBrowser())) {
     browsingContext = mRemoteBrowser->GetBrowsingContext();
--- a/dom/base/nsFrameLoader.h
+++ b/dom/base/nsFrameLoader.h
@@ -7,17 +7,17 @@
 /*
  * Class for managing loading of a subframe (creation of the docshell,
  * handling of loads in it, recursion-checking).
  */
 
 #ifndef nsFrameLoader_h_
 #define nsFrameLoader_h_
 
-#include "nsDocShell.h"
+#include "nsIDocShell.h"
 #include "nsStringFwd.h"
 #include "nsIFrameLoaderOwner.h"
 #include "nsPoint.h"
 #include "nsSize.h"
 #include "nsWrapperCache.h"
 #include "nsIURI.h"
 #include "nsFrameMessageManager.h"
 #include "mozilla/dom/BindingUtils.h"
@@ -113,17 +113,17 @@ class nsFrameLoader final : public nsStu
       const {
     return mChildMessageManager;
   }
   nsresult CreateStaticClone(nsFrameLoader* aDest);
   nsresult UpdatePositionAndSize(nsSubDocumentFrame* aIFrame);
 
   // WebIDL methods
 
-  nsDocShell* GetDocShell(mozilla::ErrorResult& aRv);
+  nsIDocShell* GetDocShell(mozilla::ErrorResult& aRv);
 
   already_AddRefed<nsITabParent> GetTabParent();
 
   already_AddRefed<nsILoadContext> LoadContext();
 
   already_AddRefed<mozilla::dom::BrowsingContext> GetBrowsingContext();
 
   /**
@@ -424,17 +424,17 @@ class nsFrameLoader final : public nsStu
   nsresult GetNewTabContext(mozilla::dom::MutableTabContext* aTabContext,
                             nsIURI* aURI = nullptr);
 
   enum TabParentChange { eTabParentRemoved, eTabParentChanged };
   void MaybeUpdatePrimaryTabParent(TabParentChange aChange);
 
   nsresult PopulateUserContextIdFromAttribute(mozilla::OriginAttributes& aAttr);
 
-  RefPtr<nsDocShell> mDocShell;
+  nsCOMPtr<nsIDocShell> mDocShell;
   nsCOMPtr<nsIURI> mURIToLoad;
   nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
   mozilla::dom::Element* mOwnerContent;  // WEAK
 
   // After the frameloader has been removed from the DOM but before all of the
   // messages from the frame have been received, we keep a strong reference to
   // our <browser> element.
   RefPtr<mozilla::dom::Element> mOwnerContentStrong;
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -294,38 +294,29 @@ using mozilla::dom::cache::CacheStorage;
   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
 
-static nsGlobalWindowOuter* GetOuterWindowForForwarding(
-    nsGlobalWindowInner* aInner, ErrorResult& aError) {
-  nsGlobalWindowOuter* outer = aInner->GetOuterWindowInternal();
-  if (MOZ_LIKELY(aInner->HasActiveDocument())) {
-    return outer;
-  }
-  if (!outer) {
-    NS_WARNING("No outer window available!");
-    aError.Throw(NS_ERROR_NOT_INITIALIZED);
-  } else {
-    aError.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO);
-  }
-  return nullptr;
-}
-
-#define FORWARD_TO_OUTER_OR_THROW(method, args, errorresult, err_rval)         \
-  PR_BEGIN_MACRO                                                               \
-  nsGlobalWindowOuter* outer = GetOuterWindowForForwarding(this, errorresult); \
-  if (MOZ_LIKELY(outer)) {                                                     \
-    return outer->method args;                                                 \
-  }                                                                            \
-  return err_rval;                                                             \
+#define FORWARD_TO_OUTER_OR_THROW(method, args, errorresult, err_rval) \
+  PR_BEGIN_MACRO                                                       \
+  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                                                     \
   nsGlobalWindowOuter* outer = GetOuterWindowInternal();             \
   if (!HasActiveDocument()) {                                        \
     NS_WARNING(outer ? "Inner window does not have active document." \
                      : "No outer window available!");                \
@@ -2116,19 +2107,19 @@ void nsPIDOMWindowInner::MuteAudioContex
 void nsPIDOMWindowInner::UnmuteAudioContexts() {
   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
     if (!mAudioContexts[i]->IsOffline()) {
       mAudioContexts[i]->Unmute();
     }
   }
 }
 
-BrowsingContext* nsGlobalWindowInner::Window() {
-  return mOuterWindow ? mOuterWindow->GetBrowsingContext() : nullptr;
-}
+nsGlobalWindowInner* nsGlobalWindowInner::Window() { return this; }
+
+nsGlobalWindowInner* nsGlobalWindowInner::Self() { return this; }
 
 Navigator* nsPIDOMWindowInner::Navigator() {
   if (!mNavigator) {
     mNavigator = new mozilla::dom::Navigator(this);
   }
 
   return mNavigator;
 }
@@ -2550,17 +2541,17 @@ bool nsGlobalWindowInner::HasActiveSpeec
     return !mSpeechSynthesis->HasEmptyQueue();
   }
 
   return false;
 }
 
 #endif
 
-Nullable<WindowProxyHolder> nsGlobalWindowInner::GetParent(
+already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowInner::GetParent(
     ErrorResult& aError) {
   FORWARD_TO_OUTER_OR_THROW(GetParentOuter, (), aError, nullptr);
 }
 
 /**
  * GetScriptableParent is called when script reads window.parent.
  *
  * In contrast to GetRealParent, GetScriptableParent respects <iframe
@@ -3310,22 +3301,22 @@ double nsGlobalWindowInner::GetScrollX(E
 }
 
 double nsGlobalWindowInner::GetScrollY(ErrorResult& aError) {
   FORWARD_TO_OUTER_OR_THROW(GetScrollYOuter, (), aError, 0);
 }
 
 uint32_t nsGlobalWindowInner::Length() { FORWARD_TO_OUTER(Length, (), 0); }
 
-Nullable<WindowProxyHolder> nsGlobalWindowInner::GetTop(
+already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowInner::GetTop(
     mozilla::ErrorResult& aError) {
   FORWARD_TO_OUTER_OR_THROW(GetTopOuter, (), aError, nullptr);
 }
 
-already_AddRefed<BrowsingContext> nsGlobalWindowInner::GetChildWindow(
+nsPIDOMWindowOuter* nsGlobalWindowInner::GetChildWindow(
     const nsAString& aName) {
   if (GetOuterWindowInternal()) {
     return GetOuterWindowInternal()->GetChildWindow(aName);
   }
   return nullptr;
 }
 
 void nsGlobalWindowInner::RefreshRealmPrincipal() {
@@ -3423,17 +3414,17 @@ void nsGlobalWindowInner::Prompt(const n
                                  nsIPrincipal& aSubjectPrincipal,
                                  ErrorResult& aError) {
   FORWARD_TO_OUTER_OR_THROW(
       PromptOuter, (aMessage, aInitial, aReturn, aSubjectPrincipal, aError),
       aError, );
 }
 
 void nsGlobalWindowInner::Focus(ErrorResult& aError) {
-  FORWARD_TO_OUTER_OR_THROW(FocusOuter, (), aError, );
+  FORWARD_TO_OUTER_OR_THROW(FocusOuter, (aError), aError, );
 }
 
 nsresult nsGlobalWindowInner::Focus() {
   ErrorResult rv;
   Focus(rv);
 
   return rv.StealNSResult();
 }
@@ -3688,34 +3679,34 @@ void nsGlobalWindowInner::CaptureEvents(
 }
 
 void nsGlobalWindowInner::ReleaseEvents() {
   if (mDoc) {
     mDoc->WarnOnceAbout(nsIDocument::eUseOfReleaseEvents);
   }
 }
 
-Nullable<WindowProxyHolder> nsGlobalWindowInner::Open(const nsAString& aUrl,
-                                                      const nsAString& aName,
-                                                      const nsAString& aOptions,
-                                                      ErrorResult& aError) {
+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);
 }
 
-Nullable<WindowProxyHolder> nsGlobalWindowInner::OpenDialog(
+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),
       aError, nullptr);
 }
 
-BrowsingContext* nsGlobalWindowInner::GetFrames(ErrorResult& aError) {
+already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowInner::GetFrames(
+    ErrorResult& aError) {
   FORWARD_TO_OUTER_OR_THROW(GetFramesOuter, (), aError, nullptr);
 }
 
 void nsGlobalWindowInner::PostMessageMoz(JSContext* aCx,
                                          JS::Handle<JS::Value> aMessage,
                                          const nsAString& aTargetOrigin,
                                          JS::Handle<JS::Value> aTransfer,
                                          nsIPrincipal& aSubjectPrincipal,
@@ -3755,18 +3746,18 @@ void nsGlobalWindowInner::PostMessageMoz
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   PostMessageMoz(aCx, aMessage, aOptions.mTargetOrigin, transferArray,
                  aSubjectPrincipal, aRv);
 }
 
-void nsGlobalWindowInner::Close(CallerType aCallerType, ErrorResult& aError) {
-  FORWARD_TO_OUTER_OR_THROW(CloseOuter, (aCallerType == CallerType::System),
+void nsGlobalWindowInner::Close(ErrorResult& aError) {
+  FORWARD_TO_OUTER_OR_THROW(CloseOuter, (nsContentUtils::IsCallerChrome()),
                             aError, );
 }
 
 nsresult nsGlobalWindowInner::Close() {
   FORWARD_TO_OUTER(Close, (), NS_ERROR_UNEXPECTED);
 }
 
 bool nsGlobalWindowInner::IsInModalState() {
@@ -3885,17 +3876,17 @@ void nsGlobalWindowInner::Btoa(const nsA
                                ErrorResult& aError) {
   aError = nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
 }
 
 //*****************************************************************************
 // EventTarget
 //*****************************************************************************
 
-nsPIDOMWindowOuter* nsGlobalWindowInner::GetOwnerGlobalForBindingsInternal() {
+nsPIDOMWindowOuter* nsGlobalWindowInner::GetOwnerGlobalForBindings() {
   return nsPIDOMWindowOuter::GetFromCurrentInner(this);
 }
 
 bool nsGlobalWindowInner::DispatchEvent(Event& aEvent, CallerType aCallerType,
                                         ErrorResult& aRv) {
   if (!IsCurrentInnerWindow()) {
     NS_WARNING(
         "DispatchEvent called on non-current inner window, dropping. "
@@ -3938,17 +3929,17 @@ EventListenerManager* nsGlobalWindowInne
 EventListenerManager* nsGlobalWindowInner::GetExistingListenerManager() const {
   return mListenerManager;
 }
 
 //*****************************************************************************
 // nsGlobalWindowInner::nsPIDOMWindow
 //*****************************************************************************
 
-Location* nsGlobalWindowInner::Location() {
+Location* nsGlobalWindowInner::GetLocation() {
   if (!mLocation) {
     mLocation = new dom::Location(this, GetDocShell());
   }
 
   return mLocation;
 }
 
 void nsGlobalWindowInner::MaybeUpdateTouchState() {
@@ -6914,17 +6905,17 @@ already_AddRefed<External> nsGlobalWindo
   return nullptr;
 #endif
 }
 
 void nsGlobalWindowInner::GetSidebar(OwningExternalOrWindowProxy& aResult,
                                      ErrorResult& aRv) {
 #ifdef HAVE_SIDEBAR
   // First check for a named frame named "sidebar"
-  RefPtr<BrowsingContext> domWindow =
+  nsCOMPtr<nsPIDOMWindowOuter> domWindow =
       GetChildWindow(NS_LITERAL_STRING("sidebar"));
   if (domWindow) {
     aResult.SetAsWindowProxy() = domWindow.forget();
     return;
   }
 
   RefPtr<External> external = GetExternal(aRv);
   if (external) {
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -92,17 +92,16 @@ class IdleRequestExecutor;
 class DialogValueHolder;
 
 class PromiseDocumentFlushedResolver;
 
 namespace mozilla {
 class AbstractThread;
 namespace dom {
 class BarProp;
-class BrowsingContext;
 struct ChannelPixelLayout;
 class ClientSource;
 class Console;
 class Crypto;
 class CustomElementRegistry;
 class DocGroup;
 class External;
 class Function;
@@ -209,18 +208,16 @@ class nsGlobalWindowInner final : public
                                   public nsIScriptGlobalObject,
                                   public nsIScriptObjectPrincipal,
                                   public nsSupportsWeakReference,
                                   public nsIInterfaceRequestor,
                                   public PRCListStr,
                                   public nsAPostRefreshObserver,
                                   public mozilla::webgpu::InstanceProvider {
  public:
-  typedef mozilla::dom::BrowsingContext RemoteProxy;
-
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
 
   typedef nsDataHashtable<nsUint64HashKey, nsGlobalWindowInner*>
       InnerWindowByIdTable;
 
   static void AssertIsOnMainThread()
 #ifdef DEBUG
@@ -304,17 +301,17 @@ class nsGlobalWindowInner final : public
 
   virtual mozilla::EventListenerManager* GetExistingListenerManager()
       const override;
 
   virtual mozilla::EventListenerManager* GetOrCreateListenerManager() override;
 
   bool ComputeDefaultWantsUntrusted(mozilla::ErrorResult& aRv) final;
 
-  virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindingsInternal() override;
+  virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override;
 
   virtual nsIGlobalObject* GetOwnerGlobal() const override;
 
   EventTarget* GetTargetForDOMEvent() override;
 
   using mozilla::dom::EventTarget::DispatchEvent;
   bool DispatchEvent(mozilla::dom::Event& aEvent,
                      mozilla::dom::CallerType aCallerType,
@@ -418,18 +415,17 @@ class nsGlobalWindowInner final : public
   void GetOwnPropertyNames(JSContext* aCx, JS::AutoIdVector& aNames,
                            bool aEnumerableOnly, mozilla::ErrorResult& aRv);
 
   nsPIDOMWindowOuter* GetScriptableTop() override;
   inline nsGlobalWindowOuter* GetTopInternal();
 
   inline nsGlobalWindowOuter* GetScriptableTopInternal();
 
-  already_AddRefed<mozilla::dom::BrowsingContext> GetChildWindow(
-      const nsAString& aName);
+  nsPIDOMWindowOuter* GetChildWindow(const nsAString& aName);
 
   // These return true if we've reached the state in this top level window
   // where we ask the user if further dialogs should be blocked.
   //
   // DialogsAreBeingAbused must be called on the scriptable top inner window.
   //
   // nsGlobalWindowOuter::ShouldPromptToBlockDialogs is implemented in terms of
   // nsGlobalWindowInner::DialogsAreBeingAbused, and will get the scriptable top
@@ -596,67 +592,65 @@ class nsGlobalWindowInner final : public
 #undef ERROR_EVENT
 #undef EVENT
 
   nsISupports* GetParentObject() { return nullptr; }
 
   static JSObject* CreateNamedPropertiesObject(JSContext* aCx,
                                                JS::Handle<JSObject*> aProto);
 
-  mozilla::dom::BrowsingContext* Window();
-  mozilla::dom::BrowsingContext* Self() { return Window(); }
+  nsGlobalWindowInner* Window();
+  nsGlobalWindowInner* Self();
   nsIDocument* GetDocument() { return GetDoc(); }
   void GetName(nsAString& aName, mozilla::ErrorResult& aError);
   void SetName(const nsAString& aName, mozilla::ErrorResult& aError);
-  mozilla::dom::Location* Location() override;
+  mozilla::dom::Location* GetLocation() override;
   nsHistory* GetHistory(mozilla::ErrorResult& aError);
   mozilla::dom::CustomElementRegistry* CustomElements() override;
   mozilla::dom::BarProp* GetLocationbar(mozilla::ErrorResult& aError);
   mozilla::dom::BarProp* GetMenubar(mozilla::ErrorResult& aError);
   mozilla::dom::BarProp* GetPersonalbar(mozilla::ErrorResult& aError);
   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::dom::CallerType aCallerType,
-             mozilla::ErrorResult& aError);
+  void Close(mozilla::ErrorResult& aError);
   nsresult Close() override;
   bool GetClosed(mozilla::ErrorResult& aError);
   void Stop(mozilla::ErrorResult& aError);
   void Focus(mozilla::ErrorResult& aError);
   nsresult Focus() override;
   void Blur(mozilla::ErrorResult& aError);
   nsDOMWindowList* GetFrames() final;
-  mozilla::dom::BrowsingContext* GetFrames(mozilla::ErrorResult& aError);
+  already_AddRefed<nsPIDOMWindowOuter> GetFrames(mozilla::ErrorResult& aError);
   uint32_t Length();
-  mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetTop(
-      mozilla::ErrorResult& aError);
+  already_AddRefed<nsPIDOMWindowOuter> GetTop(mozilla::ErrorResult& aError);
 
  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);
   void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
                  mozilla::ErrorResult& aError);
   void GetEvent(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval);
-  mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetParent(
-      mozilla::ErrorResult& aError);
+  already_AddRefed<nsPIDOMWindowOuter> GetParent(mozilla::ErrorResult& aError);
   nsPIDOMWindowOuter* GetScriptableParent() override;
   mozilla::dom::Element* GetFrameElement(nsIPrincipal& aSubjectPrincipal,
                                          mozilla::ErrorResult& aError);
   mozilla::dom::Element* GetFrameElement() override;
-  mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> Open(
-      const nsAString& aUrl, const nsAString& aName, const nsAString& aOptions,
-      mozilla::ErrorResult& aError);
+  already_AddRefed<nsPIDOMWindowOuter> Open(const nsAString& aUrl,
+                                            const nsAString& aName,
+                                            const nsAString& aOptions,
+                                            mozilla::ErrorResult& aError);
   nsDOMOfflineResourceList* GetApplicationCache(mozilla::ErrorResult& aError);
   nsDOMOfflineResourceList* GetApplicationCache() override;
 
 #if defined(MOZ_WIDGET_ANDROID)
   int16_t Orientation(mozilla::dom::CallerType aCallerType) const;
 #endif
 
   already_AddRefed<mozilla::dom::Console> GetConsole(JSContext* aCx,
@@ -858,17 +852,17 @@ class nsGlobalWindowInner final : public
   void SetFullScreen(bool aFullscreen, 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);
 
   bool ShouldResistFingerprinting();
 
-  mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> OpenDialog(
+  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);
   void UpdateCommands(const nsAString& anAction, mozilla::dom::Selection* aSel,
                       int16_t aReason);
 
   void GetContent(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval,
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -33,17 +33,16 @@
 #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/dom/WindowProxyHolder.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #if defined(MOZ_WIDGET_ANDROID)
 #include "mozilla/dom/WindowOrientationObserver.h"
 #endif
 #include "nsError.h"
 #include "nsIIdleService.h"
 #include "nsISizeOfEventTarget.h"
 #include "nsDOMJSUtils.h"
@@ -440,20 +439,16 @@ const char* nsOuterWindowProxy::classNam
 
   return "Window";
 }
 
 void nsOuterWindowProxy::finalize(JSFreeOp* fop, JSObject* proxy) const {
   nsGlobalWindowOuter* outerWindow = GetOuterWindow(proxy);
   if (outerWindow) {
     outerWindow->ClearWrapper(proxy);
-    BrowsingContext* bc = outerWindow->GetBrowsingContext();
-    if (bc) {
-      bc->ClearWindowProxy();
-    }
 
     // Ideally we would use OnFinalize here, but it's possible that
     // EnsureScriptEnvironment will later be called on the window, and we don't
     // want to create a new script object in that case. Therefore, we need to
     // write a non-null value that will reliably crash when dereferenced.
     outerWindow->PoisonOuterWindowProxy(proxy);
   }
 }
@@ -802,20 +797,16 @@ bool nsOuterWindowProxy::AppendIndexedPr
 
   return true;
 }
 
 size_t nsOuterWindowProxy::objectMoved(JSObject* obj, JSObject* old) const {
   nsGlobalWindowOuter* outerWindow = GetOuterWindow(obj);
   if (outerWindow) {
     outerWindow->UpdateWrapper(obj, old);
-    BrowsingContext* bc = outerWindow->GetBrowsingContext();
-    if (bc) {
-      bc->UpdateWindowProxy(obj, old);
-    }
   }
   return 0;
 }
 
 const nsOuterWindowProxy nsOuterWindowProxy::singleton;
 
 class nsChromeOuterWindowProxy : public nsOuterWindowProxy {
  public:
@@ -984,19 +975,16 @@ nsGlobalWindowOuter::~nsGlobalWindowOute
   }
 #endif
 
   MOZ_LOG(gDOMLeakPRLogOuter, LogLevel::Debug,
           ("DOMWINDOW %p destroyed", this));
 
   JSObject* proxy = GetWrapperMaybeDead();
   if (proxy) {
-    if (mBrowsingContext) {
-      mBrowsingContext->ClearWindowProxy();
-    }
     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
   // back pointer to this outer, and pull them out of the list of
   // inner windows.
   //
@@ -1187,17 +1175,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   // Traverse stuff from nsPIDOMWindow
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOpenerForInitialContentBrowser)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)
 
   tmp->TraverseHostObjectURIs(cb);
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mBrowserDOMWindow)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowOuter)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
@@ -1215,20 +1202,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   // Unlink stuff from nsPIDOMWindow
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOpenerForInitialContentBrowser)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)
-  if (tmp->mBrowsingContext) {
-    tmp->mBrowsingContext->ClearWindowProxy();
-    tmp->mBrowsingContext = nullptr;
-  }
 
   tmp->UnlinkHostObjectURIs();
 
   if (tmp->IsChromeWindow()) {
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mBrowserDOMWindow)
   }
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
@@ -1831,17 +1814,16 @@ nsresult nsGlobalWindowOuter::SetNewDocu
 
       JS::Rooted<JSObject*> obj(cx, GetWrapperPreserveColor());
 
       js::SetProxyReservedSlot(obj, 0, js::PrivateValue(nullptr));
       js::SetProxyReservedSlot(outerObject, 0, js::PrivateValue(nullptr));
 
       outerObject = xpc::TransplantObject(cx, obj, outerObject);
       if (!outerObject) {
-        mBrowsingContext->ClearWindowProxy();
         NS_ERROR("unable to transplant wrappers, probably OOM");
         return NS_ERROR_FAILURE;
       }
 
       js::SetProxyReservedSlot(outerObject, 0,
                                js::PrivateValue(ToSupports(this)));
 
       SetWrapper(outerObject);
@@ -1853,17 +1835,16 @@ nsresult nsGlobalWindowOuter::SetNewDocu
     }
 
     // Enter the new global's realm.
     JSAutoRealm ar(cx, GetWrapperPreserveColor());
 
     {
       JS::Rooted<JSObject*> outer(cx, GetWrapperPreserveColor());
       js::SetWindowProxy(cx, newInnerGlobal, outer);
-      mBrowsingContext->SetWindowProxy(outer);
     }
 
     // Set scriptability based on the state of the docshell.
     bool allow = GetDocShell()->GetCanExecuteScripts();
     xpc::Scriptability::Get(GetWrapperPreserveColor())
         .SetDocShellAllowsScript(allow);
 
     if (!aState) {
@@ -2098,25 +2079,24 @@ void nsGlobalWindowOuter::DispatchDOMWin
             ? "chrome-document-global-created"
             : "content-document-global-created",
         origin.get());
   }
 }
 
 void nsGlobalWindowOuter::ClearStatus() { SetStatusOuter(EmptyString()); }
 
-void nsGlobalWindowOuter::SetDocShell(nsDocShell* aDocShell) {
+void nsGlobalWindowOuter::SetDocShell(nsIDocShell* aDocShell) {
   MOZ_ASSERT(aDocShell);
 
   if (aDocShell == mDocShell) {
     return;
   }
 
   mDocShell = aDocShell;  // Weak Reference
-  mBrowsingContext = aDocShell->GetBrowsingContext();
 
   nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetScriptableParentOrNull();
   MOZ_RELEASE_ASSERT(!parentWindow || !mTabGroup ||
                      mTabGroup ==
                          nsGlobalWindowOuter::Cast(parentWindow)->mTabGroup);
 
   mTopLevelOuterContentWindow =
       !mIsChrome && GetScriptableTopInternal() == this;
@@ -2639,44 +2619,41 @@ bool nsPIDOMWindowOuter::GetServiceWorke
   // iframes get the correct devtools setting.
   nsCOMPtr<nsPIDOMWindowOuter> topWindow = GetScriptableTop();
   if (!topWindow) {
     return false;
   }
   return topWindow->mServiceWorkersTestingEnabled;
 }
 
-Nullable<WindowProxyHolder> nsGlobalWindowOuter::GetParentOuter() {
-  nsPIDOMWindowOuter* parent = GetScriptableParent();
-  BrowsingContext* parentBC;
-  if (!parent || !(parentBC = parent->GetBrowsingContext())) {
+already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowOuter::GetParentOuter() {
+  if (!mDocShell) {
     return nullptr;
   }
 
-  return WindowProxyHolder(parentBC);
+  nsCOMPtr<nsPIDOMWindowOuter> parent;
+  if (mDocShell->GetIsMozBrowser()) {
+    parent = this;
+  } else {
+    parent = GetParent();
+  }
+
+  return parent.forget();
 }
 
 /**
  * GetScriptableParent is called when script reads window.parent.
  *
  * In contrast to GetRealParent, GetScriptableParent respects <iframe
  * mozbrowser> boundaries, so if |this| is contained by an <iframe
  * mozbrowser>, we will return |this| as its own parent.
  */
 nsPIDOMWindowOuter* nsGlobalWindowOuter::GetScriptableParent() {
-  if (!mDocShell) {
-    return nullptr;
-  }
-
-  if (mDocShell->GetIsMozBrowser()) {
-    return this;
-  }
-
-  nsCOMPtr<nsPIDOMWindowOuter> parent = GetParent();
-  return parent;
+  nsCOMPtr<nsPIDOMWindowOuter> parent = GetParentOuter();
+  return parent.get();
 }
 
 /**
  * Behavies identically to GetScriptableParent extept that it returns null
  * if GetScriptableParent would return this window.
  */
 nsPIDOMWindowOuter* nsGlobalWindowOuter::GetScriptableParentOrNull() {
   nsPIDOMWindowOuter* parent = GetScriptableParent();
@@ -2714,22 +2691,25 @@ static nsresult GetTopImpl(nsGlobalWindo
   nsCOMPtr<nsPIDOMWindowOuter> parent = aWin;
   do {
     if (!parent) {
       break;
     }
 
     prevParent = parent;
 
+    nsCOMPtr<nsPIDOMWindowOuter> newParent;
     if (aScriptable) {
-      parent = parent->GetScriptableParent();
+      newParent = parent->GetScriptableParent();
     } else {
-      parent = parent->GetParent();
+      newParent = parent->GetParent();
     }
 
+    parent = newParent;
+
   } while (parent != prevParent);
 
   if (parent) {
     parent.swap(*aTop);
   }
 
   return NS_OK;
 }
@@ -2775,27 +2755,26 @@ void nsGlobalWindowOuter::GetContentOute
   }
 
   aRetval.set(nullptr);
 }
 
 already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowOuter::GetContentInternal(
     ErrorResult& aError, CallerType aCallerType) {
   // First check for a named frame named "content"
-  RefPtr<BrowsingContext> bc = GetChildWindow(NS_LITERAL_STRING("content"));
-  if (bc) {
-    nsCOMPtr<nsPIDOMWindowOuter> content(bc->GetDOMWindow());
-    return content.forget();
+  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
   // window.top.
   if (mDocShell && mDocShell->GetIsInMozBrowser()) {
-    nsCOMPtr<nsPIDOMWindowOuter> domWindow(GetScriptableTop());
-    return domWindow.forget();
+    return GetTopOuter();
   }
 
   nsCOMPtr<nsIDocShellTreeItem> primaryContent;
   if (aCallerType != CallerType::System) {
     if (mDoc) {
       mDoc->WarnOnceAbout(nsIDocument::eWindowContentUntrusted);
     }
     // If we're called by non-chrome code, make sure we don't return
@@ -2823,17 +2802,17 @@ already_AddRefed<nsPIDOMWindowOuter> nsG
 
     treeOwner->GetPrimaryContentShell(getter_AddRefs(primaryContent));
   }
 
   if (!primaryContent) {
     return nullptr;
   }
 
-  nsCOMPtr<nsPIDOMWindowOuter> domWindow = primaryContent->GetWindow();
+  domWindow = primaryContent->GetWindow();
   return domWindow.forget();
 }
 
 nsresult nsGlobalWindowOuter::GetPrompter(nsIPrompt** aPrompt) {
   if (!mDocShell) return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIPrompt> prompter(do_GetInterface(mDocShell));
   NS_ENSURE_TRUE(prompter, NS_ERROR_NO_INTERFACE);
@@ -3566,30 +3545,31 @@ double nsGlobalWindowOuter::GetScrollXOu
 double nsGlobalWindowOuter::GetScrollYOuter() { return GetScrollXY(false).y; }
 
 uint32_t nsGlobalWindowOuter::Length() {
   nsDOMWindowList* windows = GetFrames();
 
   return windows ? windows->GetLength() : 0;
 }
 
-Nullable<WindowProxyHolder> nsGlobalWindowOuter::GetTopOuter() {
+already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowOuter::GetTopOuter() {
   nsCOMPtr<nsPIDOMWindowOuter> top = GetScriptableTop();
-  BrowsingContext* topBC;
-  if (!top || !(topBC = top->GetBrowsingContext())) {
-    return nullptr;
-  }
-  return WindowProxyHolder(topBC);
-}
-
-already_AddRefed<BrowsingContext> nsGlobalWindowOuter::GetChildWindow(
+  return top.forget();
+}
+
+nsPIDOMWindowOuter* nsGlobalWindowOuter::GetChildWindow(
     const nsAString& aName) {
-  NS_ENSURE_TRUE(mBrowsingContext, nullptr);
-
-  return mBrowsingContext->FindChildWithName(aName);
+  nsCOMPtr<nsIDocShell> docShell(GetDocShell());
+  NS_ENSURE_TRUE(docShell, nullptr);
+
+  nsCOMPtr<nsIDocShellTreeItem> child;
+  docShell->FindChildWithName(aName, false, true, nullptr, nullptr,
+                              getter_AddRefs(child));
+
+  return child ? child->GetWindow() : nullptr;
 }
 
 bool nsGlobalWindowOuter::DispatchCustomEvent(const nsAString& aEventName) {
   bool defaultActionEnabled = true;
   nsContentUtils::DispatchTrustedEvent(mDoc, ToSupports(this), aEventName,
                                        CanBubble::eYes, Cancelable::eYes,
                                        &defaultActionEnabled);
 
@@ -4475,18 +4455,18 @@ void nsGlobalWindowOuter::PromptOuter(co
   nsString outValue;
   outValue.Adopt(inoutValue);
 
   if (ok && inoutValue) {
     aReturn.Assign(outValue);
   }
 }
 
-void nsGlobalWindowOuter::FocusOuter() {
-  nsFocusManager* fm = nsFocusManager::GetFocusManager();
+void nsGlobalWindowOuter::FocusOuter(ErrorResult& aError) {
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   if (!fm) {
     return;
   }
 
   nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mDocShell);
 
   bool isVisible = false;
   if (baseWin) {
@@ -4566,32 +4546,26 @@ void nsGlobalWindowOuter::FocusOuter() {
     if (!parentdoc) {
       return;
     }
 
     RefPtr<Element> frame = parentdoc->FindContentForSubDocument(mDoc);
     if (frame) {
       uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
       if (canFocus) flags |= nsIFocusManager::FLAG_RAISE;
-      DebugOnly<nsresult> rv = fm->SetFocus(frame, flags);
-      MOZ_ASSERT(NS_SUCCEEDED(rv),
-                 "SetFocus only fails if the first argument is null, "
-                 "but we pass an element");
+      aError = fm->SetFocus(frame, flags);
     }
     return;
   }
 
   if (canFocus) {
     // if there is no parent, this must be a toplevel window, so raise the
     // window if canFocus is true. If this is a child process, the raise
     // window request will get forwarded to the parent by the puppet widget.
-    DebugOnly<nsresult> rv = fm->SetActiveWindow(this);
-    MOZ_ASSERT(NS_SUCCEEDED(rv),
-               "SetActiveWindow only fails if passed null or a non-toplevel "
-               "window, which is not the case here.");
+    aError = fm->SetActiveWindow(this);
   }
 }
 
 nsresult nsGlobalWindowOuter::Focus() {
   FORWARD_TO_INNER(Focus, (), NS_ERROR_UNEXPECTED);
 }
 
 void nsGlobalWindowOuter::BlurOuter() {
@@ -5248,26 +5222,22 @@ void nsGlobalWindowOuter::FireAbuseEvent
     ios->NewURI(NS_ConvertUTF16toUTF8(aPopupURL), nullptr, baseURL,
                 getter_AddRefs(popupURI));
 
   // fire an event block full of informative URIs
   FirePopupBlockedEvent(topDoc, popupURI, aPopupWindowName,
                         aPopupWindowFeatures);
 }
 
-Nullable<WindowProxyHolder> nsGlobalWindowOuter::OpenOuter(
+already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowOuter::OpenOuter(
     const nsAString& aUrl, const nsAString& aName, const nsAString& aOptions,
     ErrorResult& aError) {
   nsCOMPtr<nsPIDOMWindowOuter> window;
   aError = OpenJS(aUrl, aName, aOptions, getter_AddRefs(window));
-  RefPtr<BrowsingContext> bc;
-  if (!window || !(bc = window->GetBrowsingContext())) {
-    return nullptr;
-  }
-  return WindowProxyHolder(bc.forget());
+  return window.forget();
 }
 
 nsresult nsGlobalWindowOuter::Open(const nsAString& aUrl,
                                    const nsAString& aName,
                                    const nsAString& aOptions,
                                    nsDocShellLoadState* aLoadState,
                                    bool aForceNoOpener,
                                    nsPIDOMWindowOuter** _retval) {
@@ -5327,17 +5297,17 @@ nsresult nsGlobalWindowOuter::OpenDialog
                       false,             // aDoJSFixups
                       false,             // aNavigate
                       nullptr, nullptr,  // No args
                       nullptr,           // aLoadState
                       false,             // aForceNoOpener
                       _retval);
 }
 
-Nullable<WindowProxyHolder> nsGlobalWindowOuter::OpenDialogOuter(
+already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowOuter::OpenDialogOuter(
     JSContext* aCx, const nsAString& aUrl, const nsAString& aName,
     const nsAString& aOptions, const Sequence<JS::Value>& aExtraArgument,
     ErrorResult& aError) {
   nsCOMPtr<nsIJSArgArray> argvArray;
   aError =
       NS_CreateJSArgv(aCx, aExtraArgument.Length(), aExtraArgument.Elements(),
                       getter_AddRefs(argvArray));
   if (aError.Failed()) {
@@ -5350,30 +5320,25 @@ Nullable<WindowProxyHolder> nsGlobalWind
                         false,               // aContentModal
                         false,               // aCalledNoScript
                         false,               // aDoJSFixups
                         true,                // aNavigate
                         argvArray, nullptr,  // Arguments
                         nullptr,             // aLoadState
                         false,               // aForceNoOpener
                         getter_AddRefs(dialog));
-  RefPtr<BrowsingContext> bc;
-  if (!dialog || !(bc = dialog->GetBrowsingContext())) {
-    return nullptr;
-  }
-  return WindowProxyHolder(bc.forget());
-}
-
-BrowsingContext* nsGlobalWindowOuter::GetFramesOuter() {
+  return dialog.forget();
+}
+
+already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowOuter::GetFramesOuter() {
   RefPtr<nsPIDOMWindowOuter> frames(this);
   FlushPendingNotifications(FlushType::ContentAndNotify);
-  return mBrowsingContext;
-}
-
-/* static */
+  return frames.forget();
+}
+
 nsGlobalWindowInner* nsGlobalWindowOuter::CallerInnerWindow(JSContext* aCx) {
   nsIGlobalObject* global = GetIncumbentGlobal();
   NS_ENSURE_TRUE(global, nullptr);
   JS::Rooted<JSObject*> scope(aCx, global->GetGlobalJSObject());
   NS_ENSURE_TRUE(scope, nullptr);
 
   // When Jetpack runs content scripts inside a sandbox, it uses
   // sandboxPrototype to make them appear as though they're running in the
@@ -5395,147 +5360,115 @@ nsGlobalWindowInner* nsGlobalWindowOuter
   }
 
   // The calling window must be holding a reference, so we can return a weak
   // pointer.
   nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(global);
   return nsGlobalWindowInner::Cast(win);
 }
 
-/* static */
-bool nsGlobalWindowOuter::GatherPostMessageData(
-    JSContext* aCx, const nsAString& aTargetOrigin, BrowsingContext** aSource,
-    nsAString& aOrigin, nsIURI** aTargetOriginURI,
-    nsIPrincipal** aCallerPrincipal, nsGlobalWindowInner** aCallerInnerWindow,
-    nsIURI** aCallerDocumentURI, ErrorResult& aError) {
+void nsGlobalWindowOuter::PostMessageMozOuter(JSContext* aCx,
+                                              JS::Handle<JS::Value> aMessage,
+                                              const nsAString& aTargetOrigin,
+                                              JS::Handle<JS::Value> aTransfer,
+                                              nsIPrincipal& aSubjectPrincipal,
+                                              ErrorResult& aError) {
   //
   // Window.postMessage is an intentional subversion of the same-origin policy.
   // As such, this code must be particularly careful in the information it
   // exposes to calling code.
   //
   // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html
   //
 
   // First, get the caller's window
   RefPtr<nsGlobalWindowInner> callerInnerWin = CallerInnerWindow(aCx);
   nsIPrincipal* callerPrin;
   if (callerInnerWin) {
-    nsCOMPtr<nsIDocument> doc = callerInnerWin->GetExtantDoc();
-    if (!doc) {
-      return false;
-    }
-    NS_IF_ADDREF(*aCallerDocumentURI = doc->GetDocumentURI());
-
     // Compute the caller's origin either from its principal or, in the case the
     // principal doesn't carry a URI (e.g. the system principal), the caller's
     // document.  We must get this now instead of when the event is created and
     // dispatched, because ultimately it is the identity of the calling window
     // *now* that determines who sent the message (and not an identity which
     // might have changed due to intervening navigations).
     callerPrin = callerInnerWin->GetPrincipal();
   } else {
     // In case the global is not a window, it can be a sandbox, and the
     // sandbox's principal can be used for the security check.
     nsIGlobalObject* global = GetIncumbentGlobal();
     NS_ASSERTION(global, "Why is there no global object?");
     callerPrin = global->PrincipalOrNull();
   }
   if (!callerPrin) {
-    return false;
+    return;
   }
 
   nsCOMPtr<nsIURI> callerOuterURI;
   if (NS_FAILED(callerPrin->GetURI(getter_AddRefs(callerOuterURI)))) {
-    return false;
-  }
-
+    return;
+  }
+
+  nsAutoString origin;
   if (callerOuterURI) {
     // if the principal has a URI, use that to generate the origin
-    nsContentUtils::GetUTFOrigin(callerPrin, aOrigin);
+    nsContentUtils::GetUTFOrigin(callerPrin, origin);
   } else if (callerInnerWin) {
-    if (!*aCallerDocumentURI) {
-      return false;
+    // otherwise use the URI of the document to generate origin
+    nsCOMPtr<nsIDocument> doc = callerInnerWin->GetExtantDoc();
+    if (!doc) {
+      return;
     }
-    // otherwise use the URI of the document to generate origin
-    nsContentUtils::GetUTFOrigin(*aCallerDocumentURI, aOrigin);
+    callerOuterURI = doc->GetDocumentURI();
+    // if the principal has a URI, use that to generate the origin
+    nsContentUtils::GetUTFOrigin(callerOuterURI, origin);
   } else {
     // in case of a sandbox with a system principal origin can be empty
     if (!nsContentUtils::IsSystemPrincipal(callerPrin)) {
-      return false;
-    }
-  }
-  NS_IF_ADDREF(*aCallerPrincipal = callerPrin);
-
-  // "/" indicates same origin as caller, "*" indicates no specific origin is
-  // required.
-  if (!aTargetOrigin.EqualsASCII("/") && !aTargetOrigin.EqualsASCII("*")) {
-    nsCOMPtr<nsIURI> targetOriginURI;
-    if (NS_FAILED(NS_NewURI(getter_AddRefs(targetOriginURI), aTargetOrigin))) {
-      aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
-      return false;
-    }
-
-    nsresult rv = NS_MutateURI(targetOriginURI)
-                      .SetUserPass(EmptyCString())
-                      .SetPathQueryRef(EmptyCString())
-                      .Finalize(aTargetOriginURI);
-    if (NS_FAILED(rv)) {
-      return false;
+      return;
     }
   }
 
-  if (!nsContentUtils::IsCallerChrome() && callerInnerWin &&
-      callerInnerWin->GetOuterWindowInternal()) {
-    NS_ADDREF(*aSource = callerInnerWin->GetOuterWindowInternal()
-                             ->GetBrowsingContext());
-  } else {
-    *aSource = nullptr;
-  }
-
-  callerInnerWin.forget(aCallerInnerWindow);
-
-  return true;
-}
-
-bool nsGlobalWindowOuter::GetPrincipalForPostMessage(
-    const nsAString& aTargetOrigin, nsIURI* aTargetOriginURI,
-    nsIPrincipal* aCallerPrincipal, nsIPrincipal& aSubjectPrincipal,
-    nsIPrincipal** aProvidedPrincipal) {
-  //
-  // Window.postMessage is an intentional subversion of the same-origin policy.
-  // As such, this code must be particularly careful in the information it
-  // exposes to calling code.
-  //
-  // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html
-  //
-
   // Convert the provided origin string into a URI for comparison purposes.
   nsCOMPtr<nsIPrincipal> providedPrincipal;
 
   if (aTargetOrigin.EqualsASCII("/")) {
-    providedPrincipal = aCallerPrincipal;
+    providedPrincipal = callerPrin;
   }
   // "*" indicates no specific origin is required.
   else if (!aTargetOrigin.EqualsASCII("*")) {
+    nsCOMPtr<nsIURI> originURI;
+    if (NS_FAILED(NS_NewURI(getter_AddRefs(originURI), aTargetOrigin))) {
+      aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+      return;
+    }
+
+    nsresult rv = NS_MutateURI(originURI)
+                      .SetUserPass(EmptyCString())
+                      .SetPathQueryRef(EmptyCString())
+                      .Finalize(originURI);
+    if (NS_FAILED(rv)) {
+      return;
+    }
+
     OriginAttributes attrs = aSubjectPrincipal.OriginAttributesRef();
     if (aSubjectPrincipal.GetIsSystemPrincipal()) {
       auto principal = BasePrincipal::Cast(GetPrincipal());
 
       if (attrs != principal->OriginAttributesRef()) {
         nsCOMPtr<nsIURI> targetURI;
         nsAutoCString targetURL;
         nsAutoCString sourceOrigin;
         nsAutoCString targetOrigin;
 
         if (NS_FAILED(principal->GetURI(getter_AddRefs(targetURI))) ||
             NS_FAILED(targetURI->GetAsciiSpec(targetURL)) ||
             NS_FAILED(principal->GetOrigin(targetOrigin)) ||
             NS_FAILED(aSubjectPrincipal.GetOrigin(sourceOrigin))) {
           NS_WARNING("Failed to get source and target origins");
-          return false;
+          return;
         }
 
         nsContentUtils::LogSimpleConsoleError(
             NS_ConvertUTF8toUTF16(nsPrintfCString(
                 R"(Attempting to post a message to window with url "%s" and )"
                 R"(origin "%s" from a system principal scope with mismatched )"
                 R"(origin "%s".)",
                 targetURL.get(), targetOrigin.get(), sourceOrigin.get())),
@@ -5543,26 +5476,26 @@ bool nsGlobalWindowOuter::GetPrincipalFo
 
         attrs = principal->OriginAttributesRef();
       }
     }
 
     // Create a nsIPrincipal inheriting the app/browser attributes from the
     // caller.
     providedPrincipal =
-        BasePrincipal::CreateCodebasePrincipal(aTargetOriginURI, attrs);
+        BasePrincipal::CreateCodebasePrincipal(originURI, attrs);
     if (NS_WARN_IF(!providedPrincipal)) {
-      return false;
+      return;
     }
   } else {
     // We still need to check the originAttributes if the target origin is '*'.
     // But we will ingore the FPD here since the FPDs are possible to be
     // different.
     auto principal = BasePrincipal::Cast(GetPrincipal());
-    NS_ENSURE_TRUE(principal, false);
+    NS_ENSURE_TRUE_VOID(principal);
 
     OriginAttributes targetAttrs = principal->OriginAttributesRef();
     OriginAttributes sourceAttrs = aSubjectPrincipal.OriginAttributesRef();
     // We have to exempt the check of OA if the subject prioncipal is a system
     // principal since there are many tests try to post messages to content from
     // chrome with a mismatch OA. For example, using the ContentTask.spawn() to
     // post a message into a private browsing window. The injected code in
     // ContentTask.spawn() will be executed under the system principal and the
@@ -5571,58 +5504,33 @@ bool nsGlobalWindowOuter::GetPrincipalFo
     MOZ_DIAGNOSTIC_ASSERT(aSubjectPrincipal.GetIsSystemPrincipal() ||
                           sourceAttrs.EqualsIgnoringFPD(targetAttrs));
 
     // If 'privacy.firstparty.isolate.block_post_message' is true, we will block
     // postMessage across different first party domains.
     if (OriginAttributes::IsBlockPostMessageForFPI() &&
         !aSubjectPrincipal.GetIsSystemPrincipal() &&
         sourceAttrs.mFirstPartyDomain != targetAttrs.mFirstPartyDomain) {
-      return false;
+      return;
     }
   }
 
-  providedPrincipal.forget(aProvidedPrincipal);
-  return true;
-}
-
-void nsGlobalWindowOuter::PostMessageMozOuter(JSContext* aCx,
-                                              JS::Handle<JS::Value> aMessage,
-                                              const nsAString& aTargetOrigin,
-                                              JS::Handle<JS::Value> aTransfer,
-                                              nsIPrincipal& aSubjectPrincipal,
-                                              ErrorResult& aError) {
-  RefPtr<BrowsingContext> sourceBc;
-  nsAutoString origin;
-  nsCOMPtr<nsIURI> targetOriginURI;
-  nsCOMPtr<nsIPrincipal> callerPrincipal;
-  RefPtr<nsGlobalWindowInner> callerInnerWindow;
-  nsCOMPtr<nsIURI> callerDocumentURI;
-  if (!GatherPostMessageData(aCx, aTargetOrigin, getter_AddRefs(sourceBc),
-                             origin, getter_AddRefs(targetOriginURI),
-                             getter_AddRefs(callerPrincipal),
-                             getter_AddRefs(callerInnerWindow),
-                             getter_AddRefs(callerDocumentURI), aError)) {
-    return;
-  }
-
-  nsCOMPtr<nsIPrincipal> providedPrincipal;
-  if (!GetPrincipalForPostMessage(aTargetOrigin, targetOriginURI,
-                                  callerPrincipal, aSubjectPrincipal,
-                                  getter_AddRefs(providedPrincipal))) {
-    return;
-  }
-
   // Create and asynchronously dispatch a runnable which will handle actual DOM
   // event creation and dispatch.
-  RefPtr<PostMessageEvent> event = new PostMessageEvent(
-      sourceBc, origin, this, providedPrincipal,
-      callerInnerWindow ? callerInnerWindow->WindowID() : 0, callerDocumentURI);
-
-  event->Write(aCx, aMessage, aTransfer, aError);
+  RefPtr<PostMessageEvent> event =
+      new PostMessageEvent(nsContentUtils::IsCallerChrome() || !callerInnerWin
+                               ? nullptr
+                               : callerInnerWin->GetOuterWindowInternal(),
+                           origin, this, providedPrincipal,
+                           callerInnerWin ? callerInnerWin->GetDoc() : nullptr);
+
+  JS::Rooted<JS::Value> message(aCx, aMessage);
+  JS::Rooted<JS::Value> transfer(aCx, aTransfer);
+
+  event->Write(aCx, message, transfer, JS::CloneDataPolicy(), aError);
   if (NS_WARN_IF(aError.Failed())) {
     return;
   }
 
   aError = Dispatch(TaskCategory::Other, event.forget());
 }
 
 class nsCloseEvent : public Runnable {
@@ -6177,17 +6085,17 @@ bool nsGlobalWindowOuter::FindOuter(cons
   aError = finder->FindNext(&didFind);
   return didFind;
 }
 
 //*****************************************************************************
 // EventTarget
 //*****************************************************************************
 
-nsPIDOMWindowOuter* nsGlobalWindowOuter::GetOwnerGlobalForBindingsInternal() {
+nsPIDOMWindowOuter* nsGlobalWindowOuter::GetOwnerGlobalForBindings() {
   return this;
 }
 
 bool nsGlobalWindowOuter::DispatchEvent(Event& aEvent, CallerType aCallerType,
                                         ErrorResult& aRv) {
   FORWARD_TO_INNER(DispatchEvent, (aEvent, aCallerType, aRv), false);
 }
 
@@ -6242,17 +6150,17 @@ nsPIDOMWindowOuter* nsGlobalWindowOuter:
   }
 
   return top;
 }
 
 // This has a caller in Windows-only code (nsNativeAppSupportWin).
 Location* nsGlobalWindowOuter::GetLocation() {
   // This method can be called on the outer window as well.
-  FORWARD_TO_INNER(Location, (), nullptr);
+  FORWARD_TO_INNER(GetLocation, (), nullptr);
 }
 
 void nsGlobalWindowOuter::ActivateOrDeactivate(bool aActivate) {
   if (!mDoc) {
     return;
   }
 
   // Set / unset mIsActive on the top level window, which is used for the
@@ -7134,23 +7042,23 @@ ChromeMessageBroadcaster* nsGlobalWindow
   if (!mInnerWindow) {
     NS_WARNING("No inner window available!");
     return nullptr;
   }
   return GetCurrentInnerWindowInternal()->GetGroupMessageManager(aGroup);
 }
 
 void nsPIDOMWindowOuter::SetOpenerForInitialContentBrowser(
-    BrowsingContext* aOpenerWindow) {
+    nsPIDOMWindowOuter* aOpenerWindow) {
   MOZ_ASSERT(!mOpenerForInitialContentBrowser,
              "Don't set OpenerForInitialContentBrowser twice!");
   mOpenerForInitialContentBrowser = aOpenerWindow;
 }
 
-already_AddRefed<BrowsingContext>
+already_AddRefed<nsPIDOMWindowOuter>
 nsPIDOMWindowOuter::TakeOpenerForInitialContentBrowser() {
   // Intentionally forget our own member
   return mOpenerForInitialContentBrowser.forget();
 }
 
 void nsGlobalWindowOuter::InitWasOffline() { mWasOffline = NS_IsOffline(); }
 
 #if defined(MOZ_WIDGET_ANDROID)
@@ -7341,17 +7249,17 @@ nsGlobalWindowOuter::TemporarilyDisableD
   }
 }
 
 mozilla::dom::TabGroup* nsPIDOMWindowOuter::TabGroup() {
   return nsGlobalWindowOuter::Cast(this)->TabGroupOuter();
 }
 
 /* static */ already_AddRefed<nsGlobalWindowOuter> nsGlobalWindowOuter::Create(
-    nsDocShell* aDocShell, bool aIsChrome) {
+    nsIDocShell* aDocShell, bool aIsChrome) {
   uint64_t outerWindowID = aDocShell->GetOuterWindowID();
   RefPtr<nsGlobalWindowOuter> window = new nsGlobalWindowOuter(outerWindowID);
   if (aIsChrome) {
     window->mIsChrome = true;
   }
   window->SetDocShell(aDocShell);
 
   window->InitWasOffline();
@@ -7484,8 +7392,13 @@ nsPIDOMWindowOuter::nsPIDOMWindowOuter(u
       mIsRootOuterWindow(false),
       mInnerWindow(nullptr),
       mWindowID(aWindowID),
       mMarkedCCGeneration(0),
       mServiceWorkersTestingEnabled(false),
       mLargeAllocStatus(LargeAllocStatus::NONE) {}
 
 nsPIDOMWindowOuter::~nsPIDOMWindowOuter() {}
+
+mozilla::dom::BrowsingContext* nsPIDOMWindowOuter::GetBrowsingContext() const {
+  return mDocShell ? nsDocShell::Cast(mDocShell)->GetBrowsingContext()
+                   : nullptr;
+}
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -52,17 +52,16 @@
 #include "mozilla/dom/WindowBinding.h"
 #include "Units.h"
 #include "nsComponentManagerUtils.h"
 #include "nsSize.h"
 #include "nsCheapSets.h"
 #include "mozilla/dom/ImageBitmapSource.h"
 #include "mozilla/UniquePtr.h"
 
-class nsDocShell;
 class nsIArray;
 class nsIBaseWindow;
 class nsIContent;
 class nsICSSDeclaration;
 class nsIDocShellTreeOwner;
 class nsIDOMWindowUtils;
 class nsIScrollableFrame;
 class nsIControllers;
@@ -89,17 +88,16 @@ class IdleRequestExecutor;
 
 struct IdleObserverHolder;
 
 namespace mozilla {
 class AbstractThread;
 class DOMEventTargetHelper;
 namespace dom {
 class BarProp;
-class BrowsingContext;
 struct ChannelPixelLayout;
 class Console;
 class Crypto;
 class CustomElementRegistry;
 class DocGroup;
 class External;
 class Function;
 class Gamepad;
@@ -108,17 +106,16 @@ class IdleRequest;
 class IdleRequestCallback;
 class IncrementalRunnable;
 class IntlUtils;
 class Location;
 class MediaQueryList;
 class Navigator;
 class OwningExternalOrWindowProxy;
 class Promise;
-class PostMessageData;
 class PostMessageEvent;
 struct RequestInit;
 class RequestOrUSVString;
 class Selection;
 class SpeechSynthesis;
 class TabGroup;
 class Timeout;
 class U2F;
@@ -214,17 +211,17 @@ class nsGlobalWindowOuter final : public
     return sOuterWindowsById;
   }
 
   static nsGlobalWindowOuter* FromSupports(nsISupports* supports) {
     // Make sure this matches the casts we do in QueryInterface().
     return (nsGlobalWindowOuter*)(mozilla::dom::EventTarget*)supports;
   }
 
-  static already_AddRefed<nsGlobalWindowOuter> Create(nsDocShell* aDocShell,
+  static already_AddRefed<nsGlobalWindowOuter> Create(nsIDocShell* aDocShell,
                                                       bool aIsChrome);
 
   // public methods
   nsPIDOMWindowOuter* GetPrivateParent();
 
   // callback for close event
   void ReallyCloseWindow();
 
@@ -269,17 +266,17 @@ class nsGlobalWindowOuter final : public
 
   virtual mozilla::EventListenerManager* GetExistingListenerManager()
       const override;
 
   virtual mozilla::EventListenerManager* GetOrCreateListenerManager() override;
 
   bool ComputeDefaultWantsUntrusted(mozilla::ErrorResult& aRv) final;
 
-  virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindingsInternal() override;
+  virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override;
 
   virtual nsIGlobalObject* GetOwnerGlobal() const override;
 
   EventTarget* GetTargetForEventTargetChain() override;
 
   using mozilla::dom::EventTarget::DispatchEvent;
   bool DispatchEvent(mozilla::dom::Event& aEvent,
                      mozilla::dom::CallerType aCallerType,
@@ -360,18 +357,17 @@ class nsGlobalWindowOuter final : public
   already_AddRefed<nsPIDOMWindowOuter> IndexedGetterOuter(uint32_t aIndex);
 
   already_AddRefed<nsPIDOMWindowOuter> GetTop() override;
   nsPIDOMWindowOuter* GetScriptableTop() override;
   inline nsGlobalWindowOuter* GetTopInternal();
 
   inline nsGlobalWindowOuter* GetScriptableTopInternal();
 
-  already_AddRefed<mozilla::dom::BrowsingContext> GetChildWindow(
-      const nsAString& aName);
+  nsPIDOMWindowOuter* GetChildWindow(const nsAString& aName);
 
   // These return true if we've reached the state in this top level window
   // where we ask the user if further dialogs should be blocked.
   //
   // DialogsAreBeingAbused must be called on the scriptable top inner window.
   //
   // ShouldPromptToBlockDialogs is implemented in terms of
   // DialogsAreBeingAbused, and will get the scriptable top inner window
@@ -522,44 +518,45 @@ class nsGlobalWindowOuter final : public
   mozilla::dom::Location* GetLocation() override;
   void GetStatusOuter(nsAString& aStatus);
   void SetStatusOuter(const nsAString& aStatus);
   void CloseOuter(bool aTrustedCaller);
   nsresult Close() override;
   bool GetClosedOuter();
   bool Closed() override;
   void StopOuter(mozilla::ErrorResult& aError);
-  void FocusOuter();
+  void FocusOuter(mozilla::ErrorResult& aError);
   nsresult Focus() override;
   void BlurOuter();
-  mozilla::dom::BrowsingContext* GetFramesOuter();
+  already_AddRefed<nsPIDOMWindowOuter> GetFramesOuter();
   nsDOMWindowList* GetFrames() final;
   uint32_t Length();
-  mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetTopOuter();
+  already_AddRefed<nsPIDOMWindowOuter> GetTopOuter();
 
   nsresult GetPrompter(nsIPrompt** aPrompt) override;
 
  protected:
   nsPIDOMWindowOuter* GetOpenerWindowOuter();
   // Initializes the mWasOffline member variable
   void InitWasOffline();
 
  public:
   nsPIDOMWindowOuter* GetSanitizedOpener(nsPIDOMWindowOuter* aOpener);
 
   already_AddRefed<nsPIDOMWindowOuter> GetOpener() override;
-  mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetParentOuter();
+  already_AddRefed<nsPIDOMWindowOuter> GetParentOuter();
   already_AddRefed<nsPIDOMWindowOuter> GetParent() override;
   nsPIDOMWindowOuter* GetScriptableParent() override;
   nsPIDOMWindowOuter* GetScriptableParentOrNull() override;
   mozilla::dom::Element* GetFrameElementOuter(nsIPrincipal& aSubjectPrincipal);
   mozilla::dom::Element* GetFrameElement() override;
-  mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> OpenOuter(
-      const nsAString& aUrl, const nsAString& aName, const nsAString& aOptions,
-      mozilla::ErrorResult& aError);
+  already_AddRefed<nsPIDOMWindowOuter> OpenOuter(const nsAString& aUrl,
+                                                 const nsAString& aName,
+                                                 const nsAString& aOptions,
+                                                 mozilla::ErrorResult& aError);
   nsresult Open(const nsAString& aUrl, const nsAString& aName,
                 const nsAString& aOptions, nsDocShellLoadState* aLoadState,
                 bool aForceNoOpener, nsPIDOMWindowOuter** _retval) override;
   mozilla::dom::Navigator* GetNavigator() override;
 
 #if defined(MOZ_WIDGET_ANDROID)
   int16_t Orientation(mozilla::dom::CallerType aCallerType) const;
 #endif
@@ -613,17 +610,17 @@ class nsGlobalWindowOuter final : public
   nsresult SetFullScreen(bool aFullscreen) override;
   bool FindOuter(const nsAString& aString, bool aCaseSensitive, bool aBackwards,
                  bool aWrapAround, bool aWholeWord, bool aSearchInFrames,
                  bool aShowDialog, mozilla::ErrorResult& aError);
   uint64_t GetMozPaintCountOuter();
 
   bool ShouldResistFingerprinting();
 
-  mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> OpenDialogOuter(
+  already_AddRefed<nsPIDOMWindowOuter> OpenDialogOuter(
       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;
   void UpdateCommands(const nsAString& anAction, mozilla::dom::Selection* aSel,
@@ -753,17 +750,17 @@ class nsGlobalWindowOuter final : public
   void CleanUp();
   void ClearControllers();
   // Outer windows only.
   void FinalClose();
 
   inline void MaybeClearInnerWindow(nsGlobalWindowInner* aExpectedInner);
 
   // We need a JSContext to get prototypes inside CallerInnerWindow.
-  static nsGlobalWindowInner* CallerInnerWindow(JSContext* aCx);
+  nsGlobalWindowInner* CallerInnerWindow(JSContext* aCx);
 
   // Get the parent, returns null if this is a toplevel window
   nsPIDOMWindowOuter* GetParentInternal();
 
  public:
   // popup tracking
   bool IsPopupSpamWindow();
 
@@ -963,80 +960,16 @@ class nsGlobalWindowOuter final : public
                                    mozilla::ErrorResult& aError);
 
   void PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                            const nsAString& aTargetOrigin,
                            JS::Handle<JS::Value> aTransfer,
                            nsIPrincipal& aSubjectPrincipal,
                            mozilla::ErrorResult& aError);
 
- public:
-  /**
-   * Compute the principal to use for checking against the target principal in a
-   * postMessage call.
-   *
-   * @param aTargetOrigin The value passed as the targetOrigin argument to the
-   * postMessage call.
-   *
-   * @param aTargetOriginURI The origin of the URI contained in aTargetOrigin
-   * (see GatherPostMessageData).
-   *
-   * @param aCallerPrincipal The principal of the incumbent global of the
-   * postMessage call (see GatherPostMessageData).
-   *
-   * @param aSubjectPrincipal The subject principal for the postMessage call.
-   *
-   * @param aProvidedPrincipal [out] The principal to use for checking against
-   * the target's principal.
-   *
-   * @return Whether the postMessage call should continue or return now.
-   */
-  bool GetPrincipalForPostMessage(const nsAString& aTargetOrigin,
-                                  nsIURI* aTargetOriginURI,
-                                  nsIPrincipal* aCallerPrincipal,
-                                  nsIPrincipal& aSubjectPrincipal,
-                                  nsIPrincipal** aProvidedPrincipal);
-
- private:
-  /**
-   * Gather the necessary data from the caller for a postMessage call.
-   *
-   * @param aCx The JSContext.
-   *
-   * @param aTargetOrigin The value passed as the targetOrigin argument to the
-   * postMessage call.
-   *
-   * @param aSource [out] The browsing context for the incumbent global.
-   *
-   * @param aOrigin [out] The value to use for the origin property of the
-   * MessageEvent object.
-   *
-   * @param aTargetOriginURI [out] The origin of the URI contained in
-   * aTargetOrigin, null if aTargetOrigin is "/" or "*".
-   *
-   * @param aCallerPrincipal [out] The principal of the incumbent global of the
-   *                               postMessage call.
-   *
-   * @param aCallerInnerWindow [out] Inner window of the caller of
-   * postMessage, or null if the incumbent global is not a Window.
-   *
-   * @param aCallerDocumentURI [out] The URI of the document of the incumbent
-   * global if it's a Window, null otherwise.
-   *
-   * @param aError [out] The error, if any.
-   *
-   * @return Whether the postMessage call should continue or return now.
-   */
-  static bool GatherPostMessageData(
-      JSContext* aCx, const nsAString& aTargetOrigin,
-      mozilla::dom::BrowsingContext** aSource, nsAString& aOrigin,
-      nsIURI** aTargetOriginURI, nsIPrincipal** aCallerPrincipal,
-      nsGlobalWindowInner** aCallerInnerWindow, nsIURI** aCallerDocumentURI,
-      mozilla::ErrorResult& aError);
-
   // Ask the user if further dialogs should be blocked, if dialogs are currently
   // being abused. This is used in the cases where we have no modifiable UI to
   // show, in that case we show a separate dialog to ask this question.
   bool ConfirmDialogIfNeeded();
 
   // Helper called after moving/resizing, to update docShell's presContext
   // if we have caused a resolution change by moving across monitors.
   void CheckForDPIChange();
@@ -1044,17 +977,17 @@ class nsGlobalWindowOuter final : public
  private:
   enum class SecureContextFlags { eDefault, eIgnoreOpener };
   // Called only on outer windows to compute the value that will be returned by
   // IsSecureContext() for the inner window that corresponds to aDocument.
   bool ComputeIsSecureContext(
       nsIDocument* aDocument,
       SecureContextFlags aFlags = SecureContextFlags::eDefault);
 
-  void SetDocShell(nsDocShell* aDocShell);
+  void SetDocShell(nsIDocShell* aDocShell);
 
   // nsPIDOMWindow{Inner,Outer} should be able to see these helper methods.
   friend class nsPIDOMWindowInner;
   friend class nsPIDOMWindowOuter;
 
   mozilla::dom::TabGroup* TabGroupOuter();
 
   void SetIsBackgroundInternal(bool aIsBackground);
@@ -1162,17 +1095,16 @@ class nsGlobalWindowOuter final : public
     // 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;
   } mChromeFields;
 
   friend class nsDOMScriptableHelper;
   friend class nsDOMWindowUtils;
-  friend class mozilla::dom::BrowsingContext;
   friend class mozilla::dom::PostMessageEvent;
   friend class DesktopNotification;
   friend class mozilla::dom::TimeoutManager;
   friend class IdleRequestExecutor;
   friend class nsGlobalWindowInner;
 };
 
 // XXX: EWW - This is an awful hack - let's not do this
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -43,17 +43,16 @@
 #include "mozilla/net/ReferrerPolicy.h"  // for member
 #include "mozilla/UseCounter.h"
 #include "mozilla/WeakPtr.h"
 #include "Units.h"
 #include "nsContentListDeclarations.h"
 #include "nsExpirationTracker.h"
 #include "nsClassHashtable.h"
 #include "mozilla/CORSMode.h"
-#include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/ContentBlockingLog.h"
 #include "mozilla/dom/DispatcherTrait.h"
 #include "mozilla/dom/DocumentOrShadowRoot.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/NotNull.h"
 #include "mozilla/SegmentedVector.h"
 #include "mozilla/ServoBindingTypes.h"
 #include "mozilla/StyleSheet.h"
@@ -3073,18 +3072,17 @@ class nsIDocument : public nsINode,
   nsIHTMLCollection* Plugins() { return Embeds(); }
   nsIHTMLCollection* Links();
   nsIHTMLCollection* Forms();
   nsIHTMLCollection* Scripts();
   already_AddRefed<nsContentList> GetElementsByName(const nsAString& aName) {
     return GetFuncStringContentList<nsCachableElementsByNameNodeList>(
         this, MatchNameAttribute, nullptr, UseExistingNameString, aName);
   }
-  mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetDefaultView()
-      const;
+  nsPIDOMWindowOuter* GetDefaultView() const { return GetWindow(); }
   Element* GetActiveElement();
   bool HasFocus(mozilla::ErrorResult& rv) const;
   nsIHTMLCollection* Applets();
   nsIHTMLCollection* Anchors();
   mozilla::TimeStamp LastFocusTime() const;
   void SetLastFocusTime(const mozilla::TimeStamp& aFocusTime);
   // Event handlers are all on nsINode already
   bool MozSyntheticDocument() const { return IsSyntheticDocument(); }
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -1042,17 +1042,17 @@ nsresult nsINode::PostHandleEvent(EventC
 EventListenerManager* nsINode::GetOrCreateListenerManager() {
   return nsContentUtils::GetListenerManagerForNode(this);
 }
 
 EventListenerManager* nsINode::GetExistingListenerManager() const {
   return nsContentUtils::GetExistingListenerManagerForNode(this);
 }
 
-nsPIDOMWindowOuter* nsINode::GetOwnerGlobalForBindingsInternal() {
+nsPIDOMWindowOuter* nsINode::GetOwnerGlobalForBindings() {
   bool dummy;
   auto* window = static_cast<nsGlobalWindowInner*>(
       OwnerDoc()->GetScriptHandlingObject(dummy));
   return window ? nsPIDOMWindowOuter::GetFromCurrentInner(window->AsInner())
                 : nullptr;
 }
 
 nsIGlobalObject* nsINode::GetOwnerGlobal() const {
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -939,17 +939,17 @@ class nsINode : public mozilla::dom::Eve
   virtual mozilla::EventListenerManager* GetExistingListenerManager()
       const override;
   virtual mozilla::EventListenerManager* GetOrCreateListenerManager() override;
 
   bool ComputeDefaultWantsUntrusted(mozilla::ErrorResult& aRv) final;
 
   virtual bool IsApzAware() const override;
 
-  virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindingsInternal() override;
+  virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override;
   virtual nsIGlobalObject* GetOwnerGlobal() const override;
 
   using mozilla::dom::EventTarget::DispatchEvent;
   bool DispatchEvent(mozilla::dom::Event& aEvent,
                      mozilla::dom::CallerType aCallerType,
                      mozilla::ErrorResult& aRv) override;
 
   nsresult PostHandleEvent(mozilla::EventChainPostVisitor& aVisitor) override;
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -1072,18 +1072,18 @@ nsObjectLoadingContent::OnDataAvailable(
 
 // nsIFrameLoaderOwner
 NS_IMETHODIMP_(already_AddRefed<nsFrameLoader>)
 nsObjectLoadingContent::GetFrameLoader() {
   RefPtr<nsFrameLoader> loader = mFrameLoader;
   return loader.forget();
 }
 
-void nsObjectLoadingContent::PresetOpenerWindow(
-    const Nullable<WindowProxyHolder>& aOpenerWindow, ErrorResult& aRv) {
+void nsObjectLoadingContent::PresetOpenerWindow(mozIDOMWindowProxy* aWindow,
+                                                mozilla::ErrorResult& aRv) {
   aRv.Throw(NS_ERROR_FAILURE);
 }
 
 void nsObjectLoadingContent::InternalSetFrameLoader(
     nsFrameLoader* aNewFrameLoader) {
   MOZ_CRASH(
       "You shouldn't be calling this function, it doesn't make any sense on "
       "this type.");
--- a/dom/base/nsObjectLoadingContent.h
+++ b/dom/base/nsObjectLoadingContent.h
@@ -34,19 +34,16 @@ class nsPluginFrame;
 class nsPluginInstanceOwner;
 
 namespace mozilla {
 namespace dom {
 template <typename T>
 class Sequence;
 struct MozPluginParameter;
 class HTMLIFrameElement;
-template <typename T>
-struct Nullable;
-class WindowProxyHolder;
 class XULFrameElement;
 }  // namespace dom
 }  // namespace mozilla
 
 class nsObjectLoadingContent : public nsImageLoadingContent,
                                public nsIStreamListener,
                                public nsIFrameLoaderOwner,
                                public nsIObjectLoadingContent,
@@ -233,18 +230,17 @@ class nsObjectLoadingContent : public ns
                   JS::MutableHandle<JS::Value> aRetval,
                   mozilla::ErrorResult& aRv);
 
   uint32_t GetRunID(mozilla::dom::SystemCallerGuarantee,
                     mozilla::ErrorResult& aRv);
 
   bool IsRewrittenYoutubeEmbed() const { return mRewrittenYoutubeEmbed; }
 
-  void PresetOpenerWindow(const mozilla::dom::Nullable<
-                              mozilla::dom::WindowProxyHolder>& aOpenerWindow,
+  void PresetOpenerWindow(mozIDOMWindowProxy* aOpenerWindow,
                           mozilla::ErrorResult& aRv);
 
  protected:
   /**
    * Begins loading the object when called
    *
    * Attributes of |this| QI'd to nsIContent will be inspected, depending on
    * the node type. This function currently assumes it is a <object> or
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -534,17 +534,17 @@ class nsPIDOMWindowInner : public mozIDO
   // WebIDL-ish APIs
   void MarkUncollectableForCCGeneration(uint32_t aGeneration) {
     mMarkedCCGeneration = aGeneration;
   }
 
   uint32_t GetMarkedCCGeneration() { return mMarkedCCGeneration; }
 
   mozilla::dom::Navigator* Navigator();
-  virtual mozilla::dom::Location* Location() = 0;
+  virtual mozilla::dom::Location* GetLocation() = 0;
 
   virtual nsresult GetControllers(nsIControllers** aControllers) = 0;
 
   virtual nsDOMWindowList* GetFrames() = 0;
 
   virtual nsresult GetInnerWidth(int32_t* aWidth) = 0;
   virtual nsresult GetInnerHeight(int32_t* aHeight) = 0;
 
@@ -878,20 +878,17 @@ class nsPIDOMWindowOuter : public mozIDO
   // the window was frozen.
   virtual nsresult FireDelayedDOMEvents() = 0;
 
   /**
    * Get the docshell in this window.
    */
   inline nsIDocShell* GetDocShell() const;
 
-  /**
-   * Get the browsing context in this window.
-   */
-  inline mozilla::dom::BrowsingContext* GetBrowsingContext() const;
+  mozilla::dom::BrowsingContext* GetBrowsingContext() const;
 
   /**
    * Set a new document in the window. Calling this method will in most cases
    * create a new inner window. This may be called with a pointer to the current
    * document, in that case the document remains unchanged, but a new inner
    * window will be created.
    *
    * aDocument must not be null.
@@ -1101,20 +1098,18 @@ class nsPIDOMWindowOuter : public mozIDO
    * the window before the content itself is created. This is important in order
    * to set the DocGroup of a document, as the opener must be set before the
    * document is created.
    *
    * SetOpenerForInitialContentBrowser is used to set which opener will be used,
    * and TakeOpenerForInitialContentBrowser is used by nsXULElement in order to
    * take the value set earlier, and null out the value in the window.
    */
-  void SetOpenerForInitialContentBrowser(
-      mozilla::dom::BrowsingContext* aOpener);
-  already_AddRefed<mozilla::dom::BrowsingContext>
-  TakeOpenerForInitialContentBrowser();
+  void SetOpenerForInitialContentBrowser(nsPIDOMWindowOuter* aOpener);
+  already_AddRefed<nsPIDOMWindowOuter> TakeOpenerForInitialContentBrowser();
 
  protected:
   // Lazily instantiate an about:blank document if necessary, and if
   // we have what it takes to do so.
   void MaybeCreateDoc();
 
   void SetChromeEventHandlerInternal(
       mozilla::dom::EventTarget* aChromeEventHandler);
@@ -1129,19 +1124,18 @@ class nsPIDOMWindowOuter : public mozIDO
   // Cache the URI when mDoc is cleared.
   nsCOMPtr<nsIURI> mDocumentURI;  // strong
 
   nsCOMPtr<mozilla::dom::EventTarget> mParentTarget;                 // strong
   RefPtr<mozilla::dom::ContentFrameMessageManager> mMessageManager;  // strong
 
   nsCOMPtr<mozilla::dom::Element> mFrameElement;
 
-  // These references are used by nsGlobalWindow.
+  // This reference is used by nsGlobalWindow.
   nsCOMPtr<nsIDocShell> mDocShell;
-  RefPtr<mozilla::dom::BrowsingContext> mBrowsingContext;
 
   uint32_t mModalStateDepth;
 
   // Tracks activation state that's used for :-moz-window-inactive.
   bool mIsActive;
 
   // Tracks whether our docshell is active.  If it is, mIsBackground
   // is false.  Too bad we have so many different concepts of
@@ -1181,17 +1175,17 @@ class nsPIDOMWindowOuter : public mozIDO
   uint32_t mMarkedCCGeneration;
 
   // Let the service workers plumbing know that some feature are enabled while
   // testing.
   bool mServiceWorkersTestingEnabled;
 
   mozilla::dom::LargeAllocStatus mLargeAllocStatus;
 
-  RefPtr<mozilla::dom::BrowsingContext> mOpenerForInitialContentBrowser;
+  nsCOMPtr<nsPIDOMWindowOuter> mOpenerForInitialContentBrowser;
 
   using PermissionInfo = std::pair<bool, mozilla::TimeStamp>;
   nsDataHashtable<nsStringHashKey, PermissionInfo> mAutoplayTemporaryPermission;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMWindowOuter, NS_PIDOMWINDOWOUTER_IID)
 
 #include "nsPIDOMWindowInlines.h"
--- a/dom/base/nsPIDOMWindowInlines.h
+++ b/dom/base/nsPIDOMWindowInlines.h
@@ -63,19 +63,15 @@ bool nsPIDOMWindowInner::IsTopInnerWindo
 }
 
 nsIDocShell* nsPIDOMWindowOuter::GetDocShell() const { return mDocShell; }
 
 nsIDocShell* nsPIDOMWindowInner::GetDocShell() const {
   return mOuterWindow ? mOuterWindow->GetDocShell() : nullptr;
 }
 
-mozilla::dom::BrowsingContext* nsPIDOMWindowOuter::GetBrowsingContext() const {
-  return mBrowsingContext;
-}
-
 mozilla::dom::Element* nsPIDOMWindowOuter::GetFocusedElement() const {
   return mInnerWindow ? mInnerWindow->GetFocusedElement() : nullptr;
 }
 
 mozilla::dom::Element* nsPIDOMWindowInner::GetFocusedElement() const {
   return mFocusedElement;
 }
--- a/dom/base/nsWindowRoot.cpp
+++ b/dom/base/nsWindowRoot.cpp
@@ -101,18 +101,18 @@ void nsWindowRoot::GetEventTargetParent(
   aVisitor.mItemData = static_cast<nsISupports*>(mWindow);
   aVisitor.SetParentTarget(mParent, false);
 }
 
 nsresult nsWindowRoot::PostHandleEvent(EventChainPostVisitor& aVisitor) {
   return NS_OK;
 }
 
-nsPIDOMWindowOuter* nsWindowRoot::GetOwnerGlobalForBindingsInternal() {
-  return mWindow;
+nsPIDOMWindowOuter* nsWindowRoot::GetOwnerGlobalForBindings() {
+  return GetWindow();
 }
 
 nsIGlobalObject* nsWindowRoot::GetOwnerGlobal() const {
   nsCOMPtr<nsIGlobalObject> global =
       do_QueryInterface(mWindow->GetCurrentInnerWindow());
   // We're still holding a ref to it, so returning the raw pointer is ok...
   return global;
 }
--- a/dom/base/nsWindowRoot.h
+++ b/dom/base/nsWindowRoot.h
@@ -55,17 +55,17 @@ class nsWindowRoot final : public nsPIWi
   virtual void SetPopupNode(nsINode* aNode) override;
 
   virtual void SetParentTarget(mozilla::dom::EventTarget* aTarget) override {
     mParent = aTarget;
   }
   virtual mozilla::dom::EventTarget* GetParentTarget() override {
     return mParent;
   }
-  virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindingsInternal() override;
+  virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override;
   virtual nsIGlobalObject* GetOwnerGlobal() const override;
 
   nsIGlobalObject* GetParentObject();
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsWindowRoot)
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -1121,21 +1121,16 @@ bool VariantToJsval(JSContext* aCx, nsIV
       Throw(aCx, NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED);
     }
     return false;
   }
 
   return true;
 }
 
-bool WrapObject(JSContext* cx, const WindowProxyHolder& p,
-                JS::MutableHandle<JS::Value> rval) {
-  return ToJSValue(cx, p, rval);
-}
-
 static int CompareIdsAtIndices(const void* aElement1, const void* aElement2,
                                void* aClosure) {
   const uint16_t index1 = *static_cast<const uint16_t*>(aElement1);
   const uint16_t index2 = *static_cast<const uint16_t*>(aElement2);
   const PropertyInfo* infos = static_cast<PropertyInfo*>(aClosure);
 
   MOZ_ASSERT(JSID_BITS(infos[index1].Id()) != JSID_BITS(infos[index2].Id()));
 
@@ -2798,28 +2793,16 @@ namespace binding_detail {
  * ExtractThisObject: Takes a CallArgs for which HasValidThisValue was true and
  *                    returns the JSObject* to use for getting |this|.
  *
  * MaybeUnwrapThisObject: If our |this| is a JSObject* that this policy wants to
  *                        allow unchecked access to for this
  *                        getter/setter/method, unwrap it.  Otherwise just
  *                        return the given object.
  *
- * UnwrapThisObject: Takes a MutableHandle for a JSObject which contains the
- *                   this object (which the caller probably got from
- *                   MaybeUnwrapThisObject). It will try to get the right native
- *                   out of aObj. In some cases there are 2 possible types for
- *                   the native (which is why aSelf is a reference to a void*).
- *                   The ThisPolicy user should use the this JSObject* to
- *                   determine what C++ class aSelf contains. aObj is used to
- *                   keep the reflector object alive while self is being used,
- *                   so its value before and after the UnwrapThisObject call
- *                   could be different (if aObj was wrapped). The return value
- *                   is an nsresult, which will signal if an error occurred.
- *
  * HandleInvalidThis: If the |this| is not valid (wrong type of value, wrong
  *                    object, etc), decide what to do about it.  Returns a
  *                    boolean to return from the JSNative (false for failure,
  *                    true for succcess).
  */
 struct NormalThisPolicy {
   // This needs to be inlined because it's called on no-exceptions fast-paths.
   static MOZ_ALWAYS_INLINE bool HasValidThisValue(const JS::CallArgs& aArgs) {
@@ -2837,24 +2820,16 @@ struct NormalThisPolicy {
       const JS::CallArgs& aArgs) {
     return &aArgs.thisv().toObject();
   }
 
   static MOZ_ALWAYS_INLINE JSObject* MaybeUnwrapThisObject(JSObject* aObj) {
     return aObj;
   }
 
-  static MOZ_ALWAYS_INLINE nsresult
-  UnwrapThisObject(JS::MutableHandle<JSObject*> aObj, void*& aSelf,
-                   prototypes::ID aProtoID, uint32_t aProtoDepth) {
-    binding_detail::MutableObjectHandleWrapper wrapper(aObj);
-    return binding_detail::UnwrapObjectInternal<void, true>(
-        wrapper, aSelf, aProtoID, aProtoDepth);
-  }
-
   static bool HandleInvalidThis(JSContext* aCx, JS::CallArgs& aArgs,
                                 bool aSecurityError, prototypes::ID aProtoId) {
     return ThrowInvalidThis(aCx, aArgs, aSecurityError, aProtoId);
   }
 };
 
 struct MaybeGlobalThisPolicy : public NormalThisPolicy {
   static MOZ_ALWAYS_INLINE bool HasValidThisValue(const JS::CallArgs& aArgs) {
@@ -2901,60 +2876,21 @@ struct CrossOriginThisPolicy : public Ma
 
   // We want the ExtractThisObject of MaybeGlobalThisPolicy.
 
   static MOZ_ALWAYS_INLINE JSObject* MaybeUnwrapThisObject(JSObject* aObj) {
     if (xpc::WrapperFactory::IsXrayWrapper(aObj)) {
       return js::UncheckedUnwrap(aObj);
     }
 
-    // Else just return aObj; our UnwrapThisObject call will try to
-    // CheckedUnwrap it, and either succeed or get a security error as needed.
+    // Else just return aObj; our UnwrapObjectInternal call will try to
+    // CheckedUnwrap it, and eitehr succeed or get a security error as needed.
     return aObj;
   }
 
-  // After calling UnwrapThisObject aSelf can contain one of 2 types, depending
-  // on whether aObj is a proxy with a RemoteObjectProxy handler or a (maybe
-  // wrapped) normal WebIDL reflector. The generated binding code relies on this
-  // and uses IsRemoteObjectProxy to determine what type aSelf points to.
-  static MOZ_ALWAYS_INLINE nsresult
-  UnwrapThisObject(JS::MutableHandle<JSObject*> aObj, void*& aSelf,
-                   prototypes::ID aProtoID, uint32_t aProtoDepth) {
-    binding_detail::MutableObjectHandleWrapper wrapper(aObj);
-    // We need to pass false here, because if aObj doesn't have a DOMJSClass
-    // it might be a remote proxy object, and we don't want to throw in that
-    // case (even though unwrapping would fail).
-    nsresult rv = binding_detail::UnwrapObjectInternal<void, false>(
-        wrapper, aSelf, aProtoID, aProtoDepth);
-    if (NS_SUCCEEDED(rv)) {
-      return rv;
-    }
-
-    if (js::IsWrapper(wrapper)) {
-      JSObject* unwrappedObj =
-          js::CheckedUnwrap(wrapper, /* stopAtWindowProxy = */ false);
-      if (!unwrappedObj) {
-        return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
-      }
-
-      // At this point we want to keep "unwrappedObj" alive, because we don't
-      // hold a strong reference in "aSelf".
-      wrapper = unwrappedObj;
-
-      return binding_detail::UnwrapObjectInternal<void, false>(
-          wrapper, aSelf, aProtoID, aProtoDepth);
-    }
-
-    if (!IsRemoteObjectProxy(wrapper, aProtoID)) {
-      return NS_ERROR_XPC_BAD_CONVERT_JS;
-    }
-    aSelf = RemoteObjectProxyBase::GetNative(wrapper);
-    return NS_OK;
-  }
-
   // We want the HandleInvalidThis of MaybeGlobalThisPolicy.
 };
 
 /**
  * An ExceptionPolicy struct provides a single HandleException method which is
  * used to handle an exception, if any.  The method is given the current
  * success/failure boolean so it can decide whether there is in fact an
  * exception involved.
@@ -3000,18 +2936,19 @@ bool GenericGetter(JSContext* cx, unsign
   JS::Rooted<JSObject*> obj(cx, ThisPolicy::ExtractThisObject(args));
 
   // NOTE: we want to leave obj in its initial compartment, so don't want to
   // pass it to UnwrapObjectInternal.  Also, the thing we pass to
   // UnwrapObjectInternal may be affected by our ThisPolicy.
   JS::Rooted<JSObject*> rootSelf(cx, ThisPolicy::MaybeUnwrapThisObject(obj));
   void* self;
   {
-    nsresult rv =
-        ThisPolicy::UnwrapThisObject(&rootSelf, self, protoID, info->depth);
+    binding_detail::MutableObjectHandleWrapper wrapper(&rootSelf);
+    nsresult rv = binding_detail::UnwrapObjectInternal<void, true>(
+        wrapper, self, protoID, info->depth);
     if (NS_FAILED(rv)) {
       bool ok = ThisPolicy::HandleInvalidThis(
           cx, args, rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO, protoID);
       return ExceptionPolicy::HandleException(cx, args, info, ok);
     }
   }
 
   MOZ_ASSERT(info->type() == JSJitInfo::Getter);
@@ -3056,18 +2993,19 @@ bool GenericSetter(JSContext* cx, unsign
   JS::Rooted<JSObject*> obj(cx, ThisPolicy::ExtractThisObject(args));
 
   // NOTE: we want to leave obj in its initial compartment, so don't want to
   // pass it to UnwrapObject.  Also the thing we pass to UnwrapObjectInternal
   // may be affected by our ThisPolicy.
   JS::Rooted<JSObject*> rootSelf(cx, ThisPolicy::MaybeUnwrapThisObject(obj));
   void* self;
   {
-    nsresult rv =
-        ThisPolicy::UnwrapThisObject(&rootSelf, self, protoID, info->depth);
+    binding_detail::MutableObjectHandleWrapper wrapper(&rootSelf);
+    nsresult rv = binding_detail::UnwrapObjectInternal<void, true>(
+        wrapper, self, protoID, info->depth);
     if (NS_FAILED(rv)) {
       return ThisPolicy::HandleInvalidThis(
           cx, args, rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO, protoID);
     }
   }
   if (args.length() == 0) {
     return ThrowNoSetterArg(cx, args, protoID);
   }
@@ -3105,18 +3043,19 @@ bool GenericMethod(JSContext* cx, unsign
   JS::Rooted<JSObject*> obj(cx, ThisPolicy::ExtractThisObject(args));
 
   // NOTE: we want to leave obj in its initial compartment, so don't want to
   // pass it to UnwrapObjectInternal.  Also, the thing we pass to
   // UnwrapObjectInternal may be affected by our ThisPolicy.
   JS::Rooted<JSObject*> rootSelf(cx, ThisPolicy::MaybeUnwrapThisObject(obj));
   void* self;
   {
-    nsresult rv =
-        ThisPolicy::UnwrapThisObject(&rootSelf, self, protoID, info->depth);
+    binding_detail::MutableObjectHandleWrapper wrapper(&rootSelf);
+    nsresult rv = binding_detail::UnwrapObjectInternal<void, true>(
+        wrapper, self, protoID, info->depth);
     if (NS_FAILED(rv)) {
       bool ok = ThisPolicy::HandleInvalidThis(
           cx, args, rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO, protoID);
       return ExceptionPolicy::HandleException(cx, args, info, ok);
     }
   }
   MOZ_ASSERT(info->type() == JSJitInfo::Method);
   JSJitMethodOp method = info->method;
@@ -3279,31 +3218,24 @@ nsresult UnwrapArgImpl(JSContext* cx, JS
 
   // We need to go through the QueryInterface logic to make this return
   // the right thing for the various 'special' interfaces; e.g.
   // nsIPropertyBag. We must use AggregatedQueryInterface in cases where
   // there is an outer to avoid nasty recursion.
   return wrappedJS->QueryInterface(iid, ppArg);
 }
 
-nsresult UnwrapWindowProxyArg(JSContext* cx, JS::Handle<JSObject*> src,
-                              WindowProxyHolder& ppArg) {
-  if (IsRemoteObjectProxy(src, prototypes::id::Window)) {
-    ppArg =
-        static_cast<BrowsingContext*>(RemoteObjectProxyBase::GetNative(src));
-    return NS_OK;
-  }
-
+nsresult UnwrapWindowProxyImpl(JSContext* cx, JS::Handle<JSObject*> src,
+                               nsPIDOMWindowOuter** ppArg) {
   nsCOMPtr<nsPIDOMWindowInner> inner;
   nsresult rv = UnwrapArg<nsPIDOMWindowInner>(cx, src, getter_AddRefs(inner));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsPIDOMWindowOuter> outer = inner->GetOuterWindow();
-  RefPtr<BrowsingContext> bc = outer ? outer->GetBrowsingContext() : nullptr;
-  ppArg = bc.forget();
+  outer.forget(ppArg);
   return NS_OK;
 }
 
 template <decltype(JS::NewMapObject) Method>
 bool GetMaplikeSetlikeBackingObject(JSContext* aCx, JS::Handle<JSObject*> aObj,
                                     size_t aSlotIndex,
                                     JS::MutableHandle<JSObject*> aBackingObj,
                                     bool* aBackingObjCreated) {
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -49,32 +49,38 @@ namespace mozilla {
 
 enum UseCounter : int16_t;
 
 namespace dom {
 class CustomElementReactionsStack;
 class MessageManagerGlobal;
 template <typename KeyType, typename ValueType>
 class Record;
-class WindowProxyHolder;
 
 nsresult UnwrapArgImpl(JSContext* cx, JS::Handle<JSObject*> src,
                        const nsIID& iid, void** ppArg);
 
+nsresult UnwrapWindowProxyImpl(JSContext* cx, JS::Handle<JSObject*> src,
+                               nsPIDOMWindowOuter** ppArg);
+
 /** Convert a jsval to an XPCOM pointer. Caller must not assume that src will
     keep the XPCOM pointer rooted. */
 template <class Interface>
 inline nsresult UnwrapArg(JSContext* cx, JS::Handle<JSObject*> src,
                           Interface** ppArg) {
   return UnwrapArgImpl(cx, src, NS_GET_TEMPLATE_IID(Interface),
                        reinterpret_cast<void**>(ppArg));
 }
 
-nsresult UnwrapWindowProxyArg(JSContext* cx, JS::Handle<JSObject*> src,
-                              WindowProxyHolder& ppArg);
+template <>
+inline nsresult UnwrapArg<nsPIDOMWindowOuter>(JSContext* cx,
+                                              JS::Handle<JSObject*> src,
+                                              nsPIDOMWindowOuter** ppArg) {
+  return UnwrapWindowProxyImpl(cx, src, ppArg);
+}
 
 bool ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
                       bool aSecurityError, const char* aInterfaceName);
 
 bool ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
                       bool aSecurityError, prototypes::ID aProtoId);
 
 // Returns true if the JSClass is used for DOM objects.
@@ -1413,19 +1419,16 @@ inline bool WrapObject<JSObject>(JSConte
 }
 
 inline bool WrapObject(JSContext* cx, JSObject& p,
                        JS::MutableHandle<JS::Value> rval) {
   rval.set(JS::ObjectValue(p));
   return true;
 }
 
-bool WrapObject(JSContext* cx, const WindowProxyHolder& p,
-                JS::MutableHandle<JS::Value> rval);
-
 // Given an object "p" that inherits from nsISupports, wrap it and return the
 // result.  Null is returned on wrapping failure.  This is somewhat similar to
 // WrapObject() above, but does NOT allow Xrays around the result, since we
 // don't want those for our parent object.
 template <typename T>
 static inline JSObject* WrapNativeISupports(JSContext* cx, T* p,
                                             nsWrapperCache* cache) {
   xpcObjectHelper helper(ToSupports(p), cache);
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1482,17 +1482,18 @@ DOMInterfaces = {
     },
     'implicitJSContext': [
         'createImageBitmap',
         'requestIdleCallback'
     ],
 },
 
 'WindowProxy': {
-    'headerFile': 'mozilla/dom/WindowProxyHolder.h',
+    'nativeType': 'nsPIDOMWindowOuter',
+    'headerFile': 'nsPIDOMWindow.h',
     'concrete': False
 },
 
 'WindowRoot': {
     'nativeType': 'nsWindowRoot'
 },
 
 'WorkerDebuggerGlobalScope': {
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1383,21 +1383,16 @@ def UnionTypes(unionTypes, config):
                             # Callback interfaces always use strong refs, so
                             # we need to include the right header to be able
                             # to Release() in our inlined code.
                             #
                             # Similarly, sequences always contain strong
                             # refs, so we'll need the header to handler
                             # those.
                             headers.add(typeDesc.headerFile)
-                        elif typeDesc.interface.identifier.name == "WindowProxy":
-                            # In UnionTypes.h we need to see the declaration of the
-                            # WindowProxyHolder that we use to store the WindowProxy, so
-                            # we have its sizeof and know how big to make our union.
-                            headers.add(typeDesc.headerFile)
                         else:
                             declarations.add((typeDesc.nativeType, False))
                             implheaders.add(typeDesc.headerFile)
                 elif f.isDictionary():
                     # For a dictionary, we need to see its declaration in
                     # UnionTypes.h so we have its sizeof and know how big to
                     # make our union.
                     headers.add(CGHeaders.getDeclarationFilename(f.inner))
@@ -2083,85 +2078,16 @@ class PropertyDefiner:
         return MemberCondition(
             PropertyDefiner.getStringAttr(interfaceMember,
                                           "Pref"),
             PropertyDefiner.getStringAttr(interfaceMember,
                                           "Func"),
             interfaceMember.getExtendedAttribute("SecureContext") is not None,
             nonExposureSet)
 
-    @staticmethod
-    def generatePrefableArrayValues(array, descriptor, specFormatter, specTerminator,
-                                    getCondition, getDataTuple,
-                                    switchToCondition=None):
-        """
-        This method generates an array of spec entries for interface members. It returns
-          a tuple containing the array of spec entries and the maximum of the number of
-          spec entries per condition.
-
-        array is an array of interface members.
-
-        descriptor is the descriptor for the interface that array contains members of.
-
-        specFormatter is a function that takes a single argument, a tuple,
-          and returns a string, a spec array entry.
-
-        specTerminator is a terminator for the spec array (inserted every time
-          our controlling pref changes and at the end of the array).
-
-        getCondition is a callback function that takes an array entry and
-          returns the corresponding MemberCondition.
-
-        getDataTuple is a callback function that takes an array entry and
-          returns a tuple suitable to be passed to specFormatter.
-
-        switchToCondition is a function that takes a MemberCondition and an array of
-          previously generated spec entries. If None is passed for this function then all
-          the interface members should return the same value from getCondition.
-        """
-        def unsupportedSwitchToCondition(condition, specs):
-            # If no specs have been added yet then this is just the first call to
-            # switchToCondition that we call to avoid putting a specTerminator at the
-            # front of the list.
-            if len(specs) == 0:
-                return
-            raise "Not supported"
-
-        if switchToCondition is None:
-            switchToCondition = unsupportedSwitchToCondition
-
-        specs = []
-        numSpecsInCurPrefable = 0
-        maxNumSpecsInPrefable = 0
-
-        # So we won't put a specTerminator at the very front of the list:
-        lastCondition = getCondition(array[0], descriptor)
-
-        switchToCondition(lastCondition, specs)
-
-        for member in array:
-            curCondition = getCondition(member, descriptor)
-            if lastCondition != curCondition:
-                # Terminate previous list
-                specs.append(specTerminator)
-                if numSpecsInCurPrefable > maxNumSpecsInPrefable:
-                    maxNumSpecsInPrefable = numSpecsInCurPrefable
-                numSpecsInCurPrefable = 0
-                # And switch to our new condition
-                switchToCondition(curCondition, specs)
-                lastCondition = curCondition
-            # And the actual spec
-            specs.append(specFormatter(getDataTuple(member, descriptor)))
-            numSpecsInCurPrefable += 1
-        if numSpecsInCurPrefable > maxNumSpecsInPrefable:
-            maxNumSpecsInPrefable = numSpecsInCurPrefable
-        specs.append(specTerminator)
-
-        return (specs, maxNumSpecsInPrefable)
-
     def generatePrefableArray(self, array, name, specFormatter, specTerminator,
                               specType, getCondition, getDataTuple):
         """
         This method generates our various arrays.
 
         array is an array of interface members as passed to generateArray
 
         name is the name as passed to generateArray
@@ -2183,54 +2109,76 @@ class PropertyDefiner:
 
         # We want to generate a single list of specs, but with specTerminator
         # inserted at every point where the pref name controlling the member
         # changes.  That will make sure the order of the properties as exposed
         # on the interface and interface prototype objects does not change when
         # pref control is added to members while still allowing us to define all
         # the members in the smallest number of JSAPI calls.
         assert len(array) != 0
-
+        # So we won't put a specTerminator at the very front of the list:
+        lastCondition = getCondition(array[0], self.descriptor)
+
+        specs = []
         disablers = []
         prefableSpecs = []
 
         disablersTemplate = dedent(
             """
             // Can't be const because the pref-enabled boolean needs to be writable
             static PrefableDisablers %s_disablers%d = {
               true, %s, %s, %s
             };
             """)
         prefableWithDisablersTemplate = '  { &%s_disablers%d, &%s_specs[%d] }'
         prefableWithoutDisablersTemplate = '  { nullptr, &%s_specs[%d] }'
         prefCacheTemplate = '&%s[%d].disablers->enabled'
 
-        def switchToCondition(condition, specs):
+        def switchToCondition(props, condition):
             # Remember the info about where our pref-controlled
             # booleans live.
             if condition.pref is not None:
-                self.prefCacheData.append(
+                props.prefCacheData.append(
                     (condition.pref,
                      prefCacheTemplate % (name, len(prefableSpecs))))
             # Set up pointers to the new sets of specs inside prefableSpecs
             if condition.hasDisablers():
                 prefableSpecs.append(prefableWithDisablersTemplate %
                                      (name, len(specs), name, len(specs)))
                 disablers.append(disablersTemplate %
                                  (name, len(specs),
                                   toStringBool(condition.secureContext),
                                   condition.nonExposedGlobals,
                                   condition.func))
             else:
                 prefableSpecs.append(prefableWithoutDisablersTemplate %
                                      (name, len(specs)))
 
-        specs, maxNumSpecsInPrefable = self.generatePrefableArrayValues(
-            array, self.descriptor, specFormatter, specTerminator, getCondition,
-            getDataTuple, switchToCondition)
+        switchToCondition(self, lastCondition)
+
+        numSpecsInCurPrefable = 0
+        maxNumSpecsInPrefable = 0
+
+        for member in array:
+            curCondition = getCondition(member, self.descriptor)
+            if lastCondition != curCondition:
+                # Terminate previous list
+                specs.append(specTerminator)
+                if numSpecsInCurPrefable > maxNumSpecsInPrefable:
+                    maxNumSpecsInPrefable = numSpecsInCurPrefable
+                numSpecsInCurPrefable = 0
+                # And switch to our new condition
+                switchToCondition(self, curCondition)
+                lastCondition = curCondition
+            # And the actual spec
+            specs.append(specFormatter(getDataTuple(member)))
+            numSpecsInCurPrefable += 1
+        specs.append(specTerminator)
+        if numSpecsInCurPrefable > maxNumSpecsInPrefable:
+            maxNumSpecsInPrefable = numSpecsInCurPrefable
         prefableSpecs.append("  { nullptr, nullptr }")
 
         specType = "const " + specType
         arrays = fill(
             """
             // We deliberately use brace-elision to make Visual Studio produce better initalization code.
             #if defined(__clang__)
             #pragma clang diagnostic push
@@ -2308,30 +2256,29 @@ def EnumerabilityFlags(member):
         return "0"
     return "JSPROP_ENUMERATE"
 
 
 class MethodDefiner(PropertyDefiner):
     """
     A class for defining methods on a prototype object.
     """
-    def __init__(self, descriptor, name, crossOriginOnly, static, unforgeable=False):
+    def __init__(self, descriptor, name, static, unforgeable=False):
         assert not (static and unforgeable)
         PropertyDefiner.__init__(self, descriptor, name)
 
         # FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=772822
         #       We should be able to check for special operations without an
         #       identifier. For now we check if the name starts with __
 
         # Ignore non-static methods for interfaces without a proto object
         if descriptor.interface.hasInterfacePrototypeObject() or static:
             methods = [m for m in descriptor.interface.members if
                        m.isMethod() and m.isStatic() == static and
                        MemberIsUnforgeable(m, descriptor) == unforgeable and
-                       (not crossOriginOnly or m.getExtendedAttribute("CrossOriginCallable")) and
                        not m.isIdentifierLess()]
         else:
             methods = []
         self.chrome = []
         self.regular = []
         for m in methods:
             if m.identifier.name == 'QueryInterface':
                 # QueryInterface is special, because instead of generating an
@@ -2358,17 +2305,26 @@ class MethodDefiner(PropertyDefiner):
                     "name": 'QueryInterface',
                     "methodInfo": False,
                     "length": 1,
                     "flags": "0",
                     "condition": PropertyDefiner.getControllingCondition(m, descriptor)
                 })
                 continue
 
-            method = self.methodData(m, descriptor)
+            method = {
+                "name": m.identifier.name,
+                "methodInfo": not m.isStatic(),
+                "length": methodLength(m),
+                "flags": EnumerabilityFlags(m),
+                "condition": PropertyDefiner.getControllingCondition(m, descriptor),
+                "allowCrossOriginThis": m.getExtendedAttribute("CrossOriginCallable"),
+                "returnsPromise": m.returnsPromise(),
+                "hasIteratorAlias": "@@iterator" in m.aliases
+            }
 
             if m.isStatic():
                 method["nativeName"] = CppKeywords.checkMethodName(IDLToCIdentifier(m.identifier.name))
 
             if isChromeOnly(m):
                 self.chrome.append(method)
             else:
                 self.regular.append(method)
@@ -2493,96 +2449,80 @@ class MethodDefiner(PropertyDefiner):
             if not descriptor.interface.hasInterfaceObject():
                 # static methods go on the interface object
                 assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
         else:
             if not descriptor.interface.hasInterfacePrototypeObject():
                 # non-static methods go on the interface prototype object
                 assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
 
-    @staticmethod
-    def methodData(m, descriptor, overrideFlags=None):
-        return {
-                "name": m.identifier.name,
-                "methodInfo": not m.isStatic(),
-                "length": methodLength(m),
-                "flags": EnumerabilityFlags(m) if (overrideFlags is None) else overrideFlags,
-                "condition": PropertyDefiner.getControllingCondition(m, descriptor),
-                "allowCrossOriginThis": m.getExtendedAttribute("CrossOriginCallable"),
-                "returnsPromise": m.returnsPromise(),
-                "hasIteratorAlias": "@@iterator" in m.aliases
-            }
-
-    @staticmethod
-    def formatSpec(fields):
-        if fields[0].startswith("@@"):
-            fields = (fields[0][2:],) + fields[1:]
-            return '  JS_SYM_FNSPEC(%s, %s, %s, %s, %s, %s)' % fields
-        return '  JS_FNSPEC("%s", %s, %s, %s, %s, %s)' % fields
-
-    @staticmethod
-    def specData(m, descriptor, unforgeable=False):
-        def flags(m, unforgeable):
-            unforgeable = " | JSPROP_PERMANENT | JSPROP_READONLY" if unforgeable else ""
-            return m["flags"] + unforgeable
-
-        if "selfHostedName" in m:
-            selfHostedName = '"%s"' % m["selfHostedName"]
-            assert not m.get("methodInfo", True)
-            accessor = "nullptr"
-            jitinfo = "nullptr"
-        else:
-            selfHostedName = "nullptr"
-            # When defining symbols, function name may not match symbol name
-            methodName = m.get("methodName", m["name"])
-            accessor = m.get("nativeName", IDLToCIdentifier(methodName))
-            if m.get("methodInfo", True):
-                if m.get("returnsPromise", False):
-                    exceptionPolicy = "ConvertExceptionsToPromises"
-                else:
-                    exceptionPolicy = "ThrowExceptions"
-
-                # Cast this in case the methodInfo is a
-                # JSTypedMethodJitInfo.
-                jitinfo = ("reinterpret_cast<const JSJitInfo*>(&%s_methodinfo)" % accessor)
-                if m.get("allowCrossOriginThis", False):
-                    accessor = ("(GenericMethod<CrossOriginThisPolicy, %s>)" %
-                                exceptionPolicy)
-                elif descriptor.interface.isOnGlobalProtoChain():
-                    accessor = ("(GenericMethod<MaybeGlobalThisPolicy, %s>)" %
-                                exceptionPolicy)
-                else:
-                    accessor = ("(GenericMethod<NormalThisPolicy, %s>)" %
-                                exceptionPolicy)
-            else:
-                if m.get("returnsPromise", False):
-                    jitinfo = "&%s_methodinfo" % accessor
-                    accessor = "StaticMethodPromiseWrapper"
-                else:
-                    jitinfo = "nullptr"
-
-        return (m["name"], accessor, jitinfo, m["length"], flags(m, unforgeable), selfHostedName)
-
-    @staticmethod
-    def condition(m, d):
-        return m["condition"]
-
     def generateArray(self, array, name):
         if len(array) == 0:
             return ""
 
+        def condition(m, d):
+            return m["condition"]
+
+        def flags(m):
+            unforgeable = " | JSPROP_PERMANENT | JSPROP_READONLY" if self.unforgeable else ""
+            return m["flags"] + unforgeable
+
+        def specData(m):
+            if "selfHostedName" in m:
+                selfHostedName = '"%s"' % m["selfHostedName"]
+                assert not m.get("methodInfo", True)
+                accessor = "nullptr"
+                jitinfo = "nullptr"
+            else:
+                selfHostedName = "nullptr"
+                # When defining symbols, function name may not match symbol name
+                methodName = m.get("methodName", m["name"])
+                accessor = m.get("nativeName", IDLToCIdentifier(methodName))
+                if m.get("methodInfo", True):
+                    if m.get("returnsPromise", False):
+                        exceptionPolicy = "ConvertExceptionsToPromises"
+                    else:
+                        exceptionPolicy = "ThrowExceptions"
+
+                    # Cast this in case the methodInfo is a
+                    # JSTypedMethodJitInfo.
+                    jitinfo = ("reinterpret_cast<const JSJitInfo*>(&%s_methodinfo)" % accessor)
+                    if m.get("allowCrossOriginThis", False):
+                        accessor = ("(GenericMethod<CrossOriginThisPolicy, %s>)" %
+                                    exceptionPolicy)
+                    elif self.descriptor.interface.isOnGlobalProtoChain():
+                        accessor = ("(GenericMethod<MaybeGlobalThisPolicy, %s>)" %
+                                    exceptionPolicy)
+                    else:
+                        accessor = ("(GenericMethod<NormalThisPolicy, %s>)" %
+                                    exceptionPolicy)
+                else:
+                    if m.get("returnsPromise", False):
+                        jitinfo = "&%s_methodinfo" % accessor
+                        accessor = "StaticMethodPromiseWrapper"
+                    else:
+                        jitinfo = "nullptr"
+
+            return (m["name"], accessor, jitinfo, m["length"], flags(m), selfHostedName)
+
+        def formatSpec(fields):
+            if fields[0].startswith("@@"):
+                fields = (fields[0][2:],) + fields[1:]
+                return '  JS_SYM_FNSPEC(%s, %s, %s, %s, %s, %s)' % fields
+            return '  JS_FNSPEC("%s", %s, %s, %s, %s, %s)' % fields
+
         return self.generatePrefableArray(
             array, name,
-            self.formatSpec,
+            formatSpec,
             '  JS_FS_END',
             'JSFunctionSpec',
-            self.condition, functools.partial(self.specData, unforgeable=self.unforgeable))
-
-
-def isCrossOriginWritable(attr, descriptor):
+            condition, specData)
+
+
+def IsCrossOriginWritable(attr, descriptor):
     """
     Return whether the IDLAttribute in question is cross-origin writable on the
     interface represented by descriptor.  This is needed to handle the fact that
     some, but not all, interfaces implementing URLUtils want a cross-origin
     writable .href.
     """
     crossOriginWritable = attr.getExtendedAttribute("CrossOriginWritable")
     if not crossOriginWritable:
@@ -2593,66 +2533,62 @@ def isCrossOriginWritable(attr, descript
             len(crossOriginWritable) == 1)
     return crossOriginWritable[0] == descriptor.interface.identifier.name
 
 def isNonExposedNavigatorObjectGetter(attr, descriptor):
     return (attr.navigatorObjectGetter and
             not descriptor.getDescriptor(attr.type.inner.identifier.name).register)
 
 class AttrDefiner(PropertyDefiner):
-    def __init__(self, descriptor, name, crossOriginOnly, static, unforgeable=False):
+    def __init__(self, descriptor, name, static, unforgeable=False):
         assert not (static and unforgeable)
         PropertyDefiner.__init__(self, descriptor, name)
         self.name = name
         # Ignore non-static attributes for interfaces without a proto object
         if descriptor.interface.hasInterfacePrototypeObject() or static:
-            idlAttrs = [m for m in descriptor.interface.members if
-                        m.isAttr() and m.isStatic() == static and
-                        MemberIsUnforgeable(m, descriptor) == unforgeable and
-                        (not crossOriginOnly or m.getExtendedAttribute("CrossOriginReadable") or
-                         isCrossOriginWritable(m, descriptor)) and
-                        not isNonExposedNavigatorObjectGetter(m, descriptor)]
-        else:
-            idlAttrs = []
-
-        attributes = []
-        for attr in idlAttrs:
-            attributes.extend(self.attrData(attr, unforgeable))
+            attributes = [m for m in descriptor.interface.members if
+                          m.isAttr() and m.isStatic() == static and
+                          MemberIsUnforgeable(m, descriptor) == unforgeable and
+                          not isNonExposedNavigatorObjectGetter(m, descriptor)]
+        else:
+            attributes = []
+
+        attributes = [
+            {"name": name, "attr": attr}
+            for attr in attributes
+            for name in [attr.identifier.name] + attr.bindingAliases
+        ]
+
         self.chrome = [m for m in attributes if isChromeOnly(m["attr"])]
         self.regular = [m for m in attributes if not isChromeOnly(m["attr"])]
         self.static = static
+        self.unforgeable = unforgeable
 
         if static:
             if not descriptor.interface.hasInterfaceObject():
                 # static attributes go on the interface object
                 assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
         else:
             if not descriptor.interface.hasInterfacePrototypeObject():
                 # non-static attributes go on the interface prototype object
                 assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
 
-    @staticmethod
-    def attrData(attr, unforgeable=False, overrideFlags=None):
-        if overrideFlags is None:
-            permanent = " | JSPROP_PERMANENT" if unforgeable else ""
-            flags = EnumerabilityFlags(attr) + permanent
-        else:
-            flags = overrideFlags
-        return ({"name": name, "attr": attr, "flags": flags} for name in [attr.identifier.name] + attr.bindingAliases)
-
-    @staticmethod
-    def condition(m, d):
-        return PropertyDefiner.getControllingCondition(m["attr"], d)
-
-    @staticmethod
-    def specData(entry, descriptor, static=False, crossOriginOnly=False):
+    def generateArray(self, array, name):
+        if len(array) == 0:
+            return ""
+
+        def condition(m, d):
+            return PropertyDefiner.getControllingCondition(m["attr"], d)
+
+        def flags(attr):
+            unforgeable = " | JSPROP_PERMANENT" if self.unforgeable else ""
+            return EnumerabilityFlags(attr) + unforgeable
+
         def getter(attr):
-            if crossOriginOnly and not attr.getExtendedAttribute("CrossOriginReadable"):
-                return "nullptr, nullptr"
-            if static:
+            if self.static:
                 if attr.type.isPromise():
                     raise TypeError("Don't know how to handle "
                                     "static Promise-returning "
                                     "attribute %s.%s" %
                                     (self.descriptor.name,
                                      attr.identifier.name))
                 accessor = 'get_' + IDLToCIdentifier(attr.identifier.name)
                 jitinfo = "nullptr"
@@ -2668,72 +2604,64 @@ class AttrDefiner(PropertyDefiner):
                                         "readable attribute %s.%s" %
                                         (self.descriptor.name,
                                          attr.identifier.name))
                     accessor = ("GenericGetter<LenientThisPolicy, %s>" %
                                 exceptionPolicy)
                 elif attr.getExtendedAttribute("CrossOriginReadable"):
                     accessor = ("GenericGetter<CrossOriginThisPolicy, %s>" %
                                 exceptionPolicy)
-                elif descriptor.interface.isOnGlobalProtoChain():
+                elif self.descriptor.interface.isOnGlobalProtoChain():
                     accessor = ("GenericGetter<MaybeGlobalThisPolicy, %s>" %
                                 exceptionPolicy)
                 else:
                     accessor = ("GenericGetter<NormalThisPolicy, %s>" %
                                 exceptionPolicy)
                 jitinfo = ("&%s_getterinfo" %
                            IDLToCIdentifier(attr.identifier.name))
             return "%s, %s" % \
                    (accessor, jitinfo)
 
         def setter(attr):
             if (attr.readonly and
                 attr.getExtendedAttribute("PutForwards") is None and
                 attr.getExtendedAttribute("Replaceable") is None and
                 attr.getExtendedAttribute("LenientSetter") is None):
                 return "nullptr, nullptr"
-            if crossOriginOnly and not isCrossOriginWritable(attr, descriptor):
-                return "nullptr, nullptr"
-            if static:
+            if self.static:
                 accessor = 'set_' + IDLToCIdentifier(attr.identifier.name)
                 jitinfo = "nullptr"
             else:
                 if attr.hasLenientThis():
-                    if isCrossOriginWritable(attr, descriptor):
+                    if IsCrossOriginWritable(attr, self.descriptor):
                         raise TypeError("Can't handle lenient cross-origin "
                                         "writable attribute %s.%s" %
-                                        (descriptor.name,
+                                        (self.descriptor.name,
                                          attr.identifier.name))
                     accessor = "GenericSetter<LenientThisPolicy>"
-                elif isCrossOriginWritable(attr, descriptor):
+                elif IsCrossOriginWritable(attr, self.descriptor):
                     accessor = "GenericSetter<CrossOriginThisPolicy>"
-                elif descriptor.interface.isOnGlobalProtoChain():
+                elif self.descriptor.interface.isOnGlobalProtoChain():
                     accessor = "GenericSetter<MaybeGlobalThisPolicy>"
                 else:
                     accessor = "GenericSetter<NormalThisPolicy>"
                 jitinfo = "&%s_setterinfo" % IDLToCIdentifier(attr.identifier.name)
             return "%s, %s" % \
                    (accessor, jitinfo)
 
-        name, attr, flags = entry["name"], entry["attr"], entry["flags"]
-        return (name, flags, getter(attr), setter(attr))
-
-    @staticmethod
-    def formatSpec(fields):
-        return '  { "%s", %s, %s, %s }' % fields
-
-    def generateArray(self, array, name):
-        if len(array) == 0:
-            return ""
+        def specData(entry):
+            name, attr = entry["name"], entry["attr"]
+            return (name, flags(attr), getter(attr), setter(attr))
 
         return self.generatePrefableArray(
-            array, name, self.formatSpec,
-            '  JS_PS_END',
+            array, name,
+            lambda fields: '  { "%s", %s, %s, %s }' % fields,
+            '  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }',
             'JSPropertySpec',
-            self.condition, functools.partial(self.specData, static=self.static))
+            condition, specData)
 
 
 class ConstDefiner(PropertyDefiner):
     """
     A class for definining constants on the interface object
     """
     def __init__(self, descriptor, name):
         PropertyDefiner.__init__(self, descriptor, name)
@@ -2741,42 +2669,40 @@ class ConstDefiner(PropertyDefiner):
         constants = [m for m in descriptor.interface.members if m.isConst()]
         self.chrome = [m for m in constants if isChromeOnly(m)]
         self.regular = [m for m in constants if not isChromeOnly(m)]
 
     def generateArray(self, array, name):
         if len(array) == 0:
             return ""
 
-        def specData(const, descriptor):
+        def specData(const):
             return (const.identifier.name,
                     convertConstIDLValueToJSVal(const.value))
 
         return self.generatePrefableArray(
             array, name,
             lambda fields: '  { "%s", %s }' % fields,
             '  { 0, JS::UndefinedValue() }',
             'ConstantSpec',
             PropertyDefiner.getControllingCondition, specData)
 
 
 class PropertyArrays():
-    def __init__(self, descriptor, crossOriginOnly=False):
-        self.staticMethods = MethodDefiner(descriptor, "StaticMethods", crossOriginOnly,
+    def __init__(self, descriptor):
+        self.staticMethods = MethodDefiner(descriptor, "StaticMethods",
                                            static=True)
-        self.staticAttrs = AttrDefiner(descriptor, "StaticAttributes", crossOriginOnly,
+        self.staticAttrs = AttrDefiner(descriptor, "StaticAttributes",
                                        static=True)
-        self.methods = MethodDefiner(descriptor, "Methods", crossOriginOnly, static=False)
-        self.attrs = AttrDefiner(descriptor, "Attributes", crossOriginOnly, static=False)
+        self.methods = MethodDefiner(descriptor, "Methods", static=False)
+        self.attrs = AttrDefiner(descriptor, "Attributes", static=False)
         self.unforgeableMethods = MethodDefiner(descriptor, "UnforgeableMethods",
-                                                crossOriginOnly, static=False,
-                                                unforgeable=True)
+                                                static=False, unforgeable=True)
         self.unforgeableAttrs = AttrDefiner(descriptor, "UnforgeableAttributes",
-                                            crossOriginOnly, static=False,
-                                            unforgeable=True)
+                                            static=False, unforgeable=True)
         self.consts = ConstDefiner(descriptor, "Constants")
 
     @staticmethod
     def arrayNames():
         return ["staticMethods", "staticAttrs", "methods", "attrs",
                 "unforgeableMethods", "unforgeableAttrs", "consts"]
 
     def hasChromeOnly(self):
@@ -4145,87 +4071,16 @@ class CGClearCachedValueMethod(CGAbstrac
             declObj=declObj,
             noopRetval=noopRetval,
             saveMember=saveMember,
             slotIndex=slotIndex,
             clearXrayExpandoSlots=clearXrayExpandoSlots,
             regetMember=regetMember)
 
 
-class CGCrossOriginProperties(CGThing):
-    def __init__(self, descriptor):
-        attrs = []
-        methods = []
-        for m in descriptor.interface.members:
-            if m.isAttr() and (m.getExtendedAttribute("CrossOriginReadable") or isCrossOriginWritable(m, descriptor)):
-                if m.isStatic():
-                    raise TypeError("Don't know how to deal with static method %s" %
-                                    m.identifier.name)
-                if PropertyDefiner.getControllingCondition(m, descriptor).hasDisablers():
-                    raise TypeError("Don't know how to deal with disabler for %s" %
-                                    m.identifier.name)
-                if len(m.bindingAliases) > 0:
-                    raise TypeError("Don't know how to deal with aliases for %s" %
-                                    m.identifier.name)
-                attrs.extend(AttrDefiner.attrData(m, overrideFlags="0"))
-            elif m.isMethod() and m.getExtendedAttribute("CrossOriginCallable"):
-                if m.isStatic():
-                    raise TypeError("Don't know how to deal with static method %s" %
-                                    m.identifier.name)
-                if PropertyDefiner.getControllingCondition(m, descriptor).hasDisablers():
-                    raise TypeError("Don't know how to deal with disabler for %s" %
-                                    m.identifier.name)
-                if len(m.aliases) > 0:
-                    raise TypeError("Don't know how to deal with aliases for %s" %
-                                    m.identifier.name)
-                methods.append(MethodDefiner.methodData(m, descriptor, overrideFlags="JSPROP_READONLY"))
-
-        if len(attrs) > 0:
-            self.attributeSpecs, _ = PropertyDefiner.generatePrefableArrayValues(
-                attrs, descriptor, AttrDefiner.formatSpec, '  JS_PS_END\n',
-                AttrDefiner.condition, functools.partial(AttrDefiner.specData, crossOriginOnly=True))
-        else:
-            self.attributeSpecs = [' JS_PS_END\n']
-        if len(methods) > 0:
-            self.methodSpecs, _ = PropertyDefiner.generatePrefableArrayValues(
-                methods, descriptor, MethodDefiner.formatSpec, '  JS_FS_END\n',
-                MethodDefiner.condition, MethodDefiner.specData)
-        else:
-            self.methodSpecs = ['  JS_FS_END\n']
-
-    def declare(self):
-        return fill("""
-            extern JSPropertySpec sCrossOriginAttributes[${attributesLength}];
-            extern JSFunctionSpec sCrossOriginMethods[${methodsLength}];
-            """,
-            attributesLength=len(self.attributeSpecs),
-            methodsLength=len(self.methodSpecs))
-
-    def define(self):
-        return fill(
-            """
-            // We deliberately use brace-elision to make Visual Studio produce better initalization code.
-            #if defined(__clang__)
-            #pragma clang diagnostic push
-            #pragma clang diagnostic ignored "-Wmissing-braces"
-            #endif
-            JSPropertySpec sCrossOriginAttributes[] = {
-              $*{attributeSpecs}
-            };
-            JSFunctionSpec sCrossOriginMethods[] = {
-              $*{methodSpecs}
-            };
-            #if defined(__clang__)
-            #pragma clang diagnostic pop
-            #endif
-            """,
-            attributeSpecs=",\n".join(self.attributeSpecs),
-            methodSpecs=",\n".join(self.methodSpecs))
-
-
 class CGIsPermittedMethod(CGAbstractMethod):
     """
     crossOriginGetters/Setters/Methods are sets of names of the relevant members.
     """
     def __init__(self, descriptor, crossOriginGetters, crossOriginSetters,
                  crossOriginMethods):
         self.crossOriginGetters = crossOriginGetters
         self.crossOriginSetters = crossOriginSetters
@@ -5631,38 +5486,16 @@ def getJSToNativeConversionInfo(type, de
                                                      isOptional)
             template = wrapObjectTemplate(conversion, type,
                                           "${declName} = nullptr;\n",
                                           failureCode)
             return JSToNativeConversionInfo(template, declType=declType,
                                             declArgs=declArgs,
                                             dealWithOptional=isOptional)
 
-        if descriptor.interface.identifier.name == "WindowProxy":
-            declType = CGGeneric("mozilla::dom::WindowProxyHolder")
-            if type.nullable():
-                declType = CGTemplatedType("Nullable", declType)
-                windowProxyHolderRef = "${declName}.SetValue()"
-            else:
-                windowProxyHolderRef = "${declName}"
-
-            failureCode = onFailureBadType(failureCode, descriptor.interface.identifier.name).define()
-            templateBody = fill("""
-                JS::Rooted<JSObject*> source(cx, &$${val}.toObject());
-                if (NS_FAILED(UnwrapWindowProxyArg(cx, source, ${windowProxyHolderRef}))) {
-                    $*{onFailure}
-                }
-                """,
-                windowProxyHolderRef=windowProxyHolderRef,
-                onFailure=failureCode)
-            templateBody = wrapObjectTemplate(templateBody, type,
-                                              "${declName}.SetNull();\n", failureCode)
-            return JSToNativeConversionInfo(templateBody, declType=declType,
-                                            dealWithOptional=isOptional)
-
         # This is an interface that we implement as a concrete class
         # or an XPCOM interface.
 
         # Allow null pointers for nullable types and old-binding classes, and
         # use an RefPtr or raw pointer for callback return values to make
         # them easier to return.
         argIsPointer = (type.nullable() or type.unroll().inner.isExternal() or
                         isCallbackReturnValue)
@@ -6837,26 +6670,16 @@ def getWrapTemplateForType(type, descrip
         # the various RefPtr, rawptr, NonNull, etc cases, which ToJSValue will
         # handle for us.  So just eat the cost of the function call.
         return (wrapAndSetPtr("ToJSValue(cx, %s, ${jsvalHandle})" % result),
                 False)
 
     if type.isGeckoInterface() and not type.isCallbackInterface():
         descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name)
         if type.nullable():
-            if descriptor.interface.identifier.name == "WindowProxy":
-                template, infal = getWrapTemplateForType(type.inner, descriptorProvider,
-                                                         "%s.Value()" % result, successCode,
-                                                         returnsNewObject, exceptionCode,
-                                                         spiderMonkeyInterfacesAreStructs)
-                return ("if (%s.IsNull()) {\n" % result +
-                        indent(setNull()) +
-                        "}\n" +
-                        template, infal)
-
             wrappingCode = ("if (!%s) {\n" % (result) +
                             indent(setNull()) +
                             "}\n")
         else:
             wrappingCode = ""
 
         if not descriptor.interface.isExternal():
             if descriptor.wrapperCache:
@@ -7168,24 +6991,18 @@ def getRetvalDeclarationForType(returnTy
         return CGGeneric("nsCString"), "ref", None, None, None
     if returnType.isEnum():
         result = CGGeneric(returnType.unroll().inner.identifier.name)
         if returnType.nullable():
             result = CGTemplatedType("Nullable", result)
         return result, None, None, None, None
     if returnType.isGeckoInterface() or returnType.isPromise():
         if returnType.isGeckoInterface():
-            typeName = returnType.unroll().inner.identifier.name
-            if typeName == "WindowProxy":
-                result = CGGeneric("WindowProxyHolder")
-                if returnType.nullable():
-                    result = CGTemplatedType("Nullable", result)
-                return result, None, None, None, None
-
-            typeName = descriptorProvider.getDescriptor(typeName).nativeType
+            typeName = descriptorProvider.getDescriptor(
+                returnType.unroll().inner.identifier.name).nativeType
         else:
             typeName = "Promise"
         if isMember:
             conversion = None
             result = CGGeneric("StrongPtrForMember<%s>::Type" % typeName)
         else:
             conversion = CGGeneric("StrongOrRawPtr<%s>" % typeName)
             result = CGGeneric("auto")
@@ -7689,49 +7506,41 @@ class CGPerSignatureCall(CGThing):
        the method is called (|self->nativeMethodName(...)| vs
        |nativeMethodName(...)|).
 
     We also need to know whether this is a method or a getter/setter
     to do error reporting correctly.
 
     The idlNode parameter can be either a method or an attr. We can query
     |idlNode.identifier| in both cases, so we can be agnostic between the two.
-
-    dontSetSlot should be set to True if the value should not be cached in a
-    slot (even if the attribute is marked as StoreInSlot or Cached in the
-    WebIDL).
     """
     # XXXbz For now each entry in the argument list is either an
     # IDLArgument or a FakeArgument, but longer-term we may want to
     # have ways of flagging things like JSContext* or optional_argc in
     # there.
 
     def __init__(self, returnType, arguments, nativeMethodName, static,
                  descriptor, idlNode, argConversionStartsAt=0, getter=False,
                  setter=False, isConstructor=False, useCounterName=None,
-                 resultVar=None, objectName="obj", dontSetSlot=False,
-                 extendedAttributes=None):
+                 resultVar=None, objectName="obj"):
         assert idlNode.isMethod() == (not getter and not setter)
         assert idlNode.isAttr() == (getter or setter)
         # Constructors are always static
         assert not isConstructor or static
 
         CGThing.__init__(self)
         self.returnType = returnType
         self.descriptor = descriptor
         self.idlNode = idlNode
-        if extendedAttributes is None:
-            extendedAttributes = descriptor.getExtendedAttributes(idlNode,
-                                                                  getter=getter,
-                                                                  setter=setter)
-        self.extendedAttributes = extendedAttributes
+        self.extendedAttributes = descriptor.getExtendedAttributes(idlNode,
+                                                                   getter=getter,
+                                                                   setter=setter)
         self.arguments = arguments
         self.argCount = len(arguments)
         self.isConstructor = isConstructor
-        self.setSlot = not dontSetSlot and idlNode.isAttr() and idlNode.slotIndices is not None
         cgThings = []
 
         deprecated = (idlNode.getExtendedAttribute("Deprecated") or
                       (idlNode.isStatic() and descriptor.interface.getExtendedAttribute("Deprecated")))
         if deprecated:
             cgThings.append(CGGeneric(dedent(
                 """
                 DeprecationWarning(cx, obj, nsIDocument::e%s);
@@ -7964,44 +7773,45 @@ class CGPerSignatureCall(CGThing):
             (self.returnType.isGeckoInterface() or
              self.returnType.isPromise())):
             wrapCode += dedent(
                 """
                 static_assert(!IsPointer<decltype(result)>::value,
                               "NewObject implies that we need to keep the object alive with a strong reference.");
                 """)
 
-        if self.setSlot:
+        setSlot = self.idlNode.isAttr() and self.idlNode.slotIndices is not None
+        if setSlot:
             # For attributes in slots, we want to do some
             # post-processing once we've wrapped them.
             successCode = "break;\n"
         else:
             successCode = None
 
         resultTemplateValues = {
             'jsvalRef': 'args.rval()',
             'jsvalHandle': 'args.rval()',
             'returnsNewObject': returnsNewObject,
             'isConstructorRetval': self.isConstructor,
             'successCode': successCode,
             # 'obj' in this dictionary is the thing whose compartment we are
             # trying to do the to-JS conversion in.  We're going to put that
             # thing in a variable named "conversionScope" if setSlot is true.
             # Otherwise, just use "obj" for lack of anything better.
-            'obj': "conversionScope" if self.setSlot else "obj"
+            'obj': "conversionScope" if setSlot else "obj"
         }
         try:
             wrapCode += wrapForType(self.returnType, self.descriptor, resultTemplateValues)
         except MethodNotNewObjectError, err:
             assert not returnsNewObject
             raise TypeError("%s being returned from non-NewObject method or property %s.%s" %
                             (err.typename,
                              self.descriptor.interface.identifier.name,
                              self.idlNode.identifier.name))
-        if self.setSlot:
+        if setSlot:
             if self.idlNode.isStatic():
                 raise TypeError(
                     "Attribute %s.%s is static, so we don't have a useful slot "
                     "to cache it in, because we don't have support for that on "
                     "interface objects.  See "
                     "https://bugzilla.mozilla.org/show_bug.cgi?id=1363870" %
                     (self.descriptor.interface.identifier.name,
                      self.idlNode.identifier.name))
@@ -8592,43 +8402,38 @@ class CGMethodCall(CGThing):
         return self.cgRoot.define()
 
 
 class CGGetterCall(CGPerSignatureCall):
     """
     A class to generate a native object getter call for a particular IDL
     getter.
     """
-    def __init__(self, returnType, nativeMethodName, descriptor, attr, dontSetSlot=False,
-                 extendedAttributes=None):
+    def __init__(self, returnType, nativeMethodName, descriptor, attr):
         if attr.getExtendedAttribute("UseCounter"):
             useCounterName = "%s_%s_getter" % (descriptor.interface.identifier.name,
                                                attr.identifier.name)
         else:
             useCounterName = None
         if attr.isStatic():
             nativeMethodName = "%s::%s" % (descriptor.nativeType, nativeMethodName)
         CGPerSignatureCall.__init__(self, returnType, [], nativeMethodName,
                                     attr.isStatic(), descriptor, attr,
-                                    getter=True, useCounterName=useCounterName,
-                                    dontSetSlot=dontSetSlot,
-                                    extendedAttributes=extendedAttributes)
+                                    getter=True, useCounterName=useCounterName)
 
 
 class CGNavigatorGetterCall(CGPerSignatureCall):
     """
     A class to generate a native object getter call for an IDL getter for a
     property generated by NavigatorProperty.
     """
-    def __init__(self, returnType, _, descriptor, attr,
-                 dontSetSlot=False):
+    def __init__(self, returnType, _, descriptor, attr):
         nativeMethodName = "%s::ConstructNavigatorObject" % (toBindingNamespace(returnType.inner.identifier.name))
         CGPerSignatureCall.__init__(self, returnType, [], nativeMethodName,
-                                    True, descriptor, attr, getter=True,
-                                    dontSetSlot=dontSetSlot)
+                                    True, descriptor, attr, getter=True)
 
     def getArguments(self):
         # The navigator object should be associated with the global of
         # the navigator it's coming from, which will be the global of
         # the object whose slot it gets cached in.  That's stored in
         # "slotStorage".
         return [(FakeArgument(BuiltinTypes[IDLBuiltinType.Types.object],
                               self.idlNode),
@@ -8798,58 +8603,28 @@ def MakeNativeName(name):
 class CGSpecializedMethod(CGAbstractStaticMethod):
     """
     A class for generating the C++ code for a specialized method that the JIT
     can call with lower overhead.
     """
     def __init__(self, descriptor, method):
         self.method = method
         name = CppKeywords.checkMethodName(IDLToCIdentifier(method.identifier.name))
-        if method.getExtendedAttribute("CrossOriginCallable"):
-            selfArg = Argument('void*', 'void_self')
-        else:
-            selfArg = Argument('%s*' % descriptor.nativeType, 'self')
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'obj'),
-                selfArg,
+                Argument('%s*' % descriptor.nativeType, 'self'),
                 Argument('const JSJitMethodCallArgs&', 'args')]
         CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args,
                                         canRunScript=True)
 
     def definition_body(self):
         nativeName = CGSpecializedMethod.makeNativeName(self.descriptor,
                                                         self.method)
-        call = CGMethodCall(nativeName, self.method.isStatic(), self.descriptor,
+        return CGMethodCall(nativeName, self.method.isStatic(), self.descriptor,
                             self.method).define()
-        if self.method.getExtendedAttribute("CrossOriginCallable"):
-            for signature in self.method.signatures():
-                # non-void signatures would require us to deal with remote proxies for the
-                # return value here.
-                if not signature[0].isVoid():
-                    raise TypeError("We don't support a method marked as CrossOriginCallable "
-                                    "with non-void return type")
-            prototypeID, _ = PrototypeIDAndDepth(self.descriptor)
-            return fill("""
-                // CrossOriginThisPolicy::UnwrapThisObject stores a ${nativeType}::RemoteProxy in void_self
-                // if obj is a proxy with a RemoteObjectProxy handler for the right type, or else it stores
-                // a ${nativeType}. If we get here from the JIT (without going through UnwrapThisObject) we
-                // know void_self contains a ${nativeType}; we don't have special cases in the JIT to deal
-                // with remote object proxies.
-                if (IsRemoteObjectProxy(obj, ${prototypeID})) {
-                    ${nativeType}::RemoteProxy* self = static_cast<${nativeType}::RemoteProxy*>(void_self);
-                    $*{call}
-                }
-                ${nativeType}* self = static_cast<${nativeType}*>(void_self);
-                $*{call}
-                """,
-                prototypeID=prototypeID,
-                ifaceName=self.descriptor.name,
-                nativeType=self.descriptor.nativeType,
-                call=call)
-        return call
 
     def auto_profiler_label(self):
         interface_name = self.descriptor.interface.identifier.name
         method_name = self.method.identifier.name
         return fill(
             """
             AUTO_PROFILER_LABEL_DYNAMIC_FAST(
               "${interface_name}", "${method_name}", DOM, cx,
@@ -9131,24 +8906,20 @@ class CGStaticMethod(CGAbstractStaticBin
 class CGSpecializedGetter(CGAbstractStaticMethod):
     """
     A class for generating the code for a specialized attribute getter
     that the JIT can call with lower overhead.
     """
     def __init__(self, descriptor, attr):
         self.attr = attr
         name = 'get_' + IDLToCIdentifier(attr.identifier.name)
-        if attr.getExtendedAttribute("CrossOriginReadable"):
-            selfArg = Argument('void*', 'void_self')
-        else:
-            selfArg = Argument('%s*' % descriptor.nativeType, 'self')
         args = [
             Argument('JSContext*', 'cx'),
             Argument('JS::Handle<JSObject*>', 'obj'),
-            selfArg,
+            Argument('%s*' % descriptor.nativeType, 'self'),
             Argument('JSJitGetterCallArgs', 'args')
         ]
         # StoreInSlot attributes have their getters called from Wrap().  We
         # really hope they can't run script, and don't want to annotate Wrap()
         # methods as doing that anyway, so let's not annotate them as
         # MOZ_CAN_RUN_SCRIPT.
         CGAbstractStaticMethod.__init__(
             self, descriptor, name, "bool", args,
@@ -9158,40 +8929,16 @@ class CGSpecializedGetter(CGAbstractStat
         if self.attr.isMaplikeOrSetlikeAttr():
             # If the interface is maplike/setlike, there will be one getter
             # method for the size property of the backing object. Due to having
             # to unpack the backing object from the slot, this requires its own
             # generator.
             return getMaplikeOrSetlikeSizeGetterBody(self.descriptor, self.attr)
         nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
                                                         self.attr)
-        prefix = ""
-        type = self.attr.type
-        if self.attr.getExtendedAttribute("CrossOriginReadable"):
-            remoteType = type
-            extendedAttributes = self.descriptor.getExtendedAttributes(self.attr, getter=True)
-            if remoteType.isGeckoInterface() and not remoteType.unroll().inner.isExternal():
-                # We'll use a JSObject. It might make more sense to use remoteType's
-                # RemoteProxy, but it's not easy to construct a type for that from here.
-                remoteType = BuiltinTypes[IDLBuiltinType.Types.object]
-                extendedAttributes.append('canOOM')
-                extendedAttributes.remove('infallible')
-            prototypeID, _ = PrototypeIDAndDepth(self.descriptor)
-            prefix = fill("""
-                if (IsRemoteObjectProxy(obj, ${prototypeID})) {
-                    ${nativeType}::RemoteProxy* self = static_cast<${nativeType}::RemoteProxy*>(void_self);
-                    $*{call}
-                }
-                ${nativeType}* self = static_cast<${nativeType}*>(void_self);
-            """,
-            prototypeID=prototypeID,
-            ifaceName=self.descriptor.name,
-            nativeType=self.descriptor.nativeType,
-            call=CGGetterCall(remoteType, nativeName, self.descriptor, self.attr, dontSetSlot=True,
-                              extendedAttributes=extendedAttributes).define())
         if self.attr.slotIndices is not None:
             # We're going to store this return value in a slot on some object,
             # to cache it.  The question is, which object?  For dictionary and
             # sequence return values, we want to use a slot on the Xray expando
             # if we're called via Xrays, and a slot on our reflector otherwise.
             # On the other hand, when dealing with some interfacce types
             # (navigator properties, window.document) we want to avoid calling
             # the getter more than once.  In the case of navigator properties
@@ -9202,31 +8949,31 @@ class CGSpecializedGetter(CGAbstractStat
             # around.
             #
             # The upshot is that we use the reflector slot for any getter whose
             # type is a gecko interface, whether we're called via Xrays or not.
             # Since [Cached] and [StoreInSlot] cannot be used with "NewObject",
             # we know that in the interface type case the returned object is
             # wrappercached.  So creating Xrays to it is reasonable.
             if mayUseXrayExpandoSlots(self.descriptor, self.attr):
-                prefix += fill(
+                prefix = fill(
                     """
                     // Have to either root across the getter call or reget after.
                     bool isXray;
                     JS::Rooted<JSObject*> slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray));
                     if (!slotStorage) {
                       return false;
                     }
                     const size_t slotIndex = isXray ? ${xraySlotIndex} : ${slotIndex};
                     """,
                     xraySlotIndex=memberXrayExpandoReservedSlot(self.attr,
                                                                 self.descriptor),
                     slotIndex=memberReservedSlot(self.attr, self.descriptor))
             else:
-                prefix += fill(
+                prefix = fill(
                     """
                     // Have to either root across the getter call or reget after.
                     JS::Rooted<JSObject*> slotStorage(cx, js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false));
                     MOZ_ASSERT(IsDOMObject(slotStorage));
                     const size_t slotIndex = ${slotIndex};
                     """,
                     slotIndex=memberReservedSlot(self.attr, self.descriptor))
 
@@ -9241,23 +8988,25 @@ class CGSpecializedGetter(CGAbstractStat
                     // The cached value is in the compartment of slotStorage,
                     // so wrap into the caller compartment as needed.
                     return ${maybeWrap}(cx, args.rval());
                   }
                 }
 
                 """,
                 maybeWrap=getMaybeWrapValueFuncForType(self.attr.type))
+        else:
+            prefix = ""
 
         if self.attr.navigatorObjectGetter:
             cgGetterCall = CGNavigatorGetterCall
         else:
             cgGetterCall = CGGetterCall
         return (prefix +
-                cgGetterCall(type, nativeName,
+                cgGetterCall(self.attr.type, nativeName,
                              self.descriptor, self.attr).define())
 
     def auto_profiler_label(self):
         interface_name = self.descriptor.interface.identifier.name
         attr_name = self.attr.identifier.name
         return fill(
             """
             AUTO_PROFILER_LABEL_DYNAMIC_FAST(
@@ -9343,53 +9092,28 @@ class CGStaticGetter(CGAbstractStaticBin
 class CGSpecializedSetter(CGAbstractStaticMethod):
     """
     A class for generating the code for a specialized attribute setter
     that the JIT can call with lower overhead.
     """
     def __init__(self, descriptor, attr):
         self.attr = attr
         name = 'set_' + IDLToCIdentifier(attr.identifier.name)
-        if attr.getExtendedAttribute("CrossOriginWritable"):
-            selfArg = Argument('void*', 'void_self')
-        else:
-            selfArg = Argument('%s*' % descriptor.nativeType, 'self')
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'obj'),
-                selfArg,
+                Argument('%s*' % descriptor.nativeType, 'self'),
                 Argument('JSJitSetterCallArgs', 'args')]
         CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args,
                                         canRunScript=True)
 
     def definition_body(self):
         nativeName = CGSpecializedSetter.makeNativeName(self.descriptor,
                                                         self.attr)
-        type = self.attr.type
-        call = CGSetterCall(type, nativeName, self.descriptor, self.attr).define()
-        if self.attr.getExtendedAttribute("CrossOriginWritable"):
-            if type.isGeckoInterface() and not type.unroll().inner.isExternal():
-                # a setter taking a Gecko interface would require us to deal with remote
-                # proxies for the value here.
-                raise TypeError("We don't support the setter of %s marked as "
-                                "CrossOriginWritable because it takes a Gecko interface "
-                                "as the value", attr.identifier.name)
-            prototypeID, _ = PrototypeIDAndDepth(self.descriptor)
-            return fill("""
-                if (IsRemoteObjectProxy(obj, ${prototypeID})) {
-                    ${nativeType}::RemoteProxy* self = static_cast<${nativeType}::RemoteProxy*>(void_self);
-                    $*{call}
-                }
-                ${nativeType}* self = static_cast<${nativeType}*>(void_self);
-                $*{call}
-                """,
-                prototypeID=prototypeID,
-                ifaceName=self.descriptor.name,
-                nativeType=self.descriptor.nativeType,
-                call=call)
-        return call
+        return CGSetterCall(self.attr.type, nativeName, self.descriptor,
+                            self.attr).define()
 
     def auto_profiler_label(self):
         interface_name = self.descriptor.interface.identifier.name
         attr_name = self.attr.identifier.name
         return fill(
             """
             AUTO_PROFILER_LABEL_DYNAMIC_FAST(
               "${interface_name}", "${attr_name}", DOM, cx,
@@ -10105,23 +9829,21 @@ def getUnionAccessorSignatureType(type, 
 
     # Nested unions are unwrapped automatically into our flatMemberTypes.
     assert not type.isUnion()
 
     if type.isGeckoInterface():
         descriptor = descriptorProvider.getDescriptor(
             type.unroll().inner.identifier.name)
         typeName = CGGeneric(descriptor.nativeType)
-        if not type.unroll().inner.isExternal():
+        # Allow null pointers for old-binding classes.
+        if type.unroll().inner.isExternal():
+            typeName = CGWrapper(typeName, post="*")
+        else:
             typeName = CGWrapper(typeName, post="&")
-        elif descriptor.interface.identifier.name == "WindowProxy":
-            typeName = CGGeneric("WindowProxyHolder const&")
-        else:
-            # Allow null pointers for old-binding classes.
-            typeName = CGWrapper(typeName, post="*")
         return typeName
 
     if type.isSpiderMonkeyInterface():
         typeName = CGGeneric(type.name)
         return CGWrapper(typeName, post=" const &")
 
     if type.isDOMString() or type.isUSVString():
         return CGGeneric("const nsAString&")
@@ -12626,24 +12348,24 @@ def memberProperties(m, descriptor):
                 if m.getExtendedAttribute("CrossOriginCallable"):
                     props.isCrossOriginMethod = True
     elif m.isAttr():
         if not m.isStatic() and descriptor.interface.hasInterfacePrototypeObject():
             if m.getExtendedAttribute("CrossOriginReadable"):
                 props.isCrossOriginGetter = True
         if not m.readonly:
             if not m.isStatic() and descriptor.interface.hasInterfacePrototypeObject():
-                if isCrossOriginWritable(m, descriptor):
+                if IsCrossOriginWritable(m, descriptor):
                     props.isCrossOriginSetter = True
         elif m.getExtendedAttribute("PutForwards"):
-            if isCrossOriginWritable(m, descriptor):
+            if IsCrossOriginWritable(m, descriptor):
                 props.isCrossOriginSetter = True
         elif (m.getExtendedAttribute("Replaceable") or
               m.getExtendedAttribute("LenientSetter")):
-            if isCrossOriginWritable(m, descriptor):
+            if IsCrossOriginWritable(m, descriptor):
                 props.isCrossOriginSetter = True
 
     return props
 
 
 class CGDescriptor(CGThing):
     def __init__(self, descriptor):
         CGThing.__init__(self)
@@ -12876,17 +12598,16 @@ class CGDescriptor(CGThing):
             if descriptor.interface.hasChildInterfaces():
                 cgThings.append(CGGetProtoObjectMethod(descriptor))
         if descriptor.interface.hasInterfaceObject():
             cgThings.append(CGGetConstructorObjectHandleMethod(descriptor))
             cgThings.append(CGGetConstructorObjectMethod(descriptor))
 
         # See whether we need we need to generate an IsPermitted method
         if crossOriginGetters or crossOriginSetters or crossOriginMethods:
-            cgThings.append(CGCrossOriginProperties(descriptor))
             cgThings.append(CGIsPermittedMethod(descriptor,
                                                 crossOriginGetters,
                                                 crossOriginSetters,
                                                 crossOriginMethods))
 
         cgThings = CGList((CGIndenter(t, declareOnly=True) for t in cgThings), "\n")
         cgThings = CGWrapper(cgThings, pre='\n', post='\n')
         self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
@@ -14178,17 +13899,16 @@ class CGBindingRoot(CGThing):
             def hasCrossOriginProperty(m):
                 props = memberProperties(m, desc)
                 return (props.isCrossOriginMethod or
                         props.isCrossOriginGetter or
                         props.isCrossOriginSetter)
 
             return any(hasCrossOriginProperty(m) for m in desc.interface.members)
 
-        bindingDeclareHeaders["mozilla/dom/RemoteObjectProxy.h"] = any(descriptorHasCrossOriginProperties(d) for d in descriptors)
         bindingDeclareHeaders["jsapi.h"] = any(descriptorHasCrossOriginProperties(d) for d in descriptors)
         bindingDeclareHeaders["jspubtd.h"] = not bindingDeclareHeaders["jsapi.h"]
         bindingDeclareHeaders["js/RootingAPI.h"] = not bindingDeclareHeaders["jsapi.h"]
 
         def descriptorHasIteratorAlias(desc):
             def hasIteratorAlias(m):
                 return m.isMethod() and "@@iterator" in m.aliases
             return any(hasIteratorAlias(m) for m in desc.interface.members)
@@ -14751,19 +14471,16 @@ class CGNativeMember(ClassMethod):
             if optional or isMember:
                 typeDecl = "OwningNonNull<Promise>"
             else:
                 typeDecl = "Promise&"
             return (typeDecl, False, False)
 
         if type.isGeckoInterface() and not type.isCallbackInterface():
             iface = type.unroll().inner
-            if iface.identifier.name == "WindowProxy":
-                return "WindowProxyHolder", True, False
-
             argIsPointer = type.nullable() or iface.isExternal()
             forceOwningType = (iface.isCallback() or isMember)
             if argIsPointer:
                 if (optional or isMember) and forceOwningType:
                     typeDecl = "RefPtr<%s>"
                 else:
                     typeDecl = "%s*"
             else:
deleted file mode 100644
--- a/dom/bindings/RemoteObjectProxy.cpp
+++ /dev/null
@@ -1,240 +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 "RemoteObjectProxy.h"
-#include "AccessCheck.h"
-#include "jsfriendapi.h"
-
-namespace mozilla {
-namespace dom {
-
-// Give RemoteObjectProxy 2 reserved slots, like the other wrappers, so
-// JSObject::swap can swap it with CrossCompartmentWrappers without requiring
-// malloc.
-const js::Class RemoteObjectProxyClass =
-    PROXY_CLASS_DEF("Proxy", JSCLASS_HAS_RESERVED_SLOTS(2));
-
-bool RemoteObjectProxyBase::getOwnPropertyDescriptor(
-    JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
-    JS::MutableHandle<JS::PropertyDescriptor> aDesc) const {
-  bool ok = getOwnPropertyDescriptorInternal(aCx, aProxy, aId, aDesc);
-  if (!ok || aDesc.object()) {
-    return ok;
-  }
-
-  return getOwnPropertyDescriptorTail(aCx, aProxy, aId, aDesc);
-}
-
-bool RemoteObjectProxyBase::defineProperty(
-    JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
-    JS::Handle<JS::PropertyDescriptor> aDesc,
-    JS::ObjectOpResult& aResult) const {
-  // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-defineownproperty
-  // step 3 and
-  // https://html.spec.whatwg.org/multipage/browsers.html#location-defineownproperty
-  // step 2
-  return ReportCrossOriginDenial(aCx, aId, NS_LITERAL_CSTRING("define"));
-}
-
-bool RemoteObjectProxyBase::ownPropertyKeys(JSContext* aCx,
-                                            JS::Handle<JSObject*> aProxy,
-                                            JS::AutoIdVector& aProps) const {
-  // https://html.spec.whatwg.org/multipage/browsers.html#crossoriginownpropertykeys-(-o-)
-  // step 2 and
-  // https://html.spec.whatwg.org/multipage/browsers.html#crossoriginproperties-(-o-)
-  JS::Rooted<JSObject*> holder(aCx);
-  if (!EnsureHolder(aCx, aProxy, &holder) ||
-      !js::GetPropertyKeys(aCx, holder,
-                           JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS,
-                           &aProps)) {
-    return false;
-  }
-
-  // https://html.spec.whatwg.org/multipage/browsers.html#crossoriginownpropertykeys-(-o-)
-  // step 3 and 4
-  return xpc::AppendCrossOriginWhitelistedPropNames(aCx, aProps);
-}
-
-bool RemoteObjectProxyBase::delete_(JSContext* aCx,
-                                    JS::Handle<JSObject*> aProxy,
-                                    JS::Handle<jsid> aId,
-                                    JS::ObjectOpResult& aResult) const {
-  // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-delete
-  // step 3 and
-  // https://html.spec.whatwg.org/multipage/browsers.html#location-delete step 2
-  return ReportCrossOriginDenial(aCx, aId, NS_LITERAL_CSTRING("delete"));
-}
-
-bool RemoteObjectProxyBase::getPrototype(
-    JSContext* aCx, JS::Handle<JSObject*> aProxy,
-    JS::MutableHandle<JSObject*> aProtop) const {
-  // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-getprototypeof
-  // step 3 and
-  // https://html.spec.whatwg.org/multipage/browsers.html#location-getprototypeof
-  // step 2
-  aProtop.set(nullptr);
-  return true;
-}
-
-bool RemoteObjectProxyBase::setPrototype(JSContext* aCx,
-                                         JS::Handle<JSObject*> aProxy,
-                                         JS::Handle<JSObject*> aProto,
-                                         JS::ObjectOpResult& aResult) const {
-  // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-setprototypeof
-  // and
-  // https://html.spec.whatwg.org/multipage/browsers.html#location-setprototypeof
-  // say to call SetImmutablePrototype, which does nothing and just returns
-  // whether the passed-in value equals the current prototype. Our current
-  // prototype is always null, so this just comes down to returning whether null
-  // was passed in.
-  //
-  // In terms of ObjectOpResult that means calling one of the fail*() things on
-  // it if non-null was passed, and it's got one that does just what we want.
-  if (!aProto) {
-    return aResult.succeed();
-  }
-  return aResult.failCantSetProto();
-}
-
-bool RemoteObjectProxyBase::getPrototypeIfOrdinary(
-    JSContext* aCx, JS::Handle<JSObject*> aProxy, bool* aIsOrdinary,
-    JS::MutableHandle<JSObject*> aProtop) const {
-  // WindowProxy's and Location's [[GetPrototypeOf]] traps aren't the ordinary
-  // definition:
-  //
-  //   https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-getprototypeof
-  //   https://html.spec.whatwg.org/multipage/browsers.html#location-getprototypeof
-  //
-  // We nonetheless can implement it with a static [[Prototype]], because the
-  // [[GetPrototypeOf]] trap should always return null.
-  *aIsOrdinary = true;
-  return true;
-}
-
-bool RemoteObjectProxyBase::preventExtensions(
-    JSContext* aCx, JS::Handle<JSObject*> aProxy,
-    JS::ObjectOpResult& aResult) const {
-  // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-preventextensions
-  // and
-  // https://html.spec.whatwg.org/multipage/browsers.html#location-preventextensions
-  return aResult.failCantPreventExtensions();
-}
-
-bool RemoteObjectProxyBase::isExtensible(JSContext* aCx,
-                                         JS::Handle<JSObject*> aProxy,
-                                         bool* aExtensible) const {
-  // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-isextensible
-  // and
-  // https://html.spec.whatwg.org/multipage/browsers.html#location-isextensible
-  *aExtensible = true;
-  return true;
-}
-
-bool RemoteObjectProxyBase::get(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                                JS::Handle<JS::Value> aReceiver,
-                                JS::Handle<jsid> aId,
-                                JS::MutableHandle<JS::Value> aVp) const {
-  Rooted<PropertyDescriptor> desc(aCx);
-  if (!getOwnPropertyDescriptor(aCx, aProxy, aId, &desc)) {
-    return false;
-  }
-
-  MOZ_ASSERT(desc.object());
-
-  if (desc.isDataDescriptor()) {
-    aVp.set(desc.value());
-    return true;
-  }
-
-  if (!desc.hasGetterObject()) {
-    return ReportCrossOriginDenial(aCx, aId, NS_LITERAL_CSTRING("get"));
-  }
-
-  JS::Rooted<JSObject*> getter(aCx, desc.getterObject());
-  return JS::Call(aCx, aReceiver, getter, JS::HandleValueArray::empty(), aVp);
-}
-
-bool RemoteObjectProxyBase::set(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                                JS::Handle<jsid> aId,
-                                JS::Handle<JS::Value> aValue,
-                                JS::Handle<JS::Value> aReceiver,
-                                JS::ObjectOpResult& aResult) const {
-  Rooted<PropertyDescriptor> desc(aCx);
-  if (!getOwnPropertyDescriptor(aCx, aProxy, aId, &desc)) {
-    return false;
-  }
-
-  MOZ_ASSERT(desc.object());
-
-  if (!desc.hasSetterObject()) {
-    return ReportCrossOriginDenial(aCx, aId, NS_LITERAL_CSTRING("set"));
-  }
-
-  JS::Rooted<JSObject*> setter(aCx, desc.setterObject());
-  JS::Rooted<JS::Value> rv(aCx);
-  return JS::Call(aCx, aReceiver, setter, JS::HandleValueArray(aValue), &rv) &&
-         aResult.succeed();
-}
-
-bool RemoteObjectProxyBase::hasOwn(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                                   JS::Handle<jsid> aId, bool* aBp) const {
-  JS::Rooted<JSObject*> holder(aCx);
-  if (!EnsureHolder(aCx, aProxy, &holder) ||
-      !JS_AlreadyHasOwnPropertyById(aCx, holder, aId, aBp)) {
-    return false;
-  }
-
-  if (!*aBp) {
-    *aBp = xpc::IsCrossOriginWhitelistedProp(aCx, aId);
-  }
-
-  return true;
-}
-
-bool RemoteObjectProxyBase::getOwnEnumerablePropertyKeys(
-    JSContext* aCx, JS::Handle<JSObject*> aProxy,
-    JS::AutoIdVector& aProps) const {
-  return true;
-}
-
-JSObject* RemoteObjectProxyBase::CreateProxyObject(
-    JSContext* aCx, void* aNative, const js::Class* aClasp) const {
-  js::ProxyOptions options;
-  options.setClass(aClasp);
-  JS::Rooted<JS::Value> native(aCx, JS::PrivateValue(aNative));
-  return js::NewProxyObject(aCx, this, native, nullptr, options);
-}
-
-/* static */
-bool RemoteObjectProxyBase::getOwnPropertyDescriptorTail(
-    JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
-    JS::MutableHandle<JS::PropertyDescriptor> aDesc) {
-  if (xpc::IsCrossOriginWhitelistedProp(aCx, aId)) {
-    // https://html.spec.whatwg.org/multipage/browsers.html#crossorigingetownpropertyhelper-(-o,-p-)
-    // step 3 says to return PropertyDescriptor {
-    //   [[Value]]: undefined, [[Writable]]: false, [[Enumerable]]: false,
-    //   [[Configurable]]: true
-    // }.
-    //
-    aDesc.setDataDescriptor(JS::UndefinedHandleValue, JSPROP_READONLY);
-    aDesc.object().set(aProxy);
-    return true;
-  }
-
-  return ReportCrossOriginDenial(aCx, aId, NS_LITERAL_CSTRING("access"));
-}
-
-/* static */
-bool RemoteObjectProxyBase::ReportCrossOriginDenial(
-    JSContext* aCx, JS::Handle<jsid> aId, const nsACString& aAccessType) {
-  xpc::AccessCheck::reportCrossOriginDenial(aCx, aId, aAccessType);
-  return false;
-}
-
-const char RemoteObjectProxyBase::sCrossOriginProxyFamily = 0;
-
-}  // namespace dom
-}  // namespace mozilla
deleted file mode 100644
--- a/dom/bindings/RemoteObjectProxy.h
+++ /dev/null
@@ -1,200 +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/. */
-
-#ifndef mozilla_dom_RemoteObjectProxy_h
-#define mozilla_dom_RemoteObjectProxy_h
-
-#include "js/Proxy.h"
-#include "mozilla/dom/PrototypeList.h"
-#include "xpcpublic.h"
-
-namespace mozilla {
-namespace dom {
-
-/**
- * Base class for RemoteObjectProxy. Implements the pieces of the handler that
- * don't depend on properties/methods of the specific WebIDL interface that this
- * proxy implements.
- */
-class RemoteObjectProxyBase : public js::BaseProxyHandler {
- protected:
-  explicit constexpr RemoteObjectProxyBase(prototypes::ID aPrototypeID)
-      : BaseProxyHandler(&sCrossOriginProxyFamily, false),
-        mPrototypeID(aPrototypeID) {}
-
- public:
-  bool finalizeInBackground(const JS::Value& priv) const final { return false; }
-
-  // Standard internal methods
-  bool getOwnPropertyDescriptor(
-      JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
-      JS::MutableHandle<JS::PropertyDescriptor> aDesc) const override;
-  bool ownPropertyKeys(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                       JS::AutoIdVector& aProps) const override;
-  bool defineProperty(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                      JS::Handle<jsid> aId,
-                      JS::Handle<JS::PropertyDescriptor> aDesc,
-                      JS::ObjectOpResult& result) const final;
-  bool delete_(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-               JS::Handle<jsid> aId, JS::ObjectOpResult& aResult) const final;
-
-  bool getPrototype(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                    JS::MutableHandle<JSObject*> aProtop) const final;
-  bool setPrototype(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                    JS::Handle<JSObject*> aProto,
-                    JS::ObjectOpResult& aResult) const final;
-  bool getPrototypeIfOrdinary(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                              bool* aIsOrdinary,
-                              JS::MutableHandle<JSObject*> aProtop) const final;
-
-  bool preventExtensions(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                         JS::ObjectOpResult& aResult) const final;
-  bool isExtensible(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                    bool* aExtensible) const final;
-
-  bool get(JSContext* cx, JS::Handle<JSObject*> aProxy,
-           JS::Handle<JS::Value> aReceiver, JS::Handle<jsid> aId,
-           JS::MutableHandle<JS::Value> aVp) const final;
-  bool set(JSContext* cx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
-           JS::Handle<JS::Value> aValue, JS::Handle<JS::Value> aReceiver,
-           JS::ObjectOpResult& aResult) const final;
-
-  // SpiderMonkey extensions
-  bool hasOwn(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-              JS::Handle<jsid> aId, bool* aBp) const override;
-  bool getOwnEnumerablePropertyKeys(JSContext* aCx,
-                                    JS::Handle<JSObject*> aProxy,
-                                    JS::AutoIdVector& aProps) const override;
-
-  bool isCallable(JSObject* aObj) const final { return false; }
-  bool isConstructor(JSObject* aObj) const final { return false; }
-
-  static void* GetNative(JSObject* aProxy) {
-    return js::GetProxyPrivate(aProxy).toPrivate();
-  }
-
-  /**
-   * Returns true if aProxy represents an object implementing the WebIDL
-   * interface for aProtoID. aProxy should be a proxy object.
-   */
-  static inline bool IsRemoteObjectProxy(JSObject* aProxy,
-                                         prototypes::ID aProtoID) {
-    const js::BaseProxyHandler* handler = js::GetProxyHandler(aProxy);
-    return handler->family() == &sCrossOriginProxyFamily &&
-           static_cast<const RemoteObjectProxyBase*>(handler)->mPrototypeID ==
-               aProtoID;
-  }
-
- protected:
-  bool getOwnPropertyDescriptorInternal(
-      JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
-      JS::MutableHandle<JS::PropertyDescriptor> aDesc) const {
-    JS::Rooted<JSObject*> holder(aCx);
-    if (!EnsureHolder(aCx, aProxy, &holder) ||
-        !JS_GetOwnPropertyDescriptorById(aCx, holder, aId, aDesc)) {
-      return false;
-    }
-
-    if (aDesc.object()) {
-      aDesc.object().set(aProxy);
-    }
-
-    return true;
-  }
-
-  JSObject* CreateProxyObject(JSContext* aCx, void* aNative,
-                              const js::Class* aClasp) const;
-
-  /**
-   * Implements the tail of getOwnPropertyDescriptor, dealing in particular with
-   * properties that are whitelisted by xpc::IsCrossOriginWhitelistedProp.
-   */
-  static bool getOwnPropertyDescriptorTail(
-      JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
-      JS::MutableHandle<JS::PropertyDescriptor> aDesc);
-  static bool ReportCrossOriginDenial(JSContext* aCx, JS::Handle<jsid> aId,
-                                      const nsACString& aAccessType);
-
-  /**
-   * This gets a cached, or creates and caches, a holder object that contains
-   * the WebIDL properties for this proxy.
-   */
-  bool EnsureHolder(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                    JS::MutableHandle<JSObject*> aHolder) const {
-    // FIXME Need to have a holder per realm, should store a weakmap in the
-    //       reserved slot.
-    JS::Value v = js::GetProxyReservedSlot(aProxy, 0);
-    if (v.isObject()) {
-      aHolder.set(&v.toObject());
-      return true;
-    }
-
-    aHolder.set(JS_NewObjectWithGivenProto(aCx, nullptr, nullptr));
-    if (!aHolder || !DefinePropertiesAndFunctions(aCx, aHolder)) {
-      return false;
-    }
-
-    js::SetProxyReservedSlot(aProxy, 0, JS::ObjectValue(*aHolder));
-    return true;
-  }
-
-  virtual bool DefinePropertiesAndFunctions(
-      JSContext* aCx, JS::Handle<JSObject*> aHolder) const = 0;
-
-  const prototypes::ID mPrototypeID;
-
-  static const char sCrossOriginProxyFamily;
-};
-
-/**
- * Proxy handler for proxy objects that represent an object implementing a
- * WebIDL interface that has cross-origin accessible properties/methods, and
- * which lives in a different process. The WebIDL code generator will create
- * arrays of cross-origin accessible properties/methods that can be used as
- * arguments to this template.
- *
- * The properties and methods can be cached on a holder JSObject, stored in a
- * reserved slot on the proxy object.
- *
- * The proxy objects that use a handler derived from this one are stored in a
- * hash map in the JS compartment's private (@see
- * xpc::CompartmentPrivate::GetRemoteProxyMap).
- */
-template <class Native, JSPropertySpec* P, JSFunctionSpec* F>
-class RemoteObjectProxy : public RemoteObjectProxyBase {
- public:
-  JSObject* CreateProxyObject(JSContext* aCx, Native* aNative,
-                              const js::Class* aClasp) const {
-    return RemoteObjectProxyBase::CreateProxyObject(aCx, aNative, aClasp);
-  }
-
- protected:
-  using RemoteObjectProxyBase::RemoteObjectProxyBase;
-
- private:
-  virtual bool DefinePropertiesAndFunctions(
-      JSContext* aCx, JS::Handle<JSObject*> aHolder) const final {
-    return JS_DefineProperties(aCx, aHolder, P) &&
-           JS_DefineFunctions(aCx, aHolder, F);
-  }
-};
-
-/**
- * Returns true if aObj is a proxy object that represents an object implementing
- * the WebIDL interface for aProtoID.
- */
-static inline bool IsRemoteObjectProxy(JSObject* aObj,
-                                       prototypes::ID aProtoID) {
-  if (!js::IsProxy(aObj)) {
-    return false;
-  }
-  return RemoteObjectProxyBase::IsRemoteObjectProxy(aObj, aProtoID);
-}
-
-}  // namespace dom
-}  // namespace mozilla
-
-#endif /* mozilla_dom_RemoteObjectProxy_h */
--- a/dom/bindings/ToJSValue.cpp
+++ b/dom/bindings/ToJSValue.cpp
@@ -3,17 +3,16 @@
 /* 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 "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/Exceptions.h"
 #include "mozilla/dom/Promise.h"
-#include "mozilla/dom/WindowProxyHolder.h"
 #include "nsAString.h"
 #include "nsContentUtils.h"
 #include "nsStringBuffer.h"
 #include "xpcpublic.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -56,37 +55,10 @@ bool ToJSValue(JSContext* aCx, ErrorResu
 }
 
 bool ToJSValue(JSContext* aCx, Promise& aArgument,
                JS::MutableHandle<JS::Value> aValue) {
   aValue.setObject(*aArgument.PromiseObj());
   return MaybeWrapObjectValue(aCx, aValue);
 }
 
-bool ToJSValue(JSContext* aCx, const WindowProxyHolder& aArgument,
-               JS::MutableHandle<JS::Value> aValue) {
-  BrowsingContext* bc = aArgument.get();
-  if (!bc) {
-    aValue.setNull();
-    return true;
-  }
-  JS::Rooted<JSObject*> windowProxy(aCx);
-  if (bc->GetDocShell()) {
-    windowProxy = bc->GetWindowProxy();
-    if (!windowProxy) {
-      nsPIDOMWindowOuter* window = bc->GetDOMWindow();
-      if (!window->EnsureInnerWindow()) {
-        return Throw(aCx, NS_ERROR_UNEXPECTED);
-      }
-      windowProxy = bc->GetWindowProxy();
-    }
-    return ToJSValue(aCx, windowProxy, aValue);
-  }
-
-  if (!GetRemoteOuterWindowProxy(aCx, bc, &windowProxy)) {
-    return false;
-  }
-  aValue.setObjectOrNull(windowProxy);
-  return true;
-}
-
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/bindings/ToJSValue.h
+++ b/dom/bindings/ToJSValue.h
@@ -18,17 +18,16 @@
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
 #include "nsAutoPtr.h"
 
 namespace mozilla {
 namespace dom {
 
 class Promise;
-class WindowProxyHolder;
 
 // If ToJSValue returns false, it must set an exception on the
 // JSContext.
 
 // Accept strings.
 MOZ_MUST_USE bool ToJSValue(JSContext* aCx, const nsAString& aArgument,
                             JS::MutableHandle<JS::Value> aValue);
 
@@ -217,19 +216,16 @@ ToJSValue(JSContext* aCx, T& aArgument, 
   // Make sure we're called in a compartment
   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
 
   xpcObjectHelper helper(ToSupports(&aArgument));
   JS::Rooted<JSObject*> scope(aCx, JS::CurrentGlobalOrNull(aCx));
   return XPCOMObjectToJsval(aCx, scope, helper, nullptr, true, aValue);
 }
 
-MOZ_MUST_USE bool ToJSValue(JSContext* aCx, const WindowProxyHolder& aArgument,
-                            JS::MutableHandle<JS::Value> aValue);
-
 // Accept nsRefPtr/nsCOMPtr
 template <typename T>
 MOZ_MUST_USE bool ToJSValue(JSContext* aCx, const nsCOMPtr<T>& aArgument,
                             JS::MutableHandle<JS::Value> aValue) {
   return ToJSValue(aCx, *aArgument.get(), aValue);
 }
 
 template <typename T>
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -44,17 +44,16 @@ EXPORTS.mozilla.dom += [
     'FakeString.h',
     'IterableIterator.h',
     'JSSlots.h',
     'NonRefcountedDOMObject.h',
     'Nullable.h',
     'PrimitiveConversions.h',
     'ReadableStream.h',
     'Record.h',
-    'RemoteObjectProxy.h',
     'RootedDictionary.h',
     'SimpleGlobalObject.h',
     'SpiderMonkeyInterface.h',
     'StructuredClone.h',
     'ToJSValue.h',
     'TypedArray.h',
     'UnionMember.h',
     'WebIDLGlobalNameHash.h',
@@ -109,17 +108,16 @@ UNIFIED_SOURCES += [
     'CallbackInterface.cpp',
     'CallbackObject.cpp',
     'Date.cpp',
     'DOMJSProxyHandler.cpp',
     'Exceptions.cpp',
     'IterableIterator.cpp',
     'nsScriptError.cpp',
     'nsScriptErrorWithStack.cpp',
-    'RemoteObjectProxy.cpp',
     'SimpleGlobalObject.cpp',
     'ToJSValue.cpp',
     'WebIDLGlobalNameHash.cpp',
 ]
 
 SOURCES += [
     'StructuredClone.cpp',
 ]
--- a/dom/bindings/nsScriptError.cpp
+++ b/dom/bindings/nsScriptError.cpp
@@ -57,17 +57,26 @@ void nsScriptErrorBase::InitializeOnMain
 
   if (mInnerWindowID) {
     nsGlobalWindowInner* window =
         nsGlobalWindowInner::GetInnerWindowWithId(mInnerWindowID);
     if (window) {
       nsPIDOMWindowOuter* outer = window->GetOuterWindow();
       if (outer) mOuterWindowID = outer->WindowID();
 
-      mIsFromPrivateWindow = ComputeIsFromPrivateWindow(window);
+      nsIDocShell* docShell = window->GetDocShell();
+      nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
+
+      if (loadContext) {
+        // Never mark exceptions from chrome windows as having come from
+        // private windows, since we always want them to be reported.
+        nsIPrincipal* winPrincipal = window->GetPrincipal();
+        mIsFromPrivateWindow = loadContext->UsePrivateBrowsing() &&
+                               !nsContentUtils::IsSystemPrincipal(winPrincipal);
+      }
     }
   }
 
   mInitializedOnMainThread = true;
 }
 
 // nsIConsoleMessage methods
 NS_IMETHODIMP
@@ -375,25 +384,16 @@ nsScriptErrorBase::GetNotes(nsIArray** a
 
   uint32_t len = mNotes.Length();
   for (uint32_t i = 0; i < len; i++) array->AppendElement(mNotes[i]);
   array.forget(aNotes);
 
   return NS_OK;
 }
 
-/* static */ bool nsScriptErrorBase::ComputeIsFromPrivateWindow(
-    nsGlobalWindowInner* aWindow) {
-  // Never mark exceptions from chrome windows as having come from private
-  // windows, since we always want them to be reported.
-  nsIPrincipal* winPrincipal = aWindow->GetPrincipal();
-  return aWindow->IsPrivateBrowsing() &&
-         !nsContentUtils::IsSystemPrincipal(winPrincipal);
-}
-
 NS_IMPL_ISUPPORTS(nsScriptError, nsIConsoleMessage, nsIScriptError)
 
 nsScriptErrorNote::nsScriptErrorNote()
     : mMessage(), mSourceName(), mLineNumber(0), mColumnNumber(0) {}
 
 nsScriptErrorNote::~nsScriptErrorNote() {}
 
 void nsScriptErrorNote::Init(const nsAString& message,
--- a/dom/bindings/nsScriptError.h
+++ b/dom/bindings/nsScriptError.h
@@ -14,18 +14,16 @@
 #include "jsapi.h"
 #include "js/RootingAPI.h"
 
 #include "nsCOMArray.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIScriptError.h"
 #include "nsString.h"
 
-class nsGlobalWindowInner;
-
 class nsScriptErrorNote final : public nsIScriptErrorNote {
  public:
   nsScriptErrorNote();
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSISCRIPTERRORNOTE
 
   void Init(const nsAString& message, const nsAString& sourceName,
@@ -46,18 +44,16 @@ class nsScriptErrorBase : public nsIScri
  public:
   nsScriptErrorBase();
 
   NS_DECL_NSICONSOLEMESSAGE
   NS_DECL_NSISCRIPTERROR
 
   void AddNote(nsIScriptErrorNote* note);
 
-  static bool ComputeIsFromPrivateWindow(nsGlobalWindowInner* aWindow);
-
  protected:
   virtual ~nsScriptErrorBase();
 
   void InitializeOnMainThread();
 
   void InitializationHelper(const nsAString& message,
                             const nsAString& sourceLine, uint32_t lineNumber,
                             uint32_t columnNumber, uint32_t flags,
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -5133,20 +5133,16 @@ class IDLMethod(IDLInterfaceMember, IDLS
         elif identifier == "Exposed":
             convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames)
         elif (identifier == "CrossOriginCallable" or
               identifier == "WebGLHandlesContextLoss"):
             # Known no-argument attributes.
             if not attr.noArguments():
                 raise WebIDLError("[%s] must take no arguments" % identifier,
                                   [attr.location])
-            if identifier == "CrossOriginCallable" and self.isStatic():
-                raise WebIDLError("[CrossOriginCallable] is only allowed on non-static "
-                                  "attributes"
-                                  [attr.location, self.location])
         elif identifier == "Pure":
             if not attr.noArguments():
                 raise WebIDLError("[Pure] must take no arguments",
                                   [attr.location])
             self._setDependsOn("DOMState")
             self._setAffects("Nothing")
         elif identifier == "Affects":
             if not attr.hasValue():
--- a/dom/browser-element/BrowserElementParent.cpp
+++ b/dom/browser-element/BrowserElementParent.cpp
@@ -13,17 +13,16 @@
 #ifdef CreateEvent
 #undef CreateEvent
 #endif
 
 #include "BrowserElementParent.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/dom/HTMLIFrameElement.h"
 #include "mozilla/dom/ToJSValue.h"
-#include "mozilla/dom/WindowProxyHolder.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsVariant.h"
 #include "mozilla/dom/BrowserElementDictionariesBinding.h"
 #include "mozilla/dom/CustomEvent.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::layers;
@@ -199,49 +198,48 @@ BrowserElementParent::OpenWindowResult B
   popupFrameElement->AllowCreateFrameLoader();
   popupFrameElement->CreateRemoteFrameLoader(aPopupTabParent);
 
   return opened;
 }
 
 /* static */
 BrowserElementParent::OpenWindowResult
-BrowserElementParent::OpenWindowInProcess(BrowsingContext* aOpenerWindow,
+BrowserElementParent::OpenWindowInProcess(nsPIDOMWindowOuter* aOpenerWindow,
                                           nsIURI* aURI, const nsAString& aName,
                                           const nsACString& aFeatures,
                                           bool aForceNoOpener,
                                           mozIDOMWindowProxy** aReturnWindow) {
   *aReturnWindow = nullptr;
 
   // If we call window.open from an <iframe> inside an <iframe mozbrowser>,
   // it's as though the top-level document inside the <iframe mozbrowser>
   // called window.open.  (Indeed, in the OOP case, the inner <iframe> lives
   // out-of-process, so we couldn't touch it if we tried.)
   //
   // GetScriptableTop gets us the <iframe mozbrowser>'s window; we'll use its
   // frame element, rather than aOpenerWindow's frame element, as our "opener
   // frame element" below.
-  nsCOMPtr<nsPIDOMWindowOuter> win = aOpenerWindow->GetDOMWindow()->GetTop();
+  nsCOMPtr<nsPIDOMWindowOuter> win = aOpenerWindow->GetScriptableTop();
 
   nsCOMPtr<Element> openerFrameElement = win->GetFrameElementInternal();
   NS_ENSURE_TRUE(openerFrameElement, BrowserElementParent::OPEN_WINDOW_IGNORED);
 
   RefPtr<HTMLIFrameElement> popupFrameElement =
       CreateIframe(openerFrameElement, aName, /* aRemote = */ false);
   NS_ENSURE_TRUE(popupFrameElement, BrowserElementParent::OPEN_WINDOW_IGNORED);
 
   nsAutoCString spec;
   if (aURI) {
     aURI->GetSpec(spec);
   }
 
   if (!aForceNoOpener) {
     ErrorResult res;
-    popupFrameElement->PresetOpenerWindow(WindowProxyHolder(aOpenerWindow),
-                                          res);
+    popupFrameElement->PresetOpenerWindow(aOpenerWindow, res);
     MOZ_ASSERT(!res.Failed());
   }
 
   OpenWindowResult opened = DispatchOpenWindowEvent(
       openerFrameElement, popupFrameElement, NS_ConvertUTF8toUTF16(spec), aName,
       NS_ConvertUTF8toUTF16(aFeatures));
 
   if (opened != BrowserElementParent::OPEN_WINDOW_ADDED) {
--- a/dom/browser-element/BrowserElementParent.h
+++ b/dom/browser-element/BrowserElementParent.h
@@ -14,17 +14,16 @@
 #include "mozilla/dom/Element.h"
 
 class nsIDOMWindow;
 class nsIURI;
 
 namespace mozilla {
 
 namespace dom {
-class BrowsingContext;
 class TabParent;
 }  // namespace dom
 
 /**
  * BrowserElementParent implements a portion of the parent-process side of
  * <iframe mozbrowser>.
  *
  * Most of the parent-process side of <iframe mozbrowser> is implemented in
@@ -99,18 +98,18 @@ class BrowserElementParent {
    * hand.  Feel free to add an override, if they are inconvenient to you.)
    *
    * @param aURI the URI the new window should load.  May be null.
    * @return an OpenWindowResult that describes whether the browser added the
    *         frame to a document or whether they called preventDefault to
    * prevent the platform from handling the open request
    */
   static OpenWindowResult OpenWindowInProcess(
-      mozilla::dom::BrowsingContext* aOpenerWindow, nsIURI* aURI,
-      const nsAString& aName, const nsACString& aFeatures, bool aForceNoOpener,
+      nsPIDOMWindowOuter* aOpenerWindow, nsIURI* aURI, const nsAString& aName,
+      const nsACString& aFeatures, bool aForceNoOpener,
       mozIDOMWindowProxy** aReturnWindow);
 
  private:
   static OpenWindowResult DispatchOpenWindowEvent(
       dom::Element* aOpenerFrameElement, dom::Element* aPopupFrameElement,
       const nsAString& aURL, const nsAString& aName,
       const nsAString& aFeatures);
 };
--- a/dom/events/DOMEventTargetHelper.h
+++ b/dom/events/DOMEventTargetHelper.h
@@ -123,17 +123,17 @@ class DOMEventTargetHelper : public dom:
   bool HasListenersFor(const nsAString& aType) const {
     return mListenerManager && mListenerManager->HasListenersFor(aType);
   }
 
   bool HasListenersFor(nsAtom* aTypeWithOn) const {
     return mListenerManager && mListenerManager->HasListenersFor(aTypeWithOn);
   }
 
-  virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindingsInternal() override {
+  virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override {
     return nsPIDOMWindowOuter::GetFromCurrentInner(GetOwner());
   }
 
   nsresult CheckInnerWindowCorrectness() const {
     NS_ENSURE_STATE(!mHasOrHasHadOwnerWindow || mOwnerWindow);
     if (mOwnerWindow && !mOwnerWindow->IsCurrentInnerWindow()) {
       return NS_ERROR_FAILURE;
     }
--- a/dom/events/EventTarget.cpp
+++ b/dom/events/EventTarget.cpp
@@ -3,18 +3,16 @@
 /* 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 "mozilla/EventListenerManager.h"
 #include "mozilla/dom/EventTarget.h"
 #include "mozilla/dom/EventTargetBinding.h"
 #include "mozilla/dom/ConstructibleEventTarget.h"
-#include "mozilla/dom/Nullable.h"
-#include "mozilla/dom/WindowProxyHolder.h"
 #include "nsIGlobalObject.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 /* static */
 already_AddRefed<EventTarget> EventTarget::Constructor(
@@ -179,19 +177,10 @@ void EventTarget::DispatchEvent(Event& a
 }
 
 void EventTarget::DispatchEvent(Event& aEvent, ErrorResult& aRv) {
   // The caller type doesn't really matter if we don't care about the
   // return value, but let's be safe and pass NonSystem.
   Unused << DispatchEvent(aEvent, CallerType::NonSystem, IgnoreErrors());
 }
 
-Nullable<WindowProxyHolder> EventTarget::GetOwnerGlobalForBindings() {
-  nsPIDOMWindowOuter* win = GetOwnerGlobalForBindingsInternal();
-  if (!win) {
-    return nullptr;
-  }
-
-  return WindowProxyHolder(win->GetBrowsingContext());
-}
-
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/events/EventTarget.h
+++ b/dom/events/EventTarget.h
@@ -29,19 +29,16 @@ class EventListenerManager;
 namespace dom {
 
 class AddEventListenerOptionsOrBoolean;
 class Event;
 class EventListener;
 class EventListenerOptionsOrBoolean;
 class EventHandlerNonNull;
 class GlobalObject;
-template <typename>
-struct Nullable;
-class WindowProxyHolder;
 
 // IID for the dom::EventTarget interface
 #define NS_EVENTTARGET_IID                           \
   {                                                  \
     0xde651c36, 0x0053, 0x4c67, {                    \
       0xb1, 0x3d, 0x67, 0xb9, 0x40, 0xfc, 0x82, 0xe4 \
     }                                                \
   }
@@ -173,18 +170,17 @@ class EventTarget : public nsISupports, 
   virtual void EventListenerAdded(nsAtom* aType) {}
 
   // For an event 'foo' aType will be 'onfoo'.
   virtual void EventListenerRemoved(nsAtom* aType) {}
 
   // Returns an outer window that corresponds to the inner window this event
   // target is associated with.  Will return null if the inner window is not the
   // current inner or if there is no window around at all.
-  Nullable<WindowProxyHolder> GetOwnerGlobalForBindings();
-  virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindingsInternal() = 0;
+  virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() = 0;
 
   // The global object this event target is associated with, if any.
   // This may be an inner window or some other global object.  This
   // will never be an outer window.
   virtual nsIGlobalObject* GetOwnerGlobal() const = 0;
 
   /**
    * Get the event listener manager, creating it if it does not already exist.
--- a/dom/events/MessageEvent.cpp
+++ b/dom/events/MessageEvent.cpp
@@ -1,23 +1,23 @@
 /* -*- 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 "mozilla/dom/MessageEvent.h"
-#include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/MessageEventBinding.h"
 #include "mozilla/dom/MessagePort.h"
 #include "mozilla/dom/MessagePortBinding.h"
 #include "mozilla/dom/ServiceWorker.h"
 
 #include "mozilla/HoldDropJSObjects.h"
 #include "jsapi.h"
+#include "nsGlobalWindow.h"  // So we can assign an nsGlobalWindow* to mWindowSource
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(MessageEvent)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessageEvent, Event)
   tmp->mData.setUndefined();
@@ -103,17 +103,17 @@ void MessageEvent::GetSource(
 
   mozilla::HoldJSObjects(event.get());
 
   event->mOrigin = aParam.mOrigin;
   event->mLastEventId = aParam.mLastEventId;
 
   if (!aParam.mSource.IsNull()) {
     if (aParam.mSource.Value().IsWindowProxy()) {
-      event->mWindowSource = aParam.mSource.Value().GetAsWindowProxy().get();
+      event->mWindowSource = aParam.mSource.Value().GetAsWindowProxy();
     } else if (aParam.mSource.Value().IsMessagePort()) {
       event->mPortSource = aParam.mSource.Value().GetAsMessagePort();
     } else {
       event->mServiceWorkerSource = aParam.mSource.Value().GetAsServiceWorker();
     }
 
     MOZ_ASSERT(event->mWindowSource || event->mPortSource ||
                event->mServiceWorkerSource);
@@ -139,17 +139,17 @@ void MessageEvent::InitMessageEvent(
   mLastEventId = aLastEventId;
 
   mWindowSource = nullptr;
   mPortSource = nullptr;
   mServiceWorkerSource = nullptr;
 
   if (!aSource.IsNull()) {
     if (aSource.Value().IsWindowProxy()) {
-      mWindowSource = aSource.Value().GetAsWindowProxy().get();
+      mWindowSource = aSource.Value().GetAsWindowProxy();
     } else if (aSource.Value().IsMessagePort()) {
       mPortSource = &aSource.Value().GetAsMessagePort();
     } else {
       mServiceWorkerSource = &aSource.Value().GetAsServiceWorker();
     }
   }
 
   mPorts.Clear();
--- a/dom/events/MessageEvent.h
+++ b/dom/events/MessageEvent.h
@@ -9,17 +9,16 @@
 
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "nsCycleCollectionParticipant.h"
 
 namespace mozilla {
 namespace dom {
 
-class BrowsingContext;
 struct MessageEventInit;
 class MessagePort;
 class OwningWindowProxyOrMessagePortOrServiceWorker;
 class ServiceWorker;
 class WindowProxyOrMessagePortOrServiceWorker;
 
 /**
  * Implements the MessageEvent event, used for cross-document messaging and
@@ -76,17 +75,17 @@ class MessageEvent final : public Event 
 
  protected:
   ~MessageEvent();
 
  private:
   JS::Heap<JS::Value> mData;
   nsString mOrigin;
   nsString mLastEventId;
-  RefPtr<BrowsingContext> mWindowSource;
+  RefPtr<nsPIDOMWindowOuter> mWindowSource;
   RefPtr<MessagePort> mPortSource;
   RefPtr<ServiceWorker> mServiceWorkerSource;
 
   nsTArray<RefPtr<MessagePort>> mPorts;
 };
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/events/UIEvent.h
+++ b/dom/events/UIEvent.h
@@ -4,21 +4,18 @@
  * 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 mozilla_dom_UIEvent_h_
 #define mozilla_dom_UIEvent_h_
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/Event.h"
-#include "mozilla/dom/Nullable.h"
 #include "mozilla/dom/UIEventBinding.h"
-#include "mozilla/dom/WindowProxyHolder.h"
 #include "nsDeviceContext.h"
-#include "nsDocShell.h"
 #include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 
 class nsINode;
 
 namespace mozilla {
 namespace dom {
 
@@ -45,22 +42,17 @@ class UIEvent : public Event {
   }
 
   UIEvent* AsUIEvent() override { return this; }
 
   void InitUIEvent(const nsAString& typeArg, bool canBubbleArg,
                    bool cancelableArg, nsGlobalWindowInner* viewArg,
                    int32_t detailArg);
 
-  Nullable<WindowProxyHolder> GetView() const {
-    if (!mView) {
-      return nullptr;
-    }
-    return WindowProxyHolder(mView->GetBrowsingContext());
-  }
+  nsPIDOMWindowOuter* GetView() const { return mView; }
 
   int32_t Detail() const { return mDetail; }
 
   int32_t LayerX() const { return GetLayerPoint().x; }
 
   int32_t LayerY() const { return GetLayerPoint().y; }
 
   int32_t PageX() const;
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -369,24 +369,21 @@ HTMLObjectElement::SubmitNamesValues(HTM
 
   return aFormSubmission->AddNameValuePair(name, value);
 }
 
 int32_t HTMLObjectElement::TabIndexDefault() {
   return IsFocusableForTabIndex() ? 0 : -1;
 }
 
-Nullable<WindowProxyHolder> HTMLObjectElement::GetContentWindow(
+nsPIDOMWindowOuter* HTMLObjectElement::GetContentWindow(
     nsIPrincipal& aSubjectPrincipal) {
   nsIDocument* doc = GetContentDocument(aSubjectPrincipal);
   if (doc) {
-    nsPIDOMWindowOuter* win = doc->GetWindow();
-    if (win) {
-      return WindowProxyHolder(win->GetBrowsingContext());
-    }
+    return doc->GetWindow();
   }
 
   return nullptr;
 }
 
 bool HTMLObjectElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
                                        const nsAString& aValue,
                                        nsIPrincipal* aMaybeScriptedPrincipal,
--- a/dom/html/HTMLObjectElement.h
+++ b/dom/html/HTMLObjectElement.h
@@ -11,19 +11,16 @@
 #include "nsGenericHTMLElement.h"
 #include "nsObjectLoadingContent.h"
 #include "nsIConstraintValidation.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLFormSubmission;
-template <typename T>
-struct Nullable;
-class WindowProxyHolder;
 
 class HTMLObjectElement final : public nsGenericHTMLFormElement,
                                 public nsObjectLoadingContent,
                                 public nsIConstraintValidation {
  public:
   explicit HTMLObjectElement(
       already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
       FromParser aFromParser = NOT_FROM_PARSER);
@@ -119,17 +116,17 @@ class HTMLObjectElement final : public n
     SetHTMLAttr(nsGkAtoms::width, aValue, aRv);
   }
   void GetHeight(DOMString& aValue) { GetHTMLAttr(nsGkAtoms::height, aValue); }
   void SetHeight(const nsAString& aValue, ErrorResult& aRv) {
     SetHTMLAttr(nsGkAtoms::height, aValue, aRv);
   }
   using nsObjectLoadingContent::GetContentDocument;
 
-  Nullable<WindowProxyHolder> GetContentWindow(nsIPrincipal& aSubjectPrincipal);
+  nsPIDOMWindowOuter* GetContentWindow(nsIPrincipal& aSubjectPrincipal);
 
   using nsIConstraintValidation::GetValidationMessage;
   using nsIConstraintValidation::SetCustomValidity;
   void GetAlign(DOMString& aValue) { GetHTMLAttr(nsGkAtoms::align, aValue); }
   void SetAlign(const nsAString& aValue, ErrorResult& aRv) {
     SetHTMLAttr(nsGkAtoms::align, aValue, aRv);
   }
   void GetArchive(DOMString& aValue) {
--- a/dom/html/nsGenericHTMLFrameElement.cpp
+++ b/dom/html/nsGenericHTMLFrameElement.cpp
@@ -66,72 +66,70 @@ int32_t nsGenericHTMLFrameElement::TabIn
 nsGenericHTMLFrameElement::~nsGenericHTMLFrameElement() {
   if (mFrameLoader) {
     mFrameLoader->Destroy();
   }
 }
 
 nsIDocument* nsGenericHTMLFrameElement::GetContentDocument(
     nsIPrincipal& aSubjectPrincipal) {
-  RefPtr<BrowsingContext> bc = GetContentWindowInternal();
-  if (!bc) {
+  nsCOMPtr<nsPIDOMWindowOuter> win = GetContentWindow();
+  if (!win) {
     return nullptr;
   }
 
-  nsIDocument* doc = bc->GetDOMWindow()->GetDoc();
+  nsIDocument* doc = win->GetDoc();
   if (!doc) {
     return nullptr;
   }
 
   // Return null for cross-origin contentDocument.
   if (!aSubjectPrincipal.SubsumesConsideringDomain(doc->NodePrincipal())) {
     return nullptr;
   }
   return doc;
 }
 
-BrowsingContext* nsGenericHTMLFrameElement::GetContentWindowInternal() {
+already_AddRefed<nsPIDOMWindowOuter>
+nsGenericHTMLFrameElement::GetContentWindow() {
   EnsureFrameLoader();
 
   if (!mFrameLoader) {
     return nullptr;
   }
 
   if (mFrameLoader->DepthTooGreat()) {
     // Claim to have no contentWindow
     return nullptr;
   }
 
-  RefPtr<nsDocShell> doc_shell = mFrameLoader->GetDocShell(IgnoreErrors());
+  nsCOMPtr<nsIDocShell> doc_shell = mFrameLoader->GetDocShell(IgnoreErrors());
   if (!doc_shell) {
     return nullptr;
   }
 
-  return doc_shell->GetBrowsingContext();
-}
+  nsCOMPtr<nsPIDOMWindowOuter> win = doc_shell->GetWindow();
 
-Nullable<WindowProxyHolder> nsGenericHTMLFrameElement::GetContentWindow() {
-  RefPtr<BrowsingContext> bc = GetContentWindowInternal();
-  if (!bc) {
+  if (!win) {
     return nullptr;
   }
-  return WindowProxyHolder(bc);
+
+  return win.forget();
 }
 
 void nsGenericHTMLFrameElement::EnsureFrameLoader() {
   if (!IsInComposedDoc() || mFrameLoader || mFrameLoaderCreationDisallowed) {
     // If frame loader is there, we just keep it around, cached
     return;
   }
 
   // Strangely enough, this method doesn't actually ensure that the
   // frameloader exists.  It's more of a best-effort kind of thing.
   mFrameLoader = nsFrameLoader::Create(
-      this, mOpenerWindow ? mOpenerWindow->GetDOMWindow() : nullptr,
-      mNetworkCreated);
+      this, nsPIDOMWindowOuter::From(mOpenerWindow), mNetworkCreated);
 }
 
 nsresult nsGenericHTMLFrameElement::CreateRemoteFrameLoader(
     nsITabParent* aTabParent) {
   MOZ_ASSERT(!mFrameLoader);
   EnsureFrameLoader();
   NS_ENSURE_STATE(mFrameLoader);
   mFrameLoader->SetRemoteBrowser(aTabParent);
@@ -147,21 +145,20 @@ nsresult nsGenericHTMLFrameElement::Crea
 }
 
 NS_IMETHODIMP_(already_AddRefed<nsFrameLoader>)
 nsGenericHTMLFrameElement::GetFrameLoader() {
   RefPtr<nsFrameLoader> loader = mFrameLoader;
   return loader.forget();
 }
 
-void nsGenericHTMLFrameElement::PresetOpenerWindow(
-    const Nullable<WindowProxyHolder>& aOpenerWindow, ErrorResult& aRv) {
+void nsGenericHTMLFrameElement::PresetOpenerWindow(mozIDOMWindowProxy* aWindow,
+                                                   ErrorResult& aRv) {
   MOZ_ASSERT(!mFrameLoader);
-  mOpenerWindow =
-      aOpenerWindow.IsNull() ? nullptr : aOpenerWindow.Value().get();
+  mOpenerWindow = nsPIDOMWindowOuter::From(aWindow);
 }
 
 void nsGenericHTMLFrameElement::InternalSetFrameLoader(
     nsFrameLoader* aNewFrameLoader) {
   mFrameLoader = aNewFrameLoader;
 }
 
 void nsGenericHTMLFrameElement::SwapFrameLoaders(
--- a/dom/html/nsGenericHTMLFrameElement.h
+++ b/dom/html/nsGenericHTMLFrameElement.h
@@ -14,21 +14,18 @@
 #include "nsFrameLoader.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMEventListener.h"
 #include "nsIFrameLoaderOwner.h"
 #include "nsIMozBrowserFrame.h"
 
 namespace mozilla {
 namespace dom {
-template <typename>
-struct Nullable;
-class WindowProxyHolder;
 class XULFrameElement;
-}  // namespace dom
+}
 }  // namespace mozilla
 
 #define NS_GENERICHTMLFRAMEELEMENT_IID               \
   {                                                  \
     0x8190db72, 0xdab0, 0x4d72, {                    \
       0x94, 0x26, 0x87, 0x5f, 0x5a, 0x8a, 0x2a, 0xe5 \
     }                                                \
   }
@@ -82,18 +79,17 @@ class nsGenericHTMLFrameElement : public
                         mozilla::ErrorResult& aError);
 
   void SwapFrameLoaders(mozilla::dom::XULFrameElement& aOtherLoaderOwner,
                         mozilla::ErrorResult& aError);
 
   void SwapFrameLoaders(nsIFrameLoaderOwner* aOtherLoaderOwner,
                         mozilla::ErrorResult& rv);
 
-  void PresetOpenerWindow(const mozilla::dom::Nullable<
-                              mozilla::dom::WindowProxyHolder>& aOpenerWindow,
+  void PresetOpenerWindow(mozIDOMWindowProxy* aOpenerWindow,
                           mozilla::ErrorResult& aRv);
 
   static void InitStatics();
   static bool BrowserFramesEnabled();
 
   /**
    * Helper method to map a HTML 'scrolling' attribute value to a nsIScrollable
    * enum value.  scrolling="no" (and its synonyms) maps to
@@ -111,29 +107,29 @@ class nsGenericHTMLFrameElement : public
  protected:
   virtual ~nsGenericHTMLFrameElement();
 
   // This doesn't really ensure a frame loader in all cases, only when
   // it makes sense.
   void EnsureFrameLoader();
   void LoadSrc();
   nsIDocument* GetContentDocument(nsIPrincipal& aSubjectPrincipal);
-  mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetContentWindow();
+  already_AddRefed<nsPIDOMWindowOuter> GetContentWindow();
 
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                           const nsAttrValueOrString& aValue,
                                           bool aNotify) override;
 
   RefPtr<nsFrameLoader> mFrameLoader;
-  RefPtr<mozilla::dom::BrowsingContext> mOpenerWindow;
+  nsCOMPtr<nsPIDOMWindowOuter> mOpenerWindow;
 
   nsCOMPtr<nsIPrincipal> mSrcTriggeringPrincipal;
 
   /**
    * True if we have already loaded the frame's original src
    */
   bool mSrcLoadHappened;
 
@@ -164,16 +160,14 @@ class nsGenericHTMLFrameElement : public
    * @param aName the localname of the attribute being set
    * @param aValue the value being set or null if the value is being unset
    * @param aNotify Whether we plan to notify document observers.
    */
   void AfterMaybeChangeAttr(int32_t aNamespaceID, nsAtom* aName,
                             const nsAttrValueOrString* aValue,
                             nsIPrincipal* aMaybeScriptedPrincipal,
                             bool aNotify);
-
-  mozilla::dom::BrowsingContext* GetContentWindowInternal();
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsGenericHTMLFrameElement,
                               NS_GENERICHTMLFRAMEELEMENT_IID)
 
 #endif  // nsGenericHTMLFrameElement_h
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -1133,17 +1133,17 @@ void nsHTMLDocument::SetCookie(const nsA
       }
     }
 
     NS_ConvertUTF16toUTF8 cookie(aCookie);
     service->SetCookieString(codebaseURI, nullptr, cookie.get(), channel);
   }
 }
 
-mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> nsHTMLDocument::Open(
+already_AddRefed<nsPIDOMWindowOuter> nsHTMLDocument::Open(
     JSContext* /* unused */, const nsAString& aURL, const nsAString& aName,
     const nsAString& aFeatures, bool aReplace, ErrorResult& rv) {
   MOZ_ASSERT(nsContentUtils::CanCallerAccess(this),
              "XOW should have caught this!");
 
   nsCOMPtr<nsPIDOMWindowInner> window = GetInnerWindow();
   if (!window) {
     rv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
@@ -1154,20 +1154,17 @@ mozilla::dom::Nullable<mozilla::dom::Win
   if (!outer) {
     rv.Throw(NS_ERROR_NOT_INITIALIZED);
     return nullptr;
   }
   RefPtr<nsGlobalWindowOuter> win = nsGlobalWindowOuter::Cast(outer);
   nsCOMPtr<nsPIDOMWindowOuter> newWindow;
   // XXXbz We ignore aReplace for now.
   rv = win->OpenJS(aURL, aName, aFeatures, getter_AddRefs(newWindow));
-  if (!newWindow) {
-    return nullptr;
-  }
-  return WindowProxyHolder(newWindow->GetBrowsingContext());
+  return newWindow.forget();
 }
 
 already_AddRefed<nsIDocument> nsHTMLDocument::Open(
     JSContext* cx, const Optional<nsAString>& /* unused */,
     const nsAString& aReplace, ErrorResult& aError) {
   // Implements the "When called with two arguments (or fewer)" steps here:
   // https://html.spec.whatwg.org/multipage/webappapis.html#opening-the-input-stream
 
--- a/dom/html/nsHTMLDocument.h
+++ b/dom/html/nsHTMLDocument.h
@@ -25,19 +25,16 @@ class nsIURI;
 class nsIDocShell;
 class nsICachingChannel;
 class nsIWyciwygChannel;
 class nsILoadGroup;
 
 namespace mozilla {
 namespace dom {
 class HTMLAllCollection;
-template <typename T>
-struct Nullable;
-class WindowProxyHolder;
 }  // namespace dom
 }  // namespace mozilla
 
 class nsHTMLDocument : public nsDocument, public nsIHTMLDocument {
   typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
 
  public:
   using nsDocument::GetPlugins;
@@ -148,17 +145,17 @@ class nsHTMLDocument : public nsDocument
     if ((aFound = ResolveName(cx, aName, &v, rv))) {
       aRetval.set(v.toObjectOrNull());
     }
   }
   void GetSupportedNames(nsTArray<nsString>& aNames);
   already_AddRefed<nsIDocument> Open(
       JSContext* cx, const mozilla::dom::Optional<nsAString>& /* unused */,
       const nsAString& aReplace, mozilla::ErrorResult& aError);
-  mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> Open(
+  already_AddRefed<nsPIDOMWindowOuter> Open(
       JSContext* cx, const nsAString& aURL, const nsAString& aName,
       const nsAString& aFeatures, bool aReplace, mozilla::ErrorResult& rv);
   void Close(mozilla::ErrorResult& rv);
   void Write(JSContext* cx, const mozilla::dom::Sequence<nsString>& aText,
              mozilla::ErrorResult& rv);
   void Writeln(JSContext* cx, const mozilla::dom::Sequence<nsString>& aText,
                mozilla::ErrorResult& rv);
   void GetDesignMode(nsAString& aDesignMode);
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -40,17 +40,16 @@
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/ExternalHelperAppChild.h"
 #include "mozilla/dom/FileCreatorHelper.h"
 #include "mozilla/dom/GetFilesHelper.h"
 #include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/LSObject.h"
 #include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/dom/PLoginReputationChild.h"
-#include "mozilla/dom/PostMessageEvent.h"
 #include "mozilla/dom/PushNotifier.h"
 #include "mozilla/dom/RemoteWorkerService.h"
 #include "mozilla/dom/ServiceWorkerManager.h"
 #include "mozilla/dom/TabGroup.h"
 #include "mozilla/dom/nsIContentChild.h"
 #include "mozilla/dom/URLClassifierChild.h"
 #include "mozilla/dom/WorkerDebugger.h"
 #include "mozilla/dom/WorkerDebuggerManager.h"
@@ -3479,105 +3478,16 @@ PContentChild::Result ContentChild::OnMe
     MOZ_ASSERT(!aMsg.is_reply());
 
     LSObject::OnSyncMessageHandled();
   }
 
   return result;
 }
 
-mozilla::ipc::IPCResult ContentChild::RecvWindowClose(
-    const BrowsingContextId& aContextId, const bool& aTrustedCaller) {
-  RefPtr<BrowsingContext> bc = BrowsingContext::Get(aContextId);
-  if (!bc) {
-    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
-            ("ChildIPC: Trying to send a message to dead or detached context "
-             "0x%08" PRIx64,
-             (uint64_t)aContextId));
-    return IPC_OK();
-  }
-
-  nsCOMPtr<nsPIDOMWindowOuter> window = bc->GetDOMWindow();
-  nsGlobalWindowOuter::Cast(window)->CloseOuter(aTrustedCaller);
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult ContentChild::RecvWindowFocus(
-    const BrowsingContextId& aContextId) {
-  RefPtr<BrowsingContext> bc = BrowsingContext::Get(aContextId);
-  if (!bc) {
-    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
-            ("ChildIPC: Trying to send a message to dead or detached context "
-             "0x%08" PRIx64,
-             (uint64_t)aContextId));
-    return IPC_OK();
-  }
-
-  nsCOMPtr<nsPIDOMWindowOuter> window = bc->GetDOMWindow();
-  nsGlobalWindowOuter::Cast(window)->FocusOuter();
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult ContentChild::RecvWindowBlur(
-    const BrowsingContextId& aContextId) {
-  RefPtr<BrowsingContext> bc = BrowsingContext::Get(aContextId);
-  if (!bc) {
-    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
-            ("ChildIPC: Trying to send a message to dead or detached context "
-             "0x%08" PRIx64,
-             (uint64_t)aContextId));
-    return IPC_OK();
-  }
-
-  nsCOMPtr<nsPIDOMWindowOuter> window = bc->GetDOMWindow();
-  nsGlobalWindowOuter::Cast(window)->BlurOuter();
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult ContentChild::RecvWindowPostMessage(
-    const BrowsingContextId& aContextId, const ClonedMessageData& aMessage,
-    const PostMessageData& aData) {
-  RefPtr<BrowsingContext> bc = BrowsingContext::Get(aContextId);
-  if (!bc) {
-    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
-            ("ChildIPC: Trying to send a message to dead or detached context "
-             "0x%08" PRIx64,
-             (uint64_t)aContextId));
-    return IPC_OK();
-  }
-
-  RefPtr<nsGlobalWindowOuter> window =
-      nsGlobalWindowOuter::Cast(bc->GetDOMWindow());
-  nsCOMPtr<nsIPrincipal> providedPrincipal;
-  if (!window->GetPrincipalForPostMessage(
-          aData.targetOrigin(), aData.targetOriginURI(),
-          aData.callerPrincipal(), *aData.subjectPrincipal(),
-          getter_AddRefs(providedPrincipal))) {
-    return IPC_OK();
-  }
-
-  RefPtr<BrowsingContext> sourceBc = BrowsingContext::Get(aData.source());
-  if (!sourceBc) {
-    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
-            ("ChildIPC: Trying to use a dead or detached context 0x%08" PRIx64,
-             (uint64_t)aData.source()));
-    return IPC_OK();
-  }
-
-  // Create and asynchronously dispatch a runnable which will handle actual DOM
-  // event creation and dispatch.
-  RefPtr<PostMessageEvent> event = new PostMessageEvent(
-      sourceBc, aData.origin(), window, providedPrincipal,
-      aData.callerDocumentURI(), aData.isFromPrivateWindow());
-  event->UnpackFrom(aMessage);
-
-  window->Dispatch(TaskCategory::Other, event.forget());
-  return IPC_OK();
-}
-
 }  // namespace dom
 
 #if defined(__OpenBSD__) && defined(MOZ_CONTENT_SANDBOX)
 #include <unistd.h>
 
 static LazyLogModule sPledgeLog("SandboxPledge");
 
 bool StartOpenBSDSandbox(GeckoProcessType type) {
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -721,26 +721,16 @@ class ContentChild final : public PConte
   virtual already_AddRefed<nsIEventTarget> GetConstructedEventTarget(
       const Message& aMsg) override;
 
   virtual already_AddRefed<nsIEventTarget> GetSpecificMessageEventTarget(
       const Message& aMsg) override;
 
   virtual void OnChannelReceivedMessage(const Message& aMsg) override;
 
-  virtual mozilla::ipc::IPCResult RecvWindowClose(
-      const BrowsingContextId& aContextId, const bool& aTrustedCaller) override;
-  virtual mozilla::ipc::IPCResult RecvWindowFocus(
-      const BrowsingContextId& aContextId) override;
-  virtual mozilla::ipc::IPCResult RecvWindowBlur(
-      const BrowsingContextId& aContextId) override;
-  virtual mozilla::ipc::IPCResult RecvWindowPostMessage(
-      const BrowsingContextId& aContextId, const ClonedMessageData& aMessage,
-      const PostMessageData& aData) override;
-
 #ifdef NIGHTLY_BUILD
   virtual PContentChild::Result OnMessageReceived(const Message& aMsg) override;
 #else
   using PContentChild::OnMessageReceived;
 #endif
 
   virtual PContentChild::Result OnMessageReceived(const Message& aMsg,
                                                   Message*& aReply) override;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -5122,16 +5122,29 @@ mozilla::ipc::IPCResult ContentParent::R
   RefPtr<IHandlerControl> proxy(aHandlerControl.Get());
   a11y::AccessibleWrap::SetHandlerControl(aPid, std::move(proxy));
   return IPC_OK();
 #else
   return IPC_FAIL_NO_REASON(this);
 #endif
 }
 
+}  // namespace dom
+}  // namespace mozilla
+
+NS_IMPL_ISUPPORTS(ParentIdleListener, nsIObserver)
+
+NS_IMETHODIMP
+ParentIdleListener::Observe(nsISupports*, const char* aTopic,
+                            const char16_t* aData) {
+  mozilla::Unused << mParent->SendNotifyIdleObserver(
+      mObserver, nsDependentCString(aTopic), nsDependentString(aData));
+  return NS_OK;
+}
+
 bool ContentParent::HandleWindowsMessages(const Message& aMsg) const {
   MOZ_ASSERT(aMsg.is_sync());
 
   // a11y messages can be triggered by windows messages, which means if we
   // allow handling windows messages while we wait for the response to a sync
   // a11y message we can reenter the ipc message sending code.
   if (a11y::PDocAccessible::PDocAccessibleStart < aMsg.type() &&
       a11y::PDocAccessible::PDocAccessibleEnd > aMsg.type()) {
@@ -5759,105 +5772,8 @@ void ContentParent::UnregisterRemoveWork
       !ShouldKeepProcessAlive() && !TryToRecycle()) {
     // In the case of normal shutdown, send a shutdown message to child to
     // allow it to perform shutdown tasks.
     MessageLoop::current()->PostTask(NewRunnableMethod<ShutDownMethod>(
         "dom::ContentParent::ShutDownProcess", this,
         &ContentParent::ShutDownProcess, SEND_SHUTDOWN_MESSAGE));
   }
 }
-
-mozilla::ipc::IPCResult ContentParent::RecvWindowClose(
-    const BrowsingContextId& aContextId, const bool& aTrustedCaller) {
-  RefPtr<ChromeBrowsingContext> bc = ChromeBrowsingContext::Get(aContextId);
-  if (!bc) {
-    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
-            ("ParentIPC: Trying to send a message to dead or detached context "
-             "0x%08" PRIx64,
-             (uint64_t)aContextId));
-    return IPC_OK();
-  }
-
-  // FIXME Need to check that the sending process has access to the unit of
-  // related
-  //       browsing contexts of bc.
-
-  ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
-  ContentParent* cp =
-      cpm->GetContentProcessById(ContentParentId(bc->OwnerProcessId()));
-  Unused << cp->SendWindowClose(aContextId, aTrustedCaller);
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult ContentParent::RecvWindowFocus(
-    const BrowsingContextId& aContextId) {
-  RefPtr<ChromeBrowsingContext> bc = ChromeBrowsingContext::Get(aContextId);
-  if (!bc) {
-    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
-            ("ParentIPC: Trying to send a message to dead or detached context "
-             "0x%08" PRIx64,
-             (uint64_t)aContextId));
-    return IPC_OK();
-  }
-
-  ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
-  ContentParent* cp =
-      cpm->GetContentProcessById(ContentParentId(bc->OwnerProcessId()));
-  Unused << cp->SendWindowFocus(aContextId);
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult ContentParent::RecvWindowBlur(
-    const BrowsingContextId& aContextId) {
-  RefPtr<ChromeBrowsingContext> bc = ChromeBrowsingContext::Get(aContextId);
-  if (!bc) {
-    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
-            ("ParentIPC: Trying to send a message to dead or detached context "
-             "0x%08" PRIx64,
-             (uint64_t)aContextId));
-    return IPC_OK();
-  }
-
-  ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
-  ContentParent* cp =
-      cpm->GetContentProcessById(ContentParentId(bc->OwnerProcessId()));
-  Unused << cp->SendWindowBlur(aContextId);
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult ContentParent::RecvWindowPostMessage(
-    const BrowsingContextId& aContextId, const ClonedMessageData& aMessage,
-    const PostMessageData& aData) {
-  RefPtr<ChromeBrowsingContext> bc = ChromeBrowsingContext::Get(aContextId);
-  if (!bc) {
-    MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
-            ("ParentIPC: Trying to send a message to dead or detached context "
-             "0x%08" PRIx64,
-             (uint64_t)aContextId));
-    return IPC_OK();
-  }
-
-  ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
-  ContentParent* cp =
-      cpm->GetContentProcessById(ContentParentId(bc->OwnerProcessId()));
-  StructuredCloneData messageFromChild;
-  UnpackClonedMessageDataForParent(aMessage, messageFromChild);
-  ClonedMessageData message;
-  if (!BuildClonedMessageDataForParent(cp, messageFromChild, message)) {
-    // FIXME Logging?
-    return IPC_OK();
-  }
-  Unused << cp->SendWindowPostMessage(aContextId, message, aData);
-  return IPC_OK();
-}
-
-}  // namespace dom
-}  // namespace mozilla
-
-NS_IMPL_ISUPPORTS(ParentIdleListener, nsIObserver)
-
-NS_IMETHODIMP
-ParentIdleListener::Observe(nsISupports*, const char* aTopic,
-                            const char16_t* aData) {
-  mozilla::Unused << mParent->SendNotifyIdleObserver(
-      mObserver, nsDependentCString(aTopic), nsDependentString(aData));
-  return NS_OK;
-}
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -632,26 +632,16 @@ class ContentParent final : public PCont
 
   virtual mozilla::ipc::IPCResult RecvDetachBrowsingContext(
       const BrowsingContextId& aContextId, const bool& aMoveToBFCache) override;
 
   virtual mozilla::ipc::IPCResult RecvSetOpenerBrowsingContext(
       const BrowsingContextId& aContextId,
       const BrowsingContextId& aOpenerContextId) override;
 
-  virtual mozilla::ipc::IPCResult RecvWindowClose(
-      const BrowsingContextId& aContextId, const bool& aTrustedCaller) override;
-  virtual mozilla::ipc::IPCResult RecvWindowFocus(
-      const BrowsingContextId& aContextId) override;
-  virtual mozilla::ipc::IPCResult RecvWindowBlur(
-      const BrowsingContextId& aContextId) override;
-  virtual mozilla::ipc::IPCResult RecvWindowPostMessage(
-      const BrowsingContextId& aContextId, const ClonedMessageData& aMessage,
-      const PostMessageData& aData) override;
-
  protected:
   void OnChannelConnected(int32_t pid) override;
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   bool ShouldContinueFromReplyTimeout() override;
 
   void OnVarChanged(const GfxVarUpdate& aVar) override;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -317,28 +317,16 @@ struct NotificationEventData
     nsString lang;
     nsString body;
     nsString tag;
     nsString icon;
     nsString data;
     nsString behavior;
 };
 
-struct PostMessageData
-{
-    BrowsingContextId source;
-    nsString origin;
-    nsString targetOrigin;
-    nsIURI targetOriginURI;
-    nsIPrincipal callerPrincipal;
-    nsIPrincipal subjectPrincipal;
-    nsIURI callerDocumentURI;
-    bool isFromPrivateWindow;
-};
-
 /**
  * The PContent protocol is a top-level protocol between the UI process
  * and a content process. There is exactly one PContentParent/PContentChild pair
  * for each content process.
  */
 nested(upto inside_cpow) sync protocol PContent
 {
     manages PBrowser;
@@ -1264,19 +1252,12 @@ both:
      async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
                         Principal aPrincipal, ClonedMessageData aData);
 
     /**
      * Notify `push-subscription-modified` observers in the parent and child.
      */
     async NotifyPushSubscriptionModifiedObservers(nsCString scope,
                                                   Principal principal);
-
-    async WindowClose(BrowsingContextId aContextId,
-                      bool aTrustedCaller);
-    async WindowFocus(BrowsingContextId aContextId);
-    async WindowBlur(BrowsingContextId aContextId);
-    async WindowPostMessage(BrowsingContextId aContextId, ClonedMessageData aMessage,
-                            PostMessageData aData);
 };
 
 }
 }
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -20,19 +20,17 @@
 #include "mozilla/BrowserElementParent.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/indexedDB/PIndexedDBPermissionRequestChild.h"
 #include "mozilla/dom/MessageManagerBinding.h"
 #include "mozilla/dom/MouseEventBinding.h"
-#include "mozilla/dom/Nullable.h"
 #include "mozilla/dom/PaymentRequestChild.h"
-#include "mozilla/dom/WindowProxyHolder.h"
 #include "mozilla/gfx/CrossProcessPaint.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/layers/APZChild.h"
 #include "mozilla/layers/APZCCallbackHelper.h"
 #include "mozilla/layers/APZCTreeManagerChild.h"
 #include "mozilla/layers/APZEventState.h"
 #include "mozilla/layers/ContentProcessController.h"
@@ -3256,23 +3254,25 @@ void TabChildMessageManager::MarkForCC()
   }
   EventListenerManager* elm = GetExistingListenerManager();
   if (elm) {
     elm->MarkForCC();
   }
   MessageManagerGlobal::MarkForCC();
 }
 
-Nullable<WindowProxyHolder> TabChildMessageManager::GetContent(
+already_AddRefed<nsPIDOMWindowOuter> TabChildMessageManager::GetContent(
     ErrorResult& aError) {
-  nsCOMPtr<nsIDocShell> docShell = GetDocShell(aError);
-  if (!docShell) {
+  if (!mTabChild) {
+    aError.Throw(NS_ERROR_NULL_POINTER);
     return nullptr;
   }
-  return WindowProxyHolder(nsDocShell::Cast(docShell)->GetBrowsingContext());
+  nsCOMPtr<nsPIDOMWindowOuter> window =
+      do_GetInterface(mTabChild->WebNavigation());
+  return window.forget();
 }
 
 already_AddRefed<nsIDocShell> TabChildMessageManager::GetDocShell(
     ErrorResult& aError) {
   if (!mTabChild) {
     aError.Throw(NS_ERROR_NULL_POINTER);
     return nullptr;
   }
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -89,17 +89,18 @@ class TabChildMessageManager : public Co
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TabChildMessageManager,
                                            DOMEventTargetHelper)
 
   void MarkForCC();
 
   JSObject* WrapObject(JSContext* aCx,
                        JS::Handle<JSObject*> aGivenProto) override;
 
-  virtual Nullable<WindowProxyHolder> GetContent(ErrorResult& aError) override;
+  virtual already_AddRefed<nsPIDOMWindowOuter> GetContent(
+      ErrorResult& aError) override;
   virtual already_AddRefed<nsIDocShell> GetDocShell(
       ErrorResult& aError) override;
   virtual already_AddRefed<nsIEventTarget> GetTabEventTarget() override;
   virtual uint64_t ChromeOuterWindowID() override;
 
   NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
 
   void GetEventTargetParent(EventChainPreVisitor& aVisitor) override {
--- a/dom/smil/TimeEvent.h
+++ b/dom/smil/TimeEvent.h
@@ -2,21 +2,18 @@
 /* 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 mozilla_dom_TimeEvent_h_
 #define mozilla_dom_TimeEvent_h_
 
-#include "nsDocShell.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/TimeEventBinding.h"
-#include "mozilla/dom/Nullable.h"
-#include "mozilla/dom/WindowProxyHolder.h"
 
 class nsGlobalWindowInner;
 
 namespace mozilla {
 namespace dom {
 
 class TimeEvent final : public Event {
  public:
@@ -32,22 +29,17 @@ class TimeEvent final : public Event {
     return TimeEvent_Binding::Wrap(aCx, this, aGivenProto);
   }
 
   void InitTimeEvent(const nsAString& aType, nsGlobalWindowInner* aView,
                      int32_t aDetail);
 
   int32_t Detail() const { return mDetail; }
 
-  Nullable<WindowProxyHolder> GetView() const {
-    if (!mView) {
-      return nullptr;
-    }
-    return WindowProxyHolder(mView->GetBrowsingContext());
-  }
+  nsPIDOMWindowOuter* GetView() const { return mView; }
 
   TimeEvent* AsTimeEvent() final { return this; }
 
  private:
   ~TimeEvent() {}
 
   nsCOMPtr<nsPIDOMWindowOuter> mView;
   int32_t mDetail;
--- a/dom/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
+++ b/dom/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
@@ -128,17 +128,17 @@ WebBrowserPersistLocalDocument::GetTitle
 NS_IMETHODIMP
 WebBrowserPersistLocalDocument::GetReferrer(nsAString& aReferrer) {
   mDocument->GetReferrer(aReferrer);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 WebBrowserPersistLocalDocument::GetContentDisposition(nsAString& aCD) {
-  nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetWindow();
+  nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetDefaultView();
   if (NS_WARN_IF(!window)) {
     aCD.SetIsVoid(true);
     return NS_OK;
   }
   nsCOMPtr<nsIDOMWindowUtils> utils =
       nsGlobalWindowOuter::Cast(window)->WindowUtils();
   nsresult rv =
       utils->GetDocumentMetadata(NS_LITERAL_STRING("content-disposition"), aCD);
@@ -171,17 +171,17 @@ WebBrowserPersistLocalDocument::GetPostD
 NS_IMETHODIMP
 WebBrowserPersistLocalDocument::GetPrincipal(nsIPrincipal** aPrincipal) {
   nsCOMPtr<nsIPrincipal> nodePrincipal = mDocument->NodePrincipal();
   nodePrincipal.forget(aPrincipal);
   return NS_OK;
 }
 
 already_AddRefed<nsISHEntry> WebBrowserPersistLocalDocument::GetHistory() {
-  nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetWindow();
+  nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetDefaultView();
   if (NS_WARN_IF(!window)) {
     return nullptr;
   }
   nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(window);
   if (NS_WARN_IF(!webNav)) {
     return nullptr;
   }
   nsCOMPtr<nsIWebPageDescriptor> desc = do_QueryInterface(webNav);
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -25,33 +25,33 @@ interface nsIDOMWindowUtils;
 
 typedef OfflineResourceList ApplicationCache;
 
 // http://www.whatwg.org/specs/web-apps/current-work/
 [PrimaryGlobal, LegacyUnenumerableNamedProperties, NeedResolve]
 /*sealed*/ interface Window : EventTarget {
   // the current browsing context
   [Unforgeable, Constant, StoreInSlot,
-   CrossOriginReadable] readonly attribute WindowProxy window;
+   CrossOriginReadable] readonly attribute Window window;
   [Replaceable, Constant, StoreInSlot,
-   CrossOriginReadable] readonly attribute WindowProxy self;
+   CrossOriginReadable] readonly attribute Window self;
   [Unforgeable, StoreInSlot, Pure] readonly attribute Document? document;
   [Throws] attribute DOMString name;
-  [PutForwards=href, Unforgeable, CrossOriginReadable,
-   CrossOriginWritable] readonly attribute Location location;
+  [PutForwards=href, Unforgeable, BinaryName="getLocation",
+   CrossOriginReadable, CrossOriginWritable] readonly attribute Location location;
   [Throws] readonly attribute History history;
   readonly attribute CustomElementRegistry customElements;
   [Replaceable, Throws] readonly attribute BarProp locationbar;
   [Replaceable, Throws] readonly attribute BarProp menubar;
   [Replaceable, Throws] readonly attribute BarProp personalbar;
   [Replaceable, Throws] readonly attribute BarProp scrollbars;
   [Replaceable, Throws] readonly attribute BarProp statusbar;
   [Replaceable, Throws] readonly attribute BarProp toolbar;
   [Throws] attribute DOMString status;
-  [Throws, CrossOriginCallable, NeedsCallerType] void close();
+  [Throws, CrossOriginCallable] void close();
   [Throws, CrossOriginReadable] readonly attribute boolean closed;
   [Throws] void stop();
   [Throws, CrossOriginCallable] void focus();
   [Throws, CrossOriginCallable] void blur();
   [Replaceable, Pref="dom.window.event.enabled"] readonly attribute any event;
 
   // other browsing contexts
   [Replaceable, Throws, CrossOriginReadable] readonly attribute WindowProxy frames;
--- a/dom/xul/XULFrameElement.cpp
+++ b/dom/xul/XULFrameElement.cpp
@@ -32,72 +32,66 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(XULFrameElement, nsXULElement,
                                              nsIFrameLoaderOwner)
 
 JSObject* XULFrameElement::WrapNode(JSContext* aCx,
                                     JS::Handle<JSObject*> aGivenProto) {
   return XULFrameElement_Binding::Wrap(aCx, this, aGivenProto);
 }
 
-nsDocShell* XULFrameElement::GetDocShell() {
+nsIDocShell* XULFrameElement::GetDocShell() {
   RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
   return frameLoader ? frameLoader->GetDocShell(IgnoreErrors()) : nullptr;
 }
 
 already_AddRefed<nsIWebNavigation> XULFrameElement::GetWebNavigation() {
   nsCOMPtr<nsIDocShell> docShell = GetDocShell();
   nsCOMPtr<nsIWebNavigation> webnav = do_QueryInterface(docShell);
   return webnav.forget();
 }
 
-Nullable<WindowProxyHolder> XULFrameElement::GetContentWindow() {
-  RefPtr<nsDocShell> docShell = GetDocShell();
+already_AddRefed<nsPIDOMWindowOuter> XULFrameElement::GetContentWindow() {
+  nsCOMPtr<nsIDocShell> docShell = GetDocShell();
   if (docShell) {
-    return WindowProxyHolder(docShell->GetWindowProxy());
+    nsCOMPtr<nsPIDOMWindowOuter> win = docShell->GetWindow();
+    return win.forget();
   }
 
   return nullptr;
 }
 
 nsIDocument* XULFrameElement::GetContentDocument() {
-  nsCOMPtr<nsIDocShell> docShell = GetDocShell();
-  if (docShell) {
-    nsCOMPtr<nsPIDOMWindowOuter> win = docShell->GetWindow();
-    if (win) {
-      return win->GetDoc();
-    }
-  }
-  return nullptr;
+  nsCOMPtr<nsPIDOMWindowOuter> win = GetContentWindow();
+  return win ? win->GetDoc() : nullptr;
 }
 
 void XULFrameElement::LoadSrc() {
   if (!IsInUncomposedDoc() || !OwnerDoc()->GetRootElement()) {
     return;
   }
   RefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
   if (!frameLoader) {
     // Check if we have an opener we need to be setting
-    RefPtr<BrowsingContext> opener = mOpener;
+    nsCOMPtr<nsPIDOMWindowOuter> opener = mOpener;
     if (!opener) {
       // If we are a primary xul-browser, we want to take the opener property!
       nsCOMPtr<nsPIDOMWindowOuter> window = OwnerDoc()->GetWindow();
       if (AttrValueIs(kNameSpaceID_None, nsGkAtoms::primary, nsGkAtoms::_true,
                       eIgnoreCase) &&
           window) {
         opener = window->TakeOpenerForInitialContentBrowser();
       }
     }
     mOpener = nullptr;
 
     // false as the last parameter so that xul:iframe/browser/editor
     // session history handling works like dynamic html:iframes.
     // Usually xul elements are used in chrome, which doesn't have
     // session history at all.
-    mFrameLoader = nsFrameLoader::Create(
-        this, opener ? opener->GetDOMWindow() : nullptr, false);
+    mFrameLoader = nsFrameLoader::Create(this, opener, false);
     if (NS_WARN_IF(!mFrameLoader)) {
       return;
     }
 
     (new AsyncEventDispatcher(this, NS_LITERAL_STRING("XULFrameLoaderCreated"),
                               CanBubble::eYes))
         ->RunDOMEventWhenSafe();
   }
--- a/dom/xul/XULFrameElement.h
+++ b/dom/xul/XULFrameElement.h
@@ -4,59 +4,54 @@
  * 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 XULFrameElement_h__
 #define XULFrameElement_h__
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
-#include "mozilla/dom/Nullable.h"
-#include "mozilla/dom/WindowProxyHolder.h"
 #include "js/TypeDecls.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsWrapperCache.h"
 #include "nsString.h"
 #include "nsXULElement.h"
 
 class nsIWebNavigation;
 class nsFrameLoader;
 
 namespace mozilla {
 namespace dom {
 
-class BrowsingContext;
-
 class XULFrameElement final : public nsXULElement, public nsIFrameLoaderOwner {
  public:
   explicit XULFrameElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
       : nsXULElement(std::move(aNodeInfo)) {}
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XULFrameElement, nsXULElement)
 
   // XULFrameElement.webidl
-  nsDocShell* GetDocShell();
+  nsIDocShell* GetDocShell();
   already_AddRefed<nsIWebNavigation> GetWebNavigation();
-  Nullable<WindowProxyHolder> GetContentWindow();
+  already_AddRefed<nsPIDOMWindowOuter> GetContentWindow();
   nsIDocument* GetContentDocument();
 
   // nsIFrameLoaderOwner / MozFrameLoaderOwner
   NS_IMETHOD_(already_AddRefed<nsFrameLoader>) GetFrameLoader() override {
     return do_AddRef(mFrameLoader);
   }
 
   NS_IMETHOD_(void)
   InternalSetFrameLoader(nsFrameLoader* aFrameLoader) override {
     mFrameLoader = aFrameLoader;
   }
 
-  void PresetOpenerWindow(const Nullable<WindowProxyHolder>& aWindow,
-                          ErrorResult& aRv) {
-    mOpener = aWindow.IsNull() ? nullptr : aWindow.Value().get();
+  void PresetOpenerWindow(mozIDOMWindowProxy* aWindow, ErrorResult& aRv) {
+    mOpener = do_QueryInterface(aWindow);
   }
 
   void SwapFrameLoaders(mozilla::dom::HTMLIFrameElement& aOtherLoaderOwner,
                         mozilla::ErrorResult& rv);
   void SwapFrameLoaders(XULFrameElement& aOtherLoaderOwner,
                         mozilla::ErrorResult& rv);
   void SwapFrameLoaders(nsIFrameLoaderOwner* aOtherLoaderOwner,
                         mozilla::ErrorResult& rv);
@@ -72,17 +67,17 @@ class XULFrameElement final : public nsX
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
  protected:
   virtual ~XULFrameElement() {}
 
   RefPtr<nsFrameLoader> mFrameLoader;
-  RefPtr<BrowsingContext> mOpener;
+  nsCOMPtr<nsPIDOMWindowOuter> mOpener;
 
   JSObject* WrapNode(JSContext* aCx,
                      JS::Handle<JSObject*> aGivenProto) override;
 
   void LoadSrc();
 };
 
 }  // namespace dom
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -964,17 +964,16 @@ void XPCJSRuntime::CustomGCCallback(JSGC
   // once for each compartment that is being swept.
   CompartmentPrivate* xpcComp = CompartmentPrivate::Get(comp);
   if (xpcComp) {
     xpcComp->UpdateWeakPointersAfterGC();
   }
 }
 
 void CompartmentPrivate::UpdateWeakPointersAfterGC() {
-  mRemoteProxies.sweep();
   mWrappedJSMap->UpdateWeakPointersAfterGC();
 }
 
 void XPCJSRuntime::CustomOutOfMemoryCallback() {
   if (!Preferences::GetBool("memory.dump_reports_on_oom")) {
     return;
   }
 
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2753,35 +2753,18 @@ class CompartmentPrivate {
 
   JSObject2WrappedJSMap* GetWrappedJSMap() const { return mWrappedJSMap; }
   void UpdateWeakPointersAfterGC();
 
   void SystemIsBeingShutDown();
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
 
-  struct SweepPolicy {
-    static bool needsSweep(const void* /* unused */,
-                           JS::Heap<JSObject*>* value) {
-      return JS::GCPolicy<JS::Heap<JSObject*>>::needsSweep(value);
-    }
-  };
-
-  typedef JS::GCHashMap<const void*, JS::Heap<JSObject*>,
-                        mozilla::PointerHasher<const void*>,
-                        js::SystemAllocPolicy, SweepPolicy>
-      RemoteProxyMap;
-  RemoteProxyMap& GetRemoteProxyMap() { return mRemoteProxies; }
-
  private:
   JSObject2WrappedJSMap* mWrappedJSMap;
-
-  // Cache holding proxy objects for Window objects (and their Location oject)
-  // that are loaded in a different process.
-  RemoteProxyMap mRemoteProxies;
 };
 
 bool IsUniversalXPConnectEnabled(JS::Compartment* compartment);
 bool IsUniversalXPConnectEnabled(JSContext* cx);
 bool EnableUniversalXPConnect(JSContext* cx);
 
 inline void CrashIfNotInAutomation() { MOZ_RELEASE_ASSERT(IsInAutomation()); }
 
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -718,25 +718,16 @@ class JSStackFrameBase {
  public:
   virtual void Clear() = 0;
 };
 
 void RegisterJSStackFrame(JS::Realm* aRealm, JSStackFrameBase* aStackFrame);
 void UnregisterJSStackFrame(JS::Realm* aRealm, JSStackFrameBase* aStackFrame);
 void NukeJSStackFrames(JS::Realm* aRealm);
 
-// Check whether the given jsid is a property name (string or symbol) whose
-// value can be gotten cross-origin.  Cross-origin gets always return undefined
-// as the value, unless the Xray actually provides a different value.
-bool IsCrossOriginWhitelistedProp(JSContext* cx, JS::HandleId id);
-
-// Appends to props the jsids for property names (strings or symbols) whose
-// value can be gotten cross-origin.
-bool AppendCrossOriginWhitelistedPropNames(JSContext* cx,
-                                           JS::AutoIdVector& props);
 }  // namespace xpc
 
 namespace mozilla {
 namespace dom {
 
 /**
  * A test for whether WebIDL methods that should only be visible to
  * chrome or XBL scopes should be exposed.
--- a/js/xpconnect/wrappers/FilteringWrapper.cpp
+++ b/js/xpconnect/wrappers/FilteringWrapper.cpp
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "FilteringWrapper.h"
 #include "AccessCheck.h"
 #include "ChromeObjectWrapper.h"
 #include "XrayWrapper.h"
 #include "nsJSUtils.h"
 #include "mozilla/ErrorResult.h"
-#include "xpcpublic.h"
 
 #include "jsapi.h"
 #include "js/Symbol.h"
 
 using namespace JS;
 using namespace js;
 
 namespace xpc {
@@ -39,47 +38,16 @@ static bool IsCrossOriginWhitelistedSymb
   return false;
 }
 
 bool IsCrossOriginWhitelistedProp(JSContext* cx, JS::HandleId id) {
   return id == GetJSIDByIndex(cx, XPCJSContext::IDX_THEN) ||
          IsCrossOriginWhitelistedSymbol(cx, id);
 }
 
-bool AppendCrossOriginWhitelistedPropNames(JSContext* cx,
-                                           JS::AutoIdVector& props) {
-  // Add "then" if it's not already in the list.
-  AutoIdVector thenProp(cx);
-  if (!thenProp.append(GetJSIDByIndex(cx, XPCJSContext::IDX_THEN))) {
-    return false;
-  }
-
-  if (!AppendUnique(cx, props, thenProp)) {
-    return false;
-  }
-
-  // Now add the three symbol-named props cross-origin objects have.
-#ifdef DEBUG
-  for (size_t n = 0; n < props.length(); ++n) {
-    MOZ_ASSERT(!JSID_IS_SYMBOL(props[n]),
-               "Unexpected existing symbol-name prop");
-  }
-#endif
-  if (!props.reserve(props.length() +
-                     ArrayLength(sCrossOriginWhitelistedSymbolCodes))) {
-    return false;
-  }
-
-  for (auto code : sCrossOriginWhitelistedSymbolCodes) {
-    props.infallibleAppend(SYMBOL_TO_JSID(JS::GetWellKnownSymbol(cx, code)));
-  }
-
-  return true;
-}
-
 template <typename Policy>
 static bool Filter(JSContext* cx, HandleObject wrapper, AutoIdVector& props) {
   size_t w = 0;
   RootedId id(cx);
   for (size_t n = 0; n < props.length(); ++n) {
     id = props[n];
     if (Policy::check(cx, wrapper, id, Wrapper::GET) ||
         Policy::check(cx, wrapper, id, Wrapper::SET)) {
@@ -288,17 +256,43 @@ bool CrossOriginXrayWrapper::ownProperty
                                              JS::AutoIdVector& props) const {
   // All properties on cross-origin objects are supposed |own|, despite what
   // the underlying native object may report. Override the inherited trap to
   // avoid passing JSITER_OWNONLY as a flag.
   if (!SecurityXrayDOM::getPropertyKeys(cx, wrapper, JSITER_HIDDEN, props)) {
     return false;
   }
 
-  return AppendCrossOriginWhitelistedPropNames(cx, props);
+  // Add "then" if it's not already in the list.
+  AutoIdVector thenProp(cx);
+  if (!thenProp.append(GetJSIDByIndex(cx, XPCJSContext::IDX_THEN))) {
+    return false;
+  }
+
+  if (!AppendUnique(cx, props, thenProp)) {
+    return false;
+  }
+
+  // Now add the three symbol-named props cross-origin objects have.
+#ifdef DEBUG
+  for (size_t n = 0; n < props.length(); ++n) {
+    MOZ_ASSERT(!JSID_IS_SYMBOL(props[n]),
+               "Unexpected existing symbol-name prop");
+  }
+#endif
+  if (!props.reserve(props.length() +
+                     ArrayLength(sCrossOriginWhitelistedSymbolCodes))) {
+    return false;
+  }
+
+  for (auto code : sCrossOriginWhitelistedSymbolCodes) {
+    props.infallibleAppend(SYMBOL_TO_JSID(JS::GetWellKnownSymbol(cx, code)));
+  }
+
+  return true;
 }
 
 bool CrossOriginXrayWrapper::defineProperty(JSContext* cx,
                                             JS::Handle<JSObject*> wrapper,
                                             JS::Handle<jsid> id,
                                             JS::Handle<PropertyDescriptor> desc,
                                             JS::ObjectOpResult& result) const {
   AccessCheck::reportCrossOriginDenial(cx, id, NS_LITERAL_CSTRING("define"));
--- a/js/xpconnect/wrappers/FilteringWrapper.h
+++ b/js/xpconnect/wrappers/FilteringWrapper.h
@@ -80,11 +80,16 @@ class CrossOriginXrayWrapper : public Se
       JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
       JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
 
   virtual bool setPrototype(JSContext* cx, JS::HandleObject wrapper,
                             JS::HandleObject proto,
                             JS::ObjectOpResult& result) const override;
 };
 
+// Check whether the given jsid is a property name (string or symbol) whose
+// value can be gotten cross-origin.  Cross-origin gets always return undefined
+// as the value, unless the Xray actually provides a different value.
+bool IsCrossOriginWhitelistedProp(JSContext* cx, JS::HandleId id);
+
 }  // namespace xpc
 
 #endif /* __FilteringWrapper_h__ */
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -17,17 +17,16 @@
 #include "xpcprivate.h"
 
 #include "jsapi.h"
 #include "nsJSUtils.h"
 #include "nsPrintfCString.h"
 
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "mozilla/dom/XrayExpandoClass.h"
 #include "nsGlobalWindow.h"
 
 using namespace mozilla::dom;
 using namespace JS;
 using namespace mozilla;
 
@@ -1923,19 +1922,18 @@ bool XrayWrapper<Base, Traits>::getPrope
   // only relevant for CrossOriginXrayWrapper, which calls
   // getPropertyDescriptor from getOwnPropertyDescriptor.
   nsGlobalWindowInner* win = nullptr;
   if (!desc.object() && JSID_IS_STRING(id) && (win = AsWindow(cx, wrapper))) {
     nsAutoJSString name;
     if (!name.init(cx, JSID_TO_STRING(id))) {
       return false;
     }
-    RefPtr<BrowsingContext> childDOMWin(win->GetChildWindow(name));
-    if (childDOMWin) {
-      auto* cwin = nsGlobalWindowOuter::Cast(childDOMWin->GetDOMWindow());
+    if (nsCOMPtr<nsPIDOMWindowOuter> childDOMWin = win->GetChildWindow(name)) {
+      auto* cwin = nsGlobalWindowOuter::Cast(childDOMWin);
       JSObject* childObj = cwin->FastGetGlobalJSObject();
       if (MOZ_UNLIKELY(!childObj)) {
         return xpc::Throw(cx, NS_ERROR_FAILURE);
       }
       ExposeObjectToActiveJS(childObj);
       FillPropertyDescriptor(desc, wrapper, ObjectValue(*childObj),
                              /* readOnly = */ true);
       return JS_WrapPropertyDescriptor(cx, desc);
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -418,22 +418,23 @@ nsresult PeerConnectionImpl::Initialize(
   NS_ENSURE_STATE(mWindow);
 
   PRTime timestamp = PR_Now();
   // Ok if we truncate this.
   char temp[128];
 
   nsAutoCString locationCStr;
 
-  RefPtr<Location> location = mWindow->Location();
-  nsAutoString locationAStr;
-  res = location->ToString(locationAStr);
-  NS_ENSURE_SUCCESS(res, res);
-
-  CopyUTF16toUTF8(locationAStr, locationCStr);
+  if (RefPtr<Location> location = mWindow->GetLocation()) {
+    nsAutoString locationAStr;
+    res = location->ToString(locationAStr);
+    NS_ENSURE_SUCCESS(res, res);
+
+    CopyUTF16toUTF8(locationAStr, locationCStr);
+  }
 
   SprintfLiteral(temp, "%" PRIu64 " (id=%" PRIu64 " url=%s)",
                  static_cast<uint64_t>(timestamp),
                  static_cast<uint64_t>(mWindow ? mWindow->WindowID() : 0),
                  locationCStr.get() ? locationCStr.get() : "NULL");
 
   mName = temp;
 
--- a/toolkit/components/antitracking/AntiTrackingCommon.cpp
+++ b/toolkit/components/antitracking/AntiTrackingCommon.cpp
@@ -355,17 +355,17 @@ already_AddRefed<nsPIDOMWindowOuter> Get
   nsIChannel* channel = document->GetChannel();
   if (!channel) {
     return nullptr;
   }
 
   nsCOMPtr<nsPIDOMWindowOuter> pwin;
   auto* outer = nsGlobalWindowOuter::Cast(aWindow->GetOuterWindow());
   if (outer) {
-    pwin = outer->GetScriptableTop();
+    pwin = outer->GetTopOuter();
   }
 
   if (!pwin) {
     return nullptr;
   }
 
   return pwin.forget();
 }
--- a/toolkit/components/extensions/ExtensionPolicyService.cpp
+++ b/toolkit/components/extensions/ExtensionPolicyService.cpp
@@ -14,17 +14,16 @@
 #include "mozilla/Services.h"
 #include "mozilla/SimpleEnumerator.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentFrameMessageManager.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/Promise-inl.h"
 #include "mozIExtensionProcessScript.h"
-#include "nsDocShell.h"
 #include "nsEscape.h"
 #include "nsGkAtoms.h"
 #include "nsIChannel.h"
 #include "nsIContentPolicy.h"
 #include "nsIDocShell.h"
 #include "nsIDocument.h"
 #include "nsGlobalWindowOuter.h"
 #include "nsILoadInfo.h"
--- a/toolkit/components/extensions/WebExtensionContentScript.h
+++ b/toolkit/components/extensions/WebExtensionContentScript.h
@@ -8,17 +8,16 @@
 
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/WebExtensionContentScriptBinding.h"
 
 #include "jspubtd.h"
 
 #include "mozilla/Maybe.h"
 #include "mozilla/Variant.h"
-#include "mozilla/dom/WindowProxyHolder.h"
 #include "mozilla/extensions/MatchGlob.h"
 #include "mozilla/extensions/MatchPattern.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsISupports.h"
 #include "nsIDocShell.h"
 #include "nsWrapperCache.h"
 
@@ -109,18 +108,18 @@ class MozDocumentMatcher : public nsISup
       ErrorResult& aRv);
 
   bool Matches(const DocInfo& aDoc) const;
   bool MatchesURI(const URLInfo& aURL) const;
 
   bool MatchesLoadInfo(const URLInfo& aURL, nsILoadInfo* aLoadInfo) const {
     return Matches({aURL, aLoadInfo});
   }
-  bool MatchesWindow(const dom::WindowProxyHolder& aWindow) const {
-    return Matches(aWindow.get()->GetDOMWindow());
+  bool MatchesWindow(nsPIDOMWindowOuter* aWindow) const {
+    return Matches(aWindow);
   }
 
   WebExtensionPolicy* GetExtension() { return mExtension; }
 
   WebExtensionPolicy* Extension() { return mExtension; }
   const WebExtensionPolicy* Extension() const { return mExtension; }
 
   bool AllFrames() const { return mAllFrames; }
--- a/toolkit/components/extensions/WebExtensionPolicy.cpp
+++ b/toolkit/components/extensions/WebExtensionPolicy.cpp
@@ -440,23 +440,22 @@ void WebExtensionPolicy::GetContentScrip
   aScripts.AppendElements(mContentScripts);
 }
 
 bool WebExtensionPolicy::CanAccessContext(nsILoadContext* aContext) const {
   MOZ_ASSERT(aContext);
   return mPrivateBrowsingAllowed || !aContext->UsePrivateBrowsing();
 }
 
-bool WebExtensionPolicy::CanAccessWindow(
-    const dom::WindowProxyHolder& aWindow) const {
+bool WebExtensionPolicy::CanAccessWindow(nsPIDOMWindowOuter* aWindow) const {
   if (mPrivateBrowsingAllowed) {
     return true;
   }
   // match browsing mode with policy
-  nsIDocShell* docShell = aWindow.get()->GetDocShell();
+  nsIDocShell* docShell = aWindow->GetDocShell();
   nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
   return !(loadContext && loadContext->UsePrivateBrowsing());
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebExtensionPolicy, mParent,
                                       mLocalizeCallback, mHostPermissions,
                                       mWebAccessiblePaths, mContentScripts)
 
@@ -670,18 +669,17 @@ void DocumentObserver::Observe(
 
 void DocumentObserver::Disconnect() {
   Unused << EPS().UnregisterObserver(*this);
 }
 
 void DocumentObserver::NotifyMatch(MozDocumentMatcher& aMatcher,
                                    nsPIDOMWindowOuter* aWindow) {
   IgnoredErrorResult rv;
-  mCallbacks->OnNewDocument(
-      aMatcher, WindowProxyHolder(aWindow->GetBrowsingContext()), rv);
+  mCallbacks->OnNewDocument(aMatcher, aWindow, rv);
 }
 
 void DocumentObserver::NotifyMatch(MozDocumentMatcher& aMatcher,
                                    nsILoadInfo* aLoadInfo) {
   IgnoredErrorResult rv;
   mCallbacks->OnPreloadDocument(aMatcher, aLoadInfo, rv);
 }
 
--- a/toolkit/components/extensions/WebExtensionPolicy.h
+++ b/toolkit/components/extensions/WebExtensionPolicy.h
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_extensions_WebExtensionPolicy_h
 #define mozilla_extensions_WebExtensionPolicy_h
 
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/Nullable.h"
 #include "mozilla/dom/WebExtensionPolicyBinding.h"
-#include "mozilla/dom/WindowProxyHolder.h"
 #include "mozilla/extensions/MatchPattern.h"
 
 #include "jspubtd.h"
 
 #include "mozilla/Result.h"
 #include "mozilla/WeakPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
@@ -124,17 +123,17 @@ class WebExtensionPolicy final : public 
 
   bool PrivateBrowsingAllowed() const { return mPrivateBrowsingAllowed; }
   void SetPrivateBrowsingAllowed(bool aPrivateBrowsingAllowed) {
     mPrivateBrowsingAllowed = aPrivateBrowsingAllowed;
   };
 
   bool CanAccessContext(nsILoadContext* aContext) const;
 
-  bool CanAccessWindow(const dom::WindowProxyHolder& aWindow) const;
+  bool CanAccessWindow(nsPIDOMWindowOuter* aWindow) const;
 
   static void GetActiveExtensions(
       dom::GlobalObject& aGlobal,
       nsTArray<RefPtr<WebExtensionPolicy>>& aResults);
 
   static already_AddRefed<WebExtensionPolicy> GetByID(
       dom::GlobalObject& aGlobal, const nsAString& aID);
 
--- a/toolkit/components/sessionstore/nsSessionStoreUtils.cpp
+++ b/toolkit/components/sessionstore/nsSessionStoreUtils.cpp
@@ -40,17 +40,17 @@ class DynamicFrameEventFilter final : pu
   ~DynamicFrameEventFilter() {}
 
   bool TargetInNonDynamicDocShell(Event* aEvent) {
     EventTarget* target = aEvent->GetTarget();
     if (!target) {
       return false;
     }
 
-    nsPIDOMWindowOuter* outer = target->GetOwnerGlobalForBindingsInternal();
+    nsPIDOMWindowOuter* outer = target->GetOwnerGlobalForBindings();
     if (!outer) {
       return false;
     }
 
     nsIDocShell* docShell = outer->GetDocShell();
     if (!docShell) {
       return false;
     }
--- a/xpfe/appshell/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/nsContentTreeOwner.cpp
@@ -28,17 +28,16 @@
 #include "nsIWebNavigation.h"
 #include "nsDocShellCID.h"
 #include "nsIExternalURLHandlerService.h"
 #include "nsIMIMEInfo.h"
 #include "nsIWidget.h"
 #include "nsWindowWatcher.h"
 #include "mozilla/BrowserElementParent.h"
 #include "mozilla/NullPrincipal.h"
-#include "nsDocShell.h"
 #include "nsDocShellLoadState.h"
 
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIURI.h"
 #include "nsIDocument.h"
 #if defined(XP_MACOSX)
 #include "nsThreadUtils.h"
 #endif
@@ -700,19 +699,17 @@ NS_IMETHODIMP
 nsContentTreeOwner::ProvideWindow(
     mozIDOMWindowProxy* aParent, uint32_t aChromeFlags, bool aCalledFromJS,
     bool aPositionSpecified, bool aSizeSpecified, nsIURI* aURI,
     const nsAString& aName, const nsACString& aFeatures, bool aForceNoOpener,
     nsDocShellLoadState* aLoadState, bool* aWindowIsNew,
     mozIDOMWindowProxy** aReturn) {
   NS_ENSURE_ARG_POINTER(aParent);
 
-  auto* parentWin = nsPIDOMWindowOuter::From(aParent);
-  dom::BrowsingContext* parent =
-      parentWin ? parentWin->GetBrowsingContext() : nullptr;
+  auto* parent = nsPIDOMWindowOuter::From(aParent);
 
   *aReturn = nullptr;
 
   if (!mXULWindow) {
     // Nothing to do here
     return NS_OK;
   }
 
@@ -757,18 +754,17 @@ nsContentTreeOwner::ProvideWindow(
           info->LaunchWithURI(aURI, nullptr);
           return NS_ERROR_ABORT;
         }
       }
     }
   }
 
   int32_t openLocation = nsWindowWatcher::GetWindowOpenLocation(
-      parentWin, aChromeFlags, aCalledFromJS, aPositionSpecified,
-      aSizeSpecified);
+      parent, aChromeFlags, aCalledFromJS, aPositionSpecified, aSizeSpecified);
 
   if (openLocation != nsIBrowserDOMWindow::OPEN_NEWTAB &&
       openLocation != nsIBrowserDOMWindow::OPEN_CURRENTWINDOW) {
     // Just open a window normally
     return NS_OK;
   }
 
   nsCOMPtr<mozIDOMWindowProxy> domWin;
--- a/xpfe/appshell/nsXULWindow.cpp
+++ b/xpfe/appshell/nsXULWindow.cpp
@@ -2022,17 +2022,17 @@ NS_IMETHODIMP nsXULWindow::CreateNewCont
 
   if (aOpener) {
     nsCOMPtr<nsIDocShell> docShell;
     xulWin->GetDocShell(getter_AddRefs(docShell));
     MOZ_ASSERT(docShell);
     nsCOMPtr<nsPIDOMWindowOuter> window = docShell->GetWindow();
     MOZ_ASSERT(window);
     window->SetOpenerForInitialContentBrowser(
-        nsPIDOMWindowOuter::From(aOpener)->GetBrowsingContext());
+        nsPIDOMWindowOuter::From(aOpener));
   }
 
   xulWin->LockUntilChromeLoad();
 
   {
     AutoNoJSAPI nojsapi;
     SpinEventLoopUntil([&]() { return !xulWin->IsLocked(); });
   }