forked from mirrors/gecko-dev
		
	 7eef772214
			
		
	
	
		7eef772214
		
	
	
	
	
		
			
			This is largely a straightforward find and replace of various methods, with the unnecessary arguments removed and compiler errors fixed. Differential Revision: https://phabricator.services.mozilla.com/D148532
		
			
				
	
	
		
			375 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			375 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #ifndef nsFrameMessageManager_h__
 | |
| #define nsFrameMessageManager_h__
 | |
| 
 | |
| #include <cstdint>
 | |
| #include <string.h>
 | |
| #include <utility>
 | |
| #include "ErrorList.h"
 | |
| #include "js/experimental/JSStencil.h"
 | |
| #include "js/TypeDecls.h"
 | |
| #include "js/Value.h"
 | |
| #include "mozilla/AlreadyAddRefed.h"
 | |
| #include "mozilla/Assertions.h"
 | |
| #include "mozilla/RefPtr.h"
 | |
| #include "mozilla/Services.h"
 | |
| #include "mozilla/StaticPtr.h"
 | |
| #include "mozilla/TypedEnumBits.h"
 | |
| #include "mozilla/UniquePtr.h"
 | |
| #include "mozilla/dom/ipc/StructuredCloneData.h"
 | |
| #include "nsCOMPtr.h"
 | |
| #include "nsClassHashtable.h"
 | |
| #include "nsCycleCollectionParticipant.h"
 | |
| #include "nsTHashMap.h"
 | |
| #include "nsHashKeys.h"
 | |
| #include "nsIMessageManager.h"
 | |
| #include "nsIObserver.h"
 | |
| #include "nsIObserverService.h"
 | |
| #include "nsISupports.h"
 | |
| #include "nsIWeakReferenceUtils.h"
 | |
| #include "nsStringFwd.h"
 | |
| #include "nsTArray.h"
 | |
| #include "nsTObserverArray.h"
 | |
| #include "nscore.h"
 | |
| 
 | |
| class nsFrameLoader;
 | |
| class nsIRunnable;
 | |
| 
 | |
| namespace mozilla {
 | |
| 
 | |
| class ErrorResult;
 | |
| 
 | |
| namespace dom {
 | |
| 
 | |
| class ChildProcessMessageManager;
 | |
| class ChromeMessageBroadcaster;
 | |
| class ClonedMessageData;
 | |
| class MessageBroadcaster;
 | |
| class MessageListener;
 | |
| class MessageListenerManager;
 | |
| class MessageManagerReporter;
 | |
| class ParentProcessMessageManager;
 | |
| class ProcessMessageManager;
 | |
| 
 | |
| namespace ipc {
 | |
| 
 | |
| class MessageManagerCallback;
 | |
| class WritableSharedMap;
 | |
| 
 | |
| // Note: we round the time we spend to the nearest millisecond. So a min value
 | |
| // of 1 ms actually captures from 500us and above.
 | |
| static const uint32_t kMinTelemetrySyncMessageManagerLatencyMs = 1;
 | |
| 
 | |
| enum class MessageManagerFlags {
 | |
|   MM_NONE = 0,
 | |
|   MM_CHROME = 1,
 | |
|   MM_GLOBAL = 2,
 | |
|   MM_PROCESSMANAGER = 4,
 | |
|   MM_BROADCASTER = 8,
 | |
|   MM_OWNSCALLBACK = 16
 | |
| };
 | |
| MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(MessageManagerFlags);
 | |
| 
 | |
| void UnpackClonedMessageData(const ClonedMessageData& aClonedData,
 | |
|                              StructuredCloneData& aData);
 | |
| 
 | |
| }  // namespace ipc
 | |
| }  // namespace dom
 | |
| }  // namespace mozilla
 | |
| 
 | |
