Bug 1448850 - Remove nsIMessageListener and nsIMessageListenerManager. r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Fri, 16 Feb 2018 15:28:31 +0100
changeset 411495 b8eff76f4ae6d9cc2166fb04b69331de96a5134b
parent 411494 9f0042d44d22771cbb428a6f885becc1f1f61f63
child 411496 abac8caba16196bb9e58b194d27ff2c77894cd96
push id101678
push userpvanderbeken@mozilla.com
push dateTue, 03 Apr 2018 18:50:19 +0000
treeherdermozilla-inbound@b8eff76f4ae6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1448850
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1448850 - Remove nsIMessageListener and nsIMessageListenerManager. r=bz.
browser/base/content/browser-media.js
browser/components/enterprisepolicies/EnterprisePoliciesContent.js
dom/base/MessageManagerGlobal.h
dom/base/ProcessGlobal.cpp
dom/base/ProcessGlobal.h
dom/base/nsCCUncollectableMarker.cpp
dom/base/nsFrameMessageManager.cpp
dom/base/nsFrameMessageManager.h
dom/base/nsIMessageManager.idl
dom/base/nsInProcessTabChildGlobal.cpp
dom/base/nsInProcessTabChildGlobal.h
dom/base/test/chrome/file_bug549682.xul
dom/chrome-webidl/MessageManager.webidl
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/nsIContentChild.cpp
dom/ipc/nsIContentParent.cpp
dom/media/PeerConnection.js
dom/notification/NotificationStorage.js
testing/marionette/driver.js
toolkit/components/printing/content/printPreviewBindings.xml
toolkit/content/widgets/browser.xml
toolkit/content/widgets/findbar.xml
toolkit/content/widgets/remote-browser.xml
toolkit/modules/DateTimePickerHelper.jsm
toolkit/mozapps/extensions/addonManager.js
toolkit/mozapps/extensions/amContentHandler.js
toolkit/mozapps/extensions/amInstallTrigger.js
--- a/browser/base/content/browser-media.js
+++ b/browser/base/content/browser-media.js
@@ -167,17 +167,16 @@ var gEMEHandler = {
     };
     let options = {
       dismissed: true,
       eventCallback: aTopic => aTopic == "swapping",
       learnMoreURL: Services.urlFormatter.formatURLPref("app.support.baseURL") + "drm-content",
     };
     PopupNotifications.show(browser, "drmContentPlaying", message, anchorId, mainAction, null, options);
   },
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener])
 };
 
 XPCOMUtils.defineLazyGetter(gEMEHandler, "_brandShortName", function() {
   return document.getElementById("bundle_brand").getString("brandShortName");
 });
 
 const TELEMETRY_DDSTAT_SHOWN = 0;
 const TELEMETRY_DDSTAT_SHOWN_FIRST = 1;
--- a/browser/components/enterprisepolicies/EnterprisePoliciesContent.js
+++ b/browser/components/enterprisepolicies/EnterprisePoliciesContent.js
@@ -46,18 +46,17 @@ function EnterprisePoliciesManagerConten
 
   Services.cpmm.addMessageListener("EnterprisePolicies:DisallowFeature", this);
   Services.cpmm.addMessageListener("EnterprisePolicies:Restart", this);
 }
 
 EnterprisePoliciesManagerContent.prototype = {
   // for XPCOM
   classID:          Components.ID("{dc6358f8-d167-4566-bf5b-4350b5e6a7a2}"),
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener,
-                                         Ci.nsIEnterprisePolicies]),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIEnterprisePolicies]),
 
   // redefine the default factory for XPCOMUtils
   _xpcom_factory: EnterprisePoliciesFactory,
 
   _status: Ci.nsIEnterprisePolicies.INACTIVE,
 
   _disallowedFeatures: [],
 
--- a/dom/base/MessageManagerGlobal.h
+++ b/dom/base/MessageManagerGlobal.h
@@ -127,19 +127,21 @@ public:
   }
 
   // MessageManagerGlobal
   void Dump(const nsAString& aStr);
   void PrivateNoteIntentionalCrash(ErrorResult& aError);
   void Atob(const nsAString& aAsciiString, nsAString& aBase64Data, ErrorResult& aError);
   void Btoa(const nsAString& aBase64Data, nsAString& aAsciiString, ErrorResult& aError);
 
-  bool MarkForCC()
+  void MarkForCC()
   {
-    return mMessageManager && mMessageManager->MarkForCC();
+    if (mMessageManager) {
+      mMessageManager->MarkForCC();
+    }
   }
 
 protected:
   explicit MessageManagerGlobal(nsFrameMessageManager* aMessageManager)
     : mMessageManager(aMessageManager)
   {}
 
   RefPtr<nsFrameMessageManager> mMessageManager;
--- a/dom/base/ProcessGlobal.cpp
+++ b/dom/base/ProcessGlobal.cpp
@@ -61,23 +61,21 @@ ProcessGlobal::Get()
 {
   nsCOMPtr<nsIGlobalObject> service = do_GetService(NS_CHILDPROCESSMESSAGEMANAGER_CONTRACTID);
   if (!service) {
     return nullptr;
   }
   return static_cast<ProcessGlobal*>(service.get());
 }
 
-// This method isn't automatically forwarded safely because it's notxpcom, so
-// the IDL binding doesn't know what value to return.
-NS_IMETHODIMP_(bool)
+void
 ProcessGlobal::MarkForCC()
 {
   MarkScopesForCC();
-  return MessageManagerGlobal::MarkForCC();
+  MessageManagerGlobal::MarkForCC();
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(ProcessGlobal)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ProcessGlobal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
   tmp->TraverseHostObjectURIs(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -92,17 +90,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Pr
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
   tmp->nsMessageManagerScriptExecutor::Unlink();
   tmp->UnlinkHostObjectURIs();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ProcessGlobal)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMessageSender)
-  NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
   NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(ProcessGlobal)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(ProcessGlobal)
--- a/dom/base/ProcessGlobal.h
+++ b/dom/base/ProcessGlobal.h
@@ -50,16 +50,18 @@ public:
 
   bool Init();
 
   static ProcessGlobal* Get();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(ProcessGlobal, nsIMessageSender)
 
+  void MarkForCC();
+
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override
   {
     MOZ_CRASH("We should never get here!");
   }
   virtual bool WrapGlobalObject(JSContext* aCx,
                                 JS::CompartmentOptions& aOptions,
                                 JS::MutableHandle<JSObject*> aReflector) override;
@@ -76,17 +78,16 @@ public:
   {
     if (!mMessageManager) {
       aError.Throw(NS_ERROR_NULL_POINTER);
       return;
     }
     mMessageManager->GetInitialProcessData(aCx, aInitialProcessData, aError);
   }
 
-  NS_FORWARD_SAFE_NSIMESSAGELISTENERMANAGER(mMessageManager)
   NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
 
   virtual void LoadScript(const nsAString& aURL);
 
   virtual JSObject* GetGlobalJSObject() override
   {
     return GetWrapper();
   }
--- a/dom/base/nsCCUncollectableMarker.cpp
+++ b/dom/base/nsCCUncollectableMarker.cpp
@@ -285,17 +285,17 @@ MarkWindowList(nsISimpleEnumerator* aWin
          iter) {
     if (nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryInterface(iter)) {
       nsCOMPtr<nsIDocShell> rootDocShell = window->GetDocShell();
 
       MarkDocShell(rootDocShell, aCleanupJS);
 
       RefPtr<TabChild> tabChild = TabChild::GetFrom(rootDocShell);
       if (tabChild) {
-        nsCOMPtr<nsIContentFrameMessageManager> mm = tabChild->GetMessageManager();
+        RefPtr<TabChildGlobal> mm = tabChild->GetMessageManager();
         if (mm) {
           // MarkForCC ends up calling UnmarkGray on message listeners, which
           // TraceBlackJS can't do yet.
           mm->MarkForCC();
         }
       }
     }
   }
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -104,16 +104,26 @@ nsFrameMessageManager::~nsFrameMessageMa
       delete mozilla::dom::SameProcessMessageQueue::Get();
     }
     if (this == sSameProcessParentManager) {
       sSameProcessParentManager = nullptr;
     }
   }
 }
 
+inline void
+ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
+                            nsMessageListenerInfo& aField,
+                            const char* aName,
+                            uint32_t aFlags = 0)
+{
+  ImplCycleCollectionTraverse(aCallback, aField.mStrongListener, aName, aFlags);
+  ImplCycleCollectionTraverse(aCallback, aField.mWeakListener, aName, aFlags);
+}
+
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameMessageManager)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameMessageManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListeners)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildManagers)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsFrameMessageManager)
@@ -128,18 +138,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildManagers)
   tmp->mInitialProcessData.setNull();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentFrameMessageManager)
 
