Bug 1480244: Part 4 - Make child message managers non-global objects. r=bz draft
authorKris Maglione <maglione.k@gmail.com>
Fri, 10 Aug 2018 14:03:18 -0700
changeset 828432 be076323bc70bf5d80261efe1504b4ae54497f98
parent 828431 93aa6a890d1a30dd044ad3d3c1acf69c82fcd9ce
child 828433 bc17120defb1e66071339f11a7e9fff3d47a95da
push id118679
push usermaglione.k@gmail.com
push dateFri, 10 Aug 2018 21:19:41 +0000
reviewersbz
bugs1480244
milestone63.0a1
Bug 1480244: Part 4 - Make child message managers non-global objects. r=bz This is mostly self-explanatory. However, the patch also contains some minor changes to frame scripts which expect to be able to call message manager methods with a null target object, which stops working when they stop being global objects. MozReview-Commit-ID: HDT2RvK3F3L
browser/components/sessionstore/test/browser_send_async_message_oom.js
dom/base/ContentFrameMessageManager.cpp
dom/base/ContentFrameMessageManager.h
dom/base/ContentProcessMessageManager.cpp
dom/base/ContentProcessMessageManager.h
dom/base/InProcessTabChildMessageManager.cpp
dom/base/InProcessTabChildMessageManager.h
dom/base/MessageListenerManager.cpp
dom/base/moz.build
dom/base/nsFrameMessageManager.cpp
dom/base/nsFrameMessageManager.h
dom/chrome-webidl/MessageManager.webidl
dom/ipc/ContentChild.cpp
dom/ipc/SharedMap.cpp
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
testing/marionette/listener.js
--- a/browser/components/sessionstore/test/browser_send_async_message_oom.js
+++ b/browser/components/sessionstore/test/browser_send_async_message_oom.js
@@ -24,18 +24,18 @@ function frameScript() {
     return function(name, ...args) {
       if (name != "SessionStore:update") {
         return original(name, ...args);
       }
       throw new Components.Exception("Simulated OOM", Cr.NS_ERROR_OUT_OF_MEMORY);
     };
   };
 