| struct nsMessageListenerInfo {
 | |
|   bool operator==(const nsMessageListenerInfo& aOther) const {
 | |
|     return &aOther == this;
 | |
|   }
 | |
| 
 | |
|   // If mWeakListener is null then mStrongListener holds a MessageListener.
 | |
|   // If mWeakListener is non-null then mStrongListener contains null.
 | |
|   RefPtr<mozilla::dom::MessageListener> mStrongListener;
 | |
|   nsWeakPtr mWeakListener;
 | |
|   bool mListenWhenClosed;
 | |
| };
 | |
| 
 | |
| class nsFrameMessageManager : public nsIMessageSender {
 | |
|   friend class mozilla::dom::MessageManagerReporter;
 | |
|   using StructuredCloneData = mozilla::dom::ipc::StructuredCloneData;
 | |
| 
 | |
|  protected:
 | |
|   using MessageManagerFlags = mozilla::dom::ipc::MessageManagerFlags;
 | |
| 
 | |
|   nsFrameMessageManager(mozilla::dom::ipc::MessageManagerCallback* aCallback,
 | |
|                         MessageManagerFlags aFlags);
 | |
| 
 | |
|   virtual ~nsFrameMessageManager();
 | |
| 
 | |
|  public:
 | |
|   explicit nsFrameMessageManager(
 | |
|       mozilla::dom::ipc::MessageManagerCallback* aCallback)
 | |
|       : nsFrameMessageManager(aCallback, MessageManagerFlags::MM_NONE) {}
 | |
| 
 | |
|   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 | |
|   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsFrameMessageManager)
 | |
| 
 | |
|   void MarkForCC();
 | |
| 
 | |
|   // MessageListenerManager
 | |
|   void AddMessageListener(const nsAString& aMessageName,
 | |
|                           mozilla::dom::MessageListener& aListener,
 | |
|                           bool aListenWhenClosed, mozilla::ErrorResult& aError);
 | |
|   void RemoveMessageListener(const nsAString& aMessageName,
 | |
|                              mozilla::dom::MessageListener& aListener,
 | |
|                              mozilla::ErrorResult& aError);
 | |
|   void AddWeakMessageListener(const nsAString& aMessageName,
 | |
|                               mozilla::dom::MessageListener& aListener,
 | |
|                               mozilla::ErrorResult& aError);
 | |
|   void RemoveWeakMessageListener(const nsAString& aMessageName,
 | |
|                                  mozilla::dom::MessageListener& aListener,
 | |
|                                  mozilla::ErrorResult& aError);
 | |
| 
 | |
|   // MessageSender
 | |
|   void SendAsyncMessage(JSContext* aCx, const nsAString& aMessageName,
 | |
|                         JS::Handle<JS::Value> aObj,
 | |
|                         JS::Handle<JS::Value> aTransfers,
 | |
|                         mozilla::ErrorResult& aError) {
 | |
|     DispatchAsyncMessage(aCx, aMessageName, aObj, aTransfers, aError);
 | |
|   }
 | |
|   already_AddRefed<mozilla::dom::ProcessMessageManager>
 | |
|   GetProcessMessageManager(mozilla::ErrorResult& aError);
 | |
|   void GetRemoteType(nsACString& aRemoteType,
 | |
|                      mozilla::ErrorResult& aError) const;
 | |
| 
 | |
|   // SyncMessageSender
 | |
|   void SendSyncMessage(JSContext* aCx, const nsAString& aMessageName,
 | |
|                        JS::Handle<JS::Value> aObj, nsTArray<JS::Value>& aResult,
 | |
|                        mozilla::ErrorResult& aError);
 | |
| 
 | |
|   // GlobalProcessScriptLoader
 | |
|   void GetInitialProcessData(JSContext* aCx,
 | |
|                              JS::MutableHandle<JS::Value> aInitialProcessData,
 | |
|                              mozilla::ErrorResult& aError);
 | |
| 
 | |
|   mozilla::dom::ipc::WritableSharedMap* SharedData();
 | |
