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 #include "RemoteWorkerControllerParent.h"
8 
9 #include <utility>
10 
11 #include "nsCOMPtr.h"
12 #include "nsDebug.h"
13 #include "nsError.h"
14 #include "nsThreadUtils.h"
15 
16 #include "mozilla/Assertions.h"
17 #include "mozilla/Unused.h"
18 #include "mozilla/dom/FetchEventOpParent.h"
19 #include "mozilla/dom/RemoteWorkerParent.h"
20 #include "mozilla/dom/ServiceWorkerOpPromise.h"
21 #include "mozilla/ipc/BackgroundParent.h"
22 
23 namespace mozilla {
24 
25 using namespace ipc;
26 
27 namespace dom {
28 
RemoteWorkerControllerParent(const RemoteWorkerData & aRemoteWorkerData)29 RemoteWorkerControllerParent::RemoteWorkerControllerParent(
30     const RemoteWorkerData& aRemoteWorkerData)
31     : mRemoteWorkerController(RemoteWorkerController::Create(
32           aRemoteWorkerData, this, 0 /* random process ID */)) {
33   AssertIsInMainProcess();
34   AssertIsOnBackgroundThread();
35   MOZ_ASSERT(mRemoteWorkerController);
36 }
37 
GetRemoteWorkerParent() const38 RefPtr<RemoteWorkerParent> RemoteWorkerControllerParent::GetRemoteWorkerParent()
39     const {
40   AssertIsOnBackgroundThread();
41   MOZ_ASSERT(mRemoteWorkerController);
42 
43   return mRemoteWorkerController->mActor;
44 }
45 
MaybeSendSetServiceWorkerSkipWaitingFlag(std::function<void (bool)> && aCallback)46 void RemoteWorkerControllerParent::MaybeSendSetServiceWorkerSkipWaitingFlag(
47     std::function<void(bool)>&& aCallback) {
48   AssertIsOnBackgroundThread();
49   MOZ_ASSERT(aCallback);
50 
51   if (!mIPCActive) {
52     aCallback(false);
53     return;
54   }
55 
56   SendSetServiceWorkerSkipWaitingFlag()->Then(
57       GetCurrentSerialEventTarget(), __func__,
58       [callback = std::move(aCallback)](
59           const SetServiceWorkerSkipWaitingFlagPromise::ResolveOrRejectValue&
60               aResult) {
61         callback(aResult.IsResolve() ? aResult.ResolveValue() : false);
62       });
63 }
64 
~RemoteWorkerControllerParent()65 RemoteWorkerControllerParent::~RemoteWorkerControllerParent() {
66   AssertIsOnBackgroundThread();
67   MOZ_ASSERT(!mIPCActive);
68   MOZ_ASSERT(!mRemoteWorkerController);
69 }
70 
AllocPFetchEventOpParent(const ServiceWorkerFetchEventOpArgs & aArgs)71 PFetchEventOpParent* RemoteWorkerControllerParent::AllocPFetchEventOpParent(
72     const ServiceWorkerFetchEventOpArgs& aArgs) {
73   AssertIsOnBackgroundThread();
74 
75   RefPtr<FetchEventOpParent> actor = new FetchEventOpParent();
76   return actor.forget().take();
77 }
78 
RecvPFetchEventOpConstructor(PFetchEventOpParent * aActor,const ServiceWorkerFetchEventOpArgs & aArgs)79 IPCResult RemoteWorkerControllerParent::RecvPFetchEventOpConstructor(
80     PFetchEventOpParent* aActor, const ServiceWorkerFetchEventOpArgs& aArgs) {
81   AssertIsOnBackgroundThread();
82   MOZ_ASSERT(aActor);
83 
84   RefPtr<FetchEventOpParent> realFetchOp =
85       static_cast<FetchEventOpParent*>(aActor);
86   mRemoteWorkerController->ExecServiceWorkerFetchEventOp(aArgs, realFetchOp)
87       ->Then(
88           GetCurrentSerialEventTarget(), __func__,
89           [fetchOp = std::move(realFetchOp)](
90               ServiceWorkerFetchEventOpPromise::ResolveOrRejectValue&&
91                   aResult) {
92             if (NS_WARN_IF(aResult.IsReject())) {
93               MOZ_ASSERT(NS_FAILED(aResult.RejectValue()));
94               Unused << fetchOp->Send__delete__(fetchOp, aResult.RejectValue());
95               return;
96             }
97 
98             Unused << fetchOp->Send__delete__(fetchOp, aResult.ResolveValue());
99           });
100 
101   return IPC_OK();
102 }
103 
DeallocPFetchEventOpParent(PFetchEventOpParent * aActor)104 bool RemoteWorkerControllerParent::DeallocPFetchEventOpParent(
105     PFetchEventOpParent* aActor) {
106   AssertIsOnBackgroundThread();
107   MOZ_ASSERT(aActor);
108 
109   RefPtr<FetchEventOpParent> actor =
110       dont_AddRef(static_cast<FetchEventOpParent*>(aActor));
111   return true;
112 }
113 
RecvExecServiceWorkerOp(ServiceWorkerOpArgs && aArgs,ExecServiceWorkerOpResolver && aResolve)114 IPCResult RemoteWorkerControllerParent::RecvExecServiceWorkerOp(
115     ServiceWorkerOpArgs&& aArgs, ExecServiceWorkerOpResolver&& aResolve) {
116   AssertIsOnBackgroundThread();
117   MOZ_ASSERT(mIPCActive);
118   MOZ_ASSERT(mRemoteWorkerController);
119 
120   mRemoteWorkerController->ExecServiceWorkerOp(std::move(aArgs))
121       ->Then(GetCurrentSerialEventTarget(), __func__,
122              [resolve = std::move(aResolve)](
123                  ServiceWorkerOpPromise::ResolveOrRejectValue&& aResult) {
124                if (NS_WARN_IF(aResult.IsReject())) {
125                  MOZ_ASSERT(NS_FAILED(aResult.RejectValue()));
126                  resolve(aResult.RejectValue());
127                  return;
128                }
129 
130                resolve(aResult.ResolveValue());
131              });
132 
133   return IPC_OK();
134 }
135 
RecvShutdown(ShutdownResolver && aResolve)136 IPCResult RemoteWorkerControllerParent::RecvShutdown(
137     ShutdownResolver&& aResolve) {
138   AssertIsOnBackgroundThread();
139   MOZ_ASSERT(mIPCActive);
140   MOZ_ASSERT(mRemoteWorkerController);
141 
142   mIPCActive = false;
143 
144   mRemoteWorkerController->Shutdown();
145   mRemoteWorkerController = nullptr;
146 
147   aResolve(true);
148 
149   return IPC_OK();
150 }
151 
Recv__delete__()152 IPCResult RemoteWorkerControllerParent::Recv__delete__() {
153   AssertIsOnBackgroundThread();
154   MOZ_ASSERT(!mIPCActive);
155   MOZ_ASSERT(!mRemoteWorkerController);
156 
157   return IPC_OK();
158 }
159 
ActorDestroy(ActorDestroyReason aReason)160 void RemoteWorkerControllerParent::ActorDestroy(ActorDestroyReason aReason) {
161   AssertIsOnBackgroundThread();
162 
163   if (NS_WARN_IF(mIPCActive)) {
164     mIPCActive = false;
165   }
166 
167   if (NS_WARN_IF(mRemoteWorkerController)) {
168     mRemoteWorkerController->Shutdown();
169     mRemoteWorkerController = nullptr;
170   }
171 }
172 
CreationFailed()173 void RemoteWorkerControllerParent::CreationFailed() {
174   AssertIsOnBackgroundThread();
175 
176   if (!mIPCActive) {
177     return;
178   }
179 
180   Unused << SendCreationFailed();
181 }
182 
CreationSucceeded()183 void RemoteWorkerControllerParent::CreationSucceeded() {
184   AssertIsOnBackgroundThread();
185 
186   if (!mIPCActive) {
187     return;
188   }
189 
190   Unused << SendCreationSucceeded();
191 }
192 
ErrorReceived(const ErrorValue & aValue)193 void RemoteWorkerControllerParent::ErrorReceived(const ErrorValue& aValue) {
194   AssertIsOnBackgroundThread();
195 
196   if (!mIPCActive) {
197     return;
198   }
199 
200   Unused << SendErrorReceived(aValue);
201 }
202 
Terminated()203 void RemoteWorkerControllerParent::Terminated() {
204   AssertIsOnBackgroundThread();
205 
206   if (!mIPCActive) {
207     return;
208   }
209 
210   Unused << SendTerminated();
211 }
212 
213 }  // namespace dom
214 }  // namespace mozilla
215