-  NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
-
   /* Message managers in child process implement nsIMessageSender.
      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(nsIMessageSender, !mChrome || !mIsBroadcaster)
 
   /* nsIContentFrameMessageManager is accessible only in TabChildGlobal. */
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIContentFrameMessageManager,
@@ -200,187 +208,135 @@ SameProcessCpowHolder::ToObject(JSContex
   if (!mObj) {
     return true;
   }
 
   aObjp.set(mObj);
   return JS_WrapObject(aCx, aObjp);
 }
 
-// nsIMessageListenerManager
-
 void
 nsFrameMessageManager::AddMessageListener(const nsAString& aMessageName,
                                           MessageListener& aListener,
                                           bool aListenWhenClosed,
                                           ErrorResult& aError)
 {
-  AddMessageListener(aMessageName, MessageListenerHolder(&aListener), aListenWhenClosed);
-}
-
-NS_IMETHODIMP
-nsFrameMessageManager::AddMessageListener(const nsAString& aMessage,
-                                          nsIMessageListener* aListener,
-                                          bool aListenWhenClosed)
-{
-  AddMessageListener(aMessage, MessageListenerHolder(aListener), aListenWhenClosed);
-  return NS_OK;
-}
-
-void
-nsFrameMessageManager::AddMessageListener(const nsAString& aMessage,
-                                          MessageListenerHolder&& aListener,
-                                          bool aListenWhenClosed)
-{
-  auto listeners = mListeners.LookupForAdd(aMessage).OrInsert([]() {
+  auto listeners = mListeners.LookupForAdd(aMessageName).OrInsert([]() {
       return new nsAutoTObserverArray<nsMessageListenerInfo, 1>();
     });
   uint32_t len = listeners->Length();
   for (uint32_t i = 0; i < len; ++i) {
-    if (listeners->ElementAt(i).mStrongListener == aListener) {
+    MessageListener* strongListener = listeners->ElementAt(i).mStrongListener;
+    if (strongListener && *strongListener == aListener) {
       return;
     }
   }
 
   nsMessageListenerInfo* entry = listeners->AppendElement();
-  entry->mStrongListener = Move(aListener);
+  entry->mStrongListener = &aListener;
   entry->mListenWhenClosed = aListenWhenClosed;
 }
 
 void
 nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessageName,
                                              MessageListener& aListener,
                                              ErrorResult& aError)
 {
-  RemoveMessageListener(aMessageName, MessageListenerHolder(&aListener));
-}
-
-NS_IMETHODIMP
-nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessage,
-                                             nsIMessageListener* aListener)
-{
-  RemoveMessageListener(aMessage, MessageListenerHolder(aListener));
-  return NS_OK;
-}
-
-void
-nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessage,
-                                             const MessageListenerHolder& aListener)
-{
   nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
-    mListeners.Get(aMessage);
+    mListeners.Get(aMessageName);
   if (listeners) {
     uint32_t len = listeners->Length();
     for (uint32_t i = 0; i < len; ++i) {
-      if (listeners->ElementAt(i).mStrongListener == aListener) {
+      MessageListener* strongListener = listeners->ElementAt(i).mStrongListener;
+      if (strongListener && *strongListener == aListener) {
         listeners->RemoveElementAt(i);
         return;
       }
     }
   }
 }
 
-static already_AddRefed<nsIMessageListener>
+static already_AddRefed<nsISupports>
 ToXPCOMMessageListener(MessageListener& aListener)
 {
-  return MessageListenerHolder(&aListener).ToXPCOMCallback();
+  return CallbackObjectHolder<mozilla::dom::MessageListener,
+                              nsISupports>(&aListener).ToXPCOMCallback();
 }
 
 void
 nsFrameMessageManager::AddWeakMessageListener(const nsAString& aMessageName,
                                               MessageListener& aListener,
                                               ErrorResult& aError)
 {
-  nsCOMPtr<nsIMessageListener> listener(ToXPCOMMessageListener(aListener));
-  if (!listener) {
-    aError.Throw(NS_ERROR_FAILURE);
+  nsCOMPtr<nsISupports> listener(ToXPCOMMessageListener(aListener));
+  nsWeakPtr weak = do_GetWeakReference(listener);
+  if (!weak) {
+    aError.Throw(NS_ERROR_NO_INTERFACE);
     return;
   }
 
-  aError = AddWeakMessageListener(aMessageName, listener);
-}
-
-NS_IMETHODIMP
-nsFrameMessageManager::AddWeakMessageListener(const nsAString& aMessage,
-                                              nsIMessageListener* aListener)
-{
-  nsWeakPtr weak = do_GetWeakReference(aListener);
-  NS_ENSURE_TRUE(weak, NS_ERROR_NO_INTERFACE);
-
 #ifdef DEBUG
   // It's technically possible that one object X could give two different
   // nsIWeakReference*'s when you do_GetWeakReference(X).  We really don't want
   // this to happen; it will break e.g. RemoveWeakMessageListener.  So let's
   // check that we're not getting ourselves into that situation.
-  nsCOMPtr<nsISupports> canonical = do_QueryInterface(aListener);
+  nsCOMPtr<nsISupports> canonical = do_QueryInterface(listener);
   for (auto iter = mListeners.Iter(); !iter.Done(); iter.Next()) {
     nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners = iter.UserData();
     uint32_t count = listeners->Length();
     for (uint32_t i = 0; i < count; i++) {
       nsWeakPtr weakListener = listeners->ElementAt(i).mWeakListener;
       if (weakListener) {
         nsCOMPtr<nsISupports> otherCanonical = do_QueryReferent(weakListener);
         MOZ_ASSERT((canonical == otherCanonical) == (weak == weakListener));
       }
     }
   }
 #endif
 
-  auto listeners = mListeners.LookupForAdd(aMessage).OrInsert([]() {
+  auto listeners = mListeners.LookupForAdd(aMessageName).OrInsert([]() {
       return new nsAutoTObserverArray<nsMessageListenerInfo, 1>();
     });
   uint32_t len = listeners->Length();
   for (uint32_t i = 0; i < len; ++i) {
     if (listeners->ElementAt(i).mWeakListener == weak) {
-      return NS_OK;
+      return;
     }
   }
 
   nsMessageListenerInfo* entry = listeners->AppendElement();
   entry->mWeakListener = weak;
   entry->mListenWhenClosed = false;
-  return NS_OK;
 }
 
 void
 nsFrameMessageManager::RemoveWeakMessageListener(const nsAString& aMessageName,
                                                  MessageListener& aListener,
                                                  ErrorResult& aError)
 {
-  nsCOMPtr<nsIMessageListener> listener(ToXPCOMMessageListener(aListener));
-  if (!listener) {
-    aError.Throw(NS_ERROR_FAILURE);
+  nsCOMPtr<nsISupports> listener(ToXPCOMMessageListener(aListener));
+  nsWeakPtr weak = do_GetWeakReference(listener);
+  if (!weak) {
+    aError.Throw(NS_ERROR_NO_INTERFACE);
     return;
   }
 
-  aError = RemoveWeakMessageListener(aMessageName, listener);
-}
-
-NS_IMETHODIMP
-nsFrameMessageManager::RemoveWeakMessageListener(const nsAString& aMessage,
-                                                 nsIMessageListener* aListener)
-{
-  nsWeakPtr weak = do_GetWeakReference(aListener);
-  NS_ENSURE_TRUE(weak, NS_OK);
-
   nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
-    mListeners.Get(aMessage);
+    mListeners.Get(aMessageName);
   if (!listeners) {
-    return NS_OK;
+    return;
   }
 
   uint32_t len = listeners->Length();
   for (uint32_t i = 0; i < len; ++i) {
     if (listeners->ElementAt(i).mWeakListener == weak) {
       listeners->RemoveElementAt(i);
-      return NS_OK;
+      return;
     }
   }
-
-  return NS_OK;
 }
 
 void
 nsFrameMessageManager::LoadScript(const nsAString& aURL,
                                   bool aAllowDelayedLoad,
                                   bool aRunInGlobalScope,
                                   ErrorResult& aError)
 {
@@ -758,42 +714,27 @@ public:
     }
   }
 
   bool mWasHandlingMessage;
   RefPtr<nsFrameMessageManager> mMM;
 };
 
 
-// nsIMessageListener
-
-nsresult
-nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
-                                      nsFrameLoader* aTargetFrameLoader,
-                                      const nsAString& aMessage,
-                                      bool aIsSync,
-                                      StructuredCloneData* aCloneData,
-                                      mozilla::jsipc::CpowHolder* aCpows,
-                                      nsIPrincipal* aPrincipal,
-                                      nsTArray<StructuredCloneData>* aRetVal)
-{
-  return ReceiveMessage(aTarget, aTargetFrameLoader, mClosed, aMessage, aIsSync,
-                        aCloneData, aCpows, aPrincipal, aRetVal);
-}
-
-nsresult
+void
 nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
                                       nsFrameLoader* aTargetFrameLoader,
                                       bool aTargetClosed,
                                       const nsAString& aMessage,
                                       bool aIsSync,
                                       StructuredCloneData* aCloneData,
                                       mozilla::jsipc::CpowHolder* aCpows,
                                       nsIPrincipal* aPrincipal,
-                                      nsTArray<StructuredCloneData>* aRetVal)
+                                      nsTArray<StructuredCloneData>* aRetVal,
+                                      ErrorResult& aError)
 {
   MOZ_ASSERT(aTarget);
 
   nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
     mListeners.Get(aMessage);
   if (listeners) {
 
     MMListenerRemover lr(this);
@@ -815,32 +756,21 @@ nsFrameMessageManager::ReceiveMessage(ns
       if (!listener.mListenWhenClosed && aTargetClosed) {
         continue;
       }
 
       JS::RootingContext* rcx = RootingCx();
       JS::Rooted<JSObject*> object(rcx);
 
       RefPtr<MessageListener> webIDLListener;
-      if (!weakListener && listener.mStrongListener.HasWebIDLCallback()) {
-        webIDLListener = listener.mStrongListener.GetWebIDLCallback();
-      } else {
-        webIDLListener = nullptr;
-      }
-
-      if (webIDLListener) {
+      if (!weakListener) {
+        webIDLListener = listener.mStrongListener;
         object = webIDLListener->CallbackOrNull();
       } else {
-        nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS;
-        if (weakListener) {
-          wrappedJS = do_QueryInterface(weakListener);
-        } else {
-          wrappedJS = do_QueryInterface(listener.mStrongListener.GetXPCOMCallback());
-        }
-
+        nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(weakListener);
         if (!wrappedJS) {
           continue;
         }
 
         object = wrappedJS->GetJSObject();
       }
 
       if (!object) {
@@ -848,48 +778,48 @@ nsFrameMessageManager::ReceiveMessage(ns
       }
 
       AutoEntryScript aes(object, "message manager handler");
       JSContext* cx = aes.cx();
 
       RootedDictionary<ReceiveMessageArgument> argument(cx);
 
       JS::Rooted<JSObject*> cpows(cx);
-      if (aCpows) {
-        if (!aCpows->ToObject(cx, &cpows)) {
-          return NS_ERROR_UNEXPECTED;
-        }
+      if (aCpows && !aCpows->ToObject(cx, &cpows)) {
+        aError.Throw(NS_ERROR_UNEXPECTED);
+        return;
       }
 
       if (!cpows) {
         cpows = JS_NewPlainObject(cx);
         if (!cpows) {
-          return NS_ERROR_UNEXPECTED;
+          aError.Throw(NS_ERROR_UNEXPECTED);
+          return;
         }
       }
       argument.mObjects = cpows;
 
       JS::Rooted<JS::Value> json(cx, JS::NullValue());
       if (aCloneData && aCloneData->DataLength()) {
-        ErrorResult rv;
-        aCloneData->Read(cx, &json, rv);
-        if (NS_WARN_IF(rv.Failed())) {
-          rv.SuppressException();
+        aCloneData->Read(cx, &json, aError);
+        if (NS_WARN_IF(aError.Failed())) {
+          aError.SuppressException();
           JS_ClearPendingException(cx);
-          return NS_OK;
+          return;
         }
       }
       argument.mData = json;
       argument.mJson = json;
 
       // Get cloned MessagePort from StructuredCloneData.
       if (aCloneData) {
         Sequence<OwningNonNull<MessagePort>> ports;
         if (!aCloneData->TakeTransferredPortsAsSequence(ports)) {
-          return NS_ERROR_FAILURE;
+          aError.Throw(NS_ERROR_FAILURE);
+          return;
         }
         argument.mPorts.Construct(Move(ports));
       }
 
       argument.mName = aMessage;
       argument.mPrincipal = aPrincipal;
       argument.mSync = aIsSync;
       argument.mTarget = aTarget;
@@ -904,70 +834,75 @@ nsFrameMessageManager::ReceiveMessage(ns
         // messageManager is wrapped in TabChildGlobal.
         nsCOMPtr<nsISupports> defaultThisValue;
         if (mChrome) {
           defaultThisValue = do_QueryObject(this);
         } else {
           defaultThisValue = aTarget;
         }
         js::AssertSameCompartment(cx, object);
-        nsresult rv = nsContentUtils::WrapNative(cx, defaultThisValue, &thisValue);
-        NS_ENSURE_SUCCESS(rv, rv);
+        aError = nsContentUtils::WrapNative(cx, defaultThisValue, &thisValue);
+        if (aError.Failed()) {
+          return;
+        }
       }
 
       JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
       if (webIDLListener) {
-        ErrorResult rv;
-        webIDLListener->ReceiveMessage(thisValue, argument, &rval, rv);
-        if (rv.Failed()) {
+        webIDLListener->ReceiveMessage(thisValue, argument, &rval, aError);
+        if (aError.Failed()) {
           // At this point the call to ReceiveMessage will have reported any exceptions
           // (we kept the default of eReportExceptions). We suppress the failure in the
           // ErrorResult and continue.
-          rv.SuppressException();
+          aError.SuppressException();
           continue;
         }
       } else {
         JS::Rooted<JS::Value> funval(cx);
         if (JS::IsCallable(object)) {
           // If the listener is a JS function:
           funval.setObject(*object);
         } else {
           // If the listener is a JS object which has receiveMessage function:
           if (!JS_GetProperty(cx, object, "receiveMessage", &funval) ||
               !funval.isObject()) {
-            return NS_ERROR_UNEXPECTED;
+            aError.Throw(NS_ERROR_UNEXPECTED);
+            return;
           }
 
           // Check if the object is even callable.
-          NS_ENSURE_STATE(JS::IsCallable(&funval.toObject()));
+          if (!JS::IsCallable(&funval.toObject())) {
+            aError.Throw(NS_ERROR_UNEXPECTED);
+            return;
+          }
           thisValue.setObject(*object);
         }
 
         JS::Rooted<JS::Value> argv(cx);
         if (!ToJSValue(cx, argument, &argv)) {
-          return NS_ERROR_UNEXPECTED;
+          aError.Throw(NS_ERROR_UNEXPECTED);
+          return;
         }
 
         {
           JS::Rooted<JSObject*> thisObject(cx, thisValue.toObjectOrNull());
           js::AssertSameCompartment(cx, thisObject);
           if (!JS_CallFunctionValue(cx, thisObject, funval,
                                     JS::HandleValueArray(argv), &rval)) {
             // Because the AutoEntryScript is inside the loop this continue will make us
             // report any exceptions (after which we'll move on to the next listener).
             continue;
           }
         }
       }
 
       if (aRetVal) {
-        ErrorResult rv;
         StructuredCloneData* data = aRetVal->AppendElement();
-        data->Write(cx, rval, rv);
-        if (NS_WARN_IF(rv.Failed())) {
+        data->Write(cx, rval, aError);
+        if (NS_WARN_IF(aError.Failed())) {
           aRetVal->RemoveLastElement();
           nsString msg = aMessage + NS_LITERAL_STRING(": message reply cannot be cloned. Are you trying to send an XPCOM object?");
 
           nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
           if (console) {
             nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
             error->Init(msg, EmptyString(), EmptyString(),
                         0, 0, nsIScriptError::warningFlag, "chrome javascript",
@@ -979,23 +914,20 @@ nsFrameMessageManager::ReceiveMessage(ns
           continue;
         }
       }
     }
   }
 
   RefPtr<nsFrameMessageManager> kungFuDeathGrip = GetParentManager();
   if (kungFuDeathGrip) {
-    return kungFuDeathGrip->ReceiveMessage(aTarget, aTargetFrameLoader,
-                                           aTargetClosed, aMessage,
-                                           aIsSync, aCloneData,
-                                           aCpows, aPrincipal,
-                                           aRetVal);
+    kungFuDeathGrip->ReceiveMessage(aTarget, aTargetFrameLoader, aTargetClosed, aMessage,
+                                    aIsSync, aCloneData, aCpows, aPrincipal, aRetVal,
+                                    aError);
   }
-  return NS_OK;
 }
 
 void
 nsFrameMessageManager::LoadPendingScripts(nsFrameMessageManager* aManager,
                                           nsFrameMessageManager* aChildMM)
 {
   // We have parent manager if we're a message broadcaster.
   // In that case we want to load the pending scripts from all parent
@@ -1747,18 +1679,18 @@ public:
                              bool aIsSync) override
   {
     SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
     queue->Flush();
 
     if (nsFrameMessageManager::sSameProcessParentManager) {
       SameProcessCpowHolder cpows(JS::RootingContext::get(aCx), aCpows);
       RefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager;
-      ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), nullptr, aMessage,
-                          true, &aData, &cpows, aPrincipal, aRetVal);
+      ppm->ReceiveMessage(ppm, nullptr, aMessage, true, &aData, &cpows, aPrincipal,
+                          aRetVal, IgnoreErrors());
     }
     return true;
   }
 
   nsresult DoSendAsyncMessage(JSContext* aCx,
                               const nsAString& aMessage,
                               StructuredCloneData& aData,
                               JS::Handle<JSObject *> aCpows,
@@ -1837,38 +1769,33 @@ NS_NewChildProcessMessageManager(nsISupp
   }
   auto* mm = new ChildProcessMessageManager(cb);
   nsFrameMessageManager::SetChildProcessManager(mm);
   RefPtr<ProcessGlobal> global = new ProcessGlobal(mm);
   NS_ENSURE_TRUE(global->Init(), NS_ERROR_UNEXPECTED);
   return CallQueryInterface(global, aResult);
 }
 
-bool
+void
 nsFrameMessageManager::MarkForCC()
 {
   for (auto iter = mListeners.Iter(); !iter.Done(); iter.Next()) {
     nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners = iter.UserData();
     uint32_t count = listeners->Length();
     for (uint32_t i = 0; i < count; i++) {
-      MessageListenerHolder& strongListener = listeners->ElementAt(i).mStrongListener;
+      MessageListener* strongListener = listeners->ElementAt(i).mStrongListener;
       if (strongListener) {
-        if (strongListener.HasWebIDLCallback()) {
-          strongListener.GetWebIDLCallback()->MarkForCC();
-        } else {
-          xpc_TryUnmarkWrappedGrayObject(strongListener.GetXPCOMCallback());
-        }
+        strongListener->MarkForCC();
       }
     }
   }
 
   if (mRefCnt.IsPurple()) {
     mRefCnt.RemovePurple();
   }
-  return true;
 }
 
 nsSameProcessAsyncMessageBase::nsSameProcessAsyncMessageBase(JS::RootingContext* aRootingCx,
                                                              JS::Handle<JSObject*> aCpows)
   : mCpows(aRootingCx, aCpows)
 #ifdef DEBUG
   , mCalledInit(false)
 #endif
@@ -1901,11 +1828,11 @@ nsSameProcessAsyncMessageBase::ReceiveMe
 {
   // Make sure that we have called Init() and it has succeeded.
   MOZ_ASSERT(mCalledInit);
   if (aManager) {
     SameProcessCpowHolder cpows(RootingCx(), mCpows);
 
     RefPtr<nsFrameMessageManager> mm = aManager;
     mm->ReceiveMessage(aTarget, aTargetFrameLoader, mMessage, false, &mData,
-                       &cpows, mPrincipal, nullptr);
+                       &cpows, mPrincipal, nullptr, IgnoreErrors());
   }
 }
--- a/dom/base/nsFrameMessageManager.h
+++ b/dom/base/nsFrameMessageManager.h
@@ -114,47 +114,33 @@ protected:
 
 void UnpackClonedMessageDataForParent(const ClonedMessageData& aClonedData,
                                       StructuredCloneData& aData);
 
 void UnpackClonedMessageDataForChild(const ClonedMessageData& aClonedData,
                                      StructuredCloneData& aData);
 
 } // namespace ipc
-
-typedef CallbackObjectHolder<mozilla::dom::MessageListener,
-                             nsIMessageListener> MessageListenerHolder;
-
 } // namespace dom
 } // namespace mozilla
 
 struct nsMessageListenerInfo
 {
   bool operator==(const nsMessageListenerInfo& aOther) const
   {
     return &aOther == this;
   }
 
-  // If mWeakListener is null then mStrongListener holds either a MessageListener or an
-  // nsIMessageListener. If mWeakListener is non-null then mStrongListener contains null.
-  mozilla::dom::MessageListenerHolder mStrongListener;
+  // If mWeakListener is null then mStrongListener holds a MessageListener.
+  // If mWeakListener is non-null then mStrongListener contains null.
+  RefPtr<mozilla::dom::MessageListener> mStrongListener;
   nsWeakPtr mWeakListener;
   bool mListenWhenClosed;
 };
 
-inline void
-ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
-                            nsMessageListenerInfo& aField,
-                            const char* aName,
-                            uint32_t aFlags = 0)
-{
-  ImplCycleCollectionTraverse(aCallback, aField.mStrongListener, aName, aFlags);
-  ImplCycleCollectionTraverse(aCallback, aField.mWeakListener, aName, aFlags);
-}
-
 class MOZ_STACK_CLASS SameProcessCpowHolder : public mozilla::jsipc::CpowHolder
 {
 public:
   SameProcessCpowHolder(JS::RootingContext* aRootingCx, JS::Handle<JSObject*> aObj)
     : mObj(aRootingCx, aObj)
   {
   }
 
@@ -182,16 +168,18 @@ public:
   explicit nsFrameMessageManager(mozilla::dom::ipc::MessageManagerCallback* aCallback)
     : nsFrameMessageManager(aCallback, MessageManagerFlags::MM_NONE)
   {}
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsFrameMessageManager,
                                                          nsIContentFrameMessageManager)
 
+  void MarkForCC();
+
   // MessageListenerManager
   void AddMessageListener(const nsAString& aMessageName,
                           mozilla::dom::MessageListener& aListener,
                           bool aListenWhenClosed,
                           mozilla::ErrorResult& aError);
   void RemoveMessageListener(const nsAString& aMessageName,
                              mozilla::dom::MessageListener& aListener,
                              mozilla::ErrorResult& aError);
@@ -237,28 +225,31 @@ public:
     SendMessage(aCx, aMessageName, aObj, aObjects, aPrincipal, false, aResult, aError);
   }
 
   // GlobalProcessScriptLoader
   void GetInitialProcessData(JSContext* aCx,
                              JS::MutableHandle<JS::Value> aInitialProcessData,
                              mozilla::ErrorResult& aError);
 
-  NS_DECL_NSIMESSAGELISTENERMANAGER
   NS_DECL_NSIMESSAGESENDER
   NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
 
   static mozilla::dom::ChromeMessageSender*
   NewProcessMessageManager(bool aIsRemote);
 
-  nsresult ReceiveMessage(nsISupports* aTarget, nsFrameLoader* aTargetFrameLoader,
-                          const nsAString& aMessage,
-                          bool aIsSync, StructuredCloneData* aCloneData,
-                          mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal,
-                          nsTArray<StructuredCloneData>* aRetVal);
+  void ReceiveMessage(nsISupports* aTarget, nsFrameLoader* aTargetFrameLoader,
+                      const nsAString& aMessage, bool aIsSync,
+                      StructuredCloneData* aCloneData, mozilla::jsipc::CpowHolder* aCpows,
+                      nsIPrincipal* aPrincipal, nsTArray<StructuredCloneData>* aRetVal,
+                      mozilla::ErrorResult& aError)
+  {
+    ReceiveMessage(aTarget, aTargetFrameLoader, mClosed, aMessage, aIsSync, aCloneData,
+                   aCpows, aPrincipal, aRetVal, aError);
+  }
 
   void Disconnect(bool aRemoveFromParent = true);
   void Close();
 
   void SetCallback(mozilla::dom::ipc::MessageManagerCallback* aCallback);
 
   mozilla::dom::ipc::MessageManagerCallback* GetCallback()
   {
@@ -332,21 +323,21 @@ protected:
                    JS::Handle<JS::Value> aObj, JS::Handle<JSObject*> aObjects,
                    nsIPrincipal* aPrincipal, bool aIsSync, nsTArray<JS::Value>& aResult,
                    mozilla::ErrorResult& aError);
   void SendMessage(JSContext* aCx, const nsAString& aMessageName,
                    StructuredCloneData& aData, JS::Handle<JSObject*> aObjects,
                    nsIPrincipal* aPrincipal, bool aIsSync,
                    nsTArray<JS::Value>& aResult, mozilla::ErrorResult& aError);
 
-  nsresult ReceiveMessage(nsISupports* aTarget, nsFrameLoader* aTargetFrameLoader,
-                          bool aTargetClosed, const nsAString& aMessage,
-                          bool aIsSync, StructuredCloneData* aCloneData,
-                          mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal,
-                          nsTArray<StructuredCloneData>* aRetVal);
+  void ReceiveMessage(nsISupports* aTarget, nsFrameLoader* aTargetFrameLoader,
+                      bool aTargetClosed, const nsAString& aMessage, bool aIsSync,
+                      StructuredCloneData* aCloneData, mozilla::jsipc::CpowHolder* aCpows,
+                      nsIPrincipal* aPrincipal, nsTArray<StructuredCloneData>* aRetVal,
+                      mozilla::ErrorResult& aError);
 
   void LoadScript(const nsAString& aURL, bool aAllowDelayedLoad,
                   bool aRunInGlobalScope, mozilla::ErrorResult& aError);
   void RemoveDelayedScript(const nsAString& aURL);
   nsresult GetDelayedScripts(JSContext* aCx,
                              JS::MutableHandle<JS::Value> aList);
   void GetDelayedScripts(JSContext* aCx, nsTArray<nsTArray<JS::Value>>& aList,
                          mozilla::ErrorResult& aError);
@@ -381,22 +372,16 @@ protected:
 
   void LoadPendingScripts(nsFrameMessageManager* aManager,
                           nsFrameMessageManager* aChildMM);
 public:
   static mozilla::dom::ChromeMessageBroadcaster* sParentProcessManager;
   static nsFrameMessageManager* sSameProcessParentManager;
   static nsTArray<nsCOMPtr<nsIRunnable> >* sPendingSameProcessAsyncMessages;
 private:
-  void AddMessageListener(const nsAString& aMessageName,
-                          mozilla::dom::MessageListenerHolder&& aListener,
-                          bool aListenWhenClosed);
-  void RemoveMessageListener(const nsAString& aMessageName,
-                             const mozilla::dom::MessageListenerHolder&  aListener);
-
   static mozilla::dom::ChildProcessMessageManager* sChildProcessManager;
 };
 
 /* A helper class for taking care of many details for async message sending
    within a single process.  Intended to be used like so:
 
    class MyAsyncMessage : public nsSameProcessAsyncMessageBase, public Runnable
    {
--- a/dom/base/nsIMessageManager.idl
+++ b/dom/base/nsIMessageManager.idl
@@ -1,277 +1,19 @@
 /* -*- 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/. */
 
 #include "nsISupports.idl"
 
