Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/cache/CacheStorage.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 "mozilla/dom/cache/CacheStorage.h"
8
9
#include "mozilla/Unused.h"
10
#include "mozilla/dom/CacheBinding.h"
11
#include "mozilla/dom/CacheStorageBinding.h"
12
#include "mozilla/dom/InternalRequest.h"
13
#include "mozilla/dom/Promise.h"
14
#include "mozilla/dom/Response.h"
15
#include "mozilla/dom/cache/AutoUtils.h"
16
#include "mozilla/dom/cache/Cache.h"
17
#include "mozilla/dom/cache/CacheChild.h"
18
#include "mozilla/dom/cache/CacheStorageChild.h"
19
#include "mozilla/dom/cache/CacheWorkerHolder.h"
20
#include "mozilla/dom/cache/PCacheChild.h"
21
#include "mozilla/dom/cache/ReadStream.h"
22
#include "mozilla/dom/cache/TypeUtils.h"
23
#include "mozilla/dom/WorkerPrivate.h"
24
#include "mozilla/ipc/BackgroundChild.h"
25
#include "mozilla/ipc/BackgroundUtils.h"
26
#include "mozilla/ipc/PBackgroundChild.h"
27
#include "mozilla/ipc/PBackgroundSharedTypes.h"
28
#include "mozilla/StaticPrefs.h"
29
#include "nsContentUtils.h"
30
#include "nsIDocument.h"
31
#include "nsIGlobalObject.h"
32
#include "nsIScriptSecurityManager.h"
33
#include "nsURLParsers.h"
34
35
namespace mozilla {
36
namespace dom {
37
namespace cache {
38
39
using mozilla::Unused;
40
using mozilla::ErrorResult;
41
using mozilla::ipc::BackgroundChild;
42
using mozilla::ipc::PBackgroundChild;
43
using mozilla::ipc::IProtocol;
44
using mozilla::ipc::PrincipalInfo;
45
using mozilla::ipc::PrincipalToPrincipalInfo;
46
47
NS_IMPL_CYCLE_COLLECTING_ADDREF(mozilla::dom::cache::CacheStorage);
48
NS_IMPL_CYCLE_COLLECTING_RELEASE(mozilla::dom::cache::CacheStorage);
49
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(mozilla::dom::cache::CacheStorage,
50
                                      mGlobal);
51
52
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CacheStorage)
53
0
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
54
0
  NS_INTERFACE_MAP_ENTRY(nsISupports)
55
0
NS_INTERFACE_MAP_END
56
57
// We cannot reference IPC types in a webidl binding implementation header.  So
58
// define this in the .cpp.
59
struct CacheStorage::Entry final
60
{
61
  RefPtr<Promise> mPromise;
62
  CacheOpArgs mArgs;
63
  // We cannot add the requests until after the actor is present.  So store
64
  // the request data separately for now.
65
  RefPtr<InternalRequest> mRequest;
66
};
67
68
namespace {
69
70
bool
71
IsTrusted(const PrincipalInfo& aPrincipalInfo, bool aTestingPrefEnabled)
72
0
{
73
0
  // Can happen on main thread or worker thread
74
0
75
0
  if (aPrincipalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) {
76
0
    return true;
77
0
  }
78
0
79
0
  // Require a ContentPrincipal to avoid null principal, etc.
80
0
  if (NS_WARN_IF(aPrincipalInfo.type() != PrincipalInfo::TContentPrincipalInfo)) {
81
0
    return false;
82
0
  }
83
0
84
0
  // If we're in testing mode, then don't do any more work to determing if
85
0
  // the origin is trusted.  We have to run some tests as http.
86
0
  if (aTestingPrefEnabled) {
87
0
    return true;
88
0
  }
89
0
90
0
  // Now parse the scheme of the principal's origin.  This is a short term
91
0
  // method for determining "trust".  In the long term we need to implement
92
0
  // the full algorithm here:
93
0
  //
94
0
  // https://w3c.github.io/webappsec/specs/powerfulfeatures/#settings-secure
95
0
  //
96
0
  // TODO: Implement full secure setting algorithm. (bug 1177856)
97
0
98
0
  const nsCString& flatURL = aPrincipalInfo.get_ContentPrincipalInfo().spec();
99
0
  const char* url = flatURL.get();
100
0
101
0
  // off the main thread URL parsing using nsStdURLParser.
102
0
  nsCOMPtr<nsIURLParser> urlParser = new nsStdURLParser();
103
0
104
0
  uint32_t schemePos;
105
0
  int32_t schemeLen;
106
0
  uint32_t authPos;
107
0
  int32_t authLen;
108
0
  nsresult rv = urlParser->ParseURL(url, flatURL.Length(),
109
0
                                    &schemePos, &schemeLen,
110
0
                                    &authPos, &authLen,
111
0
                                    nullptr, nullptr);      // ignore path
112
0
  if (NS_WARN_IF(NS_FAILED(rv))) { return false; }
113
0
114
0
  nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen));
115
0
  if (scheme.LowerCaseEqualsLiteral("https") ||
116
0
      scheme.LowerCaseEqualsLiteral("file")) {
117
0
    return true;
118
0
  }
119
0
120
0
  uint32_t hostPos;
121
0
  int32_t hostLen;
122
0
123
0
  rv = urlParser->ParseAuthority(url + authPos, authLen,
124
0
                                 nullptr, nullptr,          // ignore username
125
0
                                 nullptr, nullptr,          // ignore password
126
0
                                 &hostPos, &hostLen,
127
0
                                 nullptr);                  // ignore port
128
0
  if (NS_WARN_IF(NS_FAILED(rv))) { return false; }
129
0
130
0
  nsDependentCSubstring hostname(url + authPos + hostPos, hostLen);
131
0
132
0
  return hostname.EqualsLiteral("localhost") ||
133
0
         hostname.EqualsLiteral("127.0.0.1") ||
134
0
         hostname.EqualsLiteral("::1");
135
0
}
136
137
} // namespace
138
139
// static
140
already_AddRefed<CacheStorage>
141
CacheStorage::CreateOnMainThread(Namespace aNamespace, nsIGlobalObject* aGlobal,
142
                                 nsIPrincipal* aPrincipal,
143
                                 bool aForceTrustedOrigin, ErrorResult& aRv)
