Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / netwerk / cookie / CookieJarSettings.cpp
blob9a795738d484a3632e74e17c5f5b747fa156f32f
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 "mozIThirdPartyUtil.h"
8 #include "mozilla/AntiTrackingUtils.h"
9 #include "mozilla/BasePrincipal.h"
10 #include "mozilla/ClearOnShutdown.h"
11 #include "mozilla/Components.h"
12 #include "mozilla/ContentBlockingAllowList.h"
13 #include "mozilla/dom/BrowsingContext.h"
14 #include "mozilla/net/CookieJarSettings.h"
15 #include "mozilla/net/NeckoChannelParams.h"
16 #include "mozilla/Permission.h"
17 #include "mozilla/PermissionManager.h"
18 #include "mozilla/SchedulerGroup.h"
19 #include "mozilla/StaticPrefs_network.h"
20 #include "mozilla/StoragePrincipalHelper.h"
21 #include "mozilla/Unused.h"
22 #include "nsIPrincipal.h"
23 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
24 # include "nsIProtocolHandler.h"
25 #endif
26 #include "nsIClassInfoImpl.h"
27 #include "nsIChannel.h"
28 #include "nsICookieManager.h"
29 #include "nsICookieService.h"
30 #include "nsIObjectInputStream.h"
31 #include "nsIObjectOutputStream.h"
32 #include "nsNetUtil.h"
34 namespace mozilla {
35 namespace net {
37 NS_IMPL_CLASSINFO(CookieJarSettings, nullptr, nsIClassInfo::THREADSAFE,
38 COOKIEJARSETTINGS_CID)
40 NS_IMPL_ISUPPORTS_CI(CookieJarSettings, nsICookieJarSettings, nsISerializable)
42 static StaticRefPtr<CookieJarSettings> sBlockinAll;
44 namespace {
46 class PermissionComparator {
47 public:
48 static bool Equals(nsIPermission* aA, nsIPermission* aB) {
49 nsCOMPtr<nsIPrincipal> principalA;
50 nsresult rv = aA->GetPrincipal(getter_AddRefs(principalA));
51 if (NS_WARN_IF(NS_FAILED(rv))) {
52 return false;
55 nsCOMPtr<nsIPrincipal> principalB;
56 rv = aB->GetPrincipal(getter_AddRefs(principalB));
57 if (NS_WARN_IF(NS_FAILED(rv))) {
58 return false;
61 bool equals = false;
62 rv = principalA->Equals(principalB, &equals);
63 if (NS_WARN_IF(NS_FAILED(rv))) {
64 return false;
67 return equals;
71 class ReleaseCookiePermissions final : public Runnable {
72 public:
73 explicit ReleaseCookiePermissions(nsTArray<RefPtr<nsIPermission>>&& aArray)
74 : Runnable("ReleaseCookiePermissions"), mArray(std::move(aArray)) {}
76 NS_IMETHOD Run() override {
77 MOZ_ASSERT(NS_IsMainThread());
78 mArray.Clear();
79 return NS_OK;
82 private:
83 nsTArray<RefPtr<nsIPermission>> mArray;
86 } // namespace
88 // static
89 already_AddRefed<nsICookieJarSettings> CookieJarSettings::GetBlockingAll(
90 bool aShouldResistFingerprinting) {
91 MOZ_ASSERT(NS_IsMainThread());
93 if (sBlockinAll) {
94 return do_AddRef(sBlockinAll);
97 sBlockinAll = new CookieJarSettings(nsICookieService::BEHAVIOR_REJECT,
98 OriginAttributes::IsFirstPartyEnabled(),
99 aShouldResistFingerprinting, eFixed);
100 ClearOnShutdown(&sBlockinAll);
102 return do_AddRef(sBlockinAll);
105 // static
106 already_AddRefed<nsICookieJarSettings> CookieJarSettings::Create(
107 CreateMode aMode, bool aShouldResistFingerprinting) {
108 MOZ_ASSERT(NS_IsMainThread());
110 RefPtr<CookieJarSettings> cookieJarSettings;
112 switch (aMode) {
113 case eRegular:
114 case ePrivate:
115 cookieJarSettings = new CookieJarSettings(
116 nsICookieManager::GetCookieBehavior(aMode == ePrivate),
117 OriginAttributes::IsFirstPartyEnabled(), aShouldResistFingerprinting,
118 eProgressive);
119 break;
121 default:
122 MOZ_CRASH("Unexpected create mode.");
125 return cookieJarSettings.forget();
128 // static
129 already_AddRefed<nsICookieJarSettings> CookieJarSettings::Create(
130 nsIPrincipal* aPrincipal) {
131 MOZ_ASSERT(NS_IsMainThread());
133 bool shouldResistFingerprinting =
134 nsContentUtils::ShouldResistFingerprinting_dangerous(
135 aPrincipal, "We are constructing CookieJarSettings here.",
136 RFPTarget::IsAlwaysEnabledForPrecompute);
138 if (aPrincipal && aPrincipal->OriginAttributesRef().IsPrivateBrowsing()) {
139 return Create(ePrivate, shouldResistFingerprinting);
142 return Create(eRegular, shouldResistFingerprinting);
145 // static
146 already_AddRefed<nsICookieJarSettings> CookieJarSettings::Create(
147 uint32_t aCookieBehavior, const nsAString& aPartitionKey,
148 bool aIsFirstPartyIsolated, bool aIsOnContentBlockingAllowList,
149 bool aShouldResistFingerprinting) {
150 MOZ_ASSERT(NS_IsMainThread());
152 RefPtr<CookieJarSettings> cookieJarSettings =
153 new CookieJarSettings(aCookieBehavior, aIsFirstPartyIsolated,
154 aShouldResistFingerprinting, eProgressive);
155 cookieJarSettings->mPartitionKey = aPartitionKey;
156 cookieJarSettings->mIsOnContentBlockingAllowList =
157 aIsOnContentBlockingAllowList;
159 return cookieJarSettings.forget();
162 // static
163 already_AddRefed<nsICookieJarSettings> CookieJarSettings::CreateForXPCOM() {
164 MOZ_ASSERT(NS_IsMainThread());
165 return Create(eRegular, /* shouldResistFingerprinting */ false);
168 CookieJarSettings::CookieJarSettings(uint32_t aCookieBehavior,
169 bool aIsFirstPartyIsolated,
170 bool aShouldResistFingerprinting,
171 State aState)
172 : mCookieBehavior(aCookieBehavior),
173 mIsFirstPartyIsolated(aIsFirstPartyIsolated),
174 mIsOnContentBlockingAllowList(false),
175 mIsOnContentBlockingAllowListUpdated(false),
176 mState(aState),
177 mToBeMerged(false),
178 mShouldResistFingerprinting(aShouldResistFingerprinting),
179 mTopLevelWindowContextId(0) {
180 MOZ_ASSERT(NS_IsMainThread());
181 MOZ_ASSERT_IF(
182 mIsFirstPartyIsolated,
183 mCookieBehavior !=
184 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN);
187 CookieJarSettings::~CookieJarSettings() {
188 if (!NS_IsMainThread() && !mCookiePermissions.IsEmpty()) {
189 RefPtr<Runnable> r =
190 new ReleaseCookiePermissions(std::move(mCookiePermissions));
191 MOZ_ASSERT(mCookiePermissions.IsEmpty());
192 SchedulerGroup::Dispatch(r.forget());
196 NS_IMETHODIMP
197 CookieJarSettings::InitWithURI(nsIURI* aURI, bool aIsPrivate) {
198 NS_ENSURE_ARG(aURI);
200 mCookieBehavior = nsICookieManager::GetCookieBehavior(aIsPrivate);
202 SetPartitionKey(aURI, false);
203 return NS_OK;
206 NS_IMETHODIMP
207 CookieJarSettings::GetCookieBehavior(uint32_t* aCookieBehavior) {
208 *aCookieBehavior = mCookieBehavior;
209 return NS_OK;
212 NS_IMETHODIMP
213 CookieJarSettings::GetIsFirstPartyIsolated(bool* aIsFirstPartyIsolated) {
214 *aIsFirstPartyIsolated = mIsFirstPartyIsolated;
215 return NS_OK;
218 NS_IMETHODIMP
219 CookieJarSettings::GetShouldResistFingerprinting(
220 bool* aShouldResistFingerprinting) {
221 *aShouldResistFingerprinting = mShouldResistFingerprinting;
222 return NS_OK;
225 NS_IMETHODIMP
226 CookieJarSettings::GetRejectThirdPartyContexts(
227 bool* aRejectThirdPartyContexts) {
228 *aRejectThirdPartyContexts =
229 CookieJarSettings::IsRejectThirdPartyContexts(mCookieBehavior);
230 return NS_OK;
233 NS_IMETHODIMP
234 CookieJarSettings::GetLimitForeignContexts(bool* aLimitForeignContexts) {
235 *aLimitForeignContexts =
236 mCookieBehavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN ||
237 (StaticPrefs::privacy_dynamic_firstparty_limitForeign() &&
238 mCookieBehavior ==
239 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN);
240 return NS_OK;
243 NS_IMETHODIMP
244 CookieJarSettings::GetBlockingAllThirdPartyContexts(
245 bool* aBlockingAllThirdPartyContexts) {
246 // XXX For non-cookie forms of storage, we handle BEHAVIOR_LIMIT_FOREIGN by
247 // simply rejecting the request to use the storage. In the future, if we
248 // change the meaning of BEHAVIOR_LIMIT_FOREIGN to be one which makes sense
249 // for non-cookie storage types, this may change.
250 *aBlockingAllThirdPartyContexts =
251 mCookieBehavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN ||
252 mCookieBehavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN;
253 return NS_OK;
256 NS_IMETHODIMP
257 CookieJarSettings::GetBlockingAllContexts(bool* aBlockingAllContexts) {
258 *aBlockingAllContexts = mCookieBehavior == nsICookieService::BEHAVIOR_REJECT;
259 return NS_OK;
262 NS_IMETHODIMP
263 CookieJarSettings::GetPartitionForeign(bool* aPartitionForeign) {
264 *aPartitionForeign =
265 mCookieBehavior ==
266 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN;
267 return NS_OK;
270 NS_IMETHODIMP
271 CookieJarSettings::SetPartitionForeign(bool aPartitionForeign) {
272 if (mIsFirstPartyIsolated) {
273 return NS_OK;
276 if (aPartitionForeign) {
277 mCookieBehavior =
278 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN;
280 return NS_OK;
283 NS_IMETHODIMP
284 CookieJarSettings::GetIsOnContentBlockingAllowList(
285 bool* aIsOnContentBlockingAllowList) {
286 *aIsOnContentBlockingAllowList = mIsOnContentBlockingAllowList;
287 return NS_OK;
290 NS_IMETHODIMP
291 CookieJarSettings::GetPartitionKey(nsAString& aPartitionKey) {
292 aPartitionKey = mPartitionKey;
293 return NS_OK;
296 NS_IMETHODIMP
297 CookieJarSettings::GetFingerprintingRandomizationKey(
298 nsTArray<uint8_t>& aFingerprintingRandomizationKey) {
299 if (!mFingerprintingRandomKey) {
300 return NS_ERROR_NOT_AVAILABLE;
303 aFingerprintingRandomizationKey = mFingerprintingRandomKey->Clone();
304 return NS_OK;
307 NS_IMETHODIMP
308 CookieJarSettings::CookiePermission(nsIPrincipal* aPrincipal,
309 uint32_t* aCookiePermission) {
310 MOZ_RELEASE_ASSERT(NS_IsMainThread());
311 NS_ENSURE_ARG_POINTER(aPrincipal);
312 NS_ENSURE_ARG_POINTER(aCookiePermission);
314 *aCookiePermission = nsIPermissionManager::UNKNOWN_ACTION;
316 nsresult rv;
318 // Let's see if we know this permission.
319 if (!mCookiePermissions.IsEmpty()) {
320 for (const RefPtr<nsIPermission>& permission : mCookiePermissions) {
321 bool match = false;
322 rv = permission->Matches(aPrincipal, false, &match);
323 if (NS_WARN_IF(NS_FAILED(rv)) || !match) {
324 continue;
327 rv = permission->GetCapability(aCookiePermission);
328 if (NS_WARN_IF(NS_FAILED(rv))) {
329 return rv;
332 return NS_OK;
336 // Let's ask the permission manager.
337 RefPtr<PermissionManager> pm = PermissionManager::GetInstance();
338 if (NS_WARN_IF(!pm)) {
339 return NS_ERROR_FAILURE;
342 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
343 // Check if this protocol doesn't allow cookies.
344 bool hasFlags;
345 nsCOMPtr<nsIURI> uri;
346 BasePrincipal::Cast(aPrincipal)->GetURI(getter_AddRefs(uri));
348 rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_FORBIDS_COOKIE_ACCESS,
349 &hasFlags);
350 if (NS_FAILED(rv) || hasFlags) {
351 *aCookiePermission = PermissionManager::DENY_ACTION;
352 rv = NS_OK; // Reset, so it's not caught as a bad status after the `else`.
353 } else // Note the tricky `else` which controls the call below.
354 #endif
356 rv = pm->TestPermissionFromPrincipal(aPrincipal, "cookie"_ns,
357 aCookiePermission);
358 if (NS_WARN_IF(NS_FAILED(rv))) {
359 return rv;
362 // Let's store the permission, also if the result is UNKNOWN in order to avoid
363 // race conditions.
365 nsCOMPtr<nsIPermission> permission =
366 Permission::Create(aPrincipal, "cookie"_ns, *aCookiePermission, 0, 0, 0);
367 if (permission) {
368 mCookiePermissions.AppendElement(permission);
371 mToBeMerged = true;
372 return NS_OK;
375 void CookieJarSettings::Serialize(CookieJarSettingsArgs& aData) {
376 MOZ_RELEASE_ASSERT(NS_IsMainThread());
378 aData.isFixed() = mState == eFixed;
379 aData.cookieBehavior() = mCookieBehavior;
380 aData.isFirstPartyIsolated() = mIsFirstPartyIsolated;
381 aData.shouldResistFingerprinting() = mShouldResistFingerprinting;
382 aData.isOnContentBlockingAllowList() = mIsOnContentBlockingAllowList;
383 aData.partitionKey() = mPartitionKey;
384 if (mFingerprintingRandomKey) {
385 aData.hasFingerprintingRandomizationKey() = true;
386 aData.fingerprintingRandomizationKey() = mFingerprintingRandomKey->Clone();
387 } else {
388 aData.hasFingerprintingRandomizationKey() = false;
391 for (const RefPtr<nsIPermission>& permission : mCookiePermissions) {
392 nsCOMPtr<nsIPrincipal> principal;
393 nsresult rv = permission->GetPrincipal(getter_AddRefs(principal));
394 if (NS_WARN_IF(NS_FAILED(rv))) {
395 continue;
398 mozilla::ipc::PrincipalInfo principalInfo;
399 rv = PrincipalToPrincipalInfo(principal, &principalInfo,
400 true /* aSkipBaseDomain */);
401 if (NS_WARN_IF(NS_FAILED(rv))) {
402 continue;
405 uint32_t cookiePermission = 0;
406 rv = permission->GetCapability(&cookiePermission);
407 if (NS_WARN_IF(NS_FAILED(rv))) {
408 continue;
411 aData.cookiePermissions().AppendElement(
412 CookiePermissionData(principalInfo, cookiePermission));
415 aData.topLevelWindowContextId() = mTopLevelWindowContextId;
417 mToBeMerged = false;
420 /* static */ void CookieJarSettings::Deserialize(
421 const CookieJarSettingsArgs& aData,
422 nsICookieJarSettings** aCookieJarSettings) {
423 MOZ_RELEASE_ASSERT(NS_IsMainThread());
425 CookiePermissionList list;
426 for (const CookiePermissionData& data : aData.cookiePermissions()) {
427 auto principalOrErr = PrincipalInfoToPrincipal(data.principalInfo());
428 if (NS_WARN_IF(principalOrErr.isErr())) {
429 continue;
432 nsCOMPtr<nsIPrincipal> principal = principalOrErr.unwrap();
434 nsCOMPtr<nsIPermission> permission = Permission::Create(
435 principal, "cookie"_ns, data.cookiePermission(), 0, 0, 0);
436 if (NS_WARN_IF(!permission)) {
437 continue;
440 list.AppendElement(permission);
443 RefPtr<CookieJarSettings> cookieJarSettings = new CookieJarSettings(
444 aData.cookieBehavior(), aData.isFirstPartyIsolated(),
445 aData.shouldResistFingerprinting(),
446 aData.isFixed() ? eFixed : eProgressive);
448 cookieJarSettings->mIsOnContentBlockingAllowList =
449 aData.isOnContentBlockingAllowList();
450 cookieJarSettings->mCookiePermissions = std::move(list);
451 cookieJarSettings->mPartitionKey = aData.partitionKey();
452 cookieJarSettings->mShouldResistFingerprinting =
453 aData.shouldResistFingerprinting();
455 if (aData.hasFingerprintingRandomizationKey()) {
456 cookieJarSettings->mFingerprintingRandomKey.emplace(
457 aData.fingerprintingRandomizationKey().Clone());
460 cookieJarSettings->mTopLevelWindowContextId = aData.topLevelWindowContextId();
462 cookieJarSettings.forget(aCookieJarSettings);
465 already_AddRefed<nsICookieJarSettings> CookieJarSettings::Merge(
466 const CookieJarSettingsArgs& aData) {
467 MOZ_RELEASE_ASSERT(NS_IsMainThread());
468 MOZ_ASSERT(
469 mCookieBehavior == aData.cookieBehavior() ||
470 (mCookieBehavior == nsICookieService::BEHAVIOR_REJECT_TRACKER &&
471 aData.cookieBehavior() ==
472 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN) ||
473 (mCookieBehavior ==
474 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN &&
475 aData.cookieBehavior() == nsICookieService::BEHAVIOR_REJECT_TRACKER));
477 if (mState == eFixed) {
478 return do_AddRef(this);
481 RefPtr<CookieJarSettings> newCookieJarSettings;
482 newCookieJarSettings = Clone();
484 // Merge cookie behavior pref values
485 if (newCookieJarSettings->mCookieBehavior ==
486 nsICookieService::BEHAVIOR_REJECT_TRACKER &&
487 aData.cookieBehavior() ==
488 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN) {
489 // If the other side has decided to partition third-party cookies, update
490 // our side when first-party isolation is disabled.
491 if (!newCookieJarSettings->mIsFirstPartyIsolated) {
492 newCookieJarSettings->mCookieBehavior =
493 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN;
496 if (newCookieJarSettings->mCookieBehavior ==
497 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN &&
498 aData.cookieBehavior() == nsICookieService::BEHAVIOR_REJECT_TRACKER) {
499 // If we've decided to partition third-party cookies, the other side may not
500 // have caught up yet unless it has first-party isolation enabled.
501 if (aData.isFirstPartyIsolated()) {
502 newCookieJarSettings->mCookieBehavior =
503 nsICookieService::BEHAVIOR_REJECT_TRACKER;
504 newCookieJarSettings->mIsFirstPartyIsolated = true;
507 // Ignore all other cases.
508 MOZ_ASSERT_IF(
509 newCookieJarSettings->mIsFirstPartyIsolated,
510 newCookieJarSettings->mCookieBehavior !=
511 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN);
513 if (aData.shouldResistFingerprinting()) {
514 newCookieJarSettings->mShouldResistFingerprinting = true;
517 // Merge partition Key. When a channel is created in the the child process and
518 // then opened in the parent process, the partition key will be created in the
519 // parent process, then sending back to the child process. Merging it here to
520 // ensure the child process has the latest value.
521 newCookieJarSettings->mPartitionKey = aData.partitionKey();
523 PermissionComparator comparator;
525 for (const CookiePermissionData& data : aData.cookiePermissions()) {
526 auto principalOrErr = PrincipalInfoToPrincipal(data.principalInfo());
527 if (NS_WARN_IF(principalOrErr.isErr())) {
528 continue;
531 nsCOMPtr<nsIPrincipal> principal = principalOrErr.unwrap();
532 nsCOMPtr<nsIPermission> permission = Permission::Create(
533 principal, "cookie"_ns, data.cookiePermission(), 0, 0, 0);
534 if (NS_WARN_IF(!permission)) {
535 continue;
538 if (!newCookieJarSettings->mCookiePermissions.Contains(permission,
539 comparator)) {
540 newCookieJarSettings->mCookiePermissions.AppendElement(permission);
544 return newCookieJarSettings.forget();
547 void CookieJarSettings::SetPartitionKey(nsIURI* aURI,
548 bool aForeignByAncestorContext) {
549 MOZ_ASSERT(aURI);
551 OriginAttributes attrs;
552 attrs.SetPartitionKey(aURI, aForeignByAncestorContext);
553 mPartitionKey = std::move(attrs.mPartitionKey);
556 void CookieJarSettings::UpdatePartitionKeyForDocumentLoadedByChannel(
557 nsIChannel* aChannel) {
558 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
559 bool thirdParty = AntiTrackingUtils::IsThirdPartyChannel(aChannel);
560 bool foreignByAncestorContext =
561 thirdParty && !loadInfo->GetIsThirdPartyContextToTopWindow();
562 StoragePrincipalHelper::UpdatePartitionKeyWithForeignAncestorBit(
563 mPartitionKey, foreignByAncestorContext);
566 void CookieJarSettings::UpdateIsOnContentBlockingAllowList(
567 nsIChannel* aChannel) {
568 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
569 MOZ_ASSERT(aChannel);
571 // Early return if the flag was updated before.
572 if (mIsOnContentBlockingAllowListUpdated) {
573 return;
575 mIsOnContentBlockingAllowListUpdated = true;
577 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
579 nsCOMPtr<nsIURI> uri;
580 nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
581 if (NS_WARN_IF(NS_FAILED(rv))) {
582 return;
585 // We need to recompute the ContentBlockingAllowListPrincipal here for the
586 // top level channel because we might navigate from the the initial
587 // about:blank page or the existing page which may have a different origin
588 // than the URI we are going to load here. Thus, we need to recompute the
589 // prinicpal in order to get the correct ContentBlockingAllowListPrincipal.
590 nsCOMPtr<nsIPrincipal> contentBlockingAllowListPrincipal;
591 OriginAttributes attrs;
592 loadInfo->GetOriginAttributes(&attrs);
593 ContentBlockingAllowList::RecomputePrincipal(
594 uri, attrs, getter_AddRefs(contentBlockingAllowListPrincipal));
596 if (!contentBlockingAllowListPrincipal ||
597 !contentBlockingAllowListPrincipal->GetIsContentPrincipal()) {
598 return;
601 Unused << ContentBlockingAllowList::Check(contentBlockingAllowListPrincipal,
602 NS_UsePrivateBrowsing(aChannel),
603 mIsOnContentBlockingAllowList);
606 // static
607 bool CookieJarSettings::IsRejectThirdPartyContexts(uint32_t aCookieBehavior) {
608 return aCookieBehavior == nsICookieService::BEHAVIOR_REJECT_TRACKER ||
609 aCookieBehavior ==
610 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN;
613 NS_IMETHODIMP
614 CookieJarSettings::Read(nsIObjectInputStream* aStream) {
615 MOZ_RELEASE_ASSERT(NS_IsMainThread());
616 nsresult rv = aStream->Read32(&mCookieBehavior);
617 if (NS_WARN_IF(NS_FAILED(rv))) {
618 return rv;
621 rv = aStream->ReadBoolean(&mIsFirstPartyIsolated);
622 if (NS_WARN_IF(NS_FAILED(rv))) {
623 return rv;
626 rv = aStream->ReadBoolean(&mShouldResistFingerprinting);
627 if (NS_WARN_IF(NS_FAILED(rv))) {
628 return rv;
631 bool isFixed;
632 aStream->ReadBoolean(&isFixed);
633 if (NS_WARN_IF(NS_FAILED(rv))) {
634 return rv;
636 mState = isFixed ? eFixed : eProgressive;
638 rv = aStream->ReadBoolean(&mIsOnContentBlockingAllowList);
639 if (NS_WARN_IF(NS_FAILED(rv))) {
640 return rv;
643 rv = aStream->ReadString(mPartitionKey);
644 if (NS_WARN_IF(NS_FAILED(rv))) {
645 return rv;
648 // Deserializing the cookie permission list.
649 uint32_t cookiePermissionsLength;
650 rv = aStream->Read32(&cookiePermissionsLength);
651 if (NS_WARN_IF(NS_FAILED(rv))) {
652 return rv;
655 if (!cookiePermissionsLength) {
656 // Bailing out early because there is no cookie permission.
657 return NS_OK;
660 CookiePermissionList list;
661 mCookiePermissions.SetCapacity(cookiePermissionsLength);
662 for (uint32_t i = 0; i < cookiePermissionsLength; ++i) {
663 nsAutoCString principalJSON;
664 aStream->ReadCString(principalJSON);
665 if (NS_WARN_IF(NS_FAILED(rv))) {
666 return rv;
669 nsCOMPtr<nsIPrincipal> principal = BasePrincipal::FromJSON(principalJSON);
671 if (NS_WARN_IF(!principal)) {
672 continue;
675 uint32_t cookiePermission;
676 aStream->Read32(&cookiePermission);
677 if (NS_WARN_IF(NS_FAILED(rv))) {
678 return rv;
681 nsCOMPtr<nsIPermission> permission =
682 Permission::Create(principal, "cookie"_ns, cookiePermission, 0, 0, 0);
683 if (NS_WARN_IF(!permission)) {
684 continue;
687 list.AppendElement(permission);
690 mCookiePermissions = std::move(list);
692 return NS_OK;
695 NS_IMETHODIMP
696 CookieJarSettings::Write(nsIObjectOutputStream* aStream) {
697 MOZ_RELEASE_ASSERT(NS_IsMainThread());
698 nsresult rv = aStream->Write32(mCookieBehavior);
699 if (NS_WARN_IF(NS_FAILED(rv))) {
700 return rv;
703 rv = aStream->WriteBoolean(mIsFirstPartyIsolated);
704 if (NS_WARN_IF(NS_FAILED(rv))) {
705 return rv;
708 rv = aStream->WriteBoolean(mShouldResistFingerprinting);
709 if (NS_WARN_IF(NS_FAILED(rv))) {
710 return rv;
713 rv = aStream->WriteBoolean(mState == eFixed);
714 if (NS_WARN_IF(NS_FAILED(rv))) {
715 return rv;
718 rv = aStream->WriteBoolean(mIsOnContentBlockingAllowList);
719 if (NS_WARN_IF(NS_FAILED(rv))) {
720 return rv;
723 rv = aStream->WriteWStringZ(mPartitionKey.get());
724 if (NS_WARN_IF(NS_FAILED(rv))) {
725 return rv;
728 // Serializing the cookie permission list. It will first write the length of
729 // the list, and then, write the cookie permission consecutively.
730 uint32_t cookiePermissionsLength = mCookiePermissions.Length();
731 rv = aStream->Write32(cookiePermissionsLength);
732 if (NS_WARN_IF(NS_FAILED(rv))) {
733 return rv;
736 for (const RefPtr<nsIPermission>& permission : mCookiePermissions) {
737 nsCOMPtr<nsIPrincipal> principal;
738 nsresult rv = permission->GetPrincipal(getter_AddRefs(principal));
739 if (NS_WARN_IF(NS_FAILED(rv))) {
740 continue;
743 nsAutoCString principalJSON;
744 BasePrincipal::Cast(principal)->ToJSON(principalJSON);
746 rv = aStream->WriteStringZ(principalJSON.get());
747 if (NS_WARN_IF(NS_FAILED(rv))) {
748 return rv;
751 uint32_t cookiePermission = 0;
752 rv = permission->GetCapability(&cookiePermission);
753 if (NS_WARN_IF(NS_FAILED(rv))) {
754 continue;
757 rv = aStream->Write32(cookiePermission);
758 if (NS_WARN_IF(NS_FAILED(rv))) {
759 return rv;
763 return NS_OK;
766 } // namespace net
767 } // namespace mozilla