1 // Copyright 2020 The Chromium Authors
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 "testing/gtest/include/gtest/gtest.h"
8
9 namespace net {
10
TEST(CookieInclusionStatusTest,IncludeStatus)11 TEST(CookieInclusionStatusTest, IncludeStatus) {
12 int num_exclusion_reasons =
13 static_cast<int>(CookieInclusionStatus::NUM_EXCLUSION_REASONS);
14 int num_warning_reasons =
15 static_cast<int>(CookieInclusionStatus::NUM_WARNING_REASONS);
16 // Zero-argument constructor
17 CookieInclusionStatus status;
18 EXPECT_TRUE(status.IsInclude());
19 for (int i = 0; i < num_exclusion_reasons; ++i) {
20 EXPECT_FALSE(status.HasExclusionReason(
21 static_cast<CookieInclusionStatus::ExclusionReason>(i)));
22 }
23 for (int i = 0; i < num_warning_reasons; ++i) {
24 EXPECT_FALSE(status.HasWarningReason(
25 static_cast<CookieInclusionStatus::WarningReason>(i)));
26 }
27 EXPECT_FALSE(
28 status.HasExclusionReason(CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR));
29 }
30
TEST(CookieInclusionStatusTest,ExcludeStatus)31 TEST(CookieInclusionStatusTest, ExcludeStatus) {
32 int num_exclusion_reasons =
33 static_cast<int>(CookieInclusionStatus::NUM_EXCLUSION_REASONS);
34 // Test exactly one exclusion reason and multiple (two) exclusion reasons.
35 for (int i = 0; i < num_exclusion_reasons; ++i) {
36 auto reason1 = static_cast<CookieInclusionStatus::ExclusionReason>(i);
37 CookieInclusionStatus status_one_reason(reason1);
38 EXPECT_FALSE(status_one_reason.IsInclude());
39 EXPECT_TRUE(status_one_reason.HasExclusionReason(reason1));
40 EXPECT_TRUE(status_one_reason.HasOnlyExclusionReason(reason1));
41
42 for (int j = 0; j < num_exclusion_reasons; ++j) {
43 if (i == j)
44 continue;
45 auto reason2 = static_cast<CookieInclusionStatus::ExclusionReason>(j);
46
47 EXPECT_FALSE(status_one_reason.HasExclusionReason(reason2));
48 EXPECT_FALSE(status_one_reason.HasOnlyExclusionReason(reason2));
49
50 CookieInclusionStatus status_two_reasons = status_one_reason;
51 status_two_reasons.AddExclusionReason(reason2);
52 EXPECT_FALSE(status_two_reasons.IsInclude());
53
54 if (reason1 != CookieInclusionStatus::EXCLUDE_THIRD_PARTY_PHASEOUT &&
55 reason2 != CookieInclusionStatus::EXCLUDE_THIRD_PARTY_PHASEOUT) {
56 EXPECT_TRUE(status_two_reasons.HasExclusionReason(reason1));
57 EXPECT_TRUE(status_two_reasons.HasExclusionReason(reason2));
58 }
59 }
60 }
61 }
62
TEST(CookieInclusionStatusTest,ExcludeStatus_MaybeClearThirdPartyPhaseoutReason)63 TEST(CookieInclusionStatusTest,
64 ExcludeStatus_MaybeClearThirdPartyPhaseoutReason) {
65 int num_exclusion_reasons =
66 static_cast<int>(CookieInclusionStatus::NUM_EXCLUSION_REASONS);
67 CookieInclusionStatus::ExclusionReason reason1 =
68 CookieInclusionStatus::EXCLUDE_THIRD_PARTY_PHASEOUT;
69 const CookieInclusionStatus status_one_reason(reason1);
70 ASSERT_FALSE(status_one_reason.IsInclude());
71 ASSERT_TRUE(status_one_reason.HasOnlyExclusionReason(reason1));
72
73 for (int j = 0; j < num_exclusion_reasons; ++j) {
74 auto reason2 = static_cast<CookieInclusionStatus::ExclusionReason>(j);
75 if (reason1 == reason2) {
76 continue;
77 }
78 EXPECT_FALSE(status_one_reason.HasExclusionReason(reason2)) << reason2;
79
80 CookieInclusionStatus status_two_reasons = status_one_reason;
81 status_two_reasons.AddExclusionReason(reason2);
82 EXPECT_FALSE(status_two_reasons.IsInclude());
83
84 if (reason2 == CookieInclusionStatus::
85 EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET) {
86 EXPECT_TRUE(status_two_reasons.HasExclusionReason(reason1));
87 EXPECT_TRUE(status_two_reasons.HasExclusionReason(reason2));
88 } else {
89 EXPECT_TRUE(status_two_reasons.HasOnlyExclusionReason(reason2));
90 }
91 }
92 }
93
TEST(CookieInclusionStatusTest,AddExclusionReason_MaybeClearThirdPartyPhaseoutReason)94 TEST(CookieInclusionStatusTest,
95 AddExclusionReason_MaybeClearThirdPartyPhaseoutReason) {
96 CookieInclusionStatus status;
97 status.AddWarningReason(CookieInclusionStatus::WARN_THIRD_PARTY_PHASEOUT);
98 ASSERT_TRUE(status.ShouldWarn());
99 ASSERT_TRUE(status.HasExactlyWarningReasonsForTesting(
100 {CookieInclusionStatus::WARN_THIRD_PARTY_PHASEOUT}));
101 // Adding an exclusion reason should clear 3PCD warning reason.
102 status.AddExclusionReason(
103 CookieInclusionStatus::EXCLUDE_THIRD_PARTY_PHASEOUT);
104 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
105 {CookieInclusionStatus::EXCLUDE_THIRD_PARTY_PHASEOUT}));
106 EXPECT_FALSE(status.ShouldWarn());
107
108 status.AddExclusionReason(
109 CookieInclusionStatus::
110 EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET);
111 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
112 {CookieInclusionStatus::EXCLUDE_THIRD_PARTY_PHASEOUT,
113 CookieInclusionStatus::
114 EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET}));
115 // Adding an exclusion reason unrelated with 3PCD should clear 3PCD related
116 // exclusion reasons.
117 status.AddExclusionReason(
118 CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE);
119 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
120 {CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE,
121 // TODO(crbug.com/1516673): This should also be removed.
122 CookieInclusionStatus::
123 EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET}));
124 EXPECT_FALSE(status.IsInclude());
125 }
126
TEST(CookieInclusionStatusTest,AddExclusionReason)127 TEST(CookieInclusionStatusTest, AddExclusionReason) {
128 CookieInclusionStatus status;
129 status.AddWarningReason(
130 CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE);
131 status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
132 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
133 {CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR}));
134 // Adding an exclusion reason other than
135 // EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX or
136 // EXCLUDE_SAMESITE_NONE_INSECURE should clear any SameSite warning.
137 EXPECT_FALSE(status.ShouldWarn());
138
139 status = CookieInclusionStatus();
140 status.AddWarningReason(
141 CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT);
142 status.AddExclusionReason(
143 CookieInclusionStatus::EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX);
144 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
145 {CookieInclusionStatus::EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
146 EXPECT_TRUE(status.HasExactlyWarningReasonsForTesting(
147 {CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT}));
148 }
149
TEST(CookieInclusionStatusTest,CheckEachWarningReason)150 TEST(CookieInclusionStatusTest, CheckEachWarningReason) {
151 CookieInclusionStatus status;
152
153 int num_warning_reasons =
154 static_cast<int>(CookieInclusionStatus::NUM_WARNING_REASONS);
155 EXPECT_FALSE(status.ShouldWarn());
156 for (int i = 0; i < num_warning_reasons; ++i) {
157 auto reason = static_cast<CookieInclusionStatus::WarningReason>(i);
158 status.AddWarningReason(reason);
159 EXPECT_TRUE(status.IsInclude());
160 EXPECT_TRUE(status.ShouldWarn());
161 EXPECT_TRUE(status.HasWarningReason(reason));
162 for (int j = 0; j < num_warning_reasons; ++j) {
163 if (i == j)
164 continue;
165 EXPECT_FALSE(status.HasWarningReason(
166 static_cast<CookieInclusionStatus::WarningReason>(j)));
167 }
168 status.RemoveWarningReason(reason);
169 EXPECT_FALSE(status.ShouldWarn());
170 }
171 }
172
TEST(CookieInclusionStatusTest,RemoveExclusionReason)173 TEST(CookieInclusionStatusTest, RemoveExclusionReason) {
174 CookieInclusionStatus status(CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
175 ASSERT_TRUE(
176 status.HasExclusionReason(CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR));
177
178 status.RemoveExclusionReason(CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
179 EXPECT_FALSE(
180 status.HasExclusionReason(CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR));
181
182 // Removing a nonexistent exclusion reason doesn't do anything.
183 ASSERT_FALSE(
184 status.HasExclusionReason(CookieInclusionStatus::NUM_EXCLUSION_REASONS));
185 status.RemoveExclusionReason(CookieInclusionStatus::NUM_EXCLUSION_REASONS);
186 EXPECT_FALSE(
187 status.HasExclusionReason(CookieInclusionStatus::NUM_EXCLUSION_REASONS));
188 }
189
TEST(CookieInclusionStatusTest,RemoveWarningReason)190 TEST(CookieInclusionStatusTest, RemoveWarningReason) {
191 CookieInclusionStatus status(
192 CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR,
193 CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE);
194 EXPECT_TRUE(status.ShouldWarn());
195 ASSERT_TRUE(status.HasWarningReason(
196 CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE));
197
198 status.RemoveWarningReason(
199 CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE);
200 EXPECT_FALSE(status.ShouldWarn());
201 EXPECT_FALSE(status.HasWarningReason(
202 CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE));
203
204 // Removing a nonexistent warning reason doesn't do anything.
205 ASSERT_FALSE(status.HasWarningReason(
206 CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT));
207 status.RemoveWarningReason(
208 CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT);
209 EXPECT_FALSE(status.ShouldWarn());
210 EXPECT_FALSE(status.HasWarningReason(
211 CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT));
212 }
213
TEST(CookieInclusionStatusTest,HasSchemefulDowngradeWarning)214 TEST(CookieInclusionStatusTest, HasSchemefulDowngradeWarning) {
215 std::vector<CookieInclusionStatus::WarningReason> downgrade_warnings = {
216 CookieInclusionStatus::WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE,
217 CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE,
218 CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE,
219 CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE,
220 CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE,
221 };
222
223 CookieInclusionStatus empty_status;
224 EXPECT_FALSE(empty_status.HasSchemefulDowngradeWarning());
225
226 CookieInclusionStatus not_downgrade;
227 not_downgrade.AddWarningReason(
228 CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT);
229 EXPECT_FALSE(not_downgrade.HasSchemefulDowngradeWarning());
230
231 for (auto warning : downgrade_warnings) {
232 CookieInclusionStatus status;
233 status.AddWarningReason(warning);
234 CookieInclusionStatus::WarningReason reason;
235
236 EXPECT_TRUE(status.HasSchemefulDowngradeWarning(&reason));
237 EXPECT_EQ(warning, reason);
238 }
239 }
240
TEST(CookieInclusionStatusTest,ShouldRecordDowngradeMetrics)241 TEST(CookieInclusionStatusTest, ShouldRecordDowngradeMetrics) {
242 EXPECT_TRUE(CookieInclusionStatus::MakeFromReasonsForTesting({})
243 .ShouldRecordDowngradeMetrics());
244
245 EXPECT_TRUE(CookieInclusionStatus::MakeFromReasonsForTesting(
246 {
247 CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT,
248 })
249 .ShouldRecordDowngradeMetrics());
250
251 EXPECT_TRUE(CookieInclusionStatus::MakeFromReasonsForTesting(
252 {
253 CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
254 })
255 .ShouldRecordDowngradeMetrics());
256
257 EXPECT_TRUE(CookieInclusionStatus::MakeFromReasonsForTesting(
258 {
259 CookieInclusionStatus::
260 EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
261 })
262 .ShouldRecordDowngradeMetrics());
263
264 // Note: the following cases cannot occur under normal circumstances.
265 EXPECT_TRUE(CookieInclusionStatus::MakeFromReasonsForTesting(
266 {
267 CookieInclusionStatus::
268 EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
269 CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
270 })
271 .ShouldRecordDowngradeMetrics());
272 EXPECT_FALSE(CookieInclusionStatus::MakeFromReasonsForTesting(
273 {
274 CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE,
275 CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
276 })
277 .ShouldRecordDowngradeMetrics());
278 }
279
TEST(CookieInclusionStatusTest,RemoveExclusionReasons)280 TEST(CookieInclusionStatusTest, RemoveExclusionReasons) {
281 CookieInclusionStatus status =
282 CookieInclusionStatus::MakeFromReasonsForTesting({
283 CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR,
284 CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT,
285 CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
286 });
287 ASSERT_TRUE(status.HasExactlyExclusionReasonsForTesting({
288 CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR,
289 CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT,
290 CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
291 }));
292
293 status.RemoveExclusionReasons(
294 {CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR,
295 CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR,
296 CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT});
297 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting({
298 CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
299 }));
300
301 // Removing a nonexistent exclusion reason doesn't do anything.
302 ASSERT_FALSE(
303 status.HasExclusionReason(CookieInclusionStatus::NUM_EXCLUSION_REASONS));
304 status.RemoveExclusionReasons({CookieInclusionStatus::NUM_EXCLUSION_REASONS});
305 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting({
306 CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
307 }));
308 }
309
TEST(CookieInclusionStatusTest,ValidateExclusionAndWarningFromWire)310 TEST(CookieInclusionStatusTest, ValidateExclusionAndWarningFromWire) {
311 uint32_t exclusion_reasons = 0ul;
312 uint32_t warning_reasons = 0ul;
313
314 EXPECT_TRUE(CookieInclusionStatus::ValidateExclusionAndWarningFromWire(
315 exclusion_reasons, warning_reasons));
316
317 exclusion_reasons = static_cast<uint32_t>(~0ul);
318 warning_reasons = static_cast<uint32_t>(~0ul);
319 EXPECT_FALSE(CookieInclusionStatus::ValidateExclusionAndWarningFromWire(
320 exclusion_reasons, warning_reasons));
321 EXPECT_FALSE(CookieInclusionStatus::ValidateExclusionAndWarningFromWire(
322 exclusion_reasons, 0u));
323 EXPECT_FALSE(CookieInclusionStatus::ValidateExclusionAndWarningFromWire(
324 0u, warning_reasons));
325
326 exclusion_reasons = (1u << CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH);
327 warning_reasons = (1u << CookieInclusionStatus::WARN_PORT_MISMATCH);
328 EXPECT_TRUE(CookieInclusionStatus::ValidateExclusionAndWarningFromWire(
329 exclusion_reasons, warning_reasons));
330
331 exclusion_reasons = (1u << CookieInclusionStatus::NUM_EXCLUSION_REASONS);
332 warning_reasons = (1u << CookieInclusionStatus::NUM_WARNING_REASONS);
333 EXPECT_FALSE(CookieInclusionStatus::ValidateExclusionAndWarningFromWire(
334 exclusion_reasons, warning_reasons));
335
336 exclusion_reasons =
337 (1u << (CookieInclusionStatus::NUM_EXCLUSION_REASONS - 1));
338 warning_reasons = (1u << (CookieInclusionStatus::NUM_WARNING_REASONS - 1));
339 EXPECT_TRUE(CookieInclusionStatus::ValidateExclusionAndWarningFromWire(
340 exclusion_reasons, warning_reasons));
341 }
342
TEST(CookieInclusionStatusTest,ExcludedByUserPreferences)343 TEST(CookieInclusionStatusTest, ExcludedByUserPreferences) {
344 CookieInclusionStatus status =
345 CookieInclusionStatus::MakeFromReasonsForTesting(
346 {CookieInclusionStatus::ExclusionReason::EXCLUDE_USER_PREFERENCES});
347 EXPECT_TRUE(status.ExcludedByUserPreferences());
348
349 status = CookieInclusionStatus::MakeFromReasonsForTesting({
350 CookieInclusionStatus::ExclusionReason::EXCLUDE_USER_PREFERENCES,
351 CookieInclusionStatus::ExclusionReason::EXCLUDE_FAILURE_TO_STORE,
352 });
353 EXPECT_FALSE(status.ExcludedByUserPreferences());
354
355 status = CookieInclusionStatus::MakeFromReasonsForTesting({
356 CookieInclusionStatus::ExclusionReason::EXCLUDE_USER_PREFERENCES,
357 CookieInclusionStatus::ExclusionReason::
358 EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET,
359 });
360 EXPECT_TRUE(status.ExcludedByUserPreferences());
361
362 status = CookieInclusionStatus::MakeFromReasonsForTesting({
363 CookieInclusionStatus::ExclusionReason::
364 EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET,
365 });
366 EXPECT_FALSE(status.ExcludedByUserPreferences());
367
368 status = CookieInclusionStatus::MakeFromReasonsForTesting({
369 CookieInclusionStatus::ExclusionReason::
370 EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET,
371 CookieInclusionStatus::ExclusionReason::EXCLUDE_FAILURE_TO_STORE,
372 });
373 EXPECT_FALSE(status.ExcludedByUserPreferences());
374
375 status = CookieInclusionStatus::MakeFromReasonsForTesting({
376 CookieInclusionStatus::ExclusionReason::EXCLUDE_USER_PREFERENCES,
377 CookieInclusionStatus::ExclusionReason::
378 EXCLUDE_THIRD_PARTY_BLOCKED_WITHIN_FIRST_PARTY_SET,
379 CookieInclusionStatus::ExclusionReason::EXCLUDE_FAILURE_TO_STORE,
380 });
381 EXPECT_FALSE(status.ExcludedByUserPreferences());
382 }
383
384 } // namespace net
385