LCOV - code coverage report
Current view: top level - dom/base - nsFrameMessageManager.h (source / functions) Hit Total Coverage
Test: output.info Lines: 32 55 58.2 %
Date: 2017-07-14 16:53:18 Functions: 19 35 54.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             : #ifndef nsFrameMessageManager_h__
       8             : #define nsFrameMessageManager_h__
       9             : 
      10             : #include "nsIMessageManager.h"
      11             : #include "nsIObserver.h"
      12             : #include "nsCOMPtr.h"
      13             : #include "nsAutoPtr.h"
      14             : #include "nsCOMArray.h"
      15             : #include "nsTArray.h"
      16             : #include "nsIAtom.h"
      17             : #include "nsCycleCollectionParticipant.h"
      18             : #include "nsTArray.h"
      19             : #include "nsIPrincipal.h"
      20             : #include "nsIXPConnect.h"
      21             : #include "nsDataHashtable.h"
      22             : #include "nsClassHashtable.h"
      23             : #include "mozilla/Services.h"
      24             : #include "mozilla/StaticPtr.h"
      25             : #include "nsIObserverService.h"
      26             : #include "nsThreadUtils.h"
      27             : #include "nsWeakPtr.h"
      28             : #include "mozilla/Attributes.h"
      29             : #include "js/RootingAPI.h"
      30             : #include "nsTObserverArray.h"
      31             : #include "mozilla/dom/SameProcessMessageQueue.h"
      32             : #include "mozilla/dom/ipc/StructuredCloneData.h"
      33             : #include "mozilla/jsipc/CpowHolder.h"
      34             : 
      35             : class nsIFrameLoader;
      36             : 
      37             : namespace mozilla {
      38             : namespace dom {
      39             : 
      40             : class nsIContentParent;
      41             : class nsIContentChild;
      42             : class ClonedMessageData;
      43             : class MessageManagerReporter;
      44             : 
      45             : namespace ipc {
      46             : 
      47             : // Note: we round the time we spend to the nearest millisecond. So a min value
      48             : // of 1 ms actually captures from 500us and above.
      49             : static const uint32_t kMinTelemetrySyncMessageManagerLatencyMs = 1;
      50             : 
      51             : enum MessageManagerFlags {
      52             :   MM_CHILD = 0,
      53             :   MM_CHROME = 1,
      54             :   MM_GLOBAL = 2,
      55             :   MM_PROCESSMANAGER = 4,
      56             :   MM_BROADCASTER = 8,
      57             :   MM_OWNSCALLBACK = 16
      58             : };
      59             : 
      60          15 : class MessageManagerCallback
      61             : {
      62             : public:
      63           0 :   virtual ~MessageManagerCallback() {}
      64             : 
      65           0 :   virtual bool DoLoadMessageManagerScript(const nsAString& aURL, bool aRunInGlobalScope)
      66             :   {
      67           0 :     return true;
      68             :   }
      69             : 
      70           0 :   virtual bool DoSendBlockingMessage(JSContext* aCx,
      71             :                                      const nsAString& aMessage,
      72             :                                      StructuredCloneData& aData,
      73             :                                      JS::Handle<JSObject*> aCpows,
      74             :                                      nsIPrincipal* aPrincipal,
      75             :                                      nsTArray<StructuredCloneData>* aRetVal,
      76             :                                      bool aIsSync)
      77             :   {
      78           0 :     return true;
      79             :   }
      80             : 
      81           0 :   virtual nsresult DoSendAsyncMessage(JSContext* aCx,
      82             :                                       const nsAString& aMessage,
      83             :                                       StructuredCloneData& aData,
      84             :                                       JS::Handle<JSObject*> aCpows,
      85             :                                       nsIPrincipal* aPrincipal)
      86             :   {
      87           0 :     return NS_OK;
      88             :   }
      89             : 
      90           0 :   virtual nsIMessageSender* GetProcessMessageManager() const
      91             :   {
      92           0 :     return nullptr;
      93             :   }
      94             : 
      95             : protected:
      96             :   bool BuildClonedMessageDataForParent(nsIContentParent* aParent,
      97             :                                        StructuredCloneData& aData,
      98             :                                        ClonedMessageData& aClonedData);
      99             :   bool BuildClonedMessageDataForChild(nsIContentChild* aChild,
     100             :                                       StructuredCloneData& aData,
     101             :                                       ClonedMessageData& aClonedData);
     102             : };
     103             : 
     104             : void UnpackClonedMessageDataForParent(const ClonedMessageData& aClonedData,
     105             :                                       StructuredCloneData& aData);
     106             : 
     107             : void UnpackClonedMessageDataForChild(const ClonedMessageData& aClonedData,
     108             :                                      StructuredCloneData& aData);
     109             : 
     110             : } // namespace ipc
     111             : } // namespace dom
     112             : } // namespace mozilla
     113             : 
     114         398 : struct nsMessageListenerInfo
     115             : {
     116           0 :   bool operator==(const nsMessageListenerInfo& aOther) const
     117             :   {
     118           0 :     return &aOther == this;
     119             :   }
     120             : 
     121             :   // Exactly one of mStrongListener and mWeakListener must be non-null.
     122             :   nsCOMPtr<nsIMessageListener> mStrongListener;
     123             :   nsWeakPtr mWeakListener;
     124             :   bool mListenWhenClosed;
     125             : };
     126             : 
     127             : 
     128           5 : class MOZ_STACK_CLASS SameProcessCpowHolder : public mozilla::jsipc::CpowHolder
     129             : {
     130             : public:
     131           5 :   SameProcessCpowHolder(JS::RootingContext* aRootingCx, JS::Handle<JSObject*> aObj)
     132           5 :     : mObj(aRootingCx, aObj)
     133             :   {
     134           5 :   }
     135             : 
     136             :   virtual bool ToObject(JSContext* aCx, JS::MutableHandle<JSObject*> aObjp)
     137             :     override;
     138             : 
     139             : private:
     140             :   JS::Rooted<JSObject*> mObj;
     141             : };
     142             : 
     143             : class nsFrameMessageManager final : public nsIContentFrameMessageManager,
     144             :                                     public nsIMessageBroadcaster,
     145             :                                     public nsIFrameScriptLoader,
     146             :                                     public nsIGlobalProcessScriptLoader
     147             : {
     148             :   friend class mozilla::dom::MessageManagerReporter;
     149             :   typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData;
     150             : public:
     151             :   nsFrameMessageManager(mozilla::dom::ipc::MessageManagerCallback* aCallback,
     152             :                         nsFrameMessageManager* aParentManager,
     153             :                         /* mozilla::dom::ipc::MessageManagerFlags */ uint32_t aFlags);
     154             : 
     155             : private:
     156             :   ~nsFrameMessageManager();
     157             : 
     158             : public:
     159             :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     160        1513 :   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsFrameMessageManager,
     161             :                                                          nsIContentFrameMessageManager)
     162             :   NS_DECL_NSIMESSAGELISTENERMANAGER
     163             :   NS_DECL_NSIMESSAGESENDER
     164             :   NS_DECL_NSIMESSAGEBROADCASTER
     165             :   NS_DECL_NSISYNCMESSAGESENDER
     166             :   NS_DECL_NSIMESSAGEMANAGERGLOBAL
     167             :   NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
     168             :   NS_DECL_NSIFRAMESCRIPTLOADER
     169             :   NS_DECL_NSIPROCESSSCRIPTLOADER
     170             :   NS_DECL_NSIGLOBALPROCESSSCRIPTLOADER
     171             : 
     172             :   static nsFrameMessageManager*
     173             :   NewProcessMessageManager(bool aIsRemote);
     174             : 
     175             :   nsresult ReceiveMessage(nsISupports* aTarget, nsIFrameLoader* aTargetFrameLoader,
     176             :                           const nsAString& aMessage,
     177             :                           bool aIsSync, StructuredCloneData* aCloneData,
     178             :                           mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal,
     179             :                           nsTArray<StructuredCloneData>* aRetVal);
     180             : 
     181             :   void AddChildManager(nsFrameMessageManager* aManager);
     182           1 :   void RemoveChildManager(nsFrameMessageManager* aManager)
     183             :   {
     184           1 :     mChildManagers.RemoveObject(aManager);
     185           1 :   }
     186             :   void Disconnect(bool aRemoveFromParent = true);
     187             :   void Close();
     188             : 
     189             :   void InitWithCallback(mozilla::dom::ipc::MessageManagerCallback* aCallback);
     190             :   void SetCallback(mozilla::dom::ipc::MessageManagerCallback* aCallback);
     191             : 
     192           2 :   mozilla::dom::ipc::MessageManagerCallback* GetCallback()
     193             :   {
     194           2 :     return mCallback;
     195             :   }
     196             : 
     197             :   nsresult DispatchAsyncMessage(const nsAString& aMessageName,
     198             :                                 const JS::Value& aJSON,
     199             :                                 const JS::Value& aObjects,
     200             :                                 nsIPrincipal* aPrincipal,
     201             :                                 const JS::Value& aTransfers,
     202             :                                 JSContext* aCx,
     203             :                                 uint8_t aArgc);
     204             : 
     205             :   nsresult DispatchAsyncMessageInternal(JSContext* aCx,
     206             :                                         const nsAString& aMessage,
     207             :                                         StructuredCloneData& aData,
     208             :                                         JS::Handle<JSObject*> aCpows,
     209             :                                         nsIPrincipal* aPrincipal);
     210             :   void RemoveFromParent();
     211             :   nsFrameMessageManager* GetParentManager() { return mParentManager; }
     212             :   void SetParentManager(nsFrameMessageManager* aParent)
     213             :   {
     214             :     NS_ASSERTION(!mParentManager, "We have parent manager already!");
     215             :     NS_ASSERTION(mChrome, "Should not set parent manager!");
     216             :     mParentManager = aParent;
     217             :   }
     218           0 :   bool IsGlobal() { return mGlobal; }
     219          15 :   bool IsBroadcaster() { return mIsBroadcaster; }
     220             : 
     221             :   static nsFrameMessageManager* GetParentProcessManager()
     222             :   {
     223             :     return sParentProcessManager;
     224             :   }
     225          10 :   static nsFrameMessageManager* GetChildProcessManager()
     226             :   {
     227          10 :     return sChildProcessManager;
     228             :   }
     229           3 :   static void SetChildProcessManager(nsFrameMessageManager* aManager)
     230             :   {
     231           3 :     sChildProcessManager = aManager;
     232           3 :   }
     233             : 
     234             :   void SetInitialProcessData(JS::HandleValue aInitialData);
     235             : 
     236             :   void LoadPendingScripts();
     237             : 
     238             : private:
     239             :   nsresult SendMessage(const nsAString& aMessageName,
     240             :                        JS::Handle<JS::Value> aJSON,
     241             :                        JS::Handle<JS::Value> aObjects,
     242             :                        nsIPrincipal* aPrincipal,
     243             :                        JSContext* aCx,
     244             :                        uint8_t aArgc,
     245             :                        JS::MutableHandle<JS::Value> aRetval,
     246             :                        bool aIsSync);
     247             : 
     248             :   nsresult ReceiveMessage(nsISupports* aTarget, nsIFrameLoader* aTargetFrameLoader,
     249             :                           bool aTargetClosed, const nsAString& aMessage,
     250             :                           bool aIsSync, StructuredCloneData* aCloneData,
     251             :                           mozilla::jsipc::CpowHolder* aCpows, nsIPrincipal* aPrincipal,
     252             :                           nsTArray<StructuredCloneData>* aRetVal);
     253             : 
     254             :   NS_IMETHOD LoadScript(const nsAString& aURL,
     255             :                         bool aAllowDelayedLoad,
     256             :                         bool aRunInGlobalScope);
     257             :   NS_IMETHOD RemoveDelayedScript(const nsAString& aURL);
     258             :   NS_IMETHOD GetDelayedScripts(JSContext* aCx, JS::MutableHandle<JS::Value> aList);
     259             : 
     260             : protected:
     261             :   friend class MMListenerRemover;
     262             :   // We keep the message listeners as arrays in a hastable indexed by the
     263             :   // message name. That gives us fast lookups in ReceiveMessage().
     264             :   nsClassHashtable<nsStringHashKey,
     265             :                    nsAutoTObserverArray<nsMessageListenerInfo, 1>> mListeners;
     266             :   nsCOMArray<nsIContentFrameMessageManager> mChildManagers;
     267             :   bool mChrome;     // true if we're in the chrome process
     268             :   bool mGlobal;     // true if we're the global frame message manager
     269             :   bool mIsProcessManager; // true if the message manager belongs to the process realm
     270             :   bool mIsBroadcaster; // true if the message manager is a broadcaster
     271             :   bool mOwnsCallback;
     272             :   bool mHandlingMessage;
     273             :   bool mClosed;    // true if we can no longer send messages
     274             :   bool mDisconnected;
     275             :   mozilla::dom::ipc::MessageManagerCallback* mCallback;
     276             :   nsAutoPtr<mozilla::dom::ipc::MessageManagerCallback> mOwnedCallback;
     277             :   RefPtr<nsFrameMessageManager> mParentManager;
     278             :   nsTArray<nsString> mPendingScripts;
     279             :   nsTArray<bool> mPendingScriptsGlobalStates;
     280             :   JS::Heap<JS::Value> mInitialProcessData;
     281             : 
     282             :   void LoadPendingScripts(nsFrameMessageManager* aManager,
     283             :                           nsFrameMessageManager* aChildMM);
     284             : public:
     285             :   static nsFrameMessageManager* sParentProcessManager;
     286             :   static nsFrameMessageManager* sSameProcessParentManager;
     287             :   static nsTArray<nsCOMPtr<nsIRunnable> >* sPendingSameProcessAsyncMessages;
     288             : private:
     289             :   static nsFrameMessageManager* sChildProcessManager;
     290             :   enum ProcessCheckerType {
     291             :     PROCESS_CHECKER_PERMISSION,
     292             :     PROCESS_CHECKER_MANIFEST_URL,
     293             :     ASSERT_APP_HAS_PERMISSION
     294             :   };
     295             :   nsresult AssertProcessInternal(ProcessCheckerType aType,
     296             :                                  const nsAString& aCapability,
     297             :                                  bool* aValid);
     298             : };
     299             : 
     300             : /* A helper class for taking care of many details for async message sending
     301             :    within a single process.  Intended to be used like so:
     302             : 
     303             :    class MyAsyncMessage : public nsSameProcessAsyncMessageBase, public Runnable
     304             :    {
     305             :      NS_IMETHOD Run() override {
     306             :        ReceiveMessage(..., ...);
     307             :        return NS_OK;
     308             :      }
     309             :    };
     310             : 
     311             : 
     312             :    RefPtr<nsSameProcessAsyncMessageBase> ev = new MyAsyncMessage();
     313             :    nsresult rv = ev->Init(...);
     314             :    if (NS_SUCCEEDED(rv)) {
     315             :      NS_DispatchToMainThread(ev);
     316             :    }
     317             : */
     318           5 : class nsSameProcessAsyncMessageBase
     319             : {
     320             : public:
     321             :   typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData;
     322             : 
     323             :   nsSameProcessAsyncMessageBase(JS::RootingContext* aRootingCx,
     324             :                                 JS::Handle<JSObject*> aCpows);
     325             :   nsresult Init(const nsAString& aMessage,
     326             :                 StructuredCloneData& aData,
     327             :                 nsIPrincipal* aPrincipal);
     328             : 
     329             :   void ReceiveMessage(nsISupports* aTarget, nsIFrameLoader* aTargetFrameLoader,
     330             :                       nsFrameMessageManager* aManager);
     331             : private:
     332             :   nsSameProcessAsyncMessageBase(const nsSameProcessAsyncMessageBase&);
     333             : 
     334             :   nsString mMessage;
     335             :   StructuredCloneData mData;
     336             :   JS::PersistentRooted<JSObject*> mCpows;
     337             :   nsCOMPtr<nsIPrincipal> mPrincipal;
     338             : #ifdef DEBUG
     339             :   bool mCalledInit;
     340             : #endif
     341             : };
     342             : 
     343             : class nsScriptCacheCleaner;
     344             : 
     345             : struct nsMessageManagerScriptHolder
     346             : {
     347          39 :   nsMessageManagerScriptHolder(JSContext* aCx,
     348             :                                JSScript* aScript,
     349             :                                bool aRunInGlobalScope)
     350          39 :    : mScript(aCx, aScript), mRunInGlobalScope(aRunInGlobalScope)
     351          39 :   { MOZ_COUNT_CTOR(nsMessageManagerScriptHolder); }
     352             : 
     353           0 :   ~nsMessageManagerScriptHolder()
     354           0 :   { MOZ_COUNT_DTOR(nsMessageManagerScriptHolder); }
     355             : 
     356           0 :   bool WillRunInGlobalScope() { return mRunInGlobalScope; }
     357             : 
     358             :   JS::PersistentRooted<JSScript*> mScript;
     359             :   bool mRunInGlobalScope;
     360             : };
     361             : 
     362             : class nsMessageManagerScriptExecutor
     363             : {
     364             : public:
     365             :   static void PurgeCache();
     366             :   static void Shutdown();
     367        2078 :   JSObject* GetGlobal()
     368             :   {
     369        2078 :     return mGlobal;
     370             :   }
     371             : 
     372             :   void MarkScopesForCC();
     373             : protected:
     374             :   friend class nsMessageManagerScriptCx;
     375           5 :   nsMessageManagerScriptExecutor() { MOZ_COUNT_CTOR(nsMessageManagerScriptExecutor); }
     376           0 :   ~nsMessageManagerScriptExecutor() { MOZ_COUNT_DTOR(nsMessageManagerScriptExecutor); }
     377             : 
     378             :   void DidCreateGlobal();
     379             :   void LoadScriptInternal(const nsAString& aURL, bool aRunInGlobalScope);
     380             :   void TryCacheLoadAndCompileScript(const nsAString& aURL,
     381             :                                     bool aRunInGlobalScope,
     382             :                                     bool aShouldCache,
     383             :                                     JS::MutableHandle<JSScript*> aScriptp);
     384             :   void TryCacheLoadAndCompileScript(const nsAString& aURL,
     385             :                                     bool aRunInGlobalScope);
     386             :   bool InitChildGlobalInternal(nsISupports* aScope, const nsACString& aID);
     387             :   void Trace(const TraceCallbacks& aCallbacks, void* aClosure);
     388             :   void Unlink();
     389             :   JS::TenuredHeap<JSObject*> mGlobal;
     390             :   nsCOMPtr<nsIPrincipal> mPrincipal;
     391             :   AutoTArray<JS::Heap<JSObject*>, 2> mAnonymousGlobalScopes;
     392             : 
     393             :   static nsDataHashtable<nsStringHashKey, nsMessageManagerScriptHolder*>* sCachedScripts;
     394             :   static mozilla::StaticRefPtr<nsScriptCacheCleaner> sScriptCacheCleaner;
     395             : };
     396             : 
     397             : class nsScriptCacheCleaner final : public nsIObserver
     398             : {
     399           0 :   ~nsScriptCacheCleaner() {}
     400             : 
     401             :   NS_DECL_ISUPPORTS
     402             : 
     403           3 :   nsScriptCacheCleaner()
     404           3 :   {
     405           6 :     nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
     406           3 :     if (obsSvc) {
     407           3 :       obsSvc->AddObserver(this, "message-manager-flush-caches", false);
     408           3 :       obsSvc->AddObserver(this, "xpcom-shutdown", false);
     409             :     }
     410           3 :   }
     411             : 
     412           0 :   NS_IMETHOD Observe(nsISupports *aSubject,
     413             :                      const char *aTopic,
     414             :                      const char16_t *aData) override
     415             :   {
     416           0 :     if (strcmp("message-manager-flush-caches", aTopic) == 0) {
     417           0 :       nsMessageManagerScriptExecutor::PurgeCache();
     418           0 :     } else if (strcmp("xpcom-shutdown", aTopic) == 0) {
     419           0 :       nsMessageManagerScriptExecutor::Shutdown();
     420             :     }
     421           0 :     return NS_OK;
     422             :   }
     423             : };
     424             : 
     425             : #endif

Generated by: LCOV version 1.13