-  mm.sendAsyncMessage = wrap(mm.sendAsyncMessage);
-  mm.sendSyncMessage = wrap(mm.sendSyncMessage);
+  mm.sendAsyncMessage = wrap(mm.sendAsyncMessage.bind(mm));
+  mm.sendSyncMessage = wrap(mm.sendSyncMessage.bind(mm));
 }
 
 add_task(async function() {
   // Capture original state.
   let snapshot = Services.telemetry.getHistogramById(HISTOGRAM_NAME).snapshot();
 
   // Open a browser, configure it to cause OOM.
   let newTab = BrowserTestUtils.addTab(gBrowser, "about:robots");
new file mode 100644
--- /dev/null
+++ b/dom/base/ContentFrameMessageManager.cpp
@@ -0,0 +1,25 @@
+/* -*- 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 "ContentFrameMessageManager.h"
+#include "mozilla/dom/ScriptSettings.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+JSObject*
+ContentFrameMessageManager::GetOrCreateWrapper()
+{
+  AutoJSAPI jsapi;
+  jsapi.Init();
+
+  JS::RootedValue val(jsapi.cx());
+  if (!GetOrCreateDOMReflectorNoWrap(jsapi.cx(), this, &val)) {
+    return nullptr;
+  }
+  MOZ_ASSERT(val.isObject());
+  return &val.toObject();
+}
--- a/dom/base/ContentFrameMessageManager.h
+++ b/dom/base/ContentFrameMessageManager.h
@@ -6,71 +6,51 @@
 
 #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"
+#include "xpcpublic.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);
-  }
-
   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;
   }
 
+  JSObject* GetOrCreateWrapper();
+
 protected:
   explicit ContentFrameMessageManager(nsFrameMessageManager* aMessageManager)
-    : MessageManagerGlobal(aMessageManager)
+    : DOMEventTargetHelper(xpc::NativeGlobal(xpc::PrivilegedJunkScope()))
+    , MessageManagerGlobal(aMessageManager)
   {}
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_ContentFrameMessageManager_h
--- a/dom/base/ContentProcessMessageManager.cpp
+++ b/dom/base/ContentProcessMessageManager.cpp
@@ -6,16 +6,17 @@
 
 #include "ContentProcessMessageManager.h"
 
 #include "nsContentCID.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/MessageManagerBinding.h"
 #include "mozilla/dom/ParentProcessMessageManager.h"
 #include "mozilla/dom/ResolveSystemBinding.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/ipc/SharedMap.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 bool ContentProcessMessageManager::sWasCreated = false;
 
 ContentProcessMessageManager::ContentProcessMessageManager(nsFrameMessageManager* aMessageManager)
@@ -26,58 +27,25 @@ ContentProcessMessageManager::ContentPro
 }
 
 ContentProcessMessageManager::~ContentProcessMessageManager()
 {
   mAnonymousGlobalScopes.Clear();
   mozilla::DropJSObjects(this);
 }
 
-bool
-ContentProcessMessageManager::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
-ContentProcessMessageManager::MayResolve(jsid aId)
-{
-  return MayResolveAsSystemBindingName(aId);
-}
-
-void
-ContentProcessMessageManager::GetOwnPropertyNames(JSContext* aCx, JS::AutoIdVector& aNames,
-                                                  bool aEnumerableOnly, ErrorResult& aRv)
-{
-  JS::Rooted<JSObject*> thisObj(aCx, GetWrapper());
-  GetSystemBindingNames(aCx, thisObj, aNames, aEnumerableOnly, aRv);
-}
-
 ContentProcessMessageManager*
 ContentProcessMessageManager::Get()
 {
-  nsCOMPtr<nsIGlobalObject> service = do_GetService(NS_CHILDPROCESSMESSAGEMANAGER_CONTRACTID);
+  nsCOMPtr<nsIMessageSender> service = do_GetService(NS_CHILDPROCESSMESSAGEMANAGER_CONTRACTID);
   if (!service) {
     return nullptr;
   }
-  ContentProcessMessageManager* global = static_cast<ContentProcessMessageManager*>(service.get());
-  if (global) {
-    sWasCreated = true;
-  }
-  return global;
+  sWasCreated = true;
+  return static_cast<ContentProcessMessageManager*>(service.get());
 }
 
 already_AddRefed<mozilla::dom::ipc::SharedMap>
 ContentProcessMessageManager::SharedData()
 {
   if (ContentChild* child = ContentChild::GetSingleton()) {
     return do_AddRef(child->SharedData());
   }
@@ -97,74 +65,75 @@ ContentProcessMessageManager::MarkForCC(
   MarkScopesForCC();
   MessageManagerGlobal::MarkForCC();
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(ContentProcessMessageManager)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ContentProcessMessageManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
-  tmp->TraverseHostObjectURIs(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ContentProcessMessageManager)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
   tmp->nsMessageManagerScriptExecutor::Trace(aCallbacks, aClosure);
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ContentProcessMessageManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
   tmp->nsMessageManagerScriptExecutor::Unlink();
-  tmp->UnlinkHostObjectURIs();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ContentProcessMessageManager)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
-  NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
-  NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(ContentProcessMessageManager)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(ContentProcessMessageManager)
 
 bool
 ContentProcessMessageManager::Init()
 {
   if (mInitialized) {
     return true;
   }
   mInitialized = true;
 
-  return InitChildGlobalInternal(NS_LITERAL_CSTRING("processChildGlobal"));
+  return nsMessageManagerScriptExecutor::Init();
+}
+
+JSObject*
+ContentProcessMessageManager::WrapObject(JSContext* aCx,
+                                         JS::Handle<JSObject*> aGivenProto)
+{
+  return ContentProcessMessageManager_Binding::Wrap(aCx, this, aGivenProto);
 }
 
-bool
-ContentProcessMessageManager::WrapGlobalObject(JSContext* aCx,
-                                               JS::RealmOptions& aOptions,
-                                               JS::MutableHandle<JSObject*> aReflector)
+JSObject*
+ContentProcessMessageManager::GetOrCreateWrapper()
 {
-  bool ok = ContentProcessMessageManager_Binding::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));
+  AutoJSAPI jsapi;
+  jsapi.Init();
+
+  JS::RootedValue val(jsapi.cx());
+  if (!GetOrCreateDOMReflectorNoWrap(jsapi.cx(), this, &val)) {
+    return nullptr;
   }
-  return ok;
+  return &val.toObject();
 }
 
 void
 ContentProcessMessageManager::LoadScript(const nsAString& aURL)
 {
   Init();
-  JS::Rooted<JSObject*> global(mozilla::dom::RootingCx(), GetWrapper());
-  LoadScriptInternal(global, aURL, false);
+  JS::Rooted<JSObject*> messageManager(mozilla::dom::RootingCx(), GetOrCreateWrapper());
+  LoadScriptInternal(messageManager, aURL, true);
 }
 
 void
 ContentProcessMessageManager::SetInitialProcessData(JS::HandleValue aInitialData)
 {
   mMessageManager->SetInitialProcessData(aInitialData);
 }
--- a/dom/base/ContentProcessMessageManager.h
+++ b/dom/base/ContentProcessMessageManager.h
@@ -7,25 +7,23 @@
 #ifndef mozilla_dom_ContentProcessMessageManager_h
 #define mozilla_dom_ContentProcessMessageManager_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"
-#include "nsIScriptObjectPrincipal.h"
 #include "nsServiceManagerUtils.h"
 #include "nsWeakReference.h"
 #include "nsWrapperCache.h"
+#include "xpcpublic.h"
 
 namespace mozilla {
 namespace dom {
 
 namespace ipc {
   class SharedMap;
 }
 
@@ -34,54 +32,41 @@ namespace ipc {
  * processes. Each child process has exactly one instance of this class, which
  * hosts the process's process scripts, and may exchange messages with its
  * corresponding ParentProcessMessageManager on the parent side.
  */
 
 class ContentProcessMessageManager :
   public nsIMessageSender,
   public nsMessageManagerScriptExecutor,
-  public nsIGlobalObject,
-  public nsIScriptObjectPrincipal,
   public nsSupportsWeakReference,
   public ipc::MessageManagerCallback,
   public MessageManagerGlobal,
   public nsWrapperCache
 {
 public:
   explicit ContentProcessMessageManager(nsFrameMessageManager* aMessageManager);
 
-  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;
   using MessageManagerGlobal::GetProcessMessageManager;
 
   bool Init();
 
   static ContentProcessMessageManager* Get();
   static bool WasCreated();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(ContentProcessMessageManager, nsIMessageSender)
 
   void MarkForCC();
 
   virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override
-  {
-    MOZ_CRASH("We should never get here!");
-  }
-  virtual bool WrapGlobalObject(JSContext* aCx,
-                                JS::RealmOptions& aOptions,
-                                JS::MutableHandle<JSObject*> aReflector) override;
+                               JS::Handle<JSObject*> aGivenProto) override;
+
+  JSObject* GetOrCreateWrapper();
 
   using MessageManagerGlobal::AddMessageListener;
   using MessageManagerGlobal::RemoveMessageListener;
   using MessageManagerGlobal::AddWeakMessageListener;
   using MessageManagerGlobal::RemoveWeakMessageListener;
 
   // ContentProcessMessageManager
   void GetInitialProcessData(JSContext* aCx,
@@ -94,23 +79,19 @@ public:
     }
     mMessageManager->GetInitialProcessData(aCx, aInitialProcessData, aError);
   }
 
   already_AddRefed<ipc::SharedMap> SharedData();
 
   NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
 
-  virtual void LoadScript(const nsAString& aURL);
+  nsIGlobalObject* GetParentObject() const { return xpc::NativeGlobal(xpc::PrivilegedJunkScope()); }
 
-  virtual JSObject* GetGlobalJSObject() override
-  {
-    return GetWrapper();
-  }
-  virtual nsIPrincipal* GetPrincipal() override { return mPrincipal; }
+  virtual void LoadScript(const nsAString& aURL);
 
   bool IsProcessScoped() const override
   {
     return true;
   }
 
   void SetInitialProcessData(JS::HandleValue aInitialData);
 
--- a/dom/base/InProcessTabChildMessageManager.cpp
+++ b/dom/base/InProcessTabChildMessageManager.cpp
@@ -118,81 +118,51 @@ InProcessTabChildMessageManager::~InProc
 // the IDL binding doesn't know what value to return.
 void
 InProcessTabChildMessageManager::MarkForCC()
 {
   MarkScopesForCC();
   MessageManagerGlobal::MarkForCC();
 }
 
-bool
-InProcessTabChildMessageManager::Init()
-{
-  // If you change this, please change GetCompartmentName() in XPCJSContext.cpp
-  // accordingly.
-  nsAutoCString id;
-  id.AssignLiteral("inProcessTabChildGlobal");
-  nsIURI* uri = mOwner->OwnerDoc()->GetDocumentURI();
-  if (uri) {
-    nsAutoCString u;
-    nsresult rv = uri->GetSpec(u);
-    NS_ENSURE_SUCCESS(rv, false);
-    id.AppendLiteral("?ownedBy=");
-    id.Append(u);
-  }
-  return InitChildGlobalInternal(id);
-}
-
 NS_IMPL_CYCLE_COLLECTION_CLASS(InProcessTabChildMessageManager)
 
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(InProcessTabChildMessageManager,
                                                   DOMEventTargetHelper)
    NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
    NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)
