Bug 1550519 - Show a translucent parent highlight when a subgrid is highlighted....
[gecko.git] / dom / base / nsFrameMessageManager.h
blobf5d80996090c6c353edc8c8d183b194c93c4a1c8
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/. */
7 #ifndef nsFrameMessageManager_h__
8 #define nsFrameMessageManager_h__
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 "nsAtom.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 "nsIWeakReferenceUtils.h"
28 #include "mozilla/Attributes.h"
29 #include "js/RootingAPI.h"
30 #include "nsTObserverArray.h"
31 #include "mozilla/TypedEnumBits.h"
32 #include "mozilla/dom/CallbackObject.h"
33 #include "mozilla/dom/SameProcessMessageQueue.h"
34 #include "mozilla/dom/ipc/StructuredCloneData.h"
35 #include "mozilla/jsipc/CpowHolder.h"
37 class nsFrameLoader;
39 namespace mozilla {
41 namespace ipc {
42 class FileDescriptor;
45 namespace dom {
47 class ContentParent;
48 class ContentChild;
49 class ChildProcessMessageManager;
50 class ChromeMessageBroadcaster;
51 class ClonedMessageData;
52 class MessageBroadcaster;
53 class MessageListener;
54 class MessageListenerManager;
55 class MessageManagerReporter;
56 template <typename T>
57 class Optional;
58 class ParentProcessMessageManager;
59 class ProcessMessageManager;
61 namespace ipc {
63 class WritableSharedMap;
65 // Note: we round the time we spend to the nearest millisecond. So a min value
66 // of 1 ms actually captures from 500us and above.
67 static const uint32_t kMinTelemetrySyncMessageManagerLatencyMs = 1;
69 enum class MessageManagerFlags {
70 MM_NONE = 0,
71 MM_CHROME = 1,
72 MM_GLOBAL = 2,
73 MM_PROCESSMANAGER = 4,
74 MM_BROADCASTER = 8,
75 MM_OWNSCALLBACK = 16
77 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(MessageManagerFlags);
79 class MessageManagerCallback {
80 public:
81 virtual ~MessageManagerCallback() {}
83 virtual bool DoLoadMessageManagerScript(const nsAString& aURL,
84 bool aRunInGlobalScope) {
85 return true;
88 virtual bool DoSendBlockingMessage(JSContext* aCx, const nsAString& aMessage,
89 StructuredCloneData& aData,
90 JS::Handle<JSObject*> aCpows,
91 nsIPrincipal* aPrincipal,
92 nsTArray<StructuredCloneData>* aRetVal,
93 bool aIsSync) {
94 return true;
97 virtual nsresult DoSendAsyncMessage(JSContext* aCx, const nsAString& aMessage,
98 StructuredCloneData& aData,
99 JS::Handle<JSObject*> aCpows,
100 nsIPrincipal* aPrincipal) {
101 return NS_OK;
104 virtual mozilla::dom::ProcessMessageManager* GetProcessMessageManager()
105 const {
106 return nullptr;
109 virtual void DoGetRemoteType(nsAString& aRemoteType,
110 ErrorResult& aError) const;
112 protected:
113 bool BuildClonedMessageDataForParent(ContentParent* aParent,
114 StructuredCloneData& aData,
115 ClonedMessageData& aClonedData);
116 bool BuildClonedMessageDataForChild(ContentChild* aChild,
117 StructuredCloneData& aData,
118 ClonedMessageData& aClonedData);
121 void UnpackClonedMessageDataForParent(const ClonedMessageData& aClonedData,
122 StructuredCloneData& aData);
124 void UnpackClonedMessageDataForChild(const ClonedMessageData& aClonedData,
125 StructuredCloneData& aData);
127 } // namespace ipc
128 } // namespace dom
129 } // namespace mozilla
131 struct nsMessageListenerInfo {
132 bool operator==(const nsMessageListenerInfo& aOther) const {
133 return &aOther == this;
136 // If mWeakListener is null then mStrongListener holds a MessageListener.
137 // If mWeakListener is non-null then mStrongListener contains null.
138 RefPtr<mozilla::dom::MessageListener> mStrongListener;
139 nsWeakPtr mWeakListener;
140 bool mListenWhenClosed;
143 class MOZ_STACK_CLASS SameProcessCpowHolder
144 : public mozilla::jsipc::CpowHolder {
145 public:
146 SameProcessCpowHolder(JS::RootingContext* aRootingCx,
147 JS::Handle<JSObject*> aObj)
148 : mObj(aRootingCx, aObj) {}
150 virtual bool ToObject(JSContext* aCx,
151 JS::MutableHandle<JSObject*> aObjp) override;
153 private:
154 JS::Rooted<JSObject*> mObj;
157 class nsFrameMessageManager : public nsIMessageSender {
158 friend class mozilla::dom::MessageManagerReporter;
159 typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData;
161 protected:
162 typedef mozilla::dom::ipc::MessageManagerFlags MessageManagerFlags;
164 nsFrameMessageManager(mozilla::dom::ipc::MessageManagerCallback* aCallback,
165 MessageManagerFlags aFlags);
167 virtual ~nsFrameMessageManager();
169 public:
170 explicit nsFrameMessageManager(
171 mozilla::dom::ipc::MessageManagerCallback* aCallback)
172 : nsFrameMessageManager(aCallback, MessageManagerFlags::MM_NONE) {}
174 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
175 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsFrameMessageManager)
177 void MarkForCC();
179 // MessageListenerManager
180 void AddMessageListener(const nsAString& aMessageName,
181 mozilla::dom::MessageListener& aListener,
182 bool aListenWhenClosed, mozilla::ErrorResult& aError);
183 void RemoveMessageListener(const nsAString& aMessageName,
184 mozilla::dom::MessageListener& aListener,
185 mozilla::ErrorResult& aError);
186 void AddWeakMessageListener(const nsAString& aMessageName,
187 mozilla::dom::MessageListener& aListener,
188 mozilla::ErrorResult& aError);
189 void RemoveWeakMessageListener(const nsAString& aMessageName,
190 mozilla::dom::MessageListener& aListener,
191 mozilla::ErrorResult& aError);
193 // MessageSender
194 void SendAsyncMessage(JSContext* aCx, const nsAString& aMessageName,
195 JS::Handle<JS::Value> aObj,
196 JS::Handle<JSObject*> aObjects,
197 nsIPrincipal* aPrincipal,
198 JS::Handle<JS::Value> aTransfers,
199 mozilla::ErrorResult& aError) {
200 DispatchAsyncMessage(aCx, aMessageName, aObj, aObjects, aPrincipal,
201 aTransfers, aError);
203 already_AddRefed<mozilla::dom::ProcessMessageManager>
204 GetProcessMessageManager(mozilla::ErrorResult& aError);
205 void GetRemoteType(nsAString& aRemoteType,
206 mozilla::ErrorResult& aError) const;
208 // SyncMessageSender
209 void SendSyncMessage(JSContext* aCx, const nsAString& aMessageName,
210 JS::Handle<JS::Value> aObj,
211 JS::Handle<JSObject*> aObjects, nsIPrincipal* aPrincipal,
212 nsTArray<JS::Value>& aResult,
213 mozilla::ErrorResult& aError) {
214 SendMessage(aCx, aMessageName, aObj, aObjects, aPrincipal, true, aResult,
215 aError);
217 void SendRpcMessage(JSContext* aCx, const nsAString& aMessageName,
218 JS::Handle<JS::Value> aObj,
219 JS::Handle<JSObject*> aObjects, nsIPrincipal* aPrincipal,
220 nsTArray<JS::Value>& aResult,
221 mozilla::ErrorResult& aError) {
222 SendMessage(aCx, aMessageName, aObj, aObjects, aPrincipal, false, aResult,
223 aError);
226 // GlobalProcessScriptLoader
227 void GetInitialProcessData(JSContext* aCx,
228 JS::MutableHandle<JS::Value> aInitialProcessData,
229 mozilla::ErrorResult& aError);
231 mozilla::dom::ipc::WritableSharedMap* SharedData();
233 NS_DECL_NSIMESSAGESENDER
235 static mozilla::dom::ProcessMessageManager* NewProcessMessageManager(
236 bool aIsRemote);
238 void ReceiveMessage(nsISupports* aTarget, nsFrameLoader* aTargetFrameLoader,
239 const nsAString& aMessage, bool aIsSync,
240 StructuredCloneData* aCloneData,
241 mozilla::jsipc::CpowHolder* aCpows,
242 nsIPrincipal* aPrincipal,
243 nsTArray<StructuredCloneData>* aRetVal,
244 mozilla::ErrorResult& aError) {
245 ReceiveMessage(aTarget, aTargetFrameLoader, mClosed, aMessage, aIsSync,
246 aCloneData, aCpows, aPrincipal, aRetVal, aError);
249 void Disconnect(bool aRemoveFromParent = true);
250 void Close();
252 void SetCallback(mozilla::dom::ipc::MessageManagerCallback* aCallback);
254 mozilla::dom::ipc::MessageManagerCallback* GetCallback() { return mCallback; }
256 nsresult DispatchAsyncMessageInternal(JSContext* aCx,
257 const nsAString& aMessage,
258 StructuredCloneData& aData,
259 JS::Handle<JSObject*> aCpows,
260 nsIPrincipal* aPrincipal);
261 bool IsGlobal() { return mGlobal; }
262 bool IsBroadcaster() { return mIsBroadcaster; }
263 bool IsChrome() { return mChrome; }
265 // GetGlobalMessageManager creates the global message manager if it hasn't
266 // been yet.
267 static already_AddRefed<mozilla::dom::ChromeMessageBroadcaster>
268 GetGlobalMessageManager();
269 static mozilla::dom::ParentProcessMessageManager* GetParentProcessManager() {
270 return sParentProcessManager;
272 static mozilla::dom::ChildProcessMessageManager* GetChildProcessManager() {
273 return sChildProcessManager;
275 static void SetChildProcessManager(
276 mozilla::dom::ChildProcessMessageManager* aManager) {
277 sChildProcessManager = aManager;
280 static bool GetParamsForMessage(JSContext* aCx, const JS::Value& aValue,
281 const JS::Value& aTransfer,
282 StructuredCloneData& aData);
284 void SetInitialProcessData(JS::HandleValue aInitialData);
286 void LoadPendingScripts();
288 protected:
289 friend class MMListenerRemover;
291 virtual mozilla::dom::MessageBroadcaster* GetParentManager() {
292 return nullptr;
294 virtual void ClearParentManager(bool aRemove) {}
296 void DispatchAsyncMessage(JSContext* aCx, const nsAString& aMessageName,
297 JS::Handle<JS::Value> aObj,
298 JS::Handle<JSObject*> aObjects,
299 nsIPrincipal* aPrincipal,
300 JS::Handle<JS::Value> aTransfers,
301 mozilla::ErrorResult& aError);
303 void SendMessage(JSContext* aCx, const nsAString& aMessageName,
304 JS::Handle<JS::Value> aObj, JS::Handle<JSObject*> aObjects,
305 nsIPrincipal* aPrincipal, bool aIsSync,
306 nsTArray<JS::Value>& aResult, mozilla::ErrorResult& aError);
308 void ReceiveMessage(nsISupports* aTarget, nsFrameLoader* aTargetFrameLoader,
309 bool aTargetClosed, const nsAString& aMessage,
310 bool aIsSync, StructuredCloneData* aCloneData,
311 mozilla::jsipc::CpowHolder* aCpows,
312 nsIPrincipal* aPrincipal,
313 nsTArray<StructuredCloneData>* aRetVal,
314 mozilla::ErrorResult& aError);
316 void LoadScript(const nsAString& aURL, bool aAllowDelayedLoad,
317 bool aRunInGlobalScope, mozilla::ErrorResult& aError);
318 void RemoveDelayedScript(const nsAString& aURL);
319 void GetDelayedScripts(JSContext* aCx, nsTArray<nsTArray<JS::Value>>& aList,
320 mozilla::ErrorResult& aError);
322 // We keep the message listeners as arrays in a hastable indexed by the
323 // message name. That gives us fast lookups in ReceiveMessage().
324 nsClassHashtable<nsStringHashKey,
325 nsAutoTObserverArray<nsMessageListenerInfo, 1>>
326 mListeners;
327 nsTArray<RefPtr<mozilla::dom::MessageListenerManager>> mChildManagers;
328 bool mChrome; // true if we're in the chrome process
329 bool mGlobal; // true if we're the global frame message manager
330 bool mIsProcessManager; // true if the message manager belongs to the process
331 // realm
332 bool mIsBroadcaster; // true if the message manager is a broadcaster
333 bool mOwnsCallback;
334 bool mHandlingMessage;
335 bool mClosed; // true if we can no longer send messages
336 bool mDisconnected;
337 mozilla::dom::ipc::MessageManagerCallback* mCallback;
338 nsAutoPtr<mozilla::dom::ipc::MessageManagerCallback> mOwnedCallback;
339 nsTArray<nsString> mPendingScripts;
340 nsTArray<bool> mPendingScriptsGlobalStates;
341 JS::Heap<JS::Value> mInitialProcessData;
342 RefPtr<mozilla::dom::ipc::WritableSharedMap> mSharedData;
344 void LoadPendingScripts(nsFrameMessageManager* aManager,
345 nsFrameMessageManager* aChildMM);
347 public:
348 static mozilla::dom::ParentProcessMessageManager* sParentProcessManager;
349 static nsFrameMessageManager* sSameProcessParentManager;
350 static nsTArray<nsCOMPtr<nsIRunnable>>* sPendingSameProcessAsyncMessages;
352 private:
353 static mozilla::dom::ChildProcessMessageManager* sChildProcessManager;
356 /* A helper class for taking care of many details for async message sending
357 within a single process. Intended to be used like so:
359 class MyAsyncMessage : public nsSameProcessAsyncMessageBase, public Runnable
361 NS_IMETHOD Run() {
362 ReceiveMessage(..., ...);
363 return NS_OK;
368 RefPtr<nsSameProcessAsyncMessageBase> ev = new MyAsyncMessage();
369 nsresult rv = ev->Init(...);
370 if (NS_SUCCEEDED(rv)) {
371 NS_DispatchToMainThread(ev);
374 class nsSameProcessAsyncMessageBase {
375 public:
376 typedef mozilla::dom::ipc::StructuredCloneData StructuredCloneData;
378 nsSameProcessAsyncMessageBase(JS::RootingContext* aRootingCx,
379 JS::Handle<JSObject*> aCpows);
380 nsresult Init(const nsAString& aMessage, StructuredCloneData& aData,
381 nsIPrincipal* aPrincipal);
383 void ReceiveMessage(nsISupports* aTarget, nsFrameLoader* aTargetFrameLoader,
384 nsFrameMessageManager* aManager);
386 private:
387 nsSameProcessAsyncMessageBase(const nsSameProcessAsyncMessageBase&);
389 nsString mMessage;
390 StructuredCloneData mData;
391 JS::PersistentRooted<JSObject*> mCpows;
392 nsCOMPtr<nsIPrincipal> mPrincipal;
393 #ifdef DEBUG
394 bool mCalledInit;
395 #endif
398 class nsScriptCacheCleaner;
400 struct nsMessageManagerScriptHolder {
401 nsMessageManagerScriptHolder(JSContext* aCx, JSScript* aScript)
402 : mScript(aCx, aScript) {
403 MOZ_COUNT_CTOR(nsMessageManagerScriptHolder);
406 ~nsMessageManagerScriptHolder() {
407 MOZ_COUNT_DTOR(nsMessageManagerScriptHolder);
410 JS::PersistentRooted<JSScript*> mScript;
413 class nsMessageManagerScriptExecutor {
414 public:
415 static void PurgeCache();
416 static void Shutdown();
418 void MarkScopesForCC();
420 protected:
421 friend class nsMessageManagerScriptCx;
422 nsMessageManagerScriptExecutor() {
423 MOZ_COUNT_CTOR(nsMessageManagerScriptExecutor);
425 ~nsMessageManagerScriptExecutor() {
426 MOZ_COUNT_DTOR(nsMessageManagerScriptExecutor);
429 void DidCreateScriptLoader();
430 void LoadScriptInternal(JS::Handle<JSObject*> aMessageManager,
431 const nsAString& aURL, bool aRunInUniqueScope);
432 void TryCacheLoadAndCompileScript(const nsAString& aURL,
433 bool aRunInUniqueScope, bool aShouldCache,
434 JS::Handle<JSObject*> aMessageManager,
435 JS::MutableHandle<JSScript*> aScriptp);
436 bool Init();
437 void Trace(const TraceCallbacks& aCallbacks, void* aClosure);
438 void Unlink();
439 nsCOMPtr<nsIPrincipal> mPrincipal;
440 AutoTArray<JS::Heap<JSObject*>, 2> mAnonymousGlobalScopes;
442 // Returns true if this is a process message manager. There should only be a
443 // single process message manager per session, so instances of this type will
444 // optimize their script loading to avoid unnecessary duplication.
445 virtual bool IsProcessScoped() const { return false; }
447 static nsDataHashtable<nsStringHashKey, nsMessageManagerScriptHolder*>*
448 sCachedScripts;
449 static mozilla::StaticRefPtr<nsScriptCacheCleaner> sScriptCacheCleaner;
452 class nsScriptCacheCleaner final : public nsIObserver {
453 ~nsScriptCacheCleaner() {}
455 NS_DECL_ISUPPORTS
457 nsScriptCacheCleaner() {
458 nsCOMPtr<nsIObserverService> obsSvc =
459 mozilla::services::GetObserverService();
460 if (obsSvc) {
461 obsSvc->AddObserver(this, "message-manager-flush-caches", false);
462 obsSvc->AddObserver(this, "xpcom-shutdown", false);
466 NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
467 const char16_t* aData) override {
468 if (strcmp("message-manager-flush-caches", aTopic) == 0) {
469 nsMessageManagerScriptExecutor::PurgeCache();
470 } else if (strcmp("xpcom-shutdown", aTopic) == 0) {
471 nsMessageManagerScriptExecutor::Shutdown();
473 return NS_OK;
477 #endif