Bug 888600 - Move ContentFrameMessageManager to WebIDL. Part 5: Convert MessageManager globals to WebIDL. r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Wed, 19 Jul 2017 14:59:02 +0200
changeset 458034 2efb9b1753f63748fa547117c0665e8f3e705e08
parent 458033 af53037819615484e614e7343256f31b237f1bab
child 458035 83c87140dc3da6d521c9380beea85b30cb69c7b5
push id8799
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 16:46:23 +0000
treeherdermozilla-beta@15334014dc67 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs888600
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 888600 - Move ContentFrameMessageManager to WebIDL. Part 5: Convert MessageManager globals to WebIDL. r=bz. The change in browser_net_view-source-debugger.js is needed because we now use WebIDL callbacks for MessageListener, and they add async creation stack frames.
devtools/client/netmonitor/test/browser_net_view-source-debugger.js
dom/base/ContentFrameMessageManager.h
dom/base/MessageManagerGlobal.h
dom/base/ProcessGlobal.cpp
dom/base/ProcessGlobal.h
dom/base/moz.build
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsDOMClassInfoID.h
dom/base/nsFrameLoader.cpp
dom/base/nsFrameLoader.h
dom/base/nsFrameMessageManager.cpp
dom/base/nsFrameMessageManager.h
dom/base/nsInProcessTabChildGlobal.cpp
dom/base/nsInProcessTabChildGlobal.h
dom/base/nsWrapperCache.h
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/bindings/Bindings.conf
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/webidl/LegacyQueryInterface.webidl
dom/webidl/MessageManager.webidl
--- a/devtools/client/netmonitor/test/browser_net_view-source-debugger.js
+++ b/devtools/client/netmonitor/test/browser_net_view-source-debugger.js
@@ -18,17 +18,17 @@ add_task(async function () {
   store.dispatch(Actions.batchEnable(false));
 
   let waitForContentRequests = waitForNetworkEvents(monitor, 2);
   await ContentTask.spawn(tab.linkedBrowser, {},
     () => content.wrappedJSObject.performRequests());
   await waitForContentRequests;
 
   info("Clicking stack-trace tab and waiting for stack-trace panel to open");
-  let wait = waitForDOM(document, "#stack-trace-panel .frame-link", 4);
+  let wait = waitForDOM(document, "#stack-trace-panel .frame-link", 5);
   // Click on the first request
   EventUtils.sendMouseEvent({ type: "mousedown" },
     document.querySelector(".request-list-item"));
   // Open the stack-trace tab for that request
   document.getElementById("stack-trace-tab").click();
   await wait;
 
   let frameLinkNode = document.querySelector(".frame-link");
new file mode 100644
--- /dev/null
+++ b/dom/base/ContentFrameMessageManager.h
@@ -0,0 +1,95 @@
+/* -*- 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_ContentFrameMessageManager_h
+#define mozilla_dom_ContentFrameMessageManager_h
+
+#include "mozilla/DOMEventTargetHelper.h"
+#include "mozilla/dom/MessageManagerGlobal.h"
+#include "mozilla/dom/ResolveSystemBinding.h"
+#include "nsContentUtils.h"
+
+namespace mozilla {
+namespace dom {
+
+/**
+ * Base class for implementing the WebIDL ContentFrameMessageManager class.
+ */
+class ContentFrameMessageManager : public DOMEventTargetHelper,
+                                   public MessageManagerGlobal
+{
+public:
+  using DOMEventTargetHelper::AddRef;
+  using DOMEventTargetHelper::Release;
+
+  bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
+                 JS::Handle<jsid> aId,
+                 JS::MutableHandle<JS::PropertyDescriptor> aDesc)
+  {
+    bool found;
+    if (!SystemGlobalResolve(aCx, aObj, aId, &found)) {
+      return false;
+    }
+    if (found) {
+      FillPropertyDescriptor(aDesc, aObj, JS::UndefinedValue(), false);
+    }
+    return true;
+  }
+  static bool MayResolve(jsid aId)
+  {
+    return MayResolveAsSystemBindingName(aId);
+  }
+  void GetOwnPropertyNames(JSContext* aCx, JS::AutoIdVector& aNames,
+                           bool aEnumerableOnly, mozilla::ErrorResult& aRv)
+  {
+    JS::Rooted<JSObject*> thisObj(aCx, GetWrapper());
+    GetSystemBindingNames(aCx, thisObj, aNames, aEnumerableOnly, aRv);
+  }
+
+  nsresult AddEventListener(const nsAString& aType,
+                            nsIDOMEventListener* aListener,
+                            bool aUseCapture)
+  {
+    // By default add listeners only for trusted events!
+    return DOMEventTargetHelper::AddEventListener(aType, aListener,
+                                                  aUseCapture, false, 2);
+  }
+  using DOMEventTargetHelper::AddEventListener;
+  NS_IMETHOD AddEventListener(const nsAString& aType,
+                              nsIDOMEventListener* aListener,
+                              bool aUseCapture, bool aWantsUntrusted,
+                              uint8_t optional_argc) override
+  {
+    return DOMEventTargetHelper::AddEventListener(aType, aListener,
+                                                  aUseCapture,
+                                                  aWantsUntrusted,
+                                                  optional_argc);
+  }
+
+  virtual already_AddRefed<nsPIDOMWindowOuter> GetContent(ErrorResult& aError) = 0;
+  virtual already_AddRefed<nsIDocShell> GetDocShell(ErrorResult& aError) = 0;
+  virtual already_AddRefed<nsIEventTarget> GetTabEventTarget() = 0;
+
+  nsFrameMessageManager* GetMessageManager()
+  {
+    return mMessageManager;
+  }
+  void DisconnectMessageManager()
+  {
+    mMessageManager->Disconnect();
+    mMessageManager = nullptr;
+  }
+
+protected:
+  explicit ContentFrameMessageManager(nsFrameMessageManager* aMessageManager)
+    : MessageManagerGlobal(aMessageManager)
+  {}
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_ContentFrameMessageManager_h
new file mode 100644
--- /dev/null
+++ b/dom/base/MessageManagerGlobal.h
@@ -0,0 +1,181 @@
+/* -*- 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_MessageManagerGlobal_h
+#define mozilla_dom_MessageManagerGlobal_h
+
+#include "nsFrameMessageManager.h"
+#include "mozilla/ErrorResult.h"
+
+namespace mozilla {
+namespace dom {
+
+/**
+ * Base class for implementing the WebIDL MessageManagerGlobal class.
+ */
+class MessageManagerGlobal
+{
+public:
+  // MessageListenerManager
+  void AddMessageListener(const nsAString& aMessageName,
+                          MessageListener& aListener,
+                          bool aListenWhenClosed,
+                          ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return;
+    }
+    mMessageManager->AddMessageListener(aMessageName, aListener,
+                                        aListenWhenClosed, aError);
+  }
+  void RemoveMessageListener(const nsAString& aMessageName,
+                             MessageListener& aListener,
+                             ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return;
+    }
+    mMessageManager->RemoveMessageListener(aMessageName, aListener, aError);
+  }
+  void AddWeakMessageListener(const nsAString& aMessageName,
+                              MessageListener& aListener,
+                              ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return;
+    }
+    mMessageManager->AddWeakMessageListener(aMessageName, aListener, aError);
+  }
+  void RemoveWeakMessageListener(const nsAString& aMessageName,
+                                 MessageListener& aListener,
+                                 ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return;
+    }
+    mMessageManager->RemoveWeakMessageListener(aMessageName, aListener, aError);
+  }
+
+  // MessageSender
+  void SendAsyncMessage(JSContext* aCx, const nsAString& aMessageName,
+                        JS::Handle<JS::Value> aObj,
+                        JS::Handle<JSObject*> aObjects,
+                        nsIPrincipal* aPrincipal,
+                        JS::Handle<JS::Value> aTransfers,
+                        ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return;
+    }
+    mMessageManager->SendAsyncMessage(aCx, aMessageName, aObj, aObjects,
+                                      aPrincipal, aTransfers, aError);
+  }
+  already_AddRefed<nsIMessageSender> GetProcessMessageManager(mozilla::ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return nullptr;
+    }
+    return mMessageManager->GetProcessMessageManager(aError);
+  }
+
+  void GetRemoteType(nsAString& aRemoteType, mozilla::ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return;
+    }
+    mMessageManager->GetRemoteType(aRemoteType, aError);
+  }
+
+  // SyncMessageSender
+  void SendSyncMessage(JSContext* aCx, const nsAString& aMessageName,
+                       JS::Handle<JS::Value> aObj,
+                       JS::Handle<JSObject*> aObjects,
+                       nsIPrincipal* aPrincipal,
+                       nsTArray<JS::Value>& aResult,
+                       ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return;
+    }
+    mMessageManager->SendSyncMessage(aCx, aMessageName, aObj, aObjects,
+                                     aPrincipal, aResult, aError);
+  }
+  void SendRpcMessage(JSContext* aCx, const nsAString& aMessageName,
+                      JS::Handle<JS::Value> aObj,
+                      JS::Handle<JSObject*> aObjects,
+                      nsIPrincipal* aPrincipal,
+                      nsTArray<JS::Value>& aResult,
+                      ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return;
+    }
+    mMessageManager->SendRpcMessage(aCx, aMessageName, aObj, aObjects,
+                                    aPrincipal, aResult, aError);
+  }
+
+  // MessageManagerGlobal
+  void Dump(const nsAString& aStr, ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return;
+    }
+    aError = mMessageManager->Dump(aStr);
+  }
+  void PrivateNoteIntentionalCrash(ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return;
+    }
+    aError = mMessageManager->PrivateNoteIntentionalCrash();
+  }
+  void Atob(const nsAString& aAsciiString, nsAString& aBase64Data,
+            ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return;
+    }
+    aError = mMessageManager->Atob(aAsciiString, aBase64Data);
+  }
+  void Btoa(const nsAString& aBase64Data, nsAString& aAsciiString,
+            ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return;
+    }
+    aError = mMessageManager->Btoa(aBase64Data, aAsciiString);
+  }
+
+  bool MarkForCC()
+  {
+    return mMessageManager && mMessageManager->MarkForCC();
+  }
+
+protected:
+  explicit MessageManagerGlobal(nsFrameMessageManager* aMessageManager)
+    : mMessageManager(aMessageManager)
+  {}
+
+  RefPtr<nsFrameMessageManager> mMessageManager;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_MessageManagerGlobal_h
--- a/dom/base/ProcessGlobal.cpp
+++ b/dom/base/ProcessGlobal.cpp
@@ -2,53 +2,82 @@
 /* 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 "ProcessGlobal.h"
 
 #include "nsContentCID.h"
-#include "nsDOMClassInfoID.h"
-#include "mozilla/HoldDropJSObjects.h"
+#include "mozilla/dom/MessageManagerBinding.h"
+#include "mozilla/dom/ResolveSystemBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 ProcessGlobal::ProcessGlobal(nsFrameMessageManager* aMessageManager)
- : mInitialized(false),
-   mMessageManager(aMessageManager)
+ : MessageManagerGlobal(aMessageManager),
+   mInitialized(false)
 {
-  SetIsNotDOMBinding();
   mozilla::HoldJSObjects(this);
 }
 
 ProcessGlobal::~ProcessGlobal()
 {
   mAnonymousGlobalScopes.Clear();
   mozilla::DropJSObjects(this);
 }
 
+bool
+ProcessGlobal::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
+                         JS::Handle<jsid> aId,
+                         JS::MutableHandle<JS::PropertyDescriptor> aDesc)
+{
+    bool found;
+    if (!SystemGlobalResolve(aCx, aObj, aId, &found)) {
+      return false;
+    }
+    if (found) {
+      FillPropertyDescriptor(aDesc, aObj, JS::UndefinedValue(), false);
+    }
+    return true;
+}
+
+/* static */
+bool
+ProcessGlobal::MayResolve(jsid aId)
+{
+  return MayResolveAsSystemBindingName(aId);
+}
+
+void
+ProcessGlobal::GetOwnPropertyNames(JSContext* aCx, JS::AutoIdVector& aNames,
+                                   bool aEnumerableOnly, ErrorResult& aRv)
+{
+  JS::Rooted<JSObject*> thisObj(aCx, GetWrapper());
+  GetSystemBindingNames(aCx, thisObj, aNames, aEnumerableOnly, aRv);
+}
+
 ProcessGlobal*
 ProcessGlobal::Get()
 {
   nsCOMPtr<nsISyncMessageSender> service = do_GetService(NS_CHILDPROCESSMESSAGEMANAGER_CONTRACTID);
   if (!service) {
     return nullptr;
   }
   return static_cast<ProcessGlobal*>(service.get());
 }
 
 // This method isn't automatically forwarded safely because it's notxpcom, so
 // the IDL binding doesn't know what value to return.
 NS_IMETHODIMP_(bool)
 ProcessGlobal::MarkForCC()
 {
   MarkScopesForCC();
-  return mMessageManager ? mMessageManager->MarkForCC() : false;
+  return MessageManagerGlobal::MarkForCC();
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(ProcessGlobal)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ProcessGlobal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
   tmp->TraverseHostObjectURIs(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -70,38 +99,52 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentProcessMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
   NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsIContentProcessMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentProcessMessageManager)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(ProcessGlobal)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(ProcessGlobal)
 
 bool
 ProcessGlobal::Init()
 {
   if (mInitialized) {
     return true;
   }
   mInitialized = true;
 
-  nsISupports* scopeSupports = NS_ISUPPORTS_CAST(nsIContentProcessMessageManager*, this);
-  return InitChildGlobalInternal(scopeSupports, NS_LITERAL_CSTRING("processChildGlobal"));
+  return InitChildGlobalInternal(NS_LITERAL_CSTRING("processChildGlobal"));
+}
+
+bool
+ProcessGlobal::WrapGlobalObject(JSContext* aCx,
+                                JS::CompartmentOptions& aOptions,
+                                JS::MutableHandle<JSObject*> aReflector)
+{
+  bool ok = ContentProcessMessageManagerBinding::Wrap(aCx, this, this, aOptions,
+                                                      nsJSPrincipals::get(mPrincipal),
+                                                      true, aReflector);
+  if (ok) {
+    // Since we can't rewrap we have to preserve the global's wrapper here.
+    PreserveWrapper(ToSupports(this));
+  }
+  return ok;
 }
 
 void
 ProcessGlobal::LoadScript(const nsAString& aURL)
 {
   Init();
-  LoadScriptInternal(aURL, false);
+  JS::Rooted<JSObject*> global(mozilla::dom::RootingCx(), GetWrapper());
+  LoadScriptInternal(global, aURL, false);
 }
 
 void
 ProcessGlobal::SetInitialProcessData(JS::HandleValue aInitialData)
 {
   mMessageManager->SetInitialProcessData(aInitialData);
 }
--- a/dom/base/ProcessGlobal.h
+++ b/dom/base/ProcessGlobal.h
@@ -3,16 +3,17 @@
 /* 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_ProcessGlobal_h
 #define mozilla_dom_ProcessGlobal_h
 
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/MessageManagerGlobal.h"
 #include "nsCOMPtr.h"
 #include "nsFrameMessageManager.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsIClassInfo.h"
 #include "nsIRunnable.h"
 #include "nsIGlobalObject.h"
@@ -20,61 +21,98 @@
 #include "nsServiceManagerUtils.h"
 #include "nsWeakReference.h"
 #include "nsWrapperCache.h"
 
 namespace mozilla {
 namespace dom {
 
 class ProcessGlobal :
+  public nsIContentProcessMessageManager,
   public nsMessageManagerScriptExecutor,
-  public nsIContentProcessMessageManager,
   public nsIGlobalObject,
   public nsIScriptObjectPrincipal,
   public nsSupportsWeakReference,
-  public mozilla::dom::ipc::MessageManagerCallback,
+  public ipc::MessageManagerCallback,
+  public MessageManagerGlobal,
   public nsWrapperCache
 {
 public:
   explicit ProcessGlobal(nsFrameMessageManager* aMessageManager);
 
-  using mozilla::dom::ipc::MessageManagerCallback::GetProcessMessageManager;
+  bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
+                 JS::Handle<jsid> aId,
+                 JS::MutableHandle<JS::PropertyDescriptor> aDesc);
+  static bool MayResolve(jsid aId);
+  void GetOwnPropertyNames(JSContext* aCx, JS::AutoIdVector& aNames,
+                           bool aEnumerableOnly, ErrorResult& aRv);
+
+  using ipc::MessageManagerCallback::GetProcessMessageManager;
 
   bool Init();
 
   static ProcessGlobal* Get();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(ProcessGlobal, nsIContentProcessMessageManager)
 
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aGivenProto) override
+  {
+    MOZ_CRASH("We should never get here!");
+  }
+  virtual bool WrapGlobalObject(JSContext* aCx,
+                                JS::CompartmentOptions& aOptions,
+                                JS::MutableHandle<JSObject*> aReflector) override;
+
+  using MessageManagerGlobal::AddMessageListener;
+  using MessageManagerGlobal::RemoveMessageListener;
+  using MessageManagerGlobal::AddWeakMessageListener;
+  using MessageManagerGlobal::RemoveWeakMessageListener;
+  using MessageManagerGlobal::SendAsyncMessage;
+  using MessageManagerGlobal::GetProcessMessageManager;
+  using MessageManagerGlobal::GetRemoteType;
+  using MessageManagerGlobal::SendSyncMessage;
+  using MessageManagerGlobal::SendRpcMessage;
+  using MessageManagerGlobal::Dump;
+  using MessageManagerGlobal::PrivateNoteIntentionalCrash;
+  using MessageManagerGlobal::Atob;
+  using MessageManagerGlobal::Btoa;
+
+  // ContentProcessMessageManager
+  void GetInitialProcessData(JSContext* aCx,
+                             JS::MutableHandle<JS::Value> aInitialProcessData,
+                             ErrorResult& aError)
+  {
+    if (!mMessageManager) {
+      aError.Throw(NS_ERROR_NULL_POINTER);
+      return;
+    }
+    mMessageManager->GetInitialProcessData(aCx, aInitialProcessData, aError);
+  }
+
   NS_FORWARD_SAFE_NSIMESSAGELISTENERMANAGER(mMessageManager)
   NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
   NS_FORWARD_SAFE_NSISYNCMESSAGESENDER(mMessageManager)
   NS_FORWARD_SAFE_NSIMESSAGEMANAGERGLOBAL(mMessageManager)
   NS_FORWARD_SAFE_NSICONTENTPROCESSMESSAGEMANAGER(mMessageManager)
 
   virtual void LoadScript(const nsAString& aURL);
 
   virtual JSObject* GetGlobalJSObject() override
   {
-    return mGlobal;
+    return GetWrapper();
   }
   virtual nsIPrincipal* GetPrincipal() override { return mPrincipal; }
 
-  virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override
-  {
-    MOZ_CRASH("ProcessGlobal doesn't use DOM bindings!");
-  }
-
   void SetInitialProcessData(JS::HandleValue aInitialData);
 
 protected:
   virtual ~ProcessGlobal();
 
 private:
   bool mInitialized;
-  RefPtr<nsFrameMessageManager> mMessageManager;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_ProcessGlobal_h
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -157,16 +157,17 @@ EXPORTS.mozilla.dom += [
     'BorrowedAttrInfo.h',
     'ChildIterator.h',
     'ChildProcessMessageManager.h',
     'ChromeMessageBroadcaster.h',
     'ChromeMessageSender.h',
     'ChromeNodeList.h',
     'ChromeUtils.h',
     'Comment.h',
+    'ContentFrameMessageManager.h',
     'CustomElementRegistry.h',
     'DirectionalityUtils.h',
     'DispatcherTrait.h',
     'DocGroup.h',
     'DocumentFragment.h',
     'DocumentOrShadowRoot.h',
     'DocumentType.h',
     'DOMCursor.h',
@@ -194,16 +195,17 @@ EXPORTS.mozilla.dom += [
     'IdleRequest.h',
     'IDTracker.h',
     'ImageEncoder.h',
     'ImageTracker.h',
     'IntlUtils.h',
     'Link.h',
     'Location.h',
     'MessageListenerManager.h',
+    'MessageManagerGlobal.h',
     'MessageSender.h',
     'NameSpaceConstants.h',
     'Navigator.h',
     'NodeInfo.h',
     'NodeInfoInlines.h',
     'NodeIterator.h',
     'Pose.h',
     'ProcessGlobal.h',
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -68,17 +68,16 @@
 #include "nsIDOMEventTarget.h"
 
 // CSS related includes
 #include "nsMemory.h"
 
 // includes needed for the prototype chain interfaces
 
 #include "nsIEventListenerService.h"
-#include "nsIMessageManager.h"
 
 #include "mozilla/dom/TouchEvent.h"
 
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/dom/HTMLCollectionBinding.h"
 
 #include "nsDebug.h"
 
@@ -126,19 +125,16 @@ using namespace mozilla::dom;
     _allowXBL,                                                                \
     false,                                                                    \
     NS_DEFINE_CLASSINFO_DATA_DEBUG(_class)                                    \
   },
 
 #define NS_DEFINE_CLASSINFO_DATA(_class, _helper, _flags)                     \
   NS_DEFINE_CLASSINFO_DATA_HELPER(_class, _helper, _flags, false, false)
 
-#define NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(_class, _helper, _flags)         \
-  NS_DEFINE_CLASSINFO_DATA_HELPER(_class, _helper, _flags, true, false)
-
 #define NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(_class, _helper, _flags)          \
   NS_DEFINE_CLASSINFO_DATA_HELPER(_class, _helper, _flags, true, true)
 
 
 // This list of NS_DEFINE_CLASSINFO_DATA macros is what gives the DOM
 // classes their correct behavior when used through XPConnect. The
 // arguments that are passed to NS_DEFINE_CLASSINFO_DATA are
 //
@@ -163,27 +159,16 @@ static nsDOMClassInfoData sClassInfoData
                            XPC_SCRIPTABLE_WANT_RESOLVE |
                            XPC_SCRIPTABLE_WANT_HASINSTANCE |
                            XPC_SCRIPTABLE_WANT_CALL |
                            XPC_SCRIPTABLE_WANT_CONSTRUCT |
                            XPC_SCRIPTABLE_DONT_ENUM_QUERY_INTERFACE)
 
   // Misc Core related classes
 
-  NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentFrameMessageManager,
-                                       nsMessageManagerSH<nsEventTargetSH>,
-                                       DOM_DEFAULT_SCRIPTABLE_FLAGS |
-                                       XPC_SCRIPTABLE_WANT_ENUMERATE |
-                                       XPC_SCRIPTABLE_IS_GLOBAL_OBJECT)
-  NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentProcessMessageManager,
-                                       nsMessageManagerSH<nsDOMGenericSH>,
-                                       DOM_DEFAULT_SCRIPTABLE_FLAGS |
-                                       XPC_SCRIPTABLE_WANT_ENUMERATE |
-                                       XPC_SCRIPTABLE_IS_GLOBAL_OBJECT)
-
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULControlElement, nsDOMGenericSH,
                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULLabeledControlElement, nsDOMGenericSH,
                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULButtonElement, nsDOMGenericSH,
                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULCheckboxElement, nsDOMGenericSH,
                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -415,31 +400,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMPrototype, nsIDOMDOMConstructor)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DOMConstructor, nsIDOMDOMConstructor)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentFrameMessageManager, nsISupports)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-    DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager)
-    DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender)
-    DOM_CLASSINFO_MAP_ENTRY(nsISyncMessageSender)
-    DOM_CLASSINFO_MAP_ENTRY(nsIContentFrameMessageManager)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentProcessMessageManager, nsISupports)
-    DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager)
-    DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender)
-    DOM_CLASSINFO_MAP_ENTRY(nsISyncMessageSender)
-    DOM_CLASSINFO_MAP_ENTRY(nsIContentProcessMessageManager)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULControlElement, nsIDOMXULControlElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULControlElement)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULLabeledControlElement, nsIDOMXULLabeledControlElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULLabeledControlElement)
   DOM_CLASSINFO_MAP_END
 
@@ -1897,46 +1867,8 @@ nsDOMConstructorSH::HasInstance(nsIXPCon
     nsCOMPtr<nsIDOMDOMConstructor> is_constructor =
       do_QueryWrappedNative(wrapper);
     NS_ASSERTION(is_constructor, "How did we not get a constructor?");
   }
 #endif
 
   return wrapped->HasInstance(wrapper, cx, obj, val, bp, _retval);
 }
-
-// nsContentFrameMessageManagerSH
-
-template<typename Super>
-NS_IMETHODIMP
-nsMessageManagerSH<Super>::Resolve(nsIXPConnectWrappedNative* wrapper,
-                                   JSContext* cx, JSObject* obj_,
-                                   jsid id_, bool* resolvedp,
-                                   bool* _retval)
-{
-  JS::Rooted<JSObject*> obj(cx, obj_);
-  JS::Rooted<jsid> id(cx, id_);
-
-  *_retval = SystemGlobalResolve(cx, obj, id, resolvedp);
-  NS_ENSURE_TRUE(*_retval, NS_ERROR_FAILURE);
-
-  if (*resolvedp) {
-    return NS_OK;
-  }
-
-  return Super::Resolve(wrapper, cx, obj, id, resolvedp, _retval);
-}
-
-template<typename Super>
-NS_IMETHODIMP
-nsMessageManagerSH<Super>::Enumerate(nsIXPConnectWrappedNative* wrapper,
-                                     JSContext* cx, JSObject* obj_,
-                                     bool* _retval)
-{
-  JS::Rooted<JSObject*> obj(cx, obj_);
-
-  *_retval = SystemGlobalEnumerate(cx, obj);
-  NS_ENSURE_TRUE(*_retval, NS_ERROR_FAILURE);
-
-  // Don't call up to our superclass, since neither nsDOMGenericSH nor
-  // nsEventTargetSH have WANT_ENUMERATE.
-  return NS_OK;
-}
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -207,34 +207,9 @@ public:
                          bool *_retval) override;
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsDOMConstructorSH(aData);
   }
 };
 
-template<typename Super>
-class nsMessageManagerSH : public Super
-{
-protected:
-  explicit nsMessageManagerSH(nsDOMClassInfoData* aData)
-    : Super(aData)
-  {
-  }
-
-  virtual ~nsMessageManagerSH()
-  {
-  }
-public:
-  NS_IMETHOD Resolve(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
-                     JSObject* obj_, jsid id_, bool* resolvedp,
-                     bool* _retval) override;
-  NS_IMETHOD Enumerate(nsIXPConnectWrappedNative* wrapper, JSContext* cx,
-                       JSObject* obj_, bool* _retval) override;
-
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsMessageManagerSH(aData);
-  }
-};
-
 #endif /* nsDOMClassInfo_h___ */
--- a/dom/base/nsDOMClassInfoID.h
+++ b/dom/base/nsDOMClassInfoID.h
@@ -14,19 +14,16 @@
 
 #include "nsIXPCScriptable.h"
 
 enum nsDOMClassInfoID
 {
   eDOMClassInfo_DOMPrototype_id,
   eDOMClassInfo_DOMConstructor_id,
 
-  eDOMClassInfo_ContentFrameMessageManager_id,
-  eDOMClassInfo_ContentProcessMessageManager_id,
-
   eDOMClassInfo_XULControlElement_id,
   eDOMClassInfo_XULLabeledControlElement_id,
   eDOMClassInfo_XULButtonElement_id,
   eDOMClassInfo_XULCheckboxElement_id,
 
   // This one better be the last one in this list
   eDOMClassInfoIDCount
 };
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -1638,24 +1638,22 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
 
   ourWindow->SetFrameElementInternal(otherFrameElement);
   otherWindow->SetFrameElementInternal(ourFrameElement);
 
   RefPtr<nsFrameMessageManager> ourMessageManager = mMessageManager;
   RefPtr<nsFrameMessageManager> otherMessageManager = aOther->mMessageManager;
   // Swap pointers in child message managers.
   if (mChildMessageManager) {
-    nsInProcessTabChildGlobal* tabChild =
-      static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
+    nsInProcessTabChildGlobal* tabChild = mChildMessageManager;
     tabChild->SetOwner(otherContent);
     tabChild->SetChromeMessageManager(otherMessageManager);
   }
   if (aOther->mChildMessageManager) {
-    nsInProcessTabChildGlobal* otherTabChild =
-      static_cast<nsInProcessTabChildGlobal*>(aOther->mChildMessageManager.get());
+    nsInProcessTabChildGlobal* otherTabChild = aOther->mChildMessageManager;
     otherTabChild->SetOwner(ourContent);
     otherTabChild->SetChromeMessageManager(ourMessageManager);
   }
   // Swap and setup things in parent message managers.
   if (mMessageManager) {
     mMessageManager->SetCallback(aOther);
   }
   if (aOther->mMessageManager) {
@@ -1880,29 +1878,29 @@ nsFrameLoader::DestroyDocShell()
   // docshell, and finally destroy the PBrowser actor. This eventually leads to
   // nsFrameLoader::DestroyComplete being called.
   if (mRemoteBrowser) {
     mRemoteBrowser->Destroy();
   }
 
   // Fire the "unload" event if we're in-process.
   if (mChildMessageManager) {
-    static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->FireUnloadEvent();
+    mChildMessageManager->FireUnloadEvent();
   }
 
   // Destroy the docshell.
   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.
-    static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->DisconnectEventListeners();
+    mChildMessageManager->DisconnectEventListeners();
   }
 }
 
 void
 nsFrameLoader::DestroyComplete()
 {
   // We get here, as part of StartDestroy, after the docshell has been destroyed
   // and all message manager messages sent during docshell destruction have been
@@ -1927,17 +1925,17 @@ nsFrameLoader::DestroyComplete()
     mRemoteBrowser = nullptr;
   }
 
   if (mMessageManager) {
     mMessageManager->Disconnect();
   }
 
   if (mChildMessageManager) {
-    static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->Disconnect();
+    mChildMessageManager->Disconnect();
   }
 
   mMessageManager = nullptr;
   mChildMessageManager = nullptr;
 }
 
 NS_IMETHODIMP
 nsFrameLoader::GetDepthTooGreat(bool* aDepthTooGreat)
