tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WorkerPrivate.h (61211B)


      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/. */
      6 
      7 #ifndef mozilla_dom_workers_workerprivate_h__
      8 #define mozilla_dom_workers_workerprivate_h__
      9 
     10 #include <bitset>
     11 
     12 #include "FontVisibilityProvider.h"
     13 #include "MainThreadUtils.h"
     14 #include "ScriptLoader.h"
     15 #include "js/ContextOptions.h"
     16 #include "mozilla/Atomics.h"
     17 #include "mozilla/Attributes.h"
     18 #include "mozilla/AutoRestore.h"
     19 #include "mozilla/BasePrincipal.h"
     20 #include "mozilla/CondVar.h"
     21 #include "mozilla/DOMEventTargetHelper.h"
     22 #include "mozilla/Maybe.h"
     23 #include "mozilla/MozPromise.h"
     24 #include "mozilla/OriginTrials.h"
     25 #include "mozilla/RelativeTimeline.h"
     26 #include "mozilla/Result.h"
     27 #include "mozilla/StaticPrefs_extensions.h"
     28 #include "mozilla/StorageAccess.h"
     29 #include "mozilla/TargetShutdownTaskSet.h"
     30 #include "mozilla/ThreadBound.h"
     31 #include "mozilla/UniquePtr.h"
     32 #include "mozilla/UseCounter.h"
     33 #include "mozilla/dom/ClientSource.h"
     34 #include "mozilla/dom/FlippedOnce.h"
     35 #include "mozilla/dom/JSExecutionManager.h"
     36 #include "mozilla/dom/PRemoteWorkerNonLifeCycleOpControllerChild.h"
     37 #include "mozilla/dom/RemoteWorkerTypes.h"
     38 #include "mozilla/dom/Timeout.h"
     39 #include "mozilla/dom/Worker.h"
     40 #include "mozilla/dom/WorkerBinding.h"
     41 #include "mozilla/dom/WorkerCommon.h"
     42 #include "mozilla/dom/WorkerLoadInfo.h"
     43 #include "mozilla/dom/WorkerStatus.h"
     44 #include "mozilla/dom/quota/CheckedUnsafePtr.h"
     45 #include "mozilla/dom/workerinternals/JSSettings.h"
     46 #include "mozilla/dom/workerinternals/Queue.h"
     47 #include "mozilla/ipc/Endpoint.h"
     48 #include "mozilla/net/NeckoChannelParams.h"
     49 #include "nsContentUtils.h"
     50 #include "nsIChannel.h"
     51 #include "nsIContentPolicy.h"
     52 #include "nsID.h"
     53 #include "nsIEventTarget.h"
     54 #include "nsILoadInfo.h"
     55 #include "nsRFPService.h"
     56 #include "nsTObserverArray.h"
     57 #include "stdint.h"
     58 
     59 class nsIContentSecurityPolicy;
     60 class nsIThreadInternal;
     61 
     62 namespace JS {
     63 struct RuntimeStats;
     64 class Dispatchable;
     65 }  // namespace JS
     66 
     67 namespace mozilla {
     68 class ThrottledEventQueue;
     69 namespace dom {
     70 
     71 class PRemoteWorkerDebuggerChild;
     72 class PRemoteWorkerDebuggerParent;
     73 class RemoteWorkerChild;
     74 class RemoteWorkerDebuggerChild;
     75 class RemoteWorkerNonLifeCycleOpControllerChild;
     76 
     77 // If you change this, the corresponding list in nsIWorkerDebugger.idl needs
     78 // to be updated too. And histograms enum for worker use counters uses the same
     79 // order of worker kind. Please also update dom/base/usecounters.py.
     80 enum WorkerKind : uint8_t {
     81  WorkerKindDedicated,
     82  WorkerKindShared,
     83  WorkerKindService
     84 };
     85 
     86 class ClientInfo;
     87 class ClientSource;
     88 class Function;
     89 class JSExecutionManager;
     90 class MessagePort;
     91 class UniqueMessagePortId;
     92 class PerformanceStorage;
     93 class StrongWorkerRef;
     94 class TimeoutHandler;
     95 class WorkerControlRunnable;
     96 class WorkerCSPEventListener;
     97 class WorkerDebugger;
     98 class WorkerDebuggerGlobalScope;
     99 class WorkerErrorReport;
    100 class WorkerEventTarget;
    101 class WorkerGlobalScope;
    102 class WorkerParentRef;
    103 class WorkerRef;
    104 class WorkerRunnable;
    105 class WorkerDebuggeeRunnable;
    106 class WorkerThread;
    107 class WorkerThreadRunnable;
    108 
    109 // SharedMutex is a small wrapper around an (internal) reference-counted Mutex
    110 // object. It exists to avoid changing a lot of code to use Mutex* instead of
    111 // Mutex&.
    112 class MOZ_CAPABILITY("mutex") SharedMutex {
    113  using Mutex = mozilla::Mutex;
    114 
    115  class MOZ_CAPABILITY("mutex") RefCountedMutex final : public Mutex {
    116   public:
    117    explicit RefCountedMutex(const char* aName) : Mutex(aName) {}
    118 
    119    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedMutex)
    120 
    121   private:
    122    ~RefCountedMutex() = default;
    123  };
    124 
    125  const RefPtr<RefCountedMutex> mMutex;
    126 
    127 public:
    128  explicit SharedMutex(const char* aName)
    129      : mMutex(new RefCountedMutex(aName)) {}
    130 
    131  SharedMutex(const SharedMutex& aOther) = default;
    132 
    133  operator Mutex&() MOZ_RETURN_CAPABILITY(this) { return *mMutex; }
    134 
    135  operator const Mutex&() const MOZ_RETURN_CAPABILITY(this) { return *mMutex; }
    136 
    137  // We need these to make thread-safety analysis work
    138  void Lock() MOZ_CAPABILITY_ACQUIRE() { mMutex->Lock(); }
    139  void Unlock() MOZ_CAPABILITY_RELEASE() { mMutex->Unlock(); }
    140 
    141  // We can assert we own 'this', but we can't assert we hold mMutex
    142  void AssertCurrentThreadOwns() const
    143      MOZ_ASSERT_CAPABILITY(this) MOZ_NO_THREAD_SAFETY_ANALYSIS {
    144    mMutex->AssertCurrentThreadOwns();
    145  }
    146 };
    147 
    148 nsString ComputeWorkerPrivateId();
    149 
    150 class WorkerPrivate final
    151    : public RelativeTimeline,
    152      public SupportsCheckedUnsafePtr<CheckIf<DiagnosticAssertEnabled>>,
    153      public FontVisibilityProvider {
    154 public:
    155  // Callback invoked on the parent thread when the worker's cancellation is
    156  // about to be requested.  This covers both calls to
    157  // WorkerPrivate::Cancel() by the owner as well as self-initiated cancellation
    158  // due to top-level script evaluation failing or close() being invoked on the
    159  // global scope for Dedicated and Shared workers, but not Service Workers as
    160  // they do not expose a close() method.
    161  //
    162  // ### Parent-Initiated Cancellation
    163  //
    164  // When WorkerPrivate::Cancel is invoked on the parent thread (by the binding
    165  // exposed Worker::Terminate), this callback is invoked synchronously inside
    166  // that call.
    167  //
    168  // ### Worker Self-Cancellation
    169  //
    170  // When a worker initiates self-cancellation, the worker's notification to the
    171  // parent thread is a non-blocking, async mechanism triggered by
    172  // `WorkerPrivate::DispatchCancelingRunnable`.
    173  //
    174  // Self-cancellation races a normally scheduled runnable against a timer that
    175  // is scheduled against the parent.  The 2 paths initiated by
    176  // DispatchCancelingRunnable are:
    177  //
    178  // 1. A CancelingRunnable is dispatched at the worker's normal event target to
    179  //    wait for the event loop to be clear of runnables.  When the
    180  //    CancelingRunnable runs it will dispatch a CancelingOnParentRunnable to
    181  //    its parent which is a normal, non-control WorkerDebuggeeRunnable to
    182  //    ensure that any postMessages to the parent or similar events get a
    183  //    chance to be processed prior to cancellation.  The timer scheduled in
    184  //    the next bullet will not be canceled unless
    185  //
    186  // 2. A CancelingWithTimeoutOnParentRunnable control runnable is dispatched
    187  //    to the parent to schedule a timer which will (also) fire on the parent
    188  //    thread.  This handles the case where the worker does not yield
    189  //    control-flow, and so the normal runnable scheduled above does not get to
    190  //    run in a timely fashion.  Because this is a control runnable, if the
    191  //    parent is a worker then the runnable will be processed with urgency.
    192  //    However, if the worker is top-level, then the control-like throttled
    193  //    WorkerPrivate::mMainThreadEventTarget will end up getting used which is
    194  //    nsIRunnablePriority::PRIORITY_MEDIUMHIGH and distinct from the
    195  //    mMainThreadDebuggeeEventTarget which most runnables (like postMessage)
    196  //    use.
    197  //
    198  //    The timer will explicitly use the control event target if the parent is
    199  //    a worker and the implicit event target (via `NS_NewTimer()`) otherwise.
    200  //    The callback is CancelingTimerCallback which just calls
    201  //    WorkerPrivate::Cancel.
    202  using CancellationCallback = std::function<void(bool aEverRan)>;
    203 
    204  // Callback invoked on the parent just prior to dropping the worker thread's
    205  // strong reference that keeps the WorkerPrivate alive while the worker thread
    206  // is running.  This does not provide a guarantee that the underlying thread
    207  // has fully shutdown, just that the worker logic has fully shutdown.
    208  //
    209  // ### Details
    210  //
    211  // The last thing the worker thread's WorkerThreadPrimaryRunnable does before
    212  // initiating the shutdown of the underlying thread is call ScheduleDeletion.
    213  // ScheduleDeletion dispatches a runnable to the parent to notify it that the
    214  // worker has completed its work and will never touch the WorkerPrivate again
    215  // and that the strong self-reference can be dropped.
    216  //
    217  // For parents that are themselves workers, this will be done by
    218  // WorkerFinishedRunnable which is a WorkerControlRunnable, ensuring that this
    219  // is processed in a timely fashion.  For main-thread parents,
    220  // TopLevelWorkerFinishedRunnable will be used and sent via
    221  // mMainThreadEventTargetForMessaging which is a weird ThrottledEventQueue
    222  // which does not provide any ordering guarantees relative to
    223  // mMainThreadDebuggeeEventTarget, so if you want those, you need to enhance
    224  // things.
    225  using TerminationCallback = std::function<void(void)>;
    226 
    227  struct LocationInfo {
    228    nsCString mHref;
    229    nsCString mProtocol;
    230    nsCString mHost;
    231    nsCString mHostname;
    232    nsCString mPort;
    233    nsCString mPathname;
    234    nsCString mSearch;
    235    nsCString mHash;
    236    nsString mOrigin;
    237  };
    238 
    239  NS_INLINE_DECL_REFCOUNTING(WorkerPrivate)
    240 
    241  FONT_VISIBILITY_PROVIDER_IMPL
    242 
    243  static already_AddRefed<WorkerPrivate> Constructor(
    244      JSContext* aCx, const nsAString& aScriptURL, bool aIsChromeWorker,
    245      WorkerKind aWorkerKind, RequestCredentials aRequestCredentials,
    246      const WorkerType aWorkerType, const nsAString& aWorkerName,
    247      const nsACString& aServiceWorkerScope, WorkerLoadInfo* aLoadInfo,
    248      ErrorResult& aRv, nsString aId = u""_ns,
    249      CancellationCallback&& aCancellationCallback = {},
    250      TerminationCallback&& aTerminationCallback = {},
    251      mozilla::ipc::Endpoint<
    252          PRemoteWorkerNonLifeCycleOpControllerChild>&& aChildEp =
    253          mozilla::ipc::Endpoint<PRemoteWorkerNonLifeCycleOpControllerChild>());
    254 
    255  enum LoadGroupBehavior { InheritLoadGroup, OverrideLoadGroup };
    256 
    257  static nsresult GetLoadInfo(
    258      JSContext* aCx, nsPIDOMWindowInner* aWindow, WorkerPrivate* aParent,
    259      const nsAString& aScriptURL, const enum WorkerType& aWorkerType,
    260      const RequestCredentials& aCredentials, bool aIsChromeWorker,
    261      LoadGroupBehavior aLoadGroupBehavior, WorkerKind aWorkerKind,
    262      WorkerLoadInfo* aLoadInfo);
    263 
    264  void Traverse(nsCycleCollectionTraversalCallback& aCb);
    265 
    266  void ClearSelfAndParentEventTargetRef() {
    267    AssertIsOnParentThread();
    268    MOZ_ASSERT(mSelfRef);
    269 
    270    if (mTerminationCallback) {
    271      mTerminationCallback();
    272      mTerminationCallback = nullptr;
    273    }
    274 
    275    mParentEventTargetRef = nullptr;
    276    mSelfRef = nullptr;
    277  }
    278 
    279  // May be called on any thread...
    280  bool Start();
    281 
    282  // Called on the parent thread.
    283  bool Notify(WorkerStatus aStatus);
    284 
    285  bool Cancel() { return Notify(Canceling); }
    286 
    287  bool Close() MOZ_REQUIRES(mMutex);
    288 
    289  // The passed principal must be the Worker principal in case of a
    290  // ServiceWorker and the loading principal for any other type.
    291  static void OverrideLoadInfoLoadGroup(WorkerLoadInfo& aLoadInfo,
    292                                        nsIPrincipal* aPrincipal);
    293 
    294  bool IsDebuggerRegistered() MOZ_NO_THREAD_SAFETY_ANALYSIS {
    295    AssertIsOnMainThread();
    296 
    297    // No need to lock here since this is only ever modified by the same thread.
    298    return mDebuggerRegistered;  // would give a thread-safety warning
    299  }
    300 
    301  bool ExtensionAPIAllowed() {
    302    return (
    303        StaticPrefs::extensions_backgroundServiceWorker_enabled_AtStartup() &&
    304        mExtensionAPIAllowed);
    305  }
    306 
    307  void SetIsDebuggerRegistered(bool aDebuggerRegistered) {
    308    AssertIsOnMainThread();
    309 
    310    MutexAutoLock lock(mMutex);
    311 
    312    MOZ_ASSERT(mDebuggerRegistered != aDebuggerRegistered);
    313    mDebuggerRegistered = aDebuggerRegistered;
    314 
    315    mCondVar.Notify();
    316  }
    317 
    318  // Mark worker private as running in the background tab
    319  // for further throttling
    320  void SetIsRunningInBackground();
    321  void SetIsPlayingAudio(bool aIsPlayingAudio);
    322 
    323  bool IsPlayingAudio() {
    324    AssertIsOnWorkerThread();
    325    return mIsPlayingAudio;
    326  }
    327 
    328  bool HasActivePeerConnections() {
    329    AssertIsOnWorkerThread();
    330    return mHasActivePeerConnections;
    331  }
    332 
    333  void SetActivePeerConnections(bool aHasPeerConnections);
    334 
    335  void SetIsRunningInForeground();
    336 
    337  bool ChangeBackgroundStateInternal(bool aIsBackground);
    338  bool ChangePlaybackStateInternal(bool aIsPlayingAudio);
    339  bool ChangePeerConnectionsInternal(bool aHasPeerConnections);
    340 
    341  // returns true, if worker is running in the background tab
    342  bool IsRunningInBackground() const { return mIsInBackground; }
    343 
    344  void WaitForIsDebuggerRegistered(bool aDebuggerRegistered) {
    345    AssertIsOnParentThread();
    346 
    347    // Yield so that the main thread won't be blocked.
    348    AutoYieldJSThreadExecution yield;
    349 
    350    MOZ_ASSERT(!NS_IsMainThread());
    351 
    352    MutexAutoLock lock(mMutex);
    353 
    354    while (mDebuggerRegistered != aDebuggerRegistered) {
    355      mCondVar.Wait();
    356    }
    357  }
    358 
    359  nsresult SetIsDebuggerReady(bool aReady);
    360 
    361  WorkerDebugger* Debugger() const {
    362    AssertIsOnMainThread();
    363 
    364    MOZ_ASSERT(mDebugger);
    365    return mDebugger;
    366  }
    367 
    368  const OriginTrials& Trials() const { return mLoadInfo.mTrials; }
    369 
    370  void SetDebugger(WorkerDebugger* aDebugger) {
    371    AssertIsOnMainThread();
    372 
    373    MOZ_ASSERT(mDebugger != aDebugger);
    374    mDebugger = aDebugger;
    375  }
    376 
    377  JS::UniqueChars AdoptDefaultLocale() {
    378    MOZ_ASSERT(mDefaultLocale,
    379               "the default locale must have been successfully set for anyone "
    380               "to be trying to adopt it");
    381    return std::move(mDefaultLocale);
    382  }
    383 
    384  /**
    385   * Invoked by WorkerThreadPrimaryRunnable::Run if it already called
    386   * SetWorkerPrivateInWorkerThread but has to bail out on initialization before
    387   * calling DoRunLoop because PBackground failed to initialize or something
    388   * like that.  Note that there's currently no point earlier than this that
    389   * failure can be reported.
    390   *
    391   * When this happens, the worker will need to be deleted, plus the call to
    392   * SetWorkerPrivateInWorkerThread will have scheduled all the
    393   * mPreStartRunnables which need to be cleaned up after, as well as any
    394   * scheduled control runnables.  We're somewhat punting on debugger runnables
    395   * for now, which may leak, but the intent is to moot this whole scenario via
    396   * shutdown blockers, so we don't want the extra complexity right now.
    397   */
    398  void RunLoopNeverRan();
    399 
    400  MOZ_CAN_RUN_SCRIPT
    401  void DoRunLoop(JSContext* aCx);
    402 
    403  void UnrootGlobalScopes();
    404 
    405  MOZ_CAN_RUN_SCRIPT bool InterruptCallback(JSContext* aCx);
    406 
    407  bool IsOnCurrentThread();
    408 
    409  void CloseInternal();
    410 
    411  bool FreezeInternal();
    412 
    413  bool ThawInternal();
    414 
    415  void PropagateStorageAccessPermissionGrantedInternal();
    416 
    417  void TraverseTimeouts(nsCycleCollectionTraversalCallback& aCallback);
    418 
    419  void UnlinkTimeouts();
    420 
    421  bool AddChildWorker(WorkerPrivate& aChildWorker);
    422 
    423  void RemoveChildWorker(WorkerPrivate& aChildWorker);
    424 
    425  void PostMessageToParent(JSContext* aCx, JS::Handle<JS::Value> aMessage,
    426                           const Sequence<JSObject*>& aTransferable,
    427                           ErrorResult& aRv);
    428 
    429  void PostMessageToParentMessagePort(JSContext* aCx,
    430                                      JS::Handle<JS::Value> aMessage,
    431                                      const Sequence<JSObject*>& aTransferable,
    432                                      ErrorResult& aRv);
    433 
    434  MOZ_CAN_RUN_SCRIPT void EnterDebuggerEventLoop();
    435 
    436  void LeaveDebuggerEventLoop();
    437 
    438  void PostMessageToDebugger(const nsAString& aMessage);
    439 
    440  void SetDebuggerImmediate(Function& aHandler, ErrorResult& aRv);
    441 
    442  void ReportErrorToDebugger(const nsACString& aFilename, uint32_t aLineno,
    443                             const nsAString& aMessage);
    444 
    445  bool NotifyInternal(WorkerStatus aStatus);
    446 
    447  void ReportError(JSContext* aCx, JS::ConstUTF8CharsZ aToStringResult,
    448                   JSErrorReport* aReport);
    449 
    450  static void ReportErrorToConsole(
    451      uint32_t aErrorFlags, const nsCString& aCategory,
    452      nsContentUtils::PropertiesFile aFile, const nsCString& aMessageName,
    453      const nsTArray<nsString>& aParams = nsTArray<nsString>(),
    454      const mozilla::SourceLocation& aLocation =
    455          mozilla::JSCallingLocation::Get());
    456 
    457  int32_t SetTimeout(JSContext* aCx, TimeoutHandler* aHandler, int32_t aTimeout,
    458                     bool aIsInterval, Timeout::Reason aReason,
    459                     ErrorResult& aRv);
    460 
    461  void ClearTimeout(int32_t aId, Timeout::Reason aReason);
    462 
    463  void UpdateContextOptionsInternal(JSContext* aCx,
    464                                    const JS::ContextOptions& aContextOptions);
    465 
    466  void UpdateLanguagesInternal(const nsTArray<nsString>& aLanguages);
    467 
    468  void UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key,
    469                                             Maybe<uint32_t> aValue);
    470 
    471  enum WorkerRanOrNot { WorkerNeverRan = 0, WorkerRan };
    472 
    473  void ScheduleDeletion(WorkerRanOrNot aRanOrNot);
    474 
    475  bool CollectRuntimeStats(JS::RuntimeStats* aRtStats, bool aAnonymize);
    476 
    477 #ifdef JS_GC_ZEAL
    478  void UpdateGCZealInternal(JSContext* aCx, uint8_t aGCZeal,
    479                            uint32_t aFrequency);
    480 #endif
    481 
    482  void SetLowMemoryStateInternal(JSContext* aCx, bool aState);
    483 
    484  void GarbageCollectInternal(JSContext* aCx, bool aShrinking,
    485                              bool aCollectChildren);
    486 
    487  void CycleCollectInternal(bool aCollectChildren);
    488 
    489  void OfflineStatusChangeEventInternal(bool aIsOffline);
    490 
    491  void MemoryPressureInternal();
    492 
    493  typedef MozPromise<uint64_t, nsresult, true> JSMemoryUsagePromise;
    494  RefPtr<JSMemoryUsagePromise> GetJSMemoryUsage();
    495 
    496  void SetFetchHandlerWasAdded() {
    497    MOZ_ASSERT(IsServiceWorker());
    498    AssertIsOnWorkerThread();
    499    mFetchHandlerWasAdded = true;
    500  }
    501 
    502  bool FetchHandlerWasAdded() const {
    503    MOZ_ASSERT(IsServiceWorker());
    504    AssertIsOnWorkerThread();
    505    return mFetchHandlerWasAdded;
    506  }
    507 
    508  JSContext* GetJSContext() const MOZ_NO_THREAD_SAFETY_ANALYSIS {
    509    // mJSContext is only modified on the worker thread, so workerthread code
    510    // can safely read it without a lock
    511    AssertIsOnWorkerThread();
    512    return mJSContext;
    513  }
    514 
    515  WorkerGlobalScope* GlobalScope() const {
    516    auto data = mWorkerThreadAccessible.Access();
    517    return data->mScope;
    518  }
    519 
    520  WorkerDebuggerGlobalScope* DebuggerGlobalScope() const {
    521    auto data = mWorkerThreadAccessible.Access();
    522    return data->mDebuggerScope;
    523  }
    524 
    525  // Get the global associated with the current nested event loop.  Will return
    526  // null if we're not in a nested event loop or that nested event loop does not
    527  // have an associated global.
    528  nsIGlobalObject* GetCurrentEventLoopGlobal() const {
    529    auto data = mWorkerThreadAccessible.Access();
    530    return data->mCurrentEventLoopGlobal;
    531  }
    532 
    533  nsICSPEventListener* CSPEventListener() const;
    534 
    535  void SetThread(WorkerThread* aThread);
    536 
    537  void SetWorkerPrivateInWorkerThread(WorkerThread* aThread);
    538 
    539  void ResetWorkerPrivateInWorkerThread();
    540 
    541  bool IsOnWorkerThread() const;
    542 
    543  void AssertIsOnWorkerThread() const
    544 #ifdef DEBUG
    545      ;
    546 #else
    547  {
    548  }
    549 #endif
    550 
    551  // This may block!
    552  void BeginCTypesCall();
    553 
    554  // This may block!
    555  void EndCTypesCall();
    556 
    557  void BeginCTypesCallback();
    558 
    559  void EndCTypesCallback();
    560 
    561  bool ConnectMessagePort(JSContext* aCx, UniqueMessagePortId& aIdentifier);
    562 
    563  WorkerGlobalScope* GetOrCreateGlobalScope(JSContext* aCx);
    564 
    565  WorkerDebuggerGlobalScope* CreateDebuggerGlobalScope(JSContext* aCx);
    566 
    567  bool RegisterBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
    568 
    569  bool RegisterDebuggerBindings(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
    570 
    571  bool OnLine() const {
    572    auto data = mWorkerThreadAccessible.Access();
    573    return data->mOnLine;
    574  }
    575 
    576  void StopSyncLoop(nsIEventTarget* aSyncLoopTarget, nsresult aResult);
    577 
    578  bool MaybeStopSyncLoop(nsIEventTarget* aSyncLoopTarget, nsresult aResult);
    579 
    580  void ShutdownModuleLoader();
    581 
    582  void ClearPreStartRunnables();
    583 
    584  MOZ_CAN_RUN_SCRIPT void ProcessSingleDebuggerRunnable();
    585  void ClearDebuggerEventQueue();
    586 
    587  void OnProcessNextEvent();
    588 
    589  void AfterProcessNextEvent();
    590 
    591  void AssertValidSyncLoop(nsIEventTarget* aSyncLoopTarget)
    592 #ifdef DEBUG
    593      ;
    594 #else
    595  {
    596  }
    597 #endif
    598 
    599  void AssertIsNotPotentiallyLastGCCCRunning() {
    600 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
    601    auto data = mWorkerThreadAccessible.Access();
    602    MOZ_DIAGNOSTIC_ASSERT(!data->mIsPotentiallyLastGCCCRunning);
    603 #endif
    604  }
    605 
    606  void SetWorkerScriptExecutedSuccessfully() {
    607    AssertIsOnWorkerThread();
    608    // Should only be called once!
    609    MOZ_ASSERT(!mWorkerScriptExecutedSuccessfully);
    610    mWorkerScriptExecutedSuccessfully = true;
    611  }
    612 
    613  // Only valid after CompileScriptRunnable has finished running!
    614  bool WorkerScriptExecutedSuccessfully() const {
    615    AssertIsOnWorkerThread();
    616    return mWorkerScriptExecutedSuccessfully;
    617  }
    618 
    619  // Get the event target to use when dispatching to the main thread
    620  // from this Worker thread.  This may be the main thread itself or
    621  // a ThrottledEventQueue to the main thread.
    622  nsISerialEventTarget* MainThreadEventTargetForMessaging();
    623 
    624  nsresult DispatchToMainThreadForMessaging(
    625      nsIRunnable* aRunnable,
    626      nsIEventTarget::DispatchFlags aFlags = NS_DISPATCH_NORMAL);
    627 
    628  nsresult DispatchToMainThreadForMessaging(
    629      already_AddRefed<nsIRunnable> aRunnable,
    630      nsIEventTarget::DispatchFlags aFlags = NS_DISPATCH_NORMAL);
    631 
    632  nsISerialEventTarget* MainThreadEventTarget();
    633 
    634  nsresult DispatchToMainThread(
    635      nsIRunnable* aRunnable,
    636      nsIEventTarget::DispatchFlags aFlags = NS_DISPATCH_NORMAL);
    637 
    638  nsresult DispatchToMainThread(
    639      already_AddRefed<nsIRunnable> aRunnable,
    640      nsIEventTarget::DispatchFlags aFlags = NS_DISPATCH_NORMAL);
    641 
    642  nsresult DispatchDebuggeeToMainThread(
    643      already_AddRefed<WorkerRunnable> aRunnable,
    644      nsIEventTarget::DispatchFlags aFlags = NS_DISPATCH_NORMAL);
    645 
    646  // Get an event target that will dispatch runnables as control runnables on
    647  // the worker thread.  Implement nsICancelableRunnable if you wish to take
    648  // action on cancelation.
    649  nsISerialEventTarget* ControlEventTarget();
    650 
    651  // Get an event target that will attempt to dispatch a normal WorkerRunnable,
    652  // but if that fails will then fall back to a control runnable.
    653  nsISerialEventTarget* HybridEventTarget();
    654 
    655  void DumpCrashInformation(nsACString& aString);
    656 
    657  ClientType GetClientType() const;
    658 
    659  bool EnsureCSPEventListener();
    660 
    661  void EnsurePerformanceStorage();
    662 
    663  bool GetExecutionGranted() const;
    664  void SetExecutionGranted(bool aGranted);
    665 
    666  void ScheduleTimeSliceExpiration(uint32_t aDelay);
    667  void CancelTimeSliceExpiration();
    668 
    669  JSExecutionManager* GetExecutionManager() const;
    670  void SetExecutionManager(JSExecutionManager* aManager);
    671 
    672  void ExecutionReady();
    673 
    674  PerformanceStorage* GetPerformanceStorage();
    675 
    676  bool IsAcceptingEvents() MOZ_EXCLUDES(mMutex) {
    677    AssertIsOnParentThread();
    678 
    679    MutexAutoLock lock(mMutex);
    680    return mParentStatus < Canceling;
    681  }
    682 
    683  // This method helps know if the Worker is already at Dead status.
    684  // Note that it is racy. The status may change after the function returns.
    685  bool IsDead() MOZ_EXCLUDES(mMutex) {
    686    MutexAutoLock lock(mMutex);
    687    return mStatus == Dead;
    688  }
    689 
    690  WorkerStatus ParentStatusProtected() {
    691    AssertIsOnParentThread();
    692    MutexAutoLock lock(mMutex);
    693    return mParentStatus;
    694  }
    695 
    696  WorkerStatus ParentStatus() const MOZ_REQUIRES(mMutex) {
    697    mMutex.AssertCurrentThreadOwns();
    698    return mParentStatus;
    699  }
    700 
    701  Worker* ParentEventTargetRef() const {
    702    MOZ_DIAGNOSTIC_ASSERT(mParentEventTargetRef);
    703    return mParentEventTargetRef;
    704  }
    705 
    706  void SetParentEventTargetRef(Worker* aParentEventTargetRef) {
    707    MOZ_DIAGNOSTIC_ASSERT(aParentEventTargetRef);
    708    MOZ_DIAGNOSTIC_ASSERT(!mParentEventTargetRef);
    709    mParentEventTargetRef = aParentEventTargetRef;
    710  }
    711 
    712  // Check whether this worker is a secure context.  For use from the parent
    713  // thread only; the canonical "is secure context" boolean is stored on the
    714  // compartment of the worker global.  The only reason we don't
    715  // AssertIsOnParentThread() here is so we can assert that this value matches
    716  // the one on the compartment, which has to be done from the worker thread.
    717  bool IsSecureContext() const { return mIsSecureContext; }
    718 
    719  // Check whether we're running in automation.
    720  bool IsInAutomation() const { return mIsInAutomation; }
    721 
    722  bool IsPrivilegedAddonGlobal() const { return mIsPrivilegedAddonGlobal; }
    723 
    724  TimeStamp CreationTimeStamp() const { return mCreationTimeStamp; }
    725 
    726  DOMHighResTimeStamp CreationTime() const { return mCreationTimeHighRes; }
    727 
    728  DOMHighResTimeStamp TimeStampToDOMHighRes(const TimeStamp& aTimeStamp) const {
    729    MOZ_ASSERT(!aTimeStamp.IsNull());
    730    TimeDuration duration = aTimeStamp - mCreationTimeStamp;
    731    return duration.ToMilliseconds();
    732  }
    733 
    734  LocationInfo& GetLocationInfo() { return mLocationInfo; }
    735 
    736  void CopyJSSettings(workerinternals::JSSettings& aSettings) {
    737    mozilla::MutexAutoLock lock(mMutex);
    738    aSettings = mJSSettings;
    739  }
    740 
    741  void CopyJSRealmOptions(JS::RealmOptions& aOptions) {
    742    mozilla::MutexAutoLock lock(mMutex);
    743    aOptions = IsChromeWorker() ? mJSSettings.chromeRealmOptions
    744                                : mJSSettings.contentRealmOptions;
    745  }
    746 
    747  // The ability to be a chrome worker is orthogonal to the type of
    748  // worker [Dedicated|Shared|Service].
    749  bool IsChromeWorker() const { return mIsChromeWorker; }
    750 
    751  // TODO: Invariants require that the parent worker out-live any child
    752  // worker, so WorkerPrivate* should be safe in the moment of calling.
    753  // We would like to have stronger type-system annotated/enforced handling.
    754  WorkerPrivate* GetParent() const { return mParent; }
    755 
    756  // Returns the top level worker. It can be the current worker if it's the top
    757  // level one.
    758  WorkerPrivate* GetTopLevelWorker() const {
    759    WorkerPrivate const* wp = this;
    760    while (wp->GetParent()) {
    761      wp = wp->GetParent();
    762    }
    763    return const_cast<WorkerPrivate*>(wp);
    764  }
    765 
    766  bool IsFrozen() const;
    767 
    768  bool IsFrozenForWorkerThread() const;
    769 
    770  bool IsParentWindowPaused() const {
    771    AssertIsOnParentThread();
    772    return mParentWindowPaused;
    773  }
    774 
    775  // When we debug a worker, we want to disconnect the window and the worker
    776  // communication. This happens calling this method.
    777  // Note: this method doesn't suspend the worker! Use Freeze/Thaw instead.
    778  void ParentWindowPaused();
    779 
    780  void ParentWindowResumed();
    781 
    782  const nsString& ScriptURL() const { return mScriptURL; }
    783 
    784  const nsString& WorkerName() const { return mWorkerName; }
    785  RequestCredentials WorkerCredentials() const { return mCredentialsMode; }
    786  enum WorkerType WorkerType() const { return mWorkerType; }
    787 
    788  WorkerKind Kind() const { return mWorkerKind; }
    789 
    790  bool IsDedicatedWorker() const { return mWorkerKind == WorkerKindDedicated; }
    791 
    792  bool IsSharedWorker() const { return mWorkerKind == WorkerKindShared; }
    793 
    794  bool IsServiceWorker() const { return mWorkerKind == WorkerKindService; }
    795 
    796  nsContentPolicyType ContentPolicyType() const {
    797    return ContentPolicyType(mWorkerKind);
    798  }
    799 
    800  static nsContentPolicyType ContentPolicyType(WorkerKind aWorkerKind) {
    801    switch (aWorkerKind) {
    802      case WorkerKindDedicated:
    803        return nsIContentPolicy::TYPE_INTERNAL_WORKER;
    804      case WorkerKindShared:
    805        return nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
    806      case WorkerKindService:
    807        return nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER;
    808      default:
    809        MOZ_ASSERT_UNREACHABLE("Invalid worker type");
    810        return nsIContentPolicy::TYPE_INVALID;
    811    }
    812  }
    813 
    814  nsIScriptContext* GetScriptContext() const {
    815    AssertIsOnMainThread();
    816    return mLoadInfo.mScriptContext;
    817  }
    818 
    819  const nsCString& Domain() const { return mLoadInfo.mDomain; }
    820 
    821  bool IsFromWindow() const { return mLoadInfo.mFromWindow; }
    822 
    823  nsLoadFlags GetLoadFlags() const { return mLoadInfo.mLoadFlags; }
    824 
    825  uint64_t WindowID() const { return mLoadInfo.mWindowID; }
    826 
    827  uint64_t AssociatedBrowsingContextID() const {
    828    return mLoadInfo.mAssociatedBrowsingContextID;
    829  }
    830 
    831  uint64_t ServiceWorkerID() const { return GetServiceWorkerDescriptor().Id(); }
    832 
    833  const nsCString& ServiceWorkerScope() const {
    834    return GetServiceWorkerDescriptor().Scope();
    835  }
    836 
    837  // This value should never change after the script load completes. Before
    838  // then, it may only be called on the main thread.
    839  nsIURI* GetBaseURI() const { return mLoadInfo.mBaseURI; }
    840 
    841  void SetBaseURI(nsIURI* aBaseURI);
    842 
    843  nsIURI* GetResolvedScriptURI() const { return mLoadInfo.mResolvedScriptURI; }
    844 
    845  const nsString& ServiceWorkerCacheName() const {
    846    MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
    847    AssertIsOnMainThread();
    848    return mLoadInfo.mServiceWorkerCacheName;
    849  }
    850 
    851  const ServiceWorkerDescriptor& GetServiceWorkerDescriptor() const {
    852    MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
    853    MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mServiceWorkerDescriptor.isSome());
    854    return mLoadInfo.mServiceWorkerDescriptor.ref();
    855  }
    856 
    857  const ServiceWorkerRegistrationDescriptor&
    858  GetServiceWorkerRegistrationDescriptor() const {
    859    MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
    860    MOZ_DIAGNOSTIC_ASSERT(
    861        mLoadInfo.mServiceWorkerRegistrationDescriptor.isSome());
    862    return mLoadInfo.mServiceWorkerRegistrationDescriptor.ref();
    863  }
    864 
    865  const ClientInfo& GetSourceInfo() const {
    866    MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
    867    MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mSourceInfo.isSome());
    868    return mLoadInfo.mSourceInfo.ref();
    869  }
    870 
    871  void UpdateServiceWorkerState(ServiceWorkerState aState) {
    872    MOZ_DIAGNOSTIC_ASSERT(IsServiceWorker());
    873    MOZ_DIAGNOSTIC_ASSERT(mLoadInfo.mServiceWorkerDescriptor.isSome());
    874    return mLoadInfo.mServiceWorkerDescriptor.ref().SetState(aState);
    875  }
    876 
    877  void UpdateIsOnContentBlockingAllowList(bool aOnContentBlockingAllowList);
    878 
    879  const Maybe<ServiceWorkerDescriptor>& GetParentController() const {
    880    return mLoadInfo.mParentController;
    881  }
    882 
    883  const ChannelInfo& GetChannelInfo() const { return mLoadInfo.mChannelInfo; }
    884 
    885  void SetChannelInfo(const ChannelInfo& aChannelInfo) {
    886    AssertIsOnMainThread();
    887    MOZ_ASSERT(!mLoadInfo.mChannelInfo.IsInitialized());
    888    MOZ_ASSERT(aChannelInfo.IsInitialized());
    889    mLoadInfo.mChannelInfo = aChannelInfo;
    890  }
    891 
    892  void InitChannelInfo(nsIChannel* aChannel) {
    893    mLoadInfo.mChannelInfo.InitFromChannel(aChannel);
    894  }
    895 
    896  void InitChannelInfo(const ChannelInfo& aChannelInfo) {
    897    mLoadInfo.mChannelInfo = aChannelInfo;
    898  }
    899 
    900  nsIPrincipal* GetPrincipal() const { return mLoadInfo.mPrincipal; }
    901 
    902  nsIPrincipal* GetLoadingPrincipal() const {
    903    return mLoadInfo.mLoadingPrincipal;
    904  }
    905 
    906  nsIPrincipal* GetPartitionedPrincipal() const {
    907    return mLoadInfo.mPartitionedPrincipal;
    908  }
    909 
    910  nsIPrincipal* GetEffectiveStoragePrincipal() const;
    911 
    912  nsILoadGroup* GetLoadGroup() const {
    913    AssertIsOnMainThread();
    914    return mLoadInfo.mLoadGroup;
    915  }
    916 
    917  bool UsesSystemPrincipal() const {
    918    return GetPrincipal()->IsSystemPrincipal();
    919  }
    920  bool UsesAddonOrExpandedAddonPrincipal() const {
    921    return GetPrincipal()->GetIsAddonOrExpandedAddonPrincipal();
    922  }
    923 
    924  const mozilla::ipc::PrincipalInfo& GetPrincipalInfo() const {
    925    return *mLoadInfo.mPrincipalInfo;
    926  }
    927 
    928  const mozilla::ipc::PrincipalInfo& GetPartitionedPrincipalInfo() const {
    929    return *mLoadInfo.mPartitionedPrincipalInfo;
    930  }
    931 
    932  const mozilla::ipc::PrincipalInfo& GetEffectiveStoragePrincipalInfo() const;
    933 
    934  already_AddRefed<nsIChannel> ForgetWorkerChannel() {
    935    AssertIsOnMainThread();
    936    return mLoadInfo.mChannel.forget();
    937  }
    938 
    939  nsPIDOMWindowInner* GetWindow() const {
    940    AssertIsOnMainThread();
    941    return mLoadInfo.mWindow;
    942  }
    943 
    944  nsPIDOMWindowInner* GetAncestorWindow() const;
    945 
    946  void EvictFromBFCache();
    947 
    948  nsIContentSecurityPolicy* GetCsp() const {
    949    AssertIsOnMainThread();
    950    return mLoadInfo.mCSP;
    951  }
    952 
    953  nsresult SetCsp(nsIContentSecurityPolicy* aCSP);
    954 
    955  nsresult SetCSPFromHeaderValues(const nsACString& aCSPHeaderValue,
    956                                  const nsACString& aCSPReportOnlyHeaderValue);
    957 
    958  void StoreCSPOnClient();
    959 
    960  const mozilla::ipc::CSPInfo& GetCSPInfo() const {
    961    return mLoadInfo.mCSPContext->CSPInfo();
    962  }
    963 
    964  WorkerCSPContext* GetCSPContext() const {
    965    return mLoadInfo.mCSPContext.get();
    966  }
    967 
    968  void UpdateReferrerInfoFromHeader(
    969      const nsACString& aReferrerPolicyHeaderValue);
    970 
    971  nsIReferrerInfo* GetReferrerInfo() const { return mLoadInfo.mReferrerInfo; }
    972 
    973  ReferrerPolicy GetReferrerPolicy() const {
    974    return mLoadInfo.mReferrerInfo->ReferrerPolicy();
    975  }
    976 
    977  void SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) {
    978    mLoadInfo.mReferrerInfo = aReferrerInfo;
    979  }
    980 
    981  bool XHRParamsAllowed() const { return mLoadInfo.mXHRParamsAllowed; }
    982 
    983  void SetXHRParamsAllowed(bool aAllowed) {
    984    mLoadInfo.mXHRParamsAllowed = aAllowed;
    985  }
    986 
    987  mozilla::StorageAccess StorageAccess() const {
    988    AssertIsOnWorkerThread();
    989    if (mLoadInfo.mUsingStorageAccess) {
    990      return mozilla::StorageAccess::eAllow;
    991    }
    992 
    993    return mLoadInfo.mStorageAccess;
    994  }
    995 
    996  bool UseRegularPrincipal() const {
    997    AssertIsOnWorkerThread();
    998    return mLoadInfo.mUseRegularPrincipal;
    999  }
   1000 
   1001  bool UsingStorageAccess() const {
   1002    AssertIsOnWorkerThread();
   1003    return mLoadInfo.mUsingStorageAccess;
   1004  }
   1005 
   1006  nsICookieJarSettings* CookieJarSettings() const {
   1007    // Any thread.
   1008    MOZ_ASSERT(mLoadInfo.mCookieJarSettings);
   1009    return mLoadInfo.mCookieJarSettings;
   1010  }
   1011 
   1012  const net::CookieJarSettingsArgs& CookieJarSettingsArgs() const {
   1013    MOZ_ASSERT(mLoadInfo.mCookieJarSettings);
   1014    return mLoadInfo.mCookieJarSettingsArgs;
   1015  }
   1016 
   1017  const OriginAttributes& GetOriginAttributes() const {
   1018    return mLoadInfo.mOriginAttributes;
   1019  }
   1020 
   1021  // Determine if the SW testing per-window flag is set by devtools
   1022  bool ServiceWorkersTestingInWindow() const {
   1023    return mLoadInfo.mServiceWorkersTestingInWindow;
   1024  }
   1025 
   1026  // Determine if the worker was created under a third-party context.
   1027  bool IsThirdPartyContext() const { return mLoadInfo.mIsThirdPartyContext; }
   1028 
   1029  bool IsWatchedByDevTools() const { return mLoadInfo.mWatchedByDevTools; }
   1030 
   1031  const Maybe<RFPTargetSet>& GetOverriddenFingerprintingSettings() const {
   1032    return mLoadInfo.mOverriddenFingerprintingSettings;
   1033  }
   1034 
   1035  bool IsOn3PCBExceptionList() const {
   1036    return mLoadInfo.mIsOn3PCBExceptionList;
   1037  }
   1038 
   1039  RemoteWorkerChild* GetRemoteWorkerController();
   1040 
   1041  void SetRemoteWorkerController(RemoteWorkerChild* aController);
   1042 
   1043  RefPtr<GenericPromise> SetServiceWorkerSkipWaitingFlag();
   1044 
   1045  // We can assume that an nsPIDOMWindow will be available for Freeze, Thaw
   1046  // as these are only used for globals going in and out of the bfcache.
   1047  bool Freeze(const nsPIDOMWindowInner* aWindow);
   1048 
   1049  bool Thaw(const nsPIDOMWindowInner* aWindow);
   1050 
   1051  void PropagateStorageAccessPermissionGranted();
   1052 
   1053  void NotifyStorageKeyUsed();
   1054 
   1055  void EnableDebugger();
   1056 
   1057  void DisableDebugger();
   1058 
   1059  void BindRemoteWorkerDebuggerChild();
   1060 
   1061  void CreateRemoteDebuggerEndpoints();
   1062 
   1063  void SetIsRemoteDebuggerRegistered(const bool& aRegistered);
   1064 
   1065  void SetIsRemoteDebuggerReady(const bool& aReady);
   1066 
   1067  void EnableRemoteDebugger();
   1068 
   1069  void DisableRemoteDebugger();
   1070 
   1071  void DisableRemoteDebuggerOnWorkerThread(const bool& aForShutdown = false);
   1072 
   1073  void SetIsQueued(const bool& aQueued);
   1074 
   1075  bool IsQueued() const;
   1076 
   1077  void UpdateWindowIDToDebugger(const uint64_t& aWindowID, const bool& aIsAdd);
   1078 
   1079  already_AddRefed<WorkerRunnable> MaybeWrapAsWorkerRunnable(
   1080      already_AddRefed<nsIRunnable> aRunnable);
   1081 
   1082  bool ProxyReleaseMainThreadObjects();
   1083 
   1084  void SetLowMemoryState(bool aState);
   1085 
   1086  void GarbageCollect(bool aShrinking);
   1087 
   1088  void CycleCollect();
   1089 
   1090  nsresult SetPrincipalsAndCSPOnMainThread(nsIPrincipal* aPrincipal,
   1091                                           nsIPrincipal* aPartitionedPrincipal,
   1092                                           nsILoadGroup* aLoadGroup,
   1093                                           nsIContentSecurityPolicy* aCsp);
   1094 
   1095  nsresult SetPrincipalsAndCSPFromChannel(nsIChannel* aChannel);
   1096 
   1097  bool FinalChannelPrincipalIsValid(nsIChannel* aChannel);
   1098 
   1099 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
   1100  bool PrincipalURIMatchesScriptURL();
   1101 #endif
   1102 
   1103  void UpdateOverridenLoadGroup(nsILoadGroup* aBaseLoadGroup);
   1104 
   1105  void WorkerScriptLoaded();
   1106 
   1107  Document* GetDocument() const;
   1108 
   1109  void MemoryPressure();
   1110 
   1111  void UpdateContextOptions(const JS::ContextOptions& aContextOptions);
   1112 
   1113  void UpdateLanguages(const nsTArray<nsString>& aLanguages);
   1114 
   1115  void UpdateJSWorkerMemoryParameter(JSGCParamKey key, Maybe<uint32_t> value);
   1116 
   1117 #ifdef JS_GC_ZEAL
   1118  void UpdateGCZeal(uint8_t aGCZeal, uint32_t aFrequency);
   1119 #endif
   1120 
   1121  void OfflineStatusChangeEvent(bool aIsOffline);
   1122 
   1123  nsresult Dispatch(already_AddRefed<WorkerRunnable> aRunnable,
   1124                    nsIEventTarget* aSyncLoopTarget = nullptr);
   1125 
   1126  nsresult DispatchControlRunnable(
   1127      already_AddRefed<WorkerRunnable> aWorkerRunnable);
   1128 
   1129  nsresult DispatchDebuggerRunnable(
   1130      already_AddRefed<WorkerRunnable> aDebuggerRunnable);
   1131 
   1132  nsresult DispatchToParent(already_AddRefed<WorkerRunnable> aRunnable);
   1133 
   1134  bool IsOnParentThread() const;
   1135  void DebuggerInterruptRequest();
   1136 
   1137 #ifdef DEBUG
   1138  void AssertIsOnParentThread() const;
   1139 
   1140  void AssertInnerWindowIsCorrect() const;
   1141 #else
   1142  void AssertIsOnParentThread() const {}
   1143 
   1144  void AssertInnerWindowIsCorrect() const {}
   1145 #endif
   1146 
   1147 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
   1148  bool PrincipalIsValid() const;
   1149 #endif
   1150 
   1151  void StartCancelingTimer();
   1152 
   1153  const nsString& Id();
   1154 
   1155  const nsID& AgentClusterId() const { return mAgentClusterId; }
   1156 
   1157  bool IsSharedMemoryAllowed() const;
   1158 
   1159  // https://whatpr.org/html/4734/structured-data.html#cross-origin-isolated
   1160  bool CrossOriginIsolated() const;
   1161 
   1162  void SetUseCounter(UseCounterWorker aUseCounter) {
   1163    MOZ_ASSERT(!mReportedUseCounters);
   1164    MOZ_ASSERT(aUseCounter > UseCounterWorker::Unknown);
   1165    AssertIsOnWorkerThread();
   1166    mUseCounters[static_cast<size_t>(aUseCounter)] = true;
   1167  }
   1168 
   1169  /**
   1170   * COEP Methods
   1171   *
   1172   * If browser.tabs.remote.useCrossOriginEmbedderPolicy=false, these methods
   1173   * will, depending on the return type, return a value that will avoid
   1174   * assertion failures or a value that won't block loads.
   1175   */
   1176  nsILoadInfo::CrossOriginEmbedderPolicy GetEmbedderPolicy() const;
   1177 
   1178  // Fails if a policy has already been set or if `aPolicy` violates the owner's
   1179  // policy, if an owner exists.
   1180  mozilla::Result<Ok, nsresult> SetEmbedderPolicy(
   1181      nsILoadInfo::CrossOriginEmbedderPolicy aPolicy);
   1182 
   1183  // `aRequest` is the request loading the worker and must be QI-able to
   1184  // `nsIChannel*`. It's used to verify that the worker can indeed inherit its
   1185  // owner's COEP (when an owner exists).
   1186  //
   1187  // TODO: remove `aRequest`; currently, it's required because instances may not
   1188  // always know its final, resolved script URL or have access internally to
   1189  // `aRequest`.
   1190  void InheritOwnerEmbedderPolicyOrNull(nsIRequest* aRequest);
   1191 
   1192  // Requires a policy to already have been set.
   1193  bool MatchEmbedderPolicy(
   1194      nsILoadInfo::CrossOriginEmbedderPolicy aPolicy) const;
   1195 
   1196  nsILoadInfo::CrossOriginEmbedderPolicy GetOwnerEmbedderPolicy() const;
   1197 
   1198  void SetCCCollectedAnything(bool collectedAnything);
   1199  bool isLastCCCollectedAnything();
   1200 
   1201  uint32_t GetCurrentTimerNestingLevel() const;
   1202 
   1203  void IncreaseTopLevelWorkerFinishedRunnableCount() {
   1204    ++mTopLevelWorkerFinishedRunnableCount;
   1205  }
   1206  void DecreaseTopLevelWorkerFinishedRunnableCount() {
   1207    --mTopLevelWorkerFinishedRunnableCount;
   1208  }
   1209  void IncreaseWorkerFinishedRunnableCount() { ++mWorkerFinishedRunnableCount; }
   1210  void DecreaseWorkerFinishedRunnableCount() { --mWorkerFinishedRunnableCount; }
   1211 
   1212  void JSAsyncTaskStarted(JS::Dispatchable* aDispatchable);
   1213  void JSAsyncTaskFinished(JS::Dispatchable* aDispatchable);
   1214 
   1215  void RunShutdownTasks();
   1216 
   1217  bool CancelBeforeWorkerScopeConstructed() const {
   1218    auto data = mWorkerThreadAccessible.Access();
   1219    return data->mCancelBeforeWorkerScopeConstructed;
   1220  }
   1221 
   1222  enum class CCFlag : uint8_t {
   1223    EligibleForWorkerRef,
   1224    IneligibleForWorkerRef,
   1225    EligibleForChildWorker,
   1226    IneligibleForChildWorker,
   1227    EligibleForTimeout,
   1228    IneligibleForTimeout,
   1229    CheckBackgroundActors,
   1230  };
   1231 
   1232  // When create/release a StrongWorkerRef, child worker, and timeout, this
   1233  // method is used to setup if mParentEventTargetRef can get into
   1234  // cycle-collection.
   1235  // When this method is called, it will also checks if any background actor
   1236  // should block the mParentEventTargetRef cycle-collection when there is no
   1237  // StrongWorkerRef/ChildWorker/Timeout.
   1238  // Worker thread only.
   1239  void UpdateCCFlag(const CCFlag);
   1240 
   1241  // This is used in WorkerPrivate::Traverse() to checking if
   1242  // mParentEventTargetRef should get into cycle-collection.
   1243  // Parent thread only method.
   1244  bool IsEligibleForCC();
   1245 
   1246  // A method which adjusts the count of background actors which should not
   1247  // block WorkerPrivate::mParentEventTargetRef cycle-collection.
   1248  // Worker thread only.
   1249  void AdjustNonblockingCCBackgroundActorCount(int32_t aCount);
   1250 
   1251  RefPtr<WorkerParentRef> GetWorkerParentRef() const;
   1252 
   1253  bool MayContinueRunning() {
   1254    AssertIsOnWorkerThread();
   1255 
   1256    WorkerStatus status;
   1257    {
   1258      MutexAutoLock lock(mMutex);
   1259      status = mStatus;
   1260    }
   1261 
   1262    if (status < Canceling) {
   1263      return true;
   1264    }
   1265 
   1266    return false;
   1267  }
   1268 
   1269 private:
   1270  WorkerPrivate(
   1271      WorkerPrivate* aParent, const nsAString& aScriptURL, bool aIsChromeWorker,
   1272      WorkerKind aWorkerKind, RequestCredentials aRequestCredentials,
   1273      enum WorkerType aWorkerType, const nsAString& aWorkerName,
   1274      const nsACString& aServiceWorkerScope, WorkerLoadInfo& aLoadInfo,
   1275      nsString&& aId, const nsID& aAgentClusterId,
   1276      const nsILoadInfo::CrossOriginOpenerPolicy aAgentClusterOpenerPolicy,
   1277      CancellationCallback&& aCancellationCallback,
   1278      TerminationCallback&& aTerminationCallback,
   1279      mozilla::ipc::Endpoint<PRemoteWorkerNonLifeCycleOpControllerChild>&&
   1280          aChildEp);
   1281 
   1282  ~WorkerPrivate();
   1283 
   1284  struct AgentClusterIdAndCoop {
   1285    nsID mId;
   1286    nsILoadInfo::CrossOriginOpenerPolicy mCoop;
   1287  };
   1288 
   1289  static AgentClusterIdAndCoop ComputeAgentClusterIdAndCoop(
   1290      WorkerPrivate* aParent, WorkerKind aWorkerKind, WorkerLoadInfo* aLoadInfo,
   1291      bool aIsChromeWorker);
   1292 
   1293  void CancelAllTimeouts();
   1294 
   1295  enum class ProcessAllControlRunnablesResult {
   1296    // We did not process anything.
   1297    Nothing,
   1298    // We did process something, states may have changed, but we can keep
   1299    // executing script.
   1300    MayContinue,
   1301    // We did process something, and should not continue executing script.
   1302    Abort
   1303  };
   1304 
   1305  ProcessAllControlRunnablesResult ProcessAllControlRunnables() {
   1306    MutexAutoLock lock(mMutex);
   1307    return ProcessAllControlRunnablesLocked();
   1308  }
   1309 
   1310  ProcessAllControlRunnablesResult ProcessAllControlRunnablesLocked()
   1311      MOZ_REQUIRES(mMutex);
   1312 
   1313  void EnableMemoryReporter();
   1314 
   1315  void DisableMemoryReporter();
   1316 
   1317  void WaitForWorkerEvents() MOZ_REQUIRES(mMutex);
   1318 
   1319  // If the worker shutdown status is equal or greater then aFailStatus, this
   1320  // operation will fail and nullptr will be returned. See WorkerStatus.h for
   1321  // more information about the correct value to use.
   1322  already_AddRefed<nsISerialEventTarget> CreateNewSyncLoop(
   1323      WorkerStatus aFailStatus);
   1324 
   1325  nsresult RunCurrentSyncLoop();
   1326 
   1327  nsresult DestroySyncLoop(uint32_t aLoopIndex);
   1328 
   1329  void InitializeGCTimers();
   1330 
   1331  enum GCTimerMode { PeriodicTimer = 0, IdleTimer, NoTimer };
   1332 
   1333  void SetGCTimerMode(GCTimerMode aMode);
   1334 
   1335 public:
   1336  void CancelGCTimers() { SetGCTimerMode(NoTimer); }
   1337 
   1338 private:
   1339  void ShutdownGCTimers();
   1340 
   1341  friend class WorkerRef;
   1342 
   1343  bool AddWorkerRef(WorkerRef* aWorkerRefer, WorkerStatus aFailStatus);
   1344 
   1345  void RemoveWorkerRef(WorkerRef* aWorkerRef);
   1346 
   1347  void NotifyWorkerRefs(WorkerStatus aStatus);
   1348 
   1349  bool HasActiveWorkerRefs();
   1350 
   1351  friend class WorkerEventTarget;
   1352 
   1353  nsresult RegisterShutdownTask(nsITargetShutdownTask* aTask);
   1354 
   1355  nsresult UnregisterShutdownTask(nsITargetShutdownTask* aTask);
   1356 
   1357  // Internal logic to dispatch a runnable. This is separate from Dispatch()
   1358  // to allow runnables to be atomically dispatched in bulk.
   1359  nsresult DispatchLockHeld(already_AddRefed<WorkerRunnable> aRunnable,
   1360                            nsIEventTarget* aSyncLoopTarget,
   1361                            const MutexAutoLock& aProofOfLock)
   1362      MOZ_REQUIRES(mMutex);
   1363 
   1364  // This method dispatches a simple runnable that starts the shutdown procedure
   1365  // after a self.close(). This method is called after a ClearMainEventQueue()
   1366  // to be sure that the canceling runnable is the only one in the queue.  We
   1367  // need this async operation to be sure that all the current JS code is
   1368  // executed.
   1369  void DispatchCancelingRunnable();
   1370 
   1371  bool GetUseCounter(UseCounterWorker aUseCounter) {
   1372    MOZ_ASSERT(aUseCounter > UseCounterWorker::Unknown);
   1373    AssertIsOnWorkerThread();
   1374    return mUseCounters[static_cast<size_t>(aUseCounter)];
   1375  }
   1376 
   1377  void ReportUseCounters();
   1378 
   1379  UniquePtr<ClientSource> CreateClientSource();
   1380 
   1381  // This method is called when corresponding script loader processes the COEP
   1382  // header for the worker.
   1383  // This method should be called only once in the main thread.
   1384  // After this method is called the COEP value owner(window/parent worker) is
   1385  // cached in mOwnerEmbedderPolicy such that it can be accessed in other
   1386  // threads, i.e. WorkerThread.
   1387  void EnsureOwnerEmbedderPolicy();
   1388 
   1389  class EventTarget;
   1390  friend class EventTarget;
   1391  friend class AutoSyncLoopHolder;
   1392 
   1393  class MemoryReporter;
   1394  friend class MemoryReporter;
   1395 
   1396  friend class mozilla::dom::WorkerThread;
   1397 
   1398  SharedMutex mMutex;
   1399  mozilla::CondVar mCondVar MOZ_GUARDED_BY(mMutex);
   1400 
   1401  // We cannot make this CheckedUnsafePtr<WorkerPrivate> as this would violate
   1402  // our static assert
   1403  MOZ_NON_OWNING_REF WorkerPrivate* const mParent;
   1404 
   1405  const nsString mScriptURL;
   1406 
   1407  // This is the worker name for shared workers and dedicated workers.
   1408  const nsString mWorkerName;
   1409  const RequestCredentials mCredentialsMode;
   1410  enum WorkerType mWorkerType;
   1411 
   1412  const WorkerKind mWorkerKind;
   1413 
   1414  // The worker is owned by its thread, which is represented here.  This is set
   1415  // in Constructor() and emptied by WorkerFinishedRunnable, and conditionally
   1416  // traversed by the cycle collector if no other things preventing shutdown.
   1417  //
   1418  // There are 4 ways a worker can be terminated:
   1419  // 1. GC/CC - When the worker is in idle state (busycount == 0), it allows to
   1420  //    traverse the 'hidden' mParentEventTargetRef pointer. This is the exposed
   1421  //    Worker webidl object. Doing this, CC will be able to detect a cycle and
   1422  //    Unlink is called. In Unlink, Worker calls Cancel().
   1423  // 2. Worker::Cancel() is called - the shutdown procedure starts immediately.
   1424  // 3. WorkerScope::Close() is called - Similar to point 2.
   1425  // 4. xpcom-shutdown notification - We call Kill().
   1426  RefPtr<Worker> mParentEventTargetRef;
   1427  RefPtr<WorkerPrivate> mSelfRef;
   1428 
   1429  CancellationCallback mCancellationCallback;
   1430 
   1431  // The termination callback is passed into the constructor on the parent
   1432  // thread and invoked by `ClearSelfAndParentEventTargetRef` just before it
   1433  // drops its self-ref.
   1434  TerminationCallback mTerminationCallback;
   1435 
   1436  // The lifetime of these objects within LoadInfo is managed explicitly;
   1437  // they do not need to be cycle collected.
   1438  WorkerLoadInfo mLoadInfo;
   1439  LocationInfo mLocationInfo;
   1440 
   1441  // Protected by mMutex.
   1442  workerinternals::JSSettings mJSSettings MOZ_GUARDED_BY(mMutex);
   1443 
   1444  WorkerDebugger* mDebugger;
   1445 
   1446  workerinternals::Queue<WorkerRunnable*, 4> mControlQueue;
   1447  workerinternals::Queue<WorkerRunnable*, 4> mDebuggerQueue
   1448      MOZ_GUARDED_BY(mMutex);
   1449 
   1450  // This counts the numbers of dispatching WorkerControlRunnables.
   1451  // This is used to decouple the lock sequence between WorkerPrivate::mMutex
   1452  // and FutexThread::Lock. If this count is not zero, it means there are some
   1453  // WorkerControlRunnables are dispatching, and WorkerControlRunables might
   1454  // unlock WorkerPrivate::mMutex to request JS execution interrupt on the
   1455  // Worker thread.
   1456  // When a Worker starts shutdown, before releasing mJSContext, this value must
   1457  // be ensured to be zero.
   1458  uint32_t mDispatchingControlRunnables MOZ_GUARDED_BY(mMutex);
   1459 
   1460  // Touched on multiple threads, protected with mMutex. Only modified on the
   1461  // worker thread
   1462  JSContext* mJSContext MOZ_GUARDED_BY(mMutex);
   1463  // mThread is only modified on the Worker thread, before calling DoRunLoop
   1464  RefPtr<WorkerThread> mThread MOZ_GUARDED_BY(mMutex);
   1465  // mPRThread is only modified on another thread in ScheduleWorker(), and is
   1466  // constant for the duration of DoRunLoop.  Static mutex analysis doesn't help
   1467  // here
   1468  PRThread* mPRThread;
   1469 
   1470  // Accessed from main thread
   1471  RefPtr<ThrottledEventQueue> mMainThreadEventTargetForMessaging;
   1472  RefPtr<ThrottledEventQueue> mMainThreadEventTarget;
   1473 
   1474  // Accessed from worker thread and destructing thread
   1475  RefPtr<WorkerEventTarget> mWorkerControlEventTarget;
   1476  RefPtr<WorkerEventTarget> mWorkerHybridEventTarget;
   1477 
   1478  // A pauseable queue for WorkerDebuggeeRunnables directed at the main thread.
   1479  // See WorkerDebuggeeRunnable for details.
   1480  RefPtr<ThrottledEventQueue> mMainThreadDebuggeeEventTarget;
   1481 
   1482  struct SyncLoopInfo {
   1483    explicit SyncLoopInfo(EventTarget* aEventTarget);
   1484 
   1485    RefPtr<EventTarget> mEventTarget;
   1486    nsresult mResult;
   1487    bool mCompleted;
   1488 #ifdef DEBUG
   1489    bool mHasRun;
   1490 #endif
   1491  };
   1492 
   1493  // This is only modified on the worker thread, but in DEBUG builds
   1494  // AssertValidSyncLoop function iterates it on other threads. Therefore
   1495  // modifications are done with mMutex held *only* in DEBUG builds.
   1496  nsTArray<UniquePtr<SyncLoopInfo>> mSyncLoopStack;
   1497 
   1498  nsCOMPtr<nsITimer> mCancelingTimer;
   1499 
   1500  // fired on the main thread if the worker script fails to load
   1501  nsCOMPtr<nsIRunnable> mLoadFailedRunnable;
   1502 
   1503  RefPtr<PerformanceStorage> mPerformanceStorage;
   1504 
   1505  RefPtr<WorkerCSPEventListener> mCSPEventListener;
   1506 
   1507  // Protected by mMutex.
   1508  nsTArray<RefPtr<WorkerThreadRunnable>> mPreStartRunnables
   1509      MOZ_GUARDED_BY(mMutex);
   1510 
   1511  // Only touched on the parent thread.  Used for both SharedWorker and
   1512  // ServiceWorker RemoteWorkers.
   1513  RefPtr<RemoteWorkerChild> mRemoteWorkerController;
   1514 
   1515  // Only touched on the worker thread. Used for both SharedWorker and
   1516  // ServiceWorker RemoteWorkers.
   1517  RefPtr<RemoteWorkerNonLifeCycleOpControllerChild>
   1518      mRemoteWorkerNonLifeCycleOpController;
   1519 
   1520  mozilla::ipc::Endpoint<PRemoteWorkerNonLifeCycleOpControllerChild> mChildEp;
   1521 
   1522  RefPtr<RemoteWorkerDebuggerChild> mRemoteDebugger;
   1523  mozilla::ipc::Endpoint<PRemoteWorkerDebuggerChild> mDebuggerChildEp;
   1524  mozilla::ipc::Endpoint<PRemoteWorkerDebuggerParent> mDebuggerParentEp;
   1525  bool mRemoteDebuggerRegistered MOZ_GUARDED_BY(mMutex);
   1526  bool mRemoteDebuggerReady MOZ_GUARDED_BY(mMutex);
   1527  bool mIsQueued;  // Should only touched on parent thread.
   1528  mozilla::CondVar mDebuggerBindingCondVar MOZ_GUARDED_BY(mMutex);
   1529  RefPtr<WorkerEventTarget> mWorkerDebuggerEventTarget;
   1530 
   1531  JS::UniqueChars mDefaultLocale;  // nulled during worker JSContext init
   1532  TimeStamp mKillTime;
   1533  WorkerStatus mParentStatus MOZ_GUARDED_BY(mMutex);
   1534  WorkerStatus mStatus MOZ_GUARDED_BY(mMutex);
   1535 
   1536  TimeStamp mCreationTimeStamp;
   1537  DOMHighResTimeStamp mCreationTimeHighRes;
   1538 
   1539  // Flags for use counters used directly by this worker.
   1540  static_assert(sizeof(UseCounterWorker) <= sizeof(size_t),
   1541                "UseCounterWorker is too big");
   1542  static_assert(UseCounterWorker::Count >= static_cast<UseCounterWorker>(0),
   1543                "Should be non-negative value and safe to cast to unsigned");
   1544  std::bitset<static_cast<size_t>(UseCounterWorker::Count)> mUseCounters;
   1545  bool mReportedUseCounters;
   1546 
   1547  // This is created while creating the WorkerPrivate, so it's safe to be
   1548  // touched on any thread.
   1549  const nsID mAgentClusterId;
   1550 
   1551  // Things touched on worker thread only.
   1552  struct WorkerThreadAccessible {
   1553    explicit WorkerThreadAccessible(WorkerPrivate* aParent);
   1554 
   1555    RefPtr<WorkerGlobalScope> mScope;
   1556    RefPtr<WorkerDebuggerGlobalScope> mDebuggerScope;
   1557    // We cannot make this CheckedUnsafePtr<WorkerPrivate> as this would violate
   1558    // our static assert
   1559    nsTArray<WorkerPrivate*> mChildWorkers;
   1560    nsTObserverArray<WorkerRef*> mWorkerRefs;
   1561 
   1562    nsCOMPtr<nsITimer> mPeriodicGCTimer;
   1563    nsCOMPtr<nsITimer> mIdleGCTimer;
   1564 
   1565    RefPtr<MemoryReporter> mMemoryReporter;
   1566 
   1567    // While running a nested event loop, whether a sync loop or a debugger
   1568    // event loop we want to keep track of which global is running it, if any,
   1569    // so runnables that run off that event loop can get at that information. In
   1570    // practice this only matters for various worker debugger runnables running
   1571    // against sandboxes, because all other runnables know which globals they
   1572    // belong to already.  We could also address this by threading the relevant
   1573    // global through the chains of runnables involved, but we'd need to thread
   1574    // it through some runnables that run on the main thread, and that would
   1575    // require some care to make sure things get released on the correct thread,
   1576    // which we'd rather avoid.  This member is only accessed on the worker
   1577    // thread.
   1578    nsCOMPtr<nsIGlobalObject> mCurrentEventLoopGlobal;
   1579 
   1580    // Timer that triggers an interrupt on expiration of the current time slice
   1581    nsCOMPtr<nsITimer> mTSTimer;
   1582 
   1583    // Execution manager used to regulate execution for this worker.
   1584    RefPtr<JSExecutionManager> mExecutionManager;
   1585 
   1586    // Used to relinguish clearance for CTypes Callbacks.
   1587    nsTArray<AutoYieldJSThreadExecution> mYieldJSThreadExecution;
   1588 
   1589    uint32_t mNumWorkerRefsPreventingShutdownStart;
   1590    uint32_t mDebuggerEventLoopLevel;
   1591 
   1592    // This is the count of background actors that binding with IPCWorkerRefs.
   1593    // This count would be used in WorkerPrivate::UpdateCCFlag for checking if
   1594    // CC should be blocked by background actors.
   1595    uint32_t mNonblockingCCBackgroundActorCount;
   1596 
   1597    uint32_t mErrorHandlerRecursionCount;
   1598 
   1599    bool mFrozen;
   1600 
   1601    // This flag is set by the debugger interrupt control runnable to indicate
   1602    // that we want to process debugger runnables as part of control runnable
   1603    // processing, which is something we don't normally want to do. The flag is
   1604    // cleared after processing the debugger runnables.
   1605    bool mDebuggerInterruptRequested;
   1606 
   1607    bool mRunningExpiredTimeouts;
   1608    bool mPeriodicGCTimerRunning;
   1609    bool mIdleGCTimerRunning;
   1610    bool mOnLine;
   1611    bool mJSThreadExecutionGranted;
   1612    bool mCCCollectedAnything;
   1613    FlippedOnce<false> mDeletionScheduled;
   1614    FlippedOnce<false> mCancelBeforeWorkerScopeConstructed;
   1615    FlippedOnce<false> mPerformedShutdownAfterLastContentTaskExecuted;
   1616 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
   1617    bool mIsPotentiallyLastGCCCRunning = false;
   1618 #endif
   1619  };
   1620  ThreadBound<WorkerThreadAccessible> mWorkerThreadAccessible;
   1621 
   1622  class MOZ_RAII AutoPushEventLoopGlobal {
   1623   public:
   1624    AutoPushEventLoopGlobal(WorkerPrivate* aWorkerPrivate, JSContext* aCx);
   1625    ~AutoPushEventLoopGlobal();
   1626 
   1627   private:
   1628    nsCOMPtr<nsIGlobalObject> mOldEventLoopGlobal;
   1629 
   1630 #ifdef DEBUG
   1631    // This is used to checking if we are on the right stack while push the
   1632    // mOldEventLoopGlobal back.
   1633    nsCOMPtr<nsIGlobalObject> mNewEventLoopGlobal;
   1634 #endif
   1635  };
   1636  friend class AutoPushEventLoopGlobal;
   1637 
   1638  uint32_t mPostSyncLoopOperations;
   1639 
   1640  // List of operations to do at the end of the last sync event loop.
   1641  enum {
   1642    eDispatchCancelingRunnable = 0x02,
   1643  };
   1644 
   1645  bool mParentWindowPaused;
   1646 
   1647  bool mWorkerScriptExecutedSuccessfully;
   1648  bool mFetchHandlerWasAdded;
   1649  bool mMainThreadObjectsForgotten;
   1650  bool mIsChromeWorker;
   1651  bool mParentFrozen;
   1652 
   1653  // In order to ensure that the debugger can interrupt a busy worker,
   1654  // including when atomics are used, we reuse the worker's existing
   1655  // JS Interrupt facility used by control runnables.
   1656  // Rather that triggering an interrupt immediately when a debugger runnable
   1657  // is dispatched, we instead start a timer that will fire if we haven't
   1658  // already processed the runnable, targeting the timer's callback at the
   1659  // control event target. This allows existing runnables that were going to
   1660  // finish in a timely fashion to finish.
   1661  nsCOMPtr<nsITimer> mDebuggerInterruptTimer MOZ_GUARDED_BY(mMutex);
   1662 
   1663  // mIsSecureContext is set once in our constructor; after that it can be read
   1664  // from various threads.
   1665  //
   1666  // It's a bit unfortunate that we have to have an out-of-band boolean for
   1667  // this, but we need access to this state from the parent thread, and we can't
   1668  // use our global object's secure state there.
   1669  const bool mIsSecureContext;
   1670 
   1671  bool mDebuggerRegistered MOZ_GUARDED_BY(mMutex);
   1672  mozilla::Atomic<bool> mIsInBackground;
   1673  bool mIsPlayingAudio{};
   1674  bool mHasActivePeerConnections{};
   1675 
   1676  // During registration, this worker may be marked as not being ready to
   1677  // execute debuggee runnables or content.
   1678  //
   1679  // Protected by mMutex.
   1680  bool mDebuggerReady;
   1681  nsTArray<RefPtr<WorkerRunnable>> mDelayedDebuggeeRunnables;
   1682 
   1683  // Whether this worker should have access to the WebExtension API bindings
   1684  // (currently only the Extension Background ServiceWorker declared in the
   1685  // extension manifest is allowed to access any WebExtension API bindings).
   1686  // This default to false, and it is eventually set to true by
   1687  // RemoteWorkerChild::ExecWorkerOnMainThread if the needed conditions
   1688  // are met.
   1689  bool mExtensionAPIAllowed;
   1690 
   1691  // mIsInAutomation is true when we're running in test automation.
   1692  // We expose some extra testing functions in that case.
   1693  bool mIsInAutomation;
   1694 
   1695  nsString mId;
   1696 
   1697  // This is used to check if it's allowed to share the memory across the agent
   1698  // cluster.
   1699  const nsILoadInfo::CrossOriginOpenerPolicy mAgentClusterOpenerPolicy;
   1700 
   1701  // Member variable of this class rather than the worker global scope because
   1702  // it's received on the main thread, but the global scope is thread-bound
   1703  // to the worker thread, so storing the value in the global scope would
   1704  // involve sacrificing the thread-bound-ness or using a WorkerRunnable, and
   1705  // there isn't a strong reason to store it on the global scope other than
   1706  // better consistency with the COEP spec.
   1707  Maybe<nsILoadInfo::CrossOriginEmbedderPolicy> mEmbedderPolicy;
   1708  Maybe<nsILoadInfo::CrossOriginEmbedderPolicy> mOwnerEmbedderPolicy;
   1709 
   1710  /* Privileged add-on flag extracted from the AddonPolicy on the nsIPrincipal
   1711   * on the main thread when constructing a top-level worker. The flag is
   1712   * propagated to nested workers. The flag is only allowed to take effect in
   1713   * extension processes and is forbidden in content scripts in content
   1714   * processes. The flag may be read on either the parent/owner thread as well
   1715   * as on the worker thread itself. When bug 1443925 is fixed allowing
   1716   * nsIPrincipal to be used OMT, it may be possible to remove this flag. */
   1717  bool mIsPrivilegedAddonGlobal;
   1718 
   1719  Atomic<uint32_t> mTopLevelWorkerFinishedRunnableCount;
   1720  Atomic<uint32_t> mWorkerFinishedRunnableCount;
   1721 
   1722  // A set of active JS async tasks that should prevent idle shutdown.
   1723  HashMap<JS::Dispatchable*, RefPtr<StrongWorkerRef>> mPendingJSAsyncTasks;
   1724 
   1725  TargetShutdownTaskSet mShutdownTasks MOZ_GUARDED_BY(mMutex);
   1726  bool mShutdownTasksRun MOZ_GUARDED_BY(mMutex) = false;
   1727 
   1728  bool mCCFlagSaysEligible MOZ_GUARDED_BY(mMutex){true};
   1729 
   1730  // The flag indicates if the worke is idle for events in the main event loop.
   1731  bool mWorkerLoopIsIdle MOZ_GUARDED_BY(mMutex){false};
   1732 
   1733  // This flag is used to ensure we only call NotifyStorageKeyUsed once per
   1734  // global.
   1735  bool hasNotifiedStorageKeyUsed{false};
   1736 
   1737  RefPtr<WorkerParentRef> mParentRef;
   1738 
   1739  FontVisibility mFontVisibility;
   1740 };
   1741 
   1742 class AutoSyncLoopHolder {
   1743  RefPtr<StrongWorkerRef> mWorkerRef;
   1744  nsCOMPtr<nsISerialEventTarget> mTarget;
   1745  uint32_t mIndex;
   1746 
   1747 public:
   1748  // See CreateNewSyncLoop() for more information about the correct value to use
   1749  // for aFailStatus.
   1750  AutoSyncLoopHolder(WorkerPrivate* aWorkerPrivate, WorkerStatus aFailStatus,
   1751                     const char* const aName = "AutoSyncLoopHolder");
   1752 
   1753  ~AutoSyncLoopHolder();
   1754 
   1755  nsresult Run();
   1756 
   1757  nsISerialEventTarget* GetSerialEventTarget() const;
   1758 };
   1759 
   1760 /**
   1761 * WorkerParentRef is a RefPtr<WorkerPrivate> wrapper for cross-thread access.
   1762 * WorkerPrivate needs to be accessed in multiple threads; for example,
   1763 * in WorkerParentThreadRunnable, the associated WorkerPrivate must be accessed
   1764 * in the worker thread when creating/dispatching and in the parent thread when
   1765 * executing. Unfortunately, RefPtr can not be used on this WorkerPrivate since
   1766 * it is not a thread-safe ref-counted object.
   1767 *
   1768 * Instead of using a raw pointer and a complicated mechanism to ensure the
   1769 * WorkerPrivate's accessibility. WorkerParentRef is used to resolve the
   1770 * problem. WorkerParentRef has a RefPtr<WorkerPrivate> mWorkerPrivate
   1771 * initialized on the parent thread when WorkerPrivate::Constructor().
   1772 * WorkerParentRef is a thread-safe ref-counted object that can be copied at
   1773 * any thread by WorkerPrivate::GetWorkerParentRef() and propagated to other
   1774 * threads. In the target thread, call WorkerParentRef::Private() to get the
   1775 * reference for WorkerPrivate or get a nullptr if the Worker has shut down.
   1776 *
   1777 * Since currently usage cases, WorkerParentRef::Private() will assert to be on
   1778 * the parent thread.
   1779 */
   1780 class WorkerParentRef final {
   1781 public:
   1782  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WorkerParentRef);
   1783 
   1784  explicit WorkerParentRef(RefPtr<WorkerPrivate>& aWorkerPrivate);
   1785 
   1786  const RefPtr<WorkerPrivate>& Private() const;
   1787 
   1788  void DropWorkerPrivate();
   1789 
   1790 private:
   1791  ~WorkerParentRef();
   1792 
   1793  RefPtr<WorkerPrivate> mWorkerPrivate;
   1794 };
   1795 
   1796 }  // namespace dom
   1797 }  // namespace mozilla
   1798 
   1799 #endif /* mozilla_dom_workers_workerprivate_h__ */