Bug 1887774 convert from MediaEnginePrefs to AudioProcessing config in AudioInputProc...
[gecko.git] / netwerk / cookie / CookieServiceChild.cpp
blob84f34a9a37ba3bc46d3de1f432cc15981aaf2357
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "Cookie.h"
7 #include "CookieCommons.h"
8 #include "CookieLogging.h"
9 #include "CookieService.h"
10 #include "mozilla/net/CookieServiceChild.h"
11 #include "ErrorList.h"
12 #include "mozilla/net/HttpChannelChild.h"
13 #include "mozilla/net/NeckoChannelParams.h"
14 #include "mozilla/LoadInfo.h"
15 #include "mozilla/BasePrincipal.h"
16 #include "mozilla/ClearOnShutdown.h"
17 #include "mozilla/dom/ContentChild.h"
18 #include "mozilla/dom/Document.h"
19 #include "mozilla/ipc/URIUtils.h"
20 #include "mozilla/net/NeckoChild.h"
21 #include "mozilla/StaticPrefs_network.h"
22 #include "mozilla/StoragePrincipalHelper.h"
23 #include "nsNetCID.h"
24 #include "nsNetUtil.h"
25 #include "nsICookieJarSettings.h"
26 #include "nsIChannel.h"
27 #include "nsIClassifiedChannel.h"
28 #include "nsIHttpChannel.h"
29 #include "nsIEffectiveTLDService.h"
30 #include "nsIURI.h"
31 #include "nsIPrefBranch.h"
32 #include "nsIWebProgressListener.h"
33 #include "nsQueryObject.h"
34 #include "nsServiceManagerUtils.h"
35 #include "mozilla/Telemetry.h"
36 #include "mozilla/TimeStamp.h"
37 #include "ThirdPartyUtil.h"
38 #include "nsIConsoleReportCollector.h"
39 #include "mozilla/dom/WindowGlobalChild.h"
41 using namespace mozilla::ipc;
43 namespace mozilla {
44 namespace net {
46 static StaticRefPtr<CookieServiceChild> gCookieChildService;
48 already_AddRefed<CookieServiceChild> CookieServiceChild::GetSingleton() {
49 if (!gCookieChildService) {
50 gCookieChildService = new CookieServiceChild();
51 gCookieChildService->Init();
52 ClearOnShutdown(&gCookieChildService);
55 return do_AddRef(gCookieChildService);
58 NS_IMPL_ISUPPORTS(CookieServiceChild, nsICookieService,
59 nsISupportsWeakReference)
61 CookieServiceChild::CookieServiceChild() { NeckoChild::InitNeckoChild(); }
63 CookieServiceChild::~CookieServiceChild() { gCookieChildService = nullptr; }
65 void CookieServiceChild::Init() {
66 auto* cc = static_cast<mozilla::dom::ContentChild*>(gNeckoChild->Manager());
67 if (cc->IsShuttingDown()) {
68 return;
71 // This corresponds to Release() in DeallocPCookieService.
72 NS_ADDREF_THIS();
74 // Create a child PCookieService actor. Don't do this in the constructor
75 // since it could release 'this' on failure
76 gNeckoChild->SendPCookieServiceConstructor(this);
78 mThirdPartyUtil = ThirdPartyUtil::GetInstance();
79 NS_ASSERTION(mThirdPartyUtil, "couldn't get ThirdPartyUtil service");
81 mTLDService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
82 NS_ASSERTION(mTLDService, "couldn't get TLDService");
85 RefPtr<GenericPromise> CookieServiceChild::TrackCookieLoad(
86 nsIChannel* aChannel) {
87 if (!CanSend()) {
88 return GenericPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE, __func__);
91 uint32_t rejectedReason = 0;
92 ThirdPartyAnalysisResult result = mThirdPartyUtil->AnalyzeChannel(
93 aChannel, true, nullptr, RequireThirdPartyCheck, &rejectedReason);
95 nsCOMPtr<nsIURI> uri;
96 aChannel->GetURI(getter_AddRefs(uri));
97 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
99 OriginAttributes attrs = loadInfo->GetOriginAttributes();
100 StoragePrincipalHelper::PrepareEffectiveStoragePrincipalOriginAttributes(
101 aChannel, attrs);
103 bool isSafeTopLevelNav = CookieCommons::IsSafeTopLevelNav(aChannel);
104 bool hadCrossSiteRedirects = false;
105 bool isSameSiteForeign =
106 CookieCommons::IsSameSiteForeign(aChannel, uri, &hadCrossSiteRedirects);
108 RefPtr<CookieServiceChild> self(this);
110 // TODO (Bug 1874174): A channel could access both unpartitioned and
111 // partitioned cookie jars. We will need to pass partitioned and unpartitioned
112 // originAttributes according the storage access.
113 nsTArray<OriginAttributes> attrsList;
114 attrsList.AppendElement(attrs);
116 return SendGetCookieList(
117 uri, result.contains(ThirdPartyAnalysis::IsForeign),
118 result.contains(ThirdPartyAnalysis::IsThirdPartyTrackingResource),
119 result.contains(
120 ThirdPartyAnalysis::IsThirdPartySocialTrackingResource),
121 result.contains(
122 ThirdPartyAnalysis::IsStorageAccessPermissionGranted),
123 rejectedReason, isSafeTopLevelNav, isSameSiteForeign,
124 hadCrossSiteRedirects, attrsList)
125 ->Then(
126 GetCurrentSerialEventTarget(), __func__,
127 [self, uri](const nsTArray<CookieStructTable>& aCookiesListTable) {
128 for (auto& entry : aCookiesListTable) {
129 auto& cookies = entry.cookies();
130 for (auto& cookieEntry : cookies) {
131 RefPtr<Cookie> cookie =
132 Cookie::Create(cookieEntry, entry.attrs());
133 cookie->SetIsHttpOnly(false);
134 self->RecordDocumentCookie(cookie, entry.attrs());
137 return GenericPromise::CreateAndResolve(true, __func__);
139 [](const mozilla::ipc::ResponseRejectReason) {
140 return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
144 IPCResult CookieServiceChild::RecvRemoveAll() {
145 mCookiesMap.Clear();
147 nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
148 if (obsService) {
149 obsService->NotifyObservers(nullptr, "content-removed-all-cookies",
150 nullptr);
152 return IPC_OK();
155 IPCResult CookieServiceChild::RecvRemoveCookie(const CookieStruct& aCookie,
156 const OriginAttributes& aAttrs) {
157 RemoveSingleCookie(aCookie, aAttrs);
159 nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
160 if (obsService) {
161 obsService->NotifyObservers(nullptr, "content-removed-cookie", nullptr);
163 return IPC_OK();
166 void CookieServiceChild::RemoveSingleCookie(const CookieStruct& aCookie,
167 const OriginAttributes& aAttrs) {
168 nsCString baseDomain;
169 CookieCommons::GetBaseDomainFromHost(mTLDService, aCookie.host(), baseDomain);
170 CookieKey key(baseDomain, aAttrs);
171 CookiesList* cookiesList = nullptr;
172 mCookiesMap.Get(key, &cookiesList);
174 if (!cookiesList) {
175 return;
178 for (uint32_t i = 0; i < cookiesList->Length(); i++) {
179 Cookie* cookie = cookiesList->ElementAt(i);
180 // bug 1858366: In the case that we are updating a stale cookie
181 // from the content process: the parent process will signal
182 // a batch deletion for the old cookie.
183 // When received by the content process we should not remove
184 // the new cookie since we have already updated the content
185 // process cookies. So we also check the expiry here.
186 if (cookie->Name().Equals(aCookie.name()) &&
187 cookie->Host().Equals(aCookie.host()) &&
188 cookie->Path().Equals(aCookie.path()) &&
189 cookie->Expiry() <= aCookie.expiry()) {
190 cookiesList->RemoveElementAt(i);
191 break;
196 IPCResult CookieServiceChild::RecvAddCookie(const CookieStruct& aCookie,
197 const OriginAttributes& aAttrs) {
198 RefPtr<Cookie> cookie = Cookie::Create(aCookie, aAttrs);
199 RecordDocumentCookie(cookie, aAttrs);
201 // signal test code to check their cookie list
202 nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
203 if (obsService) {
204 obsService->NotifyObservers(nullptr, "content-added-cookie", nullptr);
207 return IPC_OK();
210 IPCResult CookieServiceChild::RecvRemoveBatchDeletedCookies(
211 nsTArray<CookieStruct>&& aCookiesList,
212 nsTArray<OriginAttributes>&& aAttrsList) {
213 MOZ_ASSERT(aCookiesList.Length() == aAttrsList.Length());
214 for (uint32_t i = 0; i < aCookiesList.Length(); i++) {
215 CookieStruct cookieStruct = aCookiesList.ElementAt(i);
216 RemoveSingleCookie(cookieStruct, aAttrsList.ElementAt(i));
219 nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
220 if (obsService) {
221 obsService->NotifyObservers(nullptr, "content-batch-deleted-cookies",
222 nullptr);
224 return IPC_OK();
227 IPCResult CookieServiceChild::RecvTrackCookiesLoad(
228 nsTArray<CookieStructTable>&& aCookiesListTable) {
229 for (auto& entry : aCookiesListTable) {
230 for (auto& cookieEntry : entry.cookies()) {
231 RefPtr<Cookie> cookie = Cookie::Create(cookieEntry, entry.attrs());
232 cookie->SetIsHttpOnly(false);
233 RecordDocumentCookie(cookie, entry.attrs());
237 nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
238 if (obsService) {
239 obsService->NotifyObservers(nullptr, "content-track-cookies-loaded",
240 nullptr);
243 return IPC_OK();
246 uint32_t CookieServiceChild::CountCookiesFromHashTable(
247 const nsACString& aBaseDomain, const OriginAttributes& aOriginAttrs) {
248 CookiesList* cookiesList = nullptr;
250 nsCString baseDomain;
251 CookieKey key(aBaseDomain, aOriginAttrs);
252 mCookiesMap.Get(key, &cookiesList);
254 return cookiesList ? cookiesList->Length() : 0;
257 /* static */ bool CookieServiceChild::RequireThirdPartyCheck(
258 nsILoadInfo* aLoadInfo) {
259 if (!aLoadInfo) {
260 return false;
263 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
264 nsresult rv =
265 aLoadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
266 if (NS_WARN_IF(NS_FAILED(rv))) {
267 return false;
270 uint32_t cookieBehavior = cookieJarSettings->GetCookieBehavior();
271 return cookieBehavior == nsICookieService::BEHAVIOR_REJECT_FOREIGN ||
272 cookieBehavior == nsICookieService::BEHAVIOR_LIMIT_FOREIGN ||
273 cookieBehavior == nsICookieService::BEHAVIOR_REJECT_TRACKER ||
274 cookieBehavior ==
275 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN ||
276 StaticPrefs::network_cookie_thirdparty_sessionOnly() ||
277 StaticPrefs::network_cookie_thirdparty_nonsecureSessionOnly();
280 void CookieServiceChild::RecordDocumentCookie(Cookie* aCookie,
281 const OriginAttributes& aAttrs) {
282 nsAutoCString baseDomain;
283 CookieCommons::GetBaseDomainFromHost(mTLDService, aCookie->Host(),
284 baseDomain);
286 CookieKey key(baseDomain, aAttrs);
287 CookiesList* cookiesList = nullptr;
288 mCookiesMap.Get(key, &cookiesList);
290 if (!cookiesList) {
291 cookiesList = mCookiesMap.GetOrInsertNew(key);
293 for (uint32_t i = 0; i < cookiesList->Length(); i++) {
294 Cookie* cookie = cookiesList->ElementAt(i);
295 if (cookie->Name().Equals(aCookie->Name()) &&
296 cookie->Host().Equals(aCookie->Host()) &&
297 cookie->Path().Equals(aCookie->Path())) {
298 if (cookie->Value().Equals(aCookie->Value()) &&
299 cookie->Expiry() == aCookie->Expiry() &&
300 cookie->IsSecure() == aCookie->IsSecure() &&
301 cookie->SameSite() == aCookie->SameSite() &&
302 cookie->RawSameSite() == aCookie->RawSameSite() &&
303 cookie->IsSession() == aCookie->IsSession() &&
304 cookie->IsHttpOnly() == aCookie->IsHttpOnly()) {
305 cookie->SetLastAccessed(aCookie->LastAccessed());
306 return;
308 cookiesList->RemoveElementAt(i);
309 break;
313 int64_t currentTime = PR_Now() / PR_USEC_PER_SEC;
314 if (aCookie->Expiry() <= currentTime) {
315 return;
318 cookiesList->AppendElement(aCookie);
321 NS_IMETHODIMP
322 CookieServiceChild::GetCookieStringFromDocument(dom::Document* aDocument,
323 nsACString& aCookieString) {
324 NS_ENSURE_ARG(aDocument);
326 aCookieString.Truncate();
328 nsCOMPtr<nsIPrincipal> cookiePrincipal =
329 aDocument->EffectiveCookiePrincipal();
331 // TODO (Bug 1874174): A document could access both unpartitioned and
332 // partitioned cookie jars. We will need to prepare partitioned and
333 // unpartitioned principals for access both cookie jars.
334 nsTArray<nsCOMPtr<nsIPrincipal>> principals;
335 principals.AppendElement(cookiePrincipal);
337 bool thirdParty = true;
338 nsPIDOMWindowInner* innerWindow = aDocument->GetInnerWindow();
339 // in gtests we don't have a window, let's consider those requests as 3rd
340 // party.
341 if (innerWindow) {
342 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
344 if (thirdPartyUtil) {
345 Unused << thirdPartyUtil->IsThirdPartyWindow(
346 innerWindow->GetOuterWindow(), nullptr, &thirdParty);
350 for (auto& principal : principals) {
351 if (!CookieCommons::IsSchemeSupported(principal)) {
352 return NS_OK;
355 nsAutoCString baseDomain;
356 nsresult rv = CookieCommons::GetBaseDomain(principal, baseDomain);
357 if (NS_WARN_IF(NS_FAILED(rv))) {
358 return NS_OK;
361 CookieKey key(baseDomain, principal->OriginAttributesRef());
362 CookiesList* cookiesList = nullptr;
363 mCookiesMap.Get(key, &cookiesList);
365 if (!cookiesList) {
366 continue;
369 nsAutoCString hostFromURI;
370 rv = nsContentUtils::GetHostOrIPv6WithBrackets(principal, hostFromURI);
371 if (NS_WARN_IF(NS_FAILED(rv))) {
372 return NS_OK;
375 nsAutoCString pathFromURI;
376 principal->GetFilePath(pathFromURI);
378 bool isPotentiallyTrustworthy =
379 principal->GetIsOriginPotentiallyTrustworthy();
380 int64_t currentTimeInUsec = PR_Now();
381 int64_t currentTime = currentTimeInUsec / PR_USEC_PER_SEC;
383 cookiesList->Sort(CompareCookiesForSending());
384 for (uint32_t i = 0; i < cookiesList->Length(); i++) {
385 Cookie* cookie = cookiesList->ElementAt(i);
386 // check the host, since the base domain lookup is conservative.
387 if (!CookieCommons::DomainMatches(cookie, hostFromURI)) {
388 continue;
391 // We don't show HttpOnly cookies in content processes.
392 if (cookie->IsHttpOnly()) {
393 continue;
396 if (thirdParty && !CookieCommons::ShouldIncludeCrossSiteCookieForDocument(
397 cookie, aDocument)) {
398 continue;
401 // do not display the cookie if it is secure and the host scheme isn't
402 if (cookie->IsSecure() && !isPotentiallyTrustworthy) {
403 continue;
406 // if the nsIURI path doesn't match the cookie path, don't send it back
407 if (!CookieCommons::PathMatches(cookie, pathFromURI)) {
408 continue;
411 // check if the cookie has expired
412 if (cookie->Expiry() <= currentTime) {
413 continue;
416 if (!cookie->Name().IsEmpty() || !cookie->Value().IsEmpty()) {
417 if (!aCookieString.IsEmpty()) {
418 aCookieString.AppendLiteral("; ");
420 if (!cookie->Name().IsEmpty()) {
421 aCookieString.Append(cookie->Name().get());
422 aCookieString.AppendLiteral("=");
423 aCookieString.Append(cookie->Value().get());
424 } else {
425 aCookieString.Append(cookie->Value().get());
431 return NS_OK;
434 NS_IMETHODIMP
435 CookieServiceChild::GetCookieStringFromHttp(nsIURI* /*aHostURI*/,
436 nsIChannel* /*aChannel*/,
437 nsACString& /*aCookieString*/) {
438 return NS_ERROR_NOT_IMPLEMENTED;
441 NS_IMETHODIMP
442 CookieServiceChild::SetCookieStringFromDocument(
443 dom::Document* aDocument, const nsACString& aCookieString) {
444 NS_ENSURE_ARG(aDocument);
446 nsCOMPtr<nsIURI> documentURI;
447 nsAutoCString baseDomain;
448 OriginAttributes attrs;
450 // This function is executed in this context, I don't need to keep objects
451 // alive.
452 auto hasExistingCookiesLambda = [&](const nsACString& aBaseDomain,
453 const OriginAttributes& aAttrs) {
454 return !!CountCookiesFromHashTable(aBaseDomain, aAttrs);
457 RefPtr<Cookie> cookie = CookieCommons::CreateCookieFromDocument(
458 aDocument, aCookieString, PR_Now(), mTLDService, mThirdPartyUtil,
459 hasExistingCookiesLambda, getter_AddRefs(documentURI), baseDomain, attrs);
460 if (!cookie) {
461 return NS_OK;
464 bool thirdParty = true;
465 nsPIDOMWindowInner* innerWindow = aDocument->GetInnerWindow();
466 // in gtests we don't have a window, let's consider those requests as 3rd
467 // party.
468 if (innerWindow) {
469 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
471 if (thirdPartyUtil) {
472 Unused << thirdPartyUtil->IsThirdPartyWindow(
473 innerWindow->GetOuterWindow(), nullptr, &thirdParty);
477 if (thirdParty && !CookieCommons::ShouldIncludeCrossSiteCookieForDocument(
478 cookie, aDocument)) {
479 return NS_OK;
482 CookieKey key(baseDomain, attrs);
483 CookiesList* cookies = mCookiesMap.Get(key);
485 if (cookies) {
486 // We need to see if the cookie we're setting would overwrite an httponly
487 // or a secure one. This would not affect anything we send over the net
488 // (those come from the parent, which already checks this),
489 // but script could see an inconsistent view of things.
491 nsCOMPtr<nsIPrincipal> principal = aDocument->EffectiveCookiePrincipal();
492 bool isPotentiallyTrustworthy =
493 principal->GetIsOriginPotentiallyTrustworthy();
495 for (uint32_t i = 0; i < cookies->Length(); ++i) {
496 RefPtr<Cookie> existingCookie = cookies->ElementAt(i);
497 if (existingCookie->Name().Equals(cookie->Name()) &&
498 existingCookie->Host().Equals(cookie->Host()) &&
499 existingCookie->Path().Equals(cookie->Path())) {
500 // Can't overwrite an httponly cookie from a script context.
501 if (existingCookie->IsHttpOnly()) {
502 return NS_OK;
505 // prevent insecure cookie from overwriting a secure one in insecure
506 // context.
507 if (existingCookie->IsSecure() && !isPotentiallyTrustworthy) {
508 return NS_OK;
514 RecordDocumentCookie(cookie, attrs);
516 if (CanSend()) {
517 nsTArray<CookieStruct> cookiesToSend;
518 cookiesToSend.AppendElement(cookie->ToIPC());
520 // Asynchronously call the parent.
521 dom::WindowGlobalChild* windowGlobalChild =
522 aDocument->GetWindowGlobalChild();
524 // If there is no WindowGlobalChild fall back to PCookieService SetCookies.
525 if (NS_WARN_IF(!windowGlobalChild)) {
526 SendSetCookies(baseDomain, attrs, documentURI, false, cookiesToSend);
527 return NS_OK;
529 windowGlobalChild->SendSetCookies(baseDomain, attrs, documentURI, false,
530 cookiesToSend);
533 return NS_OK;
536 NS_IMETHODIMP
537 CookieServiceChild::SetCookieStringFromHttp(nsIURI* aHostURI,
538 const nsACString& aCookieString,
539 nsIChannel* aChannel) {
540 NS_ENSURE_ARG(aHostURI);
541 NS_ENSURE_ARG(aChannel);
543 if (!CookieCommons::IsSchemeSupported(aHostURI)) {
544 return NS_OK;
547 // Fast past: don't bother sending IPC messages about nullprincipal'd
548 // documents.
549 nsAutoCString scheme;
550 aHostURI->GetScheme(scheme);
551 if (scheme.EqualsLiteral("moz-nullprincipal")) {
552 return NS_OK;
555 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
557 uint32_t rejectedReason = 0;
558 ThirdPartyAnalysisResult result = mThirdPartyUtil->AnalyzeChannel(
559 aChannel, false, aHostURI, RequireThirdPartyCheck, &rejectedReason);
561 nsCString cookieString(aCookieString);
563 OriginAttributes attrs = loadInfo->GetOriginAttributes();
564 StoragePrincipalHelper::PrepareEffectiveStoragePrincipalOriginAttributes(
565 aChannel, attrs);
567 bool requireHostMatch;
568 nsCString baseDomain;
569 CookieCommons::GetBaseDomain(mTLDService, aHostURI, baseDomain,
570 requireHostMatch);
572 nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
573 CookieCommons::GetCookieJarSettings(aChannel);
575 nsCOMPtr<nsIConsoleReportCollector> crc = do_QueryInterface(aChannel);
577 CookieStatus cookieStatus = CookieService::CheckPrefs(
578 crc, cookieJarSettings, aHostURI,
579 result.contains(ThirdPartyAnalysis::IsForeign),
580 result.contains(ThirdPartyAnalysis::IsThirdPartyTrackingResource),
581 result.contains(ThirdPartyAnalysis::IsThirdPartySocialTrackingResource),
582 result.contains(ThirdPartyAnalysis::IsStorageAccessPermissionGranted),
583 aCookieString, CountCookiesFromHashTable(baseDomain, attrs), attrs,
584 &rejectedReason);
586 if (cookieStatus != STATUS_ACCEPTED &&
587 cookieStatus != STATUS_ACCEPT_SESSION) {
588 return NS_OK;
591 CookieKey key(baseDomain, attrs);
593 nsTArray<CookieStruct> cookiesToSend;
595 int64_t currentTimeInUsec = PR_Now();
597 bool addonAllowsLoad = false;
598 nsCOMPtr<nsIURI> finalChannelURI;
599 NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalChannelURI));
600 addonAllowsLoad = BasePrincipal::Cast(loadInfo->TriggeringPrincipal())
601 ->AddonAllowsLoad(finalChannelURI);
603 bool isForeignAndNotAddon = false;
604 if (!addonAllowsLoad) {
605 mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI,
606 &isForeignAndNotAddon);
609 bool mustBePartitioned =
610 isForeignAndNotAddon &&
611 cookieJarSettings->GetCookieBehavior() ==
612 nsICookieService::BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN &&
613 !result.contains(ThirdPartyAnalysis::IsStorageAccessPermissionGranted);
615 bool moreCookies;
616 do {
617 CookieStruct cookieData;
618 bool canSetCookie = false;
619 moreCookies = CookieService::CanSetCookie(
620 aHostURI, baseDomain, cookieData, requireHostMatch, cookieStatus,
621 cookieString, true, isForeignAndNotAddon, mustBePartitioned, crc,
622 canSetCookie);
623 if (!canSetCookie) {
624 continue;
627 // check permissions from site permission list.
628 if (!CookieCommons::CheckCookiePermission(aChannel, cookieData)) {
629 COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieString,
630 "cookie rejected by permission manager");
631 constexpr auto CONSOLE_REJECTION_CATEGORY = "cookiesRejection"_ns;
632 CookieLogging::LogMessageToConsole(
633 crc, aHostURI, nsIScriptError::warningFlag,
634 CONSOLE_REJECTION_CATEGORY, "CookieRejectedByPermissionManager"_ns,
635 AutoTArray<nsString, 1>{
636 NS_ConvertUTF8toUTF16(cookieData.name()),
638 CookieCommons::NotifyRejected(
639 aHostURI, aChannel,
640 nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION,
641 OPERATION_WRITE);
642 continue;
645 RefPtr<Cookie> cookie = Cookie::Create(cookieData, attrs);
646 MOZ_ASSERT(cookie);
648 cookie->SetLastAccessed(currentTimeInUsec);
649 cookie->SetCreationTime(
650 Cookie::GenerateUniqueCreationTime(currentTimeInUsec));
652 RecordDocumentCookie(cookie, attrs);
653 cookiesToSend.AppendElement(cookieData);
654 } while (moreCookies);
656 // Asynchronously call the parent.
657 if (CanSend() && !cookiesToSend.IsEmpty()) {
658 RefPtr<HttpChannelChild> httpChannelChild = do_QueryObject(aChannel);
659 MOZ_ASSERT(httpChannelChild);
660 httpChannelChild->SendSetCookies(baseDomain, attrs, aHostURI, true,
661 cookiesToSend);
664 return NS_OK;
667 NS_IMETHODIMP
668 CookieServiceChild::RunInTransaction(
669 nsICookieTransactionCallback* /*aCallback*/) {
670 return NS_ERROR_NOT_IMPLEMENTED;
673 } // namespace net
674 } // namespace mozilla