1 // Copyright 2012 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/canonical_cookie.h"
6
7 #include <memory>
8 #include <optional>
9 #include <string>
10 #include <vector>
11
12 #include "base/test/metrics/histogram_tester.h"
13 #include "base/test/scoped_feature_list.h"
14 #include "base/time/time.h"
15 #include "build/build_config.h"
16 #include "net/base/features.h"
17 #include "net/cookies/canonical_cookie_test_helpers.h"
18 #include "net/cookies/cookie_constants.h"
19 #include "net/cookies/cookie_inclusion_status.h"
20 #include "net/cookies/cookie_options.h"
21 #include "net/cookies/cookie_partition_key.h"
22 #include "net/cookies/parsed_cookie.h"
23 #include "net/http/http_util.h"
24 #include "testing/gmock/include/gmock/gmock-matchers.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "url/gurl.h"
28 #include "url/third_party/mozilla/url_parse.h"
29
30 namespace net {
31
32 namespace {
33 const std::vector<std::string> kCookieableSchemes = {"http", "https", "ws",
34 "wss"};
35
36 // Helper for testing BuildCookieLine
MatchCookieLineToVector(const std::string & line,const std::vector<std::unique_ptr<CanonicalCookie>> & cookies)37 void MatchCookieLineToVector(
38 const std::string& line,
39 const std::vector<std::unique_ptr<CanonicalCookie>>& cookies) {
40 std::vector<CanonicalCookie> list;
41 for (const auto& cookie : cookies)
42 list.push_back(*cookie);
43 EXPECT_EQ(line, CanonicalCookie::BuildCookieLine(list));
44 }
45
46 } // namespace
47
48 using testing::_;
49 using testing::AllOf;
50 using testing::Eq;
51 using testing::Not;
52 using testing::Property;
53
TEST(CanonicalCookieTest,Constructor)54 TEST(CanonicalCookieTest, Constructor) {
55 base::Time current_time = base::Time::Now();
56
57 // CreateUnsafeCookieForTesting just forwards to the constructor.
58 auto cookie1 = CanonicalCookie::CreateUnsafeCookieForTesting(
59 "A", "2", "www.example.com", "/test", current_time, base::Time(),
60 base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
61 COOKIE_PRIORITY_DEFAULT, std::nullopt, CookieSourceScheme::kSecure, 443);
62 EXPECT_EQ("A", cookie1->Name());
63 EXPECT_EQ("2", cookie1->Value());
64 EXPECT_EQ("www.example.com", cookie1->Domain());
65 EXPECT_EQ("/test", cookie1->Path());
66 EXPECT_FALSE(cookie1->SecureAttribute());
67 EXPECT_FALSE(cookie1->IsHttpOnly());
68 EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie1->SameSite());
69 EXPECT_EQ(CookiePriority::COOKIE_PRIORITY_DEFAULT, cookie1->Priority());
70 EXPECT_FALSE(cookie1->IsPartitioned());
71 EXPECT_EQ(cookie1->SourceScheme(), CookieSourceScheme::kSecure);
72 EXPECT_EQ(cookie1->SourcePort(), 443);
73
74 auto cookie2 = CanonicalCookie::CreateUnsafeCookieForTesting(
75 "A", "2", ".www.example.com", "/", current_time, base::Time(),
76 base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
77 COOKIE_PRIORITY_DEFAULT,
78 CookiePartitionKey::FromURLForTesting(GURL("https://foo.com")),
79 CookieSourceScheme::kNonSecure, 65536);
80 EXPECT_EQ("A", cookie2->Name());
81 EXPECT_EQ("2", cookie2->Value());
82 EXPECT_EQ(".www.example.com", cookie2->Domain());
83 EXPECT_EQ("/", cookie2->Path());
84 EXPECT_FALSE(cookie2->SecureAttribute());
85 EXPECT_FALSE(cookie2->IsHttpOnly());
86 EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie2->SameSite());
87 EXPECT_EQ(CookiePriority::COOKIE_PRIORITY_DEFAULT, cookie2->Priority());
88 EXPECT_TRUE(cookie2->IsPartitioned());
89 EXPECT_EQ(cookie2->SourceScheme(), CookieSourceScheme::kNonSecure);
90 // Because the port can be set explicitly in the constructor its value can be
91 // independent of the other parameters. In this case, test that an out of
92 // range port is kept out of range.
93 EXPECT_EQ(cookie2->SourcePort(), 65536);
94
95 // Set Secure to true but don't specify source_scheme or port.
96 auto cookie3 = CanonicalCookie::CreateUnsafeCookieForTesting(
97 "A", "2", ".www.example.com", "/", current_time, base::Time(),
98 base::Time(), base::Time(), true /* secure */, false,
99 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT);
100 EXPECT_TRUE(cookie3->SecureAttribute());
101 EXPECT_EQ(cookie3->SourceScheme(), CookieSourceScheme::kUnset);
102 EXPECT_EQ(cookie3->SourcePort(), url::PORT_UNSPECIFIED);
103
104 auto cookie4 = CanonicalCookie::CreateUnsafeCookieForTesting(
105 "A", "2", ".www.example.com", "/test", current_time, base::Time(),
106 base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
107 COOKIE_PRIORITY_DEFAULT);
108 EXPECT_EQ("A", cookie4->Name());
109 EXPECT_EQ("2", cookie4->Value());
110 EXPECT_EQ(".www.example.com", cookie4->Domain());
111 EXPECT_EQ("/test", cookie4->Path());
112 EXPECT_FALSE(cookie4->SecureAttribute());
113 EXPECT_FALSE(cookie4->IsHttpOnly());
114 EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie4->SameSite());
115 EXPECT_FALSE(cookie4->IsPartitioned());
116 EXPECT_EQ(cookie4->SourceScheme(), CookieSourceScheme::kUnset);
117 EXPECT_EQ(cookie4->SourcePort(), url::PORT_UNSPECIFIED);
118
119 // Test some port edge cases: unspecified.
120 auto cookie5 = CanonicalCookie::CreateUnsafeCookieForTesting(
121 "A", "2", ".www.example.com", "/", current_time, base::Time(),
122 base::Time(), base::Time(), true /* secure */, false,
123 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, std::nullopt,
124 CookieSourceScheme::kUnset, url::PORT_UNSPECIFIED);
125 EXPECT_EQ(cookie5->SourcePort(), url::PORT_UNSPECIFIED);
126
127 // Test some port edge cases: invalid.
128 auto cookie6 = CanonicalCookie::CreateUnsafeCookieForTesting(
129 "A", "2", ".www.example.com", "/", current_time, base::Time(),
130 base::Time(), base::Time(), true /* secure */, false,
131 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, std::nullopt,
132 CookieSourceScheme::kUnset, url::PORT_INVALID);
133 EXPECT_EQ(cookie6->SourcePort(), url::PORT_INVALID);
134 }
135
TEST(CanonicalCookieTest,CreationCornerCases)136 TEST(CanonicalCookieTest, CreationCornerCases) {
137 base::Time creation_time = base::Time::Now();
138 std::unique_ptr<CanonicalCookie> cookie;
139 std::optional<base::Time> server_time = std::nullopt;
140
141 // Space in name.
142 cookie = CanonicalCookie::CreateForTesting(
143 GURL("http://www.example.com/test/foo.html"), "A C=2", creation_time,
144 server_time);
145 EXPECT_TRUE(cookie.get());
146 EXPECT_EQ("A C", cookie->Name());
147
148 // Semicolon in path.
149 cookie = CanonicalCookie::CreateForTesting(GURL("http://fool/;/"), "*",
150 creation_time, server_time);
151 EXPECT_TRUE(cookie.get());
152
153 // Control characters in name or value.
154 CookieInclusionStatus status;
155 cookie = CanonicalCookie::Create(GURL("http://www.example.com/test/foo.html"),
156 "\b=foo", creation_time, server_time,
157 /*cookie_partition_key=*/std::nullopt,
158 /*block_truncated=*/true,
159 CookieSourceType::kUnknown, &status);
160 EXPECT_FALSE(cookie.get());
161 EXPECT_TRUE(status.HasExclusionReason(
162 CookieInclusionStatus::ExclusionReason::EXCLUDE_DISALLOWED_CHARACTER));
163 cookie = CanonicalCookie::Create(GURL("http://www.example.com/test/foo.html"),
164 "bar=\b", creation_time, server_time,
165 /*cookie_partition_key=*/std::nullopt,
166 /*block_truncated=*/true,
167 CookieSourceType::kUnknown, &status);
168 EXPECT_FALSE(cookie.get());
169 EXPECT_TRUE(status.HasExclusionReason(
170 CookieInclusionStatus::ExclusionReason::EXCLUDE_DISALLOWED_CHARACTER));
171
172 // The ParsedCookie constructor unit tests cover many edge cases related to
173 // invalid sizes when parsing a cookie line, and since CanonicalCookie::Create
174 // creates a ParsedCookie immediately, there's no point in replicating all
175 // of those tests here. We should test that the corresponding ExclusionReason
176 // gets passed back correctly, though.
177 std::string too_long_value(ParsedCookie::kMaxCookieNamePlusValueSize + 1,
178 'a');
179
180 cookie = CanonicalCookie::Create(GURL("http://www.example.com/test/foo.html"),
181 too_long_value, creation_time, server_time,
182 /*cookie_partition_key=*/std::nullopt,
183 /*block_truncated=*/true,
184 CookieSourceType::kUnknown, &status);
185 EXPECT_FALSE(cookie.get());
186 EXPECT_TRUE(
187 status.HasExclusionReason(CookieInclusionStatus::ExclusionReason::
188 EXCLUDE_NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE));
189 }
190
TEST(CanonicalCookieTest,Create)191 TEST(CanonicalCookieTest, Create) {
192 // Test creating cookies from a cookie string.
193 GURL url("http://www.example.com/test/foo.html");
194 GURL https_url("https://www.example.com/test/foo.html");
195 base::Time creation_time = base::Time::Now();
196 std::optional<base::Time> server_time = std::nullopt;
197
198 std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::CreateForTesting(
199 url, "A=2", creation_time, server_time));
200 EXPECT_EQ("A", cookie->Name());
201 EXPECT_EQ("2", cookie->Value());
202 EXPECT_EQ("www.example.com", cookie->Domain());
203 EXPECT_EQ("/test", cookie->Path());
204 EXPECT_FALSE(cookie->SecureAttribute());
205 EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kNonSecure);
206 EXPECT_EQ(cookie->SourcePort(), 80);
207
208 GURL url2("http://www.foo.com");
209 cookie = CanonicalCookie::CreateForTesting(url2, "B=1", creation_time,
210 server_time);
211 EXPECT_EQ("B", cookie->Name());
212 EXPECT_EQ("1", cookie->Value());
213 EXPECT_EQ("www.foo.com", cookie->Domain());
214 EXPECT_EQ("/", cookie->Path());
215 EXPECT_FALSE(cookie->SecureAttribute());
216 EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kNonSecure);
217 EXPECT_EQ(cookie->SourcePort(), 80);
218
219 // Test creating secure cookies. Secure scheme is not checked upon creation,
220 // so a URL of any scheme can create a Secure cookie.
221 cookie = CanonicalCookie::CreateForTesting(url, "A=2; Secure", creation_time,
222 server_time);
223 EXPECT_TRUE(cookie->SecureAttribute());
224
225 cookie = CanonicalCookie::CreateForTesting(https_url, "A=2; Secure",
226 creation_time, server_time);
227 EXPECT_TRUE(cookie->SecureAttribute());
228
229 GURL url3("https://www.foo.com");
230 cookie = CanonicalCookie::CreateForTesting(url3, "A=2; Secure", creation_time,
231 server_time);
232 EXPECT_TRUE(cookie->SecureAttribute());
233 EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kSecure);
234
235 cookie = CanonicalCookie::CreateForTesting(url3, "A=2", creation_time,
236 server_time);
237 EXPECT_FALSE(cookie->SecureAttribute());
238 EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kSecure);
239
240 // Test creating cookie from localhost URL.
241 cookie = CanonicalCookie::CreateForTesting(GURL("http://localhost/path"),
242 "A=2", creation_time, server_time);
243 EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kNonSecure);
244
245 cookie = CanonicalCookie::CreateForTesting(GURL("http://127.0.0.1/path"),
246 "A=2", creation_time, server_time);
247 EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kNonSecure);
248
249 cookie = CanonicalCookie::CreateForTesting(GURL("http://[::1]/path"), "A=2",
250 creation_time, server_time);
251 EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kNonSecure);
252
253 cookie = CanonicalCookie::CreateForTesting(GURL("https://localhost/path"),
254 "A=2", creation_time, server_time);
255 EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kSecure);
256
257 cookie = CanonicalCookie::CreateForTesting(GURL("https://127.0.0.1/path"),
258 "A=2", creation_time, server_time);
259 EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kSecure);
260
261 cookie = CanonicalCookie::CreateForTesting(GURL("https://[::1]/path"), "A=2",
262 creation_time, server_time);
263 EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kSecure);
264
265 // Test creating http only cookies. HttpOnly is not checked upon creation.
266 cookie = CanonicalCookie::CreateForTesting(url, "A=2; HttpOnly",
267 creation_time, server_time);
268 EXPECT_TRUE(cookie->IsHttpOnly());
269
270 cookie = CanonicalCookie::CreateForTesting(url, "A=2; HttpOnly",
271 creation_time, server_time);
272 EXPECT_TRUE(cookie->IsHttpOnly());
273
274 // Test creating SameSite cookies. SameSite is not checked upon creation.
275 cookie = CanonicalCookie::CreateForTesting(url, "A=2; SameSite=Strict",
276 creation_time, server_time);
277 ASSERT_TRUE(cookie.get());
278 EXPECT_EQ(CookieSameSite::STRICT_MODE, cookie->SameSite());
279 cookie = CanonicalCookie::CreateForTesting(url, "A=2; SameSite=Lax",
280 creation_time, server_time);
281 ASSERT_TRUE(cookie.get());
282 EXPECT_EQ(CookieSameSite::LAX_MODE, cookie->SameSite());
283 cookie = CanonicalCookie::CreateForTesting(url, "A=2; SameSite=Extended",
284 creation_time, server_time);
285 ASSERT_TRUE(cookie.get());
286 EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
287 cookie = CanonicalCookie::CreateForTesting(url, "A=2; SameSite=None",
288 creation_time, server_time);
289 ASSERT_TRUE(cookie.get());
290 EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
291 cookie =
292 CanonicalCookie::CreateForTesting(url, "A=2", creation_time, server_time);
293 ASSERT_TRUE(cookie.get());
294 EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
295
296 // Test creating cookies with different ports.
297 cookie = CanonicalCookie::CreateForTesting(GURL("http://www.foo.com"), "B=1",
298 creation_time, server_time);
299 EXPECT_EQ(cookie->SourcePort(), 80);
300
301 cookie = CanonicalCookie::CreateForTesting(GURL("http://www.foo.com:81"),
302 "B=1", creation_time, server_time);
303 EXPECT_EQ(cookie->SourcePort(), 81);
304
305 cookie = CanonicalCookie::CreateForTesting(GURL("https://www.foo.com"), "B=1",
306 creation_time, server_time);
307 EXPECT_EQ(cookie->SourcePort(), 443);
308
309 cookie = CanonicalCookie::CreateForTesting(GURL("https://www.foo.com:1234"),
310 "B=1", creation_time, server_time);
311 EXPECT_EQ(cookie->SourcePort(), 1234);
312
313 cookie = CanonicalCookie::CreateForTesting(GURL("http://www.foo.com:443"),
314 "B=1", creation_time, server_time);
315 EXPECT_EQ(cookie->SourcePort(), 443);
316
317 // An invalid port leads to an invalid GURL, which causes cookie creation
318 // to fail.
319 CookieInclusionStatus status;
320 cookie = CanonicalCookie::Create(
321 GURL("http://www.foo.com:70000"), "B=1", creation_time, server_time,
322 /*cookie_partition_key=*/std::nullopt,
323 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
324 EXPECT_FALSE(cookie.get());
325 EXPECT_TRUE(status.HasExclusionReason(
326 CookieInclusionStatus::ExclusionReason::EXCLUDE_FAILURE_TO_STORE));
327 }
328
TEST(CanonicalCookieTest,CreateInvalidUrl)329 TEST(CanonicalCookieTest, CreateInvalidUrl) {
330 base::Time creation_time = base::Time::Now();
331 std::optional<base::Time> server_time = std::nullopt;
332 CookieInclusionStatus status;
333 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
334 GURL("http://.127.0.0.1/path"), "A=2", creation_time, server_time,
335 /*cookie_partition_key=*/std::nullopt, /*block_truncated=*/true,
336 CookieSourceType::kUnknown, &status);
337 EXPECT_FALSE(cookie.get());
338 EXPECT_TRUE(status.HasExclusionReason(
339 CookieInclusionStatus::ExclusionReason::EXCLUDE_FAILURE_TO_STORE));
340 }
341
342 // Test that a cookie string with an empty domain attribute generates a
343 // canonical host cookie.
TEST(CanonicalCookieTest,CreateHostCookieFromString)344 TEST(CanonicalCookieTest, CreateHostCookieFromString) {
345 // Create a new canonical host cookie via empty string domain in the
346 // cookie_line.
347 GURL url("http://www.example.com/test/foo.html");
348 base::Time creation_time = base::Time::Now();
349 std::optional<base::Time> server_time = std::nullopt;
350 std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::CreateForTesting(
351 url, "A=2; domain=; Secure", creation_time, server_time,
352 std::nullopt /*cookie_partition_key*/));
353 EXPECT_EQ("www.example.com", cookie->Domain());
354 EXPECT_TRUE(cookie->IsHostCookie());
355 }
356
TEST(CanonicalCookieTest,CreateNonStandardSameSite)357 TEST(CanonicalCookieTest, CreateNonStandardSameSite) {
358 GURL url("http://www.example.com/test/foo.html");
359 base::Time now = base::Time::Now();
360 std::unique_ptr<CanonicalCookie> cookie;
361 std::optional<base::Time> server_time = std::nullopt;
362
363 // Non-standard value for the SameSite attribute.
364 cookie = CanonicalCookie::CreateForTesting(url, "A=2; SameSite=NonStandard",
365 now, server_time);
366 EXPECT_TRUE(cookie.get());
367 EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
368
369 // Omit value for the SameSite attribute.
370 cookie =
371 CanonicalCookie::CreateForTesting(url, "A=2; SameSite", now, server_time);
372 EXPECT_TRUE(cookie.get());
373 EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
374 }
375
TEST(CanonicalCookieTest,CreateSameSiteInCrossSiteContexts)376 TEST(CanonicalCookieTest, CreateSameSiteInCrossSiteContexts) {
377 GURL url("http://www.example.com/test/foo.html");
378 base::Time now = base::Time::Now();
379 std::unique_ptr<CanonicalCookie> cookie;
380 std::optional<base::Time> server_time = std::nullopt;
381
382 // A cookie can be created from any SameSiteContext regardless of SameSite
383 // value (it is upon setting the cookie that the SameSiteContext comes into
384 // effect).
385 cookie = CanonicalCookie::CreateForTesting(url, "A=2; SameSite=Strict", now,
386 server_time);
387 EXPECT_TRUE(cookie.get());
388 cookie = CanonicalCookie::CreateForTesting(url, "A=2; SameSite=Lax", now,
389 server_time);
390 EXPECT_TRUE(cookie.get());
391 cookie = CanonicalCookie::CreateForTesting(url, "A=2; SameSite=None", now,
392 server_time);
393 EXPECT_TRUE(cookie.get());
394 cookie = CanonicalCookie::CreateForTesting(url, "A=2;", now, server_time);
395 EXPECT_TRUE(cookie.get());
396 }
397
TEST(CanonicalCookieTest,CreateHttpOnly)398 TEST(CanonicalCookieTest, CreateHttpOnly) {
399 GURL url("http://www.example.com/test/foo.html");
400 base::Time now = base::Time::Now();
401 std::optional<base::Time> server_time = std::nullopt;
402 CookieInclusionStatus status;
403
404 // An HttpOnly cookie can be created.
405 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
406 url, "A=2; HttpOnly", now, server_time,
407 /*cookie_partition_key=*/std::nullopt,
408 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
409 EXPECT_TRUE(cookie->IsHttpOnly());
410 EXPECT_TRUE(status.IsInclude());
411 }
412
TEST(CanonicalCookieTest,CreateWithInvalidDomain)413 TEST(CanonicalCookieTest, CreateWithInvalidDomain) {
414 GURL url("http://www.example.com/test/foo.html");
415 base::Time now = base::Time::Now();
416 std::optional<base::Time> server_time = std::nullopt;
417 CookieInclusionStatus status;
418
419 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
420 url, "A=2; Domain=wrongdomain.com", now, server_time,
421 /*cookie_partition_key=*/std::nullopt, /*block_truncated=*/true,
422 CookieSourceType::kUnknown, &status);
423 EXPECT_EQ(nullptr, cookie.get());
424 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
425 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
426 }
427
428 // Creating a cookie for an eTLD is possible, but it must match the hostname and
429 // be a host cookie.
TEST(CanonicalCookieTest,CreateFromPublicSuffix)430 TEST(CanonicalCookieTest, CreateFromPublicSuffix) {
431 GURL url("http://com/path");
432 base::Time now = base::Time::Now();
433 std::optional<base::Time> server_time = std::nullopt;
434 CookieInclusionStatus status;
435
436 // Host cookie can be created for an eTLD.
437 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
438 url, "A=2", now, server_time, std::nullopt,
439 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
440 EXPECT_TRUE(status.IsInclude());
441 EXPECT_TRUE(cookie->IsHostCookie());
442 EXPECT_EQ("com", cookie->Domain());
443
444 // Attempting to create a domain cookie still yields a valid cookie, but only
445 // if the domain attribute is the same as the URL's host, and it becomes a
446 // host cookie only.
447 cookie = CanonicalCookie::Create(
448 url, "A=2; domain=com", now, server_time, std::nullopt,
449 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
450 EXPECT_TRUE(status.IsInclude());
451 EXPECT_TRUE(cookie->IsHostCookie());
452 EXPECT_EQ("com", cookie->Domain());
453
454 // Same thing if the domain attribute is specified with a dot.
455 cookie = CanonicalCookie::Create(
456 url, "A=2; domain=.com", now, server_time, std::nullopt,
457 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
458 EXPECT_TRUE(status.IsInclude());
459 EXPECT_TRUE(cookie->IsHostCookie());
460 EXPECT_EQ("com", cookie->Domain());
461
462 // Capitalization is ok because everything is canonicalized.
463 cookie = CanonicalCookie::Create(
464 url, "A=2; domain=CoM", now, server_time, std::nullopt,
465 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
466 EXPECT_TRUE(status.IsInclude());
467 EXPECT_TRUE(cookie->IsHostCookie());
468 EXPECT_EQ("com", cookie->Domain());
469
470 // Test an eTLD that is more than one label.
471 // If the domain attribute minus any leading dot is the same as the url's
472 // host, allow it to become a host cookie.
473 GURL multilabel_url = GURL("http://co.uk/path");
474 cookie = CanonicalCookie::Create(
475 multilabel_url, "A=2", now, server_time, std::nullopt,
476 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
477 EXPECT_TRUE(status.IsInclude());
478 EXPECT_TRUE(cookie->IsHostCookie());
479 EXPECT_EQ("co.uk", cookie->Domain());
480
481 cookie = CanonicalCookie::Create(
482 multilabel_url, "A=2; domain=co.uk", now, server_time, std::nullopt,
483 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
484 EXPECT_TRUE(status.IsInclude());
485 EXPECT_TRUE(cookie->IsHostCookie());
486 EXPECT_EQ("co.uk", cookie->Domain());
487
488 cookie = CanonicalCookie::Create(
489 multilabel_url, "A=2; domain=.co.uk", now, server_time, std::nullopt,
490 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
491 EXPECT_TRUE(status.IsInclude());
492 EXPECT_TRUE(cookie->IsHostCookie());
493 EXPECT_EQ("co.uk", cookie->Domain());
494
495 // Don't allow setting a domain cookie from a public suffix for a superdomain.
496 cookie = CanonicalCookie::Create(
497 multilabel_url, "A=2; domain=uk", now, server_time, std::nullopt,
498 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
499 EXPECT_EQ(nullptr, cookie.get());
500 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
501 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
502
503 cookie = CanonicalCookie::Create(
504 multilabel_url, "A=2; domain=.uk", now, server_time, std::nullopt,
505 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
506 EXPECT_EQ(nullptr, cookie.get());
507 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
508 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
509
510 // Don't allow setting a domain cookie for an unrelated domain.
511 cookie = CanonicalCookie::Create(
512 multilabel_url, "A=2; domain=foo.com", now, server_time, std::nullopt,
513 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
514 EXPECT_EQ(nullptr, cookie.get());
515 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
516 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
517
518 // Don't allow setting a domain cookie for some other domain with no
519 // registrable domain.
520 cookie = CanonicalCookie::Create(
521 multilabel_url, "A=2; domain=com", now, server_time, std::nullopt,
522 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
523 EXPECT_EQ(nullptr, cookie.get());
524 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
525 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
526 }
527
TEST(CanonicalCookieTest,CreateWithNonASCIIDomain)528 TEST(CanonicalCookieTest, CreateWithNonASCIIDomain) {
529 GURL url("http://www.xn--xample-9ua.com/test/foo.html");
530 base::Time now = base::Time::Now();
531 std::optional<base::Time> server_time = std::nullopt;
532
533 // Test with feature flag enabled.
534 {
535 base::test::ScopedFeatureList feature_list;
536 feature_list.InitAndEnableFeature(features::kCookieDomainRejectNonASCII);
537 CookieInclusionStatus status;
538
539 // Test that non-ascii characters are rejected.
540 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
541 url, "A=1; Domain=\xC3\xA9xample.com", now, server_time,
542 /*cookie_partition_key=*/std::nullopt, /*block_truncated=*/true,
543 CookieSourceType::kUnknown, &status);
544 EXPECT_EQ(nullptr, cookie.get());
545 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
546 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN,
547 CookieInclusionStatus::EXCLUDE_DOMAIN_NON_ASCII}));
548 EXPECT_FALSE(
549 status.HasWarningReason(CookieInclusionStatus::WARN_DOMAIN_NON_ASCII));
550 }
551
552 // Test with feature flag disabled.
553 {
554 base::test::ScopedFeatureList feature_list;
555 feature_list.InitAndDisableFeature(features::kCookieDomainRejectNonASCII);
556 CookieInclusionStatus status2;
557
558 std::unique_ptr<CanonicalCookie> cookie2 = CanonicalCookie::Create(
559 url, "A=2; Domain=\xC3\xA9xample.com", now, server_time,
560 /*cookie_partition_key=*/std::nullopt,
561 /*block_truncated=*/true, CookieSourceType::kUnknown, &status2);
562
563 EXPECT_TRUE(cookie2.get());
564 EXPECT_TRUE(status2.IsInclude());
565 EXPECT_TRUE(
566 status2.HasWarningReason(CookieInclusionStatus::WARN_DOMAIN_NON_ASCII));
567 }
568
569 // Test that regular ascii punycode still works.
570 CookieInclusionStatus status3;
571 std::unique_ptr<CanonicalCookie> cookie3 = CanonicalCookie::Create(
572 url, "A=3; Domain=xn--xample-9ua.com", now, server_time,
573 /*cookie_partition_key=*/std::nullopt, /*block_truncated=*/true,
574 CookieSourceType::kUnknown, &status3);
575 EXPECT_TRUE(cookie3.get());
576 EXPECT_TRUE(status3.IsInclude());
577 EXPECT_FALSE(
578 status3.HasWarningReason(CookieInclusionStatus::WARN_DOMAIN_NON_ASCII));
579 }
580
TEST(CanonicalCookieTest,CreateWithDomainAsIP)581 TEST(CanonicalCookieTest, CreateWithDomainAsIP) {
582 GURL url("http://1.1.1.1");
583 GURL url6("http://[2606:2800:220:1:248:1893:25c8:1946]");
584
585 base::Time now = base::Time::Now();
586 std::optional<base::Time> server_time = std::nullopt;
587 CookieInclusionStatus status;
588
589 const struct {
590 const GURL url;
591 const std::string cookie_line;
592 const bool expectedResult;
593 } kTests[] = {
594 {url, "d=1;Domain=1.1.1.1;", true},
595 {url, "dd=1;Domain=.1.1.1.1;", true},
596 {url, "ds=1;Domain=1.1.1;", false},
597 {url, "dsd=1;Domain=.1.1.1;", false},
598 {url, "dx=1;Domain=0x01.0x1.0x1.0x1;", false},
599 {url, "dxd=1;Domain=.0x01.0x1.0x1.0x1;", false},
600 {url, "do=1;Domain=0001.0001.0001.0001;", false},
601 {url, "d10=1;Domain=16843009;", false},
602 {url, "d16=value;Domain=0x1010101;", false},
603 {url, "d8=1;Domain=0100200401;", false},
604 {url, "dm=1;Domain=00001.0x01.1.001;", false},
605 {url6, "d1ipv6=1;Domain=[2606:2800:220:1:248:1893:25c8:1946];", true},
606 {url6, "dd1ipv6=1;Domain=.[2606:2800:220:1:248:1893:25c8:1946];", true},
607 {url6, "dc1ipv6=1;Domain=[2606:2800:220:1:248:1893:25C8:1946];", true},
608 {url6, "d2ipv6=1;Domain=2606:2800:220:1:248:1893:25c8:1946;", false},
609 {url6, "dd2ipv6=1;Domain=.2606:2800:220:1:248:1893:25c8:1946;", false},
610 {url6, "dc2ipv6=1;Domain=2606:2800:220:1:248:1893:25C8:1946;", false},
611 };
612
613 for (const auto& test : kTests) {
614 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
615 test.url, test.cookie_line, now, server_time,
616 /*cookie_partition_key=*/std::nullopt,
617 /*block_truncated=*/true, CookieSourceType::kUnknown, &status);
618 if (test.expectedResult) {
619 ASSERT_TRUE(cookie.get());
620 EXPECT_EQ(test.url.host(), cookie->Domain());
621 } else {
622 EXPECT_EQ(nullptr, cookie.get());
623 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
624 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
625 }
626 }
627 }
628
TEST(CanonicalCookieTest,CreateWithPartitioned)629 TEST(CanonicalCookieTest, CreateWithPartitioned) {
630 GURL url("https://www.example.com/test/foo.html");
631 base::Time creation_time = base::Time::Now();
632 std::optional<base::Time> server_time = std::nullopt;
633 auto partition_key =
634 CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com"));
635 CookieInclusionStatus status;
636
637 // Valid Partitioned attribute
638 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
639 url, "__Host-A=2; Partitioned; Path=/; Secure", creation_time,
640 server_time, partition_key, /*block_truncated=*/true,
641 CookieSourceType::kUnknown, &status);
642 ASSERT_TRUE(cookie.get());
643 EXPECT_TRUE(status.IsInclude());
644 EXPECT_TRUE(cookie->SecureAttribute());
645 EXPECT_TRUE(cookie->IsPartitioned());
646 EXPECT_EQ(partition_key, cookie->PartitionKey());
647 EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
648
649 // Create() without Partitioned in the cookie line should not result in a
650 // partitioned cookie.
651 status = CookieInclusionStatus();
652 cookie = CanonicalCookie::Create(url, "__Host-A=2; Path=/; Secure",
653 creation_time, server_time, partition_key,
654 /*block_truncated=*/true,
655 CookieSourceType::kUnknown, &status);
656 ASSERT_TRUE(cookie.get());
657 EXPECT_TRUE(status.IsInclude());
658 EXPECT_FALSE(cookie->IsPartitioned());
659 EXPECT_FALSE(cookie->PartitionKey());
660
661 // Partitioned cookies with no __Host- prefix are still valid if they still
662 // have Secure, Path=/, and no Domain.
663 status = CookieInclusionStatus();
664 cookie = CanonicalCookie::Create(url, "A=2; Partitioned; Path=/; Secure",
665 creation_time, server_time, partition_key,
666 /*block_truncated=*/true,
667 CookieSourceType::kUnknown, &status);
668 EXPECT_TRUE(cookie.get());
669 EXPECT_TRUE(status.IsInclude());
670 EXPECT_TRUE(cookie->IsPartitioned());
671 EXPECT_EQ(partition_key, cookie->PartitionKey());
672
673 // Invalid Partitioned attribute: No Secure attribute.
674 status = CookieInclusionStatus();
675 cookie = CanonicalCookie::Create(url, "A=2; Partitioned; Path=/",
676 creation_time, server_time, partition_key,
677 /*block_truncated=*/true,
678 CookieSourceType::kUnknown, &status);
679 EXPECT_FALSE(cookie.get());
680 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
681 {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED}));
682
683 // Partitioned attribute: No Path attribute.
684 status = CookieInclusionStatus();
685 cookie = CanonicalCookie::Create(url, "A=2; Partitioned; Secure",
686 creation_time, server_time, partition_key,
687 /*block_truncated=*/true,
688 CookieSourceType::kUnknown, &status);
689 EXPECT_TRUE(cookie.get());
690 EXPECT_TRUE(status.IsInclude());
691 EXPECT_TRUE(cookie->IsPartitioned());
692 EXPECT_EQ(partition_key, cookie->PartitionKey());
693
694 // Partitioned attribute: Path attribute not equal to "/".
695 status = CookieInclusionStatus();
696 cookie = CanonicalCookie::Create(
697 url, "A=2; Partitioned; Path=/foobar; Secure", creation_time, server_time,
698 partition_key, /*block_truncated=*/true, CookieSourceType::kUnknown,
699 &status);
700 EXPECT_TRUE(cookie.get());
701 EXPECT_TRUE(status.IsInclude());
702 EXPECT_TRUE(cookie->IsPartitioned());
703 EXPECT_EQ(partition_key, cookie->PartitionKey());
704
705 // Partitioned attribute: Domain cookie.
706 status = CookieInclusionStatus();
707 cookie = CanonicalCookie::Create(
708 url, "A=2; Partitioned; Path=/; Secure; Domain=example.com",
709 creation_time, server_time, partition_key, /*block_truncated=*/true,
710 CookieSourceType::kUnknown, &status);
711 EXPECT_TRUE(cookie.get());
712 LOG(ERROR) << status;
713 EXPECT_TRUE(status.IsInclude());
714 EXPECT_TRUE(cookie->IsPartitioned());
715 EXPECT_EQ(partition_key, cookie->PartitionKey());
716
717 // No Partitioned attribute but with a nonce.
718 status = CookieInclusionStatus();
719 auto partition_key_with_nonce =
720 std::make_optional(CookiePartitionKey::FromURLForTesting(
721 GURL("https://toplevelsite.com"),
722 CookiePartitionKey::AncestorChainBit::kCrossSite,
723 base::UnguessableToken::Create()));
724 cookie = CanonicalCookie::Create(
725 url, "__Host-A=2; Path=/; Secure", creation_time, server_time,
726 partition_key_with_nonce, /*block_truncated=*/true,
727 CookieSourceType::kUnknown, &status);
728 EXPECT_TRUE(cookie.get());
729 EXPECT_TRUE(status.IsInclude());
730 EXPECT_TRUE(cookie->IsPartitioned());
731 EXPECT_EQ(partition_key_with_nonce, cookie->PartitionKey());
732 }
733
TEST(CanonicalCookieTest,CreateWithPartitioned_Localhost)734 TEST(CanonicalCookieTest, CreateWithPartitioned_Localhost) {
735 GURL url("http://localhost:8000/foo/bar.html");
736 base::Time creation_time = base::Time::Now();
737 std::optional<base::Time> server_time = std::nullopt;
738 auto partition_key =
739 CookiePartitionKey::FromURLForTesting(GURL("http://localhost:8000"));
740 CookieInclusionStatus status;
741
742 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
743 url, "foo=bar; Path=/; Secure; Partitioned", creation_time, server_time,
744 partition_key, /*block_truncated=*/true, CookieSourceType::kUnknown,
745 &status);
746 ASSERT_TRUE(cookie.get());
747 EXPECT_TRUE(status.IsInclude());
748 EXPECT_TRUE(cookie->SecureAttribute());
749 EXPECT_TRUE(cookie->IsPartitioned());
750 EXPECT_EQ(partition_key, cookie->PartitionKey());
751 EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
752 }
753
TEST(CanonicalCookieTest,CreateWithMaxAge)754 TEST(CanonicalCookieTest, CreateWithMaxAge) {
755 GURL url("http://www.example.com/test/foo.html");
756 base::Time creation_time = base::Time::Now();
757 std::optional<base::Time> server_time = std::nullopt;
758
759 // Max-age with positive integer.
760 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateForTesting(
761 url, "A=1; max-age=60", creation_time, server_time);
762 EXPECT_TRUE(cookie.get());
763 EXPECT_TRUE(cookie->IsPersistent());
764 EXPECT_FALSE(cookie->IsExpired(creation_time));
765 EXPECT_EQ(base::Seconds(60) + creation_time, cookie->ExpiryDate());
766 EXPECT_TRUE(cookie->IsCanonical());
767
768 // Max-age with expires (max-age should take precedence).
769 cookie = CanonicalCookie::CreateForTesting(
770 url, "A=1; expires=01-Jan-1970, 00:00:00 GMT; max-age=60", creation_time,
771 server_time);
772 EXPECT_TRUE(cookie.get());
773 EXPECT_TRUE(cookie->IsPersistent());
774 EXPECT_FALSE(cookie->IsExpired(creation_time));
775 EXPECT_EQ(base::Seconds(60) + creation_time, cookie->ExpiryDate());
776 EXPECT_TRUE(cookie->IsCanonical());
777
778 // Max-age=0 should create an expired cookie with expiry equal to the earliest
779 // representable time.
780 cookie = CanonicalCookie::CreateForTesting(url, "A=1; max-age=0",
781 creation_time, server_time);
782 EXPECT_TRUE(cookie.get());
783 EXPECT_TRUE(cookie->IsPersistent());
784 EXPECT_TRUE(cookie->IsExpired(creation_time));
785 EXPECT_EQ(base::Time::Min(), cookie->ExpiryDate());
786 EXPECT_TRUE(cookie->IsCanonical());
787
788 // Negative max-age should create an expired cookie with expiry equal to the
789 // earliest representable time.
790 cookie = CanonicalCookie::CreateForTesting(url, "A=1; max-age=-1",
791 creation_time, server_time);
792 EXPECT_TRUE(cookie.get());
793 EXPECT_TRUE(cookie->IsPersistent());
794 EXPECT_TRUE(cookie->IsExpired(creation_time));
795 EXPECT_EQ(base::Time::Min(), cookie->ExpiryDate());
796 EXPECT_TRUE(cookie->IsCanonical());
797
798 // Max-age with whitespace (should be trimmed out).
799 cookie = CanonicalCookie::CreateForTesting(url, "A=1; max-age = 60 ; Secure",
800 creation_time, server_time);
801 EXPECT_TRUE(cookie.get());
802 EXPECT_TRUE(cookie->IsPersistent());
803 EXPECT_FALSE(cookie->IsExpired(creation_time));
804 EXPECT_EQ(base::Seconds(60) + creation_time, cookie->ExpiryDate());
805 EXPECT_TRUE(cookie->IsCanonical());
806
807 // Max-age with non-integer should be ignored.
808 cookie = CanonicalCookie::CreateForTesting(url, "A=1; max-age=abcd",
809 creation_time, server_time);
810 EXPECT_TRUE(cookie.get());
811 EXPECT_FALSE(cookie->IsPersistent());
812 EXPECT_FALSE(cookie->IsExpired(creation_time));
813 EXPECT_TRUE(cookie->IsCanonical());
814
815 // Overflow max-age should be clipped.
816 cookie = CanonicalCookie::CreateForTesting(
817 url,
818 "A=1; "
819 "max-age="
820 "9999999999999999999999999999999999999999999"
821 "999999999999999999999999999999999999999999",
822 creation_time, server_time);
823 EXPECT_TRUE(cookie.get());
824 EXPECT_TRUE(cookie->IsPersistent());
825 EXPECT_FALSE(cookie->IsExpired(creation_time));
826 EXPECT_EQ(creation_time + base::Days(400), cookie->ExpiryDate());
827 EXPECT_TRUE(cookie->IsCanonical());
828
829 // Underflow max-age should be clipped.
830 cookie = CanonicalCookie::CreateForTesting(
831 url,
832 "A=1; "
833 "max-age=-"
834 "9999999999999999999999999999999999999999999"
835 "999999999999999999999999999999999999999999",
836 creation_time, server_time);
837 EXPECT_TRUE(cookie.get());
838 EXPECT_TRUE(cookie->IsPersistent());
839 EXPECT_TRUE(cookie->IsExpired(creation_time));
840 EXPECT_EQ(base::Time::Min(), cookie->ExpiryDate());
841 EXPECT_TRUE(cookie->IsCanonical());
842 }
843
TEST(CanonicalCookieTest,CreateWithExpires)844 TEST(CanonicalCookieTest, CreateWithExpires) {
845 GURL url("http://www.example.com/test/foo.html");
846 base::Time creation_time = base::Time::Now();
847 std::optional<base::Time> server_time = std::nullopt;
848
849 // Expires in the past
850 base::Time past_date = base::Time::Now() - base::Days(10);
851 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateForTesting(
852 url, "A=1; expires=" + HttpUtil::TimeFormatHTTP(past_date), creation_time,
853 server_time);
854 EXPECT_TRUE(cookie.get());
855 EXPECT_TRUE(cookie->IsPersistent());
856 EXPECT_TRUE(cookie->IsExpired(creation_time));
857 EXPECT_TRUE((past_date - cookie->ExpiryDate()).magnitude() <
858 base::Seconds(1));
859 EXPECT_TRUE(cookie->IsCanonical());
860
861 // Expires in the future
862 base::Time future_date = base::Time::Now() + base::Days(10);
863 cookie = CanonicalCookie::CreateForTesting(
864 url, "A=1; expires=" + HttpUtil::TimeFormatHTTP(future_date),
865 creation_time, server_time);
866 EXPECT_TRUE(cookie.get());
867 EXPECT_TRUE(cookie->IsPersistent());
868 EXPECT_FALSE(cookie->IsExpired(creation_time));
869 EXPECT_TRUE((future_date - cookie->ExpiryDate()).magnitude() <
870 base::Seconds(1));
871 EXPECT_TRUE(cookie->IsCanonical());
872
873 // Expires in the far future
874 future_date = base::Time::Now() + base::Days(800);
875 cookie = CanonicalCookie::CreateForTesting(
876 url, "A=1; expires=" + HttpUtil::TimeFormatHTTP(future_date),
877 creation_time, server_time);
878 EXPECT_TRUE(cookie.get());
879 EXPECT_TRUE(cookie->IsPersistent());
880 EXPECT_FALSE(cookie->IsExpired(creation_time));
881 EXPECT_TRUE(
882 (cookie->ExpiryDate() - creation_time - base::Days(400)).magnitude() <
883 base::Seconds(1));
884 EXPECT_TRUE(cookie->IsCanonical());
885
886 // Expires in the far future using CreateUnsafeCookieForTesting.
887 cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
888 "A", "1", url.host(), url.path(), creation_time, base::Time::Max(),
889 base::Time(), base::Time(), true, false, CookieSameSite::UNSPECIFIED,
890 COOKIE_PRIORITY_HIGH, std::nullopt /* cookie_partition_key */,
891 CookieSourceScheme::kSecure, 443);
892 EXPECT_TRUE(cookie.get());
893 EXPECT_TRUE(cookie->IsPersistent());
894 EXPECT_FALSE(cookie->IsExpired(creation_time));
895 EXPECT_EQ(base::Time::Max(), cookie->ExpiryDate());
896 EXPECT_EQ(base::Time(), cookie->LastUpdateDate());
897 EXPECT_FALSE(cookie->IsCanonical());
898
899 // Expires in the far future using FromStorage.
900 cookie = CanonicalCookie::FromStorage(
901 "A", "B", "www.foo.com", "/bar", creation_time, base::Time::Max(),
902 base::Time(), base::Time(), false /*secure*/, false /*httponly*/,
903 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
904 std::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 443,
905 CookieSourceType::kUnknown);
906 EXPECT_TRUE(cookie.get());
907 EXPECT_TRUE(cookie->IsPersistent());
908 EXPECT_FALSE(cookie->IsExpired(creation_time));
909 EXPECT_EQ(base::Time::Max(), cookie->ExpiryDate());
910 EXPECT_EQ(base::Time(), cookie->LastUpdateDate());
911 EXPECT_FALSE(cookie->IsCanonical());
912 }
913
TEST(CanonicalCookieTest,EmptyExpiry)914 TEST(CanonicalCookieTest, EmptyExpiry) {
915 GURL url("http://www7.ipdl.inpit.go.jp/Tokujitu/tjkta.ipdl?N0000=108");
916 base::Time creation_time = base::Time::Now();
917 std::optional<base::Time> server_time = std::nullopt;
918
919 std::string cookie_line =
920 "ACSTM=20130308043820420042; path=/; domain=ipdl.inpit.go.jp; Expires=";
921 std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::CreateForTesting(
922 url, cookie_line, creation_time, server_time));
923 EXPECT_TRUE(cookie.get());
924 EXPECT_FALSE(cookie->IsPersistent());
925 EXPECT_FALSE(cookie->IsExpired(creation_time));
926 EXPECT_EQ(base::Time(), cookie->ExpiryDate());
927
928 // With a stale server time
929 server_time = creation_time - base::Hours(1);
930 cookie = CanonicalCookie::CreateForTesting(url, cookie_line, creation_time,
931 server_time);
932 EXPECT_TRUE(cookie.get());
933 EXPECT_FALSE(cookie->IsPersistent());
934 EXPECT_FALSE(cookie->IsExpired(creation_time));
935 EXPECT_EQ(base::Time(), cookie->ExpiryDate());
936
937 // With a future server time
938 server_time = creation_time + base::Hours(1);
939 cookie = CanonicalCookie::CreateForTesting(url, cookie_line, creation_time,
940 server_time);
941 EXPECT_TRUE(cookie.get());
942 EXPECT_FALSE(cookie->IsPersistent());
943 EXPECT_FALSE(cookie->IsExpired(creation_time));
944 EXPECT_EQ(base::Time(), cookie->ExpiryDate());
945 }
946
TEST(CanonicalCookieTest,CreateWithLastUpdate)947 TEST(CanonicalCookieTest, CreateWithLastUpdate) {
948 GURL url("http://www.example.com/test/foo.html");
949 base::Time creation_time = base::Time::Now() - base::Days(1);
950 base::Time last_update_time = base::Time::Now() - base::Hours(1);
951 std::optional<base::Time> server_time = std::nullopt;
952
953 // Creating a cookie sets the last update date as now.
954 std::unique_ptr<CanonicalCookie> cookie =
955 CanonicalCookie::CreateForTesting(url, "A=1", creation_time, server_time,
956 /*cookie_partition_key=*/std::nullopt);
957 ASSERT_TRUE(cookie.get());
958 EXPECT_TRUE((base::Time::Now() - cookie->LastUpdateDate()).magnitude() <
959 base::Seconds(1));
960
961 // Creating a sanitized cookie sets the last update date as now.
962 cookie = CanonicalCookie::CreateSanitizedCookie(
963 url, "A", "1", url.host(), url.path(), creation_time, base::Time(),
964 creation_time, /*secure=*/true,
965 /*http_only=*/false, CookieSameSite::NO_RESTRICTION,
966 COOKIE_PRIORITY_DEFAULT,
967 /*partition_key=*/std::nullopt, /*status=*/nullptr);
968 ASSERT_TRUE(cookie.get());
969 EXPECT_TRUE((base::Time::Now() - cookie->LastUpdateDate()).magnitude() <
970 base::Seconds(1));
971
972 // Creating an unsafe cookie allows us to set the last update date.
973 cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
974 "A", "1", url.host(), url.path(), creation_time, base::Time(),
975 base::Time(), last_update_time, /*secure=*/true,
976 /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
977 COOKIE_PRIORITY_DEFAULT,
978 /*partition_key=*/std::nullopt, CookieSourceScheme::kSecure,
979 /*source_port=*/443);
980 ASSERT_TRUE(cookie.get());
981 EXPECT_EQ(last_update_time, cookie->LastUpdateDate());
982
983 // Loading a cookie from storage allows us to set the last update date.
984 cookie = CanonicalCookie::FromStorage(
985 "A", "1", url.host(), url.path(), creation_time, base::Time(),
986 base::Time(), last_update_time, /*secure=*/true,
987 /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
988 COOKIE_PRIORITY_DEFAULT,
989 /*partition_key=*/std::nullopt, CookieSourceScheme::kSecure,
990 /*source_port=*/443, CookieSourceType::kUnknown);
991 ASSERT_TRUE(cookie.get());
992 EXPECT_EQ(last_update_time, cookie->LastUpdateDate());
993 }
994
TEST(CanonicalCookieTest,IsEquivalent)995 TEST(CanonicalCookieTest, IsEquivalent) {
996 GURL url("https://www.example.com/");
997 std::string cookie_name = "A";
998 std::string cookie_value = "2EDA-EF";
999 std::string cookie_domain = ".www.example.com";
1000 std::string cookie_path = "/path";
1001 base::Time creation_time = base::Time::Now();
1002 base::Time expiration_time = creation_time + base::Days(2);
1003 base::Time update_time = creation_time + base::Days(1);
1004 bool secure = false;
1005 bool httponly = false;
1006 CookieSameSite same_site = CookieSameSite::NO_RESTRICTION;
1007
1008 // Test that a cookie is equivalent to itself.
1009 auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1010 cookie_name, cookie_value, cookie_domain, cookie_path, creation_time,
1011 expiration_time, base::Time(), update_time, secure, httponly, same_site,
1012 COOKIE_PRIORITY_MEDIUM);
1013 EXPECT_TRUE(cookie->IsEquivalent(*cookie));
1014 EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*cookie));
1015
1016 // Test that two identical cookies are equivalent.
1017 auto other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1018 cookie_name, cookie_value, cookie_domain, cookie_path, creation_time,
1019 expiration_time, base::Time(), update_time, secure, httponly, same_site,
1020 COOKIE_PRIORITY_MEDIUM);
1021 EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
1022 EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1023
1024 // Tests that use different variations of attribute values that
1025 // DON'T affect cookie equivalence.
1026 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1027 cookie_name, "2", cookie_domain, cookie_path, creation_time,
1028 expiration_time, base::Time(), update_time, secure, httponly, same_site,
1029 COOKIE_PRIORITY_HIGH);
1030 EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
1031 EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1032 EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1033
1034 base::Time other_creation_time = creation_time + base::Minutes(2);
1035 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1036 cookie_name, "2", cookie_domain, cookie_path, other_creation_time,
1037 expiration_time, base::Time(), update_time, secure, httponly, same_site,
1038 COOKIE_PRIORITY_MEDIUM);
1039 EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
1040 EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1041 EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1042
1043 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1044 cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
1045 expiration_time, base::Time(), update_time, true, httponly, same_site,
1046 COOKIE_PRIORITY_LOW);
1047 EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
1048 EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1049 EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1050
1051 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1052 cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
1053 expiration_time, base::Time(), update_time, secure, true, same_site,
1054 COOKIE_PRIORITY_LOW);
1055 EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
1056 EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1057 EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1058
1059 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1060 cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
1061 expiration_time, base::Time(), update_time, secure, httponly,
1062 CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_LOW);
1063 EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
1064 EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1065 EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1066
1067 // Test the effect of a differing last_update_time on equivalency.
1068 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1069 cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
1070 expiration_time, base::Time(), base::Time(), secure, httponly, same_site,
1071 COOKIE_PRIORITY_LOW);
1072 EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
1073 EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1074 EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1075 EXPECT_FALSE(cookie->HasEquivalentDataMembers(*other_cookie));
1076
1077 // Cookies whose names mismatch are not equivalent.
1078 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1079 "B", cookie_value, cookie_domain, cookie_path, creation_time,
1080 expiration_time, base::Time(), update_time, secure, httponly, same_site,
1081 COOKIE_PRIORITY_MEDIUM);
1082 EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
1083 EXPECT_FALSE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1084 EXPECT_FALSE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1085
1086 // A domain cookie at 'www.example.com' is not equivalent to a host cookie
1087 // at the same domain. These are, however, equivalent according to the laxer
1088 // rules of 'IsEquivalentForSecureCookieMatching'.
1089 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1090 cookie_name, cookie_value, "www.example.com", cookie_path, creation_time,
1091 expiration_time, base::Time(), update_time, secure, httponly, same_site,
1092 COOKIE_PRIORITY_MEDIUM);
1093 EXPECT_TRUE(cookie->IsDomainCookie());
1094 EXPECT_FALSE(other_cookie->IsDomainCookie());
1095 EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
1096 EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1097 EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1098
1099 // Likewise, a cookie on 'example.com' is not equivalent to a cookie on
1100 // 'www.example.com', but they are equivalent for secure cookie matching.
1101 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1102 cookie_name, cookie_value, ".example.com", cookie_path, creation_time,
1103 expiration_time, base::Time(), update_time, secure, httponly, same_site,
1104 COOKIE_PRIORITY_MEDIUM);
1105 EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
1106 EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1107 EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1108
1109 // Paths are a bit more complicated. 'IsEquivalent' requires an exact path
1110 // match, while secure cookie matching uses a more relaxed 'IsOnPath' check.
1111 // That is, |cookie| set on '/path' is not equivalent in either way to
1112 // |other_cookie| set on '/test' or '/path/subpath'. It is, however,
1113 // equivalent for secure cookie matching to |other_cookie| set on '/'.
1114 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1115 cookie_name, cookie_value, cookie_domain, "/test", creation_time,
1116 expiration_time, base::Time(), update_time, secure, httponly, same_site,
1117 COOKIE_PRIORITY_MEDIUM);
1118 EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
1119 EXPECT_FALSE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1120 EXPECT_FALSE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1121
1122 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1123 cookie_name, cookie_value, cookie_domain, cookie_path + "/subpath",
1124 creation_time, expiration_time, base::Time(), update_time, secure,
1125 httponly, same_site, COOKIE_PRIORITY_MEDIUM);
1126 EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
1127 // The path comparison is asymmetric
1128 EXPECT_FALSE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1129 EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1130
1131 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1132 cookie_name, cookie_value, cookie_domain, "/", creation_time,
1133 expiration_time, base::Time(), update_time, secure, httponly, same_site,
1134 COOKIE_PRIORITY_MEDIUM);
1135 EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
1136 EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1137 EXPECT_FALSE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1138
1139 // Partitioned cookies are not equivalent to unpartitioned cookies.
1140 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1141 cookie_name, cookie_value, cookie_domain, cookie_path, creation_time,
1142 expiration_time, base::Time(), update_time, secure, httponly, same_site,
1143 COOKIE_PRIORITY_MEDIUM,
1144 CookiePartitionKey::FromURLForTesting(GURL("https://foo.com")));
1145 EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
1146 EXPECT_FALSE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1147
1148 // Partitioned cookies are equal if they have the same partition key.
1149 auto paritioned_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1150 cookie_name, cookie_value, cookie_domain, cookie_path, creation_time,
1151 expiration_time, base::Time(), update_time, secure, httponly, same_site,
1152 COOKIE_PRIORITY_MEDIUM,
1153 CookiePartitionKey::FromURLForTesting(GURL("https://foo.com")));
1154 EXPECT_TRUE(paritioned_cookie->IsEquivalent(*other_cookie));
1155 EXPECT_TRUE(
1156 paritioned_cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1157
1158 // Partitioned cookies with different partition keys are not equal
1159 other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1160 cookie_name, cookie_value, cookie_domain, cookie_path, creation_time,
1161 expiration_time, base::Time(), update_time, secure, httponly, same_site,
1162 COOKIE_PRIORITY_MEDIUM,
1163 CookiePartitionKey::FromURLForTesting(GURL("https://bar.com")));
1164 EXPECT_FALSE(paritioned_cookie->IsEquivalent(*other_cookie));
1165 EXPECT_FALSE(
1166 paritioned_cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
1167 }
1168
TEST(CanonicalCookieTest,IsEquivalentForSecureCookieMatching)1169 TEST(CanonicalCookieTest, IsEquivalentForSecureCookieMatching) {
1170 struct {
1171 struct {
1172 const char* name;
1173 const char* domain;
1174 const char* path;
1175 std::optional<CookiePartitionKey> cookie_partition_key = std::nullopt;
1176 } cookie, secure_cookie;
1177 bool equivalent;
1178 bool is_symmetric; // Whether the reverse comparison has the same result.
1179 } kTests[] = {
1180 // Equivalent to itself
1181 {{"A", "a.foo.com", "/"}, {"A", "a.foo.com", "/"}, true, true},
1182 {{"A", ".a.foo.com", "/"}, {"A", ".a.foo.com", "/"}, true, true},
1183 // Names are different
1184 {{"A", "a.foo.com", "/"}, {"B", "a.foo.com", "/"}, false, true},
1185 // Host cookie and domain cookie with same hostname match
1186 {{"A", "a.foo.com", "/"}, {"A", ".a.foo.com", "/"}, true, true},
1187 // Subdomains and superdomains match
1188 {{"A", "a.foo.com", "/"}, {"A", ".foo.com", "/"}, true, true},
1189 {{"A", ".a.foo.com", "/"}, {"A", ".foo.com", "/"}, true, true},
1190 {{"A", "a.foo.com", "/"}, {"A", "foo.com", "/"}, true, true},
1191 {{"A", ".a.foo.com", "/"}, {"A", "foo.com", "/"}, true, true},
1192 // Different domains don't match
1193 {{"A", "a.foo.com", "/"}, {"A", "b.foo.com", "/"}, false, true},
1194 {{"A", "a.foo.com", "/"}, {"A", "ba.foo.com", "/"}, false, true},
1195 // Path attribute matches if it is a subdomain, but not vice versa.
1196 {{"A", "a.foo.com", "/sub"}, {"A", "a.foo.com", "/"}, true, false},
1197 // Different paths don't match
1198 {{"A", "a.foo.com", "/sub"}, {"A", "a.foo.com", "/other"}, false, true},
1199 {{"A", "a.foo.com", "/a/b"}, {"A", "a.foo.com", "/a/c"}, false, true},
1200 // Partitioned cookies are not equivalent to unpartitioned cookies.
1201 {{"A", ".a.foo.com", "/"},
1202 {"A", ".a.foo.com", "/",
1203 CookiePartitionKey::FromURLForTesting(GURL("https://bar.com"))},
1204 false,
1205 true},
1206 // Partitioned cookies are equivalent if they have the same partition key.
1207 {{"A", "a.foo.com", "/",
1208 CookiePartitionKey::FromURLForTesting(GURL("https://bar.com"))},
1209 {"A", "a.foo.com", "/",
1210 CookiePartitionKey::FromURLForTesting(GURL("https://bar.com"))},
1211 true,
1212 true},
1213 // Partitioned cookies are *not* equivalent if they have the different
1214 // partition keys.
1215 {{"A", "a.foo.com", "/",
1216 CookiePartitionKey::FromURLForTesting(GURL("https://bar.com"))},
1217 {"A", "a.foo.com", "/",
1218 CookiePartitionKey::FromURLForTesting(GURL("https://baz.com"))},
1219 false,
1220 true},
1221 };
1222
1223 for (auto test : kTests) {
1224 auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1225 test.cookie.name, "value1", test.cookie.domain, test.cookie.path,
1226 base::Time(), base::Time(), base::Time(), base::Time(),
1227 false /* secure */, false /* httponly */, CookieSameSite::LAX_MODE,
1228 COOKIE_PRIORITY_MEDIUM, test.cookie.cookie_partition_key);
1229 auto secure_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
1230 test.secure_cookie.name, "value2", test.secure_cookie.domain,
1231 test.secure_cookie.path, base::Time(), base::Time(), base::Time(),
1232 base::Time(), true /* secure */, false /* httponly */,
1233 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_MEDIUM,
1234 test.secure_cookie.cookie_partition_key);
1235
1236 EXPECT_EQ(test.equivalent,
1237 cookie->IsEquivalentForSecureCookieMatching(*secure_cookie));
1238 EXPECT_EQ(test.equivalent == test.is_symmetric,
1239 secure_cookie->IsEquivalentForSecureCookieMatching(*cookie));
1240 }
1241 }
1242
TEST(CanonicalCookieTest,IsEquivalentForOriginBoundCookies)1243 TEST(CanonicalCookieTest, IsEquivalentForOriginBoundCookies) {
1244 auto create_cookie = [](const char* domain_field,
1245 CookieSourceScheme source_scheme, int source_port) {
1246 const char* cookie_name = "A";
1247 const char* cookie_value = "2EDA-EF";
1248 const char* cookie_path = "/";
1249 const base::Time creation_time = base::Time::Now();
1250 const base::Time expiration_time = creation_time + base::Days(2);
1251 const base::Time update_time = creation_time + base::Days(1);
1252 const bool secure = false;
1253 const bool httponly = false;
1254 const CookieSameSite same_site = CookieSameSite::NO_RESTRICTION;
1255 const std::optional<CookiePartitionKey> partition_key = std::nullopt;
1256
1257 return CanonicalCookie::CreateUnsafeCookieForTesting(
1258 cookie_name, cookie_value, domain_field, cookie_path, creation_time,
1259 expiration_time, base::Time(), update_time, secure, httponly, same_site,
1260 COOKIE_PRIORITY_MEDIUM, partition_key, source_scheme, source_port);
1261 };
1262
1263 const char* domain = ".www.example.com";
1264 const char* host_only_domain = "www.example.com";
1265 const CookieSourceScheme http_scheme = CookieSourceScheme::kNonSecure;
1266 const int port_80 = 80;
1267
1268 auto domain_cookie = create_cookie(domain, http_scheme, port_80);
1269
1270 auto host_cookie = create_cookie(host_only_domain, http_scheme, port_80);
1271
1272 // Host cookies are never equivalent to domain cookies.
1273 ASSERT_FALSE(domain_cookie->IsEquivalent(*host_cookie));
1274 ASSERT_FALSE(host_cookie->IsEquivalent(*domain_cookie));
1275
1276 // With neither binding enabled, difference in scheme and port have no effect
1277 // on equivalency.
1278 {
1279 base::test::ScopedFeatureList feature_list;
1280 feature_list.InitWithFeatures({}, {features::kEnableSchemeBoundCookies,
1281 features::kEnablePortBoundCookies});
1282
1283 // Different schemes are equivalent.
1284 auto other_cookie =
1285 create_cookie(domain, CookieSourceScheme::kSecure, port_80);
1286 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1287
1288 other_cookie = create_cookie(domain, CookieSourceScheme::kUnset, port_80);
1289 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1290
1291 other_cookie =
1292 create_cookie(host_only_domain, CookieSourceScheme::kSecure, port_80);
1293 EXPECT_TRUE(host_cookie->IsEquivalent(*other_cookie));
1294
1295 other_cookie =
1296 create_cookie(host_only_domain, CookieSourceScheme::kUnset, port_80);
1297 EXPECT_TRUE(host_cookie->IsEquivalent(*other_cookie));
1298
1299 // Different ports are equivalent.
1300 other_cookie = create_cookie(domain, http_scheme, -1);
1301 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1302
1303 other_cookie = create_cookie(domain, http_scheme, 123);
1304 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1305
1306 other_cookie = create_cookie(host_only_domain, http_scheme, -1);
1307 EXPECT_TRUE(host_cookie->IsEquivalent(*other_cookie));
1308
1309 other_cookie = create_cookie(host_only_domain, http_scheme, 123);
1310 EXPECT_TRUE(host_cookie->IsEquivalent(*other_cookie));
1311
1312 // Different scheme and ports are equivalent.
1313 other_cookie = create_cookie(domain, CookieSourceScheme::kSecure, 123);
1314 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1315
1316 other_cookie =
1317 create_cookie(host_only_domain, CookieSourceScheme::kSecure, 123);
1318 EXPECT_TRUE(host_cookie->IsEquivalent(*other_cookie));
1319 }
1320
1321 // With scheme binding enabled, differences in scheme means cookies are not
1322 // equivalent.
1323 {
1324 base::test::ScopedFeatureList feature_list;
1325 feature_list.InitWithFeatures({features::kEnableSchemeBoundCookies},
1326 {features::kEnablePortBoundCookies});
1327
1328 // Different schemes are not equivalent.
1329 auto other_cookie =
1330 create_cookie(domain, CookieSourceScheme::kSecure, port_80);
1331 EXPECT_FALSE(domain_cookie->IsEquivalent(*other_cookie));
1332
1333 other_cookie = create_cookie(domain, CookieSourceScheme::kUnset, port_80);
1334 EXPECT_FALSE(domain_cookie->IsEquivalent(*other_cookie));
1335
1336 other_cookie =
1337 create_cookie(host_only_domain, CookieSourceScheme::kSecure, port_80);
1338 EXPECT_FALSE(host_cookie->IsEquivalent(*other_cookie));
1339
1340 other_cookie =
1341 create_cookie(host_only_domain, CookieSourceScheme::kUnset, port_80);
1342 EXPECT_FALSE(host_cookie->IsEquivalent(*other_cookie));
1343
1344 // Different ports are equivalent.
1345 other_cookie = create_cookie(domain, http_scheme, -1);
1346 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1347
1348 other_cookie = create_cookie(domain, http_scheme, 123);
1349 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1350
1351 other_cookie = create_cookie(host_only_domain, http_scheme, -1);
1352 EXPECT_TRUE(host_cookie->IsEquivalent(*other_cookie));
1353
1354 other_cookie = create_cookie(host_only_domain, http_scheme, 123);
1355 EXPECT_TRUE(host_cookie->IsEquivalent(*other_cookie));
1356
1357 // Different scheme and ports are not equivalent.
1358 other_cookie = create_cookie(domain, CookieSourceScheme::kSecure, 123);
1359 EXPECT_FALSE(domain_cookie->IsEquivalent(*other_cookie));
1360
1361 other_cookie =
1362 create_cookie(host_only_domain, CookieSourceScheme::kSecure, 123);
1363 EXPECT_FALSE(host_cookie->IsEquivalent(*other_cookie));
1364 }
1365 // With port binding enabled, domain cookies with the different ports are
1366 // equivalent. Host cookies are not equivalent.
1367 {
1368 base::test::ScopedFeatureList feature_list;
1369 feature_list.InitWithFeatures({features::kEnablePortBoundCookies},
1370 {features::kEnableSchemeBoundCookies});
1371
1372 // Different schemes are equivalent.
1373 auto other_cookie =
1374 create_cookie(domain, CookieSourceScheme::kSecure, port_80);
1375 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1376
1377 other_cookie = create_cookie(domain, CookieSourceScheme::kUnset, port_80);
1378 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1379
1380 other_cookie =
1381 create_cookie(host_only_domain, CookieSourceScheme::kSecure, port_80);
1382 EXPECT_TRUE(host_cookie->IsEquivalent(*other_cookie));
1383
1384 other_cookie =
1385 create_cookie(host_only_domain, CookieSourceScheme::kUnset, port_80);
1386 EXPECT_TRUE(host_cookie->IsEquivalent(*other_cookie));
1387
1388 // Different ports are equivalent for domain cookies.
1389 other_cookie = create_cookie(domain, http_scheme, -1);
1390 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1391
1392 other_cookie = create_cookie(domain, http_scheme, 123);
1393 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1394
1395 // But not so for host cookies.
1396 other_cookie = create_cookie(host_only_domain, http_scheme, -1);
1397 EXPECT_FALSE(host_cookie->IsEquivalent(*other_cookie));
1398
1399 other_cookie = create_cookie(host_only_domain, http_scheme, 123);
1400 EXPECT_FALSE(host_cookie->IsEquivalent(*other_cookie));
1401
1402 // Different scheme and ports are equivalent for domain cookies.
1403 other_cookie = create_cookie(domain, CookieSourceScheme::kSecure, 123);
1404 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1405
1406 // But not so for host cookies.
1407 other_cookie =
1408 create_cookie(host_only_domain, CookieSourceScheme::kSecure, 123);
1409 EXPECT_FALSE(host_cookie->IsEquivalent(*other_cookie));
1410 }
1411
1412 // When both scheme and port binding are enabled, different schemes are always
1413 // not equivalent while different ports depend on whether the cookie is host
1414 // or domain.
1415 {
1416 base::test::ScopedFeatureList feature_list;
1417 feature_list.InitWithFeatures({features::kEnablePortBoundCookies,
1418 features::kEnableSchemeBoundCookies},
1419 {});
1420
1421 // Different schemes are not equivalent.
1422 auto other_cookie =
1423 create_cookie(domain, CookieSourceScheme::kSecure, port_80);
1424 EXPECT_FALSE(domain_cookie->IsEquivalent(*other_cookie));
1425
1426 other_cookie = create_cookie(domain, CookieSourceScheme::kSecure, port_80);
1427 EXPECT_FALSE(domain_cookie->IsEquivalent(*other_cookie));
1428
1429 other_cookie =
1430 create_cookie(host_only_domain, CookieSourceScheme::kSecure, port_80);
1431 EXPECT_FALSE(host_cookie->IsEquivalent(*other_cookie));
1432
1433 other_cookie =
1434 create_cookie(host_only_domain, CookieSourceScheme::kUnset, port_80);
1435 EXPECT_FALSE(host_cookie->IsEquivalent(*other_cookie));
1436
1437 // Different ports are equivalent for domain cookies.
1438 other_cookie = create_cookie(domain, http_scheme, -1);
1439 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1440
1441 other_cookie = create_cookie(domain, http_scheme, 123);
1442 EXPECT_TRUE(domain_cookie->IsEquivalent(*other_cookie));
1443
1444 // But not so for host cookies.
1445 other_cookie = create_cookie(host_only_domain, http_scheme, -1);
1446 EXPECT_FALSE(host_cookie->IsEquivalent(*other_cookie));
1447
1448 other_cookie = create_cookie(host_only_domain, http_scheme, 123);
1449 EXPECT_FALSE(host_cookie->IsEquivalent(*other_cookie));
1450
1451 // Different scheme and ports are not equivalent.
1452 other_cookie = create_cookie(domain, CookieSourceScheme::kSecure, 123);
1453 EXPECT_FALSE(domain_cookie->IsEquivalent(*other_cookie));
1454
1455 other_cookie =
1456 create_cookie(host_only_domain, CookieSourceScheme::kSecure, 123);
1457 EXPECT_FALSE(host_cookie->IsEquivalent(*other_cookie));
1458 }
1459 }
1460
TEST(CanonicalCookieTest,IsDomainMatch)1461 TEST(CanonicalCookieTest, IsDomainMatch) {
1462 GURL url("http://www.example.com/test/foo.html");
1463 base::Time creation_time = base::Time::Now();
1464 std::optional<base::Time> server_time = std::nullopt;
1465
1466 std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::CreateForTesting(
1467 url, "A=2", creation_time, server_time));
1468 EXPECT_TRUE(cookie->IsHostCookie());
1469 EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
1470 EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
1471 EXPECT_FALSE(cookie->IsDomainMatch("foo.www.example.com"));
1472 EXPECT_FALSE(cookie->IsDomainMatch("www0.example.com"));
1473 EXPECT_FALSE(cookie->IsDomainMatch("example.com"));
1474
1475 cookie = CanonicalCookie::CreateForTesting(url, "A=2; Domain=www.example.com",
1476 creation_time, server_time);
1477 EXPECT_TRUE(cookie->IsDomainCookie());
1478 EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
1479 EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
1480 EXPECT_TRUE(cookie->IsDomainMatch("foo.www.example.com"));
1481 EXPECT_FALSE(cookie->IsDomainMatch("www0.example.com"));
1482 EXPECT_FALSE(cookie->IsDomainMatch("example.com"));
1483
1484 cookie = CanonicalCookie::CreateForTesting(
1485 url, "A=2; Domain=.www.example.com", creation_time, server_time);
1486 EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
1487 EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
1488 EXPECT_TRUE(cookie->IsDomainMatch("foo.www.example.com"));
1489 EXPECT_FALSE(cookie->IsDomainMatch("www0.example.com"));
1490 EXPECT_FALSE(cookie->IsDomainMatch("example.com"));
1491 }
1492
TEST(CanonicalCookieTest,IsOnPath)1493 TEST(CanonicalCookieTest, IsOnPath) {
1494 base::Time creation_time = base::Time::Now();
1495 std::optional<base::Time> server_time = std::nullopt;
1496
1497 std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::CreateForTesting(
1498 GURL("http://www.example.com"), "A=2", creation_time, server_time));
1499 EXPECT_TRUE(cookie->IsOnPath("/"));
1500 EXPECT_TRUE(cookie->IsOnPath("/test"));
1501 EXPECT_TRUE(cookie->IsOnPath("/test/bar.html"));
1502
1503 // Test the empty string edge case.
1504 EXPECT_FALSE(cookie->IsOnPath(std::string()));
1505
1506 cookie = CanonicalCookie::CreateForTesting(
1507 GURL("http://www.example.com/test/foo.html"), "A=2", creation_time,
1508 server_time);
1509 EXPECT_FALSE(cookie->IsOnPath("/"));
1510 EXPECT_TRUE(cookie->IsOnPath("/test"));
1511 EXPECT_TRUE(cookie->IsOnPath("/test/bar.html"));
1512 EXPECT_TRUE(cookie->IsOnPath("/test/sample/bar.html"));
1513 }
1514
TEST(CanonicalCookieTest,GetEffectiveSameSite)1515 TEST(CanonicalCookieTest, GetEffectiveSameSite) {
1516 struct {
1517 CookieSameSite same_site;
1518 CookieEffectiveSameSite expected_effective_same_site;
1519 // nullopt for following members indicates same effective SameSite result
1520 // for all possible values.
1521 std::optional<CookieAccessSemantics> access_semantics = std::nullopt;
1522 std::optional<bool> is_cookie_recent = std::nullopt;
1523 } kTestCases[] = {
1524 // Explicitly specified SameSite always has the same effective SameSite
1525 // regardless of the access semantics.
1526 {CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION},
1527 {CookieSameSite::LAX_MODE, CookieEffectiveSameSite::LAX_MODE},
1528 {CookieSameSite::STRICT_MODE, CookieEffectiveSameSite::STRICT_MODE},
1529 {CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION},
1530
1531 // UNSPECIFIED always maps to NO_RESTRICTION if LEGACY access semantics.
1532 {CookieSameSite::UNSPECIFIED, CookieEffectiveSameSite::NO_RESTRICTION,
1533 CookieAccessSemantics::LEGACY},
1534
1535 // UNSPECIFIED with non-LEGACY access semantics depends on whether cookie
1536 // is recently created.
1537 {CookieSameSite::UNSPECIFIED,
1538 CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
1539 CookieAccessSemantics::NONLEGACY, true},
1540 {CookieSameSite::UNSPECIFIED,
1541 CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
1542 CookieAccessSemantics::UNKNOWN, true},
1543 {CookieSameSite::UNSPECIFIED, CookieEffectiveSameSite::LAX_MODE,
1544 CookieAccessSemantics::NONLEGACY, false},
1545 {CookieSameSite::UNSPECIFIED, CookieEffectiveSameSite::LAX_MODE,
1546 CookieAccessSemantics::UNKNOWN, false},
1547 };
1548
1549 for (const auto& test : kTestCases) {
1550 std::vector<std::unique_ptr<CanonicalCookie>> cookies;
1551
1552 base::Time now = base::Time::Now();
1553 base::Time recent_creation_time = now - (kLaxAllowUnsafeMaxAge / 4);
1554 base::Time not_recent_creation_time = now - (kLaxAllowUnsafeMaxAge * 4);
1555 base::Time expiry_time = now + (kLaxAllowUnsafeMaxAge / 4);
1556
1557 if (!test.is_cookie_recent.has_value() || *test.is_cookie_recent) {
1558 // Recent session cookie.
1559 cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
1560 "A", "2", "example.test", "/", recent_creation_time, base::Time(),
1561 base::Time(), base::Time(), true /* secure */, false /* httponly */,
1562 test.same_site, COOKIE_PRIORITY_DEFAULT));
1563 // Recent persistent cookie.
1564 cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
1565 "A", "2", "example.test", "/", recent_creation_time, expiry_time,
1566 base::Time(), base::Time(), true /* secure */, false /* httponly */,
1567 test.same_site, COOKIE_PRIORITY_DEFAULT));
1568 }
1569 if (!test.is_cookie_recent.has_value() || !(*test.is_cookie_recent)) {
1570 // Not-recent session cookie.
1571 cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
1572 "A", "2", "example.test", "/", not_recent_creation_time, base::Time(),
1573 base::Time(), base::Time(), true /* secure */, false /* httponly */,
1574 test.same_site, COOKIE_PRIORITY_DEFAULT));
1575 // Not-recent persistent cookie.
1576 cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
1577 "A", "2", "example.test", "/", not_recent_creation_time, expiry_time,
1578 base::Time(), base::Time(), true /* secure */, false /* httponly */,
1579 test.same_site, COOKIE_PRIORITY_DEFAULT));
1580 }
1581
1582 std::vector<CookieAccessSemantics> access_semantics = {
1583 CookieAccessSemantics::UNKNOWN, CookieAccessSemantics::LEGACY,
1584 CookieAccessSemantics::NONLEGACY};
1585 if (test.access_semantics.has_value())
1586 access_semantics = {*test.access_semantics};
1587
1588 for (const auto& cookie : cookies) {
1589 for (const auto semantics : access_semantics) {
1590 EXPECT_EQ(test.expected_effective_same_site,
1591 cookie->GetEffectiveSameSiteForTesting(semantics));
1592 }
1593 }
1594 }
1595 }
1596
TEST(CanonicalCookieTest,IncludeForRequestURL)1597 TEST(CanonicalCookieTest, IncludeForRequestURL) {
1598 GURL url("http://www.example.com");
1599 base::Time creation_time = base::Time::Now();
1600 CookieOptions options = CookieOptions::MakeAllInclusive();
1601 std::optional<base::Time> server_time = std::nullopt;
1602
1603 std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::CreateForTesting(
1604 url, "A=2", creation_time, server_time));
1605 EXPECT_TRUE(
1606 cookie
1607 ->IncludeForRequestURL(
1608 url, options,
1609 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1610 /*delegate_treats_url_as_trustworthy=*/false})
1611 .status.IsInclude());
1612 EXPECT_TRUE(
1613 cookie
1614 ->IncludeForRequestURL(
1615 GURL("http://www.example.com/foo/bar"), options,
1616 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1617 /*delegate_treats_url_as_trustworthy=*/false})
1618 .status.IsInclude());
1619 EXPECT_TRUE(
1620 cookie
1621 ->IncludeForRequestURL(
1622 GURL("https://www.example.com/foo/bar"), options,
1623 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1624 /*delegate_treats_url_as_trustworthy=*/false})
1625 .status.IsInclude());
1626 EXPECT_TRUE(
1627 cookie
1628 ->IncludeForRequestURL(
1629 GURL("https://sub.example.com"), options,
1630 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1631 /*delegate_treats_url_as_trustworthy=*/false})
1632 .status.HasExactlyExclusionReasonsForTesting(
1633 {CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH}));
1634 EXPECT_TRUE(
1635 cookie
1636 ->IncludeForRequestURL(
1637 GURL("https://sub.www.example.com"), options,
1638 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1639 /*delegate_treats_url_as_trustworthy=*/false})
1640 .status.HasExactlyExclusionReasonsForTesting(
1641 {CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH}));
1642 // Test that cookie with a cookie path that does not match the url path are
1643 // not included.
1644 cookie = CanonicalCookie::CreateForTesting(url, "A=2; Path=/foo/bar",
1645 creation_time, server_time);
1646 EXPECT_TRUE(
1647 cookie
1648 ->IncludeForRequestURL(
1649 url, options,
1650 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1651 /*delegate_treats_url_as_trustworthy=*/false})
1652 .status.HasExactlyExclusionReasonsForTesting(
1653 {CookieInclusionStatus::EXCLUDE_NOT_ON_PATH}));
1654 EXPECT_TRUE(
1655 cookie
1656 ->IncludeForRequestURL(
1657 GURL("http://www.example.com/foo/bar/index.html"), options,
1658 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1659 /*delegate_treats_url_as_trustworthy=*/false})
1660 .status.IsInclude());
1661 // Test that a secure cookie is not included for a non secure URL.
1662 GURL secure_url("https://www.example.com");
1663 cookie = CanonicalCookie::CreateForTesting(secure_url, "A=2; Secure",
1664 creation_time, server_time);
1665 EXPECT_TRUE(cookie->SecureAttribute());
1666 EXPECT_TRUE(
1667 cookie
1668 ->IncludeForRequestURL(
1669 secure_url, options,
1670 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1671 /*delegate_treats_url_as_trustworthy=*/false})
1672 .status.IsInclude());
1673 EXPECT_TRUE(
1674 cookie
1675 ->IncludeForRequestURL(
1676 url, options,
1677 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1678 /*delegate_treats_url_as_trustworthy=*/false})
1679 .status.HasExactlyExclusionReasonsForTesting(
1680 {CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
1681
1682 // Test that a delegate can make an exception, however, and ask for a
1683 // non-secure URL to be treated as trustworthy... with a warning.
1684 cookie = CanonicalCookie::CreateForTesting(url, "A=2; Secure", creation_time,
1685 server_time);
1686 ASSERT_TRUE(cookie);
1687 EXPECT_TRUE(cookie->SecureAttribute());
1688 CookieAccessResult result = cookie->IncludeForRequestURL(
1689 url, options,
1690 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1691 /*delegate_treats_url_as_trustworthy=*/true});
1692 EXPECT_TRUE(result.status.IsInclude());
1693 EXPECT_TRUE(result.status.HasWarningReason(
1694 CookieInclusionStatus::WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC));
1695
1696 // The same happens for localhost even w/o delegate intervention.
1697 GURL localhost_url("http://localhost/");
1698 cookie = CanonicalCookie::CreateForTesting(localhost_url, "A=2; Secure",
1699 creation_time, server_time);
1700 ASSERT_TRUE(cookie);
1701 EXPECT_TRUE(cookie->SecureAttribute());
1702 result = cookie->IncludeForRequestURL(
1703 localhost_url, options,
1704 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1705 /*delegate_treats_url_as_trustworthy=*/false});
1706 EXPECT_TRUE(result.status.IsInclude());
1707 EXPECT_TRUE(result.status.HasWarningReason(
1708 CookieInclusionStatus::WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC));
1709
1710 // An unneeded exception doesn't add a warning, however.
1711 cookie = CanonicalCookie::CreateForTesting(secure_url, "A=2; Secure",
1712 creation_time, server_time);
1713 ASSERT_TRUE(cookie);
1714 EXPECT_TRUE(cookie->SecureAttribute());
1715 result = cookie->IncludeForRequestURL(
1716 secure_url, options,
1717 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1718 /*delegate_treats_url_as_trustworthy=*/true});
1719 EXPECT_TRUE(result.status.IsInclude());
1720 EXPECT_FALSE(result.status.ShouldWarn());
1721
1722 // Test that http only cookies are only included if the include httponly flag
1723 // is set on the cookie options.
1724 options.set_include_httponly();
1725 cookie = CanonicalCookie::CreateForTesting(url, "A=2; HttpOnly",
1726 creation_time, server_time);
1727 EXPECT_TRUE(cookie->IsHttpOnly());
1728 EXPECT_TRUE(
1729 cookie
1730 ->IncludeForRequestURL(
1731 url, options,
1732 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1733 /*delegate_treats_url_as_trustworthy=*/false})
1734 .status.IsInclude());
1735 options.set_exclude_httponly();
1736 EXPECT_TRUE(
1737 cookie
1738 ->IncludeForRequestURL(
1739 url, options,
1740 CookieAccessParams{net::CookieAccessSemantics::UNKNOWN,
1741 /*delegate_treats_url_as_trustworthy=*/false})
1742 .status.HasExactlyExclusionReasonsForTesting(
1743 {CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
1744 }
1745
1746 struct IncludeForRequestURLTestCase {
1747 std::string cookie_line;
1748 CookieSameSite expected_samesite;
1749 CookieEffectiveSameSite expected_effective_samesite;
1750 CookieOptions::SameSiteCookieContext request_options_samesite_context;
1751 CookieInclusionStatus expected_inclusion_status;
1752 base::TimeDelta creation_time_delta = base::TimeDelta();
1753 };
1754
VerifyIncludeForRequestURLTestCases(CookieAccessSemantics access_semantics,std::vector<IncludeForRequestURLTestCase> test_cases)1755 void VerifyIncludeForRequestURLTestCases(
1756 CookieAccessSemantics access_semantics,
1757 std::vector<IncludeForRequestURLTestCase> test_cases) {
1758 GURL url("https://example.test");
1759 for (const auto& test : test_cases) {
1760 base::Time creation_time = base::Time::Now() - test.creation_time_delta;
1761 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateForTesting(
1762 url, test.cookie_line, creation_time, std::nullopt /* server_time */);
1763 EXPECT_EQ(test.expected_samesite, cookie->SameSite());
1764
1765 CookieOptions request_options;
1766 request_options.set_same_site_cookie_context(
1767 test.request_options_samesite_context);
1768
1769 EXPECT_THAT(
1770 cookie->IncludeForRequestURL(
1771 url, request_options,
1772 CookieAccessParams{access_semantics,
1773 /*delegate_treats_url_as_trustworthy=*/false}),
1774 MatchesCookieAccessResult(test.expected_inclusion_status,
1775 test.expected_effective_samesite,
1776 access_semantics, true))
1777 << cookie->Name() << "=" << cookie->Value();
1778 }
1779 }
1780
TEST(CanonicalCookieTest,IncludeForRequestURLSameSite)1781 TEST(CanonicalCookieTest, IncludeForRequestURLSameSite) {
1782 const base::TimeDelta kLongAge = kLaxAllowUnsafeMaxAge * 4;
1783 const base::TimeDelta kShortAge = kLaxAllowUnsafeMaxAge / 4;
1784
1785 using SameSiteCookieContext = CookieOptions::SameSiteCookieContext;
1786
1787 // Test cases that are the same regardless of feature status or access
1788 // semantics. For Schemeful Same-Site this means that the context downgrade is
1789 // a no-op (such as for NO_RESTRICTION cookies) or that there is no downgrade:
1790 std::vector<IncludeForRequestURLTestCase> common_test_cases = {
1791 // Strict cookies:
1792 {"Common=1;SameSite=Strict", CookieSameSite::STRICT_MODE,
1793 CookieEffectiveSameSite::STRICT_MODE,
1794 SameSiteCookieContext(SameSiteCookieContext::ContextType::CROSS_SITE),
1795 CookieInclusionStatus(CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)},
1796 {"Common=2;SameSite=Strict", CookieSameSite::STRICT_MODE,
1797 CookieEffectiveSameSite::STRICT_MODE,
1798 SameSiteCookieContext(
1799 SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
1800 CookieInclusionStatus(CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)},
1801 {"Common=3;SameSite=Strict", CookieSameSite::STRICT_MODE,
1802 CookieEffectiveSameSite::STRICT_MODE,
1803 SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX),
1804 CookieInclusionStatus(CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)},
1805 {"Common=4;SameSite=Strict", CookieSameSite::STRICT_MODE,
1806 CookieEffectiveSameSite::STRICT_MODE,
1807 SameSiteCookieContext(
1808 SameSiteCookieContext::ContextType::SAME_SITE_STRICT),
1809 CookieInclusionStatus()},
1810 // Lax cookies:
1811 {"Common=5;SameSite=Lax", CookieSameSite::LAX_MODE,
1812 CookieEffectiveSameSite::LAX_MODE,
1813 SameSiteCookieContext(SameSiteCookieContext::ContextType::CROSS_SITE),
1814 CookieInclusionStatus(CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)},
1815 {"Common=6;SameSite=Lax", CookieSameSite::LAX_MODE,
1816 CookieEffectiveSameSite::LAX_MODE,
1817 SameSiteCookieContext(
1818 SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
1819 CookieInclusionStatus(CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)},
1820 {"Common=7;SameSite=Lax", CookieSameSite::LAX_MODE,
1821 CookieEffectiveSameSite::LAX_MODE,
1822 SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX),
1823 CookieInclusionStatus()},
1824 {"Common=8;SameSite=Lax", CookieSameSite::LAX_MODE,
1825 CookieEffectiveSameSite::LAX_MODE,
1826 SameSiteCookieContext(
1827 SameSiteCookieContext::ContextType::SAME_SITE_STRICT),
1828 CookieInclusionStatus()},
1829 // Lax cookies with downgrade:
1830 {"Common=9;SameSite=Lax", CookieSameSite::LAX_MODE,
1831 CookieEffectiveSameSite::LAX_MODE,
1832 SameSiteCookieContext(
1833 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
1834 SameSiteCookieContext::ContextType::SAME_SITE_LAX),
1835 CookieInclusionStatus()},
1836 // None and Secure cookies:
1837 {"Common=10;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
1838 CookieEffectiveSameSite::NO_RESTRICTION,
1839 SameSiteCookieContext(SameSiteCookieContext::ContextType::CROSS_SITE),
1840 CookieInclusionStatus()},
1841 {"Common=11;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
1842 CookieEffectiveSameSite::NO_RESTRICTION,
1843 SameSiteCookieContext(
1844 SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
1845 CookieInclusionStatus()},
1846 {"Common=12;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
1847 CookieEffectiveSameSite::NO_RESTRICTION,
1848 SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX),
1849 CookieInclusionStatus()},
1850 {"Common=13;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
1851 CookieEffectiveSameSite::NO_RESTRICTION,
1852 SameSiteCookieContext(
1853 SameSiteCookieContext::ContextType::SAME_SITE_STRICT),
1854 CookieInclusionStatus()},
1855 // Because NO_RESTRICTION cookies are always sent, the schemeful context
1856 // downgrades shouldn't matter.
1857 {"Common=14;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
1858 CookieEffectiveSameSite::NO_RESTRICTION,
1859 SameSiteCookieContext(
1860 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
1861 SameSiteCookieContext::ContextType::SAME_SITE_LAX),
1862 CookieInclusionStatus()},
1863 {"Common=15;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
1864 CookieEffectiveSameSite::NO_RESTRICTION,
1865 SameSiteCookieContext(
1866 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
1867 SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
1868 CookieInclusionStatus()},
1869 {"Common=16;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
1870 CookieEffectiveSameSite::NO_RESTRICTION,
1871 SameSiteCookieContext(
1872 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
1873 SameSiteCookieContext::ContextType::CROSS_SITE),
1874 CookieInclusionStatus()},
1875 {"Common=17;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
1876 CookieEffectiveSameSite::NO_RESTRICTION,
1877 SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX,
1878 SameSiteCookieContext::ContextType::CROSS_SITE),
1879 CookieInclusionStatus()},
1880 {"Common=18;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
1881 CookieEffectiveSameSite::NO_RESTRICTION,
1882 SameSiteCookieContext(
1883 SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE,
1884 SameSiteCookieContext::ContextType::CROSS_SITE),
1885 CookieInclusionStatus()},
1886 };
1887
1888 // Test cases where the unspecified-SameSite cookie defaults to SameSite=None
1889 // due to LEGACY access semantics):
1890 std::vector<IncludeForRequestURLTestCase> default_none_test_cases = {
1891 {"DefaultNone=1", CookieSameSite::UNSPECIFIED,
1892 CookieEffectiveSameSite::NO_RESTRICTION,
1893 SameSiteCookieContext(SameSiteCookieContext::ContextType::CROSS_SITE),
1894 CookieInclusionStatus::MakeFromReasonsForTesting(
1895 std::vector<CookieInclusionStatus::ExclusionReason>(),
1896 {CookieInclusionStatus::
1897 WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT})},
1898 {"DefaultNone=2", CookieSameSite::UNSPECIFIED,
1899 CookieEffectiveSameSite::NO_RESTRICTION,
1900 SameSiteCookieContext(
1901 SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
1902 CookieInclusionStatus::MakeFromReasonsForTesting(
1903 std::vector<CookieInclusionStatus::ExclusionReason>(),
1904 {CookieInclusionStatus::
1905 WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT})},
1906
1907 {"DefaultNone=3", CookieSameSite::UNSPECIFIED,
1908 CookieEffectiveSameSite::NO_RESTRICTION,
1909 SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX),
1910 CookieInclusionStatus()},
1911 {"DefaultNone=4", CookieSameSite::UNSPECIFIED,
1912 CookieEffectiveSameSite::NO_RESTRICTION,
1913 SameSiteCookieContext(
1914 SameSiteCookieContext::ContextType::SAME_SITE_STRICT),
1915 CookieInclusionStatus()}};
1916
1917 // Test cases where the unspecified-SameSite cookie defaults to SameSite=Lax:
1918 std::vector<IncludeForRequestURLTestCase> default_lax_test_cases = {
1919 // Unspecified recently-created cookies (with SameSite-by-default):
1920 {"DefaultLax=1", CookieSameSite::UNSPECIFIED,
1921 CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
1922 SameSiteCookieContext(SameSiteCookieContext::ContextType::CROSS_SITE),
1923 CookieInclusionStatus(
1924 CookieInclusionStatus::EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
1925 CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT),
1926 kShortAge},
1927 {"DefaultLax=2", CookieSameSite::UNSPECIFIED,
1928 CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
1929 SameSiteCookieContext(
1930 SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
1931 CookieInclusionStatus::MakeFromReasonsForTesting(
1932 std::vector<CookieInclusionStatus::ExclusionReason>(),
1933 {CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE}),
1934 kShortAge},
1935 {"DefaultLax=3", CookieSameSite::UNSPECIFIED,
1936 CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
1937 SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX),
1938 CookieInclusionStatus(), kShortAge},
1939 {"DefaultLax=4", CookieSameSite::UNSPECIFIED,
1940 CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
1941 SameSiteCookieContext(
1942 SameSiteCookieContext::ContextType::SAME_SITE_STRICT),
1943 CookieInclusionStatus(), kShortAge},
1944 // Unspecified not-recently-created cookies (with SameSite-by-default):
1945 {"DefaultLax=5", CookieSameSite::UNSPECIFIED,
1946 CookieEffectiveSameSite::LAX_MODE,
1947 SameSiteCookieContext(SameSiteCookieContext::ContextType::CROSS_SITE),
1948 CookieInclusionStatus(
1949 CookieInclusionStatus::EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
1950 CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT),
1951 kLongAge},
1952 {"DefaultLax=6", CookieSameSite::UNSPECIFIED,
1953 CookieEffectiveSameSite::LAX_MODE,
1954 SameSiteCookieContext(
1955 SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
1956 CookieInclusionStatus(
1957 CookieInclusionStatus::EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
1958 CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT),
1959 kLongAge},
1960 {"DefaultLax=7", CookieSameSite::UNSPECIFIED,
1961 CookieEffectiveSameSite::LAX_MODE,
1962 SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX),
1963 CookieInclusionStatus(), kLongAge},
1964 {"DefaultLax=8", CookieSameSite::UNSPECIFIED,
1965 CookieEffectiveSameSite::LAX_MODE,
1966 SameSiteCookieContext(
1967 SameSiteCookieContext::ContextType::SAME_SITE_STRICT),
1968 CookieInclusionStatus(), kLongAge},
1969 };
1970
1971 // Test cases that require LEGACY semantics or Schemeful Same-Site to be
1972 // disabled.
1973 std::vector<IncludeForRequestURLTestCase> schemeful_disabled_test_cases = {
1974 {"LEGACY_Schemeful=1;SameSite=Strict", CookieSameSite::STRICT_MODE,
1975 CookieEffectiveSameSite::STRICT_MODE,
1976 SameSiteCookieContext(
1977 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
1978 SameSiteCookieContext::ContextType::SAME_SITE_LAX),
1979 CookieInclusionStatus::MakeFromReasonsForTesting(
1980 std::vector<CookieInclusionStatus::ExclusionReason>(),
1981 {CookieInclusionStatus::WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE})},
1982 {"LEGACY_Schemeful=2;SameSite=Strict", CookieSameSite::STRICT_MODE,
1983 CookieEffectiveSameSite::STRICT_MODE,
1984 SameSiteCookieContext(
1985 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
1986 SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
1987 CookieInclusionStatus::MakeFromReasonsForTesting(
1988 std::vector<CookieInclusionStatus::ExclusionReason>(),
1989 {CookieInclusionStatus::
1990 WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE})},
1991 {"LEGACY_Schemeful=3;SameSite=Strict", CookieSameSite::STRICT_MODE,
1992 CookieEffectiveSameSite::STRICT_MODE,
1993 SameSiteCookieContext(
1994 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
1995 SameSiteCookieContext::ContextType::CROSS_SITE),
1996 CookieInclusionStatus::MakeFromReasonsForTesting(
1997 std::vector<CookieInclusionStatus::ExclusionReason>(),
1998 {CookieInclusionStatus::
1999 WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE})},
2000 {"LEGACY_Schemeful=4;SameSite=Lax", CookieSameSite::LAX_MODE,
2001 CookieEffectiveSameSite::LAX_MODE,
2002 SameSiteCookieContext(
2003 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
2004 SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
2005 CookieInclusionStatus::MakeFromReasonsForTesting(
2006 std::vector<CookieInclusionStatus::ExclusionReason>(),
2007 {CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE})},
2008 {"LEGACY_Schemeful=5;SameSite=Lax", CookieSameSite::LAX_MODE,
2009 CookieEffectiveSameSite::LAX_MODE,
2010 SameSiteCookieContext(
2011 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
2012 SameSiteCookieContext::ContextType::CROSS_SITE),
2013 CookieInclusionStatus::MakeFromReasonsForTesting(
2014 std::vector<CookieInclusionStatus::ExclusionReason>(),
2015 {CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE})},
2016 {"LEGACY_Schemeful=6;SameSite=Lax", CookieSameSite::LAX_MODE,
2017 CookieEffectiveSameSite::LAX_MODE,
2018 SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX,
2019 SameSiteCookieContext::ContextType::CROSS_SITE),
2020 CookieInclusionStatus::MakeFromReasonsForTesting(
2021 std::vector<CookieInclusionStatus::ExclusionReason>(),
2022 {CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE})},
2023 };
2024
2025 // Test cases that require NONLEGACY or UNKNOWN semantics with Schemeful
2026 // Same-Site enabled
2027 std::vector<IncludeForRequestURLTestCase> schemeful_enabled_test_cases = {
2028 {"NONLEGACY_Schemeful=1;SameSite=Strict", CookieSameSite::STRICT_MODE,
2029 CookieEffectiveSameSite::STRICT_MODE,
2030 SameSiteCookieContext(
2031 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
2032 SameSiteCookieContext::ContextType::SAME_SITE_LAX),
2033 CookieInclusionStatus::MakeFromReasonsForTesting(
2034 {CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
2035 {CookieInclusionStatus::WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE})},
2036 {"NONLEGACY_Schemeful=2;SameSite=Strict", CookieSameSite::STRICT_MODE,
2037 CookieEffectiveSameSite::STRICT_MODE,
2038 SameSiteCookieContext(
2039 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
2040 SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
2041 CookieInclusionStatus::MakeFromReasonsForTesting(
2042 {CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
2043 {CookieInclusionStatus::
2044 WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE})},
2045 {"NONLEGACY_Schemeful=3;SameSite=Strict", CookieSameSite::STRICT_MODE,
2046 CookieEffectiveSameSite::STRICT_MODE,
2047 SameSiteCookieContext(
2048 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
2049 SameSiteCookieContext::ContextType::CROSS_SITE),
2050 CookieInclusionStatus::MakeFromReasonsForTesting(
2051 {CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT},
2052 {CookieInclusionStatus::
2053 WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE})},
2054 {"NONLEGACY_Schemeful=4;SameSite=Lax", CookieSameSite::LAX_MODE,
2055 CookieEffectiveSameSite::LAX_MODE,
2056 SameSiteCookieContext(
2057 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
2058 SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
2059 CookieInclusionStatus::MakeFromReasonsForTesting(
2060 {CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
2061 {CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE})},
2062 {"NONLEGACY_Schemeful=5;SameSite=Lax", CookieSameSite::LAX_MODE,
2063 CookieEffectiveSameSite::LAX_MODE,
2064 SameSiteCookieContext(
2065 SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
2066 SameSiteCookieContext::ContextType::CROSS_SITE),
2067 CookieInclusionStatus::MakeFromReasonsForTesting(
2068 {CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
2069 {CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE})},
2070 {"NONLEGACY_Schemeful=6;SameSite=Lax", CookieSameSite::LAX_MODE,
2071 CookieEffectiveSameSite::LAX_MODE,
2072 SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX,
2073 SameSiteCookieContext::ContextType::CROSS_SITE),
2074 CookieInclusionStatus::MakeFromReasonsForTesting(
2075 {CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
2076 {CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE})},
2077 };
2078
2079 auto SchemefulIndependentCases = [&]() {
2080 // Run the test cases that are independent of Schemeful Same-Site.
2081 VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::UNKNOWN,
2082 common_test_cases);
2083 VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::UNKNOWN,
2084 default_lax_test_cases);
2085 VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::LEGACY,
2086 common_test_cases);
2087 VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::LEGACY,
2088 default_none_test_cases);
2089 VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::NONLEGACY,
2090 common_test_cases);
2091 VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::NONLEGACY,
2092 default_lax_test_cases);
2093 };
2094
2095 {
2096 // Schemeful Same-Site disabled.
2097 base::test::ScopedFeatureList feature_list;
2098 feature_list.InitAndDisableFeature(features::kSchemefulSameSite);
2099
2100 SchemefulIndependentCases();
2101
2102 VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::LEGACY,
2103 schemeful_disabled_test_cases);
2104 VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::NONLEGACY,
2105 schemeful_disabled_test_cases);
2106 VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::UNKNOWN,
2107 schemeful_disabled_test_cases);
2108 }
2109 {
2110 // Schemeful Same-Site enabled.
2111 base::test::ScopedFeatureList feature_list;
2112 feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
2113
2114 SchemefulIndependentCases();
2115
2116 // With LEGACY access the cases should act as if schemeful is disabled, even
2117 // when it's not.
2118 VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::LEGACY,
2119 schemeful_disabled_test_cases);
2120
2121 VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::NONLEGACY,
2122 schemeful_enabled_test_cases);
2123 VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::UNKNOWN,
2124 schemeful_enabled_test_cases);
2125 }
2126 }
2127
TEST(CanonicalCookieTest,TestFirstPartyPartitionedAndCrossSiteContext)2128 TEST(CanonicalCookieTest, TestFirstPartyPartitionedAndCrossSiteContext) {
2129 std::string histogram_name =
2130 "Cookie.FirstPartyPartitioned.HasCrossSiteAncestor";
2131 base::Time current_time = base::Time::Now();
2132 base::HistogramTester histogram_tester;
2133 GURL url("https://www.example.com");
2134 GURL url2("https://wwwnottheSame.com");
2135 CookieOptions options;
2136
2137 auto make_cookie = [current_time](const auto& partition_key) {
2138 return CanonicalCookie::CreateUnsafeCookieForTesting(
2139 "A", "2", "www.example.com", "/test", current_time, base::Time(),
2140 base::Time(), base::Time(), true /*secure*/, true /*httponly*/,
2141 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, partition_key);
2142 };
2143
2144 auto no_partition_key_cookie = make_cookie(std::nullopt);
2145 auto partitioned_cookie =
2146 make_cookie(CookiePartitionKey::FromURLForTesting(GURL(url)));
2147 auto nonced_partition_key_cookie =
2148 make_cookie(CookiePartitionKey::FromURLForTesting(
2149 GURL(url), CookiePartitionKey::AncestorChainBit::kCrossSite,
2150 base::UnguessableToken::Create()));
2151 auto different_site_partition_key_cookie =
2152 make_cookie(CookiePartitionKey::FromURLForTesting(GURL(url2)));
2153
2154 histogram_tester.ExpectBucketCount(histogram_name, true, 0);
2155 histogram_tester.ExpectBucketCount(histogram_name, false, 0);
2156 no_partition_key_cookie->IncludeForRequestURL(
2157 url, options,
2158 CookieAccessParams{CookieAccessSemantics::NONLEGACY, false});
2159
2160 histogram_tester.ExpectBucketCount(histogram_name, true, 0);
2161 histogram_tester.ExpectBucketCount(histogram_name, false, 0);
2162
2163 partitioned_cookie->IncludeForRequestURL(
2164 url, options,
2165 CookieAccessParams{CookieAccessSemantics::NONLEGACY, false});
2166 histogram_tester.ExpectBucketCount(histogram_name, true, 1);
2167 histogram_tester.ExpectBucketCount(histogram_name, false, 0);
2168
2169 nonced_partition_key_cookie->IncludeForRequestURL(
2170 url, options,
2171 CookieAccessParams{CookieAccessSemantics::NONLEGACY, false});
2172 histogram_tester.ExpectBucketCount(histogram_name, true, 1);
2173 histogram_tester.ExpectBucketCount(histogram_name, false, 0);
2174
2175 different_site_partition_key_cookie->IncludeForRequestURL(
2176 url, options,
2177 CookieAccessParams{CookieAccessSemantics::NONLEGACY, false});
2178 histogram_tester.ExpectBucketCount(histogram_name, true, 1);
2179 histogram_tester.ExpectBucketCount(histogram_name, false, 0);
2180
2181 // Show that a cookie in a non-CROSS_SITE context registers as false.
2182 options.set_same_site_cookie_context(
2183 net::CookieOptions::SameSiteCookieContext(
2184 net::CookieOptions::SameSiteCookieContext::ContextType::
2185 SAME_SITE_LAX));
2186
2187 partitioned_cookie->IncludeForRequestURL(
2188 url, options,
2189 CookieAccessParams{CookieAccessSemantics::NONLEGACY, false});
2190 histogram_tester.ExpectBucketCount(histogram_name, true, 1);
2191 histogram_tester.ExpectBucketCount(histogram_name, false, 1);
2192 }
2193 // Test that SameSite=None requires Secure.
TEST(CanonicalCookieTest,IncludeCookiesWithoutSameSiteMustBeSecure)2194 TEST(CanonicalCookieTest, IncludeCookiesWithoutSameSiteMustBeSecure) {
2195 GURL url("https://www.example.com");
2196 base::Time creation_time = base::Time::Now();
2197 std::optional<base::Time> server_time = std::nullopt;
2198 CookieOptions options;
2199
2200 // Make a SameSite=None, *not* Secure cookie.
2201 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateForTesting(
2202 url, "A=2; SameSite=None", creation_time, server_time);
2203 ASSERT_TRUE(cookie.get());
2204 EXPECT_FALSE(cookie->SecureAttribute());
2205 EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
2206 EXPECT_EQ(CookieEffectiveSameSite::NO_RESTRICTION,
2207 cookie->GetEffectiveSameSiteForTesting());
2208
2209 // UKNOWN semantics results in modern behavior (requiring Secure).
2210 EXPECT_TRUE(
2211 cookie
2212 ->IncludeForRequestURL(
2213 url, options,
2214 CookieAccessParams{CookieAccessSemantics::UNKNOWN,
2215 /*delegate_treats_url_as_trustworthy=*/false})
2216 .status.HasExactlyExclusionReasonsForTesting(
2217 {CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE}));
2218
2219 // LEGACY semantics does not require Secure for SameSite=None cookies.
2220 EXPECT_TRUE(
2221 cookie
2222 ->IncludeForRequestURL(
2223 url, options,
2224 CookieAccessParams{CookieAccessSemantics::LEGACY,
2225 /*delegate_treats_url_as_trustworthy=*/false})
2226 .status.IsInclude());
2227
2228 // NONLEGACY semantics results in modern behavior (requiring Secure).
2229 EXPECT_TRUE(
2230 cookie
2231 ->IncludeForRequestURL(
2232 url, options,
2233 CookieAccessParams{CookieAccessSemantics::NONLEGACY,
2234 /*delegate_treats_url_as_trustworthy=*/false})
2235 .status.HasExactlyExclusionReasonsForTesting(
2236 {CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE}));
2237 }
2238
TEST(CanonicalCookieTest,IncludeForRequestURL_SameSiteNone_Metrics)2239 TEST(CanonicalCookieTest, IncludeForRequestURL_SameSiteNone_Metrics) {
2240 constexpr bool delegate_treats_url_as_trustworthy = false;
2241 const base::Time now = base::Time::Now();
2242 const auto make_cookie = [now](CookieSameSite same_site) {
2243 return CanonicalCookie::CreateUnsafeCookieForTesting(
2244 "A", "1", "www.example.com", "/test", now, base::Time(), base::Time(),
2245 base::Time(), true /* secure */, false /*httponly*/, same_site,
2246 COOKIE_PRIORITY_DEFAULT);
2247 };
2248 GURL url("https://www.example.com/test");
2249
2250 const std::unique_ptr<CanonicalCookie> same_site_none_cookie =
2251 make_cookie(CookieSameSite::NO_RESTRICTION);
2252 const std::unique_ptr<CanonicalCookie> same_site_lax_cookie =
2253 make_cookie(CookieSameSite::LAX_MODE);
2254 const std::unique_ptr<CanonicalCookie> same_site_strict_cookie =
2255 make_cookie(CookieSameSite::STRICT_MODE);
2256 CookieOptions options;
2257 options.set_same_site_cookie_context(CookieOptions::SameSiteCookieContext(
2258 CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE));
2259
2260 // Check that the most restrictive context is recognized and enforced.
2261 EXPECT_THAT(same_site_none_cookie->IncludeForRequestURL(
2262 url, options,
2263 CookieAccessParams(CookieAccessSemantics::LEGACY,
2264 delegate_treats_url_as_trustworthy)),
2265 MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true));
2266 EXPECT_THAT(same_site_lax_cookie->IncludeForRequestURL(
2267 url, options,
2268 CookieAccessParams(CookieAccessSemantics::LEGACY,
2269 delegate_treats_url_as_trustworthy)),
2270 MatchesCookieAccessResult(Not(net::IsInclude()), _, _, true));
2271 EXPECT_THAT(same_site_strict_cookie->IncludeForRequestURL(
2272 url, options,
2273 CookieAccessParams(CookieAccessSemantics::LEGACY,
2274 delegate_treats_url_as_trustworthy)),
2275 MatchesCookieAccessResult(Not(net::IsInclude()), _, _, true));
2276
2277 // Next: allow a SameSite=Lax cookie.
2278 options.set_same_site_cookie_context(CookieOptions::SameSiteCookieContext(
2279 CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX));
2280 EXPECT_THAT(same_site_none_cookie->IncludeForRequestURL(
2281 url, options,
2282 CookieAccessParams(CookieAccessSemantics::LEGACY,
2283 delegate_treats_url_as_trustworthy)),
2284 MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true));
2285 EXPECT_THAT(same_site_lax_cookie->IncludeForRequestURL(
2286 url, options,
2287 CookieAccessParams(CookieAccessSemantics::LEGACY,
2288 delegate_treats_url_as_trustworthy)),
2289 MatchesCookieAccessResult(net::IsInclude(), _, _, true));
2290 EXPECT_THAT(same_site_strict_cookie->IncludeForRequestURL(
2291 url, options,
2292 CookieAccessParams(CookieAccessSemantics::LEGACY,
2293 delegate_treats_url_as_trustworthy)),
2294 MatchesCookieAccessResult(Not(net::IsInclude()), _, _, true));
2295
2296 // Next: allow a SameSite=Strict cookie.
2297 options.set_same_site_cookie_context(CookieOptions::SameSiteCookieContext(
2298 CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_STRICT));
2299 EXPECT_THAT(same_site_none_cookie->IncludeForRequestURL(
2300 url, options,
2301 CookieAccessParams(CookieAccessSemantics::LEGACY,
2302 delegate_treats_url_as_trustworthy)),
2303 MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true));
2304 EXPECT_THAT(same_site_strict_cookie->IncludeForRequestURL(
2305 url, options,
2306 CookieAccessParams(CookieAccessSemantics::LEGACY,
2307 delegate_treats_url_as_trustworthy)),
2308 MatchesCookieAccessResult(net::IsInclude(), _, _, true));
2309 }
2310
2311 // Test that the CookieInclusionStatus warning for inclusion changed by
2312 // cross-site redirect context downgrade is applied correctly.
TEST(CanonicalCookieTest,IncludeForRequestURL_RedirectDowngradeWarning)2313 TEST(CanonicalCookieTest, IncludeForRequestURL_RedirectDowngradeWarning) {
2314 using Context = CookieOptions::SameSiteCookieContext;
2315 using ContextType = Context::ContextType;
2316
2317 Context::ContextMetadata strict_lax_downgrade_metadata,
2318 strict_cross_downgrade_metadata;
2319 strict_lax_downgrade_metadata.cross_site_redirect_downgrade =
2320 Context::ContextMetadata::ContextDowngradeType::kStrictToLax;
2321 strict_cross_downgrade_metadata.cross_site_redirect_downgrade =
2322 Context::ContextMetadata::ContextDowngradeType::kStrictToCross;
2323
2324 // Because there are downgrades we need to set the HTTP method as well, since
2325 // some metrics code expects that. The actual method doesn't matter here.
2326 strict_lax_downgrade_metadata.http_method_bug_1221316 =
2327 Context::ContextMetadata::HttpMethod::kGet;
2328 strict_cross_downgrade_metadata.http_method_bug_1221316 =
2329 Context::ContextMetadata::HttpMethod::kGet;
2330
2331 GURL url("https://www.example.test/test");
2332 GURL insecure_url("http://www.example.test/test");
2333
2334 const struct {
2335 ContextType context_type;
2336 Context::ContextMetadata metadata;
2337 CookieSameSite samesite;
2338 bool expect_cross_site_redirect_warning;
2339 } kTestCases[] = {
2340 // Strict-to-lax downgrade.
2341 {ContextType::SAME_SITE_STRICT, strict_lax_downgrade_metadata,
2342 CookieSameSite::STRICT_MODE, true},
2343 {ContextType::SAME_SITE_LAX, strict_lax_downgrade_metadata,
2344 CookieSameSite::STRICT_MODE, true},
2345 {ContextType::SAME_SITE_STRICT, strict_lax_downgrade_metadata,
2346 CookieSameSite::LAX_MODE, false},
2347 {ContextType::SAME_SITE_LAX, strict_lax_downgrade_metadata,
2348 CookieSameSite::LAX_MODE, false},
2349 {ContextType::SAME_SITE_STRICT, strict_lax_downgrade_metadata,
2350 CookieSameSite::NO_RESTRICTION, false},
2351 {ContextType::SAME_SITE_LAX, strict_lax_downgrade_metadata,
2352 CookieSameSite::NO_RESTRICTION, false},
2353
2354 // Strict-to-cross downgrade.
2355 {ContextType::SAME_SITE_STRICT, strict_cross_downgrade_metadata,
2356 CookieSameSite::STRICT_MODE, true},
2357 {ContextType::CROSS_SITE, strict_cross_downgrade_metadata,
2358 CookieSameSite::STRICT_MODE, true},
2359 {ContextType::SAME_SITE_STRICT, strict_cross_downgrade_metadata,
2360 CookieSameSite::LAX_MODE, true},
2361 {ContextType::CROSS_SITE, strict_cross_downgrade_metadata,
2362 CookieSameSite::LAX_MODE, true},
2363 {ContextType::SAME_SITE_STRICT, strict_cross_downgrade_metadata,
2364 CookieSameSite::NO_RESTRICTION, false},
2365 {ContextType::CROSS_SITE, strict_cross_downgrade_metadata,
2366 CookieSameSite::NO_RESTRICTION, false},
2367 };
2368
2369 for (bool consider_redirects : {true, false}) {
2370 base::test::ScopedFeatureList feature_list;
2371 feature_list.InitWithFeatureState(
2372 features::kCookieSameSiteConsidersRedirectChain, consider_redirects);
2373
2374 for (CookieAccessSemantics semantics :
2375 {CookieAccessSemantics::LEGACY, CookieAccessSemantics::NONLEGACY}) {
2376 // There are no downgrade warnings for undowngraded contexts.
2377 for (ContextType context_type :
2378 {ContextType::SAME_SITE_STRICT, ContextType::SAME_SITE_LAX,
2379 ContextType::SAME_SITE_LAX_METHOD_UNSAFE,
2380 ContextType::CROSS_SITE}) {
2381 for (CookieSameSite samesite :
2382 {CookieSameSite::UNSPECIFIED, CookieSameSite::NO_RESTRICTION,
2383 CookieSameSite::LAX_MODE, CookieSameSite::STRICT_MODE}) {
2384 std::unique_ptr<CanonicalCookie> cookie =
2385 CanonicalCookie::CreateUnsafeCookieForTesting(
2386 "A", "1", "www.example.test", "/test", base::Time::Now(),
2387 base::Time(), base::Time(), base::Time(), /*secure=*/true,
2388 /*httponly=*/false, samesite, COOKIE_PRIORITY_DEFAULT);
2389
2390 CookieOptions options;
2391 options.set_same_site_cookie_context(Context(context_type));
2392
2393 EXPECT_FALSE(
2394 cookie
2395 ->IncludeForRequestURL(
2396 url, options,
2397 CookieAccessParams(
2398 semantics,
2399 /*delegate_treats_url_as_trustworthy=*/false))
2400 .status.HasWarningReason(
2401 CookieInclusionStatus::
2402 WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION));
2403 }
2404 }
2405
2406 for (const auto& test : kTestCases) {
2407 std::unique_ptr<CanonicalCookie> cookie =
2408 CanonicalCookie::CreateUnsafeCookieForTesting(
2409 "A", "1", "www.example.test", "/test", base::Time::Now(),
2410 base::Time(), base::Time(), base::Time(), /*secure=*/true,
2411 /*httponly=*/false, test.samesite, COOKIE_PRIORITY_DEFAULT);
2412
2413 CookieOptions options;
2414 options.set_same_site_cookie_context(
2415 Context(test.context_type, test.context_type, test.metadata,
2416 test.metadata));
2417 EXPECT_EQ(
2418 cookie
2419 ->IncludeForRequestURL(
2420 url, options,
2421 CookieAccessParams(
2422 semantics,
2423 /*delegate_treats_url_as_trustworthy=*/false))
2424 .status.HasWarningReason(
2425 CookieInclusionStatus::
2426 WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION),
2427 test.expect_cross_site_redirect_warning);
2428
2429 // SameSite warnings not applied if other exclusion reasons apply (e.g.
2430 // non-https with Secure attribute).
2431 EXPECT_FALSE(
2432 cookie
2433 ->IncludeForRequestURL(
2434 insecure_url, options,
2435 CookieAccessParams(
2436 semantics,
2437 /*delegate_treats_url_as_trustworthy=*/false))
2438 .status.HasWarningReason(
2439 CookieInclusionStatus::
2440 WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION));
2441 }
2442 }
2443 }
2444 }
2445
2446 // Test that the correct inclusion status is generated when a cookie's source
2447 // scheme does(n't) match the url's.
TEST(CanonicalCookieTest,IncludeForRequestURL_SchemeBoundStatus)2448 TEST(CanonicalCookieTest, IncludeForRequestURL_SchemeBoundStatus) {
2449 base::Time creation_time = base::Time::Now();
2450 std::optional<base::Time> server_time = std::nullopt;
2451 CookieOptions options;
2452 options.set_same_site_cookie_context(
2453 CookieOptions::SameSiteCookieContext::MakeInclusive());
2454
2455 CookieAccessParams params(CookieAccessSemantics::UNKNOWN,
2456 /*delegate_treats_url_as_trustworthy=*/false);
2457 CookieAccessParams trusted_params(
2458 CookieAccessSemantics::UNKNOWN,
2459 /*delegate_treats_url_as_trustworthy=*/true);
2460
2461 GURL secure_url("https://www.example.test:123/");
2462 GURL insecure_url("http://www.example.test:123/");
2463
2464 // Specify SameSite=Lax not because we care about SameSite in this test, but
2465 // rather to prevent warnings that SameSite isn't specified.
2466 auto secure_cookie = CanonicalCookie::CreateForTesting(
2467 secure_url, "secure=foobar; SameSite=Lax", creation_time, server_time);
2468 auto secure_attr_cookie = CanonicalCookie::CreateForTesting(
2469 secure_url, "secure=foobar; SameSite=Lax; Secure", creation_time,
2470 server_time);
2471 auto insecure_cookie = CanonicalCookie::CreateForTesting(
2472 insecure_url, "insecure=foobar; SameSite=Lax", creation_time,
2473 server_time);
2474 // Create a cookie with an unset scheme. This can happen if a cookie was
2475 // stored in the DB before we began recording source schemes.
2476 auto unset_cookie = CanonicalCookie::CreateForTesting(
2477 secure_url, "unset=foobar; SameSite=Lax", creation_time, server_time);
2478 unset_cookie->SetSourceScheme(CookieSourceScheme::kUnset);
2479
2480 // When the feature is disabled we should have warnings.
2481 {
2482 base::test::ScopedFeatureList scope_feature_list;
2483 scope_feature_list.InitAndDisableFeature(
2484 features::kEnableSchemeBoundCookies);
2485
2486 EXPECT_FALSE(
2487 secure_cookie->IncludeForRequestURL(secure_url, options, params)
2488 .status.ShouldWarn());
2489
2490 EXPECT_TRUE(
2491 secure_cookie->IncludeForRequestURL(insecure_url, options, params)
2492 .status.HasWarningReason(
2493 CookieInclusionStatus::WARN_SCHEME_MISMATCH));
2494
2495 // If a cookie is already blocked due to the `Secure` attribute then we
2496 // don't bother warning.
2497 auto status =
2498 secure_attr_cookie->IncludeForRequestURL(insecure_url, options, params)
2499 .status;
2500 EXPECT_TRUE(
2501 status.HasExclusionReason(CookieInclusionStatus::EXCLUDE_SECURE_ONLY));
2502 EXPECT_FALSE(status.ShouldWarn());
2503
2504 EXPECT_FALSE(
2505 insecure_cookie->IncludeForRequestURL(insecure_url, options, params)
2506 .status.ShouldWarn());
2507
2508 EXPECT_TRUE(
2509 insecure_cookie->IncludeForRequestURL(secure_url, options, params)
2510 .status.HasWarningReason(
2511 CookieInclusionStatus::WARN_SCHEME_MISMATCH));
2512
2513 // If a url is treated as trustworthy, then it's allowed to access cookies
2514 // with a secure source scheme.
2515 EXPECT_FALSE(
2516 secure_cookie
2517 ->IncludeForRequestURL(insecure_url, options, trusted_params)
2518 .status.ShouldWarn());
2519
2520 // Cookies with an unset source scheme should match any url scheme.
2521 EXPECT_FALSE(unset_cookie->IncludeForRequestURL(secure_url, options, params)
2522 .status.ShouldWarn());
2523 EXPECT_FALSE(
2524 unset_cookie->IncludeForRequestURL(insecure_url, options, params)
2525 .status.ShouldWarn());
2526 }
2527 // When the feature is enabled we should have exclusions.
2528 {
2529 base::test::ScopedFeatureList scope_feature_list;
2530 scope_feature_list.InitAndEnableFeature(
2531 features::kEnableSchemeBoundCookies);
2532
2533 EXPECT_TRUE(secure_cookie->IncludeForRequestURL(secure_url, options, params)
2534 .status.IsInclude());
2535
2536 EXPECT_TRUE(
2537 secure_cookie->IncludeForRequestURL(insecure_url, options, params)
2538 .status.HasExclusionReason(
2539 CookieInclusionStatus::EXCLUDE_SCHEME_MISMATCH));
2540
2541 // If a cookie is already blocked due to the `Secure` attribute then we
2542 // don't bother with our exclusion reason.
2543 auto status =
2544 secure_attr_cookie->IncludeForRequestURL(insecure_url, options, params)
2545 .status;
2546 EXPECT_TRUE(
2547 status.HasExclusionReason(CookieInclusionStatus::EXCLUDE_SECURE_ONLY));
2548 EXPECT_FALSE(status.HasExclusionReason(
2549 CookieInclusionStatus::EXCLUDE_SCHEME_MISMATCH));
2550
2551 EXPECT_TRUE(
2552 insecure_cookie->IncludeForRequestURL(insecure_url, options, params)
2553 .status.IsInclude());
2554
2555 EXPECT_TRUE(
2556 insecure_cookie->IncludeForRequestURL(secure_url, options, params)
2557 .status.HasExclusionReason(
2558 CookieInclusionStatus::EXCLUDE_SCHEME_MISMATCH));
2559
2560 // If a url is treated as trustworthy, then it's allowed to access cookies
2561 // with a secure source scheme. But we should have a warning indicating
2562 // this.
2563 status = secure_cookie
2564 ->IncludeForRequestURL(insecure_url, options, trusted_params)
2565 .status;
2566 EXPECT_TRUE(status.IsInclude());
2567 EXPECT_TRUE(status.HasWarningReason(
2568 CookieInclusionStatus::WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC));
2569
2570 // Cookies with an unset source scheme should match any url scheme.
2571 EXPECT_TRUE(unset_cookie->IncludeForRequestURL(secure_url, options, params)
2572 .status.IsInclude());
2573 EXPECT_TRUE(
2574 unset_cookie->IncludeForRequestURL(insecure_url, options, params)
2575 .status.IsInclude());
2576 }
2577 }
2578
2579 // Test that the correct inclusion status is generated when a cookie's source
2580 // port does(n't) match the url's.
TEST(CanonicalCookieTest,IncludeForRequestURL_PortBoundStatus)2581 TEST(CanonicalCookieTest, IncludeForRequestURL_PortBoundStatus) {
2582 base::Time creation_time = base::Time::Now();
2583 std::optional<base::Time> server_time = std::nullopt;
2584 CookieOptions options;
2585 options.set_same_site_cookie_context(
2586 CookieOptions::SameSiteCookieContext::MakeInclusive());
2587
2588 CookieAccessParams params(CookieAccessSemantics::UNKNOWN,
2589 /*delegate_treats_url_as_trustworthy=*/false);
2590
2591 GURL url1("https://www.example.test:443/");
2592 GURL url2("https://www.example.test:123/");
2593
2594 // Specify SameSite=Lax not because we care about SameSite in this test, but
2595 // rather to prevent warnings that SameSite isn't specified.
2596 auto cookie1 = CanonicalCookie::CreateForTesting(
2597 url1, "cookie=1; SameSite=Lax", creation_time, server_time);
2598 auto cookie2 = CanonicalCookie::CreateForTesting(
2599 url2, "cookie=2; SameSite=Lax", creation_time, server_time);
2600
2601 // Create a cookie with an unspecified port. This can happen if a cookie was
2602 // stored in the DB before we began recording source ports.
2603 auto unspecified_cookie = CanonicalCookie::CreateForTesting(
2604 url2, "cookie=unspecified; SameSite=Lax", creation_time, server_time);
2605 unspecified_cookie->SetSourcePort(url::PORT_UNSPECIFIED);
2606
2607 // When the feature is disabled we should have warnings.
2608 {
2609 base::test::ScopedFeatureList scope_feature_list;
2610 scope_feature_list.InitAndDisableFeature(features::kEnablePortBoundCookies);
2611
2612 EXPECT_FALSE(cookie1->IncludeForRequestURL(url1, options, params)
2613 .status.ShouldWarn());
2614
2615 EXPECT_TRUE(cookie1->IncludeForRequestURL(url2, options, params)
2616 .status.HasWarningReason(
2617 CookieInclusionStatus::WARN_PORT_MISMATCH));
2618
2619 // Cookies with an unspecified port should match any url port.
2620 EXPECT_FALSE(unspecified_cookie->IncludeForRequestURL(url1, options, params)
2621 .status.ShouldWarn());
2622 EXPECT_FALSE(unspecified_cookie->IncludeForRequestURL(url2, options, params)
2623 .status.ShouldWarn());
2624 }
2625 // When the feature is enabled we should have exclusions.
2626 {
2627 base::test::ScopedFeatureList scope_feature_list;
2628 scope_feature_list.InitAndEnableFeature(features::kEnablePortBoundCookies);
2629
2630 EXPECT_TRUE(cookie1->IncludeForRequestURL(url1, options, params)
2631 .status.IsInclude());
2632
2633 EXPECT_TRUE(cookie1->IncludeForRequestURL(url2, options, params)
2634 .status.HasExclusionReason(
2635 CookieInclusionStatus::EXCLUDE_PORT_MISMATCH));
2636
2637 // Cookies with an unspecified port should match any url port.
2638 EXPECT_TRUE(unspecified_cookie->IncludeForRequestURL(url1, options, params)
2639 .status.IsInclude());
2640 EXPECT_TRUE(unspecified_cookie->IncludeForRequestURL(url2, options, params)
2641 .status.IsInclude());
2642 }
2643 }
2644
2645 // Test that domain cookies match any request url port.
TEST(CanonicalCookieTest,IncludeForRequestURL_DomainCookiesPortMatch)2646 TEST(CanonicalCookieTest, IncludeForRequestURL_DomainCookiesPortMatch) {
2647 base::Time creation_time = base::Time::Now();
2648 std::optional<base::Time> server_time = std::nullopt;
2649 CookieOptions options;
2650 options.set_same_site_cookie_context(
2651 CookieOptions::SameSiteCookieContext::MakeInclusive());
2652
2653 CookieAccessParams params(CookieAccessSemantics::UNKNOWN,
2654 /*delegate_treats_url_as_trustworthy=*/false);
2655
2656 GURL url1("https://www.example.test:443/");
2657 GURL url2("https://www.example.test:123/");
2658
2659 // Specify SameSite=Lax not because we care about SameSite in this test, but
2660 // rather to prevent warnings that SameSite isn't specified.
2661 auto host_cookie = CanonicalCookie::CreateForTesting(
2662 url1, "cookie=hostonly; SameSite=Lax", creation_time, server_time);
2663
2664 auto domain_cookie = CanonicalCookie::CreateForTesting(
2665 url1, "cookie=domain; SameSite=Lax; Domain=example.test", creation_time,
2666 server_time);
2667
2668 // When the feature is disabled we shouldn't get any port mismatch warnings
2669 // for domain cookies.
2670 {
2671 base::test::ScopedFeatureList scope_feature_list;
2672 scope_feature_list.InitAndDisableFeature(features::kEnablePortBoundCookies);
2673
2674 EXPECT_FALSE(host_cookie->IncludeForRequestURL(url1, options, params)
2675 .status.ShouldWarn());
2676
2677 EXPECT_FALSE(domain_cookie->IncludeForRequestURL(url1, options, params)
2678 .status.ShouldWarn());
2679
2680 EXPECT_TRUE(host_cookie->IncludeForRequestURL(url2, options, params)
2681 .status.HasWarningReason(
2682 CookieInclusionStatus::WARN_PORT_MISMATCH));
2683
2684 EXPECT_FALSE(domain_cookie->IncludeForRequestURL(url2, options, params)
2685 .status.ShouldWarn());
2686 }
2687 // When the feature is enabled domain cookies should match any url port.
2688 {
2689 base::test::ScopedFeatureList scope_feature_list;
2690 scope_feature_list.InitAndEnableFeature(features::kEnablePortBoundCookies);
2691
2692 EXPECT_TRUE(host_cookie->IncludeForRequestURL(url1, options, params)
2693 .status.IsInclude());
2694
2695 EXPECT_TRUE(domain_cookie->IncludeForRequestURL(url1, options, params)
2696 .status.IsInclude());
2697
2698 EXPECT_TRUE(host_cookie->IncludeForRequestURL(url2, options, params)
2699 .status.HasExclusionReason(
2700 CookieInclusionStatus::EXCLUDE_PORT_MISMATCH));
2701
2702 EXPECT_TRUE(domain_cookie->IncludeForRequestURL(url2, options, params)
2703 .status.IsInclude());
2704 }
2705 }
2706
TEST(CanonicalCookieTest,InsecureCookiesExpiryTimeLimit)2707 TEST(CanonicalCookieTest, InsecureCookiesExpiryTimeLimit) {
2708 GURL url("http://www.example.com/test/foo.html");
2709 base::Time creation_time = base::Time::Now();
2710 base::Time future_date = creation_time + base::Days(1);
2711 {
2712 base::test::ScopedFeatureList scoped_feature_list;
2713 scoped_feature_list.InitWithFeatures(
2714 {features::kEnableSchemeBoundCookies,
2715 features::kTimeLimitedInsecureCookies},
2716 {});
2717 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateForTesting(
2718 url, "A=1; expires=" + HttpUtil::TimeFormatHTTP(future_date),
2719 creation_time);
2720 ASSERT_TRUE(cookie);
2721 // With the feature enabled, expiration time should be limited to 3 hours
2722 // after creation. Equality check needs to have a second margin due to
2723 // microsecond rounding causing breakage.
2724 EXPECT_TRUE(((creation_time + base::Hours(3)) - cookie->ExpiryDate())
2725 .FloorToMultiple(base::Seconds(1))
2726 .is_zero());
2727 }
2728 {
2729 base::test::ScopedFeatureList scoped_feature_list;
2730 scoped_feature_list.InitWithFeatures(
2731 {features::kEnableSchemeBoundCookies},
2732 {features::kTimeLimitedInsecureCookies});
2733 std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateForTesting(
2734 url, "A=1; expires=" + HttpUtil::TimeFormatHTTP(future_date),
2735 creation_time);
2736 ASSERT_TRUE(cookie);
2737 // With the feature disabled, expiration time should not be limited.
2738 // Equality check needs to have a second margin due to microsecond rounding
2739 // causing breakage.
2740 EXPECT_TRUE((future_date - cookie->ExpiryDate())
2741 .FloorToMultiple(base::Seconds(1))
2742 .is_zero());
2743 }
2744 }
2745
TEST(CanonicalCookieTest,MultipleExclusionReasons)2746 TEST(CanonicalCookieTest, MultipleExclusionReasons) {
2747 GURL url("http://www.not-secure.com/foo");
2748 base::Time creation_time = base::Time::Now();
2749 std::optional<base::Time> server_time = std::nullopt;
2750 CookieOptions options;
2751 options.set_exclude_httponly();
2752 options.set_same_site_cookie_context(CookieOptions::SameSiteCookieContext(
2753 CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE));
2754
2755 // Test IncludeForRequestURL()
2756 // Note: This is a cookie that should never exist normally, because Create()
2757 // would weed it out.
2758 auto cookie1 = CanonicalCookie::CreateUnsafeCookieForTesting(
2759 "name", "value", "other-domain.com", "/bar", creation_time, base::Time(),
2760 base::Time(), base::Time(), true /* secure */, true /* httponly */,
2761 CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT);
2762 EXPECT_THAT(
2763 cookie1->IncludeForRequestURL(
2764 url, options,
2765 CookieAccessParams{CookieAccessSemantics::UNKNOWN,
2766 /*delegate_treats_url_as_trustworthy=*/false}),
2767 MatchesCookieAccessResult(
2768 CookieInclusionStatus::MakeFromReasonsForTesting({
2769 CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
2770 CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
2771 CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH,
2772 CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
2773 CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT,
2774 }),
2775 _, _, false));
2776
2777 // Test Create()
2778 CookieInclusionStatus create_status;
2779 auto cookie2 = CanonicalCookie::Create(
2780 url, "__Secure-notactuallysecure=value;Domain=some-other-domain.com",
2781 creation_time, server_time, /*cookie_partition_key=*/std::nullopt, true,
2782 CookieSourceType::kUnknown, &create_status);
2783 ASSERT_FALSE(cookie2);
2784 EXPECT_TRUE(create_status.HasExactlyExclusionReasonsForTesting(
2785 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
2786 CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
2787
2788 // Test IsSetPermittedInContext()
2789 auto cookie3 = CanonicalCookie::CreateForTesting(
2790 url, "name=value;HttpOnly;SameSite=Lax", creation_time, server_time);
2791 ASSERT_TRUE(cookie3);
2792 EXPECT_THAT(
2793 cookie3->IsSetPermittedInContext(
2794 url, options,
2795 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
2796 false /* delegate_treats_url_as_trustworthy */
2797 ),
2798 kCookieableSchemes),
2799 MatchesCookieAccessResult(
2800 CookieInclusionStatus::MakeFromReasonsForTesting(
2801 {CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
2802 CookieInclusionStatus::EXCLUDE_SAMESITE_LAX}),
2803 _, _, false));
2804 }
2805
TEST(CanonicalCookieTest,PartialCompare)2806 TEST(CanonicalCookieTest, PartialCompare) {
2807 GURL url("http://www.example.com");
2808 base::Time creation_time = base::Time::Now();
2809 std::optional<base::Time> server_time = std::nullopt;
2810 std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::CreateForTesting(
2811 url, "a=b", creation_time, server_time));
2812 std::unique_ptr<CanonicalCookie> cookie_different_path(
2813 CanonicalCookie::CreateForTesting(url, "a=b; path=/foo", creation_time,
2814 server_time));
2815 std::unique_ptr<CanonicalCookie> cookie_different_value(
2816 CanonicalCookie::CreateForTesting(url, "a=c", creation_time,
2817 server_time));
2818
2819 // Cookie is equivalent to itself.
2820 EXPECT_FALSE(cookie->PartialCompare(*cookie));
2821
2822 // Changing the path affects the ordering.
2823 EXPECT_TRUE(cookie->PartialCompare(*cookie_different_path));
2824 EXPECT_FALSE(cookie_different_path->PartialCompare(*cookie));
2825
2826 // Changing the value does not affect the ordering.
2827 EXPECT_FALSE(cookie->PartialCompare(*cookie_different_value));
2828 EXPECT_FALSE(cookie_different_value->PartialCompare(*cookie));
2829
2830 // Cookies identical for PartialCompare() are equivalent.
2831 EXPECT_TRUE(cookie->IsEquivalent(*cookie_different_value));
2832 EXPECT_TRUE(cookie->IsEquivalent(*cookie));
2833 }
2834
TEST(CanonicalCookieTest,SecureCookiePrefix)2835 TEST(CanonicalCookieTest, SecureCookiePrefix) {
2836 GURL https_url("https://www.example.test");
2837 GURL http_url("http://www.example.test");
2838 base::Time creation_time = base::Time::Now();
2839 std::optional<base::Time> server_time = std::nullopt;
2840 CookieInclusionStatus status;
2841
2842 // A __Secure- cookie must be Secure.
2843 EXPECT_FALSE(CanonicalCookie::Create(
2844 https_url, "__Secure-A=B", creation_time, server_time,
2845 /*cookie_partition_key=*/std::nullopt,
2846 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
2847 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2848 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2849 EXPECT_FALSE(CanonicalCookie::Create(
2850 https_url, "__Secure-A=B; httponly", creation_time, server_time,
2851 /*cookie_partition_key=*/std::nullopt,
2852 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
2853 // (EXCLUDE_HTTP_ONLY would be fine, too)
2854 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2855 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2856
2857 // Prefixes are case insensitive.
2858 EXPECT_FALSE(CanonicalCookie::CreateForTesting(https_url, "__secure-A=C;",
2859 creation_time, server_time));
2860 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2861 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2862 EXPECT_FALSE(CanonicalCookie::CreateForTesting(https_url, "__SECURE-A=C;",
2863 creation_time, server_time));
2864 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2865 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2866 EXPECT_FALSE(CanonicalCookie::CreateForTesting(https_url, "__SeCuRe-A=C;",
2867 creation_time, server_time));
2868 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2869 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2870
2871 {
2872 base::test::ScopedFeatureList scope_feature_list;
2873 scope_feature_list.InitAndDisableFeature(
2874 features::kCaseInsensitiveCookiePrefix);
2875
2876 EXPECT_TRUE(CanonicalCookie::CreateForTesting(https_url, "__secure-A=C;",
2877 creation_time, server_time));
2878 EXPECT_TRUE(CanonicalCookie::CreateForTesting(https_url, "__SECURE-A=C;",
2879 creation_time, server_time));
2880 EXPECT_TRUE(CanonicalCookie::CreateForTesting(https_url, "__SeCuRe-A=C;",
2881 creation_time, server_time));
2882 }
2883
2884 // A typoed prefix does not have to be Secure.
2885 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
2886 https_url, "__SecureA=B; Secure", creation_time, server_time));
2887 EXPECT_TRUE(CanonicalCookie::CreateForTesting(https_url, "__SecureA=C;",
2888 creation_time, server_time));
2889 EXPECT_TRUE(CanonicalCookie::CreateForTesting(https_url, "_Secure-A=C;",
2890 creation_time, server_time));
2891 EXPECT_TRUE(CanonicalCookie::CreateForTesting(https_url, "Secure-A=C;",
2892 creation_time, server_time));
2893
2894 // A __Secure- cookie can't be set on a non-secure origin.
2895 EXPECT_FALSE(CanonicalCookie::Create(
2896 http_url, "__Secure-A=B; Secure", creation_time, server_time,
2897 /*cookie_partition_key=*/std::nullopt,
2898 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
2899 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2900 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2901
2902 // Hidden __Secure- prefixes should be rejected.
2903 EXPECT_FALSE(CanonicalCookie::Create(
2904 https_url, "=__Secure-A=B; Secure", creation_time, server_time,
2905 /*cookie_partition_key=*/std::nullopt,
2906 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
2907 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2908 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2909 EXPECT_FALSE(CanonicalCookie::Create(
2910 https_url, "=__Secure-A; Secure", creation_time, server_time,
2911 /*cookie_partition_key=*/std::nullopt,
2912 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
2913 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2914 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2915
2916 // While tricky, this isn't considered hidden and is fine.
2917 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
2918 https_url, "A=__Secure-A=B; Secure", creation_time, server_time));
2919 }
2920
TEST(CanonicalCookieTest,HostCookiePrefix)2921 TEST(CanonicalCookieTest, HostCookiePrefix) {
2922 GURL https_url("https://www.example.test");
2923 GURL http_url("http://www.example.test");
2924 base::Time creation_time = base::Time::Now();
2925 std::optional<base::Time> server_time = std::nullopt;
2926 std::string domain = https_url.host();
2927 CookieInclusionStatus status;
2928
2929 // A __Host- cookie must be Secure.
2930 EXPECT_FALSE(CanonicalCookie::Create(
2931 https_url, "__Host-A=B;", creation_time, server_time,
2932 /*cookie_partition_key=*/std::nullopt,
2933 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
2934 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2935 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2936 EXPECT_FALSE(CanonicalCookie::Create(
2937 https_url, "__Host-A=B; Domain=" + domain + "; Path=/;", creation_time,
2938 server_time, /*cookie_partition_key=*/std::nullopt,
2939 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
2940 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2941 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2942 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
2943 https_url, "__Host-A=B; Path=/; Secure;", creation_time, server_time));
2944
2945 // A __Host- cookie must be set from a secure scheme.
2946 EXPECT_FALSE(CanonicalCookie::Create(
2947 http_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
2948 creation_time, server_time, /*cookie_partition_key=*/std::nullopt,
2949 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
2950 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2951 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2952 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
2953 https_url, "__Host-A=B; Path=/; Secure;", creation_time, server_time));
2954
2955 // A __Host- cookie can't have a Domain.
2956 EXPECT_FALSE(CanonicalCookie::Create(
2957 https_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
2958 creation_time, server_time, /*cookie_partition_key=*/std::nullopt,
2959 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
2960 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2961 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2962 EXPECT_FALSE(CanonicalCookie::Create(
2963 https_url, "__Host-A=B; Domain=" + domain + "; Secure;", creation_time,
2964 server_time, /*cookie_partition_key=*/std::nullopt,
2965 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
2966 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2967 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2968
2969 // A __Host- cookie may have a domain if it's an IP address that matches the
2970 // URL.
2971 EXPECT_TRUE(CanonicalCookie::Create(
2972 GURL("https://127.0.0.1"),
2973 "__Host-A=B; Domain=127.0.0.1; Path=/; Secure;", creation_time,
2974 server_time, /*cookie_partition_key=*/std::nullopt,
2975 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
2976 // A __Host- cookie with an IP address domain does not need the domain
2977 // attribute specified explicitly (just like a normal domain).
2978 EXPECT_TRUE(CanonicalCookie::Create(
2979 GURL("https://127.0.0.1"), "__Host-A=B; Domain=; Path=/; Secure;",
2980 creation_time, server_time, /*cookie_partition_key=*/std::nullopt,
2981 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
2982
2983 // A __Host- cookie must have a Path of "/".
2984 EXPECT_FALSE(CanonicalCookie::Create(
2985 https_url, "__Host-A=B; Path=/foo; Secure;", creation_time, server_time,
2986 /*cookie_partition_key=*/std::nullopt, /*block_truncated=*/true,
2987 CookieSourceType::kUnknown, &status));
2988 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2989 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2990 EXPECT_FALSE(CanonicalCookie::Create(
2991 https_url, "__Host-A=B; Secure;", creation_time, server_time,
2992 /*cookie_partition_key=*/std::nullopt, true, CookieSourceType::kUnknown,
2993 &status));
2994 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
2995 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
2996 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
2997 https_url, "__Host-A=B; Secure; Path=/;", creation_time, server_time));
2998
2999 // Prefixes are case insensitive.
3000 EXPECT_FALSE(CanonicalCookie::Create(
3001 http_url, "__host-A=B; Domain=" + domain + "; Path=/;", creation_time,
3002 server_time, /*cookie_partition_key=*/std::nullopt,
3003 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
3004 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3005 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
3006
3007 EXPECT_FALSE(CanonicalCookie::Create(
3008 http_url, "__HOST-A=B; Domain=" + domain + "; Path=/;", creation_time,
3009 server_time, /*cookie_partition_key=*/std::nullopt,
3010 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
3011 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3012 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
3013
3014 EXPECT_FALSE(CanonicalCookie::Create(
3015 http_url, "__HoSt-A=B; Domain=" + domain + "; Path=/;", creation_time,
3016 server_time, /*cookie_partition_key=*/std::nullopt,
3017 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
3018 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3019 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
3020
3021 {
3022 base::test::ScopedFeatureList scope_feature_list;
3023 scope_feature_list.InitAndDisableFeature(
3024 features::kCaseInsensitiveCookiePrefix);
3025
3026 EXPECT_TRUE(CanonicalCookie::Create(
3027 http_url, "__host-A=B; Domain=" + domain + "; Path=/;", creation_time,
3028 server_time, /*cookie_partition_key=*/std::nullopt,
3029 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
3030
3031 EXPECT_TRUE(CanonicalCookie::Create(
3032 http_url, "__HOST-A=B; Domain=" + domain + "; Path=/;", creation_time,
3033 server_time, /*cookie_partition_key=*/std::nullopt,
3034 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
3035
3036 EXPECT_TRUE(CanonicalCookie::Create(
3037 http_url, "__HoSt-A=B; Domain=" + domain + "; Path=/;", creation_time,
3038 server_time, /*cookie_partition_key=*/std::nullopt,
3039 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
3040 }
3041
3042 // Rules don't apply for a typoed prefix.
3043 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
3044 https_url, "__HostA=B; Domain=" + domain + "; Secure;", creation_time,
3045 server_time));
3046
3047 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
3048 https_url, "_Host-A=B; Domain=" + domain + "; Secure;", creation_time,
3049 server_time));
3050
3051 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
3052 https_url, "Host-A=B; Domain=" + domain + "; Secure;", creation_time,
3053 server_time));
3054
3055 // Hidden __Host- prefixes should be rejected.
3056 EXPECT_FALSE(CanonicalCookie::Create(
3057 https_url, "=__Host-A=B; Path=/; Secure;", creation_time, server_time,
3058 /*cookie_partition_key=*/std::nullopt, /*block_truncated=*/true,
3059 CookieSourceType::kUnknown, &status));
3060 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3061 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
3062 EXPECT_FALSE(CanonicalCookie::Create(
3063 https_url, "=__Host-A; Path=/; Secure;", creation_time, server_time,
3064 /*cookie_partition_key=*/std::nullopt,
3065 /*block_truncated=*/true, CookieSourceType::kUnknown, &status));
3066 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3067 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
3068
3069 // While tricky, this isn't considered hidden and is fine.
3070 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
3071 https_url, "A=__Host-A=B; Path=/; Secure;", creation_time, server_time));
3072 }
3073
TEST(CanonicalCookieTest,CanCreateSecureCookiesFromAnyScheme)3074 TEST(CanonicalCookieTest, CanCreateSecureCookiesFromAnyScheme) {
3075 GURL http_url("http://www.example.com");
3076 GURL https_url("https://www.example.com");
3077 base::Time creation_time = base::Time::Now();
3078 std::optional<base::Time> server_time = std::nullopt;
3079
3080 std::unique_ptr<CanonicalCookie> http_cookie_no_secure(
3081 CanonicalCookie::CreateForTesting(http_url, "a=b", creation_time,
3082 server_time));
3083 std::unique_ptr<CanonicalCookie> http_cookie_secure(
3084 CanonicalCookie::CreateForTesting(http_url, "a=b; Secure", creation_time,
3085 server_time));
3086 std::unique_ptr<CanonicalCookie> https_cookie_no_secure(
3087 CanonicalCookie::CreateForTesting(https_url, "a=b", creation_time,
3088 server_time));
3089 std::unique_ptr<CanonicalCookie> https_cookie_secure(
3090 CanonicalCookie::CreateForTesting(https_url, "a=b; Secure", creation_time,
3091 server_time));
3092
3093 EXPECT_TRUE(http_cookie_no_secure.get());
3094 EXPECT_TRUE(http_cookie_secure.get());
3095 EXPECT_TRUE(https_cookie_no_secure.get());
3096 EXPECT_TRUE(https_cookie_secure.get());
3097 }
3098
TEST(CanonicalCookieTest,IsCanonical)3099 TEST(CanonicalCookieTest, IsCanonical) {
3100 // Base correct template.
3101 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3102 "A", "B", "x.y", "/path", base::Time(), base::Time(),
3103 base::Time(), base::Time(), false, false,
3104 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3105 ->IsCanonical());
3106
3107 // Newline in name.
3108 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3109 "A\n", "B", "x.y", "/path", base::Time(), base::Time(),
3110 base::Time(), base::Time(), false, false,
3111 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3112 ->IsCanonical());
3113
3114 // Carriage return in name.
3115 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3116 "A\r", "B", "x.y", "/path", base::Time(), base::Time(),
3117 base::Time(), base::Time(), false, false,
3118 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3119 ->IsCanonical());
3120
3121 // Null character in name.
3122 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3123 std::string("A\0Z", 3), "B", "x.y", "/path", base::Time(),
3124 base::Time(), base::Time(), base::Time(), false, false,
3125 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3126 ->IsCanonical());
3127
3128 // Name begins with whitespace.
3129 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3130 " A", "B", "x.y", "/path", base::Time(), base::Time(),
3131 base::Time(), base::Time(), false, false,
3132 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3133 ->IsCanonical());
3134
3135 // Name ends with whitespace.
3136 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3137 "A ", "B", "x.y", "/path", base::Time(), base::Time(),
3138 base::Time(), base::Time(), false, false,
3139 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3140 ->IsCanonical());
3141
3142 // Empty name. (Note this is against the spec but compatible with other
3143 // browsers.)
3144 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3145 "", "B", "x.y", "/path", base::Time(), base::Time(),
3146 base::Time(), base::Time(), false, false,
3147 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3148 ->IsCanonical());
3149
3150 // Space in name
3151 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3152 "A C", "B", "x.y", "/path", base::Time(), base::Time(),
3153 base::Time(), base::Time(), false, false,
3154 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3155 ->IsCanonical());
3156
3157 // Extra space suffixing name.
3158 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3159 "A ", "B", "x.y", "/path", base::Time(), base::Time(),
3160 base::Time(), base::Time(), false, false,
3161 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3162 ->IsCanonical());
3163
3164 // '=' character in name.
3165 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3166 "A=", "B", "x.y", "/path", base::Time(), base::Time(),
3167 base::Time(), base::Time(), false, false,
3168 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3169 ->IsCanonical());
3170
3171 // Separator in name.
3172 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3173 "A;", "B", "x.y", "/path", base::Time(), base::Time(),
3174 base::Time(), base::Time(), false, false,
3175 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3176 ->IsCanonical());
3177
3178 // '=' character in value.
3179 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3180 "A", "B=", "x.y", "/path", base::Time(), base::Time(),
3181 base::Time(), base::Time(), false, false,
3182 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3183 ->IsCanonical());
3184
3185 // Separator in value.
3186 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3187 "A", "B;", "x.y", "/path", base::Time(), base::Time(),
3188 base::Time(), base::Time(), false, false,
3189 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3190 ->IsCanonical());
3191
3192 // Separator in domain.
3193 //
3194 // TODO(https://crbug.com/1416013): The character ';' is permitted in the URL
3195 // host. That makes IsCanonical() return true here. However, previously,
3196 // IsCanonical() used to false because ';' was a forbidden character. We need
3197 // to verify whether this change is acceptable or not.
3198 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3199 "A", "B", ";x.y", "/path", base::Time(), base::Time(),
3200 base::Time(), base::Time(), false, false,
3201 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3202 ->IsCanonical());
3203
3204 // Garbage in domain.
3205 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3206 "A", "B", "@:&", "/path", base::Time(), base::Time(),
3207 base::Time(), base::Time(), false, false,
3208 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3209 ->IsCanonical());
3210
3211 // Space in domain.
3212 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3213 "A", "B", "x.y ", "/path", base::Time(), base::Time(),
3214 base::Time(), base::Time(), false, false,
3215 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3216 ->IsCanonical());
3217
3218 // Empty domain. (This is against cookie spec, but needed for Chrome's
3219 // out-of-spec use of cookies for extensions; see http://crbug.com/730633.
3220 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3221 "A", "B", "", "/path", base::Time(), base::Time(),
3222 base::Time(), base::Time(), false, false,
3223 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3224 ->IsCanonical());
3225
3226 // Path does not start with a "/".
3227 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3228 "A", "B", "x.y", "path", base::Time(), base::Time(),
3229 base::Time(), base::Time(), false, false,
3230 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3231 ->IsCanonical());
3232
3233 // Empty path.
3234 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3235 "A", "B", "x.y", "", base::Time(), base::Time(),
3236 base::Time(), base::Time(), false, false,
3237 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3238 ->IsCanonical());
3239
3240 // "localhost" as domain.
3241 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3242 "A", "B", "localhost", "/path", base::Time(), base::Time(),
3243 base::Time(), base::Time(), false, false,
3244 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3245 ->IsCanonical());
3246
3247 // non-ASCII domain.
3248 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3249 "A", "B", "\xC3\xA9xample.com", "/path", base::Time(),
3250 base::Time(), base::Time(), base::Time(), false, false,
3251 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3252 ->IsCanonical());
3253
3254 // punycode domain.
3255 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3256 "A", "B", "xn--xample-9ua.com", "/path", base::Time(),
3257 base::Time(), base::Time(), base::Time(), false, false,
3258 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3259 ->IsCanonical());
3260
3261 // Localhost IPv4 address as domain.
3262 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3263 "A", "B", "127.0.0.1", "/path", base::Time(), base::Time(),
3264 base::Time(), base::Time(), false, false,
3265 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3266 ->IsCanonical());
3267
3268 // Simple IPv4 address as domain.
3269 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3270 "A", "B", "1.2.3.4", "/path", base::Time(), base::Time(),
3271 base::Time(), base::Time(), false, false,
3272 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3273 ->IsCanonical());
3274
3275 // period-prefixed IPv4 address as domain.
3276 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3277 "A", "B", ".1.3.2.4", "/path", base::Time(), base::Time(),
3278 base::Time(), base::Time(), false, false,
3279 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3280 ->IsCanonical());
3281
3282 // period-prefixed truncated IPv4 address as domain.
3283 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3284 "A", "B", ".3.2.4", "/path", base::Time(), base::Time(),
3285 base::Time(), base::Time(), true, false,
3286 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3287 ->IsCanonical());
3288
3289 // truncated IPv4 address as domain.
3290 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3291 "A", "B", "3.2.4", "/path", base::Time(), base::Time(),
3292 base::Time(), base::Time(), true, false,
3293 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3294 ->IsCanonical());
3295
3296 // Non-canonical IPv4 address as domain.
3297 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3298 "A", "B", "01.2.03.4", "/path", base::Time(), base::Time(),
3299 base::Time(), base::Time(), false, false,
3300 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3301 ->IsCanonical());
3302
3303 // Non-canonical IPv4 address as domain.
3304 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3305 "A", "B", "16843009", "/path", base::Time(), base::Time(),
3306 base::Time(), base::Time(), false, false,
3307 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3308 ->IsCanonical());
3309
3310 // Non-canonical IPv4 address as domain.
3311 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3312 "A", "B", "0x1010101", "/path", base::Time(), base::Time(),
3313 base::Time(), base::Time(), false, false,
3314 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3315 ->IsCanonical());
3316
3317 // Null IPv6 address as domain.
3318 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3319 "A", "B", "[::]", "/path", base::Time(), base::Time(),
3320 base::Time(), base::Time(), false, false,
3321 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3322 ->IsCanonical());
3323
3324 // Localhost IPv6 address as domain.
3325 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3326 "A", "B", "[::1]", "/path", base::Time(), base::Time(),
3327 base::Time(), base::Time(), false, false,
3328 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3329 ->IsCanonical());
3330
3331 // Fully speced IPv6 address as domain.
3332 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3333 "A", "B", "[2001:0DB8:AC10:FE01:0000:0000:0000:0000]",
3334 "/path", base::Time(), base::Time(), base::Time(),
3335 base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
3336 COOKIE_PRIORITY_LOW)
3337 ->IsCanonical());
3338
3339 // Zero abbreviated IPv6 address as domain. Not canonical because of leading
3340 // zeros & uppercase hex letters.
3341 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3342 "A", "B", "[2001:0DB8:AC10:FE01::]", "/path", base::Time(),
3343 base::Time(), base::Time(), base::Time(), false, false,
3344 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3345 ->IsCanonical());
3346
3347 // Zero prefixes removed IPv6 address as domain. Not canoncial because of
3348 // uppercase hex letters.
3349 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3350 "A", "B", "[2001:DB8:AC10:FE01::]", "/path", base::Time(),
3351 base::Time(), base::Time(), base::Time(), false, false,
3352 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3353 ->IsCanonical());
3354
3355 // Lowercased hex IPv6 address as domain.
3356 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3357 "A", "B", "[2001:db8:ac10:fe01::]", "/path", base::Time(),
3358 base::Time(), base::Time(), base::Time(), false, false,
3359 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3360 ->IsCanonical());
3361
3362 // Lowercased hex IPv6 address as domain for domain cookie.
3363 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3364 "A", "B", ".[2001:db8:ac10:fe01::]", "/path", base::Time(),
3365 base::Time(), base::Time(), base::Time(), false, false,
3366 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3367 ->IsCanonical());
3368
3369 // Incomplete lowercased hex IPv6 address as domain.
3370 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3371 "A", "B", "[2001:db8:ac10:fe01:]", "/path", base::Time(),
3372 base::Time(), base::Time(), base::Time(), false, false,
3373 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3374 ->IsCanonical());
3375
3376 // Missing square brackets in IPv6 address as domain.
3377 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3378 "A", "B", "2606:2800:220:1:248:1893:25c8:1946", "/path",
3379 base::Time(), base::Time(), base::Time(), base::Time(),
3380 false, false, CookieSameSite::NO_RESTRICTION,
3381 COOKIE_PRIORITY_LOW)
3382 ->IsCanonical());
3383
3384 // Properly formatted host cookie.
3385 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3386 "__Host-A", "B", "x.y", "/", base::Time(), base::Time(),
3387 base::Time(), base::Time(), true, false,
3388 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3389 ->IsCanonical());
3390
3391 // Insecure host cookie.
3392 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3393 "__Host-A", "B", "x.y", "/", base::Time(), base::Time(),
3394 base::Time(), base::Time(), false, false,
3395 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3396 ->IsCanonical());
3397
3398 // Host cookie with non-null path.
3399 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3400 "__Host-A", "B", "x.y", "/path", base::Time(), base::Time(),
3401 base::Time(), base::Time(), true, false,
3402 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3403 ->IsCanonical());
3404
3405 // Host cookie with empty domain.
3406 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3407 "__Host-A", "B", "", "/", base::Time(), base::Time(),
3408 base::Time(), base::Time(), true, false,
3409 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3410 ->IsCanonical());
3411
3412 // Host cookie with period prefixed domain.
3413 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3414 "__Host-A", "B", ".x.y", "/", base::Time(), base::Time(),
3415 base::Time(), base::Time(), true, false,
3416 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3417 ->IsCanonical());
3418
3419 // Properly formatted secure cookie.
3420 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3421 "__Secure-A", "B", "x.y", "/", base::Time(), base::Time(),
3422 base::Time(), base::Time(), true, false,
3423 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3424 ->IsCanonical());
3425
3426 // Insecure secure cookie.
3427 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3428 "__Secure-A", "B", "x.y", "/", base::Time(), base::Time(),
3429 base::Time(), base::Time(), false, false,
3430 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3431 ->IsCanonical());
3432
3433 // Partitioned attribute used correctly (__Host- prefix).
3434 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3435 "__Host-A", "B", "x.y", "/", base::Time(), base::Time(),
3436 base::Time(), base::Time(), /*secure=*/true,
3437 /*httponly=*/false, CookieSameSite::UNSPECIFIED,
3438 COOKIE_PRIORITY_LOW,
3439 CookiePartitionKey::FromURLForTesting(
3440 GURL("https://toplevelsite.com")))
3441 ->IsCanonical());
3442
3443 // Partitioned attribute with no __Host- prefix is still valid if it has
3444 // Secure, Path=/, and no Domain.
3445 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3446 "A", "B", "x.y", "/", base::Time(), base::Time(),
3447 base::Time(), base::Time(), /*secure=*/true,
3448 /*httponly=*/false, CookieSameSite::UNSPECIFIED,
3449 COOKIE_PRIORITY_LOW,
3450 CookiePartitionKey::FromURLForTesting(
3451 GURL("https://toplevelsite.com")))
3452 ->IsCanonical());
3453
3454 // Partitioned attribute invalid, not Secure.
3455 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3456 "A", "B", "x.y", "/", base::Time(), base::Time(),
3457 base::Time(), base::Time(), /*secure=*/false,
3458 /*httponly=*/false, CookieSameSite::UNSPECIFIED,
3459 COOKIE_PRIORITY_LOW,
3460 CookiePartitionKey::FromURLForTesting(
3461 GURL("https://toplevelsite.com")))
3462 ->IsCanonical());
3463
3464 // Partitioned attribute is valid when Path != "/".
3465 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3466 "A", "B", "x.y", "/foo/bar", base::Time(), base::Time(),
3467 base::Time(), base::Time(), /*secure=*/true,
3468 /*httponly=*/false, CookieSameSite::UNSPECIFIED,
3469 COOKIE_PRIORITY_LOW,
3470 CookiePartitionKey::FromURLForTesting(
3471 GURL("https://toplevelsite.com")))
3472 ->IsCanonical());
3473
3474 // Partitioned attribute is valid when Domain attribute also included.
3475 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3476 "A", "B", ".x.y", "/", base::Time(), base::Time(),
3477 base::Time(), base::Time(), /*secure=*/true,
3478 /*httponly=*/false, CookieSameSite::UNSPECIFIED,
3479 COOKIE_PRIORITY_LOW,
3480 CookiePartitionKey::FromURLForTesting(
3481 GURL("https://toplevelsite.com")))
3482 ->IsCanonical());
3483
3484 // Hidden cookie prefixes.
3485 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3486 "", "__Secure-a=b", "x.y", "/", base::Time(), base::Time(),
3487 base::Time(), base::Time(), true, false,
3488 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3489 ->IsCanonical());
3490
3491 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3492 "", "__Secure-a", "x.y", "/", base::Time(), base::Time(),
3493 base::Time(), base::Time(), true, false,
3494 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3495 ->IsCanonical());
3496
3497 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3498 "", "__Host-a=b", "x.y", "/", base::Time(), base::Time(),
3499 base::Time(), base::Time(), true, false,
3500 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3501 ->IsCanonical());
3502
3503 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
3504 "", "__Host-a", "x.y", "/", base::Time(), base::Time(),
3505 base::Time(), base::Time(), true, false,
3506 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3507 ->IsCanonical());
3508
3509 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3510 "a", "__Secure-a=b", "x.y", "/", base::Time(), base::Time(),
3511 base::Time(), base::Time(), true, false,
3512 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3513 ->IsCanonical());
3514
3515 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
3516 "a", "__Host-a=b", "x.y", "/", base::Time(), base::Time(),
3517 base::Time(), base::Time(), true, false,
3518 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW)
3519 ->IsCanonical());
3520 }
3521
TEST(CanonicalCookieTest,TestSetCreationDate)3522 TEST(CanonicalCookieTest, TestSetCreationDate) {
3523 auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
3524 "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(),
3525 base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
3526 COOKIE_PRIORITY_LOW);
3527 EXPECT_TRUE(cookie->CreationDate().is_null());
3528
3529 base::Time now(base::Time::Now());
3530 cookie->SetCreationDate(now);
3531 EXPECT_EQ(now, cookie->CreationDate());
3532 }
3533
TEST(CanonicalCookieTest,TestPrefixHistograms)3534 TEST(CanonicalCookieTest, TestPrefixHistograms) {
3535 base::HistogramTester histograms;
3536 const char kCookiePrefixHistogram[] = "Cookie.CookiePrefix";
3537 const char kCookiePrefixVariantHistogram[] =
3538 "Cookie.CookiePrefix.CaseVariant";
3539 const char kVariantValidHistogram[] = "Cookie.CookiePrefix.CaseVariantValid";
3540 const char kVariantCountHistogram[] = "Cookie.CookiePrefix.CaseVariantCount";
3541 GURL https_url("https://www.example.test");
3542 base::Time creation_time = base::Time::Now();
3543 std::optional<base::Time> server_time = std::nullopt;
3544
3545 EXPECT_FALSE(CanonicalCookie::CreateForTesting(https_url, "__Host-A=B;",
3546 creation_time, server_time));
3547
3548 histograms.ExpectBucketCount(kCookiePrefixHistogram,
3549 CanonicalCookie::COOKIE_PREFIX_HOST, 1);
3550
3551 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
3552 https_url, "__Host-A=B; Path=/; Secure", creation_time, server_time));
3553 histograms.ExpectBucketCount(kCookiePrefixHistogram,
3554 CanonicalCookie::COOKIE_PREFIX_HOST, 2);
3555 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
3556 https_url, "__HostA=B; Path=/; Secure", creation_time, server_time));
3557 histograms.ExpectBucketCount(kCookiePrefixHistogram,
3558 CanonicalCookie::COOKIE_PREFIX_HOST, 2);
3559
3560 EXPECT_FALSE(CanonicalCookie::CreateForTesting(https_url, "__Secure-A=B;",
3561 creation_time, server_time));
3562
3563 histograms.ExpectBucketCount(kCookiePrefixHistogram,
3564 CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
3565 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
3566 https_url, "__Secure-A=B; Path=/; Secure", creation_time, server_time));
3567 histograms.ExpectBucketCount(kCookiePrefixHistogram,
3568 CanonicalCookie::COOKIE_PREFIX_SECURE, 2);
3569 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
3570 https_url, "__SecureA=B; Path=/; Secure", creation_time, server_time));
3571 histograms.ExpectBucketCount(kCookiePrefixHistogram,
3572 CanonicalCookie::COOKIE_PREFIX_SECURE, 2);
3573
3574 // Test prefix case variants
3575 const int sensitive_value_host = histograms.GetBucketCount(
3576 kCookiePrefixHistogram, CanonicalCookie::COOKIE_PREFIX_HOST);
3577 const int sensitive_value_secure = histograms.GetBucketCount(
3578 kCookiePrefixHistogram, CanonicalCookie::COOKIE_PREFIX_SECURE);
3579
3580 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
3581 https_url, "__SECURE-A=B; Path=/; Secure", creation_time, server_time));
3582 histograms.ExpectBucketCount(kCookiePrefixVariantHistogram,
3583 CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
3584 histograms.ExpectBucketCount(kCookiePrefixHistogram,
3585 CanonicalCookie::COOKIE_PREFIX_SECURE,
3586 sensitive_value_secure);
3587
3588 EXPECT_TRUE(CanonicalCookie::CreateForTesting(
3589 https_url, "__HOST-A=B; Path=/; Secure", creation_time, server_time));
3590 histograms.ExpectBucketCount(kCookiePrefixVariantHistogram,
3591 CanonicalCookie::COOKIE_PREFIX_HOST, 1);
3592 histograms.ExpectBucketCount(kCookiePrefixHistogram,
3593 CanonicalCookie::COOKIE_PREFIX_HOST,
3594 sensitive_value_host);
3595
3596 // True indicates a variant
3597 histograms.ExpectBucketCount(kVariantCountHistogram, true, 2);
3598 histograms.ExpectBucketCount(kVariantCountHistogram, false, 4);
3599
3600 // Invalid variants
3601 EXPECT_FALSE(CanonicalCookie::CreateForTesting(https_url, "__SECURE-A=B",
3602 creation_time, server_time));
3603
3604 EXPECT_FALSE(CanonicalCookie::CreateForTesting(https_url, "__HOST-A=B;",
3605 creation_time, server_time));
3606
3607 histograms.ExpectBucketCount(kVariantValidHistogram, true, 2);
3608 histograms.ExpectBucketCount(kVariantValidHistogram, false, 2);
3609 }
3610
TEST(CanonicalCookieTest,TestHasNonASCIIHistograms)3611 TEST(CanonicalCookieTest, TestHasNonASCIIHistograms) {
3612 base::HistogramTester histograms;
3613 const char kCookieNonASCIINameHistogram[] = "Cookie.HasNonASCII.Name";
3614 const char kCookieNonASCIIValueHistogram[] = "Cookie.HasNonASCII.Value";
3615 const GURL test_url("https://www.example.test");
3616 int expected_name_true = 0;
3617 int expected_name_false = 0;
3618 int expected_value_true = 0;
3619 int expected_value_false = 0;
3620
3621 auto create_for_test = [&](const std::string& name,
3622 const std::string& value) {
3623 return CanonicalCookie::CreateForTesting(
3624 test_url, name + "=" + value, /*creation_time=*/base::Time::Now());
3625 };
3626
3627 auto check_histograms = [&]() {
3628 histograms.ExpectBucketCount(kCookieNonASCIINameHistogram, true,
3629 expected_name_true);
3630 histograms.ExpectBucketCount(kCookieNonASCIINameHistogram, false,
3631 expected_name_false);
3632 histograms.ExpectBucketCount(kCookieNonASCIIValueHistogram, true,
3633 expected_value_true);
3634 histograms.ExpectBucketCount(kCookieNonASCIIValueHistogram, false,
3635 expected_value_false);
3636 };
3637
3638 EXPECT_TRUE(create_for_test("foo", "bar"));
3639 expected_name_false++;
3640 expected_value_false++;
3641 check_histograms();
3642
3643 EXPECT_TRUE(create_for_test("Uni\xf0\x9f\x8d\xaa", "bar"));
3644 expected_name_true++;
3645 expected_value_false++;
3646 check_histograms();
3647
3648 EXPECT_TRUE(create_for_test("foo", "Uni\xf0\x9f\x8d\xaa"));
3649 expected_name_false++;
3650 expected_value_true++;
3651 check_histograms();
3652
3653 EXPECT_TRUE(create_for_test("Uni\xf0\x9f\x8d\xaa", "Uni\xf0\x9f\x8d\xaa"));
3654 expected_name_true++;
3655 expected_value_true++;
3656 check_histograms();
3657 }
3658
TEST(CanonicalCookieTest,BuildCookieLine)3659 TEST(CanonicalCookieTest, BuildCookieLine) {
3660 std::vector<std::unique_ptr<CanonicalCookie>> cookies;
3661 GURL url("https://example.com/");
3662 base::Time now = base::Time::Now();
3663 std::optional<base::Time> server_time = std::nullopt;
3664 MatchCookieLineToVector("", cookies);
3665
3666 cookies.push_back(
3667 CanonicalCookie::CreateForTesting(url, "A=B", now, server_time));
3668 MatchCookieLineToVector("A=B", cookies);
3669 // Nameless cookies are sent back without a prefixed '='.
3670 cookies.push_back(
3671 CanonicalCookie::CreateForTesting(url, "C", now, server_time));
3672 MatchCookieLineToVector("A=B; C", cookies);
3673 // Cookies separated by ';'.
3674 cookies.push_back(
3675 CanonicalCookie::CreateForTesting(url, "D=E", now, server_time));
3676 MatchCookieLineToVector("A=B; C; D=E", cookies);
3677 // BuildCookieLine doesn't reorder the list, it relies on the caller to do so.
3678 cookies.push_back(CanonicalCookie::CreateForTesting(
3679 url, "F=G", now - base::Seconds(1), server_time));
3680 MatchCookieLineToVector("A=B; C; D=E; F=G", cookies);
3681 // BuildCookieLine doesn't deduplicate.
3682 cookies.push_back(CanonicalCookie::CreateForTesting(
3683 url, "D=E", now - base::Seconds(2), server_time));
3684 MatchCookieLineToVector("A=B; C; D=E; F=G; D=E", cookies);
3685 // BuildCookieLine should match the spec in the case of an empty name with a
3686 // value containing an equal sign (even if it currently produces "invalid"
3687 // cookie lines).
3688 cookies.push_back(
3689 CanonicalCookie::CreateForTesting(url, "=H=I", now, server_time));
3690 MatchCookieLineToVector("A=B; C; D=E; F=G; D=E; H=I", cookies);
3691 }
3692
TEST(CanonicalCookieTest,BuildCookieAttributesLine)3693 TEST(CanonicalCookieTest, BuildCookieAttributesLine) {
3694 std::unique_ptr<CanonicalCookie> cookie;
3695 GURL url("https://example.com/");
3696 base::Time now = base::Time::Now();
3697 std::optional<base::Time> server_time = std::nullopt;
3698
3699 cookie = CanonicalCookie::CreateForTesting(url, "A=B", now, server_time);
3700 EXPECT_EQ("A=B; domain=example.com; path=/",
3701 CanonicalCookie::BuildCookieAttributesLine(*cookie));
3702 // Nameless cookies are sent back without a prefixed '='.
3703 cookie = CanonicalCookie::CreateForTesting(url, "C", now, server_time);
3704 EXPECT_EQ("C; domain=example.com; path=/",
3705 CanonicalCookie::BuildCookieAttributesLine(*cookie));
3706 // BuildCookieAttributesLine should match the spec in the case of an empty
3707 // name with a value containing an equal sign (even if it currently produces
3708 // "invalid" cookie lines).
3709 cookie = CanonicalCookie::CreateForTesting(url, "=H=I", now, server_time);
3710 EXPECT_EQ("H=I; domain=example.com; path=/",
3711 CanonicalCookie::BuildCookieAttributesLine(*cookie));
3712 // BuildCookieAttributesLine should include all attributes.
3713 cookie = CanonicalCookie::CreateForTesting(
3714 url,
3715 "A=B; domain=.example.com; path=/; secure; "
3716 "httponly; partitioned; samesite=lax",
3717 now, server_time, CookiePartitionKey::FromURLForTesting(url));
3718 EXPECT_EQ(
3719 "A=B; domain=.example.com; path=/; secure; httponly; partitioned; "
3720 "samesite=lax",
3721 CanonicalCookie::BuildCookieAttributesLine(*cookie));
3722 }
3723
3724 // Confirm that input arguments are reflected in the output cookie.
TEST(CanonicalCookieTest,CreateSanitizedCookie_Inputs)3725 TEST(CanonicalCookieTest, CreateSanitizedCookie_Inputs) {
3726 base::Time two_hours_ago = base::Time::Now() - base::Hours(2);
3727 base::Time one_hour_ago = base::Time::Now() - base::Hours(1);
3728 base::Time one_hour_from_now = base::Time::Now() + base::Hours(1);
3729 CookieInclusionStatus status;
3730 std::unique_ptr<CanonicalCookie> cc;
3731
3732 cc = CanonicalCookie::CreateSanitizedCookie(
3733 GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
3734 base::Time(), base::Time(), base::Time(), false /*secure*/,
3735 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3736 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
3737 EXPECT_TRUE(cc);
3738 EXPECT_EQ("A", cc->Name());
3739 EXPECT_EQ("B", cc->Value());
3740 EXPECT_EQ("www.foo.com", cc->Domain());
3741 EXPECT_EQ("/foo", cc->Path());
3742 EXPECT_EQ(base::Time(), cc->CreationDate());
3743 EXPECT_EQ(base::Time(), cc->LastAccessDate());
3744 EXPECT_EQ(base::Time(), cc->ExpiryDate());
3745 EXPECT_FALSE(cc->SecureAttribute());
3746 EXPECT_FALSE(cc->IsHttpOnly());
3747 EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cc->SameSite());
3748 EXPECT_EQ(COOKIE_PRIORITY_MEDIUM, cc->Priority());
3749 EXPECT_FALSE(cc->IsPartitioned());
3750 EXPECT_FALSE(cc->IsDomainCookie());
3751 EXPECT_TRUE(status.IsInclude());
3752
3753 // Creation date
3754 cc = CanonicalCookie::CreateSanitizedCookie(
3755 GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
3756 two_hours_ago, base::Time(), base::Time(), false /*secure*/,
3757 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3758 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
3759 EXPECT_TRUE(cc);
3760 EXPECT_EQ(two_hours_ago, cc->CreationDate());
3761 EXPECT_TRUE(status.IsInclude());
3762
3763 // Last access date
3764 cc = CanonicalCookie::CreateSanitizedCookie(
3765 GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
3766 two_hours_ago, base::Time(), one_hour_ago, false /*secure*/,
3767 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3768 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
3769 EXPECT_TRUE(cc);
3770 EXPECT_EQ(one_hour_ago, cc->LastAccessDate());
3771 EXPECT_TRUE(status.IsInclude());
3772
3773 // Expiry
3774 cc = CanonicalCookie::CreateSanitizedCookie(
3775 GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
3776 base::Time(), one_hour_from_now, base::Time(), false /*secure*/,
3777 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3778 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
3779 EXPECT_TRUE(cc);
3780 EXPECT_EQ(one_hour_from_now, cc->ExpiryDate());
3781 EXPECT_TRUE(status.IsInclude());
3782
3783 // Secure
3784 cc = CanonicalCookie::CreateSanitizedCookie(
3785 GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
3786 base::Time(), base::Time(), base::Time(), true /*secure*/,
3787 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3788 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
3789 EXPECT_TRUE(cc);
3790 EXPECT_TRUE(cc->SecureAttribute());
3791 EXPECT_TRUE(status.IsInclude());
3792
3793 // Httponly
3794 cc = CanonicalCookie::CreateSanitizedCookie(
3795 GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
3796 base::Time(), base::Time(), base::Time(), false /*secure*/,
3797 true /*httponly*/, CookieSameSite::NO_RESTRICTION,
3798 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
3799 EXPECT_TRUE(cc);
3800 EXPECT_TRUE(cc->IsHttpOnly());
3801 EXPECT_TRUE(status.IsInclude());
3802
3803 // Same site
3804 cc = CanonicalCookie::CreateSanitizedCookie(
3805 GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
3806 base::Time(), base::Time(), base::Time(), false /*secure*/,
3807 false /*httponly*/, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
3808 std::nullopt /*partition_key*/, &status);
3809 EXPECT_TRUE(cc);
3810 EXPECT_EQ(CookieSameSite::LAX_MODE, cc->SameSite());
3811 EXPECT_TRUE(status.IsInclude());
3812
3813 // Priority
3814 cc = CanonicalCookie::CreateSanitizedCookie(
3815 GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
3816 base::Time(), base::Time(), base::Time(), false /*secure*/,
3817 false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW,
3818 std::nullopt /*partition_key*/, &status);
3819 EXPECT_TRUE(cc);
3820 EXPECT_EQ(COOKIE_PRIORITY_LOW, cc->Priority());
3821 EXPECT_TRUE(status.IsInclude());
3822
3823 // Domain cookie
3824 cc = CanonicalCookie::CreateSanitizedCookie(
3825 GURL("https://www.foo.com"), "A", "B", "www.foo.com", "/foo",
3826 base::Time(), base::Time(), base::Time(), false /*secure*/,
3827 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3828 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
3829 EXPECT_TRUE(cc);
3830 EXPECT_TRUE(cc->IsDomainCookie());
3831 EXPECT_TRUE(status.IsInclude());
3832
3833 // Partitioned
3834 cc = CanonicalCookie::CreateSanitizedCookie(
3835 GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/",
3836 base::Time(), base::Time(), base::Time(), true /*secure*/,
3837 false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW,
3838 CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com")),
3839 &status);
3840 EXPECT_TRUE(cc);
3841 EXPECT_TRUE(cc->IsPartitioned());
3842 EXPECT_TRUE(status.IsInclude());
3843 }
3844
3845 // Make sure sanitization and blocking of cookies works correctly.
TEST(CanonicalCookieTest,CreateSanitizedCookie_Logic)3846 TEST(CanonicalCookieTest, CreateSanitizedCookie_Logic) {
3847 base::Time two_hours_ago = base::Time::Now() - base::Hours(2);
3848 base::Time one_hour_ago = base::Time::Now() - base::Hours(1);
3849 base::Time one_hour_from_now = base::Time::Now() + base::Hours(1);
3850 CookieInclusionStatus status;
3851
3852 // Simple path and domain variations.
3853 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
3854 GURL("http://www.foo.com/foo"), "A", "B", std::string(), "/foo",
3855 one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
3856 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3857 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
3858 EXPECT_TRUE(status.IsInclude());
3859 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
3860 GURL("http://www.foo.com/bar"), "C", "D", "www.foo.com", "/",
3861 two_hours_ago, base::Time(), one_hour_ago, false /*secure*/,
3862 true /*httponly*/, CookieSameSite::NO_RESTRICTION,
3863 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
3864 EXPECT_TRUE(status.IsInclude());
3865 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
3866 GURL("https://www.foo.com"), "E", "F", std::string(), std::string(),
3867 base::Time(), base::Time(), base::Time(), true /*secure*/,
3868 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3869 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
3870 EXPECT_TRUE(status.IsInclude());
3871
3872 // Test the file:// protocol.
3873 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
3874 GURL("file:///"), "A", "B", std::string(), "/foo", one_hour_ago,
3875 one_hour_from_now, base::Time(), false /*secure*/, false /*httponly*/,
3876 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
3877 std::nullopt /*partition_key*/, &status));
3878 EXPECT_TRUE(status.IsInclude());
3879 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
3880 GURL("file:///home/user/foo.txt"), "A", "B", std::string(), "/foo",
3881 one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
3882 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3883 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
3884 EXPECT_TRUE(status.IsInclude());
3885 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
3886 GURL("file:///home/user/foo.txt"), "A", "B", "home", "/foo", one_hour_ago,
3887 one_hour_from_now, base::Time(), false /*secure*/, false /*httponly*/,
3888 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
3889 std::nullopt /*partition_key*/, &status));
3890 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3891 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
3892
3893 // Test that malformed attributes fail to set the cookie.
3894 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
3895 GURL("http://www.foo.com/foo"), " A", "B", std::string(), "/foo",
3896 base::Time(), base::Time(), base::Time(), /*secure=*/false,
3897 /*http_only=*/false, CookieSameSite::NO_RESTRICTION,
3898 COOKIE_PRIORITY_DEFAULT,
3899 /*partition_key=*/std::nullopt, &status));
3900 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3901 {CookieInclusionStatus::EXCLUDE_DISALLOWED_CHARACTER}));
3902 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
3903 GURL("http://www.foo.com/foo"), "A;", "B", std::string(), "/foo",
3904 base::Time(), base::Time(), base::Time(), /*secure=*/false,
3905 /*http_only=*/false, CookieSameSite::NO_RESTRICTION,
3906 COOKIE_PRIORITY_DEFAULT,
3907 /*partition_key=*/std::nullopt, &status));
3908 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3909 {CookieInclusionStatus::EXCLUDE_DISALLOWED_CHARACTER}));
3910 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
3911 GURL("http://www.foo.com/foo"), "A=", "B", std::string(), "/foo",
3912 base::Time(), base::Time(), base::Time(), /*secure=*/false,
3913 /*http_only=*/false, CookieSameSite::NO_RESTRICTION,
3914 COOKIE_PRIORITY_DEFAULT,
3915 /*partition_key=*/std::nullopt, &status));
3916 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3917 {CookieInclusionStatus::EXCLUDE_DISALLOWED_CHARACTER}));
3918 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
3919 GURL("http://www.foo.com/foo"), "A\x07", "B", std::string(), "/foo",
3920 one_hour_ago, one_hour_from_now, base::Time(), /*secure=*/false,
3921 /*http_only=*/false, CookieSameSite::NO_RESTRICTION,
3922 COOKIE_PRIORITY_DEFAULT,
3923 /*partition_key=*/std::nullopt, &status));
3924 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3925 {CookieInclusionStatus::EXCLUDE_DISALLOWED_CHARACTER}));
3926 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
3927 GURL("http://www.foo.com"), "A", " B", std::string(), "/foo",
3928 base::Time(), base::Time(), base::Time(), /*secure=*/false,
3929 /*http_only=*/false, CookieSameSite::NO_RESTRICTION,
3930 COOKIE_PRIORITY_DEFAULT,
3931 /*partition_key=*/std::nullopt, &status));
3932 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3933 {CookieInclusionStatus::EXCLUDE_DISALLOWED_CHARACTER}));
3934 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
3935 GURL("http://www.foo.com"), "A", "\x0fZ", std::string(), "/foo",
3936 base::Time(), base::Time(), base::Time(), /*secure=*/false,
3937 /*http_only=*/false, CookieSameSite::NO_RESTRICTION,
3938 COOKIE_PRIORITY_DEFAULT,
3939 /*partition_key=*/std::nullopt, &status));
3940 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3941 {CookieInclusionStatus::EXCLUDE_DISALLOWED_CHARACTER}));
3942 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
3943 GURL("http://www.foo.com"), "A", "B", "www.foo.com ", "/foo",
3944 base::Time(), base::Time(), base::Time(), false /*secure*/,
3945 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3946 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
3947 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3948 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
3949 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
3950 GURL("http://www.foo.com/foo"), "A", "B", "foo.ozzzzzzle", "/foo",
3951 base::Time(), base::Time(), base::Time(), false /*secure*/,
3952 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3953 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
3954 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3955 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
3956 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
3957 GURL("http://www.foo.com/foo"), "A", "B", std::string(), "foo",
3958 base::Time(), base::Time(), base::Time(), false /*secure*/,
3959 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3960 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
3961 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3962 {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
3963 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
3964 GURL("http://www.foo.com"), "A", "B", std::string(), "/foo ",
3965 base::Time(), base::Time(), base::Time(), /*secure=*/false,
3966 /*http_only=*/false, CookieSameSite::NO_RESTRICTION,
3967 COOKIE_PRIORITY_DEFAULT,
3968 /*partition_key=*/std::nullopt, &status));
3969 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3970 {CookieInclusionStatus::EXCLUDE_DISALLOWED_CHARACTER}));
3971 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
3972 GURL("http://www.foo.com/foo"), "A", "B", "%2Efoo.com", "/foo",
3973 one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
3974 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3975 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
3976 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3977 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
3978 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
3979 GURL("http://domaintest.%E3%81%BF%E3%82%93%E3%81%AA"), "A", "B",
3980 "domaintest.%E3%81%BF%E3%82%93%E3%81%AA", "/foo", base::Time(),
3981 base::Time(), base::Time(), false /*secure*/, false /*httponly*/,
3982 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
3983 std::nullopt /*partition_key*/, &status));
3984 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
3985 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
3986
3987 std::unique_ptr<CanonicalCookie> cc;
3988
3989 // Confirm that setting domain cookies with or without leading periods,
3990 // or on domains different from the URL's, functions correctly.
3991 cc = CanonicalCookie::CreateSanitizedCookie(
3992 GURL("http://www.foo.com/foo"), "A", "B", "www.foo.com", "/foo",
3993 one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
3994 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
3995 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
3996 ASSERT_TRUE(cc);
3997 EXPECT_TRUE(cc->IsDomainCookie());
3998 EXPECT_EQ(".www.foo.com", cc->Domain());
3999 EXPECT_TRUE(status.IsInclude());
4000
4001 cc = CanonicalCookie::CreateSanitizedCookie(
4002 GURL("http://www.foo.com/foo"), "A", "B", ".www.foo.com", "/foo",
4003 one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
4004 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4005 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
4006 ASSERT_TRUE(cc);
4007 EXPECT_TRUE(cc->IsDomainCookie());
4008 EXPECT_EQ(".www.foo.com", cc->Domain());
4009 EXPECT_TRUE(status.IsInclude());
4010
4011 cc = CanonicalCookie::CreateSanitizedCookie(
4012 GURL("http://www.foo.com/foo"), "A", "B", ".foo.com", "/foo",
4013 one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
4014 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4015 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
4016 ASSERT_TRUE(cc);
4017 EXPECT_TRUE(cc->IsDomainCookie());
4018 EXPECT_EQ(".foo.com", cc->Domain());
4019 EXPECT_TRUE(status.IsInclude());
4020
4021 cc = CanonicalCookie::CreateSanitizedCookie(
4022 GURL("http://www.foo.com/foo"), "A", "B", ".www2.www.foo.com", "/foo",
4023 one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
4024 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4025 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
4026 EXPECT_FALSE(cc);
4027 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4028 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
4029
4030 // Secure/URL Scheme mismatch.
4031 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4032 GURL("http://www.foo.com"), "A", "B", std::string(), "/foo", base::Time(),
4033 base::Time(), base::Time(), /*secure=*/true,
4034 /*http_only=*/false, CookieSameSite::NO_RESTRICTION,
4035 COOKIE_PRIORITY_DEFAULT,
4036 /*partition_key=*/std::nullopt, &status));
4037 EXPECT_TRUE(status.IsInclude());
4038 EXPECT_TRUE(status.HasExactlyWarningReasonsForTesting(
4039 {CookieInclusionStatus::WARN_TENTATIVELY_ALLOWING_SECURE_SOURCE_SCHEME}));
4040
4041 // Null creation date/non-null last access date conflict.
4042 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4043 GURL("http://www.foo.com"), "A", "B", std::string(), "/foo", base::Time(),
4044 base::Time(), base::Time::Now(), false /*secure*/, false /*httponly*/,
4045 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4046 std::nullopt /*partition_key*/, &status));
4047 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4048 {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
4049
4050 // Domain doesn't match URL
4051 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4052 GURL("http://www.foo.com"), "A", "B", "www.bar.com", "/", base::Time(),
4053 base::Time(), base::Time(), false /*secure*/, false /*httponly*/,
4054 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4055 std::nullopt /*partition_key*/, &status));
4056 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4057 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
4058
4059 // Path with unusual characters escaped.
4060 cc = CanonicalCookie::CreateSanitizedCookie(
4061 GURL("http://www.foo.com"), "A", "B", std::string(), "/foo\x7F",
4062 base::Time(), base::Time(), base::Time(), false /*secure*/,
4063 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4064 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
4065 ASSERT_TRUE(cc);
4066 EXPECT_EQ("/foo%7F", cc->Path());
4067 EXPECT_TRUE(status.IsInclude());
4068
4069 // Ensure that all characters get escaped the same on all platforms. This is
4070 // also useful for visualizing which characters will actually be escaped.
4071 std::stringstream ss;
4072 ss << "/";
4073 for (uint8_t character = 0; character < 0xFF; character++) {
4074 // Skip any "terminating characters" that CreateSanitizedCookie does not
4075 // allow to be in `path`.
4076 if (character == '\0' || character == '\n' || character == '\r' ||
4077 character == ';') {
4078 continue;
4079 }
4080 ss << character;
4081 }
4082 ss << "\xFF";
4083 std::string initial(ss.str());
4084 std::string expected =
4085 "/%01%02%03%04%05%06%07%08%09%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%"
4086 "1A%1B%1C%1D%1E%1F%20!%22%23$%&'()*+,-./"
4087 "0123456789:%3C=%3E%3F@ABCDEFGHIJKLMNOPQRSTUVWXYZ[/"
4088 "]%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F%80%81%82%83%84%85%86%87%"
4089 "88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%"
4090 "A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%"
4091 "B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%"
4092 "D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%"
4093 "E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF";
4094 cc = CanonicalCookie::CreateSanitizedCookie(
4095 GURL("http://www.foo.com"), "A", "B", std::string(), initial,
4096 base::Time(), base::Time(), base::Time(), false /*secure*/,
4097 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4098 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
4099 ASSERT_TRUE(cc);
4100 EXPECT_EQ(expected, cc->Path());
4101 EXPECT_TRUE(status.IsInclude());
4102
4103 // Empty name and value.
4104 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4105 GURL("http://www.foo.com"), "", "", std::string(), "/", base::Time(),
4106 base::Time(), base::Time(), false /*secure*/, false /*httponly*/,
4107 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4108 std::nullopt /*partition_key*/, &status));
4109 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4110 {CookieInclusionStatus::EXCLUDE_NO_COOKIE_CONTENT}));
4111
4112 // Check that value can contain an equal sign, even when no name is present.
4113 // Note that in newer drafts of RFC6265bis, it is specified that a cookie with
4114 // an empty name and a value containing an equal sign should result in a
4115 // corresponding cookie line that omits the preceding equal sign. This means
4116 // that the cookie line won't be deserialized into the original cookie in this
4117 // case. For now, we'll test for compliance with the spec here, but we aim to
4118 // collect metrics and hopefully fix this in the spec (and then in
4119 // CanonicalCookie) at some point.
4120 // For reference, see: https://github.com/httpwg/http-extensions/pull/1592
4121 cc = CanonicalCookie::CreateSanitizedCookie(
4122 GURL("http://www.foo.com"), "", "ambiguous=value", std::string(),
4123 std::string(), base::Time(), base::Time(), base::Time(), false /*secure*/,
4124 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4125 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
4126 EXPECT_TRUE(cc);
4127 std::vector<std::unique_ptr<CanonicalCookie>> cookies;
4128 cookies.push_back(std::move(cc));
4129 MatchCookieLineToVector("ambiguous=value", cookies);
4130
4131 // Check that name can't contain an equal sign ("ambiguous=name=value" should
4132 // correctly be parsed as name: "ambiguous" and value "name=value", so
4133 // allowing this case would result in cookies that can't serialize correctly).
4134 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4135 GURL("http://www.foo.com"), "ambiguous=name", "value", std::string(),
4136 std::string(), base::Time(), base::Time(), base::Time(), /*secure=*/false,
4137 /*http_only=*/false, CookieSameSite::NO_RESTRICTION,
4138 COOKIE_PRIORITY_DEFAULT,
4139 /*partition_key=*/std::nullopt, &status));
4140 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4141 {CookieInclusionStatus::EXCLUDE_DISALLOWED_CHARACTER}));
4142
4143 // A __Secure- cookie must be Secure.
4144 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4145 GURL("https://www.foo.com"), "__Secure-A", "B", ".www.foo.com", "/",
4146 two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
4147 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4148 std::nullopt /*partition_key*/, &status));
4149 EXPECT_TRUE(status.IsInclude());
4150 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4151 GURL("https://www.foo.com"), "__Secure-A", "B", ".www.foo.com", "/",
4152 two_hours_ago, one_hour_from_now, one_hour_ago, false, false,
4153 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4154 std::nullopt /*partition_key*/, &status));
4155 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4156 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
4157
4158 // A __Host- cookie must be Secure.
4159 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4160 GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/",
4161 two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
4162 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4163 std::nullopt /*partition_key*/, &status));
4164 EXPECT_TRUE(status.IsInclude());
4165 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4166 GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/",
4167 two_hours_ago, one_hour_from_now, one_hour_ago, false, false,
4168 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4169 std::nullopt /*partition_key*/, &status));
4170 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4171 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
4172
4173 // A __Host- cookie must have path "/".
4174 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4175 GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/",
4176 two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
4177 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4178 std::nullopt /*partition_key*/, &status));
4179 EXPECT_TRUE(status.IsInclude());
4180 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4181 GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/foo",
4182 two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
4183 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4184 std::nullopt /*partition_key*/, &status));
4185 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4186 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
4187
4188 // A __Host- cookie must not specify a domain.
4189 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4190 GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/",
4191 two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
4192 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4193 std::nullopt /*partition_key*/, &status));
4194 EXPECT_TRUE(status.IsInclude());
4195 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4196 GURL("https://www.foo.com"), "__Host-A", "B", ".www.foo.com", "/",
4197 two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
4198 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4199 std::nullopt /*partition_key*/, &status));
4200 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4201 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
4202
4203 // Without __Host- prefix, this is a valid host cookie because it does not
4204 // specify a domain.
4205 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4206 GURL("https://www.foo.com"), "A", "B", std::string(), "/", two_hours_ago,
4207 one_hour_from_now, one_hour_ago, true, false,
4208 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4209 std::nullopt /*partition_key*/, &status));
4210 EXPECT_TRUE(status.IsInclude());
4211
4212 // Without __Host- prefix, this is a valid domain (not host) cookie.
4213 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4214 GURL("https://www.foo.com"), "A", "B", ".www.foo.com", "/", two_hours_ago,
4215 one_hour_from_now, one_hour_ago, true, false,
4216 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4217 std::nullopt /*partition_key*/, &status));
4218 EXPECT_TRUE(status.IsInclude());
4219
4220 // The __Host- prefix should not prevent otherwise-valid host cookies from
4221 // being accepted.
4222 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4223 GURL("https://127.0.0.1"), "A", "B", std::string(), "/", two_hours_ago,
4224 one_hour_from_now, one_hour_ago, true, false,
4225 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4226 std::nullopt /*partition_key*/, &status));
4227 EXPECT_TRUE(status.IsInclude());
4228 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4229 GURL("https://127.0.0.1"), "__Host-A", "B", std::string(), "/",
4230 two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
4231 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4232 std::nullopt /*partition_key*/, &status));
4233 EXPECT_TRUE(status.IsInclude());
4234
4235 // Host cookies should not specify domain unless it is an IP address that
4236 // matches the URL.
4237 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4238 GURL("https://127.0.0.1"), "A", "B", "127.0.0.1", "/", two_hours_ago,
4239 one_hour_from_now, one_hour_ago, true, false,
4240 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4241 std::nullopt /*partition_key*/, &status));
4242 EXPECT_TRUE(status.IsInclude());
4243 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4244 GURL("https://127.0.0.1"), "__Host-A", "B", "127.0.0.1", "/",
4245 two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
4246 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4247 std::nullopt /*partition_key*/, &status));
4248 EXPECT_TRUE(status.IsInclude());
4249
4250 // Cookies with hidden prefixes should be rejected.
4251
4252 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4253 GURL("https://www.foo.com"), "", "__Host-A=B", "", "/", two_hours_ago,
4254 one_hour_from_now, one_hour_ago, true, false,
4255 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4256 std::nullopt /*partition_key*/, &status));
4257 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4258 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
4259
4260 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4261 GURL("https://www.foo.com"), "", "__Host-A", "", "/", two_hours_ago,
4262 one_hour_from_now, one_hour_ago, true, false,
4263 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4264 std::nullopt /*partition_key*/, &status));
4265 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4266 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
4267
4268 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4269 GURL("https://www.foo.com"), "", "__Secure-A=B", "", "/", two_hours_ago,
4270 one_hour_from_now, one_hour_ago, true, false,
4271 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4272 std::nullopt /*partition_key*/, &status));
4273 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4274 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
4275
4276 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4277 GURL("https://www.foo.com"), "", "__Secure-A", "", "/", two_hours_ago,
4278 one_hour_from_now, one_hour_ago, true, false,
4279 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4280 std::nullopt /*partition_key*/, &status));
4281 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4282 {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
4283
4284 // While tricky, this aren't considered hidden prefixes and should succeed.
4285 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4286 GURL("https://www.foo.com"), "A", "__Host-A=B", "", "/", two_hours_ago,
4287 one_hour_from_now, one_hour_ago, true, false,
4288 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4289 std::nullopt /*partition_key*/, &status));
4290 EXPECT_TRUE(status.IsInclude());
4291
4292 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4293 GURL("https://www.foo.com"), "A", "__Secure-A=B", "", "/", two_hours_ago,
4294 one_hour_from_now, one_hour_ago, true, false,
4295 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4296 std::nullopt /*partition_key*/, &status));
4297 EXPECT_TRUE(status.IsInclude());
4298
4299 // Partitioned attribute requires __Host-.
4300 status = CookieInclusionStatus();
4301 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4302 GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/",
4303 two_hours_ago, one_hour_from_now, one_hour_ago, true /*secure*/, false,
4304 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4305 std::optional<CookiePartitionKey>(CookiePartitionKey::FromURLForTesting(
4306 GURL("https://toplevelsite.com"))),
4307 &status));
4308 EXPECT_TRUE(status.IsInclude());
4309 // No __Host- prefix is still valid if the cookie still has Secure, Path=/,
4310 // and no Domain.
4311 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4312 GURL("https://www.foo.com"), "A", "B", std::string(), "/", two_hours_ago,
4313 one_hour_from_now, one_hour_ago, true /*secure*/, false,
4314 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4315 std::optional<CookiePartitionKey>(CookiePartitionKey::FromURLForTesting(
4316 GURL("https://toplevelsite.com"))),
4317 &status));
4318 EXPECT_TRUE(status.IsInclude());
4319 status = CookieInclusionStatus();
4320 // Invalid: Not Secure.
4321 status = CookieInclusionStatus();
4322 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4323 GURL("https://www.foo.com"), "A", "B", std::string(), "/", two_hours_ago,
4324 one_hour_from_now, one_hour_ago, /*secure=*/false, /*http_only=*/false,
4325 CookieSameSite::LAX_MODE, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4326 std::optional<CookiePartitionKey>(CookiePartitionKey::FromURLForTesting(
4327 GURL("https://toplevelsite.com"))),
4328 &status));
4329 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4330 {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED}));
4331 // Invalid: invalid Path.
4332 status = CookieInclusionStatus();
4333 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4334 GURL("https://www.foo.com"), "A", "B", std::string(), "/foobar",
4335 two_hours_ago, one_hour_from_now, one_hour_ago, /*secure=*/true,
4336 /*http_only=*/false, CookieSameSite::NO_RESTRICTION,
4337 CookiePriority::COOKIE_PRIORITY_DEFAULT,
4338 std::optional<CookiePartitionKey>(CookiePartitionKey::FromURLForTesting(
4339 GURL("https://toplevelsite.com"))),
4340 &status));
4341 EXPECT_TRUE(status.IsInclude());
4342 // Domain attribute present is still valid.
4343 status = CookieInclusionStatus();
4344 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4345 GURL("https://www.foo.com"), "A", "B", ".foo.com", "/", two_hours_ago,
4346 one_hour_from_now, one_hour_ago, /*secure=*/true, /*http_only=*/false,
4347 CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
4348 std::optional<CookiePartitionKey>(CookiePartitionKey::FromURLForTesting(
4349 GURL("https://toplevelsite.com"))),
4350 &status));
4351 EXPECT_TRUE(status.IsInclude());
4352
4353 status = CookieInclusionStatus();
4354
4355 // Check that CreateSanitizedCookie can gracefully fail on inputs that would
4356 // crash cookie_util::GetCookieDomainWithString due to failing
4357 // DCHECKs. Specifically, GetCookieDomainWithString requires that if the
4358 // domain is empty or the URL's host matches the domain, then the URL's host
4359 // must pass DomainIsHostOnly; it must not begin with a period.
4360 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4361 GURL("http://..."), "A", "B", "...", "/", base::Time(), base::Time(),
4362 base::Time(), false /*secure*/, false /*httponly*/,
4363 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4364 std::nullopt /*partition_key*/, &status));
4365 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4366 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
4367 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4368 GURL("http://."), "A", "B", std::string(), "/", base::Time(),
4369 base::Time(), base::Time(), false /*secure*/, false /*httponly*/,
4370 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4371 std::nullopt /*partition_key*/, &status));
4372 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4373 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
4374 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4375 GURL("http://.chromium.org"), "A", "B", ".chromium.org", "/",
4376 base::Time(), base::Time(), base::Time(), false /*secure*/,
4377 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4378 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
4379 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4380 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
4381
4382 // Check that a file URL with an IPv6 host, and matching IPv6 domain, are
4383 // valid.
4384 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4385 GURL("file://[A::]"), "A", "B", "[A::]", "", base::Time(), base::Time(),
4386 base::Time(), false /*secure*/, false /*httponly*/,
4387 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4388 std::nullopt /*partition_key*/, &status));
4389 EXPECT_TRUE(status.IsInclude());
4390
4391 // On Windows, URLs beginning with two backslashes are considered file
4392 // URLs. On other platforms, they are invalid.
4393 auto double_backslash_ipv6_cookie = CanonicalCookie::CreateSanitizedCookie(
4394 GURL("\\\\[A::]"), "A", "B", "[A::]", "", base::Time(), base::Time(),
4395 base::Time(), false /*secure*/, false /*httponly*/,
4396 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4397 std::nullopt /*partition_key*/, &status);
4398 #if BUILDFLAG(IS_WIN)
4399 EXPECT_TRUE(double_backslash_ipv6_cookie);
4400 EXPECT_TRUE(double_backslash_ipv6_cookie->IsCanonical());
4401 EXPECT_TRUE(status.IsInclude());
4402 #else
4403 EXPECT_FALSE(double_backslash_ipv6_cookie);
4404 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4405 {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
4406 #endif
4407
4408 // Confirm multiple error types can be set.
4409 EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
4410 GURL(""), "", "", "", "", base::Time(), base::Time(), base::Time::Now(),
4411 true /*secure*/, true /*httponly*/, CookieSameSite::STRICT_MODE,
4412 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
4413 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4414 {CookieInclusionStatus::EXCLUDE_NO_COOKIE_CONTENT,
4415 CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE,
4416 CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
4417
4418 // Check that RFC6265bis name + value string length limits are enforced.
4419 std::string max_name(ParsedCookie::kMaxCookieNamePlusValueSize, 'a');
4420 std::string max_value(ParsedCookie::kMaxCookieNamePlusValueSize, 'b');
4421 std::string almost_max_name = max_name.substr(1, std::string::npos);
4422 std::string almost_max_value = max_value.substr(1, std::string::npos);
4423
4424 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4425 GURL("http://www.foo.com/foo"), max_name, "", std::string(), "/foo",
4426 one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
4427 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4428 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
4429 EXPECT_TRUE(status.IsInclude());
4430 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4431 GURL("http://www.foo.com/foo"), "", max_value, std::string(), "/foo",
4432 one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
4433 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4434 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
4435 EXPECT_TRUE(status.IsInclude());
4436 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4437 GURL("http://www.foo.com/foo"), almost_max_name, "b", std::string(),
4438 "/foo", one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
4439 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4440 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
4441 EXPECT_TRUE(status.IsInclude());
4442 EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
4443 GURL("http://www.foo.com/foo"), "a", almost_max_value, std::string(),
4444 "/foo", one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
4445 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4446 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status));
4447 EXPECT_TRUE(status.IsInclude());
4448
4449 cc = CanonicalCookie::CreateSanitizedCookie(
4450 GURL("http://www.foo.com/foo"), max_name, "X", std::string(), "/foo",
4451 one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
4452 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4453 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
4454 EXPECT_FALSE(cc);
4455 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4456 {CookieInclusionStatus::EXCLUDE_NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE}));
4457
4458 cc = CanonicalCookie::CreateSanitizedCookie(
4459 GURL("http://www.foo.com/foo"), "X", max_value, std::string(), "/foo",
4460 one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
4461 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4462 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
4463 EXPECT_FALSE(cc);
4464 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4465 {CookieInclusionStatus::EXCLUDE_NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE}));
4466
4467 // Check that the RFC6265bis attribute value size limits apply to the Path
4468 // attribute value.
4469 std::string almost_max_path(ParsedCookie::kMaxCookieAttributeValueSize - 1,
4470 'c');
4471 std::string max_path = "/" + almost_max_path;
4472 std::string too_long_path = "/X" + almost_max_path;
4473
4474 cc = CanonicalCookie::CreateSanitizedCookie(
4475 GURL("http://www.foo.com" + max_path), "name", "value", std::string(),
4476 max_path, one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
4477 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4478 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
4479 EXPECT_TRUE(cc);
4480 EXPECT_EQ(max_path, cc->Path());
4481 EXPECT_TRUE(status.IsInclude());
4482
4483 cc = CanonicalCookie::CreateSanitizedCookie(
4484 GURL("http://www.foo.com/path-attr-from-url/"), "name", "value",
4485 std::string(), too_long_path, one_hour_ago, one_hour_from_now,
4486 base::Time(), false /*secure*/, false /*httponly*/,
4487 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4488 std::nullopt /*partition_key*/, &status);
4489 EXPECT_FALSE(cc);
4490 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4491 {CookieInclusionStatus::EXCLUDE_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE}));
4492
4493 // Check that length limits on the Path attribute value are not enforced
4494 // in the case where no Path attribute is specified and the path value is
4495 // implicitly set from the URL.
4496 cc = CanonicalCookie::CreateSanitizedCookie(
4497 GURL("http://www.foo.com" + too_long_path + "/"), "name", "value",
4498 std::string(), std::string(), one_hour_ago, one_hour_from_now,
4499 base::Time(), false /*secure*/, false /*httponly*/,
4500 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4501 std::nullopt /*partition_key*/, &status);
4502 EXPECT_TRUE(cc);
4503 EXPECT_EQ(too_long_path, cc->Path());
4504 EXPECT_TRUE(status.IsInclude());
4505
4506 // The Path attribute value gets URL-encoded, so ensure that the size
4507 // limit is enforced after this (to avoid setting cookies where the Path
4508 // attribute value would otherwise exceed the lengths specified in the
4509 // RFC).
4510 std::string expanding_path(ParsedCookie::kMaxCookieAttributeValueSize / 2,
4511 '#');
4512 expanding_path = "/" + expanding_path;
4513
4514 cc = CanonicalCookie::CreateSanitizedCookie(
4515 GURL("http://www.foo.com/path-attr-from-url/"), "name", "value",
4516 std::string(), expanding_path, one_hour_ago, one_hour_from_now,
4517 base::Time(), false /*secure*/, false /*httponly*/,
4518 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4519 std::nullopt /*partition_key*/, &status);
4520 EXPECT_FALSE(cc);
4521 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4522 {CookieInclusionStatus::EXCLUDE_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE}));
4523
4524 // Check that the RFC6265bis attribute value size limits apply to the Domain
4525 // attribute value.
4526 std::string max_domain(ParsedCookie::kMaxCookieAttributeValueSize, 'd');
4527 max_domain.replace(ParsedCookie::kMaxCookieAttributeValueSize - 4, 4, ".com");
4528 std::string too_long_domain = "x" + max_domain;
4529
4530 cc = CanonicalCookie::CreateSanitizedCookie(
4531 GURL("http://" + max_domain + "/"), "name", "value", max_domain, "/",
4532 one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
4533 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4534 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
4535 EXPECT_TRUE(cc);
4536 EXPECT_EQ(max_domain, cc->DomainWithoutDot());
4537 EXPECT_TRUE(status.IsInclude());
4538 cc = CanonicalCookie::CreateSanitizedCookie(
4539 GURL("http://www.domain-from-url.com/"), "name", "value", too_long_domain,
4540 "/", one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
4541 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4542 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
4543 EXPECT_FALSE(cc);
4544 EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
4545 {CookieInclusionStatus::EXCLUDE_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE}));
4546 // Check that length limits on the Domain attribute value are not enforced
4547 // in the case where no Domain attribute is specified and the domain value
4548 // is implicitly set from the URL.
4549 cc = CanonicalCookie::CreateSanitizedCookie(
4550 GURL("http://" + too_long_domain + "/"), "name", "value", std::string(),
4551 "/", one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
4552 false /*httponly*/, CookieSameSite::NO_RESTRICTION,
4553 COOKIE_PRIORITY_DEFAULT, std::nullopt /*partition_key*/, &status);
4554 EXPECT_TRUE(cc);
4555 EXPECT_EQ(too_long_domain, cc->DomainWithoutDot());
4556 EXPECT_TRUE(status.IsInclude());
4557 }
4558
4559 // Make sure that the source scheme and port are set correctly for cookies that
4560 // are marked as "Secure".
TEST(CanonicalCookieTest,Create_SourceSchemePort)4561 TEST(CanonicalCookieTest, Create_SourceSchemePort) {
4562 GURL secure_url("https://example.com");
4563 GURL insecure_url("http://example.com");
4564 GURL insecure_url_custom_port("http://example.com:123");
4565
4566 CookieInclusionStatus status;
4567
4568 std::unique_ptr<CanonicalCookie> cc;
4569
4570 // A secure url doesn't need "Secure" to have a source scheme of secure
4571 cc = CanonicalCookie::Create(secure_url, "a=b; SameSite=Lax",
4572 base::Time::Now(), std::nullopt, std::nullopt,
4573 /*block_truncated=*/true,
4574 CookieSourceType::kUnknown, &status);
4575 EXPECT_TRUE(cc);
4576 EXPECT_TRUE(status.IsInclude());
4577 EXPECT_FALSE(status.ShouldWarn());
4578 EXPECT_FALSE(cc->SecureAttribute());
4579 EXPECT_EQ(cc->SourceScheme(), CookieSourceScheme::kSecure);
4580 EXPECT_EQ(cc->SourcePort(), 443);
4581
4582 // But having "Secure" shouldn't change anything
4583 cc = CanonicalCookie::Create(secure_url, "a=b; SameSite=Lax; Secure",
4584 base::Time::Now(), std::nullopt, std::nullopt,
4585 /*block_truncated=*/true,
4586 CookieSourceType::kUnknown, &status);
4587 EXPECT_TRUE(cc);
4588 EXPECT_TRUE(status.IsInclude());
4589 EXPECT_FALSE(status.ShouldWarn());
4590 EXPECT_TRUE(cc->SecureAttribute());
4591 EXPECT_EQ(cc->SourceScheme(), CookieSourceScheme::kSecure);
4592 EXPECT_EQ(cc->SourcePort(), 443);
4593
4594 // An insecure url without "Secure" should get a non-secure source scheme and
4595 // a default port.
4596 cc = CanonicalCookie::Create(insecure_url, "a=b; SameSite=Lax",
4597 base::Time::Now(), std::nullopt, std::nullopt,
4598 /*block_truncated=*/true,
4599 CookieSourceType::kUnknown, &status);
4600 EXPECT_TRUE(cc);
4601 EXPECT_TRUE(status.IsInclude());
4602 EXPECT_FALSE(status.ShouldWarn());
4603 EXPECT_FALSE(cc->SecureAttribute());
4604 EXPECT_EQ(cc->SourceScheme(), CookieSourceScheme::kNonSecure);
4605 EXPECT_EQ(cc->SourcePort(), 80);
4606
4607 // An insecure url with "Secure" should get a secure source scheme and
4608 // modified port. It should also get a warning that a secure source scheme was
4609 // tentatively allowed.
4610 cc = CanonicalCookie::Create(insecure_url, "a=b; SameSite=Lax; Secure",
4611 base::Time::Now(), std::nullopt, std::nullopt,
4612 /*block_truncated=*/true,
4613 CookieSourceType::kUnknown, &status);
4614 EXPECT_TRUE(cc);
4615 EXPECT_TRUE(status.IsInclude());
4616 EXPECT_TRUE(status.HasExactlyWarningReasonsForTesting(
4617 {CookieInclusionStatus::WARN_TENTATIVELY_ALLOWING_SECURE_SOURCE_SCHEME}));
4618 EXPECT_TRUE(cc->SecureAttribute());
4619 EXPECT_EQ(cc->SourceScheme(), CookieSourceScheme::kSecure);
4620 EXPECT_EQ(cc->SourcePort(), 443);
4621
4622 // An insecure url with a non-default port without "Secure" should get a
4623 // non-secure source scheme and keep its port.
4624 cc = CanonicalCookie::Create(insecure_url_custom_port, "a=b; SameSite=Lax",
4625 base::Time::Now(), std::nullopt, std::nullopt,
4626 /*block_truncated=*/true,
4627 CookieSourceType::kUnknown, &status);
4628 EXPECT_TRUE(cc);
4629 EXPECT_TRUE(status.IsInclude());
4630 EXPECT_FALSE(status.ShouldWarn());
4631 EXPECT_FALSE(cc->SecureAttribute());
4632 EXPECT_EQ(cc->SourceScheme(), CookieSourceScheme::kNonSecure);
4633 EXPECT_EQ(cc->SourcePort(), 123);
4634
4635 // An insecure url with a non-default port with "Secure" should get a secure
4636 // source scheme and keep its port. It should also get a warning that a secure
4637 // source scheme was tentatively allowed.
4638 cc = CanonicalCookie::Create(
4639 insecure_url_custom_port, "a=b; SameSite=Lax; Secure", base::Time::Now(),
4640 std::nullopt, std::nullopt, /*block_truncated=*/true,
4641 CookieSourceType::kUnknown, &status);
4642 EXPECT_TRUE(cc);
4643 EXPECT_TRUE(status.IsInclude());
4644 EXPECT_TRUE(status.HasExactlyWarningReasonsForTesting(
4645 {CookieInclusionStatus::WARN_TENTATIVELY_ALLOWING_SECURE_SOURCE_SCHEME}));
4646 EXPECT_TRUE(cc->SecureAttribute());
4647 EXPECT_EQ(cc->SourceScheme(), CookieSourceScheme::kSecure);
4648 EXPECT_EQ(cc->SourcePort(), 123);
4649 }
4650
4651 // Make sure that the source scheme and port are set correctly for cookies that
4652 // are marked as "Secure".
TEST(CanonicalCookieTest,CreateSanitizedCookie_SourceSchemePort)4653 TEST(CanonicalCookieTest, CreateSanitizedCookie_SourceSchemePort) {
4654 GURL secure_url("https://example.com");
4655 GURL insecure_url("http://example.com");
4656 GURL insecure_url_custom_port("http://example.com:123");
4657
4658 CookieInclusionStatus status;
4659
4660 std::unique_ptr<CanonicalCookie> cc;
4661
4662 // A secure url doesn't need "Secure" to have a source scheme of secure
4663 cc = CanonicalCookie::CreateSanitizedCookie(
4664 secure_url, "a", "b", "example.com", "", base::Time(), base::Time(),
4665 base::Time(), /*secure=*/false, /*http_only=*/false,
4666 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
4667 /*partition_key=*/std::nullopt, &status);
4668 EXPECT_TRUE(cc);
4669 EXPECT_TRUE(status.IsInclude());
4670 EXPECT_FALSE(status.ShouldWarn());
4671 EXPECT_FALSE(cc->SecureAttribute());
4672 EXPECT_EQ(cc->SourceScheme(), CookieSourceScheme::kSecure);
4673 EXPECT_EQ(cc->SourcePort(), 443);
4674
4675 // But having "Secure" shouldn't change anything
4676 cc = CanonicalCookie::CreateSanitizedCookie(
4677 secure_url, "a", "b", "example.com", "", base::Time(), base::Time(),
4678 base::Time(), /*secure=*/true, /*http_only=*/false,
4679 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
4680 /*partition_key=*/std::nullopt, &status);
4681 EXPECT_TRUE(cc);
4682 EXPECT_TRUE(status.IsInclude());
4683 EXPECT_FALSE(status.ShouldWarn());
4684 EXPECT_TRUE(cc->SecureAttribute());
4685 EXPECT_EQ(cc->SourceScheme(), CookieSourceScheme::kSecure);
4686 EXPECT_EQ(cc->SourcePort(), 443);
4687
4688 // An insecure url without "Secure" should get a non-secure source scheme and
4689 // a default port.
4690 cc = CanonicalCookie::CreateSanitizedCookie(
4691 insecure_url, "a", "b", "example.com", "", base::Time(), base::Time(),
4692 base::Time(), /*secure=*/false, /*http_only=*/false,
4693 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
4694 /*partition_key=*/std::nullopt, &status);
4695 EXPECT_TRUE(cc);
4696 EXPECT_TRUE(status.IsInclude());
4697 EXPECT_FALSE(status.ShouldWarn());
4698 EXPECT_FALSE(cc->SecureAttribute());
4699 EXPECT_EQ(cc->SourceScheme(), CookieSourceScheme::kNonSecure);
4700 EXPECT_EQ(cc->SourcePort(), 80);
4701
4702 // An insecure url with "Secure" should get a secure source scheme and
4703 // modified port. It should also get a warning that a secure source scheme was
4704 // tentatively allowed.
4705 cc = CanonicalCookie::CreateSanitizedCookie(
4706 insecure_url, "a", "b", "example.com", "", base::Time(), base::Time(),
4707 base::Time(), /*secure=*/true, /*http_only=*/false,
4708 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
4709 /*partition_key=*/std::nullopt, &status);
4710 EXPECT_TRUE(cc);
4711 EXPECT_TRUE(status.IsInclude());
4712 EXPECT_TRUE(status.HasExactlyWarningReasonsForTesting(
4713 {CookieInclusionStatus::WARN_TENTATIVELY_ALLOWING_SECURE_SOURCE_SCHEME}));
4714 EXPECT_TRUE(cc->SecureAttribute());
4715 EXPECT_EQ(cc->SourceScheme(), CookieSourceScheme::kSecure);
4716 EXPECT_EQ(cc->SourcePort(), 443);
4717
4718 // An insecure url with a non-default port without "Secure" should get a
4719 // non-secure source scheme and keep its port.
4720 cc = CanonicalCookie::CreateSanitizedCookie(
4721 insecure_url_custom_port, "a", "b", "example.com", "", base::Time(),
4722 base::Time(), base::Time(), /*secure=*/false, /*http_only=*/false,
4723 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
4724 /*partition_key=*/std::nullopt, &status);
4725 EXPECT_TRUE(cc);
4726 EXPECT_TRUE(status.IsInclude());
4727 EXPECT_FALSE(status.ShouldWarn());
4728 EXPECT_FALSE(cc->SecureAttribute());
4729 EXPECT_EQ(cc->SourceScheme(), CookieSourceScheme::kNonSecure);
4730 EXPECT_EQ(cc->SourcePort(), 123);
4731
4732 // An insecure url with a non-default port with "Secure" should get a secure
4733 // source scheme and keep its port. It should also get a warning that a secure
4734 // source scheme was tentatively allowed.
4735 cc = CanonicalCookie::CreateSanitizedCookie(
4736 insecure_url_custom_port, "a", "b", "example.com", "", base::Time(),
4737 base::Time(), base::Time(), /*secure=*/true, /*http_only=*/false,
4738 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
4739 /*partition_key=*/std::nullopt, &status);
4740 EXPECT_TRUE(cc);
4741 EXPECT_TRUE(status.IsInclude());
4742 EXPECT_TRUE(status.HasExactlyWarningReasonsForTesting(
4743 {CookieInclusionStatus::WARN_TENTATIVELY_ALLOWING_SECURE_SOURCE_SCHEME}));
4744 EXPECT_TRUE(cc->SecureAttribute());
4745 EXPECT_EQ(cc->SourceScheme(), CookieSourceScheme::kSecure);
4746 EXPECT_EQ(cc->SourcePort(), 123);
4747 }
4748
TEST(CanonicalCookieTest,FromStorage)4749 TEST(CanonicalCookieTest, FromStorage) {
4750 base::Time two_hours_ago = base::Time::Now() - base::Hours(2);
4751 base::Time one_hour_ago = base::Time::Now() - base::Hours(1);
4752 base::Time one_hour_from_now = base::Time::Now() + base::Hours(1);
4753
4754 std::unique_ptr<CanonicalCookie> cc = CanonicalCookie::FromStorage(
4755 "A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now,
4756 one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/,
4757 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4758 std::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 87,
4759 CookieSourceType::kUnknown);
4760 EXPECT_TRUE(cc);
4761 EXPECT_EQ("A", cc->Name());
4762 EXPECT_EQ("B", cc->Value());
4763 EXPECT_EQ("www.foo.com", cc->Domain());
4764 EXPECT_EQ("/bar", cc->Path());
4765 EXPECT_EQ(two_hours_ago, cc->CreationDate());
4766 EXPECT_EQ(one_hour_ago, cc->LastAccessDate());
4767 EXPECT_EQ(one_hour_from_now, cc->ExpiryDate());
4768 EXPECT_EQ(one_hour_ago, cc->LastUpdateDate());
4769 EXPECT_FALSE(cc->SecureAttribute());
4770 EXPECT_FALSE(cc->IsHttpOnly());
4771 EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cc->SameSite());
4772 EXPECT_EQ(COOKIE_PRIORITY_MEDIUM, cc->Priority());
4773 EXPECT_EQ(CookieSourceScheme::kSecure, cc->SourceScheme());
4774 EXPECT_FALSE(cc->IsDomainCookie());
4775 EXPECT_EQ(cc->SourcePort(), 87);
4776
4777 // Should return nullptr when the cookie is not canonical.
4778 // In this case the cookie is not canonical because its name attribute
4779 // contains a newline character.
4780 EXPECT_FALSE(CanonicalCookie::FromStorage(
4781 "A\n", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now,
4782 one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/,
4783 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4784 std::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 80,
4785 CookieSourceType::kUnknown));
4786
4787 // If the port information gets corrupted out of the valid range
4788 // FromStorage() should result in a PORT_INVALID.
4789 std::unique_ptr<CanonicalCookie> cc2 = CanonicalCookie::FromStorage(
4790 "A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now,
4791 one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/,
4792 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4793 std::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 80000,
4794 CookieSourceType::kUnknown);
4795
4796 EXPECT_EQ(cc2->SourcePort(), url::PORT_INVALID);
4797
4798 // Test port edge cases: unspecified.
4799 std::unique_ptr<CanonicalCookie> cc3 = CanonicalCookie::FromStorage(
4800 "A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now,
4801 one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/,
4802 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4803 std::nullopt /*partition_key*/, CookieSourceScheme::kSecure,
4804 url::PORT_UNSPECIFIED, CookieSourceType::kUnknown);
4805 EXPECT_EQ(cc3->SourcePort(), url::PORT_UNSPECIFIED);
4806
4807 // Test port edge cases: invalid.
4808 std::unique_ptr<CanonicalCookie> cc4 = CanonicalCookie::FromStorage(
4809 "A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now,
4810 one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/,
4811 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
4812 std::nullopt /*partition_key*/, CookieSourceScheme::kSecure,
4813 url::PORT_INVALID, CookieSourceType::kUnknown);
4814 EXPECT_EQ(cc4->SourcePort(), url::PORT_INVALID);
4815 }
4816
TEST(CanonicalCookieTest,IsSetPermittedInContext)4817 TEST(CanonicalCookieTest, IsSetPermittedInContext) {
4818 GURL url("https://www.example.com/test");
4819 GURL insecure_url("http://www.example.com/test");
4820 base::Time current_time = base::Time::Now();
4821
4822 auto cookie_scriptable = CanonicalCookie::CreateUnsafeCookieForTesting(
4823 "A", "2", "www.example.com", "/test", current_time, base::Time(),
4824 base::Time(), base::Time(), true /*secure*/, false /*httponly*/,
4825 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT);
4826 auto cookie_httponly = CanonicalCookie::CreateUnsafeCookieForTesting(
4827 "A", "2", "www.example.com", "/test", current_time, base::Time(),
4828 base::Time(), base::Time(), true /*secure*/, true /*httponly*/,
4829 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT);
4830
4831 CookieOptions context_script;
4832 CookieOptions context_network;
4833 context_network.set_include_httponly();
4834
4835 EXPECT_THAT(
4836 cookie_scriptable->IsSetPermittedInContext(
4837 GURL("file://foo/bar.txt"), context_network,
4838 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
4839 false /* delegate_treats_url_as_trustworthy */
4840 ),
4841 kCookieableSchemes),
4842 MatchesCookieAccessResult(
4843 CookieInclusionStatus::MakeFromReasonsForTesting({
4844 CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME,
4845 CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
4846 }),
4847 _, _, false));
4848
4849 EXPECT_THAT(
4850 cookie_scriptable->IsSetPermittedInContext(
4851 insecure_url, context_network,
4852 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
4853 false /* delegate_treats_url_as_trustworthy */
4854 ),
4855 kCookieableSchemes),
4856 MatchesCookieAccessResult(
4857 CookieInclusionStatus::MakeFromReasonsForTesting(
4858 {CookieInclusionStatus::EXCLUDE_SECURE_ONLY}),
4859 _, _, false));
4860 EXPECT_THAT(
4861 cookie_scriptable->IsSetPermittedInContext(
4862 url, context_network,
4863 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
4864 false /* delegate_treats_url_as_trustworthy */
4865 ),
4866 kCookieableSchemes),
4867 MatchesCookieAccessResult(IsInclude(), _, _, true));
4868 EXPECT_THAT(
4869 cookie_scriptable->IsSetPermittedInContext(
4870 url, context_script,
4871 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
4872 false /* delegate_treats_url_as_trustworthy */
4873 ),
4874 kCookieableSchemes),
4875 MatchesCookieAccessResult(IsInclude(), _, _, true));
4876
4877 EXPECT_THAT(
4878 cookie_httponly->IsSetPermittedInContext(
4879 url, context_network,
4880 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
4881 false /* delegate_treats_url_as_trustworthy */
4882 ),
4883 kCookieableSchemes),
4884 MatchesCookieAccessResult(IsInclude(), _, _, true));
4885 EXPECT_THAT(
4886 cookie_httponly->IsSetPermittedInContext(
4887 url, context_script,
4888 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
4889 false /* delegate_treats_url_as_trustworthy */
4890 ),
4891 kCookieableSchemes),
4892 MatchesCookieAccessResult(
4893 CookieInclusionStatus::MakeFromReasonsForTesting(
4894 {CookieInclusionStatus::EXCLUDE_HTTP_ONLY}),
4895 _, _, true));
4896
4897 CookieOptions context_cross_site;
4898 CookieOptions context_same_site_lax;
4899 context_same_site_lax.set_same_site_cookie_context(
4900 CookieOptions::SameSiteCookieContext(
4901 CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX));
4902 CookieOptions context_same_site_strict;
4903 context_same_site_strict.set_same_site_cookie_context(
4904 CookieOptions::SameSiteCookieContext(
4905 CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_STRICT));
4906
4907 CookieOptions context_same_site_strict_to_lax;
4908 context_same_site_strict_to_lax.set_same_site_cookie_context(
4909 CookieOptions::SameSiteCookieContext(
4910 CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
4911 CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX));
4912
4913 CookieOptions context_same_site_strict_to_cross;
4914 context_same_site_strict_to_cross.set_same_site_cookie_context(
4915 CookieOptions::SameSiteCookieContext(
4916 CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
4917 CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE));
4918
4919 CookieOptions context_same_site_lax_to_cross;
4920 context_same_site_lax_to_cross.set_same_site_cookie_context(
4921 CookieOptions::SameSiteCookieContext(
4922 CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX,
4923 CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE));
4924
4925 {
4926 auto cookie_same_site_unrestricted =
4927 CanonicalCookie::CreateUnsafeCookieForTesting(
4928 "A", "2", "www.example.com", "/test", current_time, base::Time(),
4929 base::Time(), base::Time(), true /*secure*/, false /*httponly*/,
4930 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT);
4931
4932 EXPECT_THAT(
4933 cookie_same_site_unrestricted->IsSetPermittedInContext(
4934 url, context_cross_site,
4935 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
4936 false /* delegate_treats_url_as_trustworthy */
4937 ),
4938 kCookieableSchemes),
4939 MatchesCookieAccessResult(IsInclude(), _, _, true));
4940 EXPECT_THAT(
4941 cookie_same_site_unrestricted->IsSetPermittedInContext(
4942 url, context_same_site_lax,
4943 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
4944 false /* delegate_treats_url_as_trustworthy */
4945 ),
4946 kCookieableSchemes),
4947 MatchesCookieAccessResult(IsInclude(), _, _, true));
4948 EXPECT_THAT(
4949 cookie_same_site_unrestricted->IsSetPermittedInContext(
4950 url, context_same_site_strict,
4951 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
4952 false /* delegate_treats_url_as_trustworthy */
4953 ),
4954 kCookieableSchemes),
4955 MatchesCookieAccessResult(IsInclude(), _, _, true));
4956
4957 {
4958 // Schemeful Same-Site disabled.
4959 base::test::ScopedFeatureList feature_list;
4960 feature_list.InitAndDisableFeature(features::kSchemefulSameSite);
4961
4962 EXPECT_THAT(
4963 cookie_same_site_unrestricted->IsSetPermittedInContext(
4964 url, context_same_site_strict_to_lax,
4965 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
4966 false /* delegate_treats_url_as_trustworthy */
4967 ),
4968 kCookieableSchemes),
4969 MatchesCookieAccessResult(
4970 AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())), _, _,
4971 true));
4972 EXPECT_THAT(
4973 cookie_same_site_unrestricted->IsSetPermittedInContext(
4974 url, context_same_site_strict_to_cross,
4975 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
4976 false /* delegate_treats_url_as_trustworthy */
4977 ),
4978 kCookieableSchemes),
4979 MatchesCookieAccessResult(
4980 AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())), _, _,
4981 true));
4982 EXPECT_THAT(
4983 cookie_same_site_unrestricted->IsSetPermittedInContext(
4984 url, context_same_site_lax_to_cross,
4985 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
4986 false /* delegate_treats_url_as_trustworthy */
4987 ),
4988 kCookieableSchemes),
4989 MatchesCookieAccessResult(
4990 AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())), _, _,
4991 true));
4992 }
4993 {
4994 // Schemeful Same-Site enabled.
4995 base::test::ScopedFeatureList feature_list;
4996 feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
4997
4998 EXPECT_THAT(
4999 cookie_same_site_unrestricted->IsSetPermittedInContext(
5000 url, context_same_site_strict_to_lax,
5001 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5002 false /* delegate_treats_url_as_trustworthy */
5003 ),
5004 kCookieableSchemes),
5005 MatchesCookieAccessResult(
5006 AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())), _, _,
5007 true));
5008 EXPECT_THAT(
5009 cookie_same_site_unrestricted->IsSetPermittedInContext(
5010 url, context_same_site_strict_to_cross,
5011 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5012 false /* delegate_treats_url_as_trustworthy */
5013 ),
5014 kCookieableSchemes),
5015 MatchesCookieAccessResult(
5016 AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())), _, _,
5017 true));
5018 EXPECT_THAT(
5019 cookie_same_site_unrestricted->IsSetPermittedInContext(
5020 url, context_same_site_lax_to_cross,
5021 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5022 false /* delegate_treats_url_as_trustworthy */
5023 ),
5024 kCookieableSchemes),
5025 MatchesCookieAccessResult(
5026 AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())), _, _,
5027 true));
5028 }
5029 }
5030
5031 {
5032 auto cookie_same_site_lax = CanonicalCookie::CreateUnsafeCookieForTesting(
5033 "A", "2", "www.example.com", "/test", current_time, base::Time(),
5034 base::Time(), base::Time(), true /*secure*/, false /*httponly*/,
5035 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT);
5036
5037 EXPECT_THAT(
5038 cookie_same_site_lax->IsSetPermittedInContext(
5039 url, context_cross_site,
5040 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5041 false /* delegate_treats_url_as_trustworthy */
5042 ),
5043 kCookieableSchemes),
5044 MatchesCookieAccessResult(
5045 CookieInclusionStatus::MakeFromReasonsForTesting(
5046 {CookieInclusionStatus::EXCLUDE_SAMESITE_LAX}),
5047 _, _, true));
5048 EXPECT_THAT(
5049 cookie_same_site_lax->IsSetPermittedInContext(
5050 url, context_same_site_lax,
5051 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5052 false /* delegate_treats_url_as_trustworthy */
5053 ),
5054 kCookieableSchemes),
5055 MatchesCookieAccessResult(IsInclude(), _, _, true));
5056 EXPECT_THAT(
5057 cookie_same_site_lax->IsSetPermittedInContext(
5058 url, context_same_site_strict,
5059 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5060 false /* delegate_treats_url_as_trustworthy */
5061 ),
5062 kCookieableSchemes),
5063 MatchesCookieAccessResult(IsInclude(), _, _, true));
5064
5065 {
5066 // Schemeful Same-Site disabled.
5067 base::test::ScopedFeatureList feature_list;
5068 feature_list.InitAndDisableFeature(features::kSchemefulSameSite);
5069
5070 EXPECT_THAT(
5071 cookie_same_site_lax->IsSetPermittedInContext(
5072 url, context_same_site_strict_to_lax,
5073 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5074 false /* delegate_treats_url_as_trustworthy */
5075 ),
5076 kCookieableSchemes),
5077 MatchesCookieAccessResult(
5078 AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())), _, _,
5079 true));
5080 EXPECT_THAT(
5081 cookie_same_site_lax->IsSetPermittedInContext(
5082 url, context_same_site_strict_to_cross,
5083 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5084 false /* delegate_treats_url_as_trustworthy */
5085 ),
5086 kCookieableSchemes),
5087 MatchesCookieAccessResult(
5088 AllOf(IsInclude(),
5089 HasWarningReason(
5090 CookieInclusionStatus::
5091 WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE)),
5092 _, _, true));
5093 EXPECT_THAT(
5094 cookie_same_site_lax->IsSetPermittedInContext(
5095 url, context_same_site_lax_to_cross,
5096 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5097 false /* delegate_treats_url_as_trustworthy */
5098 ),
5099 kCookieableSchemes),
5100 MatchesCookieAccessResult(
5101 AllOf(
5102 IsInclude(),
5103 HasWarningReason(CookieInclusionStatus::
5104 WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE)),
5105 _, _, true));
5106 }
5107 {
5108 // Schemeful Same-Site enabled.
5109 base::test::ScopedFeatureList feature_list;
5110 feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
5111
5112 EXPECT_THAT(
5113 cookie_same_site_lax->IsSetPermittedInContext(
5114 url, context_same_site_strict_to_lax,
5115 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5116 false /* delegate_treats_url_as_trustworthy */
5117 ),
5118 kCookieableSchemes),
5119 MatchesCookieAccessResult(
5120 AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())), _, _,
5121 true));
5122 EXPECT_THAT(
5123 cookie_same_site_lax->IsSetPermittedInContext(
5124 url, context_same_site_strict_to_cross,
5125 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5126 false /* delegate_treats_url_as_trustworthy */
5127 ),
5128 kCookieableSchemes),
5129 MatchesCookieAccessResult(
5130 AllOf(Not(IsInclude()),
5131 HasWarningReason(
5132 CookieInclusionStatus::
5133 WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE),
5134 HasExclusionReason(
5135 CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)),
5136 _, _, true));
5137 EXPECT_THAT(
5138 cookie_same_site_lax->IsSetPermittedInContext(
5139 url, context_same_site_lax_to_cross,
5140 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5141 false /* delegate_treats_url_as_trustworthy */
5142 ),
5143 kCookieableSchemes),
5144 MatchesCookieAccessResult(
5145 AllOf(Not(IsInclude()),
5146 HasWarningReason(CookieInclusionStatus::
5147 WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE),
5148 HasExclusionReason(
5149 CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)),
5150 _, _, true));
5151 }
5152 }
5153
5154 {
5155 auto cookie_same_site_strict =
5156 CanonicalCookie::CreateUnsafeCookieForTesting(
5157 "A", "2", "www.example.com", "/test", current_time, base::Time(),
5158 base::Time(), base::Time(), true /*secure*/, false /*httponly*/,
5159 CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT);
5160
5161 // TODO(morlovich): Do compatibility testing on whether set of strict in lax
5162 // context really should be accepted.
5163 EXPECT_THAT(
5164 cookie_same_site_strict->IsSetPermittedInContext(
5165 url, context_cross_site,
5166 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5167 false /* delegate_treats_url_as_trustworthy */
5168 ),
5169 kCookieableSchemes),
5170 MatchesCookieAccessResult(
5171 CookieInclusionStatus::MakeFromReasonsForTesting(
5172 {CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT}),
5173 _, _, true));
5174 EXPECT_THAT(
5175 cookie_same_site_strict->IsSetPermittedInContext(
5176 url, context_same_site_lax,
5177 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5178 false /* delegate_treats_url_as_trustworthy */
5179 ),
5180 kCookieableSchemes),
5181 MatchesCookieAccessResult(IsInclude(), _, _, true));
5182 EXPECT_THAT(
5183 cookie_same_site_strict->IsSetPermittedInContext(
5184 url, context_same_site_strict,
5185 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5186 false /* delegate_treats_url_as_trustworthy */
5187 ),
5188 kCookieableSchemes),
5189 MatchesCookieAccessResult(IsInclude(), _, _, true));
5190
5191 {
5192 // Schemeful Same-Site disabled.
5193 base::test::ScopedFeatureList feature_list;
5194 feature_list.InitAndDisableFeature(features::kSchemefulSameSite);
5195
5196 EXPECT_THAT(
5197 cookie_same_site_strict->IsSetPermittedInContext(
5198 url, context_same_site_strict_to_lax,
5199 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5200 false /* delegate_treats_url_as_trustworthy */
5201 ),
5202 kCookieableSchemes),
5203 MatchesCookieAccessResult(
5204 AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())), _, _,
5205 true));
5206 EXPECT_THAT(
5207 cookie_same_site_strict->IsSetPermittedInContext(
5208 url, context_same_site_strict_to_cross,
5209 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5210 false /* delegate_treats_url_as_trustworthy */
5211 ),
5212 kCookieableSchemes),
5213 MatchesCookieAccessResult(
5214 AllOf(IsInclude(),
5215 HasWarningReason(
5216 CookieInclusionStatus::
5217 WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE)),
5218 _, _, true));
5219 EXPECT_THAT(
5220 cookie_same_site_strict->IsSetPermittedInContext(
5221 url, context_same_site_lax_to_cross,
5222 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5223 false /* delegate_treats_url_as_trustworthy */
5224 ),
5225 kCookieableSchemes),
5226 MatchesCookieAccessResult(
5227 AllOf(IsInclude(),
5228 HasWarningReason(
5229 CookieInclusionStatus::
5230 WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE)),
5231 _, _, true));
5232 }
5233 {
5234 // Schemeful Same-Site enabled.
5235 base::test::ScopedFeatureList feature_list;
5236 feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
5237
5238 EXPECT_THAT(
5239 cookie_same_site_strict->IsSetPermittedInContext(
5240 url, context_same_site_strict_to_lax,
5241 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5242 false /* delegate_treats_url_as_trustworthy */
5243 ),
5244 kCookieableSchemes),
5245 MatchesCookieAccessResult(
5246 AllOf(IsInclude(), Not(HasSchemefulDowngradeWarning())), _, _,
5247 true));
5248 EXPECT_THAT(
5249 cookie_same_site_strict->IsSetPermittedInContext(
5250 url, context_same_site_strict_to_cross,
5251 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5252 false /* delegate_treats_url_as_trustworthy */
5253 ),
5254 kCookieableSchemes),
5255 MatchesCookieAccessResult(
5256 AllOf(Not(IsInclude()),
5257 HasWarningReason(
5258 CookieInclusionStatus::
5259 WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE),
5260 HasExclusionReason(
5261 CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)),
5262 _, _, true));
5263 EXPECT_THAT(
5264 cookie_same_site_strict->IsSetPermittedInContext(
5265 url, context_same_site_lax_to_cross,
5266 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5267 false /* delegate_treats_url_as_trustworthy */
5268 ),
5269 kCookieableSchemes),
5270 MatchesCookieAccessResult(
5271 AllOf(Not(IsInclude()),
5272 HasWarningReason(
5273 CookieInclusionStatus::
5274 WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE),
5275 HasExclusionReason(
5276 CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)),
5277 _, _, true));
5278 }
5279
5280 // Even with Schemeful Same-Site enabled, cookies semantics could change the
5281 // inclusion.
5282 {
5283 base::test::ScopedFeatureList feature_list;
5284 feature_list.InitAndEnableFeature(features::kSchemefulSameSite);
5285
5286 EXPECT_THAT(
5287 cookie_same_site_strict->IsSetPermittedInContext(
5288 url, context_same_site_strict_to_cross,
5289 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5290 false /* delegate_treats_url_as_trustworthy */
5291 ),
5292 kCookieableSchemes),
5293 MatchesCookieAccessResult(Not(IsInclude()), _, _, true));
5294 EXPECT_THAT(
5295 cookie_same_site_strict->IsSetPermittedInContext(
5296 url, context_same_site_strict_to_cross,
5297 CookieAccessParams(CookieAccessSemantics::NONLEGACY,
5298 false /* delegate_treats_url_as_trustworthy */
5299 ),
5300 kCookieableSchemes),
5301 MatchesCookieAccessResult(Not(IsInclude()), _, _, true));
5302 // LEGACY semantics should allow cookies which Schemeful Same-Site would
5303 // normally block.
5304 EXPECT_THAT(
5305 cookie_same_site_strict->IsSetPermittedInContext(
5306 url, context_same_site_strict_to_cross,
5307 CookieAccessParams(CookieAccessSemantics::LEGACY,
5308 false /* delegate_treats_url_as_trustworthy */
5309 ),
5310 kCookieableSchemes),
5311 MatchesCookieAccessResult(IsInclude(), _, _, true));
5312 }
5313 }
5314
5315 // Behavior of UNSPECIFIED depends on CookieAccessSemantics.
5316 auto cookie_same_site_unspecified =
5317 CanonicalCookie::CreateUnsafeCookieForTesting(
5318 "A", "2", "www.example.com", "/test", current_time, base::Time(),
5319 base::Time(), base::Time(), true /*secure*/, false /*httponly*/,
5320 CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_DEFAULT);
5321
5322 EXPECT_THAT(
5323 cookie_same_site_unspecified->IsSetPermittedInContext(
5324 url, context_cross_site,
5325 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5326 false /* delegate_treats_url_as_trustworthy */
5327 ),
5328 kCookieableSchemes),
5329 MatchesCookieAccessResult(
5330 HasExactlyExclusionReasonsForTesting(
5331 std::vector<CookieInclusionStatus::ExclusionReason>(
5332 {CookieInclusionStatus::
5333 EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})),
5334 _, _, true));
5335 EXPECT_THAT(
5336 cookie_same_site_unspecified->IsSetPermittedInContext(
5337 url, context_same_site_lax,
5338 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5339 false /* delegate_treats_url_as_trustworthy */
5340 ),
5341 kCookieableSchemes),
5342 MatchesCookieAccessResult(IsInclude(), _, _, true));
5343 EXPECT_THAT(
5344 cookie_same_site_unspecified->IsSetPermittedInContext(
5345 url, context_same_site_strict,
5346 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5347 false /* delegate_treats_url_as_trustworthy */
5348 ),
5349 kCookieableSchemes),
5350 MatchesCookieAccessResult(IsInclude(), _, _, true));
5351 EXPECT_THAT(
5352 cookie_same_site_unspecified->IsSetPermittedInContext(
5353 url, context_cross_site,
5354 CookieAccessParams(CookieAccessSemantics::LEGACY,
5355 false /* delegate_treats_url_as_trustworthy */
5356 ),
5357 kCookieableSchemes),
5358 MatchesCookieAccessResult(IsInclude(), _, _, true));
5359 EXPECT_THAT(
5360 cookie_same_site_unspecified->IsSetPermittedInContext(
5361 url, context_same_site_lax,
5362 CookieAccessParams(CookieAccessSemantics::LEGACY,
5363 false /* delegate_treats_url_as_trustworthy */
5364 ),
5365 kCookieableSchemes),
5366 MatchesCookieAccessResult(IsInclude(), _, _, true));
5367 EXPECT_THAT(
5368 cookie_same_site_unspecified->IsSetPermittedInContext(
5369 url, context_same_site_strict,
5370 CookieAccessParams(CookieAccessSemantics::LEGACY,
5371 false /* delegate_treats_url_as_trustworthy */
5372 ),
5373 kCookieableSchemes),
5374 MatchesCookieAccessResult(IsInclude(), _, _, true));
5375 EXPECT_THAT(
5376 cookie_same_site_unspecified->IsSetPermittedInContext(
5377 url, context_cross_site,
5378 CookieAccessParams(CookieAccessSemantics::NONLEGACY,
5379 false /* delegate_treats_url_as_trustworthy */
5380 ),
5381 kCookieableSchemes),
5382 MatchesCookieAccessResult(
5383 HasExactlyExclusionReasonsForTesting(
5384 std::vector<CookieInclusionStatus::ExclusionReason>(
5385 {CookieInclusionStatus::
5386 EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})),
5387 _, _, true));
5388 EXPECT_THAT(
5389 cookie_same_site_unspecified->IsSetPermittedInContext(
5390 url, context_same_site_lax,
5391 CookieAccessParams(CookieAccessSemantics::NONLEGACY,
5392 false /* delegate_treats_url_as_trustworthy */
5393 ),
5394 kCookieableSchemes),
5395 MatchesCookieAccessResult(IsInclude(), _, _, true));
5396 EXPECT_THAT(
5397 cookie_same_site_unspecified->IsSetPermittedInContext(
5398 url, context_same_site_strict,
5399 CookieAccessParams(CookieAccessSemantics::NONLEGACY,
5400 false /* delegate_treats_url_as_trustworthy */
5401 ),
5402 kCookieableSchemes),
5403 MatchesCookieAccessResult(IsInclude(), _, _, true));
5404
5405 // Test IsSetPermittedInContext successfully chains warnings by passing
5406 // in a CookieAccessResult and expecting the result to have a
5407 // WARN_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE
5408 CookieInclusionStatus status;
5409 std::string long_path(ParsedCookie::kMaxCookieAttributeValueSize, 'a');
5410
5411 std::unique_ptr<CanonicalCookie> cookie_with_long_path =
5412 CanonicalCookie::Create(url, "A=B; Path=/" + long_path, current_time,
5413 std::nullopt, std::nullopt,
5414 /*block_truncated=*/true,
5415 CookieSourceType::kUnknown, &status);
5416 CookieAccessResult cookie_access_result(status);
5417 CookieOptions cookie_with_long_path_options;
5418 EXPECT_THAT(
5419 cookie_with_long_path->IsSetPermittedInContext(
5420 url, cookie_with_long_path_options,
5421 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5422 false /* delegate_treats_url_as_trustworthy */
5423 ),
5424 kCookieableSchemes, cookie_access_result),
5425 MatchesCookieAccessResult(
5426 HasWarningReason(
5427 CookieInclusionStatus::WARN_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE),
5428 _, _, _));
5429 }
5430
TEST(CanonicalCookieTest,IsSetPermittedEffectiveSameSite)5431 TEST(CanonicalCookieTest, IsSetPermittedEffectiveSameSite) {
5432 GURL url("http://www.example.com/test");
5433 base::Time current_time = base::Time::Now();
5434 CookieOptions options;
5435
5436 // Test IsSetPermitted CookieEffectiveSameSite for
5437 // CanonicalCookie with CookieSameSite::NO_RESTRICTION.
5438 auto cookie_no_restriction = CanonicalCookie::CreateUnsafeCookieForTesting(
5439 "A", "2", "www.example.com", "/test", current_time, base::Time(),
5440 base::Time(), base::Time(), true /*secure*/, false /*httponly*/,
5441 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT);
5442
5443 EXPECT_THAT(
5444 cookie_no_restriction->IsSetPermittedInContext(
5445 url, options,
5446 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5447 false /* delegate_treats_url_as_trustworthy */
5448 ),
5449 kCookieableSchemes),
5450 MatchesCookieAccessResult(_, CookieEffectiveSameSite::NO_RESTRICTION, _,
5451 false));
5452
5453 // Test IsSetPermitted CookieEffectiveSameSite for
5454 // CanonicalCookie with CookieSameSite::LAX_MODE.
5455 auto cookie_lax = CanonicalCookie::CreateUnsafeCookieForTesting(
5456 "A", "2", "www.example.com", "/test", current_time, base::Time(),
5457 base::Time(), base::Time(), true /*secure*/, false /*httponly*/,
5458 CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT);
5459
5460 EXPECT_THAT(
5461 cookie_lax->IsSetPermittedInContext(
5462 url, options,
5463 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5464 false /* delegate_treats_url_as_trustworthy */
5465 ),
5466 kCookieableSchemes),
5467 MatchesCookieAccessResult(_, CookieEffectiveSameSite::LAX_MODE, _,
5468 false));
5469
5470 // Test IsSetPermitted CookieEffectiveSameSite for
5471 // CanonicalCookie with CookieSameSite::STRICT_MODE.
5472 auto cookie_strict = CanonicalCookie::CreateUnsafeCookieForTesting(
5473 "A", "2", "www.example.com", "/test", current_time, base::Time(),
5474 base::Time(), base::Time(), true /*secure*/, false /*httponly*/,
5475 CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT);
5476
5477 EXPECT_THAT(
5478 cookie_strict->IsSetPermittedInContext(
5479 url, options,
5480 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5481 false /* delegate_treats_url_as_trustworthy */
5482 ),
5483 kCookieableSchemes),
5484 MatchesCookieAccessResult(_, CookieEffectiveSameSite::STRICT_MODE, _,
5485 false));
5486
5487 // Test IsSetPermitted CookieEffectiveSameSite for
5488 // CanonicalCookie with CookieSameSite::UNSPECIFIED.
5489 base::Time creation_time = base::Time::Now() - (kLaxAllowUnsafeMaxAge * 4);
5490 auto cookie_old_unspecified = CanonicalCookie::CreateUnsafeCookieForTesting(
5491 "A", "2", "www.example.com", "/test", creation_time, base::Time(),
5492 base::Time(), base::Time(), true /*secure*/, false /*httponly*/,
5493 CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_DEFAULT);
5494 auto cookie_unspecified = CanonicalCookie::CreateUnsafeCookieForTesting(
5495 "A", "2", "www.example.com", "/test", current_time, base::Time(),
5496 base::Time(), base::Time(), true /*secure*/, false /*httponly*/,
5497 CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_DEFAULT);
5498
5499 EXPECT_THAT(
5500 cookie_old_unspecified->IsSetPermittedInContext(
5501 url, options,
5502 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5503 false /* delegate_treats_url_as_trustworthy */
5504 ),
5505 kCookieableSchemes),
5506 MatchesCookieAccessResult(_, CookieEffectiveSameSite::LAX_MODE, _,
5507 false));
5508
5509 EXPECT_THAT(
5510 cookie_unspecified->IsSetPermittedInContext(
5511 url, options,
5512 CookieAccessParams(CookieAccessSemantics::UNKNOWN,
5513 false /* delegate_treats_url_as_trustworthy */
5514 ),
5515 kCookieableSchemes),
5516 MatchesCookieAccessResult(
5517 _, CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE, _, false));
5518
5519 EXPECT_THAT(
5520 cookie_unspecified->IsSetPermittedInContext(
5521 url, options,
5522 CookieAccessParams(CookieAccessSemantics::NONLEGACY,
5523 false /* delegate_treats_url_as_trustworthy */
5524 ),
5525 kCookieableSchemes),
5526 MatchesCookieAccessResult(
5527 _, CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE, _, false));
5528
5529 EXPECT_THAT(
5530 cookie_unspecified->IsSetPermittedInContext(
5531 url, options,
5532 CookieAccessParams(CookieAccessSemantics::LEGACY,
5533 false /* delegate_treats_url_as_trustworthy */
5534 ),
5535 kCookieableSchemes),
5536 MatchesCookieAccessResult(_, CookieEffectiveSameSite::NO_RESTRICTION, _,
5537 false));
5538 }
5539
TEST(CanonicalCookieTest,IsSetPermitted_AllowedToAccessSecureCookies)5540 TEST(CanonicalCookieTest, IsSetPermitted_AllowedToAccessSecureCookies) {
5541 GURL url("https://www.example.com/test");
5542 GURL insecure_url("http://www.example.com/test");
5543 GURL localhost_url("http://localhost/test");
5544 base::Time current_time = base::Time::Now();
5545 CookieOptions options;
5546
5547 for (bool secure : {false, true}) {
5548 for (CookieSameSite same_site : {
5549 CookieSameSite::UNSPECIFIED,
5550 CookieSameSite::NO_RESTRICTION,
5551 CookieSameSite::LAX_MODE,
5552 }) {
5553 auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
5554 "A", "2", "www.example.com", "/test", current_time, base::Time(),
5555 base::Time(), base::Time(), secure, false /*httponly*/, same_site,
5556 COOKIE_PRIORITY_DEFAULT);
5557
5558 for (bool delegate_treats_url_as_trustworthy : {false, true}) {
5559 for (CookieAccessSemantics access_semantics : {
5560 CookieAccessSemantics::UNKNOWN,
5561 CookieAccessSemantics::LEGACY,
5562 CookieAccessSemantics::NONLEGACY,
5563 }) {
5564 EXPECT_THAT(
5565 cookie->IsSetPermittedInContext(
5566 url, options,
5567 CookieAccessParams(access_semantics,
5568 delegate_treats_url_as_trustworthy),
5569 kCookieableSchemes),
5570 MatchesCookieAccessResult(_, _, _, true));
5571 EXPECT_THAT(
5572 cookie->IsSetPermittedInContext(
5573 insecure_url, options,
5574 CookieAccessParams(access_semantics,
5575 delegate_treats_url_as_trustworthy),
5576 kCookieableSchemes),
5577 MatchesCookieAccessResult(_, _, _,
5578 delegate_treats_url_as_trustworthy));
5579 EXPECT_THAT(
5580 cookie->IsSetPermittedInContext(
5581 localhost_url, options,
5582 CookieAccessParams(access_semantics,
5583 delegate_treats_url_as_trustworthy),
5584 kCookieableSchemes),
5585 MatchesCookieAccessResult(_, _, _, true));
5586 }
5587 }
5588 }
5589 }
5590 }
5591
TEST(CanonicalCookieTest,IsSetPermitted_SameSiteNone_Metrics)5592 TEST(CanonicalCookieTest, IsSetPermitted_SameSiteNone_Metrics) {
5593 constexpr bool delegate_treats_url_as_trustworthy = false;
5594 const base::Time now = base::Time::Now();
5595 const auto make_cookie = [now](CookieSameSite same_site) {
5596 return CanonicalCookie::CreateUnsafeCookieForTesting(
5597 "A", "1", "www.example.com", "/test", now, base::Time(), base::Time(),
5598 base::Time(), true /* secure */, false /*httponly*/, same_site,
5599 COOKIE_PRIORITY_DEFAULT);
5600 };
5601 GURL url("https://www.example.com/test");
5602
5603 const std::unique_ptr<CanonicalCookie> same_site_none_cookie =
5604 make_cookie(CookieSameSite::NO_RESTRICTION);
5605 const std::unique_ptr<CanonicalCookie> same_site_lax_cookie =
5606 make_cookie(CookieSameSite::LAX_MODE);
5607 const std::unique_ptr<CanonicalCookie> same_site_strict_cookie =
5608 make_cookie(CookieSameSite::STRICT_MODE);
5609 CookieOptions options;
5610
5611 options.set_same_site_cookie_context(CookieOptions::SameSiteCookieContext(
5612 CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE));
5613 EXPECT_THAT(same_site_none_cookie->IsSetPermittedInContext(
5614 url, options,
5615 CookieAccessParams(CookieAccessSemantics::LEGACY,
5616 delegate_treats_url_as_trustworthy),
5617 kCookieableSchemes),
5618 MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true));
5619 EXPECT_THAT(same_site_lax_cookie->IsSetPermittedInContext(
5620 url, options,
5621 CookieAccessParams(CookieAccessSemantics::LEGACY,
5622 delegate_treats_url_as_trustworthy),
5623 kCookieableSchemes),
5624 MatchesCookieAccessResult(Not(net::IsInclude()), _, _, true));
5625 EXPECT_THAT(same_site_strict_cookie->IsSetPermittedInContext(
5626 url, options,
5627 CookieAccessParams(CookieAccessSemantics::LEGACY,
5628 delegate_treats_url_as_trustworthy),
5629 kCookieableSchemes),
5630 MatchesCookieAccessResult(Not(net::IsInclude()), _, _, true));
5631
5632 // Next: allow a SameSite=Lax or SameSite=Strict cookie.
5633 options.set_same_site_cookie_context(CookieOptions::SameSiteCookieContext(
5634 CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX));
5635 EXPECT_THAT(same_site_none_cookie->IsSetPermittedInContext(
5636 url, options,
5637 CookieAccessParams(CookieAccessSemantics::LEGACY,
5638 delegate_treats_url_as_trustworthy),
5639 kCookieableSchemes),
5640 MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true));
5641 EXPECT_THAT(same_site_lax_cookie->IsSetPermittedInContext(
5642 url, options,
5643 CookieAccessParams(CookieAccessSemantics::LEGACY,
5644 delegate_treats_url_as_trustworthy),
5645 kCookieableSchemes),
5646 MatchesCookieAccessResult(net::IsInclude(), _, _, true));
5647 EXPECT_THAT(same_site_strict_cookie->IsSetPermittedInContext(
5648 url, options,
5649 CookieAccessParams(CookieAccessSemantics::LEGACY,
5650 delegate_treats_url_as_trustworthy),
5651 kCookieableSchemes),
5652 MatchesCookieAccessResult(net::IsInclude(), _, _, true));
5653 }
5654
5655 // Test that the CookieInclusionStatus warning for inclusion changed by
5656 // cross-site redirect context downgrade is applied correctly.
TEST(CanonicalCookieTest,IsSetPermittedInContext_RedirectDowngradeWarning)5657 TEST(CanonicalCookieTest, IsSetPermittedInContext_RedirectDowngradeWarning) {
5658 using Context = CookieOptions::SameSiteCookieContext;
5659 using ContextType = Context::ContextType;
5660
5661 GURL url("https://www.example.test/test");
5662 GURL insecure_url("http://www.example.test/test");
5663
5664 // Test cases to be used with a lax-to-cross context downgrade.
5665 const struct {
5666 ContextType context_type;
5667 CookieSameSite samesite;
5668 bool expect_cross_site_redirect_warning;
5669 } kTestCases[] = {
5670 {ContextType::SAME_SITE_LAX, CookieSameSite::STRICT_MODE, true},
5671 {ContextType::CROSS_SITE, CookieSameSite::STRICT_MODE, true},
5672 {ContextType::SAME_SITE_LAX, CookieSameSite::LAX_MODE, true},
5673 {ContextType::CROSS_SITE, CookieSameSite::LAX_MODE, true},
5674 {ContextType::SAME_SITE_LAX, CookieSameSite::NO_RESTRICTION, false},
5675 {ContextType::CROSS_SITE, CookieSameSite::NO_RESTRICTION, false},
5676 };
5677
5678 for (bool consider_redirects : {true, false}) {
5679 base::test::ScopedFeatureList feature_list;
5680 feature_list.InitWithFeatureState(
5681 features::kCookieSameSiteConsidersRedirectChain, consider_redirects);
5682
5683 for (CookieAccessSemantics semantics :
5684 {CookieAccessSemantics::LEGACY, CookieAccessSemantics::NONLEGACY}) {
5685 // There are no downgrade warnings for undowngraded contexts.
5686 for (ContextType context_type : {ContextType::SAME_SITE_LAX,
5687 ContextType::SAME_SITE_LAX_METHOD_UNSAFE,
5688 ContextType::CROSS_SITE}) {
5689 for (CookieSameSite samesite :
5690 {CookieSameSite::UNSPECIFIED, CookieSameSite::NO_RESTRICTION,
5691 CookieSameSite::LAX_MODE, CookieSameSite::STRICT_MODE}) {
5692 std::unique_ptr<CanonicalCookie> cookie =
5693 CanonicalCookie::CreateUnsafeCookieForTesting(
5694 "A", "1", "www.example.test", "/test", base::Time::Now(),
5695 base::Time(), base::Time(), base::Time(), /*secure=*/true,
5696 /*httponly=*/false, samesite, COOKIE_PRIORITY_DEFAULT);
5697
5698 CookieOptions options;
5699 options.set_same_site_cookie_context(Context(context_type));
5700
5701 EXPECT_FALSE(
5702 cookie
5703 ->IsSetPermittedInContext(
5704 url, options,
5705 CookieAccessParams(
5706 semantics,
5707 /*delegate_treats_url_as_trustworthy=*/false),
5708 kCookieableSchemes)
5709 .status.HasWarningReason(
5710 CookieInclusionStatus::
5711 WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION));
5712 }
5713 }
5714
5715 for (const auto& test : kTestCases) {
5716 std::unique_ptr<CanonicalCookie> cookie =
5717 CanonicalCookie::CreateUnsafeCookieForTesting(
5718 "A", "1", "www.example.test", "/test", base::Time::Now(),
5719 base::Time(), base::Time(), base::Time(), /*secure=*/true,
5720 /*httponly=*/false, test.samesite, COOKIE_PRIORITY_DEFAULT);
5721
5722 Context::ContextMetadata lax_cross_downgrade_metadata;
5723 lax_cross_downgrade_metadata.cross_site_redirect_downgrade =
5724 Context::ContextMetadata::ContextDowngradeType::kLaxToCross;
5725 CookieOptions options;
5726 options.set_same_site_cookie_context(Context(
5727 test.context_type, test.context_type, lax_cross_downgrade_metadata,
5728 lax_cross_downgrade_metadata));
5729
5730 EXPECT_EQ(
5731 cookie
5732 ->IsSetPermittedInContext(
5733 url, options,
5734 CookieAccessParams(
5735 semantics,
5736 /*delegate_treats_url_as_trustworthy=*/false),
5737 kCookieableSchemes)
5738 .status.HasWarningReason(
5739 CookieInclusionStatus::
5740 WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION),
5741 test.expect_cross_site_redirect_warning);
5742
5743 // SameSite warnings not applied if other exclusion reasons apply (e.g.
5744 // non-https with Secure attribute).
5745 EXPECT_FALSE(
5746 cookie
5747 ->IsSetPermittedInContext(
5748 insecure_url, options,
5749 CookieAccessParams(
5750 semantics,
5751 /*delegate_treats_url_as_trustworthy=*/false),
5752 kCookieableSchemes)
5753 .status.HasWarningReason(
5754 CookieInclusionStatus::
5755 WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION));
5756 }
5757 }
5758 }
5759 }
5760
TEST(CanonicalCookieTest,TestIsCanonicalWithInvalidSizeHistograms)5761 TEST(CanonicalCookieTest, TestIsCanonicalWithInvalidSizeHistograms) {
5762 base::HistogramTester histograms;
5763 const char kFromStorageWithValidLengthHistogram[] =
5764 "Cookie.FromStorageWithValidLength";
5765 const base::HistogramBase::Sample kInValid = 0;
5766 const base::HistogramBase::Sample kValid = 1;
5767
5768 base::Time two_hours_ago = base::Time::Now() - base::Hours(2);
5769 base::Time one_hour_ago = base::Time::Now() - base::Hours(1);
5770 base::Time one_hour_from_now = base::Time::Now() + base::Hours(1);
5771
5772 // Test a cookie that is canonical and valid size
5773 EXPECT_TRUE(CanonicalCookie::FromStorage(
5774 "A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now,
5775 one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/,
5776 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
5777 std::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 87,
5778 CookieSourceType::kUnknown));
5779
5780 histograms.ExpectBucketCount(kFromStorageWithValidLengthHistogram, kInValid,
5781 0);
5782 histograms.ExpectBucketCount(kFromStorageWithValidLengthHistogram, kValid, 1);
5783
5784 // Test loading a couple of cookies which are canonical but with an invalid
5785 // size
5786 const std::string kCookieBig(4096, 'a');
5787 EXPECT_TRUE(CanonicalCookie::FromStorage(
5788 kCookieBig, "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now,
5789 one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/,
5790 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
5791 std::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 87,
5792 CookieSourceType::kUnknown));
5793 EXPECT_TRUE(CanonicalCookie::FromStorage(
5794 "A", kCookieBig, "www.foo.com", "/bar", two_hours_ago, one_hour_from_now,
5795 one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/,
5796 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
5797 std::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 87,
5798 CookieSourceType::kUnknown));
5799
5800 histograms.ExpectBucketCount(kFromStorageWithValidLengthHistogram, kInValid,
5801 2);
5802 histograms.ExpectBucketCount(kFromStorageWithValidLengthHistogram, kValid, 1);
5803 }
5804
TEST(CanonicalCookieTest,TestGetAndAdjustPortForTrustworthyUrls)5805 TEST(CanonicalCookieTest, TestGetAndAdjustPortForTrustworthyUrls) {
5806 // GetAndAdjustPortForTrustworthyUrls assumes that http/ws schemes have a port
5807 // of 80 and https/wss schemes have a port of 443 by default. While extremely
5808 // unlikely to change, we may as well confirm that before we continue.
5809 std::string_view http_scheme(url::kHttpScheme);
5810 std::string_view https_scheme(url::kHttpsScheme);
5811 std::string_view ws_scheme(url::kWsScheme);
5812 std::string_view wss_scheme(url::kWssScheme);
5813
5814 EXPECT_EQ(url::DefaultPortForScheme(http_scheme.data(), http_scheme.length()),
5815 80);
5816 EXPECT_EQ(url::DefaultPortForScheme(ws_scheme.data(), ws_scheme.length()),
5817 80);
5818 EXPECT_EQ(
5819 url::DefaultPortForScheme(https_scheme.data(), https_scheme.length()),
5820 443);
5821 EXPECT_EQ(url::DefaultPortForScheme(wss_scheme.data(), wss_scheme.length()),
5822 443);
5823
5824 const GURL secure_http = GURL("https://example.com");
5825 const GURL secure_http_custom_port = GURL("https://example.com:123");
5826 const GURL secure_ws = GURL("wss://example.com");
5827 const GURL secure_ws_custom_port = GURL("wss://example.com:123");
5828
5829 // Secure schemes shouldn't return a different port.
5830 EXPECT_EQ(
5831 CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(secure_http, true),
5832 443);
5833 EXPECT_EQ(
5834 CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(secure_http, false),
5835 443);
5836 EXPECT_EQ(
5837 CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(secure_ws, true),
5838 443);
5839 EXPECT_EQ(
5840 CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(secure_ws, false),
5841 443);
5842 EXPECT_EQ(CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(
5843 secure_http_custom_port, true),
5844 123);
5845 EXPECT_EQ(CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(
5846 secure_http_custom_port, false),
5847 123);
5848 EXPECT_EQ(CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(
5849 secure_ws_custom_port, true),
5850 123);
5851 EXPECT_EQ(CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(
5852 secure_ws_custom_port, false),
5853 123);
5854
5855 const GURL insecure_http = GURL("http://example.com");
5856 const GURL insecure_ws = GURL("ws://example.com");
5857
5858 // Insecure schemes with their default port should return 443 only when
5859 // trustworthy.
5860 EXPECT_EQ(
5861 CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(insecure_http, false),
5862 80);
5863 EXPECT_EQ(
5864 CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(insecure_ws, false),
5865 80);
5866 EXPECT_EQ(
5867 CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(insecure_http, true),
5868 443);
5869 EXPECT_EQ(
5870 CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(insecure_ws, true),
5871 443);
5872
5873 const GURL insecure_http_custom_port = GURL("http://example.com:123");
5874 const GURL insecure_ws_custom_port = GURL("ws://example.com:123");
5875
5876 // Insecure schemes with a non-default port should never return a different
5877 // port.
5878 EXPECT_EQ(CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(
5879 insecure_http_custom_port, false),
5880 123);
5881 EXPECT_EQ(CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(
5882 insecure_ws_custom_port, false),
5883 123);
5884 EXPECT_EQ(CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(
5885 insecure_http_custom_port, true),
5886 123);
5887 EXPECT_EQ(CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(
5888 insecure_ws_custom_port, true),
5889 123);
5890
5891 // File schemes don't have a port component.
5892 const GURL insecure_file = GURL("file://example.com");
5893 EXPECT_EQ(
5894 CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(insecure_file, false),
5895 url::PORT_UNSPECIFIED);
5896 EXPECT_EQ(
5897 CanonicalCookie::GetAndAdjustPortForTrustworthyUrls(insecure_file, true),
5898 url::PORT_UNSPECIFIED);
5899 }
5900
TEST(CanonicalCookieTest,TestHasHiddenPrefixName)5901 TEST(CanonicalCookieTest, TestHasHiddenPrefixName) {
5902 const struct {
5903 const char* value;
5904 bool result;
5905 } kTestCases[] = {
5906 {"", false},
5907 {" ", false},
5908 {"foobar=", false},
5909 {"foo=bar", false},
5910 {" \t ", false},
5911 {"\t", false},
5912 {"__Secure=-", false},
5913 {"__Secure=-abc", false},
5914 {"__Secur=e-abc", false},
5915 {"__Secureabc", false},
5916 {"__Host=-", false},
5917 {"__Host=-abc", false},
5918 {"__Hos=t-abc", false},
5919 {"_Host", false},
5920 {"a__Host-abc=123", false},
5921 {"a__Secure-abc=123", false},
5922 {"__Secure-abc", true},
5923 {"__Host-abc", true},
5924 {" __Secure-abc", true},
5925 {"\t__Host-", true},
5926 {"__Host-=", true},
5927 {"__Host-=123", true},
5928 {"__host-=123", true},
5929 {"__HOST-=123", true},
5930 {"__HoSt-=123", true},
5931 {"__Host-abc=", true},
5932 {"__Host-abc=123", true},
5933 {" __Host-abc=123", true},
5934 {" __Host-abc=", true},
5935 {"\t\t\t\t\t__Host-abc=123", true},
5936 {"\t __Host-abc=", true},
5937 {"__Secure-=", true},
5938 {"__Secure-=123", true},
5939 {"__secure-=123", true},
5940 {"__SECURE-=123", true},
5941 {"__SeCuRe-=123", true},
5942 {"__Secure-abc=", true},
5943 {"__Secure-abc=123", true},
5944 {" __Secure-abc=123", true},
5945 {" __Secure-abc=", true},
5946 {"\t\t\t\t\t__Secure-abc=123", true},
5947 {"\t __Secure-abc=", true},
5948 {"__Secure-abc=123=d=4=fg=", true},
5949 };
5950
5951 for (auto test_case : kTestCases) {
5952 EXPECT_EQ(CanonicalCookie::HasHiddenPrefixName(test_case.value),
5953 test_case.result)
5954 << test_case.value << " failed check";
5955 }
5956 }
5957
TEST(CanonicalCookieTest,TestDoubleUnderscorePrefixHistogram)5958 TEST(CanonicalCookieTest, TestDoubleUnderscorePrefixHistogram) {
5959 base::HistogramTester histograms;
5960 const char kDoubleUnderscorePrefixHistogram[] =
5961 "Cookie.DoubleUnderscorePrefixedName";
5962
5963 CanonicalCookie::CreateForTesting(GURL("https://www.example.com/"),
5964 "__Secure-abc=123; Secure",
5965 base::Time::Now() /* Creation time */);
5966
5967 CanonicalCookie::CreateForTesting(GURL("https://www.example.com/"),
5968 "__Host-abc=123; Secure; Path=/",
5969 base::Time::Now() /* Creation time */);
5970
5971 // Cookie prefixes shouldn't count.
5972 histograms.ExpectTotalCount(kDoubleUnderscorePrefixHistogram, 2);
5973 histograms.ExpectBucketCount(kDoubleUnderscorePrefixHistogram, false, 2);
5974
5975 CanonicalCookie::CreateForTesting(GURL("https://www.example.com/"),
5976 "f__oo=bar",
5977 base::Time::Now() /* Creation time */);
5978
5979 CanonicalCookie::CreateForTesting(GURL("https://www.example.com/"),
5980 "foo=__bar",
5981 base::Time::Now() /* Creation time */);
5982
5983 CanonicalCookie::CreateForTesting(GURL("https://www.example.com/"),
5984 "_foo=bar",
5985 base::Time::Now() /* Creation time */);
5986
5987 CanonicalCookie::CreateForTesting(GURL("https://www.example.com/"),
5988 "_f_oo=bar",
5989 base::Time::Now() /* Creation time */);
5990
5991 // These should be counted.
5992 CanonicalCookie::CreateForTesting(GURL("https://www.example.com/"),
5993 "__foo=bar",
5994 base::Time::Now() /* Creation time */);
5995
5996 CanonicalCookie::CreateForTesting(GURL("https://www.example.com/"),
5997 "___foo=bar",
5998 base::Time::Now() /* Creation time */);
5999
6000 histograms.ExpectTotalCount(kDoubleUnderscorePrefixHistogram, 8);
6001 histograms.ExpectBucketCount(kDoubleUnderscorePrefixHistogram, false, 6);
6002 histograms.ExpectBucketCount(kDoubleUnderscorePrefixHistogram, true, 2);
6003 }
6004
TEST(CanonicalCookieTest,IsThirdPartyPartitioned)6005 TEST(CanonicalCookieTest, IsThirdPartyPartitioned) {
6006 // Partitioned cookie in 3p context.
6007 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
6008 "A", "B", "x.y", "/foo/bar", base::Time(), base::Time(),
6009 base::Time(), base::Time(), /*secure=*/true,
6010 /*httponly=*/false, CookieSameSite::UNSPECIFIED,
6011 COOKIE_PRIORITY_LOW,
6012 CookiePartitionKey::FromURLForTesting(
6013 GURL("https://toplevelsite.com")))
6014 ->IsThirdPartyPartitioned());
6015
6016 // Partitioned cookie in 1p context.
6017 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
6018 "A", "B", "x.y", "/foo/bar", base::Time(), base::Time(),
6019 base::Time(), base::Time(), /*secure=*/true,
6020 /*httponly=*/false, CookieSameSite::UNSPECIFIED,
6021 COOKIE_PRIORITY_LOW,
6022 CookiePartitionKey::FromURLForTesting(GURL("https://x.y")))
6023 ->IsThirdPartyPartitioned());
6024
6025 // Nonced-partitioned cookie should always be 3p context.
6026 auto partition_key_with_nonce =
6027 std::make_optional(CookiePartitionKey::FromURLForTesting(
6028 GURL("https://x.y"), CookiePartitionKey::AncestorChainBit::kCrossSite,
6029 base::UnguessableToken::Create()));
6030 EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
6031 "A", "B", "x.y", "/foo/bar", base::Time(), base::Time(),
6032 base::Time(), base::Time(), /*secure=*/true,
6033 /*httponly=*/false, CookieSameSite::UNSPECIFIED,
6034 COOKIE_PRIORITY_LOW, partition_key_with_nonce)
6035 ->IsThirdPartyPartitioned());
6036
6037 // Unpartitioned cookie.
6038 EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
6039 "A", "B", "x.y", "/foo/bar", base::Time(), base::Time(),
6040 base::Time(), base::Time(), /*secure=*/false,
6041 /*httponly=*/false, CookieSameSite::NO_RESTRICTION,
6042 COOKIE_PRIORITY_LOW)
6043 ->IsThirdPartyPartitioned());
6044 }
6045
6046 // Tests that IsSecure returns true if a cookie's secure attribute is true
6047 // OR if its source_scheme is kSecure when scheme binding is enabled.
TEST(CanonicalCookieTest,IsSecure)6048 TEST(CanonicalCookieTest, IsSecure) {
6049 auto create_cookie = [](bool secure_attribute,
6050 CookieSourceScheme source_scheme) {
6051 return CanonicalCookie::CreateUnsafeCookieForTesting(
6052 "A", "B", "example.com", "/", base::Time(), base::Time(), base::Time(),
6053 base::Time(), secure_attribute, /*httponly=*/false,
6054 CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW,
6055 /*partition_key=*/std::nullopt, source_scheme, /*source_port=*/1234);
6056 };
6057
6058 auto insecure_attr_unset_scheme =
6059 create_cookie(/*secure_attribute=*/false, CookieSourceScheme::kUnset);
6060 auto insecure_attr_insecure_scheme =
6061 create_cookie(/*secure_attribute=*/false, CookieSourceScheme::kNonSecure);
6062 auto insecure_attr_secure_scheme =
6063 create_cookie(/*secure_attribute=*/false, CookieSourceScheme::kSecure);
6064
6065 auto secure_attr_unset_scheme =
6066 create_cookie(/*secure_attribute=*/true, CookieSourceScheme::kUnset);
6067 auto secure_attr_insecure_scheme =
6068 create_cookie(/*secure_attribute=*/true, CookieSourceScheme::kNonSecure);
6069 auto secure_attr_secure_scheme =
6070 create_cookie(/*secure_attribute=*/true, CookieSourceScheme::kSecure);
6071
6072 {
6073 base::test::ScopedFeatureList feature_list;
6074 feature_list.InitAndDisableFeature(features::kEnableSchemeBoundCookies);
6075
6076 // When scheme binding is disabled only the secure attribute causes a return
6077 // value of true.
6078
6079 EXPECT_FALSE(insecure_attr_unset_scheme->IsSecure());
6080 EXPECT_FALSE(insecure_attr_insecure_scheme->IsSecure());
6081 EXPECT_FALSE(insecure_attr_secure_scheme->IsSecure());
6082
6083 EXPECT_TRUE(secure_attr_unset_scheme->IsSecure());
6084 EXPECT_TRUE(secure_attr_insecure_scheme->IsSecure());
6085 EXPECT_TRUE(secure_attr_secure_scheme->IsSecure());
6086 }
6087 {
6088 base::test::ScopedFeatureList feature_list;
6089 feature_list.InitAndEnableFeature(features::kEnableSchemeBoundCookies);
6090
6091 // When scheme binding is enabled a kSecure scheme also causes a returns
6092 // value of true.
6093
6094 EXPECT_FALSE(insecure_attr_unset_scheme->IsSecure());
6095 EXPECT_FALSE(insecure_attr_insecure_scheme->IsSecure());
6096 EXPECT_TRUE(insecure_attr_secure_scheme->IsSecure());
6097
6098 EXPECT_TRUE(secure_attr_unset_scheme->IsSecure());
6099 EXPECT_TRUE(secure_attr_insecure_scheme->IsSecure());
6100 EXPECT_TRUE(secure_attr_secure_scheme->IsSecure());
6101 }
6102 }
6103
6104 } // namespace net
6105