Bug 1851322 [wpt PR 41781] - HTML: "gopher" is no longer a special scheme, a=testonly
[gecko.git] / netwerk / cookie / CookieJarSettings.cpp
blob842c7bed73d0cd98610fbfe1efec8108ba5a1584
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/AntiTrackingUtils.h"
8 #include "mozilla/BasePrincipal.h"
9 #include "mozilla/ClearOnShutdown.h"
10 #include "mozilla/ContentBlockingAllowList.h"
11 #include "mozilla/dom/BrowsingContext.h"
12 #include "mozilla/net/CookieJarSettings.h"
13 #include "mozilla/net/NeckoChannelParams.h"
14 #include "mozilla/Permission.h"
15 #include "mozilla/PermissionManager.h"
16 #include "mozilla/SchedulerGroup.h"
17 #include "mozilla/StaticPrefs_network.h"
18 #include "mozilla/Unused.h"
19 #include "nsIPrincipal.h"
20 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
21 # include "nsIProtocolHandler.h"
22 #endif
23 #include "nsIClassInfoImpl.h"
24 #include "nsIChannel.h"
25 #include "nsICookieManager.h"
26 #include "nsICookieService.h"
27 #include "nsIObjectInputStream.h"
28 #include "nsIObjectOutputStream.h"
29 #include "nsNetUtil.h"
31 namespace mozilla {
32 namespace net {
34 NS_IMPL_CLASSINFO(CookieJarSettings, nullptr, nsIClassInfo::THREADSAFE,
35 COOKIEJARSETTINGS_CID)
37 NS_IMPL_ISUPPORTS_CI(CookieJarSettings, nsICookieJarSettings, nsISerializable)
39 static StaticRefPtr<CookieJarSettings> sBlockinAll;
41 namespace {
43 class PermissionComparator {
44 public:
45 static bool Equals(nsIPermission* aA, nsIPermission* aB) {
46 nsCOMPtr<nsIPrincipal> principalA;
47 nsresult rv = aA->GetPrincipal(getter_AddRefs(principalA));
48 if (NS_WARN_IF(NS_FAILED(rv))) {
49 return false;
52 nsCOMPtr<nsIPrincipal> principalB;
53 rv = aB->GetPrincipal(getter_AddRefs(principalB));
54 if (NS_WARN_IF(NS_FAILED(rv))) {
55 return false;
58 bool equals = false;
59 rv = principalA->Equals(principalB, &equals);
60 if (NS_WARN_IF(NS_FAILED(rv))) {
61 return false;
64 return equals;
68 class ReleaseCookiePermissions final : public Runnable {
69 public:
70 explicit ReleaseCookiePermissions(nsTArray<RefPtr<nsIPermission>>&& aArray)
71 : Runnable("ReleaseCookiePermissions"), mArray(std::move(aArray)) {}
73 NS_IMETHOD Run() override {
74 MOZ_ASSERT(NS_IsMainThread());
75 mArray.Clear();
76 return NS_OK;
79 private:
80 nsTArray<RefPtr<nsIPermission>> mArray;
83 } // namespace
85 // static
86 already_AddRefed<nsICookieJarSettings> CookieJarSettings::GetBlockingAll(
87 bool aShouldResistFingerprinting) {
88 MOZ_ASSERT(NS_IsMainThread());
90 if (sBlockinAll) {
91 return do_AddRef(sBlockinAll);
94 sBlockinAll = new CookieJarSettings(nsICookieService::BEHAVIOR_REJECT,
95 OriginAttributes::IsFirstPartyEnabled(),
96 aShouldResistFingerprinting, eFixed);
97 ClearOnShutdown(&sBlockinAll);
99 return do_AddRef(sBlockinAll);
102 // static
103 already_AddRefed<nsICookieJarSettings> CookieJarSettings::Create(
104 CreateMode aMode, bool aShouldResistFingerprinting) {
105 MOZ_ASSERT(NS_IsMainThread());
107 RefPtr<CookieJarSettings> cookieJarSettings;
109 switch (aMode) {
110 case eRegular:
111 case ePrivate:
112 cookieJarSettings = new CookieJarSettings(
113 nsICookieManager::GetCookieBehavior(aMode == ePrivate),
114 OriginAttributes::IsFirstPartyEnabled(), aShouldResistFingerprinting,
115 eProgressive);
116 break;
118 default:
119 MOZ_CRASH("Unexpected create mode.");
122 return cookieJarSettings.forget();
125 // static
126 already_AddRefed<nsICookieJarSettings> CookieJarSettings::Create(
127 nsIPrincipal* aPrincipal) {
128 MOZ_ASSERT(NS_IsMainThread());
130 bool shouldResistFingerprinting =
131 nsContentUtils::ShouldResistFingerprinting_dangerous(
132 aPrincipal, "We are constructing CookieJarSettings here.",
133 RFPTarget::IsAlwaysEnabledForPrecompute);
135 if (aPrincipal && aPrincipal->OriginAttributesRef().mPrivateBrowsingId > 0) {
136 return Create(ePrivate, shouldResistFingerprinting);
139 return Create(eRegular, shouldResistFingerprinting);
142 // static
143 already_AddRefed<nsICookieJarSettings> CookieJarSettings::Create(
144 uint32_t aCookieBehavior, const nsAString& aPartitionKey,
145 bool aIsFirstPartyIsolated, bool aIsOnContentBlockingAllowList,
146 bool aShouldResistFingerprinting) {
147 MOZ_ASSERT(NS_IsMainThread());
149 RefPtr<CookieJarSettings> cookieJarSettings =
150 new CookieJarSettings(aCookieBehavior, aIsFirstPartyIsolated,
151 aShouldResistFingerprinting, eProgressive);
152 cookieJarSettings->mPartitionKey = aPartitionKey;
153 cookieJarSettings->mIsOnContentBlockingAllowList =
154 aIsOnContentBlockingAllowList;
156 return cookieJarSettings.forget();
159 // static
160 already_AddRefed<nsICookieJarSettings> CookieJarSettings::CreateForXPCOM() {
161 MOZ_ASSERT(NS_IsMainThread());
162 return Create(eRegular, /* shouldResistFingerprinting */ false);
165 CookieJarSettings::CookieJarSettings(uint32_t aCookieBehavior,
166 bool aIsFirstPartyIsolated,
167 bool aShouldResistFingerprinting,
168 State aState)
169 : mCookieBehavior(aCookieBehavior),
170 mIsFirstPartyIsolated(aIsFirstPartyIsolated),
171 mIsOnContentBlockingAllowList(false),
172 mIsOnContentBlockingAllowListUpdated(false),
173 mState(aState),
174 mToBeMerged(false),
175 mShouldResistFingerprinting(aShouldResistFingerprinting) {
176 MOZ_ASSERT(NS_IsMainThread());
177 MOZ_ASSERT_IF(
178 mIsFirstPartyIsolated,
179 mCookieBehavior !=
180 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN);
183 CookieJarSettings::~CookieJarSettings() {
184 if (!NS_IsMainThread() && !mCookiePermissions.IsEmpty()) {
185 RefPtr<Runnable> r =
186 new ReleaseCookiePermissions(std::move(mCookiePermissions));
187 MOZ_ASSERT(mCookiePermissions.IsEmpty());
189 SchedulerGroup::Dispatch(TaskCategory::Other, r.forget());
193 NS_IMETHODIMP
194 CookieJarSettings::InitWithURI(nsIURI* aURI, bool aIsPrivate) {
195 NS_ENSURE_ARG(aURI);
197 mCookieBehavior = nsICookieManager::GetCookieBehavior(aIsPrivate);
199 SetPartitionKey(aURI);
200 return NS_OK;
203 NS_IMETHODIMP
204 CookieJarSettings::GetCookieBehavior(uint32_t* aCookieBehavior) {
205 *aCookieBehavior = mCookieBehavior;
206 return NS_OK;
209 NS_IMETHODIMP
210 CookieJarSettings::GetIsFirstPartyIsolated(bool* aIsFirstPartyIsolated) {
211 *aIsFirstPartyIsolated = mIsFirstPartyIsolated;
212 return NS_OK;
215 NS_IMETHODIMP
216 CookieJarSettings::GetShouldResistFingerprinting(
217 bool* aShouldResistFingerprinting) {
218 *aShouldResistFingerprinting = mShouldResistFingerprinting;
219 return NS_OK;
222 NS_IMETHODIMP
223 CookieJarSettings::GetRejectThirdPartyContexts(
224 bool* aRejectThirdPartyContexts) {
225 *aRejectThirdPartyContexts =
226 CookieJarSettings::IsRejectThirdPartyContexts(mCookieBehavior);
227 return NS_OK;
230 NS_IMETHODIMP
231 CookieJarSettings::GetLimitForeignContexts(bool* aLimitForeignContexts) {
232 *aLimitForeignContexts =
233 mCookieBehavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN ||
234 (StaticPrefs::privacy_dynamic_firstparty_limitForeign() &&
235 mCookieBehavior ==
236 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN);
237 return NS_OK;
240 NS_IMETHODIMP
241 CookieJarSettings::GetBlockingAllThirdPartyContexts(
242 bool* aBlockingAllThirdPartyContexts) {
243 // XXX For non-cookie forms of storage, we handle BEHAVIOR_LIMIT_FOREIGN by
244 // simply rejecting the request to use the storage. In the future, if we
245 // change the meaning of BEHAVIOR_LIMIT_FOREIGN to be one which makes sense
246 // for non-cookie storage types, this may change.
247 *aBlockingAllThirdPartyContexts =
248 mCookieBehavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN ||
249 (!StaticPrefs::network_cookie_rejectForeignWithExceptions_enabled() &&
250 mCookieBehavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN);
251 return NS_OK;
254 NS_IMETHODIMP
255 CookieJarSettings::GetBlockingAllContexts(bool* aBlockingAllContexts) {
256 *aBlockingAllContexts = mCookieBehavior == nsICookieService::BEHAVIOR_REJECT;
257 return NS_OK;
260 NS_IMETHODIMP
261 CookieJarSettings::GetPartitionForeign(bool* aPartitionForeign) {
262 *aPartitionForeign =
263 mCookieBehavior ==
264 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN;
265 return NS_OK;
268 NS_IMETHODIMP
269 CookieJarSettings::SetPartitionForeign(bool aPartitionForeign) {
270 if (mIsFirstPartyIsolated) {
271 return NS_OK;
274 if (aPartitionForeign) {
275 mCookieBehavior =
276 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN;
278 return NS_OK;
281 NS_IMETHODIMP
282 CookieJarSettings::GetIsOnContentBlockingAllowList(
283 bool* aIsOnContentBlockingAllowList) {
284 *aIsOnContentBlockingAllowList = mIsOnContentBlockingAllowList;
285 return NS_OK;
288 NS_IMETHODIMP
289 CookieJarSettings::GetPartitionKey(nsAString& aPartitionKey) {
290 aPartitionKey = mPartitionKey;
291 return NS_OK;
294 NS_IMETHODIMP
295 CookieJarSettings::GetFingerprintingRandomizationKey(
296 nsTArray<uint8_t>& aFingerprintingRandomizationKey) {
297 if (!mFingerprintingRandomKey) {
298 return NS_ERROR_NOT_AVAILABLE;
301 aFingerprintingRandomizationKey = mFingerprintingRandomKey->Clone();
302 return NS_OK;
305 NS_IMETHODIMP
306 CookieJarSettings::CookiePermission(nsIPrincipal* aPrincipal,
307 uint32_t* aCookiePermission) {
308 MOZ_ASSERT(NS_IsMainThread());
309 NS_ENSURE_ARG_POINTER(aPrincipal);
310 NS_ENSURE_ARG_POINTER(aCookiePermission);
312 *aCookiePermission = nsIPermissionManager::UNKNOWN_ACTION;
314 nsresult rv;
316 // Let's see if we know this permission.
317 if (!mCookiePermissions.IsEmpty()) {
318 for (const RefPtr<nsIPermission>& permission : mCookiePermissions) {
319 bool match = false;
320 rv = permission->Matches(aPrincipal, false, &match);
321 if (NS_WARN_IF(NS_FAILED(rv)) || !match) {
322 continue;
325 rv = permission->GetCapability(aCookiePermission);
326 if (NS_WARN_IF(NS_FAILED(rv))) {
327 return rv;
330 return NS_OK;
334 // Let's ask the permission manager.
335 PermissionManager* pm = PermissionManager::GetInstance();
336 if (NS_WARN_IF(!pm)) {
337 return NS_ERROR_FAILURE;
340 #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
341 // Check if this protocol doesn't allow cookies.
342 bool hasFlags;
343 nsCOMPtr<nsIURI> uri;
344 BasePrincipal::Cast(aPrincipal)->GetURI(getter_AddRefs(uri));
346 rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_FORBIDS_COOKIE_ACCESS,
347 &hasFlags);
348 if (NS_FAILED(rv) || hasFlags) {
349 *aCookiePermission = PermissionManager::DENY_ACTION;
350 rv = NS_OK; // Reset, so it's not caught as a bad status after the `else`.
351 } else // Note the tricky `else` which controls the call below.
352 #endif
354 rv = pm->TestPermissionFromPrincipal(aPrincipal, "cookie"_ns,
355 aCookiePermission);
356 if (NS_WARN_IF(NS_FAILED(rv))) {
357 return rv;
360 // Let's store the permission, also if the result is UNKNOWN in order to avoid
361 // race conditions.
363 nsCOMPtr<nsIPermission> permission =
364 Permission::Create(aPrincipal, "cookie"_ns, *aCookiePermission, 0, 0, 0);
365 if (permission) {
366 mCookiePermissions.AppendElement(permission);
369 mToBeMerged = true;
370 return NS_OK;
373 void CookieJarSettings::Serialize(CookieJarSettingsArgs& aData) {
374 MOZ_ASSERT(NS_IsMainThread());
376 aData.isFixed() = mState == eFixed;
377 aData.cookieBehavior() = mCookieBehavior;
378 aData.isFirstPartyIsolated() = mIsFirstPartyIsolated;
379 aData.shouldResistFingerprinting() = mShouldResistFingerprinting;
380 aData.isOnContentBlockingAllowList() = mIsOnContentBlockingAllowList;
381 aData.partitionKey() = mPartitionKey;
382 if (mFingerprintingRandomKey) {
383 aData.hasFingerprintingRandomizationKey() = true;
384 aData.fingerprintingRandomizationKey() = mFingerprintingRandomKey->Clone();
385 } else {
386 aData.hasFingerprintingRandomizationKey() = false;
389 for (const RefPtr<nsIPermission>& permission : mCookiePermissions) {
390 nsCOMPtr<nsIPrincipal> principal;
391 nsresult rv = permission->GetPrincipal(getter_AddRefs(principal));
392 if (NS_WARN_IF(NS_FAILED(rv))) {
393 continue;
396 ipc::PrincipalInfo principalInfo;
397 rv = PrincipalToPrincipalInfo(principal, &principalInfo,
398 true /* aSkipBaseDomain */);
399 if (NS_WARN_IF(NS_FAILED(rv))) {
400 continue;
403 uint32_t cookiePermission = 0;
404 rv = permission->GetCapability(&cookiePermission);
405 if (NS_WARN_IF(NS_FAILED(rv))) {
406 continue;
409 aData.cookiePermissions().AppendElement(
410 CookiePermissionData(principalInfo, cookiePermission));
413 mToBeMerged = false;
416 /* static */ void CookieJarSettings::Deserialize(
417 const CookieJarSettingsArgs& aData,
418 nsICookieJarSettings** aCookieJarSettings) {
419 MOZ_ASSERT(NS_IsMainThread());
421 CookiePermissionList list;
422 for (const CookiePermissionData& data : aData.cookiePermissions()) {
423 auto principalOrErr = PrincipalInfoToPrincipal(data.principalInfo());
424 if (NS_WARN_IF(principalOrErr.isErr())) {
425 continue;
428 nsCOMPtr<nsIPrincipal> principal = principalOrErr.unwrap();
430 nsCOMPtr<nsIPermission> permission = Permission::Create(
431 principal, "cookie"_ns, data.cookiePermission(), 0, 0, 0);
432 if (NS_WARN_IF(!permission)) {
433 continue;
436 list.AppendElement(permission);
439 RefPtr<CookieJarSettings> cookieJarSettings = new CookieJarSettings(
440 aData.cookieBehavior(), aData.isFirstPartyIsolated(),
441 aData.shouldResistFingerprinting(),
442 aData.isFixed() ? eFixed : eProgressive);
444 cookieJarSettings->mIsOnContentBlockingAllowList =
445 aData.isOnContentBlockingAllowList();
446 cookieJarSettings->mCookiePermissions = std::move(list);
447 cookieJarSettings->mPartitionKey = aData.partitionKey();
448 cookieJarSettings->mShouldResistFingerprinting =
449 aData.shouldResistFingerprinting();
451 if (aData.hasFingerprintingRandomizationKey()) {
452 cookieJarSettings->mFingerprintingRandomKey.emplace(
453 aData.fingerprintingRandomizationKey().Clone());
456 cookieJarSettings.forget(aCookieJarSettings);
459 void CookieJarSettings::Merge(const CookieJarSettingsArgs& aData) {
460 MOZ_ASSERT(NS_IsMainThread());
461 MOZ_ASSERT(
462 mCookieBehavior == aData.cookieBehavior() ||
463 (mCookieBehavior == nsICookieService::BEHAVIOR_REJECT_TRACKER &&
464 aData.cookieBehavior() ==
465 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN) ||
466 (mCookieBehavior ==
467 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN &&
468 aData.cookieBehavior() == nsICookieService::BEHAVIOR_REJECT_TRACKER));
470 if (mState == eFixed) {
471 return;
474 // Merge cookie behavior pref values
475 if (mCookieBehavior == nsICookieService::BEHAVIOR_REJECT_TRACKER &&
476 aData.cookieBehavior() ==
477 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN) {
478 // If the other side has decided to partition third-party cookies, update
479 // our side when first-party isolation is disabled.
480 if (!mIsFirstPartyIsolated) {
481 mCookieBehavior =
482 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN;
485 if (mCookieBehavior ==
486 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN &&
487 aData.cookieBehavior() == nsICookieService::BEHAVIOR_REJECT_TRACKER) {
488 // If we've decided to partition third-party cookies, the other side may not
489 // have caught up yet unless it has first-party isolation enabled.
490 if (aData.isFirstPartyIsolated()) {
491 mCookieBehavior = nsICookieService::BEHAVIOR_REJECT_TRACKER;
492 mIsFirstPartyIsolated = true;
495 // Ignore all other cases.
496 MOZ_ASSERT_IF(
497 mIsFirstPartyIsolated,
498 mCookieBehavior !=
499 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN);
501 if (aData.shouldResistFingerprinting()) {
502 mShouldResistFingerprinting = true;
505 PermissionComparator comparator;
507 for (const CookiePermissionData& data : aData.cookiePermissions()) {
508 auto principalOrErr = PrincipalInfoToPrincipal(data.principalInfo());
509 if (NS_WARN_IF(principalOrErr.isErr())) {
510 continue;
513 nsCOMPtr<nsIPrincipal> principal = principalOrErr.unwrap();
514 nsCOMPtr<nsIPermission> permission = Permission::Create(
515 principal, "cookie"_ns, data.cookiePermission(), 0, 0, 0);
516 if (NS_WARN_IF(!permission)) {
517 continue;
520 if (!mCookiePermissions.Contains(permission, comparator)) {
521 mCookiePermissions.AppendElement(permission);
526 void CookieJarSettings::SetPartitionKey(nsIURI* aURI) {
527 MOZ_ASSERT(aURI);
529 OriginAttributes attrs;
530 attrs.SetPartitionKey(aURI);
531 mPartitionKey = std::move(attrs.mPartitionKey);
534 void CookieJarSettings::UpdateIsOnContentBlockingAllowList(
535 nsIChannel* aChannel) {
536 MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
537 MOZ_ASSERT(aChannel);
539 // Early return if the flag was updated before.
540 if (mIsOnContentBlockingAllowListUpdated) {
541 return;
543 mIsOnContentBlockingAllowListUpdated = true;
545 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
547 nsCOMPtr<nsIURI> uri;
548 nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
549 if (NS_WARN_IF(NS_FAILED(rv))) {
550 return;
553 // We need to recompute the ContentBlockingAllowListPrincipal here for the
554 // top level channel because we might navigate from the the initial
555 // about:blank page or the existing page which may have a different origin
556 // than the URI we are going to load here. Thus, we need to recompute the
557 // prinicpal in order to get the correct ContentBlockingAllowListPrincipal.
558 nsCOMPtr<nsIPrincipal> contentBlockingAllowListPrincipal;
559 OriginAttributes attrs;
560 loadInfo->GetOriginAttributes(&attrs);
561 ContentBlockingAllowList::RecomputePrincipal(
562 uri, attrs, getter_AddRefs(contentBlockingAllowListPrincipal));
564 if (!contentBlockingAllowListPrincipal ||
565 !contentBlockingAllowListPrincipal->GetIsContentPrincipal()) {
566 return;
569 Unused << ContentBlockingAllowList::Check(contentBlockingAllowListPrincipal,
570 NS_UsePrivateBrowsing(aChannel),
571 mIsOnContentBlockingAllowList);
574 // static
575 bool CookieJarSettings::IsRejectThirdPartyContexts(uint32_t aCookieBehavior) {
576 return aCookieBehavior == nsICookieService::BEHAVIOR_REJECT_TRACKER ||
577 aCookieBehavior ==
578 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN ||
579 IsRejectThirdPartyWithExceptions(aCookieBehavior);
582 // static
583 bool CookieJarSettings::IsRejectThirdPartyWithExceptions(
584 uint32_t aCookieBehavior) {
585 return aCookieBehavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN &&
586 StaticPrefs::network_cookie_rejectForeignWithExceptions_enabled();
589 NS_IMETHODIMP
590 CookieJarSettings::Read(nsIObjectInputStream* aStream) {
591 nsresult rv = aStream->Read32(&mCookieBehavior);
592 if (NS_WARN_IF(NS_FAILED(rv))) {
593 return rv;
596 rv = aStream->ReadBoolean(&mIsFirstPartyIsolated);
597 if (NS_WARN_IF(NS_FAILED(rv))) {
598 return rv;
601 rv = aStream->ReadBoolean(&mShouldResistFingerprinting);
602 if (NS_WARN_IF(NS_FAILED(rv))) {
603 return rv;
606 bool isFixed;
607 aStream->ReadBoolean(&isFixed);
608 if (NS_WARN_IF(NS_FAILED(rv))) {
609 return rv;
611 mState = isFixed ? eFixed : eProgressive;
613 rv = aStream->ReadBoolean(&mIsOnContentBlockingAllowList);
614 if (NS_WARN_IF(NS_FAILED(rv))) {
615 return rv;
618 rv = aStream->ReadString(mPartitionKey);
619 if (NS_WARN_IF(NS_FAILED(rv))) {
620 return rv;
623 // Deserializing the cookie permission list.
624 uint32_t cookiePermissionsLength;
625 rv = aStream->Read32(&cookiePermissionsLength);
626 if (NS_WARN_IF(NS_FAILED(rv))) {
627 return rv;
630 if (!cookiePermissionsLength) {
631 // Bailing out early because there is no cookie permission.
632 return NS_OK;
635 CookiePermissionList list;
636 mCookiePermissions.SetCapacity(cookiePermissionsLength);
637 for (uint32_t i = 0; i < cookiePermissionsLength; ++i) {
638 nsAutoCString principalJSON;
639 aStream->ReadCString(principalJSON);
640 if (NS_WARN_IF(NS_FAILED(rv))) {
641 return rv;
644 nsCOMPtr<nsIPrincipal> principal = BasePrincipal::FromJSON(principalJSON);
646 if (NS_WARN_IF(!principal)) {
647 continue;
650 uint32_t cookiePermission;
651 aStream->Read32(&cookiePermission);
652 if (NS_WARN_IF(NS_FAILED(rv))) {
653 return rv;
656 nsCOMPtr<nsIPermission> permission =
657 Permission::Create(principal, "cookie"_ns, cookiePermission, 0, 0, 0);
658 if (NS_WARN_IF(!permission)) {
659 continue;
662 list.AppendElement(permission);
665 mCookiePermissions = std::move(list);
667 return NS_OK;
670 NS_IMETHODIMP
671 CookieJarSettings::Write(nsIObjectOutputStream* aStream) {
672 nsresult rv = aStream->Write32(mCookieBehavior);
673 if (NS_WARN_IF(NS_FAILED(rv))) {
674 return rv;
677 rv = aStream->WriteBoolean(mIsFirstPartyIsolated);
678 if (NS_WARN_IF(NS_FAILED(rv))) {
679 return rv;
682 rv = aStream->WriteBoolean(mShouldResistFingerprinting);
683 if (NS_WARN_IF(NS_FAILED(rv))) {
684 return rv;
687 rv = aStream->WriteBoolean(mState == eFixed);
688 if (NS_WARN_IF(NS_FAILED(rv))) {
689 return rv;
692 rv = aStream->WriteBoolean(mIsOnContentBlockingAllowList);
693 if (NS_WARN_IF(NS_FAILED(rv))) {
694 return rv;
697 rv = aStream->WriteWStringZ(mPartitionKey.get());
698 if (NS_WARN_IF(NS_FAILED(rv))) {
699 return rv;
702 // Serializing the cookie permission list. It will first write the length of
703 // the list, and then, write the cookie permission consecutively.
704 uint32_t cookiePermissionsLength = mCookiePermissions.Length();
705 rv = aStream->Write32(cookiePermissionsLength);
706 if (NS_WARN_IF(NS_FAILED(rv))) {
707 return rv;
710 for (const RefPtr<nsIPermission>& permission : mCookiePermissions) {
711 nsCOMPtr<nsIPrincipal> principal;
712 nsresult rv = permission->GetPrincipal(getter_AddRefs(principal));
713 if (NS_WARN_IF(NS_FAILED(rv))) {
714 continue;
717 nsAutoCString principalJSON;
718 BasePrincipal::Cast(principal)->ToJSON(principalJSON);
720 rv = aStream->WriteStringZ(principalJSON.get());
721 if (NS_WARN_IF(NS_FAILED(rv))) {
722 return rv;
725 uint32_t cookiePermission = 0;
726 rv = permission->GetCapability(&cookiePermission);
727 if (NS_WARN_IF(NS_FAILED(rv))) {
728 continue;
731 rv = aStream->Write32(cookiePermission);
732 if (NS_WARN_IF(NS_FAILED(rv))) {
733 return rv;
737 return NS_OK;
740 } // namespace net
741 } // namespace mozilla