Backed out changeset 9d8b4c0b99ed (bug 1945683) for causing btime failures. CLOSED...
[gecko.git] / dom / cache / CacheStorage.cpp
blob689ef5ed84ec3652f4e112587cb3b16dc81dbb1f
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/. */
7 #include "mozilla/dom/cache/CacheStorage.h"
9 #include "mozilla/Preferences.h"
10 #include "mozilla/Unused.h"
11 #include "mozilla/dom/CacheBinding.h"
12 #include "mozilla/dom/CacheStorageBinding.h"
13 #include "mozilla/dom/InternalRequest.h"
14 #include "mozilla/dom/Promise.h"
15 #include "mozilla/dom/Response.h"
16 #include "mozilla/dom/cache/AutoUtils.h"
17 #include "mozilla/dom/cache/Cache.h"
18 #include "mozilla/dom/cache/CacheChild.h"
19 #include "mozilla/dom/cache/CacheCommon.h"
20 #include "mozilla/dom/cache/CacheStorageChild.h"
21 #include "mozilla/dom/cache/CacheWorkerRef.h"
22 #include "mozilla/dom/cache/PCacheChild.h"
23 #include "mozilla/dom/cache/ReadStream.h"
24 #include "mozilla/dom/cache/TypeUtils.h"
25 #include "mozilla/dom/quota/PrincipalUtils.h"
26 #include "mozilla/dom/quota/ResultExtensions.h"
27 #include "mozilla/dom/WorkerPrivate.h"
28 #include "mozilla/ipc/BackgroundChild.h"
29 #include "mozilla/ipc/BackgroundUtils.h"
30 #include "mozilla/ipc/PBackgroundChild.h"
31 #include "mozilla/ipc/PBackgroundSharedTypes.h"
32 #include "mozilla/StaticPrefs_dom.h"
33 #include "mozilla/StaticPrefs_extensions.h"
34 #include "nsContentUtils.h"
35 #include "mozilla/dom/Document.h"
36 #include "nsIGlobalObject.h"
37 #include "nsMixedContentBlocker.h"
38 #include "nsURLParsers.h"
39 #include "js/Object.h" // JS::GetClass
40 #include "js/PropertyAndElement.h" // JS_DefineProperty
42 namespace mozilla::dom::cache {
44 using mozilla::ErrorResult;
45 using mozilla::ipc::BackgroundChild;
46 using mozilla::ipc::PBackgroundChild;
47 using mozilla::ipc::PrincipalInfo;
48 using mozilla::ipc::PrincipalToPrincipalInfo;
50 NS_IMPL_CYCLE_COLLECTING_ADDREF(mozilla::dom::cache::CacheStorage);
51 NS_IMPL_CYCLE_COLLECTING_RELEASE(mozilla::dom::cache::CacheStorage);
52 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(mozilla::dom::cache::CacheStorage,
53 mGlobal);
55 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CacheStorage)
56 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
57 NS_INTERFACE_MAP_ENTRY(nsISupports)
58 NS_INTERFACE_MAP_END
60 // We cannot reference IPC types in a webidl binding implementation header. So
61 // define this in the .cpp.
62 struct CacheStorage::Entry final {
63 RefPtr<Promise> mPromise;
64 CacheOpArgs mArgs;
65 // We cannot add the requests until after the actor is present. So store
66 // the request data separately for now.
67 SafeRefPtr<InternalRequest> mRequest;
70 namespace {
72 bool IsTrusted(const PrincipalInfo& aPrincipalInfo, bool aTestingPrefEnabled) {
73 // Can happen on main thread or worker thread
75 if (aPrincipalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) {
76 return true;
79 // Require a ContentPrincipal to avoid null principal, etc.
80 QM_TRY(OkIf(aPrincipalInfo.type() == PrincipalInfo::TContentPrincipalInfo),
81 false);
83 // If we're in testing mode, then don't do any more work to determine if
84 // the origin is trusted. We have to run some tests as http.
85 if (aTestingPrefEnabled) {
86 return true;
89 // Now parse the scheme of the principal's origin. This is a short term
90 // method for determining "trust". In the long term we need to implement
91 // the full algorithm here:
93 // https://w3c.github.io/webappsec/specs/powerfulfeatures/#settings-secure
95 // TODO: Implement full secure setting algorithm. (bug 1177856)
97 const nsCString& flatURL = aPrincipalInfo.get_ContentPrincipalInfo().spec();
98 const char* const url = flatURL.get();
100 // off the main thread URL parsing using nsStdURLParser.
101 const nsCOMPtr<nsIURLParser> urlParser = new nsStdURLParser();
103 uint32_t schemePos;
104 int32_t schemeLen;
105 uint32_t authPos;
106 int32_t authLen;
107 QM_TRY(MOZ_TO_RESULT(urlParser->ParseURL(url, flatURL.Length(), &schemePos,
108 &schemeLen, &authPos, &authLen,
109 nullptr, nullptr)), // ignore path
110 false);
112 const nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen));
113 if (scheme.LowerCaseEqualsLiteral("https") ||
114 scheme.LowerCaseEqualsLiteral("file") ||
115 scheme.LowerCaseEqualsLiteral("moz-extension")) {
116 return true;
119 uint32_t hostPos;
120 int32_t hostLen;
121 QM_TRY(MOZ_TO_RESULT(
122 urlParser->ParseAuthority(url + authPos, authLen, nullptr,
123 nullptr, // ignore username
124 nullptr, nullptr, // ignore password
125 &hostPos, &hostLen,
126 nullptr)), // ignore port
127 false);
129 return nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackHost(
130 nsDependentCSubstring(url + authPos + hostPos, hostLen));
133 } // namespace
135 // static
136 already_AddRefed<CacheStorage> CacheStorage::CreateOnMainThread(
137 Namespace aNamespace, nsIGlobalObject* aGlobal, nsIPrincipal* aPrincipal,
138 bool aForceTrustedOrigin, ErrorResult& aRv) {
139 MOZ_DIAGNOSTIC_ASSERT(aGlobal);
140 MOZ_DIAGNOSTIC_ASSERT(aPrincipal);
141 MOZ_ASSERT(NS_IsMainThread());
143 PrincipalInfo principalInfo;
144 QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(aPrincipal, &principalInfo)),
145 nullptr, [&aRv](const nsresult rv) { aRv.Throw(rv); });
147 QM_TRY(OkIf(quota::IsPrincipalInfoValid(principalInfo)),
148 RefPtr{new CacheStorage(NS_ERROR_DOM_SECURITY_ERR)}.forget(),
149 [](const auto) {
150 NS_WARNING("CacheStorage not supported on invalid origins.");
153 const bool testingEnabled =
154 aForceTrustedOrigin ||
155 Preferences::GetBool("dom.caches.testing.enabled", false) ||
156 StaticPrefs::dom_serviceWorkers_testing_enabled();
158 if (!IsTrusted(principalInfo, testingEnabled)) {
159 NS_WARNING("CacheStorage not supported on untrusted origins.");
160 RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR);
161 return ref.forget();
164 RefPtr<CacheStorage> ref =
165 new CacheStorage(aNamespace, aGlobal, principalInfo, nullptr);
166 return ref.forget();
169 // static
170 already_AddRefed<CacheStorage> CacheStorage::CreateOnWorker(
171 Namespace aNamespace, nsIGlobalObject* aGlobal,
172 WorkerPrivate* aWorkerPrivate, ErrorResult& aRv) {
173 MOZ_DIAGNOSTIC_ASSERT(aGlobal);
174 MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate);
175 aWorkerPrivate->AssertIsOnWorkerThread();
177 if (aWorkerPrivate->GetOriginAttributes().IsPrivateBrowsing() &&
178 !StaticPrefs::dom_cache_privateBrowsing_enabled()) {
179 NS_WARNING("CacheStorage not supported during private browsing.");
180 RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR);
181 return ref.forget();
184 SafeRefPtr<CacheWorkerRef> workerRef =
185 CacheWorkerRef::Create(aWorkerPrivate, CacheWorkerRef::eIPCWorkerRef);
186 if (!workerRef) {
187 NS_WARNING("Worker thread is shutting down.");
188 aRv.Throw(NS_ERROR_FAILURE);
189 return nullptr;
192 const PrincipalInfo& principalInfo =
193 aWorkerPrivate->GetEffectiveStoragePrincipalInfo();
195 QM_TRY(OkIf(quota::IsPrincipalInfoValid(principalInfo)), nullptr,
196 [&aRv](const auto) { aRv.Throw(NS_ERROR_FAILURE); });
198 // We have a number of cases where we want to skip the https scheme
199 // validation:
201 // 1) Any worker when dom.caches.testing.enabled pref is true.
202 // 2) Any worker when dom.serviceWorkers.testing.enabled pref is true. This
203 // is mainly because most sites using SWs will expect Cache to work if
204 // SWs are enabled.
205 // 3) If the window that created this worker has the devtools SW testing
206 // option enabled. Same reasoning as (2).
207 // 4) If the worker itself is a ServiceWorker, then we always skip the
208 // origin checks. The ServiceWorker has its own trusted origin checks
209 // that are better than ours. In addition, we don't have information
210 // about the window any more, so we can't do our own checks.
211 bool testingEnabled = StaticPrefs::dom_caches_testing_enabled() ||
212 StaticPrefs::dom_serviceWorkers_testing_enabled() ||
213 aWorkerPrivate->ServiceWorkersTestingInWindow() ||
214 aWorkerPrivate->IsServiceWorker();
216 if (!IsTrusted(principalInfo, testingEnabled)) {
217 NS_WARNING("CacheStorage not supported on untrusted origins.");
218 RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR);
219 return ref.forget();
222 RefPtr<CacheStorage> ref = new CacheStorage(
223 aNamespace, aGlobal, principalInfo, std::move(workerRef));
224 return ref.forget();
227 // static
228 bool CacheStorage::DefineCachesForSandbox(JSContext* aCx,
229 JS::Handle<JSObject*> aGlobal) {
230 MOZ_ASSERT(NS_IsMainThread());
231 MOZ_DIAGNOSTIC_ASSERT(JS::GetClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL,
232 "Passed object is not a global object!");
233 js::AssertSameCompartment(aCx, aGlobal);
235 if (NS_WARN_IF(!CacheStorage_Binding::CreateAndDefineOnGlobal(aCx) ||
236 !Cache_Binding::CreateAndDefineOnGlobal(aCx))) {
237 return false;
240 nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aGlobal);
241 MOZ_DIAGNOSTIC_ASSERT(principal);
243 ErrorResult rv;
244 RefPtr<CacheStorage> storage =
245 CreateOnMainThread(DEFAULT_NAMESPACE, xpc::NativeGlobal(aGlobal),
246 principal, true, /* force trusted */
247 rv);
248 if (NS_WARN_IF(rv.MaybeSetPendingException(aCx))) {
249 return false;
252 JS::Rooted<JS::Value> caches(aCx);
253 if (NS_WARN_IF(!ToJSValue(aCx, storage, &caches))) {
254 return false;
257 return JS_DefineProperty(aCx, aGlobal, "caches", caches, JSPROP_ENUMERATE);
260 CacheStorage::CacheStorage(Namespace aNamespace, nsIGlobalObject* aGlobal,
261 const PrincipalInfo& aPrincipalInfo,
262 SafeRefPtr<CacheWorkerRef> aWorkerRef)
263 : mNamespace(aNamespace),
264 mGlobal(aGlobal),
265 mPrincipalInfo(MakeUnique<PrincipalInfo>(aPrincipalInfo)),
266 mActor(nullptr),
267 mStatus(NS_OK) {
268 MOZ_DIAGNOSTIC_ASSERT(mGlobal);
270 // If the PBackground actor is already initialized then we can
271 // immediately use it
272 PBackgroundChild* actor = BackgroundChild::GetOrCreateForCurrentThread();
273 if (NS_WARN_IF(!actor)) {
274 mStatus = NS_ERROR_UNEXPECTED;
275 return;
278 // WorkerRef ownership is passed to the CacheStorageChild actor and any
279 // actors it may create. The WorkerRef will keep the worker thread alive
280 // until the actors can gracefully shutdown.
281 CacheStorageChild* newActor =
282 new CacheStorageChild(this, std::move(aWorkerRef));
283 PCacheStorageChild* constructedActor = actor->SendPCacheStorageConstructor(
284 newActor, mNamespace, *mPrincipalInfo);
286 if (NS_WARN_IF(!constructedActor)) {
287 mStatus = NS_ERROR_UNEXPECTED;
288 return;
291 MOZ_DIAGNOSTIC_ASSERT(constructedActor == newActor);
292 mActor = newActor;
295 CacheStorage::CacheStorage(nsresult aFailureResult)
296 : mNamespace(INVALID_NAMESPACE), mActor(nullptr), mStatus(aFailureResult) {
297 MOZ_DIAGNOSTIC_ASSERT(NS_FAILED(mStatus));
300 already_AddRefed<Promise> CacheStorage::Match(
301 JSContext* aCx, const RequestOrUTF8String& aRequest,
302 const MultiCacheQueryOptions& aOptions, ErrorResult& aRv) {
303 NS_ASSERT_OWNINGTHREAD(CacheStorage);
305 if (!HasStorageAccess(eUseCounter_custom_PrivateBrowsingCachesMatch,
306 UseCounterWorker::Custom_PrivateBrowsingCachesMatch)) {
307 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
308 return nullptr;
311 if (NS_WARN_IF(NS_FAILED(mStatus))) {
312 aRv.Throw(mStatus);
313 return nullptr;
316 SafeRefPtr<InternalRequest> request =
317 ToInternalRequest(aCx, aRequest, IgnoreBody, aRv);
318 if (NS_WARN_IF(aRv.Failed())) {
319 return nullptr;
322 RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
323 if (NS_WARN_IF(!promise)) {
324 return nullptr;
327 CacheQueryParams params;
328 ToCacheQueryParams(params, aOptions);
330 auto entry = MakeUnique<Entry>();
331 entry->mPromise = promise;
332 entry->mArgs = StorageMatchArgs(CacheRequest(), params, GetOpenMode());
333 entry->mRequest = std::move(request);
335 RunRequest(std::move(entry));
337 return promise.forget();
340 already_AddRefed<Promise> CacheStorage::Has(const nsAString& aKey,
341 ErrorResult& aRv) {
342 NS_ASSERT_OWNINGTHREAD(CacheStorage);
344 if (!HasStorageAccess(eUseCounter_custom_PrivateBrowsingCachesHas,
345 UseCounterWorker::Custom_PrivateBrowsingCachesHas)) {
346 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
347 return nullptr;
350 if (NS_WARN_IF(NS_FAILED(mStatus))) {
351 aRv.Throw(mStatus);
352 return nullptr;
355 RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
356 if (NS_WARN_IF(!promise)) {
357 return nullptr;
360 auto entry = MakeUnique<Entry>();
361 entry->mPromise = promise;
362 entry->mArgs = StorageHasArgs(nsString(aKey));
364 RunRequest(std::move(entry));
366 return promise.forget();
369 already_AddRefed<Promise> CacheStorage::Open(const nsAString& aKey,
370 ErrorResult& aRv) {
371 NS_ASSERT_OWNINGTHREAD(CacheStorage);
373 if (!HasStorageAccess(eUseCounter_custom_PrivateBrowsingCachesOpen,
374 UseCounterWorker::Custom_PrivateBrowsingCachesOpen)) {
375 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
376 return nullptr;
379 if (NS_WARN_IF(NS_FAILED(mStatus))) {
380 aRv.Throw(mStatus);
381 return nullptr;
384 RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
385 if (NS_WARN_IF(!promise)) {
386 return nullptr;
389 auto entry = MakeUnique<Entry>();
390 entry->mPromise = promise;
391 entry->mArgs = StorageOpenArgs(nsString(aKey));
393 RunRequest(std::move(entry));
395 return promise.forget();
398 already_AddRefed<Promise> CacheStorage::Delete(const nsAString& aKey,
399 ErrorResult& aRv) {
400 NS_ASSERT_OWNINGTHREAD(CacheStorage);
402 if (!HasStorageAccess(eUseCounter_custom_PrivateBrowsingCachesDelete,
403 UseCounterWorker::Custom_PrivateBrowsingCachesDelete)) {
404 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
405 return nullptr;
408 if (NS_WARN_IF(NS_FAILED(mStatus))) {
409 aRv.Throw(mStatus);
410 return nullptr;
413 RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
414 if (NS_WARN_IF(!promise)) {
415 return nullptr;
418 auto entry = MakeUnique<Entry>();
419 entry->mPromise = promise;
420 entry->mArgs = StorageDeleteArgs(nsString(aKey));
422 RunRequest(std::move(entry));
424 return promise.forget();
427 already_AddRefed<Promise> CacheStorage::Keys(ErrorResult& aRv) {
428 NS_ASSERT_OWNINGTHREAD(CacheStorage);
430 if (!HasStorageAccess(eUseCounter_custom_PrivateBrowsingCachesKeys,
431 UseCounterWorker::Custom_PrivateBrowsingCachesKeys)) {
432 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
433 return nullptr;
436 if (NS_WARN_IF(NS_FAILED(mStatus))) {
437 aRv.Throw(mStatus);
438 return nullptr;
441 RefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
442 if (NS_WARN_IF(!promise)) {
443 return nullptr;
446 auto entry = MakeUnique<Entry>();
447 entry->mPromise = promise;
448 entry->mArgs = StorageKeysArgs();
450 RunRequest(std::move(entry));
452 return promise.forget();
455 // static
456 already_AddRefed<CacheStorage> CacheStorage::Constructor(
457 const GlobalObject& aGlobal, CacheStorageNamespace aNamespace,
458 nsIPrincipal* aPrincipal, ErrorResult& aRv) {
459 if (NS_WARN_IF(!NS_IsMainThread())) {
460 aRv.Throw(NS_ERROR_FAILURE);
461 return nullptr;
464 // TODO: remove Namespace in favor of CacheStorageNamespace
465 static_assert(DEFAULT_NAMESPACE == (uint32_t)CacheStorageNamespace::Content,
466 "Default namespace should match webidl Content enum");
467 static_assert(
468 CHROME_ONLY_NAMESPACE == (uint32_t)CacheStorageNamespace::Chrome,
469 "Chrome namespace should match webidl Chrome enum");
470 static_assert(
471 NUMBER_OF_NAMESPACES == ContiguousEnumSize<CacheStorageNamespace>::value,
472 "Number of namespace should match webidl count");
474 Namespace ns = static_cast<Namespace>(aNamespace);
475 nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
477 bool privateBrowsing = false;
478 if (nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global)) {
479 RefPtr<Document> doc = window->GetExtantDoc();
480 if (doc) {
481 nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
482 privateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
486 if (privateBrowsing && !StaticPrefs::dom_cache_privateBrowsing_enabled()) {
487 RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR);
488 return ref.forget();
491 // Create a CacheStorage object bypassing the trusted origin checks
492 // since this is a chrome-only constructor.
493 return CreateOnMainThread(ns, global, aPrincipal,
494 true /* force trusted origin */, aRv);
497 nsISupports* CacheStorage::GetParentObject() const { return mGlobal; }
499 JSObject* CacheStorage::WrapObject(JSContext* aContext,
500 JS::Handle<JSObject*> aGivenProto) {
501 return mozilla::dom::CacheStorage_Binding::Wrap(aContext, this, aGivenProto);
504 void CacheStorage::DestroyInternal(CacheStorageChild* aActor) {
505 NS_ASSERT_OWNINGTHREAD(CacheStorage);
506 MOZ_DIAGNOSTIC_ASSERT(mActor);
507 MOZ_DIAGNOSTIC_ASSERT(mActor == aActor);
508 MOZ_DIAGNOSTIC_ASSERT(!NS_FAILED(mStatus));
509 mActor->ClearListener();
510 mActor = nullptr;
511 mStatus = NS_ERROR_UNEXPECTED;
513 // Note that we will never get an actor again in case another request is
514 // made before this object is destructed.
517 nsIGlobalObject* CacheStorage::GetGlobalObject() const { return mGlobal; }
519 #ifdef DEBUG
520 void CacheStorage::AssertOwningThread() const {
521 NS_ASSERT_OWNINGTHREAD(CacheStorage);
523 #endif
525 PBackgroundChild* CacheStorage::GetIPCManager() {
526 // This is true because CacheStorage always uses IgnoreBody for requests.
527 // So we should never need to get the IPC manager during Request or
528 // Response serialization.
529 MOZ_CRASH("CacheStorage does not implement TypeUtils::GetIPCManager()");
532 CacheStorage::~CacheStorage() {
533 NS_ASSERT_OWNINGTHREAD(CacheStorage);
534 if (mActor) {
535 mActor->StartDestroyFromListener();
536 // DestroyInternal() is called synchronously by StartDestroyFromListener().
537 // So we should have already cleared the mActor.
538 MOZ_DIAGNOSTIC_ASSERT(!mActor);
542 void CacheStorage::RunRequest(UniquePtr<Entry> aEntry) {
543 MOZ_ASSERT(mActor);
545 AutoChildOpArgs args(this, aEntry->mArgs, 1);
547 if (aEntry->mRequest) {
548 ErrorResult rv;
549 args.Add(*aEntry->mRequest, IgnoreBody, IgnoreInvalidScheme, rv);
550 if (NS_WARN_IF(rv.Failed())) {
551 aEntry->mPromise->MaybeReject(std::move(rv));
552 return;
556 mActor->ExecuteOp(mGlobal, aEntry->mPromise, this, args.SendAsOpArgs());
559 OpenMode CacheStorage::GetOpenMode() const {
560 return mNamespace == CHROME_ONLY_NAMESPACE ? OpenMode::Eager : OpenMode::Lazy;
563 bool CacheStorage::HasStorageAccess(UseCounter aLabel,
564 UseCounterWorker aLabelWorker) const {
565 NS_ASSERT_OWNINGTHREAD(CacheStorage);
566 if (NS_WARN_IF(!mGlobal)) {
567 return false;
570 StorageAccess access = mGlobal->GetStorageAccess();
571 if (access == StorageAccess::ePrivateBrowsing) {
572 if (NS_IsMainThread()) {
573 SetUseCounter(mGlobal->GetGlobalJSObject(), aLabel);
574 } else {
575 SetUseCounter(aLabelWorker);
579 // Deny storage access for private browsing unless pref is toggled on.
580 if (nsIPrincipal* principal = mGlobal->PrincipalOrNull()) {
581 if (!principal->IsSystemPrincipal() &&
582 principal->GetPrivateBrowsingId() !=
583 nsIScriptSecurityManager::DEFAULT_PRIVATE_BROWSING_ID &&
584 !StaticPrefs::dom_cache_privateBrowsing_enabled()) {
585 return false;
589 return access > StorageAccess::eDeny ||
590 (StaticPrefs::
591 privacy_partition_always_partition_third_party_non_cookie_storage() &&
592 ShouldPartitionStorage(access));
595 } // namespace mozilla::dom::cache