no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / dom / cache / CacheStorage.cpp
blobb5647ba7910f7bc754bb66f3878696084ea3fcf3
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/QuotaManager.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::dom::quota::QuotaManager;
46 using mozilla::ipc::BackgroundChild;
47 using mozilla::ipc::PBackgroundChild;
48 using mozilla::ipc::PrincipalInfo;
49 using mozilla::ipc::PrincipalToPrincipalInfo;
51 NS_IMPL_CYCLE_COLLECTING_ADDREF(mozilla::dom::cache::CacheStorage);
52 NS_IMPL_CYCLE_COLLECTING_RELEASE(mozilla::dom::cache::CacheStorage);
53 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(mozilla::dom::cache::CacheStorage,
54 mGlobal);
56 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CacheStorage)
57 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
58 NS_INTERFACE_MAP_ENTRY(nsISupports)
59 NS_INTERFACE_MAP_END
61 // We cannot reference IPC types in a webidl binding implementation header. So
62 // define this in the .cpp.
63 struct CacheStorage::Entry final {
64 RefPtr<Promise> mPromise;
65 CacheOpArgs mArgs;
66 // We cannot add the requests until after the actor is present. So store
67 // the request data separately for now.
68 SafeRefPtr<InternalRequest> mRequest;
71 namespace {
73 bool IsTrusted(const PrincipalInfo& aPrincipalInfo, bool aTestingPrefEnabled) {
74 // Can happen on main thread or worker thread
76 if (aPrincipalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) {
77 return true;
80 // Require a ContentPrincipal to avoid null principal, etc.
81 QM_TRY(OkIf(aPrincipalInfo.type() == PrincipalInfo::TContentPrincipalInfo),
82 false);
84 // If we're in testing mode, then don't do any more work to determine if
85 // the origin is trusted. We have to run some tests as http.
86 if (aTestingPrefEnabled) {
87 return true;
90 // Now parse the scheme of the principal's origin. This is a short term
91 // method for determining "trust". In the long term we need to implement
92 // the full algorithm here:
94 // https://w3c.github.io/webappsec/specs/powerfulfeatures/#settings-secure
96 // TODO: Implement full secure setting algorithm. (bug 1177856)
98 const nsCString& flatURL = aPrincipalInfo.get_ContentPrincipalInfo().spec();
99 const char* const url = flatURL.get();
101 // off the main thread URL parsing using nsStdURLParser.
102 const nsCOMPtr<nsIURLParser> urlParser = new nsStdURLParser();
104 uint32_t schemePos;
105 int32_t schemeLen;
106 uint32_t authPos;
107 int32_t authLen;
108 QM_TRY(MOZ_TO_RESULT(urlParser->ParseURL(url, flatURL.Length(), &schemePos,
109 &schemeLen, &authPos, &authLen,
110 nullptr, nullptr)), // ignore path
111 false);
113 const nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen));
114 if (scheme.LowerCaseEqualsLiteral("https") ||
115 scheme.LowerCaseEqualsLiteral("file") ||
116 scheme.LowerCaseEqualsLiteral("moz-extension")) {
117 return true;
120 uint32_t hostPos;
121 int32_t hostLen;
122 QM_TRY(MOZ_TO_RESULT(
123 urlParser->ParseAuthority(url + authPos, authLen, nullptr,
124 nullptr, // ignore username
125 nullptr, nullptr, // ignore password
126 &hostPos, &hostLen,
127 nullptr)), // ignore port
128 false);
130 return nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackHost(
131 nsDependentCSubstring(url + authPos + hostPos, hostLen));
134 } // namespace
136 // static
137 already_AddRefed<CacheStorage> CacheStorage::CreateOnMainThread(
138 Namespace aNamespace, nsIGlobalObject* aGlobal, nsIPrincipal* aPrincipal,
139 bool aForceTrustedOrigin, ErrorResult& aRv) {
140 MOZ_DIAGNOSTIC_ASSERT(aGlobal);
141 MOZ_DIAGNOSTIC_ASSERT(aPrincipal);
142 MOZ_ASSERT(NS_IsMainThread());
144 PrincipalInfo principalInfo;
145 QM_TRY(MOZ_TO_RESULT(PrincipalToPrincipalInfo(aPrincipal, &principalInfo)),
146 nullptr, [&aRv](const nsresult rv) { aRv.Throw(rv); });
148 QM_TRY(OkIf(QuotaManager::IsPrincipalInfoValid(principalInfo)),
149 RefPtr{new CacheStorage(NS_ERROR_DOM_SECURITY_ERR)}.forget(),
150 [](const auto) {
151 NS_WARNING("CacheStorage not supported on invalid origins.");
154 const bool testingEnabled =
155 aForceTrustedOrigin ||
156 Preferences::GetBool("dom.caches.testing.enabled", false) ||
157 StaticPrefs::dom_serviceWorkers_testing_enabled();
159 if (!IsTrusted(principalInfo, testingEnabled)) {
160 NS_WARNING("CacheStorage not supported on untrusted origins.");
161 RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR);
162 return ref.forget();
165 RefPtr<CacheStorage> ref =
166 new CacheStorage(aNamespace, aGlobal, principalInfo, nullptr);
167 return ref.forget();
170 // static
171 already_AddRefed<CacheStorage> CacheStorage::CreateOnWorker(
172 Namespace aNamespace, nsIGlobalObject* aGlobal,
173 WorkerPrivate* aWorkerPrivate, ErrorResult& aRv) {
174 MOZ_DIAGNOSTIC_ASSERT(aGlobal);
175 MOZ_DIAGNOSTIC_ASSERT(aWorkerPrivate);
176 aWorkerPrivate->AssertIsOnWorkerThread();
178 if (aWorkerPrivate->GetOriginAttributes().mPrivateBrowsingId > 0 &&
179 !StaticPrefs::dom_cache_privateBrowsing_enabled()) {
180 NS_WARNING("CacheStorage not supported during private browsing.");
181 RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR);
182 return ref.forget();
185 SafeRefPtr<CacheWorkerRef> workerRef =
186 CacheWorkerRef::Create(aWorkerPrivate, CacheWorkerRef::eIPCWorkerRef);
187 if (!workerRef) {
188 NS_WARNING("Worker thread is shutting down.");
189 aRv.Throw(NS_ERROR_FAILURE);
190 return nullptr;
193 const PrincipalInfo& principalInfo =
194 aWorkerPrivate->GetEffectiveStoragePrincipalInfo();
196 QM_TRY(OkIf(QuotaManager::IsPrincipalInfoValid(principalInfo)), nullptr,
197 [&aRv](const auto) { aRv.Throw(NS_ERROR_FAILURE); });
199 // We have a number of cases where we want to skip the https scheme
200 // validation:
202 // 1) Any worker when dom.caches.testing.enabled pref is true.
203 // 2) Any worker when dom.serviceWorkers.testing.enabled pref is true. This
204 // is mainly because most sites using SWs will expect Cache to work if
205 // SWs are enabled.
206 // 3) If the window that created this worker has the devtools SW testing
207 // option enabled. Same reasoning as (2).
208 // 4) If the worker itself is a ServiceWorker, then we always skip the
209 // origin checks. The ServiceWorker has its own trusted origin checks
210 // that are better than ours. In addition, we don't have information
211 // about the window any more, so we can't do our own checks.
212 bool testingEnabled = StaticPrefs::dom_caches_testing_enabled() ||
213 StaticPrefs::dom_serviceWorkers_testing_enabled() ||
214 aWorkerPrivate->ServiceWorkersTestingInWindow() ||
215 aWorkerPrivate->IsServiceWorker();
217 if (!IsTrusted(principalInfo, testingEnabled)) {
218 NS_WARNING("CacheStorage not supported on untrusted origins.");
219 RefPtr<CacheStorage> ref = new CacheStorage(NS_ERROR_DOM_SECURITY_ERR);
220 return ref.forget();
223 RefPtr<CacheStorage> ref = new CacheStorage(
224 aNamespace, aGlobal, principalInfo, std::move(workerRef));
225 return ref.forget();
228 // static
229 bool CacheStorage::DefineCaches(JSContext* aCx, 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::GetConstructorObject(aCx) ||
236 !Cache_Binding::GetConstructorObject(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 RequestOrUSVString& 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