-interface mozIDOMWindowProxy;
-interface nsIDocShell;
 interface nsIContent;
-interface nsIEventTarget;
-interface nsIPrincipal;
-interface nsFrameLoader;
-
-// We define a "native" type for nsFrameLoader so that the rust xpidl
-// codegen doesn't try to do anything with it.
-native nativeFrameLoader(nsFrameLoader*);
-
-/**
- * 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
- *  - "group message managers" which correspond to named message
- *    managers with a specific window MM as the parent
- *  - 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
- *   |    |
- *   |    +-->group MMgr1
- *   |    |    |
- *   |    |    +-->frame MMp2_1<------->frame MMc2_1
- *   |    |    |
- *   |    |    +-->frame MMp2_2<------->frame MMc2_2
- *   |    |
- *   |    +-->group MMgr2
- *   |    |    ...
- *   |    |
- *   |    ...
- *   |
- *   +-->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.
- *
- * A message sent from MMc2_1 will be sent to MMp2_1 and also notify
- * all message managers in the hierarchy above that, including the
- * group message manager MMgr1.
 
- * 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 MMgr1, which would broadcast it to MMp2_1 and MMp2_2.
- * After that it would broadcast to MMgr2 and then to MMw2, and so
- * on down the hierarchy.
- *
- *   ***** PERFORMANCE AND SECURITY WARNING *****
- * Messages broadcast through the global MM and window or group 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 (GPPMM)
- *   |
- *   +-->parent in-process PIPMM<-->child in-process CIPPMM
- *   |
- *   +-->parent (PPMM1)<------------------>child (CPMM1)
- *   |
- *   +-->parent (PPMM2)<------------------>child (CPMM2)
- *   ...
- *
- * Note, PIPMM and CIPPMM both run in the parent process.
- *
- * For example: the parent-process PPMM1 sends messages to the
- * child-process CPMM1.
- *
- * For example: CPMM1 sends messages directly to PPMM1. The global GPPMM
- * will also notify their message listeners when the message arrives.
- *
- * For example: messages sent through the global GPPMM will be
- * dispatched to the listeners of the same-process, CIPPMM, CPMM1,
- * CPMM2, etc.
- *
- *   ***** PERFORMANCE AND SECURITY WARNING *****
- * Messages broadcast through the GPPMM 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%.
-   *     data:      %structured clone of the sent message data%,
-   *     json:      %same as .data, deprecated%,
-   *     objects:   %named table of jsvals/objects, or null%
-   *     principal: %principal for the window app
-   *   }
-   *
-   * 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();
-};
-
-[uuid(b949bfec-bb7d-47bc-b387-ac6a9b655072)]
-interface nsIMessageListenerManager : nsISupports
-{
-  /**
-   * Register |listener| to receive |messageName|.  All listener
-   * callbacks for a particular message are invoked when that message
-   * is received.
-   *
-   * The message manager holds a strong ref to |listener|.
-   *
-   * If the same listener registers twice for the same message, the
-   * second registration is ignored.
-   *
-   * Pass true for listenWhenClosed if you want to receive messages
-   * during the short period after a frame has been removed from the
-   * DOM and before its frame script has finished unloading. This
-   * parameter only has an effect for frame message managers in
-   * the main process. Default is false.
-   */
-  void addMessageListener(in AString messageName,
-                          in nsIMessageListener listener,
-                          [optional] in boolean listenWhenClosed);
-
-  /**
-   * Undo an |addMessageListener| call -- that is, calling this causes us to no
-   * longer invoke |listener| when |messageName| is received.
-   *
-   * removeMessageListener does not remove a message listener added via
-   * addWeakMessageListener; use removeWeakMessageListener for that.
-   */
-  void removeMessageListener(in AString messageName,
-                             in nsIMessageListener listener);
-
-  /**
-   * This is just like addMessageListener, except the message manager holds a
-   * weak ref to |listener|.
-   *
-   * If you have two weak message listeners for the same message, they may be
-   * called in any order.
-   */
-  void addWeakMessageListener(in AString messageName,
-                              in nsIMessageListener listener);
-
-  /**
-   * This undoes an |addWeakMessageListener| call.
-   */
-  void removeWeakMessageListener(in AString messageName,
-                                 in nsIMessageListener listener);
-
-  [notxpcom] boolean markForCC();
-};
-
-/**
- * Message "senders" have a single "other side" to which messages are
- * sent.  For example, a child-process message manager will send
- * messages that are only delivered to its one parent-process message
- * manager.
- */
 [uuid(bb5d79e4-e73c-45e7-9651-4d718f4b994c)]
