Backed out 6 changesets (bug 888600) for beta simulation failures: build bustage on Linux and Windows opt (bug 1442036) and devtools failure browser_net_view-source-debugger.js (bug 1441961). a=backout
authorSebastian Hengst <archaeopteryx@coole-files.de>
Thu, 01 Mar 2018 11:51:09 +0200
changeset 405781 714ff834425c99e5521b7b0e3c3c736bf2f34916
parent 405780 cd9545935eb5223749b145b1785fa709a1e898d3
child 405782 0f8f71b0b9d84e7732c07f841e395de516b31b66
push id33533
push userarchaeopteryx@coole-files.de
push dateThu, 01 Mar 2018 09:57:02 +0000
treeherdermozilla-central@0f8f71b0b9d8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs888600, 1442036, 1441961
milestone60.0a1
backs out83c87140dc3da6d521c9380beea85b30cb69c7b5
2efb9b1753f63748fa547117c0665e8f3e705e08
af53037819615484e614e7343256f31b237f1bab
79ef59047e638311f6249f82b528d6ab5d3a7666
30d568d628dd2be0d8f928905a472a9a27bf2a18
c7bd4c6c9741aca337592b50f8533ef9a30ff28d
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 6 changesets (bug 888600) for beta simulation failures: build bustage on Linux and Windows opt (bug 1442036) and devtools failure browser_net_view-source-debugger.js (bug 1441961). a=backout Backed out changeset 83c87140dc3d (bug 888600) Backed out changeset 2efb9b1753f6 (bug 888600) Backed out changeset af5303781961 (bug 888600) Backed out changeset 79ef59047e63 (bug 888600) Backed out changeset 30d568d628dd (bug 888600) Backed out changeset c7bd4c6c9741 (bug 888600)
browser/base/content/test/general/contentSearchUI.js
browser/base/content/test/webrtc/browser_devices_get_user_media_multi_process.js
browser/components/extensions/test/browser/browser_ext_tabs_executeScript.js
browser/components/nsBrowserGlue.js
browser/components/sessionstore/test/head.js
browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm
browser/extensions/pdfjs/content/PdfjsContentUtils.jsm
browser/extensions/pocket/bootstrap.js
browser/modules/AboutHome.jsm
browser/modules/ContentCrashHandlers.jsm
browser/modules/ContentSearch.jsm
devtools/client/jsonview/converter-child.js
devtools/client/netmonitor/test/browser_net_view-source-debugger.js
devtools/client/webaudioeditor/test/browser_wa_properties-view-media-nodes.js
devtools/server/actors/process.js
devtools/server/actors/root.js
devtools/server/actors/storage.js
devtools/server/actors/webconsole/content-process-forward.js
devtools/server/content-server.jsm
devtools/server/tests/mochitest/setup-in-child.js
devtools/server/tests/mochitest/test_setupInParentChild.html
docshell/base/nsDocShell.cpp
dom/base/ChildProcessMessageManager.h
dom/base/ChromeMessageBroadcaster.cpp
dom/base/ChromeMessageBroadcaster.h
dom/base/ChromeMessageSender.cpp
dom/base/ChromeMessageSender.h
dom/base/ContentFrameMessageManager.h
dom/base/DOMMatrix.cpp
dom/base/DOMRequestHelper.jsm
dom/base/MessageListenerManager.cpp
dom/base/MessageListenerManager.h
dom/base/MessageManagerGlobal.h
dom/base/MessageSender.cpp
dom/base/MessageSender.h
dom/base/ProcessGlobal.cpp
dom/base/ProcessGlobal.h
dom/base/SyncMessageSender.h
dom/base/TextInputProcessor.cpp
dom/base/TimeoutExecutor.cpp
dom/base/TimeoutManager.h
dom/base/moz.build
dom/base/nsCCUncollectableMarker.cpp
dom/base/nsContentIterator.cpp
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/nsGlobalWindowInner.cpp
dom/base/nsGlobalWindowInner.h
dom/base/nsGlobalWindowOuter.h
dom/base/nsIMessageManager.idl
dom/base/nsInProcessTabChildGlobal.cpp
dom/base/nsInProcessTabChildGlobal.h
dom/base/nsJSUtils.cpp
dom/base/nsWrapperCache.h
dom/base/test/browser_messagemanager_loadprocessscript.js
dom/base/test/chrome/file_bug1139964.xul
dom/base/test/chrome/file_bug549682.xul
dom/base/test/chrome/file_bug990812-1.xul
dom/base/test/chrome/file_bug990812-2.xul
dom/base/test/chrome/file_bug990812-3.xul
dom/base/test/chrome/file_bug990812-4.xul
dom/base/test/chrome/file_bug990812-5.xul
dom/base/test/chrome/file_bug990812.xul
dom/base/test/chrome/test_bug1098074_throw_from_ReceiveMessage.xul
dom/base/test/test_domrequesthelper.xul
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/bindings/Bindings.conf
dom/bindings/Codegen.py
dom/bindings/ToJSValue.h
dom/bindings/WebIDLGlobalNameHash.cpp
dom/bindings/WebIDLGlobalNameHash.h
dom/file/tests/test_ipc_messagemanager_blob.html
dom/indexedDB/test/head.js
dom/indexedDB/test/test_message_manager_ipc.html
dom/interfaces/base/nsIContentProcess.idl
dom/interfaces/base/nsITabChild.idl
dom/ipc/ContentBridgeParent.cpp
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/nsIContentChild.cpp
dom/ipc/nsIContentParent.cpp
dom/ipc/nsIContentParent.h
dom/ipc/remote-test.js
dom/ipc/test.xul
dom/ipc/tests/test_blob_sliced_from_child_process.html
dom/ipc/tests/test_blob_sliced_from_parent_process.html
dom/ipc/tests/test_bug1086684.html
dom/ipc/tests/test_cpow_cookies.html
dom/media/PeerConnection.js
dom/notification/NotificationDB.jsm
dom/notification/NotificationStorage.js
dom/notification/test/unit/common_test_notificationdb.js
dom/notification/test/unit/test_notificationdb.js
dom/presentation/tests/mochitest/test_presentation_dc_receiver_oop.html
dom/push/PushComponents.js
dom/quota/test/head.js
dom/webidl/FrameLoader.webidl
dom/webidl/LegacyQueryInterface.webidl
dom/webidl/MessageManager.webidl
dom/webidl/Window.webidl
dom/webidl/moz.build
js/xpconnect/src/nsXPConnect.cpp
services/sync/tps/extensions/tps/resource/modules/tabs.jsm
testing/marionette/driver.js
testing/marionette/proxy.js
testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
testing/mochitest/ShutdownLeaksCollector.jsm
testing/mochitest/browser-test.js
testing/specialpowers/content/SpecialPowersObserver.jsm
testing/xpcshell/head.js
toolkit/components/addoncompat/RemoteAddonsChild.jsm
toolkit/components/addoncompat/RemoteAddonsParent.jsm
toolkit/components/contentprefs/ContentPrefServiceParent.jsm
toolkit/components/contentprefs/tests/mochitest/test_remoteContentPrefs.html
toolkit/components/passwordmgr/test/pwmgr_common.js
toolkit/components/satchel/FormHistoryStartup.js
toolkit/components/telemetry/TelemetrySession.jsm
toolkit/modules/Services.jsm
toolkit/modules/WebChannel.jsm
toolkit/mozapps/extensions/ChromeManifestParser.jsm
toolkit/mozapps/extensions/internal/GMPProvider.jsm
toolkit/mozapps/extensions/test/mochitest/test_bug687194.html
tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-services.js
tools/quitter/QuitterObserver.js
tools/quitter/install.rdf
tools/quitter/quitter@mozilla.org.xpi
xpcom/ds/nsClassHashtable.h
xpcom/reflect/xptinfo/ShimInterfaceInfo.cpp
--- a/browser/base/content/test/general/contentSearchUI.js
+++ b/browser/base/content/test/general/contentSearchUI.js
@@ -163,17 +163,18 @@ function waitForSuggestions(cb) {
   });
   observer.observe(gController.input, {
     attributes: true,
     attributeFilter: ["aria-expanded"],
   });
 }
 
 function waitForContentSearchEvent(messageType, cb) {
-  let mm = content.SpecialPowers.Cc["@mozilla.org/globalmessagemanager;1"].getService();
+  let mm = content.SpecialPowers.Cc["@mozilla.org/globalmessagemanager;1"].
+    getService(content.SpecialPowers.Ci.nsIMessageListenerManager);
   mm.addMessageListener("ContentSearch", function listener(aMsg) {
     if (aMsg.data.type != messageType) {
       return;
     }
     mm.removeMessageListener("ContentSearch", listener);
     cb(aMsg.data.data);
   });
 }
--- a/browser/base/content/test/webrtc/browser_devices_get_user_media_multi_process.js
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_multi_process.js
@@ -37,17 +37,20 @@ var gTests = [
     ok(webrtcUI.showMicrophoneIndicator, "webrtcUI wants the mic indicator shown");
     is(webrtcUI.getActiveStreams(false, true).length, 1, "1 active audio stream");
     is(webrtcUI.getActiveStreams(true, true, true).length, 1, "1 active stream");
 
     await expectNoObserverCalled();
 
     // If we have reached the max process count already, increase it to ensure
     // our new tab can have its own content process.
-    let childCount = Services.ppmm.childCount;
+    var ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+                 .getService(Ci.nsIMessageBroadcaster);
+    ppmm.QueryInterface(Ci.nsIProcessScriptLoader);
+    let childCount = ppmm.childCount;
     let maxContentProcess = Services.prefs.getIntPref("dom.ipc.processCount");
     // The first check is because if we are on a branch where e10s-multi is
     // disabled, we want to keep testing e10s with a single content process.
     // The + 1 is because ppmm.childCount also counts the chrome process
     // (which also runs process scripts).
     if (maxContentProcess > 1 && childCount == maxContentProcess + 1) {
       await SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount",
                                                 childCount]]});
@@ -138,17 +141,20 @@ var gTests = [
     ok(!webrtcUI.showMicrophoneIndicator, "webrtcUI wants the mic indicator hidden");
     is(webrtcUI.getActiveStreams(true).length, 1, "1 active camera stream");
     is(webrtcUI.getActiveStreams(true, true, true).length, 1, "1 active stream");
 
     await expectNoObserverCalled();
 
     // If we have reached the max process count already, increase it to ensure
     // our new tab can have its own content process.
-    let childCount = Services.ppmm.childCount;
+    var ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+                 .getService(Ci.nsIMessageBroadcaster);
+    ppmm.QueryInterface(Ci.nsIProcessScriptLoader);
+    let childCount = ppmm.childCount;
     let maxContentProcess = Services.prefs.getIntPref("dom.ipc.processCount");
     // The first check is because if we are on a branch where e10s-multi is
     // disabled, we want to keep testing e10s with a single content process.
     // The + 1 is because ppmm.childCount also counts the chrome process
     // (which also runs process scripts).
     if (maxContentProcess > 1 && childCount == maxContentProcess + 1) {
       await SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount",
                                                 childCount]]});
@@ -244,17 +250,20 @@ var gTests = [
     ok(!webrtcUI.showMicrophoneIndicator, "webrtcUI wants the mic indicator hidden");
     is(webrtcUI.getActiveStreams(false, false, true).length, 1, "1 active screen sharing stream");
     is(webrtcUI.getActiveStreams(true, true, true).length, 1, "1 active stream");
 
     await expectNoObserverCalled();
 
     // If we have reached the max process count already, increase it to ensure
     // our new tab can have its own content process.
-    let childCount = Services.ppmm.childCount;
+    var ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+                 .getService(Ci.nsIMessageBroadcaster);
+    ppmm.QueryInterface(Ci.nsIProcessScriptLoader);
+    let childCount = ppmm.childCount;
     let maxContentProcess = Services.prefs.getIntPref("dom.ipc.processCount");
     // The first check is because if we are on a branch where e10s-multi is
     // disabled, we want to keep testing e10s with a single content process.
     // The + 1 is because ppmm.childCount also counts the chrome process
     // (which also runs process scripts).
     if (maxContentProcess > 1 && childCount == maxContentProcess + 1) {
       await SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount",
                                                 childCount]]});
--- a/browser/components/extensions/test/browser/browser_ext_tabs_executeScript.js
+++ b/browser/components/extensions/test/browser/browser_ext_tabs_executeScript.js
@@ -14,16 +14,22 @@ add_task(async function testExecuteScrip
     // count them in the test because MessageChannel unsubscribes when the
     // message manager closes, which never happens to these, of course.
     let globalMMs = [
       Services.mm,
       Services.ppmm,
       Services.ppmm.getChildAt(0),
     ];
     for (let mm of messageManagerMap.keys()) {
+      // Sanity check: mm is a message manager.
+      try {
+        mm.QueryInterface(Ci.nsIMessageSender);
+      } catch (e) {
+        mm.QueryInterface(Ci.nsIMessageBroadcaster);
+      }
       if (!globalMMs.includes(mm)) {
         ++count;
       }
     }
     return count;
   }
 
   let messageManagersSize = countMM(MessageChannel.messageManagers);
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -3183,18 +3183,19 @@ var JawsScreenReaderVersionCheck = {
 };
 
 var components = [BrowserGlue, ContentPermissionPrompt];
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
 
 // Listen for UITour messages.
 // Do it here instead of the UITour module itself so that the UITour module is lazy loaded
 // when the first message is received.
