Bug 1610775 [wpt PR 21336] - Update urllib3 to 1.25.8, a=testonly
[gecko.git] / dom / workers / WorkerPrivate.h
blobcb045a486d65ca65e0e03208585e414c54012fa4
2 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #ifndef mozilla_dom_workers_workerprivate_h__
9 #define mozilla_dom_workers_workerprivate_h__
11 #include "mozilla/dom/WorkerCommon.h"
12 #include "mozilla/dom/WorkerStatus.h"
13 #include "mozilla/Attributes.h"
14 #include "mozilla/CondVar.h"
15 #include "mozilla/DOMEventTargetHelper.h"
16 #include "mozilla/MozPromise.h"
17 #include "mozilla/RelativeTimeline.h"
18 #include "mozilla/StorageAccess.h"
19 #include "mozilla/ThreadSafeWeakPtr.h"
20 #include "mozilla/UseCounter.h"
21 #include "nsContentUtils.h"
22 #include "nsIContentSecurityPolicy.h"
23 #include "nsIEventTarget.h"
24 #include "nsTObserverArray.h"
26 #include "js/ContextOptions.h"
27 #include "mozilla/dom/RemoteWorkerChild.h"
28 #include "mozilla/dom/Worker.h"
29 #include "mozilla/dom/WorkerLoadInfo.h"
30 #include "mozilla/dom/workerinternals/JSSettings.h"
31 #include "mozilla/dom/workerinternals/Queue.h"
32 #include "mozilla/PerformanceCounter.h"
33 #include "mozilla/ThreadBound.h"
35 class nsIThreadInternal;
37 namespace mozilla {
38 class ThrottledEventQueue;
39 namespace dom {
41 // If you change this, the corresponding list in nsIWorkerDebugger.idl needs
42 // to be updated too. And histograms enum for worker use counters uses the same
43 // order of worker type. Please also update dom/base/usecounters.py.
44 enum WorkerType { WorkerTypeDedicated, WorkerTypeShared, WorkerTypeService };
46 class ClientInfo;
47 class ClientSource;
48 class Function;
49 class MessagePort;
50 class UniqueMessagePortId;
51 class PerformanceStorage;
52 class TimeoutHandler;
53 class WorkerControlRunnable;
54 class WorkerCSPEventListener;
55 class WorkerDebugger;
56 class WorkerDebuggerGlobalScope;
57 class WorkerErrorReport;
58 class WorkerEventTarget;
59 class WorkerGlobalScope;
60 class WorkerRef;
61 class WorkerRunnable;
62 class WorkerDebuggeeRunnable;
63 class WorkerThread;
65 // SharedMutex is a small wrapper around an (internal) reference-counted Mutex
66 // object. It exists to avoid changing a lot of code to use Mutex* instead of
67 // Mutex&.
68 class SharedMutex {
69 typedef mozilla::Mutex Mutex;
71 class RefCountedMutex final : public Mutex {
72 public:
73 explicit RefCountedMutex(const char* aName) : Mutex(aName) {}
75 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedMutex)
77 private:
78 ~RefCountedMutex() {}
81 RefPtr<RefCountedMutex> mMutex;
83 public:
84 explicit SharedMutex(const char* aName)
85 : mMutex(new RefCountedMutex(aName)) {}
87 SharedMutex(SharedMutex& aOther) : mMutex(aOther.mMutex) {}
89 operator Mutex&() { return *mMutex; }
91 operator const Mutex&() const { return *mMutex; }
93 void AssertCurrentThreadOwns() const { mMutex->AssertCurrentThreadOwns(); }
96 nsString ComputeWorkerPrivateId();
98 class WorkerPrivate : public RelativeTimeline {
99 public:
100 struct LocationInfo {
101 nsCString mHref;
102 nsCString mProtocol;
103 nsCString mHost;
104 nsCString mHostname;
105 nsCString mPort;
106 nsCString mPathname;
107 nsCString mSearch;
108 nsCString mHash;
109 nsString mOrigin;
112 NS_INLINE_DECL_REFCOUNTING(WorkerPrivate)
114 static already_AddRefed<WorkerPrivate> Constructor(
115 JSContext* aCx, const nsAString& aScriptURL, bool aIsChromeWorker,
116 WorkerType aWorkerType, const nsAString& aWorkerName,
117 const nsACString& aServiceWorkerScope, WorkerLoadInfo* aLoadInfo,
118 ErrorResult& aRv, nsString aId = EmptyString());
120 enum LoadGroupBehavior { InheritLoadGroup, OverrideLoadGroup };
122 static nsresult GetLoadInfo(JSContext* aCx, nsPIDOMWindowInner* aWindow,
123 WorkerPrivate* aParent,
124 const nsAString& aScriptURL, bool aIsChromeWorker,
125 LoadGroupBehavior aLoadGroupBehavior,
126 WorkerType aWorkerType,
127 WorkerLoadInfo* aLoadInfo);
129 void Traverse(nsCycleCollectionTraversalCallback& aCb);
131 void ClearSelfAndParentEventTargetRef() {
132 AssertIsOnParentThread();
133 MOZ_ASSERT(mSelfRef);
134 mParentEventTargetRef = nullptr;
135 mSelfRef = nullptr;
138 // May be called on any thread...
139 bool Start();
141 // Called on the parent thread.
142 bool Notify(WorkerStatus aStatus);
144 bool Cancel() { return Notify(Canceling); }
146 bool Close();
148 // The passed principal must be the Worker principal in case of a
149 // ServiceWorker and the loading principal for any other type.
150 static void OverrideLoadInfoLoadGroup(WorkerLoadInfo& aLoadInfo,
151 nsIPrincipal* aPrincipal);
153 bool IsDebuggerRegistered() {
154 AssertIsOnMainThread();
156 // No need to lock here since this is only ever modified by the same thread.
157 return mDebuggerRegistered;
160 void SetIsDebuggerRegistered(bool aDebuggerRegistered) {
161 AssertIsOnMainThread();
163 MutexAutoLock lock(mMutex);
165 MOZ_ASSERT(mDebuggerRegistered != aDebuggerRegistered);
166 mDebuggerRegistered = aDebuggerRegistered;
168 mCondVar.Notify();
171 void WaitForIsDebuggerRegistered(bool aDebuggerRegistered) {
172 AssertIsOnParentThread();
174 MOZ_ASSERT(!NS_IsMainThread());
176 MutexAutoLock lock(mMutex);
178 while (mDebuggerRegistered != aDebuggerRegistered) {
179 mCondVar.Wait();
183 nsresult SetIsDebuggerReady(bool aReady);
185 WorkerDebugger* Debugger() const {
186 AssertIsOnMainThread();
188 MOZ_ASSERT(mDebugger);
189 return mDebugger;
192 void SetDebugger(WorkerDebugger* aDebugger) {
193 AssertIsOnMainThread();
195 MOZ_ASSERT(mDebugger != aDebugger);
196 mDebugger = aDebugger;
199 JS::UniqueChars AdoptDefaultLocale() {
200 MOZ_ASSERT(mDefaultLocale,
201 "the default locale must have been successfully set for anyone "
202 "to be trying to adopt it");
203 return std::move(mDefaultLocale);
206 MOZ_CAN_RUN_SCRIPT
207 void DoRunLoop(JSContext* aCx);
209 bool InterruptCallback(JSContext* aCx);
211 bool IsOnCurrentThread();
213 void CloseInternal();
215 bool FreezeInternal();
217 bool ThawInternal();
219 void PropagateFirstPartyStorageAccessGrantedInternal();
221 void TraverseTimeouts(nsCycleCollectionTraversalCallback& aCallback);
223 void UnlinkTimeouts();
225 bool ModifyBusyCountFromWorker(bool aIncrease);
227 bool AddChildWorker(WorkerPrivate* aChildWorker);
229 void RemoveChildWorker(WorkerPrivate* aChildWorker);
231 void PostMessageToParent(JSContext* aCx, JS::Handle<JS::Value> aMessage,
232 const Sequence<JSObject*>& aTransferable,
233 ErrorResult& aRv);
235 void PostMessageToParentMessagePort(JSContext* aCx,
236 JS::Handle<JS::Value> aMessage,
237 const Sequence<JSObject*>& aTransferable,
238 ErrorResult& aRv);
240 MOZ_CAN_RUN_SCRIPT void EnterDebuggerEventLoop();
242 void LeaveDebuggerEventLoop();
244 void PostMessageToDebugger(const nsAString& aMessage);
246 void SetDebuggerImmediate(Function& aHandler, ErrorResult& aRv);
248 void ReportErrorToDebugger(const nsAString& aFilename, uint32_t aLineno,
249 const nsAString& aMessage);
251 bool NotifyInternal(WorkerStatus aStatus);
253 void ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
254 JSErrorReport* aReport);
256 static void ReportErrorToConsole(const char* aMessage);
258 static void ReportErrorToConsole(const char* aMessage,
259 const nsTArray<nsString>& aParams);
261 int32_t SetTimeout(JSContext* aCx, TimeoutHandler* aHandler, int32_t aTimeout,
262 bool aIsInterval, ErrorResult& aRv);
264 void ClearTimeout(int32_t aId);
266 MOZ_CAN_RUN_SCRIPT bool RunExpiredTimeouts(JSContext* aCx);
268 bool RescheduleTimeoutTimer(JSContext* aCx);
270 void UpdateContextOptionsInternal(JSContext* aCx,
271 const JS::ContextOptions& aContextOptions);
273 void UpdateLanguagesInternal(const nsTArray<nsString>& aLanguages);
275 void UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key,
276 uint32_t aValue);
278 enum WorkerRanOrNot { WorkerNeverRan = 0, WorkerRan };
280 void ScheduleDeletion(WorkerRanOrNot aRanOrNot);
282 bool CollectRuntimeStats(JS::RuntimeStats* aRtStats, bool aAnonymize);
284 #ifdef JS_GC_ZEAL
285 void UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal,
286 uint32_t aFrequency);
287 #endif
289 void SetLowMemoryStateInternal(JSContext* aCx, bool aState);
291 void GarbageCollectInternal(JSContext* aCx, bool aShrinking,
292 bool aCollectChildren);
294 void CycleCollectInternal(bool aCollectChildren);
296 void OfflineStatusChangeEventInternal(bool aIsOffline);
298 void MemoryPressureInternal();
300 void SetFetchHandlerWasAdded() {
301 MOZ_ASSERT(IsServiceWorker());
302 AssertIsOnWorkerThread();
303 mFetchHandlerWasAdded = true;
306 bool FetchHandlerWasAdded() const {
307 MOZ_ASSERT(IsServiceWorker());
308 AssertIsOnWorkerThread();
309 return mFetchHandlerWasAdded;
312 JSContext* GetJSContext() const {
313 AssertIsOnWorkerThread();
314 return mJSContext;
317 WorkerGlobalScope* GlobalScope() const {
318 MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
319 return data->mScope;
322 WorkerDebuggerGlobalScope* DebuggerGlobalScope() const {
323 MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
324 return data->mDebuggerScope;
327 // Get the global associated with the current nested event loop. Will return
328 // null if we're not in a nested event loop or that nested event loop does not
329 // have an associated global.
330 nsIGlobalObject* GetCurrentEventLoopGlobal() const {
331 MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
332 return data->mCurrentEventLoopGlobal;
335 nsICSPEventListener* CSPEventListener() const;
337 void SetThread(WorkerThread* aThread);
339 void SetWorkerPrivateInWorkerThread(WorkerThread* aThread);
341 void ResetWorkerPrivateInWorkerThread();
343 bool IsOnWorkerThread() const;
345 void AssertIsOnWorkerThread() const
346 #ifdef DEBUG
348 #else
351 #endif
353 // This may block!
354 void BeginCTypesCall();
356 // This may block!
357 void EndCTypesCall();
359 void BeginCTypesCallback() {
360 // If a callback is beginning then we need to do the exact same thing as
361 // when a ctypes call ends.
362 EndCTypesCall();
365 void EndCTypesCallback() {
366 // If a callback is ending then we need to do the exact same thing as
367 // when a ctypes call begins.
368 BeginCTypesCall();
371 bool ConnectMessagePort(JSContext* aCx, UniqueMessagePortId& aIdentifier);
373 WorkerGlobalScope* GetOrCreateGlobalScope(JSContext* aCx);
375 WorkerDebuggerGlobalScope* CreateDebuggerGlobalScope(JSContext* aCx);
377 bool RegisterBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
379 bool RegisterDebuggerBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
381 bool OnLine() const {
382 MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
383 return data->mOnLine;
386 void StopSyncLoop(nsIEventTarget* aSyncLoopTarget, bool aResult);
388 bool AllPendingRunnablesShouldBeCanceled() const {
389 return mCancelAllPendingRunnables;
392 void ClearMainEventQueue(WorkerRanOrNot aRanOrNot);
394 void ClearDebuggerEventQueue();
396 void OnProcessNextEvent();
398 void AfterProcessNextEvent();
400 void AssertValidSyncLoop(nsIEventTarget* aSyncLoopTarget)
401 #ifdef DEBUG
403 #else
406 #endif
408 void SetWorkerScriptExecutedSuccessfully() {
409 AssertIsOnWorkerThread();
410 // Should only be called once!
411 MOZ_ASSERT(!mWorkerScriptExecutedSuccessfully);
412 mWorkerScriptExecutedSuccessfully = true;
415 // Only valid after CompileScriptRunnable has finished running!
416 bool WorkerScriptExecutedSuccessfully() const {
417 AssertIsOnWorkerThread();
418 return mWorkerScriptExecutedSuccessfully;
421 // Get the event target to use when dispatching to the main thread
422 // from this Worker thread. This may be the main thread itself or
423 // a ThrottledEventQueue to the main thread.
424 nsIEventTarget* MainThreadEventTargetForMessaging();
426 nsresult DispatchToMainThreadForMessaging(
427 nsIRunnable* aRunnable, uint32_t aFlags = NS_DISPATCH_NORMAL);
429 nsresult DispatchToMainThreadForMessaging(
430 already_AddRefed<nsIRunnable> aRunnable,
431 uint32_t aFlags = NS_DISPATCH_NORMAL);
433 nsIEventTarget* MainThreadEventTarget();
435 nsresult DispatchToMainThread(nsIRunnable* aRunnable,
436 uint32_t aFlags = NS_DISPATCH_NORMAL);
438 nsresult DispatchToMainThread(already_AddRefed<nsIRunnable> aRunnable,
439 uint32_t aFlags = NS_DISPATCH_NORMAL);
441 nsresult DispatchDebuggeeToMainThread(
442 already_AddRefed<WorkerDebuggeeRunnable> aRunnable,
443 uint32_t aFlags = NS_DISPATCH_NORMAL);
445 // Get an event target that will dispatch runnables as control runnables on
446 // the worker thread. Implement nsICancelableRunnable if you wish to take
447 // action on cancelation.
448 nsISerialEventTarget* ControlEventTarget();
450 // Get an event target that will attempt to dispatch a normal WorkerRunnable,
451 // but if that fails will then fall back to a control runnable.
452 nsISerialEventTarget* HybridEventTarget();
454 void DumpCrashInformation(nsACString& aString);
456 bool EnsureClientSource();
458 bool EnsureCSPEventListener();
460 void EnsurePerformanceStorage();
462 void EnsurePerformanceCounter();
464 Maybe<ClientInfo> GetClientInfo() const;
466 const ClientState GetClientState() const;
468 const Maybe<ServiceWorkerDescriptor> GetController();
470 void Control(const ServiceWorkerDescriptor& aServiceWorker);
472 void ExecutionReady();
474 PerformanceStorage* GetPerformanceStorage();
476 PerformanceCounter* GetPerformanceCounter();
478 bool IsAcceptingEvents() {
479 AssertIsOnParentThread();
481 MutexAutoLock lock(mMutex);
482 return mParentStatus < Canceling;
485 WorkerStatus ParentStatusProtected() {
486 AssertIsOnParentThread();
487 MutexAutoLock lock(mMutex);
488 return mParentStatus;
491 WorkerStatus ParentStatus() const {
492 mMutex.AssertCurrentThreadOwns();
493 return mParentStatus;
496 Worker* ParentEventTargetRef() const {
497 MOZ_DIAGNOSTIC_ASSERT(mParentEventTargetRef);
498 return mParentEventTargetRef;
501 void SetParentEventTargetRef(Worker* aParentEventTargetRef) {
502 MOZ_DIAGNOSTIC_ASSERT(aParentEventTargetRef);
503 MOZ_DIAGNOSTIC_ASSERT(!mParentEventTargetRef);
504 mParentEventTargetRef = aParentEventTargetRef;
507 bool ModifyBusyCount(bool aIncrease);
509 // This method is used by RuntimeService to know what is going wrong the
510 // shutting down.
511 uint32_t BusyCount() { return mBusyCount; }
513 // Check whether this worker is a secure context. For use from the parent
514 // thread only; the canonical "is secure context" boolean is stored on the
515 // compartment of the worker global. The only reason we don't
516 // AssertIsOnParentThread() here is so we can assert that this value matches
517 // the one on the compartment, which has to be done from the worker thread.
518 bool IsSecureContext() const { return mIsSecureContext; }
520 // Check whether we're running in automation.
521 bool IsInAutomation() const { return mIsInAutomation; }
523 TimeStamp CreationTimeStamp() const { return mCreationTimeStamp; }
525 DOMHighResTimeStamp CreationTime() const { return mCreationTimeHighRes; }
527 DOMHighResTimeStamp TimeStampToDOMHighRes(const TimeStamp& aTimeStamp) const {
528 MOZ_ASSERT(!aTimeStamp.IsNull());
529 TimeDuration duration = aTimeStamp - mCreationTimeStamp;
530 return duration.ToMilliseconds();
533 LocationInfo& GetLocationInfo() { return mLocationInfo; }
535 void CopyJSSettings(workerinternals::JSSettings& aSettings) {
536 mozilla::MutexAutoLock lock(mMutex);
537 aSettings = mJSSettings;
540 void CopyJSRealmOptions(JS::RealmOptions& aOptions) {
541 mozilla::MutexAutoLock lock(mMutex);
542 aOptions = IsChromeWorker() ? mJSSettings.chrome.realmOptions
543 : mJSSettings.content.realmOptions;
546 // The ability to be a chrome worker is orthogonal to the type of
547 // worker [Dedicated|Shared|Service].
548 bool IsChromeWorker() const { return mIsChromeWorker; }
550 WorkerPrivate* GetParent() const { return mParent; }
552 bool IsFrozen() const {
553 AssertIsOnParentThread();
554 return mParentFrozen;
557 bool IsParentWindowPaused() const {
558 AssertIsOnParentThread();
559 return mParentWindowPaused;
562 // When we debug a worker, we want to disconnect the window and the worker
563 // communication. This happens calling this method.
564 // Note: this method doesn't suspend the worker! Use Freeze/Thaw instead.
565 void ParentWindowPaused();
567 void ParentWindowResumed();
569 const nsString& ScriptURL() const { return mScriptURL; }
571 const nsString& WorkerName() const { return mWorkerName; }
573 WorkerType Type() const { return mWorkerType; }
575 bool IsDedicatedWorker() const { return mWorkerType == WorkerTypeDedicated; }
577 bool IsSharedWorker() const { return mWorkerType == WorkerTypeShared; }
579 bool IsServiceWorker() const { return mWorkerType == WorkerTypeService; }
581 nsContentPolicyType ContentPolicyType() const {
582 return ContentPolicyType(mWorkerType);
585 static nsContentPolicyType ContentPolicyType(WorkerType aWorkerType) {
586 switch (aWorkerType) {
587 case WorkerTypeDedicated:
588 return nsIContentPolicy::TYPE_INTERNAL_WORKER;
589 case WorkerTypeShared:
590 return nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
591 case WorkerTypeService:
592 return nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER;
593 default:
594 MOZ_ASSERT_UNREACHABLE("Invalid worker type");
595 return nsIContentPolicy::TYPE_INVALID;
599 nsIScriptContext* GetScriptContext() const {
600 AssertIsOnMainThread();
601 return mLoadInfo.mScriptContext;
604 const nsCString& Domain() const { return mLoadInfo.mDomain; }
606 bool IsFromWindow() const { return mLoadInfo.mFromWindow; }
608 nsLoadFlags GetLoadFlags() const { return mLoadInfo.mLoadFlags; }
610 uint64_t WindowID() const { return mLoadInfo.mWindowID; }
612 uint64_t ServiceWorkerID() const { return GetServiceWorkerDescriptor().Id(); }
614 const nsCString& ServiceWorkerScope() const {
615 return GetServiceWorkerDescriptor().Scope();
618 nsIURI* GetBaseURI() const {
619 AssertIsOnMainThread();
620 return mLoadInfo.mBaseURI;
623 void SetBaseURI(nsIURI* aBaseURI);
625 nsIURI* GetResolvedScriptURI() const {
626 AssertIsOnMainThread();
627 return mLoadInfo.mResolvedScriptURI;
630 const nsString& ServiceWorkerCacheName() const {
631 MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
632 AssertIsOnMainThread();
633 return mLoadInfo.mServiceWorkerCacheName;
636 const ServiceWorkerDescriptor& GetServiceWorkerDescriptor() const {
637 MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
638 MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mServiceWorkerDescriptor.isSome());
639 return mLoadInfo.mServiceWorkerDescriptor.ref();
642 const ServiceWorkerRegistrationDescriptor&
643 GetServiceWorkerRegistrationDescriptor() const {
644 MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
645 MOZ_DIAGNOSTIC_ASSERT(
646 mLoadInfo.mServiceWorkerRegistrationDescriptor.isSome());
647 return mLoadInfo.mServiceWorkerRegistrationDescriptor.ref();
650 void UpdateServiceWorkerState(ServiceWorkerState aState) {
651 MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
652 MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mServiceWorkerDescriptor.isSome());
653 return mLoadInfo.mServiceWorkerDescriptor.ref().SetState(aState);
656 const Maybe<ServiceWorkerDescriptor>& GetParentController() const {
657 return mLoadInfo.mParentController;
660 const ChannelInfo& GetChannelInfo() const { return mLoadInfo.mChannelInfo; }
662 void SetChannelInfo(const ChannelInfo& aChannelInfo) {
663 AssertIsOnMainThread();
664 MOZ_ASSERT(!mLoadInfo.mChannelInfo.IsInitialized());
665 MOZ_ASSERT(aChannelInfo.IsInitialized());
666 mLoadInfo.mChannelInfo = aChannelInfo;
669 void InitChannelInfo(nsIChannel* aChannel) {
670 mLoadInfo.mChannelInfo.InitFromChannel(aChannel);
673 void InitChannelInfo(const ChannelInfo& aChannelInfo) {
674 mLoadInfo.mChannelInfo = aChannelInfo;
677 nsIPrincipal* GetPrincipal() const {
678 AssertIsOnMainThread();
679 return mLoadInfo.mPrincipal;
682 nsIPrincipal* GetEffectiveStoragePrincipal() const {
683 AssertIsOnMainThread();
684 return mLoadInfo.mStoragePrincipal;
687 nsIPrincipal* GetLoadingPrincipal() const {
688 AssertIsOnMainThread();
689 return mLoadInfo.mLoadingPrincipal;
692 const nsAString& Origin() const { return mLoadInfo.mOrigin; }
694 nsILoadGroup* GetLoadGroup() const {
695 AssertIsOnMainThread();
696 return mLoadInfo.mLoadGroup;
699 bool UsesSystemPrincipal() const { return mLoadInfo.mPrincipalIsSystem; }
700 bool UsesAddonOrExpandedAddonPrincipal() const {
701 return mLoadInfo.mPrincipalIsAddonOrExpandedAddon;
704 const mozilla::ipc::PrincipalInfo& GetPrincipalInfo() const {
705 return *mLoadInfo.mPrincipalInfo;
708 const mozilla::ipc::PrincipalInfo& GetEffectiveStoragePrincipalInfo() const {
709 return *mLoadInfo.mStoragePrincipalInfo;
712 already_AddRefed<nsIChannel> ForgetWorkerChannel() {
713 AssertIsOnMainThread();
714 return mLoadInfo.mChannel.forget();
717 nsPIDOMWindowInner* GetWindow() {
718 AssertIsOnMainThread();
719 return mLoadInfo.mWindow;
722 nsIContentSecurityPolicy* GetCSP() const {
723 AssertIsOnMainThread();
724 return mLoadInfo.mCSP;
727 void SetCSP(nsIContentSecurityPolicy* aCSP);
729 nsresult SetCSPFromHeaderValues(const nsACString& aCSPHeaderValue,
730 const nsACString& aCSPReportOnlyHeaderValue);
732 void StoreCSPOnClient();
734 const mozilla::ipc::CSPInfo& GetCSPInfo() const {
735 return *mLoadInfo.mCSPInfo;
738 void UpdateReferrerInfoFromHeader(
739 const nsACString& aReferrerPolicyHeaderValue);
741 nsIReferrerInfo* GetReferrerInfo() const { return mLoadInfo.mReferrerInfo; }
743 ReferrerPolicy GetReferrerPolicy() const {
744 return mLoadInfo.mReferrerInfo->ReferrerPolicy();
747 void SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
748 mLoadInfo.mReferrerInfo = aReferrerInfo;
751 bool IsEvalAllowed() const { return mLoadInfo.mEvalAllowed; }
753 void SetEvalAllowed(bool aEvalAllowed) {
754 mLoadInfo.mEvalAllowed = aEvalAllowed;
757 bool GetReportCSPViolations() const { return mLoadInfo.mReportCSPViolations; }
759 void SetReportCSPViolations(bool aReport) {
760 mLoadInfo.mReportCSPViolations = aReport;
763 bool XHRParamsAllowed() const { return mLoadInfo.mXHRParamsAllowed; }
765 void SetXHRParamsAllowed(bool aAllowed) {
766 mLoadInfo.mXHRParamsAllowed = aAllowed;
769 mozilla::StorageAccess StorageAccess() const {
770 AssertIsOnWorkerThread();
771 if (mLoadInfo.mFirstPartyStorageAccessGranted) {
772 return mozilla::StorageAccess::eAllow;
775 return mLoadInfo.mStorageAccess;
778 nsICookieSettings* CookieSettings() const {
779 // Any thread.
780 MOZ_ASSERT(mLoadInfo.mCookieSettings);
781 return mLoadInfo.mCookieSettings;
784 const OriginAttributes& GetOriginAttributes() const {
785 return mLoadInfo.mOriginAttributes;
788 // Determine if the SW testing per-window flag is set by devtools
789 bool ServiceWorkersTestingInWindow() const {
790 return mLoadInfo.mServiceWorkersTestingInWindow;
793 bool IsWatchedByDevtools() const { return mLoadInfo.mWatchedByDevtools; }
795 // Determine if the worker is currently loading its top level script.
796 bool IsLoadingWorkerScript() const { return mLoadingWorkerScript; }
798 // Called by ScriptLoader to track when this worker is loading its
799 // top level script.
800 void SetLoadingWorkerScript(bool aLoadingWorkerScript) {
801 // any thread
802 mLoadingWorkerScript = aLoadingWorkerScript;
805 RemoteWorkerChild* GetRemoteWorkerController();
807 void SetRemoteWorkerController(RemoteWorkerChild* aController);
809 void SetRemoteWorkerControllerWeakRef(
810 ThreadSafeWeakPtr<RemoteWorkerChild> aWeakRef);
812 ThreadSafeWeakPtr<RemoteWorkerChild> GetRemoteWorkerControllerWeakRef();
814 RefPtr<GenericPromise> SetServiceWorkerSkipWaitingFlag();
816 // We can assume that an nsPIDOMWindow will be available for Freeze, Thaw
817 // as these are only used for globals going in and out of the bfcache.
818 bool Freeze(nsPIDOMWindowInner* aWindow);
820 bool Thaw(nsPIDOMWindowInner* aWindow);
822 void PropagateFirstPartyStorageAccessGranted();
824 void EnableDebugger();
826 void DisableDebugger();
828 already_AddRefed<WorkerRunnable> MaybeWrapAsWorkerRunnable(
829 already_AddRefed<nsIRunnable> aRunnable);
831 bool ProxyReleaseMainThreadObjects();
833 void SetLowMemoryState(bool aState);
835 void GarbageCollect(bool aShrinking);
837 void CycleCollect(bool aDummy);
839 nsresult SetPrincipalsAndCSPOnMainThread(nsIPrincipal* aPrincipal,
840 nsIPrincipal* aStoragePrincipal,
841 nsILoadGroup* aLoadGroup,
842 nsIContentSecurityPolicy* aCsp);
844 nsresult SetPrincipalsAndCSPFromChannel(nsIChannel* aChannel);
846 bool FinalChannelPrincipalIsValid(nsIChannel* aChannel);
848 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
849 bool PrincipalURIMatchesScriptURL();
850 #endif
852 void UpdateOverridenLoadGroup(nsILoadGroup* aBaseLoadGroup);
854 void WorkerScriptLoaded();
856 Document* GetDocument() const;
858 void MemoryPressure(bool aDummy);
860 void UpdateContextOptions(const JS::ContextOptions& aContextOptions);
862 void UpdateLanguages(const nsTArray<nsString>& aLanguages);
864 void UpdateJSWorkerMemoryParameter(JSGCParamKey key, uint32_t value);
866 #ifdef JS_GC_ZEAL
867 void UpdateGCZeal(uint8_t aGCZeal, uint32_t aFrequency);
868 #endif
870 void OfflineStatusChangeEvent(bool aIsOffline);
872 nsresult Dispatch(already_AddRefed<WorkerRunnable> aRunnable,
873 nsIEventTarget* aSyncLoopTarget = nullptr);
875 nsresult DispatchControlRunnable(
876 already_AddRefed<WorkerControlRunnable> aWorkerControlRunnable);
878 nsresult DispatchDebuggerRunnable(
879 already_AddRefed<WorkerRunnable> aDebuggerRunnable);
881 #ifdef DEBUG
882 void AssertIsOnParentThread() const;
884 void AssertInnerWindowIsCorrect() const;
885 #else
886 void AssertIsOnParentThread() const {}
888 void AssertInnerWindowIsCorrect() const {}
889 #endif
891 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
892 bool PrincipalIsValid() const;
893 #endif
895 void StartCancelingTimer();
897 const nsAString& Id();
899 const nsID& AgentClusterId() const { return mAgentClusterId; }
901 bool IsSharedMemoryAllowed() const;
903 // https://whatpr.org/html/4734/structured-data.html#cross-origin-isolated
904 bool CrossOriginIsolated() const;
906 void SetUseCounter(UseCounterWorker aUseCounter) {
907 MOZ_ASSERT(!mReportedUseCounters);
908 MOZ_ASSERT(aUseCounter > UseCounterWorker::Unknown);
909 AssertIsOnWorkerThread();
910 mUseCounters[static_cast<size_t>(aUseCounter)] = true;
913 private:
914 WorkerPrivate(
915 WorkerPrivate* aParent, const nsAString& aScriptURL, bool aIsChromeWorker,
916 WorkerType aWorkerType, const nsAString& aWorkerName,
917 const nsACString& aServiceWorkerScope, WorkerLoadInfo& aLoadInfo,
918 nsString&& aId, const nsID& aAgentClusterId,
919 const nsILoadInfo::CrossOriginOpenerPolicy aAgentClusterOpenerPolicy);
921 ~WorkerPrivate();
923 bool MayContinueRunning() {
924 AssertIsOnWorkerThread();
926 WorkerStatus status;
928 MutexAutoLock lock(mMutex);
929 status = mStatus;
932 if (status < Canceling) {
933 return true;
936 return false;
939 void CancelAllTimeouts();
941 enum class ProcessAllControlRunnablesResult {
942 // We did not process anything.
943 Nothing,
944 // We did process something, states may have changed, but we can keep
945 // executing script.
946 MayContinue,
947 // We did process something, and should not continue executing script.
948 Abort
951 ProcessAllControlRunnablesResult ProcessAllControlRunnables() {
952 MutexAutoLock lock(mMutex);
953 return ProcessAllControlRunnablesLocked();
956 ProcessAllControlRunnablesResult ProcessAllControlRunnablesLocked();
958 void EnableMemoryReporter();
960 void DisableMemoryReporter();
962 void WaitForWorkerEvents();
964 // If the worker shutdown status is equal or greater then aFailStatus, this
965 // operation will fail and nullptr will be returned. See WorkerStatus.h for
966 // more information about the correct value to use.
967 already_AddRefed<nsIEventTarget> CreateNewSyncLoop(WorkerStatus aFailStatus);
969 bool RunCurrentSyncLoop();
971 bool DestroySyncLoop(uint32_t aLoopIndex);
973 void InitializeGCTimers();
975 enum GCTimerMode { PeriodicTimer = 0, IdleTimer, NoTimer };
977 void SetGCTimerMode(GCTimerMode aMode);
979 void ShutdownGCTimers();
981 friend class WorkerRef;
983 bool AddWorkerRef(WorkerRef* aWorkerRefer, WorkerStatus aFailStatus);
985 void RemoveWorkerRef(WorkerRef* aWorkerRef);
987 void NotifyWorkerRefs(WorkerStatus aStatus);
989 bool HasActiveWorkerRefs() {
990 MOZ_ACCESS_THREAD_BOUND(mWorkerThreadAccessible, data);
991 return !(data->mChildWorkers.IsEmpty() && data->mTimeouts.IsEmpty() &&
992 data->mWorkerRefs.IsEmpty());
995 // Internal logic to dispatch a runnable. This is separate from Dispatch()
996 // to allow runnables to be atomically dispatched in bulk.
997 nsresult DispatchLockHeld(already_AddRefed<WorkerRunnable> aRunnable,
998 nsIEventTarget* aSyncLoopTarget,
999 const MutexAutoLock& aProofOfLock);
1001 // This method dispatches a simple runnable that starts the shutdown procedure
1002 // after a self.close(). This method is called after a ClearMainEventQueue()
1003 // to be sure that the canceling runnable is the only one in the queue. We
1004 // need this async operation to be sure that all the current JS code is
1005 // executed.
1006 void DispatchCancelingRunnable();
1008 bool GetUseCounter(UseCounterWorker aUseCounter) {
1009 MOZ_ASSERT(aUseCounter > UseCounterWorker::Unknown);
1010 AssertIsOnWorkerThread();
1011 return mUseCounters[static_cast<size_t>(aUseCounter)];
1014 void ReportUseCounters();
1016 class EventTarget;
1017 friend class EventTarget;
1018 friend class AutoSyncLoopHolder;
1020 struct TimeoutInfo;
1022 class MemoryReporter;
1023 friend class MemoryReporter;
1025 friend class mozilla::dom::WorkerThread;
1027 SharedMutex mMutex;
1028 mozilla::CondVar mCondVar;
1030 WorkerPrivate* mParent;
1032 nsString mScriptURL;
1034 // This is the worker name for shared workers and dedicated workers.
1035 nsString mWorkerName;
1037 WorkerType mWorkerType;
1039 // The worker is owned by its thread, which is represented here. This is set
1040 // in Constructor() and emptied by WorkerFinishedRunnable, and conditionally
1041 // traversed by the cycle collector if the busy count is zero.
1043 // There are 4 ways a worker can be terminated:
1044 // 1. GC/CC - When the worker is in idle state (busycount == 0), it allows to
1045 // traverse the 'hidden' mParentEventTargetRef pointer. This is the exposed
1046 // Worker webidl object. Doing this, CC will be able to detect a cycle and
1047 // Unlink is called. In Unlink, Worker calls Cancel().
1048 // 2. Worker::Cancel() is called - the shutdown procedure starts immediately.
1049 // 3. WorkerScope::Close() is called - Similar to point 2.
1050 // 4. xpcom-shutdown notification - We call Kill().
1051 RefPtr<Worker> mParentEventTargetRef;
1052 RefPtr<WorkerPrivate> mSelfRef;
1054 // The lifetime of these objects within LoadInfo is managed explicitly;
1055 // they do not need to be cycle collected.
1056 WorkerLoadInfo mLoadInfo;
1057 LocationInfo mLocationInfo;
1059 // Protected by mMutex.
1060 workerinternals::JSSettings mJSSettings;
1062 WorkerDebugger* mDebugger;
1064 workerinternals::Queue<WorkerControlRunnable*, 4> mControlQueue;
1065 workerinternals::Queue<WorkerRunnable*, 4> mDebuggerQueue;
1067 // Touched on multiple threads, protected with mMutex.
1068 JSContext* mJSContext;
1069 RefPtr<WorkerThread> mThread;
1070 PRThread* mPRThread;
1072 // Accessed from main thread
1073 RefPtr<ThrottledEventQueue> mMainThreadEventTargetForMessaging;
1074 RefPtr<ThrottledEventQueue> mMainThreadEventTarget;
1076 // Accessed from worker thread and destructing thread
1077 RefPtr<WorkerEventTarget> mWorkerControlEventTarget;
1078 RefPtr<WorkerEventTarget> mWorkerHybridEventTarget;
1080 // A pauseable queue for WorkerDebuggeeRunnables directed at the main thread.
1081 // See WorkerDebuggeeRunnable for details.
1082 RefPtr<ThrottledEventQueue> mMainThreadDebuggeeEventTarget;
1084 struct SyncLoopInfo {
1085 explicit SyncLoopInfo(EventTarget* aEventTarget);
1087 RefPtr<EventTarget> mEventTarget;
1088 bool mCompleted;
1089 bool mResult;
1090 #ifdef DEBUG
1091 bool mHasRun;
1092 #endif
1095 // This is only modified on the worker thread, but in DEBUG builds
1096 // AssertValidSyncLoop function iterates it on other threads. Therefore
1097 // modifications are done with mMutex held *only* in DEBUG builds.
1098 nsTArray<nsAutoPtr<SyncLoopInfo>> mSyncLoopStack;
1100 nsCOMPtr<nsITimer> mCancelingTimer;
1102 // fired on the main thread if the worker script fails to load
1103 nsCOMPtr<nsIRunnable> mLoadFailedRunnable;
1105 RefPtr<PerformanceStorage> mPerformanceStorage;
1107 RefPtr<WorkerCSPEventListener> mCSPEventListener;
1109 // Protected by mMutex.
1110 nsTArray<RefPtr<WorkerRunnable>> mPreStartRunnables;
1112 // Only touched on the parent thread. This is set only if IsSharedWorker().
1113 RefPtr<RemoteWorkerChild> mRemoteWorkerController;
1115 // This is set only if IsServiceWorker().
1116 ThreadSafeWeakPtr<RemoteWorkerChild> mRemoteWorkerControllerWeakRef;
1118 JS::UniqueChars mDefaultLocale; // nulled during worker JSContext init
1119 TimeStamp mKillTime;
1120 WorkerStatus mParentStatus;
1121 WorkerStatus mStatus;
1123 // This is touched on parent thread only, but it can be read on a different
1124 // thread before crashing because hanging.
1125 Atomic<uint64_t> mBusyCount;
1127 Atomic<bool> mLoadingWorkerScript;
1129 TimeStamp mCreationTimeStamp;
1130 DOMHighResTimeStamp mCreationTimeHighRes;
1132 // Flags for use counters used directly by this worker.
1133 static_assert(sizeof(UseCounterWorker) <= sizeof(size_t),
1134 "UseCounterWorker is too big");
1135 static_assert(UseCounterWorker::Count >= static_cast<UseCounterWorker>(0),
1136 "Should be non-negative value and safe to cast to unsigned");
1137 std::bitset<static_cast<size_t>(UseCounterWorker::Count)> mUseCounters;
1138 bool mReportedUseCounters;
1140 // This is created while creating the WorkerPrivate, so it's safe to be
1141 // touched on any thread.
1142 const nsID mAgentClusterId;
1144 // Things touched on worker thread only.
1145 struct WorkerThreadAccessible {
1146 explicit WorkerThreadAccessible(WorkerPrivate* aParent);
1148 RefPtr<WorkerGlobalScope> mScope;
1149 RefPtr<WorkerDebuggerGlobalScope> mDebuggerScope;
1150 nsTArray<WorkerPrivate*> mChildWorkers;
1151 nsTObserverArray<WorkerRef*> mWorkerRefs;
1152 nsTArray<nsAutoPtr<TimeoutInfo>> mTimeouts;
1154 nsCOMPtr<nsITimer> mTimer;
1155 nsCOMPtr<nsITimerCallback> mTimerRunnable;
1157 nsCOMPtr<nsITimer> mGCTimer;
1159 RefPtr<MemoryReporter> mMemoryReporter;
1161 UniquePtr<ClientSource> mClientSource;
1163 // While running a nested event loop, whether a sync loop or a debugger
1164 // event loop we want to keep track of which global is running it, if any,
1165 // so runnables that run off that event loop can get at that information. In
1166 // practice this only matters for various worker debugger runnables running
1167 // against sandboxes, because all other runnables know which globals they
1168 // belong to already. We could also address this by threading the relevant
1169 // global through the chains of runnables involved, but we'd need to thread
1170 // it through some runnables that run on the main thread, and that would
1171 // require some care to make sure things get released on the correct thread,
1172 // which we'd rather avoid. This member is only accessed on the worker
1173 // thread.
1174 nsCOMPtr<nsIGlobalObject> mCurrentEventLoopGlobal;
1176 uint32_t mNumWorkerRefsPreventingShutdownStart;
1177 uint32_t mDebuggerEventLoopLevel;
1179 uint32_t mErrorHandlerRecursionCount;
1180 uint32_t mNextTimeoutId;
1182 bool mFrozen;
1183 bool mTimerRunning;
1184 bool mRunningExpiredTimeouts;
1185 bool mPeriodicGCTimerRunning;
1186 bool mIdleGCTimerRunning;
1187 bool mOnLine;
1189 ThreadBound<WorkerThreadAccessible> mWorkerThreadAccessible;
1191 class MOZ_RAII AutoPushEventLoopGlobal {
1192 public:
1193 AutoPushEventLoopGlobal(WorkerPrivate* aWorkerPrivate, JSContext* aCx);
1194 ~AutoPushEventLoopGlobal();
1196 private:
1197 WorkerPrivate* mWorkerPrivate;
1198 nsCOMPtr<nsIGlobalObject> mOldEventLoopGlobal;
1200 friend class AutoPushEventLoopGlobal;
1202 uint32_t mPostSyncLoopOperations;
1204 // List of operations to do at the end of the last sync event loop.
1205 enum {
1206 ePendingEventQueueClearing = 0x01,
1207 eDispatchCancelingRunnable = 0x02,
1210 bool mParentWindowPaused;
1212 bool mCancelAllPendingRunnables;
1213 bool mWorkerScriptExecutedSuccessfully;
1214 bool mFetchHandlerWasAdded;
1215 bool mMainThreadObjectsForgotten;
1216 bool mIsChromeWorker;
1217 bool mParentFrozen;
1219 // mIsSecureContext is set once in our constructor; after that it can be read
1220 // from various threads.
1222 // It's a bit unfortunate that we have to have an out-of-band boolean for
1223 // this, but we need access to this state from the parent thread, and we can't
1224 // use our global object's secure state there.
1225 const bool mIsSecureContext;
1227 bool mDebuggerRegistered;
1229 // During registration, this worker may be marked as not being ready to
1230 // execute debuggee runnables or content.
1232 // Protected by mMutex.
1233 bool mDebuggerReady;
1234 nsTArray<RefPtr<WorkerRunnable>> mDelayedDebuggeeRunnables;
1236 // mIsInAutomation is true when we're running in test automation.
1237 // We expose some extra testing functions in that case.
1238 bool mIsInAutomation;
1240 RefPtr<mozilla::PerformanceCounter> mPerformanceCounter;
1242 nsString mId;
1244 // This is used to check if it's allowed to share the memory across the agent
1245 // cluster.
1246 const nsILoadInfo::CrossOriginOpenerPolicy mAgentClusterOpenerPolicy;
1249 class AutoSyncLoopHolder {
1250 WorkerPrivate* mWorkerPrivate;
1251 nsCOMPtr<nsIEventTarget> mTarget;
1252 uint32_t mIndex;
1254 public:
1255 // See CreateNewSyncLoop() for more information about the correct value to use
1256 // for aFailStatus.
1257 AutoSyncLoopHolder(WorkerPrivate* aWorkerPrivate, WorkerStatus aFailStatus)
1258 : mWorkerPrivate(aWorkerPrivate),
1259 mTarget(aWorkerPrivate->CreateNewSyncLoop(aFailStatus)),
1260 mIndex(aWorkerPrivate->mSyncLoopStack.Length() - 1) {
1261 aWorkerPrivate->AssertIsOnWorkerThread();
1264 ~AutoSyncLoopHolder() {
1265 if (mWorkerPrivate && mTarget) {
1266 mWorkerPrivate->AssertIsOnWorkerThread();
1267 mWorkerPrivate->StopSyncLoop(mTarget, false);
1268 mWorkerPrivate->DestroySyncLoop(mIndex);
1272 bool Run() {
1273 WorkerPrivate* workerPrivate = mWorkerPrivate;
1274 mWorkerPrivate = nullptr;
1276 workerPrivate->AssertIsOnWorkerThread();
1278 return workerPrivate->RunCurrentSyncLoop();
1281 nsIEventTarget* GetEventTarget() const {
1282 // This can be null if CreateNewSyncLoop() fails.
1283 return mTarget;
1287 } // namespace dom
1288 } // namespace mozilla
1290 #endif /* mozilla_dom_workers_workerprivate_h__ */