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 "nsCOMPtr.h"
11 #include "nsISupportsImpl.h"
12 #include "nsTArray.h"
13 
14 #include "mozilla/DataMutex.h"
15 #include "mozilla/MozPromise.h"
16 #include "mozilla/RefPtr.h"
17 #include "mozilla/ThreadBound.h"
18 #include "mozilla/ThreadSafeWeakPtr.h"
19 #include "mozilla/dom/PRemoteWorkerChild.h"
20 #include "mozilla/dom/ServiceWorkerOpArgs.h"
21 
22 class nsISerialEventTarget;
23 class nsIConsoleReportCollector;
24 
25 namespace mozilla {
26 namespace dom {
27 
28 class ErrorValue;
29 class FetchEventOpProxyChild;
30 class RemoteWorkerData;
31 class ServiceWorkerOp;
32 class UniqueMessagePortId;
33 class WeakWorkerRef;
34 class WorkerErrorReport;
35 class WorkerPrivate;
36 
37 class RemoteWorkerChild final
38     : public SupportsThreadSafeWeakPtr<RemoteWorkerChild>,
39       public PRemoteWorkerChild {
40   friend class FetchEventOpProxyChild;
41   friend class PRemoteWorkerChild;
42   friend class ServiceWorkerOp;
43 
44  public:
45   MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(RemoteWorkerChild)
46 
47   MOZ_DECLARE_REFCOUNTED_TYPENAME(RemoteWorkerChild)
48 
49   explicit RemoteWorkerChild(const RemoteWorkerData& aData);
50 
51   ~RemoteWorkerChild();
52 
53   nsISerialEventTarget* GetOwningEventTarget() const;
54 
55   void ExecWorker(const RemoteWorkerData& aData);
56 
57   void ErrorPropagationOnMainThread(const WorkerErrorReport* aReport,
58                                     bool aIsErrorEvent);
59 
60   void FlushReportsOnMainThread(nsIConsoleReportCollector* aReporter);
61 
62   void AddPortIdentifier(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
63                          UniqueMessagePortId& aPortIdentifier);
64 
65   RefPtr<GenericNonExclusivePromise> GetTerminationPromise();
66 
67   RefPtr<GenericPromise> MaybeSendSetServiceWorkerSkipWaitingFlag();
68 
69  private:
70   class InitializeWorkerRunnable;
71 
72   class Op;
73   class SharedWorkerOp;
74 
75   struct WorkerPrivateAccessibleState {
76     ~WorkerPrivateAccessibleState();
77     RefPtr<WorkerPrivate> mWorkerPrivate;
78   };
79 
80   struct Pending : WorkerPrivateAccessibleState {
81     nsTArray<RefPtr<Op>> mPendingOps;
82   };
83 
84   struct PendingTerminated {};
85 
86   struct Running : WorkerPrivateAccessibleState {
87     ~Running();
88     RefPtr<WeakWorkerRef> mWorkerRef;
89   };
90 
91   struct Terminated {};
92 
93   using State = Variant<Pending, Running, PendingTerminated, Terminated>;
94 
95   DataMutex<State> mState;
96 
97   class Op {
98    public:
99     NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
100 
101     virtual ~Op() = default;
102 
103     virtual bool MaybeStart(RemoteWorkerChild* aOwner, State& aState) = 0;
104 
105     virtual void Cancel() = 0;
106   };
107 
108   void ActorDestroy(ActorDestroyReason) override;
109 
110   mozilla::ipc::IPCResult RecvExecOp(RemoteWorkerOp&& aOp);
111 
112   mozilla::ipc::IPCResult RecvExecServiceWorkerOp(
113       ServiceWorkerOpArgs&& aArgs, ExecServiceWorkerOpResolver&& aResolve);
114 
115   PFetchEventOpProxyChild* AllocPFetchEventOpProxyChild(
116       const ServiceWorkerFetchEventOpArgs& aArgs);
117 
118   mozilla::ipc::IPCResult RecvPFetchEventOpProxyConstructor(
119       PFetchEventOpProxyChild* aActor,
120       const ServiceWorkerFetchEventOpArgs& aArgs) override;
121 
122   bool DeallocPFetchEventOpProxyChild(PFetchEventOpProxyChild* aActor);
123 
124   nsresult ExecWorkerOnMainThread(RemoteWorkerData&& aData);
125 
126   void InitializeOnWorker();
127 
128   void ShutdownOnWorker();
129 
130   void CreationSucceededOnAnyThread();
131 
132   void CreationFailedOnAnyThread();
133 
134   void CreationSucceededOrFailedOnAnyThread(bool aDidCreationSucceed);
135 
136   void CloseWorkerOnMainThread(State& aState);
137 
138   void ErrorPropagation(const ErrorValue& aValue);
139 
140   void ErrorPropagationDispatch(nsresult aError);
141 
142   void TransitionStateToPendingTerminated(State& aState);
143 
144   void TransitionStateToRunning(already_AddRefed<WorkerPrivate> aWorkerPrivate,
145                                 already_AddRefed<WeakWorkerRef> aWorkerRef);
146 
147   void TransitionStateToTerminated();
148 
149   void TransitionStateToTerminated(State& aState);
150 
151   void CancelAllPendingOps(State& aState);
152 
153   void MaybeStartOp(RefPtr<Op>&& aOp);
154 
155   const bool mIsServiceWorker;
156   const nsCOMPtr<nsISerialEventTarget> mOwningEventTarget;
157 
158   // Touched on main-thread only.
159   nsTArray<uint64_t> mWindowIDs;
160 
161   struct LauncherBoundData {
162     bool mIPCActive = true;
163     MozPromiseHolder<GenericNonExclusivePromise> mTerminationPromise;
164   };
165 
166   ThreadBound<LauncherBoundData> mLauncherData;
167 };
168 
169 }  // namespace dom
170 }  // namespace mozilla
171 
172 #endif  // mozilla_dom_RemoteWorkerChild_h
173