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