• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/cookies/cookie_util.h"
6 
7 #include <memory>
8 #include <optional>
9 #include <string>
10 #include <tuple>
11 #include <utility>
12 #include <vector>
13 
14 #include "base/containers/contains.h"
15 #include "base/functional/callback.h"
16 #include "base/strings/strcat.h"
17 #include "base/strings/string_split.h"
18 #include "base/test/bind.h"
19 #include "base/test/scoped_feature_list.h"
20 #include "base/time/time.h"
21 #include "net/base/features.h"
22 #include "net/cookies/cookie_constants.h"
23 #include "net/cookies/cookie_options.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "url/origin.h"
27 
28 namespace net {
29 
30 namespace {
31 
32 struct RequestCookieParsingTest {
33   std::string str;
34   base::StringPairs parsed;
35   // Used for malformed cookies where the parsed-then-serialized string does not
36   // match the original string.
37   std::string serialized;
38 };
39 
CheckParse(const std::string & str,const base::StringPairs & parsed_expected)40 void CheckParse(const std::string& str,
41                 const base::StringPairs& parsed_expected) {
42   cookie_util::ParsedRequestCookies parsed;
43   cookie_util::ParseRequestCookieLine(str, &parsed);
44   EXPECT_EQ(parsed_expected, parsed);
45 }
46 
CheckSerialize(const base::StringPairs & parsed,const std::string & str_expected)47 void CheckSerialize(const base::StringPairs& parsed,
48                     const std::string& str_expected) {
49   EXPECT_EQ(str_expected, cookie_util::SerializeRequestCookieLine(parsed));
50 }
51 
TEST(CookieUtilTest,TestDomainIsHostOnly)52 TEST(CookieUtilTest, TestDomainIsHostOnly) {
53   const struct {
54     const char* str;
55     const bool is_host_only;
56   } tests[] = {{"", true}, {"www.foo.com", true}, {".foo.com", false}};
57 
58   for (const auto& test : tests) {
59     EXPECT_EQ(test.is_host_only, cookie_util::DomainIsHostOnly(test.str));
60   }
61 }
62 
63 // A cookie domain containing non-ASCII characters is not allowed, even if it
64 // matches the domain from the URL.
TEST(CookieUtilTest,GetCookieDomainWithString_NonASCII)65 TEST(CookieUtilTest, GetCookieDomainWithString_NonASCII) {
66   base::test::ScopedFeatureList feature_list;
67   feature_list.InitAndEnableFeature(features::kCookieDomainRejectNonASCII);
68 
69   CookieInclusionStatus status;
70   std::string result;
71   EXPECT_FALSE(cookie_util::GetCookieDomainWithString(
72       GURL("http://éxample.com"), xample.com", status, &result));
73   EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
74       {CookieInclusionStatus::EXCLUDE_DOMAIN_NON_ASCII}));
75 }
76 
77 // An empty domain string results in the domain from the URL.
TEST(CookieUtilTest,GetCookieDomainWithString_Empty)78 TEST(CookieUtilTest, GetCookieDomainWithString_Empty) {
79   CookieInclusionStatus status;
80   std::string result;
81   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(GURL("http://example.com"),
82                                                      "", status, &result));
83   EXPECT_TRUE(status.IsInclude());
84   EXPECT_EQ(result, "example.com");
85 }
86 
87 // An empty domain string results in the domain from the URL, which has been
88 // canonicalized. Regression test for https://crbug.com/362535230.
TEST(CookieUtilTest,GetCookieDomainWithString_EmptyNonCanonical)89 TEST(CookieUtilTest, GetCookieDomainWithString_EmptyNonCanonical) {
90   // `GURL` doesn't canonicalize the below URL, since it doesn't recognize the
91   // scheme. So we ensure that `GetCookieDomainWithString` recanonicalizes it.
92   CookieInclusionStatus status;
93   std::string result;
94   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(GURL("foo://LOCALhost"),
95                                                      "", status, &result));
96   EXPECT_TRUE(status.IsInclude());
97   EXPECT_EQ(result, "localhost");
98 }
99 
100 // A cookie domain string equal to the URL host, when that is an IP, results in
101 // the IP.
TEST(CookieUtilTest,GetCookieDomainWithString_IP)102 TEST(CookieUtilTest, GetCookieDomainWithString_IP) {
103   CookieInclusionStatus status;
104   std::string result;
105   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(
106       GURL("http://192.0.2.3"), "192.0.2.3", status, &result));
107   EXPECT_TRUE(status.IsInclude());
108   EXPECT_EQ(result, "192.0.2.3");
109 }
110 
111 // A cookie domain string equal to a dot prefixed to the URL host, when that is
112 // an IP, results in the IP, without the dot.
TEST(CookieUtilTest,GetCookieDomainWithString_DotIP)113 TEST(CookieUtilTest, GetCookieDomainWithString_DotIP) {
114   CookieInclusionStatus status;
115   std::string result;
116   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(
117       GURL("http://192.0.2.3"), ".192.0.2.3", status, &result));
118   EXPECT_TRUE(status.IsInclude());
119   EXPECT_EQ(result, "192.0.2.3");
120 }
121 
122 // A cookie domain string containing %-encoding is not allowed.
TEST(CookieUtilTest,GetCookieDomainWithString_PercentEncoded)123 TEST(CookieUtilTest, GetCookieDomainWithString_PercentEncoded) {
124   CookieInclusionStatus status;
125   std::string result;
126   EXPECT_FALSE(cookie_util::GetCookieDomainWithString(
127       GURL("http://a.test"), "a%2Etest", status, &result));
128   EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting({}));
129 }
130 
131 // A cookie domain string that cannot be canonicalized is not allowed.
TEST(CookieUtilTest,GetCookieDomainWithString_UnCanonicalizable)132 TEST(CookieUtilTest, GetCookieDomainWithString_UnCanonicalizable) {
133   CookieInclusionStatus status;
134   std::string result;
135   EXPECT_FALSE(cookie_util::GetCookieDomainWithString(
136       GURL("http://a.test"), "a^test", status, &result));
137   EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting({}));
138 }
139 
140 // A cookie domain that is an eTLD but matches the URL results in a host cookie
141 // domain.
TEST(CookieUtilTest,GetCookieDomainWithString_ETldMatchesUrl)142 TEST(CookieUtilTest, GetCookieDomainWithString_ETldMatchesUrl) {
143   CookieInclusionStatus status;
144   std::string result;
145   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(
146       GURL("http://gov.uk"), "gov.uk", status, &result));
147   EXPECT_TRUE(status.IsInclude());
148   EXPECT_EQ(result, "gov.uk");
149 }
150 
151 // A cookie domain that is an eTLD but matches the URL results in a host cookie
152 // domain, even if it is given with a dot prefix.
TEST(CookieUtilTest,GetCookieDomainWithString_ETldMatchesUrl_DotPrefix)153 TEST(CookieUtilTest, GetCookieDomainWithString_ETldMatchesUrl_DotPrefix) {
154   CookieInclusionStatus status;
155   std::string result;
156   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(
157       GURL("http://gov.uk"), ".gov.uk", status, &result));
158   EXPECT_TRUE(status.IsInclude());
159   EXPECT_EQ(result, "gov.uk");
160 }
161 
162 // A cookie domain that is an eTLD but matches the URL results in a host cookie
163 // domain, even if its capitalization is non-canonical.
TEST(CookieUtilTest,GetCookieDomainWithString_ETldMatchesUrl_NonCanonical)164 TEST(CookieUtilTest, GetCookieDomainWithString_ETldMatchesUrl_NonCanonical) {
165   CookieInclusionStatus status;
166   std::string result;
167   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(
168       GURL("http://gov.uk"), "GoV.Uk", status, &result));
169   EXPECT_TRUE(status.IsInclude());
170   EXPECT_EQ(result, "gov.uk");
171 }
172 
173 // A cookie domain that is an eTLD but does not match the URL is not allowed.
TEST(CookieUtilTest,GetCookieDomainWithString_ETldDifferentUrl)174 TEST(CookieUtilTest, GetCookieDomainWithString_ETldDifferentUrl) {
175   CookieInclusionStatus status;
176   std::string result;
177   EXPECT_FALSE(cookie_util::GetCookieDomainWithString(
178       GURL("http://nhs.gov.uk"), "gov.uk", status, &result));
179   EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting({}));
180 }
181 
182 // A cookie domain with a different eTLD+1 ("organization-identifying host")
183 // from the URL is not allowed.
TEST(CookieUtilTest,GetCookieDomainWithString_DifferentOrgHost)184 TEST(CookieUtilTest, GetCookieDomainWithString_DifferentOrgHost) {
185   CookieInclusionStatus status;
186   std::string result;
187   EXPECT_FALSE(cookie_util::GetCookieDomainWithString(
188       GURL("http://portal.globex.com"), "portal.initech.com", status, &result));
189   EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting({}));
190 }
191 
192 // A cookie domain that matches the URL results in a domain cookie domain.
TEST(CookieUtilTest,GetCookieDomainWithString_MatchesUrl)193 TEST(CookieUtilTest, GetCookieDomainWithString_MatchesUrl) {
194   CookieInclusionStatus status;
195   std::string result;
196   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(
197       GURL("http://globex.com"), "globex.com", status, &result));
198   EXPECT_TRUE(status.IsInclude());
199   EXPECT_EQ(result, ".globex.com");
200 }
201 
202 // A cookie domain that matches the URL but has a `.` prefix results in a domain
203 // cookie domain.
TEST(CookieUtilTest,GetCookieDomainWithString_MatchesUrlWithDot)204 TEST(CookieUtilTest, GetCookieDomainWithString_MatchesUrlWithDot) {
205   CookieInclusionStatus status;
206   std::string result;
207   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(
208       GURL("http://globex.com"), ".globex.com", status, &result));
209   EXPECT_TRUE(status.IsInclude());
210   EXPECT_EQ(result, ".globex.com");
211 }
212 
213 // A cookie domain that is a subdomain of the URL host is not allowed.
TEST(CookieUtilTest,GetCookieDomainWithString_Subdomain)214 TEST(CookieUtilTest, GetCookieDomainWithString_Subdomain) {
215   CookieInclusionStatus status;
216   std::string result;
217   EXPECT_FALSE(cookie_util::GetCookieDomainWithString(
218       GURL("http://globex.com"), "mail.globex.com", status, &result));
219   EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting({}));
220 }
221 
222 // A URL that is a subdomain of the cookie domain results in a domain cookie.
TEST(CookieUtilTest,GetCookieDomainWithString_UrlSubdomain)223 TEST(CookieUtilTest, GetCookieDomainWithString_UrlSubdomain) {
224   CookieInclusionStatus status;
225   std::string result;
226   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(
227       GURL("http://mail.globex.com"), "globex.com", status, &result));
228   EXPECT_TRUE(status.IsInclude());
229   EXPECT_EQ(result, ".globex.com");
230 }
231 
232 // A URL of which the cookie domain is a substring, but not a dotted suffix,
233 // is not allowed.
TEST(CookieUtilTest,GetCookieDomainWithString_SubstringButUrlNotSubdomain)234 TEST(CookieUtilTest, GetCookieDomainWithString_SubstringButUrlNotSubdomain) {
235   CookieInclusionStatus status;
236   std::string result;
237   EXPECT_FALSE(cookie_util::GetCookieDomainWithString(
238       GURL("http://myglobex.com"), "globex.com", status, &result));
239   EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting({}));
240 }
241 
242 // A URL which has a different subdomain of the eTLD+1 than the cookie domain is
243 // not allowed, regardless of which hostname is longer.
TEST(CookieUtilTest,GetCookieDomainWithString_DifferentSubdomain)244 TEST(CookieUtilTest, GetCookieDomainWithString_DifferentSubdomain) {
245   CookieInclusionStatus status;
246   std::string result;
247   EXPECT_FALSE(cookie_util::GetCookieDomainWithString(
248       GURL("http://l.globex.com"), "portal.globex.com", status, &result));
249   EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting({}));
250   EXPECT_FALSE(cookie_util::GetCookieDomainWithString(
251       GURL("http://portal.globex.com"), "l.globex.com", status, &result));
252   EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting({}));
253 }
254 
255 // A URL without a host can set a "host" cookie with no cookie domain.
TEST(CookieUtilTest,GetCookieDomainWithString_NoUrlHost)256 TEST(CookieUtilTest, GetCookieDomainWithString_NoUrlHost) {
257   CookieInclusionStatus status;
258   std::string result;
259   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(
260       GURL("file:///C:/bar.html"), "", status, &result));
261   EXPECT_EQ(result, "");
262 }
263 
264 // A URL with two trailing dots (which is an invalid hostname per
265 // rfc6265bis-11#5.1.2 and will cause GetDomainAndRegistry to return an empty
266 // string) is not allowed.
TEST(CookieUtilTest,GetCookieDomainWithString_TrailingDots)267 TEST(CookieUtilTest, GetCookieDomainWithString_TrailingDots) {
268   CookieInclusionStatus status;
269   std::string result;
270   EXPECT_FALSE(cookie_util::GetCookieDomainWithString(
271       GURL("http://foo.com../"), "foo.com..", status, &result));
272   EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting({}));
273 }
274 
275 // A "normal" URL does not match with a cookie containing two trailing dots (or
276 // just one).
TEST(CookieUtilTest,GetCookieDomainWithString_TrailingDots_NotMatchingUrlHost)277 TEST(CookieUtilTest,
278      GetCookieDomainWithString_TrailingDots_NotMatchingUrlHost) {
279   CookieInclusionStatus status;
280   std::string result;
281   EXPECT_FALSE(cookie_util::GetCookieDomainWithString(
282       GURL("http://foo.com/"), ".foo.com..", status, &result));
283   EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting({}));
284   EXPECT_FALSE(cookie_util::GetCookieDomainWithString(
285       GURL("http://foo.com/"), ".foo.com.", status, &result));
286   EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting({}));
287 }
288 
289 // A URL containing an IP address is allowed, if that IP matches the cookie
290 // domain.
TEST(CookieUtilTest,GetCookieDomainWithString_UrlHostIP)291 TEST(CookieUtilTest, GetCookieDomainWithString_UrlHostIP) {
292   CookieInclusionStatus status;
293   std::string result;
294   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(
295       GURL("http://192.0.2.3/"), "192.0.2.3", status, &result));
296   EXPECT_EQ(result, "192.0.2.3");
297 }
298 
299 // A cookie domain with a dot-prefixed IP is allowed, if the IP matches
300 // the URL, but is transformed to a host cookie domain.
TEST(CookieUtilTest,GetCookieDomainWithString_UrlHostIP_DomainCookie)301 TEST(CookieUtilTest, GetCookieDomainWithString_UrlHostIP_DomainCookie) {
302   CookieInclusionStatus status;
303   std::string result;
304   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(
305       GURL("http://192.0.2.3/"), ".192.0.2.3", status, &result));
306   EXPECT_EQ(result, "192.0.2.3");  // No dot.
307 }
308 
309 // A URL containing a TLD that is unknown as a registry is allowed, if it
310 // matches the cookie domain.
TEST(CookieUtilTest,GetCookieDomainWithString_UnknownRegistry)311 TEST(CookieUtilTest, GetCookieDomainWithString_UnknownRegistry) {
312   CookieInclusionStatus status;
313   std::string result;
314   EXPECT_TRUE(cookie_util::GetCookieDomainWithString(GURL("http://bar/"), "bar",
315                                                      status, &result));
316   EXPECT_EQ(result, "bar");
317 }
318 
TEST(CookieUtilTest,TestCookieDateParsing)319 TEST(CookieUtilTest, TestCookieDateParsing) {
320   const struct {
321     const char* str;
322     const bool valid;
323     const double epoch;
324   } tests[] = {
325       {"Sat, 15-Apr-17 21:01:22 GMT", true, 1492290082},
326       {"Thu, 19-Apr-2007 16:00:00 GMT", true, 1176998400},
327       {"Wed, 25 Apr 2007 21:02:13 GMT", true, 1177534933},
328       {"Thu, 19/Apr\\2007 16:00:00 GMT", true, 1176998400},
329       {"Fri, 1 Jan 2010 01:01:50 GMT", true, 1262307710},
330       {"Wednesday, 1-Jan-2003 00:00:00 GMT", true, 1041379200},
331       {", 1-Jan-2003 00:00:00 GMT", true, 1041379200},
332       {" 1-Jan-2003 00:00:00 GMT", true, 1041379200},
333       {"1-Jan-2003 00:00:00 GMT", true, 1041379200},
334       {"Wed,18-Apr-07 22:50:12 GMT", true, 1176936612},
335       {"WillyWonka  , 18-Apr-07 22:50:12 GMT", true, 1176936612},
336       {"WillyWonka  , 18-Apr-07 22:50:12", true, 1176936612},
337       {"WillyWonka  ,  18-apr-07   22:50:12", true, 1176936612},
338       {"Mon, 18-Apr-1977 22:50:13 GMT", true, 230251813},
339       {"Mon, 18-Apr-77 22:50:13 GMT", true, 230251813},
340       // If the cookie came in with the expiration quoted (which in terms of
341       // the RFC you shouldn't do), we will get string quoted.  Bug 1261605.
342       {"\"Sat, 15-Apr-17\\\"21:01:22\\\"GMT\"", true, 1492290082},
343       // Test with full month names and partial names.
344       {"Partyday, 18- April-07 22:50:12", true, 1176936612},
345       {"Partyday, 18 - Apri-07 22:50:12", true, 1176936612},
346       {"Wednes, 1-Januar-2003 00:00:00 GMT", true, 1041379200},
347       // Test that we always take GMT even with other time zones or bogus
348       // values.  The RFC says everything should be GMT, and in the worst case
349       // we are 24 hours off because of zone issues.
350       {"Sat, 15-Apr-17 21:01:22", true, 1492290082},
351       {"Sat, 15-Apr-17 21:01:22 GMT-2", true, 1492290082},
352       {"Sat, 15-Apr-17 21:01:22 GMT BLAH", true, 1492290082},
353       {"Sat, 15-Apr-17 21:01:22 GMT-0400", true, 1492290082},
354       {"Sat, 15-Apr-17 21:01:22 GMT-0400 (EDT)", true, 1492290082},
355       {"Sat, 15-Apr-17 21:01:22 DST", true, 1492290082},
356       {"Sat, 15-Apr-17 21:01:22 -0400", true, 1492290082},
357       {"Sat, 15-Apr-17 21:01:22 (hello there)", true, 1492290082},
358       // Test that if we encounter multiple : fields, that we take the first
359       // that correctly parses.
360       {"Sat, 15-Apr-17 21:01:22 11:22:33", true, 1492290082},
361       {"Sat, 15-Apr-17 ::00 21:01:22", true, 1492290082},
362       {"Sat, 15-Apr-17 boink:z 21:01:22", true, 1492290082},
363       // We take the first, which in this case is invalid.
364       {"Sat, 15-Apr-17 91:22:33 21:01:22", false, 0},
365       // amazon.com formats their cookie expiration like this.
366       {"Thu Apr 18 22:50:12 2007 GMT", true, 1176936612},
367       // Test that hh:mm:ss can occur anywhere.
368       {"22:50:12 Thu Apr 18 2007 GMT", true, 1176936612},
369       {"Thu 22:50:12 Apr 18 2007 GMT", true, 1176936612},
370       {"Thu Apr 22:50:12 18 2007 GMT", true, 1176936612},
371       {"Thu Apr 18 22:50:12 2007 GMT", true, 1176936612},
372       {"Thu Apr 18 2007 22:50:12 GMT", true, 1176936612},
373       {"Thu Apr 18 2007 GMT 22:50:12", true, 1176936612},
374       // Test that the day and year can be anywhere if they are unambigious.
375       {"Sat, 15-Apr-17 21:01:22 GMT", true, 1492290082},
376       {"15-Sat, Apr-17 21:01:22 GMT", true, 1492290082},
377       {"15-Sat, Apr 21:01:22 GMT 17", true, 1492290082},
378       {"15-Sat, Apr 21:01:22 GMT 2017", true, 1492290082},
379       {"15 Apr 21:01:22 2017", true, 1492290082},
380       {"15 17 Apr 21:01:22", true, 1492290082},
381       {"Apr 15 17 21:01:22", true, 1492290082},
382       {"Apr 15 21:01:22 17", true, 1492290082},
383       {"2017 April 15 21:01:22", true, 1492290082},
384       {"15 April 2017 21:01:22", true, 1492290082},
385       // Test two-digit abbreviated year numbers.
386       {"1-Jan-71 00:00:00 GMT" /* 1971 */, true, 31536000},
387       {"1-Jan-70 00:00:00 GMT" /* 1970 */, true, 0},
388       {"1-Jan-69 00:00:00 GMT" /* 2069 */, true, 3124224000},
389       {"1-Jan-68 00:00:00 GMT" /* 2068 */, true, 3092601600},
390       // Some invalid dates
391       {"98 April 17 21:01:22", false, 0},
392       {"Thu, 012-Aug-2008 20:49:07 GMT", false, 0},
393       {"Thu, 12-Aug-9999999999 20:49:07 GMT", false, 0},
394       {"Thu, 999999999999-Aug-2007 20:49:07 GMT", false, 0},
395       {"Thu, 12-Aug-2007 20:61:99999999999 GMT", false, 0},
396       {"IAintNoDateFool", false, 0},
397       {"1600 April 33 21:01:22", false, 0},
398       {"1970 April 33 21:01:22", false, 0},
399       {"Thu, 33-Aug-31841 20:49:07 GMT", false, 0},
400   };
401 
402   base::Time parsed_time;
403   for (const auto& test : tests) {
404     parsed_time = cookie_util::ParseCookieExpirationTime(test.str);
405     if (!test.valid) {
406       EXPECT_TRUE(parsed_time.is_null()) << test.str;
407       continue;
408     }
409     EXPECT_TRUE(!parsed_time.is_null()) << test.str;
410     EXPECT_EQ(test.epoch, parsed_time.InSecondsFSinceUnixEpoch()) << test.str;
411   }
412 }
413 
414 // Tests parsing dates that are beyond 2038. 32-bit (non-Mac) POSIX systems are
415 // incapable of doing this, however the expectation is for cookie parsing to
416 // succeed anyway (and return the minimum value Time::FromUTCExploded() can
417 // parse on the current platform). Also checks a date outside the limit on
418 // Windows, which is year 30827.
TEST(CookieUtilTest,ParseCookieExpirationTimeBeyond2038)419 TEST(CookieUtilTest, ParseCookieExpirationTimeBeyond2038) {
420   const char* kTests[] = {
421       "Thu, 12-Aug-31841 20:49:07 GMT", "2039 April 15 21:01:22",
422       "2039 April 15 21:01:22",         "2038 April 15 21:01:22",
423       "15 April 69 21:01:22",           "15 April 68, 21:01:22",
424   };
425 
426   for (auto* test : kTests) {
427     base::Time parsed_time = cookie_util::ParseCookieExpirationTime(test);
428     EXPECT_FALSE(parsed_time.is_null());
429 
430     // It should either have an exact value, or be base::Time::Max(). For
431     // simplicity just check that it is greater than an arbitray date.
432     base::Time almost_jan_2038 = base::Time::UnixEpoch() + base::Days(365 * 68);
433     EXPECT_LT(almost_jan_2038, parsed_time);
434   }
435 }
436 
437 // Tests parsing dates that are prior to (or around) 1970. Non-Mac POSIX systems
438 // are incapable of doing this, however the expectation is for cookie parsing to
439 // succeed anyway (and return a minimal base::Time).
TEST(CookieUtilTest,ParseCookieExpirationTimeBefore1970)440 TEST(CookieUtilTest, ParseCookieExpirationTimeBefore1970) {
441   const char* kTests[] = {
442       // Times around the Unix epoch.
443       "1970 Jan 1 00:00:00",
444       "1969 March 3 21:01:22",
445       // Two digit year abbreviations.
446       "1-Jan-70 00:00:00",
447       "Jan 1, 70 00:00:00",
448       // Times around the Windows epoch.
449       "1601 Jan 1 00:00:00",
450       "1600 April 15 21:01:22",
451       // Times around kExplodedMinYear on Mac.
452       "1902 Jan 1 00:00:00",
453       "1901 Jan 1 00:00:00",
454   };
455 
456   for (auto* test : kTests) {
457     base::Time parsed_time = cookie_util::ParseCookieExpirationTime(test);
458     EXPECT_FALSE(parsed_time.is_null()) << test;
459 
460     // It should either have an exact value, or should be base::Time(1)
461     // For simplicity just check that it is less than the unix epoch.
462     EXPECT_LE(parsed_time, base::Time::UnixEpoch()) << test;
463   }
464 }
465 
TEST(CookieUtilTest,TestRequestCookieParsing)466 TEST(CookieUtilTest, TestRequestCookieParsing) {
467   std::vector<RequestCookieParsingTest> tests;
468 
469   // Simple case.
470   tests.emplace_back();
471   tests.back().str = "key=value";
472   tests.back().parsed.emplace_back(std::string("key"), std::string("value"));
473   // Multiple key/value pairs.
474   tests.emplace_back();
475   tests.back().str = "key1=value1; key2=value2";
476   tests.back().parsed.emplace_back(std::string("key1"), std::string("value1"));
477   tests.back().parsed.emplace_back(std::string("key2"), std::string("value2"));
478   // Empty value.
479   tests.emplace_back();
480   tests.back().str = "key=; otherkey=1234";
481   tests.back().parsed.emplace_back(std::string("key"), std::string());
482   tests.back().parsed.emplace_back(std::string("otherkey"),
483                                    std::string("1234"));
484   // Special characters (including equals signs) in value.
485   tests.emplace_back();
486   tests.back().str = "key=; a2=s=(./&t=:&u=a#$; a3=+~";
487   tests.back().parsed.emplace_back(std::string("key"), std::string());
488   tests.back().parsed.emplace_back(std::string("a2"),
489                                    std::string("s=(./&t=:&u=a#$"));
490   tests.back().parsed.emplace_back(std::string("a3"), std::string("+~"));
491   // Quoted value.
492   tests.emplace_back();
493   tests.back().str = "key=\"abcdef\"; otherkey=1234";
494   tests.back().parsed.emplace_back(std::string("key"),
495                                    std::string("\"abcdef\""));
496   tests.back().parsed.emplace_back(std::string("otherkey"),
497                                    std::string("1234"));
498 
499   for (size_t i = 0; i < tests.size(); i++) {
500     SCOPED_TRACE(testing::Message() << "Test " << i);
501     CheckParse(tests[i].str, tests[i].parsed);
502     CheckSerialize(tests[i].parsed, tests[i].str);
503   }
504 }
505 
TEST(CookieUtilTest,TestRequestCookieParsing_Malformed)506 TEST(CookieUtilTest, TestRequestCookieParsing_Malformed) {
507   std::vector<RequestCookieParsingTest> tests;
508 
509   // Missing equal sign.
510   tests.emplace_back();
511   tests.back().str = "key";
512   tests.back().parsed.emplace_back(std::string("key"), std::string());
513   tests.back().serialized = "key=";
514 
515   // Quoted value with unclosed quote.
516   tests.emplace_back();
517   tests.back().str = "key=\"abcdef";
518 
519   // Quoted value with unclosed quote followed by regular value.
520   tests.emplace_back();
521   tests.back().str = "key=\"abcdef; otherkey=1234";
522 
523   // Quoted value with unclosed quote followed by another quoted value.
524   tests.emplace_back();
525   tests.back().str = "key=\"abcdef; otherkey=\"1234\"";
526   tests.back().parsed.emplace_back(std::string("key"),
527                                    std::string("\"abcdef; otherkey=\""));
528   tests.back().parsed.emplace_back(std::string("234\""), std::string());
529   tests.back().serialized = "key=\"abcdef; otherkey=\"; 234\"=";
530 
531   // Regular value followed by quoted value with unclosed quote.
532   tests.emplace_back();
533   tests.back().str = "key=abcdef; otherkey=\"1234";
534   tests.back().parsed.emplace_back(std::string("key"), std::string("abcdef"));
535   tests.back().serialized = "key=abcdef";
536 
537   for (size_t i = 0; i < tests.size(); i++) {
538     SCOPED_TRACE(testing::Message() << "Test " << i);
539     CheckParse(tests[i].str, tests[i].parsed);
540     CheckSerialize(tests[i].parsed, tests[i].serialized);
541   }
542 }
543 
TEST(CookieUtilTest,CookieDomainAndPathToURL)544 TEST(CookieUtilTest, CookieDomainAndPathToURL) {
545   struct {
546     std::string domain;
547     std::string path;
548     bool is_https;
549     std::string expected_url;
550   } kTests[]{
551       {"a.com", "/", true, "https://a.com/"},
552       {"a.com", "/", false, "http://a.com/"},
553       {".a.com", "/", true, "https://a.com/"},
554       {".a.com", "/", false, "http://a.com/"},
555       {"b.a.com", "/", true, "https://b.a.com/"},
556       {"b.a.com", "/", false, "http://b.a.com/"},
557       {"a.com", "/example/path", true, "https://a.com/example/path"},
558       {".a.com", "/example/path", false, "http://a.com/example/path"},
559       {"b.a.com", "/example/path", true, "https://b.a.com/example/path"},
560       {".b.a.com", "/example/path", false, "http://b.a.com/example/path"},
561   };
562 
563   for (auto& test : kTests) {
564     GURL url1 = cookie_util::CookieDomainAndPathToURL(test.domain, test.path,
565                                                       test.is_https);
566     GURL url2 = cookie_util::CookieDomainAndPathToURL(
567         test.domain, test.path, std::string(test.is_https ? "https" : "http"));
568     // Test both overloads for equality.
569     EXPECT_EQ(url1, url2);
570     EXPECT_EQ(url1, GURL(test.expected_url));
571   }
572 }
573 
TEST(CookieUtilTest,SimulatedCookieSource)574 TEST(CookieUtilTest, SimulatedCookieSource) {
575   GURL secure_url("https://b.a.com");
576   GURL insecure_url("http://b.a.com");
577 
578   struct {
579     std::string cookie;
580     std::string source_scheme;
581     std::string expected_simulated_source;
582   } kTests[]{
583       {"cookie=foo", "http", "http://b.a.com/"},
584       {"cookie=foo", "https", "https://b.a.com/"},
585       {"cookie=foo", "wss", "wss://b.a.com/"},
586       {"cookie=foo", "file", "file://b.a.com/"},
587       {"cookie=foo; Domain=b.a.com", "https", "https://b.a.com/"},
588       {"cookie=foo; Domain=a.com", "https", "https://a.com/"},
589       {"cookie=foo; Domain=.b.a.com", "https", "https://b.a.com/"},
590       {"cookie=foo; Domain=.a.com", "https", "https://a.com/"},
591       {"cookie=foo; Path=/", "https", "https://b.a.com/"},
592       {"cookie=foo; Path=/bar", "https", "https://b.a.com/bar"},
593       {"cookie=foo; Domain=b.a.com; Path=/", "https", "https://b.a.com/"},
594       {"cookie=foo; Domain=b.a.com; Path=/bar", "https", "https://b.a.com/bar"},
595       {"cookie=foo; Domain=a.com; Path=/", "https", "https://a.com/"},
596       {"cookie=foo; Domain=a.com; Path=/bar", "https", "https://a.com/bar"},
597   };
598 
599   for (const auto& test : kTests) {
600     std::vector<std::unique_ptr<CanonicalCookie>> cookies;
601     // It shouldn't depend on the cookie's secureness or actual source scheme.
602     cookies.push_back(CanonicalCookie::CreateForTesting(
603         insecure_url, test.cookie, base::Time::Now()));
604     cookies.push_back(CanonicalCookie::CreateForTesting(secure_url, test.cookie,
605                                                         base::Time::Now()));
606     cookies.push_back(CanonicalCookie::CreateForTesting(
607         secure_url, test.cookie + "; Secure", base::Time::Now()));
608     for (const auto& cookie : cookies) {
609       GURL simulated_source =
610           cookie_util::SimulatedCookieSource(*cookie, test.source_scheme);
611       EXPECT_EQ(GURL(test.expected_simulated_source), simulated_source);
612     }
613   }
614 }
615 
TEST(CookieUtilTest,TestGetEffectiveDomain)616 TEST(CookieUtilTest, TestGetEffectiveDomain) {
617   // Note: registry_controlled_domains::GetDomainAndRegistry is tested in its
618   // own unittests.
619   EXPECT_EQ("example.com",
620             cookie_util::GetEffectiveDomain("http", "www.example.com"));
621   EXPECT_EQ("example.com",
622             cookie_util::GetEffectiveDomain("https", "www.example.com"));
623   EXPECT_EQ("example.com",
624             cookie_util::GetEffectiveDomain("ws", "www.example.com"));
625   EXPECT_EQ("example.com",
626             cookie_util::GetEffectiveDomain("wss", "www.example.com"));
627   EXPECT_EQ("www.example.com",
628             cookie_util::GetEffectiveDomain("ftp", "www.example.com"));
629 }
630 
TEST(CookieUtilTest,TestIsDomainMatch)631 TEST(CookieUtilTest, TestIsDomainMatch) {
632   EXPECT_TRUE(cookie_util::IsDomainMatch("example.com", "example.com"));
633   EXPECT_FALSE(cookie_util::IsDomainMatch("www.example.com", "example.com"));
634 
635   EXPECT_TRUE(cookie_util::IsDomainMatch(".example.com", "example.com"));
636   EXPECT_TRUE(cookie_util::IsDomainMatch(".example.com", "www.example.com"));
637   EXPECT_FALSE(cookie_util::IsDomainMatch(".www.example.com", "example.com"));
638 
639   EXPECT_FALSE(cookie_util::IsDomainMatch("example.com", "example.de"));
640   EXPECT_FALSE(cookie_util::IsDomainMatch(".example.com", "example.de"));
641   EXPECT_FALSE(cookie_util::IsDomainMatch(".example.de", "example.de.vu"));
642 }
643 
TEST(CookieUtilTest,TestIsOnPath)644 TEST(CookieUtilTest, TestIsOnPath) {
645   EXPECT_TRUE(cookie_util::IsOnPath("/", "/"));
646   EXPECT_TRUE(cookie_util::IsOnPath("/", "/test"));
647   EXPECT_TRUE(cookie_util::IsOnPath("/", "/test/bar.html"));
648 
649   // Test the empty string edge case.
650   EXPECT_FALSE(cookie_util::IsOnPath("/", std::string()));
651 
652   EXPECT_FALSE(cookie_util::IsOnPath("/test", "/"));
653 
654   EXPECT_TRUE(cookie_util::IsOnPath("/test", "/test"));
655   EXPECT_FALSE(cookie_util::IsOnPath("/test", "/testtest/"));
656 
657   EXPECT_TRUE(cookie_util::IsOnPath("/test", "/test/bar.html"));
658   EXPECT_TRUE(cookie_util::IsOnPath("/test", "/test/sample/bar.html"));
659 }
660 
TEST(CookieUtilTest,TestIsOnPathCaseSensitive)661 TEST(CookieUtilTest, TestIsOnPathCaseSensitive) {
662   EXPECT_TRUE(cookie_util::IsOnPath("/test", "/test"));
663   EXPECT_FALSE(cookie_util::IsOnPath("/test", "/TEST"));
664   EXPECT_FALSE(cookie_util::IsOnPath("/TEST", "/test"));
665 }
666 
667 using ::testing::AllOf;
668 using SameSiteCookieContext = CookieOptions::SameSiteCookieContext;
669 using ContextType = CookieOptions::SameSiteCookieContext::ContextType;
670 using ContextRedirectTypeBug1221316 = CookieOptions::SameSiteCookieContext::
671     ContextMetadata::ContextRedirectTypeBug1221316;
672 using HttpMethod =
673     CookieOptions::SameSiteCookieContext::ContextMetadata::HttpMethod;
674 
675 MATCHER_P2(ContextTypeIsWithSchemefulMode, context_type, schemeful, "") {
676   return context_type == (schemeful ? arg.schemeful_context() : arg.context());
677 }
678 
679 // Checks for the expected metadata related to context downgrades from
680 // cross-site redirects.
681 MATCHER_P5(CrossSiteRedirectMetadataCorrectWithSchemefulMode,
682            method,
683            context_type_without_chain,
684            context_type_with_chain,
685            redirect_type_with_chain,
686            schemeful,
687            "") {
688   using ContextDowngradeType = CookieOptions::SameSiteCookieContext::
689       ContextMetadata::ContextDowngradeType;
690 
691   const auto& metadata = schemeful ? arg.schemeful_metadata() : arg.metadata();
692 
693   if (metadata.redirect_type_bug_1221316 != redirect_type_with_chain)
694     return false;
695 
696   // http_method_bug_1221316 is only set when there is a context downgrade.
697   if (metadata.cross_site_redirect_downgrade !=
698           ContextDowngradeType::kNoDowngrade &&
699       metadata.http_method_bug_1221316 != method) {
700     return false;
701   }
702 
703   switch (metadata.cross_site_redirect_downgrade) {
704     case ContextDowngradeType::kNoDowngrade:
705       return context_type_without_chain == context_type_with_chain;
706     case ContextDowngradeType::kStrictToLax:
707       return context_type_without_chain == ContextType::SAME_SITE_STRICT &&
708              (context_type_with_chain == ContextType::SAME_SITE_LAX ||
709               context_type_with_chain ==
710                   ContextType::SAME_SITE_LAX_METHOD_UNSAFE);
711     case ContextDowngradeType::kStrictToCross:
712       return context_type_without_chain == ContextType::SAME_SITE_STRICT &&
713              context_type_with_chain == ContextType::CROSS_SITE;
714     case ContextDowngradeType::kLaxToCross:
715       return (context_type_without_chain == ContextType::SAME_SITE_LAX ||
716               context_type_without_chain ==
717                   ContextType::SAME_SITE_LAX_METHOD_UNSAFE) &&
718              context_type_with_chain == ContextType::CROSS_SITE;
719   }
720 }
721 
UrlChainToString(const std::vector<GURL> & url_chain)722 std::string UrlChainToString(const std::vector<GURL>& url_chain) {
723   std::string s;
724   for (const GURL& url : url_chain) {
725     base::StrAppend(&s, {" ", url.spec()});
726   }
727   return s;
728 }
729 
730 // Tests for the various ComputeSameSiteContextFor*() functions. The first
731 // boolean test param is whether the results of the computations are evaluated
732 // schemefully. The second boolean param is whether SameSite considers redirect
733 // chains.
734 class CookieUtilComputeSameSiteContextTest
735     : public ::testing::TestWithParam<std::tuple<bool, bool>> {
736  public:
CookieUtilComputeSameSiteContextTest()737   CookieUtilComputeSameSiteContextTest() {
738     if (DoesSameSiteConsiderRedirectChain()) {
739       feature_list_.InitAndEnableFeature(
740           features::kCookieSameSiteConsidersRedirectChain);
741     } else {
742       // No need to explicitly disable the redirect chain feature because it
743       // is disabled by default.
744       feature_list_.Init();
745     }
746   }
747   ~CookieUtilComputeSameSiteContextTest() override = default;
748 
IsSchemeful() const749   bool IsSchemeful() const { return std::get<0>(GetParam()); }
750 
DoesSameSiteConsiderRedirectChain() const751   bool DoesSameSiteConsiderRedirectChain() const {
752     return std::get<1>(GetParam());
753   }
754 
755   // Returns the proper gtest matcher to use for the schemeless/schemeful mode.
ContextTypeIs(ContextType context_type) const756   auto ContextTypeIs(ContextType context_type) const {
757     return ContextTypeIsWithSchemefulMode(context_type, IsSchemeful());
758   }
759 
CrossSiteRedirectMetadataCorrect(HttpMethod method,ContextType context_type_without_chain,ContextType context_type_with_chain,ContextRedirectTypeBug1221316 redirect_type_with_chain) const760   auto CrossSiteRedirectMetadataCorrect(
761       HttpMethod method,
762       ContextType context_type_without_chain,
763       ContextType context_type_with_chain,
764       ContextRedirectTypeBug1221316 redirect_type_with_chain) const {
765     return CrossSiteRedirectMetadataCorrectWithSchemefulMode(
766         method, context_type_without_chain, context_type_with_chain,
767         redirect_type_with_chain, IsSchemeful());
768   }
769 
770   // The following methods return the sets of URLs/SiteForCookies/initiators/URL
771   // chains that are same-site or cross-site with respect to kSiteUrl.
772 
GetAllUrls() const773   std::vector<GURL> GetAllUrls() const {
774     return {kSiteUrl,
775             kSiteUrlWithPath,
776             kSecureSiteUrl,
777             kCrossSiteUrl,
778             kSecureCrossSiteUrl,
779             kSubdomainUrl,
780             kSecureSubdomainUrl,
781             kWsUrl,
782             kWssUrl};
783   }
784 
GetSameSiteUrls() const785   std::vector<GURL> GetSameSiteUrls() const {
786     // Same-site-same-scheme URLs are always same-site. (ws counts as
787     // same-scheme with http.)
788     std::vector<GURL> same_site_urls{kSiteUrl, kSiteUrlWithPath, kSubdomainUrl,
789                                      kWsUrl};
790     // If schemeless, the cross-scheme URLs are also same-site.
791     if (!IsSchemeful()) {
792       same_site_urls.push_back(kSecureSiteUrl);
793       same_site_urls.push_back(kSecureSubdomainUrl);
794       same_site_urls.push_back(kWssUrl);
795     }
796     return same_site_urls;
797   }
798 
GetCrossSiteUrls() const799   std::vector<GURL> GetCrossSiteUrls() const {
800     std::vector<GURL> cross_site_urls;
801     std::vector<GURL> same_site_urls = GetSameSiteUrls();
802     for (const GURL& url : GetAllUrls()) {
803       if (!base::Contains(same_site_urls, url))
804         cross_site_urls.push_back(url);
805     }
806     return cross_site_urls;
807   }
808 
GetAllSitesForCookies() const809   std::vector<SiteForCookies> GetAllSitesForCookies() const {
810     return {kNullSiteForCookies, kSiteForCookies, kSecureSiteForCookies,
811             kCrossSiteForCookies, kSecureCrossSiteForCookies};
812   }
813 
GetSameSiteSitesForCookies() const814   std::vector<SiteForCookies> GetSameSiteSitesForCookies() const {
815     std::vector<SiteForCookies> same_site_sfc = {kSiteForCookies};
816     // If schemeless, the cross-scheme SFC is also same-site.
817     if (!IsSchemeful())
818       same_site_sfc.push_back(kSecureSiteForCookies);
819     return same_site_sfc;
820   }
821 
GetCrossSiteSitesForCookies() const822   std::vector<SiteForCookies> GetCrossSiteSitesForCookies() const {
823     std::vector<SiteForCookies> cross_site_sfc;
824     std::vector<SiteForCookies> same_site_sfc = GetSameSiteSitesForCookies();
825     for (const SiteForCookies& sfc : GetAllSitesForCookies()) {
826       if (!base::Contains(same_site_sfc, sfc.RepresentativeUrl(),
827                           &SiteForCookies::RepresentativeUrl)) {
828         cross_site_sfc.push_back(sfc);
829       }
830     }
831     return cross_site_sfc;
832   }
833 
GetAllInitiators() const834   std::vector<std::optional<url::Origin>> GetAllInitiators() const {
835     return {kBrowserInitiated,   kOpaqueInitiator,
836             kSiteInitiator,      kSecureSiteInitiator,
837             kCrossSiteInitiator, kSecureCrossSiteInitiator,
838             kSubdomainInitiator, kSecureSubdomainInitiator,
839             kUnrelatedInitiator};
840   }
841 
GetSameSiteInitiators() const842   std::vector<std::optional<url::Origin>> GetSameSiteInitiators() const {
843     std::vector<std::optional<url::Origin>> same_site_initiators{
844         kBrowserInitiated, kSiteInitiator, kSubdomainInitiator};
845     // If schemeless, the cross-scheme origins are also same-site.
846     if (!IsSchemeful()) {
847       same_site_initiators.push_back(kSecureSiteInitiator);
848       same_site_initiators.push_back(kSecureSubdomainInitiator);
849     }
850     return same_site_initiators;
851   }
852 
GetCrossSiteInitiators() const853   std::vector<std::optional<url::Origin>> GetCrossSiteInitiators() const {
854     std::vector<std::optional<url::Origin>> cross_site_initiators;
855     std::vector<std::optional<url::Origin>> same_site_initiators =
856         GetSameSiteInitiators();
857     for (const std::optional<url::Origin>& initiator : GetAllInitiators()) {
858       if (!base::Contains(same_site_initiators, initiator))
859         cross_site_initiators.push_back(initiator);
860     }
861     return cross_site_initiators;
862   }
863 
864   // Returns an assortment of redirect chains that end in `url` as the
865   // current request URL, and are completely same-site. `url` is expected to be
866   // same-site to kSiteUrl.
GetSameSiteUrlChains(const GURL & url) const867   std::vector<std::vector<GURL>> GetSameSiteUrlChains(const GURL& url) const {
868     std::vector<std::vector<GURL>> same_site_url_chains;
869     for (const GURL& same_site_url : GetSameSiteUrls()) {
870       same_site_url_chains.push_back({same_site_url, url});
871       for (const GURL& other_same_site_url : GetSameSiteUrls()) {
872         same_site_url_chains.push_back(
873             {other_same_site_url, same_site_url, url});
874       }
875     }
876     return same_site_url_chains;
877   }
878 
879   // Returns an assortment of redirect chains that end in `url` as the
880   // current request URL, and are cross-site. `url` is expected to be same-site
881   // to kSiteUrl.
GetCrossSiteUrlChains(const GURL & url) const882   std::vector<std::vector<GURL>> GetCrossSiteUrlChains(const GURL& url) const {
883     std::vector<std::vector<GURL>> cross_site_url_chains;
884     for (const GURL& cross_site_url : GetCrossSiteUrls()) {
885       cross_site_url_chains.push_back({cross_site_url, url});
886       for (const GURL& same_site_url : GetSameSiteUrls()) {
887         cross_site_url_chains.push_back({cross_site_url, same_site_url, url});
888         cross_site_url_chains.push_back({same_site_url, cross_site_url, url});
889       }
890     }
891     return cross_site_url_chains;
892   }
893 
894   // Computes possible values of is_main_frame_navigation that are consistent
895   // with the DCHECKs.
CanBeMainFrameNavigation(const GURL & url,const SiteForCookies & site_for_cookies) const896   bool CanBeMainFrameNavigation(const GURL& url,
897                                 const SiteForCookies& site_for_cookies) const {
898     return (site_for_cookies.IsNull() ||
899             site_for_cookies.IsFirstPartyWithSchemefulMode(url, true)) &&
900            !url.SchemeIsWSOrWSS();
901   }
902 
IsMainFrameNavigationPossibleValues(const GURL & url,const SiteForCookies & site_for_cookies) const903   std::vector<bool> IsMainFrameNavigationPossibleValues(
904       const GURL& url,
905       const SiteForCookies& site_for_cookies) const {
906     return CanBeMainFrameNavigation(url, site_for_cookies)
907                ? std::vector<bool>{false, true}
908                : std::vector<bool>{false};
909   }
910 
911   // Request URL.
912   const GURL kSiteUrl{"http://example.test/"};
913   const GURL kSiteUrlWithPath{"http://example.test/path"};
914   const GURL kSecureSiteUrl{"https://example.test/"};
915   const GURL kCrossSiteUrl{"http://notexample.test/"};
916   const GURL kSecureCrossSiteUrl{"https://notexample.test/"};
917   const GURL kSubdomainUrl{"http://subdomain.example.test/"};
918   const GURL kSecureSubdomainUrl{"https://subdomain.example.test/"};
919   const GURL kWsUrl{"ws://example.test/"};
920   const GURL kWssUrl{"wss://example.test/"};
921   // Site for cookies.
922   const SiteForCookies kNullSiteForCookies;
923   const SiteForCookies kSiteForCookies = SiteForCookies::FromUrl(kSiteUrl);
924   const SiteForCookies kSecureSiteForCookies =
925       SiteForCookies::FromUrl(kSecureSiteUrl);
926   const SiteForCookies kCrossSiteForCookies =
927       SiteForCookies::FromUrl(kCrossSiteUrl);
928   const SiteForCookies kSecureCrossSiteForCookies =
929       SiteForCookies::FromUrl(kSecureCrossSiteUrl);
930   // Initiator origin.
931   const std::optional<url::Origin> kBrowserInitiated = std::nullopt;
932   const std::optional<url::Origin> kOpaqueInitiator =
933       std::make_optional(url::Origin());
934   const std::optional<url::Origin> kSiteInitiator =
935       std::make_optional(url::Origin::Create(kSiteUrl));
936   const std::optional<url::Origin> kSecureSiteInitiator =
937       std::make_optional(url::Origin::Create(kSecureSiteUrl));
938   const std::optional<url::Origin> kCrossSiteInitiator =
939       std::make_optional(url::Origin::Create(kCrossSiteUrl));
940   const std::optional<url::Origin> kSecureCrossSiteInitiator =
941       std::make_optional(url::Origin::Create(kSecureCrossSiteUrl));
942   const std::optional<url::Origin> kSubdomainInitiator =
943       std::make_optional(url::Origin::Create(kSubdomainUrl));
944   const std::optional<url::Origin> kSecureSubdomainInitiator =
945       std::make_optional(url::Origin::Create(kSecureSubdomainUrl));
946   const std::optional<url::Origin> kUnrelatedInitiator =
947       std::make_optional(url::Origin::Create(GURL("https://unrelated.test/")));
948 
949  protected:
950   base::test::ScopedFeatureList feature_list_;
951 };
952 
TEST_P(CookieUtilComputeSameSiteContextTest,UrlAndSiteForCookiesCrossSite)953 TEST_P(CookieUtilComputeSameSiteContextTest, UrlAndSiteForCookiesCrossSite) {
954   // If the SiteForCookies and URL are cross-site, then the context is always
955   // cross-site.
956   for (const GURL& url : GetSameSiteUrls()) {
957     for (const SiteForCookies& site_for_cookies :
958          GetCrossSiteSitesForCookies()) {
959       for (const std::optional<url::Origin>& initiator : GetAllInitiators()) {
960         for (const std::string& method : {"GET", "POST", "PUT", "HEAD"}) {
961           EXPECT_THAT(cookie_util::ComputeSameSiteContextForScriptGet(
962                           url, site_for_cookies, initiator,
963                           false /* force_ignore_site_for_cookies */),
964                       ContextTypeIs(ContextType::CROSS_SITE));
965           EXPECT_THAT(cookie_util::ComputeSameSiteContextForScriptSet(
966                           url, site_for_cookies,
967                           false /* force_ignore_site_for_cookies */),
968                       ContextTypeIs(ContextType::CROSS_SITE));
969           for (bool is_main_frame_navigation :
970                IsMainFrameNavigationPossibleValues(url, site_for_cookies)) {
971             EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
972                             method, {url}, site_for_cookies, initiator,
973                             is_main_frame_navigation,
974                             false /* force_ignore_site_for_cookies */),
975                         ContextTypeIs(ContextType::CROSS_SITE));
976             EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
977                             {url}, site_for_cookies, initiator,
978                             is_main_frame_navigation,
979                             false /* force_ignore_site_for_cookies */),
980                         ContextTypeIs(ContextType::CROSS_SITE));
981             // If the current request URL is cross-site to the site-for-cookies,
982             // the request context is always cross-site even if the URL chain
983             // contains members that are same-site to the site-for-cookies.
984             EXPECT_THAT(
985                 cookie_util::ComputeSameSiteContextForRequest(
986                     method, {site_for_cookies.RepresentativeUrl(), url},
987                     site_for_cookies, initiator, is_main_frame_navigation,
988                     false /* force_ignore_site_for_cookies */),
989                 ContextTypeIs(ContextType::CROSS_SITE));
990             EXPECT_THAT(
991                 cookie_util::ComputeSameSiteContextForResponse(
992                     {site_for_cookies.RepresentativeUrl(), url},
993                     site_for_cookies, initiator, is_main_frame_navigation,
994                     false /* force_ignore_site_for_cookies */),
995                 ContextTypeIs(ContextType::CROSS_SITE));
996           }
997           EXPECT_THAT(cookie_util::ComputeSameSiteContextForSubresource(
998                           url, site_for_cookies,
999                           false /* force_ignore_site_for_cookies */),
1000                       ContextTypeIs(ContextType::CROSS_SITE));
1001         }
1002       }
1003     }
1004   }
1005 }
1006 
TEST_P(CookieUtilComputeSameSiteContextTest,SiteForCookiesNotSchemefullySame)1007 TEST_P(CookieUtilComputeSameSiteContextTest, SiteForCookiesNotSchemefullySame) {
1008   // If the SiteForCookies is not schemefully_same, even if its value is
1009   // schemefully same-site, the schemeful context type will be cross-site.
1010   if (!IsSchemeful())
1011     return;
1012 
1013   std::vector<SiteForCookies> sites_for_cookies = GetAllSitesForCookies();
1014   for (SiteForCookies& sfc : sites_for_cookies) {
1015     sfc.SetSchemefullySameForTesting(false);
1016   }
1017 
1018   for (const GURL& url : GetSameSiteUrls()) {
1019     for (const SiteForCookies& site_for_cookies : sites_for_cookies) {
1020       for (const std::optional<url::Origin>& initiator : GetAllInitiators()) {
1021         for (const std::string& method : {"GET", "POST", "PUT", "HEAD"}) {
1022           EXPECT_THAT(cookie_util::ComputeSameSiteContextForScriptGet(
1023                           url, site_for_cookies, initiator,
1024                           false /* force_ignore_site_for_cookies */),
1025                       ContextTypeIs(ContextType::CROSS_SITE));
1026           EXPECT_THAT(cookie_util::ComputeSameSiteContextForScriptSet(
1027                           url, site_for_cookies,
1028                           false /* force_ignore_site_for_cookies */),
1029                       ContextTypeIs(ContextType::CROSS_SITE));
1030 
1031           // If the site-for-cookies isn't schemefully_same, this cannot be a
1032           // main frame navigation.
1033           EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
1034                           method, {url}, site_for_cookies, initiator,
1035                           false /* is_main_frame_navigation */,
1036                           false /* force_ignore_site_for_cookies */),
1037                       ContextTypeIs(ContextType::CROSS_SITE));
1038           EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
1039                           {url}, site_for_cookies, initiator,
1040                           false /* is_main_frame_navigation */,
1041                           false /* force_ignore_site_for_cookies */),
1042                       ContextTypeIs(ContextType::CROSS_SITE));
1043 
1044           EXPECT_THAT(cookie_util::ComputeSameSiteContextForSubresource(
1045                           url, site_for_cookies,
1046                           false /* force_ignore_site_for_cookies */),
1047                       ContextTypeIs(ContextType::CROSS_SITE));
1048         }
1049       }
1050     }
1051   }
1052 }
1053 
TEST_P(CookieUtilComputeSameSiteContextTest,ForScriptGet)1054 TEST_P(CookieUtilComputeSameSiteContextTest, ForScriptGet) {
1055   for (const GURL& url : GetSameSiteUrls()) {
1056     // Same-site site-for-cookies.
1057     // (Cross-site cases covered above in UrlAndSiteForCookiesCrossSite test.)
1058     for (const SiteForCookies& site_for_cookies :
1059          GetSameSiteSitesForCookies()) {
1060       // Cross-site initiator -> it's same-site lax.
1061       for (const std::optional<url::Origin>& initiator :
1062            GetCrossSiteInitiators()) {
1063         EXPECT_THAT(cookie_util::ComputeSameSiteContextForScriptGet(
1064                         url, site_for_cookies, initiator,
1065                         false /* force_ignore_site_for_cookies */),
1066                     ContextTypeIs(ContextType::SAME_SITE_LAX));
1067       }
1068 
1069       // Same-site initiator -> it's same-site strict.
1070       for (const std::optional<url::Origin>& initiator :
1071            GetSameSiteInitiators()) {
1072         EXPECT_THAT(cookie_util::ComputeSameSiteContextForScriptGet(
1073                         url, site_for_cookies, initiator,
1074                         false /* force_ignore_site_for_cookies */),
1075                     ContextTypeIs(ContextType::SAME_SITE_STRICT));
1076       }
1077     }
1078   }
1079 }
1080 
TEST_P(CookieUtilComputeSameSiteContextTest,ForScriptGet_SchemefulDowngrade)1081 TEST_P(CookieUtilComputeSameSiteContextTest, ForScriptGet_SchemefulDowngrade) {
1082   // Some test cases where the context is downgraded when computed schemefully.
1083   // (Should already be covered above, but just to be explicit.)
1084   EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_STRICT,
1085                                   ContextType::SAME_SITE_LAX),
1086             cookie_util::ComputeSameSiteContextForScriptGet(
1087                 kSiteUrl, kSiteForCookies, kSecureSiteInitiator,
1088                 false /* force_ignore_site_for_cookies */));
1089   EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_STRICT,
1090                                   ContextType::SAME_SITE_LAX),
1091             cookie_util::ComputeSameSiteContextForScriptGet(
1092                 kSecureSiteUrl, kSecureSiteForCookies, kSiteInitiator,
1093                 false /* force_ignore_site_for_cookies */));
1094   EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_LAX,
1095                                   ContextType::CROSS_SITE),
1096             cookie_util::ComputeSameSiteContextForScriptGet(
1097                 kSecureSiteUrl, kSiteForCookies, kCrossSiteInitiator,
1098                 false /* force_ignore_site_for_cookies */));
1099   EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_LAX,
1100                                   ContextType::CROSS_SITE),
1101             cookie_util::ComputeSameSiteContextForScriptGet(
1102                 kSiteUrl, kSecureSiteForCookies, kCrossSiteInitiator,
1103                 false /* force_ignore_site_for_cookies */));
1104 }
1105 
TEST_P(CookieUtilComputeSameSiteContextTest,ForScriptGet_WebSocketSchemes)1106 TEST_P(CookieUtilComputeSameSiteContextTest, ForScriptGet_WebSocketSchemes) {
1107   // wss/https and http/ws are considered the same for schemeful purposes.
1108   EXPECT_THAT(cookie_util::ComputeSameSiteContextForScriptGet(
1109                   kWssUrl, kSecureSiteForCookies, kSecureSiteInitiator,
1110                   false /* force_ignore_site_for_cookies */),
1111               ContextTypeIs(ContextType::SAME_SITE_STRICT));
1112   EXPECT_THAT(cookie_util::ComputeSameSiteContextForScriptGet(
1113                   kWssUrl, kSecureSiteForCookies, kSecureCrossSiteInitiator,
1114                   false /* force_ignore_site_for_cookies */),
1115               ContextTypeIs(ContextType::SAME_SITE_LAX));
1116 
1117   EXPECT_THAT(cookie_util::ComputeSameSiteContextForScriptGet(
1118                   kWsUrl, kSiteForCookies, kSiteInitiator,
1119                   false /* force_ignore_site_for_cookies */),
1120               ContextTypeIs(ContextType::SAME_SITE_STRICT));
1121   EXPECT_THAT(cookie_util::ComputeSameSiteContextForScriptGet(
1122                   kWsUrl, kSiteForCookies, kCrossSiteInitiator,
1123                   false /* force_ignore_site_for_cookies */),
1124               ContextTypeIs(ContextType::SAME_SITE_LAX));
1125 }
1126 
1127 // Test cases where the URL chain has 1 member (i.e. no redirects).
TEST_P(CookieUtilComputeSameSiteContextTest,ForRequest)1128 TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest) {
1129   for (const GURL& url : GetSameSiteUrls()) {
1130     // Same-site site-for-cookies.
1131     // (Cross-site cases covered above in UrlAndSiteForCookiesCrossSite test.)
1132     for (const SiteForCookies& site_for_cookies :
1133          GetSameSiteSitesForCookies()) {
1134       // Same-Site initiator -> it's same-site strict.
1135       for (const std::optional<url::Origin>& initiator :
1136            GetSameSiteInitiators()) {
1137         for (const std::string& method : {"GET", "POST", "PUT", "HEAD"}) {
1138           for (bool is_main_frame_navigation :
1139                IsMainFrameNavigationPossibleValues(url, site_for_cookies)) {
1140             EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
1141                             method, {url}, site_for_cookies, initiator,
1142                             is_main_frame_navigation,
1143                             false /* force_ignore_site_for_cookies */),
1144                         ContextTypeIs(ContextType::SAME_SITE_STRICT));
1145           }
1146         }
1147       }
1148 
1149       // Cross-Site initiator -> it's same-site lax iff the method is safe.
1150       for (const std::optional<url::Origin>& initiator :
1151            GetCrossSiteInitiators()) {
1152         // For main frame navigations, the context is Lax (or Lax-unsafe).
1153         for (const std::string& method : {"GET", "HEAD"}) {
1154           if (!CanBeMainFrameNavigation(url, site_for_cookies))
1155             break;
1156           EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
1157                           method, {url}, site_for_cookies, initiator,
1158                           true /* is_main_frame_navigation */,
1159                           false /* force_ignore_site_for_cookies */),
1160                       ContextTypeIs(ContextType::SAME_SITE_LAX));
1161         }
1162         for (const std::string& method : {"POST", "PUT"}) {
1163           if (!CanBeMainFrameNavigation(url, site_for_cookies))
1164             break;
1165           EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
1166                           method, {url}, site_for_cookies, initiator,
1167                           true /* is_main_frame_navigation */,
1168                           false /* force_ignore_site_for_cookies */),
1169                       ContextTypeIs(ContextType::SAME_SITE_LAX_METHOD_UNSAFE));
1170         }
1171 
1172         // For non-main-frame-navigation requests, the context should be
1173         // cross-site.
1174         for (const std::string& method : {"GET", "POST", "PUT", "HEAD"}) {
1175           EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
1176                           method, {url}, site_for_cookies, initiator,
1177                           false /* is_main_frame_navigation */,
1178                           false /* force_ignore_site_for_cookies */),
1179                       ContextTypeIs(ContextType::CROSS_SITE));
1180         }
1181       }
1182     }
1183   }
1184 }
1185 
TEST_P(CookieUtilComputeSameSiteContextTest,ForRequest_SchemefulDowngrade)1186 TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_SchemefulDowngrade) {
1187   // Some test cases where the context is downgraded when computed schemefully.
1188   // (Should already be covered above, but just to be explicit.)
1189 
1190   // Cross-scheme URL and site-for-cookies with (schemelessly) same-site
1191   // initiator.
1192   // (The request cannot be a main frame navigation if the site-for-cookies is
1193   // not schemefully same-site).
1194   for (const std::string& method : {"GET", "POST"}) {
1195     EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_STRICT,
1196                                     ContextType::CROSS_SITE),
1197               cookie_util::ComputeSameSiteContextForRequest(
1198                   method, {kSecureSiteUrl}, kSiteForCookies, kSiteInitiator,
1199                   false /* is_main_frame_navigation */,
1200                   false /* force_ignore_site_for_cookies */));
1201     EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_STRICT,
1202                                     ContextType::CROSS_SITE),
1203               cookie_util::ComputeSameSiteContextForRequest(
1204                   method, {kSiteUrl}, kSecureSiteForCookies, kSiteInitiator,
1205                   false /* is_main_frame_navigation */,
1206                   false /* force_ignore_site_for_cookies */));
1207   }
1208 
1209   // Schemefully same-site URL and site-for-cookies with cross-scheme
1210   // initiator.
1211   for (bool is_main_frame_navigation : {false, true}) {
1212     ContextType lax_if_main_frame = is_main_frame_navigation
1213                                         ? ContextType::SAME_SITE_LAX
1214                                         : ContextType::CROSS_SITE;
1215     ContextType lax_unsafe_if_main_frame =
1216         is_main_frame_navigation ? ContextType::SAME_SITE_LAX_METHOD_UNSAFE
1217                                  : ContextType::CROSS_SITE;
1218 
1219     EXPECT_EQ(
1220         SameSiteCookieContext(ContextType::SAME_SITE_STRICT, lax_if_main_frame),
1221         cookie_util::ComputeSameSiteContextForRequest(
1222             "GET", {kSecureSiteUrl}, kSecureSiteForCookies, kSiteInitiator,
1223             is_main_frame_navigation,
1224             false /* force_ignore_site_for_cookies */));
1225     EXPECT_EQ(
1226         SameSiteCookieContext(ContextType::SAME_SITE_STRICT, lax_if_main_frame),
1227         cookie_util::ComputeSameSiteContextForRequest(
1228             "GET", {kSiteUrl}, kSiteForCookies, kSecureSiteInitiator,
1229             is_main_frame_navigation,
1230             false /* force_ignore_site_for_cookies */));
1231     EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_STRICT,
1232                                     lax_unsafe_if_main_frame),
1233               cookie_util::ComputeSameSiteContextForRequest(
1234                   "POST", {kSecureSiteUrl}, kSecureSiteForCookies,
1235                   kSiteInitiator, is_main_frame_navigation,
1236                   false /* force_ignore_site_for_cookies */));
1237     EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_STRICT,
1238                                     lax_unsafe_if_main_frame),
1239               cookie_util::ComputeSameSiteContextForRequest(
1240                   "POST", {kSiteUrl}, kSiteForCookies, kSecureSiteInitiator,
1241                   is_main_frame_navigation,
1242                   false /* force_ignore_site_for_cookies */));
1243   }
1244 
1245   // Cross-scheme URL and site-for-cookies with cross-site initiator.
1246   // (The request cannot be a main frame navigation if the site-for-cookies is
1247   // not schemefully same-site).
1248   EXPECT_EQ(SameSiteCookieContext(ContextType::CROSS_SITE),
1249             cookie_util::ComputeSameSiteContextForRequest(
1250                 "GET", {kSiteUrl}, kSecureSiteForCookies, kCrossSiteInitiator,
1251                 false /* is_main_frame_navigation */,
1252                 false /* force_ignore_site_for_cookies */));
1253   EXPECT_EQ(SameSiteCookieContext(ContextType::CROSS_SITE),
1254             cookie_util::ComputeSameSiteContextForRequest(
1255                 "GET", {kSecureSiteUrl}, kSiteForCookies, kCrossSiteInitiator,
1256                 false /* is_main_frame_navigation */,
1257                 false /* force_ignore_site_for_cookies */));
1258   EXPECT_EQ(SameSiteCookieContext(ContextType::CROSS_SITE),
1259             cookie_util::ComputeSameSiteContextForRequest(
1260                 "POST", {kSiteUrl}, kSecureSiteForCookies, kCrossSiteInitiator,
1261                 false /* is_main_frame_navigation */,
1262                 false /* force_ignore_site_for_cookies */));
1263   EXPECT_EQ(SameSiteCookieContext(ContextType::CROSS_SITE),
1264             cookie_util::ComputeSameSiteContextForRequest(
1265                 "POST", {kSecureSiteUrl}, kSiteForCookies, kCrossSiteInitiator,
1266                 false /* is_main_frame_navigation */,
1267                 false /* force_ignore_site_for_cookies */));
1268 }
1269 
TEST_P(CookieUtilComputeSameSiteContextTest,ForRequest_WebSocketSchemes)1270 TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_WebSocketSchemes) {
1271   // wss/https and http/ws are considered the same for schemeful purposes.
1272   // (ws/wss requests cannot be main frame navigations.)
1273   EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
1274                   "GET", {kWssUrl}, kSecureSiteForCookies, kSecureSiteInitiator,
1275                   false /* is_main_frame_navigation */,
1276                   false /* force_ignore_site_for_cookies */),
1277               ContextTypeIs(ContextType::SAME_SITE_STRICT));
1278   EXPECT_THAT(
1279       cookie_util::ComputeSameSiteContextForRequest(
1280           "GET", {kWssUrl}, kSecureSiteForCookies, kSecureCrossSiteInitiator,
1281           false /* is_main_frame_navigation */,
1282           false /* force_ignore_site_for_cookies */),
1283       ContextTypeIs(ContextType::CROSS_SITE));
1284 
1285   EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
1286                   "GET", {kWsUrl}, kSiteForCookies, kSiteInitiator,
1287                   false /* is_main_frame_navigation */,
1288                   false /* force_ignore_site_for_cookies */),
1289               ContextTypeIs(ContextType::SAME_SITE_STRICT));
1290   EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
1291                   "GET", {kWsUrl}, kSiteForCookies, kCrossSiteInitiator,
1292                   false /* is_main_frame_navigation */,
1293                   false /* force_ignore_site_for_cookies */),
1294               ContextTypeIs(ContextType::CROSS_SITE));
1295 }
1296 
1297 // Test cases where the URL chain contains multiple members, where the last
1298 // member (current request URL) is same-site to kSiteUrl. (Everything is listed
1299 // as same-site or cross-site relative to kSiteUrl.)
TEST_P(CookieUtilComputeSameSiteContextTest,ForRequest_Redirect)1300 TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_Redirect) {
1301   struct {
1302     std::string method;
1303     bool url_chain_is_same_site;
1304     bool site_for_cookies_is_same_site;
1305     bool initiator_is_same_site;
1306     // These are the expected context types considering redirect chains:
1307     ContextType expected_context_type;  // for non-main-frame-nav requests.
1308     ContextType expected_context_type_for_main_frame_navigation;
1309     // These are the expected context types not considering redirect chains:
1310     ContextType expected_context_type_without_chain;
1311     ContextType expected_context_type_for_main_frame_navigation_without_chain;
1312     // The expected redirect type (only applicable for chains):
1313     ContextRedirectTypeBug1221316 expected_redirect_type_with_chain;
1314   } kTestCases[] = {
1315       // If the url chain is same-site, then the result is the same with or
1316       // without considering the redirect chain.
1317       {"GET", true, true, true, ContextType::SAME_SITE_STRICT,
1318        ContextType::SAME_SITE_STRICT, ContextType::SAME_SITE_STRICT,
1319        ContextType::SAME_SITE_STRICT,
1320        ContextRedirectTypeBug1221316::kAllSameSiteRedirect},
1321       {"GET", true, true, false, ContextType::CROSS_SITE,
1322        ContextType::SAME_SITE_LAX, ContextType::CROSS_SITE,
1323        ContextType::SAME_SITE_LAX,
1324        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1325       {"GET", true, false, true, ContextType::CROSS_SITE,
1326        ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1327        ContextType::CROSS_SITE,
1328        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1329       {"GET", true, false, false, ContextType::CROSS_SITE,
1330        ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1331        ContextType::CROSS_SITE,
1332        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1333       // If the url chain is cross-site, then the result will differ depending
1334       // on whether the redirect chain is considered, when the site-for-cookies
1335       // and initiator are both same-site.
1336       {"GET", false, true, true, ContextType::CROSS_SITE,
1337        ContextType::SAME_SITE_LAX, ContextType::SAME_SITE_STRICT,
1338        ContextType::SAME_SITE_STRICT,
1339        ContextRedirectTypeBug1221316::kPartialSameSiteRedirect},
1340       {"GET", false, true, false, ContextType::CROSS_SITE,
1341        ContextType::SAME_SITE_LAX, ContextType::CROSS_SITE,
1342        ContextType::SAME_SITE_LAX,
1343        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1344       {"GET", false, false, true, ContextType::CROSS_SITE,
1345        ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1346        ContextType::CROSS_SITE,
1347        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1348       {"GET", false, false, false, ContextType::CROSS_SITE,
1349        ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1350        ContextType::CROSS_SITE,
1351        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1352       // If the url chain is same-site, then the result is the same with or
1353       // without considering the redirect chain.
1354       {"POST", true, true, true, ContextType::SAME_SITE_STRICT,
1355        ContextType::SAME_SITE_STRICT, ContextType::SAME_SITE_STRICT,
1356        ContextType::SAME_SITE_STRICT,
1357        ContextRedirectTypeBug1221316::kAllSameSiteRedirect},
1358       {"POST", true, true, false, ContextType::CROSS_SITE,
1359        ContextType::SAME_SITE_LAX_METHOD_UNSAFE, ContextType::CROSS_SITE,
1360        ContextType::SAME_SITE_LAX_METHOD_UNSAFE,
1361        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1362       {"POST", true, false, true, ContextType::CROSS_SITE,
1363        ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1364        ContextType::CROSS_SITE,
1365        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1366       {"POST", true, false, false, ContextType::CROSS_SITE,
1367        ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1368        ContextType::CROSS_SITE,
1369        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1370       // If the url chain is cross-site, then the result will differ depending
1371       // on whether the redirect chain is considered, when the site-for-cookies
1372       // and initiator are both same-site.
1373       {"POST", false, true, true, ContextType::CROSS_SITE,
1374        ContextType::SAME_SITE_LAX_METHOD_UNSAFE, ContextType::SAME_SITE_STRICT,
1375        ContextType::SAME_SITE_STRICT,
1376        ContextRedirectTypeBug1221316::kPartialSameSiteRedirect},
1377       {"POST", false, true, false, ContextType::CROSS_SITE,
1378        ContextType::SAME_SITE_LAX_METHOD_UNSAFE, ContextType::CROSS_SITE,
1379        ContextType::SAME_SITE_LAX_METHOD_UNSAFE,
1380        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1381       {"POST", false, false, true, ContextType::CROSS_SITE,
1382        ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1383        ContextType::CROSS_SITE,
1384        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1385       {"POST", false, false, false, ContextType::CROSS_SITE,
1386        ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1387        ContextType::CROSS_SITE,
1388        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1389   };
1390 
1391   for (const auto& test_case : kTestCases) {
1392     std::vector<std::vector<GURL>> url_chains =
1393         test_case.url_chain_is_same_site ? GetSameSiteUrlChains(kSiteUrl)
1394                                          : GetCrossSiteUrlChains(kSiteUrl);
1395     std::vector<SiteForCookies> sites_for_cookies =
1396         test_case.site_for_cookies_is_same_site ? GetSameSiteSitesForCookies()
1397                                                 : GetCrossSiteSitesForCookies();
1398     std::vector<std::optional<url::Origin>> initiators =
1399         test_case.initiator_is_same_site ? GetSameSiteInitiators()
1400                                          : GetCrossSiteInitiators();
1401     ContextType expected_context_type =
1402         DoesSameSiteConsiderRedirectChain()
1403             ? test_case.expected_context_type
1404             : test_case.expected_context_type_without_chain;
1405     ContextType expected_context_type_for_main_frame_navigation =
1406         DoesSameSiteConsiderRedirectChain()
1407             ? test_case.expected_context_type_for_main_frame_navigation
1408             : test_case
1409                   .expected_context_type_for_main_frame_navigation_without_chain;
1410     for (const std::vector<GURL>& url_chain : url_chains) {
1411       for (const SiteForCookies& site_for_cookies : sites_for_cookies) {
1412         for (const std::optional<url::Origin>& initiator : initiators) {
1413           EXPECT_THAT(
1414               cookie_util::ComputeSameSiteContextForRequest(
1415                   test_case.method, url_chain, site_for_cookies, initiator,
1416                   false /* is_main_frame_navigation */,
1417                   false /* force_ignore_site_for_cookies */),
1418               AllOf(ContextTypeIs(expected_context_type),
1419                     CrossSiteRedirectMetadataCorrect(
1420                         cookie_util::HttpMethodStringToEnum(test_case.method),
1421                         test_case.expected_context_type_without_chain,
1422                         test_case.expected_context_type,
1423                         test_case.expected_redirect_type_with_chain)))
1424               << UrlChainToString(url_chain) << " "
1425               << site_for_cookies.ToDebugString() << " "
1426               << (initiator ? initiator->Serialize() : "nullopt");
1427           if (!CanBeMainFrameNavigation(url_chain.back(), site_for_cookies))
1428             continue;
1429           EXPECT_THAT(
1430               cookie_util::ComputeSameSiteContextForRequest(
1431                   test_case.method, url_chain, site_for_cookies, initiator,
1432                   true /* is_main_frame_navigation */,
1433                   false /* force_ignore_site_for_cookies */),
1434               AllOf(
1435                   ContextTypeIs(
1436                       expected_context_type_for_main_frame_navigation),
1437                   CrossSiteRedirectMetadataCorrect(
1438                       cookie_util::HttpMethodStringToEnum(test_case.method),
1439                       test_case
1440                           .expected_context_type_for_main_frame_navigation_without_chain,
1441                       test_case.expected_context_type_for_main_frame_navigation,
1442                       test_case.expected_redirect_type_with_chain)))
1443               << UrlChainToString(url_chain) << " "
1444               << site_for_cookies.ToDebugString() << " "
1445               << (initiator ? initiator->Serialize() : "nullopt");
1446         }
1447       }
1448     }
1449   }
1450 }
1451 
TEST_P(CookieUtilComputeSameSiteContextTest,ForScriptSet)1452 TEST_P(CookieUtilComputeSameSiteContextTest, ForScriptSet) {
1453   for (const GURL& url : GetSameSiteUrls()) {
1454     for (const SiteForCookies& site_for_cookies :
1455          GetSameSiteSitesForCookies()) {
1456       // Same-site site-for-cookies -> it's same-site lax.
1457       // (Cross-site cases covered above in UrlAndSiteForCookiesCrossSite test.)
1458       EXPECT_THAT(
1459           cookie_util::ComputeSameSiteContextForScriptSet(
1460               url, site_for_cookies, false /* force_ignore_site_for_cookies */),
1461           ContextTypeIs(ContextType::SAME_SITE_LAX));
1462     }
1463   }
1464 }
1465 
TEST_P(CookieUtilComputeSameSiteContextTest,ForScriptSet_SchemefulDowngrade)1466 TEST_P(CookieUtilComputeSameSiteContextTest, ForScriptSet_SchemefulDowngrade) {
1467   // Some test cases where the context is downgraded when computed schemefully.
1468   // (Should already be covered above, but just to be explicit.)
1469   EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_LAX,
1470                                   ContextType::CROSS_SITE),
1471             cookie_util::ComputeSameSiteContextForScriptSet(
1472                 kSiteUrl, kSecureSiteForCookies,
1473                 false /* force_ignore_site_for_cookies */));
1474   EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_LAX,
1475                                   ContextType::CROSS_SITE),
1476             cookie_util::ComputeSameSiteContextForScriptSet(
1477                 kSecureSiteUrl, kSiteForCookies,
1478                 false /* force_ignore_site_for_cookies */));
1479 }
1480 
TEST_P(CookieUtilComputeSameSiteContextTest,ForScriptSet_WebSocketSchemes)1481 TEST_P(CookieUtilComputeSameSiteContextTest, ForScriptSet_WebSocketSchemes) {
1482   // wss/https and http/ws are considered the same for schemeful purposes.
1483   EXPECT_THAT(cookie_util::ComputeSameSiteContextForScriptSet(
1484                   kWssUrl, kSecureSiteForCookies,
1485                   false /* force_ignore_site_for_cookies */),
1486               ContextTypeIs(ContextType::SAME_SITE_LAX));
1487   EXPECT_THAT(
1488       cookie_util::ComputeSameSiteContextForScriptSet(
1489           kWsUrl, kSiteForCookies, false /* force_ignore_site_for_cookies */),
1490       ContextTypeIs(ContextType::SAME_SITE_LAX));
1491 }
1492 
1493 // Test cases where the URL chain has 1 member (i.e. no redirects).
TEST_P(CookieUtilComputeSameSiteContextTest,ForResponse)1494 TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse) {
1495   for (const GURL& url : GetSameSiteUrls()) {
1496     // Same-site site-for-cookies.
1497     // (Cross-site cases covered above in UrlAndSiteForCookiesCrossSite test.)
1498     for (const SiteForCookies& site_for_cookies :
1499          GetSameSiteSitesForCookies()) {
1500       // For main frame navigations, setting all SameSite cookies is allowed
1501       // regardless of initiator.
1502       for (const std::optional<url::Origin>& initiator : GetAllInitiators()) {
1503         if (!CanBeMainFrameNavigation(url, site_for_cookies))
1504           break;
1505         EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
1506                         {url}, site_for_cookies, initiator,
1507                         true /* is_main_frame_navigation */,
1508                         false /* force_ignore_site_for_cookies */),
1509                     ContextTypeIs(ContextType::SAME_SITE_LAX));
1510       }
1511 
1512       // For non-main-frame-navigation requests, the context should be lax iff
1513       // the initiator is same-site, and cross-site otherwise.
1514       for (const std::optional<url::Origin>& initiator :
1515            GetSameSiteInitiators()) {
1516         EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
1517                         {url}, site_for_cookies, initiator,
1518                         false /* is_main_frame_navigation */,
1519                         false /* force_ignore_site_for_cookies */),
1520                     ContextTypeIs(ContextType::SAME_SITE_LAX));
1521       }
1522       for (const std::optional<url::Origin>& initiator :
1523            GetCrossSiteInitiators()) {
1524         EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
1525                         {url}, site_for_cookies, initiator,
1526                         false /* is_main_frame_navigation */,
1527                         false /* force_ignore_site_for_cookies */),
1528                     ContextTypeIs(ContextType::CROSS_SITE));
1529       }
1530     }
1531   }
1532 }
1533 
TEST_P(CookieUtilComputeSameSiteContextTest,ForResponse_SchemefulDowngrade)1534 TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_SchemefulDowngrade) {
1535   // Some test cases where the context is downgraded when computed schemefully.
1536   // (Should already be covered above, but just to be explicit.)
1537 
1538   // URL and site-for-cookies are cross-scheme.
1539   // (If the URL and site-for-cookies are not schemefully same-site, this cannot
1540   // be a main frame navigation.)
1541   // With same-site initiator:
1542   EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_LAX,
1543                                   ContextType::CROSS_SITE),
1544             cookie_util::ComputeSameSiteContextForResponse(
1545                 {kSiteUrl}, kSecureSiteForCookies, kSiteInitiator,
1546                 false /* is_main_frame_navigation */,
1547                 false /* force_ignore_site_for_cookies */));
1548   EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_LAX,
1549                                   ContextType::CROSS_SITE),
1550             cookie_util::ComputeSameSiteContextForResponse(
1551                 {kSecureSiteUrl}, kSiteForCookies, kSecureSiteInitiator,
1552                 false /* is_main_frame_navigation */,
1553                 false /* force_ignore_site_for_cookies */));
1554   // With cross-site initiator:
1555   EXPECT_EQ(SameSiteCookieContext(ContextType::CROSS_SITE),
1556             cookie_util::ComputeSameSiteContextForResponse(
1557                 {kSiteUrl}, kSecureSiteForCookies, kCrossSiteInitiator,
1558                 false /* is_main_frame_navigation */,
1559                 false /* force_ignore_site_for_cookies */));
1560   EXPECT_EQ(SameSiteCookieContext(ContextType::CROSS_SITE),
1561             cookie_util::ComputeSameSiteContextForResponse(
1562                 {kSecureSiteUrl}, kSiteForCookies, kCrossSiteInitiator,
1563                 false /* is_main_frame_navigation */,
1564                 false /* force_ignore_site_for_cookies */));
1565 
1566   // Schemefully same-site URL and site-for-cookies with cross-scheme
1567   // initiator.
1568   for (bool is_main_frame_navigation : {false, true}) {
1569     ContextType lax_if_main_frame = is_main_frame_navigation
1570                                         ? ContextType::SAME_SITE_LAX
1571                                         : ContextType::CROSS_SITE;
1572     EXPECT_EQ(
1573         SameSiteCookieContext(ContextType::SAME_SITE_LAX, lax_if_main_frame),
1574         cookie_util::ComputeSameSiteContextForResponse(
1575             {kSiteUrl}, kSiteForCookies, kSecureSiteInitiator,
1576             is_main_frame_navigation,
1577             false /* force_ignore_site_for_cookies */));
1578     EXPECT_EQ(
1579         SameSiteCookieContext(ContextType::SAME_SITE_LAX, lax_if_main_frame),
1580         cookie_util::ComputeSameSiteContextForResponse(
1581             {kSecureSiteUrl}, kSecureSiteForCookies, kSiteInitiator,
1582             is_main_frame_navigation,
1583             false /* force_ignore_site_for_cookies */));
1584   }
1585 }
1586 
TEST_P(CookieUtilComputeSameSiteContextTest,ForResponse_WebSocketSchemes)1587 TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_WebSocketSchemes) {
1588   // wss/https and http/ws are considered the same for schemeful purposes.
1589   // (ws/wss requests cannot be main frame navigations.)
1590 
1591   // Same-site initiators.
1592   for (const std::optional<url::Origin>& initiator : GetSameSiteInitiators()) {
1593     EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
1594                     {kWsUrl}, kSiteForCookies, initiator,
1595                     false /* is_main_frame_navigation */,
1596                     false /* force_ignore_site_for_cookies */),
1597                 ContextTypeIs(ContextType::SAME_SITE_LAX));
1598   }
1599   // Cross-site initiators.
1600   for (const std::optional<url::Origin>& initiator : GetCrossSiteInitiators()) {
1601     EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
1602                     {kWsUrl}, kSiteForCookies, initiator,
1603                     false /* is_main_frame_navigation */,
1604                     false /* force_ignore_site_for_cookies */),
1605                 ContextTypeIs(ContextType::CROSS_SITE));
1606   }
1607 }
1608 
1609 // Test cases where the URL chain contains multiple members, where the last
1610 // member (current request URL) is same-site to kSiteUrl. (Everything is listed
1611 // as same-site or cross-site relative to kSiteUrl.)
TEST_P(CookieUtilComputeSameSiteContextTest,ForResponse_Redirect)1612 TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_Redirect) {
1613   struct {
1614     bool url_chain_is_same_site;
1615     bool site_for_cookies_is_same_site;
1616     bool initiator_is_same_site;
1617     // These are the expected context types considering redirect chains:
1618     ContextType expected_context_type;  // for non-main-frame-nav requests.
1619     ContextType expected_context_type_for_main_frame_navigation;
1620     // These are the expected context types not considering redirect chains:
1621     ContextType expected_context_type_without_chain;
1622     ContextType expected_context_type_for_main_frame_navigation_without_chain;
1623     // The expected redirect type (only applicable for chains):
1624     ContextRedirectTypeBug1221316 expected_redirect_type_with_chain;
1625   } kTestCases[] = {
1626       // If the url chain is same-site, then the result is the same with or
1627       // without considering the redirect chain.
1628       {true, true, true, ContextType::SAME_SITE_LAX, ContextType::SAME_SITE_LAX,
1629        ContextType::SAME_SITE_LAX, ContextType::SAME_SITE_LAX,
1630        ContextRedirectTypeBug1221316::kAllSameSiteRedirect},
1631       {true, true, false, ContextType::CROSS_SITE, ContextType::SAME_SITE_LAX,
1632        ContextType::CROSS_SITE, ContextType::SAME_SITE_LAX,
1633        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1634       {true, false, true, ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1635        ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1636        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1637       {true, false, false, ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1638        ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1639        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1640       // If the url chain is cross-site, then the result will differ depending
1641       // on whether the redirect chain is considered, when the site-for-cookies
1642       // and initiator are both same-site.
1643       {false, true, true, ContextType::CROSS_SITE, ContextType::SAME_SITE_LAX,
1644        ContextType::SAME_SITE_LAX, ContextType::SAME_SITE_LAX,
1645        ContextRedirectTypeBug1221316::kPartialSameSiteRedirect},
1646       {false, true, false, ContextType::CROSS_SITE, ContextType::SAME_SITE_LAX,
1647        ContextType::CROSS_SITE, ContextType::SAME_SITE_LAX,
1648        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1649       {false, false, true, ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1650        ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1651        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1652       {false, false, false, ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1653        ContextType::CROSS_SITE, ContextType::CROSS_SITE,
1654        ContextRedirectTypeBug1221316::kCrossSiteRedirect},
1655   };
1656   for (const auto& test_case : kTestCases) {
1657     std::vector<std::vector<GURL>> url_chains =
1658         test_case.url_chain_is_same_site ? GetSameSiteUrlChains(kSiteUrl)
1659                                          : GetCrossSiteUrlChains(kSiteUrl);
1660     std::vector<SiteForCookies> sites_for_cookies =
1661         test_case.site_for_cookies_is_same_site ? GetSameSiteSitesForCookies()
1662                                                 : GetCrossSiteSitesForCookies();
1663     std::vector<std::optional<url::Origin>> initiators =
1664         test_case.initiator_is_same_site ? GetSameSiteInitiators()
1665                                          : GetCrossSiteInitiators();
1666     ContextType expected_context_type =
1667         DoesSameSiteConsiderRedirectChain()
1668             ? test_case.expected_context_type
1669             : test_case.expected_context_type_without_chain;
1670     ContextType expected_context_type_for_main_frame_navigation =
1671         DoesSameSiteConsiderRedirectChain()
1672             ? test_case.expected_context_type_for_main_frame_navigation
1673             : test_case
1674                   .expected_context_type_for_main_frame_navigation_without_chain;
1675     for (const std::vector<GURL>& url_chain : url_chains) {
1676       for (const SiteForCookies& site_for_cookies : sites_for_cookies) {
1677         for (const std::optional<url::Origin>& initiator : initiators) {
1678           EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
1679                           url_chain, site_for_cookies, initiator,
1680                           false /* is_main_frame_navigation */,
1681                           false /* force_ignore_site_for_cookies */),
1682                       AllOf(ContextTypeIs(expected_context_type),
1683                             // The 'method' field is kept empty because it's
1684                             // only used to check http_method_bug_1221316 which
1685                             // is always empty for responses.
1686                             CrossSiteRedirectMetadataCorrect(
1687                                 HttpMethod::kUnset,
1688                                 test_case.expected_context_type_without_chain,
1689                                 test_case.expected_context_type,
1690                                 test_case.expected_redirect_type_with_chain)))
1691               << UrlChainToString(url_chain) << " "
1692               << site_for_cookies.ToDebugString() << " "
1693               << (initiator ? initiator->Serialize() : "nullopt");
1694           if (!CanBeMainFrameNavigation(url_chain.back(), site_for_cookies))
1695             continue;
1696           EXPECT_THAT(
1697               cookie_util::ComputeSameSiteContextForResponse(
1698                   url_chain, site_for_cookies, initiator,
1699                   true /* is_main_frame_navigation */,
1700                   false /* force_ignore_site_for_cookies */),
1701               AllOf(
1702                   ContextTypeIs(
1703                       expected_context_type_for_main_frame_navigation),
1704                   CrossSiteRedirectMetadataCorrect(
1705                       HttpMethod::kUnset,
1706                       test_case
1707                           .expected_context_type_for_main_frame_navigation_without_chain,
1708                       test_case.expected_context_type_for_main_frame_navigation,
1709                       test_case.expected_redirect_type_with_chain)))
1710               << UrlChainToString(url_chain) << " "
1711               << site_for_cookies.ToDebugString() << " "
1712               << (initiator ? initiator->Serialize() : "nullopt");
1713         }
1714       }
1715     }
1716   }
1717 }
1718 
TEST_P(CookieUtilComputeSameSiteContextTest,ForSubresource)1719 TEST_P(CookieUtilComputeSameSiteContextTest, ForSubresource) {
1720   for (const GURL& url : GetSameSiteUrls()) {
1721     // Same-site site-for-cookies.
1722     // (Cross-site cases covered above in UrlAndSiteForCookiesCrossSite test.)
1723     for (const SiteForCookies& site_for_cookies :
1724          GetSameSiteSitesForCookies()) {
1725       EXPECT_THAT(
1726           cookie_util::ComputeSameSiteContextForSubresource(
1727               url, site_for_cookies, false /* force_ignore_site_for_cookies */),
1728           ContextTypeIs(ContextType::SAME_SITE_STRICT));
1729     }
1730   }
1731 }
1732 
TEST_P(CookieUtilComputeSameSiteContextTest,ForSubresource_SchemefulDowngrade)1733 TEST_P(CookieUtilComputeSameSiteContextTest,
1734        ForSubresource_SchemefulDowngrade) {
1735   // Some test cases where the context is downgraded when computed schemefully.
1736   // (Should already be covered above, but just to be explicit.)
1737   EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_STRICT,
1738                                   ContextType::CROSS_SITE),
1739             cookie_util::ComputeSameSiteContextForSubresource(
1740                 kSiteUrl, kSecureSiteForCookies,
1741                 false /* force_ignore_site_for_cookies */));
1742   EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_STRICT,
1743                                   ContextType::CROSS_SITE),
1744             cookie_util::ComputeSameSiteContextForSubresource(
1745                 kSecureSiteUrl, kSiteForCookies,
1746                 false /* force_ignore_site_for_cookies */));
1747 }
1748 
TEST_P(CookieUtilComputeSameSiteContextTest,ForSubresource_WebSocketSchemes)1749 TEST_P(CookieUtilComputeSameSiteContextTest, ForSubresource_WebSocketSchemes) {
1750   // wss/https and http/ws are considered the same for schemeful purposes.
1751   EXPECT_THAT(cookie_util::ComputeSameSiteContextForSubresource(
1752                   kWssUrl, kSecureSiteForCookies,
1753                   false /* force_ignore_site_for_cookies */),
1754               ContextTypeIs(ContextType::SAME_SITE_STRICT));
1755   EXPECT_THAT(
1756       cookie_util::ComputeSameSiteContextForSubresource(
1757           kWsUrl, kSiteForCookies, false /* force_ignore_site_for_cookies */),
1758       ContextTypeIs(ContextType::SAME_SITE_STRICT));
1759 }
1760 
TEST_P(CookieUtilComputeSameSiteContextTest,ForceIgnoreSiteForCookies)1761 TEST_P(CookieUtilComputeSameSiteContextTest, ForceIgnoreSiteForCookies) {
1762   // force_ignore_site_for_cookies overrides all checks and returns same-site
1763   // (STRICT for get or LAX for set).
1764   for (const GURL& url : GetAllUrls()) {
1765     for (const SiteForCookies& site_for_cookies : GetAllSitesForCookies()) {
1766       for (const std::optional<url::Origin>& initiator : GetAllInitiators()) {
1767         for (const std::string& method : {"GET", "POST", "PUT", "HEAD"}) {
1768           EXPECT_THAT(cookie_util::ComputeSameSiteContextForScriptGet(
1769                           url, site_for_cookies, initiator,
1770                           true /* force_ignore_site_for_cookies */),
1771                       ContextTypeIs(ContextType::SAME_SITE_STRICT));
1772           EXPECT_THAT(cookie_util::ComputeSameSiteContextForScriptSet(
1773                           url, site_for_cookies,
1774                           true /* force_ignore_site_for_cookies */),
1775                       ContextTypeIs(ContextType::SAME_SITE_LAX));
1776           for (bool is_main_frame_navigation :
1777                IsMainFrameNavigationPossibleValues(url, site_for_cookies)) {
1778             EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
1779                             method, {url}, site_for_cookies, initiator,
1780                             is_main_frame_navigation,
1781                             true /* force_ignore_site_for_cookies */),
1782                         ContextTypeIs(ContextType::SAME_SITE_STRICT));
1783             EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
1784                             {url}, site_for_cookies, initiator,
1785                             is_main_frame_navigation,
1786                             true /* force_ignore_site_for_cookies */),
1787                         ContextTypeIs(ContextType::SAME_SITE_LAX));
1788             EXPECT_THAT(
1789                 cookie_util::ComputeSameSiteContextForRequest(
1790                     method, {site_for_cookies.RepresentativeUrl(), url},
1791                     site_for_cookies, initiator, is_main_frame_navigation,
1792                     true /* force_ignore_site_for_cookies */),
1793                 ContextTypeIs(ContextType::SAME_SITE_STRICT));
1794             EXPECT_THAT(
1795                 cookie_util::ComputeSameSiteContextForResponse(
1796                     {site_for_cookies.RepresentativeUrl(), url},
1797                     site_for_cookies, initiator, is_main_frame_navigation,
1798                     true /* force_ignore_site_for_cookies */),
1799                 ContextTypeIs(ContextType::SAME_SITE_LAX));
1800           }
1801           EXPECT_THAT(cookie_util::ComputeSameSiteContextForSubresource(
1802                           url, site_for_cookies,
1803                           true /* force_ignore_site_for_cookies */),
1804                       ContextTypeIs(ContextType::SAME_SITE_STRICT));
1805         }
1806       }
1807     }
1808   }
1809 }
1810 
1811 INSTANTIATE_TEST_SUITE_P(/* no label */,
1812                          CookieUtilComputeSameSiteContextTest,
1813                          ::testing::Combine(::testing::Bool(),
1814                                             ::testing::Bool()));
1815 
TEST(CookieUtilTest,IsCookieAccessResultInclude)1816 TEST(CookieUtilTest, IsCookieAccessResultInclude) {
1817   EXPECT_FALSE(cookie_util::IsCookieAccessResultInclude(
1818       CookieAccessResult(CookieInclusionStatus::MakeFromReasonsForTesting(
1819           /*exclusions=*/{CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR}))));
1820 
1821   EXPECT_TRUE(cookie_util::IsCookieAccessResultInclude(CookieAccessResult()));
1822 }
1823 
1824 }  // namespace
1825 
1826 }  // namespace net
1827