144
0
{
145
0
  MOZ_DIAGNOSTIC_ASSERT(aGlobal);
146
0
  MOZ_DIAGNOSTIC_ASSERT(aPrincipal);
147
0
  MOZ_ASSERT(NS_IsMainThread());
148
0
149
0
  PrincipalInfo principalInfo;
150
0
  nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
151
0
  if (NS_WARN_IF(NS_FAILED(rv))) {
152
0
    aRv.Throw(rv);
153
0
    return nullptr;
154
0
  }
155
0
156
0
  bool testingEnabled = aForceTrustedOrigin ||
157
0
    Preferences::GetBool("dom.caches.testing.enabled", false) ||
158
0
    StaticPrefs::dom_serviceWorkers_testing_enabled();
159
0
160
0
  if (!IsTrusted(principalInfo, testingEnabled)) {
161
0
    NS_WARNING("CacheStorage not supported on untrusted origins.");
162
0
    RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR);
163
0
    return ref.forget();
164
0
  }
165
0
166
0
  RefPtr<CacheStorage> ref = new CacheStorage(aNamespace, aGlobal,
167
0
                                              principalInfo, nullptr);
168
0
  return ref.forget();
169
0
}
170
171
// static
172
already_AddRefed<CacheStorage>
173
CacheStorage::CreateOnWorker(Namespace aNamespace, nsIGlobalObject* aGlobal,
174
                             WorkerPrivate* aWorkerPrivate, ErrorResult& aRv)
175
0
{
176
0
  MOZ_DIAGNOSTIC_ASSERT(aGlobal);
177
0
  MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate);
178
0
  aWorkerPrivate->AssertIsOnWorkerThread();
179
0
180
0
  if (aWorkerPrivate->GetOriginAttributes().mPrivateBrowsingId > 0) {
181
0
    NS_WARNING("CacheStorage not supported during private browsing.");
182
0
    RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR);
183
0
    return ref.forget();
184
0
  }
185
0
186
0
  RefPtr<CacheWorkerHolder> workerHolder =
187
0
    CacheWorkerHolder::Create(aWorkerPrivate,
188
0
                              CacheWorkerHolder::AllowIdleShutdownStart);
189
0
  if (!workerHolder) {
190
0
    NS_WARNING("Worker thread is shutting down.");
191
0
    aRv.Throw(NS_ERROR_FAILURE);
192
0
    return nullptr;
193
0
  }
