Bug 776825 - Separate message managers into senders and broadcasters. r=smaug
authorPhilipp von Weitershausen <philipp@weitershausen.de>
Mon, 27 Aug 2012 11:13:02 -0300
changeset 109557 5acb2a155d121f7686460c30e2dacd40cea315a4
parent 109556 d36a98542b01fee2c7469eb466c27099f1e727b1
child 109558 f400c8e5cea46069f4e68b2b801eb34ba810a250
push id214
push userakeybl@mozilla.com
push dateWed, 14 Nov 2012 20:38:59 +0000
treeherdermozilla-release@c8b08ec8e1aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs776825
milestone17.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 776825 - Separate message managers into senders and broadcasters. r=smaug
b2g/chrome/content/shell.js
b2g/components/ContentHandler.js
b2g/components/MozKeyboard.js
browser/base/content/browser.js
content/base/public/Makefile.in
content/base/public/nsIFrameLoader.idl
content/base/public/nsIFrameMessageManager.idl
content/base/public/nsIMessageManager.idl
content/base/src/messageWakeupService.js
content/base/src/nsCCUncollectableMarker.cpp
content/base/src/nsFrameLoader.cpp
content/base/src/nsFrameMessageManager.cpp
content/base/src/nsFrameMessageManager.h
content/base/src/nsInProcessTabChildGlobal.cpp
content/base/src/nsInProcessTabChildGlobal.h
content/base/test/chrome/file_bug549682.xul
content/base/test/chrome/file_bug616841.xul
docshell/base/nsDocShell.cpp
dom/activities/src/ActivitiesService.jsm
dom/activities/src/ActivityProxy.js
dom/activities/src/ActivityRequestHandler.js
dom/alarm/AlarmService.jsm
dom/apps/src/AppsService.js
dom/apps/src/Webapps.js
dom/apps/src/Webapps.jsm
dom/base/DOMRequestHelper.jsm
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/contacts/ContactManager.js
dom/contacts/fallback/ContactService.jsm
dom/devicestorage/ipc/test_ipc.html
dom/identity/DOMIdentity.jsm
dom/identity/nsDOMIdentity.js
dom/indexedDB/ipc/test_ipc.html
dom/interfaces/base/nsIDOMChromeWindow.idl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/test.xul
dom/ipc/tests/process_error.xul
dom/messages/SystemMessageInternal.js
dom/messages/SystemMessageManager.js
dom/permission/PermissionPromptHelper.jsm
dom/settings/SettingsChangeNotifier.jsm
dom/settings/SettingsManager.js
dom/system/gonk/RILContentHelper.js
dom/system/gonk/RadioInterfaceLayer.js
dom/tests/mochitest/general/test_interfaces.html
dom/wifi/WifiWorker.js
extensions/cookie/test/unit_ipc/test_parent.js
layout/base/nsPresContext.cpp
layout/build/nsLayoutModule.cpp
layout/ipc/test-ipcbrowser-chrome.js
layout/tools/reftest/reftest.js
mobile/xul/chrome/content/CapturePickerUI.js
mobile/xul/chrome/content/WebappsUI.js
mobile/xul/chrome/content/bindings/browser.xml
mobile/xul/components/LoginManager.js
netwerk/protocol/app/AppProtocolHandler.js
testing/marionette/marionette-actors.js
testing/mochitest/specialpowers/components/SpecialPowersObserver.js
toolkit/components/contentprefs/nsContentPrefService.js
toolkit/components/contentprefs/tests/unit_ipc/test_contentPrefs_parentipc.js
toolkit/components/satchel/nsFormHistory.js
toolkit/mozapps/extensions/ChromeManifestParser.jsm
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/extensions/addonManager.js
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -44,17 +44,17 @@ XPCOMUtils.defineLazyServiceGetter(Servi
 
 XPCOMUtils.defineLazyGetter(this, 'DebuggerServer', function() {
   Cu.import('resource://gre/modules/devtools/dbg-server.jsm');
   return DebuggerServer;
 });
 
 XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
   return Cc["@mozilla.org/parentprocessmessagemanager;1"]
-         .getService(Ci.nsIFrameMessageManager);
+         .getService(Ci.nsIMessageListenerManager);
 });
 
 function getContentWindow() {
   return shell.contentBrowser.contentWindow;
 }
 
 var shell = {
 
--- a/b2g/components/ContentHandler.js
+++ b/b2g/components/ContentHandler.js
@@ -9,17 +9,18 @@ const Cr = Components.results;
 const Cu = Components.utils;
 
 const PDF_CONTENT_TYPE = "application/pdf";
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
-  return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
+  return Cc["@mozilla.org/childprocessmessagemanager;1"]
+           .getService(Ci.nsIMessageSender);
 });
 
 function log(aMsg) {
   let msg = "ContentHandler.js: " + (aMsg.join ? aMsg.join("") : aMsg);
   Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
                                      .logStringMessage(msg);
   dump(msg + "\n");
 }
--- a/b2g/components/MozKeyboard.js
+++ b/b2g/components/MozKeyboard.js
@@ -9,17 +9,17 @@ const Ci = Components.interfaces;
 const Cu = Components.utils;
 const kFormsFrameScript = "chrome://browser/content/forms.js";
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/ObjectWrapper.jsm");
 
 const messageManager = Cc["@mozilla.org/globalmessagemanager;1"]
-                         .getService(Ci.nsIChromeFrameMessageManager);
+                         .getService(Ci.nsIMessageBroadcaster);
 
 
 // -----------------------------------------------------------------------
 // MozKeyboard
 // -----------------------------------------------------------------------
 
 function MozKeyboard() { } 
 
