Bug 1550519 - Show a translucent parent highlight when a subgrid is highlighted....
[gecko.git] / dom / workers / WorkerPrivate.h
blob312e7e72b231748286b1d862030c926b74cc0ce4
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 mozilla_dom_workers_workerprivate_h__
8 #define mozilla_dom_workers_workerprivate_h__
10 #include "mozilla/dom/WorkerCommon.h"
11 #include "mozilla/Attributes.h"
12 #include "mozilla/CondVar.h"
13 #include "mozilla/DOMEventTargetHelper.h"
14 #include "mozilla/RelativeTimeline.h"
15 #include "mozilla/StorageAccess.h"
16 #include "nsContentUtils.h"
17 #include "nsIContentSecurityPolicy.h"
18 #include "nsIEventTarget.h"
19 #include "nsTObserverArray.h"
21 #include "js/ContextOptions.h"
22 #include "mozilla/dom/Worker.h"
23 #include "mozilla/dom/WorkerHolder.h"
24 #include "mozilla/dom/WorkerLoadInfo.h"
25 #include "mozilla/dom/workerinternals/JSSettings.h"
26 #include "mozilla/dom/workerinternals/Queue.h"
27 #include "mozilla/PerformanceCounter.h"
28 #include "mozilla/ThreadBound.h"
30 class nsIThreadInternal;
32 namespace mozilla {
33 class ThrottledEventQueue;
34 namespace dom {
36 // If you change this, the corresponding list in nsIWorkerDebugger.idl needs
37 // to be updated too.
38 enum WorkerType { WorkerTypeDedicated, WorkerTypeShared, WorkerTypeService };
40 class ClientInfo;
41 class ClientSource;
42 class Function;
43 class MessagePort;
44 class MessagePortIdentifier;
45 class PerformanceStorage;
46 class RemoteWorkerChild;
47 class WorkerControlRunnable;
48 class WorkerCSPEventListener;
49 class WorkerDebugger;
50 class WorkerDebuggerGlobalScope;
51 class WorkerErrorReport;
52 class WorkerEventTarget;
53 class WorkerGlobalScope;
54 class WorkerRunnable;
55 class WorkerDebuggeeRunnable;
56 class WorkerThread;
58 // SharedMutex is a small wrapper around an (internal) reference-counted Mutex
59 // object. It exists to avoid changing a lot of code to use Mutex* instead of
60 // Mutex&.
61 class SharedMutex {
62 typedef mozilla::Mutex Mutex;
64 class RefCountedMutex final : public Mutex {
65 public:
66 explicit RefCountedMutex(const char* aName) : Mutex(aName) {}
68 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedMutex)
70 private:
71 ~RefCountedMutex() {}
74 RefPtr<RefCountedMutex> mMutex;
76 public:
77 explicit SharedMutex(const char* aName)
78 : mMutex(new RefCountedMutex(aName)) {}
80 SharedMutex(SharedMutex& aOther) : mMutex(aOther.mMutex) {}
82 operator Mutex&() { return *mMutex; }
84 operator const Mutex&() const { return *mMutex; }
86 void AssertCurrentThreadOwns() const { mMutex->AssertCurrentThreadOwns(); }
89 class WorkerPrivate : public RelativeTimeline {
90 public:
91 struct LocationInfo {
92 nsCString mHref;
93 nsCString mProtocol;
94 nsCString mHost;
95 nsCString mHostname;
96 nsCString mPort;
97 nsCString mPathname;
98 nsCString mSearch;
99 nsCString mHash;
100 nsString mOrigin;
103 NS_INLINE_DECL_REFCOUNTING(WorkerPrivate)
105 static already_AddRefed<WorkerPrivate> Constructor(
106 JSContext* aCx, const nsAString& aScriptURL, bool aIsChromeWorker,
107 WorkerType aWorkerType, const nsAString& aWorkerName,
108 const nsACString& aServiceWorkerScope, WorkerLoadInfo* aLoadInfo,
109 ErrorResult& aRv);
111 enum LoadGroupBehavior { InheritLoadGroup, OverrideLoadGroup };
113 static nsresult GetLoadInfo(JSContext* aCx, nsPIDOMWindowInner* aWindow,
114 WorkerPrivate* aParent,
115 const nsAString& aScriptURL, bool aIsChromeWorker,
116 LoadGroupBehavior aLoadGroupBehavior,
117 WorkerType aWorkerType,
118 WorkerLoadInfo* aLoadInfo);
120 void Traverse(nsCycleCollectionTraversalCallback& aCb);
122 void ClearSelfAndParentEventTargetRef() {
123 AssertIsOnParentThread();
124 MOZ_ASSERT(mSelfRef);
125 mParentEventTargetRef = nullptr;
126 mSelfRef = nullptr;
129 // May be called on any thread...
130 bool Start();
132 // Called on the parent thread.
133 bool Notify(WorkerStatus aStatus);
135 bool Cancel() { return Notify(Canceling); }
137 bool Close();
139 // The passed principal must be the Worker principal in case of a
140 // ServiceWorker and the loading principal for any other type.
141 static void OverrideLoadInfoLoadGroup(WorkerLoadInfo& aLoadInfo,
142 nsIPrincipal* aPrincipal);
144 bool IsDebuggerRegistered() {
145 AssertIsOnMainThread();
147 // No need to lock here since this is only ever modified by the same thread.
148 return mDebuggerRegistered;
151 void SetIsDebuggerRegistered(bool aDebuggerRegistered) {
152 AssertIsOnMainThread();
154 MutexAutoLock lock(mMutex);
156 MOZ_ASSERT(mDebuggerRegistered != aDebuggerRegistered);
157 mDebuggerRegistered = aDebuggerRegistered;
159 mCondVar.Notify();
162 void WaitForIsDebuggerRegistered(bool aDebuggerRegistered) {
163 AssertIsOnParentThread();
165 MOZ_ASSERT(!NS_IsMainThread());
167 MutexAutoLock lock(mMutex);
169 while (mDebuggerRegistered != aDebuggerRegistered) {
170 mCondVar.Wait();
174 nsresult SetIsDebuggerReady(bool aReady);
176 WorkerDebugger* Debugger() const {
177 AssertIsOnMainThread();
179 MOZ_ASSERT(mDebugger);
180 return mDebugger;
183 void SetDebugger(WorkerDebugger* aDebugger) {
184 AssertIsOnMainThread();
186 MOZ_ASSERT(mDebugger != aDebugger);
187 mDebugger = aDebugger;
190 JS::UniqueChars AdoptDefaultLocale() {
191 MOZ_ASSERT(mDefaultLocale,
192 "the default locale must have been successfully set for anyone "
193 "to be trying to adopt it");
194 return std::move(mDefaultLocale);
197 MOZ_CAN_RUN_SCRIPT
198 void DoRunLoop(JSContext* aCx);
200 bool InterruptCallback(JSContext* aCx);
202 bool IsOnCurrentThread();
204 void CloseInternal();
206 bool FreezeInternal();
208 bool ThawInternal();
210 void PropagateFirstPartyStorageAccessGrantedInternal();
212 void TraverseTimeouts(nsCycleCollectionTraversalCallback& aCallback);
214 void UnlinkTimeouts();
216 bool ModifyBusyCountFromWorker(bool aIncrease);
218 bool AddChildWorker(WorkerPrivate* aChildWorker);
220 void RemoveChildWorker(WorkerPrivate* aChildWorker);
222 void PostMessageToParent(JSContext* aCx, JS::Handle<JS::Value> aMessage,
223 const Sequence<JSObject*>& aTransferable,
224 ErrorResult& aRv);
226 void PostMessageToParentMessagePort(JSContext* aCx,
227 JS::Handle<JS::Value> aMessage,
228 const Sequence<JSObject*>& aTransferable,
229 ErrorResult& aRv);
231 MOZ_CAN_RUN_SCRIPT void EnterDebuggerEventLoop();
233 void LeaveDebuggerEventLoop();
235 void PostMessageToDebugger(const nsAString& aMessage);
237 void SetDebuggerImmediate(Function& aHandler, ErrorResult& aRv);
239 void ReportErrorToDebugger(const nsAString& aFilename, uint32_t aLineno,
240 const nsAString& aMessage);
242 bool NotifyInternal(WorkerStatus aStatus);
244 void ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
245 JSErrorReport* aReport);
247 static void ReportErrorToConsole(const char* aMessage);
249 static void ReportErrorToConsole(const char* aMessage,
250 const nsTArray<nsString>& aParams);
252 int32_t SetTimeout(JSContext* aCx, nsIScriptTimeoutHandler* aHandler,
253 int32_t aTimeout, bool aIsInterval, ErrorResult& aRv);
255 void ClearTimeout(int32_t aId);
257 MOZ_CAN_RUN_SCRIPT bool RunExpiredTimeouts(JSContext* aCx);
259 bool RescheduleTimeoutTimer(JSContext* aCx);
261 void UpdateContextOptionsInternal(JSContext* aCx,
262 const JS::ContextOptions& aContextOptions);
264 void UpdateLanguagesInternal(const nsTArray<nsString>& aLanguages);
266 void UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key,
267 uint32_t aValue);
269 enum WorkerRanOrNot { WorkerNeverRan = 0, WorkerRan };
271 void ScheduleDeletion(WorkerRanOrNot aRanOrNot);
273 bool CollectRuntimeStats(JS::RuntimeStats* aRtStats, bool aAnonymize);
275 #ifdef JS_GC_ZEAL
276 void UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal,
277 uint32_t aFrequency);
278 #endif
280 void GarbageCollectInternal(JSContext* aCx, bool aShrinking,
281 bool aCollectChildren);
283 void CycleCollectInternal(bool aCollectChildren);
285 void OfflineStatusChangeEventInternal(bool aIsOffline);
287 void MemoryPressureInternal();
289 void SetFetchHandlerWasAdded() {
290 MOZ_ASSERT(IsServiceWorker());
291 AssertIsOnWorkerThread();
292 mFetchHandlerWasAdded = true;
295 bool FetchHandlerWasAdded() const {
296 MOZ_ASSERT(IsServiceWorker());
297 AssertIsOnWorkerThread();
298 return mFetchHandlerWasAdded;
301 JSContext* GetJSContext() const {
302 AssertIsOnWorkerThread();
303 return mJSContext;
306 WorkerGlobalScope* GlobalScope() const {
307 MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
308 return data->mScope;
311 WorkerDebuggerGlobalScope* DebuggerGlobalScope() const {
312 MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
313 return data->mDebuggerScope;
316 nsICSPEventListener* CSPEventListener() const;
318 void SetThread(WorkerThread* aThread);
320 void SetWorkerPrivateInWorkerThread(WorkerThread* aThread);
322 void ResetWorkerPrivateInWorkerThread();
324 bool IsOnWorkerThread() const;
326 void AssertIsOnWorkerThread() const
327 #ifdef DEBUG
329 #else
332 #endif
334 // This may block!
335 void BeginCTypesCall();
337 // This may block!
338 void EndCTypesCall();
340 void BeginCTypesCallback() {
341 // If a callback is beginning then we need to do the exact same thing as
342 // when a ctypes call ends.
343 EndCTypesCall();
346 void EndCTypesCallback() {
347 // If a callback is ending then we need to do the exact same thing as
348 // when a ctypes call begins.
349 BeginCTypesCall();
352 bool ConnectMessagePort(JSContext* aCx,
353 const MessagePortIdentifier& aIdentifier);
355 WorkerGlobalScope* GetOrCreateGlobalScope(JSContext* aCx);
357 WorkerDebuggerGlobalScope* CreateDebuggerGlobalScope(JSContext* aCx);
359 bool RegisterBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
361 bool RegisterDebuggerBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
363 bool OnLine() const {
364 MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
365 return data->mOnLine;
368 void StopSyncLoop(nsIEventTarget* aSyncLoopTarget, bool aResult);
370 bool AllPendingRunnablesShouldBeCanceled() const {
371 return mCancelAllPendingRunnables;
374 void ClearMainEventQueue(WorkerRanOrNot aRanOrNot);
376 void ClearDebuggerEventQueue();
378 void OnProcessNextEvent();
380 void AfterProcessNextEvent();
382 void AssertValidSyncLoop(nsIEventTarget* aSyncLoopTarget)
383 #ifdef DEBUG
385 #else
388 #endif
390 void SetWorkerScriptExecutedSuccessfully() {
391 AssertIsOnWorkerThread();
392 // Should only be called once!
393 MOZ_ASSERT(!mWorkerScriptExecutedSuccessfully);
394 mWorkerScriptExecutedSuccessfully = true;
397 // Only valid after CompileScriptRunnable has finished running!
398 bool WorkerScriptExecutedSuccessfully() const {
399 AssertIsOnWorkerThread();
400 return mWorkerScriptExecutedSuccessfully;
403 // Get the event target to use when dispatching to the main thread
404 // from this Worker thread. This may be the main thread itself or
405 // a ThrottledEventQueue to the main thread.
406 nsIEventTarget* MainThreadEventTargetForMessaging();
408 nsresult DispatchToMainThreadForMessaging(
409 nsIRunnable* aRunnable, uint32_t aFlags = NS_DISPATCH_NORMAL);
411 nsresult DispatchToMainThreadForMessaging(
412 already_AddRefed<nsIRunnable> aRunnable,
413 uint32_t aFlags = NS_DISPATCH_NORMAL);
415 nsIEventTarget* MainThreadEventTarget();
417 nsresult DispatchToMainThread(nsIRunnable* aRunnable,
418 uint32_t aFlags = NS_DISPATCH_NORMAL);
420 nsresult DispatchToMainThread(already_AddRefed<nsIRunnable> aRunnable,
421 uint32_t aFlags = NS_DISPATCH_NORMAL);
423 nsresult DispatchDebuggeeToMainThread(
424 already_AddRefed<WorkerDebuggeeRunnable> aRunnable,
425 uint32_t aFlags = NS_DISPATCH_NORMAL);
427 // Get an event target that will dispatch runnables as control runnables on
428 // the worker thread. Implement nsICancelableRunnable if you wish to take
429 // action on cancelation.
430 nsISerialEventTarget* ControlEventTarget();
432 // Get an event target that will attempt to dispatch a normal WorkerRunnable,
433 // but if that fails will then fall back to a control runnable.
434 nsISerialEventTarget* HybridEventTarget();
436 void DumpCrashInformation(nsACString& aString);
438 bool EnsureClientSource();
440 bool EnsureCSPEventListener();
442 void EnsurePerformanceStorage();
444 void EnsurePerformanceCounter();
446 Maybe<ClientInfo> GetClientInfo() const;
448 const ClientState GetClientState() const;
450 const Maybe<ServiceWorkerDescriptor> GetController();
452 void Control(const ServiceWorkerDescriptor& aServiceWorker);
454 void ExecutionReady();
456 PerformanceStorage* GetPerformanceStorage();
458 PerformanceCounter* GetPerformanceCounter();
460 bool IsAcceptingEvents() {
461 AssertIsOnParentThread();
463 MutexAutoLock lock(mMutex);
464 return mParentStatus < Canceling;
467 WorkerStatus ParentStatusProtected() {
468 AssertIsOnParentThread();
469 MutexAutoLock lock(mMutex);
470 return mParentStatus;
473 WorkerStatus ParentStatus() const {
474 mMutex.AssertCurrentThreadOwns();
475 return mParentStatus;
478 Worker* ParentEventTargetRef() const {
479 MOZ_DIAGNOSTIC_ASSERT(mParentEventTargetRef);
480 return mParentEventTargetRef;
483 void SetParentEventTargetRef(Worker* aParentEventTargetRef) {
484 MOZ_DIAGNOSTIC_ASSERT(aParentEventTargetRef);
485 MOZ_DIAGNOSTIC_ASSERT(!mParentEventTargetRef);
486 mParentEventTargetRef = aParentEventTargetRef;
489 bool ModifyBusyCount(bool aIncrease);
491 // This method is used by RuntimeService to know what is going wrong the
492 // shutting down.
493 uint32_t BusyCount() { return mBusyCount; }
495 // Check whether this worker is a secure context. For use from the parent
496 // thread only; the canonical "is secure context" boolean is stored on the
497 // compartment of the worker global. The only reason we don't
498 // AssertIsOnParentThread() here is so we can assert that this value matches
499 // the one on the compartment, which has to be done from the worker thread.
500 bool IsSecureContext() const { return mIsSecureContext; }
502 // Check whether we're running in automation.
503 bool IsInAutomation() const { return mIsInAutomation; }
505 TimeStamp CreationTimeStamp() const { return mCreationTimeStamp; }
507 DOMHighResTimeStamp CreationTime() const { return mCreationTimeHighRes; }
509 DOMHighResTimeStamp TimeStampToDOMHighRes(const TimeStamp& aTimeStamp) const {
510 MOZ_ASSERT(!aTimeStamp.IsNull());
511 TimeDuration duration = aTimeStamp - mCreationTimeStamp;
512 return duration.ToMilliseconds();
515 LocationInfo& GetLocationInfo() { return mLocationInfo; }
517 void CopyJSSettings(workerinternals::JSSettings& aSettings) {
518 mozilla::MutexAutoLock lock(mMutex);
519 aSettings = mJSSettings;
522 void CopyJSRealmOptions(JS::RealmOptions& aOptions) {
523 mozilla::MutexAutoLock lock(mMutex);
524 aOptions = IsChromeWorker() ? mJSSettings.chrome.realmOptions
525 : mJSSettings.content.realmOptions;
528 // The ability to be a chrome worker is orthogonal to the type of
529 // worker [Dedicated|Shared|Service].
530 bool IsChromeWorker() const { return mIsChromeWorker; }
532 WorkerPrivate* GetParent() const { return mParent; }
534 bool IsFrozen() const {
535 AssertIsOnParentThread();
536 return mParentFrozen;
539 bool IsParentWindowPaused() const {
540 AssertIsOnParentThread();
541 return mParentWindowPaused;
544 // When we debug a worker, we want to disconnect the window and the worker
545 // communication. This happens calling this method.
546 // Note: this method doesn't suspend the worker! Use Freeze/Thaw instead.
547 void ParentWindowPaused();
549 void ParentWindowResumed();
551 const nsString& ScriptURL() const { return mScriptURL; }
553 const nsString& WorkerName() const { return mWorkerName; }
555 WorkerType Type() const { return mWorkerType; }
557 bool IsDedicatedWorker() const { return mWorkerType == WorkerTypeDedicated; }
559 bool IsSharedWorker() const { return mWorkerType == WorkerTypeShared; }
561 bool IsServiceWorker() const { return mWorkerType == WorkerTypeService; }
563 nsContentPolicyType ContentPolicyType() const {
564 return ContentPolicyType(mWorkerType);
567 static nsContentPolicyType ContentPolicyType(WorkerType aWorkerType) {
568 switch (aWorkerType) {
569 case WorkerTypeDedicated:
570 return nsIContentPolicy::TYPE_INTERNAL_WORKER;
571 case WorkerTypeShared:
572 return nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
573 case WorkerTypeService:
574 return nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER;
575 default:
576 MOZ_ASSERT_UNREACHABLE("Invalid worker type");
577 return nsIContentPolicy::TYPE_INVALID;
581 nsIScriptContext* GetScriptContext() const {
582 AssertIsOnMainThread();
583 return mLoadInfo.mScriptContext;
586 const nsCString& Domain() const { return mLoadInfo.mDomain; }
588 bool IsFromWindow() const { return mLoadInfo.mFromWindow; }
590 nsLoadFlags GetLoadFlags() const { return mLoadInfo.mLoadFlags; }
592 uint64_t WindowID() const { return mLoadInfo.mWindowID; }
594 uint64_t ServiceWorkerID() const { return GetServiceWorkerDescriptor().Id(); }
596 const nsCString& ServiceWorkerScope() const {
597 return GetServiceWorkerDescriptor().Scope();
600 nsIURI* GetBaseURI() const {
601 AssertIsOnMainThread();
602 return mLoadInfo.mBaseURI;
605 void SetBaseURI(nsIURI* aBaseURI);
607 nsIURI* GetResolvedScriptURI() const {
608 AssertIsOnMainThread();
609 return mLoadInfo.mResolvedScriptURI;
612 const nsString& ServiceWorkerCacheName() const {
613 MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
614 AssertIsOnMainThread();
615 return mLoadInfo.mServiceWorkerCacheName;
618 const ServiceWorkerDescriptor& GetServiceWorkerDescriptor() const {
619 MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
620 MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mServiceWorkerDescriptor.isSome());
621 return mLoadInfo.mServiceWorkerDescriptor.ref();
624 const ServiceWorkerRegistrationDescriptor&
625 GetServiceWorkerRegistrationDescriptor() const {
626 MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
627 MOZ_DIAGNOSTIC_ASSERT(
628 mLoadInfo.mServiceWorkerRegistrationDescriptor.isSome());
629 return mLoadInfo.mServiceWorkerRegistrationDescriptor.ref();
632 void UpdateServiceWorkerState(ServiceWorkerState aState) {
633 MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
634 MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mServiceWorkerDescriptor.isSome());
635 return mLoadInfo.mServiceWorkerDescriptor.ref().SetState(aState);
638 const Maybe<ServiceWorkerDescriptor>& GetParentController() const {
639 return mLoadInfo.mParentController;
642 const ChannelInfo& GetChannelInfo() const { return mLoadInfo.mChannelInfo; }
644 void SetChannelInfo(const ChannelInfo& aChannelInfo) {
645 AssertIsOnMainThread();
646 MOZ_ASSERT(!mLoadInfo.mChannelInfo.IsInitialized());
647 MOZ_ASSERT(aChannelInfo.IsInitialized());
648 mLoadInfo.mChannelInfo = aChannelInfo;
651 void InitChannelInfo(nsIChannel* aChannel) {
652 mLoadInfo.mChannelInfo.InitFromChannel(aChannel);
655 void InitChannelInfo(const ChannelInfo& aChannelInfo) {
656 mLoadInfo.mChannelInfo = aChannelInfo;
659 nsIPrincipal* GetPrincipal() const {
660 AssertIsOnMainThread();
661 return mLoadInfo.mPrincipal;
664 nsIPrincipal* GetEffectiveStoragePrincipal() const {
665 AssertIsOnMainThread();
666 return mLoadInfo.mStoragePrincipal;
669 nsIPrincipal* GetLoadingPrincipal() const {
670 AssertIsOnMainThread();
671 return mLoadInfo.mLoadingPrincipal;
674 const nsAString& Origin() const { return mLoadInfo.mOrigin; }
676 nsILoadGroup* GetLoadGroup() const {
677 AssertIsOnMainThread();
678 return mLoadInfo.mLoadGroup;
681 bool UsesSystemPrincipal() const { return mLoadInfo.mPrincipalIsSystem; }
683 const mozilla::ipc::PrincipalInfo& GetPrincipalInfo() const {
684 return *mLoadInfo.mPrincipalInfo;
687 const mozilla::ipc::PrincipalInfo& GetEffectiveStoragePrincipalInfo() const {
688 return *mLoadInfo.mStoragePrincipalInfo;
691 already_AddRefed<nsIChannel> ForgetWorkerChannel() {
692 AssertIsOnMainThread();
693 return mLoadInfo.mChannel.forget();
696 nsPIDOMWindowInner* GetWindow() {
697 AssertIsOnMainThread();
698 return mLoadInfo.mWindow;
701 nsIContentSecurityPolicy* GetCSP() const {
702 AssertIsOnMainThread();
703 return mLoadInfo.mCSP;
706 void SetCSP(nsIContentSecurityPolicy* aCSP);
708 nsresult SetCSPFromHeaderValues(const nsACString& aCSPHeaderValue,
709 const nsACString& aCSPReportOnlyHeaderValue);
711 void StoreCSPOnClient();
713 const mozilla::ipc::CSPInfo& GetCSPInfo() const {
714 return *mLoadInfo.mCSPInfo;
717 void SetReferrerPolicyFromHeaderValue(
718 const nsACString& aReferrerPolicyHeaderValue);
720 net::ReferrerPolicy GetReferrerPolicy() const {
721 return mLoadInfo.mReferrerPolicy;
724 void SetReferrerPolicy(net::ReferrerPolicy aReferrerPolicy) {
725 mLoadInfo.mReferrerPolicy = aReferrerPolicy;
728 bool IsEvalAllowed() const { return mLoadInfo.mEvalAllowed; }
730 void SetEvalAllowed(bool aEvalAllowed) {
731 mLoadInfo.mEvalAllowed = aEvalAllowed;
734 bool GetReportCSPViolations() const { return mLoadInfo.mReportCSPViolations; }
736 void SetReportCSPViolations(bool aReport) {
737 mLoadInfo.mReportCSPViolations = aReport;
740 bool XHRParamsAllowed() const { return mLoadInfo.mXHRParamsAllowed; }
742 void SetXHRParamsAllowed(bool aAllowed) {
743 mLoadInfo.mXHRParamsAllowed = aAllowed;
746 mozilla::StorageAccess StorageAccess() const {
747 AssertIsOnWorkerThread();
748 if (mLoadInfo.mFirstPartyStorageAccessGranted) {
749 return mozilla::StorageAccess::eAllow;
752 return mLoadInfo.mStorageAccess;
755 nsICookieSettings* CookieSettings() const {
756 // Any thread.
757 MOZ_ASSERT(mLoadInfo.mCookieSettings);
758 return mLoadInfo.mCookieSettings;
761 const OriginAttributes& GetOriginAttributes() const {
762 return mLoadInfo.mOriginAttributes;
765 // Determine if the SW testing per-window flag is set by devtools
766 bool ServiceWorkersTestingInWindow() const {
767 return mLoadInfo.mServiceWorkersTestingInWindow;
770 bool IsWatchedByDevtools() const { return mLoadInfo.mWatchedByDevtools; }
772 // Determine if the worker is currently loading its top level script.
773 bool IsLoadingWorkerScript() const { return mLoadingWorkerScript; }
775 // Called by ScriptLoader to track when this worker is loading its
776 // top level script.
777 void SetLoadingWorkerScript(bool aLoadingWorkerScript) {
778 // any thread
779 mLoadingWorkerScript = aLoadingWorkerScript;
782 RemoteWorkerChild* GetRemoteWorkerController();
784 void SetRemoteWorkerController(RemoteWorkerChild* aController);
786 // We can assume that an nsPIDOMWindow will be available for Freeze, Thaw
787 // as these are only used for globals going in and out of the bfcache.
788 bool Freeze(nsPIDOMWindowInner* aWindow);
790 bool Thaw(nsPIDOMWindowInner* aWindow);
792 void PropagateFirstPartyStorageAccessGranted();
794 void EnableDebugger();
796 void DisableDebugger();
798 already_AddRefed<WorkerRunnable> MaybeWrapAsWorkerRunnable(
799 already_AddRefed<nsIRunnable> aRunnable);
801 bool ProxyReleaseMainThreadObjects();
803 void GarbageCollect(bool aShrinking);
805 void CycleCollect(bool aDummy);
807 nsresult SetPrincipalsAndCSPOnMainThread(nsIPrincipal* aPrincipal,
808 nsIPrincipal* aStoragePrincipal,
809 nsILoadGroup* aLoadGroup,
810 nsIContentSecurityPolicy* aCsp);
812 nsresult SetPrincipalsAndCSPFromChannel(nsIChannel* aChannel);
814 bool FinalChannelPrincipalIsValid(nsIChannel* aChannel);
816 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
817 bool PrincipalURIMatchesScriptURL();
818 #endif
820 void UpdateOverridenLoadGroup(nsILoadGroup* aBaseLoadGroup);
822 void WorkerScriptLoaded();
824 Document* GetDocument() const;
826 void MemoryPressure(bool aDummy);
828 void UpdateContextOptions(const JS::ContextOptions& aContextOptions);
830 void UpdateLanguages(const nsTArray<nsString>& aLanguages);
832 void UpdateJSWorkerMemoryParameter(JSGCParamKey key, uint32_t value);
834 #ifdef JS_GC_ZEAL
835 void UpdateGCZeal(uint8_t aGCZeal, uint32_t aFrequency);
836 #endif
838 void OfflineStatusChangeEvent(bool aIsOffline);
840 nsresult Dispatch(already_AddRefed<WorkerRunnable> aRunnable,
841 nsIEventTarget* aSyncLoopTarget = nullptr);
843 nsresult DispatchControlRunnable(
844 already_AddRefed<WorkerControlRunnable> aWorkerControlRunnable);
846 nsresult DispatchDebuggerRunnable(
847 already_AddRefed<WorkerRunnable> aDebuggerRunnable);
849 #ifdef DEBUG
850 void AssertIsOnParentThread() const;
852 void AssertInnerWindowIsCorrect() const;
853 #else
854 void AssertIsOnParentThread() const {}
856 void AssertInnerWindowIsCorrect() const {}
857 #endif
859 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
860 bool PrincipalIsValid() const;
861 #endif
863 void StartCancelingTimer();
865 nsAString& Id();
867 private:
868 WorkerPrivate(WorkerPrivate* aParent, const nsAString& aScriptURL,
869 bool aIsChromeWorker, WorkerType aWorkerType,
870 const nsAString& aWorkerName,
871 const nsACString& aServiceWorkerScope,
872 WorkerLoadInfo& aLoadInfo);
874 ~WorkerPrivate();
876 bool MayContinueRunning() {
877 AssertIsOnWorkerThread();
879 WorkerStatus status;
881 MutexAutoLock lock(mMutex);
882 status = mStatus;
885 if (status < Canceling) {
886 return true;
889 return false;
892 void CancelAllTimeouts();
894 enum class ProcessAllControlRunnablesResult {
895 // We did not process anything.
896 Nothing,
897 // We did process something, states may have changed, but we can keep
898 // executing script.
899 MayContinue,
900 // We did process something, and should not continue executing script.
901 Abort
904 ProcessAllControlRunnablesResult ProcessAllControlRunnables() {
905 MutexAutoLock lock(mMutex);
906 return ProcessAllControlRunnablesLocked();
909 ProcessAllControlRunnablesResult ProcessAllControlRunnablesLocked();
911 void EnableMemoryReporter();
913 void DisableMemoryReporter();
915 void WaitForWorkerEvents();
917 // If the worker shutdown status is equal or greater then aFailStatus, this
918 // operation will fail and nullptr will be returned. See WorkerHolder.h for
919 // more information about the correct value to use.
920 already_AddRefed<nsIEventTarget> CreateNewSyncLoop(WorkerStatus aFailStatus);
922 bool RunCurrentSyncLoop();
924 bool DestroySyncLoop(uint32_t aLoopIndex);
926 void InitializeGCTimers();
928 enum GCTimerMode { PeriodicTimer = 0, IdleTimer, NoTimer };
930 void SetGCTimerMode(GCTimerMode aMode);
932 void ShutdownGCTimers();
934 bool AddHolder(WorkerHolder* aHolder, WorkerStatus aFailStatus);
936 void RemoveHolder(WorkerHolder* aHolder);
938 void NotifyHolders(WorkerStatus aStatus);
940 bool HasActiveHolders() {
941 MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
942 return !(data->mChildWorkers.IsEmpty() && data->mTimeouts.IsEmpty() &&
943 data->mHolders.IsEmpty());
946 // Internal logic to dispatch a runnable. This is separate from Dispatch()
947 // to allow runnables to be atomically dispatched in bulk.
948 nsresult DispatchLockHeld(already_AddRefed<WorkerRunnable> aRunnable,
949 nsIEventTarget* aSyncLoopTarget,
950 const MutexAutoLock& aProofOfLock);
952 // This method dispatches a simple runnable that starts the shutdown procedure
953 // after a self.close(). This method is called after a ClearMainEventQueue()
954 // to be sure that the canceling runnable is the only one in the queue. We
955 // need this async operation to be sure that all the current JS code is
956 // executed.
957 void DispatchCancelingRunnable();
959 class EventTarget;
960 friend class EventTarget;
961 friend class mozilla::dom::WorkerHolder;
962 friend class AutoSyncLoopHolder;
964 struct TimeoutInfo;
966 class MemoryReporter;
967 friend class MemoryReporter;
969 friend class mozilla::dom::WorkerThread;
971 SharedMutex mMutex;
972 mozilla::CondVar mCondVar;
974 WorkerPrivate* mParent;
976 nsString mScriptURL;
978 // This is the worker name for shared workers and dedicated workers.
979 nsString mWorkerName;
981 WorkerType mWorkerType;
983 // The worker is owned by its thread, which is represented here. This is set
984 // in Constructor() and emptied by WorkerFinishedRunnable, and conditionally
985 // traversed by the cycle collector if the busy count is zero.
987 // There are 4 ways a worker can be terminated:
988 // 1. GC/CC - When the worker is in idle state (busycount == 0), it allows to
989 // traverse the 'hidden' mParentEventTargetRef pointer. This is the exposed
990 // Worker webidl object. Doing this, CC will be able to detect a cycle and
991 // Unlink is called. In Unlink, Worker calls Cancel().
992 // 2. Worker::Cancel() is called - the shutdown procedure starts immediately.
993 // 3. WorkerScope::Close() is called - Similar to point 2.
994 // 4. xpcom-shutdown notification - We call Kill().
995 RefPtr<Worker> mParentEventTargetRef;
996 RefPtr<WorkerPrivate> mSelfRef;
998 // The lifetime of these objects within LoadInfo is managed explicitly;
999 // they do not need to be cycle collected.
1000 WorkerLoadInfo mLoadInfo;
1001 LocationInfo mLocationInfo;
1003 // Protected by mMutex.
1004 workerinternals::JSSettings mJSSettings;
1006 WorkerDebugger* mDebugger;
1008 workerinternals::Queue<WorkerControlRunnable*, 4> mControlQueue;
1009 workerinternals::Queue<WorkerRunnable*, 4> mDebuggerQueue;
1011 // Touched on multiple threads, protected with mMutex.
1012 JSContext* mJSContext;
1013 RefPtr<WorkerThread> mThread;
1014 PRThread* mPRThread;
1016 // Accessed from main thread
1017 RefPtr<ThrottledEventQueue> mMainThreadEventTargetForMessaging;
1018 RefPtr<ThrottledEventQueue> mMainThreadEventTarget;
1020 // Accessed from worker thread and destructing thread
1021 RefPtr<WorkerEventTarget> mWorkerControlEventTarget;
1022 RefPtr<WorkerEventTarget> mWorkerHybridEventTarget;
1024 // A pauseable queue for WorkerDebuggeeRunnables directed at the main thread.
1025 // See WorkerDebuggeeRunnable for details.
1026 RefPtr<ThrottledEventQueue> mMainThreadDebuggeeEventTarget;
1028 struct SyncLoopInfo {
1029 explicit SyncLoopInfo(EventTarget* aEventTarget);
1031 RefPtr<EventTarget> mEventTarget;
1032 bool mCompleted;
1033 bool mResult;
1034 #ifdef DEBUG
1035 bool mHasRun;
1036 #endif
1039 // This is only modified on the worker thread, but in DEBUG builds
1040 // AssertValidSyncLoop function iterates it on other threads. Therefore
1041 // modifications are done with mMutex held *only* in DEBUG builds.
1042 nsTArray<nsAutoPtr<SyncLoopInfo>> mSyncLoopStack;
1044 nsCOMPtr<nsITimer> mCancelingTimer;
1046 // fired on the main thread if the worker script fails to load
1047 nsCOMPtr<nsIRunnable> mLoadFailedRunnable;
1049 RefPtr<PerformanceStorage> mPerformanceStorage;
1051 RefPtr<WorkerCSPEventListener> mCSPEventListener;
1053 // Protected by mMutex.
1054 nsTArray<RefPtr<WorkerRunnable>> mPreStartRunnables;
1056 // Only touched on the parent thread. This is set only if IsSharedWorker().
1057 RefPtr<RemoteWorkerChild> mRemoteWorkerController;
1059 JS::UniqueChars mDefaultLocale; // nulled during worker JSContext init
1060 TimeStamp mKillTime;
1061 WorkerStatus mParentStatus;
1062 WorkerStatus mStatus;
1064 // This is touched on parent thread only, but it can be read on a different
1065 // thread before crashing because hanging.
1066 Atomic<uint64_t> mBusyCount;
1068 Atomic<bool> mLoadingWorkerScript;
1070 TimeStamp mCreationTimeStamp;
1071 DOMHighResTimeStamp mCreationTimeHighRes;
1073 // Things touched on worker thread only.
1074 struct WorkerThreadAccessible {
1075 explicit WorkerThreadAccessible(WorkerPrivate* aParent);
1077 RefPtr<WorkerGlobalScope> mScope;
1078 RefPtr<WorkerDebuggerGlobalScope> mDebuggerScope;
1079 nsTArray<WorkerPrivate*> mChildWorkers;
1080 nsTObserverArray<WorkerHolder*> mHolders;
1081 nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts;
1083 nsCOMPtr<nsITimer> mTimer;
1084 nsCOMPtr<nsITimerCallback> mTimerRunnable;
1086 nsCOMPtr<nsITimer> mGCTimer;
1088 RefPtr<MemoryReporter> mMemoryReporter;
1090 UniquePtr<ClientSource> mClientSource;
1092 uint32_t mNumHoldersPreventingShutdownStart;
1093 uint32_t mDebuggerEventLoopLevel;
1095 uint32_t mErrorHandlerRecursionCount;
1096 uint32_t mNextTimeoutId;
1098 bool mFrozen;
1099 bool mTimerRunning;
1100 bool mRunningExpiredTimeouts;
1101 bool mPeriodicGCTimerRunning;
1102 bool mIdleGCTimerRunning;
1103 bool mOnLine;
1105 ThreadBound<WorkerThreadAccessible> mWorkerThreadAccessible;
1107 uint32_t mPostSyncLoopOperations;
1109 // List of operations to do at the end of the last sync event loop.
1110 enum {
1111 ePendingEventQueueClearing = 0x01,
1112 eDispatchCancelingRunnable = 0x02,
1115 bool mParentWindowPaused;
1117 bool mCancelAllPendingRunnables;
1118 bool mWorkerScriptExecutedSuccessfully;
1119 bool mFetchHandlerWasAdded;
1120 bool mMainThreadObjectsForgotten;
1121 bool mIsChromeWorker;
1122 bool mParentFrozen;
1124 // mIsSecureContext is set once in our constructor; after that it can be read
1125 // from various threads.
1127 // It's a bit unfortunate that we have to have an out-of-band boolean for
1128 // this, but we need access to this state from the parent thread, and we can't
1129 // use our global object's secure state there.
1130 const bool mIsSecureContext;
1132 bool mDebuggerRegistered;
1134 // During registration, this worker may be marked as not being ready to
1135 // execute debuggee runnables or content.
1137 // Protected by mMutex.
1138 bool mDebuggerReady;
1139 nsTArray<RefPtr<WorkerRunnable>> mDelayedDebuggeeRunnables;
1141 // mIsInAutomation is true when we're running in test automation.
1142 // We expose some extra testing functions in that case.
1143 bool mIsInAutomation;
1145 RefPtr<mozilla::PerformanceCounter> mPerformanceCounter;
1147 nsString mID;
1150 class AutoSyncLoopHolder {
1151 WorkerPrivate* mWorkerPrivate;
1152 nsCOMPtr<nsIEventTarget> mTarget;
1153 uint32_t mIndex;
1155 public:
1156 // See CreateNewSyncLoop() for more information about the correct value to use
1157 // for aFailStatus.
1158 AutoSyncLoopHolder(WorkerPrivate* aWorkerPrivate, WorkerStatus aFailStatus)
1159 : mWorkerPrivate(aWorkerPrivate),
1160 mTarget(aWorkerPrivate->CreateNewSyncLoop(aFailStatus)),
1161 mIndex(aWorkerPrivate->mSyncLoopStack.Length() - 1) {
1162 aWorkerPrivate->AssertIsOnWorkerThread();
1165 ~AutoSyncLoopHolder() {
1166 if (mWorkerPrivate && mTarget) {
1167 mWorkerPrivate->AssertIsOnWorkerThread();
1168 mWorkerPrivate->StopSyncLoop(mTarget, false);
1169 mWorkerPrivate->DestroySyncLoop(mIndex);
1173 bool Run() {
1174 WorkerPrivate* workerPrivate = mWorkerPrivate;
1175 mWorkerPrivate = nullptr;
1177 workerPrivate->AssertIsOnWorkerThread();
1179 return workerPrivate->RunCurrentSyncLoop();
1182 nsIEventTarget* GetEventTarget() const {
1183 // This can be null if CreateNewSyncLoop() fails.
1184 return mTarget;
1188 } // namespace dom
1189 } // namespace mozilla
1191 #endif /* mozilla_dom_workers_workerprivate_h__ */