194
0
195
0
  const PrincipalInfo& principalInfo = aWorkerPrivate->GetPrincipalInfo();
196
0
197
0
  // We have a number of cases where we want to skip the https scheme
198
0
  // validation:
199
0
  //
200
0
  // 1) Any worker when dom.caches.testing.enabled pref is true.
201
0
  // 2) Any worker when dom.serviceWorkers.testing.enabled pref is true.  This
202
0
  //    is mainly because most sites using SWs will expect Cache to work if
203
0
  //    SWs are enabled.
204
0
  // 3) If the window that created this worker has the devtools SW testing
205
0
  //    option enabled.  Same reasoning as (2).
206
0
  // 4) If the worker itself is a ServiceWorker, then we always skip the
207
0
  //    origin checks.  The ServiceWorker has its own trusted origin checks
208
0
  //    that are better than ours.  In addition, we don't have information
209
0
  //    about the window any more, so we can't do our own checks.
210
0
  bool testingEnabled = StaticPrefs::dom_caches_testing_enabled() ||
211
0
                        StaticPrefs::dom_serviceWorkers_testing_enabled() ||
212
0
                        aWorkerPrivate->ServiceWorkersTestingInWindow() ||
213
0
                        aWorkerPrivate->IsServiceWorker();
214
0
215
0
  if (!IsTrusted(principalInfo, testingEnabled)) {
216
0
    NS_WARNING("CacheStorage not supported on untrusted origins.");
217
0
    RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR);
218
0
    return ref.forget();
219
0
  }
220
0
221
0
  RefPtr<CacheStorage> ref = new CacheStorage(aNamespace, aGlobal,
222
0
                                              principalInfo, workerHolder);
223
0
  return ref.forget();
224
0
}
225
226
// static
227
bool
228
CacheStorage::DefineCaches(JSContext* aCx, JS::Handle<JSObject*> aGlobal)
229
0
{
230
0
  MOZ_ASSERT(NS_IsMainThread());
231
0
  MOZ_DIAGNOSTIC_ASSERT(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL,
232
0
                                           "Passed object is not a global object!");
233
0
  js::AssertSameCompartment(aCx, aGlobal);
234
0
235
0
  if (NS_WARN_IF(!CacheStorage_Binding::GetConstructorObject(aCx) ||
236
0
                 !Cache_Binding::GetConstructorObject(aCx))) {
237
0
    return false;
238
0
  }
239
0
240
0
  nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aGlobal);
241
0
  MOZ_DIAGNOSTIC_ASSERT(principal);
242
0
243
0
  ErrorResult rv;
244
0
  RefPtr<CacheStorage> storage =
245
0
    CreateOnMainThread(DEFAULT_NAMESPACE, xpc::NativeGlobal(aGlobal), principal,
246
0
                       true,  /* force trusted */
247
0
                       rv);
248
0
  if (NS_WARN_IF(rv.MaybeSetPendingException(aCx))) {
249
0
    return false;
250
0
  }
251
0
252
0
  JS::Rooted<JS::Value> caches(aCx);
253
0
  if (NS_WARN_IF(!ToJSValue(aCx, storage, &caches))) {
254
0
    return false;
255
0
  }
256
0
257
0
  return JS_DefineProperty(aCx, aGlobal, "caches", caches, JSPROP_ENUMERATE);
258
0
}
259
260
CacheStorage::CacheStorage(Namespace aNamespace, nsIGlobalObject* aGlobal,
261
                           const PrincipalInfo& aPrincipalInfo,
262
                           CacheWorkerHolder* aWorkerHolder)
263
  : mNamespace(aNamespace)
264
  , mGlobal(aGlobal)
265
  , mPrincipalInfo(MakeUnique<PrincipalInfo>(aPrincipalInfo))
266
  , mActor(nullptr)
267
  , mStatus(NS_OK)