-interface nsIMessageSender : nsIMessageListenerManager
+interface nsIMessageSender : nsISupports
 {
 };
 
 [uuid(694e367c-aa25-4446-8499-2c527c4bd838)]
 interface nsIContentFrameMessageManager : nsIMessageSender
 {
 };
 
--- a/dom/base/nsInProcessTabChildGlobal.cpp
+++ b/dom/base/nsInProcessTabChildGlobal.cpp
@@ -36,17 +36,17 @@ nsInProcessTabChildGlobal::DoSendBlockin
   SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
   queue->Flush();
 
   if (mChromeMessageManager) {
     SameProcessCpowHolder cpows(JS::RootingContext::get(aCx), aCpows);
     RefPtr<nsFrameMessageManager> mm = mChromeMessageManager;
     RefPtr<nsFrameLoader> fl = GetFrameLoader();
     mm->ReceiveMessage(mOwner, fl, aMessage, true, &aData, &cpows, aPrincipal,
-                       aRetVal);
+                       aRetVal, IgnoreErrors());
   }
   return true;
 }
 
 class nsAsyncMessageToParent : public nsSameProcessAsyncMessageBase,
                                public SameProcessMessageQueue::Runnable
 {
 public:
@@ -111,21 +111,21 @@ nsInProcessTabChildGlobal::nsInProcessTa
 nsInProcessTabChildGlobal::~nsInProcessTabChildGlobal()
 {
   mAnonymousGlobalScopes.Clear();
   mozilla::DropJSObjects(this);
 }
 
 // This method isn't automatically forwarded safely because it's notxpcom, so
 // the IDL binding doesn't know what value to return.
-NS_IMETHODIMP_(bool)
+void
 nsInProcessTabChildGlobal::MarkForCC()
 {
   MarkScopesForCC();
-  return MessageManagerGlobal::MarkForCC();
+  MessageManagerGlobal::MarkForCC();
 }
 
 nsresult
 nsInProcessTabChildGlobal::Init()
 {
 #ifdef DEBUG
   nsresult rv =
 #endif
@@ -155,17 +155,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
                                                 DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)
   tmp->nsMessageManagerScriptExecutor::Unlink();
   tmp->UnlinkHostObjectURIs();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsInProcessTabChildGlobal)
