LCOV - code coverage report
Current view: top level - dom/base - nsFrameMessageManager.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 523 953 54.9 %
Date: 2017-07-14 16:53:18 Functions: 70 118 59.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "base/basictypes.h"
       8             : 
       9             : #include "nsFrameMessageManager.h"
      10             : 
      11             : #include "ContentChild.h"
      12             : #include "GeckoProfiler.h"
      13             : #include "nsASCIIMask.h"
      14             : #include "nsContentUtils.h"
      15             : #include "nsDOMClassInfoID.h"
      16             : #include "nsError.h"
      17             : #include "nsIXPConnect.h"
      18             : #include "jsapi.h"
      19             : #include "jsfriendapi.h"
      20             : #include "nsJSUtils.h"
      21             : #include "nsJSPrincipals.h"
      22             : #include "nsNetUtil.h"
      23             : #include "mozilla/dom/ScriptLoader.h"
      24             : #include "nsFrameLoader.h"
      25             : #include "nsIInputStream.h"
      26             : #include "nsIXULRuntime.h"
      27             : #include "nsIScriptError.h"
      28             : #include "nsIConsoleService.h"
      29             : #include "nsIMemoryReporter.h"
      30             : #include "nsIProtocolHandler.h"
      31             : #include "nsIScriptSecurityManager.h"
      32             : #include "nsIDOMClassInfo.h"
      33             : #include "xpcpublic.h"
      34             : #include "mozilla/CycleCollectedJSContext.h"
      35             : #include "mozilla/IntentionalCrash.h"
      36             : #include "mozilla/Preferences.h"
      37             : #include "mozilla/ScriptPreloader.h"
      38             : #include "mozilla/Telemetry.h"
      39             : #include "mozilla/dom/File.h"
      40             : #include "mozilla/dom/MessagePort.h"
      41             : #include "mozilla/dom/ContentParent.h"
      42             : #include "mozilla/dom/PermissionMessageUtils.h"
      43             : #include "mozilla/dom/ProcessGlobal.h"
      44             : #include "mozilla/dom/SameProcessMessageQueue.h"
      45             : #include "mozilla/dom/ScriptSettings.h"
      46             : #include "mozilla/dom/ipc/StructuredCloneData.h"
      47             : #include "mozilla/dom/DOMStringList.h"
      48             : #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
      49             : #include "nsPrintfCString.h"
      50             : #include "nsXULAppAPI.h"
      51             : #include "nsQueryObject.h"
      52             : #include <algorithm>
      53             : #include "chrome/common/ipc_channel.h" // for IPC::Channel::kMaximumMessageSize
      54             : 
      55             : #ifdef MOZ_CRASHREPORTER
      56             : #include "nsExceptionHandler.h"
      57             : #endif
      58             : 
      59             : #ifdef ANDROID
      60             : #include <android/log.h>
      61             : #endif
      62             : #ifdef XP_WIN
      63             : #include <windows.h>
      64             : # if defined(SendMessage)
      65             : #  undef SendMessage
      66             : # endif
      67             : #endif
      68             : 
      69             : #ifdef FUZZING
      70             : #include "MessageManagerFuzzer.h"
      71             : #endif
      72             : 
      73             : using namespace mozilla;
      74             : using namespace mozilla::dom;
      75             : using namespace mozilla::dom::ipc;
      76             : 
      77          14 : nsFrameMessageManager::nsFrameMessageManager(mozilla::dom::ipc::MessageManagerCallback* aCallback,
      78             :                                              nsFrameMessageManager* aParentManager,
      79          14 :                                              /* mozilla::dom::ipc::MessageManagerFlags */ uint32_t aFlags)
      80          14 :  : mChrome(!!(aFlags & mozilla::dom::ipc::MM_CHROME)),
      81          14 :    mGlobal(!!(aFlags & mozilla::dom::ipc::MM_GLOBAL)),
      82          14 :    mIsProcessManager(!!(aFlags & mozilla::dom::ipc::MM_PROCESSMANAGER)),
      83          14 :    mIsBroadcaster(!!(aFlags & mozilla::dom::ipc::MM_BROADCASTER)),
      84          14 :    mOwnsCallback(!!(aFlags & mozilla::dom::ipc::MM_OWNSCALLBACK)),
      85             :   mHandlingMessage(false),
      86             :   mClosed(false),
      87             :   mDisconnected(false),
      88             :   mCallback(aCallback),
      89          84 :   mParentManager(aParentManager)
      90             : {
      91          14 :   NS_ASSERTION(mChrome || !aParentManager, "Should not set parent manager!");
      92          14 :   NS_ASSERTION(!mIsBroadcaster || !mCallback,
      93             :                "Broadcasters cannot have callbacks!");
      94          14 :   if (mIsProcessManager && (!mChrome || IsBroadcaster())) {
      95           4 :     mozilla::HoldJSObjects(this);
      96             :   }
      97             :   // This is a bit hackish. When parent manager is global, we want
      98             :   // to attach the message manager to it immediately.
      99             :   // Is it just the frame message manager which waits until the
     100             :   // content process is running.
     101          14 :   if (mParentManager && (mCallback || IsBroadcaster())) {
     102           3 :     mParentManager->AddChildManager(this);
     103             :   }
     104          14 :   if (mOwnsCallback) {
     105           4 :     mOwnedCallback = aCallback;
     106             :   }
     107          14 : }
     108             : 
     109           0 : nsFrameMessageManager::~nsFrameMessageManager()
     110             : {
     111           0 :   if (mIsProcessManager && (!mChrome || IsBroadcaster())) {
     112           0 :     mozilla::DropJSObjects(this);
     113             :   }
     114           0 :   for (int32_t i = mChildManagers.Count(); i > 0; --i) {
     115           0 :     static_cast<nsFrameMessageManager*>(mChildManagers[i - 1])->
     116           0 :       Disconnect(false);
     117             :   }
     118           0 :   if (mIsProcessManager) {
     119           0 :     if (this == sParentProcessManager) {
     120           0 :       sParentProcessManager = nullptr;
     121             :     }
     122           0 :     if (this == sChildProcessManager) {
     123           0 :       sChildProcessManager = nullptr;
     124           0 :       delete mozilla::dom::SameProcessMessageQueue::Get();
     125             :     }
     126           0 :     if (this == sSameProcessParentManager) {
     127           0 :       sSameProcessParentManager = nullptr;
     128             :     }
     129             :   }
     130           0 : }
     131             : 
     132             : NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameMessageManager)
     133             : 
     134           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameMessageManager)
     135           0 :   for (auto iter = tmp->mListeners.Iter(); !iter.Done(); iter.Next()) {
     136           0 :     nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners = iter.UserData();
     137           0 :     uint32_t count = listeners->Length();
     138           0 :     for (uint32_t i = 0; i < count; ++i) {
     139           0 :       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "listeners[i] mStrongListener");
     140           0 :       cb.NoteXPCOMChild(listeners->ElementAt(i).mStrongListener.get());
     141             :     }
     142             :   }
     143           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildManagers)
     144           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentManager)
     145           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     146             : 
     147           2 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsFrameMessageManager)
     148           2 :   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mInitialProcessData)
     149           2 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
     150             : 
     151           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameMessageManager)
     152           0 :   tmp->mListeners.Clear();
     153           0 :   for (int32_t i = tmp->mChildManagers.Count(); i > 0; --i) {
     154           0 :     static_cast<nsFrameMessageManager*>(tmp->mChildManagers[i - 1])->
     155           0 :       Disconnect(false);
     156             :   }
     157           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildManagers)
     158           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentManager)
     159           0 :   tmp->mInitialProcessData.setNull();
     160           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     161             : 
     162             : 
     163        1270 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameMessageManager)
     164        1244 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentFrameMessageManager)
     165             : 
     166             :   /* nsFrameMessageManager implements nsIMessageSender and nsIMessageBroadcaster,
     167             :    * both of which descend from nsIMessageListenerManager. QI'ing to
     168             :    * nsIMessageListenerManager is therefore ambiguous and needs explicit casts
     169             :    * depending on which child interface applies. */
     170         935 :   NS_INTERFACE_MAP_ENTRY_AGGREGATED(nsIMessageListenerManager,
     171             :                                     (mIsBroadcaster ?
     172             :                                        static_cast<nsIMessageListenerManager*>(
     173             :                                          static_cast<nsIMessageBroadcaster*>(this)) :
     174             :                                        static_cast<nsIMessageListenerManager*>(
     175             :                                          static_cast<nsIMessageSender*>(this))))
     176             : 
     177             :   /* Message managers in child process implement nsIMessageSender and
     178             :      nsISyncMessageSender.  Message managers in the chrome process are
     179             :      either broadcasters (if they have subordinate/child message
     180             :      managers) or they're simple message senders. */
     181         884 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISyncMessageSender, !mChrome)
     182         884 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIMessageSender, !mChrome || !mIsBroadcaster)
     183         876 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIMessageBroadcaster, mChrome && mIsBroadcaster)
     184             : 
     185             :   /* nsIContentFrameMessageManager is accessible only in TabChildGlobal. */
     186         850 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIContentFrameMessageManager,
     187             :                                      !mChrome && !mIsProcessManager)
     188             : 
     189             :   /* Frame message managers (non-process message managers) support nsIFrameScriptLoader. */
     190         848 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIFrameScriptLoader,
     191             :                                      mChrome && !mIsProcessManager)
     192             : 
     193             :   /* Process message managers (process message managers) support nsIProcessScriptLoader. */
     194         837 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIProcessScriptLoader,
     195             :                                      mChrome && mIsProcessManager)
     196             : 
     197             :   /* Global process message managers (process message managers) support nsIGlobalProcessScriptLoader. */
     198         828 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIGlobalProcessScriptLoader,
     199             :                                      mChrome && mIsProcessManager && mIsBroadcaster)
     200             : 
     201         825 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(ChromeMessageBroadcaster,
     202             :                                                    mChrome && mIsBroadcaster)
     203         786 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(ChromeMessageSender,
     204             :                                                    mChrome && !mIsBroadcaster)
     205         775 : NS_INTERFACE_MAP_END
     206             : 
     207         840 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameMessageManager)
     208         639 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameMessageManager)
     209             : 
     210             : bool
     211          10 : MessageManagerCallback::BuildClonedMessageDataForParent(nsIContentParent* aParent,
     212             :                                                         StructuredCloneData& aData,
     213             :                                                         ClonedMessageData& aClonedData)
     214             : {
     215          10 :   return aData.BuildClonedMessageDataForParent(aParent, aClonedData);
     216             : }
     217             : 
     218             : bool
     219          34 : MessageManagerCallback::BuildClonedMessageDataForChild(nsIContentChild* aChild,
     220             :                                                        StructuredCloneData& aData,
     221             :                                                        ClonedMessageData& aClonedData)
     222             : {
     223          34 :   return aData.BuildClonedMessageDataForChild(aChild, aClonedData);
     224             : }
     225             : 
     226             : void
     227          32 : mozilla::dom::ipc::UnpackClonedMessageDataForParent(const ClonedMessageData& aClonedData,
     228             :                                                     StructuredCloneData& aData)
     229             : {
     230          32 :   aData.BorrowFromClonedMessageDataForParent(aClonedData);
     231          32 : }
     232             : 
     233             : void
     234          10 : mozilla::dom::ipc::UnpackClonedMessageDataForChild(const ClonedMessageData& aClonedData,
     235             :                                                    StructuredCloneData& aData)
     236             : {
     237          10 :   aData.BorrowFromClonedMessageDataForChild(aClonedData);
     238          10 : }
     239             : 
     240             : bool
     241           5 : SameProcessCpowHolder::ToObject(JSContext* aCx,
     242             :                                 JS::MutableHandle<JSObject*> aObjp)
     243             : {
     244           5 :   if (!mObj) {
     245           5 :     return true;
     246             :   }
     247             : 
     248           0 :   aObjp.set(mObj);
     249           0 :   return JS_WrapObject(aCx, aObjp);
     250             : }
     251             : 
     252             : // nsIMessageListenerManager
     253             : 
     254             : NS_IMETHODIMP
     255         366 : nsFrameMessageManager::AddMessageListener(const nsAString& aMessage,
     256             :                                           nsIMessageListener* aListener,
     257             :                                           bool aListenWhenClosed)
     258             : {
     259        1089 :   auto listeners = mListeners.LookupForAdd(aMessage).OrInsert([]() {
     260         357 :       return new nsAutoTObserverArray<nsMessageListenerInfo, 1>();
     261         723 :     });
     262         366 :   uint32_t len = listeners->Length();
     263         371 :   for (uint32_t i = 0; i < len; ++i) {
     264           9 :     if (listeners->ElementAt(i).mStrongListener == aListener) {
     265           4 :       return NS_OK;
     266             :     }
     267             :   }
     268             : 
     269         362 :   nsMessageListenerInfo* entry = listeners->AppendElement();
     270         362 :   NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
     271         362 :   entry->mStrongListener = aListener;
     272         362 :   entry->mListenWhenClosed = aListenWhenClosed;
     273         362 :   return NS_OK;
     274             : }
     275             : 
     276             : NS_IMETHODIMP
     277           7 : nsFrameMessageManager::RemoveMessageListener(const nsAString& aMessage,
     278             :                                              nsIMessageListener* aListener)
     279             : {
     280             :   nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
     281           7 :     mListeners.Get(aMessage);
     282           7 :   if (!listeners) {
     283           0 :     return NS_OK;
     284             :   }
     285             : 
     286           7 :   uint32_t len = listeners->Length();
     287           7 :   for (uint32_t i = 0; i < len; ++i) {
     288           7 :     if (listeners->ElementAt(i).mStrongListener == aListener) {
     289           7 :       listeners->RemoveElementAt(i);
     290           7 :       return NS_OK;
     291             :     }
     292             :   }
     293           0 :   return NS_OK;
     294             : }
     295             : 
     296             : NS_IMETHODIMP
     297           0 : nsFrameMessageManager::AddWeakMessageListener(const nsAString& aMessage,
     298             :                                               nsIMessageListener* aListener)
     299             : {
     300           0 :   nsWeakPtr weak = do_GetWeakReference(aListener);
     301           0 :   NS_ENSURE_TRUE(weak, NS_ERROR_NO_INTERFACE);
     302             : 
     303             : #ifdef DEBUG
     304             :   // It's technically possible that one object X could give two different
     305             :   // nsIWeakReference*'s when you do_GetWeakReference(X).  We really don't want
     306             :   // this to happen; it will break e.g. RemoveWeakMessageListener.  So let's
     307             :   // check that we're not getting ourselves into that situation.
     308           0 :   nsCOMPtr<nsISupports> canonical = do_QueryInterface(aListener);
     309           0 :   for (auto iter = mListeners.Iter(); !iter.Done(); iter.Next()) {
     310           0 :     nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners = iter.UserData();
     311           0 :     uint32_t count = listeners->Length();
     312           0 :     for (uint32_t i = 0; i < count; i++) {
     313           0 :       nsWeakPtr weakListener = listeners->ElementAt(i).mWeakListener;
     314           0 :       if (weakListener) {
     315           0 :         nsCOMPtr<nsISupports> otherCanonical = do_QueryReferent(weakListener);
     316           0 :         MOZ_ASSERT((canonical == otherCanonical) == (weak == weakListener));
     317             :       }
     318             :     }
     319             :   }
     320             : #endif
     321             : 
     322           0 :   auto listeners = mListeners.LookupForAdd(aMessage).OrInsert([]() {
     323           0 :       return new nsAutoTObserverArray<nsMessageListenerInfo, 1>();
     324           0 :     });
     325           0 :   uint32_t len = listeners->Length();
     326           0 :   for (uint32_t i = 0; i < len; ++i) {
     327           0 :     if (listeners->ElementAt(i).mWeakListener == weak) {
     328           0 :       return NS_OK;
     329             :     }
     330             :   }
     331             : 
     332           0 :   nsMessageListenerInfo* entry = listeners->AppendElement();
     333           0 :   entry->mWeakListener = weak;
     334           0 :   entry->mListenWhenClosed = false;
     335           0 :   return NS_OK;
     336             : }
     337             : 
     338             : NS_IMETHODIMP
     339           0 : nsFrameMessageManager::RemoveWeakMessageListener(const nsAString& aMessage,
     340             :                                                  nsIMessageListener* aListener)
     341             : {
     342           0 :   nsWeakPtr weak = do_GetWeakReference(aListener);
     343           0 :   NS_ENSURE_TRUE(weak, NS_OK);
     344             : 
     345             :   nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
     346           0 :     mListeners.Get(aMessage);
     347           0 :   if (!listeners) {
     348           0 :     return NS_OK;
     349             :   }
     350             : 
     351           0 :   uint32_t len = listeners->Length();
     352           0 :   for (uint32_t i = 0; i < len; ++i) {
     353           0 :     if (listeners->ElementAt(i).mWeakListener == weak) {
     354           0 :       listeners->RemoveElementAt(i);
     355           0 :       return NS_OK;
     356             :     }
     357             :   }
     358             : 
     359           0 :   return NS_OK;
     360             : }
     361             : 
     362             : // nsIFrameScriptLoader
     363             : 
     364             : NS_IMETHODIMP
     365          77 : nsFrameMessageManager::LoadScript(const nsAString& aURL,
     366             :                                   bool aAllowDelayedLoad,
     367             :                                   bool aRunInGlobalScope)
     368             : {
     369          77 :   if (aAllowDelayedLoad) {
     370             :     // Cache for future windows or frames
     371          21 :     mPendingScripts.AppendElement(aURL);
     372          21 :     mPendingScriptsGlobalStates.AppendElement(aRunInGlobalScope);
     373             :   }
     374             : 
     375          77 :   if (mCallback) {
     376             : #ifdef DEBUG_smaug
     377             :     printf("Will load %s \n", NS_ConvertUTF16toUTF8(aURL).get());
     378             : #endif
     379          45 :     NS_ENSURE_TRUE(mCallback->DoLoadMessageManagerScript(aURL, aRunInGlobalScope),
     380             :                    NS_ERROR_FAILURE);
     381             :   }
     382             : 
     383          94 :   for (int32_t i = 0; i < mChildManagers.Count(); ++i) {
     384             :     RefPtr<nsFrameMessageManager> mm =
     385          34 :       static_cast<nsFrameMessageManager*>(mChildManagers[i]);
     386          17 :     if (mm) {
     387             :       // Use false here, so that child managers don't cache the script, which
     388             :       // is already cached in the parent.
     389          17 :       mm->LoadScript(aURL, false, aRunInGlobalScope);
     390             :     }
     391             :   }
     392          77 :   return NS_OK;
     393             : }
     394             : 
     395             : NS_IMETHODIMP
     396           0 : nsFrameMessageManager::RemoveDelayedScript(const nsAString& aURL)
     397             : {
     398           0 :   for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
     399           0 :     if (mPendingScripts[i] == aURL) {
     400           0 :       mPendingScripts.RemoveElementAt(i);
     401           0 :       mPendingScriptsGlobalStates.RemoveElementAt(i);
     402           0 :       break;
     403             :     }
     404             :   }
     405           0 :   return NS_OK;
     406             : }
     407             : 
     408             : NS_IMETHODIMP
     409           0 : nsFrameMessageManager::GetDelayedScripts(JSContext* aCx, JS::MutableHandle<JS::Value> aList)
     410             : {
     411             :   // Frame message managers may return an incomplete list because scripts
     412             :   // that were loaded after it was connected are not added to the list.
     413           0 :   if (!IsGlobal() && !IsBroadcaster()) {
     414             :     NS_WARNING("Cannot retrieve list of pending frame scripts for frame"
     415           0 :                "message managers as it may be incomplete");
     416           0 :     return NS_ERROR_NOT_IMPLEMENTED;
     417             :   }
     418             : 
     419           0 :   JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, mPendingScripts.Length()));
     420           0 :   NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
     421             : 
     422           0 :   JS::Rooted<JSString*> url(aCx);
     423           0 :   JS::Rooted<JSObject*> pair(aCx);
     424           0 :   for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
     425           0 :     url = JS_NewUCStringCopyN(aCx, mPendingScripts[i].get(), mPendingScripts[i].Length());
     426           0 :     NS_ENSURE_TRUE(url, NS_ERROR_OUT_OF_MEMORY);
     427             : 
     428           0 :     JS::AutoValueArray<2> pairElts(aCx);
     429           0 :     pairElts[0].setString(url);
     430           0 :     pairElts[1].setBoolean(mPendingScriptsGlobalStates[i]);
     431             : 
     432           0 :     pair = JS_NewArrayObject(aCx, pairElts);
     433           0 :     NS_ENSURE_TRUE(pair, NS_ERROR_OUT_OF_MEMORY);
     434             : 
     435           0 :     NS_ENSURE_TRUE(JS_DefineElement(aCx, array, i, pair, JSPROP_ENUMERATE),
     436             :                    NS_ERROR_OUT_OF_MEMORY);
     437             :   }
     438             : 
     439           0 :   aList.setObject(*array);
     440           0 :   return NS_OK;
     441             : }
     442             : 
     443             : // nsIFrameScriptLoader
     444             : 
     445             : NS_IMETHODIMP
     446          51 : nsFrameMessageManager::LoadFrameScript(const nsAString& aURL,
     447             :                                        bool aAllowDelayedLoad,
     448             :                                        bool aRunInGlobalScope)
     449             : {
     450          51 :   return LoadScript(aURL, aAllowDelayedLoad, aRunInGlobalScope);
     451             : }
     452             : 
     453             : NS_IMETHODIMP
     454           0 : nsFrameMessageManager::RemoveDelayedFrameScript(const nsAString& aURL)
     455             : {
     456           0 :   return RemoveDelayedScript(aURL);
     457             : }
     458             : 
     459             : NS_IMETHODIMP
     460           0 : nsFrameMessageManager::GetDelayedFrameScripts(JSContext* aCx, JS::MutableHandle<JS::Value> aList)
     461             : {
     462           0 :   return GetDelayedScripts(aCx, aList);
     463             : }
     464             : 
     465             : // nsIProcessScriptLoader
     466             : 
     467             : NS_IMETHODIMP
     468           9 : nsFrameMessageManager::LoadProcessScript(const nsAString& aURL,
     469             :                                          bool aAllowDelayedLoad)
     470             : {
     471           9 :   return LoadScript(aURL, aAllowDelayedLoad, false);
     472             : }
     473             : 
     474             : NS_IMETHODIMP
     475           0 : nsFrameMessageManager::RemoveDelayedProcessScript(const nsAString& aURL)
     476             : {
     477           0 :   return RemoveDelayedScript(aURL);
     478             : }
     479             : 
     480             : NS_IMETHODIMP
     481           0 : nsFrameMessageManager::GetDelayedProcessScripts(JSContext* aCx, JS::MutableHandle<JS::Value> aList)
     482             : {
     483           0 :   return GetDelayedScripts(aCx, aList);
     484             : }
     485             : 
     486             : static bool
     487           0 : JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData)
     488             : {
     489           0 :   nsAString* result = static_cast<nsAString*>(aData);
     490             :   result->Append(static_cast<const char16_t*>(aBuf),
     491           0 :                  static_cast<uint32_t>(aLen));
     492           0 :   return true;
     493             : }
     494             : 
     495             : static bool
     496          42 : GetParamsForMessage(JSContext* aCx,
     497             :                     const JS::Value& aValue,
     498             :                     const JS::Value& aTransfer,
     499             :                     StructuredCloneData& aData)
     500             : {
     501             :   // First try to use structured clone on the whole thing.
     502          84 :   JS::RootedValue v(aCx, aValue);
     503          84 :   JS::RootedValue t(aCx, aTransfer);
     504          84 :   ErrorResult rv;
     505          42 :   aData.Write(aCx, v, t, rv);
     506          42 :   if (!rv.Failed()) {
     507          42 :     return true;
     508             :   }
     509             : 
     510           0 :   rv.SuppressException();
     511           0 :   JS_ClearPendingException(aCx);
     512             : 
     513           0 :   nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
     514           0 :   if (console) {
     515           0 :     nsAutoString filename;
     516           0 :     uint32_t lineno = 0, column = 0;
     517           0 :     nsJSUtils::GetCallingLocation(aCx, filename, &lineno, &column);
     518           0 :     nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
     519           0 :     error->Init(NS_LITERAL_STRING("Sending message that cannot be cloned. Are you trying to send an XPCOM object?"),
     520           0 :                 filename, EmptyString(), lineno, column,
     521           0 :                 nsIScriptError::warningFlag, "chrome javascript");
     522           0 :     console->LogMessage(error);
     523             :   }
     524             : 
     525             :   // Not clonable, try JSON
     526             :   //XXX This is ugly but currently structured cloning doesn't handle
     527             :   //    properly cases when interface is implemented in JS and used
     528             :   //    as a dictionary.
     529           0 :   nsAutoString json;
     530           0 :   NS_ENSURE_TRUE(JS_Stringify(aCx, &v, nullptr, JS::NullHandleValue,
     531             :                               JSONCreator, &json), false);
     532           0 :   NS_ENSURE_TRUE(!json.IsEmpty(), false);
     533             : 
     534           0 :   JS::Rooted<JS::Value> val(aCx, JS::NullValue());
     535           0 :   NS_ENSURE_TRUE(JS_ParseJSON(aCx, static_cast<const char16_t*>(json.get()),
     536             :                               json.Length(), &val), false);
     537             : 
     538           0 :   aData.Write(aCx, val, rv);
     539           0 :   if (NS_WARN_IF(rv.Failed())) {
     540           0 :     rv.SuppressException();
     541           0 :     return false;
     542             :   }
     543             : 
     544           0 :   return true;
     545             : }
     546             : 
     547             : // nsISyncMessageSender
     548             : 
     549             : static bool sSendingSyncMessage = false;
     550             : 
     551             : NS_IMETHODIMP
     552           0 : nsFrameMessageManager::SendSyncMessage(const nsAString& aMessageName,
     553             :                                        JS::Handle<JS::Value> aJSON,
     554             :                                        JS::Handle<JS::Value> aObjects,
     555             :                                        nsIPrincipal* aPrincipal,
     556             :                                        JSContext* aCx,
     557             :                                        uint8_t aArgc,
     558             :                                        JS::MutableHandle<JS::Value> aRetval)
     559             : {
     560           0 :   return SendMessage(aMessageName, aJSON, aObjects, aPrincipal, aCx, aArgc,
     561           0 :                      aRetval, true);
     562             : }
     563             : 
     564             : NS_IMETHODIMP
     565           0 : nsFrameMessageManager::SendRpcMessage(const nsAString& aMessageName,
     566             :                                       JS::Handle<JS::Value> aJSON,
     567             :                                       JS::Handle<JS::Value> aObjects,
     568             :                                       nsIPrincipal* aPrincipal,
     569             :                                       JSContext* aCx,
     570             :                                       uint8_t aArgc,
     571             :                                       JS::MutableHandle<JS::Value> aRetval)
     572             : {
     573           0 :   return SendMessage(aMessageName, aJSON, aObjects, aPrincipal, aCx, aArgc,
     574           0 :                      aRetval, false);
     575             : }
     576             : 
     577             : static bool
     578          48 : AllowMessage(size_t aDataLength, const nsAString& aMessageName)
     579             : {
     580             :   // A message includes more than structured clone data, so subtract
     581             :   // 20KB to make it more likely that a message within this bound won't
     582             :   // result in an overly large IPC message.
     583             :   static const size_t kMaxMessageSize = IPC::Channel::kMaximumMessageSize - 20 * 1024;
     584          48 :   if (aDataLength < kMaxMessageSize) {
     585          48 :     return true;
     586             :   }
     587             : 
     588           0 :   NS_ConvertUTF16toUTF8 messageName(aMessageName);
     589           0 :   messageName.StripTaggedASCII(ASCIIMask::Mask0to9());
     590             : 
     591             :   Telemetry::Accumulate(Telemetry::REJECTED_MESSAGE_MANAGER_MESSAGE,
     592           0 :                         messageName);
     593             : 
     594           0 :   return false;
     595             : }
     596             : 
     597             : nsresult
     598           0 : nsFrameMessageManager::SendMessage(const nsAString& aMessageName,
     599             :                                    JS::Handle<JS::Value> aJSON,
     600             :                                    JS::Handle<JS::Value> aObjects,
     601             :                                    nsIPrincipal* aPrincipal,
     602             :                                    JSContext* aCx,
     603             :                                    uint8_t aArgc,
     604             :                                    JS::MutableHandle<JS::Value> aRetval,
     605             :                                    bool aIsSync)
     606             : {
     607           0 :   if (profiler_is_active()) {
     608           0 :     NS_LossyConvertUTF16toASCII messageNameCStr(aMessageName);
     609           0 :     AUTO_PROFILER_LABEL_DYNAMIC("nsFrameMessageManager::SendMessage", EVENTS,
     610             :                                 messageNameCStr.get());
     611             :   }
     612             : 
     613           0 :   NS_ASSERTION(!IsGlobal(), "Should not call SendSyncMessage in chrome");
     614           0 :   NS_ASSERTION(!IsBroadcaster(), "Should not call SendSyncMessage in chrome");
     615           0 :   NS_ASSERTION(!mParentManager, "Should not have parent manager in content!");
     616             : 
     617           0 :   aRetval.setUndefined();
     618           0 :   NS_ENSURE_TRUE(mCallback, NS_ERROR_NOT_INITIALIZED);
     619             : 
     620           0 :   if (sSendingSyncMessage && aIsSync) {
     621             :     // No kind of blocking send should be issued on top of a sync message.
     622           0 :     return NS_ERROR_UNEXPECTED;
     623             :   }
     624             : 
     625           0 :   StructuredCloneData data;
     626           0 :   if (aArgc >= 2 && !GetParamsForMessage(aCx, aJSON, JS::UndefinedHandleValue, data)) {
     627           0 :     return NS_ERROR_DOM_DATA_CLONE_ERR;
     628             :   }
     629             : 
     630             : #ifdef FUZZING
     631             :   if (data.DataLength() > 0) {
     632             :     MessageManagerFuzzer::TryMutate(
     633             :       aCx,
     634             :       aMessageName,
     635             :       &data,
     636             :       JS::UndefinedHandleValue);
     637             :   }
     638             : #endif
     639             : 
     640           0 :   if (!AllowMessage(data.DataLength(), aMessageName)) {
     641           0 :     return NS_ERROR_FAILURE;
     642             :   }
     643             : 
     644           0 :   JS::Rooted<JSObject*> objects(aCx);
     645           0 :   if (aArgc >= 3 && aObjects.isObject()) {
     646           0 :     objects = &aObjects.toObject();
     647             :   }
     648             : 
     649           0 :   nsTArray<StructuredCloneData> retval;
     650             : 
     651           0 :   TimeStamp start = TimeStamp::Now();
     652           0 :   sSendingSyncMessage |= aIsSync;
     653           0 :   bool ok = mCallback->DoSendBlockingMessage(aCx, aMessageName, data, objects,
     654           0 :                                              aPrincipal, &retval, aIsSync);
     655           0 :   if (aIsSync) {
     656           0 :     sSendingSyncMessage = false;
     657             :   }
     658             : 
     659           0 :   uint32_t latencyMs = round((TimeStamp::Now() - start).ToMilliseconds());
     660           0 :   if (latencyMs >= kMinTelemetrySyncMessageManagerLatencyMs) {
     661           0 :     NS_ConvertUTF16toUTF8 messageName(aMessageName);
     662             :     // NOTE: We need to strip digit characters from the message name in order to
     663             :     // avoid a large number of buckets due to generated names from addons (such
     664             :     // as "ublock:sb:{N}"). See bug 1348113 comment 10.
     665           0 :     messageName.StripTaggedASCII(ASCIIMask::Mask0to9());
     666             :     Telemetry::Accumulate(Telemetry::IPC_SYNC_MESSAGE_MANAGER_LATENCY_MS,
     667           0 :                           messageName, latencyMs);
     668             :   }
     669             : 
     670           0 :   if (!ok) {
     671           0 :     return NS_OK;
     672             :   }
     673             : 
     674           0 :   uint32_t len = retval.Length();
     675           0 :   JS::Rooted<JSObject*> dataArray(aCx, JS_NewArrayObject(aCx, len));
     676           0 :   NS_ENSURE_TRUE(dataArray, NS_ERROR_OUT_OF_MEMORY);
     677             : 
     678           0 :   for (uint32_t i = 0; i < len; ++i) {
     679           0 :     JS::Rooted<JS::Value> ret(aCx);
     680           0 :     ErrorResult rv;
     681           0 :     retval[i].Read(aCx, &ret, rv);
     682           0 :     if (rv.Failed()) {
     683           0 :       MOZ_ASSERT(false, "Unable to read structured clone in SendMessage");
     684             :       rv.SuppressException();
     685             :       return NS_ERROR_UNEXPECTED;
     686             :     }
     687             : 
     688           0 :     NS_ENSURE_TRUE(JS_DefineElement(aCx, dataArray, i, ret, JSPROP_ENUMERATE),
     689             :                    NS_ERROR_OUT_OF_MEMORY);
     690             :   }
     691             : 
     692           0 :   aRetval.setObject(*dataArray);
     693           0 :   return NS_OK;
     694             : }
     695             : 
     696             : nsresult
     697          55 : nsFrameMessageManager::DispatchAsyncMessageInternal(JSContext* aCx,
     698             :                                                     const nsAString& aMessage,
     699             :                                                     StructuredCloneData& aData,
     700             :                                                     JS::Handle<JSObject *> aCpows,
     701             :                                                     nsIPrincipal* aPrincipal)
     702             : {
     703          55 :   if (mIsBroadcaster) {
     704           6 :     int32_t len = mChildManagers.Count();
     705          13 :     for (int32_t i = 0; i < len; ++i) {
     706           7 :       static_cast<nsFrameMessageManager*>(mChildManagers[i])->
     707           7 :          DispatchAsyncMessageInternal(aCx, aMessage, aData, aCpows, aPrincipal);
     708             :     }
     709           6 :     return NS_OK;
     710             :   }
     711             : 
     712          49 :   if (!mCallback) {
     713           0 :     return NS_ERROR_NOT_INITIALIZED;
     714             :   }
     715             : 
     716          49 :   nsresult rv = mCallback->DoSendAsyncMessage(aCx, aMessage, aData, aCpows, aPrincipal);
     717          49 :   if (NS_FAILED(rv)) {
     718           0 :     return rv;
     719             :   }
     720          49 :   return NS_OK;
     721             : }
     722             : 
     723             : nsresult
     724          48 : nsFrameMessageManager::DispatchAsyncMessage(const nsAString& aMessageName,
     725             :                                             const JS::Value& aJSON,
     726             :                                             const JS::Value& aObjects,
     727             :                                             nsIPrincipal* aPrincipal,
     728             :                                             const JS::Value& aTransfers,
     729             :                                             JSContext* aCx,
     730             :                                             uint8_t aArgc)
     731             : {
     732          96 :   StructuredCloneData data;
     733          48 :   if (aArgc >= 2 && !GetParamsForMessage(aCx, aJSON, aTransfers, data)) {
     734           0 :     return NS_ERROR_DOM_DATA_CLONE_ERR;
     735             :   }
     736             : 
     737             : #ifdef FUZZING
     738             :   if (data.DataLength()) {
     739             :     MessageManagerFuzzer::TryMutate(aCx, aMessageName, &data, aTransfers);
     740             :   }
     741             : #endif
     742             : 
     743          48 :   if (!AllowMessage(data.DataLength(), aMessageName)) {
     744           0 :     return NS_ERROR_FAILURE;
     745             :   }
     746             : 
     747          96 :   JS::Rooted<JSObject*> objects(aCx);
     748          48 :   if (aArgc >= 3 && aObjects.isObject()) {
     749          11 :     objects = &aObjects.toObject();
     750             :   }
     751             : 
     752          96 :   return DispatchAsyncMessageInternal(aCx, aMessageName, data, objects,
     753          48 :                                       aPrincipal);
     754             : }
     755             : 
     756             : // nsIMessageSender
     757             : 
     758             : NS_IMETHODIMP
     759          44 : nsFrameMessageManager::SendAsyncMessage(const nsAString& aMessageName,
     760             :                                         JS::Handle<JS::Value> aJSON,
     761             :                                         JS::Handle<JS::Value> aObjects,
     762             :                                         nsIPrincipal* aPrincipal,
     763             :                                         JS::Handle<JS::Value> aTransfers,
     764             :                                         JSContext* aCx,
     765             :                                         uint8_t aArgc)
     766             : {
     767          44 :   return DispatchAsyncMessage(aMessageName, aJSON, aObjects, aPrincipal,
     768          44 :                               aTransfers, aCx, aArgc);
     769             : }
     770             : 
     771             : 
     772             : // nsIMessageBroadcaster
     773             : 
     774             : NS_IMETHODIMP
     775           4 : nsFrameMessageManager::BroadcastAsyncMessage(const nsAString& aMessageName,
     776             :                                              JS::Handle<JS::Value> aJSON,
     777             :                                              JS::Handle<JS::Value> aObjects,
     778             :                                              JSContext* aCx,
     779             :                                              uint8_t aArgc)
     780             : {
     781           4 :   return DispatchAsyncMessage(aMessageName, aJSON, aObjects, nullptr,
     782           4 :                               JS::UndefinedHandleValue, aCx, aArgc);
     783             : }
     784             : 
     785             : NS_IMETHODIMP
     786           4 : nsFrameMessageManager::GetChildCount(uint32_t* aChildCount)
     787             : {
     788           4 :   *aChildCount = static_cast<uint32_t>(mChildManagers.Count());
     789           4 :   return NS_OK;
     790             : }
     791             : 
     792             : NS_IMETHODIMP
     793           4 : nsFrameMessageManager::GetChildAt(uint32_t aIndex,
     794             :                                   nsIMessageListenerManager** aMM)
     795             : {
     796           4 :   *aMM = nullptr;
     797             :   nsCOMPtr<nsIMessageListenerManager> mm =
     798           8 :     do_QueryInterface(mChildManagers.SafeObjectAt(static_cast<uint32_t>(aIndex)));
     799           4 :   mm.swap(*aMM);
     800           8 :   return NS_OK;
     801             : }
     802             : 
     803             : NS_IMETHODIMP
     804           0 : nsFrameMessageManager::ReleaseCachedProcesses()
     805             : {
     806           0 :   ContentParent::ReleaseCachedProcesses();
     807           0 :   return NS_OK;
     808             : }
     809             : 
     810             : // nsIContentFrameMessageManager
     811             : 
     812             : NS_IMETHODIMP
     813           0 : nsFrameMessageManager::Dump(const nsAString& aStr)
     814             : {
     815             : #ifdef ANDROID
     816             :   __android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", NS_ConvertUTF16toUTF8(aStr).get());
     817             : #endif
     818             : #ifdef XP_WIN
     819             :   if (IsDebuggerPresent()) {
     820             :     OutputDebugStringW(PromiseFlatString(aStr).get());
     821             :   }
     822             : #endif
     823           0 :   fputs(NS_ConvertUTF16toUTF8(aStr).get(), stdout);
     824           0 :   fflush(stdout);
     825           0 :   return NS_OK;
     826             : }
     827             : 
     828             : NS_IMETHODIMP
     829           0 : nsFrameMessageManager::PrivateNoteIntentionalCrash()
     830             : {
     831           0 :   if (XRE_IsContentProcess()) {
     832           0 :     mozilla::NoteIntentionalCrash("tab");
     833           0 :     return NS_OK;
     834             :   }
     835           0 :   return NS_ERROR_NOT_IMPLEMENTED;
     836             : }
     837             : 
     838             : NS_IMETHODIMP
     839           0 : nsFrameMessageManager::GetContent(mozIDOMWindowProxy** aContent)
     840             : {
     841           0 :   *aContent = nullptr;
     842           0 :   return NS_OK;
     843             : }
     844             : 
     845             : NS_IMETHODIMP
     846           0 : nsFrameMessageManager::GetDocShell(nsIDocShell** aDocShell)
     847             : {
     848           0 :   *aDocShell = nullptr;
     849           0 :   return NS_OK;
     850             : }
     851             : 
     852             : NS_IMETHODIMP
     853           0 : nsFrameMessageManager::Btoa(const nsAString& aBinaryData,
     854             :                             nsAString& aAsciiBase64String)
     855             : {
     856           0 :   return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
     857             : }
     858             : 
     859             : NS_IMETHODIMP
     860           0 : nsFrameMessageManager::Atob(const nsAString& aAsciiString,
     861             :                             nsAString& aBinaryData)
     862             : {
     863           0 :   return nsContentUtils::Atob(aAsciiString, aBinaryData);
     864             : }
     865             : 
     866             : class MMListenerRemover
     867             : {
     868             : public:
     869          46 :   explicit MMListenerRemover(nsFrameMessageManager* aMM)
     870          46 :     : mWasHandlingMessage(aMM->mHandlingMessage)
     871          46 :     , mMM(aMM)
     872             :   {
     873          46 :     mMM->mHandlingMessage = true;
     874          46 :   }
     875          45 :   ~MMListenerRemover()
     876          45 :   {
     877          45 :     if (!mWasHandlingMessage) {
     878          45 :       mMM->mHandlingMessage = false;
     879          45 :       if (mMM->mDisconnected) {
     880           0 :         mMM->mListeners.Clear();
     881             :       }
     882             :     }
     883          45 :   }
     884             : 
     885             :   bool mWasHandlingMessage;
     886             :   RefPtr<nsFrameMessageManager> mMM;
     887             : };
     888             : 
     889             : 
     890             : // nsIMessageListener
     891             : 
     892             : nsresult
     893          47 : nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
     894             :                                       nsIFrameLoader* aTargetFrameLoader,
     895             :                                       const nsAString& aMessage,
     896             :                                       bool aIsSync,
     897             :                                       StructuredCloneData* aCloneData,
     898             :                                       mozilla::jsipc::CpowHolder* aCpows,
     899             :                                       nsIPrincipal* aPrincipal,
     900             :                                       nsTArray<StructuredCloneData>* aRetVal)
     901             : {
     902          47 :   return ReceiveMessage(aTarget, aTargetFrameLoader, mClosed, aMessage, aIsSync,
     903          47 :                         aCloneData, aCpows, aPrincipal, aRetVal);
     904             : }
     905             : 
     906             : nsresult
     907         138 : nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
     908             :                                       nsIFrameLoader* aTargetFrameLoader,
     909             :                                       bool aTargetClosed,
     910             :                                       const nsAString& aMessage,
     911             :                                       bool aIsSync,
     912             :                                       StructuredCloneData* aCloneData,
     913             :                                       mozilla::jsipc::CpowHolder* aCpows,
     914             :                                       nsIPrincipal* aPrincipal,
     915             :                                       nsTArray<StructuredCloneData>* aRetVal)
     916             : {
     917             :   nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
     918         138 :     mListeners.Get(aMessage);
     919         138 :   if (listeners) {
     920             : 
     921          91 :     MMListenerRemover lr(this);
     922             : 
     923             :     nsAutoTObserverArray<nsMessageListenerInfo, 1>::EndLimitedIterator
     924          91 :       iter(*listeners);
     925         136 :     while(iter.HasMore()) {
     926          46 :       nsMessageListenerInfo& listener = iter.GetNext();
     927             :       // Remove mListeners[i] if it's an expired weak listener.
     928          91 :       nsCOMPtr<nsISupports> weakListener;
     929          46 :       if (listener.mWeakListener) {
     930           0 :         weakListener = do_QueryReferent(listener.mWeakListener);
     931           0 :         if (!weakListener) {
     932           0 :           listeners->RemoveElement(listener);
     933           0 :           continue;
     934             :         }
     935             :       }
     936             : 
     937          46 :       if (!listener.mListenWhenClosed && aTargetClosed) {
     938           0 :         continue;
     939             :       }
     940             : 
     941          91 :       nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS;
     942          46 :       if (weakListener) {
     943           0 :         wrappedJS = do_QueryInterface(weakListener);
     944             :       } else {
     945          46 :         wrappedJS = do_QueryInterface(listener.mStrongListener);
     946             :       }
     947             : 
     948          46 :       if (!wrappedJS) {
     949           0 :         continue;
     950             :       }
     951             : 
     952          46 :       if (!wrappedJS->GetJSObject()) {
     953           0 :         continue;
     954             :       }
     955             : 
     956          91 :       AutoEntryScript aes(wrappedJS->GetJSObject(), "message manager handler");
     957          46 :       JSContext* cx = aes.cx();
     958          91 :       JS::Rooted<JSObject*> object(cx, wrappedJS->GetJSObject());
     959             : 
     960             :       // The parameter for the listener function.
     961          91 :       JS::Rooted<JSObject*> param(cx, JS_NewPlainObject(cx));
     962          46 :       NS_ENSURE_TRUE(param, NS_ERROR_OUT_OF_MEMORY);
     963             : 
     964          91 :       JS::Rooted<JS::Value> targetv(cx);
     965          46 :       js::AssertSameCompartment(cx, object);
     966          46 :       nsresult rv = nsContentUtils::WrapNative(cx, aTarget, &targetv);
     967          46 :       NS_ENSURE_SUCCESS(rv, rv);
     968             : 
     969          91 :       JS::Rooted<JSObject*> cpows(cx);
     970          46 :       if (aCpows) {
     971          46 :         if (!aCpows->ToObject(cx, &cpows)) {
     972           0 :           return NS_ERROR_UNEXPECTED;
     973             :         }
     974             :       }
     975             : 
     976          46 :       if (!cpows) {
     977          35 :         cpows = JS_NewPlainObject(cx);
     978          35 :         if (!cpows) {
     979           0 :           return NS_ERROR_UNEXPECTED;
     980             :         }
     981             :       }
     982             : 
     983          91 :       JS::Rooted<JS::Value> cpowsv(cx, JS::ObjectValue(*cpows));
     984             : 
     985          91 :       JS::Rooted<JS::Value> json(cx, JS::NullValue());
     986          46 :       if (aCloneData && aCloneData->DataLength()) {
     987          82 :         ErrorResult rv;
     988          41 :         aCloneData->Read(cx, &json, rv);
     989          41 :         if (NS_WARN_IF(rv.Failed())) {
     990           0 :           rv.SuppressException();
     991           0 :           JS_ClearPendingException(cx);
     992           0 :           return NS_OK;
     993             :         }
     994             :       }
     995             : 
     996             :       // Get cloned MessagePort from StructuredCloneData.
     997          91 :       nsTArray<RefPtr<mozilla::dom::MessagePort>> ports;
     998          46 :       if (aCloneData) {
     999          46 :         ports = aCloneData->TakeTransferredPorts();
    1000             :       }
    1001             : 
    1002          91 :       JS::Rooted<JS::Value> transferredList(cx);
    1003          46 :       if (NS_WARN_IF(!ToJSValue(cx, ports, &transferredList))) {
    1004           0 :         return NS_ERROR_UNEXPECTED;
    1005             :       }
    1006             : 
    1007             :       JS::Rooted<JSString*> jsMessage(cx,
    1008         138 :         JS_NewUCStringCopyN(cx,
    1009          46 :                             static_cast<const char16_t*>(aMessage.BeginReading()),
    1010         137 :                             aMessage.Length()));
    1011          46 :       NS_ENSURE_TRUE(jsMessage, NS_ERROR_OUT_OF_MEMORY);
    1012          91 :       JS::Rooted<JS::Value> syncv(cx, JS::BooleanValue(aIsSync));
    1013         368 :       bool ok = JS_DefineProperty(cx, param, "target", targetv, JSPROP_ENUMERATE) &&
    1014         322 :                 JS_DefineProperty(cx, param, "name", jsMessage, JSPROP_ENUMERATE) &&
    1015         322 :                 JS_DefineProperty(cx, param, "sync", syncv, JSPROP_ENUMERATE) &&
    1016         322 :                 JS_DefineProperty(cx, param, "json", json, JSPROP_ENUMERATE) && // deprecated
    1017         322 :                 JS_DefineProperty(cx, param, "data", json, JSPROP_ENUMERATE) &&
    1018         506 :                 JS_DefineProperty(cx, param, "objects", cpowsv, JSPROP_ENUMERATE) &&
    1019         184 :                 JS_DefineProperty(cx, param, "ports", transferredList, JSPROP_ENUMERATE);
    1020             : 
    1021          46 :       NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED);
    1022             : 
    1023          46 :       if (aTargetFrameLoader) {
    1024          60 :         JS::Rooted<JS::Value> targetFrameLoaderv(cx);
    1025          30 :         nsresult rv = nsContentUtils::WrapNative(cx, aTargetFrameLoader, &targetFrameLoaderv);
    1026          30 :         NS_ENSURE_SUCCESS(rv, rv);
    1027             : 
    1028          60 :         ok = JS_DefineProperty(cx, param, "targetFrameLoader", targetFrameLoaderv,
    1029          30 :                                JSPROP_ENUMERATE);
    1030          30 :         NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED);
    1031             :       }
    1032             : 
    1033             :       // message.principal == null
    1034          46 :       if (!aPrincipal) {
    1035          92 :         bool ok = JS_DefineProperty(cx, param, "principal",
    1036          46 :                                     JS::UndefinedHandleValue, JSPROP_ENUMERATE);
    1037          46 :         NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED);
    1038             :       }
    1039             : 
    1040             :       // message.principal = the principal
    1041             :       else {
    1042           0 :         JS::Rooted<JS::Value> principalValue(cx);
    1043           0 :         nsresult rv = nsContentUtils::WrapNative(cx, aPrincipal,
    1044             :                                                  &NS_GET_IID(nsIPrincipal),
    1045           0 :                                                  &principalValue);
    1046           0 :         NS_ENSURE_SUCCESS(rv, rv);
    1047           0 :         bool ok = JS_DefineProperty(cx, param, "principal", principalValue,
    1048           0 :                                     JSPROP_ENUMERATE);
    1049           0 :         NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED);
    1050             :       }
    1051             : 
    1052          91 :       JS::Rooted<JS::Value> thisValue(cx, JS::UndefinedValue());
    1053             : 
    1054          91 :       JS::Rooted<JS::Value> funval(cx);
    1055          46 :       if (JS::IsCallable(object)) {
    1056             :         // If the listener is a JS function:
    1057          25 :         funval.setObject(*object);
    1058             : 
    1059             :         // A small hack to get 'this' value right on content side where
    1060             :         // messageManager is wrapped in TabChildGlobal.
    1061          50 :         nsCOMPtr<nsISupports> defaultThisValue;
    1062          25 :         if (mChrome) {
    1063          13 :           defaultThisValue = do_QueryObject(this);
    1064             :         } else {
    1065          12 :           defaultThisValue = aTarget;
    1066             :         }
    1067          25 :         js::AssertSameCompartment(cx, object);
    1068          25 :         nsresult rv = nsContentUtils::WrapNative(cx, defaultThisValue, &thisValue);
    1069          25 :         NS_ENSURE_SUCCESS(rv, rv);
    1070             :       } else {
    1071             :         // If the listener is a JS object which has receiveMessage function:
    1072          42 :         if (!JS_GetProperty(cx, object, "receiveMessage", &funval) ||
    1073          21 :             !funval.isObject()) {
    1074           0 :           return NS_ERROR_UNEXPECTED;
    1075             :         }
    1076             : 
    1077             :         // Check if the object is even callable.
    1078          21 :         NS_ENSURE_STATE(JS::IsCallable(&funval.toObject()));
    1079          21 :         thisValue.setObject(*object);
    1080             :       }
    1081             : 
    1082          91 :       JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
    1083          91 :       JS::Rooted<JS::Value> argv(cx, JS::ObjectValue(*param));
    1084             : 
    1085             :       {
    1086          91 :         JS::Rooted<JSObject*> thisObject(cx, thisValue.toObjectOrNull());
    1087             : 
    1088          91 :         JSAutoCompartment tac(cx, thisObject);
    1089          46 :         if (!JS_WrapValue(cx, &argv)) {
    1090           0 :           return NS_ERROR_UNEXPECTED;
    1091             :         }
    1092             : 
    1093         137 :         if (!JS_CallFunctionValue(cx, thisObject, funval,
    1094          91 :                                   JS::HandleValueArray(argv), &rval)) {
    1095           0 :           continue;
    1096             :         }
    1097          45 :         if (aRetVal) {
    1098           0 :           ErrorResult rv;
    1099           0 :           StructuredCloneData* data = aRetVal->AppendElement();
    1100           0 :           data->Write(cx, rval, rv);
    1101           0 :           if (NS_WARN_IF(rv.Failed())) {
    1102           0 :             aRetVal->RemoveElementAt(aRetVal->Length() - 1);
    1103           0 :             nsString msg = aMessage + NS_LITERAL_STRING(": message reply cannot be cloned. Are you trying to send an XPCOM object?");
    1104             : 
    1105           0 :             nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
    1106           0 :             if (console) {
    1107           0 :               nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
    1108           0 :               error->Init(msg, EmptyString(), EmptyString(),
    1109           0 :                           0, 0, nsIScriptError::warningFlag, "chrome javascript");
    1110           0 :               console->LogMessage(error);
    1111             :             }
    1112             : 
    1113           0 :             JS_ClearPendingException(cx);
    1114           0 :             continue;
    1115             :           }
    1116             :         }
    1117             :       }
    1118             :     }
    1119             :   }
    1120             : 
    1121         271 :   RefPtr<nsFrameMessageManager> kungFuDeathGrip = mParentManager;
    1122         137 :   if (kungFuDeathGrip) {
    1123          91 :     return kungFuDeathGrip->ReceiveMessage(aTarget, aTargetFrameLoader,
    1124             :                                            aTargetClosed, aMessage,
    1125             :                                            aIsSync, aCloneData,
    1126             :                                            aCpows, aPrincipal,
    1127          91 :                                            aRetVal);
    1128             :   }
    1129          46 :   return NS_OK;
    1130             : }
    1131             : 
    1132             : void
    1133           7 : nsFrameMessageManager::AddChildManager(nsFrameMessageManager* aManager)
    1134             : {
    1135           7 :   mChildManagers.AppendObject(aManager);
    1136             : 
    1137          14 :   RefPtr<nsFrameMessageManager> kungfuDeathGrip = this;
    1138          14 :   RefPtr<nsFrameMessageManager> kungfuDeathGrip2 = aManager;
    1139             : 
    1140           7 :   LoadPendingScripts(this, aManager);
    1141           7 : }
    1142             : 
    1143             : void
    1144          12 : nsFrameMessageManager::LoadPendingScripts(nsFrameMessageManager* aManager,
    1145             :                                           nsFrameMessageManager* aChildMM)
    1146             : {
    1147             :   // We have parent manager if we're a message broadcaster.
    1148             :   // In that case we want to load the pending scripts from all parent
    1149             :   // message managers in the hierarchy. Process the parent first so
    1150             :   // that pending scripts higher up in the hierarchy are loaded before others.
    1151          12 :   if (aManager->mParentManager) {
    1152           5 :     LoadPendingScripts(aManager->mParentManager, aChildMM);
    1153             :   }
    1154             : 
    1155          51 :   for (uint32_t i = 0; i < aManager->mPendingScripts.Length(); ++i) {
    1156          39 :     aChildMM->LoadFrameScript(aManager->mPendingScripts[i],
    1157             :                               false,
    1158          78 :                               aManager->mPendingScriptsGlobalStates[i]);
    1159             :   }
    1160          12 : }
    1161             : 
    1162             : void
    1163           0 : nsFrameMessageManager::LoadPendingScripts()
    1164             : {
    1165           0 :   RefPtr<nsFrameMessageManager> kungfuDeathGrip = this;
    1166           0 :   LoadPendingScripts(this, this);
    1167           0 : }
    1168             : 
    1169             : void
    1170           4 : nsFrameMessageManager::SetCallback(MessageManagerCallback* aCallback)
    1171             : {
    1172           4 :   MOZ_ASSERT(!mIsBroadcaster || !mCallback,
    1173             :              "Broadcasters cannot have callbacks!");
    1174           4 :   if (aCallback && mCallback != aCallback) {
    1175           4 :     mCallback = aCallback;
    1176           4 :     if (mOwnsCallback) {
    1177           0 :       mOwnedCallback = aCallback;
    1178             :     }
    1179             :   }
    1180           4 : }
    1181             : 
    1182             : void
    1183           4 : nsFrameMessageManager::InitWithCallback(MessageManagerCallback* aCallback)
    1184             : {
    1185           4 :   if (mCallback) {
    1186             :     // Initialization should only happen once.
    1187           0 :     return;
    1188             :   }
    1189             : 
    1190           4 :   SetCallback(aCallback);
    1191             : 
    1192             :   // First load parent scripts by adding this to parent manager.
    1193           4 :   if (mParentManager) {
    1194           4 :     mParentManager->AddChildManager(this);
    1195             :   }
    1196             : 
    1197           4 :   for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
    1198           0 :     LoadFrameScript(mPendingScripts[i], false, mPendingScriptsGlobalStates[i]);
    1199             :   }
    1200             : }
    1201             : 
    1202             : void
    1203           0 : nsFrameMessageManager::RemoveFromParent()
    1204             : {
    1205           0 :   if (mParentManager) {
    1206           0 :     mParentManager->RemoveChildManager(this);
    1207             :   }
    1208           0 :   mParentManager = nullptr;
    1209           0 :   mCallback = nullptr;
    1210           0 :   mOwnedCallback = nullptr;
    1211           0 : }
    1212             : 
    1213             : void
    1214           3 : nsFrameMessageManager::Close()
    1215             : {
    1216           3 :   if (!mClosed) {
    1217           4 :     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
    1218           2 :     if (obs) {
    1219           4 :       obs->NotifyObservers(NS_ISUPPORTS_CAST(nsIContentFrameMessageManager*, this),
    1220           4 :                             "message-manager-close", nullptr);
    1221             :     }
    1222             :   }
    1223           3 :   mClosed = true;
    1224           3 :   mCallback = nullptr;
    1225           3 :   mOwnedCallback = nullptr;
    1226           3 : }
    1227             : 
    1228             : void
    1229           2 : nsFrameMessageManager::Disconnect(bool aRemoveFromParent)
    1230             : {
    1231             :   // Notify message-manager-close if we haven't already.
    1232           2 :   Close();
    1233             : 
    1234           2 :   if (!mDisconnected) {
    1235           4 :     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
    1236           2 :     if (obs) {
    1237           4 :        obs->NotifyObservers(NS_ISUPPORTS_CAST(nsIContentFrameMessageManager*, this),
    1238           4 :                             "message-manager-disconnect", nullptr);
    1239             :     }
    1240             :   }
    1241           2 :   if (mParentManager && aRemoveFromParent) {
    1242           1 :     mParentManager->RemoveChildManager(this);
    1243             :   }
    1244           2 :   mDisconnected = true;
    1245           2 :   mParentManager = nullptr;
    1246           2 :   if (!mHandlingMessage) {
    1247           2 :     mListeners.Clear();
    1248             :   }
    1249           2 : }
    1250             : 
    1251             : void
    1252           2 : nsFrameMessageManager::SetInitialProcessData(JS::HandleValue aInitialData)
    1253             : {
    1254           2 :   MOZ_ASSERT(!mChrome);
    1255           2 :   MOZ_ASSERT(mIsProcessManager);
    1256           2 :   mInitialProcessData = aInitialData;
    1257           2 : }
    1258             : 
    1259             : NS_IMETHODIMP
    1260          15 : nsFrameMessageManager::GetInitialProcessData(JSContext* aCx, JS::MutableHandleValue aResult)
    1261             : {
    1262          15 :   MOZ_ASSERT(mIsProcessManager);
    1263          15 :   MOZ_ASSERT_IF(mChrome, IsBroadcaster());
    1264             : 
    1265          30 :   JS::RootedValue init(aCx, mInitialProcessData);
    1266          15 :   if (mChrome && init.isUndefined()) {
    1267             :     // We create the initial object in the junk scope. If we created it in a
    1268             :     // normal compartment, that compartment would leak until shutdown.
    1269           2 :     JS::RootedObject global(aCx, xpc::PrivilegedJunkScope());
    1270           2 :     JSAutoCompartment ac(aCx, global);
    1271             : 
    1272           2 :     JS::RootedObject obj(aCx, JS_NewPlainObject(aCx));
    1273           1 :     if (!obj) {
    1274           0 :       return NS_ERROR_OUT_OF_MEMORY;
    1275             :     }
    1276             : 
    1277           1 :     mInitialProcessData.setObject(*obj);
    1278           1 :     init.setObject(*obj);
    1279             :   }
    1280             : 
    1281          15 :   if (!mChrome && XRE_IsParentProcess()) {
    1282             :     // This is the cpmm in the parent process. We should use the same object as the ppmm.
    1283             :     nsCOMPtr<nsIGlobalProcessScriptLoader> ppmm =
    1284           6 :       do_GetService("@mozilla.org/parentprocessmessagemanager;1");
    1285           3 :     ppmm->GetInitialProcessData(aCx, &init);
    1286           3 :     mInitialProcessData = init;
    1287             :   }
    1288             : 
    1289          15 :   if (!JS_WrapValue(aCx, &init)) {
    1290           0 :     return NS_ERROR_OUT_OF_MEMORY;
    1291             :   }
    1292          15 :   aResult.set(init);
    1293          15 :   return NS_OK;
    1294             : }
    1295             : 
    1296             : NS_IMETHODIMP
    1297           0 : nsFrameMessageManager::GetProcessMessageManager(nsIMessageSender** aPMM)
    1298             : {
    1299           0 :   *aPMM = nullptr;
    1300           0 :   if (mCallback) {
    1301           0 :     nsCOMPtr<nsIMessageSender> pmm = mCallback->GetProcessMessageManager();
    1302           0 :     pmm.swap(*aPMM);
    1303             :   }
    1304           0 :   return NS_OK;
    1305             : }
    1306             : 
    1307             : namespace {
    1308             : 
    1309           0 : struct MessageManagerReferentCount
    1310             : {
    1311           0 :   MessageManagerReferentCount() : mStrong(0), mWeakAlive(0), mWeakDead(0) {}
    1312             :   size_t mStrong;
    1313             :   size_t mWeakAlive;
    1314             :   size_t mWeakDead;
    1315             :   nsTArray<nsString> mSuspectMessages;
    1316             :   nsDataHashtable<nsStringHashKey, uint32_t> mMessageCounter;
    1317             : };
    1318             : 
    1319             : } // namespace
    1320             : 
    1321             : namespace mozilla {
    1322             : namespace dom {
    1323             : 
    1324           3 : class MessageManagerReporter final : public nsIMemoryReporter
    1325             : {
    1326             :   ~MessageManagerReporter() = default;
    1327             : 
    1328             : public:
    1329             :   NS_DECL_ISUPPORTS
    1330             :   NS_DECL_NSIMEMORYREPORTER
    1331             : 
    1332             :   static const size_t kSuspectReferentCount = 300;
    1333             : protected:
    1334             :   void CountReferents(nsFrameMessageManager* aMessageManager,
    1335             :                       MessageManagerReferentCount* aReferentCount);
    1336             : };
    1337             : 
    1338          39 : NS_IMPL_ISUPPORTS(MessageManagerReporter, nsIMemoryReporter)
    1339             : 
    1340             : void
    1341           0 : MessageManagerReporter::CountReferents(nsFrameMessageManager* aMessageManager,
    1342             :                                        MessageManagerReferentCount* aReferentCount)
    1343             : {
    1344           0 :   for (auto it = aMessageManager->mListeners.Iter(); !it.Done(); it.Next()) {
    1345             :     nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
    1346           0 :       it.UserData();
    1347           0 :     uint32_t listenerCount = listeners->Length();
    1348           0 :     if (listenerCount == 0) {
    1349           0 :       continue;
    1350             :     }
    1351             : 
    1352           0 :     nsString key(it.Key());
    1353           0 :     uint32_t oldCount = 0;
    1354           0 :     aReferentCount->mMessageCounter.Get(key, &oldCount);
    1355           0 :     uint32_t currentCount = oldCount + listenerCount;
    1356           0 :     aReferentCount->mMessageCounter.Put(key, currentCount);
    1357             : 
    1358             :     // Keep track of messages that have a suspiciously large
    1359             :     // number of referents (symptom of leak).
    1360           0 :     if (currentCount == MessageManagerReporter::kSuspectReferentCount) {
    1361           0 :       aReferentCount->mSuspectMessages.AppendElement(key);
    1362             :     }
    1363             : 
    1364           0 :     for (uint32_t i = 0; i < listenerCount; ++i) {
    1365           0 :       const nsMessageListenerInfo& listenerInfo = listeners->ElementAt(i);
    1366           0 :       if (listenerInfo.mWeakListener) {
    1367             :         nsCOMPtr<nsISupports> referent =
    1368           0 :           do_QueryReferent(listenerInfo.mWeakListener);
    1369           0 :         if (referent) {
    1370           0 :           aReferentCount->mWeakAlive++;
    1371             :         } else {
    1372           0 :           aReferentCount->mWeakDead++;
    1373             :         }
    1374             :       } else {
    1375           0 :         aReferentCount->mStrong++;
    1376             :       }
    1377             :     }
    1378             :   }
    1379             : 
    1380             :   // Add referent count in child managers because the listeners
    1381             :   // participate in messages dispatched from parent message manager.
    1382           0 :   for (uint32_t i = 0; i < aMessageManager->mChildManagers.Length(); ++i) {
    1383             :     RefPtr<nsFrameMessageManager> mm =
    1384           0 :       static_cast<nsFrameMessageManager*>(aMessageManager->mChildManagers[i]);
    1385           0 :     CountReferents(mm, aReferentCount);
    1386             :   }
    1387           0 : }
    1388             : 
    1389             : static void
    1390           0 : ReportReferentCount(const char* aManagerType,
    1391             :                     const MessageManagerReferentCount& aReferentCount,
    1392             :                     nsIHandleReportCallback* aHandleReport,
    1393             :                     nsISupports* aData)
    1394             : {
    1395             : #define REPORT(_path, _amount, _desc) \
    1396             :     do { \
    1397             :       aHandleReport->Callback(EmptyCString(), _path, \
    1398             :                               nsIMemoryReporter::KIND_OTHER, \
    1399             :                               nsIMemoryReporter::UNITS_COUNT, _amount, \
    1400             :                               _desc, aData); \
    1401             :     } while (0)
    1402             : 
    1403           0 :   REPORT(nsPrintfCString("message-manager/referent/%s/strong", aManagerType),
    1404             :          aReferentCount.mStrong,
    1405             :          nsPrintfCString("The number of strong referents held by the message "
    1406             :                          "manager in the %s manager.", aManagerType));
    1407           0 :   REPORT(nsPrintfCString("message-manager/referent/%s/weak/alive", aManagerType),
    1408             :          aReferentCount.mWeakAlive,
    1409             :          nsPrintfCString("The number of weak referents that are still alive "
    1410             :                          "held by the message manager in the %s manager.",
    1411             :                          aManagerType));
    1412           0 :   REPORT(nsPrintfCString("message-manager/referent/%s/weak/dead", aManagerType),
    1413             :          aReferentCount.mWeakDead,
    1414             :          nsPrintfCString("The number of weak referents that are dead "
    1415             :                          "held by the message manager in the %s manager.",
    1416             :                          aManagerType));
    1417             : 
    1418           0 :   for (uint32_t i = 0; i < aReferentCount.mSuspectMessages.Length(); i++) {
    1419           0 :     uint32_t totalReferentCount = 0;
    1420           0 :     aReferentCount.mMessageCounter.Get(aReferentCount.mSuspectMessages[i],
    1421           0 :                                        &totalReferentCount);
    1422           0 :     NS_ConvertUTF16toUTF8 suspect(aReferentCount.mSuspectMessages[i]);
    1423           0 :     REPORT(nsPrintfCString("message-manager-suspect/%s/referent(message=%s)",
    1424             :                            aManagerType, suspect.get()), totalReferentCount,
    1425             :            nsPrintfCString("A message in the %s message manager with a "
    1426             :                            "suspiciously large number of referents (symptom "
    1427             :                            "of a leak).", aManagerType));
    1428             :   }
    1429             : 
    1430             : #undef REPORT
    1431           0 : }
    1432             : 
    1433             : NS_IMETHODIMP
    1434           0 : MessageManagerReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
    1435             :                                        nsISupports* aData, bool aAnonymize)
    1436             : {
    1437           0 :   if (XRE_IsParentProcess()) {
    1438             :     nsCOMPtr<nsIMessageBroadcaster> globalmm =
    1439           0 :       do_GetService("@mozilla.org/globalmessagemanager;1");
    1440           0 :     if (globalmm) {
    1441             :       RefPtr<nsFrameMessageManager> mm =
    1442           0 :         static_cast<nsFrameMessageManager*>(globalmm.get());
    1443           0 :       MessageManagerReferentCount count;
    1444           0 :       CountReferents(mm, &count);
    1445           0 :       ReportReferentCount("global-manager", count, aHandleReport, aData);
    1446             :     }
    1447             :   }
    1448             : 
    1449           0 :   if (nsFrameMessageManager::sParentProcessManager) {
    1450           0 :     MessageManagerReferentCount count;
    1451           0 :     CountReferents(nsFrameMessageManager::sParentProcessManager, &count);
    1452           0 :     ReportReferentCount("parent-process-manager", count, aHandleReport, aData);
    1453             :   }
    1454             : 
    1455           0 :   if (nsFrameMessageManager::sChildProcessManager) {
    1456           0 :     MessageManagerReferentCount count;
    1457           0 :     CountReferents(nsFrameMessageManager::sChildProcessManager, &count);
    1458           0 :     ReportReferentCount("child-process-manager", count, aHandleReport, aData);
    1459             :   }
    1460             : 
    1461           0 :   return NS_OK;
    1462             : }
    1463             : 
    1464             : } // namespace dom
    1465             : } // namespace mozilla
    1466             : 
    1467             : nsresult
    1468           1 : NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult)
    1469             : {
    1470           1 :   NS_ENSURE_TRUE(XRE_IsParentProcess(),
    1471             :                  NS_ERROR_NOT_AVAILABLE);
    1472             :   RefPtr<nsFrameMessageManager> mm = new nsFrameMessageManager(nullptr,
    1473             :                                                                  nullptr,
    1474           2 :                                                                  MM_CHROME | MM_GLOBAL | MM_BROADCASTER);
    1475           1 :   RegisterStrongMemoryReporter(new MessageManagerReporter());
    1476           1 :   mm.forget(aResult);
    1477           1 :   return NS_OK;
    1478             : }
    1479             : 
    1480             : nsDataHashtable<nsStringHashKey, nsMessageManagerScriptHolder*>*
    1481             :   nsMessageManagerScriptExecutor::sCachedScripts = nullptr;
    1482           3 : StaticRefPtr<nsScriptCacheCleaner> nsMessageManagerScriptExecutor::sScriptCacheCleaner;
    1483             : 
    1484             : void
    1485           5 : nsMessageManagerScriptExecutor::DidCreateGlobal()
    1486             : {
    1487           5 :   NS_ASSERTION(mGlobal, "Should have mGlobal!");
    1488           5 :   if (!sCachedScripts) {
    1489           3 :     sCachedScripts =
    1490           3 :       new nsDataHashtable<nsStringHashKey, nsMessageManagerScriptHolder*>;
    1491           3 :     sScriptCacheCleaner = new nsScriptCacheCleaner();
    1492             :   }
    1493           5 : }
    1494             : 
    1495             : // static
    1496             : void
    1497           0 : nsMessageManagerScriptExecutor::PurgeCache()
    1498             : {
    1499           0 :   if (sCachedScripts) {
    1500           0 :     NS_ASSERTION(sCachedScripts != nullptr, "Need cached scripts");
    1501           0 :     for (auto iter = sCachedScripts->Iter(); !iter.Done(); iter.Next()) {
    1502           0 :       delete iter.Data();
    1503           0 :       iter.Remove();
    1504             :     }
    1505             :   }
    1506           0 : }
    1507             : 
    1508             : // static
    1509             : void
    1510           0 : nsMessageManagerScriptExecutor::Shutdown()
    1511             : {
    1512           0 :   if (sCachedScripts) {
    1513           0 :     PurgeCache();
    1514             : 
    1515           0 :     delete sCachedScripts;
    1516           0 :     sCachedScripts = nullptr;
    1517           0 :     sScriptCacheCleaner = nullptr;
    1518             :   }
    1519           0 : }
    1520             : 
    1521             : void
    1522          45 : nsMessageManagerScriptExecutor::LoadScriptInternal(const nsAString& aURL,
    1523             :                                                    bool aRunInGlobalScope)
    1524             : {
    1525          45 :   if (profiler_is_active()) {
    1526           0 :     NS_LossyConvertUTF16toASCII urlCStr(aURL);
    1527           0 :     AUTO_PROFILER_LABEL_DYNAMIC(
    1528             :       "nsMessageManagerScriptExecutor::LoadScriptInternal", OTHER,
    1529             :       urlCStr.get());
    1530             :   }
    1531             : 
    1532          45 :   if (!mGlobal || !sCachedScripts) {
    1533           0 :     return;
    1534             :   }
    1535             : 
    1536          45 :   JS::RootingContext* rcx = RootingCx();
    1537          90 :   JS::Rooted<JSScript*> script(rcx);
    1538             : 
    1539          45 :   nsMessageManagerScriptHolder* holder = sCachedScripts->Get(aURL);
    1540          45 :   if (holder && holder->WillRunInGlobalScope() == aRunInGlobalScope) {
    1541           0 :     script = holder->mScript;
    1542             :   } else {
    1543             :     // Don't put anything in the cache if we already have an entry
    1544             :     // with a different WillRunInGlobalScope() value.
    1545          45 :     bool shouldCache = !holder;
    1546          90 :     TryCacheLoadAndCompileScript(aURL, aRunInGlobalScope,
    1547          45 :                                  shouldCache, &script);
    1548             :   }
    1549             : 
    1550          90 :   JS::Rooted<JSObject*> global(rcx, mGlobal);
    1551          45 :   if (global) {
    1552          90 :     AutoEntryScript aes(global, "message manager script load");
    1553          45 :     JSContext* cx = aes.cx();
    1554          45 :     if (script) {
    1555          45 :       if (aRunInGlobalScope) {
    1556           0 :         JS::RootedValue rval(cx);
    1557           0 :         JS::CloneAndExecuteScript(cx, script, &rval);
    1558             :       } else {
    1559          90 :         JS::Rooted<JSObject*> scope(cx);
    1560          45 :         bool ok = js::ExecuteInGlobalAndReturnScope(cx, global, script, &scope);
    1561          45 :         if (ok) {
    1562             :           // Force the scope to stay alive.
    1563          45 :           mAnonymousGlobalScopes.AppendElement(scope);
    1564             :         }
    1565             :       }
    1566             :     }
    1567             :   }
    1568             : }
    1569             : 
    1570             : void
    1571          45 : nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
    1572             :   const nsAString& aURL,
    1573             :   bool aRunInGlobalScope,
    1574             :   bool aShouldCache,
    1575             :   JS::MutableHandle<JSScript*> aScriptp)
    1576             : {
    1577          90 :   nsCString url = NS_ConvertUTF16toUTF8(aURL);
    1578          90 :   nsCOMPtr<nsIURI> uri;
    1579          45 :   nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
    1580          45 :   if (NS_FAILED(rv)) {
    1581           0 :     return;
    1582             :   }
    1583             : 
    1584             :   bool hasFlags;
    1585          45 :   rv = NS_URIChainHasFlags(uri,
    1586             :                            nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
    1587          45 :                            &hasFlags);
    1588          45 :   if (NS_FAILED(rv) || !hasFlags) {
    1589           0 :     NS_WARNING("Will not load a frame script!");
    1590           0 :     return;
    1591             :   }
    1592             : 
    1593             :   // Compile the script in the compilation scope instead of the current global
    1594             :   // to avoid keeping the current compartment alive.
    1595          90 :   AutoJSAPI jsapi;
    1596          45 :   if (!jsapi.Init(xpc::CompilationScope())) {
    1597           0 :     return;
    1598             :   }
    1599          45 :   JSContext* cx = jsapi.cx();
    1600          90 :   JS::Rooted<JSScript*> script(cx);
    1601             : 
    1602          45 :   script = ScriptPreloader::GetChildSingleton().GetCachedScript(cx, url);
    1603             : 
    1604          45 :   if (!script) {
    1605          56 :     nsCOMPtr<nsIChannel> channel;
    1606          56 :     NS_NewChannel(getter_AddRefs(channel),
    1607             :                   uri,
    1608             :                   nsContentUtils::GetSystemPrincipal(),
    1609             :                   nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
    1610          28 :                   nsIContentPolicy::TYPE_OTHER);
    1611             : 
    1612          28 :     if (!channel) {
    1613           0 :       return;
    1614             :     }
    1615             : 
    1616          56 :     nsCOMPtr<nsIInputStream> input;
    1617          28 :     rv = channel->Open2(getter_AddRefs(input));
    1618          28 :     NS_ENSURE_SUCCESS_VOID(rv);
    1619          56 :     nsString dataString;
    1620          28 :     char16_t* dataStringBuf = nullptr;
    1621          28 :     size_t dataStringLength = 0;
    1622          28 :     uint64_t avail64 = 0;
    1623          28 :     if (input && NS_SUCCEEDED(input->Available(&avail64)) && avail64) {
    1624          28 :       if (avail64 > UINT32_MAX) {
    1625           0 :         return;
    1626             :       }
    1627          56 :       nsCString buffer;
    1628          28 :       uint32_t avail = (uint32_t)std::min(avail64, (uint64_t)UINT32_MAX);
    1629          28 :       if (NS_FAILED(NS_ReadInputStreamToString(input, buffer, avail))) {
    1630           0 :         return;
    1631             :       }
    1632          28 :       ScriptLoader::ConvertToUTF16(channel, (uint8_t*)buffer.get(), avail,
    1633          28 :                                    EmptyString(), nullptr,
    1634          28 :                                    dataStringBuf, dataStringLength);
    1635             :     }
    1636             : 
    1637             :     JS::SourceBufferHolder srcBuf(dataStringBuf, dataStringLength,
    1638          56 :                                   JS::SourceBufferHolder::GiveOwnership);
    1639             : 
    1640          28 :     if (!dataStringBuf || dataStringLength == 0) {
    1641           0 :       return;
    1642             :     }
    1643             : 
    1644          56 :     JS::CompileOptions options(cx, JSVERSION_LATEST);
    1645          28 :     options.setFileAndLine(url.get(), 1);
    1646          28 :     options.setNoScriptRval(true);
    1647             : 
    1648          28 :     if (aRunInGlobalScope) {
    1649           0 :       if (!JS::Compile(cx, options, srcBuf, &script)) {
    1650           0 :         return;
    1651             :       }
    1652             :     // We're going to run these against some non-global scope.
    1653          28 :     } else if (!JS::CompileForNonSyntacticScope(cx, options, srcBuf, &script)) {
    1654           0 :       return;
    1655             :     }
    1656             :   }
    1657             : 
    1658          45 :   MOZ_ASSERT(script);
    1659          45 :   aScriptp.set(script);
    1660             : 
    1661          90 :   nsAutoCString scheme;
    1662          45 :   uri->GetScheme(scheme);
    1663             :   // We don't cache data: scripts!
    1664          45 :   if (aShouldCache && !scheme.EqualsLiteral("data")) {
    1665          39 :     ScriptPreloader::GetChildSingleton().NoteScript(url, url, script);
    1666             :     // Root the object also for caching.
    1667          78 :     auto* holder = new nsMessageManagerScriptHolder(cx, script, aRunInGlobalScope);
    1668          39 :     sCachedScripts->Put(aURL, holder);
    1669             :   }
    1670             : }
    1671             : 
    1672             : void
    1673           0 : nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
    1674             :   const nsAString& aURL,
    1675             :   bool aRunInGlobalScope)
    1676             : {
    1677           0 :   JS::Rooted<JSScript*> script(RootingCx());
    1678           0 :   TryCacheLoadAndCompileScript(aURL, aRunInGlobalScope, true, &script);
    1679           0 : }
    1680             : 
    1681             : void
    1682           3 : nsMessageManagerScriptExecutor::Trace(const TraceCallbacks& aCallbacks, void* aClosure)
    1683             : {
    1684          27 :   for (size_t i = 0, length = mAnonymousGlobalScopes.Length(); i < length; ++i) {
    1685          24 :     aCallbacks.Trace(&mAnonymousGlobalScopes[i], "mAnonymousGlobalScopes[i]", aClosure);
    1686             :   }
    1687           3 :   aCallbacks.Trace(&mGlobal, "mGlobal", aClosure);
    1688           3 : }
    1689             : 
    1690             : void
    1691           0 : nsMessageManagerScriptExecutor::Unlink()
    1692             : {
    1693           0 :   ImplCycleCollectionUnlink(mAnonymousGlobalScopes);
    1694           0 :   mGlobal = nullptr;
    1695           0 : }
    1696             : 
    1697             : bool
    1698           5 : nsMessageManagerScriptExecutor::InitChildGlobalInternal(
    1699             :   nsISupports* aScope,
    1700             :   const nsACString& aID)
    1701             : {
    1702          10 :   AutoSafeJSContext cx;
    1703           5 :   nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
    1704             : 
    1705           5 :   nsIXPConnect* xpc = nsContentUtils::XPConnect();
    1706           5 :   const uint32_t flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES;
    1707             : 
    1708           5 :   JS::CompartmentOptions options;
    1709           5 :   options.creationOptions().setSystemZone();
    1710           5 :   options.behaviors().setVersion(JSVERSION_LATEST);
    1711             : 
    1712           5 :   if (xpc::SharedMemoryEnabled()) {
    1713           5 :     options.creationOptions().setSharedMemoryAndAtomicsEnabled(true);
    1714             :   }
    1715             : 
    1716          10 :   nsCOMPtr<nsIXPConnectJSObjectHolder> globalHolder;
    1717             :   nsresult rv =
    1718           5 :     xpc->InitClassesWithNewWrappedGlobal(cx, aScope, mPrincipal,
    1719             :                                          flags, options,
    1720          10 :                                          getter_AddRefs(globalHolder));
    1721           5 :   NS_ENSURE_SUCCESS(rv, false);
    1722             : 
    1723           5 :   mGlobal = globalHolder->GetJSObject();
    1724           5 :   NS_ENSURE_TRUE(mGlobal, false);
    1725             : 
    1726             :   // Set the location information for the new global, so that tools like
    1727             :   // about:memory may use that information.
    1728           5 :   xpc::SetLocationForGlobal(mGlobal, aID);
    1729             : 
    1730           5 :   DidCreateGlobal();
    1731           5 :   return true;
    1732             : }
    1733             : 
    1734             : void
    1735           0 : nsMessageManagerScriptExecutor::MarkScopesForCC()
    1736             : {
    1737           0 :   for (uint32_t i = 0; i < mAnonymousGlobalScopes.Length(); ++i) {
    1738           0 :     mAnonymousGlobalScopes[i].exposeToActiveJS();
    1739             :   }
    1740           0 : }
    1741             : 
    1742           9 : NS_IMPL_ISUPPORTS(nsScriptCacheCleaner, nsIObserver)
    1743             : 
    1744             : nsFrameMessageManager* nsFrameMessageManager::sChildProcessManager = nullptr;
    1745             : nsFrameMessageManager* nsFrameMessageManager::sParentProcessManager = nullptr;
    1746             : nsFrameMessageManager* nsFrameMessageManager::sSameProcessParentManager = nullptr;
    1747             : 
    1748          12 : class nsAsyncMessageToSameProcessChild : public nsSameProcessAsyncMessageBase,
    1749             :                                          public Runnable
    1750             : {
    1751             : public:
    1752           4 :   nsAsyncMessageToSameProcessChild(JS::RootingContext* aRootingCx,
    1753             :                                    JS::Handle<JSObject*> aCpows)
    1754           4 :     : nsSameProcessAsyncMessageBase(aRootingCx, aCpows)
    1755           4 :     , mozilla::Runnable("nsAsyncMessageToSameProcessChild")
    1756           4 :   { }
    1757           4 :   NS_IMETHOD Run() override
    1758             :   {
    1759           4 :     nsFrameMessageManager* ppm = nsFrameMessageManager::GetChildProcessManager();
    1760           4 :     ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm), nullptr, ppm);
    1761           4 :     return NS_OK;
    1762             :   }
    1763             : };
    1764             : 
    1765             : 
    1766             : /**
    1767             :  * Send messages to an imaginary child process in a single-process scenario.
    1768             :  */
    1769             : class SameParentProcessMessageManagerCallback : public MessageManagerCallback
    1770             : {
    1771             : public:
    1772           1 :   SameParentProcessMessageManagerCallback()
    1773           1 :   {
    1774           1 :     MOZ_COUNT_CTOR(SameParentProcessMessageManagerCallback);
    1775           1 :   }
    1776           0 :   ~SameParentProcessMessageManagerCallback() override
    1777           0 :   {
    1778           0 :     MOZ_COUNT_DTOR(SameParentProcessMessageManagerCallback);
    1779           0 :   }
    1780             : 
    1781           9 :   bool DoLoadMessageManagerScript(const nsAString& aURL,
    1782             :                                   bool aRunInGlobalScope) override
    1783             :   {
    1784           9 :     ProcessGlobal* global = ProcessGlobal::Get();
    1785           9 :     MOZ_ASSERT(!aRunInGlobalScope);
    1786           9 :     global->LoadScript(aURL);
    1787           9 :     return true;
    1788             :   }
    1789             : 
    1790           4 :   nsresult DoSendAsyncMessage(JSContext* aCx,
    1791             :                               const nsAString& aMessage,
    1792             :                               StructuredCloneData& aData,
    1793             :                               JS::Handle<JSObject *> aCpows,
    1794             :                               nsIPrincipal* aPrincipal) override
    1795             :   {
    1796           4 :     JS::RootingContext* rcx = JS::RootingContext::get(aCx);
    1797             :     RefPtr<nsAsyncMessageToSameProcessChild> ev =
    1798          12 :       new nsAsyncMessageToSameProcessChild(rcx, aCpows);
    1799             : 
    1800           4 :     nsresult rv = ev->Init(aMessage, aData, aPrincipal);
    1801           4 :     if (NS_FAILED(rv)) {
    1802           0 :       return rv;
    1803             :     }
    1804           4 :     rv = NS_DispatchToCurrentThread(ev);
    1805           4 :     if (NS_FAILED(rv)) {
    1806           0 :       return rv;
    1807             :     }
    1808           4 :     return NS_OK;
    1809             :   }
    1810             : };
    1811             : 
    1812             : 
    1813             : /**
    1814             :  * Send messages to the parent process.
    1815             :  */
    1816             : class ChildProcessMessageManagerCallback : public MessageManagerCallback
    1817             : {
    1818             : public:
    1819           2 :   ChildProcessMessageManagerCallback()
    1820           2 :   {
    1821           2 :     MOZ_COUNT_CTOR(ChildProcessMessageManagerCallback);
    1822           2 :   }
    1823           0 :   ~ChildProcessMessageManagerCallback() override
    1824           0 :   {
    1825           0 :     MOZ_COUNT_DTOR(ChildProcessMessageManagerCallback);
    1826           0 :   }
    1827             : 
    1828           0 :   bool DoSendBlockingMessage(JSContext* aCx,
    1829             :                              const nsAString& aMessage,
    1830             :                              StructuredCloneData& aData,
    1831             :                              JS::Handle<JSObject *> aCpows,
    1832             :                              nsIPrincipal* aPrincipal,
    1833             :                              nsTArray<StructuredCloneData>* aRetVal,
    1834             :                              bool aIsSync) override
    1835             :   {
    1836             :     mozilla::dom::ContentChild* cc =
    1837           0 :       mozilla::dom::ContentChild::GetSingleton();
    1838           0 :     if (!cc) {
    1839           0 :       return true;
    1840             :     }
    1841           0 :     ClonedMessageData data;
    1842           0 :     if (!BuildClonedMessageDataForChild(cc, aData, data)) {
    1843           0 :       return false;
    1844             :     }
    1845           0 :     InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
    1846           0 :     if (aCpows && !cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
    1847           0 :       return false;
    1848             :     }
    1849           0 :     if (aIsSync) {
    1850           0 :       return cc->SendSyncMessage(PromiseFlatString(aMessage), data, cpows,
    1851           0 :                                  IPC::Principal(aPrincipal), aRetVal);
    1852             :     }
    1853           0 :     return cc->SendRpcMessage(PromiseFlatString(aMessage), data, cpows,
    1854           0 :                               IPC::Principal(aPrincipal), aRetVal);
    1855             :   }
    1856             : 
    1857           4 :   nsresult DoSendAsyncMessage(JSContext* aCx,
    1858             :                               const nsAString& aMessage,
    1859             :                               StructuredCloneData& aData,
    1860             :                               JS::Handle<JSObject *> aCpows,
    1861             :                               nsIPrincipal* aPrincipal) override
    1862             :   {
    1863             :     mozilla::dom::ContentChild* cc =
    1864           4 :       mozilla::dom::ContentChild::GetSingleton();
    1865           4 :     if (!cc) {
    1866           0 :       return NS_OK;
    1867             :     }
    1868           8 :     ClonedMessageData data;
    1869           4 :     if (!BuildClonedMessageDataForChild(cc, aData, data)) {
    1870           0 :       return NS_ERROR_DOM_DATA_CLONE_ERR;
    1871             :     }
    1872           8 :     InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
    1873           4 :     if (aCpows && !cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
    1874           0 :       return NS_ERROR_UNEXPECTED;
    1875             :     }
    1876           8 :     if (!cc->SendAsyncMessage(PromiseFlatString(aMessage), cpows,
    1877           8 :                               IPC::Principal(aPrincipal), data)) {
    1878           0 :       return NS_ERROR_UNEXPECTED;
    1879             :     }
    1880             : 
    1881           4 :     return NS_OK;
    1882             :   }
    1883             : };
    1884             : 
    1885             : 
    1886           3 : class nsAsyncMessageToSameProcessParent : public nsSameProcessAsyncMessageBase,
    1887             :                                           public SameProcessMessageQueue::Runnable
    1888             : {
    1889             : public:
    1890           1 :   nsAsyncMessageToSameProcessParent(JS::RootingContext* aRootingCx,
    1891             :                                     JS::Handle<JSObject*> aCpows)
    1892           1 :     : nsSameProcessAsyncMessageBase(aRootingCx, aCpows)
    1893           1 :   { }
    1894           1 :   nsresult HandleMessage() override
    1895             :   {
    1896           1 :     nsFrameMessageManager* ppm = nsFrameMessageManager::sSameProcessParentManager;
    1897           1 :     ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm), nullptr, ppm);
    1898           1 :     return NS_OK;
    1899             :   }
    1900             : };
    1901             : 
    1902             : /**
    1903             :  * Send messages to the imaginary parent process in a single-process scenario.
    1904             :  */
    1905             : class SameChildProcessMessageManagerCallback : public MessageManagerCallback
    1906             : {
    1907             : public:
    1908           1 :   SameChildProcessMessageManagerCallback()
    1909           1 :   {
    1910           1 :     MOZ_COUNT_CTOR(SameChildProcessMessageManagerCallback);
    1911           1 :   }
    1912           0 :   ~SameChildProcessMessageManagerCallback() override
    1913           0 :   {
    1914           0 :     MOZ_COUNT_DTOR(SameChildProcessMessageManagerCallback);
    1915           0 :   }
    1916             : 
    1917           0 :   bool DoSendBlockingMessage(JSContext* aCx,
    1918             :                              const nsAString& aMessage,
    1919             :                              StructuredCloneData& aData,
    1920             :                              JS::Handle<JSObject *> aCpows,
    1921             :                              nsIPrincipal* aPrincipal,
    1922             :                              nsTArray<StructuredCloneData>* aRetVal,
    1923             :                              bool aIsSync) override
    1924             :   {
    1925           0 :     SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
    1926           0 :     queue->Flush();
    1927             : 
    1928           0 :     if (nsFrameMessageManager::sSameProcessParentManager) {
    1929           0 :       SameProcessCpowHolder cpows(JS::RootingContext::get(aCx), aCpows);
    1930           0 :       RefPtr<nsFrameMessageManager> ppm = nsFrameMessageManager::sSameProcessParentManager;
    1931           0 :       ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()), nullptr, aMessage,
    1932           0 :                           true, &aData, &cpows, aPrincipal, aRetVal);
    1933             :     }
    1934           0 :     return true;
    1935             :   }
    1936             : 
    1937           1 :   nsresult DoSendAsyncMessage(JSContext* aCx,
    1938             :                               const nsAString& aMessage,
    1939             :                               StructuredCloneData& aData,
    1940             :                               JS::Handle<JSObject *> aCpows,
    1941             :                               nsIPrincipal* aPrincipal) override
    1942             :   {
    1943           1 :     SameProcessMessageQueue* queue = SameProcessMessageQueue::Get();
    1944           1 :     JS::RootingContext* rcx = JS::RootingContext::get(aCx);
    1945             :     RefPtr<nsAsyncMessageToSameProcessParent> ev =
    1946           3 :       new nsAsyncMessageToSameProcessParent(rcx, aCpows);
    1947           1 :     nsresult rv = ev->Init(aMessage, aData, aPrincipal);
    1948             : 
    1949           1 :     if (NS_FAILED(rv)) {
    1950           0 :       return rv;
    1951             :     }
    1952           1 :     queue->Push(ev);
    1953           1 :     return NS_OK;
    1954             :   }
    1955             : 
    1956             : };
    1957             : 
    1958             : 
    1959             : // This creates the global parent process message manager.
    1960             : nsresult
    1961           1 : NS_NewParentProcessMessageManager(nsIMessageBroadcaster** aResult)
    1962             : {
    1963           1 :   NS_ASSERTION(!nsFrameMessageManager::sParentProcessManager,
    1964             :                "Re-creating sParentProcessManager");
    1965             :   RefPtr<nsFrameMessageManager> mm = new nsFrameMessageManager(nullptr,
    1966             :                                                                  nullptr,
    1967           2 :                                                                  MM_CHROME | MM_PROCESSMANAGER | MM_BROADCASTER);
    1968           1 :   nsFrameMessageManager::sParentProcessManager = mm;
    1969           1 :   nsFrameMessageManager::NewProcessMessageManager(false); // Create same process message manager.
    1970           1 :   mm.forget(aResult);
    1971           2 :   return NS_OK;
    1972             : }
    1973             : 
    1974             : 
    1975             : nsFrameMessageManager*
    1976           3 : nsFrameMessageManager::NewProcessMessageManager(bool aIsRemote)
    1977             : {
    1978           3 :   if (!nsFrameMessageManager::sParentProcessManager) {
    1979             :      nsCOMPtr<nsIMessageBroadcaster> dummy =
    1980           0 :        do_GetService("@mozilla.org/parentprocessmessagemanager;1");
    1981             :   }
    1982             : 
    1983           3 :   MOZ_ASSERT(nsFrameMessageManager::sParentProcessManager,
    1984             :              "parent process manager not created");
    1985             :   nsFrameMessageManager* mm;
    1986           3 :   if (aIsRemote) {
    1987             :     // Callback is set in ContentParent::InitInternal so that the process has
    1988             :     // already started when we send pending scripts.
    1989           2 :     mm = new nsFrameMessageManager(nullptr,
    1990             :                                    nsFrameMessageManager::sParentProcessManager,
    1991           2 :                                    MM_CHROME | MM_PROCESSMANAGER);
    1992             :   } else {
    1993           2 :     mm = new nsFrameMessageManager(new SameParentProcessMessageManagerCallback(),
    1994             :                                    nsFrameMessageManager::sParentProcessManager,
    1995           1 :                                    MM_CHROME | MM_PROCESSMANAGER | MM_OWNSCALLBACK);
    1996           1 :     sSameProcessParentManager = mm;
    1997             :   }
    1998           3 :   return mm;
    1999             : }
    2000             : 
    2001             : nsresult
    2002           3 : NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
    2003             : {
    2004           3 :   NS_ASSERTION(!nsFrameMessageManager::GetChildProcessManager(),
    2005             :                "Re-creating sChildProcessManager");
    2006             : 
    2007             :   MessageManagerCallback* cb;
    2008           3 :   if (XRE_IsParentProcess()) {
    2009           1 :     cb = new SameChildProcessMessageManagerCallback();
    2010             :   } else {
    2011           2 :     cb = new ChildProcessMessageManagerCallback();
    2012           2 :     RegisterStrongMemoryReporter(new MessageManagerReporter());
    2013             :   }
    2014             :   auto* mm = new nsFrameMessageManager(cb, nullptr,
    2015           3 :                                        MM_PROCESSMANAGER | MM_OWNSCALLBACK);
    2016           3 :   nsFrameMessageManager::SetChildProcessManager(mm);
    2017           6 :   RefPtr<ProcessGlobal> global = new ProcessGlobal(mm);
    2018           3 :   NS_ENSURE_TRUE(global->Init(), NS_ERROR_UNEXPECTED);
    2019           3 :   global.forget(aResult);
    2020           3 :   return NS_OK;
    2021             : }
    2022             : 
    2023             : bool
    2024           0 : nsFrameMessageManager::MarkForCC()
    2025             : {
    2026           0 :   for (auto iter = mListeners.Iter(); !iter.Done(); iter.Next()) {
    2027           0 :     nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners = iter.UserData();
    2028           0 :     uint32_t count = listeners->Length();
    2029           0 :     for (uint32_t i = 0; i < count; i++) {
    2030             :       nsCOMPtr<nsIMessageListener> strongListener =
    2031           0 :         listeners->ElementAt(i).mStrongListener;
    2032           0 :       if (strongListener) {
    2033           0 :         xpc_TryUnmarkWrappedGrayObject(strongListener);
    2034             :       }
    2035             :     }
    2036             :   }
    2037             : 
    2038           0 :   if (mRefCnt.IsPurple()) {
    2039           0 :     mRefCnt.RemovePurple();
    2040             :   }
    2041           0 :   return true;
    2042             : }
    2043             : 
    2044           5 : nsSameProcessAsyncMessageBase::nsSameProcessAsyncMessageBase(JS::RootingContext* aRootingCx,
    2045           5 :                                                              JS::Handle<JSObject*> aCpows)
    2046             :   : mCpows(aRootingCx, aCpows)
    2047             : #ifdef DEBUG
    2048           5 :   , mCalledInit(false)
    2049             : #endif
    2050           5 : { }
    2051             : 
    2052             : 
    2053             : nsresult
    2054           5 : nsSameProcessAsyncMessageBase::Init(const nsAString& aMessage,
    2055             :                                     StructuredCloneData& aData,
    2056             :                                     nsIPrincipal* aPrincipal)
    2057             : {
    2058           5 :   if (!mData.Copy(aData)) {
    2059           0 :     Telemetry::Accumulate(Telemetry::IPC_SAME_PROCESS_MESSAGE_COPY_OOM_KB, aData.DataLength());
    2060           0 :     return NS_ERROR_OUT_OF_MEMORY;
    2061             :   }
    2062             : 
    2063           5 :   mMessage = aMessage;
    2064           5 :   mPrincipal = aPrincipal;
    2065             : #ifdef DEBUG
    2066           5 :   mCalledInit = true;
    2067             : #endif
    2068             : 
    2069           5 :   return NS_OK;
    2070             : }
    2071             : 
    2072             : void
    2073           5 : nsSameProcessAsyncMessageBase::ReceiveMessage(nsISupports* aTarget,
    2074             :                                               nsIFrameLoader* aTargetFrameLoader,
    2075             :                                               nsFrameMessageManager* aManager)
    2076             : {
    2077             :   // Make sure that we have called Init() and it has succeeded.
    2078           5 :   MOZ_ASSERT(mCalledInit);
    2079           5 :   if (aManager) {
    2080          10 :     SameProcessCpowHolder cpows(RootingCx(), mCpows);
    2081             : 
    2082          10 :     RefPtr<nsFrameMessageManager> mm = aManager;
    2083           5 :     mm->ReceiveMessage(aTarget, aTargetFrameLoader, mMessage, false, &mData,
    2084           5 :                        &cpows, mPrincipal, nullptr);
    2085             :   }
    2086          14 : }

Generated by: LCOV version 1.13