Line data Source code
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 "ServiceWorkerManagerParent.h"
8 : #include "ServiceWorkerManagerService.h"
9 : #include "ServiceWorkerUpdaterParent.h"
10 : #include "mozilla/dom/ContentParent.h"
11 : #include "mozilla/dom/ServiceWorkerRegistrar.h"
12 : #include "mozilla/ipc/BackgroundParent.h"
13 : #include "mozilla/ipc/BackgroundUtils.h"
14 : #include "mozilla/Unused.h"
15 : #include "nsThreadUtils.h"
16 :
17 : namespace mozilla {
18 :
19 : using namespace ipc;
20 :
21 : namespace dom {
22 : namespace workers {
23 :
24 : namespace {
25 :
26 : uint64_t sServiceWorkerManagerParentID = 0;
27 :
28 0 : class RegisterServiceWorkerCallback final : public Runnable
29 : {
30 : public:
31 0 : RegisterServiceWorkerCallback(const ServiceWorkerRegistrationData& aData,
32 : uint64_t aParentID)
33 0 : : Runnable("dom::workers::RegisterServiceWorkerCallback")
34 : , mData(aData)
35 0 : , mParentID(aParentID)
36 : {
37 0 : AssertIsInMainProcess();
38 0 : AssertIsOnBackgroundThread();
39 0 : }
40 :
41 : NS_IMETHOD
42 0 : Run() override
43 : {
44 0 : AssertIsInMainProcess();
45 0 : AssertIsOnBackgroundThread();
46 :
47 : RefPtr<dom::ServiceWorkerRegistrar> service =
48 0 : dom::ServiceWorkerRegistrar::Get();
49 :
50 : // Shutdown during the process of trying to update the registrar. Give
51 : // up on this modification.
52 0 : if (!service) {
53 0 : return NS_OK;
54 : }
55 :
56 0 : service->RegisterServiceWorker(mData);
57 :
58 : RefPtr<ServiceWorkerManagerService> managerService =
59 0 : ServiceWorkerManagerService::Get();
60 0 : if (managerService) {
61 0 : managerService->PropagateRegistration(mParentID, mData);
62 : }
63 :
64 0 : return NS_OK;
65 : }
66 :
67 : private:
68 : ServiceWorkerRegistrationData mData;
69 : const uint64_t mParentID;
70 : };
71 :
72 0 : class UnregisterServiceWorkerCallback final : public Runnable
73 : {
74 : public:
75 0 : UnregisterServiceWorkerCallback(const PrincipalInfo& aPrincipalInfo,
76 : const nsString& aScope,
77 : uint64_t aParentID)
78 0 : : Runnable("dom::workers::UnregisterServiceWorkerCallback")
79 : , mPrincipalInfo(aPrincipalInfo)
80 : , mScope(aScope)
81 0 : , mParentID(aParentID)
82 : {
83 0 : AssertIsInMainProcess();
84 0 : AssertIsOnBackgroundThread();
85 0 : }
86 :
87 : NS_IMETHOD
88 0 : Run() override
89 : {
90 0 : AssertIsInMainProcess();
91 0 : AssertIsOnBackgroundThread();
92 :
93 : RefPtr<dom::ServiceWorkerRegistrar> service =
94 0 : dom::ServiceWorkerRegistrar::Get();
95 :
96 : // Shutdown during the process of trying to update the registrar. Give
97 : // up on this modification.
98 0 : if (!service) {
99 0 : return NS_OK;
100 : }
101 :
102 0 : service->UnregisterServiceWorker(mPrincipalInfo,
103 0 : NS_ConvertUTF16toUTF8(mScope));
104 :
105 : RefPtr<ServiceWorkerManagerService> managerService =
106 0 : ServiceWorkerManagerService::Get();
107 0 : if (managerService) {
108 0 : managerService->PropagateUnregister(mParentID, mPrincipalInfo,
109 0 : mScope);
110 : }
111 :
112 0 : return NS_OK;
113 : }
114 :
115 : private:
116 : const PrincipalInfo mPrincipalInfo;
117 : nsString mScope;
118 : uint64_t mParentID;
119 : };
120 :
121 0 : class CheckPrincipalWithCallbackRunnable final : public Runnable
122 : {
123 : public:
124 0 : CheckPrincipalWithCallbackRunnable(already_AddRefed<ContentParent> aParent,
125 : const PrincipalInfo& aPrincipalInfo,
126 : Runnable* aCallback)
127 0 : : Runnable("dom::workers::CheckPrincipalWithCallbackRunnable")
128 : , mContentParent(aParent)
129 : , mPrincipalInfo(aPrincipalInfo)
130 : , mCallback(aCallback)
131 0 : , mBackgroundEventTarget(GetCurrentThreadEventTarget())
132 : {
133 0 : AssertIsInMainProcess();
134 0 : AssertIsOnBackgroundThread();
135 :
136 0 : MOZ_ASSERT(mContentParent);
137 0 : MOZ_ASSERT(mCallback);
138 0 : MOZ_ASSERT(mBackgroundEventTarget);
139 0 : }
140 :
141 0 : NS_IMETHOD Run() override
142 : {
143 0 : if (NS_IsMainThread()) {
144 0 : mContentParent = nullptr;
145 :
146 0 : mBackgroundEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
147 0 : return NS_OK;
148 : }
149 :
150 0 : AssertIsOnBackgroundThread();
151 0 : mCallback->Run();
152 0 : mCallback = nullptr;
153 :
154 0 : return NS_OK;
155 : }
156 :
157 : private:
158 : RefPtr<ContentParent> mContentParent;
159 : PrincipalInfo mPrincipalInfo;
160 : RefPtr<Runnable> mCallback;
161 : nsCOMPtr<nsIEventTarget> mBackgroundEventTarget;
162 : };
163 :
164 : } // namespace
165 :
166 2 : ServiceWorkerManagerParent::ServiceWorkerManagerParent()
167 4 : : mService(ServiceWorkerManagerService::GetOrCreate())
168 6 : , mID(++sServiceWorkerManagerParentID)
169 : {
170 2 : AssertIsOnBackgroundThread();
171 2 : mService->RegisterActor(this);
172 2 : }
173 :
174 0 : ServiceWorkerManagerParent::~ServiceWorkerManagerParent()
175 : {
176 0 : AssertIsOnBackgroundThread();
177 0 : }
178 :
179 : mozilla::ipc::IPCResult
180 0 : ServiceWorkerManagerParent::RecvRegister(
181 : const ServiceWorkerRegistrationData& aData)
182 : {
183 0 : AssertIsInMainProcess();
184 0 : AssertIsOnBackgroundThread();
185 :
186 : // Basic validation.
187 0 : if (aData.scope().IsEmpty() ||
188 0 : aData.principal().type() == PrincipalInfo::TNullPrincipalInfo ||
189 0 : aData.principal().type() == PrincipalInfo::TSystemPrincipalInfo) {
190 0 : return IPC_FAIL_NO_REASON(this);
191 : }
192 :
193 : RefPtr<RegisterServiceWorkerCallback> callback =
194 0 : new RegisterServiceWorkerCallback(aData, mID);
195 :
196 : RefPtr<ContentParent> parent =
197 0 : BackgroundParent::GetContentParent(Manager());
198 :
199 : // If the ContentParent is null we are dealing with a same-process actor.
200 0 : if (!parent) {
201 0 : callback->Run();
202 0 : return IPC_OK();
203 : }
204 :
205 : RefPtr<CheckPrincipalWithCallbackRunnable> runnable =
206 0 : new CheckPrincipalWithCallbackRunnable(parent.forget(), aData.principal(),
207 0 : callback);
208 0 : MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
209 :
210 0 : return IPC_OK();
211 : }
212 :
213 : mozilla::ipc::IPCResult
214 0 : ServiceWorkerManagerParent::RecvUnregister(const PrincipalInfo& aPrincipalInfo,
215 : const nsString& aScope)
216 : {
217 0 : AssertIsInMainProcess();
218 0 : AssertIsOnBackgroundThread();
219 :
220 : // Basic validation.
221 0 : if (aScope.IsEmpty() ||
222 0 : aPrincipalInfo.type() == PrincipalInfo::TNullPrincipalInfo ||
223 0 : aPrincipalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) {
224 0 : return IPC_FAIL_NO_REASON(this);
225 : }
226 :
227 : RefPtr<UnregisterServiceWorkerCallback> callback =
228 0 : new UnregisterServiceWorkerCallback(aPrincipalInfo, aScope, mID);
229 :
230 : RefPtr<ContentParent> parent =
231 0 : BackgroundParent::GetContentParent(Manager());
232 :
233 : // If the ContentParent is null we are dealing with a same-process actor.
234 0 : if (!parent) {
235 0 : callback->Run();
236 0 : return IPC_OK();
237 : }
238 :
239 : RefPtr<CheckPrincipalWithCallbackRunnable> runnable =
240 0 : new CheckPrincipalWithCallbackRunnable(parent.forget(), aPrincipalInfo,
241 0 : callback);
242 0 : MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
243 :
244 0 : return IPC_OK();
245 : }
246 :
247 : mozilla::ipc::IPCResult
248 0 : ServiceWorkerManagerParent::RecvPropagateSoftUpdate(const OriginAttributes& aOriginAttributes,
249 : const nsString& aScope)
250 : {
251 0 : AssertIsOnBackgroundThread();
252 :
253 0 : if (NS_WARN_IF(!mService)) {
254 0 : return IPC_FAIL_NO_REASON(this);
255 : }
256 :
257 0 : mService->PropagateSoftUpdate(mID, aOriginAttributes, aScope);
258 0 : return IPC_OK();
259 : }
260 :
261 : mozilla::ipc::IPCResult
262 0 : ServiceWorkerManagerParent::RecvPropagateUnregister(const PrincipalInfo& aPrincipalInfo,
263 : const nsString& aScope)
264 : {
265 0 : AssertIsOnBackgroundThread();
266 :
267 0 : if (NS_WARN_IF(!mService)) {
268 0 : return IPC_FAIL_NO_REASON(this);
269 : }
270 :
271 0 : mService->PropagateUnregister(mID, aPrincipalInfo, aScope);
272 0 : return IPC_OK();
273 : }
274 :
275 : mozilla::ipc::IPCResult
276 0 : ServiceWorkerManagerParent::RecvPropagateRemove(const nsCString& aHost)
277 : {
278 0 : AssertIsOnBackgroundThread();
279 :
280 0 : if (NS_WARN_IF(!mService)) {
281 0 : return IPC_FAIL_NO_REASON(this);
282 : }
283 :
284 0 : mService->PropagateRemove(mID, aHost);
285 0 : return IPC_OK();
286 : }
287 :
288 : mozilla::ipc::IPCResult
289 0 : ServiceWorkerManagerParent::RecvPropagateRemoveAll()
290 : {
291 0 : AssertIsOnBackgroundThread();
292 :
293 0 : if (NS_WARN_IF(!mService)) {
294 0 : return IPC_FAIL_NO_REASON(this);
295 : }
296 :
297 0 : mService->PropagateRemoveAll(mID);
298 0 : return IPC_OK();
299 : }
300 :
301 : mozilla::ipc::IPCResult
302 0 : ServiceWorkerManagerParent::RecvShutdown()
303 : {
304 0 : AssertIsOnBackgroundThread();
305 :
306 0 : if (NS_WARN_IF(!mService)) {
307 0 : return IPC_FAIL_NO_REASON(this);
308 : }
309 :
310 0 : mService->UnregisterActor(this);
311 0 : mService = nullptr;
312 :
313 0 : Unused << Send__delete__(this);
314 0 : return IPC_OK();
315 : }
316 :
317 : PServiceWorkerUpdaterParent*
318 0 : ServiceWorkerManagerParent::AllocPServiceWorkerUpdaterParent(const OriginAttributes& aOriginAttributes,
319 : const nsCString& aScope)
320 : {
321 0 : AssertIsOnBackgroundThread();
322 0 : return new ServiceWorkerUpdaterParent();
323 : }
324 :
325 : mozilla::ipc::IPCResult
326 0 : ServiceWorkerManagerParent::RecvPServiceWorkerUpdaterConstructor(PServiceWorkerUpdaterParent* aActor,
327 : const OriginAttributes& aOriginAttributes,
328 : const nsCString& aScope)
329 : {
330 0 : AssertIsOnBackgroundThread();
331 :
332 0 : if (NS_WARN_IF(!mService)) {
333 0 : return IPC_FAIL_NO_REASON(this);
334 : }
335 :
336 0 : mService->ProcessUpdaterActor(static_cast<ServiceWorkerUpdaterParent*>(aActor),
337 0 : aOriginAttributes, aScope, mID);
338 0 : return IPC_OK();
339 : }
340 :
341 : bool
342 0 : ServiceWorkerManagerParent::DeallocPServiceWorkerUpdaterParent(PServiceWorkerUpdaterParent* aActor)
343 : {
344 0 : AssertIsOnBackgroundThread();
345 0 : delete aActor;
346 0 : return true;
347 : }
348 :
349 : void
350 0 : ServiceWorkerManagerParent::ActorDestroy(ActorDestroyReason aWhy)
351 : {
352 0 : AssertIsOnBackgroundThread();
353 :
354 0 : if (mService) {
355 : // This object is about to be released and with it, also mService will be
356 : // released too.
357 0 : mService->UnregisterActor(this);
358 : }
359 0 : }
360 :
361 : } // namespace workers
362 : } // namespace dom
363 : } // namespace mozilla
|