-  NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
   NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
--- a/dom/base/nsInProcessTabChildGlobal.h
+++ b/dom/base/nsInProcessTabChildGlobal.h
@@ -40,16 +40,18 @@ class nsInProcessTabChildGlobal : public
 
 public:
   nsInProcessTabChildGlobal(nsIDocShell* aShell, nsIContent* aOwner,
                             nsFrameMessageManager* aChrome);
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsInProcessTabChildGlobal,
                                                          mozilla::DOMEventTargetHelper)
 
+  void MarkForCC();
+
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override
   {
     MOZ_CRASH("We should never get here!");
   }
   virtual bool WrapGlobalObject(JSContext* aCx,
                                 JS::CompartmentOptions& aOptions,
                                 JS::MutableHandle<JSObject*> aReflector) override;
@@ -59,17 +61,16 @@ public:
   virtual already_AddRefed<nsIDocShell>
     GetDocShell(mozilla::ErrorResult& aError) override
   {
     nsCOMPtr<nsIDocShell> docShell(mDocShell);
     return docShell.forget();
   }
   virtual already_AddRefed<nsIEventTarget> GetTabEventTarget() override;
 
-  NS_FORWARD_SAFE_NSIMESSAGELISTENERMANAGER(mMessageManager)
   NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
   NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
 
   NS_DECL_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER
 
   void CacheFrameLoader(nsFrameLoader* aFrameLoader);
 
   /**
--- a/dom/base/test/chrome/file_bug549682.xul
+++ b/dom/base/test/chrome/file_bug549682.xul
@@ -87,35 +87,33 @@ https://bugzilla.mozilla.org/show_bug.cg
   function localL(m) {
     is(m.name, "lasync", "Wrong message!");
     is(m.json.data, 2345, "Wrong data!");
     didRunLocal = true;
   }
 
   var weakMessageReceived = false;
   var weakListener = {
-    QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener,
-                                           Ci.nsISupportsWeakReference]),
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference]),
 
     receiveMessage: function(msg) {
       if (weakMessageReceived) {
         ok(false, 'Weak listener fired twice.');
         return;
       }
 
       ok(true, 'Weak listener fired once.');
       weakMessageReceived = true;
       document.getElementById('ifr').messageManager
               .removeWeakMessageListener('weak', weakListener);
     }
   };
 
   var weakListener2 = {
-    QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener,
-                                           Ci.nsISupportsWeakReference]),
+    QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference]),
 
     receiveMessage: function(msg) {
       ok(false, 'Should not have received a message.');
     }
   };
 
   function weakDoneListener() {
     ok(weakMessageReceived, 'Got "weak" message.');
--- a/dom/chrome-webidl/MessageManager.webidl
+++ b/dom/chrome-webidl/MessageManager.webidl
@@ -1,16 +1,173 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 interface nsIEventTarget;
 interface Principal;
 
+/**
+ * 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 MessageSender.  Parent-side message managers that have many
+ * "other sides" are of type ChromeMessageBroadcaster.
+ *
+ * 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
+ *  - "group message managers" which correspond to named message
+ *    managers with a specific window MM as the parent
+ *  - 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
+ *   |    |
+ *   |    +-->group MMgr1
+ *   |    |    |
+ *   |    |    +-->frame MMp2_1<------->frame MMc2_1
+ *   |    |    |
+ *   |    |    +-->frame MMp2_2<------->frame MMc2_2
+ *   |    |
+ *   |    +-->group MMgr2
+ *   |    |    ...
+ *   |    |
+ *   |    ...
+ *   |
+ *   +-->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.
+ *
+ * A message sent from MMc2_1 will be sent to MMp2_1 and also notify
+ * all message managers in the hierarchy above that, including the
+ * group message manager MMgr1.
+
+ * 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 MMgr1, which would broadcast it to MMp2_1 and MMp2_2.
+ * After that it would broadcast to MMgr2 and then to MMw2, and so
+ * on down the hierarchy.
+ *
+ *   ***** PERFORMANCE AND SECURITY WARNING *****
+ * Messages broadcast through the global MM and window or group 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
+ * ChromeMessageBroadcaster while the frame MMp's are simple message
+ * senders (MessageSender). Their counterparts in the content processes
+ * are message senders implementing ContentFrameMessageManager.
+ *
+ *                 MessageListenerManager
+ *               /                        \
+ * MessageSender                            ChromeMessageBroadcaster
+ *       |
+ * SyncMessageSender (content process/in-process only)
+ *       |
+ * ContentFrameMessageManager (content process/in-process only)
+ *       |
+ * nsIInProcessContentFrameMessageManager (in-process only)
+ *
+ *
+ * Message managers in the chrome process also implement FrameScriptLoader.
+ *
+ *
+ * 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 (GPPMM)
+ *   |
+ *   +-->parent in-process PIPMM<-->child in-process CIPPMM
+ *   |
+ *   +-->parent (PPMM1)<------------------>child (CPMM1)
+ *   |
+ *   +-->parent (PPMM2)<------------------>child (CPMM2)
+ *   ...
+ *
+ * Note, PIPMM and CIPPMM both run in the parent process.
+ *
+ * For example: the parent-process PPMM1 sends messages to the
+ * child-process CPMM1.
+ *
+ * For example: CPMM1 sends messages directly to PPMM1. The global GPPMM
+ * will also notify their message listeners when the message arrives.
+ *
+ * For example: messages sent through the global GPPMM will be
+ * dispatched to the listeners of the same-process, CIPPMM, CPMM1,
+ * CPMM2, etc.
+ *
+ *   ***** PERFORMANCE AND SECURITY WARNING *****
+ * Messages broadcast through the GPPMM 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) {
+ *      switch (aMessage.name) {
+ *      case "Foo:Request":
+ *        // service request
+ *        aMessage.target.sendAsyncMessage("Foo:Response", { data });
+ *      }
+ *    }
+ *  };
+ */
+
 dictionary ReceiveMessageArgument
 {
   /**
    * The target of the message. Either an element owning the message manager, or message
    * manager itself if no element owns it.
    */
   required nsISupports target;
 
@@ -112,16 +269,22 @@ interface MessageListenerManager
   /**
    * This undoes an |addWeakMessageListener| call.
    */
   [Throws]
   void removeWeakMessageListener(DOMString messageName,
                                  MessageListener listener);
 };
 
