Coverage Report

Created: 2018-09-25 14:53

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