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__
11 #include "MainThreadUtils.h"
12 #include "ScriptLoader.h"
13 #include "js/ContextOptions.h"
14 #include "mozilla/Attributes.h"
15 #include "mozilla/AutoRestore.h"
16 #include "mozilla/CondVar.h"
17 #include "mozilla/DOMEventTargetHelper.h"
18 #include "mozilla/Maybe.h"
19 #include "mozilla/MozPromise.h"
20 #include "mozilla/OriginTrials.h"
21 #include "mozilla/PerformanceCounter.h"
22 #include "mozilla/RelativeTimeline.h"
23 #include "mozilla/Result.h"
24 #include "mozilla/StorageAccess.h"
25 #include "mozilla/ThreadBound.h"
26 #include "mozilla/ThreadSafeWeakPtr.h"
27 #include "mozilla/UniquePtr.h"
28 #include "mozilla/UseCounter.h"
29 #include "mozilla/dom/ClientSource.h"
30 #include "mozilla/dom/FlippedOnce.h"
31 #include "mozilla/dom/Timeout.h"
32 #include "mozilla/dom/quota/CheckedUnsafePtr.h"
33 #include "mozilla/dom/Worker.h"
34 #include "mozilla/dom/WorkerCommon.h"
35 #include "mozilla/dom/WorkerLoadInfo.h"
36 #include "mozilla/dom/WorkerStatus.h"
37 #include "mozilla/dom/workerinternals/JSSettings.h"
38 #include "mozilla/dom/workerinternals/Queue.h"
39 #include "mozilla/dom/JSExecutionManager.h"
40 #include "mozilla/StaticPrefs_extensions.h"
41 #include "nsContentUtils.h"
42 #include "nsIChannel.h"
43 #include "nsIContentSecurityPolicy.h"
44 #include "nsIEventTarget.h"
45 #include "nsILoadInfo.h"
46 #include "nsTObserverArray.h"
48 class nsIThreadInternal
;
55 class ThrottledEventQueue
;
58 class RemoteWorkerChild
;
60 // If you change this, the corresponding list in nsIWorkerDebugger.idl needs
61 // to be updated too. And histograms enum for worker use counters uses the same
62 // order of worker kind. Please also update dom/base/usecounters.py.
63 enum WorkerKind
{ WorkerKindDedicated
, WorkerKindShared
, WorkerKindService
};
68 class JSExecutionManager
;
70 class UniqueMessagePortId
;
71 class PerformanceStorage
;
73 class WorkerControlRunnable
;
74 class WorkerCSPEventListener
;
76 class WorkerDebuggerGlobalScope
;
77 class WorkerErrorReport
;
78 class WorkerEventTarget
;
79 class WorkerGlobalScope
;
82 class WorkerDebuggeeRunnable
;
85 // SharedMutex is a small wrapper around an (internal) reference-counted Mutex
86 // object. It exists to avoid changing a lot of code to use Mutex* instead of
88 class CAPABILITY SharedMutex
{
89 using Mutex
= mozilla::Mutex
;
91 class CAPABILITY RefCountedMutex final
: public Mutex
{
93 explicit RefCountedMutex(const char* aName
) : Mutex(aName
) {}
95 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedMutex
)
98 ~RefCountedMutex() = default;
101 const RefPtr
<RefCountedMutex
> mMutex
;
104 explicit SharedMutex(const char* aName
)
105 : mMutex(new RefCountedMutex(aName
)) {}
107 SharedMutex(const SharedMutex
& aOther
) = default;
109 operator Mutex
&() RETURN_CAPABILITY(this) { return *mMutex
; }
111 operator const Mutex
&() const RETURN_CAPABILITY(this) { return *mMutex
; }
113 // We need these to make thread-safety analysis work
114 void Lock() CAPABILITY_ACQUIRE() { mMutex
->Lock(); }
115 void Unlock() CAPABILITY_RELEASE() { mMutex
->Unlock(); }
117 // We can assert we own 'this', but we can't assert we hold mMutex
118 void AssertCurrentThreadOwns() const
119 ASSERT_CAPABILITY(this) NO_THREAD_SAFETY_ANALYSIS
{
120 mMutex
->AssertCurrentThreadOwns();
124 nsString
ComputeWorkerPrivateId();
126 class WorkerPrivate final
127 : public RelativeTimeline
,
128 public SupportsCheckedUnsafePtr
<CheckIf
<DiagnosticAssertEnabled
>> {
130 struct LocationInfo
{
142 NS_INLINE_DECL_REFCOUNTING(WorkerPrivate
)
144 static already_AddRefed
<WorkerPrivate
> Constructor(
145 JSContext
* aCx
, const nsAString
& aScriptURL
, bool aIsChromeWorker
,
146 WorkerKind aWorkerKind
, const nsAString
& aWorkerName
,
147 const nsACString
& aServiceWorkerScope
, WorkerLoadInfo
* aLoadInfo
,
148 ErrorResult
& aRv
, nsString aId
= u
""_ns
);
150 enum LoadGroupBehavior
{ InheritLoadGroup
, OverrideLoadGroup
};
152 static nsresult
GetLoadInfo(JSContext
* aCx
, nsPIDOMWindowInner
* aWindow
,
153 WorkerPrivate
* aParent
,
154 const nsAString
& aScriptURL
, bool aIsChromeWorker
,
155 LoadGroupBehavior aLoadGroupBehavior
,
156 WorkerKind aWorkerKind
,
157 WorkerLoadInfo
* aLoadInfo
);
159 void Traverse(nsCycleCollectionTraversalCallback
& aCb
);
161 void ClearSelfAndParentEventTargetRef() {
162 AssertIsOnParentThread();
163 MOZ_ASSERT(mSelfRef
);
164 mParentEventTargetRef
= nullptr;
168 // May be called on any thread...
171 // Called on the parent thread.
172 bool Notify(WorkerStatus aStatus
);
174 bool Cancel() { return Notify(Canceling
); }
176 bool Close() REQUIRES(mMutex
);
178 // The passed principal must be the Worker principal in case of a
179 // ServiceWorker and the loading principal for any other type.
180 static void OverrideLoadInfoLoadGroup(WorkerLoadInfo
& aLoadInfo
,
181 nsIPrincipal
* aPrincipal
);
183 bool IsDebuggerRegistered() NO_THREAD_SAFETY_ANALYSIS
{
184 AssertIsOnMainThread();
186 // No need to lock here since this is only ever modified by the same thread.
187 return mDebuggerRegistered
; // would give a thread-safety warning
190 bool ExtensionAPIAllowed() {
192 StaticPrefs::extensions_backgroundServiceWorker_enabled_AtStartup() &&
193 mExtensionAPIAllowed
);
196 void SetIsDebuggerRegistered(bool aDebuggerRegistered
) {
197 AssertIsOnMainThread();
199 MutexAutoLock
lock(mMutex
);
201 MOZ_ASSERT(mDebuggerRegistered
!= aDebuggerRegistered
);
202 mDebuggerRegistered
= aDebuggerRegistered
;
207 void WaitForIsDebuggerRegistered(bool aDebuggerRegistered
) {
208 AssertIsOnParentThread();
210 // Yield so that the main thread won't be blocked.
211 AutoYieldJSThreadExecution yield
;
213 MOZ_ASSERT(!NS_IsMainThread());
215 MutexAutoLock
lock(mMutex
);
217 while (mDebuggerRegistered
!= aDebuggerRegistered
) {
222 nsresult
SetIsDebuggerReady(bool aReady
);
224 WorkerDebugger
* Debugger() const {
225 AssertIsOnMainThread();
227 MOZ_ASSERT(mDebugger
);
231 const OriginTrials
& Trials() const { return mLoadInfo
.mTrials
; }
233 void SetDebugger(WorkerDebugger
* aDebugger
) {
234 AssertIsOnMainThread();
236 MOZ_ASSERT(mDebugger
!= aDebugger
);
237 mDebugger
= aDebugger
;
240 JS::UniqueChars
AdoptDefaultLocale() {
241 MOZ_ASSERT(mDefaultLocale
,
242 "the default locale must have been successfully set for anyone "
243 "to be trying to adopt it");
244 return std::move(mDefaultLocale
);
248 * Invoked by WorkerThreadPrimaryRunnable::Run if it already called
249 * SetWorkerPrivateInWorkerThread but has to bail out on initialization before
250 * calling DoRunLoop because PBackground failed to initialize or something
251 * like that. Note that there's currently no point earlier than this that
252 * failure can be reported.
254 * When this happens, the worker will need to be deleted, plus the call to
255 * SetWorkerPrivateInWorkerThread will have scheduled all the
256 * mPreStartRunnables which need to be cleaned up after, as well as any
257 * scheduled control runnables. We're somewhat punting on debugger runnables
258 * for now, which may leak, but the intent is to moot this whole scenario via
259 * shutdown blockers, so we don't want the extra complexity right now.
261 void RunLoopNeverRan();
264 void DoRunLoop(JSContext
* aCx
);
266 void UnrootGlobalScopes();
268 bool InterruptCallback(JSContext
* aCx
);
270 bool IsOnCurrentThread();
272 void CloseInternal();
274 bool FreezeInternal();
278 void PropagateStorageAccessPermissionGrantedInternal();
280 void TraverseTimeouts(nsCycleCollectionTraversalCallback
& aCallback
);
282 void UnlinkTimeouts();
284 bool ModifyBusyCountFromWorker(bool aIncrease
);
286 bool AddChildWorker(WorkerPrivate
& aChildWorker
);
288 void RemoveChildWorker(WorkerPrivate
& aChildWorker
);
290 void PostMessageToParent(JSContext
* aCx
, JS::Handle
<JS::Value
> aMessage
,
291 const Sequence
<JSObject
*>& aTransferable
,
294 void PostMessageToParentMessagePort(JSContext
* aCx
,
295 JS::Handle
<JS::Value
> aMessage
,
296 const Sequence
<JSObject
*>& aTransferable
,
299 MOZ_CAN_RUN_SCRIPT
void EnterDebuggerEventLoop();
301 void LeaveDebuggerEventLoop();
303 void PostMessageToDebugger(const nsAString
& aMessage
);
305 void SetDebuggerImmediate(Function
& aHandler
, ErrorResult
& aRv
);
307 void ReportErrorToDebugger(const nsAString
& aFilename
, uint32_t aLineno
,
308 const nsAString
& aMessage
);
310 bool NotifyInternal(WorkerStatus aStatus
);
312 void ReportError(JSContext
* aCx
, JS::ConstUTF8CharsZ aToStringResult
,
313 JSErrorReport
* aReport
);
315 static void ReportErrorToConsole(const char* aMessage
);
317 static void ReportErrorToConsole(const char* aMessage
,
318 const nsTArray
<nsString
>& aParams
);
320 int32_t SetTimeout(JSContext
* aCx
, TimeoutHandler
* aHandler
, int32_t aTimeout
,
321 bool aIsInterval
, Timeout::Reason aReason
,
324 void ClearTimeout(int32_t aId
, Timeout::Reason aReason
);
326 MOZ_CAN_RUN_SCRIPT
bool RunExpiredTimeouts(JSContext
* aCx
);
328 bool RescheduleTimeoutTimer(JSContext
* aCx
);
330 void UpdateContextOptionsInternal(JSContext
* aCx
,
331 const JS::ContextOptions
& aContextOptions
);
333 void UpdateLanguagesInternal(const nsTArray
<nsString
>& aLanguages
);
335 void UpdateJSWorkerMemoryParameterInternal(JSContext
* aCx
, JSGCParamKey key
,
336 Maybe
<uint32_t> aValue
);
338 enum WorkerRanOrNot
{ WorkerNeverRan
= 0, WorkerRan
};
340 void ScheduleDeletion(WorkerRanOrNot aRanOrNot
);
342 bool CollectRuntimeStats(JS::RuntimeStats
* aRtStats
, bool aAnonymize
);
345 void UpdateGCZealInternal(JSContext
* aCx
, uint8_t aGCZeal
,
346 uint32_t aFrequency
);
349 void SetLowMemoryStateInternal(JSContext
* aCx
, bool aState
);
351 void GarbageCollectInternal(JSContext
* aCx
, bool aShrinking
,
352 bool aCollectChildren
);
354 void CycleCollectInternal(bool aCollectChildren
);
356 void OfflineStatusChangeEventInternal(bool aIsOffline
);
358 void MemoryPressureInternal();
360 void SetFetchHandlerWasAdded() {
361 MOZ_ASSERT(IsServiceWorker());
362 AssertIsOnWorkerThread();
363 mFetchHandlerWasAdded
= true;
366 bool FetchHandlerWasAdded() const {
367 MOZ_ASSERT(IsServiceWorker());
368 AssertIsOnWorkerThread();
369 return mFetchHandlerWasAdded
;
372 JSContext
* GetJSContext() const NO_THREAD_SAFETY_ANALYSIS
{
373 // mJSContext is only modified on the worker thread, so workerthread code
374 // can safely read it without a lock
375 AssertIsOnWorkerThread();
379 WorkerGlobalScope
* GlobalScope() const {
380 auto data
= mWorkerThreadAccessible
.Access();
384 WorkerDebuggerGlobalScope
* DebuggerGlobalScope() const {
385 auto data
= mWorkerThreadAccessible
.Access();
386 return data
->mDebuggerScope
;
389 // Get the global associated with the current nested event loop. Will return
390 // null if we're not in a nested event loop or that nested event loop does not
391 // have an associated global.
392 nsIGlobalObject
* GetCurrentEventLoopGlobal() const {
393 auto data
= mWorkerThreadAccessible
.Access();
394 return data
->mCurrentEventLoopGlobal
;
397 nsICSPEventListener
* CSPEventListener() const;
399 void SetThread(WorkerThread
* aThread
);
401 void SetWorkerPrivateInWorkerThread(WorkerThread
* aThread
);
403 void ResetWorkerPrivateInWorkerThread();
405 bool IsOnWorkerThread() const;
407 void AssertIsOnWorkerThread() const
416 void BeginCTypesCall();
419 void EndCTypesCall();
421 void BeginCTypesCallback();
423 void EndCTypesCallback();
425 bool ConnectMessagePort(JSContext
* aCx
, UniqueMessagePortId
& aIdentifier
);
427 WorkerGlobalScope
* GetOrCreateGlobalScope(JSContext
* aCx
);
429 WorkerDebuggerGlobalScope
* CreateDebuggerGlobalScope(JSContext
* aCx
);
431 bool RegisterBindings(JSContext
* aCx
, JS::Handle
<JSObject
*> aGlobal
);
433 bool RegisterDebuggerBindings(JSContext
* aCx
, JS::Handle
<JSObject
*> aGlobal
);
435 bool OnLine() const {
436 auto data
= mWorkerThreadAccessible
.Access();
437 return data
->mOnLine
;
440 void StopSyncLoop(nsIEventTarget
* aSyncLoopTarget
, bool aResult
);
442 bool AllPendingRunnablesShouldBeCanceled() const {
443 return mCancelAllPendingRunnables
;
446 void ClearMainEventQueue(WorkerRanOrNot aRanOrNot
);
448 void ClearDebuggerEventQueue();
450 void OnProcessNextEvent();
452 void AfterProcessNextEvent();
454 void AssertValidSyncLoop(nsIEventTarget
* aSyncLoopTarget
)
462 void SetWorkerScriptExecutedSuccessfully() {
463 AssertIsOnWorkerThread();
464 // Should only be called once!
465 MOZ_ASSERT(!mWorkerScriptExecutedSuccessfully
);
466 mWorkerScriptExecutedSuccessfully
= true;
469 // Only valid after CompileScriptRunnable has finished running!
470 bool WorkerScriptExecutedSuccessfully() const {
471 AssertIsOnWorkerThread();
472 return mWorkerScriptExecutedSuccessfully
;
475 // Get the event target to use when dispatching to the main thread
476 // from this Worker thread. This may be the main thread itself or
477 // a ThrottledEventQueue to the main thread.
478 nsIEventTarget
* MainThreadEventTargetForMessaging();
480 nsresult
DispatchToMainThreadForMessaging(
481 nsIRunnable
* aRunnable
, uint32_t aFlags
= NS_DISPATCH_NORMAL
);
483 nsresult
DispatchToMainThreadForMessaging(
484 already_AddRefed
<nsIRunnable
> aRunnable
,
485 uint32_t aFlags
= NS_DISPATCH_NORMAL
);
487 nsIEventTarget
* MainThreadEventTarget();
489 nsresult
DispatchToMainThread(nsIRunnable
* aRunnable
,
490 uint32_t aFlags
= NS_DISPATCH_NORMAL
);
492 nsresult
DispatchToMainThread(already_AddRefed
<nsIRunnable
> aRunnable
,
493 uint32_t aFlags
= NS_DISPATCH_NORMAL
);
495 nsresult
DispatchDebuggeeToMainThread(
496 already_AddRefed
<WorkerDebuggeeRunnable
> aRunnable
,
497 uint32_t aFlags
= NS_DISPATCH_NORMAL
);
499 // Get an event target that will dispatch runnables as control runnables on
500 // the worker thread. Implement nsICancelableRunnable if you wish to take
501 // action on cancelation.
502 nsISerialEventTarget
* ControlEventTarget();
504 // Get an event target that will attempt to dispatch a normal WorkerRunnable,
505 // but if that fails will then fall back to a control runnable.
506 nsISerialEventTarget
* HybridEventTarget();
508 void DumpCrashInformation(nsACString
& aString
);
510 ClientType
GetClientType() const;
512 bool EnsureCSPEventListener();
514 void EnsurePerformanceStorage();
516 bool GetExecutionGranted() const;
517 void SetExecutionGranted(bool aGranted
);
519 void ScheduleTimeSliceExpiration(uint32_t aDelay
);
520 void CancelTimeSliceExpiration();
522 JSExecutionManager
* GetExecutionManager() const;
523 void SetExecutionManager(JSExecutionManager
* aManager
);
525 void ExecutionReady();
527 PerformanceStorage
* GetPerformanceStorage();
529 PerformanceCounter
& MutablePerformanceCounterRef() const {
530 return *mPerformanceCounter
;
533 const PerformanceCounter
& PerformanceCounterRef() const {
534 return MutablePerformanceCounterRef();
537 bool IsAcceptingEvents() {
538 AssertIsOnParentThread();
540 MutexAutoLock
lock(mMutex
);
541 return mParentStatus
< Canceling
;
544 WorkerStatus
ParentStatusProtected() {
545 AssertIsOnParentThread();
546 MutexAutoLock
lock(mMutex
);
547 return mParentStatus
;
550 WorkerStatus
ParentStatus() const REQUIRES(mMutex
) {
551 mMutex
.AssertCurrentThreadOwns();
552 return mParentStatus
;
555 Worker
* ParentEventTargetRef() const {
556 MOZ_DIAGNOSTIC_ASSERT(mParentEventTargetRef
);
557 return mParentEventTargetRef
;
560 void SetParentEventTargetRef(Worker
* aParentEventTargetRef
) {
561 MOZ_DIAGNOSTIC_ASSERT(aParentEventTargetRef
);
562 MOZ_DIAGNOSTIC_ASSERT(!mParentEventTargetRef
);
563 mParentEventTargetRef
= aParentEventTargetRef
;
566 bool ModifyBusyCount(bool aIncrease
);
568 // This method is used by RuntimeService to know what is going wrong the
570 uint32_t BusyCount() { return mBusyCount
; }
572 // Check whether this worker is a secure context. For use from the parent
573 // thread only; the canonical "is secure context" boolean is stored on the
574 // compartment of the worker global. The only reason we don't
575 // AssertIsOnParentThread() here is so we can assert that this value matches
576 // the one on the compartment, which has to be done from the worker thread.
577 bool IsSecureContext() const { return mIsSecureContext
; }
579 // Check whether we're running in automation.
580 bool IsInAutomation() const { return mIsInAutomation
; }
582 bool IsPrivilegedAddonGlobal() const { return mIsPrivilegedAddonGlobal
; }
584 TimeStamp
CreationTimeStamp() const { return mCreationTimeStamp
; }
586 DOMHighResTimeStamp
CreationTime() const { return mCreationTimeHighRes
; }
588 DOMHighResTimeStamp
TimeStampToDOMHighRes(const TimeStamp
& aTimeStamp
) const {
589 MOZ_ASSERT(!aTimeStamp
.IsNull());
590 TimeDuration duration
= aTimeStamp
- mCreationTimeStamp
;
591 return duration
.ToMilliseconds();
594 LocationInfo
& GetLocationInfo() { return mLocationInfo
; }
596 void CopyJSSettings(workerinternals::JSSettings
& aSettings
) {
597 mozilla::MutexAutoLock
lock(mMutex
);
598 aSettings
= mJSSettings
;
601 void CopyJSRealmOptions(JS::RealmOptions
& aOptions
) {
602 mozilla::MutexAutoLock
lock(mMutex
);
603 aOptions
= IsChromeWorker() ? mJSSettings
.chromeRealmOptions
604 : mJSSettings
.contentRealmOptions
;
607 // The ability to be a chrome worker is orthogonal to the type of
608 // worker [Dedicated|Shared|Service].
609 bool IsChromeWorker() const { return mIsChromeWorker
; }
611 // TODO: Invariants require that the parent worker out-live any child
612 // worker, so WorkerPrivate* should be safe in the moment of calling.
613 // We would like to have stronger type-system annotated/enforced handling.
614 WorkerPrivate
* GetParent() const { return mParent
; }
616 bool IsFrozen() const {
617 AssertIsOnParentThread();
618 return mParentFrozen
;
621 bool IsParentWindowPaused() const {
622 AssertIsOnParentThread();
623 return mParentWindowPaused
;
626 // When we debug a worker, we want to disconnect the window and the worker
627 // communication. This happens calling this method.
628 // Note: this method doesn't suspend the worker! Use Freeze/Thaw instead.
629 void ParentWindowPaused();
631 void ParentWindowResumed();
633 const nsString
& ScriptURL() const { return mScriptURL
; }
635 const nsString
& WorkerName() const { return mWorkerName
; }
637 WorkerKind
Kind() const { return mWorkerKind
; }
639 bool IsDedicatedWorker() const { return mWorkerKind
== WorkerKindDedicated
; }
641 bool IsSharedWorker() const { return mWorkerKind
== WorkerKindShared
; }
643 bool IsServiceWorker() const { return mWorkerKind
== WorkerKindService
; }
645 nsContentPolicyType
ContentPolicyType() const {
646 return ContentPolicyType(mWorkerKind
);
649 static nsContentPolicyType
ContentPolicyType(WorkerKind aWorkerKind
) {
650 switch (aWorkerKind
) {
651 case WorkerKindDedicated
:
652 return nsIContentPolicy::TYPE_INTERNAL_WORKER
;
653 case WorkerKindShared
:
654 return nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER
;
655 case WorkerKindService
:
656 return nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER
;
658 MOZ_ASSERT_UNREACHABLE("Invalid worker type");
659 return nsIContentPolicy::TYPE_INVALID
;
663 nsIScriptContext
* GetScriptContext() const {
664 AssertIsOnMainThread();
665 return mLoadInfo
.mScriptContext
;
668 const nsCString
& Domain() const { return mLoadInfo
.mDomain
; }
670 bool IsFromWindow() const { return mLoadInfo
.mFromWindow
; }
672 nsLoadFlags
GetLoadFlags() const { return mLoadInfo
.mLoadFlags
; }
674 uint64_t WindowID() const { return mLoadInfo
.mWindowID
; }
676 uint64_t ServiceWorkerID() const { return GetServiceWorkerDescriptor().Id(); }
678 const nsCString
& ServiceWorkerScope() const {
679 return GetServiceWorkerDescriptor().Scope();
682 // This value should never change after the script load completes. Before
683 // then, it may only be called on the main thread.
684 nsIURI
* GetBaseURI() const { return mLoadInfo
.mBaseURI
; }
686 void SetBaseURI(nsIURI
* aBaseURI
);
688 nsIURI
* GetResolvedScriptURI() const { return mLoadInfo
.mResolvedScriptURI
; }
690 const nsString
& ServiceWorkerCacheName() const {
691 MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
692 AssertIsOnMainThread();
693 return mLoadInfo
.mServiceWorkerCacheName
;
696 const ServiceWorkerDescriptor
& GetServiceWorkerDescriptor() const {
697 MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
698 MOZ_DIAGNOSTIC_ASSERT(mLoadInfo
.mServiceWorkerDescriptor
.isSome());
699 return mLoadInfo
.mServiceWorkerDescriptor
.ref();
702 const ServiceWorkerRegistrationDescriptor
&
703 GetServiceWorkerRegistrationDescriptor() const {
704 MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
705 MOZ_DIAGNOSTIC_ASSERT(
706 mLoadInfo
.mServiceWorkerRegistrationDescriptor
.isSome());
707 return mLoadInfo
.mServiceWorkerRegistrationDescriptor
.ref();
710 void UpdateServiceWorkerState(ServiceWorkerState aState
) {
711 MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
712 MOZ_DIAGNOSTIC_ASSERT(mLoadInfo
.mServiceWorkerDescriptor
.isSome());
713 return mLoadInfo
.mServiceWorkerDescriptor
.ref().SetState(aState
);
716 const Maybe
<ServiceWorkerDescriptor
>& GetParentController() const {
717 return mLoadInfo
.mParentController
;
720 const ChannelInfo
& GetChannelInfo() const { return mLoadInfo
.mChannelInfo
; }
722 void SetChannelInfo(const ChannelInfo
& aChannelInfo
) {
723 AssertIsOnMainThread();
724 MOZ_ASSERT(!mLoadInfo
.mChannelInfo
.IsInitialized());
725 MOZ_ASSERT(aChannelInfo
.IsInitialized());
726 mLoadInfo
.mChannelInfo
= aChannelInfo
;
729 void InitChannelInfo(nsIChannel
* aChannel
) {
730 mLoadInfo
.mChannelInfo
.InitFromChannel(aChannel
);
733 void InitChannelInfo(const ChannelInfo
& aChannelInfo
) {
734 mLoadInfo
.mChannelInfo
= aChannelInfo
;
737 nsIPrincipal
* GetPrincipal() const {
738 AssertIsOnMainThread();
739 return mLoadInfo
.mPrincipal
;
742 nsIPrincipal
* GetLoadingPrincipal() const {
743 AssertIsOnMainThread();
744 return mLoadInfo
.mLoadingPrincipal
;
747 nsIPrincipal
* GetPartitionedPrincipal() const {
748 AssertIsOnMainThread();
749 return mLoadInfo
.mPartitionedPrincipal
;
752 const nsAString
& OriginNoSuffix() const { return mLoadInfo
.mOriginNoSuffix
; }
754 const nsACString
& Origin() const { return mLoadInfo
.mOrigin
; }
756 const nsACString
& EffectiveStoragePrincipalOrigin() const;
758 nsILoadGroup
* GetLoadGroup() const {
759 AssertIsOnMainThread();
760 return mLoadInfo
.mLoadGroup
;
763 bool UsesSystemPrincipal() const { return mLoadInfo
.mPrincipalIsSystem
; }
764 bool UsesAddonOrExpandedAddonPrincipal() const {
765 return mLoadInfo
.mPrincipalIsAddonOrExpandedAddon
;
768 const mozilla::ipc::PrincipalInfo
& GetPrincipalInfo() const {
769 return *mLoadInfo
.mPrincipalInfo
;
772 const mozilla::ipc::PrincipalInfo
& GetPartitionedPrincipalInfo() const {
773 return *mLoadInfo
.mPartitionedPrincipalInfo
;
776 uint32_t GetPrincipalHashValue() const {
777 return mLoadInfo
.mPrincipalHashValue
;
780 const mozilla::ipc::PrincipalInfo
& GetEffectiveStoragePrincipalInfo() const;
782 already_AddRefed
<nsIChannel
> ForgetWorkerChannel() {
783 AssertIsOnMainThread();
784 return mLoadInfo
.mChannel
.forget();
787 nsPIDOMWindowInner
* GetWindow() const {
788 AssertIsOnMainThread();
789 return mLoadInfo
.mWindow
;
792 nsPIDOMWindowInner
* GetAncestorWindow() const;
794 nsIContentSecurityPolicy
* GetCSP() const {
795 AssertIsOnMainThread();
796 return mLoadInfo
.mCSP
;
799 void SetCSP(nsIContentSecurityPolicy
* aCSP
);
801 nsresult
SetCSPFromHeaderValues(const nsACString
& aCSPHeaderValue
,
802 const nsACString
& aCSPReportOnlyHeaderValue
);
804 void StoreCSPOnClient();
806 const mozilla::ipc::CSPInfo
& GetCSPInfo() const {
807 return *mLoadInfo
.mCSPInfo
;
810 void UpdateReferrerInfoFromHeader(
811 const nsACString
& aReferrerPolicyHeaderValue
);
813 nsIReferrerInfo
* GetReferrerInfo() const { return mLoadInfo
.mReferrerInfo
; }
815 ReferrerPolicy
GetReferrerPolicy() const {
816 return mLoadInfo
.mReferrerInfo
->ReferrerPolicy();
819 void SetReferrerInfo(nsIReferrerInfo
* aReferrerInfo
) {
820 mLoadInfo
.mReferrerInfo
= aReferrerInfo
;
823 bool IsEvalAllowed() const { return mLoadInfo
.mEvalAllowed
; }
825 void SetEvalAllowed(bool aAllowed
) { mLoadInfo
.mEvalAllowed
= aAllowed
; }
827 bool GetReportEvalCSPViolations() const {
828 return mLoadInfo
.mReportEvalCSPViolations
;
831 void SetReportEvalCSPViolations(bool aReport
) {
832 mLoadInfo
.mReportEvalCSPViolations
= aReport
;
835 bool IsWasmEvalAllowed() const { return mLoadInfo
.mWasmEvalAllowed
; }
837 void SetWasmEvalAllowed(bool aAllowed
) {
838 mLoadInfo
.mWasmEvalAllowed
= aAllowed
;
841 bool GetReportWasmEvalCSPViolations() const {
842 return mLoadInfo
.mReportWasmEvalCSPViolations
;
845 void SetReportWasmEvalCSPViolations(bool aReport
) {
846 mLoadInfo
.mReportWasmEvalCSPViolations
= aReport
;
849 bool XHRParamsAllowed() const { return mLoadInfo
.mXHRParamsAllowed
; }
851 void SetXHRParamsAllowed(bool aAllowed
) {
852 mLoadInfo
.mXHRParamsAllowed
= aAllowed
;
855 mozilla::StorageAccess
StorageAccess() const {
856 AssertIsOnWorkerThread();
857 if (mLoadInfo
.mHasStorageAccessPermissionGranted
) {
858 return mozilla::StorageAccess::eAllow
;
861 return mLoadInfo
.mStorageAccess
;
864 bool UseRegularPrincipal() const {
865 AssertIsOnWorkerThread();
866 return mLoadInfo
.mUseRegularPrincipal
;
869 bool HasStorageAccessPermissionGranted() const {
870 AssertIsOnWorkerThread();
871 return mLoadInfo
.mHasStorageAccessPermissionGranted
;
874 nsICookieJarSettings
* CookieJarSettings() const {
876 MOZ_ASSERT(mLoadInfo
.mCookieJarSettings
);
877 return mLoadInfo
.mCookieJarSettings
;
880 const OriginAttributes
& GetOriginAttributes() const {
881 return mLoadInfo
.mOriginAttributes
;
884 // Determine if the SW testing per-window flag is set by devtools
885 bool ServiceWorkersTestingInWindow() const {
886 return mLoadInfo
.mServiceWorkersTestingInWindow
;
889 bool ShouldResistFingerprinting() const {
890 return mLoadInfo
.mShouldResistFingerprinting
;
893 // Determin if the worker was created under a third-party context.
894 bool IsThirdPartyContextToTopWindow() const {
895 return mLoadInfo
.mIsThirdPartyContextToTopWindow
;
898 bool IsWatchedByDevTools() const { return mLoadInfo
.mWatchedByDevTools
; }
900 // Determine if the worker is currently loading its top level script.
901 bool IsLoadingWorkerScript() const { return mLoadingWorkerScript
; }
903 // Called by ScriptLoader to track when this worker is loading its
905 void SetLoadingWorkerScript(bool aLoadingWorkerScript
) {
907 mLoadingWorkerScript
= aLoadingWorkerScript
;
910 RemoteWorkerChild
* GetRemoteWorkerController();
912 void SetRemoteWorkerController(RemoteWorkerChild
* aController
);
914 void SetRemoteWorkerControllerWeakRef(
915 ThreadSafeWeakPtr
<RemoteWorkerChild
> aWeakRef
);
917 ThreadSafeWeakPtr
<RemoteWorkerChild
> GetRemoteWorkerControllerWeakRef();
919 RefPtr
<GenericPromise
> SetServiceWorkerSkipWaitingFlag();
921 // We can assume that an nsPIDOMWindow will be available for Freeze, Thaw
922 // as these are only used for globals going in and out of the bfcache.
923 bool Freeze(const nsPIDOMWindowInner
* aWindow
);
925 bool Thaw(const nsPIDOMWindowInner
* aWindow
);
927 void PropagateStorageAccessPermissionGranted();
929 void EnableDebugger();
931 void DisableDebugger();
933 already_AddRefed
<WorkerRunnable
> MaybeWrapAsWorkerRunnable(
934 already_AddRefed
<nsIRunnable
> aRunnable
);
936 bool ProxyReleaseMainThreadObjects();
938 void SetLowMemoryState(bool aState
);
940 void GarbageCollect(bool aShrinking
);
944 nsresult
SetPrincipalsAndCSPOnMainThread(nsIPrincipal
* aPrincipal
,
945 nsIPrincipal
* aPartitionedPrincipal
,
946 nsILoadGroup
* aLoadGroup
,
947 nsIContentSecurityPolicy
* aCsp
);
949 nsresult
SetPrincipalsAndCSPFromChannel(nsIChannel
* aChannel
);
951 bool FinalChannelPrincipalIsValid(nsIChannel
* aChannel
);
953 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
954 bool PrincipalURIMatchesScriptURL();
957 void UpdateOverridenLoadGroup(nsILoadGroup
* aBaseLoadGroup
);
959 void WorkerScriptLoaded();
961 Document
* GetDocument() const;
963 void MemoryPressure();
965 void UpdateContextOptions(const JS::ContextOptions
& aContextOptions
);
967 void UpdateLanguages(const nsTArray
<nsString
>& aLanguages
);
969 void UpdateJSWorkerMemoryParameter(JSGCParamKey key
, Maybe
<uint32_t> value
);
972 void UpdateGCZeal(uint8_t aGCZeal
, uint32_t aFrequency
);
975 void OfflineStatusChangeEvent(bool aIsOffline
);
977 nsresult
Dispatch(already_AddRefed
<WorkerRunnable
> aRunnable
,
978 nsIEventTarget
* aSyncLoopTarget
= nullptr);
980 nsresult
DispatchControlRunnable(
981 already_AddRefed
<WorkerControlRunnable
> aWorkerControlRunnable
);
983 nsresult
DispatchDebuggerRunnable(
984 already_AddRefed
<WorkerRunnable
> aDebuggerRunnable
);
987 void AssertIsOnParentThread() const;
989 void AssertInnerWindowIsCorrect() const;
991 void AssertIsOnParentThread() const {}
993 void AssertInnerWindowIsCorrect() const {}
996 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
997 bool PrincipalIsValid() const;
1000 void StartCancelingTimer();
1002 const nsAString
& Id();
1004 const nsID
& AgentClusterId() const { return mAgentClusterId
; }
1006 bool IsSharedMemoryAllowed() const;
1008 // https://whatpr.org/html/4734/structured-data.html#cross-origin-isolated
1009 bool CrossOriginIsolated() const;
1011 void SetUseCounter(UseCounterWorker aUseCounter
) {
1012 MOZ_ASSERT(!mReportedUseCounters
);
1013 MOZ_ASSERT(aUseCounter
> UseCounterWorker::Unknown
);
1014 AssertIsOnWorkerThread();
1015 mUseCounters
[static_cast<size_t>(aUseCounter
)] = true;
1021 * If browser.tabs.remote.useCrossOriginEmbedderPolicy=false, these methods
1022 * will, depending on the return type, return a value that will avoid
1023 * assertion failures or a value that won't block loads.
1025 nsILoadInfo::CrossOriginEmbedderPolicy
GetEmbedderPolicy() const;
1027 // Fails if a policy has already been set or if `aPolicy` violates the owner's
1028 // policy, if an owner exists.
1029 mozilla::Result
<Ok
, nsresult
> SetEmbedderPolicy(
1030 nsILoadInfo::CrossOriginEmbedderPolicy aPolicy
);
1032 // `aRequest` is the request loading the worker and must be QI-able to
1033 // `nsIChannel*`. It's used to verify that the worker can indeed inherit its
1034 // owner's COEP (when an owner exists).
1036 // TODO: remove `aRequest`; currently, it's required because instances may not
1037 // always know its final, resolved script URL or have access internally to
1039 void InheritOwnerEmbedderPolicyOrNull(nsIRequest
* aRequest
);
1041 // Requires a policy to already have been set.
1042 bool MatchEmbedderPolicy(
1043 nsILoadInfo::CrossOriginEmbedderPolicy aPolicy
) const;
1045 nsILoadInfo::CrossOriginEmbedderPolicy
GetOwnerEmbedderPolicy() const;
1047 void SetCCCollectedAnything(bool collectedAnything
);
1049 uint32_t GetCurrentTimerNestingLevel() const {
1050 auto data
= mWorkerThreadAccessible
.Access();
1051 return data
->mCurrentTimerNestingLevel
;
1054 void IncreaseTopLevelWorkerFinishedRunnableCount() {
1055 ++mTopLevelWorkerFinishedRunnableCount
;
1057 void DecreaseTopLevelWorkerFinishedRunnableCount() {
1058 --mTopLevelWorkerFinishedRunnableCount
;
1060 void IncreaseWorkerFinishedRunnableCount() { ++mWorkerFinishedRunnableCount
; }
1061 void DecreaseWorkerFinishedRunnableCount() { --mWorkerFinishedRunnableCount
; }
1065 WorkerPrivate
* aParent
, const nsAString
& aScriptURL
, bool aIsChromeWorker
,
1066 WorkerKind aWorkerKind
, const nsAString
& aWorkerName
,
1067 const nsACString
& aServiceWorkerScope
, WorkerLoadInfo
& aLoadInfo
,
1068 nsString
&& aId
, const nsID
& aAgentClusterId
,
1069 const nsILoadInfo::CrossOriginOpenerPolicy aAgentClusterOpenerPolicy
);
1073 struct AgentClusterIdAndCoop
{
1075 nsILoadInfo::CrossOriginOpenerPolicy mCoop
;
1078 static AgentClusterIdAndCoop
ComputeAgentClusterIdAndCoop(
1079 WorkerPrivate
* aParent
, WorkerKind aWorkerKind
,
1080 WorkerLoadInfo
* aLoadInfo
);
1082 bool MayContinueRunning() {
1083 AssertIsOnWorkerThread();
1085 WorkerStatus status
;
1087 MutexAutoLock
lock(mMutex
);
1091 if (status
< Canceling
) {
1098 void CancelAllTimeouts();
1100 enum class ProcessAllControlRunnablesResult
{
1101 // We did not process anything.
1103 // We did process something, states may have changed, but we can keep
1104 // executing script.
1106 // We did process something, and should not continue executing script.
1110 ProcessAllControlRunnablesResult
ProcessAllControlRunnables() {
1111 MutexAutoLock
lock(mMutex
);
1112 return ProcessAllControlRunnablesLocked();
1115 ProcessAllControlRunnablesResult
ProcessAllControlRunnablesLocked()
1118 void EnableMemoryReporter();
1120 void DisableMemoryReporter();
1122 void WaitForWorkerEvents() REQUIRES(mMutex
);
1124 // If the worker shutdown status is equal or greater then aFailStatus, this
1125 // operation will fail and nullptr will be returned. See WorkerStatus.h for
1126 // more information about the correct value to use.
1127 already_AddRefed
<nsIEventTarget
> CreateNewSyncLoop(WorkerStatus aFailStatus
);
1129 bool RunCurrentSyncLoop();
1131 bool DestroySyncLoop(uint32_t aLoopIndex
);
1133 void InitializeGCTimers();
1135 enum GCTimerMode
{ PeriodicTimer
= 0, IdleTimer
, NoTimer
};
1137 void SetGCTimerMode(GCTimerMode aMode
);
1139 void ShutdownGCTimers();
1141 friend class WorkerRef
;
1143 bool AddWorkerRef(WorkerRef
* aWorkerRefer
, WorkerStatus aFailStatus
);
1145 void RemoveWorkerRef(WorkerRef
* aWorkerRef
);
1147 void NotifyWorkerRefs(WorkerStatus aStatus
);
1149 bool HasActiveWorkerRefs() {
1150 auto data
= mWorkerThreadAccessible
.Access();
1151 return !(data
->mChildWorkers
.IsEmpty() && data
->mTimeouts
.IsEmpty() &&
1152 data
->mWorkerRefs
.IsEmpty());
1155 // Internal logic to dispatch a runnable. This is separate from Dispatch()
1156 // to allow runnables to be atomically dispatched in bulk.
1157 nsresult
DispatchLockHeld(already_AddRefed
<WorkerRunnable
> aRunnable
,
1158 nsIEventTarget
* aSyncLoopTarget
,
1159 const MutexAutoLock
& aProofOfLock
) REQUIRES(mMutex
);
1161 // This method dispatches a simple runnable that starts the shutdown procedure
1162 // after a self.close(). This method is called after a ClearMainEventQueue()
1163 // to be sure that the canceling runnable is the only one in the queue. We
1164 // need this async operation to be sure that all the current JS code is
1166 void DispatchCancelingRunnable();
1168 bool GetUseCounter(UseCounterWorker aUseCounter
) {
1169 MOZ_ASSERT(aUseCounter
> UseCounterWorker::Unknown
);
1170 AssertIsOnWorkerThread();
1171 return mUseCounters
[static_cast<size_t>(aUseCounter
)];
1174 void ReportUseCounters();
1176 UniquePtr
<ClientSource
> CreateClientSource();
1178 // This method is called when corresponding script loader processes the COEP
1179 // header for the worker.
1180 // This method should be called only once in the main thread.
1181 // After this method is called the COEP value owner(window/parent worker) is
1182 // cached in mOwnerEmbedderPolicy such that it can be accessed in other
1183 // threads, i.e. WorkerThread.
1184 void EnsureOwnerEmbedderPolicy();
1187 friend class EventTarget
;
1188 friend class AutoSyncLoopHolder
;
1192 class MemoryReporter
;
1193 friend class MemoryReporter
;
1195 friend class mozilla::dom::WorkerThread
;
1198 mozilla::CondVar mCondVar
GUARDED_BY(mMutex
);
1200 // We cannot make this CheckedUnsafePtr<WorkerPrivate> as this would violate
1201 // our static assert
1202 MOZ_NON_OWNING_REF WorkerPrivate
* const mParent
;
1204 const nsString mScriptURL
;
1206 // This is the worker name for shared workers and dedicated workers.
1207 const nsString mWorkerName
;
1209 const WorkerKind mWorkerKind
;
1211 // The worker is owned by its thread, which is represented here. This is set
1212 // in Constructor() and emptied by WorkerFinishedRunnable, and conditionally
1213 // traversed by the cycle collector if the busy count is zero.
1215 // There are 4 ways a worker can be terminated:
1216 // 1. GC/CC - When the worker is in idle state (busycount == 0), it allows to
1217 // traverse the 'hidden' mParentEventTargetRef pointer. This is the exposed
1218 // Worker webidl object. Doing this, CC will be able to detect a cycle and
1219 // Unlink is called. In Unlink, Worker calls Cancel().
1220 // 2. Worker::Cancel() is called - the shutdown procedure starts immediately.
1221 // 3. WorkerScope::Close() is called - Similar to point 2.
1222 // 4. xpcom-shutdown notification - We call Kill().
1223 RefPtr
<Worker
> mParentEventTargetRef
;
1224 RefPtr
<WorkerPrivate
> mSelfRef
;
1226 // The lifetime of these objects within LoadInfo is managed explicitly;
1227 // they do not need to be cycle collected.
1228 WorkerLoadInfo mLoadInfo
;
1229 LocationInfo mLocationInfo
;
1231 // Protected by mMutex.
1232 workerinternals::JSSettings mJSSettings
GUARDED_BY(mMutex
);
1234 WorkerDebugger
* mDebugger
;
1236 workerinternals::Queue
<WorkerControlRunnable
*, 4> mControlQueue
;
1237 workerinternals::Queue
<WorkerRunnable
*, 4> mDebuggerQueue
;
1239 // Touched on multiple threads, protected with mMutex. Only modified on the
1241 JSContext
* mJSContext
GUARDED_BY(mMutex
);
1242 // mThread is only modified on the Worker thread, before calling DoRunLoop
1243 RefPtr
<WorkerThread
> mThread
GUARDED_BY(mMutex
);
1244 // mPRThread is only modified on another thread in ScheduleWorker(), and is
1245 // constant for the duration of DoRunLoop. Static mutex analysis doesn't help
1247 PRThread
* mPRThread
;
1249 // Accessed from main thread
1250 RefPtr
<ThrottledEventQueue
> mMainThreadEventTargetForMessaging
;
1251 RefPtr
<ThrottledEventQueue
> mMainThreadEventTarget
;
1253 // Accessed from worker thread and destructing thread
1254 RefPtr
<WorkerEventTarget
> mWorkerControlEventTarget
;
1255 RefPtr
<WorkerEventTarget
> mWorkerHybridEventTarget
;
1257 // A pauseable queue for WorkerDebuggeeRunnables directed at the main thread.
1258 // See WorkerDebuggeeRunnable for details.
1259 RefPtr
<ThrottledEventQueue
> mMainThreadDebuggeeEventTarget
;
1261 struct SyncLoopInfo
{
1262 explicit SyncLoopInfo(EventTarget
* aEventTarget
);
1264 RefPtr
<EventTarget
> mEventTarget
;
1272 // This is only modified on the worker thread, but in DEBUG builds
1273 // AssertValidSyncLoop function iterates it on other threads. Therefore
1274 // modifications are done with mMutex held *only* in DEBUG builds.
1275 nsTArray
<UniquePtr
<SyncLoopInfo
>> mSyncLoopStack
;
1277 nsCOMPtr
<nsITimer
> mCancelingTimer
;
1279 // fired on the main thread if the worker script fails to load
1280 nsCOMPtr
<nsIRunnable
> mLoadFailedRunnable
;
1282 RefPtr
<PerformanceStorage
> mPerformanceStorage
;
1284 RefPtr
<WorkerCSPEventListener
> mCSPEventListener
;
1286 // Protected by mMutex.
1287 nsTArray
<RefPtr
<WorkerRunnable
>> mPreStartRunnables
GUARDED_BY(mMutex
);
1289 // Only touched on the parent thread. This is set only if IsSharedWorker().
1290 RefPtr
<RemoteWorkerChild
> mRemoteWorkerController
;
1292 // This is set only if IsServiceWorker().
1293 ThreadSafeWeakPtr
<RemoteWorkerChild
> mRemoteWorkerControllerWeakRef
;
1295 JS::UniqueChars mDefaultLocale
; // nulled during worker JSContext init
1296 TimeStamp mKillTime
;
1297 WorkerStatus mParentStatus
GUARDED_BY(mMutex
);
1298 WorkerStatus mStatus
GUARDED_BY(mMutex
);
1300 // This is touched on parent thread only, but it can be read on a different
1301 // thread before crashing because hanging.
1302 Atomic
<uint64_t> mBusyCount
;
1304 Atomic
<bool> mLoadingWorkerScript
;
1306 TimeStamp mCreationTimeStamp
;
1307 DOMHighResTimeStamp mCreationTimeHighRes
;
1309 // Flags for use counters used directly by this worker.
1310 static_assert(sizeof(UseCounterWorker
) <= sizeof(size_t),
1311 "UseCounterWorker is too big");
1312 static_assert(UseCounterWorker::Count
>= static_cast<UseCounterWorker
>(0),
1313 "Should be non-negative value and safe to cast to unsigned");
1314 std::bitset
<static_cast<size_t>(UseCounterWorker::Count
)> mUseCounters
;
1315 bool mReportedUseCounters
;
1317 // This is created while creating the WorkerPrivate, so it's safe to be
1318 // touched on any thread.
1319 const nsID mAgentClusterId
;
1321 // Things touched on worker thread only.
1322 struct WorkerThreadAccessible
{
1323 explicit WorkerThreadAccessible(WorkerPrivate
* aParent
);
1325 RefPtr
<WorkerGlobalScope
> mScope
;
1326 RefPtr
<WorkerDebuggerGlobalScope
> mDebuggerScope
;
1327 // We cannot make this CheckedUnsafePtr<WorkerPrivate> as this would violate
1328 // our static assert
1329 nsTArray
<WorkerPrivate
*> mChildWorkers
;
1330 nsTObserverArray
<WorkerRef
*> mWorkerRefs
;
1331 nsTArray
<UniquePtr
<TimeoutInfo
>> mTimeouts
;
1333 nsCOMPtr
<nsITimer
> mTimer
;
1334 nsCOMPtr
<nsITimerCallback
> mTimerRunnable
;
1336 nsCOMPtr
<nsITimer
> mGCTimer
;
1338 RefPtr
<MemoryReporter
> mMemoryReporter
;
1340 // While running a nested event loop, whether a sync loop or a debugger
1341 // event loop we want to keep track of which global is running it, if any,
1342 // so runnables that run off that event loop can get at that information. In
1343 // practice this only matters for various worker debugger runnables running
1344 // against sandboxes, because all other runnables know which globals they
1345 // belong to already. We could also address this by threading the relevant
1346 // global through the chains of runnables involved, but we'd need to thread
1347 // it through some runnables that run on the main thread, and that would
1348 // require some care to make sure things get released on the correct thread,
1349 // which we'd rather avoid. This member is only accessed on the worker
1351 nsCOMPtr
<nsIGlobalObject
> mCurrentEventLoopGlobal
;
1353 // Timer that triggers an interrupt on expiration of the current time slice
1354 nsCOMPtr
<nsITimer
> mTSTimer
;
1356 // Execution manager used to regulate execution for this worker.
1357 RefPtr
<JSExecutionManager
> mExecutionManager
;
1359 // Used to relinguish clearance for CTypes Callbacks.
1360 nsTArray
<AutoYieldJSThreadExecution
> mYieldJSThreadExecution
;
1362 uint32_t mNumWorkerRefsPreventingShutdownStart
;
1363 uint32_t mDebuggerEventLoopLevel
;
1365 uint32_t mErrorHandlerRecursionCount
;
1366 int32_t mNextTimeoutId
;
1368 // Tracks the current setTimeout/setInterval nesting level.
1369 // When there isn't a TimeoutHandler on the stack, this will be 0.
1370 // Whenever setTimeout/setInterval are called, a new TimeoutInfo will be
1371 // created with a nesting level one more than the current nesting level,
1372 // saturating at the kClampTimeoutNestingLevel.
1374 // When RunExpiredTimeouts is run, it sets this value to the
1375 // TimeoutInfo::mNestingLevel for the duration of
1376 // the WorkerScriptTimeoutHandler::Call which will explicitly trigger a
1377 // microtask checkpoint so that any immediately-resolved promises will
1378 // still see the nesting level.
1379 uint32_t mCurrentTimerNestingLevel
;
1383 bool mRunningExpiredTimeouts
;
1384 bool mPeriodicGCTimerRunning
;
1385 bool mIdleGCTimerRunning
;
1387 bool mJSThreadExecutionGranted
;
1388 bool mCCCollectedAnything
;
1389 FlippedOnce
<false> mDeletionScheduled
;
1391 ThreadBound
<WorkerThreadAccessible
> mWorkerThreadAccessible
;
1393 class MOZ_RAII AutoPushEventLoopGlobal
{
1395 AutoPushEventLoopGlobal(WorkerPrivate
* aWorkerPrivate
, JSContext
* aCx
);
1396 ~AutoPushEventLoopGlobal();
1399 // We cannot make this CheckedUnsafePtr<WorkerPrivate> as this would violate
1400 // our static assert
1401 MOZ_NON_OWNING_REF WorkerPrivate
* mWorkerPrivate
;
1402 nsCOMPtr
<nsIGlobalObject
> mOldEventLoopGlobal
;
1404 friend class AutoPushEventLoopGlobal
;
1406 uint32_t mPostSyncLoopOperations
;
1408 // List of operations to do at the end of the last sync event loop.
1410 ePendingEventQueueClearing
= 0x01,
1411 eDispatchCancelingRunnable
= 0x02,
1414 bool mParentWindowPaused
;
1416 bool mCancelAllPendingRunnables
;
1417 bool mWorkerScriptExecutedSuccessfully
;
1418 bool mFetchHandlerWasAdded
;
1419 bool mMainThreadObjectsForgotten
;
1420 bool mIsChromeWorker
;
1423 // mIsSecureContext is set once in our constructor; after that it can be read
1424 // from various threads.
1426 // It's a bit unfortunate that we have to have an out-of-band boolean for
1427 // this, but we need access to this state from the parent thread, and we can't
1428 // use our global object's secure state there.
1429 const bool mIsSecureContext
;
1431 bool mDebuggerRegistered
GUARDED_BY(mMutex
);
1433 // During registration, this worker may be marked as not being ready to
1434 // execute debuggee runnables or content.
1436 // Protected by mMutex.
1437 bool mDebuggerReady
;
1438 nsTArray
<RefPtr
<WorkerRunnable
>> mDelayedDebuggeeRunnables
;
1440 // Whether this worker should have access to the WebExtension API bindings
1441 // (currently only the Extension Background ServiceWorker declared in the
1442 // extension manifest is allowed to access any WebExtension API bindings).
1443 // This default to false, and it is eventually set to true by
1444 // RemoteWorkerChild::ExecWorkerOnMainThread if the needed conditions
1446 bool mExtensionAPIAllowed
;
1448 // mIsInAutomation is true when we're running in test automation.
1449 // We expose some extra testing functions in that case.
1450 bool mIsInAutomation
;
1452 const RefPtr
<PerformanceCounter
> mPerformanceCounter
=
1453 MakeRefPtr
<PerformanceCounter
>(nsPrintfCString(
1454 "Worker:%s", NS_ConvertUTF16toUTF8(mWorkerName
).get()));
1458 // This is used to check if it's allowed to share the memory across the agent
1460 const nsILoadInfo::CrossOriginOpenerPolicy mAgentClusterOpenerPolicy
;
1462 // Member variable of this class rather than the worker global scope because
1463 // it's received on the main thread, but the global scope is thread-bound
1464 // to the worker thread, so storing the value in the global scope would
1465 // involve sacrificing the thread-bound-ness or using a WorkerRunnable, and
1466 // there isn't a strong reason to store it on the global scope other than
1467 // better consistency with the COEP spec.
1468 Maybe
<nsILoadInfo::CrossOriginEmbedderPolicy
> mEmbedderPolicy
;
1469 Maybe
<nsILoadInfo::CrossOriginEmbedderPolicy
> mOwnerEmbedderPolicy
;
1471 /* Privileged add-on flag extracted from the AddonPolicy on the nsIPrincipal
1472 * on the main thread when constructing a top-level worker. The flag is
1473 * propagated to nested workers. The flag is only allowed to take effect in
1474 * extension processes and is forbidden in content scripts in content
1475 * processes. The flag may be read on either the parent/owner thread as well
1476 * as on the worker thread itself. When bug 1443925 is fixed allowing
1477 * nsIPrincipal to be used OMT, it may be possible to remove this flag. */
1478 bool mIsPrivilegedAddonGlobal
;
1480 Atomic
<uint32_t> mTopLevelWorkerFinishedRunnableCount
;
1481 Atomic
<uint32_t> mWorkerFinishedRunnableCount
;
1484 class AutoSyncLoopHolder
{
1485 CheckedUnsafePtr
<WorkerPrivate
> mWorkerPrivate
;
1486 nsCOMPtr
<nsIEventTarget
> mTarget
;
1490 // See CreateNewSyncLoop() for more information about the correct value to use
1492 AutoSyncLoopHolder(WorkerPrivate
* aWorkerPrivate
, WorkerStatus aFailStatus
)
1493 : mWorkerPrivate(aWorkerPrivate
),
1494 mTarget(aWorkerPrivate
->CreateNewSyncLoop(aFailStatus
)),
1495 mIndex(aWorkerPrivate
->mSyncLoopStack
.Length() - 1) {
1496 aWorkerPrivate
->AssertIsOnWorkerThread();
1499 ~AutoSyncLoopHolder() {
1500 if (mWorkerPrivate
&& mTarget
) {
1501 mWorkerPrivate
->AssertIsOnWorkerThread();
1502 mWorkerPrivate
->StopSyncLoop(mTarget
, false);
1503 mWorkerPrivate
->DestroySyncLoop(mIndex
);
1508 CheckedUnsafePtr
<WorkerPrivate
> workerPrivate
= mWorkerPrivate
;
1509 mWorkerPrivate
= nullptr;
1511 workerPrivate
->AssertIsOnWorkerThread();
1513 return workerPrivate
->RunCurrentSyncLoop();
1516 nsIEventTarget
* GetEventTarget() const {
1517 // This can be null if CreateNewSyncLoop() fails.
1523 } // namespace mozilla
1525 #endif /* mozilla_dom_workers_workerprivate_h__ */