blob: b389dfb7f5c2a08ccfbab6a08003ff57f5aa6b81 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2020 The Chromium Authors
Alexander Timin1cc31f42020-05-12 16:26:012// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
danakjc492bf82020-09-09 20:02:445#include "content/browser/renderer_host/cookie_utils.h"
Alexander Timin1cc31f42020-05-12 16:26:016
Peter Kasting1557e5f2025-01-28 01:14:087#include <algorithm>
Sandor Major7c3e612f2023-12-01 20:48:088#include <cstddef>
9#include <ostream>
10#include <string>
11
12#include "base/feature_list.h"
13#include "base/logging.h"
sbingler8e26e212023-09-27 23:23:2714#include "base/strings/string_util.h"
Shuran Huang7a6757c22024-04-17 15:17:3915#include "base/unguessable_token.h"
Alexander Timin1cc31f42020-05-12 16:26:0116#include "content/browser/devtools/devtools_instrumentation.h"
Sandor Major7c3e612f2023-12-01 20:48:0817#include "content/browser/navigation_or_document_handle.h"
18#include "content/browser/renderer_host/navigation_request.h"
danakjc492bf82020-09-09 20:02:4419#include "content/browser/renderer_host/render_frame_host_impl.h"
Alexander Timin1cc31f42020-05-12 16:26:0120#include "content/public/browser/browser_context.h"
21#include "content/public/browser/cookie_access_details.h"
Sandor Major7c3e612f2023-12-01 20:48:0822#include "content/public/browser/legacy_tech_cookie_issue_details.h"
Alexander Timin1cc31f42020-05-12 16:26:0123#include "content/public/common/content_client.h"
Sandor Major7c3e612f2023-12-01 20:48:0824#include "content/public/common/content_features.h"
Jihwan Marc Kim3e132f12020-05-20 17:33:1925#include "net/cookies/cookie_inclusion_status.h"
sbingler870b63f2023-04-25 16:47:5826#include "services/metrics/public/cpp/metrics_utils.h"
Alexander Timin1cc31f42020-05-12 16:26:0127#include "services/metrics/public/cpp/ukm_builders.h"
Sandor Major7c3e612f2023-12-01 20:48:0828#include "url/gurl.h"
Alexander Timin1cc31f42020-05-12 16:26:0129
30namespace content {
31
32namespace {
33
sbingler8e26e212023-09-27 23:23:2734void PotentiallyRecordNonAsciiCookieNameValue(
35 RenderFrameHost* rfh,
36 CookieAccessDetails::Type access_type,
37 const std::string& name,
38 const std::string& value) {
39 CHECK(rfh);
40
41 if (access_type != CookieAccessDetails::Type::kChange) {
42 return;
43 }
44
45 // Our data collection policy disallows collecting UKMs while prerendering.
46 // See //content/browser/preloading/prerender/README.md and ask the team to
47 // explore options to record data for prerendering pages if we need to
48 // support the case.
49 if (rfh->IsInLifecycleState(RenderFrameHost::LifecycleState::kPrerendering)) {
50 return;
51 }
52
53 bool name_has_non_ascii = !base::IsStringASCII(name);
54 bool value_has_non_ascii = !base::IsStringASCII(value);
55
56 if (name_has_non_ascii || value_has_non_ascii) {
57 ukm::SourceId source_id = rfh->GetPageUkmSourceId();
58
59 auto event = ukm::builders::CookieHasNonAsciiCharacter(source_id);
60
61 // The event itself is what we're interested in, the value of "true" here
62 // can be ignored.
63 if (name_has_non_ascii) {
64 event.SetName(true);
65 }
66
67 if (value_has_non_ascii) {
68 event.SetValue(true);
69 }
70
71 event.Record(ukm::UkmRecorder::Get());
72 }
73}
74
amarjotgilld43eb5d12024-11-11 17:53:3675void PotentiallyRecordCookieOriginMismatch(
76 RenderFrameHost* rfh,
77 CookieAccessDetails::Type access_type,
78 const net::CookieInclusionStatus& status) {
79 CHECK(rfh);
80
81 if (access_type != CookieAccessDetails::Type::kRead) {
82 return;
83 }
84
85 // Our data collection policy disallows collecting UKMs while prerendering.
86 // See //content/browser/preloading/prerender/README.md and ask the team to
87 // explore options to record data for prerendering pages if we need to
88 // support the case.
89 if (rfh->IsInLifecycleState(RenderFrameHost::LifecycleState::kPrerendering)) {
90 return;
91 }
92 const bool port_mismatch =
Chris Fredrickson66f167f2025-01-21 18:18:2093 status.HasWarningReason(
94 net::CookieInclusionStatus::WarningReason::WARN_PORT_MISMATCH) ||
amarjotgilld43eb5d12024-11-11 17:53:3695 status.HasExclusionReason(
Chris Fredrickson0a9673e2025-01-21 16:45:1496 net::CookieInclusionStatus::ExclusionReason::EXCLUDE_PORT_MISMATCH);
amarjotgilld43eb5d12024-11-11 17:53:3697
98 const bool scheme_mismatch =
99 status.HasWarningReason(
Chris Fredrickson66f167f2025-01-21 18:18:20100 net::CookieInclusionStatus::WarningReason::WARN_SCHEME_MISMATCH) ||
amarjotgilld43eb5d12024-11-11 17:53:36101 status.HasExclusionReason(
Chris Fredrickson0a9673e2025-01-21 16:45:14102 net::CookieInclusionStatus::ExclusionReason::EXCLUDE_SCHEME_MISMATCH);
amarjotgilld43eb5d12024-11-11 17:53:36103
104 if (port_mismatch || scheme_mismatch) {
105 ukm::SourceId source_id = rfh->GetPageUkmSourceId();
106
107 auto event = ukm::builders::Cookies_Blocked_DueToOriginMismatch(source_id);
108
109 // The event itself is what we're interested in, the value of "true" here
110 // can be ignored.
111 if (port_mismatch) {
112 event.SetPortMismatch(true);
113 }
114
115 if (scheme_mismatch) {
116 event.SetSchemeMismatch(true);
117 }
118
119 event.Record(ukm::UkmRecorder::Get());
120 }
121}
122
selya19cc0d22024-12-10 20:36:07123void RecordCookiesExemptedByTopLevelStorage(ukm::SourceId source_id,
124 int affected_cookies_in_request) {
125 ukm::builders::RequestStorageAccessFor_TopLevelStorageIsExemptionReason(
126 source_id)
127 .SetNumberOfCookies(ukm::GetExponentialBucketMin(
128 affected_cookies_in_request, /*bucket_spacing=*/2.0))
129 .Record(ukm::UkmRecorder::Get());
130}
131
selya7d96d6182024-04-22 11:35:51132// Relies on checks in RecordPartitionedCookiesUKMs to confirm that that the
133// cookie name is not "receive-cookie-deprecation", that cookie is first party
134// partitioned and the RenderFrameHost is not prerendering.
selya778265bc2023-10-23 14:37:55135void RecordFirstPartyPartitionedCookieCrossSiteContextUKM(
136 RenderFrameHostImpl* render_frame_host_impl,
selya7d96d6182024-04-22 11:35:51137 const net::CanonicalCookie& cookie,
138 const ukm::SourceId& source_id) {
selya778265bc2023-10-23 14:37:55139 // Same-site embed with cross-site ancestors (ABA embeds) have a null site
140 // for cookies since it is a cross-site context. If the result of
141 // ComputeSiteForCookies is first-party that means we are not in an ABA
142 // embedded context.
selya01be4aa22024-01-25 18:36:24143 bool has_cross_site_ancestor =
144 !render_frame_host_impl->ComputeSiteForCookies().IsFirstParty(
selya778265bc2023-10-23 14:37:55145 GURL(base::StrCat({url::kHttpsScheme, url::kStandardSchemeSeparator,
selya01be4aa22024-01-25 18:36:24146 cookie.DomainWithoutDot()})));
selya778265bc2023-10-23 14:37:55147
selya7d96d6182024-04-22 11:35:51148 ukm::builders::Cookies_FirstPartyPartitionedInCrossSiteContextV3(source_id)
selya01be4aa22024-01-25 18:36:24149 .SetCookiePresent(has_cross_site_ancestor)
selya778265bc2023-10-23 14:37:55150 .Record(ukm::UkmRecorder::Get());
151}
152
selya7d96d6182024-04-22 11:35:51153// Relies on checks in RecordPartitionedCookiesUKMs to confirm that that the
154// cookie is partitioned, the cookie name is not
155// "receive-cookie-deprecation" and the RenderFrameHost is not prerendering.
156void RecordPartitionedCookieUseV2UKM(RenderFrameHost* rfh,
157 const net::CanonicalCookie& cookie,
158 const ukm::SourceId& source_id) {
159 ukm::builders::PartitionedCookiePresentV2(source_id)
160 .SetPartitionedCookiePresentV2(true)
161 .Record(ukm::UkmRecorder::Get());
162}
163
164void RecordPartitionedCookiesUKMs(RenderFrameHostImpl* render_frame_host_impl,
165 const net::CanonicalCookie& cookie) {
selya27d093e2023-08-02 22:20:00166 // Our data collection policy disallows collecting UKMs while prerendering.
167 // See //content/browser/preloading/prerender/README.md and ask the team to
168 // explore options to record data for prerendering pages if we need to
169 // support the case.
selya7d96d6182024-04-22 11:35:51170 if (render_frame_host_impl->IsInLifecycleState(
171 RenderFrameHost::LifecycleState::kPrerendering)) {
selya27d093e2023-08-02 22:20:00172 return;
173 }
selya27d093e2023-08-02 22:20:00174
selya7d96d6182024-04-22 11:35:51175 // Cookies_FirstPartyPartitionedInCrossSiteContextV3 and
176 // PartitionedCookiePresentV2 both measure cookies
177 // without the name of 'receive-cookie-deprecation'. Return here to ensure
178 // that the metrics do not include those cookies.
179 if (cookie.Name() == "receive-cookie-deprecation") {
180 return;
181 }
182
183 ukm::SourceId source_id = render_frame_host_impl->GetPageUkmSourceId();
184
185 if (cookie.IsFirstPartyPartitioned()) {
186 RecordFirstPartyPartitionedCookieCrossSiteContextUKM(render_frame_host_impl,
187 cookie, source_id);
188 }
189
190 RecordPartitionedCookieUseV2UKM(render_frame_host_impl, cookie, source_id);
selya27d093e2023-08-02 22:20:00191}
192
sbingler870b63f2023-04-25 16:47:58193void RecordRedirectContextDowngradeUKM(RenderFrameHost* rfh,
194 CookieAccessDetails::Type access_type,
195 const net::CanonicalCookie& cookie,
196 const GURL& url) {
197 CHECK(rfh);
Takashi Toyoshimad540b932023-06-30 02:30:27198
199 // Our data collection policy disallows collecting UKMs while prerendering.
200 // See //content/browser/preloading/prerender/README.md and ask the team to
201 // explore options to record data for prerendering pages if we need to
202 // support the case.
203 if (rfh->IsInLifecycleState(RenderFrameHost::LifecycleState::kPrerendering)) {
204 return;
205 }
206
sbingler870b63f2023-04-25 16:47:58207 ukm::SourceId source_id = rfh->GetPageUkmSourceId();
208
209 int64_t samesite_value = static_cast<int64_t>(cookie.SameSite());
210 if (access_type == CookieAccessDetails::Type::kRead) {
211 base::TimeDelta cookie_age = base::Time::Now() - cookie.CreationDate();
212
213 ukm::builders::SamesiteRedirectContextDowngrade(source_id)
214 .SetSamesiteValueReadPerCookie(samesite_value)
215 .SetAgePerCookie(
216 ukm::GetExponentialBucketMinForUserTiming(cookie_age.InMinutes()))
217 .Record(ukm::UkmRecorder::Get());
218 } else {
219 CHECK(access_type == CookieAccessDetails::Type::kChange);
220 ukm::builders::SamesiteRedirectContextDowngrade(source_id)
221 .SetSamesiteValueWritePerCookie(samesite_value)
222 .Record(ukm::UkmRecorder::Get());
223 }
224}
225
226void RecordSchemefulContextDowngradeUKM(
227 RenderFrameHost* rfh,
228 CookieAccessDetails::Type access_type,
229 const net::CookieInclusionStatus& status,
230 const GURL& url) {
231 CHECK(rfh);
Takashi Toyoshimad540b932023-06-30 02:30:27232
233 // Our data collection policy disallows collecting UKMs while prerendering.
234 // See //content/browser/preloading/prerender/README.md and ask the team to
235 // explore options to record data for prerendering pages if we need to
236 // support the case.
237 if (rfh->IsInLifecycleState(RenderFrameHost::LifecycleState::kPrerendering)) {
238 return;
239 }
240
Alexander Timin1cc31f42020-05-12 16:26:01241 ukm::SourceId source_id = rfh->GetPageUkmSourceId();
242
Lei Zhang3ab30192022-08-15 19:52:20243 auto downgrade_metric =
244 static_cast<int64_t>(status.GetBreakingDowngradeMetricsEnumValue(url));
Alexander Timin1cc31f42020-05-12 16:26:01245 if (access_type == CookieAccessDetails::Type::kRead) {
246 ukm::builders::SchemefulSameSiteContextDowngrade(source_id)
Lei Zhang3ab30192022-08-15 19:52:20247 .SetRequestPerCookie(downgrade_metric)
Alexander Timin1cc31f42020-05-12 16:26:01248 .Record(ukm::UkmRecorder::Get());
249 } else {
sbingler870b63f2023-04-25 16:47:58250 CHECK(access_type == CookieAccessDetails::Type::kChange);
Alexander Timin1cc31f42020-05-12 16:26:01251 ukm::builders::SchemefulSameSiteContextDowngrade(source_id)
Lei Zhang3ab30192022-08-15 19:52:20252 .SetResponsePerCookie(downgrade_metric)
Alexander Timin1cc31f42020-05-12 16:26:01253 .Record(ukm::UkmRecorder::Get());
254 }
255}
256
Simon Zünd657178e2021-05-27 06:19:55257bool ShouldReportDevToolsIssueForStatus(
258 const net::CookieInclusionStatus& status) {
259 return status.ShouldWarn() ||
Chris Fredrickson0a9673e2025-01-21 16:45:14260 status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
261 EXCLUDE_DOMAIN_NON_ASCII) ||
262 status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
263 EXCLUDE_PORT_MISMATCH) ||
264 status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
265 EXCLUDE_SCHEME_MISMATCH) ||
Simon Zünd657178e2021-05-27 06:19:55266 status.HasExclusionReason(
Chris Fredrickson0a9673e2025-01-21 16:45:14267 net::CookieInclusionStatus::ExclusionReason::
Shuran Huangdc0b8d82023-09-19 14:49:30268 EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET) ||
Chris Fredrickson0a9673e2025-01-21 16:45:14269 status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
270 EXCLUDE_THIRD_PARTY_PHASEOUT) ||
Joshua Thomas48f0eea2024-09-17 02:25:52271 status.exemption_reason() ==
272 net::CookieInclusionStatus::ExemptionReason::k3PCDMetadata ||
273 status.exemption_reason() ==
274 net::CookieInclusionStatus::ExemptionReason::k3PCDHeuristics;
Simon Zünd657178e2021-05-27 06:19:55275}
276
Sandor Major77742112025-01-14 18:36:11277} // namespace
278
279void SplitCookiesIntoAllowedAndBlocked(
280 const network::mojom::CookieAccessDetailsPtr& cookie_details,
Ryan Tarpine60f087a92025-03-10 14:46:59281 CookieAccessDetails::Source source,
Sandor Major77742112025-01-14 18:36:11282 CookieAccessDetails* allowed,
283 CookieAccessDetails* blocked) {
284 // For some cases `site_for_cookies` representative url is empty when
285 // OnCookieAccess is triggered for a third party. For example iframe third
286 // party accesses cookies when TPCD Metadata allows third party cookie access.
287 //
288 // Make `first_party_url` considering both `top_frame_origin` and
289 // `site_for_cookies` which is similar with GetFirstPartyURL() in
290 // components/content_settings/core/common/cookie_settings_base.h.
291 // If the `top_frame_origin` is non-opaque, it is chosen; otherwise, the
292 // `site_for_cookies` representative url is used.
293 const GURL first_party_url =
294 cookie_details->top_frame_origin.opaque()
295 ? cookie_details->site_for_cookies.RepresentativeUrl()
296 : cookie_details->top_frame_origin.GetURL();
297
298 *allowed = CookieAccessDetails({cookie_details->type,
299 cookie_details->url,
300 first_party_url,
301 {},
302 /* blocked_by_policy=*/false,
303 cookie_details->is_ad_tagged,
304 cookie_details->cookie_setting_overrides,
Ryan Tarpine60f087a92025-03-10 14:46:59305 cookie_details->site_for_cookies,
306 source});
Peter Kasting1557e5f2025-01-28 01:14:08307 int allowed_count = std::ranges::count_if(
Sandor Major77742112025-01-14 18:36:11308 cookie_details->cookie_list,
309 [](const network::mojom::CookieOrLineWithAccessResultPtr&
310 cookie_and_access_result) {
311 // "Included" cookies have no exclusion reasons so we don't also have to
Chris Fredrickson0a9673e2025-01-21 16:45:14312 // check for
313 // !(net::CookieInclusionStatus::ExclusionReason::EXCLUDE_USER_PREFERENCES).
Sandor Major77742112025-01-14 18:36:11314 return cookie_and_access_result->access_result.status.IsInclude();
315 });
316 allowed->cookie_access_result_list.reserve(allowed_count);
317
318 *blocked = CookieAccessDetails({cookie_details->type,
319 cookie_details->url,
320 first_party_url,
321 {},
322 /* blocked_by_policy=*/true,
323 cookie_details->is_ad_tagged,
324 cookie_details->cookie_setting_overrides,
Ryan Tarpine60f087a92025-03-10 14:46:59325 cookie_details->site_for_cookies,
326 source});
Peter Kasting1557e5f2025-01-28 01:14:08327 int blocked_count = std::ranges::count_if(
Sandor Major77742112025-01-14 18:36:11328 cookie_details->cookie_list,
329 [](const network::mojom::CookieOrLineWithAccessResultPtr&
330 cookie_and_access_result) {
331 return cookie_and_access_result->access_result.status
332 .ExcludedByUserPreferencesOrTPCD();
333 });
334 blocked->cookie_access_result_list.reserve(blocked_count);
335
336 for (const auto& cookie_and_access_result : cookie_details->cookie_list) {
337 if (cookie_and_access_result->access_result.status
338 .ExcludedByUserPreferencesOrTPCD()) {
339 blocked->cookie_access_result_list.emplace_back(
340 std::move(cookie_and_access_result->cookie_or_line->get_cookie()),
341 cookie_and_access_result->access_result);
342 } else if (cookie_and_access_result->access_result.status.IsInclude()) {
343 allowed->cookie_access_result_list.emplace_back(
344 std::move(cookie_and_access_result->cookie_or_line->get_cookie()),
345 cookie_and_access_result->access_result);
346 }
347 }
Sandor Major7c3e612f2023-12-01 20:48:08348}
Sandor Major7c3e612f2023-12-01 20:48:08349
350// Logs cookie issues to DevTools Issues Panel and logs events to UseCounters
Shuran Huang8fa11c72023-12-04 16:53:44351// and UKM for a single cookie-accessed event.
Alison Gale770f3fc2024-04-27 00:39:58352// TODO(crbug.com/40632967): Remove when no longer needed.
Sandor Major77742112025-01-14 18:36:11353void EmitCookieWarningsAndMetrics(
Alexander Timin1cc31f42020-05-12 16:26:01354 RenderFrameHostImpl* rfh,
355 const network::mojom::CookieAccessDetailsPtr& cookie_details) {
356 RenderFrameHostImpl* root_frame_host = rfh->GetMainFrame();
357
Sreeja Kamishettye49854f82021-06-02 00:52:03358 if (!root_frame_host->IsActive())
Alexander Timin1cc31f42020-05-12 16:26:01359 return;
360
361 bool samesite_treated_as_lax_cookies = false;
362 bool samesite_none_insecure_cookies = false;
Alexander Timin1cc31f42020-05-12 16:26:01363 bool breaking_context_downgrade = false;
Lily Chenc4423c02021-03-11 16:02:02364 bool lax_allow_unsafe_cookies = false;
Alexander Timin1cc31f42020-05-12 16:26:01365
Lily Chen2db3a422021-07-20 18:02:25366 bool samesite_cookie_inclusion_changed_by_cross_site_redirect = false;
367
Dylan Cutler8d5f8912022-03-04 17:39:19368 bool partitioned_cookies_exist = false;
369
Ari Chivukula5f21c112022-04-26 19:23:34370 bool cookie_has_not_been_refreshed_in_201_to_300_days = false;
371 bool cookie_has_not_been_refreshed_in_301_to_350_days = false;
372 bool cookie_has_not_been_refreshed_in_351_to_400_days = false;
373
Johann Hofmanne5764d12022-07-13 23:06:28374 bool cookie_has_domain_non_ascii = false;
375
selya19cc0d22024-12-10 20:36:07376 int cookies_exempted_by_top_level_storage_access = 0;
377
cfredric76b2d222021-01-27 20:12:04378 for (const network::mojom::CookieOrLineWithAccessResultPtr& cookie :
Alexander Timin1cc31f42020-05-12 16:26:01379 cookie_details->cookie_list) {
Johann Hofmann975c0b42022-08-02 21:05:51380 const net::CookieInclusionStatus& status = cookie->access_result.status;
381 if (ShouldReportDevToolsIssueForStatus(status)) {
Shuran Huang7a6757c22024-04-17 15:17:39382 std::optional<std::string> devtools_issue_id;
383 if (status.HasExclusionReason(
Chris Fredrickson0a9673e2025-01-21 16:45:14384 net::CookieInclusionStatus::ExclusionReason::
385 EXCLUDE_THIRD_PARTY_PHASEOUT) ||
Chris Fredrickson66f167f2025-01-21 18:18:20386 status.HasWarningReason(net::CookieInclusionStatus::WarningReason::
387 WARN_THIRD_PARTY_PHASEOUT)) {
Shuran Huang7a6757c22024-04-17 15:17:39388 devtools_issue_id = base::UnguessableToken::Create().ToString();
389 }
Juba Borgohainc93969e2022-02-25 21:56:12390 devtools_instrumentation::ReportCookieIssue(
Simon Zünd657178e2021-05-27 06:19:55391 root_frame_host, cookie, cookie_details->url,
392 cookie_details->site_for_cookies,
393 cookie_details->type == CookieAccessDetails::Type::kRead
Juba Borgohainc93969e2022-02-25 21:56:12394 ? blink::mojom::CookieOperation::kReadCookie
395 : blink::mojom::CookieOperation::kSetCookie,
Shuran Huang7a6757c22024-04-17 15:17:39396 cookie_details->devtools_request_id, devtools_issue_id);
Shuran Huang8fa11c72023-12-04 16:53:44397 }
398
cfredric76b2d222021-01-27 20:12:04399 if (cookie->access_result.status.ShouldWarn()) {
Lily Chen9de4065b2020-06-24 20:18:47400 samesite_treated_as_lax_cookies =
401 samesite_treated_as_lax_cookies ||
cfredrica5fb0982021-01-09 00:18:01402 status.HasWarningReason(
Chris Fredrickson66f167f2025-01-21 18:18:20403 net::CookieInclusionStatus::WarningReason::
Lily Chen9de4065b2020-06-24 20:18:47404 WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT) ||
cfredrica5fb0982021-01-09 00:18:01405 status.HasWarningReason(
Chris Fredrickson66f167f2025-01-21 18:18:20406 net::CookieInclusionStatus::WarningReason::
Lily Chen9de4065b2020-06-24 20:18:47407 WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE);
Alexander Timin1cc31f42020-05-12 16:26:01408
Lily Chen9de4065b2020-06-24 20:18:47409 samesite_none_insecure_cookies =
410 samesite_none_insecure_cookies ||
Chris Fredrickson66f167f2025-01-21 18:18:20411 status.HasWarningReason(net::CookieInclusionStatus::WarningReason::
412 WARN_SAMESITE_NONE_INSECURE);
Lily Chen9de4065b2020-06-24 20:18:47413
Lily Chenc4423c02021-03-11 16:02:02414 lax_allow_unsafe_cookies =
415 lax_allow_unsafe_cookies ||
416 status.HasWarningReason(
Chris Fredrickson66f167f2025-01-21 18:18:20417 net::CookieInclusionStatus::WarningReason::
Lily Chenc4423c02021-03-11 16:02:02418 WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE);
419
Lily Chen2db3a422021-07-20 18:02:25420 samesite_cookie_inclusion_changed_by_cross_site_redirect =
421 samesite_cookie_inclusion_changed_by_cross_site_redirect ||
422 status.HasWarningReason(
Chris Fredrickson66f167f2025-01-21 18:18:20423 net::CookieInclusionStatus::WarningReason::
Lily Chen2db3a422021-07-20 18:02:25424 WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION);
Alexander Timin1cc31f42020-05-12 16:26:01425 }
Alexander Timin1cc31f42020-05-12 16:26:01426
Johann Hofmann975c0b42022-08-02 21:05:51427 cookie_has_domain_non_ascii =
428 cookie_has_domain_non_ascii ||
429 status.HasWarningReason(
Chris Fredrickson66f167f2025-01-21 18:18:20430 net::CookieInclusionStatus::WarningReason::WARN_DOMAIN_NON_ASCII) ||
Chris Fredrickson0a9673e2025-01-21 16:45:14431 status.HasExclusionReason(net::CookieInclusionStatus::ExclusionReason::
432 EXCLUDE_DOMAIN_NON_ASCII);
Johann Hofmann975c0b42022-08-02 21:05:51433
Dylan Cutler8d5f8912022-03-04 17:39:19434 partitioned_cookies_exist =
435 partitioned_cookies_exist ||
436 (cookie->cookie_or_line->is_cookie() &&
Dylan Cutler051411b42022-07-12 22:20:07437 cookie->cookie_or_line->get_cookie().IsPartitioned() &&
438 // Ignore nonced partition keys since this metric is meant to track
439 // usage of the Partitioned attribute.
440 !cookie->cookie_or_line->get_cookie().PartitionKey()->nonce());
Dylan Cutler8d5f8912022-03-04 17:39:19441
selya27d093e2023-08-02 22:20:00442
selya778265bc2023-10-23 14:37:55443 if (partitioned_cookies_exist) {
selya7d96d6182024-04-22 11:35:51444 RecordPartitionedCookiesUKMs(rfh, cookie->cookie_or_line->get_cookie());
selya778265bc2023-10-23 14:37:55445 }
446
selya19cc0d22024-12-10 20:36:07447 if (cookie->access_result.status.exemption_reason() ==
448 net::CookieInclusionStatus::ExemptionReason::kTopLevelStorageAccess) {
449 cookies_exempted_by_top_level_storage_access++;
450 }
451
Ayu Ishii2e3998902020-07-14 18:22:30452 breaking_context_downgrade =
453 breaking_context_downgrade ||
sbingler870b63f2023-04-25 16:47:58454 cookie->access_result.status.HasSchemefulDowngradeWarning();
Alexander Timin1cc31f42020-05-12 16:26:01455
sbingler870b63f2023-04-25 16:47:58456 if (cookie->access_result.status.HasSchemefulDowngradeWarning()) {
457 // Unlike with UMA, do not record cookies that have no schemeful downgrade
458 // warning.
459 RecordSchemefulContextDowngradeUKM(rfh, cookie_details->type,
460 cookie->access_result.status,
461 cookie_details->url);
462 }
463
464 if (status.HasWarningReason(
Chris Fredrickson66f167f2025-01-21 18:18:20465 net::CookieInclusionStatus::WarningReason::
sbingler870b63f2023-04-25 16:47:58466 WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION) &&
467 cookie->cookie_or_line->is_cookie()) {
468 RecordRedirectContextDowngradeUKM(rfh, cookie_details->type,
469 cookie->cookie_or_line->get_cookie(),
470 cookie_details->url);
Alexander Timin1cc31f42020-05-12 16:26:01471 }
Ari Chivukula5f21c112022-04-26 19:23:34472
sbingler8e26e212023-09-27 23:23:27473 if (cookie->cookie_or_line->is_cookie()) {
474 PotentiallyRecordNonAsciiCookieNameValue(
475 rfh, cookie_details->type,
476 cookie->cookie_or_line->get_cookie().Name(),
477 cookie->cookie_or_line->get_cookie().Value());
478 }
479
amarjotgilld43eb5d12024-11-11 17:53:36480 PotentiallyRecordCookieOriginMismatch(rfh, cookie_details->type, status);
481
Ari Chivukula5f21c112022-04-26 19:23:34482 // In order to anticipate the potential effects of the expiry limit in
483 // rfc6265bis, we need to check how long it's been since the cookie was
484 // refreshed (if LastUpdateDate is populated). These three buckets were
485 // picked so we could engage sites with some granularity around urgency.
486 // We ignore the space under 200 days as these cookies are not at risk
487 // of expiring and we ignore the space over 400 days as these cookies
488 // have already expired. Metrics will take 200 days from M103 to populate.
489 base::Time last_update_date =
490 cookie->cookie_or_line->is_cookie()
491 ? cookie->cookie_or_line->get_cookie().LastUpdateDate()
492 : base::Time();
493 if (!last_update_date.is_null()) {
494 int days_since_refresh = (base::Time::Now() - last_update_date).InDays();
495 cookie_has_not_been_refreshed_in_201_to_300_days |=
496 days_since_refresh > 200 && days_since_refresh <= 300;
497 cookie_has_not_been_refreshed_in_301_to_350_days |=
498 days_since_refresh > 300 && days_since_refresh <= 350;
499 cookie_has_not_been_refreshed_in_351_to_400_days |=
500 days_since_refresh > 350 && days_since_refresh <= 400;
501 }
Alexander Timin1cc31f42020-05-12 16:26:01502 }
503
Alexander Timin1cc31f42020-05-12 16:26:01504 if (samesite_treated_as_lax_cookies) {
505 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
506 rfh, blink::mojom::WebFeature::kCookieNoSameSite);
507 }
508
509 if (samesite_none_insecure_cookies) {
510 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
511 rfh, blink::mojom::WebFeature::kCookieInsecureAndSameSiteNone);
512 }
513
514 if (breaking_context_downgrade) {
515 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
516 rfh, blink::mojom::WebFeature::kSchemefulSameSiteContextDowngrade);
517 }
cfredrica5fb0982021-01-09 00:18:01518
Lily Chenc4423c02021-03-11 16:02:02519 if (lax_allow_unsafe_cookies) {
520 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
521 rfh, blink::mojom::WebFeature::kLaxAllowingUnsafeCookies);
522 }
523
Lily Chen2db3a422021-07-20 18:02:25524 if (samesite_cookie_inclusion_changed_by_cross_site_redirect) {
525 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
526 rfh, blink::mojom::WebFeature::
527 kSameSiteCookieInclusionChangedByCrossSiteRedirect);
528 }
Dylan Cutler8d5f8912022-03-04 17:39:19529
530 if (partitioned_cookies_exist) {
531 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
532 rfh, blink::mojom::WebFeature::kPartitionedCookies);
533 }
Ari Chivukula5f21c112022-04-26 19:23:34534
535 if (cookie_has_not_been_refreshed_in_201_to_300_days) {
536 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
537 rfh,
538 blink::mojom::WebFeature::kCookieHasNotBeenRefreshedIn201To300Days);
539 }
540
541 if (cookie_has_not_been_refreshed_in_301_to_350_days) {
542 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
543 rfh,
544 blink::mojom::WebFeature::kCookieHasNotBeenRefreshedIn301To350Days);
545 }
546
547 if (cookie_has_not_been_refreshed_in_351_to_400_days) {
548 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
549 rfh,
550 blink::mojom::WebFeature::kCookieHasNotBeenRefreshedIn351To400Days);
551 }
Johann Hofmanne5764d12022-07-13 23:06:28552
553 if (cookie_has_domain_non_ascii) {
554 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
555 rfh, blink::mojom::WebFeature::kCookieDomainNonASCII);
556 }
selya19cc0d22024-12-10 20:36:07557
558 if (cookies_exempted_by_top_level_storage_access) {
559 RecordCookiesExemptedByTopLevelStorage(
560 rfh->GetPageUkmSourceId(),
561 cookies_exempted_by_top_level_storage_access);
562 }
Alexander Timin1cc31f42020-05-12 16:26:01563}
564
Alexander Timin1cc31f42020-05-12 16:26:01565} // namespace content