-   tmp->TraverseHostObjectURIs(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(InProcessTabChildMessageManager,
                                                DOMEventTargetHelper)
   tmp->nsMessageManagerScriptExecutor::Trace(aCallbacks, aClosure);
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(InProcessTabChildMessageManager,
                                                 DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)
   tmp->nsMessageManagerScriptExecutor::Unlink();
-  tmp->UnlinkHostObjectURIs();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InProcessTabChildMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
-  NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
-  NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(InProcessTabChildMessageManager, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(InProcessTabChildMessageManager, DOMEventTargetHelper)
 
-bool
-InProcessTabChildMessageManager::WrapGlobalObject(JSContext* aCx,
-                                                  JS::RealmOptions& aOptions,
-                                                  JS::MutableHandle<JSObject*> aReflector)
+JSObject*
+InProcessTabChildMessageManager::WrapObject(JSContext* aCx,
+                                            JS::Handle<JSObject*> aGivenProto)
 {
-  bool ok = ContentFrameMessageManager_Binding::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;
+  return ContentFrameMessageManager_Binding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 InProcessTabChildMessageManager::CacheFrameLoader(nsFrameLoader* aFrameLoader)
 {
   mFrameLoader = aFrameLoader;
 }
 
@@ -348,18 +318,18 @@ void
 InProcessTabChildMessageManager::LoadFrameScript(const nsAString& aURL, bool aRunInGlobalScope)
 {
   if (!nsContentUtils::IsSafeToRunScript()) {
     nsContentUtils::AddScriptRunner(new nsAsyncScriptLoad(this, aURL, aRunInGlobalScope));
     return;
   }
   bool tmp = mLoadingScript;
   mLoadingScript = true;
-  JS::Rooted<JSObject*> global(mozilla::dom::RootingCx(), GetWrapper());
-  LoadScriptInternal(global, aURL, aRunInGlobalScope);
+  JS::Rooted<JSObject*> mm(mozilla::dom::RootingCx(), GetOrCreateWrapper());
+  LoadScriptInternal(mm, aURL, !aRunInGlobalScope);
   mLoadingScript = tmp;
 }
 
 already_AddRefed<nsFrameLoader>
 InProcessTabChildMessageManager::GetFrameLoader()
 {
   nsCOMPtr<nsIFrameLoaderOwner> owner = do_QueryInterface(mOwner);
   RefPtr<nsFrameLoader> fl = owner ? owner->GetFrameLoader() : nullptr;
--- a/dom/base/InProcessTabChildMessageManager.h
+++ b/dom/base/InProcessTabChildMessageManager.h
@@ -15,74 +15,62 @@
 #include "nsFrameMessageManager.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsIClassInfo.h"
 #include "nsIDocShell.h"
 #include "nsCOMArray.h"
 #include "nsIRunnable.h"
-#include "nsIGlobalObject.h"
-#include "nsIScriptObjectPrincipal.h"
 #include "nsWeakReference.h"
 
 namespace mozilla {
 class EventChainPreVisitor;
 
 namespace dom {
 
 /**
  * This class implements a ContentFrameMessageManager for use by frame loaders
  * in the parent process. It is bound to a DocShell rather than a TabChild, and
  * does not use any IPC infrastructure for its message passing.
  */
 
 class InProcessTabChildMessageManager final : public ContentFrameMessageManager,
                                               public nsMessageManagerScriptExecutor,
                                               public nsIInProcessContentFrameMessageManager,
-                                              public nsIGlobalObject,
-                                              public nsIScriptObjectPrincipal,
                                               public nsSupportsWeakReference,
                                               public mozilla::dom::ipc::MessageManagerCallback
 {
   typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData;
 
 private:
   InProcessTabChildMessageManager(nsIDocShell* aShell, nsIContent* aOwner,
                                   nsFrameMessageManager* aChrome);
 
-  bool Init();
-
 public:
   static already_AddRefed<InProcessTabChildMessageManager> Create(nsIDocShell* aShell,
                                                                   nsIContent* aOwner,
                                                                   nsFrameMessageManager* aChrome)
   {
-    RefPtr<InProcessTabChildMessageManager> global =
+    RefPtr<InProcessTabChildMessageManager> mm =
       new InProcessTabChildMessageManager(aShell, aOwner, aChrome);
 
-    NS_ENSURE_TRUE(global->Init(), nullptr);
+    NS_ENSURE_TRUE(mm->Init(), nullptr);
 
-    return global.forget();
+    return mm.forget();
   }
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(InProcessTabChildMessageManager,
                                                          DOMEventTargetHelper)
 
   void MarkForCC();
 
   virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override
-  {
-    MOZ_CRASH("We should never get here!");
-  }
-  virtual bool WrapGlobalObject(JSContext* aCx,
-                                JS::RealmOptions& aOptions,
-                                JS::MutableHandle<JSObject*> aReflector) override;
+                               JS::Handle<JSObject*> aGivenProto) override;
 
   virtual already_AddRefed<nsPIDOMWindowOuter>
     GetContent(ErrorResult& aError) override;
   virtual already_AddRefed<nsIDocShell>
     GetDocShell(ErrorResult& aError) override
   {
     nsCOMPtr<nsIDocShell> docShell(mDocShell);
     return docShell.forget();
@@ -109,17 +97,16 @@ public:
   virtual nsresult DoSendAsyncMessage(JSContext* aCx,
                                       const nsAString& aMessage,
                                       StructuredCloneData& aData,
                                       JS::Handle<JSObject *> aCpows,
                                       nsIPrincipal* aPrincipal) override;
 
   void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
 
-  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,
                            nsTArray<nsString>* aJSONRetVal);
   nsFrameMessageManager* GetInnerManager()
@@ -132,21 +119,16 @@ public:
   {
     return mChromeMessageManager;
   }
   void SetChromeMessageManager(nsFrameMessageManager* aParent)
   {
     mChromeMessageManager = aParent;
   }
 
-  virtual JSObject* GetGlobalJSObject() override
-  {
-    return GetWrapper();
-  }
-
   already_AddRefed<nsFrameLoader> GetFrameLoader();
 
 protected:
   virtual ~InProcessTabChildMessageManager();
 
   nsCOMPtr<nsIDocShell> mDocShell;
   bool mLoadingScript;
 
--- a/dom/base/MessageListenerManager.cpp
+++ b/dom/base/MessageListenerManager.cpp
@@ -1,15 +1,16 @@
 /* -*- 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/MessageListenerManager.h"
+#include "mozilla/dom/MessageBroadcaster.h"
 
 namespace mozilla {
 namespace dom {
 
 MessageListenerManager::MessageListenerManager(ipc::MessageManagerCallback* aCallback,
                                                MessageBroadcaster* aParentManager,
                                                ipc::MessageManagerFlags aFlags)
   : nsFrameMessageManager(aCallback, aFlags),
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -243,16 +243,17 @@ UNIFIED_SOURCES += [
     'BorrowedAttrInfo.cpp',
     'CharacterData.cpp',
     'ChildIterator.cpp',
     'ChromeMessageBroadcaster.cpp',
     'ChromeMessageSender.cpp',
     'ChromeNodeList.cpp',
     'ChromeUtils.cpp',
     'Comment.cpp',
+    'ContentFrameMessageManager.cpp',
     'ContentProcessMessageManager.cpp',
     'Crypto.cpp',
     'CustomElementRegistry.cpp',
     'DirectionalityUtils.cpp',
     'DispatcherTrait.cpp',
     'DocGroup.cpp',
     'DocumentFragment.cpp',
     'DocumentOrShadowRoot.cpp',
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -1242,17 +1242,17 @@ NS_NewGlobalMessageManager(nsISupports**
   return NS_OK;
 }
 
 nsDataHashtable<nsStringHashKey, nsMessageManagerScriptHolder*>*
   nsMessageManagerScriptExecutor::sCachedScripts = nullptr;
 StaticRefPtr<nsScriptCacheCleaner> nsMessageManagerScriptExecutor::sScriptCacheCleaner;
 
 void
-nsMessageManagerScriptExecutor::DidCreateGlobal()
+nsMessageManagerScriptExecutor::DidCreateScriptLoader()
 {
   if (!sCachedScripts) {
     sCachedScripts =
       new nsDataHashtable<nsStringHashKey, nsMessageManagerScriptHolder*>;
     sScriptCacheCleaner = new nsScriptCacheCleaner();
   }
 }
 
@@ -1278,64 +1278,65 @@ nsMessageManagerScriptExecutor::Shutdown
 
     delete sCachedScripts;
     sCachedScripts = nullptr;
     sScriptCacheCleaner = nullptr;
   }
 }
 
 void
-nsMessageManagerScriptExecutor::LoadScriptInternal(JS::Handle<JSObject*> aGlobal,
+nsMessageManagerScriptExecutor::LoadScriptInternal(JS::Handle<JSObject*> aMessageManager,
                                                    const nsAString& aURL,
-                                                   bool aRunInGlobalScope)
+                                                   bool aRunInUniqueScope)
 {
   AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(
     "nsMessageManagerScriptExecutor::LoadScriptInternal", OTHER, aURL);
 
   if (!sCachedScripts) {
     return;
   }
 
   JS::RootingContext* rcx = RootingCx();
   JS::Rooted<JSScript*> script(rcx);
 
   nsMessageManagerScriptHolder* holder = sCachedScripts->Get(aURL);
-  if (holder && holder->WillRunInGlobalScope() == aRunInGlobalScope) {
+  if (holder) {
     script = holder->mScript;
   } 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, aGlobal, &script);
+    TryCacheLoadAndCompileScript(aURL, aRunInUniqueScope, true,
+                                 aMessageManager, &script);
   }
 
-  AutoEntryScript aes(aGlobal, "message manager script load");
+  AutoEntryScript aes(aMessageManager, "message manager script load");
   JSContext* cx = aes.cx();
   if (script) {
-    if (aRunInGlobalScope) {
-      JS::RootedValue rval(cx);
-      JS::CloneAndExecuteScript(cx, script, &rval);
-    } else {
+    if (aRunInUniqueScope) {
       JS::Rooted<JSObject*> scope(cx);
-      bool ok = js::ExecuteInFrameScriptEnvironment(cx, aGlobal, script, &scope);
+      bool ok = js::ExecuteInFrameScriptEnvironment(cx, aMessageManager, script, &scope);
       if (ok) {
         // Force the scope to stay alive.
         mAnonymousGlobalScopes.AppendElement(scope);
       }
+    } else {
+      JS::RootedValue rval(cx);
+      JS::AutoObjectVector envChain(cx);
+      if (!envChain.append(aMessageManager)) {
+        return;
+      }
+      JS::CloneAndExecuteScript(cx, envChain, script, &rval);
     }
   }
 }
 
 void
 nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
   const nsAString& aURL,
-  bool aRunInGlobalScope,
+  bool aRunInUniqueScope,
   bool aShouldCache,
-  JS::Handle<JSObject*> aGlobal,
+  JS::Handle<JSObject*> aMessageManager,
   JS::MutableHandle<JSScript*> aScriptp)
 {
   nsCString url = NS_ConvertUTF16toUTF8(aURL);
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
   if (NS_FAILED(rv)) {
     return;
   }
@@ -1354,17 +1355,17 @@ nsMessageManagerScriptExecutor::TryCache
   // scripts can be compiled directly for the target global, and will be dropped
   // from the preloader cache after they're executed and serialized.
   bool isRunOnce = !aShouldCache || IsProcessScoped();
 
   // If the script will be reused in this session, compile it in the compilation
   // scope instead of the current global to avoid keeping the current
   // compartment alive.
   AutoJSAPI jsapi;
-  if (!jsapi.Init(isRunOnce ? aGlobal : xpc::CompilationScope())) {
+  if (!jsapi.Init(isRunOnce ? aMessageManager : xpc::CompilationScope())) {
     return;
   }
   JSContext* cx = jsapi.cx();
   JS::Rooted<JSScript*> script(cx);
 
   script = ScriptPreloader::GetChildSingleton().GetCachedScript(cx, url);
 
   if (!script) {
@@ -1404,22 +1405,17 @@ nsMessageManagerScriptExecutor::TryCache
     if (!dataStringBuf || dataStringLength == 0) {
       return;
     }
 
     JS::CompileOptions options(cx);
     options.setFileAndLine(url.get(), 1);
     options.setNoScriptRval(true);
 
-    if (aRunInGlobalScope) {
-      if (!JS::Compile(cx, options, srcBuf, &script)) {
-        return;
-      }
-    // We're going to run these against some non-global scope.
-    } else if (!JS::CompileForNonSyntacticScope(cx, options, srcBuf, &script)) {
+    if (!JS::CompileForNonSyntacticScope(cx, options, srcBuf, &script)) {
       return;
     }
   }
 
   MOZ_ASSERT(script);
   aScriptp.set(script);
 
   nsAutoCString scheme;
@@ -1427,17 +1423,17 @@ nsMessageManagerScriptExecutor::TryCache
   // We don't cache data: scripts!
   if (aShouldCache && !scheme.EqualsLiteral("data")) {
     ScriptPreloader::GetChildSingleton().NoteScript(url, url, script, isRunOnce);
 
     // If this script will only run once per process, only cache it in the
     // preloader cache, not the session cache.
     if (!isRunOnce) {
       // Root the object also for caching.
-      auto* holder = new nsMessageManagerScriptHolder(cx, script, aRunInGlobalScope);
+      auto* holder = new nsMessageManagerScriptHolder(cx, script);
       sCachedScripts->Put(aURL, holder);
     }
   }
 }
 
 void
 nsMessageManagerScriptExecutor::Trace(const TraceCallbacks& aCallbacks, void* aClosure)
 {
@@ -1448,41 +1444,19 @@ nsMessageManagerScriptExecutor::Trace(co
 
 void
 nsMessageManagerScriptExecutor::Unlink()
 {
   ImplCycleCollectionUnlink(mAnonymousGlobalScopes);
 }
 
 bool
-nsMessageManagerScriptExecutor::InitChildGlobalInternal(const nsACString& aID)
+nsMessageManagerScriptExecutor::Init()
 {
-  AutoSafeJSContext cx;
-  if (!SystemBindingInitIds(cx)) {
-    return false;
-  }
-
-  nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
-
-  JS::RealmOptions options;
-  options.creationOptions().setNewCompartmentInSystemZone();
-
-  xpc::InitGlobalObjectOptions(options, mPrincipal);
-  JS::Rooted<JSObject*> global(cx);
-  if (!WrapGlobalObject(cx, options, &global)) {
-    return 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(global, aID);
-
-  DidCreateGlobal();
+  DidCreateScriptLoader();
   return true;
 }
 
 void
 nsMessageManagerScriptExecutor::MarkScopesForCC()
 {
   for (uint32_t i = 0; i < mAnonymousGlobalScopes.Length(); ++i) {
     mAnonymousGlobalScopes[i].exposeToActiveJS();
--- a/dom/base/nsFrameMessageManager.h
+++ b/dom/base/nsFrameMessageManager.h
@@ -402,54 +402,47 @@ private:
 #endif
 };
 
 class nsScriptCacheCleaner;
 
 struct nsMessageManagerScriptHolder
 {
   nsMessageManagerScriptHolder(JSContext* aCx,
-                               JSScript* aScript,
-                               bool aRunInGlobalScope)
-   : mScript(aCx, aScript), mRunInGlobalScope(aRunInGlobalScope)
+                               JSScript* aScript)
+   : mScript(aCx, aScript)
   { MOZ_COUNT_CTOR(nsMessageManagerScriptHolder); }
 
   ~nsMessageManagerScriptHolder()
   { MOZ_COUNT_DTOR(nsMessageManagerScriptHolder); }
 
-  bool WillRunInGlobalScope() { return mRunInGlobalScope; }
-
   JS::PersistentRooted<JSScript*> mScript;
-  bool mRunInGlobalScope;
 };
 
 class nsMessageManagerScriptExecutor
 {
 public:
   static void PurgeCache();
   static void Shutdown();
 
   void MarkScopesForCC();
 protected:
   friend class nsMessageManagerScriptCx;
   nsMessageManagerScriptExecutor() { MOZ_COUNT_CTOR(nsMessageManagerScriptExecutor); }
   ~nsMessageManagerScriptExecutor() { MOZ_COUNT_DTOR(nsMessageManagerScriptExecutor); }
 
-  void DidCreateGlobal();
-  void LoadScriptInternal(JS::Handle<JSObject*> aGlobal, const nsAString& aURL,
-                          bool aRunInGlobalScope);
+  void DidCreateScriptLoader();
+  void LoadScriptInternal(JS::Handle<JSObject*> aMessageManager, const nsAString& aURL,
+                          bool aRunInUniqueScope);
   void TryCacheLoadAndCompileScript(const nsAString& aURL,
-                                    bool aRunInGlobalScope,
+                                    bool aRunInUniqueScope,
                                     bool aShouldCache,
-                                    JS::Handle<JSObject*> aGlobal,
+                                    JS::Handle<JSObject*> aMessageManager,
                                     JS::MutableHandle<JSScript*> aScriptp);
-  bool InitChildGlobalInternal(const nsACString& aID);
-  virtual bool WrapGlobalObject(JSContext* aCx,
-                                JS::RealmOptions& aOptions,
-                                JS::MutableHandle<JSObject*> aReflector) = 0;
+  bool Init();
   void Trace(const TraceCallbacks& aCallbacks, void* aClosure);
   void Unlink();
   nsCOMPtr<nsIPrincipal> mPrincipal;
   AutoTArray<JS::Heap<JSObject*>, 2> mAnonymousGlobalScopes;
 
   // Returns true if this is a process message manager. There should only be a
   // single process message manager per session, so instances of this type will
   // optimize their script loading to avoid unnecessary duplication.
--- a/dom/chrome-webidl/MessageManager.webidl
+++ b/dom/chrome-webidl/MessageManager.webidl
@@ -456,17 +456,17 @@ interface GlobalProcessScriptLoader : Pr
    * unique enough that other Gecko consumers won't accidentally choose it.
    */
   [Throws]
   readonly attribute any initialProcessData;
 
   readonly attribute MozWritableSharedMap sharedData;
 };
 
-[ChromeOnly, Global, NeedResolve]
+[ChromeOnly]
 interface ContentFrameMessageManager : EventTarget
 {
   /**
    * The current top level window in the frame or null.
    */
   [Throws]
   readonly attribute WindowProxy? content;
 
@@ -490,17 +490,17 @@ interface ContentFrameMessageManager : E
   readonly attribute long long chromeOuterWindowID;
 
 };
 // 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]
+[ChromeOnly]
 interface ContentProcessMessageManager
 {
   /**
    * Read out a copy of the object that was initialized in the parent
    * process via ProcessScriptLoader.initialProcessData.
    */
   [Throws]
   readonly attribute any initialProcessData;
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2600,18 +2600,18 @@ ContentChild::RecvUpdateSharedData(const
     blobImpls.AppendElement(IPCBlobUtils::Deserialize(ipcBlob));
   }
 
   if (mSharedData) {
     mSharedData->Update(aMapFile, aMapSize,
                         std::move(blobImpls),
                         std::move(aChangedKeys));
   } else {
-    mSharedData = new SharedMap(ContentProcessMessageManager::Get(), aMapFile,
-                                aMapSize, std::move(blobImpls));
+    mSharedData = new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(),
+                                aMapFile, aMapSize, std::move(blobImpls));
   }
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ContentChild::RecvGeolocationUpdate(nsIDOMGeoPosition* aPosition)
 {
--- a/dom/ipc/SharedMap.cpp
+++ b/dom/ipc/SharedMap.cpp
@@ -280,17 +280,17 @@ WritableSharedMap::WritableSharedMap()
   MOZ_RELEASE_ASSERT(mMap.initialized());
 }
 
 SharedMap*
 WritableSharedMap::GetReadOnly()
 {
   if (!mReadOnly) {
     nsTArray<RefPtr<BlobImpl>> blobs(mBlobImpls);
-    mReadOnly = new SharedMap(ContentProcessMessageManager::Get(),
+    mReadOnly = new SharedMap(ContentProcessMessageManager::Get()->GetParentObject(),
                               CloneMapFile(), MapSize(), std::move(blobs));
   }
   return mReadOnly;
 }
 
 Result<Ok, nsresult>
 WritableSharedMap::Serialize()
 {
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -159,35 +159,35 @@ static const char BEFORE_FIRST_PAINT[] =
 
 nsTHashtable<nsPtrHashKey<TabChild>>* TabChild::sVisibleTabs;
 
 typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
 static TabChildMap* sTabChildren;
 StaticMutex sTabChildrenMutex;
 
 TabChildBase::TabChildBase()
-  : mTabChildGlobal(nullptr)
+  : mTabChildMessageManager(nullptr)
 {
 }
 
 TabChildBase::~TabChildBase()
 {
   mAnonymousGlobalScopes.Clear();
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(TabChildBase)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TabChildBase)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChildGlobal)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChildMessageManager)
   tmp->nsMessageManagerScriptExecutor::Unlink();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebBrowserChrome)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TabChildBase)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChildGlobal)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChildMessageManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebBrowserChrome)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(TabChildBase)
   tmp->nsMessageManagerScriptExecutor::Trace(aCallbacks, aClosure);
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildBase)
@@ -229,21 +229,21 @@ TabChildBase::DispatchMessageManagerMess
         ErrorResult rv;
         data.Write(cx, json, rv);
         if (NS_WARN_IF(rv.Failed())) {
             rv.SuppressException();
             return;
         }
     }
 
