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