@@ -65,29 +65,29 @@ MozKeyboard.prototype = {
   sendKey: function mozKeyboardSendKey(keyCode, charCode) {
     charCode = (charCode == undefined) ? keyCode : charCode;
     ["keydown", "keypress", "keyup"].forEach((function sendKey(type) {
       this._utils.sendKeyEvent(type, keyCode, charCode, null);
     }).bind(this));
   },
 
   setSelectedOption: function mozKeyboardSetSelectedOption(index) {
-    messageManager.sendAsyncMessage("Forms:Select:Choice", {
+    messageManager.broadcastAsyncMessage("Forms:Select:Choice", {
       "index": index
     });
   },
 
   setValue: function mozKeyboardSetValue(value) {
-    messageManager.sendAsyncMessage("Forms:Input:Value", {
+    messageManager.broadcastAsyncMessage("Forms:Input:Value", {
       "value": value
     });
   },
 
   setSelectedOptions: function mozKeyboardSetSelectedOptions(indexes) {
-    messageManager.sendAsyncMessage("Forms:Select:Choice", {
+    messageManager.broadcastAsyncMessage("Forms:Select:Choice", {
       "indexes": indexes || []
     });
   },
 
   set onfocuschange(val) {
     this._focusHandler = val;
   },
 
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -355,17 +355,17 @@ const gSessionHistoryObserver = {
       return;
 
     var backCommand = document.getElementById("Browser:Back");
     backCommand.setAttribute("disabled", "true");
     var fwdCommand = document.getElementById("Browser:Forward");
     fwdCommand.setAttribute("disabled", "true");
 
     // Hide session restore button on about:home
-    window.messageManager.sendAsyncMessage("Browser:HideSessionRestoreButton");
+    window.messageManager.broadcastAsyncMessage("Browser:HideSessionRestoreButton");
 
     if (gURLBar) {
       // Clear undo history of the URL bar
       gURLBar.editor.transactionManager.clear()
     }
   }
 };
 
--- a/content/base/public/Makefile.in
+++ b/content/base/public/Makefile.in
@@ -76,15 +76,15 @@ XPIDLSRCS	= \
 		nsISelectionPrivate.idl  \
 		nsIScriptLoaderObserver.idl  \
 		nsIDroppedLinkHandler.idl \
 		nsIImageLoadingContent.idl \
 		nsIObjectLoadingContent.idl \
 		nsIFrameLoader.idl \
 		nsIXMLHttpRequest.idl \
 		nsIContentSecurityPolicy.idl \
-		nsIFrameMessageManager.idl \
+		nsIMessageManager.idl \
 		nsIWebSocket.idl \
 		nsIEventSource.idl \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/content/base/public/nsIFrameLoader.idl
+++ b/content/base/public/nsIFrameLoader.idl
@@ -3,17 +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/. */
 
 #include "nsISupports.idl"
 
 interface nsIDocShell;
 interface nsIURI;
 interface nsIFrame;
-interface nsIChromeFrameMessageManager;
+interface nsIMessageSender;
 interface nsIVariant;
 interface nsIDOMElement;
 
 typedef unsigned long long nsContentViewId;
 
 /**
  * These interfaces do *not* scroll or scale the content document;
  * instead they set a "goal" scroll/scale wrt the current content
@@ -103,17 +103,17 @@ interface nsIContentViewManager : nsISup
                          [retval, array, size_is(aLength)] out nsIContentView aResult);
 
   /**
    * The root content view.
    */
   readonly attribute nsIContentView rootContentView;
 };
 
-[scriptable, uuid(fc338eea-47dc-475e-add7-a3933fcfa07c)]
+[scriptable, uuid(f234c232-bb17-4450-b324-bf1ef5ccfd34)]
 interface nsIFrameLoader : nsISupports
 {
   /**
    * Get the docshell from the frame loader.
    */
   readonly attribute nsIDocShell docShell;
 
   /**
@@ -172,17 +172,17 @@ interface nsIFrameLoader : nsISupports
                                   [optional] in boolean aIgnoreRootScrollFrame);
 
   /**
    * Activate event forwarding from client (remote frame) to parent.
    */
   void activateFrameEvent(in AString aType, in boolean capture);
 
   // Note, when frameloaders are swapped, also messageManagers are swapped.
-  readonly attribute nsIChromeFrameMessageManager messageManager;
+  readonly attribute nsIMessageSender messageManager;
 
   /**
    * @see nsIDOMWindowUtils sendKeyEvent.
    */
   void sendCrossProcessKeyEvent(in AString aType,
                                 in long aKeyCode,
                                 in long aCharCode,
                                 in long aModifiers,
rename from content/base/public/nsIFrameMessageManager.idl
rename to content/base/public/nsIMessageManager.idl
--- a/content/base/public/nsIFrameMessageManager.idl
+++ b/content/base/public/nsIMessageManager.idl
@@ -4,64 +4,282 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMWindow;
 interface nsIDocShell;
 interface nsIContent;
 
-[scriptable, function, uuid(938fcb95-3d63-46be-aa72-94d08fd3b418)]
-interface nsIFrameMessageListener : nsISupports
+/**
+ * Message managers provide a way for chrome-privileged JS code to
+ * communicate with each other, even across process boundaries.
+ *
+ * Message managers are separated into "parent side" and "child side".
+ * These don't always correspond to process boundaries, but can.  For
+ * each child-side message manager, there is always exactly one
+ * corresponding parent-side message manager that it sends messages
+ * to.  However, for each parent-side message manager, there may be
+ * either one or many child-side managers it can message.
+ *
+ * Message managers that always have exactly one "other side" are of
+ * type nsIMessageSender.  Parent-side message managers that have many
+ * "other sides" are of type nsIMessageBroadcaster.
+ *
+ * Child-side message managers can send synchronous messages to their
+ * parent side, but not the other way around.
+ *
+ * There are two realms of message manager hierarchies.  One realm
+ * approximately corresponds to DOM elements, the other corresponds to
+ * process boundaries.
+ *
+ * Message managers corresponding to DOM elements
+ * ==============================================
+ *
+ * In this realm of message managers, there are
+ *  - "frame message managers" which correspond to frame elements
+ *  - "window message managers" which correspond to top-level chrome
+ *    windows
+ *  - the "global message manager", on the parent side.  See below.
+ *
+ * The DOM-realm message managers can communicate in the ways shown by
+ * the following diagram.  The parent side and child side can
+ * correspond to process boundaries, but don't always.
+ *
+ *  Parent side                         Child side
+ * -------------                       ------------
+ *  global MMg
+ *   |
+ *   +-->window MMw1
+ *   |    |
+ *   |    +-->frame MMp1_1<------------>frame MMc1_1
+ *   |    |
+ *   |    +-->frame MMp1_2<------------>frame MMc1_2
+ *   |    ...
+ *   |
+ *   +-->window MMw2
+ *   ...
+ *
+ * For example: a message sent from MMc1_1, from the child side, is
+ * sent only to MMp1_1 on the parent side.  However, note that all
+ * message managers in the hierarchy above MMp1_1, in this diagram
+ * MMw1 and MMg, will also notify their message listeners when the
+ * message arrives.
+
+ * For example: a message broadcast through the global MMg on the
+ * parent side would be broadcast to MMw1, which would transitively
+ * broadcast it to MMp1_1, MM1p_2".  The message would next be
+ * broadcast to MMw2, and so on down the hierarchy.
+ *
+ *   ***** PERFORMANCE AND SECURITY WARNING *****
+ * Messages broadcast through the global MM and window MMs can result
+ * in messages being dispatched across many OS processes, and to many
+ * processes with different permissions.  Great care should be taken
+ * when broadcasting.
+ *
+ * Interfaces
+ * ----------
+ *
+ * The global MMg and window MMw's are message broadcasters implementing
+ * nsIMessageBroadcaster while the frame MMp's are simple message senders
+ * (nsIMessageSender). Their counterparts in the content processes are
+ * message senders implementing nsIContentFrameMessageManager.
+ *
+ *                    nsIMessageListenerManager
+ *                  /                           \
+ * nsIMessageSender                               nsIMessageBroadcaster
+ *       |
+ * nsISyncMessageSender (content process/in-process only)
+ *       |
+ * nsIContentFrameMessageManager (content process/in-process only)
+ *       |
+ * nsIInProcessContentFrameMessageManager (in-process only)
+ *
+ *
+ * Message managers in the chrome process can also be QI'ed to nsIFrameScriptLoader.
+ *
+ *
+ * Message managers corresponding to process boundaries
+ * ====================================================
+ *
+ * The second realm of message managers is the "process message
+ * managers".  With one exception, these always correspond to process
+ * boundaries.  The picture looks like
+ *
+ *  Parent process                      Child processes
+ * ----------------                    -----------------
+ *  global PPMM
+ *   |
+ *   +<----> child PPMM
+ *   |
+ *   +-->parent PMM1<------------------>child process CMM1
+ *   |
+ *   +-->parent PMM2<------------------>child process PMM2
+ *   ...
+ *
+ * For example: the parent-process PMM1 sends messages directly to
+ * only the child-process CMM1.
+ *
+ * For example: CMM1 sends messages directly to PMM1.  The global PPMM
+ * will also notify their message listeners when the message arrives.
+ *
+ * For example: messages sent through the global PPMM will be
+ * dispatched to the listeners of the same-process, "child PPMM".
+ * They will also be broadcast to PPM1, PPM2, etc.
+ *
+ *   ***** PERFORMANCE AND SECURITY WARNING *****
+ * Messages broadcast through the global PPMM can result in messages
+ * being dispatched across many OS processes, and to many processes
+ * with different permissions.  Great care should be taken when
+ * broadcasting.
+ *
+ * Requests sent to parent-process message listeners should usually
+ * have replies scoped to the requesting CPMM.  The following pattern
+ * is common
+ *
+ *  const ParentProcessListener = {
+ *    receiveMessage: function(aMessage) {
+ *      let childMM = aMessage.target.QueryInterface(Ci.nsIMessageSender);
+ *      switch (aMessage.name) {
+ *      case "Foo:Request":
+ *        // service request
+ *        childMM.sendAsyncMessage("Foo:Response", { data });
+ *      }
+ *    }
+ *  };
+ */
+
+[scriptable, function, uuid(2b44eb57-a9c6-4773-9a1e-fe0818739a4c)]
+interface nsIMessageListener : nsISupports
 {
   /**
    * This is for JS only.
    * receiveMessage is called with one parameter, which has the following
    * properties:
    *   {
    *     target:  %the target of the message. Either an element owning
    *               the message manager, or message manager itself if no
    *               element owns it%
    *     name:    %message name%,
    *     sync:    %true or false%.
-   *     json:    %structured clone of the sent message data%,
+   *     data:    %structured clone of the sent message data%,
    *     json:    %same as .data, deprecated%,
    *     objects: %array of handles or null, always null if sync is false%
    *   }
    * @note objects property isn't implemented yet.
    *
-   * if the message is synchronous, possible return value is sent back
-   * as JSON (will be changed to use structured clones).
+   * 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.
    */
   void receiveMessage();
 };
 
-[scriptable, builtinclass, uuid(9be42627-a5db-456f-8de2-9097da45a8c3)]
-interface nsIFrameMessageManager : nsISupports
+[scriptable, builtinclass, uuid(9c37a142-3de3-4902-a1a4-133f37d5980a)]
+interface nsIMessageListenerManager : nsISupports
 {
-  void addMessageListener(in AString aMessage, in nsIFrameMessageListener aListener);
-  void removeMessageListener(in AString aMessage, in nsIFrameMessageListener aListener);
-  [implicit_jscontext,optional_argc]
-  void sendAsyncMessage([optional] in AString messageName, [optional] in jsval obj);
+  /**
+   * 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.
+   */
+  void addMessageListener(in AString messageName,
+                          in nsIMessageListener listener);
+
+  /**
+   * No longer invoke |listener| when |messageName| is received, after
+   * the first time removeMessageListener() is called.
+   */
+  void removeMessageListener(in AString messageName,
+                             in nsIMessageListener listener);
+
   [notxpcom] boolean markForCC();
 };
 
-[scriptable, builtinclass, uuid(28a36ac7-2868-4fa0-ae24-be957d7dce10)]
-interface nsISyncMessageSender : nsIFrameMessageManager
+/**
+ * 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.
+ */
+[scriptable, builtinclass, uuid(7f23767d-0f39-40c1-a22d-d3ab8a481f9d)]
+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
+   * data delivered to listeners.
+   */
+  [implicit_jscontext, optional_argc]
+  void sendAsyncMessage([optional] in AString messageName,
+                        [optional] in jsval obj);
+};
+
+/**
+ * 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.
+ */
+[scriptable, builtinclass, uuid(d36346b9-5d3b-497d-9c28-ffbc3e4f6d0d)]
+interface nsIMessageBroadcaster : nsIMessageListenerManager
 {
   /**
-   * Returns an array of JSON objects.
+   * 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.
    */
-  [implicit_jscontext,optional_argc]
-  jsval sendSyncMessage([optional] in AString messageName, [optional] in jsval obj);
+  [implicit_jscontext, optional_argc]
+  void broadcastAsyncMessage([optional] in AString messageName,
+                             [optional] in jsval obj);
+
+  /**
+   * Number of subordinate message managers.
+   */
+  readonly attribute unsigned long childCount;
+
+  /**
+   * Return a single subordinate message manager.
+   */
+  nsIMessageListenerManager getChildAt(in unsigned long aIndex);
 };
 
-[scriptable, builtinclass, uuid(a83f4393-e3cf-44da-8867-1f9174c2c595)]
+[scriptable, builtinclass, uuid(83be5862-2996-4685-ae7d-ae25bd795d50)]
+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]
+  jsval sendSyncMessage([optional] in AString messageName,
+                        [optional] in jsval obj);
+};
+
+[scriptable, builtinclass, uuid(894ff2d4-39a3-4df8-9d76-8ee329975488)]
 interface nsIContentFrameMessageManager : nsISyncMessageSender
 {
   /**
    * The current top level window in the frame or null.
    */
   readonly attribute nsIDOMWindow content;
 
   /**
@@ -82,39 +300,31 @@ interface nsIContentFrameMessageManager 
 
    /**
     * Ascii base64 data to binary data and vice versa
     */
    DOMString atob(in DOMString aAsciiString);
    DOMString btoa(in DOMString aBase64Data);
 };
 
-[uuid(f0936c56-e92c-4927-a85b-e289c3d4a01c)]
+[uuid(a2325927-9c0c-437d-9215-749c79235031)]
 interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager
 {
   [notxpcom] nsIContent getOwnerContent();
 };
 
-[scriptable, builtinclass, uuid(09f79e8c-101b-432b-a494-02f9b5e111c0)]
-interface nsITreeItemFrameMessageManager : nsIFrameMessageManager
-{
-  readonly attribute unsigned long childCount;
-  nsITreeItemFrameMessageManager getChildAt(in unsigned long aIndex);
-};
-
-[scriptable, builtinclass, uuid(a51597f0-d669-4260-83e6-1d426a8ac802)]
-interface nsIChromeFrameMessageManager : nsITreeItemFrameMessageManager
+[scriptable, builtinclass, uuid(a54acd34-4141-46f5-b71b-e2ca32879b08)]
+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.
    */
   void loadFrameScript(in AString aURL, in boolean aAllowDelayedLoad);
 
   /**
    * Removes aURL from the list of scripts which support delayed load.
    */
   void removeDelayedFrameScript(in AString aURL);
 };
-
--- a/content/base/src/messageWakeupService.js
+++ b/content/base/src/messageWakeupService.js
@@ -16,17 +16,17 @@ MessageWakeupService.prototype =
   classID:          Components.ID("{f9798742-4f7b-4188-86ba-48b116412b29}"),
   QueryInterface:   XPCOMUtils.generateQI([Ci.nsIObserver]),
 
   messagesData: [],
 
   get messageManager() {
     if (!this._messageManager)
       this._messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"].
-                             getService(Ci.nsIFrameMessageManager);
+                             getService(Ci.nsIMessageListenerManager);
     return this._messageManager;
   },
 
   requestWakeup: function(aMessageName, aCid, aIid, aMethod) {
     this.messagesData[aMessageName] = {
       cid: aCid,
       iid: aIid,
       method: aMethod,
@@ -34,17 +34,17 @@ MessageWakeupService.prototype =
 
     this.messageManager.addMessageListener(aMessageName, this);
   },
 
   receiveMessage: function(aMessage) {
     let data = this.messagesData[aMessage.name];
     // TODO: When bug 593407 is ready, stop doing the wrappedJSObject hack
     //       and use this line instead:
-    //                  QueryInterface(Ci.nsIFrameMessageListener);
+    //                  QueryInterface(Ci.nsIMessageListener);
     let service = Cc[data.cid][data.method](Ci[data.iid]).
                   wrappedJSObject;
 
     // The receiveMessage() call itself may spin an event loop, and we
     // do not want to swap listeners in that - it would cause the current
     // message to be answered by two listeners. So, we call that first,
     // then queue the swap for the next event loop
     let ret = service.receiveMessage(aMessage);
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -87,40 +87,42 @@ MarkUserDataHandler(void* aNode, nsIAtom
   if (d && nsCCUncollectableMarker::InGeneration(d->GetMarkedCCGeneration())) {
     nsGenericElement::MarkUserDataHandler(aNode, aKey, aValue, aData);
   }
 }
 
 static void
 MarkMessageManagers()
 {
-  nsCOMPtr<nsIChromeFrameMessageManager> globalMM =
+  nsCOMPtr<nsIMessageBroadcaster> globalMM =
     do_GetService("@mozilla.org/globalmessagemanager;1");
   if (!globalMM) {
     return;
   }
 
   globalMM->MarkForCC();
   uint32_t childCount = 0;
   globalMM->GetChildCount(&childCount);
   for (uint32_t i = 0; i < childCount; ++i) {
-    nsCOMPtr<nsITreeItemFrameMessageManager> windowMM;
-    globalMM->GetChildAt(i, getter_AddRefs(windowMM));
-    if (!windowMM) {
+    nsCOMPtr<nsIMessageListenerManager> childMM;
+    globalMM->GetChildAt(i, getter_AddRefs(childMM));
+    if (!childMM) {
       continue;
     }
+    nsCOMPtr<nsIMessageBroadcaster> windowMM = do_QueryInterface(childMM);
     windowMM->MarkForCC();
     uint32_t tabChildCount = 0;
     windowMM->GetChildCount(&tabChildCount);
     for (uint32_t j = 0; j < tabChildCount; ++j) {
-      nsCOMPtr<nsITreeItemFrameMessageManager> tabMM;
-      windowMM->GetChildAt(j, getter_AddRefs(tabMM));
-      if (!tabMM) {
+      nsCOMPtr<nsIMessageListenerManager> childMM;
+      windowMM->GetChildAt(j, getter_AddRefs(childMM));
+      if (!childMM) {
         continue;
       }
+      nsCOMPtr<nsIMessageSender> tabMM = do_QueryInterface(childMM);
       tabMM->MarkForCC();
       //XXX hack warning, but works, since we know that
       //    callback data is frameloader.
       void* cb = static_cast<nsFrameMessageManager*>(tabMM.get())->
         GetCallbackData();
       nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
       if (fl) {
         nsIDOMEventTarget* et = fl->GetTabChildGlobalAsEventTarget();
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -2239,17 +2239,17 @@ bool SendAsyncMessageToChild(void* aCall
   nsRefPtr<nsIRunnable> ev =
     new nsAsyncMessageToChild(static_cast<nsFrameLoader*>(aCallbackData),
                                     aMessage, aData);
   NS_DispatchToCurrentThread(ev);
   return true;
 }
 
 NS_IMETHODIMP
-nsFrameLoader::GetMessageManager(nsIChromeFrameMessageManager** aManager)
+nsFrameLoader::GetMessageManager(nsIMessageSender** aManager)
 {
   EnsureMessageManager();
   if (mMessageManager) {
     CallQueryInterface(mMessageManager, aManager);
   }
   return NS_OK;
 }
 
@@ -2331,31 +2331,31 @@ nsFrameLoader::EnsureMessageManager()
   nsIScriptContext* sctx = mOwnerContent->GetContextForEventHandlers(&rv);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_STATE(sctx);
   JSContext* cx = sctx->GetNativeContext();
   NS_ENSURE_STATE(cx);
 
   nsCOMPtr<nsIDOMChromeWindow> chromeWindow =
     do_QueryInterface(GetOwnerDoc()->GetWindow());
-  nsCOMPtr<nsIChromeFrameMessageManager> parentManager;
+  nsCOMPtr<nsIMessageBroadcaster> parentManager;
   if (chromeWindow) {
     chromeWindow->GetMessageManager(getter_AddRefs(parentManager));
   }
 
   if (ShouldUseRemoteProcess()) {
-    mMessageManager = new nsFrameMessageManager(true,
+    mMessageManager = new nsFrameMessageManager(true, /* aChrome */
                                                 nullptr,
                                                 SendAsyncMessageToChild,
                                                 LoadScript,
                                                 mRemoteBrowserShown ? this : nullptr,
                                                 static_cast<nsFrameMessageManager*>(parentManager.get()),
                                                 cx);
   } else {
-    mMessageManager = new nsFrameMessageManager(true,
+    mMessageManager = new nsFrameMessageManager(true, /* aChrome */
                                                 nullptr,
                                                 SendAsyncMessageToChild,
                                                 LoadScript,
                                                 nullptr,
                                                 static_cast<nsFrameMessageManager*>(parentManager.get()),
                                                 cx);
     mChildMessageManager =
       new nsInProcessTabChildGlobal(mDocShell, mOwnerContent, mMessageManager);
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -19,16 +19,17 @@
 #include "nsScriptLoader.h"
 #include "nsIJSContextStack.h"
 #include "nsIXULRuntime.h"
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsIProtocolHandler.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIJSRuntimeService.h"
+#include "nsIDOMClassInfo.h"
 #include "nsIDOMFile.h"
 #include "xpcpublic.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/StructuredCloneUtils.h"
 
 #ifdef ANDROID
 #include <android/log.h>
 #endif
@@ -59,50 +60,68 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mListeners[i] mListener");
     cb.NoteXPCOMChild(tmp->mListeners[i].mListener.get());
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mChildManagers)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameMessageManager)
   tmp->mListeners.Clear();
-  for (int32_t i = tmp->mChildManagers.Count(); i > 0; --i) {
+  for (PRInt32 i = tmp->mChildManagers.Count(); i > 0; --i) {
     static_cast<nsFrameMessageManager*>(tmp->mChildManagers[i - 1])->
       Disconnect(false);
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mChildManagers)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentFrameMessageManager)
-  NS_INTERFACE_MAP_ENTRY_AGGREGATED(nsIFrameMessageManager,
-                                    (mChrome ?
-                                       static_cast<nsIFrameMessageManager*>(
-                                         static_cast<nsIChromeFrameMessageManager*>(this)) :
-                                       static_cast<nsIFrameMessageManager*>(
-                                         static_cast<nsIContentFrameMessageManager*>(this))))
+
+  /* nsFrameMessageManager implements nsIMessageSender and nsIMessageBroadcaster,
+   * both of which descend from nsIMessageListenerManager. QI'ing to
+   * nsIMessageListenerManager is therefore ambiguous and needs explicit casts
+   * depending on which child interface applies. */
+  NS_INTERFACE_MAP_ENTRY_AGGREGATED(nsIMessageListenerManager,
+                                    (mIsBroadcaster ?
+                                       static_cast<nsIMessageListenerManager*>(
+                                         static_cast<nsIMessageBroadcaster*>(this)) :
+                                       static_cast<nsIMessageListenerManager*>(
+                                         static_cast<nsIMessageSender*>(this))))
+
+  /* Message managers in child process implement nsIMessageSender and
+     nsISyncMessageSender.  Message managers in the chrome process are
+     either broadcasters (if they have subordinate/child message
+     managers) or they're simple message senders. */
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISyncMessageSender, !mChrome)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIMessageSender, !mChrome || !mIsBroadcaster)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIMessageBroadcaster, mChrome && mIsBroadcaster)
+
   /* nsIContentFrameMessageManager is accessible only in TabChildGlobal. */
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIContentFrameMessageManager,
                                      !mChrome && !mIsProcessManager)
-  /* Message managers in child process support nsISyncMessageSender. */
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISyncMessageSender, !mChrome)
-  /* Message managers in chrome process support nsITreeItemFrameMessageManager. */
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITreeItemFrameMessageManager, mChrome)
-  /* Process message manager doesn't support nsIChromeFrameMessageManager. */
-  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIChromeFrameMessageManager,
+
+  /* Frame message managers (non-process message managers) support nsIFrameScriptLoader. */
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIFrameScriptLoader,
                                      mChrome && !mIsProcessManager)
+
+  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)
 
+// nsIMessageListenerManager
+
 NS_IMETHODIMP
 nsFrameMessageManager::AddMessageListener(const nsAString& aMessage,
-                                          nsIFrameMessageListener* aListener)
+                                          nsIMessageListener* aListener)
 {
   nsCOMPtr<nsIAtom> message = do_GetAtom(aMessage);
   uint32_t len = mListeners.Length();
   for (uint32_t i = 0; i < len; ++i) {
     if (mListeners[i].mMessage == message &&
       mListeners[i].mListener == aListener) {
       return NS_OK;
     }
@@ -111,30 +130,32 @@ nsFrameMessageManager::AddMessageListene
   NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
   entry->mMessage = message;
   entry->mListener = aListener;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessage,
-                                             nsIFrameMessageListener* aListener)
+                                             nsIMessageListener* aListener)
 {
   nsCOMPtr<nsIAtom> message = do_GetAtom(aMessage);
   uint32_t len = mListeners.Length();
   for (uint32_t i = 0; i < len; ++i) {
     if (mListeners[i].mMessage == message &&
       mListeners[i].mListener == aListener) {
       mListeners.RemoveElementAt(i);
       return NS_OK;
     }
   }
   return NS_OK;
 }
 
+// nsIFrameScriptLoader
+
 NS_IMETHODIMP
 nsFrameMessageManager::LoadFrameScript(const nsAString& aURL,
                                        bool aAllowDelayedLoad)
 {
   if (aAllowDelayedLoad) {
     if (IsGlobal() || IsWindowLevel()) {
       // Cache for future windows or frames
       mPendingScripts.AppendElement(aURL);
@@ -147,17 +168,17 @@ nsFrameMessageManager::LoadFrameScript(c
 
   if (mCallbackData) {
 #ifdef DEBUG_smaug
     printf("Will load %s \n", NS_ConvertUTF16toUTF8(aURL).get());
 #endif
     NS_ENSURE_TRUE(mLoadScriptCallback(mCallbackData, aURL), NS_ERROR_FAILURE);
   }
 
-  for (int32_t i = 0; i < mChildManagers.Count(); ++i) {
+  for (PRInt32 i = 0; i < mChildManagers.Count(); ++i) {
     nsRefPtr<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->LoadFrameScript(aURL, false);
     }
   }
@@ -203,16 +224,19 @@ GetParamsForMessage(JSContext* aCx,
 
   jsval val = JSVAL_NULL;
   NS_ENSURE_TRUE(JS_ParseJSON(aCx, static_cast<const jschar*>(PromiseFlatString(json).get()),
                               json.Length(), &val), false);
 
   return WriteStructuredClone(aCx, val, aBuffer, aClosure);
 }
 
+
+// nsISyncMessageSender
+
 NS_IMETHODIMP
 nsFrameMessageManager::SendSyncMessage(const nsAString& aMessageName,
                                        const jsval& aObject,
                                        JSContext* aCx,
                                        uint8_t aArgc,
                                        jsval* aRetval)
 {
   NS_ASSERTION(!IsGlobal(), "Should not call SendSyncMessage in chrome");
@@ -252,51 +276,100 @@ nsFrameMessageManager::SendSyncMessage(c
 
       *aRetval = OBJECT_TO_JSVAL(dataArray);
     }
   }
   return NS_OK;
 }
 
 nsresult
-nsFrameMessageManager::SendAsyncMessageInternal(const nsAString& aMessage,
-                                                const StructuredCloneData& aData)
+nsFrameMessageManager::DispatchAsyncMessageInternal(const nsAString& aMessage,
+                                                    const StructuredCloneData& aData,
+                                                    ShouldBroadcast aBroadcast)
 {
   if (mAsyncCallback) {
     NS_ENSURE_TRUE(mCallbackData, NS_ERROR_NOT_INITIALIZED);
     mAsyncCallback(mCallbackData, aMessage, aData);
   }
-  int32_t len = mChildManagers.Count();
-  for (int32_t i = 0; i < len; ++i) {
-    static_cast<nsFrameMessageManager*>(mChildManagers[i])->
-      SendAsyncMessageInternal(aMessage, aData);
+  if (aBroadcast == BROADCAST) {
+    PRInt32 len = mChildManagers.Count();
+    for (PRInt32 i = 0; i < len; ++i) {
+      static_cast<nsFrameMessageManager*>(mChildManagers[i])->
+         DispatchAsyncMessageInternal(aMessage, aData, aBroadcast);
+    }
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName,
-                                        const jsval& aObject,
-                                        JSContext* aCx,
-                                        uint8_t aArgc)
+nsresult
+nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName,
+                                            const jsval& aObject,
+                                            JSContext* aCx,
+                                            uint8_t aArgc,
+                                            ShouldBroadcast aBroadcast)
 {
   StructuredCloneData data;
   JSAutoStructuredCloneBuffer buffer;
 
   if (aArgc >= 2 &&
       !GetParamsForMessage(aCx, aObject, buffer, data.mClosure)) {
     return NS_ERROR_DOM_DATA_CLONE_ERR;
   }
 
   data.mData = buffer.data();
   data.mDataLength = buffer.nbytes();
 
-  return SendAsyncMessageInternal(aMessageName, data);
+  return DispatchAsyncMessageInternal(aMessageName, data, aBroadcast);
+}
+
+
+// nsIMessageSender
+
+NS_IMETHODIMP
+nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName,
+                                        const jsval& aObject,
+                                        JSContext* aCx,
+                                        uint8_t aArgc)
+{
+  return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc, DONT_BROADCAST);
 }
 
+
+// nsIMessageBroadcaster
+
+NS_IMETHODIMP
+nsFrameMessageManager::BroadcastAsyncMessage(const nsAString& aMessageName,
+                                             const jsval& aObject,
+                                             JSContext* aCx,
+                                             uint8_t aArgc)
+{
+  return DispatchAsyncMessage(aMessageName, aObject, aCx, aArgc, BROADCAST);
+}
+
+NS_IMETHODIMP
+nsFrameMessageManager::GetChildCount(uint32_t* aChildCount)
+{
+  *aChildCount = static_cast<uint32_t>(mChildManagers.Count()); 
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFrameMessageManager::GetChildAt(uint32_t aIndex, 
+                                  nsIMessageListenerManager** aMM)
+{
+  *aMM = nullptr;
+  nsCOMPtr<nsIMessageListenerManager> mm =
+    do_QueryInterface(mChildManagers.SafeObjectAt(static_cast<uint32_t>(aIndex)));
+  mm.swap(*aMM);
+  return NS_OK;
+}
+
+
+// nsIContentFrameMessageManager
+
 NS_IMETHODIMP
 nsFrameMessageManager::Dump(const nsAString& aStr)
 {
 #ifdef ANDROID
   __android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", NS_ConvertUTF16toUTF8(aStr).get());
 #endif
 #ifdef XP_WIN
   if (IsDebuggerPresent()) {
@@ -324,47 +397,30 @@ nsFrameMessageManager::GetContent(nsIDOM
 NS_IMETHODIMP
 nsFrameMessageManager::GetDocShell(nsIDocShell** aDocShell)
 {
   *aDocShell = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsFrameMessageManager::GetChildCount(uint32_t* aChildCount)
-{
-  *aChildCount = static_cast<uint32_t>(mChildManagers.Count()); 
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsFrameMessageManager::GetChildAt(uint32_t aIndex, 
-                                  nsITreeItemFrameMessageManager** aMM)
-{
-  *aMM = nullptr;
-  nsCOMPtr<nsITreeItemFrameMessageManager> mm =
-    do_QueryInterface(mChildManagers.SafeObjectAt(static_cast<uint32_t>(aIndex)));
-  mm.swap(*aMM);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsFrameMessageManager::Btoa(const nsAString& aBinaryData,
                             nsAString& aAsciiBase64String)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameMessageManager::Atob(const nsAString& aAsciiString,
                             nsAString& aBinaryData)
 {
   return NS_OK;
 }
 
+
 class MMListenerRemover
 {
 public:
   MMListenerRemover(nsFrameMessageManager* aMM)
     : mWasHandlingMessage(aMM->mHandlingMessage)
     , mMM(aMM)
   {
     mMM->mHandlingMessage = true;
@@ -378,16 +434,19 @@ public:
       }
     }
   }
 
   bool mWasHandlingMessage;
   nsRefPtr<nsFrameMessageManager> mMM;
 };
 
+
+// nsIMessageListener
+
 nsresult
 nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
                                       const nsAString& aMessage,
                                       bool aSync,
                                       const StructuredCloneData* aCloneData,
                                       JSObject* aObjectsArray,
                                       InfallibleTArray<nsString>* aJSONRetVal,
                                       JSContext* aContext)
@@ -586,27 +645,29 @@ nsFrameMessageManager::Disconnect(bool a
   mCallbackData = nullptr;
   mContext = nullptr;
   if (!mHandlingMessage) {
     mListeners.Clear();
   }
 }
 
 nsresult
-NS_NewGlobalMessageManager(nsIChromeFrameMessageManager** aResult)
+NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult)
 {
   NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE);
-  nsFrameMessageManager* mm = new nsFrameMessageManager(true,
+  nsFrameMessageManager* mm = new nsFrameMessageManager(true /* aChrome */,
                                                         nullptr,
                                                         nullptr,
                                                         nullptr,
                                                         nullptr,
                                                         nullptr,
                                                         nullptr,
-                                                        true);
+                                                        true /* aGlobal */,
+                                                        false /* aProcessManager */,
+                                                        true /* aBroadcaster */);
   NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY);
   return CallQueryInterface(mm, aResult);
 }
 
 void
 ContentScriptErrorReporter(JSContext* aCx,
                            const char* aMessage,
                            JSErrorReport* aReport)
@@ -1129,78 +1190,79 @@ bool SendAsyncMessageToSameProcessParent
     new nsAsyncMessageToSameProcessParent(aMessage, aData);
   nsFrameMessageManager::sPendingSameProcessAsyncMessages->AppendElement(ev);
   NS_DispatchToCurrentThread(ev);
   return true;
 }
 
 // This creates the global parent process message manager.
 nsresult
-NS_NewParentProcessMessageManager(nsIFrameMessageManager** aResult)
+NS_NewParentProcessMessageManager(nsIMessageBroadcaster** aResult)
 {
   NS_ASSERTION(!nsFrameMessageManager::sParentProcessManager,
                "Re-creating sParentProcessManager");
   NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE);
-  nsRefPtr<nsFrameMessageManager> mm = new nsFrameMessageManager(true,
+  nsRefPtr<nsFrameMessageManager> mm = new nsFrameMessageManager(true /* aChrome */,
                                                                  nullptr,
                                                                  nullptr,
                                                                  nullptr,
                                                                  nullptr,
                                                                  nullptr,
                                                                  nullptr,
-                                                                 false,
-                                                                 true);
+                                                                 false, /* aGlobal */
+                                                                 true /* aProcessManager */,
+                                                                 true /* aBroadcaster */);
   NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY);
   nsFrameMessageManager::sParentProcessManager = mm;
   nsFrameMessageManager::NewProcessMessageManager(nullptr); // Create same process message manager.
   return CallQueryInterface(mm, aResult);
 }
 
 nsFrameMessageManager*
 nsFrameMessageManager::NewProcessMessageManager(mozilla::dom::ContentParent* aProcess)
 {
   if (!nsFrameMessageManager::sParentProcessManager) {
-     nsCOMPtr<nsIFrameMessageManager> dummy;
+     nsCOMPtr<nsIMessageBroadcaster> dummy;
      NS_NewParentProcessMessageManager(getter_AddRefs(dummy));
   }
 
-  nsFrameMessageManager* mm = new nsFrameMessageManager(true,
+  nsFrameMessageManager* mm = new nsFrameMessageManager(true /* aChrome */,
                                                         nullptr,
                                                         aProcess ? SendAsyncMessageToChildProcess
                                                                  : SendAsyncMessageToSameProcessChild,
                                                         nullptr,
                                                         aProcess ? static_cast<void*>(aProcess)
                                                                  : static_cast<void*>(&nsFrameMessageManager::sChildProcessManager),
                                                         nsFrameMessageManager::sParentProcessManager,
                                                         nullptr,
-                                                        false,
-                                                        true);
+                                                        false, /* aGlobal */
+                                                        true /* aProcessManager */);
   if (!aProcess) {
     sSameProcessParentManager = mm;
   }
   return mm;
 }
 
 nsresult
 NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
 {
   NS_ASSERTION(!nsFrameMessageManager::sChildProcessManager,
                "Re-creating sChildProcessManager");
   bool isChrome = IsChromeProcess();
-  nsFrameMessageManager* mm = new nsFrameMessageManager(false,
+  nsFrameMessageManager* mm = new nsFrameMessageManager(false /* aChrome */,
                                                         isChrome ? SendSyncMessageToSameProcessParent
                                                                  : SendSyncMessageToParentProcess,
                                                         isChrome ? SendAsyncMessageToSameProcessParent
                                                                  : SendAsyncMessageToParentProcess,
                                                         nullptr,
                                                         &nsFrameMessageManager::sChildProcessManager,
                                                         nullptr,
                                                         nullptr,
-                                                        false,
-                                                        true);
+                                                        false /* aGlobal */,
+                                                        true /* aProcessManager */);
   NS_ENSURE_TRUE(mm, NS_ERROR_OUT_OF_MEMORY);
   nsFrameMessageManager::sChildProcessManager = mm;
   return CallQueryInterface(mm, aResult);
 }
 
 bool
 nsFrameMessageManager::MarkForCC()
 {
--- a/content/base/src/nsFrameMessageManager.h
+++ b/content/base/src/nsFrameMessageManager.h
@@ -1,16 +1,16 @@
 /* -*- 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/. */
 #ifndef nsFrameMessageManager_h__
 #define nsFrameMessageManager_h__
 
-#include "nsIFrameMessageManager.h"
+#include "nsIMessageManager.h"
 #include "nsIObserver.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsTArray.h"
 #include "nsIAtom.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsTArray.h"
@@ -30,46 +30,54 @@ struct StructuredCloneData;
 }
 
 class nsAXPCNativeCallContext;
 struct JSContext;
 struct JSObject;
 
 struct nsMessageListenerInfo
 {
-  nsCOMPtr<nsIFrameMessageListener> mListener;
+  nsCOMPtr<nsIMessageListener> mListener;
   nsCOMPtr<nsIAtom> mMessage;
 };
 
 typedef bool (*nsLoadScriptCallback)(void* aCallbackData, const nsAString& aURL);
 typedef bool (*nsSyncMessageCallback)(void* aCallbackData,
                                       const nsAString& aMessage,
                                       const mozilla::dom::StructuredCloneData& aData,
                                       InfallibleTArray<nsString>* aJSONRetVal);
 typedef bool (*nsAsyncMessageCallback)(void* aCallbackData,
                                        const nsAString& aMessage,
                                              const mozilla::dom::StructuredCloneData& aData);
 
 class nsFrameMessageManager MOZ_FINAL : public nsIContentFrameMessageManager,
-                                        public nsIChromeFrameMessageManager
+                                        public nsIMessageBroadcaster,
+                                        public nsIFrameScriptLoader
 {
   typedef mozilla::dom::StructuredCloneData StructuredCloneData;
 public:
   nsFrameMessageManager(bool aChrome,
                         nsSyncMessageCallback aSyncCallback,
                         nsAsyncMessageCallback aAsyncCallback,
                         nsLoadScriptCallback aLoadScriptCallback,
                         void* aCallbackData,
                         nsFrameMessageManager* aParentManager,
                         JSContext* aContext,
                         bool aGlobal = false,
-                        bool aProcessManager = false)
-  : mChrome(aChrome), mGlobal(aGlobal), mIsProcessManager(aProcessManager),
-    mHandlingMessage(false), mDisconnected(false), mParentManager(aParentManager),
-    mSyncCallback(aSyncCallback), mAsyncCallback(aAsyncCallback),
+                        bool aProcessManager = false,
+                        bool aBroadcaster = false)
+  : mChrome(aChrome),
+    mGlobal(aGlobal),
+    mIsProcessManager(aProcessManager),
+    mIsBroadcaster(aBroadcaster),
+    mHandlingMessage(false),
+    mDisconnected(false),
+    mParentManager(aParentManager),
+    mSyncCallback(aSyncCallback),
+    mAsyncCallback(aAsyncCallback),
     mLoadScriptCallback(aLoadScriptCallback),
     mCallbackData(aCallbackData),
     mContext(aContext)
   {
     NS_ASSERTION(mContext || (aChrome && !aParentManager) || aProcessManager,
                  "Should have mContext in non-global/non-process manager!");
     NS_ASSERTION(aChrome || !aParentManager, "Should not set parent manager!");
     // This is a bit hackish. When parent manager is global, we want
@@ -100,21 +108,22 @@ public:
         sSameProcessParentManager = nullptr;
       }
     }
   }
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFrameMessageManager,
                                            nsIContentFrameMessageManager)