| 
 | |
|   NS_DECL_NSIMESSAGESENDER
 | |
| 
 | |
|   static mozilla::dom::ProcessMessageManager* NewProcessMessageManager(
 | |
|       bool aIsRemote);
 | |
| 
 | |
|   void ReceiveMessage(nsISupports* aTarget, nsFrameLoader* aTargetFrameLoader,
 | |
|                       const nsAString& aMessage, bool aIsSync,
 | |
|                       StructuredCloneData* aCloneData,
 | |
|                       nsTArray<StructuredCloneData>* aRetVal,
 | |
|                       mozilla::ErrorResult& aError) {
 | |
|     ReceiveMessage(aTarget, aTargetFrameLoader, mClosed, aMessage, aIsSync,
 | |
|                    aCloneData, aRetVal, aError);
 | |
|   }
 | |
| 
 | |
|   void Disconnect(bool aRemoveFromParent = true);
 | |
|   void Close();
 | |
| 
 | |
|   void SetCallback(mozilla::dom::ipc::MessageManagerCallback* aCallback);
 | |
| 
 | |
|   mozilla::dom::ipc::MessageManagerCallback* GetCallback() { return mCallback; }
 | |
| 
 | |
|   nsresult DispatchAsyncMessageInternal(JSContext* aCx,
 | |
|                                         const nsAString& aMessage,
 | |
|                                         StructuredCloneData& aData);
 | |
|   bool IsGlobal() { return mGlobal; }
 | |
|   bool IsBroadcaster() { return mIsBroadcaster; }
 | |
|   bool IsChrome() { return mChrome; }
 | |
| 
 | |
|   // GetGlobalMessageManager creates the global message manager if it hasn't
 | |
|   // been yet.
 | |
|   static already_AddRefed<mozilla::dom::ChromeMessageBroadcaster>
 | |
|   GetGlobalMessageManager();
 | |
|   static mozilla::dom::ParentProcessMessageManager* GetParentProcessManager() {
 | |
|     return sParentProcessManager;
 | |
|   }
 | |
|   static mozilla::dom::ChildProcessMessageManager* GetChildProcessManager() {
 | |
|     return sChildProcessManager;
 | |
|   }
 | |
|   static void SetChildProcessManager(
 | |
|       mozilla::dom::ChildProcessMessageManager* aManager) {
 | |
|     sChildProcessManager = aManager;
 | |
|   }
 | |
| 
 | |
|   static bool GetParamsForMessage(JSContext* aCx, const JS::Value& aValue,
 | |
|                                   const JS::Value& aTransfer,
 | |
|                                   StructuredCloneData& aData);
 | |
| 
 | |
|   void SetInitialProcessData(JS::Handle<JS::Value> aInitialData);
 | |
| 
 | |
|   void LoadPendingScripts();
 | |
| 
 | |
|  protected:
 | |
|   friend class MMListenerRemover;
 | |
| 
 | |
|   virtual mozilla::dom::MessageBroadcaster* GetParentManager() {
 | |
|     return nullptr;
 | |
|   }
 | |
|   virtual void ClearParentManager(bool aRemove) {}
 | |
| 
 | |
|   void DispatchAsyncMessage(JSContext* aCx, const nsAString& aMessageName,
 | |
|                             JS::Handle<JS::Value> aObj,
 | |
|                             JS::Handle<JS::Value> aTransfers,
 | |
|                             mozilla::ErrorResult& aError);
 | |
| 
 | |
|   void ReceiveMessage(nsISupports* aTarget, nsFrameLoader* aTargetFrameLoader,
 | |
|                       bool aTargetClosed, const nsAString& aMessage,
 | |
|                       bool aIsSync, StructuredCloneData* aCloneData,
 | |
|                       nsTArray<StructuredCloneData>* aRetVal,
 | |
|                       mozilla::ErrorResult& aError);
 | |
| 
 | |