@@ -2983,22 +2981,21 @@ public:
     : nsSameProcessAsyncMessageBase(aRootingCx, aCpows)
     , mozilla::Runnable("nsAsyncMessageToChild")
     , mFrameLoader(aFrameLoader)
   {
   }
 
   NS_IMETHOD Run() override
   {
-    nsInProcessTabChildGlobal* tabChild =
-      static_cast<nsInProcessTabChildGlobal*>(mFrameLoader->mChildMessageManager.get());
+    nsInProcessTabChildGlobal* tabChild = mFrameLoader->mChildMessageManager;
     // Since bug 1126089, messages can arrive even when the docShell is destroyed.
     // Here we make sure that those messages are not delivered.
     if (tabChild && tabChild->GetInnerManager() && mFrameLoader->GetExistingDocShell()) {
-      JS::Rooted<JSObject*> kungFuDeathGrip(dom::RootingCx(), tabChild->GetGlobal());
+      JS::Rooted<JSObject*> kungFuDeathGrip(dom::RootingCx(), tabChild->GetWrapper());
       ReceiveMessage(static_cast<EventTarget*>(tabChild), mFrameLoader,
                      tabChild->GetInnerManager());
     }
     return NS_OK;
   }
   RefPtr<nsFrameLoader> mFrameLoader;
 };
 
