blob: b26798dd429a3de3221911c3e5fe6df3e7e2f1e6 [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
Sandor Major7c3e612f2023-12-01 20:48:087#include <cstddef>
8#include <ostream>
9#include <string>
10
11#include "base/feature_list.h"
12#include "base/logging.h"
Jayson Adams295430202021-07-27 01:07:5713#include "base/ranges/algorithm.h"
sbingler8e26e212023-09-27 23:23:2714#include "base/strings/string_util.h"
Alexander Timin1cc31f42020-05-12 16:26:0115#include "content/browser/devtools/devtools_instrumentation.h"
Sandor Major7c3e612f2023-12-01 20:48:0816#include "content/browser/navigation_or_document_handle.h"
17#include "content/browser/renderer_host/navigation_request.h"
danakjc492bf82020-09-09 20:02:4418#include "content/browser/renderer_host/render_frame_host_impl.h"
Alexander Timin1cc31f42020-05-12 16:26:0119#include "content/public/browser/browser_context.h"
20#include "content/public/browser/cookie_access_details.h"
Sandor Major7c3e612f2023-12-01 20:48:0821#include "content/public/browser/legacy_tech_cookie_issue_details.h"
Alexander Timin1cc31f42020-05-12 16:26:0122#include "content/public/common/content_client.h"
Sandor Major7c3e612f2023-12-01 20:48:0823#include "content/public/common/content_features.h"
Jihwan Marc Kim3e132f12020-05-20 17:33:1924#include "net/cookies/cookie_inclusion_status.h"
sbingler870b63f2023-04-25 16:47:5825#include "services/metrics/public/cpp/metrics_utils.h"
Alexander Timin1cc31f42020-05-12 16:26:0126#include "services/metrics/public/cpp/ukm_builders.h"
Sandor Major7c3e612f2023-12-01 20:48:0827#include "url/gurl.h"
Alexander Timin1cc31f42020-05-12 16:26:0128
29namespace content {
30
31namespace {
32
sbingler8e26e212023-09-27 23:23:2733void PotentiallyRecordNonAsciiCookieNameValue(
34 RenderFrameHost* rfh,
35 CookieAccessDetails::Type access_type,
36 const std::string& name,
37 const std::string& value) {
38 CHECK(rfh);
39
40 if (access_type != CookieAccessDetails::Type::kChange) {
41 return;
42 }
43
44 // Our data collection policy disallows collecting UKMs while prerendering.
45 // See //content/browser/preloading/prerender/README.md and ask the team to
46 // explore options to record data for prerendering pages if we need to
47 // support the case.
48 if (rfh->IsInLifecycleState(RenderFrameHost::LifecycleState::kPrerendering)) {
49 return;
50 }
51
52 bool name_has_non_ascii = !base::IsStringASCII(name);
53 bool value_has_non_ascii = !base::IsStringASCII(value);
54
55 if (name_has_non_ascii || value_has_non_ascii) {
56 ukm::SourceId source_id = rfh->GetPageUkmSourceId();
57
58 auto event = ukm::builders::CookieHasNonAsciiCharacter(source_id);
59
60 // The event itself is what we're interested in, the value of "true" here
61 // can be ignored.
62 if (name_has_non_ascii) {
63 event.SetName(true);
64 }
65
66 if (value_has_non_ascii) {
67 event.SetValue(true);
68 }
69
70 event.Record(ukm::UkmRecorder::Get());
71 }
72}
73
selya778265bc2023-10-23 14:37:5574void RecordFirstPartyPartitionedCookieCrossSiteContextUKM(
75 RenderFrameHostImpl* render_frame_host_impl,
76 const net::CanonicalCookie& cookie) {
77 // Our data collection policy disallows collecting UKMs while prerendering.
78 // See //content/browser/preloading/prerender/README.md and ask the team to
79 // explore options to record data for prerendering pages if we need to
80 // support the case.
81 if (render_frame_host_impl->IsInLifecycleState(
82 RenderFrameHost::LifecycleState::kPrerendering)) {
83 return;
84 }
85
86 if (!cookie.IsFirstPartyPartitioned()) {
87 return;
88 }
89
90 // Same-site embed with cross-site ancestors (ABA embeds) have a null site
91 // for cookies since it is a cross-site context. If the result of
92 // ComputeSiteForCookies is first-party that means we are not in an ABA
93 // embedded context.
94 if (render_frame_host_impl->ComputeSiteForCookies().IsFirstParty(
95 GURL(base::StrCat({url::kHttpsScheme, url::kStandardSchemeSeparator,
96 cookie.DomainWithoutDot()})))) {
97 return;
98 }
99
100 ukm::builders::Cookies_FirstPartyPartitionedInCrossSiteContext(
101 render_frame_host_impl->GetPageUkmSourceId())
102 .SetCookiePresent(true)
103 .Record(ukm::UkmRecorder::Get());
104}
105
selya27d093e2023-08-02 22:20:00106void RecordPartitionedCookieUseUKM(RenderFrameHost* rfh,
107 bool partitioned_cookies_exist) {
108 // Our data collection policy disallows collecting UKMs while prerendering.
109 // See //content/browser/preloading/prerender/README.md and ask the team to
110 // explore options to record data for prerendering pages if we need to
111 // support the case.
112 if (rfh->IsInLifecycleState(RenderFrameHost::LifecycleState::kPrerendering)) {
113 return;
114 }
selya9d48d7f2023-08-10 14:19:04115 if (!partitioned_cookies_exist) {
116 return;
117 }
selya27d093e2023-08-02 22:20:00118 ukm::SourceId source_id = rfh->GetPageUkmSourceId();
119
120 ukm::builders::PartitionedCookiePresent(source_id)
121 .SetPartitionedCookiePresent(partitioned_cookies_exist)
122 .Record(ukm::UkmRecorder::Get());
123}
124
sbingler870b63f2023-04-25 16:47:58125void RecordRedirectContextDowngradeUKM(RenderFrameHost* rfh,
126 CookieAccessDetails::Type access_type,
127 const net::CanonicalCookie& cookie,
128 const GURL& url) {
129 CHECK(rfh);
Takashi Toyoshimad540b932023-06-30 02:30:27130
131 // Our data collection policy disallows collecting UKMs while prerendering.
132 // See //content/browser/preloading/prerender/README.md and ask the team to
133 // explore options to record data for prerendering pages if we need to
134 // support the case.
135 if (rfh->IsInLifecycleState(RenderFrameHost::LifecycleState::kPrerendering)) {
136 return;
137 }
138
sbingler870b63f2023-04-25 16:47:58139 ukm::SourceId source_id = rfh->GetPageUkmSourceId();
140
141 int64_t samesite_value = static_cast<int64_t>(cookie.SameSite());
142 if (access_type == CookieAccessDetails::Type::kRead) {
143 base::TimeDelta cookie_age = base::Time::Now() - cookie.CreationDate();
144
145 ukm::builders::SamesiteRedirectContextDowngrade(source_id)
146 .SetSamesiteValueReadPerCookie(samesite_value)
147 .SetAgePerCookie(
148 ukm::GetExponentialBucketMinForUserTiming(cookie_age.InMinutes()))
149 .Record(ukm::UkmRecorder::Get());
150 } else {
151 CHECK(access_type == CookieAccessDetails::Type::kChange);
152 ukm::builders::SamesiteRedirectContextDowngrade(source_id)
153 .SetSamesiteValueWritePerCookie(samesite_value)
154 .Record(ukm::UkmRecorder::Get());
155 }
156}
157
158void RecordSchemefulContextDowngradeUKM(
159 RenderFrameHost* rfh,
160 CookieAccessDetails::Type access_type,
161 const net::CookieInclusionStatus& status,
162 const GURL& url) {
163 CHECK(rfh);
Takashi Toyoshimad540b932023-06-30 02:30:27164
165 // Our data collection policy disallows collecting UKMs while prerendering.
166 // See //content/browser/preloading/prerender/README.md and ask the team to
167 // explore options to record data for prerendering pages if we need to
168 // support the case.
169 if (rfh->IsInLifecycleState(RenderFrameHost::LifecycleState::kPrerendering)) {
170 return;
171 }
172
Alexander Timin1cc31f42020-05-12 16:26:01173 ukm::SourceId source_id = rfh->GetPageUkmSourceId();
174
Lei Zhang3ab30192022-08-15 19:52:20175 auto downgrade_metric =
176 static_cast<int64_t>(status.GetBreakingDowngradeMetricsEnumValue(url));
Alexander Timin1cc31f42020-05-12 16:26:01177 if (access_type == CookieAccessDetails::Type::kRead) {
178 ukm::builders::SchemefulSameSiteContextDowngrade(source_id)
Lei Zhang3ab30192022-08-15 19:52:20179 .SetRequestPerCookie(downgrade_metric)
Alexander Timin1cc31f42020-05-12 16:26:01180 .Record(ukm::UkmRecorder::Get());
181 } else {
sbingler870b63f2023-04-25 16:47:58182 CHECK(access_type == CookieAccessDetails::Type::kChange);
Alexander Timin1cc31f42020-05-12 16:26:01183 ukm::builders::SchemefulSameSiteContextDowngrade(source_id)
Lei Zhang3ab30192022-08-15 19:52:20184 .SetResponsePerCookie(downgrade_metric)
Alexander Timin1cc31f42020-05-12 16:26:01185 .Record(ukm::UkmRecorder::Get());
186 }
187}
188
Sandor Major7c3e612f2023-12-01 20:48:08189// LINT.IfChange(should_report_dev_tools)
Simon Zünd657178e2021-05-27 06:19:55190bool ShouldReportDevToolsIssueForStatus(
191 const net::CookieInclusionStatus& status) {
192 return status.ShouldWarn() ||
193 status.HasExclusionReason(
Dylan Cutler15fdd1e2022-11-15 22:54:46194 net::CookieInclusionStatus::EXCLUDE_DOMAIN_NON_ASCII) ||
195 status.HasExclusionReason(
196 net::CookieInclusionStatus::
Shuran Huangdc0b8d82023-09-19 14:49:30197 EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET) ||
198 status.HasExclusionReason(
199 net::CookieInclusionStatus::EXCLUDE_THIRD_PARTY_PHASEOUT);
Simon Zünd657178e2021-05-27 06:19:55200}
Sandor Major7c3e612f2023-12-01 20:48:08201// LINT.ThenChange(//content/browser/renderer_host/cookie_utils.cc:should_report_legacy_tech_report)
Simon Zünd657178e2021-05-27 06:19:55202
Sandor Major7c3e612f2023-12-01 20:48:08203// LINT.IfChange(should_report_legacy_tech_report)
204bool ShouldReportLegacyTechIssueForStatus(
205 const net::CookieInclusionStatus& status) {
206 return status.HasExclusionReason(
207 net::CookieInclusionStatus::
208 EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET) ||
209 status.HasExclusionReason(
210 net::CookieInclusionStatus::EXCLUDE_THIRD_PARTY_PHASEOUT) ||
211 status.HasWarningReason(
212 net::CookieInclusionStatus::WARN_THIRD_PARTY_PHASEOUT);
213}
214// LINT.ThenChange(//content/browser/renderer_host/cookie_utils.cc:should_report_dev_tools)
215
216// Logs cookie issues to DevTools Issues Panel and logs events to UseCounters
Shuran Huang8fa11c72023-12-04 16:53:44217// and UKM for a single cookie-accessed event.
Sandor Major0d7fd6292023-10-26 20:15:44218// TODO(crbug.com/977040): Remove when no longer needed.
219void EmitCookieWarningsAndMetricsOnce(
Alexander Timin1cc31f42020-05-12 16:26:01220 RenderFrameHostImpl* rfh,
221 const network::mojom::CookieAccessDetailsPtr& cookie_details) {
222 RenderFrameHostImpl* root_frame_host = rfh->GetMainFrame();
223
Sreeja Kamishettye49854f82021-06-02 00:52:03224 if (!root_frame_host->IsActive())
Alexander Timin1cc31f42020-05-12 16:26:01225 return;
226
227 bool samesite_treated_as_lax_cookies = false;
228 bool samesite_none_insecure_cookies = false;
Alexander Timin1cc31f42020-05-12 16:26:01229 bool breaking_context_downgrade = false;
Lily Chenc4423c02021-03-11 16:02:02230 bool lax_allow_unsafe_cookies = false;
Alexander Timin1cc31f42020-05-12 16:26:01231
Lily Chen2db3a422021-07-20 18:02:25232 bool samesite_cookie_inclusion_changed_by_cross_site_redirect = false;
233
Dylan Cutler8d5f8912022-03-04 17:39:19234 bool partitioned_cookies_exist = false;
235
Ari Chivukula5f21c112022-04-26 19:23:34236 bool cookie_has_not_been_refreshed_in_201_to_300_days = false;
237 bool cookie_has_not_been_refreshed_in_301_to_350_days = false;
238 bool cookie_has_not_been_refreshed_in_351_to_400_days = false;
239
Johann Hofmanne5764d12022-07-13 23:06:28240 bool cookie_has_domain_non_ascii = false;
241
cfredric76b2d222021-01-27 20:12:04242 for (const network::mojom::CookieOrLineWithAccessResultPtr& cookie :
Alexander Timin1cc31f42020-05-12 16:26:01243 cookie_details->cookie_list) {
Johann Hofmann975c0b42022-08-02 21:05:51244 const net::CookieInclusionStatus& status = cookie->access_result.status;
245 if (ShouldReportDevToolsIssueForStatus(status)) {
Juba Borgohainc93969e2022-02-25 21:56:12246 devtools_instrumentation::ReportCookieIssue(
Simon Zünd657178e2021-05-27 06:19:55247 root_frame_host, cookie, cookie_details->url,
248 cookie_details->site_for_cookies,
249 cookie_details->type == CookieAccessDetails::Type::kRead
Juba Borgohainc93969e2022-02-25 21:56:12250 ? blink::mojom::CookieOperation::kReadCookie
251 : blink::mojom::CookieOperation::kSetCookie,
Simon Zünd657178e2021-05-27 06:19:55252 cookie_details->devtools_request_id);
253 }
254
Shuran Huang8fa11c72023-12-04 16:53:44255 // Log to the JS console if there is cookie affected by 3PCD.
256 if (status.HasExclusionReason(
257 net::CookieInclusionStatus::EXCLUDE_THIRD_PARTY_PHASEOUT)) {
258 root_frame_host->AddMessageToConsole(
259 blink::mojom::ConsoleMessageLevel::kWarning,
260 "Blocked third-party cookie. Learn more in the Issues tab.");
261 } else if (status.HasWarningReason(
262 net::CookieInclusionStatus::WARN_THIRD_PARTY_PHASEOUT)) {
263 root_frame_host->AddMessageToConsole(
264 blink::mojom::ConsoleMessageLevel::kWarning,
265 "Third-party cookie will be blocked. Learn more in the Issues tab.");
266 }
267
cfredric76b2d222021-01-27 20:12:04268 if (cookie->access_result.status.ShouldWarn()) {
Lily Chen9de4065b2020-06-24 20:18:47269 samesite_treated_as_lax_cookies =
270 samesite_treated_as_lax_cookies ||
cfredrica5fb0982021-01-09 00:18:01271 status.HasWarningReason(
Jihwan Marc Kim3e132f12020-05-20 17:33:19272 net::CookieInclusionStatus::
Lily Chen9de4065b2020-06-24 20:18:47273 WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT) ||
cfredrica5fb0982021-01-09 00:18:01274 status.HasWarningReason(
Jihwan Marc Kim3e132f12020-05-20 17:33:19275 net::CookieInclusionStatus::
Lily Chen9de4065b2020-06-24 20:18:47276 WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE);
Alexander Timin1cc31f42020-05-12 16:26:01277
Lily Chen9de4065b2020-06-24 20:18:47278 samesite_none_insecure_cookies =
279 samesite_none_insecure_cookies ||
cfredrica5fb0982021-01-09 00:18:01280 status.HasWarningReason(
Lily Chen9de4065b2020-06-24 20:18:47281 net::CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE);
282
Lily Chenc4423c02021-03-11 16:02:02283 lax_allow_unsafe_cookies =
284 lax_allow_unsafe_cookies ||
285 status.HasWarningReason(
286 net::CookieInclusionStatus::
287 WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE);
288
Lily Chen2db3a422021-07-20 18:02:25289 samesite_cookie_inclusion_changed_by_cross_site_redirect =
290 samesite_cookie_inclusion_changed_by_cross_site_redirect ||
291 status.HasWarningReason(
292 net::CookieInclusionStatus::
293 WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION);
Alexander Timin1cc31f42020-05-12 16:26:01294 }
Alexander Timin1cc31f42020-05-12 16:26:01295
Johann Hofmann975c0b42022-08-02 21:05:51296 cookie_has_domain_non_ascii =
297 cookie_has_domain_non_ascii ||
298 status.HasWarningReason(
299 net::CookieInclusionStatus::WARN_DOMAIN_NON_ASCII) ||
300 status.HasExclusionReason(
301 net::CookieInclusionStatus::EXCLUDE_DOMAIN_NON_ASCII);
302
Dylan Cutler8d5f8912022-03-04 17:39:19303 partitioned_cookies_exist =
304 partitioned_cookies_exist ||
305 (cookie->cookie_or_line->is_cookie() &&
Dylan Cutler051411b42022-07-12 22:20:07306 cookie->cookie_or_line->get_cookie().IsPartitioned() &&
307 // Ignore nonced partition keys since this metric is meant to track
308 // usage of the Partitioned attribute.
309 !cookie->cookie_or_line->get_cookie().PartitionKey()->nonce());
Dylan Cutler8d5f8912022-03-04 17:39:19310
selya27d093e2023-08-02 22:20:00311 RecordPartitionedCookieUseUKM(rfh, partitioned_cookies_exist);
312
selya778265bc2023-10-23 14:37:55313 if (partitioned_cookies_exist) {
314 RecordFirstPartyPartitionedCookieCrossSiteContextUKM(
315 rfh, cookie->cookie_or_line->get_cookie());
316 }
317
Ayu Ishii2e3998902020-07-14 18:22:30318 breaking_context_downgrade =
319 breaking_context_downgrade ||
sbingler870b63f2023-04-25 16:47:58320 cookie->access_result.status.HasSchemefulDowngradeWarning();
Alexander Timin1cc31f42020-05-12 16:26:01321
sbingler870b63f2023-04-25 16:47:58322 if (cookie->access_result.status.HasSchemefulDowngradeWarning()) {
323 // Unlike with UMA, do not record cookies that have no schemeful downgrade
324 // warning.
325 RecordSchemefulContextDowngradeUKM(rfh, cookie_details->type,
326 cookie->access_result.status,
327 cookie_details->url);
328 }
329
330 if (status.HasWarningReason(
331 net::CookieInclusionStatus::
332 WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION) &&
333 cookie->cookie_or_line->is_cookie()) {
334 RecordRedirectContextDowngradeUKM(rfh, cookie_details->type,
335 cookie->cookie_or_line->get_cookie(),
336 cookie_details->url);
Alexander Timin1cc31f42020-05-12 16:26:01337 }
Ari Chivukula5f21c112022-04-26 19:23:34338
sbingler8e26e212023-09-27 23:23:27339 if (cookie->cookie_or_line->is_cookie()) {
340 PotentiallyRecordNonAsciiCookieNameValue(
341 rfh, cookie_details->type,
342 cookie->cookie_or_line->get_cookie().Name(),
343 cookie->cookie_or_line->get_cookie().Value());
344 }
345
Ari Chivukula5f21c112022-04-26 19:23:34346 // In order to anticipate the potential effects of the expiry limit in
347 // rfc6265bis, we need to check how long it's been since the cookie was
348 // refreshed (if LastUpdateDate is populated). These three buckets were
349 // picked so we could engage sites with some granularity around urgency.
350 // We ignore the space under 200 days as these cookies are not at risk
351 // of expiring and we ignore the space over 400 days as these cookies
352 // have already expired. Metrics will take 200 days from M103 to populate.
353 base::Time last_update_date =
354 cookie->cookie_or_line->is_cookie()
355 ? cookie->cookie_or_line->get_cookie().LastUpdateDate()
356 : base::Time();
357 if (!last_update_date.is_null()) {
358 int days_since_refresh = (base::Time::Now() - last_update_date).InDays();
359 cookie_has_not_been_refreshed_in_201_to_300_days |=
360 days_since_refresh > 200 && days_since_refresh <= 300;
361 cookie_has_not_been_refreshed_in_301_to_350_days |=
362 days_since_refresh > 300 && days_since_refresh <= 350;
363 cookie_has_not_been_refreshed_in_351_to_400_days |=
364 days_since_refresh > 350 && days_since_refresh <= 400;
365 }
Alexander Timin1cc31f42020-05-12 16:26:01366 }
367
Alexander Timin1cc31f42020-05-12 16:26:01368 if (samesite_treated_as_lax_cookies) {
369 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
370 rfh, blink::mojom::WebFeature::kCookieNoSameSite);
371 }
372
373 if (samesite_none_insecure_cookies) {
374 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
375 rfh, blink::mojom::WebFeature::kCookieInsecureAndSameSiteNone);
376 }
377
378 if (breaking_context_downgrade) {
379 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
380 rfh, blink::mojom::WebFeature::kSchemefulSameSiteContextDowngrade);
381 }
cfredrica5fb0982021-01-09 00:18:01382
Lily Chenc4423c02021-03-11 16:02:02383 if (lax_allow_unsafe_cookies) {
384 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
385 rfh, blink::mojom::WebFeature::kLaxAllowingUnsafeCookies);
386 }
387
Lily Chen2db3a422021-07-20 18:02:25388 if (samesite_cookie_inclusion_changed_by_cross_site_redirect) {
389 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
390 rfh, blink::mojom::WebFeature::
391 kSameSiteCookieInclusionChangedByCrossSiteRedirect);
392 }
Dylan Cutler8d5f8912022-03-04 17:39:19393
394 if (partitioned_cookies_exist) {
395 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
396 rfh, blink::mojom::WebFeature::kPartitionedCookies);
397 }
Ari Chivukula5f21c112022-04-26 19:23:34398
399 if (cookie_has_not_been_refreshed_in_201_to_300_days) {
400 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
401 rfh,
402 blink::mojom::WebFeature::kCookieHasNotBeenRefreshedIn201To300Days);
403 }
404
405 if (cookie_has_not_been_refreshed_in_301_to_350_days) {
406 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
407 rfh,
408 blink::mojom::WebFeature::kCookieHasNotBeenRefreshedIn301To350Days);
409 }
410
411 if (cookie_has_not_been_refreshed_in_351_to_400_days) {
412 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
413 rfh,
414 blink::mojom::WebFeature::kCookieHasNotBeenRefreshedIn351To400Days);
415 }
Johann Hofmanne5764d12022-07-13 23:06:28416
417 if (cookie_has_domain_non_ascii) {
418 GetContentClient()->browser()->LogWebFeatureForCurrentPage(
419 rfh, blink::mojom::WebFeature::kCookieDomainNonASCII);
420 }
Alexander Timin1cc31f42020-05-12 16:26:01421}
422
Sandor Major7c3e612f2023-12-01 20:48:08423// Logs cookie issues to Legacy Technology Report.
424void ReportLegacyTechEvent(
425 RenderFrameHostImpl* render_frame_host,
426 NavigationRequest* navigation_request,
427 const network::mojom::CookieAccessDetailsPtr& cookie_details) {
428 if (!base::FeatureList::IsEnabled(
429 features::kLegacyTechReportEnableCookieIssueReports)) {
430 return;
431 }
432 CHECK(render_frame_host);
433
434 for (const network::mojom::CookieOrLineWithAccessResultPtr& cookie :
435 cookie_details->cookie_list) {
436 const net::CookieInclusionStatus& status = cookie->access_result.status;
437 if (ShouldReportLegacyTechIssueForStatus(status) &&
438 cookie->cookie_or_line->is_cookie()) {
439 std::string type;
440 if (status.HasExclusionReason(
441 net::CookieInclusionStatus::
442 EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET) ||
443 status.HasExclusionReason(
444 net::CookieInclusionStatus::EXCLUDE_THIRD_PARTY_PHASEOUT)) {
445 type = "ThirdPartyCookieAccessError";
446 } else if (status.HasWarningReason(
447 net::CookieInclusionStatus::WARN_THIRD_PARTY_PHASEOUT)) {
448 type = "ThirdPartyCookieAccessWarning";
449 } else {
450 DLOG(ERROR) << "Unexpected call of ReportLegacyTechEvent.";
451 }
452
453 GURL url = render_frame_host->GetOutermostMainFrameOrEmbedder()
454 ->GetLastCommittedURL();
455 GURL frame_url = render_frame_host->GetLastCommittedURL();
456 if (navigation_request != nullptr) {
457 if (!navigation_request->frame_tree_node()
458 ->GetParentOrOuterDocumentOrEmbedder()) {
459 url = navigation_request->GetURL();
460 frame_url = navigation_request->GetURL();
461 } else {
462 frame_url = navigation_request->GetURL();
463 }
464 }
465
466 LegacyTechCookieIssueDetails cookie_issue_details = {
467 cookie_details->url.spec(),
468 cookie->cookie_or_line->get_cookie().Name(),
469 cookie->cookie_or_line->get_cookie().Domain(),
470 cookie->cookie_or_line->get_cookie().Path(),
471 cookie_details->type == CookieAccessDetails::Type::kChange
472 ? LegacyTechCookieIssueDetails::AccessOperation::kWrite
473 : LegacyTechCookieIssueDetails::AccessOperation::kRead};
474
475 GetContentClient()->browser()->ReportLegacyTechEvent(
476 render_frame_host, type, url, frame_url, /*filename=*/"", /*line=*/0,
477 /*column=*/0, cookie_issue_details);
478 }
479 }
480}
481
Sandor Major0d7fd6292023-10-26 20:15:44482} // namespace
483
484void SplitCookiesIntoAllowedAndBlocked(
485 const network::mojom::CookieAccessDetailsPtr& cookie_details,
486 CookieAccessDetails* allowed,
487 CookieAccessDetails* blocked) {
Victor Tane1f2bc62023-11-15 00:12:20488 // For some cases `site_for_cookies` representative url is empty when
489 // OnCookieAccess is triggered for a third party. For example iframe third
490 // party accesses cookies when TPCD Metadata allows third party cookie access.
491 //
492 // Make `first_party_url` considering both `top_frame_origin` and
493 // `site_for_cookies` which is similar with GetFirstPartyURL() in
494 // components/content_settings/core/common/cookie_settings_base.h.
495 // If the `top_frame_origin` is non-opaque, it is chosen; otherwise, the
496 // `site_for_cookies` representative url is used.
497 const GURL first_party_url =
498 cookie_details->top_frame_origin.opaque()
499 ? cookie_details->site_for_cookies.RepresentativeUrl()
500 : cookie_details->top_frame_origin.GetURL();
501
502 *allowed = CookieAccessDetails({cookie_details->type,
503 cookie_details->url,
504 first_party_url,
505 {},
506 cookie_details->count,
507 /* blocked_by_policy=*/false,
Victor Tanf288abf2023-11-15 05:33:54508 cookie_details->is_ad_tagged,
509 cookie_details->cookie_setting_overrides});
Sandor Major0d7fd6292023-10-26 20:15:44510 int allowed_count = base::ranges::count_if(
511 cookie_details->cookie_list,
512 [](const network::mojom::CookieOrLineWithAccessResultPtr&
513 cookie_and_access_result) {
514 // "Included" cookies have no exclusion reasons so we don't also have to
515 // check for !(net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES).
516 return cookie_and_access_result->access_result.status.IsInclude();
517 });
518 allowed->cookie_list.reserve(allowed_count);
519
Victor Tane1f2bc62023-11-15 00:12:20520 *blocked = CookieAccessDetails({cookie_details->type,
521 cookie_details->url,
522 first_party_url,
523 {},
524 cookie_details->count,
525 /* blocked_by_policy=*/true,
Victor Tanf288abf2023-11-15 05:33:54526 cookie_details->is_ad_tagged,
527 cookie_details->cookie_setting_overrides});
Sandor Major0d7fd6292023-10-26 20:15:44528 int blocked_count = base::ranges::count_if(
529 cookie_details->cookie_list,
530 [](const network::mojom::CookieOrLineWithAccessResultPtr&
531 cookie_and_access_result) {
532 return cookie_and_access_result->access_result.status
533 .ExcludedByUserPreferences();
534 });
535 blocked->cookie_list.reserve(blocked_count);
536
537 for (const auto& cookie_and_access_result : cookie_details->cookie_list) {
538 if (cookie_and_access_result->access_result.status
539 .ExcludedByUserPreferences()) {
540 blocked->cookie_list.emplace_back(
541 std::move(cookie_and_access_result->cookie_or_line->get_cookie()));
542 } else if (cookie_and_access_result->access_result.status.IsInclude()) {
543 allowed->cookie_list.emplace_back(
544 std::move(cookie_and_access_result->cookie_or_line->get_cookie()));
545 }
546 }
547}
548
549void EmitCookieWarningsAndMetrics(
550 RenderFrameHostImpl* rfh,
Sandor Major7c3e612f2023-12-01 20:48:08551 NavigationRequest* navigation_request,
Sandor Major0d7fd6292023-10-26 20:15:44552 const network::mojom::CookieAccessDetailsPtr& cookie_details) {
Sandor Major7c3e612f2023-12-01 20:48:08553 ReportLegacyTechEvent(rfh, navigation_request, cookie_details);
Sandor Major0d7fd6292023-10-26 20:15:44554 for (size_t i = 0; i < cookie_details->count; ++i) {
555 EmitCookieWarningsAndMetricsOnce(rfh, cookie_details);
556 }
557}
558
Alexander Timin1cc31f42020-05-12 16:26:01559} // namespace content