|   void LoadScript(const nsAString& aURL, bool aAllowDelayedLoad,
 | |
|                   bool aRunInGlobalScope, mozilla::ErrorResult& aError);
 | |
|   void RemoveDelayedScript(const nsAString& aURL);
 | |
|   void GetDelayedScripts(JSContext* aCx, nsTArray<nsTArray<JS::Value>>& aList,
 | |
|                          mozilla::ErrorResult& aError);
 | |
| 
 | |
|   // We keep the message listeners as arrays in a hastable indexed by the
 | |
|   // message name. That gives us fast lookups in ReceiveMessage().
 | |
|   nsClassHashtable<nsStringHashKey,
 | |
|                    nsAutoTObserverArray<nsMessageListenerInfo, 1>>
 | |
|       mListeners;
 | |
|   nsTArray<RefPtr<mozilla::dom::MessageListenerManager>> mChildManagers;
 | |
|   bool mChrome;            // true if we're in the chrome process
 | |
|   bool mGlobal;            // true if we're the global frame message manager
 | |
|   bool mIsProcessManager;  // true if the message manager belongs to the process
 | |
|                            // realm
 | |
|   bool mIsBroadcaster;     // true if the message manager is a broadcaster
 | |
|   bool mOwnsCallback;
 | |
|   bool mHandlingMessage;
 | |
|   bool mClosed;  // true if we can no longer send messages
 | |
|   bool mDisconnected;
 | |
|   mozilla::dom::ipc::MessageManagerCallback* mCallback;
 | |
|   mozilla::UniquePtr<mozilla::dom::ipc::MessageManagerCallback> mOwnedCallback;
 | |
|   nsTArray<nsString> mPendingScripts;
 | |
|   nsTArray<bool> mPendingScriptsGlobalStates;
 | |
|   JS::Heap<JS::Value> mInitialProcessData;
 | |
|   RefPtr<mozilla::dom::ipc::WritableSharedMap> mSharedData;
 | |
| 
 | |
|   void LoadPendingScripts(nsFrameMessageManager* aManager,
 | |
|                           nsFrameMessageManager* aChildMM);
 | |
| 
 | |
|  public:
 | |
|   static mozilla::dom::ParentProcessMessageManager* sParentProcessManager;
 | |
|   static nsFrameMessageManager* sSameProcessParentManager;
 | |
|   static nsTArray<nsCOMPtr<nsIRunnable>>* sPendingSameProcessAsyncMessages;
 | |
| 
 | |
|  private:
 | |
|   static mozilla::dom::ChildProcessMessageManager* sChildProcessManager;
 | |
| };
 | |
| 
 | |
| /* A helper class for taking care of many details for async message sending
 | |
|    within a single process.  Intended to be used like so:
 | |
| 
 | |
|    class MyAsyncMessage : public nsSameProcessAsyncMessageBase, public Runnable
 | |
|    {
 | |
|      NS_IMETHOD Run() {
 | |
|        ReceiveMessage(..., ...);
 | |
|        return NS_OK;
 | |
|      }
 | |
|    };
 | |
| 
 | |
| 
 | |
|    RefPtr<nsSameProcessAsyncMessageBase> ev = new MyAsyncMessage();
 | |
|    nsresult rv = ev->Init(...);
 | |
|    if (NS_SUCCEEDED(rv)) {
 | |
|      NS_DispatchToMainThread(ev);
 | |
|    }
 | |
| */
 | |
| class nsSameProcessAsyncMessageBase {
 | |
|  public:
 | |
|   using StructuredCloneData = mozilla::dom::ipc::StructuredCloneData;
 | |
| 
 | |
|   nsSameProcessAsyncMessageBase();
 | |
|   nsresult Init(const nsAString& aMessage, StructuredCloneData& aData);
 | |
| 
 | |
|   void ReceiveMessage(nsISupports* aTarget, nsFrameLoader* aTargetFrameLoader,
 | |
|                       nsFrameMessageManager* aManager);
 | |
| 
 | |
|  private:
 | |
|   nsSameProcessAsyncMessageBase(const nsSameProcessAsyncMessageBase&);
 | |
| 
 | |
|   nsString mMessage;
 | |
|   StructuredCloneData mData;
 | |
| #ifdef DEBUG
 | |
|   bool mCalledInit;
 | |
| #endif
 | |
| };
 | |