-  NS_DECL_NSIFRAMEMESSAGEMANAGER
+  NS_DECL_NSIMESSAGELISTENERMANAGER
+  NS_DECL_NSIMESSAGESENDER
+  NS_DECL_NSIMESSAGEBROADCASTER
   NS_DECL_NSISYNCMESSAGESENDER
   NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
-  NS_DECL_NSICHROMEFRAMEMESSAGEMANAGER
-  NS_DECL_NSITREEITEMFRAMEMESSAGEMANAGER
+  NS_DECL_NSIFRAMESCRIPTLOADER
 
   static nsFrameMessageManager*
   NewProcessMessageManager(mozilla::dom::ContentParent* aProcess);
 
   nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
                           bool aSync, const StructuredCloneData* aCloneData,
                           JSObject* aObjectsArray,
                           InfallibleTArray<nsString>* aJSONRetVal,
@@ -125,18 +134,25 @@ public:
   void RemoveChildManager(nsFrameMessageManager* aManager)
   {
     mChildManagers.RemoveObject(aManager);
   }
 
   void Disconnect(bool aRemoveFromParent = true);
   void SetCallbackData(void* aData, bool aLoadScripts = true);
   void* GetCallbackData() { return mCallbackData; }
-  nsresult SendAsyncMessageInternal(const nsAString& aMessage,
-                                          const StructuredCloneData& aData);
+  enum ShouldBroadcast { BROADCAST, DONT_BROADCAST };
+  nsresult DispatchAsyncMessage(const nsAString& aMessageName,
+                                const jsval& aObject,
+                                JSContext* aCx,
+                                PRUint8 aArgc,
+                                ShouldBroadcast aBroadcast);
+  nsresult DispatchAsyncMessageInternal(const nsAString& aMessage,
+                                        const StructuredCloneData& aData,
+                                        ShouldBroadcast aBroadcast);
   JSContext* GetJSContext() { return mContext; }
   void SetJSContext(JSContext* aCx) { mContext = aCx; }
   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!");
@@ -152,19 +168,20 @@ public:
   static nsFrameMessageManager* GetChildProcessManager()
   {
     return sChildProcessManager;
   }
 protected:
   friend class MMListenerRemover;
   nsTArray<nsMessageListenerInfo> mListeners;
   nsCOMArray<nsIContentFrameMessageManager> mChildManagers;
-  bool mChrome;
-  bool mGlobal;
-  bool mIsProcessManager;
+  bool mChrome;     // true if we're in the chrome process
+  bool mGlobal;     // true if 
+  bool mIsProcessManager; // true if the message manager belongs to the process realm
+  bool mIsBroadcaster; // true if the message manager is a broadcaster
   bool mHandlingMessage;
   bool mDisconnected;
   nsFrameMessageManager* mParentManager;
   nsSyncMessageCallback mSyncCallback;
   nsAsyncMessageCallback mAsyncCallback;
   nsLoadScriptCallback mLoadScriptCallback;
   void* mCallbackData;
   JSContext* mContext;
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -121,17 +121,17 @@ nsresult
 nsInProcessTabChildGlobal::Init()
 {
 #ifdef DEBUG
   nsresult rv =
 #endif
   InitTabChildGlobal();
   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
                    "Couldn't initialize nsInProcessTabChildGlobal");
-  mMessageManager = new nsFrameMessageManager(false,
+  mMessageManager = new nsFrameMessageManager(false, /* aChrome */
                                               SendSyncMessageToParent,
                                               SendAsyncMessageToParent,
                                               nullptr,
                                               this,
                                               nullptr,
                                               mCx);
 
   // Set the location information for the new global, so that tools like
@@ -155,17 +155,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsInProcessTabChildGlobal,
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager)
   nsFrameScriptExecutor::Traverse(tmp, cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal)
