xref: /aosp_15_r20/external/cronet/net/cookies/canonical_cookie_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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