268
0
{
269
0
  MOZ_DIAGNOSTIC_ASSERT(mGlobal);
270
0
271
0
  // If the PBackground actor is already initialized then we can
272
0
  // immediately use it
273
0
  PBackgroundChild* actor = BackgroundChild::GetOrCreateForCurrentThread();
274
0
  if (NS_WARN_IF(!actor)) {
275
0
    mStatus = NS_ERROR_UNEXPECTED;
276
0
    return;
277
0
  }
278
0
279
0
  // WorkerHolder ownership is passed to the CacheStorageChild actor and any
280
0
  // actors it may create.  The WorkerHolder will keep the worker thread alive
281
0
  // until the actors can gracefully shutdown.
282
0
  CacheStorageChild* newActor = new CacheStorageChild(this, aWorkerHolder);
283
0
  PCacheStorageChild* constructedActor =
284
0
    actor->SendPCacheStorageConstructor(newActor, mNamespace, *mPrincipalInfo);
285
0
286
0
  if (NS_WARN_IF(!constructedActor)) {
287
0
    mStatus = NS_ERROR_UNEXPECTED;
288
0
    return;
289
0
  }
290
0
291
0
  MOZ_DIAGNOSTIC_ASSERT(constructedActor == newActor);
292
0
  mActor = newActor;
293
0
}
294
295
CacheStorage::CacheStorage(nsresult aFailureResult)
296
  : mNamespace(INVALID_NAMESPACE)
297
  , mActor(nullptr)
298
  , mStatus(aFailureResult)
299
0
{
300
0
  MOZ_DIAGNOSTIC_ASSERT(NS_FAILED(mStatus));
301
0
}
302
303
already_AddRefed<Promise>
304
CacheStorage::Match(JSContext* aCx, const RequestOrUSVString& aRequest,
305
                    const CacheQueryOptions& aOptions, ErrorResult& aRv)
306
0
{
307
0
  NS_ASSERT_OWNINGTHREAD(CacheStorage);
308
0
309
0
  if (!HasStorageAccess()) {
310
0
    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
311
0
    return nullptr;
312
0
  }
313
0
314
0
  if (NS_WARN_IF(NS_FAILED(mStatus))) {
315
0
    aRv.Throw(mStatus);
316
0
    return nullptr;
317
0
  }
318
0
319
0
  RefPtr<InternalRequest> request =
320
0
    ToInternalRequest(aCx, aRequest, IgnoreBody, aRv);
321
0
  if (NS_WARN_IF(aRv.Failed())) {
322
0
    return nullptr;
323
0
  }
324
0
325
0
  RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
326
0
  if (NS_WARN_IF(!promise)) {
327
0
    return nullptr;
328
0
  }
329
0
330
0
  CacheQueryParams params;
331
0
  ToCacheQueryParams(params, aOptions);
332
0
333
0
  nsAutoPtr<Entry> entry(new Entry());
334
0
  entry->mPromise = promise;
335
0
  entry->mArgs = StorageMatchArgs(CacheRequest(), params, GetOpenMode());
336
0
  entry->mRequest = request;
337
0
338
0
  RunRequest(std::move(entry));
339
0
340
0
  return promise.forget();
341
0
}
342
343
already_AddRefed<Promise>
344
CacheStorage::Has(const nsAString& aKey, ErrorResult& aRv)
345
0
{
346
0
  NS_ASSERT_OWNINGTHREAD(CacheStorage);
347
0
348
0
  if (!HasStorageAccess()) {
349
0
    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
350
0
    return nullptr;
351
0
  }
352
0
353
0
  if (NS_WARN_IF(NS_FAILED(mStatus))) {
354
0
    aRv.Throw(mStatus);
355
0
    return nullptr;
356
0
  }
357
0
358
0
  RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
359
0
  if (NS_WARN_IF(!promise)) {
360
0
    return nullptr;
361
0
  }
362
0
363
0
  nsAutoPtr<Entry> entry(new Entry());
364
0
  entry->mPromise = promise;
365
0
  entry->mArgs = StorageHasArgs(nsString(aKey));
366
0
367
0
  RunRequest(std::move(entry));
368
0
369
0
  return promise.forget();
370
0
}
371
372
already_AddRefed<Promise>
373
CacheStorage::Open(const nsAString& aKey, ErrorResult& aRv)
374
0
{
375
0
  NS_ASSERT_OWNINGTHREAD(CacheStorage);
376
0
377
0
  if (!HasStorageAccess()) {
378
0
    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
379
0
    return nullptr;
380
0
  }
381
0
382
0
  if (NS_WARN_IF(NS_FAILED(mStatus))) {
383
0
    aRv.Throw(mStatus);
384
0
    return nullptr;
385
0
  }
386
0
387
0
  RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
388
0
  if (NS_WARN_IF(!promise)) {
389
0
    return nullptr;
390
0
  }
391
0
392
0
  nsAutoPtr<Entry> entry(new Entry());
393
0
  entry->mPromise = promise;
394
0
  entry->mArgs = StorageOpenArgs(nsString(aKey));
395
0
396
0
  RunRequest(std::move(entry));
397
0
398
0
  return promise.forget();
399
0
}
400
401
already_AddRefed<Promise>
402
CacheStorage::Delete(const nsAString& aKey, ErrorResult& aRv)
403
0
{
404
0
  NS_ASSERT_OWNINGTHREAD(CacheStorage);
405
0
406
0
  if (!HasStorageAccess()) {
407
0
    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
408
0
    return nullptr;
409
0
  }
410
0
411
0
  if (NS_WARN_IF(NS_FAILED(mStatus))) {
412
0
    aRv.Throw(mStatus);
413
0
    return nullptr;
414
0
  }
415
0
416
0
  RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
417
0
  if (NS_WARN_IF(!promise)) {
418
0
    return nullptr;
419
0
  }
420
0
421
0
  nsAutoPtr<Entry> entry(new Entry());
422
0
  entry->mPromise = promise;
423
0
  entry->mArgs = StorageDeleteArgs(nsString(aKey));
424
0
425
0
  RunRequest(std::move(entry));
426
0
427
0
  return promise.forget();
428
0
}
429
430
already_AddRefed<Promise>
431
CacheStorage::Keys(ErrorResult& aRv)
432
0
{
433
0
  NS_ASSERT_OWNINGTHREAD(CacheStorage);
434
0
435
0
  if (!HasStorageAccess()) {
436
0
    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
437
0
    return nullptr;
438
0
  }
439
0
440
0
  if (NS_WARN_IF(NS_FAILED(mStatus))) {
441
0
    aRv.Throw(mStatus);
442
0
    return nullptr;
443
0
  }
444
0
445
0
  RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
446
0
  if (NS_WARN_IF(!promise)) {
447
0
    return nullptr;
448
0
  }
449
0
450
0
  nsAutoPtr<Entry> entry(new Entry());
451
0
  entry->mPromise = promise;
452
0
  entry->mArgs = StorageKeysArgs();
453
0
454
0
  RunRequest(std::move(entry));
455
0
456
0
  return promise.forget();
457
0
}
458
459
// static
460
already_AddRefed<CacheStorage>
461
CacheStorage::Constructor(const GlobalObject& aGlobal,
462
                          CacheStorageNamespace aNamespace,
463
                          nsIPrincipal* aPrincipal, ErrorResult& aRv)
