tor-browser

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

RemoteWorkerChild.h (7463B)


      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_RemoteWorkerChild_h
      8 #define mozilla_dom_RemoteWorkerChild_h
      9 
     10 #include "mozilla/DataMutex.h"
     11 #include "mozilla/MozPromise.h"
     12 #include "mozilla/RefPtr.h"
     13 #include "mozilla/ThreadBound.h"
     14 #include "mozilla/dom/PRemoteWorkerChild.h"
     15 #include "mozilla/dom/PRemoteWorkerNonLifeCycleOpControllerChild.h"
     16 #include "mozilla/dom/RemoteWorkerOp.h"
     17 #include "mozilla/dom/ServiceWorkerOpArgs.h"
     18 #include "mozilla/dom/SharedWorkerOpArgs.h"
     19 #include "nsCOMPtr.h"
     20 #include "nsISupportsImpl.h"
     21 #include "nsTArray.h"
     22 
     23 class nsISerialEventTarget;
     24 class nsIConsoleReportCollector;
     25 
     26 namespace mozilla::dom {
     27 
     28 using remoteworker::RemoteWorkerState;
     29 
     30 class ErrorValue;
     31 class FetchEventOpProxyChild;
     32 class RemoteWorkerData;
     33 class RemoteWorkerServiceKeepAlive;
     34 class ServiceWorkerOp;
     35 class SharedWorkerOp;
     36 class UniqueMessagePortId;
     37 class WeakWorkerRef;
     38 class WorkerErrorReport;
     39 class WorkerPrivate;
     40 
     41 /**
     42 * Background-managed "Worker Launcher"-thread-resident created via the
     43 * RemoteWorkerManager to actually spawn the worker. Currently, the worker will
     44 * be spawned from the main thread due to nsIPrincipal not being able to be
     45 * created on background threads and other ownership invariants, most of which
     46 * can be relaxed in the future.
     47 */
     48 class RemoteWorkerChild final : public PRemoteWorkerChild {
     49  friend class FetchEventOpProxyChild;
     50  friend class PRemoteWorkerChild;
     51  friend class ServiceWorkerOp;
     52  friend class SharedWorkerOp;
     53 
     54  ~RemoteWorkerChild();
     55 
     56 public:
     57  // Note that all IPC-using methods must only be invoked on the
     58  // RemoteWorkerService thread which the inherited
     59  // IProtocol::GetActorEventTarget() will return for us.
     60  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteWorkerChild, final)
     61 
     62  explicit RemoteWorkerChild(const RemoteWorkerData& aData);
     63 
     64  void ExecWorker(
     65      const RemoteWorkerData& aData,
     66      mozilla::ipc::Endpoint<PRemoteWorkerNonLifeCycleOpControllerChild>&&
     67          aChildEp);
     68 
     69  void ErrorPropagationOnMainThread(const WorkerErrorReport* aReport,
     70                                    bool aIsErrorEvent);
     71 
     72  void CSPViolationPropagationOnMainThread(const nsAString& aJSON);
     73 
     74  void NotifyLock(bool aCreated);
     75 
     76  void NotifyWebTransport(bool aCreated);
     77 
     78  void FlushReportsOnMainThread(nsIConsoleReportCollector* aReporter);
     79 
     80  RefPtr<GenericNonExclusivePromise> GetTerminationPromise();
     81 
     82  RefPtr<GenericPromise> MaybeSendSetServiceWorkerSkipWaitingFlag();
     83 
     84  const nsTArray<uint64_t>& WindowIDs() const { return mWindowIDs; }
     85 
     86  void SetIsThawing(const bool aIsThawing) { mIsThawing = aIsThawing; }
     87  bool IsThawing() const { return mIsThawing; }
     88  void PendRemoteWorkerOp(RefPtr<RemoteWorkerOp> aOp);
     89  void RunAllPendingOpsOnMainThread();
     90 
     91 private:
     92  class InitializeWorkerRunnable;
     93 
     94  // The state of the WorkerPrivate as perceived by the owner on the main
     95  // thread.  All state transitions now happen on the main thread, but the
     96  // Worker Launcher thread will consult the state and will directly append ops
     97  // to the Pending queue
     98  DataMutex<RemoteWorkerState> mState;
     99 
    100  const RefPtr<RemoteWorkerServiceKeepAlive> mServiceKeepAlive;
    101 
    102  void ActorDestroy(ActorDestroyReason) override;
    103 
    104  mozilla::ipc::IPCResult RecvExecOp(SharedWorkerOpArgs&& aOpArgs);
    105 
    106  mozilla::ipc::IPCResult RecvExecServiceWorkerOp(
    107      ServiceWorkerOpArgs&& aArgs, ExecServiceWorkerOpResolver&& aResolve);
    108 
    109  already_AddRefed<PFetchEventOpProxyChild> AllocPFetchEventOpProxyChild(
    110      const ParentToChildServiceWorkerFetchEventOpArgs& aArgs);
    111 
    112  mozilla::ipc::IPCResult RecvPFetchEventOpProxyConstructor(
    113      PFetchEventOpProxyChild* aActor,
    114      const ParentToChildServiceWorkerFetchEventOpArgs& aArgs) override;
    115 
    116  nsresult ExecWorkerOnMainThread(
    117      RemoteWorkerData&& aData,
    118      mozilla::ipc::Endpoint<PRemoteWorkerNonLifeCycleOpControllerChild>&&
    119          aChildEp);
    120 
    121  void ExceptionalErrorTransitionDuringExecWorker();
    122 
    123  void RequestWorkerCancellation();
    124 
    125  void InitializeOnWorker();
    126 
    127  void CreationSucceededOnAnyThread();
    128 
    129  void CreationFailedOnAnyThread();
    130 
    131  void CreationSucceededOrFailedOnAnyThread(bool aDidCreationSucceed);
    132 
    133  // Cancels the worker if it has been started and ensures that we transition
    134  // to the Terminated state once the worker has been terminated or we have
    135  // ensured that it will never start.
    136  void CloseWorkerOnMainThread();
    137 
    138  void ErrorPropagation(const ErrorValue& aValue);
    139 
    140  void ErrorPropagationDispatch(nsresult aError);
    141 
    142  // When the WorkerPrivate Cancellation lambda is invoked, it's possible that
    143  // we have not yet advanced to running from pending, so we could be in either
    144  // state.  This method is expected to be called by the Workers' cancellation
    145  // lambda and will obtain the lock and call the
    146  // TransitionStateFromPendingToCanceled if appropriate.  Otherwise it will
    147  // directly move from the running state to the canceled state which does not
    148  // require additional cleanup.
    149  void OnWorkerCancellationTransitionStateFromPendingOrRunningToCanceled();
    150  // A helper used by the above method by the worker cancellation lambda if the
    151  // the worker hasn't started running, or in exceptional cases where we bail
    152  // out of the ExecWorker method early.  The caller must be holding the lock
    153  // (in order to pass in the state).
    154  void TransitionStateFromPendingToCanceled(RemoteWorkerState& aState);
    155  void TransitionStateFromCanceledToKilled();
    156 
    157  void TransitionStateToRunning();
    158 
    159  void TransitionStateToTerminated();
    160 
    161  void TransitionStateToTerminated(RemoteWorkerState& aState);
    162 
    163  void CancelAllPendingOps(RemoteWorkerState& aState);
    164 
    165  void MaybeStartOp(RefPtr<RemoteWorkerOp>&& aOp);
    166 
    167  const bool mIsServiceWorker;
    168 
    169  // Touched on main-thread only.
    170  nsTArray<uint64_t> mWindowIDs;
    171 
    172  struct LauncherBoundData {
    173    MozPromiseHolder<GenericNonExclusivePromise> mTerminationPromise;
    174    // Flag to ensure we report creation at most once.  This could be cleaned up
    175    // further.
    176    bool mDidSendCreated = false;
    177  };
    178 
    179  ThreadBound<LauncherBoundData> mLauncherData;
    180 
    181  // Thaw operation holds mState.lock. It means other operations will be blocked
    182  // until mState.lock is released. However, Thaw operation is blocked by
    183  // RemoteWorkerDebugger registration that needs WorkerLauncher thread to send
    184  // IPC to continue the registration on the parent process. If a RemoteWorkerOp
    185  // is received on WorkerLauncher thread when the RemoteWorker is thawing, a
    186  // deadlock could be happen between WorkerLauncher thread and RemoteWorker's
    187  // parent thread. So mIsThawing and mPendingOps are introduced to avoid the
    188  // deadlock by pending the operations when RemoteWorker is thawing.
    189  //
    190  // Note that these could be removed once RemoteWorkerChild off-main-thread
    191  // done since the RemoteWorker's parent thread will be WorkerLauncher thread.
    192  // And it means when executing WorkerPrivate::Thaw on WorkerLauncher thread,
    193  // it is impossible to handle the IPC callback on WorkerLauncher thread at the
    194  // same time.
    195  Atomic<bool> mIsThawing{false};
    196  DataMutex<nsTArray<RefPtr<RemoteWorkerOp>>> mPendingOps;
    197 };
    198 
    199 }  // namespace mozilla::dom
    200 
    201 #endif  // mozilla_dom_RemoteWorkerChild_h