blob: 9ac8a050758182c610d34a77496512d8dec384d2 [file] [log] [blame]
Jihwan Marc Kim3e132f12020-05-20 17:33:191// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/cookies/cookie_inclusion_status.h"
6
7#include "base/strings/strcat.h"
8#include "url/gurl.h"
9
10namespace net {
11
12namespace {
13
14uint32_t GetExclusionBitmask(CookieInclusionStatus::ExclusionReason reason) {
15 return 1u << static_cast<uint32_t>(reason);
16}
17
18uint32_t GetWarningBitmask(CookieInclusionStatus::WarningReason reason) {
19 return 1u << static_cast<uint32_t>(reason);
20}
21
22} // namespace
23
cfredric2c5cfa62020-11-16 19:59:2524CookieInclusionStatus::CookieInclusionStatus() = default;
Jihwan Marc Kim3e132f12020-05-20 17:33:1925
26CookieInclusionStatus::CookieInclusionStatus(ExclusionReason reason)
27 : exclusion_reasons_(GetExclusionBitmask(reason)) {}
28
29CookieInclusionStatus::CookieInclusionStatus(ExclusionReason reason,
30 WarningReason warning)
31 : exclusion_reasons_(GetExclusionBitmask(reason)),
32 warning_reasons_(GetWarningBitmask(warning)) {}
33
cfredric362c4a02021-07-09 22:40:4034CookieInclusionStatus::CookieInclusionStatus(WarningReason warning)
35 : warning_reasons_(GetWarningBitmask(warning)) {}
36
Jihwan Marc Kim3e132f12020-05-20 17:33:1937bool CookieInclusionStatus::operator==(
38 const CookieInclusionStatus& other) const {
39 return exclusion_reasons_ == other.exclusion_reasons_ &&
40 warning_reasons_ == other.warning_reasons_;
41}
42
43bool CookieInclusionStatus::operator!=(
44 const CookieInclusionStatus& other) const {
45 return !operator==(other);
46}
47
48bool CookieInclusionStatus::IsInclude() const {
49 return exclusion_reasons_ == 0u;
50}
51
52bool CookieInclusionStatus::HasExclusionReason(ExclusionReason reason) const {
53 return exclusion_reasons_ & GetExclusionBitmask(reason);
54}
55
Lily Chen70c537a2020-07-20 18:02:0956bool CookieInclusionStatus::HasOnlyExclusionReason(
57 ExclusionReason reason) const {
58 return exclusion_reasons_ == GetExclusionBitmask(reason);
59}
60
Jihwan Marc Kim3e132f12020-05-20 17:33:1961void CookieInclusionStatus::AddExclusionReason(ExclusionReason reason) {
62 exclusion_reasons_ |= GetExclusionBitmask(reason);
63 // If the cookie would be excluded for reasons other than the new SameSite
64 // rules, don't bother warning about it.
65 MaybeClearSameSiteWarning();
66}
67
68void CookieInclusionStatus::RemoveExclusionReason(ExclusionReason reason) {
69 exclusion_reasons_ &= ~(GetExclusionBitmask(reason));
70}
71
cfredric05c78ac2021-01-06 18:10:2672void CookieInclusionStatus::RemoveExclusionReasons(
73 const std::vector<ExclusionReason>& reasons) {
74 exclusion_reasons_ = ExclusionReasonsWithout(reasons);
75}
76
cfredric2c5cfa62020-11-16 19:59:2577uint32_t CookieInclusionStatus::ExclusionReasonsWithout(
78 const std::vector<ExclusionReason>& reasons) const {
79 uint32_t mask = 0u;
80 for (const ExclusionReason reason : reasons) {
81 mask |= GetExclusionBitmask(reason);
82 }
83 return exclusion_reasons_ & ~mask;
84}
85
Jihwan Marc Kim3e132f12020-05-20 17:33:1986void CookieInclusionStatus::MaybeClearSameSiteWarning() {
cfredric2c5cfa62020-11-16 19:59:2587 if (ExclusionReasonsWithout({
88 EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
89 EXCLUDE_SAMESITE_NONE_INSECURE,
90 }) != 0u) {
Lily Chen2db3a422021-07-20 18:02:2591 RemoveWarningReason(WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT);
92 RemoveWarningReason(WARN_SAMESITE_NONE_INSECURE);
93 RemoveWarningReason(WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE);
Jihwan Marc Kim3e132f12020-05-20 17:33:1994 }
95
cfredric2c5cfa62020-11-16 19:59:2596 if (!ShouldRecordDowngradeMetrics()) {
Lily Chen2db3a422021-07-20 18:02:2597 RemoveWarningReason(WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE);
98 RemoveWarningReason(WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE);
99 RemoveWarningReason(WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE);
100 RemoveWarningReason(WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE);
101 RemoveWarningReason(WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE);
102
103 RemoveWarningReason(WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION);
Jihwan Marc Kim3e132f12020-05-20 17:33:19104 }
105}
106
107bool CookieInclusionStatus::ShouldRecordDowngradeMetrics() const {
cfredric2c5cfa62020-11-16 19:59:25108 return ExclusionReasonsWithout({
109 EXCLUDE_SAMESITE_STRICT,
110 EXCLUDE_SAMESITE_LAX,
111 EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
112 }) == 0u;
Jihwan Marc Kim3e132f12020-05-20 17:33:19113}
114
115bool CookieInclusionStatus::ShouldWarn() const {
116 return warning_reasons_ != 0u;
117}
118
119bool CookieInclusionStatus::HasWarningReason(WarningReason reason) const {
120 return warning_reasons_ & GetWarningBitmask(reason);
121}
122
123bool CookieInclusionStatus::HasDowngradeWarning(
124 CookieInclusionStatus::WarningReason* reason) const {
125 if (!ShouldWarn())
126 return false;
127
128 const CookieInclusionStatus::WarningReason kDowngradeWarnings[] = {
129 WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE,
130 WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE,
131 WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE,
132 WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE,
133 WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE,
134 };
135
136 for (auto warning : kDowngradeWarnings) {
137 if (!HasWarningReason(warning))
138 continue;
139
140 if (reason)
141 *reason = warning;
142
143 return true;
144 }
145
146 return false;
147}
148
149void CookieInclusionStatus::AddWarningReason(WarningReason reason) {
150 warning_reasons_ |= GetWarningBitmask(reason);
151}
152
153void CookieInclusionStatus::RemoveWarningReason(WarningReason reason) {
154 warning_reasons_ &= ~(GetWarningBitmask(reason));
155}
156
157CookieInclusionStatus::ContextDowngradeMetricValues
158CookieInclusionStatus::GetBreakingDowngradeMetricsEnumValue(
159 const GURL& url) const {
160 bool url_is_secure = url.SchemeIsCryptographic();
161
162 // Start the |reason| as something other than the downgrade warnings.
163 WarningReason reason = WarningReason::NUM_WARNING_REASONS;
164
165 // Don't bother checking the return value because the default switch case
166 // will handle if no reason was found.
167 HasDowngradeWarning(&reason);
168
169 switch (reason) {
170 case WarningReason::WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE:
171 return url_is_secure
172 ? ContextDowngradeMetricValues::STRICT_LAX_STRICT_SECURE
173 : ContextDowngradeMetricValues::STRICT_LAX_STRICT_INSECURE;
174 case WarningReason::WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE:
175 return url_is_secure
176 ? ContextDowngradeMetricValues::STRICT_CROSS_STRICT_SECURE
177 : ContextDowngradeMetricValues::STRICT_CROSS_STRICT_INSECURE;
178 case WarningReason::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE:
179 return url_is_secure
180 ? ContextDowngradeMetricValues::STRICT_CROSS_LAX_SECURE
181 : ContextDowngradeMetricValues::STRICT_CROSS_LAX_INSECURE;
182 case WarningReason::WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE:
183 return url_is_secure
184 ? ContextDowngradeMetricValues::LAX_CROSS_STRICT_SECURE
185 : ContextDowngradeMetricValues::LAX_CROSS_STRICT_INSECURE;
186 case WarningReason::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE:
187 return url_is_secure
188 ? ContextDowngradeMetricValues::LAX_CROSS_LAX_SECURE
189 : ContextDowngradeMetricValues::LAX_CROSS_LAX_INSECURE;
190 default:
191 return url_is_secure
192 ? ContextDowngradeMetricValues::NO_DOWNGRADE_SECURE
193 : ContextDowngradeMetricValues::NO_DOWNGRADE_INSECURE;
194 }
195}
196
197std::string CookieInclusionStatus::GetDebugString() const {
198 std::string out;
199
Jihwan Marc Kim3e132f12020-05-20 17:33:19200 if (IsInclude())
201 base::StrAppend(&out, {"INCLUDE, "});
cfredrica50e8532021-06-29 19:44:56202 for (const auto& reason :
203 std::initializer_list<std::pair<ExclusionReason, std::string>>{
204 {EXCLUDE_UNKNOWN_ERROR, "EXCLUDE_UNKNOWN_ERROR"},
205 {EXCLUDE_HTTP_ONLY, "EXCLUDE_HTTP_ONLY"},
206 {EXCLUDE_SECURE_ONLY, "EXCLUDE_SECURE_ONLY"},
207 {EXCLUDE_DOMAIN_MISMATCH, "EXCLUDE_DOMAIN_MISMATCH"},
208 {EXCLUDE_NOT_ON_PATH, "EXCLUDE_NOT_ON_PATH"},
209 {EXCLUDE_SAMESITE_STRICT, "EXCLUDE_SAMESITE_STRICT"},
210 {EXCLUDE_SAMESITE_LAX, "EXCLUDE_SAMESITE_LAX"},
211 {EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
212 "EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX"},
213 {EXCLUDE_SAMESITE_NONE_INSECURE, "EXCLUDE_SAMESITE_NONE_INSECURE"},
214 {EXCLUDE_USER_PREFERENCES, "EXCLUDE_USER_PREFERENCES"},
215 {EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT,
216 "EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT"},
217 {EXCLUDE_FAILURE_TO_STORE, "EXCLUDE_FAILURE_TO_STORE"},
218 {EXCLUDE_NONCOOKIEABLE_SCHEME, "EXCLUDE_NONCOOKIEABLE_SCHEME"},
219 {EXCLUDE_OVERWRITE_SECURE, "EXCLUDE_OVERWRITE_SECURE"},
220 {EXCLUDE_OVERWRITE_HTTP_ONLY, "EXCLUDE_OVERWRITE_HTTP_ONLY"},
221 {EXCLUDE_INVALID_DOMAIN, "EXCLUDE_INVALID_DOMAIN"},
222 {EXCLUDE_INVALID_PREFIX, "EXCLUDE_INVALID_PREFIX"},
223 {EXCLUDE_INVALID_SAMEPARTY, "EXCLUDE_INVALID_SAMEPARTY"},
Dylan Cutler01ca8e32021-07-16 18:01:35224 {EXCLUDE_INVALID_PARTITIONED, "EXCLUDE_INVALID_PARTITIONED"},
Andrew Williamse320767e02021-09-10 04:38:00225 {EXCLUDE_NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE,
226 "EXCLUDE_NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE"},
227 {EXCLUDE_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE,
228 "EXCLUDE_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE"},
cfredrica50e8532021-06-29 19:44:56229 }) {
230 if (HasExclusionReason(reason.first))
231 base::StrAppend(&out, {reason.second, ", "});
232 }
Jihwan Marc Kim3e132f12020-05-20 17:33:19233
234 // Add warning
235 if (!ShouldWarn()) {
236 base::StrAppend(&out, {"DO_NOT_WARN"});
237 return out;
238 }
239
cfredrica50e8532021-06-29 19:44:56240 for (const auto& reason :
241 std::initializer_list<std::pair<WarningReason, std::string>>{
242 {WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT,
243 "WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT"},
244 {WARN_SAMESITE_NONE_INSECURE, "WARN_SAMESITE_NONE_INSECURE"},
245 {WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE,
246 "WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE"},
247 {WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE,
248 "WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE"},
249 {WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE,
250 "WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE"},
251 {WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE,
252 "WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE"},
253 {WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE,
254 "WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE"},
255 {WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE,
256 "WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE"},
257 {WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC,
258 "WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC"},
259 {WARN_SAMEPARTY_EXCLUSION_OVERRULED_SAMESITE,
260 "WARN_SAMEPARTY_EXCLUSION_OVERRULED_SAMESITE"},
261 {WARN_SAMEPARTY_INCLUSION_OVERRULED_SAMESITE,
262 "WARN_SAMEPARTY_INCLUSION_OVERRULED_SAMESITE"},
cfredric362c4a02021-07-09 22:40:40263 {WARN_SAMESITE_NONE_REQUIRED, "WARN_SAMESITE_NONE_REQUIRED"},
264 {WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE,
265 "WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE"},
266 {WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS,
267 "WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS"},
268 {WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX,
269 "WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX"},
270 {WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT,
271 "WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT"},
Lily Chen2db3a422021-07-20 18:02:25272 {WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION,
273 "WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION"},
cfredrica50e8532021-06-29 19:44:56274 }) {
275 if (HasWarningReason(reason.first))
276 base::StrAppend(&out, {reason.second, ", "});
Lily Chenef77a172021-02-22 22:42:26277 }
Jihwan Marc Kim3e132f12020-05-20 17:33:19278
279 // Strip trailing comma and space.
280 out.erase(out.end() - 2, out.end());
281
282 return out;
283}
284
285bool CookieInclusionStatus::IsValid() const {
286 // Bit positions where there should not be any true bits.
287 uint32_t exclusion_mask = ~0u << static_cast<int>(NUM_EXCLUSION_REASONS);
288 uint32_t warning_mask = ~0u << static_cast<int>(NUM_WARNING_REASONS);
289 return (exclusion_mask & exclusion_reasons_) == 0u &&
290 (warning_mask & warning_reasons_) == 0u;
291}
292
293bool CookieInclusionStatus::HasExactlyExclusionReasonsForTesting(
294 std::vector<CookieInclusionStatus::ExclusionReason> reasons) const {
295 CookieInclusionStatus expected = MakeFromReasonsForTesting(reasons);
296 return expected.exclusion_reasons_ == exclusion_reasons_;
297}
298
299bool CookieInclusionStatus::HasExactlyWarningReasonsForTesting(
300 std::vector<WarningReason> reasons) const {
301 CookieInclusionStatus expected = MakeFromReasonsForTesting({}, reasons);
302 return expected.warning_reasons_ == warning_reasons_;
303}
304
305// static
306CookieInclusionStatus CookieInclusionStatus::MakeFromReasonsForTesting(
307 std::vector<ExclusionReason> reasons,
308 std::vector<WarningReason> warnings) {
309 CookieInclusionStatus status;
310 for (ExclusionReason reason : reasons) {
311 status.AddExclusionReason(reason);
312 }
313 for (WarningReason warning : warnings) {
314 status.AddWarningReason(warning);
315 }
316 return status;
317}
318
319} // namespace net