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 105596 5acb2a155d121f7686460c30e2dacd40cea315a4
parent 105595 d36a98542b01fee2c7469eb466c27099f1e727b1
child 105597 f400c8e5cea46069f4e68b2b801eb34ba810a250
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewerssmaug
bugs776825
milestone17.0a1
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) {