+/**
+ * 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.
+ */
 [ChromeOnly]
 interface MessageSender : MessageListenerManager
 {
   /**
    * Send |messageName| and |obj| to the "other side" of this message
    * manager.  This invokes listeners who registered for
    * |messageName|.
    *
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2546,19 +2546,18 @@ ContentChild::RecvAsyncMessage(const nsS
     "ContentChild::RecvAsyncMessage", EVENTS, aMsg);
 
   CrossProcessCpowHolder cpows(this, aCpows);
   RefPtr<nsFrameMessageManager> cpm =
     nsFrameMessageManager::GetChildProcessManager();
   if (cpm) {
     StructuredCloneData data;
     ipc::UnpackClonedMessageDataForChild(aData, data);
-    cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()),
-                        nullptr, aMsg, false, &data, &cpows, aPrincipal,
-                        nullptr);
+    cpm->ReceiveMessage(cpm, nullptr, aMsg, false, &data, &cpows, aPrincipal, nullptr,
+                        IgnoreErrors());
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ContentChild::RecvGeolocationUpdate(const GeoPosition& somewhere)
 {
   nsCOMPtr<nsIGeolocationUpdate> gs =
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1447,20 +1447,19 @@ ContentParent::RecvFinishShutdown()
 
 void
 ContentParent::ShutDownMessageManager()
 {
   if (!mMessageManager) {
   return;
   }
 
-  mMessageManager->ReceiveMessage(
-      static_cast<nsIContentFrameMessageManager*>(mMessageManager.get()), nullptr,
+  mMessageManager->ReceiveMessage(mMessageManager, nullptr,
       CHILD_PROCESS_SHUTDOWN_MESSAGE, false,
-      nullptr, nullptr, nullptr, nullptr);
+      nullptr, nullptr, nullptr, nullptr, IgnoreErrors());
 
   mMessageManager->Disconnect();
   mMessageManager = nullptr;
 }
 
 void
 ContentParent::RemoveFromList()
 {
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -237,17 +237,18 @@ TabChildBase::DispatchMessageManagerMess
         }
     }
 
     JS::Rooted<JSObject*> kungFuDeathGrip(cx, mTabChildGlobal->GetWrapper());
     // Let the BrowserElementScrolling helper (if it exists) for this
     // content manipulate the frame state.
     RefPtr<nsFrameMessageManager> mm = mTabChildGlobal->GetMessageManager();
     mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal), nullptr,
-                       aMessageName, false, &data, nullptr, nullptr, nullptr);
+                       aMessageName, false, &data, nullptr, nullptr, nullptr,
+                       IgnoreErrors());
 }
 
 bool
 TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics)
 {
   MOZ_ASSERT(aFrameMetrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID);
 
   if (aFrameMetrics.IsRootContent()) {
@@ -2315,17 +2316,18 @@ TabChild::RecvAsyncMessage(const nsStrin
   if (!mm) {
     return IPC_OK();
   }
 
   JS::Rooted<JSObject*> kungFuDeathGrip(dom::RootingCx(), mTabChildGlobal->GetWrapper());
   StructuredCloneData data;
   UnpackClonedMessageDataForChild(aData, data);
   mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal), nullptr,
-                     aMessage, false, &data, &cpows, aPrincipal, nullptr);
+                     aMessage, false, &data, &cpows, aPrincipal, nullptr,
+                     IgnoreErrors());
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabChild::RecvSwappedWithOtherRemoteLoader(const IPCTabContext& aContext)
 {
   nsCOMPtr<nsIDocShell> ourDocShell = do_GetInterface(WebNavigation());
   if (NS_WARN_IF(!ourDocShell)) {
@@ -3510,17 +3512,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TabChildGlobal,
                                                   DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChild)
   tmp->TraverseHostObjectURIs(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TabChildGlobal)
-  NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
   NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(TabChildGlobal, DOMEventTargetHelper)
@@ -3536,29 +3537,27 @@ TabChildGlobal::WrapGlobalObject(JSConte
                                                     true, aReflector);
   if (ok) {
     // Since we can't rewrap we have to preserve the global's wrapper here.
     PreserveWrapper(ToSupports(this));
   }
   return ok;
 }
 
-// This method isn't automatically forwarded safely because it's notxpcom, so
-// the IDL binding doesn't know what value to return.
-NS_IMETHODIMP_(bool)
+void
 TabChildGlobal::MarkForCC()
 {
   if (mTabChild) {
     mTabChild->MarkScopesForCC();
   }
   EventListenerManager* elm = GetExistingListenerManager();
   if (elm) {
     elm->MarkForCC();
   }
-  return MessageManagerGlobal::MarkForCC();
+  MessageManagerGlobal::MarkForCC();
 }
 
 already_AddRefed<nsPIDOMWindowOuter>
 TabChildGlobal::GetContent(ErrorResult& aError)
 {
   if (!mTabChild) {
     aError.Throw(NS_ERROR_NULL_POINTER);
     return nullptr;
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -86,30 +86,31 @@ class TabChildGlobal : public ContentFra
                        public nsSupportsWeakReference
 {
 public:
   explicit TabChildGlobal(TabChild* aTabChild);
   void Init();
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TabChildGlobal, DOMEventTargetHelper)
 
+  void MarkForCC();
+
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override
   {
     MOZ_CRASH("We should never get here!");
   }
   bool WrapGlobalObject(JSContext* aCx,
                         JS::CompartmentOptions& aOptions,
                         JS::MutableHandle<JSObject*> aReflector);
 
   virtual already_AddRefed<nsPIDOMWindowOuter> GetContent(ErrorResult& aError) override;
   virtual already_AddRefed<nsIDocShell> GetDocShell(ErrorResult& aError) override;
   virtual already_AddRefed<nsIEventTarget> GetTabEventTarget() override;
 
-  NS_FORWARD_SAFE_NSIMESSAGELISTENERMANAGER(mMessageManager)
   NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
   NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
 
   nsresult
   GetEventTargetParent(EventChainPreVisitor& aVisitor) override
   {
     aVisitor.mForceContentDispatch = true;
     return NS_OK;
@@ -273,17 +274,17 @@ public:
   NS_DECL_NSITABCHILD
   NS_DECL_NSIOBSERVER
   NS_DECL_NSITOOLTIPLISTENER
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(TabChild, TabChildBase)
 
   FORWARD_SHMEM_ALLOCATOR_TO(PBrowserChild)
 
-  nsIContentFrameMessageManager* GetMessageManager()
+  TabChildGlobal* GetMessageManager()
   {
     return mTabChildGlobal;
   }
 
   /**
    * MessageManagerCallback methods that we override.
    */
   virtual bool DoSendBlockingMessage(JSContext* aCx,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -2561,17 +2561,18 @@ TabParent::ReceiveMessage(const nsString
 
     manager->ReceiveMessage(mFrameElement,
                             frameLoader,
                             aMessage,
                             aSync,
                             aData,
                             aCpows,
                             aPrincipal,
-                            aRetVal);
+                            aRetVal,
+                            IgnoreErrors());
   }
   return true;
 }
 
 // nsIAuthPromptProvider
 
 // This method is largely copied from nsDocShell::GetAuthPrompt
 NS_IMETHODIMP