-  NS_INTERFACE_MAP_ENTRY(nsIFrameMessageManager)
+  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(nsIScriptContextPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
--- a/content/base/src/nsInProcessTabChildGlobal.h
+++ b/content/base/src/nsInProcessTabChildGlobal.h
@@ -28,17 +28,18 @@ class nsInProcessTabChildGlobal : public
 {
 public:
   nsInProcessTabChildGlobal(nsIDocShell* aShell, nsIContent* aOwner,
                             nsFrameMessageManager* aChrome);
   virtual ~nsInProcessTabChildGlobal();
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsInProcessTabChildGlobal,
                                            nsDOMEventTargetHelper)
-  NS_FORWARD_SAFE_NSIFRAMEMESSAGEMANAGER(mMessageManager)
+  NS_FORWARD_SAFE_NSIMESSAGELISTENERMANAGER(mMessageManager)
+  NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
   NS_IMETHOD SendSyncMessage(const nsAString& aMessageName,
                              const jsval& aObject,
                              JSContext* aCx,
                              uint8_t aArgc,
                              jsval* aRetval)
   {
     return mMessageManager
       ? mMessageManager->SendSyncMessage(aMessageName, aObject, aCx, aArgc, aRetval)
--- a/content/base/test/chrome/file_bug549682.xul
+++ b/content/base/test/chrome/file_bug549682.xul
@@ -8,19 +8,22 @@ https://bugzilla.mozilla.org/show_bug.cg
 <window title="Mozilla Bug 549682"
   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 = Components.classes["@mozilla.org/globalmessagemanager;1"].getService(Components.interfaces.nsIChromeFrameMessageManager);
-  var ppm = Components.classes["@mozilla.org/parentprocessmessagemanager;1"].getService(Components.interfaces.nsIFrameMessageManager);
-  var cpm = Components.classes["@mozilla.org/childprocessmessagemanager;1"].getService(Components.interfaces.nsISyncMessageSender);
+  var global = Components.classes["@mozilla.org/globalmessagemanager;1"]
+                         .getService(Components.interfaces.nsIMessageBroadcaster);
+  var ppm = Components.classes["@mozilla.org/parentprocessmessagemanager;1"]
+                      .getService(Components.interfaces.nsIMessageBroadcaster);
+  var cpm = Components.classes["@mozilla.org/childprocessmessagemanager;1"]
+                      .getService(Components.interfaces.nsISyncMessageSender);
 
   var asyncPPML = false;
   function ppmASL(m) {
     asyncPPML = true;
   }
   var syncPPML = false;
   function ppmSL(m) {
     syncPPML = true;
@@ -31,17 +34,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   cpm.sendAsyncMessage("processmessageAsync", "");
   cpm.sendSyncMessage("processmessageSync", "");
 
   var asyncCPML = false;
   function cpmASL(m) {
     asyncCPML = true;
   }
   cpm.addMessageListener("childprocessmessage", cpmASL);
-  ppm.sendAsyncMessage("childprocessmessage", "");
+  ppm.broadcastAsyncMessage("childprocessmessage", "");
   
   function checkPMMMessages() {
     opener.wrappedJSObject.ok(asyncPPML, "should have handled async message");
     opener.wrappedJSObject.ok(syncPPML, "should have handled sync message");
     opener.wrappedJSObject.ok(asyncCPML, "should have handled async message");
     ppm.removeMessageListener("processmessageAsync", ppmASL);
     ppm.removeMessageListener("processmessageSync", ppmSL);
     cpm.removeMessageListener("childprocessmessage", cpmASL);
--- a/content/base/test/chrome/file_bug616841.xul
+++ b/content/base/test/chrome/file_bug616841.xul
@@ -25,18 +25,18 @@ https://bugzilla.mozilla.org/show_bug.cg
                       [ "D", "C" ],
                       [ "\u010C", "D" ],
                       [ "D", "\u010C" ] ];
     var nCmps = 0;
 
     function recvContentReady(m) {
       for (var i = 0; i < toCompare.length; ++i) {
         var pair = toCompare[i];
-        messageManager.sendAsyncMessage("cmp",
-                                        { i: i, a: pair[0], b: pair[1] });
+        messageManager.broadcastAsyncMessage("cmp",
+                                             { i: i, a: pair[0], b: pair[1] });
       }
     }
 
     function recvCmp(m) {
       var i = m.json.i, cmp = m.json.cmp;
       var pair = toCompare[i];
       opener.wrappedJSObject.is(pair[0].localeCompare(pair[1]), cmp, "localeCompare returned same result in frame script");
 
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -185,17 +185,16 @@
 #include "nsIContentSecurityPolicy.h"
 #include "nsSandboxFlags.h"
 
 #include "nsXULAppAPI.h"
 
 #include "nsDOMNavigationTiming.h"
 #include "nsITimedChannel.h"
 #include "mozilla/StartupTimeline.h"
-#include "nsIFrameMessageManager.h"
 
 #include "mozilla/Telemetry.h"
 #include "nsISecurityUITelemetry.h"
 
 static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
                      NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
--- a/dom/activities/src/ActivitiesService.jsm
+++ b/dom/activities/src/ActivitiesService.jsm
@@ -7,20 +7,19 @@
 const Cu = Components.utils; 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
-  return Cc["@mozilla.org/parentprocessmessagemanager;1"]
-           .getService(Ci.nsIFrameMessageManager);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
+                                   "@mozilla.org/parentprocessmessagemanager;1",
+                                   "nsIMessageBroadcaster");
 
 const EXPORTED_SYMBOLS = [];
 
 let idbGlobal = this;
 
 function debug(aMsg) { 
   //dump("-- ActivitiesService.jsm " + Date.now() + " " + aMsg + "\n");
 }
@@ -189,29 +188,29 @@ let Activities = {
   startActivity: function activities_startActivity(aMsg) {
     debug("StartActivity: " + JSON.stringify(aMsg));
 
     let successCb = function successCb(aResults) {
       debug(JSON.stringify(aResults));
 
       // We have no matching activity registered, let's fire an error.
       if (aResults.options.length === 0) {
-        ppmm.sendAsyncMessage("Activity:FireError", {
+        ppmm.broadcastAsyncMessage("Activity:FireError", {
           "id": aMsg.id,
           "error": "NO_PROVIDER"
         });
         return;
       }
 
       function getActivityChoice(aChoice) {
         debug("Activity choice: " + aChoice);
 
         // The user has cancelled the choice, fire an error.
         if (aChoice === -1) {
-          ppmm.sendAsyncMessage("Activity:FireError", {
+          ppmm.broadcastAsyncMessage("Activity:FireError", {
             "id": aMsg.id,
             "error": "USER_ABORT"
           });
           return;
         }
 
         let sysmm = Cc["@mozilla.org/system-message-internal;1"]
                       .getService(Ci.nsISystemMessagesInternal);
@@ -226,17 +225,17 @@ let Activities = {
             "id": aMsg.id,
             "payload": aMsg.options,
             "target": result.description
           },
           Services.io.newURI(result.description.href, null, null),
           Services.io.newURI(result.manifest, null, null));
 
         if (!result.description.returnValue) {
-          ppmm.sendAsyncMessage("Activity:FireSuccess", {
+          ppmm.broadcastAsyncMessage("Activity:FireSuccess", {
             "id": aMsg.id,
             "result": null
           });
         }
       };
 
       let glue = Cc["@mozilla.org/dom/activities/ui-glue;1"]
                    .createInstance(Ci.nsIActivityUIGlue);
@@ -261,28 +260,28 @@ let Activities = {
       }
       return true;
     };
 
     this.db.find(aMsg, successCb, errorCb, matchFunc);
   },
 
   receiveMessage: function activities_receiveMessage(aMessage) {
-    let mm = aMessage.target.QueryInterface(Ci.nsIFrameMessageManager);
+    let mm = aMessage.target;
     let msg = aMessage.json;
     switch(aMessage.name) {
       case "Activity:Start":
         this.startActivity(msg);
         break;
 
       case "Activity:PostResult":
-        ppmm.sendAsyncMessage("Activity:FireSuccess", msg);
+        ppmm.broadcastAsyncMessage("Activity:FireSuccess", msg);
         break;
       case "Activity:PostError":
-        ppmm.sendAsyncMessage("Activity:FireError", msg);
+        ppmm.broadcastAsyncMessage("Activity:FireError", msg);
         break;
 
       case "Activities:Register":
         this.db.add(msg, function onSuccess(aEvent) {
           mm.sendAsyncMessage("Activities:Register:OK", msg);
         },
         function onError(aEvent) {
           msg.error = "REGISTER_ERROR";
--- a/dom/activities/src/ActivityProxy.js
+++ b/dom/activities/src/ActivityProxy.js
@@ -7,21 +7,19 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/ObjectWrapper.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
-  return Cc["@mozilla.org/childprocessmessagemanager;1"]
-           .getService(Ci.nsIFrameMessageManager)
-           .QueryInterface(Ci.nsISyncMessageSender);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsISyncMessageSender");
 
 function debug(aMsg) {
   //dump("-- ActivityProxy " + Date.now() + " : " + aMsg + "\n");
 }
 
 /**
   * nsIActivityProxy implementation
   * We keep a reference to the C++ Activity object, and
--- a/dom/activities/src/ActivityRequestHandler.js
+++ b/dom/activities/src/ActivityRequestHandler.js
@@ -5,21 +5,19 @@
 "use strict";
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
-  return Cc["@mozilla.org/childprocessmessagemanager;1"]
-           .getService(Ci.nsIFrameMessageManager)
-           .QueryInterface(Ci.nsISyncMessageSender);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsISyncMessageSender");
 
 function debug(aMsg) {
   //dump("-- ActivityRequestHandler.js " + Date.now() + " : " + aMsg + "\n");
 }
 
 /**
   * nsIDOMMozActivityRequestHandler implementation.
   */
--- a/dom/alarm/AlarmService.jsm
+++ b/dom/alarm/AlarmService.jsm
@@ -15,19 +15,19 @@ function debug(aStr) {
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/AlarmDB.jsm");
 
 let EXPORTED_SYMBOLS = ["AlarmService"];
 
-XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
-  return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
+                                   "@mozilla.org/parentprocessmessagemanager;1",
+                                   "nsIMessageListenerManager");
 
 XPCOMUtils.defineLazyGetter(this, "messenger", function() {
   return Cc["@mozilla.org/system-message-internal;1"].getService(Ci.nsISystemMessagesInternal);
 });
 
 let myGlobal = this;
 
 let AlarmService = {
@@ -70,17 +70,17 @@ let AlarmService = {
 
     if (!this._alarmHalService.setAlarm(this._getAlarmTime(aAlarm) / 1000, 0))
       throw Components.results.NS_ERROR_FAILURE;
   },
 
   receiveMessage: function receiveMessage(aMessage) {
     debug("receiveMessage(): " + aMessage.name);
 
-    let mm = aMessage.target.QueryInterface(Ci.nsIFrameMessageManager);
+    let mm = aMessage.target.QueryInterface(Ci.nsIMessageSender);
     let json = aMessage.json;
     switch (aMessage.name) {
       case "AlarmsManager:GetAll":
         this._db.getAll(
           json.manifestURL,
           function getAllSuccessCb(aAlarms) {
             debug("Callback after getting alarms from database: " + JSON.stringify(aAlarms));
             this._sendAsyncMessage(mm, "GetAll", true, json.requestId, aAlarms);
--- a/dom/apps/src/AppsService.js
+++ b/dom/apps/src/AppsService.js
@@ -21,18 +21,17 @@ function AppsService()
   debug("AppsService Constructor");
   this.inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
                   .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
   debug("inParent: " + this.inParent);
   if (this.inParent) {
     Cu.import("resource://gre/modules/Webapps.jsm");
   } else {
     this.cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
-                .getService(Ci.nsIFrameMessageManager)
-                .QueryInterface(Ci.nsISyncMessageSender);
+                .getService(Ci.nsISyncMessageSender);
   }
 }
 
 AppsService.prototype = {
   getAppByManifestURL: function getAppByManifestURL(aManifestURL) {
     debug("GetAppByManifestURL( " + aManifestURL + " )");
     if (this.inParent) {
       return DOMApplicationRegistry.getAppByManifestURL(aManifestURL);
--- a/dom/apps/src/Webapps.js
+++ b/dom/apps/src/Webapps.js
@@ -7,19 +7,19 @@ const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
 Cu.import("resource://gre/modules/ObjectWrapper.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
-  return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsIMessageSender");
 
 function convertAppsArray(aApps, aWindow) {
   let apps = Cu.createArrayIn(aWindow);
   for (let i = 0; i < aApps.length; i++) {
     let app = aApps[i];
     apps.push(createApplicationObject(aWindow, app.origin, app.manifest, app.manifestURL, 
                                       app.receipts, app.installOrigin, app.installTime));
   }
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -18,24 +18,23 @@ Cu.import('resource://gre/modules/Activi
 
 const WEBAPP_RUNTIME = Services.appinfo.ID == "webapprt@mozilla.org";
 
 XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
   Cu.import("resource://gre/modules/NetUtil.jsm");
   return NetUtil;
 });
 
-XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
-  return Cc["@mozilla.org/parentprocessmessagemanager;1"]
-         .getService(Ci.nsIFrameMessageManager);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
+                                   "@mozilla.org/parentprocessmessagemanager;1",
+                                   "nsIMessageBroadcaster");
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
                                    "@mozilla.org/childprocessmessagemanager;1",
-                                   "nsIFrameMessageManager");
+                                   "nsIMessageSender");
 
 XPCOMUtils.defineLazyGetter(this, "msgmgr", function() {
   return Cc["@mozilla.org/system-message-internal;1"]
          .getService(Ci.nsISystemMessagesInternal);
 });
 
 #ifdef MOZ_WIDGET_GONK
   const DIRECTORY_NAME = "webappsDir";
@@ -238,17 +237,17 @@ let DOMApplicationRegistry = {
         break;
       case "Webapps:GetNotInstalled":
         this.getNotInstalled(msg);
         break;
       case "Webapps:GetAll":
         if (msg.hasPrivileges)
           this.getAll(msg);
         else
-          ppmm.sendAsyncMessage("Webapps:GetAll:Return:KO", msg);
+          ppmm.broadcastAsyncMessage("Webapps:GetAll:Return:KO", msg);
         break;
       case "Webapps:InstallPackage":
         this.installPackage(msg);
         break;
       case "Webapps:GetBasePath":
         return FileUtils.getFile(DIRECTORY_NAME, ["webapps"], true).path;
         break;
       case "WebApps:GetAppByManifestURL":
@@ -302,17 +301,17 @@ let DOMApplicationRegistry = {
     if (packageId) {
       let dir = FileUtils.getDir("TmpD", ["webapps", packageId],
                                  true, true);
       try {
         dir.remove(true);
       } catch(e) {
       }
     }
-    ppmm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
+    ppmm.broadcastAsyncMessage("Webapps:Install:Return:KO", aData);
   },
 
   confirmInstall: function(aData, aFromSync, aProfileDir, aOfflineCacheObserver) {
     let app = aData.app;
     let id = app.syncId || this._appId(app.origin);
     let localId = this.getAppLocalIdByManifestURL(app.manifestURL);
 
     // Installing an application again is considered as an update.
@@ -360,17 +359,17 @@ let DOMApplicationRegistry = {
     this.webapps[id] = appObject;
 
     appObject.status = "installed";
     
     let manifest = new DOMApplicationManifest(app.manifest, app.origin);
 
     if (!aFromSync)
       this._saveApps((function() {
-        ppmm.sendAsyncMessage("Webapps:Install:Return:OK", aData);
+        ppmm.broadcastAsyncMessage("Webapps:Install:Return:OK", aData);
         Services.obs.notifyObservers(this, "webapps-sync-install", appNote);
       }).bind(this));
 
 #ifdef MOZ_SYS_MSG
     this._registerSystemMessages(id, app);
 #endif
 
     // if the manifest has an appcache_path property, use it to populate the appcache
@@ -487,17 +486,17 @@ let DOMApplicationRegistry = {
       return true;
     }
 
     // Removes the directory we created, and sends an error to the DOM side.
     function cleanup(aError) {
       try {
         dir.remove(true);
       } catch (e) { }
-      ppmm.sendAsyncMessage("Webapps:Install:Return:KO",
+      ppmm.broadcastAsyncMessage("Webapps:Install:Return:KO",
                             { oid: aData.oid,
                               requestID: aData.requestID,
                               error: aError });
     }
 
     NetUtil.asyncFetch(aData.url, function(aInput, aResult, aRequest) {
       if (!Components.isSuccessCode(aResult)) {
         // We failed to fetch the zip.
@@ -579,23 +578,23 @@ let DOMApplicationRegistry = {
       let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
       try {
         dir.remove(true);
       } catch (e) {}
 
       delete this.webapps[id];
 
       this._saveApps((function() {
-        ppmm.sendAsyncMessage("Webapps:Uninstall:Return:OK", aData);
+        ppmm.broadcastAsyncMessage("Webapps:Uninstall:Return:OK", aData);
         Services.obs.notifyObservers(this, "webapps-sync-uninstall", appNote);
       }).bind(this));
     }
 
     if (!found) {
-      ppmm.sendAsyncMessage("Webapps:Uninstall:Return:KO", aData);
+      ppmm.broadcastAsyncMessage("Webapps:Uninstall:Return:KO", aData);
     }
   },
 
   getSelf: function(aData) {
     aData.apps = [];
     let tmp = [];
     let id = this._appId(aData.origin);
 
@@ -603,17 +602,17 @@ let DOMApplicationRegistry = {
       let app = this._cloneAppObject(this.webapps[id]);
       aData.apps.push(app);
       tmp.push({ id: id });
     }
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
-      ppmm.sendAsyncMessage("Webapps:GetSelf:Return:OK", aData);
+      ppmm.broadcastAsyncMessage("Webapps:GetSelf:Return:OK", aData);
     }).bind(this));
   },
 
   getInstalled: function(aData) {
     aData.apps = [];
     let tmp = [];
 
     for (let id in this.webapps) {
@@ -622,17 +621,17 @@ let DOMApplicationRegistry = {
         aData.apps.push(this._cloneAppObject(this.webapps[id]));
         tmp.push({ id: id });
       }
     }
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
-      ppmm.sendAsyncMessage("Webapps:GetInstalled:Return:OK", aData);
+      ppmm.broadcastAsyncMessage("Webapps:GetInstalled:Return:OK", aData);
     }).bind(this));
   },
 
   getNotInstalled: function(aData) {
     aData.apps = [];
     let tmp = [];
 
     for (let id in this.webapps) {
@@ -640,17 +639,17 @@ let DOMApplicationRegistry = {
         aData.apps.push(this._cloneAppObject(this.webapps[id]));
         tmp.push({ id: id });
       }
     }
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
-      ppmm.sendAsyncMessage("Webapps:GetNotInstalled:Return:OK", aData);
+      ppmm.broadcastAsyncMessage("Webapps:GetNotInstalled:Return:OK", aData);
     }).bind(this));
   },
 
   getAll: function(aData) {
     aData.apps = [];
     let tmp = [];
 
     for (let id in this.webapps) {
@@ -660,17 +659,17 @@ let DOMApplicationRegistry = {
 
       aData.apps.push(app);
       tmp.push({ id: id });
     }
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
-      ppmm.sendAsyncMessage("Webapps:GetAll:Return:OK", aData);
+      ppmm.broadcastAsyncMessage("Webapps:GetAll:Return:OK", aData);
     }).bind(this));
   },
 
   getManifestFor: function(aOrigin, aCallback) {
     if (!aCallback)
       return;
 
     let id = this._appId(aOrigin);
@@ -778,25 +777,25 @@ let DOMApplicationRegistry = {
           continue;
         let origin = this.webapps[record.id].origin;
         delete this.webapps[record.id];
         let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", record.id], true, true);
         try {
           dir.remove(true);
         } catch (e) {
         }
-        ppmm.sendAsyncMessage("Webapps:Uninstall:Return:OK", { origin: origin });
+        ppmm.broadcastAsyncMessage("Webapps:Uninstall:Return:OK", { origin: origin });
       } else {
         if (this.webapps[record.id]) {
           this.webapps[record.id] = record.value;
           delete this.webapps[record.id].manifest;
         } else {
           let data = { app: record.value };
           this.confirmInstall(data, true);
-          ppmm.sendAsyncMessage("Webapps:Install:Return:OK", data);
+          ppmm.broadcastAsyncMessage("Webapps:Install:Return:OK", data);
         }
       }
     }
     this._saveApps(aCallback);
   },
 
   getAllIDs: function() {
     let apps = {};
@@ -888,17 +887,17 @@ AppcacheObserver.prototype = {
   // nsIOfflineCacheUpdateObserver implementation
   updateStateChanged: function appObs_Update(aUpdate, aState) {
     let mustSave = false;
     let app = this.app;
 
     let setStatus = function appObs_setStatus(aStatus) {
       mustSave = (app.status != aStatus);
       app.status = aStatus;
-      ppmm.sendAsyncMessage("Webapps:OfflineCache", { manifest: app.manifestURL, status: aStatus });
+      ppmm.broadcastAsyncMessage("Webapps:OfflineCache", { manifest: app.manifestURL, status: aStatus });
     }
 
     switch (aState) {
       case Ci.nsIOfflineCacheUpdateObserver.STATE_ERROR:
         aUpdate.removeObserver(this);
         setStatus("cache-error");
         break;
       case Ci.nsIOfflineCacheUpdateObserver.STATE_NOUPDATE:
--- a/dom/base/DOMRequestHelper.jsm
+++ b/dom/base/DOMRequestHelper.jsm
@@ -10,19 +10,19 @@ const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 let EXPORTED_SYMBOLS = ["DOMRequestIpcHelper"];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
-  return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsIMessageListenerManager");
 
 function DOMRequestIpcHelper() {
 }
 
 DOMRequestIpcHelper.prototype = {
   getRequestId: function(aRequest) {
     let id = "id" + this._getRandomId();
     this._requests[id] = aRequest;
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -456,17 +456,17 @@
 #include "nsPluginArray.h"
 #include "nsMimeTypeArray.h"
 
 // Simple gestures include
 #include "nsIDOMSimpleGestureEvent.h"
 #include "nsIDOMMozTouchEvent.h"
 
 #include "nsIEventListenerService.h"
-#include "nsIFrameMessageManager.h"
+#include "nsIMessageManager.h"
 #include "mozilla/dom/Element.h"
 #include "nsHTMLSelectElement.h"
 #include "nsHTMLLegendElement.h"
 
 #include "DOMSVGStringList.h"
 
 #include "mozilla/dom/indexedDB/IDBWrapperCache.h"
 #include "mozilla/dom/indexedDB/IDBFactory.h"
@@ -635,16 +635,18 @@ static const char kDOMStringBundleURL[] 
 #define DOMCI_DATA_NO_CLASS(_dom_class)                                       \
 const uint32_t kDOMClassInfo_##_dom_class##_interfaces =                      \
   0;
 
 DOMCI_DATA_NO_CLASS(Crypto)
 DOMCI_DATA_NO_CLASS(CRMFObject)
 DOMCI_DATA_NO_CLASS(SmartCardEvent)
 DOMCI_DATA_NO_CLASS(ContentFrameMessageManager)
+DOMCI_DATA_NO_CLASS(ChromeMessageBroadcaster)
+DOMCI_DATA_NO_CLASS(ChromeMessageSender)
 
 DOMCI_DATA_NO_CLASS(DOMPrototype)
 DOMCI_DATA_NO_CLASS(DOMConstructor)
 
 #define NS_DEFINE_CLASSINFO_DATA_WITH_NAME(_class, _name, _helper,            \
                                            _flags)                            \
   { #_name,                                                                   \
     nullptr,                                                                   \
@@ -1590,18 +1592,23 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(ScrollAreaEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(EventListenerInfo, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(TransitionEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(AnimationEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(ContentFrameMessageManager, nsEventTargetSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS | nsIXPCScriptable::IS_GLOBAL_OBJECT)
+  NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentFrameMessageManager, nsEventTargetSH,
+                                       DOM_DEFAULT_SCRIPTABLE_FLAGS |
+                                       nsIXPCScriptable::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_CLASSINFO_DATA(FormData, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(DesktopNotification, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(DesktopNotificationCenter, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -4300,23 +4307,36 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(AnimationEvent, nsIDOMAnimationEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMAnimationEvent)
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentFrameMessageManager, nsIContentFrameMessageManager)
+  DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentFrameMessageManager, nsISupports)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-    DOM_CLASSINFO_MAP_ENTRY(nsIFrameMessageManager)
+    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(ChromeMessageBroadcaster, nsISupports)
+    DOM_CLASSINFO_MAP_ENTRY(nsIFrameScriptLoader)
+    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(nsIMessageListenerManager)
+    DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender)
+  DOM_CLASSINFO_MAP_END
+
   DOM_CLASSINFO_MAP_BEGIN(FormData, nsIDOMFormData)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMFormData)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DesktopNotification, nsIDOMDesktopNotification)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDesktopNotification)
   DOM_CLASSINFO_MAP_END
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -470,16 +470,18 @@ DOMCI_CLASS(PaintRequestList)
 DOMCI_CLASS(ScrollAreaEvent)
 
 DOMCI_CLASS(EventListenerInfo)
 
 DOMCI_CLASS(TransitionEvent)
 DOMCI_CLASS(AnimationEvent)
 
 DOMCI_CLASS(ContentFrameMessageManager)
+DOMCI_CLASS(ChromeMessageBroadcaster)
+DOMCI_CLASS(ChromeMessageSender)
 
 DOMCI_CLASS(FormData)
 
 DOMCI_CLASS(DesktopNotification)
 DOMCI_CLASS(DesktopNotificationCenter)
 
 // WebSocket
 DOMCI_CLASS(WebSocket)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -10952,34 +10952,37 @@ nsGlobalChromeWindow::NotifyDefaultButto
     return NS_OK;
   return rv;
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif
 }
 
 NS_IMETHODIMP
-nsGlobalChromeWindow::GetMessageManager(nsIChromeFrameMessageManager** aManager)
+nsGlobalChromeWindow::GetMessageManager(nsIMessageBroadcaster** aManager)
 {
   FORWARD_TO_INNER_CHROME(GetMessageManager, (aManager), NS_ERROR_FAILURE);
   if (!mMessageManager) {
     nsIScriptContext* scx = GetContextInternal();
     NS_ENSURE_STATE(scx);
     JSContext* cx = scx->GetNativeContext();
     NS_ENSURE_STATE(cx);
-    nsCOMPtr<nsIChromeFrameMessageManager> globalMM =
+    nsCOMPtr<nsIMessageBroadcaster> globalMM =
       do_GetService("@mozilla.org/globalmessagemanager;1");
     mMessageManager =
-      new nsFrameMessageManager(true,
+      new nsFrameMessageManager(true, /* aChrome */
                                 nullptr,
                                 nullptr,
                                 nullptr,
                                 nullptr,
                                 static_cast<nsFrameMessageManager*>(globalMM.get()),
-                                cx);
+                                cx,
+                                false, /* aGlobal */
+                                false, /* aProcessManager */
+                                true /* aBroadcaster */);
     NS_ENSURE_TRUE(mMessageManager, NS_ERROR_OUT_OF_MEMORY);
   }
   CallQueryInterface(mMessageManager, aManager);
   return NS_OK;
 }
 
 // nsGlobalModalWindow implementation
 
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -1130,17 +1130,17 @@ public:
 
     mCleanMessageManager = false;
   }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsGlobalChromeWindow,
                                            nsGlobalWindow)
 
   nsCOMPtr<nsIBrowserDOMWindow> mBrowserDOMWindow;
-  nsCOMPtr<nsIChromeFrameMessageManager> mMessageManager;
+  nsCOMPtr<nsIMessageBroadcaster> mMessageManager;
 };
 
 /*
  * nsGlobalModalWindow inherits from nsGlobalWindow. It is the global
  * object created for a modal content windows only (i.e. not modal
  * chrome dialogs).
  */
 class nsGlobalModalWindow : public nsGlobalWindow,
--- a/dom/contacts/ContactManager.js
+++ b/dom/contacts/ContactManager.js
@@ -14,19 +14,19 @@ const Cu = Components.utils;
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
 
 XPCOMUtils.defineLazyGetter(Services, "DOMRequest", function() {
   return Cc["@mozilla.org/dom/dom-request-service;1"].getService(Ci.nsIDOMRequestService);
 });
 
-XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
-  return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsIMessageSender");
 
 XPCOMUtils.defineLazyGetter(this, "mRIL", function () {
   return Cc["@mozilla.org/telephony/system-worker-manager;1"].getService(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIRadioInterfaceLayer);
 });
 
 const nsIClassInfo            = Ci.nsIClassInfo;
 const CONTACTPROPERTIES_CID   = Components.ID("{f5181640-89e8-11e1-b0c4-0800200c9a66}");
 const nsIDOMContactProperties = Ci.nsIDOMContactProperties;
--- a/dom/contacts/fallback/ContactService.jsm
+++ b/dom/contacts/fallback/ContactService.jsm
@@ -12,19 +12,19 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 let EXPORTED_SYMBOLS = ["DOMContactManager"];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/ContactDB.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
-  return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
+                                   "@mozilla.org/parentprocessmessagemanager;1",
+                                   "nsIMessageListenerManager");
 
 let myGlobal = this;
 
 let DOMContactManager = {
   init: function() {
     if (DEBUG) debug("Init");
     this._messages = ["Contacts:Find", "Contacts:Clear", "Contact:Save", "Contact:Remove"];
     this._messages.forEach((function(msgName) {
@@ -49,17 +49,17 @@ let DOMContactManager = {
     this._messages = null;
     if (this._db)
       this._db.close();
     this._db = null;
   },
 
   receiveMessage: function(aMessage) {
     if (DEBUG) debug("Fallback DOMContactManager::receiveMessage " + aMessage.name);
-    let mm = aMessage.target.QueryInterface(Ci.nsIFrameMessageManager);
+    let mm = aMessage.target;
     let msg = aMessage.data;
 
     /*
      * Sorting the contacts by sortBy field. sortBy can either be familyName or givenName.
      * If 2 entries have the same sortyBy field or no sortBy field is present, we continue 
      * sorting with the other sortyBy field.
      */
     function sortfunction(a, b){
--- a/dom/devicestorage/ipc/test_ipc.html
+++ b/dom/devicestorage/ipc/test_ipc.html
@@ -95,17 +95,17 @@
         iframe.addEventListener("mozbrowserloadend", iframeLoadSecond);
 
         let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
 
         let comp = SpecialPowers.wrap(Components);
 
         let spObserver =
           comp.classes["@mozilla.org/special-powers-observer;1"]
-              .getService(comp.interfaces.nsIFrameMessageListener);
+              .getService(comp.interfaces.nsIMessageListener);
 
         mm.addMessageListener("SPPrefService", spObserver);
         mm.addMessageListener("SPProcessCrashService", spObserver);
         mm.addMessageListener("SPPingService", spObserver);
         mm.addMessageListener("SpecialPowers.Quit", spObserver);
         mm.addMessageListener("SPPermissionManager", spObserver);
 
         mm.addMessageListener("test:DeviceStorage:ipcTestMessage", onTestMessage);
--- a/dom/identity/DOMIdentity.jsm
+++ b/dom/identity/DOMIdentity.jsm
@@ -111,17 +111,17 @@ RPWatchContext.prototype = {
   },
 
   doError: function RPWatchContext_onerror(aMessage) {
     log("doError: " + aMessage);
   }
 };
 
 let DOMIdentity = {
-  // nsIFrameMessageListener
+  // nsIMessageListener
   receiveMessage: function DOMIdentity_receiveMessage(aMessage) {
     let msg = aMessage.json;
 
     // Target is the frame message manager that called us and is
     // used to send replies back to the proper window.
     let targetMM = aMessage.target
                            .QueryInterface(Ci.nsIFrameLoaderOwner)
                            .frameLoader.messageManager;
@@ -195,17 +195,17 @@ let DOMIdentity = {
   _configureMessages: function DOMIdentity__configureMessages(aWindow, aRegister) {
     if (!aWindow.messageManager)
       return;
 
     let func = aWindow.messageManager[aRegister ? "addMessageListener"
                                                 : "removeMessageListener"];
 
     for (let message of this.messages) {
-      func(message, this);
+      func.call(aWindow.messageManager, message, this);
     }
   },
 
   _resetFrameState: function(aContext) {
     log("_resetFrameState: ", aContext.id);
     if (!aContext._mm) {
       throw new Error("ERROR: Trying to reset an invalid context");
     }
--- a/dom/identity/nsDOMIdentity.js
+++ b/dom/identity/nsDOMIdentity.js
@@ -415,17 +415,17 @@ nsDOMIdentity.prototype = {
 
 /**
  * Internal functions that shouldn't be exposed to content.
  */
 function nsDOMIdentityInternal() {
 }
 nsDOMIdentityInternal.prototype = {
 
-  // nsIFrameMessageListener
+  // nsIMessageListener
   receiveMessage: function nsDOMIdentityInternal_receiveMessage(aMessage) {
     let msg = aMessage.json;
     // Is this message intended for this window?
     if (msg.id != this._id) {
       return;
     }
     this._identity._receiveMessage(aMessage);
   },
@@ -510,17 +510,17 @@ nsDOMIdentityInternal.prototype = {
     }
     dump("nsDOMIdentity (" + this._id + "): " + msg + "\n");
   },
 
   // Component setup.
   classID: Components.ID("{8bcac6a3-56a4-43a4-a44c-cdf42763002f}"),
 
   QueryInterface: XPCOMUtils.generateQI(
-    [Ci.nsIDOMGlobalPropertyInitializer, Ci.nsIFrameMessageListener]
+    [Ci.nsIDOMGlobalPropertyInitializer, Ci.nsIMessageListener]
   ),
 
   classInfo: XPCOMUtils.generateCI({
     classID: Components.ID("{8bcac6a3-56a4-43a4-a44c-cdf42763002f}"),
     contractID: "@mozilla.org/dom/identity;1",
     interfaces: [],
     classDescription: "Identity DOM Implementation"
   })
--- a/dom/indexedDB/ipc/test_ipc.html
+++ b/dom/indexedDB/ipc/test_ipc.html
@@ -109,17 +109,17 @@
         iframe.addEventListener("mozbrowserloadend", iframeLoadSecond);
 
         let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
 
         let comp = SpecialPowers.wrap(Components);
 
         let spObserver =
           comp.classes["@mozilla.org/special-powers-observer;1"]
-              .getService(comp.interfaces.nsIFrameMessageListener);
+              .getService(comp.interfaces.nsIMessageListener);
 
         mm.addMessageListener("SPPrefService", spObserver);
         mm.addMessageListener("SPProcessCrashService", spObserver);
         mm.addMessageListener("SPPingService", spObserver);
         mm.addMessageListener("SpecialPowers.Quit", spObserver);
         mm.addMessageListener("SPPermissionManager", spObserver);
 
         mm.addMessageListener("test:indexedDB:ipcTestMessage", onTestMessage);
--- a/dom/interfaces/base/nsIDOMChromeWindow.idl
+++ b/dom/interfaces/base/nsIDOMChromeWindow.idl
@@ -3,19 +3,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/. */
 
 #include "domstubs.idl"
 
 interface nsIBrowserDOMWindow;
 interface nsIDOMElement;
 interface nsIDOMEvent;
-interface nsIChromeFrameMessageManager;
+interface nsIMessageBroadcaster;
 
-[scriptable, uuid(7cfbc355-cbf9-4408-8e4c-a3c603ff1428)]
+[scriptable, uuid(6ff5df67-22da-4379-bf57-da775dad19f8)]
 interface nsIDOMChromeWindow : nsISupports
 {
   const unsigned short STATE_MAXIMIZED = 1;
   const unsigned short STATE_MINIMIZED = 2;
   const unsigned short STATE_NORMAL = 3;
   const unsigned short STATE_FULLSCREEN = 4;
 
   readonly attribute unsigned short              windowState;
@@ -38,17 +38,17 @@ interface nsIDOMChromeWindow : nsISuppor
   void                      restore();
 
   /**
    * Notify a default button is loaded on a dialog or a wizard.
    * defaultButton is the default button.
    */
   void notifyDefaultButtonLoaded(in nsIDOMElement defaultButton);
 
-  readonly attribute nsIChromeFrameMessageManager messageManager;
+  readonly attribute nsIMessageBroadcaster messageManager;
 
   /**
    * 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/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1367,17 +1367,17 @@ TabChildGlobal::TabChildGlobal(TabChild*
 : mTabChild(aTabChild)
 {
 }
 
 void
 TabChildGlobal::Init()
 {
   NS_ASSERTION(!mMessageManager, "Re-initializing?!?");
-  mMessageManager = new nsFrameMessageManager(false,
+  mMessageManager = new nsFrameMessageManager(false, /* aChrome */
                                               SendSyncMessageToParent,
                                               SendAsyncMessageToParent,
                                               nullptr,
                                               mTabChild,
                                               nullptr,
                                               mTabChild->GetJSContext());
 }
 
@@ -1389,17 +1389,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TabChildGlobal,
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChildGlobal)
-  NS_INTERFACE_MAP_ENTRY(nsIFrameMessageManager)
+  NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
+  NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIScriptContextPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(TabChildGlobal, nsDOMEventTargetHelper)
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -67,17 +67,18 @@ class TabChildGlobal : public nsDOMEvent
                        public nsIScriptObjectPrincipal,
                        public nsIScriptContextPrincipal
 {
 public:
   TabChildGlobal(TabChild* aTabChild);
   void Init();
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TabChildGlobal, nsDOMEventTargetHelper)
-  NS_FORWARD_SAFE_NSIFRAMEMESSAGEMANAGER(mMessageManager)
+  NS_FORWARD_SAFE_NSIMESSAGELISTENERMANAGER(mMessageManager)
+  NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
   NS_IMETHOD SendSyncMessage(const nsAString& aMessageName,
                              const jsval& aObject,
                              JSContext* aCx,
                              uint8_t aArgc,
                              jsval* aRetval)
   {
     return mMessageManager
       ? mMessageManager->SendSyncMessage(aMessageName, aObject, aCx, aArgc, aRetval)
--- a/dom/ipc/test.xul
+++ b/dom/ipc/test.xul
@@ -92,27 +92,26 @@
     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(Components.interfaces.nsIFrameMessageManager);
+                          .getService(Components.interfaces.nsIMessageBroadcaster);
       var gm = Components.classes["@mozilla.org/globalmessagemanager;1"]
-                         .getService(Components.interfaces.nsIChromeFrameMessageManager);
+                         .getService(Components.interfaces.nsIMessageBroadcaster);
       var cpm = Components.classes["@mozilla.org/childprocessmessagemanager;1"]
-                            .getService(Components.interfaces.nsISyncMessageSender);  
+                            .getService(Components.interfaces.nsISyncMessageSender);
 
-      var tppm = ppm.QueryInterface(Components.interfaces.nsITreeItemFrameMessageManager);
-      if (tppm.childCount != 2) {
+      if (ppm.childCount != 2) {
         alert("Should have two child processes!");
       }
-      var childprocessmm = tppm.getChildAt(1); // 0 is the in-process child process mm
+      var childprocessmm = ppm.getChildAt(1); // 0 is the in-process child process mm
       
       childprocessmm.addMessageListener("ppm-sync",
         function(m) {
           if (m.target != childprocessmm) alert("Wrong target!");
           document.getElementById("messageLog").value += "[SYNC1 PPM]"; 
         }
       );
       
@@ -156,17 +155,17 @@
       // 4. Test that receiving an async message works.
       //    Test also that sending async message to content works.
       //    Test also that { receiveMessage: function(m) {} } works.
       messageManager.addMessageListener("linkclick-reply-object",
         { foobarObjectVar: true,
           receiveMessage: function(m) {
             var s = (m.json.message == "linkclick-received") &amp;&amp;
                     (this.foobarObjectVar) ? "PASS" : "FAIL";
-            messageManager.sendAsyncMessage("chrome-message", { ok : s } );
+            messageManager.broadcastAsyncMessage("chrome-message", { ok : s } );
           }
         }
         );
 
       // 5. Final test to check that everything went ok.
       messageManager.addMessageListener("chrome-message-reply",
         function(m) {
           // Check that 'this' and .target values are handled correctly
@@ -192,17 +191,17 @@
         });
     }
 
     var speedTestStartTime = 0;
     var speedTestCount = 0;
     function messageSpeed() {
       speedTestCount = 0;
       messageManager.addMessageListener("speed-test", speedHandler);
-      messageManager.sendAsyncMessage("speed-test-start");
+      messageManager.broadcastAsyncMessage("speed-test-start");
     }
 
     function speedHandler() {
       if (!speedTestCount) {
         speedTestStartTime = new Date().getTime();
       }
       if (++speedTestCount == 1000) {
         setTimeout("alert('" + speedTestCount + " in "  + (new Date().getTime() - speedTestStartTime) +  "ms')", 0);
@@ -212,26 +211,26 @@
     }
 
     var addRemoveTestCount = 0;
 
     function echoListener() {
       if (++addRemoveTestCount == 1) {
         alert("Expected echo message");
         messageManager.removeMessageListener("async-echo", echoListener);
-        messageManager.sendAsyncMessage("async-echo");
+        messageManager.broadcastAsyncMessage("async-echo");
         return;
       }
       alert("Unexpected echo message");
     }
 
     function listenerAddRemove() {
       addRemoveTestCount = 0;
       messageManager.addMessageListener("async-echo", echoListener);
-      messageManager.sendAsyncMessage("async-echo");
+      messageManager.broadcastAsyncMessage("async-echo");
     }
 
     var MozAfterPaintCount = 0;
     function enableMozAfterPaint() {
       messageManager.addMessageListener("MozAfterPaint",
         function(m) {
           document.getElementById("messageLog").value = m.name + "[" + (++MozAfterPaintCount) + "]";
         });
@@ -281,18 +280,20 @@
     <toolbarbutton onclick="messageSpeed()" label="test message handling speed"/>
     <toolbarbutton onclick="listenerAddRemove()" label="test listener add/remove"/>
     <toolbarbutton onclick="enableMozAfterPaint()" label="MozAfterPaint"/>
     <toolbarbutton onclick="openWindow()" label="open new window"/>
     <toolbarbutton onclick="closeWindow()" label="close this window"/>
   </toolbar>
   <toolbar><label value="Load a script (URL) to content process:"/>
     <textbox flex="1" id="script"/><button
-      label="send" oncommand="document.getElementById('page').QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader.
-                              messageManager.loadFrameScript(this.previousSibling.value, false);"/>
+      label="send" oncommand="document.getElementById('page')
+                                      .QueryInterface(Components.interfaces.nsIFrameLoaderOwner)
+                                      .frameLoader.messageManager
+                                      .loadFrameScript(this.previousSibling.value, false);"/>
   </toolbar>
   <toolbar>
     <label value="Eval script in chrome context"/>
     <textbox flex="1"/><button label="run" oncommand="eval(this.previousSibling.value);"/>
   </toolbar>
   <toolbar>
     <checkbox label="allow dialogs from remote content"
                oncommand="document.getElementById('page').QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader.delayRemoteDialogs = this.checked;"/>
--- a/dom/ipc/tests/process_error.xul
+++ b/dom/ipc/tests/process_error.xul
@@ -44,14 +44,15 @@
         removeFile(minidumpDirectory, dumpID + '.extra');
       }
 
       Services.obs.removeObserver(crashObserver, 'ipc:content-shutdown');
       done();
     }
     Services.obs.addObserver(crashObserver, 'ipc:content-shutdown', false);
 
-    document.getElementById('thebrowser').
-      QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader.
-      messageManager.loadFrameScript('chrome://mochitests/content/chrome/dom/ipc/tests/process_error_contentscript.js', true);
+    document.getElementById('thebrowser')
+            .QueryInterface(Components.interfaces.nsIFrameLoaderOwner)
+            .frameLoader.messageManager
+            .loadFrameScript('chrome://mochitests/content/chrome/dom/ipc/tests/process_error_contentscript.js', true);
   ]]></script>
 
 </window>
--- a/dom/messages/SystemMessageInternal.js
+++ b/dom/messages/SystemMessageInternal.js
@@ -7,19 +7,19 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
-  return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
+                                   "@mozilla.org/parentprocessmessagemanager;1",
+                                   "nsIMessageBroadcaster");
 
 // Limit the number of pending messages for a given page.
 let kMaxPendingMessages;
 try {
   kMaxPendingMessages = Services.prefs.getIntPref("dom.messages.maxPendingMessages");
 } catch(e) {
   // getIntPref throws when the pref is not set.
   kMaxPendingMessages = 5;
@@ -37,19 +37,19 @@ function SystemMessageInternal() {
   this._pages = [];
   Services.obs.addObserver(this, "xpcom-shutdown", false);
   ppmm.addMessageListener("SystemMessageManager:GetPending", this);
 }
 
 SystemMessageInternal.prototype = {
   sendMessage: function sendMessage(aType, aMessage, aPageURI, aManifestURI) {
     debug("Broadcasting " + aType + " " + JSON.stringify(aMessage));
-    ppmm.sendAsyncMessage("SystemMessageManager:Message" , { type: aType,
-                                                             msg: aMessage,
-                                                             manifest: aManifestURI.spec });
+    ppmm.broadcastAsyncMessage("SystemMessageManager:Message" , { type: aType,
+                                                                  msg: aMessage,
+                                                                  manifest: aManifestURI.spec });
 
     // Queue the message for pages that registered an handler for this type.
     this._pages.forEach(function sendMess_openPage(aPage) {
       if (aPage.type != aType ||
           aPage.manifest != aManifestURI.spec ||
           aPage.uri != aPageURI.spec) {
         return;
       }
--- a/dom/messages/SystemMessageManager.js
+++ b/dom/messages/SystemMessageManager.js
@@ -8,21 +8,19 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/ObjectWrapper.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
-  return Cc["@mozilla.org/childprocessmessagemanager;1"]
-         .getService(Ci.nsIFrameMessageManager)
-         .QueryInterface(Ci.nsISyncMessageSender);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsISyncMessageSender");
 
 // Limit the number of pending messages for a given type.
 let kMaxPendingMessages;
 try {
   kMaxPendingMessages = Services.prefs.getIntPref("dom.messages.maxPendingMessages");
 } catch(e) {
   // getIntPref throws when the pref is not set.
   kMaxPendingMessages = 5;
--- a/dom/permission/PermissionPromptHelper.jsm
+++ b/dom/permission/PermissionPromptHelper.jsm
@@ -29,19 +29,19 @@ const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 let EXPORTED_SYMBOLS = ["PermissionPromptHelper"];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
-  return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
+                                   "@mozilla.org/parentprocessmessagemanager;1",
+                                   "nsIMessageListenerManager");
 
 var permissionManager = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
 var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
 var appsService = Cc["@mozilla.org/AppsService;1"].getService(Ci.nsIAppsService);
 
 let PermissionPromptHelper = {
   init: function() {
     debug("Init");
@@ -72,17 +72,17 @@ let PermissionPromptHelper = {
   observe: function(aSubject, aTopic, aData) {
     ppmm.removeMessageListener("PermissionPromptHelper:AskPermission", this);
     Services.obs.removeObserver(this, "profile-before-change");
     ppmm = null;
   },
 
   receiveMessage: function(aMessage) {
     debug("PermissionPromptHelper::receiveMessage " + aMessage.name);
-    let mm = aMessage.target.QueryInterface(Ci.nsIFrameMessageManager);
+    let mm = aMessage.target;
     let msg = aMessage.data;
 
     let result;
     if (aMessage.name == "PermissionPromptHelper:AskPermission") {
       this.askPermission(aMessage, {
         cancel: function() {
           mm.sendAsyncMessage("PermissionPromptHelper:AskPermission:OK", {result: Ci.nsIPermissionManager.DENY_ACTION, requestID: msg.requestID});
         },
--- a/dom/settings/SettingsChangeNotifier.jsm
+++ b/dom/settings/SettingsChangeNotifier.jsm
@@ -12,19 +12,19 @@ const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 let EXPORTED_SYMBOLS = ["SettingsChangeNotifier"];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
-  return Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
+                                   "@mozilla.org/parentprocessmessagemanager;1",
+                                   "nsIMessageBroadcaster");
 
 
 let SettingsChangeNotifier = {
   init: function() {
     debug("init");
     ppmm.addMessageListener("Settings:Changed", this);
     Services.obs.addObserver(this, "xpcom-shutdown", false);
   },
@@ -36,17 +36,17 @@ let SettingsChangeNotifier = {
     ppmm = null;
   },
 
   receiveMessage: function(aMessage) {
     debug("receiveMessage");
     let msg = aMessage.json;
     switch (aMessage.name) {
       case "Settings:Changed":
-        ppmm.sendAsyncMessage("Settings:Change:Return:OK", { key: msg.key, value: msg.value });
+        ppmm.broadcastAsyncMessage("Settings:Change:Return:OK", { key: msg.key, value: msg.value });
         Services.obs.notifyObservers(this, "mozsettings-changed", JSON.stringify({
           key: msg.key,
           value: msg.value
         }));
         break;
       default: 
         debug("Wrong message: " + aMessage.name);
     }
--- a/dom/settings/SettingsManager.js
+++ b/dom/settings/SettingsManager.js
@@ -12,19 +12,19 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/SettingsQueue.jsm");
 Cu.import("resource://gre/modules/SettingsDB.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
-  return Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsIMessageSender");
 
 const nsIClassInfo            = Ci.nsIClassInfo;
 const SETTINGSLOCK_CONTRACTID = "@mozilla.org/settingsLock;1";
 const SETTINGSLOCK_CID        = Components.ID("{ef95ddd0-6308-11e1-b86c-0800200c9a66}");
 const nsIDOMSettingsLock      = Ci.nsIDOMSettingsLock;
 
 function SettingsLock(aSettingsManager)
 {
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -61,17 +61,17 @@ const RIL_IPC_MSG_NAMES = [
 
 const kVoiceChangedTopic     = "mobile-connection-voice-changed";
 const kDataChangedTopic      = "mobile-connection-data-changed";
 const kCardStateChangedTopic = "mobile-connection-cardstate-changed";
 const kUssdReceivedTopic     = "mobile-connection-ussd-received";
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
                                    "@mozilla.org/childprocessmessagemanager;1",
-                                   "nsIFrameMessageManager");
+                                   "nsISyncMessageSender");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
                                    "@mozilla.org/uuid-generator;1",
                                    "nsIUUIDGenerator");
 
 function MobileConnectionInfo() {}
 MobileConnectionInfo.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileConnectionInfo]),
@@ -156,18 +156,17 @@ function RILContentHelper() {
   this.voiceConnectionInfo = new MobileConnectionInfo();
   this.dataConnectionInfo = new MobileConnectionInfo();
 
   this.initRequests();
   this.initMessageListener(RIL_IPC_MSG_NAMES);
   Services.obs.addObserver(this, "xpcom-shutdown", false);
 
   // Request initial context.
-  let rilContext = cpmm.QueryInterface(Ci.nsISyncMessageSender)
-                       .sendSyncMessage("RIL:GetRilContext")[0];
+  let rilContext = cpmm.sendSyncMessage("RIL:GetRilContext")[0];
 
   if (!rilContext) {
     debug("Received null rilContext from chrome process.");
     return;
   }
   this.cardState = rilContext.cardState;
   this.updateConnectionInfo(rilContext.voice, this.voiceConnectionInfo);
   this.updateConnectionInfo(rilContext.data, this.dataConnectionInfo);
@@ -503,17 +502,17 @@ RILContentHelper.prototype = {
   observe: function observe(subject, topic, data) {
     if (topic == "xpcom-shutdown") {
       this.removeMessageListener();
       Services.obs.removeObserver(this, "xpcom-shutdown");
       cpmm = null;
     }
   },
 
-  // nsIFrameMessageListener
+  // nsIMessageListener
 
   fireRequestSuccess: function fireRequestSuccess(requestId, result) {
     let request = this.takeRequest(requestId);
     if (!request) {
       if (DEBUG) {
         debug("not firing success for id: " + requestId +
               ", result: " + JSON.stringify(result));
       }
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -74,17 +74,17 @@ XPCOMUtils.defineLazyServiceGetter(this,
                                    "nsISmsRequestManager");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSmsDatabaseService",
                                    "@mozilla.org/sms/rilsmsdatabaseservice;1",
                                    "nsISmsDatabaseService");
 
 XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
                                    "@mozilla.org/parentprocessmessagemanager;1",
-                                   "nsIFrameMessageManager");
+                                   "nsIMessageBroadcaster");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
                                    "@mozilla.org/settingsService;1",
                                    "nsISettingsService");
 
 XPCOMUtils.defineLazyGetter(this, "WAP", function () {
   let WAP = {};
   Cu.import("resource://gre/modules/WapPushManager.js", WAP);
@@ -371,17 +371,17 @@ RadioInterfaceLayer.prototype = {
       case "operatorchange":
         this.handleOperatorChange(message);
         break;
       case "radiostatechange":
         this.handleRadioStateChange(message);
         break;
       case "cardstatechange":
         this.rilContext.cardState = message.cardState;
-        ppmm.sendAsyncMessage("RIL:CardStateChanged", message);
+        ppmm.broadcastAsyncMessage("RIL:CardStateChanged", message);
         break;
       case "sms-received":
         this.handleSmsReceived(message);
         return;
       case "sms-sent":
         this.handleSmsSent(message);
         return;
       case "sms-delivered":
@@ -423,17 +423,17 @@ RadioInterfaceLayer.prototype = {
         }
         let callback = this._contactsCallbacks[message.requestId];
         if (callback) {
           delete this._contactsCallbacks[message.requestId];
           callback.receiveContactsList(message.contactType, message.contacts);
         }
         break;
       case "iccmbdn":
-        ppmm.sendAsyncMessage("RIL:VoicemailNumberChanged", message);
+        ppmm.broadcastAsyncMessage("RIL:VoicemailNumberChanged", message);
         break;
       case "ussdreceived":
         debug("ussdreceived " + JSON.stringify(message));
         this.handleUSSDReceived(message);
         break;
       case "sendussd":
         this.handleSendUSSD(message);
         break;
@@ -449,29 +449,28 @@ RadioInterfaceLayer.prototype = {
   _messageManagerByRequest: null,
   saveRequestTarget: function saveRequestTarget(msg) {
     let requestId = msg.json.requestId;
     if (!requestId) {
       // The content is not interested in a response;
       return;
     }
 
-    let mm = msg.target.QueryInterface(Ci.nsIFrameMessageManager);
-    this._messageManagerByRequest[requestId] = mm;
+    this._messageManagerByRequest[requestId] = msg.target;
   },
 
   _sendRequestResults: function _sendRequestResults(requestType, options) {
     let target = this._messageManagerByRequest[options.requestId];
     delete this._messageManagerByRequest[options.requestId];
 
     if (!target) {
       return;
     }
 
-    target.sendAsyncMessage(requestType, options);
+    target.syncAsyncMessage(requestType, options);
   },
 
   updateNetworkInfo: function updateNetworkInfo(message) {
     let voiceMessage = message[RIL.NETWORK_INFO_VOICE_REGISTRATION_STATE];
     let dataMessage = message[RIL.NETWORK_INFO_DATA_REGISTRATION_STATE];
     let operatorMessage = message[RIL.NETWORK_INFO_OPERATOR];
     let selectionMessage = message[RIL.NETWORK_INFO_NETWORK_SELECTION_MODE];
 
@@ -494,20 +493,20 @@ RadioInterfaceLayer.prototype = {
         voice.network = operatorMessage;
       }
       if (this.networkChanged(operatorMessage, data.network)) {
         data.network = operatorMessage;
       }
     }
 
     if (voiceMessage || operatorMessage) {
-      ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voice);
+      ppmm.broadcastAsyncMessage("RIL:VoiceInfoChanged", voice);
     }
     if (dataMessage || operatorMessage) {
-      ppmm.sendAsyncMessage("RIL:DataInfoChanged", data);
+      ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", data);
     }
 
     if (selectionMessage) {
       this.updateNetworkSelectionMode(selectionMessage);
     }
   },
 
   /**
@@ -539,17 +538,17 @@ RadioInterfaceLayer.prototype = {
     let newCell = newInfo.cell;
     if ((newCell.gsmLocationAreaCode < 0) || (newCell.gsmCellId < 0)) {
       voiceInfo.cell = null;
     } else {
       voiceInfo.cell = newCell;
     }
 
     if (!newInfo.batch) {
-      ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo);
+      ppmm.broadcastAsyncMessage("RIL:VoiceInfoChanged", voiceInfo);
     }
   },
 
   updateDataConnection: function updateDataConnection(newInfo) {
     let dataInfo = this.rilContext.data;
     dataInfo.state = newInfo.state;
     dataInfo.roaming = newInfo.roaming;
     dataInfo.emergencyCallsOnly = newInfo.emergencyCallsOnly;
@@ -569,17 +568,17 @@ RadioInterfaceLayer.prototype = {
     let newCell = newInfo.cell;
     if ((newCell.gsmLocationAreaCode < 0) || (newCell.gsmCellId < 0)) {
       dataInfo.cell = null;
     } else {
       dataInfo.cell = newCell;
     }
 
     if (!newInfo.batch) {
-      ppmm.sendAsyncMessage("RIL:DataInfoChanged", dataInfo);
+      ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", dataInfo);
     }
 
     if (!this.dataCallSettings["enabled"]) {
       return;
     }
 
     let isRegistered =
       newInfo.state == RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED &&
@@ -595,25 +594,25 @@ RadioInterfaceLayer.prototype = {
 
   handleSignalStrengthChange: function handleSignalStrengthChange(message) {
     let voiceInfo = this.rilContext.voice;
     // TODO CDMA, EVDO, LTE, etc. (see bug 726098)
     if (voiceInfo.signalStrength != message.gsmDBM ||
         voiceInfo.relSignalStrength != message.gsmRelative) {
       voiceInfo.signalStrength = message.gsmDBM;
       voiceInfo.relSignalStrength = message.gsmRelative;
-      ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voiceInfo);
+      ppmm.broadcastAsyncMessage("RIL:VoiceInfoChanged", voiceInfo);
     }
 
     let dataInfo = this.rilContext.data;
     if (dataInfo.signalStrength != message.gsmDBM ||
         dataInfo.relSignalStrength != message.gsmRelative) {
       dataInfo.signalStrength = message.gsmDBM;
       dataInfo.relSignalStrength = message.gsmRelative;
-      ppmm.sendAsyncMessage("RIL:DataInfoChanged", dataInfo);
+      ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", dataInfo);
     }
   },
 
   networkChanged: function networkChanged(srcNetwork, destNetwork) {
     return !destNetwork ||
       destNetwork.longName != srcNetwork.longName ||
       destNetwork.shortName != srcNetwork.shortName ||
       destNetwork.mnc != srcNetwork.mnc ||
@@ -621,22 +620,22 @@ RadioInterfaceLayer.prototype = {
   },
 
   handleOperatorChange: function handleOperatorChange(message) {
     let voice = this.rilContext.voice;
     let data = this.rilContext.data;
 
     if (this.networkChanged(message, voice.network)) {
       voice.network = message;
-      ppmm.sendAsyncMessage("RIL:VoiceInfoChanged", voice);
+      ppmm.broadcastAsyncMessage("RIL:VoiceInfoChanged", voice);
     }
 
     if (this.networkChanged(message, data.network)) {
       data.network = message;
-      ppmm.sendAsyncMessage("RIL:DataInfoChanged", data);
+      ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", data);
     }
   },
 
   handleRadioStateChange: function handleRadioStateChange(message) {
     let newState = message.radioState;
     if (this.rilContext.radioState == newState) {
       return;
     }
@@ -743,30 +742,30 @@ RadioInterfaceLayer.prototype = {
     if (call.isActive) {
       this._activeCall = call;
     } else if (this._activeCall &&
                this._activeCall.callIndex == call.callIndex) {
       // Previously active call is not active now.
       this._activeCall = null;
     }
     this.updateCallAudioState();
-    ppmm.sendAsyncMessage("RIL:CallStateChanged", call);
+    ppmm.broadcastAsyncMessage("RIL:CallStateChanged", call);
   },
 
   /**
    * Handle call disconnects by updating our current state and the audio system.
    */
   handleCallDisconnected: function handleCallDisconnected(call) {
     debug("handleCallDisconnected: " + JSON.stringify(call));
     if (call.isActive) {
       this._activeCall = null;
     }
     this.updateCallAudioState();
     call.state = nsIRadioInterfaceLayer.CALL_STATE_DISCONNECTED;
-    ppmm.sendAsyncMessage("RIL:CallStateChanged", call);
+    ppmm.broadcastAsyncMessage("RIL:CallStateChanged", call);
   },
 
   /**
    * Handle calls delivered in response to a 'enumerateCalls' request.
    */
   handleEnumerateCalls: function handleEnumerateCalls(options) {
     debug("handleEnumerateCalls: " + JSON.stringify(options));
     for (let i in options.calls) {
@@ -784,17 +783,17 @@ RadioInterfaceLayer.prototype = {
     this._sendRequestResults("RIL:GetAvailableNetworks", message);
   },
 
   /**
    * Update network selection mode
    */
   updateNetworkSelectionMode: function updateNetworkSelectionMode(message) {
     debug("updateNetworkSelectionMode: " + JSON.stringify(message));
-    ppmm.sendAsyncMessage("RIL:NetworkSelectionModeChanged", message);
+    ppmm.broadcastAsyncMessage("RIL:NetworkSelectionModeChanged", message);
   },
 
   /**
    * Handle "manual" network selection request.
    */
   handleSelectNetwork: function handleSelectNetwork(message) {
     debug("handleSelectNetwork: " + JSON.stringify(message));
     this._sendRequestResults("RIL:SelectNetwork", message);
@@ -807,17 +806,17 @@ RadioInterfaceLayer.prototype = {
     debug("handleSelectNetworkAuto: " + JSON.stringify(message));
     this._sendRequestResults("RIL:SelectNetworkAuto", message);
   },
 
   /**
    * Handle call error.
    */
   handleCallError: function handleCallError(message) {
-    ppmm.sendAsyncMessage("RIL:CallError", message);   
+    ppmm.broadcastAsyncMessage("RIL:CallError", message);   
   },
 
   /**
    * Handle WDP port push PDU. Constructor WDP bearer information and deliver
    * to WapPushManager.
    *
    * @param message
    *        A SMS message.
@@ -868,17 +867,17 @@ RadioInterfaceLayer.prototype = {
     // For now we don't store indicators persistently. When the mwi.discard
     // flag is false, we'll need to persist the indicator to EFmwis.
     // See TS 23.040 9.2.3.24.2
 
     let mwi = message.mwi;
     if (mwi) {
       mwi.returnNumber = message.sender || null;
       mwi.returnMessage = message.fullBody || null;
-      ppmm.sendAsyncMessage("RIL:VoicemailNotification", mwi);
+      ppmm.broadcastAsyncMessage("RIL:VoicemailNotification", mwi);
       return;
     }
 
     let id = gSmsDatabaseService.saveReceivedMessage(message.sender || null,
                                                      message.fullBody || null,
                                                      message.timestamp);
     let sms = gSmsService.createSmsMessage(id,
                                            DOM_SMS_DELIVERY_RECEIVED,
@@ -970,17 +969,17 @@ RadioInterfaceLayer.prototype = {
   /**
    * Handle data call state changes.
    */
   handleDataCallState: function handleDataCallState(datacall) {
     let data = this.rilContext.data;
 
     if (datacall.ifname) {
       data.connected = (datacall.state == RIL.GECKO_NETWORK_STATE_CONNECTED);
-      ppmm.sendAsyncMessage("RIL:DataInfoChanged", data);    
+      ppmm.broadcastAsyncMessage("RIL:DataInfoChanged", data);    
     }
 
     this._deliverDataCallCallback("dataCallStateChanged",
                                   [datacall]);
   },
 
   /**
    * Handle data call list.
@@ -991,17 +990,17 @@ RadioInterfaceLayer.prototype = {
   },
 
   handleICCCardLockResult: function handleICCCardLockResult(message) {
     this._sendRequestResults("RIL:CardLockResult", message);
   },
 
   handleUSSDReceived: function handleUSSDReceived(ussd) {
     debug("handleUSSDReceived " + JSON.stringify(ussd));
-    ppmm.sendAsyncMessage("RIL:UssdReceived", ussd);
+    ppmm.broadcastAsyncMessage("RIL:UssdReceived", ussd);
   },
 
   handleSendUSSD: function handleSendUSSD(message) {
     debug("handleSendUSSD " + JSON.stringify(message));
     let messageType = message.success ? "RIL:SendUssd:Return:OK" :
                                         "RIL:SendUssd:Return:KO";
     this._sendRequestResults(messageType, message);
   },
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -291,17 +291,16 @@ var interfaceNamesInGlobalScope =
     "CSSPrimitiveValue",
     "SVGStopElement",
     "WebGLExtensionCompressedTextureS3TC",
     "XULCommandEvent",
     "HTMLMediaElement",
     "SVGPathSegLinetoHorizontalAbs",
     "SVGAnimatedRect",
     "SVGTextContentElement",
-    "SyncMessageSender",
     "WebGLRenderbuffer",
     "TreeColumn",
     "WebGLExtensionStandardDerivatives",
     "WebGLShaderPrecisionFormat",
     "XPathNamespace",
     "FontFace",
     "SVGPathSegCurvetoCubicSmoothRel",
     "HTMLMapElement",
@@ -397,17 +396,16 @@ var interfaceNamesInGlobalScope =
     "MozTouchEvent",
     "MozWakeLockListener",
     "Selection",
     "XULTreeBuilder",
     "ScrollAreaEvent",
     "SVGStyleElement",
     "XULContainerElement",
     "DOMTokenList",
-    "FrameMessageManager",
     "HTMLHRElement",
     "HTMLFontElement",
     "SVGFEFloodElement",
     "HTMLDListElement",
     "SVGSymbolElement",
     "SVGLengthList",
     "TreeColumns",
     "PaintRequestList",
@@ -485,17 +483,16 @@ var interfaceNamesInGlobalScope =
     "GeoPositionCallback",
     "XULCommandDispatcher",
     "DocumentTouch",
     "XULSelectControlItemElement",
     "SVGPathSegCurvetoQuadraticAbs",
     "MutationObserver",
     "RequestService",
     "Counter",
-    "ContentFrameMessageManager",
     "SVGAnimatedAngle",
     "SVGPathSegList",
     "SVGFEFuncAElement",
     "WebSocket",
     "ElementTimeControl",
     "HTMLLegendElement",
     "SVGFEGaussianBlurElement",
     "SVGEllipseElement",
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -1321,17 +1321,18 @@ let WifiNetworkInterface = {
 // TODO Make the difference between a DOM-based network object and our
 // networks objects much clearer.
 let netToDOM;
 let netFromDOM;
 
 function WifiWorker() {
   var self = this;
 
-  this._mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
+  this._mm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+               .getService(Ci.nsIMessageListenerManager);
   const messages = ["WifiManager:setEnabled", "WifiManager:getNetworks",
                     "WifiManager:associate", "WifiManager:forget",
                     "WifiManager:wps", "WifiManager:getState",
                     "WifiManager:managerFinished"];
 
   messages.forEach((function(msgName) {
     this._mm.addMessageListener(msgName, this);
   }).bind(this));
@@ -1884,17 +1885,17 @@ WifiWorker.prototype = {
 
   _sendMessage: function(message, success, data, msg) {
     msg.manager.sendAsyncMessage(message + (success ? ":OK" : ":NO"),
                                  { data: data, rid: msg.rid, mid: msg.mid });
   },
 
   receiveMessage: function MessageManager_receiveMessage(aMessage) {
     let msg = aMessage.json || {};
-    msg.manager = aMessage.target.QueryInterface(Ci.nsIFrameMessageManager);
+    msg.manager = aMessage.target;
 
     switch (aMessage.name) {
       case "WifiManager:setEnabled":
         this.setWifiEnabled(msg);
         break;
       case "WifiManager:getNetworks":
         this.getNetworks(msg);
         break;
--- a/extensions/cookie/test/unit_ipc/test_parent.js
+++ b/extensions/cookie/test/unit_ipc/test_parent.js
@@ -22,27 +22,27 @@ function run_test() {
     var pm = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
 
     // Permissions created before the child is present
     pm.addFromPrincipal(getPrincipalForURI("http://mozilla.org"), "cookie1", pm.ALLOW_ACTION, pm.EXPIRE_NEVER, 0);
     pm.addFromPrincipal(getPrincipalForURI("http://mozilla.com"), "cookie2", pm.DENY_ACTION, pm.EXPIRE_SESSION, 0);
     pm.addFromPrincipal(getPrincipalForURI("http://mozilla.net"), "cookie3", pm.ALLOW_ACTION, pm.EXPIRE_TIME, Date.now() + 1000*60*60*24);
 
     var mM = Cc["@mozilla.org/parentprocessmessagemanager;1"].
-             getService(Ci.nsIFrameMessageManager);
+             getService(Ci.nsIMessageBroadcaster);
 
     var messageListener = {
       receiveMessage: function(aMessage) {
         switch(aMessage.name) {
           case "TESTING:Stage2":
             // Permissions created after the child is present
             pm.addFromPrincipal(getPrincipalForURI("http://firefox.org"), "cookie1", pm.ALLOW_ACTION, pm.EXPIRE_NEVER, 0);
             pm.addFromPrincipal(getPrincipalForURI("http://firefox.com"), "cookie2", pm.DENY_ACTION, pm.EXPIRE_SESSION, 0);
             pm.addFromPrincipal(getPrincipalForURI("http://firefox.net"), "cookie3", pm.ALLOW_ACTION, pm.EXPIRE_TIME, Date.now() + 1000*60*60*24);
-            mM.sendAsyncMessage("TESTING:Stage2A");
+            mM.broadcastAsyncMessage("TESTING:Stage2A");
             break;
 
           case "TESTING:Stage3":
             do_test_finished();
             break;
         }
         return true;
       },
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -53,17 +53,17 @@
 #include "nsStyleStructInlines.h"
 #include "nsIAppShell.h"
 #include "prenv.h"
 #include "nsIDOMEventTarget.h"
 #include "nsObjectFrame.h"
 #include "nsTransitionManager.h"
 #include "nsAnimationManager.h"
 #include "mozilla/dom/Element.h"
-#include "nsIFrameMessageManager.h"
+#include "nsIMessageManager.h"
 #include "FrameLayerBuilder.h"
 #include "nsDOMMediaQueryList.h"
 #include "nsSMILAnimationController.h"
 #include "mozilla/css/ImageLoader.h"
 
 #ifdef IBMBIDI
 #include "nsBidiPresUtils.h"
 #endif // IBMBIDI
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -49,17 +49,17 @@
 #include "nsStyleSheetService.h"
 #include "nsFocusManager.h"
 #include "ThirdPartyUtil.h"
 #include "mozilla/Services.h"
 #include "nsStructuredCloneContainer.h"
 #include "mozilla/Attributes.h"
 
 #include "nsIEventListenerService.h"
-#include "nsIFrameMessageManager.h"
+#include "nsIMessageManager.h"
 
 // Transformiix stuff
 #include "nsXPathEvaluator.h"
 #include "txMozillaXSLTProcessor.h"
 #include "txNodeSetAdaptor.h"
 
 #include "nsDOMParser.h"
 #include "nsDOMSerializer.h"
@@ -417,18 +417,18 @@ nsresult NS_NewContentViewer(nsIContentV
 nsresult NS_NewGenRegularIterator(nsIContentIterator** aResult);
 nsresult NS_NewGenSubtreeIterator(nsIContentIterator** aInstancePtrResult);
 nsresult NS_NewContentDocumentLoaderFactory(nsIDocumentLoaderFactory** aResult);
 nsresult NS_NewHTMLCopyTextEncoder(nsIDocumentEncoder** aResult);
 nsresult NS_NewTextEncoder(nsIDocumentEncoder** aResult);
 nsresult NS_NewContentPolicy(nsIContentPolicy** aResult);
 
 nsresult NS_NewEventListenerService(nsIEventListenerService** aResult);
-nsresult NS_NewGlobalMessageManager(nsIChromeFrameMessageManager** aResult);
-nsresult NS_NewParentProcessMessageManager(nsIFrameMessageManager** aResult);
+nsresult NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult);
+nsresult NS_NewParentProcessMessageManager(nsIMessageBroadcaster** aResult);
 nsresult NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult);
 
 nsresult NS_NewXULControllers(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 
 #define MAKE_CTOR(ctor_, iface_, func_)                   \
 static nsresult                                           \
 ctor_(nsISupports* aOuter, REFNSIID aIID, void** aResult) \
 {                                                         \
@@ -514,19 +514,19 @@ MAKE_CTOR(CreateXULDocument,            
 // NS_NewXULControllers
 #endif
 #ifdef MOZ_XTF
 MAKE_CTOR(CreateXTFService,               nsIXTFService,               NS_NewXTFService)
 MAKE_CTOR(CreateXMLContentBuilder,        nsIXMLContentBuilder,        NS_NewXMLContentBuilder)
 #endif
 MAKE_CTOR(CreateContentDLF,               nsIDocumentLoaderFactory,    NS_NewContentDocumentLoaderFactory)
 MAKE_CTOR(CreateEventListenerService,     nsIEventListenerService,     NS_NewEventListenerService)
-MAKE_CTOR(CreateGlobalMessageManager,     nsIChromeFrameMessageManager,NS_NewGlobalMessageManager)
-MAKE_CTOR(CreateParentMessageManager,     nsIFrameMessageManager,NS_NewParentProcessMessageManager)
-MAKE_CTOR(CreateChildMessageManager,     nsISyncMessageSender,NS_NewChildProcessMessageManager)
+MAKE_CTOR(CreateGlobalMessageManager,     nsIMessageBroadcaster,       NS_NewGlobalMessageManager)
+MAKE_CTOR(CreateParentMessageManager,     nsIMessageBroadcaster,       NS_NewParentProcessMessageManager)
+MAKE_CTOR(CreateChildMessageManager,      nsISyncMessageSender,        NS_NewChildProcessMessageManager)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDataDocumentContentPolicy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsNoDataProtocolContentPolicy)
 MAKE_CTOR(CreatePluginDocument,           nsIDocument,                 NS_NewPluginDocument)
 #ifdef MOZ_MEDIA
 MAKE_CTOR(CreateVideoDocument,            nsIDocument,                 NS_NewVideoDocument)
 #endif
 MAKE_CTOR(CreateFocusManager,             nsIFocusManager,      NS_NewFocusManager)
 
--- a/layout/ipc/test-ipcbrowser-chrome.js
+++ b/layout/ipc/test-ipcbrowser-chrome.js
@@ -31,39 +31,39 @@ function enableAsyncScrolling() {
 
 // Functions affecting the content window.
 
 function loadURL(url) {
     browser().setAttribute('src', url);
 }
 
 function scrollContentBy(dx, dy) {
-    messageManager.sendAsyncMessage("scrollBy",
-                                    { dx: dx, dy: dy });
+    messageManager.broadcastAsyncMessage("scrollBy",
+                                         { dx: dx, dy: dy });
 
 }
 
 function scrollContentTo(x, y) {
-    messageManager.sendAsyncMessage("scrollTo",
-                                    { x: x, y: y });
+    messageManager.broadcastAsyncMessage("scrollTo",
+                                         { x: x, y: y });
 }
 
 function setContentViewport(w, h) {
-    messageManager.sendAsyncMessage("setViewport",
-                                    { w: w, h: h });
+    messageManager.broadcastAsyncMessage("setViewport",
+                                         { w: w, h: h });
 }
 
 function setContentDisplayPort(x, y, w, h) {
-    messageManager.sendAsyncMessage("setDisplayPort",
-                                    { x: x, y: y, w: w, h: h });
+    messageManager.broadcastAsyncMessage("setDisplayPort",
+                                         { x: x, y: y, w: w, h: h });
 }
 
 function setContentResolution(xres, yres) {
-    messageManager.sendAsyncMessage("setResolution",
-                                    { xres: xres, yres: yres });
+    messageManager.broadcastAsyncMessage("setResolution",
+                                         { xres: xres, yres: yres });
 }
 
 // Functions affecting <browser>.
 
 function scrollViewportBy(dx, dy) {
     rootView().scrollBy(dx, dy);
 }
 
@@ -102,18 +102,18 @@ function startAnimatedScrollBy(dx, dy) {
         ddx = Math.min(dx - accumDx, ddx);
         ddy = Math.min(dy - accumDy, ddy);
         accumDx += ddx;
         accumDy += ddy;
 
         rootView().scrollBy(ddx, ddy);
 
         if (!sentScrollBy && 100 <= (now - start)) {
-            messageManager.sendAsyncMessage("scrollBy",
-                                            { dx: dx, dy: dy });
+            messageManager.broadcastAsyncMessage("scrollBy",
+                                                 { dx: dx, dy: dy });
             sentScrollBy = true;
         }
 
         if (now >= end || (accumDx >= dx && accumDy >= dy)) {
             var fixupDx = Math.max(dx - accumDx, 0);
             var fixupDy = Math.max(dy - accumDy, 0);
             rootView().scrollBy(fixupDx, fixupDy);
 
--- a/layout/tools/reftest/reftest.js
+++ b/layout/tools/reftest/reftest.js
@@ -257,17 +257,17 @@ function OnRefTestLoad(win)
       doc.removeChild(doc.firstChild);
     }
     doc.appendChild(gBrowser);
 #else
     document.getElementById("reftest-window").appendChild(gBrowser);
 #endif
 
     gBrowserMessageManager = gBrowser.QueryInterface(CI.nsIFrameLoaderOwner)
-                             .frameLoader.messageManager;
+                                     .frameLoader.messageManager;
     // The content script waits for the initial onload, then notifies
     // us.
     RegisterMessageListenersAndLoadContentScript();
 }
 
 function InitAndStartRefTests()
 {
     /* These prefs are optional, so we don't need to spit an error to the log */
--- a/mobile/xul/chrome/content/CapturePickerUI.js
+++ b/mobile/xul/chrome/content/CapturePickerUI.js
@@ -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/. */
 
 var CapturePickerUI = {
   init: function() {
-    this.messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
+    this.messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+                            .getService(Ci.nsIMessageListenerManager);
     this.messageManager.addMessageListener("CapturePicker:Show", this);
   },
   
   receiveMessage: function(aMessage) {
     switch (aMessage.name) {
       case "CapturePicker:Show":
         let params = { result: true };
         let dialog = importDialog(null, "chrome://browser/content/CaptureDialog.xul", params);
--- a/mobile/xul/chrome/content/WebappsUI.js
+++ b/mobile/xul/chrome/content/WebappsUI.js
@@ -6,17 +6,18 @@ var WebappsUI = {
   _dialog: null,
   _manifest: null,
   _perms: [],
   _application: null,
   _browser: null,
 
   init: function() {
     Cu.import("resource://gre/modules/OpenWebapps.jsm");
-    this.messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
+    this.messageManager = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+                            .getService(Ci.nsIMessageBroadcaster);
     this.messageManager.addMessageListener("OpenWebapps:Install", this);
     this.messageManager.addMessageListener("OpenWebapps:GetInstalledBy", this);
     this.messageManager.addMessageListener("OpenWebapps:AmInstalled", this);
     this.messageManager.addMessageListener("OpenWebapps:MgmtLaunch", this);
     this.messageManager.addMessageListener("OpenWebapps:MgmtList", this);
     this.messageManager.addMessageListener("OpenWebapps:MgmtUninstall", this);
   },
 
@@ -91,61 +92,61 @@ var WebappsUI = {
       allow: function() {
         Services.perms.addFromPrincipal(principal, aType, Ci.nsIPermissionManager.ALLOW_ACTION);
         aCallbacks.allow();
       }
     });
   },
 
   receiveMessage: function(aMessage) {
-    this._browser = aMessage.target.QueryInterface(Ci.nsIFrameMessageManager);
+    this._browser = aMessage.target.QueryInterface(Ci.nsIMessageSender);
     switch(aMessage.name) {
       case "OpenWebapps:Install":
         WebappsUI.show(WebappsUI.convertManifest(aMessage.json));
         break;
       case "OpenWebapps:GetInstalledBy":
         let apps = OpenWebapps.getInstalledBy(aMessage.json.storeURI);
-        this._browser.sendAsyncMessage("OpenWebapps:GetInstalledBy:Return",
+        this._browser.broadcastAsyncMessage("OpenWebapps:GetInstalledBy:Return",
             { apps: apps, callbackID: aMessage.json.callbackID });
         break;
       case "OpenWebapps:AmInstalled":
         let app = OpenWebapps.amInstalled(aMessage.json.appURI);
-        this._browser.sendAsyncMessage("OpenWebapps:AmInstalled:Return",
+        this._browser.broadcastAsyncMessage("OpenWebapps:AmInstalled:Return",
             { installed: app != null, app: app, callbackID: aMessage.json.callbackID });
         break;
       case "OpenWebapps:MgmtList":
         this.askPermission(aMessage, "openWebappsManage", {
           cancel: function() {
-            WebappsUI.messageManager.sendAsyncMessage("OpenWebapps:MgmtList:Return",
+            WebappsUI.messageManager.broadcastAsyncMessage("OpenWebapps:MgmtList:Return",
               { ok: false, callbackID: aMessage.json.callbackID });
           },
 
           allow: function() {
             let list = OpenWebapps.mgmtList();
-            WebappsUI.messageManager.sendAsyncMessage("OpenWebapps:MgmtList:Return",
+            WebappsUI.messageManager.broadcastAsyncMessage("OpenWebapps:MgmtList:Return",
               { ok: true, apps: list, callbackID: aMessage.json.callbackID });
           }
         });
         break;
       case "OpenWebapps:MgmtLaunch":
         let res = OpenWebapps.mgmtLaunch(aMessage.json.origin);
-        this._browser.sendAsyncMessage("OpenWebapps:MgmtLaunch:Return",
+        this._browser.broadcastAsyncMessage("OpenWebapps:MgmtLaunch:Return",
             { ok: res, callbackID: aMessage.json.callbackID });
         break;
       case "OpenWebapps:MgmtUninstall":
         this.askPermission(aMessage, "openWebappsManage", {
           cancel: function() {
-            WebappsUI.messageManager.sendAsyncMessage("OpenWebapps:MgmtUninstall:Return",
+            WebappsUI.messageManager.broadcastAsyncMessage("OpenWebapps:MgmtUninstall:Return",
               { ok: false, callbackID: aMessage.json.callbackID });
           },
 
           allow: function() {
             let app = OpenWebapps.amInstalled(aMessage.json.origin);
             let uninstalled = OpenWebapps.mgmtUninstall(aMessage.json.origin);
-            WebappsUI.messageManager.sendAsyncMessage("OpenWebapps:MgmtUninstall:Return",
+            WebappsUI.messageManager.broadcastAsyncMessage("OpenWebapps:MgmtUninstall:Return",
               { ok: uninstalled, app: app, callbackID: aMessage.json.callbackID });
           }
         });
         break;
     }
   },
 
   checkBox: function(aEvent) {
@@ -191,17 +192,17 @@ var WebappsUI = {
 
     // Force a modal dialog
     this._dialog.waitForClose();
   },
 
   hide: function hide() {
     this.close();
 
-    this._browser.sendAsyncMessage("OpenWebapps:InstallAborted", { callbackID: this._application.callbackID });
+    this._browser.broadcastAsyncMessage("OpenWebapps:InstallAborted", { callbackID: this._application.callbackID });
   },
   
   close: function close() {
     this._dialog.close();
     this._dialog = null;
     BrowserUI.popPopup(this);
   },
 
@@ -234,14 +235,14 @@ var WebappsUI = {
 
     if (document.getElementById("webapps-homescreen-checkbox").checked)
       WebappsUI.addToHome(this._application);
 
     this.close();
     try {
       OpenWebapps.install(this._application);
       let app = OpenWebapps.amInstalled(this._application.appURI);
-      this.messageManager.sendAsyncMessage("OpenWebapps:InstallDone", { app: app, callbackID: this._application.callbackID });
+      this.messageManager.broadcastAsyncMessage("OpenWebapps:InstallDone", { app: app, callbackID: this._application.callbackID });
     } catch(e) {
       Cu.reportError(e);
     }
   }
 };
--- a/mobile/xul/chrome/content/bindings/browser.xml
+++ b/mobile/xul/chrome/content/bindings/browser.xml
@@ -9,17 +9,17 @@
   %findBarDTD;
 ]>
 
 <bindings id="remoteBrowserBindings"
           xmlns="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <binding id="local-browser" extends="chrome://global/content/bindings/browser.xml#browser">
-    <implementation type="application/javascript" implements="nsIAccessibleProvider, nsIObserver, nsIDOMEventListener, nsIFrameMessageListener">
+    <implementation type="application/javascript" implements="nsIAccessibleProvider, nsIObserver, nsIDOMEventListener, nsIMessageListener">
       <field name="_securityUI">null</field>
       <property name="securityUI">
         <getter><![CDATA[
           return this._securityUI || {};
         ]]></getter>
         <setter><![CDATA[
           this._securityUI = val;
         ]]></setter>
@@ -589,17 +589,17 @@
           return;
         ]]></body>
       </method>
 
     </implementation>
   </binding>
 
   <binding id="remote-browser" extends="#local-browser">
-    <implementation type="application/javascript" implements="nsIAccessibleProvider, nsIObserver, nsIDOMEventListener, nsIFrameMessageListener">
+    <implementation type="application/javascript" implements="nsIAccessibleProvider, nsIObserver, nsIDOMEventListener, nsIMessageListener">
       <property name="accessibleType" readonly="true">
         <getter>
           <![CDATA[
             throw "accessibleType: Supports Remote?";
           ]]>
         </getter>
       </property>
 
--- a/mobile/xul/components/LoginManager.js
+++ b/mobile/xul/components/LoginManager.js
@@ -66,17 +66,17 @@ LoginManager.prototype = {
      * is created.
      *
      * Note: Service created in /browser/base/content/browser.js,
      *       delayedStartup()
      */
     init : function () {
         // Add content listener.
         var messageManager = Cc["@mozilla.org/globalmessagemanager;1"].
-                             getService(Ci.nsIChromeFrameMessageManager);
+                             getService(Ci.nsIMessageListenerManager);
         messageManager.loadFrameScript("chrome://browser/content/LoginManagerChild.js", true);
         messageManager.addMessageListener("PasswordMgr:FormSubmitted", this);
         messageManager.addMessageListener("PasswordMgr:GetPasswords", this);
 
         // Get constructor for nsILoginInfo
         this._nsLoginInfo = new Components.Constructor(
             "@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo);
 
--- a/netwerk/protocol/app/AppProtocolHandler.js
+++ b/netwerk/protocol/app/AppProtocolHandler.js
@@ -6,21 +6,19 @@
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
-  return Cc["@mozilla.org/childprocessmessagemanager;1"]
-         .getService(Ci.nsIFrameMessageManager)
-         .QueryInterface(Ci.nsISyncMessageSender);
-});
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsISyncMessageSender");
 
 function AppProtocolHandler() {
   this._basePath = null;
 }
 
 AppProtocolHandler.prototype = {
   classID: Components.ID("{b7ad6144-d344-4687-b2d0-b6b9dce1f07f}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler]),
--- a/testing/marionette/marionette-actors.js
+++ b/testing/marionette/marionette-actors.js
@@ -110,17 +110,17 @@ MarionetteRootActor.prototype.requestTyp
  */
 function MarionetteDriverActor(aConnection)
 {
   this.uuidGen = Cc["@mozilla.org/uuid-generator;1"]
                    .getService(Ci.nsIUUIDGenerator);
 
   this.conn = aConnection;
   this.messageManager = Cc["@mozilla.org/globalmessagemanager;1"]
-                          .getService(Ci.nsIChromeFrameMessageManager);
+                          .getService(Ci.nsIMessageBroadcaster);
   this.browsers = {}; //holds list of BrowserObjs
   this.curBrowser = null; // points to current browser
   this.context = "content";
   this.scriptTimeout = null;
   this.timer = null;
   this.marionetteLog = new MarionetteLogObj();
   this.marionettePerf = new MarionettePerfData();
   this.command_id = null;
@@ -148,17 +148,17 @@ MarionetteDriverActor.prototype = {
    * Helper method to send async messages to the content listener
    *
    * @param string name
    *        Suffix of the targetted message listener (Marionette:<suffix>)
    * @param object values
    *        Object to send to the listener
    */
   sendAsync: function MDA_sendAsync(name, values) {
-    this.messageManager.sendAsyncMessage("Marionette:" + name + this.curBrowser.curFrameId, values);
+    this.messageManager.broadcastAsyncMessage("Marionette:" + name + this.curBrowser.curFrameId, values);
   },
 
   /**
    * Helper methods:
    */
 
   /**
    * Generic method to pass a response to the client
@@ -362,17 +362,17 @@ MarionetteDriverActor.prototype = {
 
     if (!Services.prefs.getBoolPref("marionette.contentListener")) {
       waitForWindow.call(this);
     }
     else if ((appName == "B2G") && (this.curBrowser == null)) {
       //if there is a content listener, then we just wake it up
       this.addBrowser(this.getCurrentWindow());
       this.curBrowser.startSession(false);
-      this.messageManager.sendAsyncMessage("Marionette:restart", {});
+      this.messageManager.broadcastAsyncMessage("Marionette:restart", {});
     }
     else {
       this.sendError("Session already running", 500, null);
     }
   },
 
   getSessionCapabilities: function MDA_getSessionCapabilities(){
     let rotatable = appName == "B2G" ? true : false;
@@ -1294,28 +1294,28 @@ MarionetteDriverActor.prototype = {
    *
    * If it is a B2G environment, it will make the main content listener sleep, and close
    * all other listeners. The main content listener persists after disconnect (it's the homescreen),
    * and can safely be reused.
    */
   deleteSession: function MDA_deleteSession() {
     if (this.curBrowser != null) {
       if (appName == "B2G") {
-        this.messageManager.sendAsyncMessage("Marionette:sleepSession" + this.curBrowser.mainContentId, {});
+        this.messageManager.broadcastAsyncMessage("Marionette:sleepSession" + this.curBrowser.mainContentId, {});
         this.curBrowser.knownFrames.splice(this.curBrowser.knownFrames.indexOf(this.curBrowser.mainContentId), 1);
       }
       else {
         //don't set this pref for B2G since the framescript can be safely reused
         Services.prefs.setBoolPref("marionette.contentListener", false);
       }
       this.curBrowser.closeTab();
       //delete session in each frame in each browser
       for (let win in this.browsers) {
         for (let i in this.browsers[win].knownFrames) {
-          this.messageManager.sendAsyncMessage("Marionette:deleteSession" + this.browsers[win].knownFrames[i], {});
+          this.messageManager.broadcastAsyncMessage("Marionette:deleteSession" + this.browsers[win].knownFrames[i], {});
         }
       }
       let winEnum = this.getWinEnumerator();
       while (winEnum.hasMoreElements()) {
         winEnum.getNext().messageManager.removeDelayedFrameScript("chrome://marionette/content/marionette-listener.js"); 
       }
     }
     this.sendOk();
@@ -1514,18 +1514,18 @@ function BrowserObj(win) {
   this.DESKTOP = "desktop";
   this.B2G = "B2G";
   this.browser;
   this.tab = null;
   this.knownFrames = [];
   this.curFrameId = null;
   this.startPage = "about:blank";
   this.mainContentId = null; // used in B2G to identify the homescreen content page
-  this.messageManager = Cc["@mozilla.org/globalmessagemanager;1"].
-                             getService(Ci.nsIChromeFrameMessageManager);
+  this.messageManager = Cc["@mozilla.org/globalmessagemanager;1"]
+                          .getService(Ci.nsIMessageBroadcaster);
   this.newSession = true; //used to set curFrameId upon new session
   this.elementManager = new ElementManager([SELECTOR, NAME, LINK_TEXT, PARTIAL_LINK_TEXT]);
   this.setBrowser(win);
 }
 
 BrowserObj.prototype = {
   /**
    * Set the browser if the application is not B2G
--- a/testing/mochitest/specialpowers/components/SpecialPowersObserver.js
+++ b/testing/mochitest/specialpowers/components/SpecialPowersObserver.js
@@ -25,17 +25,17 @@ var loader = Components.classes["@mozill
                        .getService(Components.interfaces.mozIJSSubScriptLoader);
 loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserverAPI.js");
 
 
 /* XPCOM gunk */
 function SpecialPowersObserver() {
   this._isFrameScriptLoaded = false;
   this._messageManager = Cc["@mozilla.org/globalmessagemanager;1"].
-                         getService(Ci.nsIChromeFrameMessageManager);
+                         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";
@@ -72,17 +72,17 @@ SpecialPowersObserver.prototype = new Sp
       default:
         this._observe(aSubject, aTopic, aData);
         break;
     }
   };
 
   SpecialPowersObserver.prototype._sendAsyncMessage = function(msgname, msg)
   {
-    this._messageManager.sendAsyncMessage(msgname, msg);
+    this._messageManager.broadcastAsyncMessage(msgname, msg);
   };
 
   SpecialPowersObserver.prototype._receiveMessage = function(aMessage) {
     return this._receiveMessageAPI(aMessage);
   };
 
   SpecialPowersObserver.prototype.init = function()
   {
--- a/toolkit/components/contentprefs/nsContentPrefService.js
+++ b/toolkit/components/contentprefs/nsContentPrefService.js
@@ -162,17 +162,17 @@ var inMemoryPrefsProto = {
 };
 
 ContentPrefService.prototype = {
   //**************************************************************************//
   // XPCOM Plumbing
 
   classID:          Components.ID("{e6a3f533-4ffa-4615-8eb4-d4e72d883fa7}"),
   QueryInterface:   XPCOMUtils.generateQI([Ci.nsIContentPrefService,
-                                           Ci.nsIFrameMessageListener]),
+                                           Ci.nsIMessageListener]),
 
 
   //**************************************************************************//
   // Convenience Getters
 
   // Observer Service
   __observerSvc: null,
   get _observerSvc() {
--- a/toolkit/components/contentprefs/tests/unit_ipc/test_contentPrefs_parentipc.js
+++ b/toolkit/components/contentprefs/tests/unit_ipc/test_contentPrefs_parentipc.js
@@ -6,17 +6,17 @@ function run_test() {
             createInstance(Ci.nsIContentPrefService).
             wrappedJSObject;
 
   var messageHandler = cps;
   // FIXME: For now, use the wrappedJSObject hack, until bug
   //        593407 which will clean that up. After that, use
   //        the commented out line below it.
   messageHandler = cps.wrappedJSObject;
-  //messageHandler = cps.QueryInterface(Ci.nsIFrameMessageListener);
+  //messageHandler = cps.QueryInterface(Ci.nsIMessageListener);
 
   // Cannot get values
   do_check_false(messageHandler.receiveMessage({
     name: "ContentPref:getPref",
     json: { group: 'group2', name: 'name' } }).succeeded);
 
   // Cannot set general values
   messageHandler.receiveMessage({ name: "ContentPref:setPref",
@@ -50,17 +50,17 @@ function run_test() {
         return true;
       } else {
         return messageHandler.receiveMessage(aMessage);
       }
     },
   };
 
   var mM = Cc["@mozilla.org/parentprocessmessagemanager;1"].
-           getService(Ci.nsIFrameMessageManager);
+           getService(Ci.nsIMessageListenerManager);
   mM.addMessageListener("ContentPref:setPref", messageProxy);
   mM.addMessageListener("ContentPref:getPref", messageProxy);
   mM.addMessageListener("ContentPref:QUIT", messageProxy);
 
   // Mock storage. This is necessary because
   // the IPC xpcshell setup doesn't do well with the normal storage
   // engine.
 
--- a/toolkit/components/satchel/nsFormHistory.js
+++ b/toolkit/components/satchel/nsFormHistory.js
@@ -16,17 +16,17 @@ const DAY_IN_MS  = 86400000; // 1 day in
 function FormHistory() {
     this.init();
 }
 
 FormHistory.prototype = {
     classID          : Components.ID("{0c1bb408-71a2-403f-854a-3a0659829ded}"),
     QueryInterface   : XPCOMUtils.generateQI([Ci.nsIFormHistory2,
                                               Ci.nsIObserver,
-                                              Ci.nsIFrameMessageListener,
+                                              Ci.nsIMessageListener,
                                               Ci.nsISupportsWeakReference,
                                               ]),
 
     debug          : true,
     enabled        : true,
     saveHttpsForms : true,
 
     // The current database schema.
@@ -99,17 +99,17 @@ FormHistory.prototype = {
     init : function init() {
         Services.prefs.addObserver("browser.formfill.", this, true);
 
         this.updatePrefs();
 
         this.dbStmts = {};
 
         this.messageManager = Cc["@mozilla.org/globalmessagemanager;1"].
-                              getService(Ci.nsIChromeFrameMessageManager);
+                              getService(Ci.nsIMessageListenerManager);
         this.messageManager.loadFrameScript("chrome://satchel/content/formSubmitListener.js", true);
         this.messageManager.addMessageListener("FormHistory:FormSubmitEntries", this);
 
         // Add observers
         Services.obs.addObserver(this, "profile-before-change", true);
         Services.obs.addObserver(this, "idle-daily", true);
         Services.obs.addObserver(this, "formhistory-expire-now", true);
     },
--- a/toolkit/mozapps/extensions/ChromeManifestParser.jsm
+++ b/toolkit/mozapps/extensions/ChromeManifestParser.jsm
@@ -20,18 +20,18 @@ const MSG_JAR_FLUSH = "AddonJarFlush";
 /**
  * Sends local and remote notifications to flush a JAR file cache entry
  *
  * @param aJarFile
  *        The ZIP/XPI/JAR file as a nsIFile
  */
 function flushJarCache(aJarFile) {
   Services.obs.notifyObservers(aJarFile, "flush-cache-entry", null);
-  Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIChromeFrameMessageManager)
-    .sendAsyncMessage(MSG_JAR_FLUSH, aJarFile.path);
+  Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageBroadcaster)
+    .broadcastAsyncMessage(MSG_JAR_FLUSH, aJarFile.path);
 }
 
 
 /**
  * Parses chrome manifest files.
  */
 var ChromeManifestParser = {
 
--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -1020,18 +1020,18 @@ function buildJarURI(aJarfile, aPath) {
 /**
  * Sends local and remote notifications to flush a JAR file cache entry
  *
  * @param aJarFile
  *        The ZIP/XPI/JAR file as a nsIFile
  */
 function flushJarCache(aJarFile) {
   Services.obs.notifyObservers(aJarFile, "flush-cache-entry", null);
-  Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIChromeFrameMessageManager)
-    .sendAsyncMessage(MSG_JAR_FLUSH, aJarFile.path);
+  Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageBroadcaster)
+    .broadcastAsyncMessage(MSG_JAR_FLUSH, aJarFile.path);
 }
 
 function flushStartupCache() {
   // Init this, so it will get the notification.
   Services.obs.notifyObservers(null, "startupcache-invalidate", null);
 }
 
 /**
--- a/toolkit/mozapps/extensions/addonManager.js
+++ b/toolkit/mozapps/extensions/addonManager.js
@@ -35,17 +35,17 @@ Components.utils.import("resource://gre/
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 var gSingleton = null;
 
 function amManager() {
   Components.utils.import("resource://gre/modules/AddonManager.jsm");
 
   var messageManager = Cc["@mozilla.org/globalmessagemanager;1"].
-                       getService(Ci.nsIChromeFrameMessageManager);
+                       getService(Ci.nsIMessageListenerManager);
 
   messageManager.addMessageListener(MSG_INSTALL_ENABLED, this);
   messageManager.addMessageListener(MSG_INSTALL_ADDONS, this);
   messageManager.loadFrameScript(CHILD_SCRIPT, true, true);
 }
 
 amManager.prototype = {
   observe: function AMC_observe(aSubject, aTopic, aData) {