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 "ServiceWorkerManagerService.h"
8 : #include "ServiceWorkerManagerParent.h"
9 : #include "ServiceWorkerRegistrar.h"
10 : #include "ServiceWorkerUpdaterParent.h"
11 : #include "mozilla/dom/ContentParent.h"
12 : #include "mozilla/ipc/BackgroundParent.h"
13 : #include "mozilla/Unused.h"
14 : #include "nsAutoPtr.h"
15 :
16 : namespace mozilla {
17 :
18 : using namespace ipc;
19 :
20 : namespace dom {
21 : namespace workers {
22 :
23 : namespace {
24 :
25 : ServiceWorkerManagerService* sInstance = nullptr;
26 :
27 : } // namespace
28 :
29 1 : ServiceWorkerManagerService::ServiceWorkerManagerService()
30 : {
31 1 : AssertIsOnBackgroundThread();
32 :
33 : // sInstance is a raw ServiceWorkerManagerService*.
34 1 : MOZ_ASSERT(!sInstance);
35 1 : sInstance = this;
36 1 : }
37 :
38 0 : ServiceWorkerManagerService::~ServiceWorkerManagerService()
39 : {
40 0 : AssertIsOnBackgroundThread();
41 0 : MOZ_ASSERT(sInstance == this);
42 0 : MOZ_ASSERT(mAgents.Count() == 0);
43 :
44 0 : sInstance = nullptr;
45 0 : }
46 :
47 : /* static */ already_AddRefed<ServiceWorkerManagerService>
48 0 : ServiceWorkerManagerService::Get()
49 : {
50 0 : AssertIsOnBackgroundThread();
51 :
52 0 : RefPtr<ServiceWorkerManagerService> instance = sInstance;
53 0 : return instance.forget();
54 : }
55 :
56 : /* static */ already_AddRefed<ServiceWorkerManagerService>
57 2 : ServiceWorkerManagerService::GetOrCreate()
58 : {
59 2 : AssertIsOnBackgroundThread();
60 :
61 4 : RefPtr<ServiceWorkerManagerService> instance = sInstance;
62 2 : if (!instance) {
63 1 : instance = new ServiceWorkerManagerService();
64 : }
65 4 : return instance.forget();
66 : }
67 :
68 : void
69 2 : ServiceWorkerManagerService::RegisterActor(ServiceWorkerManagerParent* aParent)
70 : {
71 2 : AssertIsOnBackgroundThread();
72 2 : MOZ_ASSERT(aParent);
73 2 : MOZ_ASSERT(!mAgents.Contains(aParent));
74 :
75 2 : mAgents.PutEntry(aParent);
76 2 : }
77 :
78 : void
79 0 : ServiceWorkerManagerService::UnregisterActor(ServiceWorkerManagerParent* aParent)
80 : {
81 0 : AssertIsOnBackgroundThread();
82 0 : MOZ_ASSERT(aParent);
83 0 : MOZ_ASSERT(mAgents.Contains(aParent));
84 :
85 0 : mAgents.RemoveEntry(aParent);
86 0 : }
87 :
88 : void
89 0 : ServiceWorkerManagerService::PropagateRegistration(
90 : uint64_t aParentID,
91 : ServiceWorkerRegistrationData& aData)
92 : {
93 0 : AssertIsOnBackgroundThread();
94 :
95 0 : DebugOnly<bool> parentFound = false;
96 0 : for (auto iter = mAgents.Iter(); !iter.Done(); iter.Next()) {
97 0 : RefPtr<ServiceWorkerManagerParent> parent = iter.Get()->GetKey();
98 0 : MOZ_ASSERT(parent);
99 :
100 0 : if (parent->ID() != aParentID) {
101 0 : Unused << parent->SendNotifyRegister(aData);
102 : #ifdef DEBUG
103 : } else {
104 0 : parentFound = true;
105 : #endif
106 : }
107 : }
108 :
109 : // Send permissions fot the newly registered service worker to all of the
110 : // content processes.
111 0 : PrincipalInfo pi = aData.principal();
112 0 : NS_DispatchToMainThread(NS_NewRunnableFunction(
113 0 : "dom::workers::ServiceWorkerManagerService::PropagateRegistration", [pi]() {
114 0 : nsTArray<ContentParent*> cps;
115 0 : ContentParent::GetAll(cps);
116 0 : for (auto* cp : cps) {
117 0 : nsCOMPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(pi);
118 0 : if (principal) {
119 0 : cp->TransmitPermissionsForPrincipal(principal);
120 : }
121 : }
122 0 : }));
123 :
124 : #ifdef DEBUG
125 0 : MOZ_ASSERT(parentFound);
126 : #endif
127 0 : }
128 :
129 : void
130 0 : ServiceWorkerManagerService::PropagateSoftUpdate(
131 : uint64_t aParentID,
132 : const OriginAttributes& aOriginAttributes,
133 : const nsAString& aScope)
134 : {
135 0 : AssertIsOnBackgroundThread();
136 :
137 0 : DebugOnly<bool> parentFound = false;
138 0 : for (auto iter = mAgents.Iter(); !iter.Done(); iter.Next()) {
139 0 : RefPtr<ServiceWorkerManagerParent> parent = iter.Get()->GetKey();
140 0 : MOZ_ASSERT(parent);
141 :
142 0 : nsString scope(aScope);
143 0 : Unused << parent->SendNotifySoftUpdate(aOriginAttributes,
144 : scope);
145 :
146 : #ifdef DEBUG
147 0 : if (parent->ID() == aParentID) {
148 0 : parentFound = true;
149 : }
150 : #endif
151 : }
152 :
153 : #ifdef DEBUG
154 0 : MOZ_ASSERT(parentFound);
155 : #endif
156 0 : }
157 :
158 : void
159 0 : ServiceWorkerManagerService::PropagateUnregister(
160 : uint64_t aParentID,
161 : const PrincipalInfo& aPrincipalInfo,
162 : const nsAString& aScope)
163 : {
164 0 : AssertIsOnBackgroundThread();
165 :
166 : RefPtr<dom::ServiceWorkerRegistrar> service =
167 0 : dom::ServiceWorkerRegistrar::Get();
168 0 : MOZ_ASSERT(service);
169 :
170 : // It's possible that we don't have any ServiceWorkerManager managing this
171 : // scope but we still need to unregister it from the ServiceWorkerRegistrar.
172 0 : service->UnregisterServiceWorker(aPrincipalInfo,
173 0 : NS_ConvertUTF16toUTF8(aScope));
174 :
175 0 : DebugOnly<bool> parentFound = false;
176 0 : for (auto iter = mAgents.Iter(); !iter.Done(); iter.Next()) {
177 0 : RefPtr<ServiceWorkerManagerParent> parent = iter.Get()->GetKey();
178 0 : MOZ_ASSERT(parent);
179 :
180 0 : if (parent->ID() != aParentID) {
181 0 : nsString scope(aScope);
182 0 : Unused << parent->SendNotifyUnregister(aPrincipalInfo, scope);
183 : #ifdef DEBUG
184 : } else {
185 0 : parentFound = true;
186 : #endif
187 : }
188 : }
189 :
190 : #ifdef DEBUG
191 0 : MOZ_ASSERT(parentFound);
192 : #endif
193 0 : }
194 :
195 : void
196 0 : ServiceWorkerManagerService::PropagateRemove(uint64_t aParentID,
197 : const nsACString& aHost)
198 : {
199 0 : AssertIsOnBackgroundThread();
200 :
201 0 : DebugOnly<bool> parentFound = false;
202 0 : for (auto iter = mAgents.Iter(); !iter.Done(); iter.Next()) {
203 0 : RefPtr<ServiceWorkerManagerParent> parent = iter.Get()->GetKey();
204 0 : MOZ_ASSERT(parent);
205 :
206 0 : if (parent->ID() != aParentID) {
207 0 : nsCString host(aHost);
208 0 : Unused << parent->SendNotifyRemove(host);
209 : #ifdef DEBUG
210 : } else {
211 0 : parentFound = true;
212 : #endif
213 : }
214 : }
215 :
216 : #ifdef DEBUG
217 0 : MOZ_ASSERT(parentFound);
218 : #endif
219 0 : }
220 :
221 : void
222 0 : ServiceWorkerManagerService::PropagateRemoveAll(uint64_t aParentID)
223 : {
224 0 : AssertIsOnBackgroundThread();
225 :
226 : RefPtr<dom::ServiceWorkerRegistrar> service =
227 0 : dom::ServiceWorkerRegistrar::Get();
228 0 : MOZ_ASSERT(service);
229 :
230 0 : service->RemoveAll();
231 :
232 0 : DebugOnly<bool> parentFound = false;
233 0 : for (auto iter = mAgents.Iter(); !iter.Done(); iter.Next()) {
234 0 : RefPtr<ServiceWorkerManagerParent> parent = iter.Get()->GetKey();
235 0 : MOZ_ASSERT(parent);
236 :
237 0 : if (parent->ID() != aParentID) {
238 0 : Unused << parent->SendNotifyRemoveAll();
239 : #ifdef DEBUG
240 : } else {
241 0 : parentFound = true;
242 : #endif
243 : }
244 : }
245 :
246 : #ifdef DEBUG
247 0 : MOZ_ASSERT(parentFound);
248 : #endif
249 0 : }
250 :
251 : void
252 0 : ServiceWorkerManagerService::ProcessUpdaterActor(ServiceWorkerUpdaterParent* aActor,
253 : const OriginAttributes& aOriginAttributes,
254 : const nsACString& aScope,
255 : uint64_t aParentId)
256 : {
257 0 : AssertIsOnBackgroundThread();
258 :
259 0 : nsAutoCString suffix;
260 0 : aOriginAttributes.CreateSuffix(suffix);
261 :
262 0 : nsCString scope(aScope);
263 0 : scope.Append(suffix);
264 :
265 0 : for (uint32_t i = 0; i < mPendingUpdaterActors.Length(); ++i) {
266 : // We already have an actor doing this update on another process.
267 0 : if (mPendingUpdaterActors[i].mScope.Equals(scope) &&
268 0 : mPendingUpdaterActors[i].mParentId != aParentId) {
269 0 : Unused << aActor->SendProceed(false);
270 0 : return;
271 : }
272 : }
273 :
274 0 : if (aActor->Proceed(this)) {
275 0 : PendingUpdaterActor* pua = mPendingUpdaterActors.AppendElement();
276 0 : pua->mActor = aActor;
277 0 : pua->mScope = scope;
278 0 : pua->mParentId = aParentId;
279 : }
280 : }
281 :
282 : void
283 0 : ServiceWorkerManagerService::UpdaterActorDestroyed(ServiceWorkerUpdaterParent* aActor)
284 : {
285 0 : for (uint32_t i = 0; i < mPendingUpdaterActors.Length(); ++i) {
286 : // We already have an actor doing the update for this scope.
287 0 : if (mPendingUpdaterActors[i].mActor == aActor) {
288 0 : mPendingUpdaterActors.RemoveElementAt(i);
289 0 : return;
290 : }
291 : }
292 :
293 0 : MOZ_CRASH("The actor should be found");
294 : }
295 :
296 : } // namespace workers
297 : } // namespace dom
298 : } // namespace mozilla
|