-Services.mm.addMessageListener("UITour:onPageEvent", function(aMessage) {
+var globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
+globalMM.addMessageListener("UITour:onPageEvent", function(aMessage) {
   UITour.onPageEvent(aMessage, aMessage.data);
 });
 
 // Listen for HybridContentTelemetry messages.
 // Do it here instead of HybridContentTelemetry.init() so that
 // the module can be lazily loaded on the first message.
-Services.mm.addMessageListener("HybridContentTelemetry:onTelemetryMessage", aMessage => {
+globalMM.addMessageListener("HybridContentTelemetry:onTelemetryMessage", aMessage => {
   HybridContentTelemetry.onTelemetryMessage(aMessage, aMessage.data);
 });
--- a/browser/components/sessionstore/test/head.js
+++ b/browser/components/sessionstore/test/head.js
@@ -10,23 +10,26 @@ const TAB_STATE_RESTORING = 2;
 
 const ROOT = getRootDirectory(gTestPath);
 const HTTPROOT = ROOT.replace("chrome://mochitests/content/", "http://example.com/");
 const FRAME_SCRIPTS = [
   ROOT + "content.js",
   ROOT + "content-forms.js"
 ];
 
+var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+           .getService(Ci.nsIMessageListenerManager);
+
 for (let script of FRAME_SCRIPTS) {
-  Services.mm.loadFrameScript(script, true);
+  globalMM.loadFrameScript(script, true);
 }
 
 registerCleanupFunction(() => {
   for (let script of FRAME_SCRIPTS) {
-    Services.mm.removeDelayedFrameScript(script, true);
+    globalMM.removeDelayedFrameScript(script, true);
   }
 });
 
 const {SessionStore} = ChromeUtils.import("resource:///modules/sessionstore/SessionStore.jsm", {});
 const {SessionSaver} = ChromeUtils.import("resource:///modules/sessionstore/SessionSaver.jsm", {});
 const {SessionFile} = ChromeUtils.import("resource:///modules/sessionstore/SessionFile.jsm", {});
 const {TabState} = ChromeUtils.import("resource:///modules/sessionstore/TabState.jsm", {});
 const {TabStateFlusher} = ChromeUtils.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
--- a/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm
+++ b/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm
@@ -63,26 +63,28 @@ var PdfjsChromeUtils = {
   /*
    * Public API
    */
 
   init() {
     this._browsers = new WeakSet();
     if (!this._ppmm) {
       // global parent process message manager (PPMM)
-      this._ppmm = Services.ppmm;
+      this._ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"].
+        getService(Ci.nsIMessageBroadcaster);
       this._ppmm.addMessageListener("PDFJS:Parent:clearUserPref", this);
       this._ppmm.addMessageListener("PDFJS:Parent:setIntPref", this);
       this._ppmm.addMessageListener("PDFJS:Parent:setBoolPref", this);
       this._ppmm.addMessageListener("PDFJS:Parent:setCharPref", this);
       this._ppmm.addMessageListener("PDFJS:Parent:setStringPref", this);
       this._ppmm.addMessageListener("PDFJS:Parent:isDefaultHandlerApp", this);
 
       // global dom message manager (MMg)
-      this._mmg = Services.mm;
+      this._mmg = Cc["@mozilla.org/globalmessagemanager;1"].
+        getService(Ci.nsIMessageListenerManager);
       this._mmg.addMessageListener("PDFJS:Parent:displayWarning", this);
 
       this._mmg.addMessageListener("PDFJS:Parent:addEventListener", this);
       this._mmg.addMessageListener("PDFJS:Parent:removeEventListener", this);
       this._mmg.addMessageListener("PDFJS:Parent:updateControlState", this);
 
       // Observer to handle shutdown.
       Services.obs.addObserver(this, "quit-application");
--- a/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm
+++ b/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm
@@ -30,17 +30,18 @@ var PdfjsContentUtils = {
     return (Services.appinfo.processType ===
             Services.appinfo.PROCESS_TYPE_CONTENT);
   },
 
   init() {
     // child *process* mm, or when loaded into the parent for in-content
     // support the psuedo child process mm 'child PPMM'.
     if (!this._mm) {
-      this._mm = Services.cpmm;
+      this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].
+        getService(Ci.nsISyncMessageSender);
       this._mm.addMessageListener("PDFJS:Child:updateSettings", this);
 
       Services.obs.addObserver(this, "quit-application");
     }
   },
 
   uninit() {
     if (this._mm) {
--- a/browser/extensions/pocket/bootstrap.js
+++ b/browser/extensions/pocket/bootstrap.js
@@ -403,17 +403,19 @@ var PocketOverlay = {
     PocketReader.startup();
     PocketPageAction.init();
     PocketContextMenu.init();
     for (let win of browserWindows()) {
       this.onWindowOpened(win);
     }
   },
   shutdown(reason) {
-    Services.ppmm.broadcastAsyncMessage("PocketShuttingDown");
+    let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+                 .getService(Ci.nsIMessageBroadcaster);
+    ppmm.broadcastAsyncMessage("PocketShuttingDown");
     Services.obs.removeObserver(this, "browser-delayed-startup-finished");
     // Although the ppmm loads the scripts into the chrome process as well,
     // we need to manually unregister here anyway to ensure these aren't part
     // of the chrome process and avoid errors.
     AboutPocket.aboutSaved.unregister();
     AboutPocket.aboutSignup.unregister();
 
     PocketPageAction.shutdown();
--- a/browser/modules/AboutHome.jsm
+++ b/browser/modules/AboutHome.jsm
@@ -173,16 +173,17 @@ var AboutHome = {
         // Set pref to indicate we've shown the notification.
         let currentVersion = Services.prefs.getIntPref("browser.rights.version");
         Services.prefs.setBoolPref("browser.rights." + currentVersion + ".shown", true);
       }
 
       if (target && target.messageManager) {
         target.messageManager.sendAsyncMessage("AboutHome:Update", data);
       } else {
-        Services.mm.broadcastAsyncMessage("AboutHome:Update", data);
+        let mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
+        mm.broadcastAsyncMessage("AboutHome:Update", data);
       }
     }).catch(function onError(x) {
       Cu.reportError("Error in AboutHome.sendAboutHomeData: " + x);
     });
   },
 
 };
--- a/browser/modules/ContentCrashHandlers.jsm
+++ b/browser/modules/ContentCrashHandlers.jsm
@@ -990,20 +990,22 @@ var PluginCrashReporter = {
         let pluginDumpID = propertyBag.getPropertyAsAString("pluginDumpID");
         if (pluginDumpID) {
           this.crashReports.set(pluginID, { pluginDumpID });
         }
 
         // Only the parent process gets the gmp-plugin-crash observer
         // notification, so we need to inform any content processes that
         // the GMP has crashed.
-        if (Services.ppmm) {
+        if (Cc["@mozilla.org/parentprocessmessagemanager;1"]) {
           let pluginName = propertyBag.getPropertyAsAString("pluginName");
-          Services.ppmm.broadcastAsyncMessage("gmp-plugin-crash",
-                                              { pluginName, pluginID });
+          let mm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+            .getService(Ci.nsIMessageListenerManager);
+          mm.broadcastAsyncMessage("gmp-plugin-crash",
+                                   { pluginName, pluginID });
         }
         break;
       }
       case "profile-after-change":
         this.uninit();
         break;
     }
   },
--- a/browser/modules/ContentSearch.jsm
+++ b/browser/modules/ContentSearch.jsm
@@ -484,17 +484,19 @@ var ContentSearch = {
     // We reply asyncly to messages, and by the time we reply the browser we're
     // responding to may have been destroyed.  messageManager is null then.
     if (!Cu.isDeadWrapper(msg.target) && msg.target.messageManager) {
       msg.target.messageManager.sendAsyncMessage(...this._msgArgs(type, data));
     }
   },
 
   _broadcast(type, data) {
-    Services.mm.broadcastAsyncMessage(...this._msgArgs(type, data));
+    Cc["@mozilla.org/globalmessagemanager;1"].
+      getService(Ci.nsIMessageListenerManager).
+      broadcastAsyncMessage(...this._msgArgs(type, data));
   },
 
   _msgArgs(type, data) {
     return [OUTBOUND_MESSAGE, {
       type,
       data,
     }];
   },
--- a/devtools/client/jsonview/converter-child.js
+++ b/devtools/client/jsonview/converter-child.js
@@ -1,27 +1,30 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=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/. */
 
 "use strict";
 
-const {Ci, Cu, CC} = require("chrome");
+const {Cc, Ci, Cu, CC} = require("chrome");
 const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
 const Services = require("Services");
 
 loader.lazyRequireGetter(this, "NetworkHelper",
                                "devtools/shared/webconsole/network-helper");
 loader.lazyGetter(this, "debug", function () {
   let {AppConstants} = require("resource://gre/modules/AppConstants.jsm");
   return !!(AppConstants.DEBUG || AppConstants.DEBUG_JS_MODULES);
 });
 
+const childProcessMessageManager =
+  Cc["@mozilla.org/childprocessmessagemanager;1"]
+    .getService(Ci.nsISyncMessageSender);
 const BinaryInput = CC("@mozilla.org/binaryinputstream;1",
                        "nsIBinaryInputStream", "setInputStream");
 const BufferStream = CC("@mozilla.org/io/arraybuffer-input-stream;1",
                        "nsIArrayBufferInputStream", "setData");
 
 // Localization
 loader.lazyGetter(this, "jsonViewStrings", () => {
   return Services.strings.createBundle(
@@ -296,17 +299,17 @@ function onContentMessage(e) {
   let win = this;
   if (win != e.target) {
     return;
   }
 
   let value = e.detail.value;
   switch (e.detail.type) {
     case "save":
-      Services.cpmm.sendAsyncMessage(
+      childProcessMessageManager.sendAsyncMessage(
         "devtools:jsonview:save", value);
   }
 }
 
 function createInstance() {
   return new Converter();
 }
 
--- 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", 5);
+  let wait = waitForDOM(document, "#stack-trace-panel .frame-link", 4);
   // 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");
--- a/devtools/client/webaudioeditor/test/browser_wa_properties-view-media-nodes.js
+++ b/devtools/client/webaudioeditor/test/browser_wa_properties-view-media-nodes.js
@@ -15,20 +15,22 @@ function waitForDeviceClosed() {
   ChromeUtils.import("resource:///modules/webrtcUI.jsm", temp);
   let webrtcUI = temp.webrtcUI;
 
   if (!webrtcUI.showGlobalIndicator)
     return Promise.resolve();
 
   return new Promise((resolve, reject) => {
     const message = "webrtc:UpdateGlobalIndicators";
-    Services.ppmm.addMessageListener(message, function listener(aMessage) {
+    let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+                 .getService(Ci.nsIMessageBroadcaster);
+    ppmm.addMessageListener(message, function listener(aMessage) {
       info("Received " + message + " message");
       if (!aMessage.data.showGlobalIndicator) {
-        Services.ppmm.removeMessageListener(message, listener);
+        ppmm.removeMessageListener(message, listener);
         resolve();
       }
     });
   });
 }
 
 add_task(function* () {
   let { target, panel } = yield initWebAudioEditor(MEDIA_NODES_URL);
--- a/devtools/server/actors/process.js
+++ b/devtools/server/actors/process.js
@@ -1,18 +1,19 @@
 /* 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/. */
 
 "use strict";
 
-var { Cc } = require("chrome");
+var { Cc, Ci } = require("chrome");
 
 loader.lazyGetter(this, "ppmm", () => {
-  return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService();
+  return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(
+    Ci.nsIMessageBroadcaster);
 });
 
 function ProcessActorList() {
   this._actors = new Map();
   this._onListChanged = null;
   this._mustNotify = false;
 
   this._onMessage = this._onMessage.bind(this);
--- a/devtools/server/actors/root.js
+++ b/devtools/server/actors/root.js
@@ -1,21 +1,25 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=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/. */
 
 "use strict";
 
-const { Cu } = require("chrome");
+const { Cc, Ci, Cu } = require("chrome");
 const Services = require("Services");
 const { ActorPool, appendExtraActors, createExtraActors } = require("devtools/server/actors/common");
 const { DebuggerServer } = require("devtools/server/main");
 
+loader.lazyGetter(this, "ppmm", () => {
+  return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(
+    Ci.nsIMessageBroadcaster);
+});
 loader.lazyRequireGetter(this, "WindowActor",
   "devtools/server/actors/window", true);
 
 /* Root actor for the remote debugging protocol. */
 
 /**
  * Create a remote debugging protocol root actor.
  *
@@ -538,17 +542,17 @@ RootActor.prototype = {
         this._chromeActor = new ChromeActor(this.conn);
         this._globalActorPool.addActor(this._chromeActor);
       }
 
       return { form: this._chromeActor.form() };
     }
 
     let { id } = request;
-    let mm = Services.ppmm.getChildAt(id);
+    let mm = ppmm.getChildAt(id);
     if (!mm) {
       return { error: "noProcess",
                message: "There is no process with id '" + id + "'." };
     }
     let form = this._processActors.get(id);
     if (form) {
       return { form };
     }
--- a/devtools/server/actors/storage.js
+++ b/devtools/server/actors/storage.js
@@ -1,15 +1,15 @@
 /* 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/. */
 
 "use strict";
 
-const {Ci, Cu, CC} = require("chrome");
+const {Cc, Ci, Cu, CC} = require("chrome");
 const protocol = require("devtools/shared/protocol");
 const {LongStringActor} = require("devtools/server/actors/string");
 const {DebuggerServer} = require("devtools/server/main");
 const Services = require("Services");
 const defer = require("devtools/shared/defer");
 const {isWindowIncluded} = require("devtools/shared/layout/utils");
 const specs = require("devtools/shared/specs/storage");
 
@@ -1933,24 +1933,30 @@ StorageActors.createActor({
           { name: "objectStores", editable: false },
         ];
     }
   }
 });
 
 var indexedDBHelpers = {
   backToChild(...args) {
-    Services.mm.broadcastAsyncMessage("debug:storage-indexedDB-request-child", {
+    let mm = Cc["@mozilla.org/globalmessagemanager;1"]
+               .getService(Ci.nsIMessageListenerManager);
+
+    mm.broadcastAsyncMessage("debug:storage-indexedDB-request-child", {
       method: "backToChild",
       args: args
     });
   },
 
   onItemUpdated(action, host, path) {
-    Services.mm.broadcastAsyncMessage("debug:storage-indexedDB-request-child", {
+    let mm = Cc["@mozilla.org/globalmessagemanager;1"]
+               .getService(Ci.nsIMessageListenerManager);
+
+    mm.broadcastAsyncMessage("debug:storage-indexedDB-request-child", {
       method: "onItemUpdated",
       args: [ action, host, path ]
     });
   },
 
   /**
    * Fetches and stores all the metadata information for the given database
    * `name` for the given `host` with its `principal`. The stored metadata
--- a/devtools/server/actors/webconsole/content-process-forward.js
+++ b/devtools/server/actors/webconsole/content-process-forward.js
@@ -2,16 +2,19 @@
  * 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/. */
 
 "use strict";
 
 const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm", {});
 const { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", {});
 
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsIMessageSender");
 ChromeUtils.defineModuleGetter(this, "E10SUtils",
                                "resource://gre/modules/E10SUtils.jsm");
 
 /*
  * The message manager has an upper limit on message sizes that it can
  * reliably forward to the parent so we limit the size of console log event
  * messages that we forward here. The web console is local and receives the
  * full console message, but addons subscribed to console event messages
@@ -29,17 +32,17 @@ ChromeUtils.defineModuleGetter(this, "E1
  */
 const MSG_MGR_CONSOLE_MAX_SIZE = 1024 * 1024; // 1MB
 const MSG_MGR_CONSOLE_VAR_SIZE = 8;
 const MSG_MGR_CONSOLE_INFO_MAX = 1024;
 
 function ContentProcessForward() {
   Services.obs.addObserver(this, "console-api-log-event");
   Services.obs.addObserver(this, "xpcom-shutdown");
-  Services.cpmm.addMessageListener("DevTools:StopForwardingContentProcessMessage", this);
+  cpmm.addMessageListener("DevTools:StopForwardingContentProcessMessage", this);
 }
 ContentProcessForward.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference]),
 
   receiveMessage(message) {
     if (message.name == "DevTools:StopForwardingContentProcessMessage") {
       this.uninit();
@@ -100,31 +103,30 @@ ContentProcessForward.prototype = {
             msgData.arguments.push(arg);
           } else {
             // arguments take up too much space
             msgData.arguments = ["<truncated>"];
             break;
           }
         }
 
-        Services.cpmm.sendAsyncMessage("Console:Log", msgData);
+        cpmm.sendAsyncMessage("Console:Log", msgData);
         break;
       }
 
       case "xpcom-shutdown":
         this.uninit();
         break;
     }
   },
 
   uninit() {
     Services.obs.removeObserver(this, "console-api-log-event");
     Services.obs.removeObserver(this, "xpcom-shutdown");
-    Services.cpmm.removeMessageListener("DevTools:StopForwardingContentProcessMessage",
-                                        this);
+    cpmm.removeMessageListener("DevTools:StopForwardingContentProcessMessage", this);
   }
 };
 
 // loadProcessScript loads in all processes, including the parent,
 // in which we don't need any forwarding
 if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
   new ContentProcessForward();
 }
--- a/devtools/server/content-server.jsm
+++ b/devtools/server/content-server.jsm
@@ -44,16 +44,17 @@ function setupServer(mm) {
     gLoader = null;
   });
 
   return gLoader;
 }
 
 function init(msg) {
   let mm = msg.target;
+  mm.QueryInterface(Ci.nsISyncMessageSender);
   let prefix = msg.data.prefix;
 
   // Using the JS debugger causes problems when we're trying to
   // schedule those zone groups across different threads. Calling
   // blockThreadedExecution causes Gecko to switch to a simpler
   // single-threaded model until unblockThreadedExecution is called
   // later. We cannot start the debugger until the callback passed to
   // blockThreadedExecution has run, signaling that we're running
--- a/devtools/server/tests/mochitest/setup-in-child.js
+++ b/devtools/server/tests/mochitest/setup-in-child.js
@@ -1,12 +1,13 @@
 "use strict";
 
-const {Cc} = require("chrome");
-const cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService();
+const {Cc, Ci} = require("chrome");
+const cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
+             .getService(Ci.nsIMessageListenerManager);
 const { DebuggerServer } = require("devtools/server/main");
 
 exports.setupChild = function (a, b, c) {
   cpmm.sendAsyncMessage("test:setupChild", [a, b, c]);
 };
 
 exports.callParent = function () {
   // Hack! Fetch DebuggerServerConnection objects directly within DebuggerServer guts.
--- a/devtools/server/tests/mochitest/test_setupInParentChild.html
+++ b/devtools/server/tests/mochitest/test_setupInParentChild.html
@@ -44,31 +44,33 @@ function runTests() {
   }
 
   // Fake a connection to an iframe
   let transport = DebuggerServer.connectPipe();
   let conn = transport._serverConnection;
   let client = new DebuggerClient(transport);
 
   // Wait for a response from setupInChild
+  const ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+                 .getService(Ci.nsIMessageListenerManager);
   let onChild = msg => {
-    Services.ppmm.removeMessageListener("test:setupChild", onChild);
+    ppmm.removeMessageListener("test:setupChild", onChild);
     let args = msg.json;
 
     is(args[0], 1, "Got first numeric argument");
     is(args[1], "two", "Got second string argument");
     is(args[2].three, true, "Got last JSON argument");
 
     // Ask the child to call setupInParent
     DebuggerServer.setupInChild({
       module: "chrome://mochitests/content/chrome/devtools/server/tests/mochitest/setup-in-child.js",
       setupChild: "callParent"
     });
   };
-  Services.ppmm.addMessageListener("test:setupChild", onChild);
+  ppmm.addMessageListener("test:setupChild", onChild);
 
   // Wait also for a reponse from setupInParent called from setup-in-child.js
   let onParent = (_, topic, args) => {
     Services.obs.removeObserver(onParent, "test:setupParent");
     args = JSON.parse(args);
 
     is(args[0], true, "Got `mm` argument, a message manager");
     ok(args[1].match(/server\d+.conn\d+.child\d+/), "Got `prefix` argument");
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -644,20 +644,21 @@ nsDocShell::GetInterface(const nsIID& aI
     nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner));
     if (NS_SUCCEEDED(rv) && treeOwner) {
       return treeOwner->QueryInterface(aIID, aSink);
     }
   } else if (aIID.Equals(NS_GET_IID(nsITabChild))) {
     *aSink = GetTabChild().take();
     return *aSink ? NS_OK : NS_ERROR_FAILURE;
   } else if (aIID.Equals(NS_GET_IID(nsIContentFrameMessageManager))) {
-    RefPtr<TabChild> tabChild = TabChild::GetFrom(this);
+    nsCOMPtr<nsITabChild> tabChild =
+      do_GetInterface(static_cast<nsIDocShell*>(this));
     nsCOMPtr<nsIContentFrameMessageManager> mm;
     if (tabChild) {
-      mm = tabChild->GetMessageManager();
+      tabChild->GetMessageManager(getter_AddRefs(mm));
     } else {
       if (nsPIDOMWindowOuter* win = GetWindow()) {
         mm = do_QueryInterface(win->GetParentTarget());
       }
     }
     *aSink = mm.get();
   } else {
     return nsDocLoader::GetInterface(aIID, aSink);
deleted file mode 100644
--- a/dom/base/ChildProcessMessageManager.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_ChildProcessMessageManager_h
-#define mozilla_dom_ChildProcessMessageManager_h
-
-#include "mozilla/dom/SyncMessageSender.h"
-#include "mozilla/dom/MessageManagerBinding.h"
-
-namespace mozilla {
-namespace dom {
-
-class ChildProcessMessageManager final : public SyncMessageSender
-{
-public:
-  explicit ChildProcessMessageManager(ipc::MessageManagerCallback* aCallback)
-    : SyncMessageSender(aCallback,
-                        MessageManagerFlags::MM_PROCESSMANAGER |
-                        MessageManagerFlags::MM_OWNSCALLBACK)
-  {
-    mozilla::HoldJSObjects(this);
-  }
-
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
-  {
-    return ChildProcessMessageManagerBinding::Wrap(aCx, this, aGivenProto);
-  }
-
-protected:
-  virtual ~ChildProcessMessageManager()
-  {
-    mozilla::DropJSObjects(this);
-  }
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_ChildProcessMessageManager_h
deleted file mode 100644
--- a/dom/base/ChromeMessageBroadcaster.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/ChromeMessageBroadcaster.h"
-#include "AccessCheck.h"
-#include "mozilla/HoldDropJSObjects.h"
-#include "mozilla/dom/MessageManagerBinding.h"
-
-namespace mozilla {
-namespace dom {
-
-ChromeMessageBroadcaster::ChromeMessageBroadcaster(nsFrameMessageManager* aParentManager,
-                                                   MessageManagerFlags aFlags)
-  : MessageListenerManager(nullptr, aParentManager,
-                           aFlags |
-                           MessageManagerFlags::MM_BROADCASTER |
-                           MessageManagerFlags::MM_CHROME)
-{
-  if (mIsProcessManager) {
-    mozilla::HoldJSObjects(this);
-  }
-  if (aParentManager) {
-    aParentManager->AddChildManager(this);
-  }
-}
-
-ChromeMessageBroadcaster::~ChromeMessageBroadcaster()
-{
-  if (mIsProcessManager) {
-    mozilla::DropJSObjects(this);
-  }
-}
-
-JSObject*
-ChromeMessageBroadcaster::WrapObject(JSContext* aCx,
-                                     JS::Handle<JSObject*> aGivenProto)
-{
-  MOZ_ASSERT(nsContentUtils::IsSystemCaller(aCx));
-
-  return ChromeMessageBroadcasterBinding::Wrap(aCx, this, aGivenProto);
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/base/ChromeMessageBroadcaster.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_ChromeMessageBroadcaster_h
-#define mozilla_dom_ChromeMessageBroadcaster_h
-
-#include "mozilla/dom/MessageListenerManager.h"
-
-namespace mozilla {
-namespace dom {
-
-class ChromeMessageBroadcaster final : public MessageListenerManager
-{
-public:
-  explicit ChromeMessageBroadcaster(MessageManagerFlags aFlags)
-    : ChromeMessageBroadcaster(nullptr, aFlags)
-  {
-    MOZ_ASSERT(!(aFlags & ~(MessageManagerFlags::MM_GLOBAL |
-                            MessageManagerFlags::MM_PROCESSMANAGER |
-                            MessageManagerFlags::MM_OWNSCALLBACK)));
-  }
-  explicit ChromeMessageBroadcaster(nsFrameMessageManager* aParentManager)
-    : ChromeMessageBroadcaster(aParentManager, MessageManagerFlags::MM_NONE)
-  {}
-
-  virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
-  using nsFrameMessageManager::BroadcastAsyncMessage;
-  void BroadcastAsyncMessage(JSContext* aCx, const nsAString& aMessageName,
-                             JS::Handle<JS::Value> aObj,
-                             JS::Handle<JSObject*> aObjects,
-                             mozilla::ErrorResult& aError)
-  {
-    DispatchAsyncMessage(aCx, aMessageName, aObj, aObjects, nullptr,
-                         JS::UndefinedHandleValue, aError);
-  }
-  uint32_t ChildCount()
-  {
-    return mChildManagers.Length();
-  }
-  using nsFrameMessageManager::GetChildAt;
-  MessageListenerManager* GetChildAt(uint32_t aIndex)
-  {
-    return mChildManagers.SafeElementAt(aIndex);
-  }
-  // XPCOM ReleaseCachedProcesses is OK
-
-  // ProcessScriptLoader
-  using nsFrameMessageManager::LoadProcessScript;
-  void LoadProcessScript(const nsAString& aUrl, bool aAllowDelayedLoad,
-                         mozilla::ErrorResult& aError)
-  {
-    LoadScript(aUrl, aAllowDelayedLoad, false, aError);
-  }
-  // XPCOM RemoveDelayedProcessScript is OK
-  using nsFrameMessageManager::GetDelayedProcessScripts;
-  void GetDelayedProcessScripts(JSContext* aCx,
-                                nsTArray<nsTArray<JS::Value>>& aScripts,
-                                mozilla::ErrorResult& aError)
-  {
-    GetDelayedScripts(aCx, aScripts, aError);
-  }
-
-  // GlobalProcessScriptLoader
-  // XPCOM GetInitialProcessData is OK
-
-  // FrameScriptLoader
-  using nsFrameMessageManager::LoadFrameScript;
-  void LoadFrameScript(const nsAString& aUrl, bool aAllowDelayedLoad,
-                       bool aRunInGlobalScope, mozilla::ErrorResult& aError)
-  {
-    LoadScript(aUrl, aAllowDelayedLoad, aRunInGlobalScope, aError);
-  }
-  using nsFrameMessageManager::GetDelayedFrameScripts;
-  void GetDelayedFrameScripts(JSContext* aCx,
-                              nsTArray<nsTArray<JS::Value>>& aScripts,
-                              mozilla::ErrorResult& aError)
-  {
-    GetDelayedScripts(aCx, aScripts, aError);
-  }
-
-private:
-  ChromeMessageBroadcaster(nsFrameMessageManager* aParentManager,
-                           MessageManagerFlags aFlags);
-  virtual ~ChromeMessageBroadcaster();
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_ChromeMessageBroadcaster_h
deleted file mode 100644
--- a/dom/base/ChromeMessageSender.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/ChromeMessageSender.h"
-#include "mozilla/dom/MessageManagerBinding.h"
-
-namespace mozilla {
-namespace dom {
-
-ChromeMessageSender::ChromeMessageSender(ipc::MessageManagerCallback* aCallback,
-                                         nsFrameMessageManager* aParentManager,
-                                         MessageManagerFlags aFlags)
-  : MessageSender(aCallback, aParentManager, aFlags | MessageManagerFlags::MM_CHROME)
-{
-  MOZ_ASSERT(!(aFlags & ~(MessageManagerFlags::MM_GLOBAL |
-                          MessageManagerFlags::MM_PROCESSMANAGER |
-                          MessageManagerFlags::MM_OWNSCALLBACK)));
-
-  // This is a bit hackish. We attach to the parent, but only if we have a callback. We
-  // don't have a callback for the frame message manager, and for parent process message
-  // managers (except the parent in-process message manager). In those cases we wait until
-  // the child process is running (see MessageSender::InitWithCallback).
-  if (aParentManager && mCallback) {
-    aParentManager->AddChildManager(this);
-  }
-}
-
-JSObject*
-ChromeMessageSender::WrapObject(JSContext* aCx,
-                                JS::Handle<JSObject*> aGivenProto)
-{
-  MOZ_ASSERT(nsContentUtils::IsSystemCaller(aCx));
-
-  return ChromeMessageSenderBinding::Wrap(aCx, this, aGivenProto);
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/base/ChromeMessageSender.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_ChromeMessageSender_h
-#define mozilla_dom_ChromeMessageSender_h
-
-#include "mozilla/dom/MessageSender.h"
-
-namespace mozilla {
-namespace dom {
-
-class ChromeMessageSender final : public MessageSender
-{
-public:
-  ChromeMessageSender(ipc::MessageManagerCallback* aCallback,
-                      nsFrameMessageManager* aParentManager,
-                      MessageManagerFlags aFlags=MessageManagerFlags::MM_NONE);
-
-  virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
-  // ProcessScriptLoader
-  using nsFrameMessageManager::LoadProcessScript;
-  void LoadProcessScript(const nsAString& aUrl, bool aAllowDelayedLoad,
-                         mozilla::ErrorResult& aError)
-  {
-    LoadScript(aUrl, aAllowDelayedLoad, false, aError);
-  }
-  // XPCOM RemoveDelayedProcessScript is OK
-  using nsFrameMessageManager::GetDelayedProcessScripts;
-  void GetDelayedProcessScripts(JSContext* aCx,
-                                nsTArray<nsTArray<JS::Value>>& aScripts,
-                                mozilla::ErrorResult& aError)
-  {
-    GetDelayedScripts(aCx, aScripts, aError);
-  }
-
-  // FrameScriptLoader
-  using nsFrameMessageManager::LoadFrameScript;
-  void LoadFrameScript(const nsAString& aUrl, bool aAllowDelayedLoad,
-                       bool aRunInGlobalScope, mozilla::ErrorResult& aError)
-  {
-    LoadScript(aUrl, aAllowDelayedLoad, aRunInGlobalScope, aError);
-  }
-  using nsFrameMessageManager::GetDelayedFrameScripts;
-  void GetDelayedFrameScripts(JSContext* aCx,
-                              nsTArray<nsTArray<JS::Value>>& aScripts,
-                              mozilla::ErrorResult& aError)
-  {
-    GetDelayedScripts(aCx, aScripts, aError);
-  }
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_ChromeMessageSender_h
deleted file mode 100644
--- a/dom/base/ContentFrameMessageManager.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_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
--- a/dom/base/DOMMatrix.cpp
+++ b/dom/base/DOMMatrix.cpp
@@ -7,20 +7,18 @@
 #include "mozilla/dom/DOMMatrix.h"
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DOMMatrixBinding.h"
 #include "mozilla/dom/DOMPoint.h"
 #include "mozilla/dom/DOMPointBinding.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/ToJSValue.h"
-#include "mozilla/RuleNodeCacheConditions.h"
 #include "mozilla/ServoCSSParser.h"
 #include "nsCSSParser.h"
-#include "nsGlobalWindowInner.h"
 #include "nsStyleTransformMatrix.h"
 
 #include <math.h>
 
 namespace mozilla {
 namespace dom {
 
 static const double radPerDegree = 2.0 * M_PI / 360.0;
--- a/dom/base/DOMRequestHelper.jsm
+++ b/dom/base/DOMRequestHelper.jsm
@@ -16,16 +16,20 @@
  * to the child side of frame and process message manager and removing them
  * when needed.
  */
 var EXPORTED_SYMBOLS = ["DOMRequestIpcHelper"];
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsIMessageListenerManager");
+
 function DOMRequestIpcHelper() {
   // _listeners keeps a list of messages for which we added a listener and the
   // kind of listener that we added (strong or weak). It's an object of this
   // form:
   //  {
   //    "message1": true,
   //    "messagen": false
   //  }
@@ -80,18 +84,18 @@ DOMRequestIpcHelper.prototype = {
         if (!!aMsg.weakRef == this._listeners[name].weakRef) {
           this._listeners[name].count++;
           return;
         } else {
           throw Cr.NS_ERROR_FAILURE;
         }
       }
 
-      aMsg.weakRef ? Services.cpmm.addWeakMessageListener(name, this)
-                   : Services.cpmm.addMessageListener(name, this);
+      aMsg.weakRef ? cpmm.addWeakMessageListener(name, this)
+                   : cpmm.addMessageListener(name, this);
       this._listeners[name] = {
         weakRef: !!aMsg.weakRef,
         count: 1
       };
     });
   },
 
   /**
@@ -111,18 +115,18 @@ DOMRequestIpcHelper.prototype = {
       if (this._listeners[aName] == undefined) {
         return;
       }
 
       // Only remove the listener really when we don't have anybody that could
       // be waiting on a message.
       if (!--this._listeners[aName].count) {
         this._listeners[aName].weakRef ?
-            Services.cpmm.removeWeakMessageListener(aName, this)
-          : Services.cpmm.removeMessageListener(aName, this);
+            cpmm.removeWeakMessageListener(aName, this)
+          : cpmm.removeMessageListener(aName, this);
         delete this._listeners[aName];
       }
     });
   },
 
   /**
    * Initialize the helper adding the corresponding listeners to the messages
    * provided as the second parameter.
@@ -172,19 +176,18 @@ DOMRequestIpcHelper.prototype = {
     }
 
     this._destroyed = true;
 
     Services.obs.removeObserver(this, "inner-window-destroyed");
 
     if (this._listeners) {
       Object.keys(this._listeners).forEach((aName) => {
-        this._listeners[aName].weakRef ?
-            Services.cpmm.removeWeakMessageListener(aName, this)
-          : Services.cpmm.removeMessageListener(aName, this);
+        this._listeners[aName].weakRef ? cpmm.removeWeakMessageListener(aName, this)
+                                       : cpmm.removeMessageListener(aName, this);
       });
     }
 
     this._listeners = null;
     this._requests = null;
 
     // Objects inheriting from DOMRequestIPCHelper may have an uninit function.
     if (this.uninit) {
deleted file mode 100644
--- a/dom/base/MessageListenerManager.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/MessageListenerManager.h"
-
-namespace mozilla {
-namespace dom {
-
-MessageListenerManager::MessageListenerManager(ipc::MessageManagerCallback* aCallback,
-                                               nsFrameMessageManager* aParentManager,
-                                               ipc::MessageManagerFlags aFlags)
-  : nsFrameMessageManager(aCallback, aFlags),
-    mParentManager(aParentManager)
-{
-}
-
-MessageListenerManager::~MessageListenerManager()
-{
-}
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MessageListenerManager)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-NS_INTERFACE_MAP_END_INHERITING(nsFrameMessageManager)
-NS_IMPL_ADDREF_INHERITED(MessageListenerManager, nsFrameMessageManager)
-NS_IMPL_RELEASE_INHERITED(MessageListenerManager, nsFrameMessageManager)
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(MessageListenerManager)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessageListenerManager,
-                                                  nsFrameMessageManager)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentManager)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MessageListenerManager,
-                                               nsFrameMessageManager)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessageListenerManager,
-                                                nsFrameMessageManager)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentManager)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-void
-MessageListenerManager::ClearParentManager(bool aRemove)
-{
-  if (aRemove && mParentManager) {
-    mParentManager->RemoveChildManager(this);
-  }
-  mParentManager = nullptr;
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/base/MessageListenerManager.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_MessageListenerManager_h
-#define mozilla_dom_MessageListenerManager_h
-
-#include "nsCycleCollectionNoteChild.h"
-#include "nsFrameMessageManager.h"
-#include "nsWrapperCache.h"
-
-namespace mozilla {
-namespace dom {
-
-class MessageListenerManager : public nsFrameMessageManager,
-                               public nsWrapperCache
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MessageListenerManager,
-                                                         nsFrameMessageManager)
-
-  nsISupports* GetParentObject()
-  {
-    return ToSupports(mParentManager.get());
-  }
-
-  virtual nsFrameMessageManager* GetParentManager() override
-  {
-    return mParentManager;
-  }
-
-  /**
-   * If aRemove is true then RemoveChildManager(this) will be called on the parent manager
-   * first.
-   */
-  virtual void ClearParentManager(bool aRemove) override;
-
-protected:
-  MessageListenerManager(ipc::MessageManagerCallback* aCallback,
-                         nsFrameMessageManager* aParentManager,
-                         MessageManagerFlags aFlags);
-  virtual ~MessageListenerManager();
-
-  RefPtr<nsFrameMessageManager> mParentManager;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_MessageListenerManager_h
deleted file mode 100644
--- a/dom/base/MessageManagerGlobal.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_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
deleted file mode 100644
--- a/dom/base/MessageSender.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/MessageSender.h"
-
-namespace mozilla {
-namespace dom {
-
-void
-MessageSender::InitWithCallback(ipc::MessageManagerCallback* aCallback)
-{
-  if (mCallback) {
-    // Initialization should only happen once.
-    return;
-  }
-
-  SetCallback(aCallback);
-
-  // First load parent scripts by adding this to parent manager.
-  if (mParentManager) {
-    mParentManager->AddChildManager(this);
-  }
-
-  for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
-    LoadFrameScript(mPendingScripts[i], false, mPendingScriptsGlobalStates[i]);
-  }
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/base/MessageSender.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_MessageSender_h
-#define mozilla_dom_MessageSender_h
-
-#include "mozilla/dom/MessageListenerManager.h"
-
-namespace mozilla {
-namespace dom {
-
-class MessageSender : public MessageListenerManager
-{
-public:
-  void InitWithCallback(ipc::MessageManagerCallback* aCallback);
-
-protected:
-  MessageSender(ipc::MessageManagerCallback* aCallback,
-                nsFrameMessageManager* aParentManager,
-                MessageManagerFlags aFlags)
-    : MessageListenerManager(aCallback, aParentManager, aFlags)
-  {}
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_MessageSender_h
--- a/dom/base/ProcessGlobal.cpp
+++ b/dom/base/ProcessGlobal.cpp
@@ -2,82 +2,53 @@
 /* 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 "mozilla/dom/MessageManagerBinding.h"
-#include "mozilla/dom/ResolveSystemBinding.h"
+#include "nsDOMClassInfoID.h"
+#include "mozilla/HoldDropJSObjects.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 ProcessGlobal::ProcessGlobal(nsFrameMessageManager* aMessageManager)
- : MessageManagerGlobal(aMessageManager),
-   mInitialized(false)
+ : mInitialized(false),
+   mMessageManager(aMessageManager)
 {
+  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 MessageManagerGlobal::MarkForCC();
+  return mMessageManager ? mMessageManager->MarkForCC() : false;
 }
 
 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
@@ -99,52 +70,38 @@ 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;
 
-  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;
+  nsISupports* scopeSupports = NS_ISUPPORTS_CAST(nsIContentProcessMessageManager*, this);
+  return InitChildGlobalInternal(scopeSupports, NS_LITERAL_CSTRING("processChildGlobal"));
 }
 
 void
 ProcessGlobal::LoadScript(const nsAString& aURL)
 {
   Init();
-  JS::Rooted<JSObject*> global(mozilla::dom::RootingCx(), GetWrapper());
-  LoadScriptInternal(global, aURL, false);
+  LoadScriptInternal(aURL, false);
 }
 
 void
 ProcessGlobal::SetInitialProcessData(JS::HandleValue aInitialData)
 {
   mMessageManager->SetInitialProcessData(aInitialData);
 }
--- a/dom/base/ProcessGlobal.h
+++ b/dom/base/ProcessGlobal.h
@@ -3,17 +3,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #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"
@@ -21,98 +20,61 @@
 #include "nsServiceManagerUtils.h"
 #include "nsWeakReference.h"
 #include "nsWrapperCache.h"
 
 namespace mozilla {
 namespace dom {
 
 class ProcessGlobal :
+  public nsMessageManagerScriptExecutor,
   public nsIContentProcessMessageManager,
-  public nsMessageManagerScriptExecutor,
   public nsIGlobalObject,
   public nsIScriptObjectPrincipal,
   public nsSupportsWeakReference,
-  public ipc::MessageManagerCallback,
-  public MessageManagerGlobal,
+  public mozilla::dom::ipc::MessageManagerCallback,
   public nsWrapperCache
 {
 public:
   explicit ProcessGlobal(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 mozilla::dom::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 GetWrapper();
+    return mGlobal;
   }
   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
deleted file mode 100644
--- a/dom/base/SyncMessageSender.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_SyncMessageSender_h
-#define mozilla_dom_SyncMessageSender_h
-
-#include "mozilla/dom/MessageSender.h"
-
-namespace mozilla {
-namespace dom {
-
-class SyncMessageSender : public MessageSender
-{
-protected:
-  SyncMessageSender(ipc::MessageManagerCallback* aCallback,
-                    MessageManagerFlags aFlags)
-    : MessageSender(aCallback, nullptr, aFlags)
-  {}
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_SyncMessageSender_h
--- a/dom/base/TextInputProcessor.cpp
+++ b/dom/base/TextInputProcessor.cpp
@@ -13,17 +13,16 @@
 #include "mozilla/widget/IMEData.h"
 #include "mozilla/dom/KeyboardEvent.h"
 #include "nsContentUtils.h"
 #include "nsIDocShell.h"
 #include "nsIWidget.h"
 #include "nsPIDOMWindow.h"
 #include "nsPresContext.h"
 
-using mozilla::dom::KeyboardEvent;
 using namespace mozilla::widget;
 
 namespace mozilla {
 
 /******************************************************************************
  * TextInputProcessorNotification
  ******************************************************************************/
 
--- a/dom/base/TimeoutExecutor.cpp
+++ b/dom/base/TimeoutExecutor.cpp
@@ -3,17 +3,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "TimeoutExecutor.h"
 
 #include "mozilla/dom/TimeoutManager.h"
 #include "nsComponentManagerUtils.h"
-#include "nsIEventTarget.h"
 #include "nsString.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_ISUPPORTS(TimeoutExecutor, nsIRunnable, nsITimerCallback, nsINamed)
 
 TimeoutExecutor::~TimeoutExecutor()
--- a/dom/base/TimeoutManager.h
+++ b/dom/base/TimeoutManager.h
@@ -7,17 +7,16 @@
 #ifndef mozilla_dom_TimeoutManager_h__
 #define mozilla_dom_TimeoutManager_h__
 
 #include "mozilla/dom/Timeout.h"
 #include "nsTArray.h"
 
 class nsIEventTarget;
 class nsITimeoutHandler;
-class nsITimer;
 class nsGlobalWindowInner;
 
 namespace mozilla {
 namespace dom {
 
 class OrderedTimeoutIterator;
 class TimeoutExecutor;
 
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -151,23 +151,19 @@ EXPORTS.mozilla += [
 EXPORTS.mozilla.dom += [
     '!UseCounterList.h',
     'AnonymousContent.h',
     'Attr.h',
     'BarProps.h',
     'BodyUtil.h',
     '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,19 +190,16 @@ EXPORTS.mozilla.dom += [
     'IdleDeadline.h',
     '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',
     'ResponsiveImageSelector.h',
@@ -214,17 +207,16 @@ EXPORTS.mozilla.dom += [
     'ScreenOrientation.h',
     'Selection.h',
     'ShadowRoot.h',
     'StructuredCloneBlob.h',
     'StructuredCloneHolder.h',
     'StructuredCloneTags.h',
     'StyleSheetList.h',
     'SubtleCrypto.h',
-    'SyncMessageSender.h',
     'TabGroup.h',
     'Text.h',
     'Timeout.h',
     'TimeoutHandler.h',
     'TimeoutManager.h',
     'TreeWalker.h',
     'WebKitCSSMatrix.h',
     'WindowOrientationObserver.h',
@@ -237,18 +229,16 @@ if CONFIG['FUZZING']:
 
 UNIFIED_SOURCES += [
     'AnonymousContent.cpp',
     'Attr.cpp',
     'BarProps.cpp',
     'BodyUtil.cpp',
     'BorrowedAttrInfo.cpp',
     'ChildIterator.cpp',
-    'ChromeMessageBroadcaster.cpp',
-    'ChromeMessageSender.cpp',
     'ChromeNodeList.cpp',
     'ChromeUtils.cpp',
     'Comment.cpp',
     'Crypto.cpp',
     'CustomElementRegistry.cpp',
     'DirectionalityUtils.cpp',
     'DispatcherTrait.cpp',
     'DocGroup.cpp',
@@ -274,18 +264,16 @@ UNIFIED_SOURCES += [
     'IdleDeadline.cpp',
     'IdleRequest.cpp',
     'IDTracker.cpp',
     'ImageEncoder.cpp',
     'ImageTracker.cpp',
     'IntlUtils.cpp',
     'Link.cpp',
     'Location.cpp',
-    'MessageListenerManager.cpp',
-    'MessageSender.cpp',
     'Navigator.cpp',
     'NodeInfo.cpp',
     'NodeIterator.cpp',
     'nsAtomListUtils.cpp',
     'nsAttrAndChildArray.cpp',
     'nsAttrValue.cpp',
     'nsAttrValueOrString.cpp',
     'nsCCUncollectableMarker.cpp',
--- a/dom/base/nsCCUncollectableMarker.cpp
+++ b/dom/base/nsCCUncollectableMarker.cpp
@@ -12,32 +12,32 @@
 #include "nsIDocument.h"
 #include "XULDocument.h"
 #include "nsIWindowMediator.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebNavigation.h"
 #include "nsISHistory.h"
 #include "nsISHEntry.h"
 #include "nsISHContainer.h"
+#include "nsITabChild.h"
 #include "nsIWindowWatcher.h"
 #include "mozilla/Services.h"
 #include "nsIXULWindow.h"
 #include "nsIAppShellService.h"
 #include "nsAppShellCID.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsJSEnvironment.h"
 #include "nsInProcessTabChildGlobal.h"
 #include "nsFrameLoader.h"
 #include "mozilla/CycleCollectedJSContext.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ProcessGlobal.h"
-#include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/TimeoutManager.h"
 #include "xpcpublic.h"
 #include "nsObserverService.h"
 #include "nsFocusManager.h"
 #include "nsIInterfaceRequestorUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -306,19 +306,21 @@ MarkWindowList(nsISimpleEnumerator* aWin
   nsCOMPtr<nsISupports> iter;
   while (NS_SUCCEEDED(aWindowList->GetNext(getter_AddRefs(iter))) &&
          iter) {
     if (nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(iter)) {
       nsCOMPtr<nsIDocShell> rootDocShell = window->GetDocShell();
 
       MarkDocShell(rootDocShell, aCleanupJS, aPrepareForCC);
 
-      RefPtr<TabChild> tabChild = TabChild::GetFrom(rootDocShell);
+      nsCOMPtr<nsITabChild> tabChild =
+        rootDocShell ? rootDocShell->GetTabChild() : nullptr;
       if (tabChild) {
-        nsCOMPtr<nsIContentFrameMessageManager> mm = tabChild->GetMessageManager();
+        nsCOMPtr<nsIContentFrameMessageManager> mm;
+        tabChild->GetMessageManager(getter_AddRefs(mm));
         if (mm) {
           // MarkForCC ends up calling UnmarkGray on message listeners, which
           // TraceBlackJS can't do yet.
           mm->MarkForCC();
         }
       }
     }
   }
@@ -526,17 +528,17 @@ mozilla::dom::TraceBlackJS(JSTracer* aTr
         if (window->IsRootOuterWindow()) {
           // In child process trace all the TabChildGlobals.
           // Since there is one root outer window per TabChildGlobal, we need
           // to look for only those windows, not all.
           nsIDocShell* ds = window->GetDocShell();
           if (ds) {
             nsCOMPtr<nsITabChild> tabChild = ds->GetTabChild();
             if (tabChild) {
-              nsCOMPtr<nsISupports> mm;
+              nsCOMPtr<nsIContentFrameMessageManager> mm;
               tabChild->GetMessageManager(getter_AddRefs(mm));
               nsCOMPtr<EventTarget> et = do_QueryInterface(mm);
               if (et) {
                 nsCOMPtr<nsISupports> tabChildAsSupports =
                   do_QueryInterface(tabChild);
                 mozilla::TraceScriptHolder(tabChildAsSupports, aTrc);
                 EventListenerManager* elm = et->GetExistingListenerManager();
                 if (elm) {
--- a/dom/base/nsContentIterator.cpp
+++ b/dom/base/nsContentIterator.cpp
@@ -13,17 +13,16 @@
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "nsContentUtils.h"
 #include "nsINode.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsElementTable.h"
 
 using mozilla::DebugOnly;
-using mozilla::Move;
 using mozilla::RawRangeBoundary;
 
 // couple of utility static functs
 
 ///////////////////////////////////////////////////////////////////////////
 // NodeIsInTraversalRange: returns true if content is visited during
 // the traversal of the range in the specified mode.
 //
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -68,16 +68,17 @@
 #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"
 
@@ -125,16 +126,19 @@ 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
 //
@@ -159,16 +163,32 @@ 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_ONLY_CLASSINFO_DATA(ChromeMessageBroadcaster, nsDOMGenericSH,
+                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageSender, nsDOMGenericSH,
+                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
+
+
   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)
@@ -400,16 +420,46 @@ 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(ChromeMessageBroadcaster, nsISupports)
+    DOM_CLASSINFO_MAP_ENTRY(nsIFrameScriptLoader)
+    DOM_CLASSINFO_MAP_ENTRY(nsIProcessScriptLoader)
+    DOM_CLASSINFO_MAP_ENTRY(nsIGlobalProcessScriptLoader)
+    DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager)
+    DOM_CLASSINFO_MAP_ENTRY(nsIMessageBroadcaster)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeMessageSender, nsISupports)
+    DOM_CLASSINFO_MAP_ENTRY(nsIFrameScriptLoader)
+    DOM_CLASSINFO_MAP_ENTRY(nsIProcessScriptLoader)
+    DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager)
+    DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender)
+  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
 
@@ -1867,8 +1917,46 @@ 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,9 +207,34 @@ 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,16 +14,21 @@
 
 #include "nsIXPCScriptable.h"
 
 enum nsDOMClassInfoID
 {
   eDOMClassInfo_DOMPrototype_id,
   eDOMClassInfo_DOMConstructor_id,
 
+  eDOMClassInfo_ContentFrameMessageManager_id,
+  eDOMClassInfo_ContentProcessMessageManager_id,
+  eDOMClassInfo_ChromeMessageBroadcaster_id,
+  eDOMClassInfo_ChromeMessageSender_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
@@ -74,17 +74,16 @@
 #include "ContentParent.h"
 #include "TabParent.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Unused.h"
-#include "mozilla/dom/ChromeMessageSender.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FrameLoaderBinding.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/layout/RenderFrameParent.h"
 #include "nsGenericHTMLFrameElement.h"
 #include "GeckoProfiler.h"
 
 #include "jsapi.h"
@@ -1638,22 +1637,24 @@ 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 = mChildMessageManager;
+    nsInProcessTabChildGlobal* tabChild =
+      static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
     tabChild->SetOwner(otherContent);
     tabChild->SetChromeMessageManager(otherMessageManager);
   }
   if (aOther->mChildMessageManager) {
-    nsInProcessTabChildGlobal* otherTabChild = aOther->mChildMessageManager;
+    nsInProcessTabChildGlobal* otherTabChild =
+      static_cast<nsInProcessTabChildGlobal*>(aOther->mChildMessageManager.get());
     otherTabChild->SetOwner(ourContent);
     otherTabChild->SetChromeMessageManager(ourMessageManager);
   }
   // Swap and setup things in parent message managers.
   if (mMessageManager) {
     mMessageManager->SetCallback(aOther);
   }
   if (aOther->mMessageManager) {
@@ -1878,29 +1879,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) {
-    mChildMessageManager->FireUnloadEvent();
+    static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->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.
-    mChildMessageManager->DisconnectEventListeners();
+    static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->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
@@ -1925,17 +1926,17 @@ nsFrameLoader::DestroyComplete()
     mRemoteBrowser = nullptr;
   }
 
   if (mMessageManager) {
     mMessageManager->Disconnect();
   }
 
   if (mChildMessageManager) {
-    mChildMessageManager->Disconnect();
+    static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->Disconnect();
   }
 
   mMessageManager = nullptr;
   mChildMessageManager = nullptr;
 }
 
 NS_IMETHODIMP
 nsFrameLoader::GetDepthTooGreat(bool* aDepthTooGreat)
@@ -2981,21 +2982,22 @@ public:
     : nsSameProcessAsyncMessageBase(aRootingCx, aCpows)
     , mozilla::Runnable("nsAsyncMessageToChild")
     , mFrameLoader(aFrameLoader)
   {
   }
 
   NS_IMETHOD Run() override
   {
-    nsInProcessTabChildGlobal* tabChild = mFrameLoader->mChildMessageManager;
+    nsInProcessTabChildGlobal* tabChild =
+      static_cast<nsInProcessTabChildGlobal*>(mFrameLoader->mChildMessageManager.get());
     // 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->GetWrapper());
+      JS::Rooted<JSObject*> kungFuDeathGrip(dom::RootingCx(), tabChild->GetGlobal());
       ReceiveMessage(static_cast<EventTarget*>(tabChild), mFrameLoader,
                      tabChild->GetInnerManager());
     }
     return NS_OK;
   }
   RefPtr<nsFrameLoader> mFrameLoader;
 };
 
@@ -3099,18 +3101,19 @@ nsFrameLoader::EnsureMessageManager()
 
     if (!parentManager) {
       chromeWindow->GetMessageManager(getter_AddRefs(parentManager));
     }
   } else {
     parentManager = do_GetService("@mozilla.org/globalmessagemanager;1");
   }
 
-  mMessageManager = new ChromeMessageSender(nullptr,
-                                            static_cast<nsFrameMessageManager*>(parentManager.get()));
+  mMessageManager = new nsFrameMessageManager(nullptr,
+                                              static_cast<nsFrameMessageManager*>(parentManager.get()),
+                                              MM_CHROME);
   if (!IsRemoteFrame()) {
     nsresult rv = MaybeCreateDocShell();
     if (NS_FAILED(rv)) {
       return rv;
     }
     NS_ASSERTION(mDocShell,
                  "MaybeCreateDocShell succeeded, but null mDocShell");
     if (!mDocShell) {
@@ -3133,17 +3136,17 @@ nsFrameLoader::ReallyLoadFrameScripts()
     mMessageManager->InitWithCallback(this);
   }
   return NS_OK;
 }
 
 EventTarget*
 nsFrameLoader::GetTabChildGlobalAsEventTarget()
 {
-  return mChildMessageManager.get();
+  return static_cast<nsInProcessTabChildGlobal*>(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,29 +27,28 @@
 #include "Units.h"
 #include "nsIWebBrowserPersistable.h"
 #include "nsIFrame.h"
 #include "nsPluginTags.h"
 
 class nsIURI;
 class nsSubDocumentFrame;
 class nsView;
-class nsInProcessTabChildGlobal;
+class nsIInProcessContentFrameMessageManager;
 class AutoResetInShow;
 class AutoResetInFrameSwap;
 class nsITabParent;
 class nsIDocShellTreeItem;
 class nsIDocShellTreeOwner;
 
 namespace mozilla {
 
 class OriginAttributes;
 
 namespace dom {
-class ChromeMessageSender;
 class ContentParent;
 class PBrowserParent;
 class Promise;
 class TabParent;
 class MutableTabContext;
 
 namespace ipc {
 class StructuredCloneData;
@@ -264,17 +263,17 @@ public:
    * constructed for this->GetURL().  This can happen, e.g., if the
    * <browser> was just navigated to a new URL, but hasn't painted the
    * new page yet.  A render frame for the previous page may be
    * returned.  (In-process <browser> behaves similarly, and this
    * behavior seems desirable.)
    */
   RenderFrameParent* GetCurrentRenderFrame() const;
 
-  mozilla::dom::ChromeMessageSender* GetFrameMessageManager() { return mMessageManager; }
+  nsFrameMessageManager* GetFrameMessageManager() { return mMessageManager; }
 
   mozilla::dom::Element* GetOwnerContent() { return mOwnerContent; }
   bool ShouldClipSubdocument() { return mClipSubdocument; }
 
   bool ShouldClampScrollPosition() { return mClampScrollPosition; }
 
   /**
    * Tell this FrameLoader to use a particular remote browser.
@@ -315,18 +314,18 @@ public:
   void GetURL(nsString& aURL, nsIPrincipal** aTriggeringPrincipal);
 
   // 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;
-  RefPtr<nsInProcessTabChildGlobal> mChildMessageManager;
+  RefPtr<nsFrameMessageManager> mMessageManager;
+  nsCOMPtr<nsIInProcessContentFrameMessageManager> 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
@@ -7,59 +7,54 @@
 #include "base/basictypes.h"
 
 #include "nsFrameMessageManager.h"
 
 #include "ContentChild.h"
 #include "GeckoProfiler.h"
 #include "nsASCIIMask.h"
 #include "nsContentUtils.h"
+#include "nsDOMClassInfoID.h"
 #include "nsError.h"
 #include "nsIXPConnect.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "nsJSUtils.h"
 #include "nsJSPrincipals.h"
 #include "nsNetUtil.h"
 #include "mozilla/dom/ScriptLoader.h"
 #include "nsFrameLoader.h"
 #include "nsIInputStream.h"
 #include "nsIXULRuntime.h"
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsIMemoryReporter.h"
 #include "nsIProtocolHandler.h"
 #include "nsIScriptSecurityManager.h"
+#include "nsIDOMClassInfo.h"
 #include "xpcpublic.h"
 #include "mozilla/CycleCollectedJSContext.h"
 #include "mozilla/IntentionalCrash.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ScriptPreloader.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/DOMPrefs.h"
-#include "mozilla/dom/ChildProcessMessageManager.h"
-#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"
 #include "nsQueryObject.h"
-#include "xpcprivate.h"
 #include <algorithm>
 #include "chrome/common/ipc_channel.h" // for IPC::Channel::kMaximumMessageSize
 
 #ifdef ANDROID
 #include <android/log.h>
 #endif
 #ifdef XP_WIN
 #include <windows.h>
@@ -71,39 +66,56 @@
 #ifdef FUZZING
 #include "MessageManagerFuzzer.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::dom::ipc;
 
-nsFrameMessageManager::nsFrameMessageManager(MessageManagerCallback* aCallback,
-                                             MessageManagerFlags aFlags)
- : mChrome(aFlags & MessageManagerFlags::MM_CHROME),
-   mGlobal(aFlags & MessageManagerFlags::MM_GLOBAL),
-   mIsProcessManager(aFlags & MessageManagerFlags::MM_PROCESSMANAGER),
-   mIsBroadcaster(aFlags & MessageManagerFlags::MM_BROADCASTER),
-   mOwnsCallback(aFlags & MessageManagerFlags::MM_OWNSCALLBACK),
-   mHandlingMessage(false),
-   mClosed(false),
-   mDisconnected(false),
-   mCallback(aCallback)
+nsFrameMessageManager::nsFrameMessageManager(mozilla::dom::ipc::MessageManagerCallback* aCallback,
+                                             nsFrameMessageManager* aParentManager,
+                                             /* mozilla::dom::ipc::MessageManagerFlags */ uint32_t aFlags)
+ : mChrome(!!(aFlags & mozilla::dom::ipc::MM_CHROME)),
+   mGlobal(!!(aFlags & mozilla::dom::ipc::MM_GLOBAL)),
+   mIsProcessManager(!!(aFlags & mozilla::dom::ipc::MM_PROCESSMANAGER)),
+   mIsBroadcaster(!!(aFlags & mozilla::dom::ipc::MM_BROADCASTER)),
+   mOwnsCallback(!!(aFlags & mozilla::dom::ipc::MM_OWNSCALLBACK)),
+  mHandlingMessage(false),
+  mClosed(false),
+  mDisconnected(false),
+  mCallback(aCallback),
+  mParentManager(aParentManager)
 {
+  NS_ASSERTION(mChrome || !aParentManager, "Should not set parent manager!");
   NS_ASSERTION(!mIsBroadcaster || !mCallback,
                "Broadcasters cannot have callbacks!");
+  if (mIsProcessManager && (!mChrome || IsBroadcaster())) {
+    mozilla::HoldJSObjects(this);
+  }
+  // This is a bit hackish. When parent manager is global, we want
+  // to attach the message manager to it immediately.
+  // Is it just the frame message manager which waits until the
+  // content process is running.
+  if (mParentManager && (mCallback || IsBroadcaster())) {
+    mParentManager->AddChildManager(this);
+  }
   if (mOwnsCallback) {
     mOwnedCallback = aCallback;
   }
 }
 
 nsFrameMessageManager::~nsFrameMessageManager()
 {
-  for (int32_t i = mChildManagers.Length(); i > 0; --i) {
-    mChildManagers[i - 1]->Disconnect(false);
+  if (mIsProcessManager && (!mChrome || IsBroadcaster())) {
+    mozilla::DropJSObjects(this);
+  }
+  for (int32_t i = mChildManagers.Count(); i > 0; --i) {
+    static_cast<nsFrameMessageManager*>(mChildManagers[i - 1])->
+      Disconnect(false);
   }
   if (mIsProcessManager) {
     if (this == sParentProcessManager) {
       sParentProcessManager = nullptr;
     }
     if (this == sChildProcessManager) {
       sChildProcessManager = nullptr;
       delete mozilla::dom::SameProcessMessageQueue::Get();
@@ -112,30 +124,40 @@ nsFrameMessageManager::~nsFrameMessageMa
       sSameProcessParentManager = nullptr;
     }
   }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameMessageManager)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameMessageManager)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListeners)
+  for (auto iter = tmp->mListeners.Iter(); !iter.Done(); iter.Next()) {
+    nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners = iter.UserData();
+    uint32_t count = listeners->Length();
+    for (uint32_t i = 0; i < count; ++i) {
+      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "listeners[i] mStrongListener");
+      cb.NoteXPCOMChild(listeners->ElementAt(i).mStrongListener.get());
+    }
+  }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildManagers)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentManager)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsFrameMessageManager)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mInitialProcessData)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameMessageManager)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mListeners)
-  for (int32_t i = tmp->mChildManagers.Length(); i > 0; --i) {
-    tmp->mChildManagers[i - 1]->Disconnect(false);
+  tmp->mListeners.Clear();
+  for (int32_t i = tmp->mChildManagers.Count(); i > 0; --i) {
+    static_cast<nsFrameMessageManager*>(tmp->mChildManagers[i - 1])->
+      Disconnect(false);
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildManagers)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentManager)
   tmp->mInitialProcessData.setNull();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentFrameMessageManager)
 
   /* nsFrameMessageManager implements nsIMessageSender and nsIMessageBroadcaster,
@@ -168,16 +190,20 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   /* Process message managers (process message managers) support nsIProcessScriptLoader. */
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIProcessScriptLoader,
                                      mChrome && mIsProcessManager)
 
   /* Global process message managers (process message managers) support nsIGlobalProcessScriptLoader. */
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIGlobalProcessScriptLoader,
                                      mChrome && mIsProcessManager && mIsBroadcaster)
 
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(ChromeMessageBroadcaster,
+                                                   mChrome && mIsBroadcaster)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(ChromeMessageSender,
+                                                   mChrome && !mIsBroadcaster)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameMessageManager)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameMessageManager)
 
 bool
 MessageManagerCallback::BuildClonedMessageDataForParent(nsIContentParent* aParent,
                                                         StructuredCloneData& aData,
@@ -217,105 +243,56 @@ SameProcessCpowHolder::ToObject(JSContex
   }
 
   aObjp.set(mObj);
   return JS_WrapObject(aCx, aObjp);
 }
 
 // nsIMessageListenerManager
 
-void
-nsFrameMessageManager::AddMessageListener(const nsAString& aMessageName,
-                                          MessageListener& aListener,
-                                          bool aListenWhenClosed,
-                                          ErrorResult& aError)
-{
-  AddMessageListener(aMessageName, MessageListenerHolder(&aListener), aListenWhenClosed);
-}
-
 NS_IMETHODIMP
 nsFrameMessageManager::AddMessageListener(const nsAString& aMessage,
                                           nsIMessageListener* aListener,
                                           bool aListenWhenClosed)
 {
-  AddMessageListener(aMessage, MessageListenerHolder(aListener), aListenWhenClosed);
-  return NS_OK;
-}
-
-void
-nsFrameMessageManager::AddMessageListener(const nsAString& aMessage,
-                                          MessageListenerHolder&& aListener,
-                                          bool aListenWhenClosed)
-{
   auto listeners = mListeners.LookupForAdd(aMessage).OrInsert([]() {
       return new nsAutoTObserverArray<nsMessageListenerInfo, 1>();
     });
   uint32_t len = listeners->Length();
   for (uint32_t i = 0; i < len; ++i) {
     if (listeners->ElementAt(i).mStrongListener == aListener) {
-      return;
+      return NS_OK;
     }
   }
 
   nsMessageListenerInfo* entry = listeners->AppendElement();
-  entry->mStrongListener = Move(aListener);
+  NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
+  entry->mStrongListener = aListener;
   entry->mListenWhenClosed = aListenWhenClosed;
-}
-
-void
-nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessageName,
-                                             MessageListener& aListener,
-                                             ErrorResult& aError)
-{
-  RemoveMessageListener(aMessageName, MessageListenerHolder(&aListener));
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessage,
                                              nsIMessageListener* aListener)
 {
-  RemoveMessageListener(aMessage, MessageListenerHolder(aListener));
-  return NS_OK;
-}
-
-void
-nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessage,
-                                             const MessageListenerHolder& aListener)
-{
   nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
     mListeners.Get(aMessage);
-  if (listeners) {
-    uint32_t len = listeners->Length();
-    for (uint32_t i = 0; i < len; ++i) {
-      if (listeners->ElementAt(i).mStrongListener == aListener) {
-        listeners->RemoveElementAt(i);
-        return;
-      }
+  if (!listeners) {
+    return NS_OK;
+  }
+
+  uint32_t len = listeners->Length();
+  for (uint32_t i = 0; i < len; ++i) {
+    if (listeners->ElementAt(i).mStrongListener == aListener) {
+      listeners->RemoveElementAt(i);
+      return NS_OK;
     }
   }
-}
-
-static already_AddRefed<nsIMessageListener>
-ToXPCOMMessageListener(MessageListener& aListener)
-{
-  return MessageListenerHolder(&aListener).ToXPCOMCallback();
-}
-
-void
-nsFrameMessageManager::AddWeakMessageListener(const nsAString& aMessageName,
-                                              MessageListener& aListener,
-                                              ErrorResult& aError)
-{
-  nsCOMPtr<nsIMessageListener> listener(ToXPCOMMessageListener(aListener));
-  if (!listener) {
-    aError.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  aError = AddWeakMessageListener(aMessageName, listener);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::AddWeakMessageListener(const nsAString& aMessage,
                                               nsIMessageListener* aListener)
 {
   nsWeakPtr weak = do_GetWeakReference(aListener);
   NS_ENSURE_TRUE(weak, NS_ERROR_NO_INTERFACE);
@@ -350,30 +327,16 @@ nsFrameMessageManager::AddWeakMessageLis
   }
 
   nsMessageListenerInfo* entry = listeners->AppendElement();
   entry->mWeakListener = weak;
   entry->mListenWhenClosed = false;
   return NS_OK;
 }
 
-void
-nsFrameMessageManager::RemoveWeakMessageListener(const nsAString& aMessageName,
-                                                 MessageListener& aListener,
-                                                 ErrorResult& aError)
-{
-  nsCOMPtr<nsIMessageListener> listener(ToXPCOMMessageListener(aListener));
-  if (!listener) {
-    aError.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
-  aError = RemoveWeakMessageListener(aMessageName, listener);
-}
-
 NS_IMETHODIMP
 nsFrameMessageManager::RemoveWeakMessageListener(const nsAString& aMessage,
                                                  nsIMessageListener* aListener)
 {
   nsWeakPtr weak = do_GetWeakReference(aListener);
   NS_ENSURE_TRUE(weak, NS_OK);
 
   nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
@@ -390,151 +353,130 @@ nsFrameMessageManager::RemoveWeakMessage
     }
   }
 
   return NS_OK;
 }
 
 // nsIFrameScriptLoader
 
-void
+NS_IMETHODIMP
 nsFrameMessageManager::LoadScript(const nsAString& aURL,
                                   bool aAllowDelayedLoad,
-                                  bool aRunInGlobalScope,
-                                  ErrorResult& aError)
+                                  bool aRunInGlobalScope)
 {
   if (aAllowDelayedLoad) {
     // Cache for future windows or frames
     mPendingScripts.AppendElement(aURL);
     mPendingScriptsGlobalStates.AppendElement(aRunInGlobalScope);
   }
 
   if (mCallback) {
 #ifdef DEBUG_smaug
     printf("Will load %s \n", NS_ConvertUTF16toUTF8(aURL).get());
 #endif
-    if (!mCallback->DoLoadMessageManagerScript(aURL, aRunInGlobalScope)) {
-      aError.Throw(NS_ERROR_FAILURE);
-      return;
-    }
+    NS_ENSURE_TRUE(mCallback->DoLoadMessageManagerScript(aURL, aRunInGlobalScope),
+                   NS_ERROR_FAILURE);
   }
 
-  for (uint32_t i = 0; i < mChildManagers.Length(); ++i) {
-    RefPtr<nsFrameMessageManager> mm = mChildManagers[i];
+  for (int32_t i = 0; i < mChildManagers.Count(); ++i) {
+    RefPtr<nsFrameMessageManager> mm =
+      static_cast<nsFrameMessageManager*>(mChildManagers[i]);
     if (mm) {
       // Use false here, so that child managers don't cache the script, which
       // is already cached in the parent.
-      mm->LoadScript(aURL, false, aRunInGlobalScope, IgnoreErrors());
+      mm->LoadScript(aURL, false, aRunInGlobalScope);
     }
   }
+  return NS_OK;
 }
 
-void
+NS_IMETHODIMP
 nsFrameMessageManager::RemoveDelayedScript(const nsAString& aURL)
 {
   for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
     if (mPendingScripts[i] == aURL) {
       mPendingScripts.RemoveElementAt(i);
       mPendingScriptsGlobalStates.RemoveElementAt(i);
       break;
     }
   }
+  return NS_OK;
 }
 
-void
-nsFrameMessageManager::GetDelayedScripts(JSContext* aCx,
-                                         nsTArray<nsTArray<JS::Value>>& aList,
-                                         ErrorResult& aError)
+NS_IMETHODIMP
+nsFrameMessageManager::GetDelayedScripts(JSContext* aCx, JS::MutableHandle<JS::Value> aList)
 {
   // Frame message managers may return an incomplete list because scripts
   // that were loaded after it was connected are not added to the list.
   if (!IsGlobal() && !IsBroadcaster()) {
     NS_WARNING("Cannot retrieve list of pending frame scripts for frame"
                "message managers as it may be incomplete");
-    aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
-    return;
+    return NS_ERROR_NOT_IMPLEMENTED;
   }
 
-  aError.MightThrowJSException();
+  JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, mPendingScripts.Length()));
+  NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
 
-  aList.SetCapacity(mPendingScripts.Length());
+  JS::Rooted<JSString*> url(aCx);
+  JS::Rooted<JSObject*> pair(aCx);
   for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
-    JS::Rooted<JS::Value> url(aCx);
-    if (!ToJSValue(aCx, mPendingScripts[i], &url)) {
-      aError.NoteJSContextException(aCx);
-      return;
-    }
+    url = JS_NewUCStringCopyN(aCx, mPendingScripts[i].get(), mPendingScripts[i].Length());
+    NS_ENSURE_TRUE(url, NS_ERROR_OUT_OF_MEMORY);
 
-    nsTArray<JS::Value>* array = aList.AppendElement(2);
-    array->AppendElement(url);
-    array->AppendElement(JS::BooleanValue(mPendingScriptsGlobalStates[i]));
-  }
-}
+    JS::AutoValueArray<2> pairElts(aCx);
+    pairElts[0].setString(url);
+    pairElts[1].setBoolean(mPendingScriptsGlobalStates[i]);
 
-nsresult
-nsFrameMessageManager::GetDelayedScripts(JSContext* aCx,
-                                         JS::MutableHandle<JS::Value> aList)
-{
-  ErrorResult rv;
-  nsTArray<nsTArray<JS::Value>> list;
-  SequenceRooter<nsTArray<JS::Value>> listRooter(aCx, &list);
-  GetDelayedScripts(aCx, list, rv);
-  rv.WouldReportJSException();
-  if (rv.Failed()) {
-    return rv.StealNSResult();
+    pair = JS_NewArrayObject(aCx, pairElts);
+    NS_ENSURE_TRUE(pair, NS_ERROR_OUT_OF_MEMORY);
+
+    NS_ENSURE_TRUE(JS_DefineElement(aCx, array, i, pair, JSPROP_ENUMERATE),
+                   NS_ERROR_OUT_OF_MEMORY);
   }
 
-  if (!ToJSValue(aCx, list, aList)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
+  aList.setObject(*array);
   return NS_OK;
 }
 
 // nsIFrameScriptLoader
 
 NS_IMETHODIMP
 nsFrameMessageManager::LoadFrameScript(const nsAString& aURL,
                                        bool aAllowDelayedLoad,
                                        bool aRunInGlobalScope)
 {
-  ErrorResult rv;
-  LoadScript(aURL, aAllowDelayedLoad, aRunInGlobalScope, rv);
-  return rv.StealNSResult();
+  return LoadScript(aURL, aAllowDelayedLoad, aRunInGlobalScope);
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::RemoveDelayedFrameScript(const nsAString& aURL)
 {
-  RemoveDelayedScript(aURL);
-  return NS_OK;
+  return RemoveDelayedScript(aURL);
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::GetDelayedFrameScripts(JSContext* aCx, JS::MutableHandle<JS::Value> aList)
 {
   return GetDelayedScripts(aCx, aList);
 }
 
 // nsIProcessScriptLoader
 
 NS_IMETHODIMP
 nsFrameMessageManager::LoadProcessScript(const nsAString& aURL,
                                          bool aAllowDelayedLoad)
 {
-  ErrorResult rv;
-  LoadScript(aURL, aAllowDelayedLoad, false, rv);
-  return rv.StealNSResult();
+  return LoadScript(aURL, aAllowDelayedLoad, false);
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::RemoveDelayedProcessScript(const nsAString& aURL)
 {
-  RemoveDelayedScript(aURL);
-  return NS_OK;
+  return RemoveDelayedScript(aURL);
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::GetDelayedProcessScripts(JSContext* aCx, JS::MutableHandle<JS::Value> aList)
 {
   return GetDelayedScripts(aCx, aList);
 }
 
@@ -657,120 +599,57 @@ nsFrameMessageManager::SendMessage(const
                                    JSContext* aCx,
                                    uint8_t aArgc,
                                    JS::MutableHandle<JS::Value> aRetval,
                                    bool aIsSync)
 {
   AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(
     "nsFrameMessageManager::SendMessage", EVENTS, aMessageName);
 
+  NS_ASSERTION(!IsGlobal(), "Should not call SendSyncMessage in chrome");
+  NS_ASSERTION(!IsBroadcaster(), "Should not call SendSyncMessage in chrome");
+  NS_ASSERTION(!mParentManager, "Should not have parent manager in content!");
+
   aRetval.setUndefined();
+  NS_ENSURE_TRUE(mCallback, NS_ERROR_NOT_INITIALIZED);
 
   if (sSendingSyncMessage && aIsSync) {
     // No kind of blocking send should be issued on top of a sync message.
     return NS_ERROR_UNEXPECTED;
   }
 
   StructuredCloneData data;
   if (aArgc >= 2 && !GetParamsForMessage(aCx, aJSON, JS::UndefinedHandleValue, data)) {
     return NS_ERROR_DOM_DATA_CLONE_ERR;
   }
 
-  JS::Rooted<JSObject*> objects(aCx);
-  if (aArgc >= 3 && aObjects.isObject()) {
-    objects = &aObjects.toObject();
-  }
-
-  nsTArray<JS::Value> result;
-  SequenceRooter<JS::Value> resultRooter(aCx, &result);
-  ErrorResult rv;
-  SendMessage(aCx, aMessageName, data, objects, aPrincipal, aIsSync, result, rv);
-  rv.WouldReportJSException();
-  if (rv.Failed()) {
-    return rv.StealNSResult();
-  }
-
-  JS::Rooted<JSObject*> dataArray(aCx);
-  if (!ToJSValue(aCx, result, aRetval)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  return NS_OK;
-}
-
-void
-nsFrameMessageManager::SendMessage(JSContext* aCx,
-                                   const nsAString& aMessageName,
-                                   JS::Handle<JS::Value> aObj,
-                                   JS::Handle<JSObject*> aObjects,
-                                   nsIPrincipal* aPrincipal,
-                                   bool aIsSync,
-                                   nsTArray<JS::Value>& aResult,
-                                   ErrorResult& aError)
-{
-  AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(
-    "nsFrameMessageManager::SendMessage", EVENTS, aMessageName);
-
-  if (sSendingSyncMessage && aIsSync) {
-    // No kind of blocking send should be issued on top of a sync message.
-    aError.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-
-  StructuredCloneData data;
-  if (!aObj.isUndefined() &&
-      !GetParamsForMessage(aCx, aObj, JS::UndefinedHandleValue, data)) {
-    aError.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
-    return;
-  }
-
-  SendMessage(aCx, aMessageName, data, aObjects, aPrincipal, aIsSync, aResult,
-              aError);
-}
-
-void
-nsFrameMessageManager::SendMessage(JSContext* aCx,
-                                   const nsAString& aMessageName,
-                                   StructuredCloneData& aData,
-                                   JS::Handle<JSObject*> aObjects,
-                                   nsIPrincipal* aPrincipal,
-                                   bool aIsSync,
-                                   nsTArray<JS::Value>& aResult,
-                                   ErrorResult& aError)
-{
-  NS_ASSERTION(!IsGlobal(), "Should not call SendSyncMessage in chrome");
-  NS_ASSERTION(!IsBroadcaster(), "Should not call SendSyncMessage in chrome");
-  NS_ASSERTION(!GetParentManager(),
-               "Should not have parent manager in content!");
-
-  if (!AllowMessage(aData.DataLength(), aMessageName)) {
-    aError.Throw(NS_ERROR_FAILURE);
-    return;
-  }
-
 #ifdef FUZZING
-  if (aData.DataLength() > 0) {
+  if (data.DataLength() > 0) {
     MessageManagerFuzzer::TryMutate(
       aCx,
       aMessageName,
-      &aData,
+      &data,
       JS::UndefinedHandleValue);
   }
 #endif
 
-  if (!mCallback) {
-    aError.Throw(NS_ERROR_NOT_INITIALIZED);
-    return;
+  if (!AllowMessage(data.DataLength(), aMessageName)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  JS::Rooted<JSObject*> objects(aCx);
+  if (aArgc >= 3 && aObjects.isObject()) {
+    objects = &aObjects.toObject();
   }
 
   nsTArray<StructuredCloneData> retval;
 
   TimeStamp start = TimeStamp::Now();
   sSendingSyncMessage |= aIsSync;
-  bool ok = mCallback->DoSendBlockingMessage(aCx, aMessageName, aData, aObjects,
+  bool ok = mCallback->DoSendBlockingMessage(aCx, aMessageName, data, objects,
                                              aPrincipal, &retval, aIsSync);
   if (aIsSync) {
     sSendingSyncMessage = false;
   }
 
   uint32_t latencyMs = round((TimeStamp::Now() - start).ToMilliseconds());
   if (latencyMs >= kMinTelemetrySyncMessageManagerLatencyMs) {
     NS_ConvertUTF16toUTF8 messageName(aMessageName);
@@ -778,43 +657,52 @@ nsFrameMessageManager::SendMessage(JSCon
     // avoid a large number of buckets due to generated names from addons (such
     // as "ublock:sb:{N}"). See bug 1348113 comment 10.
     messageName.StripTaggedASCII(ASCIIMask::Mask0to9());
     Telemetry::Accumulate(Telemetry::IPC_SYNC_MESSAGE_MANAGER_LATENCY_MS,
                           messageName, latencyMs);
   }
 
   if (!ok) {
-    return;
+    return NS_OK;
   }
 
   uint32_t len = retval.Length();
-  aResult.SetCapacity(len);
+  JS::Rooted<JSObject*> dataArray(aCx, JS_NewArrayObject(aCx, len));
+  NS_ENSURE_TRUE(dataArray, NS_ERROR_OUT_OF_MEMORY);
+
   for (uint32_t i = 0; i < len; ++i) {
     JS::Rooted<JS::Value> ret(aCx);
-    retval[i].Read(aCx, &ret, aError);
-    if (aError.Failed()) {
+    ErrorResult rv;
+    retval[i].Read(aCx, &ret, rv);
+    if (rv.Failed()) {
       MOZ_ASSERT(false, "Unable to read structured clone in SendMessage");
-      return;
+      rv.SuppressException();
+      return NS_ERROR_UNEXPECTED;
     }
-    aResult.AppendElement(ret);
+
+    NS_ENSURE_TRUE(JS_DefineElement(aCx, dataArray, i, ret, JSPROP_ENUMERATE),
+                   NS_ERROR_OUT_OF_MEMORY);
   }
+
+  aRetval.setObject(*dataArray);
+  return NS_OK;
 }
 
 nsresult
 nsFrameMessageManager::DispatchAsyncMessageInternal(JSContext* aCx,
                                                     const nsAString& aMessage,
                                                     StructuredCloneData& aData,
                                                     JS::Handle<JSObject *> aCpows,
                                                     nsIPrincipal* aPrincipal)
 {
   if (mIsBroadcaster) {
-    uint32_t len = mChildManagers.Length();
-    for (uint32_t i = 0; i < len; ++i) {
-      mChildManagers[i]->
+    int32_t len = mChildManagers.Count();
+    for (int32_t i = 0; i < len; ++i) {
+      static_cast<nsFrameMessageManager*>(mChildManagers[i])->
          DispatchAsyncMessageInternal(aCx, aMessage, aData, aCpows, aPrincipal);
     }
     return NS_OK;
   }
 
   if (!mCallback) {
     return NS_ERROR_NOT_INITIALIZED;
   }
@@ -854,35 +742,16 @@ nsFrameMessageManager::DispatchAsyncMess
   if (aArgc >= 3 && aObjects.isObject()) {
     objects = &aObjects.toObject();
   }
 
   return DispatchAsyncMessageInternal(aCx, aMessageName, data, objects,
                                       aPrincipal);
 }
 
-void
-nsFrameMessageManager::DispatchAsyncMessage(JSContext* aCx,
-                                            const nsAString& aMessageName,
-                                            JS::Handle<JS::Value> aObj,
-                                            JS::Handle<JSObject*> aObjects,
-                                            nsIPrincipal* aPrincipal,
-                                            JS::Handle<JS::Value> aTransfers,
-                                            ErrorResult& aError)
-{
-  StructuredCloneData data;
-  if (!aObj.isUndefined() && !GetParamsForMessage(aCx, aObj, aTransfers, data)) {
-    aError.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
-    return;
-  }
-
-  aError = DispatchAsyncMessageInternal(aCx, aMessageName, data, aObjects,
-                                        aPrincipal);
-}
-
 // nsIMessageSender
 
 NS_IMETHODIMP
 nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName,
                                         JS::Handle<JS::Value> aJSON,
                                         JS::Handle<JS::Value> aObjects,
                                         nsIPrincipal* aPrincipal,
                                         JS::Handle<JS::Value> aTransfers,
@@ -905,30 +774,28 @@ nsFrameMessageManager::BroadcastAsyncMes
 {
   return DispatchAsyncMessage(aMessageName, aJSON, aObjects, nullptr,
                               JS::UndefinedHandleValue, aCx, aArgc);
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::GetChildCount(uint32_t* aChildCount)
 {
-  *aChildCount = mChildManagers.Length();
+  *aChildCount = static_cast<uint32_t>(mChildManagers.Count());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::GetChildAt(uint32_t aIndex,
                                   nsIMessageListenerManager** aMM)
 {
-  MessageListenerManager* mm = mChildManagers.SafeElementAt(aIndex);
-  if (mm) {
-    CallQueryInterface(mm, aMM);
-  } else {
-    *aMM = nullptr;
-  }
+  *aMM = nullptr;
+  nsCOMPtr<nsIMessageListenerManager> mm =
+    do_QueryInterface(mChildManagers.SafeObjectAt(static_cast<uint32_t>(aIndex)));
+  mm.swap(*aMM);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::ReleaseCachedProcesses()
 {
   ContentParent::ReleaseCachedProcesses();
   return NS_OK;
@@ -1047,18 +914,16 @@ nsFrameMessageManager::ReceiveMessage(ns
                                       bool aTargetClosed,
                                       const nsAString& aMessage,
                                       bool aIsSync,
                                       StructuredCloneData* aCloneData,
                                       mozilla::jsipc::CpowHolder* aCpows,
                                       nsIPrincipal* aPrincipal,
                                       nsTArray<StructuredCloneData>* aRetVal)
 {
-  MOZ_ASSERT(aTarget);
-
   nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
     mListeners.Get(aMessage);
   if (listeners) {
 
     MMListenerRemover lr(this);
 
     nsAutoTObserverArray<nsMessageListenerInfo, 1>::EndLimitedIterator
       iter(*listeners);
@@ -1073,220 +938,228 @@ nsFrameMessageManager::ReceiveMessage(ns
           continue;
         }
       }
 
       if (!listener.mListenWhenClosed && aTargetClosed) {
         continue;
       }
 
-      JS::RootingContext* rcx = RootingCx();
-      JS::Rooted<JSObject*> object(rcx);
-
-      RefPtr<MessageListener> webIDLListener;
-      if (!weakListener && listener.mStrongListener.HasWebIDLCallback()) {
-        webIDLListener = listener.mStrongListener.GetWebIDLCallback();
+      nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS;
+      if (weakListener) {
+        wrappedJS = do_QueryInterface(weakListener);
       } else {
-        webIDLListener = nullptr;
+        wrappedJS = do_QueryInterface(listener.mStrongListener);
       }
 
-      if (webIDLListener) {
-        object = webIDLListener->CallbackOrNull();
-      } else {
-        nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS;
-        if (weakListener) {
-          wrappedJS = do_QueryInterface(weakListener);
-        } else {
-          wrappedJS = do_QueryInterface(listener.mStrongListener.GetXPCOMCallback());
-        }
-
-        if (!wrappedJS) {
-          continue;
-        }
-
-        object = wrappedJS->GetJSObject();
-      }
-
-      if (!object) {
+      if (!wrappedJS) {
         continue;
       }
 
-      AutoEntryScript aes(object, "message manager handler");
+      if (!wrappedJS->GetJSObject()) {
+        continue;
+      }
+
+      AutoEntryScript aes(wrappedJS->GetJSObject(), "message manager handler");
       JSContext* cx = aes.cx();
+      JS::Rooted<JSObject*> object(cx, wrappedJS->GetJSObject());
 
-      RootedDictionary<ReceiveMessageArgument> argument(cx);
+      // The parameter for the listener function.
+      JS::Rooted<JSObject*> param(cx, JS_NewPlainObject(cx));
+      NS_ENSURE_TRUE(param, NS_ERROR_OUT_OF_MEMORY);
+
+      JS::Rooted<JS::Value> targetv(cx);
+      js::AssertSameCompartment(cx, object);
+      nsresult rv = nsContentUtils::WrapNative(cx, aTarget, &targetv);
+      NS_ENSURE_SUCCESS(rv, rv);
 
       JS::Rooted<JSObject*> cpows(cx);
       if (aCpows) {
         if (!aCpows->ToObject(cx, &cpows)) {
           return NS_ERROR_UNEXPECTED;
         }
       }
 
       if (!cpows) {
         cpows = JS_NewPlainObject(cx);
         if (!cpows) {
           return NS_ERROR_UNEXPECTED;
         }
       }
-      argument.mObjects = cpows;
+
+      JS::Rooted<JS::Value> cpowsv(cx, JS::ObjectValue(*cpows));
 
       JS::Rooted<JS::Value> json(cx, JS::NullValue());
       if (aCloneData && aCloneData->DataLength()) {
         ErrorResult rv;
         aCloneData->Read(cx, &json, rv);
         if (NS_WARN_IF(rv.Failed())) {
           rv.SuppressException();
           JS_ClearPendingException(cx);
           return NS_OK;
         }
       }
-      argument.mData = json;
-      argument.mJson = json;
 
       // Get cloned MessagePort from StructuredCloneData.
+      nsTArray<RefPtr<mozilla::dom::MessagePort>> ports;
       if (aCloneData) {
-        Sequence<OwningNonNull<MessagePort>> ports;
-        if (!aCloneData->TakeTransferredPortsAsSequence(ports)) {
-          return NS_ERROR_FAILURE;
-        }
-        argument.mPorts.Construct(Move(ports));
+        ports = aCloneData->TakeTransferredPorts();
+      }
+
+      JS::Rooted<JS::Value> transferredList(cx);
+      if (NS_WARN_IF(!ToJSValue(cx, ports, &transferredList))) {
+        return NS_ERROR_UNEXPECTED;
       }
 
-      argument.mName = aMessage;
-      argument.mPrincipal = aPrincipal;
-      argument.mSync = aIsSync;
-      argument.mTarget = aTarget;
+      JS::Rooted<JSString*> jsMessage(cx,
+        JS_NewUCStringCopyN(cx,
+                            static_cast<const char16_t*>(aMessage.BeginReading()),
+                            aMessage.Length()));
+      NS_ENSURE_TRUE(jsMessage, NS_ERROR_OUT_OF_MEMORY);
+      JS::Rooted<JS::Value> syncv(cx, JS::BooleanValue(aIsSync));
+      bool ok = JS_DefineProperty(cx, param, "target", targetv, JSPROP_ENUMERATE) &&
+                JS_DefineProperty(cx, param, "name", jsMessage, JSPROP_ENUMERATE) &&
+                JS_DefineProperty(cx, param, "sync", syncv, JSPROP_ENUMERATE) &&
+                JS_DefineProperty(cx, param, "json", json, JSPROP_ENUMERATE) && // deprecated
+                JS_DefineProperty(cx, param, "data", json, JSPROP_ENUMERATE) &&
+                JS_DefineProperty(cx, param, "objects", cpowsv, JSPROP_ENUMERATE) &&
+                JS_DefineProperty(cx, param, "ports", transferredList, JSPROP_ENUMERATE);
+
+      NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED);
+
       if (aTargetFrameLoader) {
-        argument.mTargetFrameLoader.Construct(aTargetFrameLoader);
+        JS::Rooted<JS::Value> targetFrameLoaderv(cx);
+        nsresult rv = nsContentUtils::WrapNative(cx, aTargetFrameLoader, &targetFrameLoaderv);
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        ok = JS_DefineProperty(cx, param, "targetFrameLoader", targetFrameLoaderv,
+                               JSPROP_ENUMERATE);
+        NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED);
+      }
+
+      // message.principal == null
+      if (!aPrincipal) {
+        bool ok = JS_DefineProperty(cx, param, "principal",
+                                    JS::UndefinedHandleValue, JSPROP_ENUMERATE);
+        NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED);
+      }
+
+      // message.principal = the principal
+      else {
+        JS::Rooted<JS::Value> principalValue(cx);
+        nsresult rv = nsContentUtils::WrapNative(cx, aPrincipal,
+                                                 &NS_GET_IID(nsIPrincipal),
+                                                 &principalValue);
+        NS_ENSURE_SUCCESS(rv, rv);
+        bool ok = JS_DefineProperty(cx, param, "principal", principalValue,
+                                    JSPROP_ENUMERATE);
+        NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED);
       }
 
       JS::Rooted<JS::Value> thisValue(cx, JS::UndefinedValue());
 
+      JS::Rooted<JS::Value> funval(cx);
       if (JS::IsCallable(object)) {
+        // If the listener is a JS function:
+        funval.setObject(*object);
+
         // A small hack to get 'this' value right on content side where
         // messageManager is wrapped in TabChildGlobal.
         nsCOMPtr<nsISupports> defaultThisValue;
         if (mChrome) {
           defaultThisValue = do_QueryObject(this);
         } else {
           defaultThisValue = aTarget;
         }
         js::AssertSameCompartment(cx, object);
         nsresult rv = nsContentUtils::WrapNative(cx, defaultThisValue, &thisValue);
         NS_ENSURE_SUCCESS(rv, rv);
+      } else {
+        // If the listener is a JS object which has receiveMessage function:
+        if (!JS_GetProperty(cx, object, "receiveMessage", &funval) ||
+            !funval.isObject()) {
+          return NS_ERROR_UNEXPECTED;
+        }
+
+        // Check if the object is even callable.
+        NS_ENSURE_STATE(JS::IsCallable(&funval.toObject()));
+        thisValue.setObject(*object);
       }
 
       JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
-      if (webIDLListener) {
-        ErrorResult rv;
-        webIDLListener->ReceiveMessage(thisValue, argument, &rval, rv);
-        if (rv.Failed()) {
-          // At this point the call to ReceiveMessage will have reported any exceptions
-          // (we kept the default of eReportExceptions). We suppress the failure in the
-          // ErrorResult and continue.
-          rv.SuppressException();
-          continue;
-        }
-      } else {
-        JS::Rooted<JS::Value> funval(cx);
-        if (JS::IsCallable(object)) {
-          // If the listener is a JS function:
-          funval.setObject(*object);
-        } else {
-          // If the listener is a JS object which has receiveMessage function:
-          if (!JS_GetProperty(cx, object, "receiveMessage", &funval) ||
-              !funval.isObject()) {
-            return NS_ERROR_UNEXPECTED;
-          }
+      JS::Rooted<JS::Value> argv(cx, JS::ObjectValue(*param));
 
-          // Check if the object is even callable.
-          NS_ENSURE_STATE(JS::IsCallable(&funval.toObject()));
-          thisValue.setObject(*object);
-        }
+      {
+        JS::Rooted<JSObject*> thisObject(cx, thisValue.toObjectOrNull());
 
-        JS::Rooted<JS::Value> argv(cx);
-        if (!ToJSValue(cx, argument, &argv)) {
+        JSAutoCompartment tac(cx, thisObject);
+        if (!JS_WrapValue(cx, &argv)) {
           return NS_ERROR_UNEXPECTED;
         }
 
-        {
-          JS::Rooted<JSObject*> thisObject(cx, thisValue.toObjectOrNull());
-          js::AssertSameCompartment(cx, thisObject);
-          if (!JS_CallFunctionValue(cx, thisObject, funval,
-                                    JS::HandleValueArray(argv), &rval)) {
-            // Because the AutoEntryScript is inside the loop this continue will make us
-            // report any exceptions (after which we'll move on to the next listener).
+        if (!JS_CallFunctionValue(cx, thisObject, funval,
+                                  JS::HandleValueArray(argv), &rval)) {
+          continue;
+        }
+        if (aRetVal) {
+          ErrorResult rv;
+          StructuredCloneData* data = aRetVal->AppendElement();
+          data->Write(cx, rval, rv);
+          if (NS_WARN_IF(rv.Failed())) {
+            aRetVal->RemoveElementAt(aRetVal->Length() - 1);
+            nsString msg = aMessage + NS_LITERAL_STRING(": message reply cannot be cloned. Are you trying to send an XPCOM object?");
+
+            nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
+            if (console) {
+              nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
+              error->Init(msg, EmptyString(), EmptyString(),
+                          0, 0, nsIScriptError::warningFlag, "chrome javascript");
+              console->LogMessage(error);
+            }
+
+            JS_ClearPendingException(cx);
             continue;
           }
         }
       }
-
-      if (aRetVal) {
-        ErrorResult rv;
-        StructuredCloneData* data = aRetVal->AppendElement();
-        data->Write(cx, rval, rv);
-        if (NS_WARN_IF(rv.Failed())) {
-          aRetVal->RemoveElementAt(aRetVal->Length() - 1);
-          nsString msg = aMessage + NS_LITERAL_STRING(": message reply cannot be cloned. Are you trying to send an XPCOM object?");
-
-          nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
-          if (console) {
-            nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
-            error->Init(msg, EmptyString(), EmptyString(),
-                        0, 0, nsIScriptError::warningFlag, "chrome javascript");
-            console->LogMessage(error);
-          }
-
-          JS_ClearPendingException(cx);
-          continue;
-        }
-      }
     }
   }
 
-  RefPtr<nsFrameMessageManager> kungFuDeathGrip = GetParentManager();
+  RefPtr<nsFrameMessageManager> kungFuDeathGrip = mParentManager;
   if (kungFuDeathGrip) {
     return kungFuDeathGrip->ReceiveMessage(aTarget, aTargetFrameLoader,
                                            aTargetClosed, aMessage,
                                            aIsSync, aCloneData,
                                            aCpows, aPrincipal,
                                            aRetVal);
   }
   return NS_OK;
 }
 
 void
-nsFrameMessageManager::AddChildManager(MessageListenerManager* aManager)
+nsFrameMessageManager::AddChildManager(nsFrameMessageManager* aManager)
 {
-  mChildManagers.AppendElement(aManager);
+  mChildManagers.AppendObject(aManager);
 
   RefPtr<nsFrameMessageManager> kungfuDeathGrip = this;
   RefPtr<nsFrameMessageManager> kungfuDeathGrip2 = aManager;
 
   LoadPendingScripts(this, aManager);
 }
 
 void
-nsFrameMessageManager::RemoveChildManager(MessageListenerManager* aManager)
-{
-  mChildManagers.RemoveElement(aManager);
-}
-
-void
 nsFrameMessageManager::LoadPendingScripts(nsFrameMessageManager* aManager,
                                           nsFrameMessageManager* aChildMM)
 {
   // We have parent manager if we're a message broadcaster.
   // In that case we want to load the pending scripts from all parent
   // message managers in the hierarchy. Process the parent first so
   // that pending scripts higher up in the hierarchy are loaded before others.
-  nsFrameMessageManager* parentManager = aManager->GetParentManager();
-  if (parentManager) {
-    LoadPendingScripts(parentManager, aChildMM);
+  if (aManager->mParentManager) {
+    LoadPendingScripts(aManager->mParentManager, aChildMM);
   }
 
   for (uint32_t i = 0; i < aManager->mPendingScripts.Length(); ++i) {
     aChildMM->LoadFrameScript(aManager->mPendingScripts[i],
                               false,
                               aManager->mPendingScriptsGlobalStates[i]);
   }
 }
@@ -1307,16 +1180,47 @@ nsFrameMessageManager::SetCallback(Messa
     mCallback = aCallback;
     if (mOwnsCallback) {
       mOwnedCallback = aCallback;
     }
   }
 }
 
 void
+nsFrameMessageManager::InitWithCallback(MessageManagerCallback* aCallback)
+{
+  if (mCallback) {
+    // Initialization should only happen once.
+    return;
+  }
+
+  SetCallback(aCallback);
+
+  // First load parent scripts by adding this to parent manager.
+  if (mParentManager) {
+    mParentManager->AddChildManager(this);
+  }
+
+  for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
+    LoadFrameScript(mPendingScripts[i], false, mPendingScriptsGlobalStates[i]);
+  }
+}
+
+void
+nsFrameMessageManager::RemoveFromParent()
+{
+  if (mParentManager) {
+    mParentManager->RemoveChildManager(this);
+  }
+  mParentManager = nullptr;
+  mCallback = nullptr;
+  mOwnedCallback = nullptr;
+}
+
+void
 nsFrameMessageManager::Close()
 {
   if (!mClosed) {
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     if (obs) {
       obs->NotifyObservers(NS_ISUPPORTS_CAST(nsIContentFrameMessageManager*, this),
                             "message-manager-close", nullptr);
     }
@@ -1334,115 +1238,90 @@ nsFrameMessageManager::Disconnect(bool a
 
   if (!mDisconnected) {
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     if (obs) {
        obs->NotifyObservers(NS_ISUPPORTS_CAST(nsIContentFrameMessageManager*, this),
                             "message-manager-disconnect", nullptr);
     }
   }
-
-  ClearParentManager(aRemoveFromParent);
-
+  if (mParentManager && aRemoveFromParent) {
+    mParentManager->RemoveChildManager(this);
+  }
   mDisconnected = true;
+  mParentManager = nullptr;
   if (!mHandlingMessage) {
     mListeners.Clear();
   }
 }
 
 void
 nsFrameMessageManager::SetInitialProcessData(JS::HandleValue aInitialData)
 {
   MOZ_ASSERT(!mChrome);
   MOZ_ASSERT(mIsProcessManager);
-  MOZ_ASSERT(aInitialData.isObject());
   mInitialProcessData = aInitialData;
 }
 
-void
-nsFrameMessageManager::GetInitialProcessData(JSContext* aCx,
-                                             JS::MutableHandle<JS::Value> aInitialProcessData,
-                                             ErrorResult& aError)
+NS_IMETHODIMP
+nsFrameMessageManager::GetInitialProcessData(JSContext* aCx, JS::MutableHandleValue aResult)
 {
   MOZ_ASSERT(mIsProcessManager);
   MOZ_ASSERT_IF(mChrome, IsBroadcaster());
 
   JS::RootedValue init(aCx, mInitialProcessData);
   if (mChrome && init.isUndefined()) {
     // We create the initial object in the junk scope. If we created it in a
     // normal compartment, that compartment would leak until shutdown.
     JS::RootedObject global(aCx, xpc::PrivilegedJunkScope());
     JSAutoCompartment ac(aCx, global);
 
     JS::RootedObject obj(aCx, JS_NewPlainObject(aCx));
     if (!obj) {
-      aError.NoteJSContextException(aCx);
-      return;
+      return NS_ERROR_OUT_OF_MEMORY;
     }
 
     mInitialProcessData.setObject(*obj);
     init.setObject(*obj);
   }
 
   if (!mChrome && XRE_IsParentProcess()) {
     // This is the cpmm in the parent process. We should use the same object as the ppmm.
     nsCOMPtr<nsIGlobalProcessScriptLoader> ppmm =
       do_GetService("@mozilla.org/parentprocessmessagemanager;1");
     ppmm->GetInitialProcessData(aCx, &init);
     mInitialProcessData = init;
   }
 
   if (!JS_WrapValue(aCx, &init)) {
-    aError.NoteJSContextException(aCx);
-    return;
+    return NS_ERROR_OUT_OF_MEMORY;
   }
-  aInitialProcessData.set(init);
-}
-
-NS_IMETHODIMP
-nsFrameMessageManager::GetInitialProcessData(JSContext* aCx, JS::MutableHandleValue aResult)
-{
-  ErrorResult rv;
-  GetInitialProcessData(aCx, aResult, rv);
-  return rv.StealNSResult();
-}
-
-already_AddRefed<nsIMessageSender>
-nsFrameMessageManager::GetProcessMessageManager(ErrorResult& aError)
-{
-  nsCOMPtr<nsIMessageSender> pmm;
-  if (mCallback) {
-    pmm = mCallback->GetProcessMessageManager();
-  }
-  return pmm.forget();
+  aResult.set(init);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::GetProcessMessageManager(nsIMessageSender** aPMM)
 {
-  ErrorResult rv;
-  *aPMM = GetProcessMessageManager(rv).take();
-  return rv.StealNSResult();
-}
-
-void
-nsFrameMessageManager::GetRemoteType(nsAString& aRemoteType, ErrorResult& aError) const
-{
-  aRemoteType.Truncate();
+  *aPMM = nullptr;
   if (mCallback) {
-    aError = mCallback->DoGetRemoteType(aRemoteType);
+    nsCOMPtr<nsIMessageSender> pmm = mCallback->GetProcessMessageManager();
+    pmm.swap(*aPMM);
   }
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::GetRemoteType(nsAString& aRemoteType)
 {
-  ErrorResult rv;
-  GetRemoteType(aRemoteType, rv);
-  return rv.StealNSResult();
+  aRemoteType.Truncate();
+  if (mCallback) {
+    return mCallback->DoGetRemoteType(aRemoteType);
+  }
+  return NS_OK;
 }
 
 namespace {
 
 struct MessageManagerReferentCount
 {
   MessageManagerReferentCount() : mStrong(0), mWeakAlive(0), mWeakDead(0) {}
   size_t mStrong;
@@ -1511,17 +1390,18 @@ MessageManagerReporter::CountReferents(n
         aReferentCount->mStrong++;
       }
     }
   }
 
   // Add referent count in child managers because the listeners
   // participate in messages dispatched from parent message manager.
   for (uint32_t i = 0; i < aMessageManager->mChildManagers.Length(); ++i) {
-    RefPtr<nsFrameMessageManager> mm = aMessageManager->mChildManagers[i];
+    RefPtr<nsFrameMessageManager> mm =
+      static_cast<nsFrameMessageManager*>(aMessageManager->mChildManagers[i]);
     CountReferents(mm, aReferentCount);
   }
 }
 
 static void
 ReportReferentCount(const char* aManagerType,
                     const MessageManagerReferentCount& aReferentCount,
                     nsIHandleReportCallback* aHandleReport,
@@ -1599,30 +1479,32 @@ MessageManagerReporter::CollectReports(n
 } // namespace dom
 } // namespace mozilla
 
 nsresult
 NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult)
 {
   NS_ENSURE_TRUE(XRE_IsParentProcess(),
                  NS_ERROR_NOT_AVAILABLE);
-  RefPtr<nsFrameMessageManager> mm =
-    new ChromeMessageBroadcaster(MessageManagerFlags::MM_GLOBAL);
+  RefPtr<nsFrameMessageManager> mm = new nsFrameMessageManager(nullptr,
+                                                                 nullptr,
+                                                                 MM_CHROME | MM_GLOBAL | MM_BROADCASTER);
   RegisterStrongMemoryReporter(new MessageManagerReporter());
   mm.forget(aResult);
   return NS_OK;
 }
 
 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,24 +1529,23 @@ nsMessageManagerScriptExecutor::Shutdown
 
     delete sCachedScripts;
     sCachedScripts = nullptr;
     sScriptCacheCleaner = nullptr;
   }
 }
 
 void
-nsMessageManagerScriptExecutor::LoadScriptInternal(JS::Handle<JSObject*> aGlobal,
-                                                   const nsAString& aURL,
+nsMessageManagerScriptExecutor::LoadScriptInternal(const nsAString& aURL,
                                                    bool aRunInGlobalScope)
 {
   AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(
     "nsMessageManagerScriptExecutor::LoadScriptInternal", OTHER, aURL);
 
-  if (!sCachedScripts) {
+  if (!mGlobal || !sCachedScripts) {
     return;
   }
 
   JS::RootingContext* rcx = RootingCx();
   JS::Rooted<JSScript*> script(rcx);
 
   nsMessageManagerScriptHolder* holder = sCachedScripts->Get(aURL);
   if (holder && holder->WillRunInGlobalScope() == aRunInGlobalScope) {
@@ -1672,28 +1553,31 @@ 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);
   }
 
-  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);
+  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);
+        }
       }
     }
   }
 }
 
 void
 nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
   const nsAString& aURL,
@@ -1804,64 +1688,71 @@ 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(const nsACString& aID)
+nsMessageManagerScriptExecutor::InitChildGlobalInternal(
+  nsISupports* aScope,
+  const nsACString& aID)
 {
   AutoSafeJSContext cx;
-  if (!SystemBindingInitIds(cx)) {
-    return false;
-  }
+  nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
 
-  nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
+  const uint32_t flags = xpc::INIT_JS_STANDARD_CLASSES;
 
   JS::CompartmentOptions options;
   options.creationOptions().setSystemZone();
 
-  xpc::InitGlobalObjectOptions(options, mPrincipal);
-  JS::Rooted<JSObject*> global(cx);
-  if (!WrapGlobalObject(cx, options, &global)) {
-    return false;
+  if (xpc::SharedMemoryEnabled()) {
+    options.creationOptions().setSharedMemoryAndAtomicsEnabled(true);
   }
 
-  xpc::InitGlobalObject(cx, global, 0);
+  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);
 
   // Set the location information for the new global, so that tools like
   // about:memory may use that information.
-  xpc::SetLocationForGlobal(global, aID);
+  xpc::SetLocationForGlobal(mGlobal, aID);
 
   DidCreateGlobal();
   return true;
 }
 
 void
 nsMessageManagerScriptExecutor::MarkScopesForCC()
 {
   for (uint32_t i = 0; i < mAnonymousGlobalScopes.Length(); ++i) {
     mAnonymousGlobalScopes[i].exposeToActiveJS();
   }
 }
 
 NS_IMPL_ISUPPORTS(nsScriptCacheCleaner, nsIObserver)
 
-ChildProcessMessageManager* nsFrameMessageManager::sChildProcessManager = nullptr;
+nsFrameMessageManager* nsFrameMessageManager::sChildProcessManager = nullptr;
 nsFrameMessageManager* nsFrameMessageManager::sParentProcessManager = nullptr;
 nsFrameMessageManager* nsFrameMessageManager::sSameProcessParentManager = nullptr;
 
 class nsAsyncMessageToSameProcessChild : public nsSameProcessAsyncMessageBase,
                                          public Runnable
 {
 public:
   nsAsyncMessageToSameProcessChild(JS::RootingContext* aRootingCx,
@@ -2072,47 +1963,47 @@ public:
 
 
 // This creates the global parent process message manager.
 nsresult
 NS_NewParentProcessMessageManager(nsIMessageBroadcaster** aResult)
 {
   NS_ASSERTION(!nsFrameMessageManager::sParentProcessManager,
                "Re-creating sParentProcessManager");
-  RefPtr<nsFrameMessageManager> mm =
-    new ChromeMessageBroadcaster(MessageManagerFlags::MM_PROCESSMANAGER);
+  RefPtr<nsFrameMessageManager> mm = new nsFrameMessageManager(nullptr,
+                                                                 nullptr,
+                                                                 MM_CHROME | MM_PROCESSMANAGER | MM_BROADCASTER);
   nsFrameMessageManager::sParentProcessManager = mm;
   nsFrameMessageManager::NewProcessMessageManager(false); // Create same process message manager.
   mm.forget(aResult);
   return NS_OK;
 }
 
 
-ChromeMessageSender*
+nsFrameMessageManager*
 nsFrameMessageManager::NewProcessMessageManager(bool aIsRemote)
 {
   if (!nsFrameMessageManager::sParentProcessManager) {
      nsCOMPtr<nsIMessageBroadcaster> dummy =
        do_GetService("@mozilla.org/parentprocessmessagemanager;1");
   }
 
   MOZ_ASSERT(nsFrameMessageManager::sParentProcessManager,
              "parent process manager not created");
-  ChromeMessageSender* mm;
+  nsFrameMessageManager* mm;
   if (aIsRemote) {
     // Callback is set in ContentParent::InitInternal so that the process has
     // already started when we send pending scripts.
-    mm = new ChromeMessageSender(nullptr,
-                                 nsFrameMessageManager::sParentProcessManager,
-                                 MessageManagerFlags::MM_PROCESSMANAGER);
+    mm = new nsFrameMessageManager(nullptr,
+                                   nsFrameMessageManager::sParentProcessManager,
+                                   MM_CHROME | MM_PROCESSMANAGER);
   } else {
-    mm = new ChromeMessageSender(new SameParentProcessMessageManagerCallback(),
-                                 nsFrameMessageManager::sParentProcessManager,
-                                 MessageManagerFlags::MM_PROCESSMANAGER |
-                                 MessageManagerFlags::MM_OWNSCALLBACK);
+    mm = new nsFrameMessageManager(new SameParentProcessMessageManagerCallback(),
+                                   nsFrameMessageManager::sParentProcessManager,
+                                   MM_CHROME | MM_PROCESSMANAGER | MM_OWNSCALLBACK);
     sSameProcessParentManager = mm;
   }
   return mm;
 }
 
 nsresult
 NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
 {
@@ -2121,38 +2012,36 @@ NS_NewChildProcessMessageManager(nsISync
 
   MessageManagerCallback* cb;
   if (XRE_IsParentProcess()) {
     cb = new SameChildProcessMessageManagerCallback();
   } else {
     cb = new ChildProcessMessageManagerCallback();
     RegisterStrongMemoryReporter(new MessageManagerReporter());
   }
-  auto* mm = new ChildProcessMessageManager(cb);
+  auto* mm = new nsFrameMessageManager(cb, nullptr,
+                                       MM_PROCESSMANAGER | MM_OWNSCALLBACK);
   nsFrameMessageManager::SetChildProcessManager(mm);
   RefPtr<ProcessGlobal> global = new ProcessGlobal(mm);
   NS_ENSURE_TRUE(global->Init(), NS_ERROR_UNEXPECTED);
   global.forget(aResult);
   return NS_OK;
 }
 
 bool
 nsFrameMessageManager::MarkForCC()
 {
   for (auto iter = mListeners.Iter(); !iter.Done(); iter.Next()) {
     nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners = iter.UserData();
     uint32_t count = listeners->Length();
     for (uint32_t i = 0; i < count; i++) {
-      MessageListenerHolder& strongListener = listeners->ElementAt(i).mStrongListener;
+      nsCOMPtr<nsIMessageListener> strongListener =
+        listeners->ElementAt(i).mStrongListener;
       if (strongListener) {
-        if (strongListener.HasWebIDLCallback()) {
-          strongListener.GetWebIDLCallback()->MarkForCC();
-        } else {
-          xpc_TryUnmarkWrappedGrayObject(strongListener.GetXPCOMCallback());
-        }
+        xpc_TryUnmarkWrappedGrayObject(strongListener);
       }
     }
   }
 
   if (mRefCnt.IsPurple()) {
     mRefCnt.RemovePurple();
   }
   return true;
--- a/dom/base/nsFrameMessageManager.h
+++ b/dom/base/nsFrameMessageManager.h
@@ -23,52 +23,44 @@
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsIObserverService.h"
 #include "nsThreadUtils.h"
 #include "nsWeakPtr.h"
 #include "mozilla/Attributes.h"
 #include "js/RootingAPI.h"
 #include "nsTObserverArray.h"
-#include "mozilla/TypedEnumBits.h"
-#include "mozilla/dom/CallbackObject.h"
 #include "mozilla/dom/SameProcessMessageQueue.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
 #include "mozilla/jsipc/CpowHolder.h"
 
 class nsIFrameLoader;
 
 namespace mozilla {
 namespace dom {
 
 class nsIContentParent;
 class nsIContentChild;
-class ChildProcessMessageManager;
-class ChromeMessageSender;
 class ClonedMessageData;
-class MessageListener;
-class MessageListenerManager;
 class MessageManagerReporter;
-template<typename T> class Optional;
 
 namespace ipc {
 
 // Note: we round the time we spend to the nearest millisecond. So a min value
 // of 1 ms actually captures from 500us and above.
 static const uint32_t kMinTelemetrySyncMessageManagerLatencyMs = 1;
 
-enum class MessageManagerFlags {
-  MM_NONE = 0,
+enum MessageManagerFlags {
+  MM_CHILD = 0,
   MM_CHROME = 1,
   MM_GLOBAL = 2,
   MM_PROCESSMANAGER = 4,
   MM_BROADCASTER = 8,
   MM_OWNSCALLBACK = 16
 };
-MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(MessageManagerFlags);
 
 class MessageManagerCallback
 {
 public:
   virtual ~MessageManagerCallback() {}
 
   virtual bool DoLoadMessageManagerScript(const nsAString& aURL, bool aRunInGlobalScope)
   {
@@ -121,166 +113,95 @@ protected:
 
 void UnpackClonedMessageDataForParent(const ClonedMessageData& aClonedData,
                                       StructuredCloneData& aData);
 
 void UnpackClonedMessageDataForChild(const ClonedMessageData& aClonedData,
                                      StructuredCloneData& aData);
 
 } // namespace ipc
-
-typedef CallbackObjectHolder<mozilla::dom::MessageListener,
-                             nsIMessageListener> MessageListenerHolder;
-
 } // namespace dom
 } // namespace mozilla
 
 struct nsMessageListenerInfo
 {
   bool operator==(const nsMessageListenerInfo& aOther) const
   {
     return &aOther == this;
   }
 
-  // If mWeakListener is null then mStrongListener holds either a MessageListener or an
-  // nsIMessageListener. If mWeakListener is non-null then mStrongListener contains null.
-  mozilla::dom::MessageListenerHolder mStrongListener;
+  // Exactly one of mStrongListener and mWeakListener must be non-null.
+  nsCOMPtr<nsIMessageListener> mStrongListener;
   nsWeakPtr mWeakListener;
   bool mListenWhenClosed;
 };
 
-inline void
-ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
-                            nsMessageListenerInfo& aField,
-                            const char* aName,
-                            uint32_t aFlags = 0)
-{
-  ImplCycleCollectionTraverse(aCallback, aField.mStrongListener, aName, aFlags);
-  ImplCycleCollectionTraverse(aCallback, aField.mWeakListener, aName, aFlags);
-}
 
 class MOZ_STACK_CLASS SameProcessCpowHolder : public mozilla::jsipc::CpowHolder
 {
 public:
   SameProcessCpowHolder(JS::RootingContext* aRootingCx, JS::Handle<JSObject*> aObj)
     : mObj(aRootingCx, aObj)
   {
   }
 
   virtual bool ToObject(JSContext* aCx, JS::MutableHandle<JSObject*> aObjp)
     override;
 
 private:
   JS::Rooted<JSObject*> mObj;
 };
 
-class nsFrameMessageManager : public nsIContentFrameMessageManager,
-                              public nsIMessageBroadcaster,
-                              public nsIFrameScriptLoader,
-                              public nsIGlobalProcessScriptLoader
+class nsFrameMessageManager final : public nsIContentFrameMessageManager,
+                                    public nsIMessageBroadcaster,
+                                    public nsIFrameScriptLoader,
+                                    public nsIGlobalProcessScriptLoader
 {
   friend class mozilla::dom::MessageManagerReporter;
   typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData;
-
-protected:
-  typedef mozilla::dom::ipc::MessageManagerFlags MessageManagerFlags;
+public:
+  nsFrameMessageManager(mozilla::dom::ipc::MessageManagerCallback* aCallback,
+                        nsFrameMessageManager* aParentManager,
+                        /* mozilla::dom::ipc::MessageManagerFlags */ uint32_t aFlags);
 
-  nsFrameMessageManager(mozilla::dom::ipc::MessageManagerCallback* aCallback,
-                        MessageManagerFlags aFlags);
-
-  virtual ~nsFrameMessageManager();
+private:
+  ~nsFrameMessageManager();
 
 public:
-  explicit nsFrameMessageManager(mozilla::dom::ipc::MessageManagerCallback* aCallback)
-    : nsFrameMessageManager(aCallback, MessageManagerFlags::MM_NONE)
-  {}
-
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsFrameMessageManager,
                                                          nsIContentFrameMessageManager)
-
-  // MessageListenerManager
-  void AddMessageListener(const nsAString& aMessageName,
-                          mozilla::dom::MessageListener& aListener,
-                          bool aListenWhenClosed,
-                          mozilla::ErrorResult& aError);
-  void RemoveMessageListener(const nsAString& aMessageName,
-                             mozilla::dom::MessageListener& aListener,
-                             mozilla::ErrorResult& aError);
-  void AddWeakMessageListener(const nsAString& aMessageName,
-                              mozilla::dom::MessageListener& aListener,
-                              mozilla::ErrorResult& aError);
-  void RemoveWeakMessageListener(const nsAString& aMessageName,
-                                 mozilla::dom::MessageListener& aListener,
-                                 mozilla::ErrorResult& 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,
-                        mozilla::ErrorResult& aError)
-  {
-    DispatchAsyncMessage(aCx, aMessageName, aObj, aObjects, aPrincipal, aTransfers,
-                         aError);
-  }
-  already_AddRefed<nsIMessageSender>
-    GetProcessMessageManager(mozilla::ErrorResult& aError);
-  void GetRemoteType(nsAString& aRemoteType, mozilla::ErrorResult& aError) const;
-
-  // SyncMessageSender
-  void SendSyncMessage(JSContext* aCx, const nsAString& aMessageName,
-                       JS::Handle<JS::Value> aObj,
-                       JS::Handle<JSObject*> aObjects,
-                       nsIPrincipal* aPrincipal,
-                       nsTArray<JS::Value>& aResult,
-                       mozilla::ErrorResult& aError)
-  {
-    SendMessage(aCx, aMessageName, aObj, aObjects, aPrincipal, true, aResult, aError);
-  }
-  void SendRpcMessage(JSContext* aCx, const nsAString& aMessageName,
-                      JS::Handle<JS::Value> aObj,
-                      JS::Handle<JSObject*> aObjects,
-                      nsIPrincipal* aPrincipal,
-                      nsTArray<JS::Value>& aResult,
-                      mozilla::ErrorResult& aError)
-  {
-    SendMessage(aCx, aMessageName, aObj, aObjects, aPrincipal, false, aResult, aError);
-  }
-
-  // GlobalProcessScriptLoader
-  void GetInitialProcessData(JSContext* aCx,
-                             JS::MutableHandle<JS::Value> aInitialProcessData,
-                             mozilla::ErrorResult& aError);
-
   NS_DECL_NSIMESSAGELISTENERMANAGER
   NS_DECL_NSIMESSAGESENDER
   NS_DECL_NSIMESSAGEBROADCASTER
   NS_DECL_NSISYNCMESSAGESENDER
   NS_DECL_NSIMESSAGEMANAGERGLOBAL
   NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
   NS_DECL_NSIFRAMESCRIPTLOADER
   NS_DECL_NSIPROCESSSCRIPTLOADER
   NS_DECL_NSIGLOBALPROCESSSCRIPTLOADER
 
-  static mozilla::dom::ChromeMessageSender*
+  static nsFrameMessageManager*
   NewProcessMessageManager(bool aIsRemote);
 
   nsresult ReceiveMessage(nsISupports* aTarget, nsIFrameLoader* aTargetFrameLoader,
                           const nsAString& aMessage,
                           bool aIsSync, StructuredCloneData* aCloneData,
                           mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal,
                           nsTArray<StructuredCloneData>* aRetVal);
 
-  void AddChildManager(mozilla::dom::MessageListenerManager* aManager);
-  void RemoveChildManager(mozilla::dom::MessageListenerManager* aManager);
+  void AddChildManager(nsFrameMessageManager* aManager);
+  void RemoveChildManager(nsFrameMessageManager* aManager)
+  {
+    mChildManagers.RemoveObject(aManager);
+  }
   void Disconnect(bool aRemoveFromParent = true);
   void Close();
 
+  void InitWithCallback(mozilla::dom::ipc::MessageManagerCallback* aCallback);
   void SetCallback(mozilla::dom::ipc::MessageManagerCallback* aCallback);
 
   mozilla::dom::ipc::MessageManagerCallback* GetCallback()
   {
     return mCallback;
   }
 
   nsresult DispatchAsyncMessage(const nsAString& aMessageName,
@@ -291,127 +212,104 @@ public:
                                 JSContext* aCx,
                                 uint8_t aArgc);
 
   nsresult DispatchAsyncMessageInternal(JSContext* aCx,
                                         const nsAString& aMessage,
                                         StructuredCloneData& aData,
                                         JS::Handle<JSObject*> aCpows,
                                         nsIPrincipal* aPrincipal);
+  void RemoveFromParent();
+  nsFrameMessageManager* GetParentManager() { return mParentManager; }
+  void SetParentManager(nsFrameMessageManager* aParent)
+  {
+    NS_ASSERTION(!mParentManager, "We have parent manager already!");
+    NS_ASSERTION(mChrome, "Should not set parent manager!");
+    mParentManager = aParent;
+  }
   bool IsGlobal() { return mGlobal; }
   bool IsBroadcaster() { return mIsBroadcaster; }
 
   static nsFrameMessageManager* GetParentProcessManager()
   {
     return sParentProcessManager;
   }
-  static mozilla::dom::ChildProcessMessageManager* GetChildProcessManager()
+  static nsFrameMessageManager* GetChildProcessManager()
   {
     return sChildProcessManager;
   }
-  static void SetChildProcessManager(mozilla::dom::ChildProcessMessageManager* aManager)
+  static void SetChildProcessManager(nsFrameMessageManager* aManager)
   {
     sChildProcessManager = aManager;
   }
 
   void SetInitialProcessData(JS::HandleValue aInitialData);
 
   void LoadPendingScripts();
 
-protected:
-  friend class MMListenerRemover;
-
-  virtual nsFrameMessageManager* GetParentManager()
-  {
-    return nullptr;
-  }
-  virtual void ClearParentManager(bool aRemove)
-  {
-  }
-
-  void DispatchAsyncMessage(JSContext* aCx, const nsAString& aMessageName,
-                            JS::Handle<JS::Value> aObj,
-                            JS::Handle<JSObject*> aObjects,
-                            nsIPrincipal* aPrincipal,
-                            JS::Handle<JS::Value> aTransfers,
-                            mozilla::ErrorResult& aError);
-
+private:
   nsresult SendMessage(const nsAString& aMessageName,
                        JS::Handle<JS::Value> aJSON,
                        JS::Handle<JS::Value> aObjects,
                        nsIPrincipal* aPrincipal,
                        JSContext* aCx,
                        uint8_t aArgc,
                        JS::MutableHandle<JS::Value> aRetval,
                        bool aIsSync);
-  void SendMessage(JSContext* aCx, const nsAString& aMessageName,
-                   JS::Handle<JS::Value> aObj, JS::Handle<JSObject*> aObjects,
-                   nsIPrincipal* aPrincipal, bool aIsSync, nsTArray<JS::Value>& aResult,
-                   mozilla::ErrorResult& aError);
-  void SendMessage(JSContext* aCx, const nsAString& aMessageName,
-                   StructuredCloneData& aData, JS::Handle<JSObject*> aObjects,
-                   nsIPrincipal* aPrincipal, bool aIsSync,
-                   nsTArray<JS::Value>& aResult, mozilla::ErrorResult& aError);
 
   nsresult ReceiveMessage(nsISupports* aTarget, nsIFrameLoader* aTargetFrameLoader,
                           bool aTargetClosed, const nsAString& aMessage,
                           bool aIsSync, StructuredCloneData* aCloneData,
                           mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal,
                           nsTArray<StructuredCloneData>* aRetVal);
 
-  void LoadScript(const nsAString& aURL, bool aAllowDelayedLoad,
-                  bool aRunInGlobalScope, mozilla::ErrorResult& aError);
-  void RemoveDelayedScript(const nsAString& aURL);
-  nsresult GetDelayedScripts(JSContext* aCx,
-                             JS::MutableHandle<JS::Value> aList);
-  void GetDelayedScripts(JSContext* aCx, nsTArray<nsTArray<JS::Value>>& aList,
-                         mozilla::ErrorResult& aError);
+  NS_IMETHOD LoadScript(const nsAString& aURL,
+                        bool aAllowDelayedLoad,
+                        bool aRunInGlobalScope);
+  NS_IMETHOD RemoveDelayedScript(const nsAString& aURL);
+  NS_IMETHOD GetDelayedScripts(JSContext* aCx, JS::MutableHandle<JS::Value> aList);
 
-  enum ProcessCheckerType {
-    PROCESS_CHECKER_PERMISSION,
-    PROCESS_CHECKER_MANIFEST_URL,
-    ASSERT_APP_HAS_PERMISSION
-  };
-  bool AssertProcessInternal(ProcessCheckerType aType,
-                             const nsAString& aCapability,
-                             mozilla::ErrorResult& aError);
-
+protected:
+  friend class MMListenerRemover;
   // We keep the message listeners as arrays in a hastable indexed by the
   // message name. That gives us fast lookups in ReceiveMessage().
   nsClassHashtable<nsStringHashKey,
                    nsAutoTObserverArray<nsMessageListenerInfo, 1>> mListeners;
-  nsTArray<RefPtr<mozilla::dom::MessageListenerManager>> mChildManagers;
+  nsCOMArray<nsIContentFrameMessageManager> mChildManagers;
   bool mChrome;     // true if we're in the chrome process
   bool mGlobal;     // true if we're the global frame message manager
   bool mIsProcessManager; // true if the message manager belongs to the process realm
   bool mIsBroadcaster; // true if the message manager is a broadcaster
   bool mOwnsCallback;
   bool mHandlingMessage;
   bool mClosed;    // true if we can no longer send messages
   bool mDisconnected;
   mozilla::dom::ipc::MessageManagerCallback* mCallback;
   nsAutoPtr<mozilla::dom::ipc::MessageManagerCallback> mOwnedCallback;
+  RefPtr<nsFrameMessageManager> mParentManager;
   nsTArray<nsString> mPendingScripts;
   nsTArray<bool> mPendingScriptsGlobalStates;
   JS::Heap<JS::Value> mInitialProcessData;
 
   void LoadPendingScripts(nsFrameMessageManager* aManager,
                           nsFrameMessageManager* aChildMM);
 public:
   static nsFrameMessageManager* sParentProcessManager;
   static nsFrameMessageManager* sSameProcessParentManager;
   static nsTArray<nsCOMPtr<nsIRunnable> >* sPendingSameProcessAsyncMessages;
 private:
-  void AddMessageListener(const nsAString& aMessageName,
-                          mozilla::dom::MessageListenerHolder&& aListener,
-                          bool aListenWhenClosed);
-  void RemoveMessageListener(const nsAString& aMessageName,
-                             const mozilla::dom::MessageListenerHolder&  aListener);
-
-  static mozilla::dom::ChildProcessMessageManager* sChildProcessManager;
+  static nsFrameMessageManager* sChildProcessManager;
+  enum ProcessCheckerType {
+    PROCESS_CHECKER_PERMISSION,
+    PROCESS_CHECKER_MANIFEST_URL,
+    ASSERT_APP_HAS_PERMISSION
+  };
+  nsresult AssertProcessInternal(ProcessCheckerType aType,
+                                 const nsAString& aCapability,
+                                 bool* aValid);
 };
 
 /* A helper class for taking care of many details for async message sending
    within a single process.  Intended to be used like so:
 
    class MyAsyncMessage : public nsSameProcessAsyncMessageBase, public Runnable
    {
      NS_IMETHOD Run() {
@@ -471,38 +369,39 @@ 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(JS::Handle<JSObject*> aGlobal, const nsAString& aURL,
-                          bool aRunInGlobalScope);
+  void LoadScriptInternal(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(const nsACString& aID);
-  virtual bool WrapGlobalObject(JSContext* aCx,
-                                JS::CompartmentOptions& aOptions,
-                                JS::MutableHandle<JSObject*> aReflector) = 0;
+  bool InitChildGlobalInternal(nsISupports* aScope, const nsACString& aID);
   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/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -1241,17 +1241,18 @@ nsGlobalWindowInner::CleanUp()
   DisableVRUpdates();
   mHasVREvents = false;
   mHasVRDisplayActivateEvents = false;
   DisableIdleCallbackRequests();
 
   if (mCleanMessageManager) {
     MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned");
     if (mChromeFields.mMessageManager) {
-      mChromeFields.mMessageManager->Disconnect();
+      static_cast<nsFrameMessageManager*>(
+        mChromeFields.mMessageManager.get())->Disconnect();
     }
   }
 
   CleanupCachedXBLHandlers();
 
   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
     mAudioContexts[i]->Shutdown();
   }
@@ -7587,51 +7588,56 @@ nsGlobalWindowInner::NotifyDefaultButton
 NS_IMETHODIMP
 nsGlobalWindowInner::GetMessageManager(nsIMessageBroadcaster** aManager)
 {
   ErrorResult rv;
   NS_IF_ADDREF(*aManager = GetMessageManager(rv));
   return rv.StealNSResult();
 }
 
-ChromeMessageBroadcaster*
+nsIMessageBroadcaster*
 nsGlobalWindowInner::GetMessageManager(ErrorResult& aError)
 {
   MOZ_ASSERT(IsChromeWindow());
   if (!mChromeFields.mMessageManager) {
     nsCOMPtr<nsIMessageBroadcaster> globalMM =
       do_GetService("@mozilla.org/globalmessagemanager;1");
     mChromeFields.mMessageManager =
-      new ChromeMessageBroadcaster(static_cast<nsFrameMessageManager*>(globalMM.get()));
+      new nsFrameMessageManager(nullptr,
+                                static_cast<nsFrameMessageManager*>(globalMM.get()),
+                                MM_CHROME | MM_BROADCASTER);
   }
   return mChromeFields.mMessageManager;
 }
 
 NS_IMETHODIMP
 nsGlobalWindowInner::GetGroupMessageManager(const nsAString& aGroup,
                                             nsIMessageBroadcaster** aManager)
 {
   MOZ_RELEASE_ASSERT(IsChromeWindow());
   ErrorResult rv;
   NS_IF_ADDREF(*aManager = GetGroupMessageManager(aGroup, rv));
   return rv.StealNSResult();
 }
 
-ChromeMessageBroadcaster*
+nsIMessageBroadcaster*
 nsGlobalWindowInner::GetGroupMessageManager(const nsAString& aGroup,
                                             ErrorResult& aError)
 {
   MOZ_ASSERT(IsChromeWindow());
 
-  RefPtr<ChromeMessageBroadcaster> messageManager =
+  nsCOMPtr<nsIMessageBroadcaster> messageManager =
     mChromeFields.mGroupMessageManagers.LookupForAdd(aGroup).OrInsert(
       [this, &aError] () {
-        nsFrameMessageManager* parent = GetMessageManager(aError);
-
-        return new ChromeMessageBroadcaster(parent);
+        nsFrameMessageManager* parent =
+          static_cast<nsFrameMessageManager*>(GetMessageManager(aError));
+
+        return new nsFrameMessageManager(nullptr,
+                                         parent,
+                                         MM_CHROME | MM_BROADCASTER);
       });
   return messageManager;
 }
 
 void
 nsGlobalWindowInner::InitWasOffline()
 {
   mWasOffline = NS_IsOffline();
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -32,21 +32,21 @@
 #include "nsITimer.h"
 #include "mozilla/EventListenerManager.h"
 #include "nsIPrincipal.h"
 #include "nsSize.h"
 #include "mozilla/FlushType.h"
 #include "prclist.h"
 #include "mozilla/dom/DOMPrefs.h"
 #include "mozilla/dom/BindingDeclarations.h"
-#include "mozilla/dom/ChromeMessageBroadcaster.h"
 #include "mozilla/dom/StorageEvent.h"
 #include "mozilla/dom/StorageEventBinding.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/ErrorResult.h"
+#include "nsFrameMessageManager.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/TimeStamp.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsIIdleObserver.h"
 #include "nsIDocument.h"
 #include "mozilla/dom/EventTarget.h"
@@ -936,21 +936,19 @@ public:
   void GetAttentionWithCycleCount(int32_t aCycleCount,
                                   mozilla::ErrorResult& aError);
   void SetCursor(const nsAString& aCursor, mozilla::ErrorResult& aError);
   void Maximize();
   void Minimize();
   void Restore();
   void NotifyDefaultButtonLoaded(mozilla::dom::Element& aDefaultButton,
                                  mozilla::ErrorResult& aError);
-  mozilla::dom::ChromeMessageBroadcaster*
-    GetMessageManager(mozilla::ErrorResult& aError);
-  mozilla::dom::ChromeMessageBroadcaster*
-    GetGroupMessageManager(const nsAString& aGroup,
-                           mozilla::ErrorResult& aError);
+  nsIMessageBroadcaster* GetMessageManager(mozilla::ErrorResult& aError);
+  nsIMessageBroadcaster* GetGroupMessageManager(const nsAString& aGroup,
+                                                mozilla::ErrorResult& aError);
   void BeginWindowMove(mozilla::dom::Event& aMouseDownEvent,
                        mozilla::dom::Element* aPanel,
                        mozilla::ErrorResult& aError);
 
   already_AddRefed<mozilla::dom::Promise>
   PromiseDocumentFlushed(mozilla::dom::PromiseDocumentFlushedCallback& aCallback,
                          mozilla::ErrorResult& aError);
 
@@ -1268,19 +1266,19 @@ private:
 
   bool IsBackgroundInternal() const;
 
   // NOTE: Chrome Only
   void DisconnectAndClearGroupMessageManagers()
   {
     MOZ_RELEASE_ASSERT(IsChromeWindow());
     for (auto iter = mChromeFields.mGroupMessageManagers.Iter(); !iter.Done(); iter.Next()) {
-      mozilla::dom::ChromeMessageBroadcaster* mm = iter.UserData();
+      nsIMessageBroadcaster* mm = iter.UserData();
       if (mm) {
-        mm->Disconnect();
+        static_cast<nsFrameMessageManager*>(mm)->Disconnect();
       }
     }
     mChromeFields.mGroupMessageManagers.Clear();
   }
 
   void CallDocumentFlushedResolvers();
   void CancelDocumentFlushedResolvers();
 
@@ -1470,19 +1468,18 @@ protected:
 
   // Members in the mChromeFields member should only be used in chrome windows.
   // All accesses to this field should be guarded by a check of mIsChrome.
   struct ChromeFields {
     ChromeFields()
       : mGroupMessageManagers(1)
     {}
 
-    RefPtr<mozilla::dom::ChromeMessageBroadcaster> mMessageManager;
-    nsRefPtrHashtable<nsStringHashKey,
-                      mozilla::dom::ChromeMessageBroadcaster> mGroupMessageManagers;
+    nsCOMPtr<nsIMessageBroadcaster> mMessageManager;
+    nsInterfaceHashtable<nsStringHashKey, nsIMessageBroadcaster> mGroupMessageManagers;
   } mChromeFields;
 
   // These fields are used by the inner and outer windows to prevent
   // programatically moving the window while the mouse is down.
   static bool sMouseDown;
   static bool sDragServiceDisabled;
 
   friend class nsDOMScriptableHelper;
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -32,21 +32,21 @@
 #include "nsIScriptObjectPrincipal.h"
 #include "nsITimer.h"
 #include "mozilla/EventListenerManager.h"
 #include "nsIPrincipal.h"
 #include "nsSize.h"
 #include "mozilla/FlushType.h"
 #include "prclist.h"
 #include "mozilla/dom/BindingDeclarations.h"
-#include "mozilla/dom/ChromeMessageBroadcaster.h"
 #include "mozilla/dom/StorageEvent.h"
 #include "mozilla/dom/StorageEventBinding.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/ErrorResult.h"
+#include "nsFrameMessageManager.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/LinkedList.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsIIdleObserver.h"
 #include "nsIDocument.h"
 #include "mozilla/dom/EventTarget.h"
 #include "mozilla/dom/WindowBinding.h"
--- a/dom/base/nsIMessageManager.idl
+++ b/dom/base/nsIMessageManager.idl
@@ -198,17 +198,17 @@ interface nsIMessageListener : nsISuppor
    * returned as JSON (will be changed to use structured clones).
    * When there are multiple listeners to sync messages, each
    * listener's return value is sent back as an array.  |undefined|
    * return values show up as undefined values in the array.
    */
   void receiveMessage();
 };
 
-[uuid(b949bfec-bb7d-47bc-b387-ac6a9b655072)]
+[scriptable, builtinclass, uuid(b949bfec-bb7d-47bc-b387-ac6a9b655072)]
 interface nsIMessageListenerManager : nsISupports
 {
   /**
    * Register |listener| to receive |messageName|.  All listener
    * callbacks for a particular message are invoked when that message
    * is received.
    *
    * The message manager holds a strong ref to |listener|.
@@ -256,17 +256,17 @@ interface nsIMessageListenerManager : ns
 };
 
 /**
  * Message "senders" have a single "other side" to which messages are
  * sent.  For example, a child-process message manager will send
  * messages that are only delivered to its one parent-process message
  * manager.
  */
-[uuid(bb5d79e4-e73c-45e7-9651-4d718f4b994c)]
+[scriptable, builtinclass, uuid(bb5d79e4-e73c-45e7-9651-4d718f4b994c)]
 interface nsIMessageSender : nsIMessageListenerManager
 {
   /**
    * Send |messageName| and |obj| to the "other side" of this message
    * manager.  This invokes listeners who registered for
    * |messageName|.
    *
    * See nsIMessageListener::receiveMessage() for the format of the
@@ -304,17 +304,17 @@ interface nsIMessageSender : nsIMessageL
 
 /**
  * Message "broadcasters" don't have a single "other side" that they
  * send messages to, but rather a set of subordinate message managers.
  * For example, broadcasting a message through a window message
  * manager will broadcast the message to all frame message managers
  * within its window.
  */
-[uuid(4d7d62ad-4725-4f39-86cf-8fb22bf9c1d8)]
+[scriptable, builtinclass, uuid(4d7d62ad-4725-4f39-86cf-8fb22bf9c1d8)]
 interface nsIMessageBroadcaster : nsIMessageListenerManager
 {
   /**
    * Like |sendAsyncMessage()|, but also broadcasts this message to
    * all "child" message managers of this message manager.  See long
    * comment above for details.
    *
    * WARNING: broadcasting messages can be very expensive and leak
@@ -337,17 +337,17 @@ interface nsIMessageBroadcaster : nsIMes
 
   /**
    * Some processes are kept alive after their last tab/window are closed for testing
    * (see dom.ipc.keepProcessesAlive). This function releases those.
    */
    void releaseCachedProcesses();
 };
 
-[uuid(0e602c9e-1977-422a-a8e4-fe0d4a4f78d0)]
+[scriptable, builtinclass, uuid(0e602c9e-1977-422a-a8e4-fe0d4a4f78d0)]
 interface nsISyncMessageSender : nsIMessageSender
 {
   /**
    * Like |sendAsyncMessage()|, except blocks the sender until all
    * listeners of the message have been invoked.  Returns an array
    * containing return values from each listener invoked.
    */
   [implicit_jscontext, optional_argc]
@@ -367,17 +367,17 @@ interface nsISyncMessageSender : nsIMess
    */
   [implicit_jscontext, optional_argc]
   jsval sendRpcMessage([optional] in AString messageName,
                        [optional] in jsval obj,
                        [optional] in jsval objects,
                        [optional] in nsIPrincipal principal);
 };
 
-[uuid(13f3555f-769e-44ea-b607-5239230c3162)]
+[scriptable, builtinclass, uuid(13f3555f-769e-44ea-b607-5239230c3162)]
 interface nsIMessageManagerGlobal : nsISyncMessageSender
 {
   /**
    * Print a string to stdout.
    */
   void dump(in DOMString aStr);
 
   /**
@@ -388,17 +388,17 @@ interface nsIMessageManagerGlobal : nsIS
 
   /**
    * Ascii base64 data to binary data and vice versa
    */
   DOMString atob(in DOMString aAsciiString);
   DOMString btoa(in DOMString aBase64Data);
 };
 
-[uuid(694e367c-aa25-4446-8499-2c527c4bd838)]
+[scriptable, builtinclass, uuid(694e367c-aa25-4446-8499-2c527c4bd838)]
 interface nsIContentFrameMessageManager : nsIMessageManagerGlobal
 {
   /**
    * The current top level window in the frame or null.
    */
   readonly attribute mozIDOMWindowProxy content;
 
   /**
@@ -415,28 +415,28 @@ interface nsIContentFrameMessageManager 
 
 [uuid(b39a3324-b574-4f85-8cdb-274d04f807ef)]
 interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager
 {
   [notxpcom] nsIContent getOwnerContent();
   [notxpcom] void cacheFrameLoader(in nsIFrameLoader aFrameLoader);
 };
 
-[uuid(6d12e467-2446-46db-9965-e4e93cb87ca5)]
+[scriptable, builtinclass, uuid(6d12e467-2446-46db-9965-e4e93cb87ca5)]
 interface nsIContentProcessMessageManager : nsIMessageManagerGlobal
 {
   /**
    * Read out a copy of the object that was initialized in the parent
    * process via nsIProcessScriptLoader.initialProcessData.
    */
   [implicit_jscontext]
   readonly attribute jsval initialProcessData;
 };
 
-[uuid(bf61446b-ba24-4b1d-88c7-4f94724b9ce1)]
+[scriptable, builtinclass, uuid(bf61446b-ba24-4b1d-88c7-4f94724b9ce1)]
 interface nsIFrameScriptLoader : nsISupports
 {
   /**
    * Load a script in the (remote) frame. aURL must be the absolute URL.
    * data: URLs are also supported. For example data:,dump("foo\n");
    * If aAllowDelayedLoad 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.
@@ -453,17 +453,17 @@ interface nsIFrameScriptLoader : nsISupp
    * Returns all delayed scripts that will be loaded once a (remote)
    * frame becomes available. The return value is a list of pairs
    * [<URL>, <WasLoadedInGlobalScope>].
    */
   [implicit_jscontext]
   jsval getDelayedFrameScripts();
 };
 
-[uuid(7e1e1a20-b24f-11e4-ab27-0800200c9a66)]
+[scriptable, builtinclass, uuid(7e1e1a20-b24f-11e4-ab27-0800200c9a66)]
 interface nsIProcessScriptLoader : nsISupports
 {
   /**
    * Load a script in the (possibly remote) process. aURL must be the absolute URL.
    * data: URLs are also supported. For example data:,dump("foo\n");
    * If aAllowDelayedLoad 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.
@@ -478,17 +478,17 @@ interface nsIProcessScriptLoader : nsISu
   /**
    * Returns all delayed scripts that will be loaded once a (remote)
    * frame becomes available. The return value is a list of URLs.
    */
   [implicit_jscontext]
   jsval getDelayedProcessScripts();
 };
 
-[uuid(5b390753-abb3-49b0-ae3b-b803dab58144)]
+[scriptable, builtinclass, uuid(5b390753-abb3-49b0-ae3b-b803dab58144)]
 interface nsIGlobalProcessScriptLoader : nsIProcessScriptLoader
 {
   /**
    * Allows the parent process to set the initial process data for
    * new, not-yet-created child processes. This attribute should only
    * be used by the global parent process message manager. When a new
    * process is created, it gets a copy of this data (via structured
    * cloning). It can access the data via the initialProcessData
--- a/dom/base/nsInProcessTabChildGlobal.cpp
+++ b/dom/base/nsInProcessTabChildGlobal.cpp
@@ -9,19 +9,18 @@
 #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
@@ -85,21 +84,21 @@ nsInProcessTabChildGlobal::DoSendAsyncMe
 
   queue->Push(ev);
   return NS_OK;
 }
 
 nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
                                                      nsIContent* aOwner,
                                                      nsFrameMessageManager* aChrome)
-: ContentFrameMessageManager(aChrome),
-  mDocShell(aShell), mInitialized(false), mLoadingScript(false),
+: 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();
   }
@@ -115,29 +114,31 @@ 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 MessageManagerGlobal::MarkForCC();
+  return mMessageManager ? mMessageManager->MarkForCC() : false;
 }
 
 nsresult
 nsInProcessTabChildGlobal::Init()
 {
 #ifdef DEBUG
   nsresult rv =
 #endif
   InitTabChildGlobal();
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                        "Couldn't initialize nsInProcessTabChildGlobal");
-  mMessageManager = new nsFrameMessageManager(this);
+  mMessageManager = new nsFrameMessageManager(this,
+                                              nullptr,
+                                              dom::ipc::MM_CHILD);
   return NS_OK;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsInProcessTabChildGlobal)
 
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsInProcessTabChildGlobal,
                                                   DOMEventTargetHelper)
@@ -163,79 +164,53 @@ 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)
 {
-  ErrorResult rv;
-  *aContent = GetContent(rv).take();
-  return rv.StealNSResult();
+  *aContent = nullptr;
+  if (!mDocShell) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsPIDOMWindowOuter> window = mDocShell->GetWindow();
+  window.forget(aContent);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
 {
-  ErrorResult rv;
-  *aDocShell = GetDocShell(rv).take();
-  return rv.StealNSResult();
-}
-
-already_AddRefed<nsIEventTarget>
-nsInProcessTabChildGlobal::GetTabEventTarget()
-{
-  nsCOMPtr<nsIEventTarget> target = GetMainThreadEventTarget();
-  return target.forget();
+  NS_IF_ADDREF(*aDocShell = mDocShell);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsInProcessTabChildGlobal::GetTabEventTarget(nsIEventTarget** aTarget)
 {
-  *aTarget = GetTabEventTarget().take();
+  nsCOMPtr<nsIEventTarget> target = GetMainThreadEventTarget();
+  target.forget(aTarget);
   return NS_OK;
 }
 
 void
 nsInProcessTabChildGlobal::FireUnloadEvent()
 {
   // We're called from nsDocument::MaybeInitializeFinalizeFrameLoaders, so it
   // should be safe to run script.
@@ -332,17 +307,18 @@ 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);
   }
-  NS_ENSURE_STATE(InitChildGlobalInternal(id));
+  nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, this);
+  NS_ENSURE_STATE(InitChildGlobalInternal(scopeSupports, id));
   return NS_OK;
 }
 
 class nsAsyncScriptLoad : public Runnable
 {
 public:
   nsAsyncScriptLoad(nsInProcessTabChildGlobal* aTabChild,
                     const nsAString& aURL,
@@ -372,18 +348,17 @@ nsInProcessTabChildGlobal::LoadFrameScri
     return;
   }
   if (!mInitialized) {
     mInitialized = true;
     Init();
   }
   bool tmp = mLoadingScript;
   mLoadingScript = true;
-  JS::Rooted<JSObject*> global(mozilla::dom::RootingCx(), GetWrapper());
-  LoadScriptInternal(global, aURL, aRunInGlobalScope);
+  LoadScriptInternal(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,17 +4,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef 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"
@@ -23,17 +22,17 @@
 #include "nsIGlobalObject.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsWeakReference.h"
 
 namespace mozilla {
 class EventChainPreVisitor;
 } // namespace mozilla
 
-class nsInProcessTabChildGlobal : public mozilla::dom::ContentFrameMessageManager,
+class nsInProcessTabChildGlobal : public mozilla::DOMEventTargetHelper,
                                   public nsMessageManagerScriptExecutor,
                                   public nsIInProcessContentFrameMessageManager,
                                   public nsIGlobalObject,
                                   public nsIScriptObjectPrincipal,
                                   public nsSupportsWeakReference,
                                   public mozilla::dom::ipc::MessageManagerCallback
 {
   typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData;
@@ -42,40 +41,48 @@ 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_DECL_NSICONTENTFRAMEMESSAGEMANAGER
+  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_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER
 
   /**
    * MessageManagerCallback methods that we override.
    */
   virtual bool DoSendBlockingMessage(JSContext* aCx,
                                       const nsAString& aMessage,
@@ -87,16 +94,36 @@ 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,
@@ -111,28 +138,32 @@ public:
   {
     return mChromeMessageManager;
   }
   void SetChromeMessageManager(nsFrameMessageManager* aParent)
   {
     mChromeMessageManager = aParent;
   }
 
-  virtual JSObject* GetGlobalJSObject() override
+  virtual JSObject* GetGlobalJSObject() override {
+    return mGlobal;
+  }
+  virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override
   {
-    return GetWrapper();
+    MOZ_CRASH("nsInProcessTabChildGlobal doesn't use DOM bindings!");
   }
 
   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/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -10,17 +10,16 @@
  * The goal of the utility functions is to cut down on the size of
  * the generated code itself.
  */
 
 #include "nsJSUtils.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "nsIScriptContext.h"
-#include "nsIScriptElement.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIXPConnect.h"
 #include "nsCOMPtr.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsPIDOMWindow.h"
 #include "GeckoProfiler.h"
 #include "nsJSPrincipals.h"
 #include "xpcpublic.h"
--- a/dom/base/nsWrapperCache.h
+++ b/dom/base/nsWrapperCache.h
@@ -339,17 +339,21 @@ 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/base/test/browser_messagemanager_loadprocessscript.js
+++ b/dom/base/test/browser_messagemanager_loadprocessscript.js
@@ -1,24 +1,30 @@
+var ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+           .getService(Ci.nsIMessageBroadcaster);
+ppmm.QueryInterface(Ci.nsIProcessScriptLoader);
+
 const BASE_NUMBER_OF_PROCESSES = 3;
 function checkBaseProcessCount(description) {
-  const {childCount} = Services.ppmm;
+  const {childCount} = ppmm;
   // With preloaded activity-stream, process count is a bit undeterministic, so
   // allow for some variation
   const extraCount = BASE_NUMBER_OF_PROCESSES + 1;
   ok(childCount === BASE_NUMBER_OF_PROCESSES || childCount === extraCount, `${description} (${BASE_NUMBER_OF_PROCESSES} or ${extraCount})`);
 }
 
 function processScript() {
-  if (Services.cpmm !== this) {
+  let cpmm = Components.classes["@mozilla.org/childprocessmessagemanager;1"]
+           .getService(Components.interfaces.nsISyncMessageSender);
+  if (cpmm !== this) {
     dump("Test failed: wrong global object\n");
     return;
   }
 
-  this.cpmm = Services.cpmm;
+  this.cpmm = cpmm;
 
   addMessageListener("ProcessTest:Reply", function listener(msg) {
     removeMessageListener("ProcessTest:Reply", listener);
     sendAsyncMessage("ProcessTest:Finished");
   });
   sendSyncMessage("ProcessTest:Loaded");
 }
 var processScriptURL = "data:,(" + processScript.toString() + ")()";
@@ -59,89 +65,89 @@ add_task(async function(){
   ]});
 })
 
 add_task(async function(){
   // This test is only relevant in e10s.
   if (!gMultiProcessBrowser)
     return;
 
-  Services.ppmm.releaseCachedProcesses();
+  ppmm.releaseCachedProcesses();
 
   await SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount", 5]]})
   await SpecialPowers.pushPrefEnv({"set": [["dom.ipc.keepProcessesAlive.web", 5]]})
 
   let tabs = [];
   for (let i = 0; i < 3; i++) {
     tabs[i] = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
   }
 
   for (let i = 0; i < 3; i++) {
     await BrowserTestUtils.removeTab(tabs[i]);
   }
 
-  Services.ppmm.releaseCachedProcesses();
+  ppmm.releaseCachedProcesses();
   checkBaseProcessCount("Should get back to the base number of processes at this point");
 })
 
 // Test that loading a process script loads in all existing processes
 add_task(async function() {
   let checks = [];
-  for (let i = 0; i < Services.ppmm.childCount; i++)
-    checks.push(checkProcess(Services.ppmm.getChildAt(i)));
+  for (let i = 0; i < ppmm.childCount; i++)
+    checks.push(checkProcess(ppmm.getChildAt(i)));
 
-  Services.ppmm.loadProcessScript(processScriptURL, false);
+  ppmm.loadProcessScript(processScriptURL, false);
   await Promise.all(checks);
 });
 
 // Test that loading a process script loads in new processes
 add_task(async function() {
   // This test is only relevant in e10s
   if (!gMultiProcessBrowser)
     return;
 
   checkBaseProcessCount("Should still be at the base number of processes at this point");
 
   // Load something in the main process
   gBrowser.selectedBrowser.loadURI("about:robots");
   await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
 
-  let init = Services.ppmm.initialProcessData;
+  let init = ppmm.initialProcessData;
   init.test123 = "hello";
   init.test456 = new Map();
   init.test456.set("hi", "bye");
 
   // With no remote frames left we should be down to one process.
   // However, stuff like remote thumbnails can cause a content
   // process to exist nonetheless. This should be rare, though,
   // so the test is useful most of the time.
-  if (Services.ppmm.childCount == 2) {
-    let mainMM = Services.ppmm.getChildAt(0);
+  if (ppmm.childCount == 2) {
+    let mainMM = ppmm.getChildAt(0);
 
-    let check = checkProcess(Services.ppmm);
-    Services.ppmm.loadProcessScript(processScriptURL, true);
+    let check = checkProcess(ppmm);
+    ppmm.loadProcessScript(processScriptURL, true);
 
     // The main process should respond
     await check;
 
-    check = checkProcess(Services.ppmm);
+    check = checkProcess(ppmm);
     // Reset the default browser to start a new child process
     gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser, true);
     gBrowser.selectedBrowser.loadURI("about:blank");
     await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
 
     checkBaseProcessCount("Should be back to the base number of processes at this point");
 
     // The new process should have responded
     await check;
 
-    Services.ppmm.removeDelayedProcessScript(processScriptURL);
+    ppmm.removeDelayedProcessScript(processScriptURL);
 
     let childMM;
-    childMM = Services.ppmm.getChildAt(2);
+    childMM = ppmm.getChildAt(2);
 
     childMM.loadProcessScript(initTestScriptURL, false);
     let msg = await promiseMessage(childMM, "ProcessTest:InitGood");
     is(msg.data, "bye", "initial process data was correct");
   } else {
     info("Unable to finish test entirely");
   }
 });
--- a/dom/base/test/chrome/file_bug1139964.xul
+++ b/dom/base/test/chrome/file_bug1139964.xul
@@ -6,17 +6,18 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=1139964
 -->
 <window title="Mozilla Bug 1139964"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
   onload="run()">
   <label value="Mozilla Bug 1139964"/>
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
-  var ppm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService();
+  var ppm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+              .getService(Ci.nsIMessageBroadcaster);
 
   function ok(cond, msg) {
     opener.wrappedJSObject.ok(cond, msg);
   }
 
   var msgName = "TEST:Global_has_Promise";
 
   function mmScriptForPromiseTest() {
--- a/dom/base/test/chrome/file_bug549682.xul
+++ b/dom/base/test/chrome/file_bug549682.xul
@@ -9,19 +9,22 @@ https://bugzilla.mozilla.org/show_bug.cg
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
   onload="run()">
   <label value="Mozilla Bug 549682"/>
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
   var didRunAsync = false;
   var didRunLocal = false;
 
-  var global = Cc["@mozilla.org/globalmessagemanager;1"].getService();
-  var ppm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService();
-  var cpm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService();
+  var global = Cc["@mozilla.org/globalmessagemanager;1"]
+                 .getService(Components.interfaces.nsIMessageBroadcaster);
+  var ppm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+              .getService(Components.interfaces.nsIMessageBroadcaster);
+  var cpm = Cc["@mozilla.org/childprocessmessagemanager;1"]
+              .getService(Components.interfaces.nsISyncMessageSender);
 
   ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
   function ok(cond, msg) {
     opener.wrappedJSObject.ok(cond, msg);
   }
 
   function is(actual, expected, msg) {
--- a/dom/base/test/chrome/file_bug990812-1.xul
+++ b/dom/base/test/chrome/file_bug990812-1.xul
@@ -11,17 +11,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <label value="Mozilla Bug 990812"/>
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
 
     var FRAME_SCRIPT_GLOBAL = "data:,sendSyncMessage('test', 'global')";
     var FRAME_SCRIPT_WINDOW = "data:,sendSyncMessage('test', 'window')";
     var FRAME_SCRIPT_GROUP  = "data:,sendSyncMessage('test', 'group')";
 
-    var globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService();
+    var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+                     .getService(Ci.nsIMessageListenerManager);
 
     function is(val, exp, msg) {
       opener.wrappedJSObject.is(val, exp, msg);
     }
 
     /**
      * Ensures that delayed frame scripts are loaded in the expected order.
      * Global frame scripts will be loaded before delayed frame scripts from
--- a/dom/base/test/chrome/file_bug990812-2.xul
+++ b/dom/base/test/chrome/file_bug990812-2.xul
@@ -10,17 +10,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   onload="start();">
   <label value="Mozilla Bug 990812"/>
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
 
     var FRAME_SCRIPT = "data:,sendAsyncMessage('test')";
     var order = ["group", "window", "global"];
 
-    var globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService();
+    var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+                     .getService(Ci.nsIMessageListenerManager);
 
     function is(val, exp, msg) {
       opener.wrappedJSObject.is(val, exp, msg);
     }
 
     function promiseMessage(type, mm) {
       return new Promise(function (resolve) {
         mm.addMessageListener("test", function onMessage() {
--- a/dom/base/test/chrome/file_bug990812-3.xul
+++ b/dom/base/test/chrome/file_bug990812-3.xul
@@ -10,17 +10,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   onload="start();">
   <label value="Mozilla Bug 990812"/>
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
 
     var FRAME_SCRIPT = "data:,addMessageListener('test', function (msg) {" +
                        "sendSyncMessage('test', msg.data)})";
 
-    var globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService();
+    var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+                     .getService(Ci.nsIMessageListenerManager);
 
     function is(val, exp, msg) {
       opener.wrappedJSObject.is(val, exp, msg);
     }
 
     function promiseMessage(type, mm) {
       var order = [type, "window", "global"];
 
--- a/dom/base/test/chrome/file_bug990812-4.xul
+++ b/dom/base/test/chrome/file_bug990812-4.xul
@@ -12,17 +12,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
 
     var FRAME_SCRIPT1 = "data:,addMessageListener('test', function () {" +
                         "sendSyncMessage('test', 'frame1')})";
     var FRAME_SCRIPT2 = "data:,addMessageListener('test', function () {" +
                         "sendSyncMessage('test', 'frame2')})";
 
-    var globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService();
+    var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+                     .getService(Ci.nsIMessageListenerManager);
 
     function is(val, exp, msg) {
       opener.wrappedJSObject.is(val, exp, msg);
     }
 
     function promiseMessage(type, mm) {
       return new Promise(function (resolve) {
         mm.addMessageListener("test", function onMessage(msg) {
--- a/dom/base/test/chrome/file_bug990812-5.xul
+++ b/dom/base/test/chrome/file_bug990812-5.xul
@@ -12,17 +12,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
 
     var FRAME_SCRIPT1 = "data:,addMessageListener('test', function () {" +
                         "sendSyncMessage('test', 'group1')})";
     var FRAME_SCRIPT2 = "data:,addMessageListener('test', function () {" +
                         "sendSyncMessage('test', 'group2')})";
 
-    var globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService();
+    var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+                     .getService(Ci.nsIMessageListenerManager);
 
     function is(val, exp, msg) {
       opener.wrappedJSObject.is(val, exp, msg);
     }
 
     function promiseTwoMessages(type, mm) {
       var numLeft = 2;
 
--- a/dom/base/test/chrome/file_bug990812.xul
+++ b/dom/base/test/chrome/file_bug990812.xul
@@ -11,17 +11,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   <label value="Mozilla Bug 990812"/>
   <!-- test code goes here -->
   <script type="application/javascript"><![CDATA[
 
     var FRAME_SCRIPT_GLOBAL = "data:,sendSyncMessage('test', 'global')";
     var FRAME_SCRIPT_WINDOW = "data:,sendSyncMessage('test', 'window')";
     var FRAME_SCRIPT_GROUP  = "data:,sendSyncMessage('test', 'group')";
 
-    var globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService();
+    var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+                     .getService(Ci.nsIMessageListenerManager);
 
     function is(val, exp, msg) {
       opener.wrappedJSObject.is(val, exp, msg);
     }
 
     function start() {
       globalMM.loadFrameScript(FRAME_SCRIPT_GLOBAL, true);
       messageManager.loadFrameScript(FRAME_SCRIPT_WINDOW, true);
--- a/dom/base/test/chrome/test_bug1098074_throw_from_ReceiveMessage.xul
+++ b/dom/base/test/chrome/test_bug1098074_throw_from_ReceiveMessage.xul
@@ -16,17 +16,18 @@ https://bugzilla.mozilla.org/show_bug.cg
   /** Test for Bug 1098074 **/
   SimpleTest.waitForExplicitFinish();
   SimpleTest.expectUncaughtException();
 
   // Tell the test to expect exactly one console error with the given parameters,
   // with SimpleTest.finish as a continuation function.
   SimpleTest.monitorConsole(SimpleTest.finish, [{errorMessage: new RegExp('acopia')}]);
 
-  var globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService();
+  var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+                   .getService(Ci.nsIMessageListenerManager);
   globalMM.addMessageListener("flimfniffle", function onMessage(msg) {
     globalMM.removeMessageListener("flimfniffle", onMessage);
     is(msg.data, "teufeltor", "correct message");
 
     // Cleanup the monitor after we throw.
     SimpleTest.executeSoon(SimpleTest.endMonitorConsole);
 
     throw "acopia";
--- a/dom/base/test/test_domrequesthelper.xul
+++ b/dom/base/test/test_domrequesthelper.xul
@@ -13,17 +13,18 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
 
   <script type="application/javascript">
   <![CDATA[
     ChromeUtils.import("resource://gre/modules/DOMRequestHelper.jsm");
     let obs = Cc["@mozilla.org/observer-service;1"].
               getService(Ci.nsIObserverService);
-    let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService();
+    let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"].
+              getService(Ci.nsIMessageBroadcaster);
 
     function DummyHelperSubclass() {
       this.onuninit = null;
     }
     DummyHelperSubclass.prototype = {
       __proto__: DOMRequestIpcHelper.prototype,
       uninit: function() {
         if (typeof this.onuninit === "function") {
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -3122,32 +3122,21 @@ ConvertExceptionToPromise(JSContext* cx,
   }
 
   rval.setObject(*promise);
   return true;
 }
 
 /* static */
 void
-CreateGlobalOptionsWithXPConnect::TraceGlobal(JSTracer* aTrc, JSObject* aObj)
+CreateGlobalOptions<nsGlobalWindowInner>::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;
   }
@@ -3171,17 +3160,20 @@ bool
 CreateGlobalOptions<nsGlobalWindowInner>::PostCreateGlobal(JSContext* aCx,
                                                            JS::Handle<JSObject*> aGlobal)
 {
   nsresult rv = RegisterDOMNames();
   if (NS_FAILED(rv)) {
     return Throw(aCx, rv);
   }
 
-  return CreateGlobalOptionsWithXPConnect::PostCreateGlobal(aCx, aGlobal);
+  // Invoking the XPCWrappedNativeScope constructor automatically hooks it
+  // up to the compartment of aGlobal.
+  (void) new XPCWrappedNativeScope(aCx, aGlobal);
+  return true;
 }
 
 #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,17 +45,16 @@ 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,
@@ -3096,59 +3095,39 @@ 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);
 
-
-struct CreateGlobalOptionsGeneric
+template <class T>
+struct CreateGlobalOptions
 {
+  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.
@@ -3229,21 +3208,21 @@ class PinnedStringId
   bool init(JSContext *cx, const char *string) {
     JSString* str = JS_AtomizeAndPinString(cx, string);
     if (!str)
       return false;
     id = INTERNED_STRING_TO_JSID(cx, str);
     return true;
   }
 
-  operator const jsid& () const {
+  operator const jsid& () {
     return id;
   }
 
-  operator JS::Handle<jsid> () const {
+  operator JS::Handle<jsid> () {
     /* This is safe because we have pinned the string. */
     return JS::Handle<jsid>::fromMarkedLocation(&id);
   }
 };
 
 bool
 GenericBindingGetter(JSContext* cx, unsigned argc, JS::Value* vp);
 
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -147,20 +147,16 @@ 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'
 },
 
@@ -569,28 +565,16 @@ DOMInterfaces = {
 'MediaStreamTrack': {
     'concrete': False
 },
 
 'MediaRecorder': {
     'headerFile': 'MediaRecorder.h',
 },
 
-'MessageBroadcaster': {
-    'concrete': False
-},
-
-'MessageListenerManager': {
-    'concrete': False
-},
-
-'MessageSender': {
-    'concrete': False
-},
-
 'MimeType': {
     'headerFile' : 'nsMimeTypeArray.h',
     'nativeType': 'nsMimeType',
 },
 
 'MimeTypeArray': {
     'nativeType': 'nsMimeTypeArray',
 },
@@ -1026,20 +1010,16 @@ DOMInterfaces = {
 'SVGUnitTypes' : {
     'concrete': False,
 },
 
 'SVGZoomAndPan' : {
     'concrete': False,
 },
 
-'SyncMessageSender' : {
-    'concrete': False,
-},
-
 'TestFunctions': {
     'wrapperCache': False
 },
 
 'Text': {
     # Total hack to allow binding code to realize that nsTextNode can
     # in fact be cast to Text.
     'headerFile': 'nsTextNode.h',
@@ -1726,20 +1706,23 @@ 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('nsIMessageBroadcaster', nativeType='nsIMessageBroadcaster',
+                 headerFile='nsIMessageManager.h', notflattened=True)
+addExternalIface('nsIMessageSender', nativeType='nsIMessageSender',
+                 headerFile='nsIMessageManager.h', notflattened=True)
 addExternalIface('nsIPrintSettings', nativeType='nsIPrintSettings',
                  notflattened=True)
 addExternalIface('nsISelectionListener', nativeType='nsISelectionListener')
 addExternalIface('nsIStreamListener', nativeType='nsIStreamListener', notflattened=True)
 addExternalIface('nsITransportProvider', nativeType='nsITransportProvider')
 addExternalIface('nsITreeSelection', nativeType='nsITreeSelection',
                  notflattened=True)
 addExternalIface('nsISupports', nativeType='nsISupports')
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -276,45 +276,41 @@ class CGStringTable(CGThing):
 
     const char *table[] = {
       ...
     };
 
     The uint16_t indices are smaller than the pointer equivalents, and the
     string table requires no runtime relocations.
     """
-    def __init__(self, accessorName, strings, static=False):
+    def __init__(self, accessorName, strings):
         CGThing.__init__(self)
         self.accessorName = accessorName
         self.strings = strings
-        self.static = static
 
     def declare(self):
-        if self.static:
-            return ""
         return "extern const char *%s(unsigned int aIndex);\n" % self.accessorName
 
     def define(self):
         table = ' "\\0" '.join('"%s"' % s for s in self.strings)
         indices = []
         currentIndex = 0
         for s in self.strings:
             indices.append(currentIndex)
             currentIndex += len(s) + 1  # for the null terminator
         return fill(
             """
-            ${static}const char *${name}(unsigned int aIndex)
+            const char *${name}(unsigned int aIndex)
             {
               static const char table[] = ${table};
               static const uint16_t indices[] = { ${indices} };
               static_assert(${currentIndex} <= UINT16_MAX, "string table overflow!");
               return &table[indices[aIndex]];
             }
             """,
-            static="static " if self.static else "",
             name=self.accessorName,
             table=table,
             indices=", ".join("%d" % index for index in indices),
             currentIndex=currentIndex)
 
 
 class CGNativePropertyHooks(CGThing):
     """
@@ -1102,17 +1098,17 @@ class CGHeaders(CGWrapper):
         # Grab the includes for checking hasInstance
         interfacesImplementingSelf = set()
         for d in descriptors:
             interfacesImplementingSelf |= d.interface.interfacesImplementingSelf
         implementationIncludes |= set(self.getDeclarationFilename(i) for i in
                                       interfacesImplementingSelf)
 
         # Grab the includes for the things that involve XPCOM interfaces
-        hasInstanceIncludes = set(self.getDeclarationFilename(d.interface) for d
+        hasInstanceIncludes = set("nsIDOM" + d.interface.identifier.name + ".h" for d
                                   in descriptors if
                                   d.interface.hasInterfaceObject() and
                                   NeedsGeneratedHasInstance(d) and
                                   d.interface.hasInterfacePrototypeObject())
         if len(hasInstanceIncludes) > 0:
             hasInstanceIncludes.add("nsContentUtils.h")
 
         # Now find all the things we'll need as arguments because we
@@ -13948,130 +13944,68 @@ class CGRegisterWorkletBindings(CGAbstra
                     "%s::ConstructorEnabled(aCx, aObj) && " % bindingNS
                     + condition)
             conditions.append(condition)
         lines = [CGIfWrapper(CGGeneric("return false;\n"), condition) for
                  condition in conditions]
         lines.append(CGGeneric("return true;\n"))
         return CGList(lines, "\n").define()
 
-
-class CGSystemBindingInitIds(CGAbstractMethod):
-    def __init__(self):
-        CGAbstractMethod.__init__(self, None, 'SystemBindingInitIds', 'bool',
-                                  [Argument('JSContext*', 'aCx')])
-
-    def definition_body(self):
-        return dedent("""
-            MOZ_ASSERT(NS_IsMainThread());
-
-            if (!idsInited) {
-              // We can't use range-based for because we need the index to call IdString.
-              for (uint32_t i = 0; i < ArrayLength(properties); ++i) {
-                if (!properties[i].id.init(aCx, IdString(i))) {
-                  return false;
-                }
-              }
-              idsInited = true;
-            }
-
-            return true;
-            """)
-
-
 class CGResolveSystemBinding(CGAbstractMethod):
-    def __init__(self):
+    def __init__(self, config):
         CGAbstractMethod.__init__(self, None, 'ResolveSystemBinding', 'bool',
                                   [Argument('JSContext*', 'aCx'),
                                    Argument('JS::Handle<JSObject*>', 'aObj'),
                                    Argument('JS::Handle<jsid>', 'aId'),
                                    Argument('bool*', 'aResolvedp')])
-
-    def definition_body(self):
-        return dedent("""
-            MOZ_ASSERT(NS_IsMainThread());
-            MOZ_ASSERT(idsInited);
-
-            if (JSID_IS_VOID(aId)) {
-              for (const auto& property : properties) {
-                if (!property.enabled || property.enabled(aCx, aObj)) {
-                  if (!property.define(aCx)) {
-                    return false;
-                  }
-                  *aResolvedp = true;
-                }
-              }
-              return true;
-            }
-
-            for (const auto& property : properties) {
-              if (property.id == aId) {
-                if (!property.enabled || property.enabled(aCx, aObj)) {
-                  if (!property.define(aCx)) {
-                    return false;
-                  }
-                  *aResolvedp = true;
-                  break;
-                }
-              }
-            }
-            return true;
-            """)
-
-
-class CGMayResolveAsSystemBindingName(CGAbstractMethod):
-    def __init__(self):
-        CGAbstractMethod.__init__(self, None, 'MayResolveAsSystemBindingName', 'bool',
-                                  [Argument('jsid', 'aId')])
+        self.config = config
 
     def definition_body(self):
-        return dedent("""
-            MOZ_ASSERT(NS_IsMainThread());
-            MOZ_ASSERT(idsInited);
-
-            for (const auto& property : properties) {
-              if (aId == property.id) {
-                return true;
-              }
-            }
-            return false;
-            """)
-
-
-class CGGetSystemBindingNames(CGAbstractMethod):
-    def __init__(self):
-        CGAbstractMethod.__init__(self, None, 'GetSystemBindingNames', 'void',
-                                  [Argument('JSContext*', 'aCx'),
-                                   Argument('JS::Handle<JSObject*>', 'aObj'),
-                                   Argument('JS::AutoIdVector&', 'aNames'),
-                                   Argument('bool', 'aEnumerableOnly'),
-                                   Argument('mozilla::ErrorResult&', 'aRv')])
-
-    def definition_body(self):
-        return dedent("""
-            MOZ_ASSERT(NS_IsMainThread());
-
-            if (aEnumerableOnly) {
-              return;
-            }
-
-            if (!SystemBindingInitIds(aCx)) {
-              aRv.NoteJSContextException(aCx);
-              return;
-            }
-
-            for (const auto& property : properties) {
-              if (!property.enabled || property.enabled(aCx, aObj)) {
-                if (!aNames.append(property.id)) {
-                  aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-                  return;
-                }
-              }
-            }
-            """)
+        descriptors = self.config.getDescriptors(hasInterfaceObject=True,
+                                                 isExposedInSystemGlobals=True,
+                                                 register=True)
+
+        def descNameToId(name):
+            return "s%s_id" % name
+        jsidNames = [descNameToId(desc.name) for desc in descriptors]
+        jsidDecls = CGList(CGGeneric("static jsid %s;\n" % name)
+                           for name in jsidNames)
+
+        jsidInits = CGList(
+            (CGIfWrapper(
+                CGGeneric("return false;\n"),
+                '!AtomizeAndPinJSString(aCx, %s, "%s")' %
+                (descNameToId(desc.name), desc.interface.identifier.name))
+             for desc in descriptors),
+            "\n")
+        jsidInits.append(CGGeneric("idsInited = true;\n"))
+        jsidInits = CGIfWrapper(jsidInits, "!idsInited")
+        jsidInits = CGList([CGGeneric("static bool idsInited = false;\n"),
+                            jsidInits])
+
+        definitions = CGList([], "\n")
+        for desc in descriptors:
+            bindingNS = toBindingNamespace(desc.name)
+            defineCode = "!%s::GetConstructorObject(aCx)" % bindingNS
+            defineCode = CGIfWrapper(CGGeneric("return false;\n"), defineCode)
+            defineCode = CGList([defineCode,
+                                 CGGeneric("*aResolvedp = true;\n")])
+
+            condition = "JSID_IS_VOID(aId) || aId == %s" % descNameToId(desc.name)
+            if desc.isExposedConditionally():
+                condition = "(%s) && %s::ConstructorEnabled(aCx, aObj)" % (condition, bindingNS)
+
+            definitions.append(CGIfWrapper(defineCode, condition))
+
+        return CGList([CGGeneric("MOZ_ASSERT(NS_IsMainThread());\n"),
+                       jsidDecls,
+                       jsidInits,
+                       definitions,
+                       CGGeneric("return true;\n")],
+                      "\n").define()
 
 
 def getGlobalNames(config):
     names = []
     for desc in config.getDescriptors(registersGlobalNamesOnWindow=True):
         names.append((desc.name, desc))
         names.extend((n.identifier.name, desc) for n in desc.interface.namedConstructors)
     return names
@@ -17557,68 +17491,32 @@ class GlobalGenRoots():
         # Add include guards.
         curr = CGIncludeGuard('RegisterWorkletBindings', curr)
 
         # Done.
         return curr
 
     @staticmethod
     def ResolveSystemBinding(config):
-        curr = CGList([], "\n")
-        
-        descriptors = config.getDescriptors(hasInterfaceObject=True,
-                                            isExposedInSystemGlobals=True,
-                                            register=True)
-        properties = [desc.name for desc in descriptors]
-        
-        curr.append(CGStringTable("IdString", properties, static=True))
-
-        initValues = []
-        for desc in descriptors:
-            bindingNS = toBindingNamespace(desc.name)
-            if desc.isExposedConditionally():
-                enabled = "%s::ConstructorEnabled" % bindingNS
-            else:
-                enabled = "nullptr"
-            define = "%s::GetConstructorObject" % bindingNS
-            initValues.append("{ %s, %s },\n" % (enabled, define))
-        curr.append(CGGeneric(fill("""
-            struct SystemProperty
-            {
-              WebIDLGlobalNameHash::ConstructorEnabled enabled;
-              ProtoGetter define;
-              PinnedStringId id;
-            };
-          
-            static SystemProperty properties[] = {
-              $*{init}
-            };
-
-            static bool idsInited = false;
-            """,
-            init="".join(initValues))))
-
-        curr.append(CGSystemBindingInitIds())
-        curr.append(CGResolveSystemBinding())
-        curr.append(CGMayResolveAsSystemBindingName())
-        curr.append(CGGetSystemBindingNames())
+
+        curr = CGResolveSystemBinding(config)
 
         # Wrap all of that in our namespaces.
         curr = CGNamespace.build(['mozilla', 'dom'],
                                  CGWrapper(curr, post='\n'))
         curr = CGWrapper(curr, post='\n')
 
         # Add the includes
         defineIncludes = [CGHeaders.getDeclarationFilename(desc.interface)
                           for desc in config.getDescriptors(hasInterfaceObject=True,
                                                             register=True,
                                                             isExposedInSystemGlobals=True)]
         defineIncludes.append("nsThreadUtils.h")  # For NS_IsMainThread
         defineIncludes.append("js/Id.h")  # For jsid
-        defineIncludes.append("mozilla/dom/WebIDLGlobalNameHash.h")
+        defineIncludes.append("mozilla/dom/BindingUtils.h")  # AtomizeAndPinJSString
 
         curr = CGHeaders([], [], [], [], [], defineIncludes,
                          'ResolveSystemBinding', curr)
 
         # Add include guards.
         curr = CGIncludeGuard('ResolveSystemBinding', curr)
 
         # Done.
--- a/dom/bindings/ToJSValue.h
+++ b/dom/bindings/ToJSValue.h
@@ -228,23 +228,16 @@ ToJSValue(JSContext* aCx,
           const T& aArgument,
           JS::MutableHandle<JS::Value> aValue)
 {
   return aArgument.ToObjectInternal(aCx, aValue);
 }
 
 // Accept existing JS values (which may not be same-compartment with us
 MOZ_MUST_USE inline bool
-ToJSValue(JSContext* aCx, const JS::Value& aArgument,
-          JS::MutableHandle<JS::Value> aValue)
-{
-  aValue.set(aArgument);
-  return MaybeWrapValue(aCx, aValue);
-}
-MOZ_MUST_USE inline bool
 ToJSValue(JSContext* aCx, JS::Handle<JS::Value> aArgument,
           JS::MutableHandle<JS::Value> aValue)
 {
   aValue.set(aArgument);
   return MaybeWrapValue(aCx, aValue);
 }
 
 // Accept existing JS values on the Heap (which may not be same-compartment with us
@@ -314,23 +307,43 @@ ToJSValue(JSContext* aCx,
 }
 
 // Accept Promise objects, which need special handling.
 MOZ_MUST_USE bool
 ToJSValue(JSContext* aCx,
           Promise& aArgument,
           JS::MutableHandle<JS::Value> aValue);
 
-// Accept arrays (and nested arrays) of other things we accept
+// Accept arrays of other things we accept
 template <typename T>
 MOZ_MUST_USE bool
 ToJSValue(JSContext* aCx,
           T* aArguments,
           size_t aLength,
-          JS::MutableHandle<JS::Value> aValue);
+          JS::MutableHandle<JS::Value> aValue)
+{
+  // Make sure we're called in a compartment
+  MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
+
+  JS::AutoValueVector v(aCx);
+  if (!v.resize(aLength)) {
+    return false;
+  }
+  for (size_t i = 0; i < aLength; ++i) {
+    if (!ToJSValue(aCx, aArguments[i], v[i])) {
+      return false;
+    }
+  }
+  JSObject* arrayObj = JS_NewArrayObject(aCx, v);
+  if (!arrayObj) {
+    return false;
+  }
+  aValue.setObject(*arrayObj);
+  return true;
+}
 
 template <typename T>
 MOZ_MUST_USE bool
 ToJSValue(JSContext* aCx,
           const nsTArray<T>& aArgument,
           JS::MutableHandle<JS::Value> aValue)
 {
   return ToJSValue(aCx, aArgument.Elements(),
@@ -351,40 +364,12 @@ template <typename T, int N>
 MOZ_MUST_USE bool
 ToJSValue(JSContext* aCx,
           const T(&aArgument)[N],
           JS::MutableHandle<JS::Value> aValue)
 {
   return ToJSValue(aCx, aArgument, N, aValue);
 }
 
-// Accept arrays of other things we accept
-template <typename T>
-MOZ_MUST_USE bool
-ToJSValue(JSContext* aCx,
-          T* aArguments,
-          size_t aLength,
-          JS::MutableHandle<JS::Value> aValue)
-{
-  // Make sure we're called in a compartment
-  MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
-
-  JS::AutoValueVector v(aCx);
-  if (!v.resize(aLength)) {
-    return false;
-  }
-  for (size_t i = 0; i < aLength; ++i) {
-    if (!ToJSValue(aCx, aArguments[i], v[i])) {
-      return false;
-    }
-  }
-  JSObject* arrayObj = JS_NewArrayObject(aCx, v);
-  if (!arrayObj) {
-    return false;
-  }
-  aValue.setObject(*arrayObj);
-  return true;
-}
-
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_ToJSValue_h */
--- a/dom/bindings/WebIDLGlobalNameHash.cpp
+++ b/dom/bindings/WebIDLGlobalNameHash.cpp
@@ -106,17 +106,17 @@ struct WebIDLNameTableEntry : public PLD
 
   enum { ALLOW_MEMMOVE = true };
 
   uint16_t mNameOffset;
   uint16_t mNameLength;
   constructors::id::ID mConstructorId;
   WebIDLGlobalNameHash::DefineGlobalName mDefine;
   // May be null if enabled unconditionally
-  WebIDLGlobalNameHash::ConstructorEnabled mEnabled;
+  WebIDLGlobalNameHash::ConstructorEnabled* mEnabled;
 };
 
 static nsTHashtable<WebIDLNameTableEntry>* sWebIDLGlobalNames;
 
 class WebIDLGlobalNamesHashReporter final : public nsIMemoryReporter
 {
   MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
 
@@ -158,17 +158,17 @@ WebIDLGlobalNameHash::Shutdown()
 {
   delete sWebIDLGlobalNames;
 }
 
 /* static */
 void
 WebIDLGlobalNameHash::Register(uint16_t aNameOffset, uint16_t aNameLength,
                                DefineGlobalName aDefine,
-                               ConstructorEnabled aEnabled,
+                               ConstructorEnabled* aEnabled,
                                constructors::id::ID aConstructorId)
 {
   const char* name = sNames + aNameOffset;
   WebIDLNameTableKey key(name, aNameLength);
   WebIDLNameTableEntry* entry = sWebIDLGlobalNames->PutEntry(key);
   entry->mNameOffset = aNameOffset;
   entry->mNameLength = aNameLength;
   entry->mDefine = aDefine;
@@ -206,17 +206,17 @@ WebIDLGlobalNameHash::DefineIfEnabled(JS
 
   if (!entry) {
     *aFound = false;
     return true;
   }
 
   *aFound = true;
 
-  ConstructorEnabled checkEnabledForScope = entry->mEnabled;
+  ConstructorEnabled* checkEnabledForScope = entry->mEnabled;
   // We do the enabled check on the current compartment of aCx, but for the
   // actual object we pass in the underlying object in the Xray case.  That
   // way the callee can decide whether to allow access based on the caller
   // or the window being touched.
   JS::Rooted<JSObject*> global(aCx,
     js::CheckedUnwrap(aObj, /* stopAtWindowProxy = */ false));
   if (!global) {
     return Throw(aCx, NS_ERROR_DOM_SECURITY_ERR);
--- a/dom/bindings/WebIDLGlobalNameHash.h
+++ b/dom/bindings/WebIDLGlobalNameHash.h
@@ -33,20 +33,20 @@ public:
 
   // Check whether a constructor should be enabled for the given object.
   // Note that the object should NOT be an Xray, since Xrays will end up
   // defining constructors on the underlying object.
   // This is a typedef for the function type itself, not the function
   // pointer, so it's more obvious that pointers to a ConstructorEnabled
   // can be null.
   typedef bool
-  (*ConstructorEnabled)(JSContext* cx, JS::Handle<JSObject*> obj);
+  (ConstructorEnabled)(JSContext* cx, JS::Handle<JSObject*> obj);
 
   static void Register(uint16_t aNameOffset, uint16_t aNameLength,
-                       DefineGlobalName aDefine, ConstructorEnabled aEnabled,
+                       DefineGlobalName aDefine, ConstructorEnabled* aEnabled,
                        constructors::id::ID aConstructorId);
 
   static void Remove(const char* aName, uint32_t aLength);
 
   // Returns false if something failed. aFound is set to true if the name is in
   // the hash, whether it's enabled or not.
   static bool DefineIfEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj,
                               JS::Handle<jsid> aId,
--- a/dom/file/tests/test_ipc_messagemanager_blob.html
+++ b/dom/file/tests/test_ipc_messagemanager_blob.html
@@ -67,20 +67,20 @@
 
           // Make sure this one is always last.
           new Blob(["this ", "is ", "a ", "great ", "success!"],
                    {"type" : "text\/plain"}),
         ];
         let receivedMessageIndex = 0;
 
         let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
-        mm.addMessageListener("test:ipcClonedMessage", SpecialPowers.wrapCallback(function(message) {
+        mm.addMessageListener("test:ipcClonedMessage", function(message) {
           let data = message.json;
 
-          if (SpecialPowers.call_Instanceof(data, Blob)) {
+          if (data instanceof Blob) {
             is(receivedMessageIndex, messages.length - 1, "Blob is last");
             is (data.size,
                 messages[receivedMessageIndex].size,
                 "Correct blob size");
             is (data.type,
                 messages[receivedMessageIndex].type,
                 "Correct blob type");
 
@@ -99,25 +99,25 @@
             reader2.onload = function() {
               result2 = reader2.result == blobString ? reader2.result : "bad2";
               if (result1) {
                 is(result1, result2, "Same results");
                 done();
               }
             };
 
-            SpecialPowers.wrap(reader1).readAsText(data);
+            reader1.readAsText(data);
             reader2.readAsText(messages[receivedMessageIndex]);
             return;
           }
 
           is(message.json,
              messages[receivedMessageIndex++],
              "Got correct round-tripped response");
-        }));
+        });
         mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")();",
                            false);
 
         for (let message of messages) {
           mm.sendAsyncMessage("test:ipcClonedMessage", message);
         }
       });
 
--- a/dom/indexedDB/test/head.js
+++ b/dom/indexedDB/test/head.js
@@ -75,24 +75,21 @@ function dismissNotification(popup)
     EventUtils.synthesizeKey("KEY_Escape");
   });
 }
 
 function waitForMessage(aMessage, browser)
 {
   return new Promise((resolve, reject) => {
     /* eslint-disable no-undef */
-    // When contentScript runs, "this" is a ContentFrameMessageManager (so that's where
-    // addEventListener will add the listener), but the non-bubbling "message" event is
-    // sent to the Window involved, so we need a capturing listener.
     function contentScript() {
       addEventListener("message", function(event) {
         sendAsyncMessage("testLocal:message",
           {message: event.data});
-      }, {once: true, capture: true}, true);
+      }, {once: true}, true);
     }
     /* eslint-enable no-undef */
 
     let script = "data:,(" + contentScript.toString() + ")();";
 
     let mm = browser.selectedBrowser.messageManager;
 
     mm.addMessageListener("testLocal:message", function listener(msg) {
--- a/dom/indexedDB/test/test_message_manager_ipc.html
+++ b/dom/indexedDB/test/test_message_manager_ipc.html
@@ -209,69 +209,69 @@ function parentFrameScript(mm) {
 
   function grabAndContinue(arg) {
     testGenerator.next(arg);
   }
 
   function* testSteps() {
     let result = yield undefined;
 
-    is(SpecialPowers.Cu.getClassName(result, true), "Array", "Child delivered an array of results");
+    is(Array.isArray(result), true, "Child delivered an array of results");
     is(result.length, 2, "Child delivered two results");
 
     let blob = result[0];
-    is(SpecialPowers.call_Instanceof(blob, Blob), true, "Child delivered a blob");
+    is(blob instanceof Blob, true, "Child delivered a blob");
     is(blob.size, blobText.length, "Blob has correct size");
     is(blob.type, blobType, "Blob has correct type");
 
     let slice = result[1];
-    is(SpecialPowers.call_Instanceof(slice, Blob), true, "Child delivered a slice");
+    is(slice instanceof Blob, true, "Child delivered a slice");
     is(slice.size, blobData[0].length, "Slice has correct size");
     is(slice.type, blobType, "Slice has correct type");
 
     info("Reading blob");
 
     let reader = new FileReader();
     reader.onload = grabAndContinue;
-    SpecialPowers.wrap(reader).readAsText(blob);
+    reader.readAsText(blob);
     yield undefined;
 
     is(reader.result, blobText, "Blob has correct data");
 
     info("Reading slice");
 
     reader = new FileReader();
     reader.onload = grabAndContinue;
-    SpecialPowers.wrap(reader).readAsText(slice);
+    reader.readAsText(slice);
     yield undefined;
 
     is(reader.result, blobData[0], "Slice has correct data");
 
     slice = blob.slice(0, blobData[0].length, blobType);
 
-    is(SpecialPowers.call_Instanceof(slice, Blob), true, "Child delivered a slice");
+    is(slice instanceof Blob, true, "Made a new slice from blob");
     is(slice.size, blobData[0].length, "Second slice has correct size");
     is(slice.type, blobType, "Second slice has correct type");
 
     info("Reading second slice");
 
     reader = new FileReader();
     reader.onload = grabAndContinue;
-    SpecialPowers.wrap(reader).readAsText(slice);
+    reader.readAsText(slice);
     yield undefined;
 
     is(reader.result, blobData[0], "Second slice has correct data");
 
     SimpleTest.finish();
   }
 
   let testGenerator = testSteps();
   testGenerator.next();
 
-  mm.addMessageListener(messageName, SpecialPowers.wrapCallback(function(message) {
+  mm.addMessageListener(messageName, function(message) {
     let data = message.data;
     switch (data.op) {
       case "info": {
         info(data.msg);
         break;
       }
 
       case "ok": {
@@ -284,17 +284,17 @@ function parentFrameScript(mm) {
         break;
       }
 
       default: {
         ok(false, "Unknown op: " + data.op);
         SimpleTest.finish();
       }
     }
-  }));
+  });
 
   mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")();",
                       false);
 
   mm.sendAsyncMessage(messageName, blob);
 }
 
 function setup() {
--- a/dom/interfaces/base/nsIContentProcess.idl
+++ b/dom/interfaces/base/nsIContentProcess.idl
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMElement;
+interface nsIMessageSender;
 interface nsIURI;
 
 [scriptable, builtinclass, uuid(456f58be-29dd-4973-885b-95aece1c9a8a)]
 interface nsIContentProcessInfo : nsISupports
 {
   /**
    * Is this content process alive?
    */
@@ -30,17 +31,17 @@ interface nsIContentProcessInfo : nsISup
    * Number of opened tabs living in this content process.
    */
   readonly attribute int32_t tabCount;
 
   /**
    * The process manager for this ContentParent (so a process message manager
    * as opposed to a frame message manager.
    */
-  readonly attribute nsISupports messageManager;
+  readonly attribute nsIMessageSender messageManager;
 };
 
 [scriptable, uuid(83ffb063-5f65-4c45-ae07-3f553e0809bb)]
 interface nsIContentProcessProvider : nsISupports
 {
   /**
    * Return this from provideProcess to create a new process.
    */
--- a/dom/interfaces/base/nsITabChild.idl
+++ b/dom/interfaces/base/nsITabChild.idl
@@ -1,25 +1,26 @@
 /* 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 "domstubs.idl"
 #include "nsIDroppedLinkHandler.idl"
 
+interface nsIContentFrameMessageManager;
 interface nsIWebBrowserChrome3;
 
 native CommandsArray(nsTArray<nsCString>);
 [ref] native CommandsArrayRef(nsTArray<nsCString>);
 
 [scriptable, uuid(1fb79c27-e760-4088-b19c-1ce3673ec24e)]
 interface nsITabChild : nsISupports
 {
-  readonly attribute nsISupports messageManager;
+  readonly attribute nsIContentFrameMessageManager messageManager;
 
   attribute nsIWebBrowserChrome3 webBrowserChrome;
 
   [notxpcom] void sendRequestFocus(in boolean canFocus);
 
   [notxpcom] void sendGetTabCount(out uint32_t tabCount);
 
   [noscript, notxpcom] void enableDisableCommands(in AString action,
--- a/dom/ipc/ContentBridgeParent.cpp
+++ b/dom/ipc/ContentBridgeParent.cpp
@@ -1,16 +1,15 @@
 /* -*- 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/ContentBridgeParent.h"
-#include "mozilla/dom/ChromeMessageSender.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "nsXULAppAPI.h"
 #include "nsIObserverService.h"
 #include "base/task.h"
 
 using namespace mozilla::ipc;
 using namespace mozilla::jsipc;
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -19,17 +19,16 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/ProcessHangMonitorIPC.h"
 #include "mozilla/Unused.h"
 #include "mozilla/TelemetryIPC.h"
 #include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
 #include "mozilla/docshell/OfflineCacheUpdateChild.h"
 #include "mozilla/dom/ClientManager.h"
 #include "mozilla/dom/ClientOpenWindowOpActors.h"
-#include "mozilla/dom/ChildProcessMessageManager.h"
 #include "mozilla/dom/ContentBridgeChild.h"
 #include "mozilla/dom/ContentBridgeParent.h"
 #include "mozilla/dom/DOMPrefs.h"
 #include "mozilla/dom/VideoDecoderManagerChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/ExternalHelperAppChild.h"
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -521,17 +521,17 @@ ScriptableCPInfo::GetTabCount(int32_t* a
 
   ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
   *aTabCount = cpm->GetTabParentCountByProcessId(mContentParent->ChildID());
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-ScriptableCPInfo::GetMessageManager(nsISupports** aMessenger)
+ScriptableCPInfo::GetMessageManager(nsIMessageSender** aMessenger)
 {
   *aMessenger = nullptr;
   if (!mContentParent) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   nsCOMPtr<nsIMessageSender> manager = mContentParent->GetMessageManager();
   manager.forget(aMessenger);
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -14,17 +14,16 @@
 #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"
@@ -100,16 +99,17 @@
 #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,20 +231,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());
+    JS::Rooted<JSObject*> kungFuDeathGrip(cx, GetGlobal());
     // Let the BrowserElementScrolling helper (if it exists) for this
     // content manipulate the frame state.
-    RefPtr<nsFrameMessageManager> mm = mTabChildGlobal->GetMessageManager();
+    RefPtr<nsFrameMessageManager> mm =
+      static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
     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);
@@ -266,17 +267,17 @@ TabChildBase::UpdateFrameHandler(const F
     return true;
   }
   return true;
 }
 
 void
 TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
 {
-    if (!mTabChildGlobal) {
+    if (!mGlobal || !mTabChildGlobal) {
         return;
     }
 
     FrameMetrics newMetrics = aFrameMetrics;
     APZCCallbackHelper::UpdateRootFrame(newMetrics);
 }
 
 NS_IMETHODIMP
@@ -1103,21 +1104,23 @@ 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->GetMessageManager());
-    if (mTabChildGlobal->GetMessageManager()) {
+    MOZ_DIAGNOSTIC_ASSERT(mTabChildGlobal->mMessageManager);
+    if (mTabChildGlobal->mMessageManager) {
       // The messageManager relays messages via the TabChild which
       // no longer exists.
-      mTabChildGlobal->DisconnectMessageManager();
+      static_cast<nsFrameMessageManager*>
+        (mTabChildGlobal->mMessageManager.get())->Disconnect();
+      mTabChildGlobal->mMessageManager = nullptr;
     }
   }
 
   CompositorBridgeChild* compositorChild = CompositorBridgeChild::Get();
   if (compositorChild) {
     compositorChild->CancelNotifyAfterRemotePaint(this);
   }
 
@@ -1354,21 +1357,19 @@ 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(),
-    mTabChildGlobal ? mTabChildGlobal->GetWrapper() : nullptr,
-    mTabChildGlobal.get());
-
-  if (!mTabChildGlobal || !mTabChildGlobal->GetWrapper()) {
+    Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get());
+
+  if (!mGlobal || !mTabChildGlobal) {
     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
@@ -1399,36 +1400,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 (mGlobal && mTabChildGlobal) {
       mAPZEventState->ProcessSingleTap(point, scale, aModifiers, aGuid, 1);
     }
     break;
   case GeckoContentController::TapType::eDoubleTap:
     HandleDoubleTap(point, aModifiers, aGuid);
     break;
   case GeckoContentController::TapType::eSecondTap:
-    if (mTabChildGlobal) {
+    if (mGlobal && mTabChildGlobal) {
       mAPZEventState->ProcessSingleTap(point, scale, aModifiers, aGuid, 2);
     }
     break;
   case GeckoContentController::TapType::eLongTap:
-    if (mTabChildGlobal) {
+    if (mGlobal && mTabChildGlobal) {
       mAPZEventState->ProcessLongTap(presShell, point, scale, aModifiers, aGuid,
           aInputBlockId);
     }
     break;
   case GeckoContentController::TapType::eLongTapUp:
-    if (mTabChildGlobal) {
+    if (mGlobal && mTabChildGlobal) {
       mAPZEventState->ProcessLongTapUp(presShell, point, scale, aModifiers);
     }
     break;
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
@@ -2270,28 +2271,22 @@ 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 (!mGlobal && !InitTabChildGlobal())
     // 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) {
-    // This can happen if we're half-destroyed.  It's not a fatal error.
-    return IPC_OK();
-  }
-
-  LoadScriptInternal(global, aURL, aRunInGlobalScope);
+  LoadScriptInternal(aURL, aRunInGlobalScope);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabChild::RecvAsyncMessage(const nsString& aMessage,
                            InfallibleTArray<CpowEntry>&& aCpows,
                            const IPC::Principal& aPrincipal,
                            const ClonedMessageData& aData)
@@ -2299,29 +2294,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(mm);
-  if (!mm) {
+  MOZ_DIAGNOSTIC_ASSERT(mTabChildGlobal->mMessageManager);
+  if (!mTabChildGlobal->mMessageManager) {
     return IPC_OK();
   }
 
-  JS::Rooted<JSObject*> kungFuDeathGrip(dom::RootingCx(), mTabChildGlobal->GetWrapper());
+  JS::Rooted<JSObject*> kungFuDeathGrip(dom::RootingCx(), GetGlobal());
   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)
 {
@@ -2717,39 +2712,37 @@ TabChild::DeallocPRenderFrameChild(PRend
 {
     delete aFrame;
     return true;
 }
 
 bool
 TabChild::InitTabChildGlobal()
 {
-  if (!mTabChildGlobal) {
+  if (!mGlobal && !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 = mTabChildGlobal = new TabChildGlobal(this);
+    RefPtr<TabChildGlobal> scope = new TabChildGlobal(this);
+
+    nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, scope);
 
     NS_NAMED_LITERAL_CSTRING(globalId, "outOfProcessTabChildGlobal");
-    if (NS_WARN_IF(!InitChildGlobalInternal(globalId))) {
-        mTabChildGlobal = nullptr;
-        return false;
-    }
+    NS_ENSURE_TRUE(InitChildGlobalInternal(scopeSupports, globalId), false);
 
     scope->Init();
 
     nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(chromeHandler);
-    if (NS_WARN_IF(!root)) {
-        mTabChildGlobal = nullptr;
-        return false;
-    }
+    NS_ENSURE_TRUE(root, 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);
@@ -2960,21 +2953,24 @@ TabChild::MakeHidden()
 
 bool
 TabChild::IsVisible()
 {
   return mPuppetWidget && mPuppetWidget->IsVisible();
 }
 
 NS_IMETHODIMP
-TabChild::GetMessageManager(nsISupports** aResult)
+TabChild::GetMessageManager(nsIContentFrameMessageManager** aResult)
 {
-  nsCOMPtr<nsIContentFrameMessageManager> mm(mTabChildGlobal);
-  mm.forget(aResult);
-  return *aResult ? NS_OK : NS_ERROR_FAILURE;
+  if (mTabChildGlobal) {
+    NS_ADDREF(*aResult = mTabChildGlobal);
+    return NS_OK;
+  }
+  *aResult = nullptr;
+  return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 TabChild::GetWebBrowserChrome(nsIWebBrowserChrome3** aWebBrowserChrome)
 {
   NS_IF_ADDREF(*aWebBrowserChrome = mWebBrowserChrome);
   return NS_OK;
 }
@@ -3472,28 +3468,33 @@ TabChild::BeforeUnloadRemoved()
 
 mozilla::dom::TabGroup*
 TabChild::TabGroup()
 {
   return mTabGroup;
 }
 
 TabChildGlobal::TabChildGlobal(TabChild* aTabChild)
-: ContentFrameMessageManager(new nsFrameMessageManager(aTabChild)),
-  mTabChild(aTabChild)
+: mTabChild(aTabChild)
 {
+  SetIsNotDOMBinding();
 }
 
 TabChildGlobal::~TabChildGlobal()
 {
 }
 
 void
 TabChildGlobal::Init()
 {
+  NS_ASSERTION(!mMessageManager, "Re-initializing?!?");
+  mMessageManager = new nsFrameMessageManager(mTabChild,
+                                              nullptr,
+                                              MM_CHILD);
+
   TelemetryScrollProbe::Create(this);
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(TabChildGlobal)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TabChildGlobal,
                                                 DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager);
@@ -3511,117 +3512,80 @@ 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 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();
+  return mMessageManager ? mMessageManager->MarkForCC() : false;
 }
 
 NS_IMETHODIMP
 TabChildGlobal::GetContent(mozIDOMWindowProxy** aContent)
 {
-  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();
+  *aContent = nullptr;
+  if (!mTabChild)
+    return NS_ERROR_NULL_POINTER;
+  nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(mTabChild->WebNavigation());
+  window.forget(aContent);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 TabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
 {
-  ErrorResult rv;
-  *aDocShell = GetDocShell(rv).take();
-  return rv.StealNSResult();
-}
-
-already_AddRefed<nsIEventTarget>
-TabChildGlobal::GetTabEventTarget()
-{
-  nsCOMPtr<nsIEventTarget> target = EventTargetFor(TaskCategory::Other);
-  return target.forget();
+  *aDocShell = nullptr;
+  if (!mTabChild)
+    return NS_ERROR_NULL_POINTER;
+  nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mTabChild->WebNavigation());
+  docShell.swap(*aDocShell);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 TabChildGlobal::GetTabEventTarget(nsIEventTarget** aTarget)
 {
-  *aTarget = GetTabEventTarget().take();
+  nsCOMPtr<nsIEventTarget> target = EventTargetFor(TaskCategory::Other);
+  target.forget(aTarget);
   return NS_OK;
 }
 
 nsIPrincipal*
 TabChildGlobal::GetPrincipal()
 {
   if (!mTabChild)
     return nullptr;
   return mTabChild->GetPrincipal();
 }
 
 JSObject*
 TabChildGlobal::GetGlobalJSObject()
 {
   NS_ENSURE_TRUE(mTabChild, nullptr);
-  return GetWrapper();
+  return mTabChild->GetGlobal();
 }
 
 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,17 +2,16 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef 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"
@@ -74,67 +73,106 @@ struct AutoCacheNativeKeyCommands;
 namespace dom {
 
 class TabChild;
 class TabGroup;
 class ClonedMessageData;
 class CoalescedMouseData;
 class CoalescedWheelData;
 
-class TabChildGlobal : public ContentFrameMessageManager,
+class TabChildGlobal : public DOMEventTargetHelper,
                        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_DECL_NSICONTENTFRAMEMESSAGEMANAGER
+  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);
+  }
 
   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
 {
@@ -159,23 +197,16 @@ 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;
@@ -274,21 +305,16 @@ public:
   NS_DECL_NSITABCHILD
   NS_DECL_NSIOBSERVER
   NS_DECL_NSITOOLTIPLISTENER
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(TabChild, TabChildBase)
 
   FORWARD_SHMEM_ALLOCATOR_TO(PBrowserChild)
 
-  nsIContentFrameMessageManager* GetMessageManager()
-  {
-    return mTabChildGlobal;
-  }
-
   /**
    * MessageManagerCallback methods that we override.
    */
   virtual bool DoSendBlockingMessage(JSContext* aCx,
                                      const nsAString& aMessage,
                                      StructuredCloneData& aData,
                                      JS::Handle<JSObject *> aCpows,
                                      nsIPrincipal* aPrincipal,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -8,17 +8,16 @@
 
 #include "TabParent.h"
 
 #ifdef ACCESSIBILITY
 #include "mozilla/a11y/DocAccessibleParent.h"
 #include "nsAccessibilityService.h"
 #endif
 #include "mozilla/BrowserElementParent.h"
-#include "mozilla/dom/ChromeMessageSender.h"
 #include "mozilla/dom/ContentBridgeParent.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/DataTransferItemList.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/indexedDB/ActorsParent.h"
 #include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/PaymentRequestParent.h"
--- a/dom/ipc/nsIContentChild.cpp
+++ b/dom/ipc/nsIContentChild.cpp
@@ -2,17 +2,16 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIContentChild.h"
 
 #include "mozilla/dom/ContentChild.h"
-#include "mozilla/dom/ChildProcessMessageManager.h"
 #include "mozilla/dom/DOMTypes.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/TabGroup.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
 #include "mozilla/ipc/FileDescriptorSetChild.h"
 #include "mozilla/ipc/InputStreamUtils.h"
--- a/dom/ipc/nsIContentParent.cpp
+++ b/dom/ipc/nsIContentParent.cpp
@@ -3,33 +3,33 @@
 /* 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 "nsIContentParent.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/File.h"
-#include "mozilla/dom/ChromeMessageSender.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ContentBridgeParent.h"
 #include "mozilla/dom/ContentProcessManager.h"
 #include "mozilla/dom/PTabContext.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/dom/ipc/IPCBlobInputStreamParent.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/ipc/FileDescriptorSetParent.h"
 #include "mozilla/ipc/PFileDescriptorSetParent.h"
 #include "mozilla/ipc/IPCStreamAlloc.h"
 #include "mozilla/ipc/IPCStreamDestination.h"
 #include "mozilla/ipc/IPCStreamSource.h"
 #include "mozilla/Unused.h"
 
+#include "nsFrameMessageManager.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsPrintfCString.h"
 #include "xpcpublic.h"
 
 using namespace mozilla::jsipc;
 
 // XXX need another bug to move this to a common header.
 #ifdef DISABLE_ASSERTS_FOR_FUZZING
--- a/dom/ipc/nsIContentParent.h
+++ b/dom/ipc/nsIContentParent.h
@@ -39,17 +39,16 @@ class PParentToChildStreamParent;
 class PIPCBlobInputStreamParent;
 }
 
 namespace dom {
 
 class Blob;
 class BlobConstructorParams;
 class BlobImpl;
-class ChromeMessageSender;
 class ContentParent;
 class ContentBridgeParent;
 class IPCTabContext;
 class PBrowserParent;
 
 class nsIContentParent : public nsISupports
                        , public mozilla::dom::ipc::MessageManagerCallback
                        , public CPOWManagerGetter
@@ -84,17 +83,17 @@ public:
   virtual bool IsContentParent() const { return false; }
 
   ContentParent* AsContentParent();
 
   virtual bool IsContentBridgeParent() const { return false; }
 
   ContentBridgeParent* AsContentBridgeParent();
 
-  mozilla::dom::ChromeMessageSender* GetMessageManager() const { return mMessageManager; }
+  nsFrameMessageManager* GetMessageManager() const { return mMessageManager; }
 
   virtual bool SendActivate(PBrowserParent* aTab) = 0;
 
   virtual bool SendDeactivate(PBrowserParent* aTab) = 0;
 
   virtual int32_t Pid() const = 0;
 
   virtual mozilla::ipc::PParentToChildStreamParent*
@@ -157,17 +156,17 @@ protected: // IPDL methods
                                                  const IPC::Principal& aPrincipal,
                                                  nsTArray<ipc::StructuredCloneData>* aRetvals);
   virtual mozilla::ipc::IPCResult RecvAsyncMessage(const nsString& aMsg,
                                                    InfallibleTArray<jsipc::CpowEntry>&& aCpows,
                                                    const IPC::Principal& aPrincipal,
                                                    const ClonedMessageData& aData);
 
 protected: // members
-  RefPtr<mozilla::dom::ChromeMessageSender> mMessageManager;
+  RefPtr<nsFrameMessageManager> mMessageManager;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIContentParent, NS_ICONTENTPARENT_IID)
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_nsIContentParent_h */
--- a/dom/ipc/remote-test.js
+++ b/dom/ipc/remote-test.js
@@ -1,16 +1,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/. */
 
 dump("Loading remote script!\n");
 dump(content + "\n");
 
-var cpm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService();
+var cpm = Cc["@mozilla.org/childprocessmessagemanager;1"]
+            .getService(Components.interfaces.nsISyncMessageSender);
 cpm.addMessageListener("cpm-async",
   function(m) {
     cpm.sendSyncMessage("ppm-sync");
     dump(content.document.documentElement);
     cpm.sendAsyncMessage("ppm-async");
   });
 
 var dshell = content.QueryInterface(Ci.nsIInterfaceRequestor)
--- a/dom/ipc/test.xul
+++ b/dom/ipc/test.xul
@@ -80,21 +80,21 @@
     function closeWindow() {
       window.close();
     }
 
     function initRemoteFrameScript() {
       // 1. Test that loading a script works, and that accessing process level mm and
       //     global mm works.
       var ppm = Components.classes["@mozilla.org/parentprocessmessagemanager;1"]
-                          .getService();
+                          .getService(Components.interfaces.nsIMessageBroadcaster);
       var gm = Components.classes["@mozilla.org/globalmessagemanager;1"]
-                         .getService();
+                         .getService(Components.interfaces.nsIMessageBroadcaster);
       var cpm = Components.classes["@mozilla.org/childprocessmessagemanager;1"]
-                          .getService();
+                            .getService(Components.interfaces.nsISyncMessageSender);
 
       if (ppm.childCount != 2) {
         alert("Should have two child processes!");
       }
       var childprocessmm = ppm.getChildAt(1); // 0 is the in-process child process mm
       
       childprocessmm.addMessageListener("ppm-sync",
         function(m) {
--- a/dom/ipc/tests/test_blob_sliced_from_child_process.html
+++ b/dom/ipc/tests/test_blob_sliced_from_child_process.html
@@ -48,37 +48,37 @@ function parentFrameScript(mm) {
   const sliceText = "an";
 
   let receivedBlob = false;
   let receivedSlice = false;
 
   let finishedTestingBlob = false;
   let finishedTestingSlice = false;
 
-  mm.addMessageListener(messageName, SpecialPowers.wrapCallback(function(message) {
+  mm.addMessageListener(messageName, function(message) {
     if ("blob" in message.data) {
       is(receivedBlob, false, "Have not yet received Blob");
       is(receivedSlice, false, "Have not yet received Slice");
       is(finishedTestingBlob, false, "Have not yet finished testing Blob");
       is(finishedTestingSlice, false, "Have not yet finished testing Slice");
 
       receivedBlob = true;
 
       let blob = message.data.blob;
 
-      ok(SpecialPowers.call_Instanceof(blob, Blob), "Received a Blob");
+      ok(blob instanceof Blob, "Received a Blob");
       is(blob.size, blobText.length, "Blob has correct size");
       is(blob.type, blobType, "Blob has correct type");
 
       let slice = blob.slice(blobText.length -
                                 blobData[blobData.length - 1].length,
                               blob.size,
                               blobType);
 
-      ok(SpecialPowers.call_Instanceof(slice, Blob), "Slice returned a Blob");
+      ok(slice instanceof Blob, "Slice returned a Blob");
       is(slice.size,
           blobData[blobData.length - 1].length,
           "Slice has correct size");
       is(slice.type, blobType, "Slice has correct type");
 
       let reader = new FileReader();
       reader.onload = function() {
         is(reader.result,
@@ -86,63 +86,63 @@ function parentFrameScript(mm) {
             "Slice has correct data");
 
         finishedTestingBlob = true;
 
         if (finishedTestingSlice) {
           SimpleTest.finish();
         }
       };
-      SpecialPowers.wrap(reader).readAsText(slice);
+      reader.readAsText(slice);
 
       return;
     }
 
     if ("slice" in message.data) {
       is(receivedBlob, true, "Already received Blob");
       is(receivedSlice, false, "Have not yet received Slice");
       is(finishedTestingSlice, false, "Have not yet finished testing Slice");
 
       receivedSlice = true;
 
       let slice = message.data.slice;
 
-      ok(SpecialPowers.call_Instanceof(slice, Blob), "Received a Blob for slice");
+      ok(slice instanceof Blob, "Received a Blob for slice");
       is(slice.size, sliceText.length, "Slice has correct size");
       is(slice.type, blobType, "Slice has correct type");
 
       let reader = new FileReader();
       reader.onload = function() {
         is(reader.result, sliceText, "Slice has correct data");
 
         let slice2 = slice.slice(1, 2, blobType);
 
-        ok(SpecialPowers.call_Instanceof(slice2, Blob), "Slice returned a Blob");
+        ok(slice2 instanceof Blob, "Slice returned a Blob");
         is(slice2.size, 1, "Slice has correct size");
         is(slice2.type, blobType, "Slice has correct type");
 
         let reader2 = new FileReader();
         reader2.onload = function() {
           is(reader2.result, sliceText[1], "Slice has correct data");
 
           finishedTestingSlice = true;
 
           if (finishedTestingBlob) {
             SimpleTest.finish();
           }
         };
-        SpecialPowers.wrap(reader2).readAsText(slice2);
+        reader2.readAsText(slice2);
       };
-      SpecialPowers.wrap(reader).readAsText(slice);
+      reader.readAsText(slice);
 
       return;
     }
 
     ok(false, "Received a bad message: " + JSON.stringify(message.data));
-  }));
+  });
 
   mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")();",
                       false);
 }
 
 function setup() {
   info("Got load event");
 
--- a/dom/ipc/tests/test_blob_sliced_from_parent_process.html
+++ b/dom/ipc/tests/test_blob_sliced_from_parent_process.html
@@ -112,33 +112,33 @@ function parentFrameScript(mm) {
 
   function grabAndContinue(arg) {
     testGenerator.next(arg);
   }
 
   function* testSteps() {
     let slice = yield undefined;
 
-    ok(SpecialPowers.call_Instanceof(slice, Blob), "Received a Blob");
+    ok(slice instanceof Blob, "Received a Blob");
     is(slice.size, sliceText.length, "Slice has correct size");
     is(slice.type, blobType, "Slice has correct type");
 
     let reader = new FileReader();
     reader.onload = grabAndContinue;
-    SpecialPowers.wrap(reader).readAsText(slice);
+    reader.readAsText(slice);
     yield undefined;
 
     is(reader.result, sliceText, "Slice has correct data");
     SimpleTest.finish();
   }
 
   let testGenerator = testSteps();
   testGenerator.next();
 
-  mm.addMessageListener(messageName, SpecialPowers.wrapCallback(function(message) {
+  mm.addMessageListener(messageName, function(message) {
     let data = message.data;
     switch (data.op) {
       case "info": {
         info(data.msg);
         break;
       }
 
       case "ok": {
@@ -151,17 +151,17 @@ function parentFrameScript(mm) {
         break;
       }
 
       default: {
         ok(false, "Unknown op: " + data.op);
         SimpleTest.finish();
       }
     }
-  }));
+  });
 
   mm.loadFrameScript("data:,(" + childFrameScript.toString() + ")();",
                       false);
 
   let blob = new Blob(blobData, { type: blobType });
   mm.sendAsyncMessage(messageName, blob);
 }
 
--- a/dom/ipc/tests/test_bug1086684.html
+++ b/dom/ipc/tests/test_bug1086684.html
@@ -47,18 +47,17 @@
     let test;
     function* testStructure(mm) {
       let value;
 
       function testDone(msg) {
         test.next(msg.data.value);
       }
 
-      mm.addMessageListener("testBug1086684:childDone",
-                            SpecialPowers.wrapCallback(testDone));
+      mm.addMessageListener("testBug1086684:childDone", testDone);
 
       let blob = new Blob([]);
       let file = new File([blob], "helloworld.txt", { type: "text/plain" });
 
       mm.sendAsyncMessage("testBug1086684:parentReady", { file });
       value = yield;
 
       // Note that the "helloworld.txt" passed in above doesn't affect the
--- a/dom/ipc/tests/test_cpow_cookies.html
+++ b/dom/ipc/tests/test_cpow_cookies.html
@@ -35,18 +35,17 @@
     let test;
     function* testStructure(mm) {
       let lastResult;
 
       function testDone(msg) {
         test.next(msg.data);
       }
 
-      mm.addMessageListener("testCPOWCookies:test1Finished",
-                            SpecialPowers.wrapCallback(testDone));
+      mm.addMessageListener("testCPOWCookies:test1Finished", testDone);
 
       mm.sendAsyncMessage("testCPOWCookies:test1", {});
       lastResult = yield;
       ok(lastResult.pass, "got the right answer and didn't crash");
 
       SimpleTest.finish();
     }
 
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -63,18 +63,19 @@ class GlobalPCList {
     this._nextId = 1;
     Services.obs.addObserver(this, "inner-window-destroyed", true);
     Services.obs.addObserver(this, "profile-change-net-teardown", true);
     Services.obs.addObserver(this, "network:offline-about-to-go-offline", true);
     Services.obs.addObserver(this, "network:offline-status-changed", true);
     Services.obs.addObserver(this, "gmp-plugin-crash", true);
     Services.obs.addObserver(this, "PeerConnection:response:allow", true);
     Services.obs.addObserver(this, "PeerConnection:response:deny", true);
-    if (Services.cpmm) {
-      Services.cpmm.addMessageListener("gmp-plugin-crash", this);
+    if (Cc["@mozilla.org/childprocessmessagemanager;1"]) {
+      let mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
+      mm.addMessageListener("gmp-plugin-crash", this);
     }
   }
 
   notifyLifecycleObservers(pc, type) {
     for (var key of Object.keys(this._lifecycleobservers)) {
       this._lifecycleobservers[key](pc, pc._winID, type);
     }
   }
--- a/dom/notification/NotificationDB.jsm
+++ b/dom/notification/NotificationDB.jsm
@@ -10,16 +10,20 @@ const DEBUG = false;
 function debug(s) { dump("-*- NotificationDB component: " + s + "\n"); }
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/osfile.jsm");
 
 ChromeUtils.defineModuleGetter(this, "Services",
                                "resource://gre/modules/Services.jsm");
 
+XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
+                                   "@mozilla.org/parentprocessmessagemanager;1",
+                                   "nsIMessageListenerManager");
+
 XPCOMUtils.defineLazyServiceGetter(this, "notificationStorage",
                                    "@mozilla.org/notificationStorage;1",
                                    "nsINotificationStorage");
 
 const NOTIFICATION_STORE_DIR = OS.Constants.Path.profileDir;
 const NOTIFICATION_STORE_PATH =
         OS.Path.join(NOTIFICATION_STORE_DIR, "notificationstore.json");
 
@@ -47,23 +51,23 @@ var NotificationDB = {
     this.runningTask = null;
 
     Services.obs.addObserver(this, "xpcom-shutdown");
     this.registerListeners();
   },
 
   registerListeners: function() {
     for (let message of kMessages) {
-      Services.ppmm.addMessageListener(message, this);
+      ppmm.addMessageListener(message, this);
     }
   },
 
   unregisterListeners: function() {
     for (let message of kMessages) {
-      Services.ppmm.removeMessageListener(message, this);
+      ppmm.removeMessageListener(message, this);
     }
   },
 
   observe: function(aSubject, aTopic, aData) {
     if (DEBUG) debug("Topic: " + aTopic);
     if (aTopic == "xpcom-shutdown") {
       this._shutdownInProgress = true;
       Services.obs.removeObserver(this, "xpcom-shutdown");
--- a/dom/notification/NotificationStorage.js
+++ b/dom/notification/NotificationStorage.js
@@ -10,16 +10,20 @@ function debug(s) { dump("-*- Notificati
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const NOTIFICATIONSTORAGE_CID = "{37f819b0-0b5c-11e3-8ffd-0800200c9a66}";
 const NOTIFICATIONSTORAGE_CONTRACTID = "@mozilla.org/notificationStorage;1";
 
 ChromeUtils.defineModuleGetter(this, "Services",
                                "resource://gre/modules/Services.jsm");
 
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsIMessageSender");
+
 const kMessageNotificationGetAllOk = "Notification:GetAll:Return:OK";
 const kMessageNotificationGetAllKo = "Notification:GetAll:Return:KO";
 const kMessageNotificationSaveKo   = "Notification:Save:Return:KO";
 const kMessageNotificationDeleteKo = "Notification:Delete:Return:KO";
 
 const kMessages = [
   kMessageNotificationGetAllOk,
   kMessageNotificationGetAllKo,
@@ -41,23 +45,23 @@ function NotificationStorage() {
   // Register for message listeners.
   this.registerListeners();
 }
 
 NotificationStorage.prototype = {
 
   registerListeners: function() {
     for (let message of kMessages) {
-      Services.cpmm.addMessageListener(message, this);
+      cpmm.addMessageListener(message, this);
     }
   },
 
   unregisterListeners: function() {
     for (let message of kMessages) {
-      Services.cpmm.removeMessageListener(message, this);
+      cpmm.removeMessageListener(message, this);
     }
   },
 
   observe: function(aSubject, aTopic, aData) {
     if (DEBUG) debug("Topic: " + aTopic);
     if (aTopic === "xpcom-shutdown") {
       Services.obs.removeObserver(this, "xpcom-shutdown");
       this.unregisterListeners();
@@ -95,17 +99,17 @@ NotificationStorage.prototype = {
         var oldNotification = this._byTag[origin][tag];
         delete this._notifications[oldNotification.id];
       }
 
       this._byTag[origin][tag] = notification;
     };
 
     if (serviceWorkerRegistrationScope) {
-      Services.cpmm.sendAsyncMessage("Notification:Save", {
+      cpmm.sendAsyncMessage("Notification:Save", {
         origin: origin,
         notification: notification
       });
     }
   },
 
   get: function(origin, tag, callback) {
     if (DEBUG) { debug("GET: " + origin + " " + tag); }
@@ -140,17 +144,17 @@ NotificationStorage.prototype = {
     var notification = this._notifications[id];
     if (notification) {
       if (notification.tag) {
         delete this._byTag[origin][notification.tag];
       }
       delete this._notifications[id];
     }
 
-    Services.cpmm.sendAsyncMessage("Notification:Delete", {
+    cpmm.sendAsyncMessage("Notification:Delete", {
       origin: origin,
       id: id
     });
   },
 
   receiveMessage: function(message) {
     var request = this._requests[message.data.requestID];
 
@@ -185,17 +189,17 @@ NotificationStorage.prototype = {
   _fetchFromDB: function(origin, tag, callback) {
     var request = {
       origin: origin,
       tag: tag,
       callback: callback
     };
     var requestID = this._requestCount++;
     this._requests[requestID] = request;
-    Services.cpmm.sendAsyncMessage("Notification:GetAll", {
+    cpmm.sendAsyncMessage("Notification:GetAll", {
       origin: origin,
       requestID: requestID
     });
   },
 
   _fetchFromCache: function(origin, tag, callback) {
     var notifications = [];
     // If a tag was specified and we have a notification
--- a/dom/notification/test/unit/common_test_notificationdb.js
+++ b/dom/notification/test/unit/common_test_notificationdb.js
@@ -1,13 +1,17 @@
 "use strict";
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsIMessageSender");
+
 function getNotificationObject(app, id, tag) {
   return {
     origin: "https://" + app + ".gaiamobile.org/",
     id: id,
     title: app + "Notification:" + Date.now(),
     dir: "auto",
     lang: "",
     body: app + " notification body",
@@ -27,26 +31,26 @@ function startNotificationDB() {
   ChromeUtils.import("resource://gre/modules/NotificationDB.jsm");
 }
 
 // Helper function to add a listener, send message and treat the reply
 function addAndSend(msg, reply, callback, payload, runNext = true) {
   let handler = {
     receiveMessage: function(message) {
       if (message.name === reply) {
-        Services.cpmm.removeMessageListener(reply, handler);
+        cpmm.removeMessageListener(reply, handler);
         callback(message);
         if (runNext) {
           run_next_test();
         }
       }
     }
   };
-  Services.cpmm.addMessageListener(reply, handler);
-  Services.cpmm.sendAsyncMessage(msg, payload);
+  cpmm.addMessageListener(reply, handler);
+  cpmm.sendAsyncMessage(msg, payload);
 }
 
 // helper fonction, comparing two notifications
 function compareNotification(notif1, notif2) {
   // retrieved notification should be the second one sent
   for (let prop in notif1) {
     // compare each property
     Assert.equal(notif1[prop], notif2[prop]);
--- a/dom/notification/test/unit/test_notificationdb.js
+++ b/dom/notification/test/unit/test_notificationdb.js
@@ -159,36 +159,36 @@ add_test(function test_send_two_get_one(
     getNotificationObject("system", "{f271f9ee-3955-4c10-b1f2-af552fb270ee}", tag);
   let systemNotification2 =
     getNotificationObject("system", "{8ef9a628-f0f4-44b4-820d-c117573c33e3}", tag);
 
   let msgGetReply = "Notification:GetAll:Return:OK";
   let msgGetNotifHandler = {
     receiveMessage: function(message) {
       if (message.name === msgGetReply) {
-        Services.cpmm.removeMessageListener(msgGetReply, msgGetNotifHandler);
+        cpmm.removeMessageListener(msgGetReply, msgGetNotifHandler);
         let notifications = message.data.notifications;
         // same tag, so replaced
         Assert.equal(1, notifications.length);
         // compare the content
         compareNotification(systemNotification2, notifications[0]);
         run_next_test();
       }
     }
   };
 
-  Services.cpmm.addMessageListener(msgGetReply, msgGetNotifHandler);
+  cpmm.addMessageListener(msgGetReply, msgGetNotifHandler);
 
   let msgSaveReply = "Notification:Save:Return:OK";
   let msgSaveCalls = 0;
   let msgSaveHandler = function(message) {
     msgSaveCalls++;
     // Once both request have been sent, trigger getall
     if (msgSaveCalls === 2) {
-      Services.cpmm.sendAsyncMessage("Notification:GetAll", {
+      cpmm.sendAsyncMessage("Notification:GetAll", {
         origin: systemNotification1.origin,
         requestID: message.data.requestID + 2 // 12, 13
       });
     }
   };
 
   addAndSend("Notification:Save", msgSaveReply, msgSaveHandler, {
     origin: systemNotification1.origin,
@@ -242,57 +242,57 @@ add_test(function test_send_two_get_two(
 
         // first call should be system notification
         if (msgGetCalls === 1) {
           compareNotification(systemNotification1, notifications[0]);
         }
 
         // second and last call should be calendar notification
         if (msgGetCalls === 2) {
-          Services.cpmm.removeMessageListener(msgGetReply, msgGetHandler);
+          cpmm.removeMessageListener(msgGetReply, msgGetHandler);
           compareNotification(calendarNotification2, notifications[0]);
           run_next_test();
         }
       }
     }
   };
-  Services.cpmm.addMessageListener(msgGetReply, msgGetHandler);
+  cpmm.addMessageListener(msgGetReply, msgGetHandler);
 
   let msgSaveReply = "Notification:Save:Return:OK";
   let msgSaveCalls = 0;
   let msgSaveHandler = {
     receiveMessage: function(message) {
       if (message.name === msgSaveReply) {
         msgSaveCalls++;
         if (msgSaveCalls === 2) {
-          Services.cpmm.removeMessageListener(msgSaveReply, msgSaveHandler);
+          cpmm.removeMessageListener(msgSaveReply, msgSaveHandler);
 
           // Trigger getall for each origin
-          Services.cpmm.sendAsyncMessage("Notification:GetAll", {
+          cpmm.sendAsyncMessage("Notification:GetAll", {
             origin: systemNotification1.origin,
             requestID: message.data.requestID + 1 // 22
           });
 
-          Services.cpmm.sendAsyncMessage("Notification:GetAll", {
+          cpmm.sendAsyncMessage("Notification:GetAll", {
             origin: calendarNotification2.origin,
             requestID: message.data.requestID + 2 // 23
           });
         }
       }
     }
   };
-  Services.cpmm.addMessageListener(msgSaveReply, msgSaveHandler);
+  cpmm.addMessageListener(msgSaveReply, msgSaveHandler);
 
-  Services.cpmm.sendAsyncMessage("Notification:Save", {
+  cpmm.sendAsyncMessage("Notification:Save", {
     origin: systemNotification1.origin,
     notification: systemNotification1,
     requestID: requestID // 20
   });
 
-  Services.cpmm.sendAsyncMessage("Notification:Save", {
+  cpmm.sendAsyncMessage("Notification:Save", {
     origin: calendarNotification2.origin,
     notification: calendarNotification2,
     requestID: (requestID + 1) // 21
   });
 });
 
 // Cleanup previous notification
 add_test(function test_delete_previous() {
--- a/dom/presentation/tests/mochitest/test_presentation_dc_receiver_oop.html
+++ b/dom/presentation/tests/mochitest/test_presentation_dc_receiver_oop.html
@@ -125,27 +125,27 @@ function setup() {
     gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
       gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
       is(aReason, SpecialPowers.Cr.NS_OK, "The control channel is closed normally.");
     });
 
     var mm = SpecialPowers.getBrowserFrameMessageManager(receiverIframe);
     mm.addMessageListener('check-navigator', function checknavigatorHandler(aSuccess) {
       mm.removeMessageListener('check-navigator', checknavigatorHandler);
-      ok(SpecialPowers.wrap(aSuccess).data.data, "buildDataChannel get correct window object");
+      ok(aSuccess.data.data, "buildDataChannel get correct window object");
     });
 
     mm.addMessageListener('data-transport-notification-enabled', function dataTransportNotificationEnabledHandler() {
       mm.removeMessageListener('data-transport-notification-enabled', dataTransportNotificationEnabledHandler);
       info("Data notification is enabled for data transport channel.");
     });
 
     mm.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
       mm.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
-      is(SpecialPowers.wrap(aReason).data.data, SpecialPowers.Cr.NS_OK, "The data transport should be closed normally.");
+      is(aReason.data.data, SpecialPowers.Cr.NS_OK, "The data transport should be closed normally.");
     });
 
     aResolve();
   });
 }
 
 function testIncomingSessionRequest() {
   return new Promise(function(aResolve, aReject) {
--- a/dom/push/PushComponents.js
+++ b/dom/push/PushComponents.js
@@ -112,17 +112,17 @@ PushServiceBase.prototype = {
  */
 function PushServiceParent() {
   PushServiceBase.call(this);
 }
 
 PushServiceParent.prototype = Object.create(PushServiceBase.prototype);
 
 XPCOMUtils.defineLazyServiceGetter(PushServiceParent.prototype, "_mm",
-  "@mozilla.org/parentprocessmessagemanager;1", "nsISupports");
+  "@mozilla.org/parentprocessmessagemanager;1", "nsIMessageBroadcaster");
 
 Object.assign(PushServiceParent.prototype, {
   _xpcom_factory: XPCOMUtils.generateSingletonFactory(PushServiceParent),
 
   _messages: [
     "Push:Register",
     "Push:Registration",
     "Push:Unregister",
@@ -207,23 +207,24 @@ Object.assign(PushServiceParent.prototyp
     if (name === "Push:NotificationForOriginClosed") {
       this.notificationForOriginClosed(data);
       return;
     }
     if (name === "Push:ReportError") {
       this.reportDeliveryError(data.messageId, data.reason);
       return;
     }
+    let sender = target.QueryInterface(Ci.nsIMessageSender);
     return this._handleRequest(name, principal, data).then(result => {
-      target.sendAsyncMessage(this._getResponseName(name, "OK"), {
+      sender.sendAsyncMessage(this._getResponseName(name, "OK"), {
         requestID: data.requestID,
         result: result
       });
     }, error => {
-      target.sendAsyncMessage(this._getResponseName(name, "KO"), {
+      sender.sendAsyncMessage(this._getResponseName(name, "KO"), {
         requestID: data.requestID,
         result: error.result,
       });
     }).catch(Cu.reportError);
   },
 
   _handleReady() {
     this.service.init();
@@ -314,17 +315,17 @@ function PushServiceContent() {
   this._requests = new Map();
   this._requestId = 0;
 }
 
 PushServiceContent.prototype = Object.create(PushServiceBase.prototype);
 
 XPCOMUtils.defineLazyServiceGetter(PushServiceContent.prototype,
   "_mm", "@mozilla.org/childprocessmessagemanager;1",
-  "nsISupports");
+  "nsISyncMessageSender");
 
 Object.assign(PushServiceContent.prototype, {
   _xpcom_factory: XPCOMUtils.generateSingletonFactory(PushServiceContent),
 
   _messages: [
     "PushService:Register:OK",
     "PushService:Register:KO",
     "PushService:Registration:OK",
--- a/dom/quota/test/head.js
+++ b/dom/quota/test/head.js
@@ -75,24 +75,21 @@ function dismissNotification(popup, win)
   executeSoon(function () {
     EventUtils.synthesizeKey("VK_ESCAPE", {}, win);
   });
 }
 
 function waitForMessage(aMessage, browser)
 {
   return new Promise((resolve, reject) => {
-    // When contentScript runs, "this" is a ContentFrameMessageManager (so that's where
-    // addEventListener will add the listener), but the non-bubbling "message" event is
-    // sent to the Window involved, so we need a capturing listener.
     function contentScript() {
       addEventListener("message", function(event) {
         sendAsyncMessage("testLocal:persisted",
           {persisted: event.data});
-      }, {once: true, capture: true}, true);
+      }, {once: true}, true);
     }
 
     let script = "data:,(" + contentScript.toString() + ")();";
 
     let mm = browser.selectedBrowser.messageManager;
 
     mm.addMessageListener("testLocal:persisted", function listener(msg) {
       mm.removeMessageListener("testLocal:persisted", listener);
--- a/dom/webidl/FrameLoader.webidl
+++ b/dom/webidl/FrameLoader.webidl
@@ -3,16 +3,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/.
  */
 
 interface LoadContext;
 interface TabParent;
 interface URI;
 interface nsIDocShell;
+interface nsIMessageSender;
 interface nsIPrintSettings;
 interface nsIWebBrowserPersistDocumentReceiver;
 interface nsIWebProgressListener;
 
 [ChromeOnly]
 interface FrameLoader {
   /**
    * Get the docshell from the frame loader.
@@ -98,17 +99,17 @@ interface FrameLoader {
 
   /**
    * Activate event forwarding from client (remote frame) to parent.
    */
   [Throws]
   void activateFrameEvent(DOMString aType, boolean capture);
 
   // Note, when frameloaders are swapped, also messageManagers are swapped.
-  readonly attribute MessageSender? messageManager;
+  readonly attribute nsIMessageSender? messageManager;
 
   /**
    * Request that the next time a remote layer transaction has been
    * received by the Compositor, a MozAfterRemoteFrame event be sent
    * to the window.
    */
   [Throws]
   void requestNotifyAfterRemotePaint();
--- a/dom/webidl/LegacyQueryInterface.webidl
+++ b/dom/webidl/LegacyQueryInterface.webidl
@@ -17,22 +17,17 @@ interface LegacyQueryInterface {
   [Exposed=Window]
   nsISupports queryInterface(IID iid);
 };
 
 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;
deleted file mode 100644
--- a/dom/webidl/MessageManager.webidl
+++ /dev/null
@@ -1,378 +0,0 @@
-/* -*- 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.
-   */
-  required nsISupports target;
-
-  /**
-   * Message name.
-   */
-  required DOMString name;
-
-  required boolean sync;
-
-  /**
-   * Structured clone of the sent message data
-   */
-  any data = null;
-
-  /**
-   * Same as .data, deprecated.
-   */
-  any json = null;
-
-  /**
-   * Named table of jsvals/objects, or null.
-   */
-  required object objects;
-
-  sequence<MessagePort> ports;
-
-  /**
-   * Principal for the window app.
-   */
-  required Principal? principal;
-
-  MozFrameLoader targetFrameLoader;
-};
-
-callback interface MessageListener
-{
-  /**
-   * Each listener is invoked with its own copy of the message
-   * parameter.
-   *
-   * When the listener is called, 'this' value is the target of the message.
-   *
-   * If the message is synchronous, the possible return value is
-   * returned as JSON (will be changed to use structured clones).
-   * When there are multiple listeners to sync messages, each
-   * listener's return value is sent back as an array.  |undefined|
-   * return values show up as undefined values in the array.
-   */
-  any receiveMessage(optional ReceiveMessageArgument argument);
-};
-
-[ChromeOnly]
-interface MessageListenerManager
-{
-  /**
-   * Register |listener| to receive |messageName|.  All listener
-   * callbacks for a particular message are invoked when that message
-   * is received.
-   *
-   * The message manager holds a strong ref to |listener|.
-   *
-   * If the same listener registers twice for the same message, the
-   * second registration is ignored.
-   *
-   * Pass true for listenWhenClosed if you want to receive messages
-   * during the short period after a frame has been removed from the
-   * DOM and before its frame script has finished unloading. This
-   * parameter only has an effect for frame message managers in
-   * the main process. Default is false.
-   */
-  [Throws]
-  void addMessageListener(DOMString messageName,
-                          MessageListener listener,
-                          optional boolean listenWhenClosed = false);
-
-  /**
-   * Undo an |addMessageListener| call -- that is, calling this causes us to no
-   * longer invoke |listener| when |messageName| is received.
-   *
-   * removeMessageListener does not remove a message listener added via
-   * addWeakMessageListener; use removeWeakMessageListener for that.
-   */
-  [Throws]
-  void removeMessageListener(DOMString messageName,
-                             MessageListener listener);
-
-  /**
-   * This is just like addMessageListener, except the message manager holds a
-   * weak ref to |listener|.
-   *
-   * If you have two weak message listeners for the same message, they may be
-   * called in any order.
-   */
-  [Throws]
-  void addWeakMessageListener(DOMString messageName,
-                              MessageListener listener);
-
-  /**
-   * This undoes an |addWeakMessageListener| call.
-   */
-  [Throws]
-  void removeWeakMessageListener(DOMString messageName,
-                                 MessageListener listener);
-};
-
-[ChromeOnly]
-interface MessageSender : MessageListenerManager
-{
-  /**
-   * Send |messageName| and |obj| to the "other side" of this message
-   * manager.  This invokes listeners who registered for
-   * |messageName|.
-   *
-   * See ReceiveMessageArgument for the format of the data delivered to listeners.
-   * @throws NS_ERROR_NOT_INITIALIZED if the sender is not initialized.  For
-   *         example, we will throw NS_ERROR_NOT_INITIALIZED if we try to send
-   *         a message to a cross-process frame but the other process has not
-   *         yet been set up.
-   * @throws NS_ERROR_FAILURE when the message receiver cannot be found.  For
-   *         example, we will throw NS_ERROR_FAILURE if we try to send a message
-   *         to a cross-process frame whose process has crashed.
-   */
-  [Throws]
-  void sendAsyncMessage(optional DOMString? messageName = null,
-                        optional any obj,
-                        optional object? objects = null,
-                        optional Principal? principal = null,
-                        optional any transfers);
-
-  /**
-   * For remote browsers there is always a corresponding process message
-   * manager. The intention of this attribute is to link leaf level frame
-   * message managers on the parent side with the corresponding process
-   * message managers (if there is one). For any other cases this property
-   * is null.
-   */
-  [Throws]
-  readonly attribute MessageSender? processMessageManager;
-
-  /**
-   * For remote browsers, this contains the remoteType of the content child.
-   * Otherwise, it is empty.
-   */
-  [Throws]
-  readonly attribute DOMString remoteType;
-};
-
-[ChromeOnly]
-interface SyncMessageSender : MessageSender
-{
-  /**
-   * Like |sendAsyncMessage()|, except blocks the sender until all
-   * listeners of the message have been invoked.  Returns an array
-   * containing return values from each listener invoked.
-   */
-  [Throws]
-  sequence<any> sendSyncMessage(optional DOMString? messageName = null,
-                                optional any obj,
-                                optional object? objects = null,
-                                optional Principal? principal = null);
-
-  /**
-   * Like |sendSyncMessage()|, except re-entrant. New RPC messages may be
-   * issued even if, earlier on the call stack, we are waiting for a reply
-   * to an earlier sendRpcMessage() call.
-   *
-   * Both sendSyncMessage and sendRpcMessage will block until a reply is
-   * received, but they may be temporarily interrupted to process an urgent
-   * incoming message (such as a CPOW request).
-   */
-  [Throws]
-  sequence<any> sendRpcMessage(optional DOMString? messageName = null,
-                               optional any obj,
-                               optional object? objects = null,
-                               optional Principal? principal = null);
-};
-
-[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.
-   */
-  [Throws]
-  void loadFrameScript(DOMString url, boolean allowDelayedLoad,
-                       optional boolean runInGlobalScope = false);
-
-  /**
-   * Removes |url| from the list of scripts which support delayed load.
-   */
-  void removeDelayedFrameScript(DOMString url);
-
-  /**
-   * Returns all delayed scripts that will be loaded once a (remote)
-   * frame becomes available. The return value is a list of pairs
-   * [<URL>, <WasLoadedInGlobalScope>].
-   */
-  [Throws]
-  sequence<sequence<any>> getDelayedFrameScripts();
-};
-
-[NoInterfaceObject]
-interface ProcessScriptLoader
-{
-  /**
-   * Load a script in the (possibly remote) process. |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.
-   */
-  [Throws]
-  void loadProcessScript(DOMString url, boolean allowDelayedLoad);
-
-  /**
-   * Removes |url| from the list of scripts which support delayed load.
-   */
-  void removeDelayedProcessScript(DOMString url);
-
-  /**
-   * Returns all delayed scripts that will be loaded once a (remote)
-   * frame becomes available. The return value is a list of pairs
-   * [<URL>, <WasLoadedInGlobalScope>].
-   */
-  [Throws]
-  sequence<sequence<any>> getDelayedProcessScripts();
-};
-
-[NoInterfaceObject]
-interface GlobalProcessScriptLoader : ProcessScriptLoader
-{
-  /**
-   * Allows the parent process to set the initial process data for
-   * new, not-yet-created child processes. This attribute should only
-   * be used by the global parent process message manager. When a new
-   * process is created, it gets a copy of this data (via structured
-   * cloning). It can access the data via the initialProcessData
-   * attribute of its childprocessmessagemanager.
-   *
-   * 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.
-   *
-   * WARNING: broadcasting messages can be very expensive and leak
-   * sensitive data.  Use with extreme caution.
-   */
-  [Throws]
-  void broadcastAsyncMessage(optional DOMString? messageName = null,
-                             optional any obj,
-                             optional object? objects = null);
-
-  /**
-   * Number of subordinate message managers.
-   */
-  readonly attribute unsigned long childCount;
-
-  /**
-   * Return a single subordinate message manager.
-   */
-  MessageListenerManager getChildAt(unsigned long aIndex);
-
-  /**
-   * Some processes are kept alive after their last tab/window are closed for testing
-   * (see dom.ipc.keepProcessesAlive). This function releases those.
-   */
-   void releaseCachedProcesses();
-};
-ChromeMessageBroadcaster implements GlobalProcessScriptLoader;
-ChromeMessageBroadcaster implements FrameScriptLoader;
-
-[ChromeOnly]
-interface ChromeMessageSender : MessageSender
-{
-};
-ChromeMessageSender implements ProcessScriptLoader;
-ChromeMessageSender implements FrameScriptLoader;
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -17,16 +17,17 @@
  * https://w3c.github.io/requestidlecallback/
  * https://webaudio.github.io/web-audio-api/#widl-Window-audioWorklet
  * https://drafts.css-houdini.org/css-paint-api-1/#dom-window-paintworklet
  */
 
 interface ApplicationCache;
 interface IID;
 interface nsIBrowserDOMWindow;
+interface nsIMessageBroadcaster;
 interface XULControllers;
 
 // http://www.whatwg.org/specs/web-apps/current-work/
 [PrimaryGlobal, LegacyUnenumerableNamedProperties, NeedResolve]
 /*sealed*/ interface Window : EventTarget {
   // the current browsing context
   [Unforgeable, Constant, StoreInSlot,
    CrossOriginReadable] readonly attribute Window window;
@@ -418,24 +419,24 @@ partial interface Window {
   /**
    * Notify a default button is loaded on a dialog or a wizard.
    * defaultButton is the default button.
    */
   [Throws, Func="nsGlobalWindowInner::IsPrivilegedChromeWindow"]
   void notifyDefaultButtonLoaded(Element defaultButton);
 
   [Throws, Func="nsGlobalWindowInner::IsPrivilegedChromeWindow"]
-  readonly attribute ChromeMessageBroadcaster messageManager;
+  readonly attribute nsIMessageBroadcaster messageManager;
 
   /**
    * Returns the message manager identified by the given group name that
    * manages all frame loaders belonging to that group.
    */
   [Throws, Func="nsGlobalWindowInner::IsPrivilegedChromeWindow"]
-  ChromeMessageBroadcaster getGroupMessageManager(DOMString aGroup);
+  nsIMessageBroadcaster getGroupMessageManager(DOMString aGroup);
 
   /**
    * On some operating systems, we must allow the window manager to
    * handle window dragging. This function tells the window manager to
    * start dragging the window. This function will fail unless called
    * while the left mouse button is held down, callers must check this.
    *
    * The optional panel argument should be set when moving a panel.
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -673,17 +673,16 @@ WEBIDL_FILES = [
     'MediaStreamError.webidl',
     'MediaStreamTrack.webidl',
     'MediaTrackConstraintSet.webidl',
     'MediaTrackSettings.webidl',
     'MediaTrackSupportedConstraints.webidl',
     'MenuBoxObject.webidl',
     'MessageChannel.webidl',
     'MessageEvent.webidl',
-    'MessageManager.webidl',
     'MessagePort.webidl',
     'MIDIAccess.webidl',
     'MIDIInput.webidl',
     'MIDIInputMap.webidl',
     'MIDIMessageEvent.webidl',
     'MIDIOptions.webidl',
     'MIDIOutput.webidl',
     'MIDIOutputMap.webidl',
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -21,17 +21,16 @@
 #include "WrapperFactory.h"
 #include "AccessCheck.h"
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMPrefs.h"
 #include "mozilla/dom/Exceptions.h"
 #include "mozilla/dom/Promise.h"
-#include "mozilla/dom/ResolveSystemBinding.h"
 
 #include "nsDOMMutationObserver.h"
 #include "nsICycleCollectorListener.h"
 #include "mozilla/XPTInterfaceInfoManager.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsScriptSecurityManager.h"
 #include "nsIPermissionManager.h"
@@ -557,20 +556,16 @@ InitClassesWithNewWrappedGlobal(JSContex
 {
     MOZ_ASSERT(aJSContext, "bad param");
     MOZ_ASSERT(aCOMObj, "bad param");
 
     // We pass null for the 'extra' pointer during global object creation, so
     // we need to have a principal.
     MOZ_ASSERT(aPrincipal);
 
-    if (!SystemBindingInitIds(aJSContext)) {
-      return NS_ERROR_FAILURE;
-    }
-
     InitGlobalObjectOptions(aOptions, aPrincipal);
 
     // Call into XPCWrappedNative to make a new global object, scope, and global
     // prototype.
     xpcObjectHelper helper(aCOMObj);
     MOZ_ASSERT(helper.GetScriptableFlags() & XPC_SCRIPTABLE_IS_GLOBAL_OBJECT);
     RefPtr<XPCWrappedNative> wrappedGlobal;
     nsresult rv =
--- a/services/sync/tps/extensions/tps/resource/modules/tabs.jsm
+++ b/services/sync/tps/extensions/tps/resource/modules/tabs.jsm
@@ -11,18 +11,18 @@ const EXPORTED_SYMBOLS = ["BrowserTabs"]
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://services-sync/main.js");
 
 // Unfortunately, due to where TPS is run, we can't directly reuse the logic from
 // BrowserTestUtils.jsm. Moreover, we can't resolve the URI it loads the content
 // frame script from ("chrome://mochikit/content/tests/BrowserTestUtils/content-utils.js"),
 // hence the hackiness here and in BrowserTabs.Add.
-Services
-.mm
+Cc["@mozilla.org/globalmessagemanager;1"]
+.getService(Ci.nsIMessageListenerManager)
 .loadFrameScript("data:application/javascript;charset=utf-8," + encodeURIComponent(`
   Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
   addEventListener("load", function(event) {
     let subframe = event.target != content.document;
     sendAsyncMessage("tps:loadEvent", {subframe: subframe, url: event.target.documentURI});
   }, true)`), true);
 
 var BrowserTabs = {
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -71,17 +71,18 @@ const SUPPORTED_STRATEGIES = new Set([
   element.Strategy.ID,
   element.Strategy.TagName,
   element.Strategy.XPath,
   element.Strategy.Anon,
   element.Strategy.AnonAttribute,
 ]);
 
 const logger = Log.repository.getLogger("Marionette");
-const globalMessageManager = Services.mm;
+const globalMessageManager = Cc["@mozilla.org/globalmessagemanager;1"]
+    .getService(Ci.nsIMessageBroadcaster);
 
 /**
  * The Marionette WebDriver services provides a standard conforming
  * implementation of the W3C WebDriver specification.
  *
  * @see {@link https://w3c.github.io/webdriver/webdriver-spec.html}
  * @namespace driver
  */
--- a/testing/marionette/proxy.js
+++ b/testing/marionette/proxy.js
@@ -14,16 +14,19 @@ const {
 } = ChromeUtils.import("chrome://marionette/content/error.js", {});
 ChromeUtils.import("chrome://marionette/content/evaluate.js");
 ChromeUtils.import("chrome://marionette/content/modal.js");
 
 this.EXPORTED_SYMBOLS = ["proxy"];
 
 XPCOMUtils.defineLazyServiceGetter(
     this, "uuidgen", "@mozilla.org/uuid-generator;1", "nsIUUIDGenerator");
+XPCOMUtils.defineLazyServiceGetter(
+    this, "globalMessageManager", "@mozilla.org/globalmessagemanager;1",
+    "nsIMessageBroadcaster");
 
 const log = Log.repository.getLogger("Marionette");
 
 // Proxy handler that traps requests to get a property.  Will prioritise
 // properties that exist on the object's own prototype.
 const ownPriorityGetterTrap = {
   get: (obj, prop) => {
     if (obj.hasOwnProperty(prop)) {
@@ -281,27 +284,27 @@ proxy.AsyncMessageChannel = class {
 
   addListener_(path, callback) {
     let autoRemover = msg => {
       this.removeListener_(path);
       this.removeHandlers();
       callback(msg);
     };
 
-    Services.mm.addMessageListener(path, autoRemover);
+    globalMessageManager.addMessageListener(path, autoRemover);
     this.listeners_.set(path, autoRemover);
   }
 
   removeListener_(path) {
     if (!this.listeners_.has(path)) {
       return true;
     }
 
     let l = this.listeners_.get(path);
-    Services.mm.removeMessageListener(path, l);
+    globalMessageManager.removeMessageListener(path, l[1]);
     return this.listeners_.delete(path);
   }
 
   removeAllListeners_() {
     let ok = true;
     for (let [p] of this.listeners_) {
       ok |= this.removeListener_(p);
     }
--- a/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
+++ b/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
@@ -16,18 +16,18 @@ var EXPORTED_SYMBOLS = [
 ];
 
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://testing-common/TestUtils.jsm");
 ChromeUtils.import("resource://testing-common/ContentTask.jsm");
 
-Services
-  .mm
+Cc["@mozilla.org/globalmessagemanager;1"]
+  .getService(Ci.nsIMessageListenerManager)
   .loadFrameScript(
     "chrome://mochikit/content/tests/BrowserTestUtils/content-utils.js", true);
 
 ChromeUtils.defineModuleGetter(this, "E10SUtils",
   "resource://gre/modules/E10SUtils.jsm");
 
 const PROCESSSELECTOR_CONTRACTID = "@mozilla.org/ipc/processselector;1";
 const OUR_PROCESSSELECTOR_CID =
--- a/testing/mochitest/ShutdownLeaksCollector.jsm
+++ b/testing/mochitest/ShutdownLeaksCollector.jsm
@@ -15,17 +15,19 @@ var EXPORTED_SYMBOLS = ["ContentCollecto
 var ContentCollector = {
   init: function() {
       let processType = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).processType;
       if (processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {
         // In the main process, we handle triggering collections in browser-test.js
         return;
       }
 
-    Services.cpmm.addMessageListener("browser-test:collect-request", this);
+    let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
+                 .getService(Ci.nsISyncMessageSender);
+    cpmm.addMessageListener("browser-test:collect-request", this);
   },
 
   receiveMessage: function(aMessage) {
     switch (aMessage.name) {
       case "browser-test:collect-request":
         Services.obs.notifyObservers(null, "memory-pressure", "heap-minimize");
 
         Cu.forceGC();
@@ -52,13 +54,15 @@ var ContentCollector = {
         break;
     }
   },
 
   finish() {
     let pid = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).processID;
     dump("Completed ShutdownLeaks collections in process " + pid + "\n");
 
-    Services.cpmm.removeMessageListener("browser-test:collect-request", this);
+    let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
+                 .getService(Ci.nsISyncMessageSender);
+    cpmm.removeMessageListener("browser-test:collect-request", this);
   },
 
 };
 ContentCollector.init();
--- a/testing/mochitest/browser-test.js
+++ b/testing/mochitest/browser-test.js
@@ -105,23 +105,26 @@ function testInit() {
 
     let processCount = prefs.getIntPref("dom.ipc.processCount", 1);
     if (processCount > 1) {
       // Currently starting a content process is slow, to aviod timeouts, let's
       // keep alive content processes.
       prefs.setIntPref("dom.ipc.keepProcessesAlive.web", processCount);
     }
 
-    Services.mm.loadFrameScript("chrome://mochikit/content/shutdown-leaks-collector.js", true);
+    let globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+                     .getService(Ci.nsIMessageListenerManager);
+    globalMM.loadFrameScript("chrome://mochikit/content/shutdown-leaks-collector.js", true);
   } else {
     // In non-e10s, only run the ShutdownLeaksCollector in the parent process.
     ChromeUtils.import("chrome://mochikit/content/ShutdownLeaksCollector.jsm");
   }
 
-  Services.mm.loadFrameScript("chrome://mochikit/content/tests/SimpleTest/AsyncUtilsContent.js", true);
+  let gmm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
+  gmm.loadFrameScript("chrome://mochikit/content/tests/SimpleTest/AsyncUtilsContent.js", true);
 
   var testSuite = Cc["@mozilla.org/process/environment;1"].
                     getService(Ci.nsIEnvironment).
                     get("TEST_SUITE");
   if (testSuite == "browser-chrome-instrumentation") {
     takeInstrumentation();
   }
 }
--- a/testing/specialpowers/content/SpecialPowersObserver.jsm
+++ b/testing/specialpowers/content/SpecialPowersObserver.jsm
@@ -23,17 +23,18 @@ const CHILD_LOGGER_SCRIPT = "chrome://sp
 
 
 // Glue to add in the observer API to this object.  This allows us to share code with chrome tests
 Services.scriptloader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserverAPI.js");
 
 /* XPCOM gunk */
 function SpecialPowersObserver() {
   this._isFrameScriptLoaded = false;
-  this._messageManager = Services.mm;
+  this._messageManager = Cc["@mozilla.org/globalmessagemanager;1"].
+                         getService(Ci.nsIMessageBroadcaster);
 }
 
 
 SpecialPowersObserver.prototype = new SpecialPowersObserverAPI();
 
 SpecialPowersObserver.prototype.classDescription = "Special powers Observer for use in testing.";
 SpecialPowersObserver.prototype.classID = Components.ID("{59a52458-13e0-4d93-9d85-a637344f29a1}");
 SpecialPowersObserver.prototype.contractID = "@mozilla.org/special-powers-observer;1";
--- a/testing/xpcshell/head.js
+++ b/testing/xpcshell/head.js
@@ -1254,37 +1254,37 @@ function do_await_remote_message(name, o
             do_test_finished();
           }
         }
       }
     };
 
     var mm;
     if (runningInParent) {
-      mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService();
+      mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIMessageBroadcaster);
     } else {
-      mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService();
+      mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
     }
     do_test_pending();
     mm.addMessageListener(name, listener);
   });
 }
 
 /**
  * Asynchronously send a message to all remote processes. Pairs with do_await_remote_message
  * or equivalent ProcessMessageManager listeners.
  */
 function do_send_remote_message(name) {
   var mm;
   var sender;
   if (runningInParent) {
-    mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService();
+    mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIMessageBroadcaster);
     sender = "broadcastAsyncMessage";
   } else {
-    mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService();
+    mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
     sender = "sendAsyncMessage";
   }
   mm[sender](name);
 }
 
 /**
  * Add a test function to the list of tests that are to be run asynchronously.
  *
--- a/toolkit/components/addoncompat/RemoteAddonsChild.jsm
+++ b/toolkit/components/addoncompat/RemoteAddonsChild.jsm
@@ -38,18 +38,20 @@ function setDefault(dict, key, default_)
 // children can request the current set of paths. The purpose is to
 // keep track of all the observers and events that the child should
 // monitor for the parent.
 //
 // In the child, clients can watch for changes to all paths that start
 // with a given component.
 var NotificationTracker = {
   init() {
-    Services.cpmm.addMessageListener("Addons:ChangeNotification", this);
-    this._paths = Services.cpmm.initialProcessData.remoteAddonsNotificationPaths;
+    let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
+               .getService(Ci.nsISyncMessageSender);
+    cpmm.addMessageListener("Addons:ChangeNotification", this);
+    this._paths = cpmm.initialProcessData.remoteAddonsNotificationPaths;
     this._registered = new Map();
     this._watchers = {};
   },
 
   receiveMessage(msg) {
     let path = msg.data.path;
     let count = msg.data.count;
 
@@ -241,17 +243,19 @@ var ContentPolicyChild = {
                        node, mimeTypeGuess, extra, requestPrincipal) {
     let startTime = Cu.now();
 
     let addons = NotificationTracker.findSuffixes(["content-policy"]);
     let [prefetched, cpows] = Prefetcher.prefetch("ContentPolicy.shouldLoad",
                                                   addons, {InitNode: node});
     cpows.node = node;
 
-    let rval = Services.cpmm.sendRpcMessage("Addons:ContentPolicy:Run", {
+    let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
+               .getService(Ci.nsISyncMessageSender);
+    let rval = cpmm.sendRpcMessage("Addons:ContentPolicy:Run", {
       contentType,
       contentLocation: contentLocation.spec,
       requestOrigin: requestOrigin ? requestOrigin.spec : null,
       mimeTypeGuess,
       requestPrincipal,
       prefetched,
     }, cpows);
 
@@ -303,17 +307,19 @@ AboutProtocolChannel.prototype = {
   notificationCallbacks: null,
   loadFlags: 0,
   loadGroup: null,
   name: null,
   status: Cr.NS_OK,
 
   asyncOpen(listener, context) {
     // Ask the parent to synchronously read all the data from the channel.
-    let rval = Services.cpmm.sendRpcMessage("Addons:AboutProtocol:OpenChannel", {
+    let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
+               .getService(Ci.nsISyncMessageSender);
+    let rval = cpmm.sendRpcMessage("Addons:AboutProtocol:OpenChannel", {
       uri: this.URI.spec,
       contractID: this._contractID,
       loadingPrincipal: this._loadingPrincipal,
       securityFlags: this._securityFlags,
       contentPolicyType: this._contentPolicyType
     }, {
       notificationCallbacks: this.notificationCallbacks,
       loadGroupNotificationCallbacks: this.loadGroup ? this.loadGroup.notificationCallbacks : null,
@@ -395,17 +401,20 @@ AboutProtocolInstance.prototype = {
   },
 
   getURIFlags(uri) {
     // Cache the result to avoid the extra IPC.
     if (this._uriFlags !== undefined) {
       return this._uriFlags;
     }
 
-    let rval = Services.cpmm.sendRpcMessage("Addons:AboutProtocol:GetURIFlags", {
+    let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
+               .getService(Ci.nsISyncMessageSender);
+
+    let rval = cpmm.sendRpcMessage("Addons:AboutProtocol:GetURIFlags", {
       uri: uri.spec,
       contractID: this._contractID
     });
 
     if (rval.length != 1) {
       throw Cr.NS_ERROR_FAILURE;
     }
 
@@ -471,17 +480,19 @@ var ObserverChild = {
     if (register) {
       Services.obs.addObserver(this, topic);
     } else {
       Services.obs.removeObserver(this, topic);
     }
   },
 
   observe(subject, topic, data) {
-    Services.cpmm.sendRpcMessage("Addons:Observer:Run", {}, {
+    let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
+               .getService(Ci.nsISyncMessageSender);
+    cpmm.sendRpcMessage("Addons:Observer:Run", {}, {
       topic,
       subject,
       data
     });
   }
 };
 
 // There is one of these objects per browser tab in the child. When an
--- a/toolkit/components/addoncompat/RemoteAddonsParent.jsm
+++ b/toolkit/components/addoncompat/RemoteAddonsParent.jsm
@@ -38,39 +38,45 @@ var NotificationTracker = {
   // [A, C]. Then _paths will look like this:
   //   { 'A': { 'B': { '_count': 1 }, 'C': { '_count': 1 } } }
   // Each component in a path will be a key in some dictionary. At the
   // end, the _count property keeps track of how many instances of the
   // given path are present in _paths.
   _paths: {},
 
   init() {
-    Services.ppmm.initialProcessData.remoteAddonsNotificationPaths = this._paths;
+    let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+               .getService(Ci.nsIMessageBroadcaster);
+    ppmm.initialProcessData.remoteAddonsNotificationPaths = this._paths;
   },
 
   add(path) {
     let tracked = this._paths;
     for (let component of path) {
       tracked = setDefault(tracked, component, {});
     }
     let count = tracked._count || 0;
     count++;
     tracked._count = count;
 
-    Services.ppmm.broadcastAsyncMessage("Addons:ChangeNotification", {path, count});
+    let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+               .getService(Ci.nsIMessageBroadcaster);
+    ppmm.broadcastAsyncMessage("Addons:ChangeNotification", {path, count});
   },
 
   remove(path) {
     let tracked = this._paths;
     for (let component of path) {
       tracked = setDefault(tracked, component, {});
     }
     tracked._count--;
 
-    Services.ppmm.broadcastAsyncMessage("Addons:ChangeNotification", {path, count: tracked._count});
+    let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+               .getService(Ci.nsIMessageBroadcaster);
+    ppmm.broadcastAsyncMessage("Addons:ChangeNotification", {path, count: tracked._count});
   },
 };
 NotificationTracker.init();
 
 // An interposition is an object with three properties: methods,
 // getters, and setters. See multiprocessShims.js for an explanation
 // of how these are used. The constructor here just allows one
 // interposition to inherit members from another.
@@ -87,17 +93,19 @@ function Interposition(name, base) {
   }
 }
 
 // This object is responsible for notifying the child when a new
 // content policy is added or removed. It also runs all the registered
 // add-on content policies when the child asks it to do so.
 var ContentPolicyParent = {
   init() {
-    Services.ppmm.addMessageListener("Addons:ContentPolicy:Run", this);
+    let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+               .getService(Ci.nsIMessageBroadcaster);
+    ppmm.addMessageListener("Addons:ContentPolicy:Run", this);
 
     this._policies = new Map();
   },
 
   addContentPolicy(addon, name, cid) {
     this._policies.set(name, cid);
     NotificationTracker.add(["content-policy", addon]);
   },
@@ -175,18 +183,20 @@ CategoryManagerInterposition.methods.del
     target.deleteCategoryEntry(category, entry, persist);
   };
 
 // This shim handles the case where an add-on registers an about:
 // protocol handler in the parent and we want the child to be able to
 // use it. This code is pretty specific to Adblock's usage.
 var AboutProtocolParent = {
   init() {
-    Services.ppmm.addMessageListener("Addons:AboutProtocol:GetURIFlags", this);
-    Services.ppmm.addMessageListener("Addons:AboutProtocol:OpenChannel", this);
+    let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+               .getServ