@@ -3136,17 +3133,17 @@ nsFrameLoader::ReallyLoadFrameScripts()
     mMessageManager->InitWithCallback(this);
   }
   return NS_OK;
 }
 
 EventTarget*
 nsFrameLoader::GetTabChildGlobalAsEventTarget()
 {
-  return static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
+  return mChildMessageManager.get();
 }
 
 already_AddRefed<Element>
 nsFrameLoader::GetOwnerElement()
 {
   nsCOMPtr<Element> element = do_QueryInterface(mOwnerContent);
   return element.forget();
 }
--- a/dom/base/nsFrameLoader.h
+++ b/dom/base/nsFrameLoader.h
@@ -27,17 +27,17 @@
 #include "Units.h"
 #include "nsIWebBrowserPersistable.h"
 #include "nsIFrame.h"
 #include "nsPluginTags.h"
 
 class nsIURI;
 class nsSubDocumentFrame;
 class nsView;
-class nsIInProcessContentFrameMessageManager;
+class nsInProcessTabChildGlobal;
 class AutoResetInShow;
 class AutoResetInFrameSwap;
 class nsITabParent;
 class nsIDocShellTreeItem;
 class nsIDocShellTreeOwner;
 
 namespace mozilla {
 
@@ -316,17 +316,17 @@ public:
 
   // Properly retrieves documentSize of any subdocument type.
   nsresult GetWindowDimensions(nsIntRect& aRect);
 
   virtual nsIMessageSender* GetProcessMessageManager() const override;
 
   // public because a callback needs these.
   RefPtr<mozilla::dom::ChromeMessageSender> mMessageManager;
-  nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager;
+  RefPtr<nsInProcessTabChildGlobal> mChildMessageManager;
 
   virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   nsFrameLoader(mozilla::dom::Element* aOwner,
                 nsPIDOMWindowOuter* aOpener,
                 bool aNetworkCreated,
                 int32_t aJSPluginID);
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -39,16 +39,17 @@
 #include "mozilla/dom/ChromeMessageBroadcaster.h"
 #include "mozilla/dom/ChromeMessageSender.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/MessageManagerBinding.h"
 #include "mozilla/dom/MessagePort.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/ProcessGlobal.h"
+#include "mozilla/dom/ResolveSystemBinding.h"
 #include "mozilla/dom/SameProcessMessageQueue.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
 #include "mozilla/dom/DOMStringList.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "nsPrintfCString.h"
 #include "nsXULAppAPI.h"
@@ -1612,17 +1613,16 @@ NS_NewGlobalMessageManager(nsIMessageBro
 
 nsDataHashtable<nsStringHashKey, nsMessageManagerScriptHolder*>*
   nsMessageManagerScriptExecutor::sCachedScripts = nullptr;
 StaticRefPtr<nsScriptCacheCleaner> nsMessageManagerScriptExecutor::sScriptCacheCleaner;
 
 void
 nsMessageManagerScriptExecutor::DidCreateGlobal()
 {
-  NS_ASSERTION(mGlobal, "Should have mGlobal!");
   if (!sCachedScripts) {
     sCachedScripts =
       new nsDataHashtable<nsStringHashKey, nsMessageManagerScriptHolder*>;
     sScriptCacheCleaner = new nsScriptCacheCleaner();
   }
 }
 
 // static
@@ -1647,23 +1647,24 @@ nsMessageManagerScriptExecutor::Shutdown
 
     delete sCachedScripts;
     sCachedScripts = nullptr;
     sScriptCacheCleaner = nullptr;
   }
 }
 
 void
