merge mozilla-central to mozilla-inbound. CLOSED TREE
authorSebastian Hengst <archaeopteryx@coole-files.de>
Thu, 01 Mar 2018 12:29:42 +0200
changeset 444811 e3ea96705280635679da1265c022ba8e4b206e1d
parent 444807 29e1fceaf48d9a09662a18789d034f3093c4b5e8 (current diff)
parent 444810 0f8f71b0b9d84e7732c07f841e395de516b31b66 (diff)
child 444812 a0e26f6b2784e7946f166dbaed90861342fa6fb1
push id8
push userbugmail@asutherland.org
push dateSat, 11 Aug 2018 16:11:21 +0000
milestone60.0a1
merge mozilla-central to mozilla-inbound. CLOSED TREE
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/MessageListenerManager.cpp
dom/base/MessageListenerManager.h
dom/base/MessageManagerGlobal.h
dom/base/MessageSender.cpp
dom/base/MessageSender.h
dom/base/SyncMessageSender.h
dom/base/nsGlobalWindowInner.cpp
dom/webidl/MessageManager.webidl
testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
third_party/python/fluent/fluent/migrate/cldr.py
third_party/python/fluent/fluent/migrate/cldr_data/plurals.json
third_party/python/fluent/fluent/migrate/cldr_data/unicode-license.txt
--- 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();
   }