-    JS::Rooted<JSObject*> kungFuDeathGrip(cx, mTabChildGlobal->GetWrapper());
+    RefPtr<TabChildMessageManager> kungFuDeathGrip = mTabChildMessageManager;
     // Let the BrowserElementScrolling helper (if it exists) for this
     // content manipulate the frame state.
-    RefPtr<nsFrameMessageManager> mm = mTabChildGlobal->GetMessageManager();
-    mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal), nullptr,
+    RefPtr<nsFrameMessageManager> mm = mTabChildMessageManager->GetMessageManager();
+    mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildMessageManager), nullptr,
                        aMessageName, false, &data, nullptr, nullptr, nullptr,
                        IgnoreErrors());
 }
 
 bool
 TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics)
 {
   MOZ_ASSERT(aFrameMetrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID);
@@ -265,17 +265,17 @@ TabChildBase::UpdateFrameHandler(const F
     return true;
   }
   return true;
 }
 
 void
 TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
 {
-    if (!mTabChildGlobal) {
+    if (!mTabChildMessageManager) {
         return;
     }
 
     FrameMetrics newMetrics = aFrameMetrics;
     APZCCallbackHelper::UpdateRootFrame(newMetrics);
 }
 
 NS_IMETHODIMP
@@ -1104,25 +1104,25 @@ TabChild::DestroyWindow()
 
 void
 TabChild::ActorDestroy(ActorDestroyReason why)
 {
   mIPCOpen = false;
 
   DestroyWindow();
 
-  if (mTabChildGlobal) {
+  if (mTabChildMessageManager) {
     // 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->GetMessageManager());
-    if (mTabChildGlobal->GetMessageManager()) {
+    MOZ_DIAGNOSTIC_ASSERT(mTabChildMessageManager->GetMessageManager());
+    if (mTabChildMessageManager->GetMessageManager()) {
       // The messageManager relays messages via the TabChild which
       // no longer exists.
-      mTabChildGlobal->DisconnectMessageManager();
+      mTabChildMessageManager->DisconnectMessageManager();
     }
   }
 
   CompositorBridgeChild* compositorChild = CompositorBridgeChild::Get();
   if (compositorChild) {
     compositorChild->CancelNotifyAfterRemotePaint(this);
   }
 
@@ -1152,17 +1152,17 @@ TabChild::~TabChild()
 }
 
 mozilla::ipc::IPCResult
 TabChild::RecvLoadURL(const nsCString& aURI,
                       const ShowInfo& aInfo)
 {
   if (!mDidLoadURLInit) {
     mDidLoadURLInit = true;
-    if (!InitTabChildGlobal()) {
+    if (!InitTabChildMessageManager()) {
       return IPC_FAIL_NO_REASON(this);
     }
 
     ApplyShowInfo(aInfo);
   }
 
   nsresult rv =
     WebNavigation()->LoadURI(NS_ConvertUTF8toUTF16(aURI).get(),
@@ -1257,17 +1257,17 @@ TabChild::RecvShow(const ScreenIntSize& 
   if (!mDidFakeShow) {
     nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
     if (!baseWindow) {
         NS_ERROR("WebNavigation() doesn't QI to nsIBaseWindow");
         return IPC_FAIL_NO_REASON(this);
     }
 
     baseWindow->SetVisibility(true);
-    res = InitTabChildGlobal();
+    res = InitTabChildMessageManager();
   }
 
   ApplyShowInfo(aInfo);
   RecvParentActivated(aParentIsActive);
 
   if (!res) {
     return IPC_FAIL_NO_REASON(this);
   }
@@ -1357,20 +1357,20 @@ TabChild::RecvSuppressDisplayport(const 
 }
 
 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(),
-    mTabChildGlobal ? mTabChildGlobal->GetWrapper() : nullptr,
-    mTabChildGlobal.get());
-
-  if (!mTabChildGlobal || !mTabChildGlobal->GetWrapper()) {
+    mTabChildMessageManager ? mTabChildMessageManager->GetWrapper() : nullptr,
+    mTabChildMessageManager.get());
+
+  if (!mTabChildMessageManager) {
     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
@@ -1401,36 +1401,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 (mTabChildGlobal) {
+    if (mTabChildMessageManager) {
       mAPZEventState->ProcessSingleTap(point, scale, aModifiers, aGuid, 1);
     }
     break;
   case GeckoContentController::TapType::eDoubleTap:
     HandleDoubleTap(point, aModifiers, aGuid);
     break;
   case GeckoContentController::TapType::eSecondTap:
-    if (mTabChildGlobal) {
+    if (mTabChildMessageManager) {
       mAPZEventState->ProcessSingleTap(point, scale, aModifiers, aGuid, 2);
     }
     break;
   case GeckoContentController::TapType::eLongTap:
-    if (mTabChildGlobal) {
+    if (mTabChildMessageManager) {
       mAPZEventState->ProcessLongTap(presShell, point, scale, aModifiers, aGuid,
           aInputBlockId);
     }
     break;
   case GeckoContentController::TapType::eLongTapUp:
-    if (mTabChildGlobal) {
+    if (mTabChildMessageManager) {
       mAPZEventState->ProcessLongTapUp(presShell, point, scale, aModifiers);
     }
     break;
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
@@ -2295,59 +2295,59 @@ 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 (!InitTabChildGlobal())
+  if (!InitTabChildMessageManager())
     // This can happen if we're half-destroyed.  It's not a fatal
     // error.
     return IPC_OK();
 
-  JS::Rooted<JSObject*> global(RootingCx(), mTabChildGlobal->GetWrapper());
-  if (!global) {
+  JS::Rooted<JSObject*> mm(RootingCx(), mTabChildMessageManager->GetOrCreateWrapper());
+  if (!mm) {
     // This can happen if we're half-destroyed.  It's not a fatal error.
     return IPC_OK();
   }
 
-  LoadScriptInternal(global, aURL, aRunInGlobalScope);
+  LoadScriptInternal(mm, aURL, !aRunInGlobalScope);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabChild::RecvAsyncMessage(const nsString& aMessage,
                            InfallibleTArray<CpowEntry>&& aCpows,
                            const IPC::Principal& aPrincipal,
                            const ClonedMessageData& aData)
 {
   AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(
     "TabChild::RecvAsyncMessage", OTHER, aMessage);
 
   CrossProcessCpowHolder cpows(Manager(), aCpows);
-  if (!mTabChildGlobal) {
+  if (!mTabChildMessageManager) {
     return IPC_OK();
   }
 
-  RefPtr<nsFrameMessageManager> mm = mTabChildGlobal->GetMessageManager();
+  RefPtr<nsFrameMessageManager> mm = mTabChildMessageManager->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(mm);
   if (!mm) {
     return IPC_OK();
   }
 
-  JS::Rooted<JSObject*> kungFuDeathGrip(dom::RootingCx(), mTabChildGlobal->GetWrapper());
+  JS::Rooted<JSObject*> kungFuDeathGrip(dom::RootingCx(), mTabChildMessageManager->GetWrapper());
   StructuredCloneData data;
   UnpackClonedMessageDataForChild(aData, data);
-  mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal), nullptr,
+  mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildMessageManager), nullptr,
                      aMessage, false, &data, &cpows, aPrincipal, nullptr,
                      IgnoreErrors());
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabChild::RecvSwappedWithOtherRemoteLoader(const IPCTabContext& aContext)
 {
@@ -2505,21 +2505,21 @@ TabChild::RecvDestroy()
       nsContentPermissionUtils::GetContentPermissionRequestChildById(GetTabId());
 
   // Need to close undeleted ContentPermissionRequestChilds before tab is closed.
   for (auto& permissionRequestChild : childArray) {
       auto child = static_cast<RemotePermissionRequest*>(permissionRequestChild);
       child->Destroy();
   }
 
-  if (mTabChildGlobal) {
+  if (mTabChildMessageManager) {
     // Message handlers are called from the event loop, so it better be safe to
     // run script.
     MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
-    mTabChildGlobal->DispatchTrustedEvent(NS_LITERAL_STRING("unload"));
+    mTabChildMessageManager->DispatchTrustedEvent(NS_LITERAL_STRING("unload"));
   }
 
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
 
   observerService->RemoveObserver(this, BEFORE_FIRST_PAINT);
 
   // XXX what other code in ~TabChild() should we be running here?
@@ -2742,36 +2742,32 @@ TabChild::AllocPRenderFrameChild()
 bool
 TabChild::DeallocPRenderFrameChild(PRenderFrameChild* aFrame)
 {
     delete aFrame;
     return true;
 }
 
 bool
-TabChild::InitTabChildGlobal()
+TabChild::InitTabChildMessageManager()
 {
-  if (!mTabChildGlobal) {
+  if (!mTabChildMessageManager) {
     nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(WebNavigation());
     NS_ENSURE_TRUE(window, false);
     nsCOMPtr<EventTarget> chromeHandler =
       do_QueryInterface(window->GetChromeEventHandler());
     NS_ENSURE_TRUE(chromeHandler, false);
 
-    RefPtr<TabChildMessageManager> scope = mTabChildGlobal = new TabChildMessageManager(this);
-
-    NS_NAMED_LITERAL_CSTRING(globalId, "outOfProcessTabChildGlobal");
-    if (NS_WARN_IF(!InitChildGlobalInternal(globalId))) {
-        mTabChildGlobal = nullptr;
-        return false;
-    }
+    RefPtr<TabChildMessageManager> scope = mTabChildMessageManager = new TabChildMessageManager(this);
+
+    MOZ_ALWAYS_TRUE(nsMessageManagerScriptExecutor::Init());
 
     nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(chromeHandler);
     if (NS_WARN_IF(!root)) {
-        mTabChildGlobal = nullptr;
+        mTabChildMessageManager = nullptr;
         return false;
     }
     root->SetParentTarget(scope);
   }
 
   if (!mTriedBrowserInit) {
     mTriedBrowserInit = true;
     // Initialize the child side of the browser element machinery,
@@ -2990,17 +2986,17 @@ bool
 TabChild::IsVisible()
 {
   return mPuppetWidget && mPuppetWidget->IsVisible();
 }
 
 NS_IMETHODIMP
 TabChild::GetMessageManager(ContentFrameMessageManager** aResult)
 {
-  RefPtr<ContentFrameMessageManager> mm(mTabChildGlobal);
+  RefPtr<ContentFrameMessageManager> mm(mTabChildMessageManager);
   mm.forget(aResult);
   return *aResult ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 TabChild::GetWebBrowserChrome(nsIWebBrowserChrome3** aWebBrowserChrome)
 {
   NS_IF_ADDREF(*aWebBrowserChrome = mWebBrowserChrome);
@@ -3534,49 +3530,37 @@ TabChildMessageManager::~TabChildMessage
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(TabChildMessageManager)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TabChildMessageManager,
                                                 DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChild);
-  tmp->UnlinkHostObjectURIs();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TabChildMessageManager,
                                                   DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChild)
-  tmp->TraverseHostObjectURIs(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
-  NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
-  NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(TabChildMessageManager, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(TabChildMessageManager, DOMEventTargetHelper)
 
-bool
-TabChildMessageManager::WrapGlobalObject(JSContext* aCx,
-                                         JS::RealmOptions& aOptions,
-                                         JS::MutableHandle<JSObject*> aReflector)
+JSObject*
+TabChildMessageManager::WrapObject(JSContext* aCx,
+                                   JS::Handle<JSObject*> aGivenProto)
 {
-  bool ok = ContentFrameMessageManager_Binding::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;
+  return ContentFrameMessageManager_Binding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 TabChildMessageManager::MarkForCC()
 {
   if (mTabChild) {
     mTabChild->MarkScopesForCC();
   }
@@ -3621,31 +3605,16 @@ uint64_t
 TabChildMessageManager::ChromeOuterWindowID()
 {
   if (!mTabChild) {
     return 0;
   }
   return mTabChild->ChromeOuterWindowID();
 }
 
-nsIPrincipal*
-TabChildMessageManager::GetPrincipal()
-{
-  if (!mTabChild)
-    return nullptr;
-  return mTabChild->GetPrincipal();
-}
-
-JSObject*
-TabChildMessageManager::GetGlobalJSObject()
-{
-  NS_ENSURE_TRUE(mTabChild, nullptr);
-  return GetWrapper();
-}
-
 nsresult
 TabChildMessageManager::Dispatch(TaskCategory aCategory,
                          already_AddRefed<nsIRunnable>&& aRunnable)
 {
   if (mTabChild && mTabChild->TabGroup()) {
     return mTabChild->TabGroup()->Dispatch(aCategory, std::move(aRunnable));
   }
   return DispatcherTrait::Dispatch(aCategory, std::move(aRunnable));
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -18,17 +18,16 @@
 #include "nsIDOMEventListener.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIWindowProvider.h"
 #include "nsIDOMWindow.h"
 #include "nsIDocShell.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsFrameMessageManager.h"
 #include "nsIPresShell.h"
-#include "nsIScriptObjectPrincipal.h"
 #include "nsWeakReference.h"
 #include "nsITabChild.h"
 #include "nsITooltipListener.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/TabContext.h"
 #include "mozilla/dom/CoalescedMouseData.h"
 #include "mozilla/dom/CoalescedWheelData.h"
 #include "mozilla/DOMEventTargetHelper.h"
@@ -76,53 +75,43 @@ namespace dom {
 class TabChild;
 class TabGroup;
 class ClonedMessageData;
 class CoalescedMouseData;
 class CoalescedWheelData;
 
 class TabChildMessageManager : public ContentFrameMessageManager,
                                public nsIMessageSender,
-                               public nsIScriptObjectPrincipal,
-                               public nsIGlobalObject,
+                               public DispatcherTrait,
                                public nsSupportsWeakReference
 {
 public:
   explicit TabChildMessageManager(TabChild* aTabChild);
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TabChildMessageManager, DOMEventTargetHelper)
 
   void MarkForCC();
 
-  virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override
-  {
-    MOZ_CRASH("We should never get here!");
-  }
-  bool WrapGlobalObject(JSContext* aCx,
-                        JS::RealmOptions& aOptions,
-                        JS::MutableHandle<JSObject*> aReflector);
+  JSObject* WrapObject(JSContext* aCx,
+                       JS::Handle<JSObject*> aGivenProto) 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
   {
     aVisitor.mForceContentDispatch = true;
   }
 
-  virtual nsIPrincipal* GetPrincipal() override;
-  virtual JSObject* GetGlobalJSObject() override;
-
   // 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*
@@ -157,23 +146,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::RealmOptions& aOptions,
-                                JS::MutableHandle<JSObject*> aReflector) override
+  JSObject* WrapObject(JSContext* aCx,
+                       JS::Handle<JSObject*> aGivenProto)
   {
-    return mTabChildGlobal->WrapGlobalObject(aCx, aOptions, aReflector);
+    return mTabChildMessageManager->WrapObject(aCx, aGivenProto);
   }
 
+
   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;
@@ -195,17 +184,17 @@ protected:
   void DispatchMessageManagerMessage(const nsAString& aMessageName,
                                      const nsAString& aJSONData);
 
   void ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
 
   bool UpdateFrameHandler(const mozilla::layers::FrameMetrics& aFrameMetrics);
 
 protected:
-  RefPtr<TabChildMessageManager> mTabChildGlobal;
+  RefPtr<TabChildMessageManager> mTabChildMessageManager;
   nsCOMPtr<nsIWebBrowserChrome3> mWebBrowserChrome;
 };
 
 class TabChild final : public TabChildBase,
                        public PBrowserChild,
                        public nsIWebBrowserChrome2,
                        public nsIEmbeddingSiteWindow,
                        public nsIWebBrowserChromeFocus,
@@ -275,17 +264,17 @@ public:
   NS_DECL_NSITOOLTIPLISTENER
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(TabChild, TabChildBase)
 
   FORWARD_SHMEM_ALLOCATOR_TO(PBrowserChild)
 
   TabChildMessageManager* GetMessageManager()
   {
-    return mTabChildGlobal;
+    return mTabChildMessageManager;
   }
 
   /**
    * MessageManagerCallback methods that we override.
    */
   virtual bool DoSendBlockingMessage(JSContext* aCx,
                                      const nsAString& aMessage,
                                      StructuredCloneData& aData,
@@ -767,17 +756,17 @@ private:
   // @param aIsPreallocated  true if this is called for Preallocated Tab.
   void NotifyTabContextUpdated(bool aIsPreallocated);
 
   // Update the frameType on our docshell.
   void UpdateFrameType();
 
   void ActorDestroy(ActorDestroyReason why) override;
 
-  bool InitTabChildGlobal();
+  bool InitTabChildMessageManager();
 
   void InitRenderingState(const TextureFactoryIdentifier& aTextureFactoryIdentifier,
                           const layers::LayersId& aLayersId,
                           const mozilla::layers::CompositorOptions& aCompositorOptions,
                           PRenderFrameChild* aRenderFrame);
   void InitAPZState();
 
   void DestroyWindow();
--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -616,20 +616,20 @@ function deleteSession() {
  * @param {UUID} uuid
  *     Unique identifier of the request.
  * @param {AsyncContentSender.ResponseType} type
  *     Type of response.
  * @param {*} [Object] data
  *     JSON serialisable object to accompany the message.  Defaults to
  *     an empty dictionary.
  */
-function sendToServer(uuid, data = undefined) {
+let sendToServer = (uuid, data = undefined) => {
   let channel = new proxy.AsyncMessageChannel(sendAsyncMessage.bind(this));
   channel.reply(uuid, data);
-}
+};
 
 /**
  * Send asynchronous reply with value to chrome.
  *
  * @param {Object} obj
  *     JSON serialisable object of arbitrary type and complexity.
  * @param {UUID} uuid
  *     Unique identifier of the request.