-nsMessageManagerScriptExecutor::LoadScriptInternal(const nsAString& aURL,
+nsMessageManagerScriptExecutor::LoadScriptInternal(JS::Handle<JSObject*> aGlobal,
+                                                   const nsAString& aURL,
                                                    bool aRunInGlobalScope)
 {
   AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(
     "nsMessageManagerScriptExecutor::LoadScriptInternal", OTHER, aURL);
 
-  if (!mGlobal || !sCachedScripts) {
+  if (!sCachedScripts) {
     return;
   }
 
   JS::RootingContext* rcx = RootingCx();
   JS::Rooted<JSScript*> script(rcx);
 
   nsMessageManagerScriptHolder* holder = sCachedScripts->Get(aURL);
   if (holder && holder->WillRunInGlobalScope() == aRunInGlobalScope) {
@@ -1671,31 +1672,28 @@ nsMessageManagerScriptExecutor::LoadScri
   } else {
     // Don't put anything in the cache if we already have an entry
     // with a different WillRunInGlobalScope() value.
     bool shouldCache = !holder;
     TryCacheLoadAndCompileScript(aURL, aRunInGlobalScope,
                                  shouldCache, &script);
   }
 
-  JS::Rooted<JSObject*> global(rcx, mGlobal);
-  if (global) {
-    AutoEntryScript aes(global, "message manager script load");
-    JSContext* cx = aes.cx();
-    if (script) {
-      if (aRunInGlobalScope) {
-        JS::RootedValue rval(cx);
-        JS::CloneAndExecuteScript(cx, script, &rval);
-      } else {
-        JS::Rooted<JSObject*> scope(cx);
-        bool ok = js::ExecuteInGlobalAndReturnScope(cx, global, script, &scope);
-        if (ok) {
-          // Force the scope to stay alive.
-          mAnonymousGlobalScopes.AppendElement(scope);
-        }
+  AutoEntryScript aes(aGlobal, "message manager script load");
+  JSContext* cx = aes.cx();
+  if (script) {
+    if (aRunInGlobalScope) {
+      JS::RootedValue rval(cx);
+      JS::CloneAndExecuteScript(cx, script, &rval);
+    } else {
+      JS::Rooted<JSObject*> scope(cx);
+      bool ok = js::ExecuteInGlobalAndReturnScope(cx, aGlobal, script, &scope);
+      if (ok) {
+        // Force the scope to stay alive.
+        mAnonymousGlobalScopes.AppendElement(scope);
       }
     }
   }
 }
 
 void
 nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
   const nsAString& aURL,
@@ -1806,55 +1804,48 @@ nsMessageManagerScriptExecutor::TryCache
 }
 
 void
 nsMessageManagerScriptExecutor::Trace(const TraceCallbacks& aCallbacks, void* aClosure)
 {
   for (size_t i = 0, length = mAnonymousGlobalScopes.Length(); i < length; ++i) {
     aCallbacks.Trace(&mAnonymousGlobalScopes[i], "mAnonymousGlobalScopes[i]", aClosure);
   }
-  aCallbacks.Trace(&mGlobal, "mGlobal", aClosure);
 }
 
 void
 nsMessageManagerScriptExecutor::Unlink()
 {
   ImplCycleCollectionUnlink(mAnonymousGlobalScopes);
-  mGlobal = nullptr;
 }
 
 bool
-nsMessageManagerScriptExecutor::InitChildGlobalInternal(
-  nsISupports* aScope,
-  const nsACString& aID)
+nsMessageManagerScriptExecutor::InitChildGlobalInternal(const nsACString& aID)
 {
   AutoSafeJSContext cx;
-  nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
+  if (!SystemBindingInitIds(cx)) {
+    return false;
+  }
 
-  const uint32_t flags = xpc::INIT_JS_STANDARD_CLASSES;
+  nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
 
   JS::CompartmentOptions options;
   options.creationOptions().setSystemZone();
 
-  if (xpc::SharedMemoryEnabled()) {
-    options.creationOptions().setSharedMemoryAndAtomicsEnabled(true);
+  xpc::InitGlobalObjectOptions(options, mPrincipal);
+  JS::Rooted<JSObject*> global(cx);
+  if (!WrapGlobalObject(cx, options, &global)) {
+    return false;
   }
 
-  JS::Rooted<JSObject*> global(cx);
-  nsresult rv = xpc::InitClassesWithNewWrappedGlobal(cx, aScope, mPrincipal,
-                                                     flags, options,
-                                                     &global);
-  NS_ENSURE_SUCCESS(rv, false);
-
-  mGlobal = global;
-  NS_ENSURE_TRUE(mGlobal, false);
+  xpc::InitGlobalObject(cx, global, 0);
 
   // Set the location information for the new global, so that tools like
   // about:memory may use that information.
-  xpc::SetLocationForGlobal(mGlobal, aID);
+  xpc::SetLocationForGlobal(global, aID);
 
   DidCreateGlobal();
   return true;
 }
 
 void
 nsMessageManagerScriptExecutor::MarkScopesForCC()
 {
--- a/dom/base/nsFrameMessageManager.h
+++ b/dom/base/nsFrameMessageManager.h
@@ -471,39 +471,38 @@ struct nsMessageManagerScriptHolder
   bool mRunInGlobalScope;
 };
 
 class nsMessageManagerScriptExecutor
 {
 public:
   static void PurgeCache();
   static void Shutdown();
-  JSObject* GetGlobal()
-  {
-    return mGlobal;
-  }
 
   void MarkScopesForCC();
 protected:
   friend class nsMessageManagerScriptCx;
   nsMessageManagerScriptExecutor() { MOZ_COUNT_CTOR(nsMessageManagerScriptExecutor); }
   ~nsMessageManagerScriptExecutor() { MOZ_COUNT_DTOR(nsMessageManagerScriptExecutor); }
 
   void DidCreateGlobal();
-  void LoadScriptInternal(const nsAString& aURL, bool aRunInGlobalScope);
+  void LoadScriptInternal(JS::Handle<JSObject*> aGlobal, const nsAString& aURL,
+                          bool aRunInGlobalScope);
   void TryCacheLoadAndCompileScript(const nsAString& aURL,
                                     bool aRunInGlobalScope,
                                     bool aShouldCache,
                                     JS::MutableHandle<JSScript*> aScriptp);
   void TryCacheLoadAndCompileScript(const nsAString& aURL,
                                     bool aRunInGlobalScope);
-  bool InitChildGlobalInternal(nsISupports* aScope, const nsACString& aID);
+  bool InitChildGlobalInternal(const nsACString& aID);
+  virtual bool WrapGlobalObject(JSContext* aCx,
+                                JS::CompartmentOptions& aOptions,
+                                JS::MutableHandle<JSObject*> aReflector) = 0;
   void Trace(const TraceCallbacks& aCallbacks, void* aClosure);
   void Unlink();
-  JS::TenuredHeap<JSObject*> mGlobal;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   AutoTArray<JS::Heap<JSObject*>, 2> mAnonymousGlobalScopes;
 
   static nsDataHashtable<nsStringHashKey, nsMessageManagerScriptHolder*>* sCachedScripts;
   static mozilla::StaticRefPtr<nsScriptCacheCleaner> sScriptCacheCleaner;
 };
 
 class nsScriptCacheCleaner final : public nsIObserver
--- a/dom/base/nsInProcessTabChildGlobal.cpp
+++ b/dom/base/nsInProcessTabChildGlobal.cpp
@@ -9,18 +9,19 @@
 #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 "nsDOMClassInfoID.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"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::dom::ipc;
 
 bool
@@ -84,21 +85,21 @@ nsInProcessTabChildGlobal::DoSendAsyncMe
 
   queue->Push(ev);
   return NS_OK;
 }
 
 nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
                                                      nsIContent* aOwner,
                                                      nsFrameMessageManager* aChrome)
-: mDocShell(aShell), mInitialized(false), mLoadingScript(false),
+: ContentFrameMessageManager(aChrome),
+  mDocShell(aShell), mInitialized(false), mLoadingScript(false),
   mPreventEventsEscaping(false),
   mOwner(aOwner), mChromeMessageManager(aChrome)
 {
-  SetIsNotDOMBinding();
   mozilla::HoldJSObjects(this);
 
   // If owner corresponds to an <iframe mozbrowser>, we'll have to tweak our
   // GetEventTargetParent implementation.
   nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwner);
   if (browserFrame) {
     mIsBrowserFrame = browserFrame->GetReallyIsBrowser();
   }
@@ -114,17 +115,17 @@ nsInProcessTabChildGlobal::~nsInProcessT
 }
 
 // This method isn't automatically forwarded safely because it's notxpcom, so
 // the IDL binding doesn't know what value to return.
 NS_IMETHODIMP_(bool)
 nsInProcessTabChildGlobal::MarkForCC()
 {
   MarkScopesForCC();
-  return mMessageManager ? mMessageManager->MarkForCC() : false;
+  return MessageManagerGlobal::MarkForCC();
 }
 
 nsresult
 nsInProcessTabChildGlobal::Init()
 {
 #ifdef DEBUG
   nsresult rv =
 #endif
@@ -162,53 +163,79 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
   NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(nsInProcessTabChildGlobal, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(nsInProcessTabChildGlobal, DOMEventTargetHelper)
 
+bool
+nsInProcessTabChildGlobal::WrapGlobalObject(JSContext* aCx,
+                                            JS::CompartmentOptions& aOptions,
+                                            JS::MutableHandle<JSObject*> aReflector)
+{
+  bool ok = ContentFrameMessageManagerBinding::Wrap(aCx, this, this, aOptions,
+                                                    nsJSPrincipals::get(mPrincipal),
+                                                    true, aReflector);
+  if (ok) {
+    // Since we can't rewrap we have to preserve the global's wrapper here.
+    PreserveWrapper(ToSupports(this));
+  }
+  return ok;
+}
+
 void
 nsInProcessTabChildGlobal::CacheFrameLoader(nsIFrameLoader* aFrameLoader)
 {
   mFrameLoader = aFrameLoader;
 }
 
+already_AddRefed<nsPIDOMWindowOuter>
+nsInProcessTabChildGlobal::GetContent(ErrorResult& aError)
+{
+  nsCOMPtr<nsPIDOMWindowOuter> content;
+  if (mDocShell) {
+    content = mDocShell->GetWindow();
+  }
+  return content.forget();
+}
+
 NS_IMETHODIMP
 nsInProcessTabChildGlobal::GetContent(mozIDOMWindowProxy** aContent)
 {
-  *aContent = nullptr;
-  if (!mDocShell) {
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsPIDOMWindowOuter> window = mDocShell->GetWindow();
-  window.forget(aContent);
-  return NS_OK;
+  ErrorResult rv;
+  *aContent = GetContent(rv).take();
+  return rv.StealNSResult();
 }
 
 NS_IMETHODIMP
 nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
 {
-  NS_IF_ADDREF(*aDocShell = mDocShell);
-  return NS_OK;
+  ErrorResult rv;
+  *aDocShell = GetDocShell(rv).take();
+  return rv.StealNSResult();
+}
+
+already_AddRefed<nsIEventTarget>
+nsInProcessTabChildGlobal::GetTabEventTarget()
+{
+  nsCOMPtr<nsIEventTarget> target = GetMainThreadEventTarget();
+  return target.forget();
 }
 
 NS_IMETHODIMP
 nsInProcessTabChildGlobal::GetTabEventTarget(nsIEventTarget** aTarget)
 {
-  nsCOMPtr<nsIEventTarget> target = GetMainThreadEventTarget();
-  target.forget(aTarget);
+  *aTarget = GetTabEventTarget().take();
   return NS_OK;
 }
 
 void
 nsInProcessTabChildGlobal::FireUnloadEvent()
 {
   // We're called from nsDocument::MaybeInitializeFinalizeFrameLoaders, so it
   // should be safe to run script.
@@ -305,18 +332,17 @@ nsInProcessTabChildGlobal::InitTabChildG
   nsIURI* uri = mOwner->OwnerDoc()->GetDocumentURI();
   if (uri) {
     nsAutoCString u;
     nsresult rv = uri->GetSpec(u);
     NS_ENSURE_SUCCESS(rv, rv);
     id.AppendLiteral("?ownedBy=");
     id.Append(u);
   }
-  nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, this);
-  NS_ENSURE_STATE(InitChildGlobalInternal(scopeSupports, id));
+  NS_ENSURE_STATE(InitChildGlobalInternal(id));
   return NS_OK;
 }
 
 class nsAsyncScriptLoad : public Runnable
 {
 public:
   nsAsyncScriptLoad(nsInProcessTabChildGlobal* aTabChild,
                     const nsAString& aURL,
@@ -346,17 +372,18 @@ nsInProcessTabChildGlobal::LoadFrameScri
     return;
   }
   if (!mInitialized) {
     mInitialized = true;
     Init();
   }
   bool tmp = mLoadingScript;
   mLoadingScript = true;
-  LoadScriptInternal(aURL, aRunInGlobalScope);
+  JS::Rooted<JSObject*> global(mozilla::dom::RootingCx(), GetWrapper());
+  LoadScriptInternal(global, aURL, aRunInGlobalScope);
   mLoadingScript = tmp;
 }
 
 already_AddRefed<nsIFrameLoader>
 nsInProcessTabChildGlobal::GetFrameLoader()
 {
   nsCOMPtr<nsIFrameLoaderOwner> owner = do_QueryInterface(mOwner);
   nsCOMPtr<nsIFrameLoader> fl = owner ? owner->GetFrameLoader() : nullptr;
--- a/dom/base/nsInProcessTabChildGlobal.h
+++ b/dom/base/nsInProcessTabChildGlobal.h
@@ -4,16 +4,17 @@
  * 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 nsInProcessTabChildGlobal_h
 #define nsInProcessTabChildGlobal_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/DOMEventTargetHelper.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 "nsIDocShell.h"
 #include "nsIDOMElement.h"
@@ -22,17 +23,17 @@
 #include "nsIGlobalObject.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsWeakReference.h"
 
 namespace mozilla {
 class EventChainPreVisitor;
 } // namespace mozilla
 
-class nsInProcessTabChildGlobal : public mozilla::DOMEventTargetHelper,
+class nsInProcessTabChildGlobal : public mozilla::dom::ContentFrameMessageManager,
                                   public nsMessageManagerScriptExecutor,
                                   public nsIInProcessContentFrameMessageManager,
                                   public nsIGlobalObject,
                                   public nsIScriptObjectPrincipal,
                                   public nsSupportsWeakReference,
                                   public mozilla::dom::ipc::MessageManagerCallback
 {
   typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData;
@@ -41,48 +42,40 @@ class nsInProcessTabChildGlobal : public
 
 public:
   nsInProcessTabChildGlobal(nsIDocShell* aShell, nsIContent* aOwner,
                             nsFrameMessageManager* aChrome);
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsInProcessTabChildGlobal,
                                                          mozilla::DOMEventTargetHelper)
 
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aGivenProto) override
+  {
+    MOZ_CRASH("We should never get here!");
+  }
+  virtual bool WrapGlobalObject(JSContext* aCx,
+                                JS::CompartmentOptions& aOptions,
+                                JS::MutableHandle<JSObject*> aReflector) override;
+
+  virtual already_AddRefed<nsPIDOMWindowOuter>
+    GetContent(mozilla::ErrorResult& aError) override;
+  virtual already_AddRefed<nsIDocShell>
+    GetDocShell(mozilla::ErrorResult& aError) override
+  {
+    nsCOMPtr<nsIDocShell> docShell(mDocShell);
+    return docShell.forget();
+  }
+  virtual already_AddRefed<nsIEventTarget> GetTabEventTarget() override;
+
   NS_FORWARD_SAFE_NSIMESSAGELISTENERMANAGER(mMessageManager)
   NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
+  NS_FORWARD_SAFE_NSISYNCMESSAGESENDER(mMessageManager);
   NS_FORWARD_SAFE_NSIMESSAGEMANAGERGLOBAL(mMessageManager)
-  NS_IMETHOD SendSyncMessage(const nsAString& aMessageName,
-                             JS::Handle<JS::Value> aObject,
-                             JS::Handle<JS::Value> aRemote,
-                             nsIPrincipal* aPrincipal,
-                             JSContext* aCx,
-                             uint8_t aArgc,
-                             JS::MutableHandle<JS::Value> aRetval) override
-  {
-    return mMessageManager
-      ? mMessageManager->SendSyncMessage(aMessageName, aObject, aRemote,
-                                         aPrincipal, aCx, aArgc, aRetval)
-      : NS_ERROR_NULL_POINTER;
-  }
-  NS_IMETHOD SendRpcMessage(const nsAString& aMessageName,
-                            JS::Handle<JS::Value> aObject,
-                            JS::Handle<JS::Value> aRemote,
-                            nsIPrincipal* aPrincipal,
-                            JSContext* aCx,
-                            uint8_t aArgc,
-                            JS::MutableHandle<JS::Value> aRetval) override
-  {
-    return mMessageManager
-      ? mMessageManager->SendRpcMessage(aMessageName, aObject, aRemote,
-                                        aPrincipal, aCx, aArgc, aRetval)
-      : NS_ERROR_NULL_POINTER;
-  }
-  NS_IMETHOD GetContent(mozIDOMWindowProxy** aContent) override;
-  NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) override;
-  NS_IMETHOD GetTabEventTarget(nsIEventTarget** aTarget) override;
+  NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
 
   NS_DECL_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER
 
   /**
    * MessageManagerCallback methods that we override.
    */
   virtual bool DoSendBlockingMessage(JSContext* aCx,
                                       const nsAString& aMessage,
@@ -94,36 +87,16 @@ public:
   virtual nsresult DoSendAsyncMessage(JSContext* aCx,
                                       const nsAString& aMessage,
                                       StructuredCloneData& aData,
                                       JS::Handle<JSObject *> aCpows,
                                       nsIPrincipal* aPrincipal) override;
 
   virtual nsresult GetEventTargetParent(
                      mozilla::EventChainPreVisitor& aVisitor) override;
-  NS_IMETHOD AddEventListener(const nsAString& aType,
-                              nsIDOMEventListener* aListener,
-                              bool aUseCapture)
-  {
-    // By default add listeners only for trusted events!
-    return mozilla::DOMEventTargetHelper::AddEventListener(aType, aListener,
-                                                           aUseCapture, false,
-                                                           2);
-  }
-  NS_IMETHOD AddEventListener(const nsAString& aType,
-                              nsIDOMEventListener* aListener,
-                              bool aUseCapture, bool aWantsUntrusted,
-                              uint8_t optional_argc) override
-  {
-    return mozilla::DOMEventTargetHelper::AddEventListener(aType, aListener,
-                                                           aUseCapture,
-                                                           aWantsUntrusted,
-                                                           optional_argc);
-  }
-  using mozilla::DOMEventTargetHelper::AddEventListener;
 
   virtual nsIPrincipal* GetPrincipal() override { return mPrincipal; }
   void LoadFrameScript(const nsAString& aURL, bool aRunInGlobalScope);
   void FireUnloadEvent();
   void DisconnectEventListeners();
   void Disconnect();
   void SendMessageToParent(const nsString& aMessage, bool aSync,
                            const nsString& aJSON,
@@ -138,32 +111,28 @@ public:
   {
     return mChromeMessageManager;
   }
   void SetChromeMessageManager(nsFrameMessageManager* aParent)
   {
     mChromeMessageManager = aParent;
   }
 
-  virtual JSObject* GetGlobalJSObject() override {
-    return mGlobal;
-  }
-  virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override
+  virtual JSObject* GetGlobalJSObject() override
   {
-    MOZ_CRASH("nsInProcessTabChildGlobal doesn't use DOM bindings!");
+    return GetWrapper();
   }
 
   already_AddRefed<nsIFrameLoader> GetFrameLoader();
 
 protected:
   virtual ~nsInProcessTabChildGlobal();
 
   nsresult Init();
   nsresult InitTabChildGlobal();
-  nsCOMPtr<nsIContentFrameMessageManager> mMessageManager;
   nsCOMPtr<nsIDocShell> mDocShell;
   bool mInitialized;
   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;
--- a/dom/base/nsWrapperCache.h
+++ b/dom/base/nsWrapperCache.h
@@ -339,21 +339,17 @@ protected:
       mWrapper = reinterpret_cast<JSObject*>(1);
     }
   }
 
 private:
   // Friend declarations for things that need to be able to call
   // SetIsNotDOMBinding().  The goal is to get rid of all of these, and
   // SetIsNotDOMBinding() too.
-  friend class mozilla::dom::TabChildGlobal;
-  friend class mozilla::dom::ProcessGlobal;
   friend class SandboxPrivate;
-  friend class nsInProcessTabChildGlobal;
-  friend class nsWindowRoot;
   void SetIsNotDOMBinding()
   {
     MOZ_ASSERT(!mWrapper && !(GetWrapperFlags() & ~WRAPPER_IS_NOT_DOM_BINDING),
                "This flag should be set before creating any wrappers.");
     SetWrapperFlags(WRAPPER_IS_NOT_DOM_BINDING);
   }
 
   void SetWrapperJSObject(JSObject* aWrapper);
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -3122,21 +3122,32 @@ ConvertExceptionToPromise(JSContext* cx,
   }
 
   rval.setObject(*promise);
   return true;
 }
 
 /* static */
 void
-CreateGlobalOptions<nsGlobalWindowInner>::TraceGlobal(JSTracer* aTrc, JSObject* aObj)
+CreateGlobalOptionsWithXPConnect::TraceGlobal(JSTracer* aTrc, JSObject* aObj)
 {
   xpc::TraceXPCGlobal(aTrc, aObj);
 }
 
+/* static */
+bool
+CreateGlobalOptionsWithXPConnect::PostCreateGlobal(JSContext* aCx,
+                                                   JS::Handle<JSObject*> aGlobal)
+{
+  // Invoking the XPCWrappedNativeScope constructor automatically hooks it
+  // up to the compartment of aGlobal.
+  (void) new XPCWrappedNativeScope(aCx, aGlobal);
+  return true;
+}
+
 static bool sRegisteredDOMNames = false;
 
 nsresult
 RegisterDOMNames()
 {
   if (sRegisteredDOMNames) {
     return NS_OK;
   }
@@ -3160,20 +3171,17 @@ bool
 CreateGlobalOptions<nsGlobalWindowInner>::PostCreateGlobal(JSContext* aCx,
                                                            JS::Handle<JSObject*> aGlobal)
 {
   nsresult rv = RegisterDOMNames();
   if (NS_FAILED(rv)) {
     return Throw(aCx, rv);
   }
 
-  // Invoking the XPCWrappedNativeScope constructor automatically hooks it
-  // up to the compartment of aGlobal.
-  (void) new XPCWrappedNativeScope(aCx, aGlobal);
-  return true;
+  return CreateGlobalOptionsWithXPConnect::PostCreateGlobal(aCx, aGlobal);
 }
 
 #ifdef DEBUG
 void
 AssertReturnTypeMatchesJitinfo(const JSJitInfo* aJitInfo,
                                JS::Handle<JS::Value> aValue)
 {
   switch (aJitInfo->returnType()) {
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -45,16 +45,17 @@ class nsGenericHTMLElement;
 class nsIJSID;
 
 namespace mozilla {
 
 enum UseCounter : int16_t;
 
 namespace dom {
 class CustomElementReactionsStack;
+class MessageManagerGlobal;
 template<typename KeyType, typename ValueType> class Record;
 
 nsresult
 UnwrapArgImpl(JSContext* cx, JS::Handle<JSObject*> src, const nsIID& iid,
               void** ppArg);
 
 nsresult
 UnwrapWindowProxyImpl(JSContext* cx, JS::Handle<JSObject*> src,
@@ -3095,39 +3096,59 @@ ResolveGlobal(JSContext* aCx, JS::Handle
 
 bool
 MayResolveGlobal(const JSAtomState& aNames, jsid aId, JSObject* aMaybeObj);
 
 bool
 EnumerateGlobal(JSContext* aCx, JS::HandleObject aObj,
                 JS::AutoIdVector& aProperties, bool aEnumerableOnly);
 
-template <class T>
-struct CreateGlobalOptions
+
+struct CreateGlobalOptionsGeneric
 {
-  static constexpr ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
-    ProtoAndIfaceCache::NonWindowLike;
   static void TraceGlobal(JSTracer* aTrc, JSObject* aObj)
   {
     mozilla::dom::TraceProtoAndIfaceCache(aTrc, aObj);
   }
   static bool PostCreateGlobal(JSContext* aCx, JS::Handle<JSObject*> aGlobal)
   {
     MOZ_ALWAYS_TRUE(TryPreserveWrapper(aGlobal));
 
     return true;
   }
 };
 
+struct CreateGlobalOptionsWithXPConnect
+{
+  static void TraceGlobal(JSTracer* aTrc, JSObject* aObj);
+  static bool PostCreateGlobal(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
+};
+
+template <class T>
+using IsGlobalWithXPConnect =
+  IntegralConstant<bool,
+                   IsBaseOf<nsGlobalWindowInner, T>::value ||
+                   IsBaseOf<MessageManagerGlobal, T>::value>;
+
+template <class T>
+struct CreateGlobalOptions
+  : Conditional<IsGlobalWithXPConnect<T>::value,
+                CreateGlobalOptionsWithXPConnect,
+                CreateGlobalOptionsGeneric>::Type
+{
+  static constexpr ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
+    ProtoAndIfaceCache::NonWindowLike;
+};
+
 template <>
 struct CreateGlobalOptions<nsGlobalWindowInner>
+  : public CreateGlobalOptionsWithXPConnect
 {
   static constexpr ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
     ProtoAndIfaceCache::WindowLike;
-  static void TraceGlobal(JSTracer* aTrc, JSObject* aObj);
   static bool PostCreateGlobal(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
 };
 
 nsresult
 RegisterDOMNames();
 
 // The return value is true if we created and successfully performed our part of
 // the setup for the global, false otherwise.
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -147,16 +147,20 @@ DOMInterfaces = {
 'console': {
     'nativeType': 'mozilla::dom::Console',
 },
 
 'ConsoleInstance': {
     'implicitJSContext': ['clear', 'count', 'groupEnd', 'time', 'timeEnd'],
 },
 
+'ContentProcessMessageManager': {
+    'nativeType': 'mozilla::dom::ProcessGlobal'
+},
+
 'ConvolverNode': {
     'implicitJSContext': [ 'buffer' ],
 },
 
 'Coordinates': {
     'headerFile': 'nsGeoPosition.h'
 },
 
@@ -1722,16 +1726,17 @@ addExternalIface('MozObserver', nativeTy
 addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSource',
                  notflattened=True)
 addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True)
 addExternalIface('MozTreeView', nativeType='nsITreeView',
                   headerFile='nsITreeView.h', notflattened=True)
 addExternalIface('MozWakeLockListener', headerFile='nsIDOMWakeLockListener.h')
 addExternalIface('nsIBrowserDOMWindow', nativeType='nsIBrowserDOMWindow',
                  notflattened=True)
+addExternalIface('nsIEventTarget', nativeType='nsIEventTarget', notflattened=True)
 addExternalIface('nsIFile', nativeType='nsIFile', notflattened=True)
 addExternalIface('nsILoadGroup', nativeType='nsILoadGroup',
                  headerFile='nsILoadGroup.h', notflattened=True)
 addExternalIface('nsIPrintSettings', nativeType='nsIPrintSettings',
                  notflattened=True)
 addExternalIface('nsISelectionListener', nativeType='nsISelectionListener')
 addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True)
 addExternalIface('nsITransportProvider', nativeType='nsITransportProvider')
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -14,16 +14,17 @@
 #endif
 #include "Layers.h"
 #include "ContentChild.h"
 #include "TabParent.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/BrowserElementParent.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/EventListenerManager.h"
+#include "mozilla/dom/MessageManagerBinding.h"
 #include "mozilla/dom/indexedDB/PIndexedDBPermissionRequestChild.h"
 #include "mozilla/dom/PaymentRequestChild.h"
 #include "mozilla/dom/TelemetryScrollProbe.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/ipc/URIUtils.h"
 #include "mozilla/layers/APZChild.h"
 #include "mozilla/layers/APZCCallbackHelper.h"
 #include "mozilla/layers/APZCTreeManager.h"
@@ -99,17 +100,16 @@
 #include "StructuredCloneData.h"
 #include "nsViewportInfo.h"
 #include "nsILoadContext.h"
 #include "ipc/nsGUIEventIPC.h"
 #include "mozilla/gfx/Matrix.h"
 #include "UnitTransforms.h"
 #include "ClientLayerManager.h"
 #include "LayersLogging.h"
-#include "nsDOMClassInfoID.h"
 #include "nsColorPickerProxy.h"
 #include "nsContentPermissionHelper.h"
 #include "nsNetUtil.h"
 #include "nsIPermissionManager.h"
 #include "nsIURILoader.h"
 #include "nsIScriptError.h"
 #include "mozilla/EventForwards.h"
 #include "nsDeviceContext.h"
@@ -231,21 +231,20 @@ TabChildBase::DispatchMessageManagerMess
         ErrorResult rv;
         data.Write(cx, json, rv);
         if (NS_WARN_IF(rv.Failed())) {
             rv.SuppressException();
             return;
         }
     }
 
-    JS::Rooted<JSObject*> kungFuDeathGrip(cx, GetGlobal());
+    JS::Rooted<JSObject*> kungFuDeathGrip(cx, mTabChildGlobal->GetWrapper());
     // Let the BrowserElementScrolling helper (if it exists) for this
     // content manipulate the frame state.
-    RefPtr<nsFrameMessageManager> mm =
-      static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
+    RefPtr<nsFrameMessageManager> mm = mTabChildGlobal->GetMessageManager();
     mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal), nullptr,
                        aMessageName, false, &data, nullptr, nullptr, nullptr);
 }
 
 bool
 TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics)
 {
   MOZ_ASSERT(aFrameMetrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID);
@@ -267,17 +266,17 @@ TabChildBase::UpdateFrameHandler(const F
     return true;
   }
   return true;
 }
 
 void
 TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
 {
-    if (!mGlobal || !mTabChildGlobal) {
+    if (!mTabChildGlobal) {
         return;
     }
 
     FrameMetrics newMetrics = aFrameMetrics;
     APZCCallbackHelper::UpdateRootFrame(newMetrics);
 }
 
 NS_IMETHODIMP
@@ -1104,23 +1103,21 @@ TabChild::ActorDestroy(ActorDestroyReaso
   mIPCOpen = false;
 
   DestroyWindow();
 
   if (mTabChildGlobal) {
     // We should have a message manager if the global is alive, but it
     // seems sometimes we don't.  Assert in aurora/nightly, but don't
     // crash in release builds.
-    MOZ_DIAGNOSTIC_ASSERT(mTabChildGlobal->mMessageManager);
-    if (mTabChildGlobal->mMessageManager) {
+    MOZ_DIAGNOSTIC_ASSERT(mTabChildGlobal->GetMessageManager());
+    if (mTabChildGlobal->GetMessageManager()) {
       // The messageManager relays messages via the TabChild which
       // no longer exists.
-      static_cast<nsFrameMessageManager*>
-        (mTabChildGlobal->mMessageManager.get())->Disconnect();
-      mTabChildGlobal->mMessageManager = nullptr;
+      mTabChildGlobal->DisconnectMessageManager();
     }
   }
 
   CompositorBridgeChild* compositorChild = CompositorBridgeChild::Get();
   if (compositorChild) {
     compositorChild->CancelNotifyAfterRemotePaint(this);
   }
 
@@ -1357,19 +1354,21 @@ TabChild::RecvSuppressDisplayport(const 
   return IPC_OK();
 }
 
 void
 TabChild::HandleDoubleTap(const CSSPoint& aPoint, const Modifiers& aModifiers,
                           const ScrollableLayerGuid& aGuid)
 {
   TABC_LOG("Handling double tap at %s with %p %p\n",
-    Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get());
-
-  if (!mGlobal || !mTabChildGlobal) {
+    Stringify(aPoint).c_str(),
+    mTabChildGlobal ? mTabChildGlobal->GetWrapper() : nullptr,
+    mTabChildGlobal.get());
+
+  if (!mTabChildGlobal || !mTabChildGlobal->GetWrapper()) {
     return;
   }
 
   // Note: there is nothing to do with the modifiers here, as we are not
   // synthesizing any sort of mouse event.
   nsCOMPtr<nsIDocument> document = GetDocument();
   CSSRect zoomToRect = CalculateRectToZoomTo(document, aPoint);
   // The double-tap can be dispatched by any scroll frame (so |aGuid| could be
@@ -1400,36 +1399,36 @@ TabChild::RecvHandleTap(const GeckoConte
   if (!presShell->GetPresContext()) {
     return IPC_OK();
   }
   CSSToLayoutDeviceScale scale(presShell->GetPresContext()->CSSToDevPixelScale());
   CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint / scale, aGuid);
 
   switch (aType) {
   case GeckoContentController::TapType::eSingleTap:
-    if (mGlobal && mTabChildGlobal) {
+    if (mTabChildGlobal) {
       mAPZEventState->ProcessSingleTap(point, scale, aModifiers, aGuid, 1);
     }
     break;
   case GeckoContentController::TapType::eDoubleTap:
     HandleDoubleTap(point, aModifiers, aGuid);
     break;
   case GeckoContentController::TapType::eSecondTap:
-    if (mGlobal && mTabChildGlobal) {
+    if (mTabChildGlobal) {
       mAPZEventState->ProcessSingleTap(point, scale, aModifiers, aGuid, 2);
     }
     break;
   case GeckoContentController::TapType::eLongTap:
-    if (mGlobal && mTabChildGlobal) {
+    if (mTabChildGlobal) {
       mAPZEventState->ProcessLongTap(presShell, point, scale, aModifiers, aGuid,
           aInputBlockId);
     }
     break;
   case GeckoContentController::TapType::eLongTapUp:
-    if (mGlobal && mTabChildGlobal) {
+    if (mTabChildGlobal) {
       mAPZEventState->ProcessLongTapUp(presShell, point, scale, aModifiers);
     }
     break;
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
@@ -2271,22 +2270,28 @@ TabChild::RecvActivateFrameEvent(const n
   RefPtr<ContentListener> listener = new ContentListener(this);
   chromeHandler->AddEventListener(aType, listener, capture);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabChild::RecvLoadRemoteScript(const nsString& aURL, const bool& aRunInGlobalScope)
 {
-  if (!mGlobal && !InitTabChildGlobal())
+  if (!InitTabChildGlobal())
     // This can happen if we're half-destroyed.  It's not a fatal
     // error.
     return IPC_OK();
 
-  LoadScriptInternal(aURL, aRunInGlobalScope);
+  JS::Rooted<JSObject*> global(RootingCx(), mTabChildGlobal->GetWrapper());
+  if (!global) {
+    // This can happen if we're half-destroyed.  It's not a fatal error.
+    return IPC_OK();
+  }
+
+  LoadScriptInternal(global, aURL, aRunInGlobalScope);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabChild::RecvAsyncMessage(const nsString& aMessage,
                            InfallibleTArray<CpowEntry>&& aCpows,
                            const IPC::Principal& aPrincipal,
                            const ClonedMessageData& aData)
@@ -2294,29 +2299,29 @@ TabChild::RecvAsyncMessage(const nsStrin
   AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(
     "TabChild::RecvAsyncMessage", EVENTS, aMessage);
 
   CrossProcessCpowHolder cpows(Manager(), aCpows);
   if (!mTabChildGlobal) {
     return IPC_OK();
   }
 
+  RefPtr<nsFrameMessageManager> mm = mTabChildGlobal->GetMessageManager();
+
   // We should have a message manager if the global is alive, but it
   // seems sometimes we don't.  Assert in aurora/nightly, but don't
   // crash in release builds.
-  MOZ_DIAGNOSTIC_ASSERT(mTabChildGlobal->mMessageManager);
-  if (!mTabChildGlobal->mMessageManager) {
+  MOZ_DIAGNOSTIC_ASSERT(mm);
+  if (!mm) {
     return IPC_OK();
   }
 
-  JS::Rooted<JSObject*> kungFuDeathGrip(dom::RootingCx(), GetGlobal());
+  JS::Rooted<JSObject*> kungFuDeathGrip(dom::RootingCx(), mTabChildGlobal->GetWrapper());
   StructuredCloneData data;
   UnpackClonedMessageDataForChild(aData, data);
-  RefPtr<nsFrameMessageManager> mm =
-    static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
   mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal), nullptr,
                      aMessage, false, &data, &cpows, aPrincipal, nullptr);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabChild::RecvSwappedWithOtherRemoteLoader(const IPCTabContext& aContext)
 {
@@ -2712,37 +2717,39 @@ TabChild::DeallocPRenderFrameChild(PRend
 {
     delete aFrame;
     return true;
 }
 
 bool
 TabChild::InitTabChildGlobal()
 {
-  if (!mGlobal && !mTabChildGlobal) {
+  if (!mTabChildGlobal) {
     nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(WebNavigation());
     NS_ENSURE_TRUE(window, false);
     nsCOMPtr<EventTarget> chromeHandler =
       do_QueryInterface(window->GetChromeEventHandler());
     NS_ENSURE_TRUE(chromeHandler, false);
 
-    RefPtr<TabChildGlobal> scope = new TabChildGlobal(this);
-
-    nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, scope);
+    RefPtr<TabChildGlobal> scope = mTabChildGlobal = new TabChildGlobal(this);
 
     NS_NAMED_LITERAL_CSTRING(globalId, "outOfProcessTabChildGlobal");
-    NS_ENSURE_TRUE(InitChildGlobalInternal(scopeSupports, globalId), false);
+    if (NS_WARN_IF(!InitChildGlobalInternal(globalId))) {
+        mTabChildGlobal = nullptr;
+        return false;
+    }
 
     scope->Init();
 
     nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(chromeHandler);
-    NS_ENSURE_TRUE(root, false);
+    if (NS_WARN_IF(!root)) {
+        mTabChildGlobal = nullptr;
+        return false;
+    }
     root->SetParentTarget(scope);
-
-    mTabChildGlobal = scope.forget();;
   }
 
   if (!mTriedBrowserInit) {
     mTriedBrowserInit = true;
     // Initialize the child side of the browser element machinery,
     // if appropriate.
     if (IsMozBrowser()) {
       RecvLoadRemoteScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
@@ -3468,31 +3475,28 @@ TabChild::BeforeUnloadRemoved()
 
 mozilla::dom::TabGroup*
 TabChild::TabGroup()
 {
   return mTabGroup;
 }
 
 TabChildGlobal::TabChildGlobal(TabChild* aTabChild)
-: mTabChild(aTabChild)
+: ContentFrameMessageManager(new nsFrameMessageManager(aTabChild)),
+  mTabChild(aTabChild)
 {
-  SetIsNotDOMBinding();
 }
 
 TabChildGlobal::~TabChildGlobal()
 {
 }
 
 void
 TabChildGlobal::Init()
 {
-  NS_ASSERTION(!mMessageManager, "Re-initializing?!?");
-  mMessageManager = new nsFrameMessageManager(mTabChild);
-
   TelemetryScrollProbe::Create(this);
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(TabChildGlobal)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TabChildGlobal,
                                                 DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager);
@@ -3510,80 +3514,117 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildGlobal)
   NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
   NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(TabChildGlobal, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(TabChildGlobal, DOMEventTargetHelper)
 
+bool
+TabChildGlobal::WrapGlobalObject(JSContext* aCx,
+                                 JS::CompartmentOptions& aOptions,
+                                 JS::MutableHandle<JSObject*> aReflector)
+{
+  bool ok = ContentFrameMessageManagerBinding::Wrap(aCx, this, this, aOptions,
+                                                    nsJSPrincipals::get(mTabChild->GetPrincipal()),
+                                                    true, aReflector);
+  if (ok) {
+    // Since we can't rewrap we have to preserve the global's wrapper here.
+    PreserveWrapper(ToSupports(this));
+  }
+  return ok;
+}
+
 // This method isn't automatically forwarded safely because it's notxpcom, so
 // the IDL binding doesn't know what value to return.
 NS_IMETHODIMP_(bool)
 TabChildGlobal::MarkForCC()
 {
   if (mTabChild) {
     mTabChild->MarkScopesForCC();
   }
   EventListenerManager* elm = GetExistingListenerManager();
   if (elm) {
     elm->MarkForCC();
   }
-  return mMessageManager ? mMessageManager->MarkForCC() : false;
+  return MessageManagerGlobal::MarkForCC();
+}
+
+already_AddRefed<nsPIDOMWindowOuter>
+TabChildGlobal::GetContent(ErrorResult& aError)
+{
+  if (!mTabChild) {
+    aError.Throw(NS_ERROR_NULL_POINTER);
+    return nullptr;
+  }
+  nsCOMPtr<nsPIDOMWindowOuter> window =
+    do_GetInterface(mTabChild->WebNavigation());
+  return window.forget();
 }
 
 NS_IMETHODIMP
 TabChildGlobal::GetContent(mozIDOMWindowProxy** aContent)
 {
-  *aContent = nullptr;
-  if (!mTabChild)
-    return NS_ERROR_NULL_POINTER;
-  nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(mTabChild->WebNavigation());
-  window.forget(aContent);
-  return NS_OK;
+  ErrorResult rv;
+  *aContent = GetContent(rv).take();
+  return rv.StealNSResult();
+}
+
+already_AddRefed<nsIDocShell>
+TabChildGlobal::GetDocShell(ErrorResult& aError)
+{
+  if (!mTabChild) {
+    aError.Throw(NS_ERROR_NULL_POINTER);
+    return nullptr;
+  }
+  nsCOMPtr<nsIDocShell> window = do_GetInterface(mTabChild->WebNavigation());
+  return window.forget();
 }
 
 NS_IMETHODIMP
 TabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
 {
-  *aDocShell = nullptr;
-  if (!mTabChild)
-    return NS_ERROR_NULL_POINTER;
-  nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mTabChild->WebNavigation());
-  docShell.swap(*aDocShell);
-  return NS_OK;
+  ErrorResult rv;
+  *aDocShell = GetDocShell(rv).take();
+  return rv.StealNSResult();
+}
+
+already_AddRefed<nsIEventTarget>
+TabChildGlobal::GetTabEventTarget()
+{
+  nsCOMPtr<nsIEventTarget> target = EventTargetFor(TaskCategory::Other);
+  return target.forget();
 }
 
 NS_IMETHODIMP
 TabChildGlobal::GetTabEventTarget(nsIEventTarget** aTarget)
 {
-  nsCOMPtr<nsIEventTarget> target = EventTargetFor(TaskCategory::Other);
-  target.forget(aTarget);
+  *aTarget = GetTabEventTarget().take();
   return NS_OK;
 }
 
 nsIPrincipal*
 TabChildGlobal::GetPrincipal()
 {
   if (!mTabChild)
     return nullptr;
   return mTabChild->GetPrincipal();
 }
 
 JSObject*
 TabChildGlobal::GetGlobalJSObject()
 {
   NS_ENSURE_TRUE(mTabChild, nullptr);
-  return mTabChild->GetGlobal();
+  return GetWrapper();
 }
 
 nsresult
 TabChildGlobal::Dispatch(TaskCategory aCategory,
                          already_AddRefed<nsIRunnable>&& aRunnable)
 {
   if (mTabChild && mTabChild->TabGroup()) {
     return mTabChild->TabGroup()->Dispatch(aCategory, Move(aRunnable));
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -2,16 +2,17 @@
 /* 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_TabChild_h
 #define mozilla_dom_TabChild_h
 
+#include "mozilla/dom/ContentFrameMessageManager.h"
 #include "mozilla/dom/PBrowserChild.h"
 #include "nsIWebNavigation.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsIWebBrowserChrome2.h"
 #include "nsIEmbeddingSiteWindow.h"
 #include "nsIWebBrowserChromeFocus.h"
 #include "nsIDOMEventListener.h"
@@ -73,106 +74,67 @@ struct AutoCacheNativeKeyCommands;
 namespace dom {
 
 class TabChild;
 class TabGroup;
 class ClonedMessageData;
 class CoalescedMouseData;
 class CoalescedWheelData;
 
-class TabChildGlobal : public DOMEventTargetHelper,
+class TabChildGlobal : public ContentFrameMessageManager,
                        public nsIContentFrameMessageManager,
                        public nsIScriptObjectPrincipal,
                        public nsIGlobalObject,
                        public nsSupportsWeakReference
 {
 public:
   explicit TabChildGlobal(TabChild* aTabChild);
   void Init();
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TabChildGlobal, DOMEventTargetHelper)
+
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aGivenProto) override
+  {
+    MOZ_CRASH("We should never get here!");
+  }
+  bool WrapGlobalObject(JSContext* aCx,
+                        JS::CompartmentOptions& aOptions,
+                        JS::MutableHandle<JSObject*> aReflector);
+
+  virtual already_AddRefed<nsPIDOMWindowOuter> GetContent(ErrorResult& aError) override;
+  virtual already_AddRefed<nsIDocShell> GetDocShell(ErrorResult& aError) override;
+  virtual already_AddRefed<nsIEventTarget> GetTabEventTarget() override;
+
   NS_FORWARD_SAFE_NSIMESSAGELISTENERMANAGER(mMessageManager)
   NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
+  NS_FORWARD_SAFE_NSISYNCMESSAGESENDER(mMessageManager);
   NS_FORWARD_SAFE_NSIMESSAGEMANAGERGLOBAL(mMessageManager)
-  NS_IMETHOD SendSyncMessage(const nsAString& aMessageName,
-                             JS::Handle<JS::Value> aObject,
-                             JS::Handle<JS::Value> aRemote,
-                             nsIPrincipal* aPrincipal,
-                             JSContext* aCx,
-                             uint8_t aArgc,
-                             JS::MutableHandle<JS::Value> aRetval) override
-  {
-    return mMessageManager
-      ? mMessageManager->SendSyncMessage(aMessageName, aObject, aRemote,
-                                         aPrincipal, aCx, aArgc, aRetval)
-      : NS_ERROR_NULL_POINTER;
-  }
-  NS_IMETHOD SendRpcMessage(const nsAString& aMessageName,
-                            JS::Handle<JS::Value> aObject,
-                            JS::Handle<JS::Value> aRemote,
-                            nsIPrincipal* aPrincipal,
-                            JSContext* aCx,
-                            uint8_t aArgc,
-                            JS::MutableHandle<JS::Value> aRetval) override
-  {
-    return mMessageManager
-      ? mMessageManager->SendRpcMessage(aMessageName, aObject, aRemote,
-                                        aPrincipal, aCx, aArgc, aRetval)
-      : NS_ERROR_NULL_POINTER;
-  }
-  NS_IMETHOD GetContent(mozIDOMWindowProxy** aContent) override;
-  NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) override;
-  NS_IMETHOD GetTabEventTarget(nsIEventTarget** aTarget) override;
-
-  nsresult AddEventListener(const nsAString& aType,
-                            nsIDOMEventListener* aListener,
-                            bool aUseCapture)
-  {
-    // By default add listeners only for trusted events!
-    return DOMEventTargetHelper::AddEventListener(aType, aListener,
-                                                  aUseCapture, false, 2);
-  }
-  using DOMEventTargetHelper::AddEventListener;
-  NS_IMETHOD AddEventListener(const nsAString& aType,
-                              nsIDOMEventListener* aListener,
-                              bool aUseCapture, bool aWantsUntrusted,
-                              uint8_t optional_argc) override
-  {
-    return DOMEventTargetHelper::AddEventListener(aType, aListener,
-                                                  aUseCapture,
-                                                  aWantsUntrusted,
-                                                  optional_argc);
-  }
+  NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
 
   nsresult
   GetEventTargetParent(EventChainPreVisitor& aVisitor) override
   {
     aVisitor.mForceContentDispatch = true;
     return NS_OK;
   }
 
   virtual nsIPrincipal* GetPrincipal() override;
   virtual JSObject* GetGlobalJSObject() override;
 
-  virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override
-  {
-    MOZ_CRASH("TabChildGlobal doesn't use DOM bindings!");
-  }
-
   // Dispatch a runnable related to the global.
   virtual nsresult Dispatch(mozilla::TaskCategory aCategory,
                             already_AddRefed<nsIRunnable>&& aRunnable) override;
 
   virtual nsISerialEventTarget*
   EventTargetFor(mozilla::TaskCategory aCategory) const override;
 
   virtual AbstractThread*
   AbstractMainThreadFor(mozilla::TaskCategory aCategory) override;
 
-  nsCOMPtr<nsIContentFrameMessageManager> mMessageManager;
   RefPtr<TabChild> mTabChild;
 
 protected:
   ~TabChildGlobal();
 };
 
 class ContentListener final : public nsIDOMEventListener
 {
@@ -197,16 +159,23 @@ protected:
   typedef mozilla::widget::PuppetWidget PuppetWidget;
 
 public:
   TabChildBase();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TabChildBase)
 
+  virtual bool WrapGlobalObject(JSContext* aCx,
+                                JS::CompartmentOptions& aOptions,
+                                JS::MutableHandle<JSObject*> aReflector) override
+  {
+    return mTabChildGlobal->WrapGlobalObject(aCx, aOptions, aReflector);
+  }
+
   virtual nsIWebNavigation* WebNavigation() const = 0;
   virtual PuppetWidget* WebWidget() = 0;
   nsIPrincipal* GetPrincipal() { return mPrincipal; }
   virtual bool DoUpdateZoomConstraints(const uint32_t& aPresShellId,
                                        const mozilla::layers::FrameMetrics::ViewID& aViewId,
                                        const Maybe<mozilla::layers::ZoomConstraints>& aConstraints) = 0;
 
   virtual ScreenIntSize GetInnerSize() = 0;
--- a/dom/webidl/LegacyQueryInterface.webidl
+++ b/dom/webidl/LegacyQueryInterface.webidl
@@ -21,16 +21,18 @@ interface LegacyQueryInterface {
 Attr implements LegacyQueryInterface;
 BarProp implements LegacyQueryInterface;
 BoxObject implements LegacyQueryInterface;
 CaretPosition implements LegacyQueryInterface;
 ChildProcessMessageManager implements LegacyQueryInterface;
 ChromeMessageBroadcaster implements LegacyQueryInterface;
 ChromeMessageSender implements LegacyQueryInterface;
 Comment implements LegacyQueryInterface;
+ContentFrameMessageManager implements LegacyQueryInterface;
+ContentProcessMessageManager implements LegacyQueryInterface;
 Crypto implements LegacyQueryInterface;
 CSSMozDocumentRule implements LegacyQueryInterface;
 CSSPrimitiveValue implements LegacyQueryInterface;
 CSSStyleDeclaration implements LegacyQueryInterface;
 CSSStyleRule implements LegacyQueryInterface;
 CSSValueList implements LegacyQueryInterface;
 DOMImplementation implements LegacyQueryInterface;
 DOMParser implements LegacyQueryInterface;
--- a/dom/webidl/MessageManager.webidl
+++ b/dom/webidl/MessageManager.webidl
@@ -1,14 +1,15 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 interface MozFrameLoader;
+interface nsIEventTarget;
 interface Principal;
 
 dictionary ReceiveMessageArgument
 {
   /**
    * The target of the message. Either an element owning the message manager, or message
    * manager itself if no element owns it.
    */
@@ -190,16 +191,41 @@ interface SyncMessageSender : MessageSen
 };
 
 [ChromeOnly]
 interface ChildProcessMessageManager : SyncMessageSender
 {
 };
 
 [NoInterfaceObject]
+interface MessageManagerGlobal : SyncMessageSender
+{
+  /**
+   * Print a string to stdout.
+   */
+  [Throws]
+  void dump(DOMString str);
+
+  /**
+   * If leak detection is enabled, print a note to the leak log that this
+   * process will intentionally crash.
+   */
+  [Throws]
+  void privateNoteIntentionalCrash();
+
+  /**
+   * Ascii base64 data to binary data and vice versa
+   */
+  [Throws]
+  DOMString atob(DOMString asciiString);
+  [Throws]
+  DOMString btoa(DOMString base64Data);
+};
+
+[NoInterfaceObject]
 interface FrameScriptLoader
 {
   /**
    * Load a script in the (remote) frame. |url| must be the absolute URL.
    * data: URLs are also supported. For example data:,dump("foo\n");
    * If allowDelayedLoad is true, script will be loaded when the
    * remote frame becomes available. Otherwise the script will be loaded
    * only if the frame is already available.
@@ -263,16 +289,57 @@ interface GlobalProcessScriptLoader : Pr
    * This value will always be a JS object if it's not null or undefined. Different
    * users are expected to set properties on this object. The property name should be
    * unique enough that other Gecko consumers won't accidentally choose it.
    */
   [Throws]
   readonly attribute any initialProcessData;
 };
 
+[ChromeOnly, Global, NeedResolve]
+interface ContentFrameMessageManager : EventTarget
+{
+  /**
+   * The current top level window in the frame or null.
+   */
+  [Throws]
+  readonly attribute WindowProxy? content;
+
+  /**
+   * The top level docshell or null.
+   */
+  [Throws]
+  readonly attribute nsIDocShell? docShell;
+
+  /**
+   * Returns the SchedulerEventTarget corresponding to the TabGroup
+   * for this frame.
+   */
+  readonly attribute nsIEventTarget? tabEventTarget;
+};
+// MessageManagerGlobal inherits from SyncMessageSender, which is a real interface, not a
+// mixin. This will need to change when we implement mixins according to the current
+// WebIDL spec.
+ContentFrameMessageManager implements MessageManagerGlobal;
+
+[ChromeOnly, Global, NeedResolve]
+interface ContentProcessMessageManager
+{
+  /**
+   * Read out a copy of the object that was initialized in the parent
+   * process via ProcessScriptLoader.initialProcessData.
+   */
+  [Throws]
+  readonly attribute any initialProcessData;
+};
+// MessageManagerGlobal inherits from SyncMessageSender, which is a real interface, not a
+// mixin. This will need to change when we implement mixins according to the current
+// WebIDL spec.
+ContentProcessMessageManager implements MessageManagerGlobal;
+
 [ChromeOnly]
 interface ChromeMessageBroadcaster : MessageListenerManager
 {
   /**
    * Like |sendAsyncMessage()|, but also broadcasts this message to
    * all "child" message managers of this message manager.  See long
    * comment above for details.
    *