464
0
{
465
0
  if (NS_WARN_IF(!NS_IsMainThread())) {
466
0
    aRv.Throw(NS_ERROR_FAILURE);
467
0
    return nullptr;
468
0
  }
469
0
470
0
  // TODO: remove Namespace in favor of CacheStorageNamespace
471
0
  static_assert(DEFAULT_NAMESPACE == (uint32_t)CacheStorageNamespace::Content,
472
0
                "Default namespace should match webidl Content enum");
473
0
  static_assert(CHROME_ONLY_NAMESPACE == (uint32_t)CacheStorageNamespace::Chrome,
474
0
                "Chrome namespace should match webidl Chrome enum");
475
0
  static_assert(NUMBER_OF_NAMESPACES == (uint32_t)CacheStorageNamespace::EndGuard_,
476
0
                "Number of namespace should match webidl endguard enum");
477
0
478
0
  Namespace ns = static_cast<Namespace>(aNamespace);
479
0
  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
480
0
481
0
  bool privateBrowsing = false;
482
0
  if (nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global)) {
483
0
    nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
484
0
    if (doc) {
485
0
      nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
486
0
      privateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
487
0
    }
488
0
  }
489
0
490
0
  if (privateBrowsing) {
491
0
    RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR);
492
0
    return ref.forget();
493
0
  }
494
0
495
0
  // Create a CacheStorage object bypassing the trusted origin checks
496
0
  // since this is a chrome-only constructor.
497
0
  return CreateOnMainThread(ns, global, aPrincipal,
498
0
                            true /* force trusted origin */, aRv);