--- a/dom/ipc/nsIContentChild.cpp
+++ b/dom/ipc/nsIContentChild.cpp
@@ -177,18 +177,18 @@ nsIContentChild::RecvAsyncMessage(const 
     "nsIContentChild::RecvAsyncMessage", EVENTS, aMsg);
 
   CrossProcessCpowHolder cpows(this, aCpows);
   RefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::GetChildProcessManager();
   if (cpm) {
     ipc::StructuredCloneData data;
     ipc::UnpackClonedMessageDataForChild(aData, data);
 
-    cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()), nullptr,
-                        aMsg, false, &data, &cpows, aPrincipal, nullptr);
+    cpm->ReceiveMessage(cpm, nullptr, aMsg, false, &data, &cpows, aPrincipal, nullptr,
+                        IgnoreErrors());
   }
   return IPC_OK();
 }
 
 /* static */
 already_AddRefed<nsIEventTarget>
 nsIContentChild::GetConstructedEventTarget(const IPC::Message& aMsg)
 {
--- a/dom/ipc/nsIContentParent.cpp
+++ b/dom/ipc/nsIContentParent.cpp
@@ -251,18 +251,18 @@ nsIContentParent::RecvSyncMessage(const 
     "nsIContentParent::RecvSyncMessage", EVENTS, aMsg);
 
   CrossProcessCpowHolder cpows(this, aCpows);
   RefPtr<nsFrameMessageManager> ppm = mMessageManager;
   if (ppm) {
     ipc::StructuredCloneData data;
     ipc::UnpackClonedMessageDataForParent(aData, data);
 
-    ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), nullptr,
-                        aMsg, true, &data, &cpows, aPrincipal, aRetvals);
+    ppm->ReceiveMessage(ppm, nullptr, aMsg, true, &data, &cpows, aPrincipal, aRetvals,
+                        IgnoreErrors());
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 nsIContentParent::RecvRpcMessage(const nsString& aMsg,
                                  const ClonedMessageData& aData,
                                  InfallibleTArray<CpowEntry>&& aCpows,
@@ -273,18 +273,18 @@ nsIContentParent::RecvRpcMessage(const n
     "nsIContentParent::RecvRpcMessage", EVENTS, aMsg);
 
   CrossProcessCpowHolder cpows(this, aCpows);
   RefPtr<nsFrameMessageManager> ppm = mMessageManager;
   if (ppm) {
     ipc::StructuredCloneData data;
     ipc::UnpackClonedMessageDataForParent(aData, data);
 
-    ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), nullptr,
-                        aMsg, true, &data, &cpows, aPrincipal, aRetvals);
+    ppm->ReceiveMessage(ppm, nullptr, aMsg, true, &data, &cpows, aPrincipal, aRetvals,
+                        IgnoreErrors());
   }
   return IPC_OK();
 }
 
 PFileDescriptorSetParent*
 nsIContentParent::AllocPFileDescriptorSetParent(const FileDescriptor& aFD)
 {
   return new FileDescriptorSetParent(aFD);
@@ -333,16 +333,16 @@ nsIContentParent::RecvAsyncMessage(const
     "nsIContentParent::RecvAsyncMessage", EVENTS, aMsg);
 
   CrossProcessCpowHolder cpows(this, aCpows);
   RefPtr<nsFrameMessageManager> ppm = mMessageManager;
   if (ppm) {
     ipc::StructuredCloneData data;
     ipc::UnpackClonedMessageDataForParent(aData, data);
 
-    ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), nullptr,
-                        aMsg, false, &data, &cpows, aPrincipal, nullptr);
+    ppm->ReceiveMessage(ppm, nullptr, aMsg, false, &data, &cpows, aPrincipal, nullptr,
+                        IgnoreErrors());
   }
   return IPC_OK();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -199,17 +199,16 @@ class GlobalPCList {
   }
 
   _registerPeerConnectionLifecycleCallback(winID, cb) {
     this._lifecycleobservers[winID] = cb;
   }
 }
 setupPrototype(GlobalPCList, {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
-                                         Ci.nsIMessageListener,
                                          Ci.nsISupportsWeakReference]),
   classID: PC_MANAGER_CID,
   _xpcom_factory: {
     createInstance(outer, iid) {
       if (outer) {
         throw Cr.NS_ERROR_NO_AGGREGATION;
       }
       return _globalPCList.QueryInterface(iid);
--- a/dom/notification/NotificationStorage.js
+++ b/dom/notification/NotificationStorage.js
@@ -251,14 +251,13 @@ NotificationStorage.prototype = {
         this._byTag[origin][tag] = notification;
       }
     });
     this._cached = true;
   },
 
   classID : Components.ID(NOTIFICATIONSTORAGE_CID),
   contractID : NOTIFICATIONSTORAGE_CONTRACTID,
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsINotificationStorage,
-                                         Ci.nsIMessageListener]),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsINotificationStorage]),
 };
 
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NotificationStorage]);
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -265,17 +265,16 @@ Object.defineProperty(GeckoDriver.protot
       hs.push(getOuterWindowId(win));
     }
 
     return hs;
   },
 });
 
 GeckoDriver.prototype.QueryInterface = XPCOMUtils.generateQI([
-  Ci.nsIMessageListener,
   Ci.nsIObserver,
   Ci.nsISupportsWeakReference,
 ]);
 
 GeckoDriver.prototype.init = function() {
   this.mm.addMessageListener("Marionette:WebDriver:GetCapabilities", this);
   this.mm.addMessageListener("Marionette:GetLogLevel", this);
   this.mm.addMessageListener("Marionette:ListenersAttached", this);
--- a/toolkit/components/printing/content/printPreviewBindings.xml
+++ b/toolkit/components/printing/content/printPreviewBindings.xml
@@ -94,17 +94,17 @@
         oncommand="this.parentNode.simplify();"/>
 
       <xul:toolbarseparator class="toolbarseparator-primary"/>
       <xul:button label="&close.label;" accesskey="&close.accesskey;"
         oncommand="PrintUtils.exitPrintPreview();" icon="close"/>
       <xul:data value="&customPrompt.title;"/>
     </content>
 
-    <implementation implements="nsIMessageListener">
+    <implementation>
       <field name="mPrintButton">
         document.getAnonymousNodes(this)[0]
       </field>
       <field name="mPageSetupButton">
         document.getAnonymousElementByAttribute(this, "anonid", "pageSetup");
       </field>
       <field name="mNavigateHomeButton">
         document.getAnonymousElementByAttribute(this, "anonid", "navigateHome");
@@ -436,17 +436,16 @@
         <parameter name="flags"/>
         <body><![CDATA[
           var PSSVC = Cc["@mozilla.org/gfx/printsettings-service;1"]
                         .getService(Ci.nsIPrintSettingsService);
           PSSVC.savePrintSettingsToPrefs(settings, true, flags);
         ]]></body>
       </method>
 
-      <!-- nsIMessageListener -->
       <method name="receiveMessage">
         <parameter name="message"/>
         <body>
         <![CDATA[
           if (message.name == "Printing:Preview:UpdatePageCount") {
             let numPages = message.data.numPages;
             this.mTotalPages.value = numPages;
             this.mPageTextBox.max = numPages;
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -7,17 +7,17 @@
 <bindings id="browserBindings"
           xmlns="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <binding id="browser" extends="xul:browser">
     <content clickthrough="never">
       <children/>
     </content>
-    <implementation type="application/javascript" implements="nsIObserver, nsIDOMEventListener, nsIMessageListener, nsIBrowser">
+    <implementation type="application/javascript" implements="nsIObserver, nsIDOMEventListener, nsIBrowser">
       <property name="autoscrollEnabled">
         <getter>
           <![CDATA[
             if (this.getAttribute("autoscroll") == "false")
               return false;
 
             return this.mPrefs.getBoolPref("general.autoScroll", true);
           ]]>
--- a/toolkit/content/widgets/findbar.xml
+++ b/toolkit/content/widgets/findbar.xml
@@ -212,17 +212,17 @@
       </xul:description>
     </xul:hbox>
     <xul:toolbarbutton anonid="find-closebutton"
                        class="findbar-closebutton close-icon"
                        tooltiptext="&findCloseButton.tooltip;"
                        oncommand="close();"/>
     </content>
 
-    <implementation implements="nsIMessageListener, nsIEditActionListener">
+    <implementation implements="nsIEditActionListener">
       <!-- Please keep in sync with toolkit/content/browser-content.js -->
       <field name="FIND_NORMAL">0</field>
       <field name="FIND_TYPEAHEAD">1</field>
       <field name="FIND_LINKS">2</field>
 
       <field name="__findMode">0</field>
       <property name="_findMode" onget="return this.__findMode;"
                 onset="this.__findMode = val; this._updateBrowserWithState(); return val;"/>
@@ -889,17 +889,17 @@
               this._updateStatusUI(this.nsITypeAheadFind.FIND_FOUND);
 
             return false;
           }
           return undefined;
         ]]></body>
       </method>
 
-      <!-- See nsIMessageListener -->
+      <!-- See MessageListener -->
       <method name="receiveMessage">
         <parameter name="aMessage"/>
         <body><![CDATA[
           if (aMessage.target != this._browser) {
             return undefined;
           }
           switch (aMessage.name) {
             case "Findbar:Mouseup":
--- a/toolkit/content/widgets/remote-browser.xml
+++ b/toolkit/content/widgets/remote-browser.xml
@@ -6,17 +6,17 @@
 
 <bindings id="firefoxBrowserBindings"
           xmlns="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <binding id="remote-browser" extends="chrome://global/content/bindings/browser.xml#browser">
 
     <implementation type="application/javascript"
-                    implements="nsIObserver, nsIDOMEventListener, nsIMessageListener, nsIRemoteBrowser">
+                    implements="nsIObserver, nsIDOMEventListener, nsIRemoteBrowser">
 
       <field name="_securityUI">null</field>
 
       <property name="securityUI"
                 readonly="true">
         <getter><![CDATA[
           if (!this._securityUI) {
             // Don't attempt to create the remote web progress if the
--- a/toolkit/modules/DateTimePickerHelper.jsm
+++ b/toolkit/modules/DateTimePickerHelper.jsm
@@ -41,17 +41,17 @@ var DateTimePickerHelper = {
   },
 
   uninit() {
     for (let msg of this.MESSAGES) {
       Services.mm.removeMessageListener(msg, this);
     }
   },
 
-  // nsIMessageListener
+  // MessageListener
   receiveMessage(aMessage) {
     debug("receiveMessage: " + aMessage.name);
     switch (aMessage.name) {
       case "FormDateTime:OpenPicker": {
         this.showPicker(aMessage.target, aMessage.data);
         break;
       }
       case "FormDateTime:ClosePicker": {
--- a/toolkit/mozapps/extensions/addonManager.js
+++ b/toolkit/mozapps/extensions/addonManager.js
@@ -249,13 +249,12 @@ amManager.prototype = {
 
       if (!gSingleton)
         gSingleton = new amManager();
       return gSingleton.QueryInterface(aIid);
     }
   },
   QueryInterface: XPCOMUtils.generateQI([Ci.amIAddonManager,
                                          Ci.nsITimerCallback,
-                                         Ci.nsIObserver,
-                                         Ci.nsIMessageListener])
+                                         Ci.nsIObserver])
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([amManager]);
--- a/toolkit/mozapps/extensions/amContentHandler.js
+++ b/toolkit/mozapps/extensions/amContentHandler.js
@@ -57,18 +57,17 @@ amContentHandler.prototype = {
       // in-content UI page, walk up to find the first frame element in a chrome
       // privileged document
       let element = window.frameElement;
       let ssm = Services.scriptSecurityManager;
       while (element && !ssm.isSystemPrincipal(element.ownerDocument.nodePrincipal))
         element = element.ownerGlobal.frameElement;
 
       if (element) {
-        let listener = Cc["@mozilla.org/addons/integration;1"].
-                       getService(Ci.nsIMessageListener);
+        let listener = Cc["@mozilla.org/addons/integration;1"].getService();
         listener.wrappedJSObject.receiveMessage({
           name: MSG_INSTALL_ADDON,
           target: element,
           data: install
         });
         return;
       }
     }
--- a/toolkit/mozapps/extensions/amInstallTrigger.js
+++ b/toolkit/mozapps/extensions/amInstallTrigger.js
@@ -78,18 +78,17 @@ RemoteMediator.prototype = {
       // in-content UI page, walk up to find the first frame element in a chrome
       // privileged document
       let element = window.frameElement;
       let ssm = Services.scriptSecurityManager;
       while (element && !ssm.isSystemPrincipal(element.ownerDocument.nodePrincipal))
         element = element.ownerGlobal.frameElement;
 
       if (element) {
-        let listener = Cc["@mozilla.org/addons/integration;1"].
-                       getService(Ci.nsIMessageListener);
+        let listener = Cc["@mozilla.org/addons/integration;1"].getService();
         return listener.wrappedJSObject.receiveMessage({
           name: MSG_INSTALL_ADDON,
           target: element,
           data: install,
         });
       }
     }