@@ -7581,51 +7582,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/clients/manager/ClientSource.cpp
+++ b/dom/clients/manager/ClientSource.cpp
@@ -203,19 +203,17 @@ ClientSource::WorkerExecutionReady(Worke
     return;
   }
 
   // A client without access to storage should never be controlled by
   // a service worker.  Check this here in case we were controlled before
   // execution ready.  We can't reliably determine what our storage policy
   // is before execution ready, unfortunately.
   if (mController.isSome()) {
-    MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate->IsStorageAllowed() ||
-                          StringBeginsWith(aWorkerPrivate->ScriptURL(),
-                                           NS_LITERAL_STRING("blob:")));
+    MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate->IsStorageAllowed());
   }
 
   // Its safe to store the WorkerPrivate* here because the ClientSource
   // is explicitly destroyed by WorkerPrivate before exiting its run loop.
   MOZ_DIAGNOSTIC_ASSERT(mOwner.is<Nothing>());
   mOwner = AsVariant(aWorkerPrivate);
 
   ClientSourceExecutionReadyArgs args(
@@ -233,46 +231,44 @@ ClientSource::WindowExecutionReady(nsPID
   MOZ_DIAGNOSTIC_ASSERT(aInnerWindow->IsCurrentInnerWindow());
   MOZ_DIAGNOSTIC_ASSERT(aInnerWindow->HasActiveDocument());
 
   if (IsShutdown()) {
     return NS_OK;
   }
 
   nsIDocument* doc = aInnerWindow->GetExtantDoc();
-  NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
-
-  nsIURI* uri = doc->GetOriginalURI();
-  NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
-
-  // Don't use nsAutoCString here since IPC requires a full nsCString anyway.
-  nsCString spec;
-  nsresult rv = uri->GetSpec(spec);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(!doc)) {
+    return NS_ERROR_UNEXPECTED;
+  }
 
   // A client without access to storage should never be controlled by
   // a service worker.  Check this here in case we were controlled before
   // execution ready.  We can't reliably determine what our storage policy
   // is before execution ready, unfortunately.
-  //
-  // Note, explicitly avoid checking storage policy for windows that inherit
-  // service workers from their parent.  If a user opens a controlled window
-  // and then blocks storage, that window will continue to be controlled by
-  // the SW until the window is closed.  Any about:blank or blob URL should
-  // continue to inherit the SW as well.  We need to avoid triggering the
-  // assertion in this corner case.
   if (mController.isSome()) {
-    MOZ_DIAGNOSTIC_ASSERT(spec.LowerCaseEqualsLiteral("about:blank") ||
-                          StringBeginsWith(spec, NS_LITERAL_CSTRING("blob:")) ||
-                          nsContentUtils::StorageAllowedForWindow(aInnerWindow) ==
+    MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::StorageAllowedForWindow(aInnerWindow) ==
                           nsContentUtils::StorageAccess::eAllow);
   }
 
+  // Don't use nsAutoCString here since IPC requires a full nsCString anyway.
+  nsCString spec;
+
+  nsIURI* uri = doc->GetOriginalURI();
+  if (uri) {
+    nsresult rv = uri->GetSpec(spec);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
   nsPIDOMWindowOuter* outer = aInnerWindow->GetOuterWindow();
-  NS_ENSURE_TRUE(outer, NS_ERROR_UNEXPECTED);
+  if (NS_WARN_IF(!outer)) {
+    return NS_ERROR_UNEXPECTED;
+  }
 
   FrameType frameType = FrameType::Top_level;
   if (!outer->IsTopLevelWindow()) {
     frameType = FrameType::Nested;
   } else if(outer->HadOriginalOpener()) {
     frameType = FrameType::Auxiliary;
   }
 
@@ -385,29 +381,21 @@ ClientSource::SetController(const Servic
   // A client in private browsing mode should never be controlled by
   // a service worker.  The principal origin attributes should guarantee
   // this invariant.
   MOZ_DIAGNOSTIC_ASSERT(!mClientInfo.IsPrivateBrowsing());
 
   // A client without access to storage should never be controlled a
   // a service worker.  If we are already execution ready with a real
   // window or worker, then verify assert the storage policy is correct.
-  //
-  // Note, explicitly avoid checking storage policy for clients that inherit
-  // service workers from their parent.  This basically means blob: URLs
-  // and about:blank windows.
   if (GetInnerWindow()) {
-    MOZ_DIAGNOSTIC_ASSERT(Info().URL().LowerCaseEqualsLiteral("about:blank") ||
-                          StringBeginsWith(Info().URL(), NS_LITERAL_CSTRING("blob:")) ||
-                          nsContentUtils::StorageAllowedForWindow(GetInnerWindow()) ==
+    MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::StorageAllowedForWindow(GetInnerWindow()) ==
                           nsContentUtils::StorageAccess::eAllow);
-  } else if (WorkerPrivate* wp = GetWorkerPrivate()) {
-    MOZ_DIAGNOSTIC_ASSERT(wp->IsStorageAllowed() ||
-                          StringBeginsWith(wp->ScriptURL(),
-                                           NS_LITERAL_STRING("blob:")));
+  } else if (GetWorkerPrivate()) {
+    MOZ_DIAGNOSTIC_ASSERT(GetWorkerPrivate()->IsStorageAllowed());
   }
 
   if (mController.isSome() && mController.ref() == aServiceWorker) {
     return;
   }
 
   mController.reset();
   mController.emplace(aServiceWorker);
--- 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/serviceworkers/test/browser_storage_permission.js
+++ b/dom/serviceworkers/test/browser_storage_permission.js
@@ -90,158 +90,16 @@ add_task(async function test_session_per
   });
 
   is(controller, null, "page should be not controlled with session storage");
 
   await BrowserTestUtils.removeTab(tab);
   Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
 });
 