499
0
}
500
501
nsISupports*
502
CacheStorage::GetParentObject() const
503
0
{
504
0
  return mGlobal;
505
0
}
506
507
JSObject*
508
CacheStorage::WrapObject(JSContext* aContext, JS::Handle<JSObject*> aGivenProto)
509
0
{
510
0
  return mozilla::dom::CacheStorage_Binding::Wrap(aContext, this, aGivenProto);
511
0
}
512
513
void
514
CacheStorage::DestroyInternal(CacheStorageChild* aActor)
515
0
{
516
0
  NS_ASSERT_OWNINGTHREAD(CacheStorage);
517
0
  MOZ_DIAGNOSTIC_ASSERT(mActor);
518
0
  MOZ_DIAGNOSTIC_ASSERT(mActor == aActor);
519
0
  MOZ_DIAGNOSTIC_ASSERT(!NS_FAILED(mStatus));
520
0
  mActor->ClearListener();
521
0
  mActor = nullptr;
522
0
  mStatus = NS_ERROR_UNEXPECTED;
523
0
524
0
  // Note that we will never get an actor again in case another request is
525
0
  // made before this object is destructed.
526
0
}
527
528
nsIGlobalObject*
529
CacheStorage::GetGlobalObject() const
530
0
{
531
0
  return mGlobal;
532
0
}
533
534
#ifdef DEBUG
535
void
536
CacheStorage::AssertOwningThread() const
537
{
538
  NS_ASSERT_OWNINGTHREAD(CacheStorage);
539
}
540
#endif
541
542
PBackgroundChild*
543
CacheStorage::GetIPCManager()
544
0
{
545
0
  // This is true because CacheStorage always uses IgnoreBody for requests.
546
0
  // So we should never need to get the IPC manager during Request or
547
0
  // Response serialization.
548
0
  MOZ_CRASH("CacheStorage does not implement TypeUtils::GetIPCManager()");
549
0
}
550
551
CacheStorage::~CacheStorage()
552
0
{
553
0
  NS_ASSERT_OWNINGTHREAD(CacheStorage);
554
0
  if (mActor) {
555
0
    mActor->StartDestroyFromListener();
556
0
    // DestroyInternal() is called synchronously by StartDestroyFromListener().
557
0
    // So we should have already cleared the mActor.
558
0
    MOZ_DIAGNOSTIC_ASSERT(!mActor);
559
0
  }
560
0
}
561
562
void
563
CacheStorage::RunRequest(nsAutoPtr<Entry>&& aEntry)
564
0
{
565
0
  MOZ_ASSERT(mActor);
566
0
567
0
  nsAutoPtr<Entry> entry(std::move(aEntry));
568
0
569
0
  AutoChildOpArgs args(this, entry->mArgs, 1);
570
0
571
0
  if (entry->mRequest) {
572
0
    ErrorResult rv;
573
0
    args.Add(entry->mRequest, IgnoreBody, IgnoreInvalidScheme, rv);
574
0
    if (NS_WARN_IF(rv.Failed())) {
575
0
      entry->mPromise->MaybeReject(rv);
576
0
      return;
577
0
    }
578
0
  }
579
0
580
0
  mActor->ExecuteOp(mGlobal, entry->mPromise, this, args.SendAsOpArgs());
581
0
}
582
583
OpenMode
584
CacheStorage::GetOpenMode() const
585
0
{
586
0
  return mNamespace == CHROME_ONLY_NAMESPACE ? OpenMode::Eager : OpenMode::Lazy;
587
0
}
588
589
bool
590
CacheStorage::HasStorageAccess() const
591
0
{
592
0
  NS_ASSERT_OWNINGTHREAD(CacheStorage);
593
0
594
0
  if (NS_IsMainThread()) {
595
0
    nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mGlobal);
596
0
    if (NS_WARN_IF(!window)) {
597
0
      return true;
598
0
    }
599
0
600
0
    nsContentUtils::StorageAccess access =
601
0
      nsContentUtils::StorageAllowedForWindow(window);
602
0
    return access > nsContentUtils::StorageAccess::ePrivateBrowsing;
603
0
  }
604
0
605
0
  WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
606
0
  MOZ_ASSERT(workerPrivate);
607
0
608
0
  return workerPrivate->IsStorageAllowed();
609
0
}
610
611
} // namespace cache
612
} // namespace dom
613
} // namespace mozilla