| 
 | |
| class nsScriptCacheCleaner;
 | |
| 
 | |
| struct nsMessageManagerScriptHolder {
 | |
|   explicit nsMessageManagerScriptHolder(JS::Stencil* aStencil)
 | |
|       : mStencil(aStencil) {
 | |
|     MOZ_COUNT_CTOR(nsMessageManagerScriptHolder);
 | |
|   }
 | |
| 
 | |
|   MOZ_COUNTED_DTOR(nsMessageManagerScriptHolder)
 | |
| 
 | |
|   RefPtr<JS::Stencil> mStencil;
 | |
| };
 | |
| 
 | |
| class nsMessageManagerScriptExecutor {
 | |
|  public:
 | |
|   static void PurgeCache();
 | |
|   static void Shutdown();
 | |
| 
 | |
|   void MarkScopesForCC();
 | |
| 
 | |
|  protected:
 | |
|   friend class nsMessageManagerScriptCx;
 | |
|   nsMessageManagerScriptExecutor() {
 | |
|     MOZ_COUNT_CTOR(nsMessageManagerScriptExecutor);
 | |
|   }
 | |
|   MOZ_COUNTED_DTOR(nsMessageManagerScriptExecutor)
 | |
| 
 | |
|   void DidCreateScriptLoader();
 | |
|   void LoadScriptInternal(JS::Handle<JSObject*> aMessageManager,
 | |
|                           const nsAString& aURL, bool aRunInUniqueScope);
 | |
|   already_AddRefed<JS::Stencil> TryCacheLoadAndCompileScript(
 | |
|       const nsAString& aURL, bool aRunInUniqueScope,
 | |
|       JS::Handle<JSObject*> aMessageManager);
 | |
|   bool Init();
 | |
|   void Trace(const TraceCallbacks& aCallbacks, void* aClosure);
 | |
|   void Unlink();
 | |
|   AutoTArray<JS::Heap<JSObject*>, 2> mAnonymousGlobalScopes;
 | |
| 
 | |
|   // Returns true if this is a process message manager. There should only be a
 | |
|   // single process message manager per session, so instances of this type will
 | |
|   // optimize their script loading to avoid unnecessary duplication.
 | |
|   virtual bool IsProcessScoped() const { return false; }
 | |
| 
 | |
|   static nsTHashMap<nsStringHashKey, nsMessageManagerScriptHolder*>*
 | |
|       sCachedScripts;
 | |
|   static mozilla::StaticRefPtr<nsScriptCacheCleaner> sScriptCacheCleaner;
 | |
| };
 | |
| 
 | |
| class nsScriptCacheCleaner final : public nsIObserver {
 | |
|   ~nsScriptCacheCleaner() = default;
 | |
| 
 | |
|   NS_DECL_ISUPPORTS
 | |
| 
 | |
|   nsScriptCacheCleaner() {
 | |
|     nsCOMPtr<nsIObserverService> obsSvc =
 | |
|         mozilla::services::GetObserverService();
 | |
|     if (obsSvc) {
 | |
|       obsSvc->AddObserver(this, "xpcom-shutdown", false);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
 | |
|                      const char16_t* aData) override {
 | |
|     if (strcmp("xpcom-shutdown", aTopic) == 0) {
 | |
|       nsMessageManagerScriptExecutor::Shutdown();
 | |
|     }
 | |
|     return NS_OK;
 | |
|   }
 | |
| };
 | |
| 
 | |
| #endif
 |