-// Test to verify an about:blank iframe successfully inherits the
-// parent's controller when storage is blocked between opening the
-// parent page and creating the iframe.
-add_task(async function test_block_storage_before_blank_iframe() {
-  Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
-
-  let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
-  let browser = gBrowser.getBrowserForTab(tab);
-  await BrowserTestUtils.browserLoaded(browser);
-
-  let controller = await ContentTask.spawn(browser, null, async function() {
-    return content.navigator.serviceWorker.controller;
-  });
-
-  ok(!!controller, "page should be controlled with storage allowed");
-
-  let controller2 = await ContentTask.spawn(browser, null, async function() {
-    let f = content.document.createElement("iframe");
-    content.document.body.appendChild(f);
-    await new Promise(resolve => f.onload = resolve);
-    return !!f.contentWindow.navigator.serviceWorker.controller;
-  });
-
-  ok(!!controller2, "page should be controlled with storage allowed");
-
-  await SpecialPowers.pushPrefEnv({"set": [
-    ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT],
-  ]});
-
-  let controller3 = await ContentTask.spawn(browser, null, async function() {
-    let f = content.document.createElement("iframe");
-    content.document.body.appendChild(f);
-    await new Promise(resolve => f.onload = resolve);
-    return !!f.contentWindow.navigator.serviceWorker.controller;
-  });
-
-  ok(!!controller3, "page should be controlled with storage allowed");
-
-  await SpecialPowers.popPrefEnv();
-  await BrowserTestUtils.removeTab(tab);
-});
-
-// Test to verify a blob URL iframe successfully inherits the
-// parent's controller when storage is blocked between opening the
-// parent page and creating the iframe.
-add_task(async function test_block_storage_before_blob_iframe() {
-  Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
-
-  let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
-  let browser = gBrowser.getBrowserForTab(tab);
-  await BrowserTestUtils.browserLoaded(browser);
-
-  let controller = await ContentTask.spawn(browser, null, async function() {
-    return content.navigator.serviceWorker.controller;
-  });
-
-  ok(!!controller, "page should be controlled with storage allowed");
-
-  let controller2 = await ContentTask.spawn(browser, null, async function() {
-    let b = new content.Blob(["<!DOCTYPE html><html></html>"], { type: "text/html" });
-    let f = content.document.createElement("iframe");
-    // No need to call revokeObjectURL() since the window will be closed shortly.
-    f.src = content.URL.createObjectURL(b);
-    content.document.body.appendChild(f);
-    await new Promise(resolve => f.onload = resolve);
-    return !!f.contentWindow.navigator.serviceWorker.controller;
-  });
-
-  ok(!!controller2, "page should be controlled with storage allowed");
-
-  await SpecialPowers.pushPrefEnv({"set": [
-    ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT],
-  ]});
-
-  let controller3 = await ContentTask.spawn(browser, null, async function() {
-    let b = new content.Blob(["<!DOCTYPE html><html></html>"], { type: "text/html" });
-    let f = content.document.createElement("iframe");
-    // No need to call revokeObjectURL() since the window will be closed shortly.
-    f.src = content.URL.createObjectURL(b);
-    content.document.body.appendChild(f);
-    await new Promise(resolve => f.onload = resolve);
-    return !!f.contentWindow.navigator.serviceWorker.controller;
-  });
-
-  ok(!!controller3, "page should be controlled with storage allowed");
-
-  await SpecialPowers.popPrefEnv();
-  await BrowserTestUtils.removeTab(tab);
-});
-
-// Test to verify a blob worker script does not hit our service
-// worker storage assertions when storage is blocked between opening
-// the parent page and creating the worker.  Note, we cannot
-// explicitly check if the worker is controlled since we don't expose
-// WorkerNavigator.serviceWorkers.controller yet.
-add_task(async function test_block_storage_before_blob_worker() {
-  Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
-
-  let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
-  let browser = gBrowser.getBrowserForTab(tab);
-  await BrowserTestUtils.browserLoaded(browser);
-
-  let controller = await ContentTask.spawn(browser, null, async function() {
-    return content.navigator.serviceWorker.controller;
-  });
-
-  ok(!!controller, "page should be controlled with storage allowed");
-
-  let scriptURL = await ContentTask.spawn(browser, null, async function() {
-    let b = new content.Blob(["self.postMessage(self.location.href);self.close()"],
-                             { type: "application/javascript" });
-    // No need to call revokeObjectURL() since the window will be closed shortly.
-    let u = content.URL.createObjectURL(b);
-    let w = new content.Worker(u);
-    return await new Promise(resolve => {
-      w.onmessage = e => resolve(e.data);
-    });
-  });
-
-  ok(scriptURL.startsWith("blob:"), "blob URL worker should run");
-
-  await SpecialPowers.pushPrefEnv({"set": [
-    ["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT],
-  ]});
-
-  let scriptURL2 = await ContentTask.spawn(browser, null, async function() {
-    let b = new content.Blob(["self.postMessage(self.location.href);self.close()"],
-                             { type: "application/javascript" });
-    // No need to call revokeObjectURL() since the window will be closed shortly.
-    let u = content.URL.createObjectURL(b);
-    let w = new content.Worker(u);
-    return await new Promise(resolve => {
-      w.onmessage = e => resolve(e.data);
-    });
-  });
-
-  ok(scriptURL2.startsWith("blob:"), "blob URL worker should run");
-
-  await SpecialPowers.popPrefEnv();
-  await BrowserTestUtils.removeTab(tab);
-});
-
 add_task(async function cleanup() {
   Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
 
   let tab = BrowserTestUtils.addTab(gBrowser, PAGE_URI);
   let browser = gBrowser.getBrowserForTab(tab);
   await BrowserTestUtils.browserLoaded(browser);
 
   await ContentTask.spawn(browser, SCOPE, async function(uri) {
--- 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.
  *
deleted file mode 100644
--- a/third_party/python/fluent/fluent/migrate/cldr.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# coding=utf8
-
-import pkgutil
-import json
-
-
-def in_canonical_order(item):
-    return canonical_order.index(item)
-
-
-cldr_plurals = json.loads(
-    pkgutil.get_data('fluent.migrate', 'cldr_data/plurals.json').decode('utf-8')
-)
-
-rules = cldr_plurals['supplemental']['plurals-type-cardinal']
-canonical_order = ('zero', 'one', 'two', 'few', 'many', 'other')
-
-categories = {}
-for lang, rules in rules.items():
-    categories[lang] = tuple(sorted(map(
-        lambda key: key.replace('pluralRule-count-', ''),
-        rules.keys()
-    ), key=in_canonical_order))
-
-
-def get_plural_categories(lang):
-    """Return a tuple of CLDR plural categories for `lang`.
-
-    If an exact match for `lang` is not available, recursively fall back to
-    a language code with the last subtag stripped. That is, if `ja-JP-mac` is
-    not defined in CLDR, the code will try `ja-JP` and then `ja`.
-
-    If no matches are found, a `RuntimeError` is raised.
-
-    >>> get_plural_categories('sl')
-    ('one', 'two', 'few', 'other')
-    >>> get_plural_categories('ga-IE')
-    ('one', 'few', 'two', 'few', 'other')
-    >>> get_plural_categories('ja-JP-mac')
-    ('other')
-
-    """
-
-    langs_categories = categories.get(lang, None)
-
-    if langs_categories is None:
-        # Remove the trailing subtag.
-        fallback_lang, _, _ = lang.rpartition('-')
-
-        if fallback_lang == '':
-            raise RuntimeError('Missing plural categories for {}'.format(lang))
-
-        return get_plural_categories(fallback_lang)
-
-    return langs_categories
deleted file mode 100644
--- a/third_party/python/fluent/fluent/migrate/cldr_data/plurals.json
+++ /dev/null
@@ -1,857 +0,0 @@
-{
-  "supplemental": {
-    "version": {
-      "_number": "$Revision: 12805 $",
-      "_unicodeVersion": "9.0.0",
-      "_cldrVersion": "30"
-    },
-    "plurals-type-cardinal": {
-      "af": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ak": {
-        "pluralRule-count-one": "n = 0..1 @integer 0, 1 @decimal 0.0, 1.0, 0.00, 1.00, 0.000, 1.000, 0.0000, 1.0000",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "am": {
-        "pluralRule-count-one": "i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~2.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ar": {
-        "pluralRule-count-zero": "n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000",
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-two": "n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000",
-        "pluralRule-count-few": "n % 100 = 3..10 @integer 3~10, 103~110, 1003, … @decimal 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 103.0, 1003.0, …",
-        "pluralRule-count-many": "n % 100 = 11..99 @integer 11~26, 111, 1011, … @decimal 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 111.0, 1011.0, …",
-        "pluralRule-count-other": " @integer 100~102, 200~202, 300~302, 400~402, 500~502, 600, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ars": {
-        "pluralRule-count-zero": "n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000",
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-two": "n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000",
-        "pluralRule-count-few": "n % 100 = 3..10 @integer 3~10, 103~110, 1003, … @decimal 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 103.0, 1003.0, …",
-        "pluralRule-count-many": "n % 100 = 11..99 @integer 11~26, 111, 1011, … @decimal 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 111.0, 1011.0, …",
-        "pluralRule-count-other": " @integer 100~102, 200~202, 300~302, 400~402, 500~502, 600, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "as": {
-        "pluralRule-count-one": "i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~2.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "asa": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ast": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "az": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "be": {
-        "pluralRule-count-one": "n % 10 = 1 and n % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 81.0, 101.0, 1001.0, …",
-        "pluralRule-count-few": "n % 10 = 2..4 and n % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 2.0, 3.0, 4.0, 22.0, 23.0, 24.0, 32.0, 33.0, 102.0, 1002.0, …",
-        "pluralRule-count-many": "n % 10 = 0 or n % 10 = 5..9 or n % 100 = 11..14 @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …",
-        "pluralRule-count-other": "   @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.1, 1000.1, …"
-      },
-      "bem": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "bez": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "bg": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "bh": {
-        "pluralRule-count-one": "n = 0..1 @integer 0, 1 @decimal 0.0, 1.0, 0.00, 1.00, 0.000, 1.000, 0.0000, 1.0000",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "bm": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "bn": {
-        "pluralRule-count-one": "i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~2.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "bo": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "br": {
-        "pluralRule-count-one": "n % 10 = 1 and n % 100 != 11,71,91 @integer 1, 21, 31, 41, 51, 61, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 81.0, 101.0, 1001.0, …",
-        "pluralRule-count-two": "n % 10 = 2 and n % 100 != 12,72,92 @integer 2, 22, 32, 42, 52, 62, 82, 102, 1002, … @decimal 2.0, 22.0, 32.0, 42.0, 52.0, 62.0, 82.0, 102.0, 1002.0, …",
-        "pluralRule-count-few": "n % 10 = 3..4,9 and n % 100 != 10..19,70..79,90..99 @integer 3, 4, 9, 23, 24, 29, 33, 34, 39, 43, 44, 49, 103, 1003, … @decimal 3.0, 4.0, 9.0, 23.0, 24.0, 29.0, 33.0, 34.0, 103.0, 1003.0, …",
-        "pluralRule-count-many": "n != 0 and n % 1000000 = 0 @integer 1000000, … @decimal 1000000.0, 1000000.00, 1000000.000, …",
-        "pluralRule-count-other": " @integer 0, 5~8, 10~20, 100, 1000, 10000, 100000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, …"
-      },
-      "brx": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "bs": {
-        "pluralRule-count-one": "v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …",
-        "pluralRule-count-few": "v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 0.2~0.4, 1.2~1.4, 2.2~2.4, 3.2~3.4, 4.2~4.4, 5.2, 10.2, 100.2, 1000.2, …",
-        "pluralRule-count-other": " @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.5~1.0, 1.5~2.0, 2.5~2.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ca": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ce": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "cgg": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "chr": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ckb": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "cs": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-few": "i = 2..4 and v = 0 @integer 2~4",
-        "pluralRule-count-many": "v != 0   @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …",
-        "pluralRule-count-other": " @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, …"
-      },
-      "cy": {
-        "pluralRule-count-zero": "n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000",
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-two": "n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000",
-        "pluralRule-count-few": "n = 3 @integer 3 @decimal 3.0, 3.00, 3.000, 3.0000",
-        "pluralRule-count-many": "n = 6 @integer 6 @decimal 6.0, 6.00, 6.000, 6.0000",
-        "pluralRule-count-other": " @integer 4, 5, 7~20, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "da": {
-        "pluralRule-count-one": "n = 1 or t != 0 and i = 0,1 @integer 1 @decimal 0.1~1.6",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 2.0~3.4, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "de": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "dsb": {
-        "pluralRule-count-one": "v = 0 and i % 100 = 1 or f % 100 = 1 @integer 1, 101, 201, 301, 401, 501, 601, 701, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …",
-        "pluralRule-count-two": "v = 0 and i % 100 = 2 or f % 100 = 2 @integer 2, 102, 202, 302, 402, 502, 602, 702, 1002, … @decimal 0.2, 1.2, 2.2, 3.2, 4.2, 5.2, 6.2, 7.2, 10.2, 100.2, 1000.2, …",
-        "pluralRule-count-few": "v = 0 and i % 100 = 3..4 or f % 100 = 3..4 @integer 3, 4, 103, 104, 203, 204, 303, 304, 403, 404, 503, 504, 603, 604, 703, 704, 1003, … @decimal 0.3, 0.4, 1.3, 1.4, 2.3, 2.4, 3.3, 3.4, 4.3, 4.4, 5.3, 5.4, 6.3, 6.4, 7.3, 7.4, 10.3, 100.3, 1000.3, …",
-        "pluralRule-count-other": " @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.5~1.0, 1.5~2.0, 2.5~2.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "dv": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "dz": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ee": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "el": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "en": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "eo": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "es": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "et": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "eu": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "fa": {
-        "pluralRule-count-one": "i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~2.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ff": {
-        "pluralRule-count-one": "i = 0,1 @integer 0, 1 @decimal 0.0~1.5",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "fi": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "fil": {
-        "pluralRule-count-one": "v = 0 and i = 1,2,3 or v = 0 and i % 10 != 4,6,9 or v != 0 and f % 10 != 4,6,9 @integer 0~3, 5, 7, 8, 10~13, 15, 17, 18, 20, 21, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.3, 0.5, 0.7, 0.8, 1.0~1.3, 1.5, 1.7, 1.8, 2.0, 2.1, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …",
-        "pluralRule-count-other": " @integer 4, 6, 9, 14, 16, 19, 24, 26, 104, 1004, … @decimal 0.4, 0.6, 0.9, 1.4, 1.6, 1.9, 2.4, 2.6, 10.4, 100.4, 1000.4, …"
-      },
-      "fo": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "fr": {
-        "pluralRule-count-one": "i = 0,1 @integer 0, 1 @decimal 0.0~1.5",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "fur": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "fy": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ga": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-two": "n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000",
-        "pluralRule-count-few": "n = 3..6 @integer 3~6 @decimal 3.0, 4.0, 5.0, 6.0, 3.00, 4.00, 5.00, 6.00, 3.000, 4.000, 5.000, 6.000, 3.0000, 4.0000, 5.0000, 6.0000",
-        "pluralRule-count-many": "n = 7..10 @integer 7~10 @decimal 7.0, 8.0, 9.0, 10.0, 7.00, 8.00, 9.00, 10.00, 7.000, 8.000, 9.000, 10.000, 7.0000, 8.0000, 9.0000, 10.0000",
-        "pluralRule-count-other": " @integer 0, 11~25, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "gd": {
-        "pluralRule-count-one": "n = 1,11 @integer 1, 11 @decimal 1.0, 11.0, 1.00, 11.00, 1.000, 11.000, 1.0000",
-        "pluralRule-count-two": "n = 2,12 @integer 2, 12 @decimal 2.0, 12.0, 2.00, 12.00, 2.000, 12.000, 2.0000",
-        "pluralRule-count-few": "n = 3..10,13..19 @integer 3~10, 13~19 @decimal 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 3.00",
-        "pluralRule-count-other": " @integer 0, 20~34, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "gl": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "gsw": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "gu": {
-        "pluralRule-count-one": "i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~2.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "guw": {
-        "pluralRule-count-one": "n = 0..1 @integer 0, 1 @decimal 0.0, 1.0, 0.00, 1.00, 0.000, 1.000, 0.0000, 1.0000",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "gv": {
-        "pluralRule-count-one": "v = 0 and i % 10 = 1 @integer 1, 11, 21, 31, 41, 51, 61, 71, 101, 1001, …",
-        "pluralRule-count-two": "v = 0 and i % 10 = 2 @integer 2, 12, 22, 32, 42, 52, 62, 72, 102, 1002, …",
-        "pluralRule-count-few": "v = 0 and i % 100 = 0,20,40,60,80 @integer 0, 20, 40, 60, 80, 100, 120, 140, 1000, 10000, 100000, 1000000, …",
-        "pluralRule-count-many": "v != 0   @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …",
-        "pluralRule-count-other": " @integer 3~10, 13~19, 23, 103, 1003, …"
-      },
-      "ha": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "haw": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "he": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-two": "i = 2 and v = 0 @integer 2",
-        "pluralRule-count-many": "v = 0 and n != 0..10 and n % 10 = 0 @integer 20, 30, 40, 50, 60, 70, 80, 90, 100, 1000, 10000, 100000, 1000000, …",
-        "pluralRule-count-other": " @integer 0, 3~17, 101, 1001, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "hi": {
-        "pluralRule-count-one": "i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~2.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "hr": {
-        "pluralRule-count-one": "v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …",
-        "pluralRule-count-few": "v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14 @integer 2~4, 22~24, 32~34, 42~44, 52~54, 62, 102, 1002, … @decimal 0.2~0.4, 1.2~1.4, 2.2~2.4, 3.2~3.4, 4.2~4.4, 5.2, 10.2, 100.2, 1000.2, …",
-        "pluralRule-count-other": " @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.5~1.0, 1.5~2.0, 2.5~2.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "hsb": {
-        "pluralRule-count-one": "v = 0 and i % 100 = 1 or f % 100 = 1 @integer 1, 101, 201, 301, 401, 501, 601, 701, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …",
-        "pluralRule-count-two": "v = 0 and i % 100 = 2 or f % 100 = 2 @integer 2, 102, 202, 302, 402, 502, 602, 702, 1002, … @decimal 0.2, 1.2, 2.2, 3.2, 4.2, 5.2, 6.2, 7.2, 10.2, 100.2, 1000.2, …",
-        "pluralRule-count-few": "v = 0 and i % 100 = 3..4 or f % 100 = 3..4 @integer 3, 4, 103, 104, 203, 204, 303, 304, 403, 404, 503, 504, 603, 604, 703, 704, 1003, … @decimal 0.3, 0.4, 1.3, 1.4, 2.3, 2.4, 3.3, 3.4, 4.3, 4.4, 5.3, 5.4, 6.3, 6.4, 7.3, 7.4, 10.3, 100.3, 1000.3, …",
-        "pluralRule-count-other": " @integer 0, 5~19, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.5~1.0, 1.5~2.0, 2.5~2.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "hu": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "hy": {
-        "pluralRule-count-one": "i = 0,1 @integer 0, 1 @decimal 0.0~1.5",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "id": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ig": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ii": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "in": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "is": {
-        "pluralRule-count-one": "t = 0 and i % 10 = 1 and i % 100 != 11 or t != 0 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1~1.6, 10.1, 100.1, 1000.1, …",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "it": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "iu": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-two": "n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000",
-        "pluralRule-count-other": " @integer 0, 3~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "iw": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-two": "i = 2 and v = 0 @integer 2",
-        "pluralRule-count-many": "v = 0 and n != 0..10 and n % 10 = 0 @integer 20, 30, 40, 50, 60, 70, 80, 90, 100, 1000, 10000, 100000, 1000000, …",
-        "pluralRule-count-other": " @integer 0, 3~17, 101, 1001, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ja": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "jbo": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "jgo": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ji": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "jmc": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "jv": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "jw": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ka": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "kab": {
-        "pluralRule-count-one": "i = 0,1 @integer 0, 1 @decimal 0.0~1.5",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "kaj": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "kcg": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "kde": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "kea": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "kk": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "kkj": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "kl": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "km": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "kn": {
-        "pluralRule-count-one": "i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~2.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ko": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ks": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ksb": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ksh": {
-        "pluralRule-count-zero": "n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000",
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ku": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "kw": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-two": "n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000",
-        "pluralRule-count-other": " @integer 0, 3~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ky": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "lag": {
-        "pluralRule-count-zero": "n = 0 @integer 0 @decimal 0.0, 0.00, 0.000, 0.0000",
-        "pluralRule-count-one": "i = 0,1 and n != 0 @integer 1 @decimal 0.1~1.6",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 2.0~3.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "lb": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "lg": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "lkt": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ln": {
-        "pluralRule-count-one": "n = 0..1 @integer 0, 1 @decimal 0.0, 1.0, 0.00, 1.00, 0.000, 1.000, 0.0000, 1.0000",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "lo": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "lt": {
-        "pluralRule-count-one": "n % 10 = 1 and n % 100 != 11..19 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 1.0, 21.0, 31.0, 41.0, 51.0, 61.0, 71.0, 81.0, 101.0, 1001.0, …",
-        "pluralRule-count-few": "n % 10 = 2..9 and n % 100 != 11..19 @integer 2~9, 22~29, 102, 1002, … @decimal 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 22.0, 102.0, 1002.0, …",
-        "pluralRule-count-many": "f != 0   @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.1, 1000.1, …",
-        "pluralRule-count-other": " @integer 0, 10~20, 30, 40, 50, 60, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "lv": {
-        "pluralRule-count-zero": "n % 10 = 0 or n % 100 = 11..19 or v = 2 and f % 100 = 11..19 @integer 0, 10~20, 30, 40, 50, 60, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …",
-        "pluralRule-count-one": "n % 10 = 1 and n % 100 != 11 or v = 2 and f % 10 = 1 and f % 100 != 11 or v != 2 and f % 10 = 1 @integer 1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, … @decimal 0.1, 1.0, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …",
-        "pluralRule-count-other": " @integer 2~9, 22~29, 102, 1002, … @decimal 0.2~0.9, 1.2~1.9, 10.2, 100.2, 1000.2, …"
-      },
-      "mas": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "mg": {
-        "pluralRule-count-one": "n = 0..1 @integer 0, 1 @decimal 0.0, 1.0, 0.00, 1.00, 0.000, 1.000, 0.0000, 1.0000",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "mgo": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "mk": {
-        "pluralRule-count-one": "v = 0 and i % 10 = 1 or f % 10 = 1 @integer 1, 11, 21, 31, 41, 51, 61, 71, 101, 1001, … @decimal 0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 10.1, 100.1, 1000.1, …",
-        "pluralRule-count-other": " @integer 0, 2~10, 12~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0, 0.2~1.0, 1.2~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ml": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "mn": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "mo": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-few": "v != 0 or n = 0 or n != 1 and n % 100 = 1..19 @integer 0, 2~16, 101, 1001, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …",
-        "pluralRule-count-other": " @integer 20~35, 100, 1000, 10000, 100000, 1000000, …"
-      },
-      "mr": {
-        "pluralRule-count-one": "i = 0 or n = 1 @integer 0, 1 @decimal 0.0~1.0, 0.00~0.04",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 1.1~2.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ms": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "mt": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-few": "n = 0 or n % 100 = 2..10 @integer 0, 2~10, 102~107, 1002, … @decimal 0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 102.0, 1002.0, …",
-        "pluralRule-count-many": "n % 100 = 11..19 @integer 11~19, 111~117, 1011, … @decimal 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 111.0, 1011.0, …",
-        "pluralRule-count-other": " @integer 20~35, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.1, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "my": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "nah": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "naq": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-two": "n = 2 @integer 2 @decimal 2.0, 2.00, 2.000, 2.0000",
-        "pluralRule-count-other": " @integer 0, 3~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "nb": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "nd": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ne": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "nl": {
-        "pluralRule-count-one": "i = 1 and v = 0 @integer 1",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "nn": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "nnh": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "no": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "nqo": {
-        "pluralRule-count-other": " @integer 0~15, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~1.5, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "nr": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "nso": {
-        "pluralRule-count-one": "n = 0..1 @integer 0, 1 @decimal 0.0, 1.0, 0.00, 1.00, 0.000, 1.000, 0.0000, 1.0000",
-        "pluralRule-count-other": " @integer 2~17, 100, 1000, 10000, 100000, 1000000, … @decimal 0.1~0.9, 1.1~1.7, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "ny": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000, … @decimal 0.0~0.9, 1.1~1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …"
-      },
-      "nyn": {
-        "pluralRule-count-one": "n = 1 @integer 1 @decimal 1.0, 1.00, 1.000, 1.0000",
-        "pluralRule-count-other": " @integer 0, 2~16, 100, 1000, 10000, 100000, 1000000