1 // Copyright 2019 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/site_for_cookies.h"
6 
7 #include <string>
8 #include <vector>
9 
10 #include "base/strings/strcat.h"
11 #include "base/test/scoped_feature_list.h"
12 #include "net/base/features.h"
13 #include "net/base/url_util.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "url/gurl.h"
16 #include "url/origin.h"
17 #include "url/url_util.h"
18 
19 namespace net {
20 namespace {
21 
22 class SchemelessSiteForCookiesTest : public ::testing::Test {
23  public:
SchemelessSiteForCookiesTest()24   SchemelessSiteForCookiesTest() {
25     scope_feature_list_.InitAndDisableFeature(features::kSchemefulSameSite);
26   }
27 
28  protected:
29   base::test::ScopedFeatureList scope_feature_list_;
30 };
31 
NormalizedScheme(const GURL & url)32 std::string NormalizedScheme(const GURL& url) {
33   return url.SchemeIsWSOrWSS() ? ChangeWebSocketSchemeToHttpScheme(url).scheme()
34                                : url.scheme();
35 }
36 
37 // Tests that all URLs from |equivalent| produce SiteForCookies that match
38 // URLs in the set and are equivalent to each other, and are distinct and
39 // don't match |distinct|.
TestEquivalentAndDistinct(const std::vector<GURL> & equivalent,const std::vector<GURL> & distinct,const std::string & expect_host)40 void TestEquivalentAndDistinct(const std::vector<GURL>& equivalent,
41                                const std::vector<GURL>& distinct,
42                                const std::string& expect_host) {
43   for (const GURL& equiv_url_a : equivalent) {
44     SiteForCookies equiv_a = SiteForCookies::FromUrl(equiv_url_a);
45     EXPECT_EQ(NormalizedScheme(equiv_url_a), equiv_a.scheme());
46 
47     EXPECT_EQ(equiv_a.RepresentativeUrl().spec(),
48               base::StrCat({equiv_a.scheme(), "://", expect_host, "/"}));
49 
50     for (const GURL& equiv_url_b : equivalent) {
51       SiteForCookies equiv_b = SiteForCookies::FromUrl(equiv_url_a);
52 
53       EXPECT_TRUE(equiv_a.IsEquivalent(equiv_b));
54       EXPECT_TRUE(equiv_b.IsEquivalent(equiv_a));
55       EXPECT_TRUE(equiv_a.IsFirstParty(equiv_url_a));
56       EXPECT_TRUE(equiv_a.IsFirstParty(equiv_url_b));
57       EXPECT_TRUE(equiv_b.IsFirstParty(equiv_url_a));
58       EXPECT_TRUE(equiv_b.IsFirstParty(equiv_url_b));
59     }
60 
61     for (const GURL& other_url : distinct) {
62       SiteForCookies other = SiteForCookies::FromUrl(other_url);
63       EXPECT_EQ(NormalizedScheme(other_url), other.scheme());
64       EXPECT_EQ(other.RepresentativeUrl().spec(),
65                 base::StrCat({other.scheme(), "://", other_url.host(), "/"}));
66 
67       EXPECT_FALSE(equiv_a.IsEquivalent(other));
68       EXPECT_FALSE(other.IsEquivalent(equiv_a));
69       EXPECT_FALSE(equiv_a.IsFirstParty(other_url))
70           << equiv_a.ToDebugString() << " " << other_url.spec();
71       EXPECT_FALSE(other.IsFirstParty(equiv_url_a));
72 
73       EXPECT_TRUE(other.IsFirstParty(other_url));
74     }
75   }
76 }
77 
TEST(SiteForCookiesTest,Default)78 TEST(SiteForCookiesTest, Default) {
79   SiteForCookies should_match_none;
80   EXPECT_FALSE(should_match_none.IsFirstParty(GURL("http://example.com")));
81   EXPECT_FALSE(should_match_none.IsFirstParty(GURL("file:///home/me/.bashrc")));
82   EXPECT_FALSE(should_match_none.IsFirstParty(GURL::EmptyGURL()));
83 
84   // Before SiteForCookies existed, empty URL would represent match-none
85   EXPECT_TRUE(should_match_none.IsEquivalent(
86       SiteForCookies::FromUrl(GURL::EmptyGURL())));
87   EXPECT_TRUE(should_match_none.RepresentativeUrl().is_empty());
88   EXPECT_TRUE(should_match_none.IsEquivalent(
89       SiteForCookies::FromOrigin(url::Origin())));
90 
91   EXPECT_TRUE(should_match_none.site().opaque());
92   EXPECT_EQ("", should_match_none.scheme());
93   EXPECT_EQ("SiteForCookies: {site=null; schemefully_same=false}",
94             should_match_none.ToDebugString());
95 }
96 
TEST_F(SchemelessSiteForCookiesTest,Basic)97 TEST_F(SchemelessSiteForCookiesTest, Basic) {
98   std::vector<GURL> equivalent = {
99       GURL("https://example.com"),
100       GURL("http://sub1.example.com:42/something"),
101       GURL("ws://sub2.example.com/something"),
102       // This one is disputable.
103       GURL("file://example.com/helo"),
104   };
105 
106   std::vector<GURL> distinct = {GURL("https://example.org"),
107                                 GURL("http://com/i_am_a_tld")};
108 
109   TestEquivalentAndDistinct(equivalent, distinct, "example.com");
110 }
111 
112 // Similar to SchemelessSiteForCookiesTest_Basic with a focus on testing secure
113 // SFCs.
TEST(SiteForCookiesTest,BasicSecure)114 TEST(SiteForCookiesTest, BasicSecure) {
115   std::vector<GURL> equivalent = {GURL("https://example.com"),
116                                   GURL("wss://example.com"),
117                                   GURL("https://sub1.example.com:42/something"),
118                                   GURL("wss://sub2.example.com/something")};
119 
120   std::vector<GURL> distinct = {
121       GURL("http://example.com"),      GURL("https://example.org"),
122       GURL("ws://example.com"),        GURL("https://com/i_am_a_tld"),
123       GURL("file://example.com/helo"),
124   };
125 
126   TestEquivalentAndDistinct(equivalent, distinct, "example.com");
127 }
128 
129 // Similar to SchemelessSiteForCookiesTest_Basic with a focus on testing
130 // insecure SFCs.
TEST(SiteForCookiesTest,BasicInsecure)131 TEST(SiteForCookiesTest, BasicInsecure) {
132   std::vector<GURL> equivalent = {GURL("http://example.com"),
133                                   GURL("ws://example.com"),
134                                   GURL("http://sub1.example.com:42/something"),
135                                   GURL("ws://sub2.example.com/something")};
136 
137   std::vector<GURL> distinct = {
138       GURL("https://example.com"),     GURL("http://example.org"),
139       GURL("wss://example.com"),       GURL("http://com/i_am_a_tld"),
140       GURL("file://example.com/helo"),
141   };
142 
143   TestEquivalentAndDistinct(equivalent, distinct, "example.com");
144 }
145 
TEST(SiteForCookiesTest,File)146 TEST(SiteForCookiesTest, File) {
147   std::vector<GURL> equivalent = {GURL("file:///a/b/c"),
148                                   GURL("file:///etc/shaaadow")};
149 
150   std::vector<GURL> distinct = {GURL("file://nonlocal/file.txt")};
151 
152   TestEquivalentAndDistinct(equivalent, distinct, "");
153 }
154 
TEST_F(SchemelessSiteForCookiesTest,Extension)155 TEST_F(SchemelessSiteForCookiesTest, Extension) {
156   url::ScopedSchemeRegistryForTests scoped_registry;
157   url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST);
158   std::vector<GURL> equivalent = {GURL("chrome-extension://abc/"),
159                                   GURL("chrome-extension://abc/foo.txt"),
160                                   GURL("https://abc"), GURL("http://abc"),
161                                   // This one is disputable.
162                                   GURL("file://abc/bar.txt")};
163 
164   std::vector<GURL> distinct = {GURL("chrome-extension://def")};
165 
166   TestEquivalentAndDistinct(equivalent, distinct, "abc");
167 }
168 
169 // Similar to SchemelessSiteForCookiesTest_Extension with a focus on ensuring
170 // that http(s) schemes are distinct.
TEST(SiteForCookiesTest,Extension)171 TEST(SiteForCookiesTest, Extension) {
172   url::ScopedSchemeRegistryForTests scoped_registry;
173   url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST);
174   std::vector<GURL> equivalent = {
175       GURL("chrome-extension://abc/"),
176       GURL("chrome-extension://abc/foo.txt"),
177   };
178 
179   std::vector<GURL> distinct = {GURL("chrome-extension://def"),
180                                 GURL("https://abc"), GURL("http://abc"),
181                                 GURL("file://abc/bar.txt")};
182 
183   TestEquivalentAndDistinct(equivalent, distinct, "abc");
184 }
185 
TEST(SiteForCookiesTest,NonStandard)186 TEST(SiteForCookiesTest, NonStandard) {
187   // If we don't register the scheme, nothing matches, even identical ones
188   std::vector<GURL> equivalent;
189   std::vector<GURL> distinct = {GURL("non-standard://abc"),
190                                 GURL("non-standard://abc"),
191                                 GURL("non-standard://def")};
192 
193   // Last parameter is "" since GURL doesn't put the hostname in if
194   // the URL is non-standard.
195   TestEquivalentAndDistinct(equivalent, distinct, "");
196 }
197 
TEST_F(SchemelessSiteForCookiesTest,Blob)198 TEST_F(SchemelessSiteForCookiesTest, Blob) {
199   // This case isn't really well-specified and is inconsistent between
200   // different user agents; the behavior chosen here was to be more
201   // consistent between url and origin handling.
202   //
203   // Thanks file API spec for the sample blob URL.
204   SiteForCookies from_blob = SiteForCookies::FromUrl(
205       GURL("blob:https://example.org/9115d58c-bcda-ff47-86e5-083e9a2153041"));
206 
207   EXPECT_TRUE(from_blob.IsFirstParty(GURL("http://sub.example.org/resource")));
208   EXPECT_EQ("https", from_blob.scheme());
209   EXPECT_EQ("SiteForCookies: {site=https://example.org; schemefully_same=true}",
210             from_blob.ToDebugString());
211   EXPECT_EQ("https://example.org/", from_blob.RepresentativeUrl().spec());
212   EXPECT_TRUE(from_blob.IsEquivalent(
213       SiteForCookies::FromUrl(GURL("http://www.example.org:631"))));
214 }
215 
216 // Similar to SchemelessSiteForCookiesTest_Blob with a focus on a secure blob.
TEST(SiteForCookiesTest,SecureBlob)217 TEST(SiteForCookiesTest, SecureBlob) {
218   SiteForCookies from_blob = SiteForCookies::FromUrl(
219       GURL("blob:https://example.org/9115d58c-bcda-ff47-86e5-083e9a2153041"));
220 
221   EXPECT_TRUE(from_blob.IsFirstParty(GURL("https://sub.example.org/resource")));
222   EXPECT_FALSE(from_blob.IsFirstParty(GURL("http://sub.example.org/resource")));
223   EXPECT_EQ("https", from_blob.scheme());
224   EXPECT_EQ("SiteForCookies: {site=https://example.org; schemefully_same=true}",
225             from_blob.ToDebugString());
226   EXPECT_EQ("https://example.org/", from_blob.RepresentativeUrl().spec());
227   EXPECT_TRUE(from_blob.IsEquivalent(
228       SiteForCookies::FromUrl(GURL("https://www.example.org:631"))));
229   EXPECT_FALSE(from_blob.IsEquivalent(
230       SiteForCookies::FromUrl(GURL("http://www.example.org:631"))));
231 }
232 
233 // Similar to SchemelessSiteForCookiesTest_Blob with a focus on an insecure
234 // blob.
TEST(SiteForCookiesTest,InsecureBlob)235 TEST(SiteForCookiesTest, InsecureBlob) {
236   SiteForCookies from_blob = SiteForCookies::FromUrl(
237       GURL("blob:http://example.org/9115d58c-bcda-ff47-86e5-083e9a2153041"));
238 
239   EXPECT_TRUE(from_blob.IsFirstParty(GURL("http://sub.example.org/resource")));
240   EXPECT_FALSE(
241       from_blob.IsFirstParty(GURL("https://sub.example.org/resource")));
242   EXPECT_EQ("http", from_blob.scheme());
243   EXPECT_EQ("SiteForCookies: {site=http://example.org; schemefully_same=true}",
244             from_blob.ToDebugString());
245   EXPECT_EQ("http://example.org/", from_blob.RepresentativeUrl().spec());
246   EXPECT_TRUE(from_blob.IsEquivalent(
247       SiteForCookies::FromUrl(GURL("http://www.example.org:631"))));
248   EXPECT_FALSE(from_blob.IsEquivalent(
249       SiteForCookies::FromUrl(GURL("https://www.example.org:631"))));
250 }
251 
TEST_F(SchemelessSiteForCookiesTest,Wire)252 TEST_F(SchemelessSiteForCookiesTest, Wire) {
253   SiteForCookies out;
254 
255   // Empty one.
256   EXPECT_TRUE(SiteForCookies::FromWire(SchemefulSite(), false, &out));
257   EXPECT_TRUE(out.IsNull());
258 
259   EXPECT_TRUE(SiteForCookies::FromWire(SchemefulSite(), true, &out));
260   EXPECT_TRUE(out.IsNull());
261 
262   // Not a valid site. (Scheme should have been converted to https.)
263   EXPECT_FALSE(SiteForCookies::FromWire(
264       SchemefulSite(GURL("wss://host.example.test")), false, &out));
265   EXPECT_TRUE(out.IsNull());
266 
267   // Not a valid scheme. (Same result as opaque SchemefulSite.)
268   EXPECT_TRUE(SiteForCookies::FromWire(SchemefulSite(GURL("aH://example.test")),
269                                        false, &out));
270   EXPECT_TRUE(out.IsNull());
271 
272   // Not a eTLD + 1 (or something hosty), but this is fine. (Is converted to a
273   // registrable domain by SchemefulSite constructor.)
274   EXPECT_TRUE(SiteForCookies::FromWire(
275       SchemefulSite(GURL("http://sub.example.test")), false, &out));
276   EXPECT_FALSE(out.IsNull());
277   EXPECT_EQ(
278       "SiteForCookies: {site=http://example.test; schemefully_same=false}",
279       out.ToDebugString());
280 
281   // IP address is fine.
282   EXPECT_TRUE(SiteForCookies::FromWire(SchemefulSite(GURL("https://127.0.0.1")),
283                                        true, &out));
284   EXPECT_FALSE(out.IsNull());
285   EXPECT_EQ("SiteForCookies: {site=https://127.0.0.1; schemefully_same=true}",
286             out.ToDebugString());
287 
288   EXPECT_TRUE(SiteForCookies::FromWire(SchemefulSite(GURL("https://127.0.0.1")),
289                                        false, &out));
290   EXPECT_FALSE(out.IsNull());
291   EXPECT_EQ("SiteForCookies: {site=https://127.0.0.1; schemefully_same=false}",
292             out.ToDebugString());
293 
294   // An actual eTLD+1 is fine.
295   EXPECT_TRUE(SiteForCookies::FromWire(
296       SchemefulSite(GURL("http://example.test")), true, &out));
297   EXPECT_FALSE(out.IsNull());
298   EXPECT_EQ("SiteForCookies: {site=http://example.test; schemefully_same=true}",
299             out.ToDebugString());
300 }
301 
302 // Similar to SchemelessSiteForCookiesTest_Wire except that schemefully_same has
303 // an effect (makes IsNull() return true if schemefully_same is false).
TEST(SiteForCookiesTest,Wire)304 TEST(SiteForCookiesTest, Wire) {
305   SiteForCookies out;
306 
307   // Empty one.
308   EXPECT_TRUE(SiteForCookies::FromWire(SchemefulSite(), false, &out));
309   EXPECT_TRUE(out.IsNull());
310 
311   EXPECT_TRUE(SiteForCookies::FromWire(SchemefulSite(), true, &out));
312   EXPECT_TRUE(out.IsNull());
313 
314   // Not a valid site. (Scheme should have been converted to https.)
315   EXPECT_FALSE(SiteForCookies::FromWire(
316       SchemefulSite(GURL("wss://host.example.test")), false, &out));
317   EXPECT_TRUE(out.IsNull());
318 
319   // Not a valid scheme. (Same result as opaque SchemefulSite.)
320   EXPECT_TRUE(SiteForCookies::FromWire(SchemefulSite(GURL("aH://example.test")),
321                                        false, &out));
322   EXPECT_TRUE(out.IsNull());
323 
324   // Not a eTLD + 1 (or something hosty), but this is fine. (Is converted to a
325   // registrable domain by SchemefulSite constructor.)
326   EXPECT_TRUE(SiteForCookies::FromWire(
327       SchemefulSite(GURL("http://sub.example.test")), false, &out));
328   EXPECT_TRUE(out.IsNull());
329   EXPECT_EQ(
330       "SiteForCookies: {site=http://example.test; schemefully_same=false}",
331       out.ToDebugString());
332 
333   // IP address is fine.
334   EXPECT_TRUE(SiteForCookies::FromWire(SchemefulSite(GURL("https://127.0.0.1")),
335                                        true, &out));
336   EXPECT_FALSE(out.IsNull());
337   EXPECT_EQ("SiteForCookies: {site=https://127.0.0.1; schemefully_same=true}",
338             out.ToDebugString());
339 
340   // This one's schemefully_same is false
341   EXPECT_TRUE(SiteForCookies::FromWire(SchemefulSite(GURL("https://127.0.0.1")),
342                                        false, &out));
343   EXPECT_TRUE(out.IsNull());
344   EXPECT_EQ("SiteForCookies: {site=https://127.0.0.1; schemefully_same=false}",
345             out.ToDebugString());
346 
347   // An actual eTLD+1 is fine.
348   EXPECT_TRUE(SiteForCookies::FromWire(
349       SchemefulSite(GURL("http://example.test")), true, &out));
350   EXPECT_FALSE(out.IsNull());
351   EXPECT_EQ("SiteForCookies: {site=http://example.test; schemefully_same=true}",
352             out.ToDebugString());
353 
354   // This one's schemefully_same is false.
355   EXPECT_TRUE(SiteForCookies::FromWire(
356       SchemefulSite(GURL("http://example.test")), false, &out));
357   EXPECT_TRUE(out.IsNull());
358   EXPECT_EQ(
359       "SiteForCookies: {site=http://example.test; schemefully_same=false}",
360       out.ToDebugString());
361 }
362 
TEST(SiteForCookiesTest,SchemefulSite)363 TEST(SiteForCookiesTest, SchemefulSite) {
364   const char* kTestCases[] = {"opaque.com",
365                               "http://a.com",
366                               "https://sub1.example.com:42/something",
367                               "https://a.com",
368                               "ws://a.com",
369                               "wss://a.com",
370                               "file://a.com",
371                               "file://folder1/folder2/file.txt",
372                               "file:///file.txt"};
373 
374   for (std::string url : kTestCases) {
375     url::Origin origin = url::Origin::Create(GURL(url));
376     SiteForCookies from_origin = SiteForCookies::FromOrigin(origin);
377     SchemefulSite schemeful_site = SchemefulSite(origin);
378     SiteForCookies from_schemeful_site = SiteForCookies(schemeful_site);
379 
380     EXPECT_TRUE(from_origin.IsEquivalent(from_schemeful_site));
381     EXPECT_TRUE(from_schemeful_site.IsEquivalent(from_origin));
382   }
383 }
384 
TEST(SiteForCookiesTest,CompareWithFrameTreeSiteAndRevise)385 TEST(SiteForCookiesTest, CompareWithFrameTreeSiteAndRevise) {
386   SchemefulSite secure_example = SchemefulSite(GURL("https://example.com"));
387   SchemefulSite insecure_example = SchemefulSite(GURL("http://example.com"));
388   SchemefulSite secure_other = SchemefulSite(GURL("https://other.com"));
389   SchemefulSite insecure_other = SchemefulSite(GURL("http://other.com"));
390 
391   // Other scheme tests.
392   url::ScopedSchemeRegistryForTests scoped_registry;
393   AddStandardScheme("other", url::SCHEME_WITH_HOST);
394   SchemefulSite file_scheme =
395       SchemefulSite(GURL("file:///C:/Users/Default/Pictures/photo.png"));
396   SchemefulSite file_scheme2 = SchemefulSite(GURL("file:///C:/file.txt"));
397   SchemefulSite other_scheme = SchemefulSite(GURL("other://"));
398 
399   // This function should work the same regardless the state of Schemeful
400   // Same-Site.
401   for (const bool toggle : {false, true}) {
402     base::test::ScopedFeatureList scope_feature_list;
403     scope_feature_list.InitWithFeatureState(features::kSchemefulSameSite,
404                                             toggle);
405 
406     SiteForCookies candidate1 = SiteForCookies(secure_example);
407     EXPECT_TRUE(candidate1.CompareWithFrameTreeSiteAndRevise(secure_example));
408     EXPECT_FALSE(candidate1.site().opaque());
409     EXPECT_TRUE(candidate1.schemefully_same());
410 
411     SiteForCookies candidate2 = SiteForCookies(secure_example);
412     EXPECT_TRUE(candidate2.CompareWithFrameTreeSiteAndRevise(insecure_example));
413     EXPECT_FALSE(candidate2.site().opaque());
414     EXPECT_FALSE(candidate2.schemefully_same());
415 
416     SiteForCookies candidate3 = SiteForCookies(secure_example);
417     EXPECT_FALSE(candidate3.CompareWithFrameTreeSiteAndRevise(secure_other));
418     EXPECT_TRUE(candidate3.site().opaque());
419     // schemefully_same is N/A if the site() is opaque.
420 
421     SiteForCookies candidate4 = SiteForCookies(secure_example);
422     EXPECT_FALSE(candidate4.CompareWithFrameTreeSiteAndRevise(insecure_other));
423     EXPECT_TRUE(candidate4.site().opaque());
424     // schemefully_same is N/A if the site() is opaque.
425 
426     // This function's check is bi-directional, so try reversed pairs just in
427     // case.
428     SiteForCookies candidate2_reversed = SiteForCookies(insecure_example);
429     EXPECT_TRUE(
430         candidate2_reversed.CompareWithFrameTreeSiteAndRevise(secure_example));
431     EXPECT_FALSE(candidate2_reversed.site().opaque());
432     EXPECT_FALSE(candidate2_reversed.schemefully_same());
433 
434     SiteForCookies candidate3_reversed = SiteForCookies(secure_other);
435     EXPECT_FALSE(
436         candidate3_reversed.CompareWithFrameTreeSiteAndRevise(secure_example));
437     EXPECT_TRUE(candidate3_reversed.site().opaque());
438     // schemefully_same is N/A if the site() is opaque.
439 
440     SiteForCookies candidate4_reversed = SiteForCookies(insecure_other);
441     EXPECT_FALSE(
442         candidate4_reversed.CompareWithFrameTreeSiteAndRevise(secure_example));
443     EXPECT_TRUE(candidate4_reversed.site().opaque());
444     // schemefully_same is N/A if the site() is opaque.
445 
446     // Now try some different schemes.
447     SiteForCookies candidate5 = SiteForCookies(file_scheme);
448     EXPECT_TRUE(candidate5.CompareWithFrameTreeSiteAndRevise(file_scheme2));
449     EXPECT_FALSE(candidate5.site().opaque());
450     EXPECT_TRUE(candidate5.schemefully_same());
451 
452     SiteForCookies candidate6 = SiteForCookies(file_scheme);
453     EXPECT_FALSE(candidate6.CompareWithFrameTreeSiteAndRevise(other_scheme));
454     EXPECT_TRUE(candidate6.site().opaque());
455     // schemefully_same is N/A if the site() is opaque.
456 
457     SiteForCookies candidate5_reversed = SiteForCookies(file_scheme2);
458     EXPECT_TRUE(
459         candidate5_reversed.CompareWithFrameTreeSiteAndRevise(file_scheme));
460     EXPECT_FALSE(candidate5_reversed.site().opaque());
461     EXPECT_TRUE(candidate5_reversed.schemefully_same());
462 
463     SiteForCookies candidate6_reversed = SiteForCookies(other_scheme);
464     EXPECT_FALSE(
465         candidate6_reversed.CompareWithFrameTreeSiteAndRevise(file_scheme));
466     EXPECT_TRUE(candidate6_reversed.site().opaque());
467     // schemefully_same is N/A if the site() is opaque.
468   }
469 }
470 
TEST(SiteForCookiesTest,CompareWithFrameTreeSiteAndReviseOpaque)471 TEST(SiteForCookiesTest, CompareWithFrameTreeSiteAndReviseOpaque) {
472   url::Origin opaque1 = url::Origin();
473   url::Origin opaque2 = url::Origin();
474 
475   SchemefulSite opaque_site1 = SchemefulSite(opaque1);
476   SchemefulSite opaque_site2 = SchemefulSite(opaque2);
477   SchemefulSite example = SchemefulSite(GURL("https://example.com"));
478 
479   // Opaque origins are able to match on the frame comparison.
480   SiteForCookies candidate1 = SiteForCookies(opaque_site1);
481   EXPECT_TRUE(candidate1.CompareWithFrameTreeSiteAndRevise(opaque_site1));
482   EXPECT_TRUE(candidate1.site().opaque());
483   // schemefully_same is N/A if the site() is opaque.
484   EXPECT_EQ(candidate1.site(), opaque_site1);
485 
486   SiteForCookies candidate2 = SiteForCookies(opaque_site1);
487   EXPECT_TRUE(candidate2.CompareWithFrameTreeSiteAndRevise(opaque_site2));
488   EXPECT_TRUE(candidate2.site().opaque());
489   // schemefully_same is N/A if the site() is opaque.
490   EXPECT_EQ(candidate2.site(), opaque_site1);
491 
492   // But if only one is opaque they won't match.
493   SiteForCookies candidate3 = SiteForCookies(example);
494   EXPECT_FALSE(candidate3.CompareWithFrameTreeSiteAndRevise(opaque_site1));
495   EXPECT_TRUE(candidate3.site().opaque());
496   // schemefully_same is N/A if the site() is opaque.
497   EXPECT_NE(candidate3.site(), opaque_site1);
498 
499   SiteForCookies candidate4 = SiteForCookies(opaque_site1);
500   EXPECT_FALSE(candidate4.CompareWithFrameTreeSiteAndRevise(example));
501   EXPECT_TRUE(candidate4.site().opaque());
502   // schemefully_same is N/A if the site() is opaque.
503   EXPECT_EQ(candidate4.site(), opaque_site1);
504 }
505 
TEST(SiteForCookiesTest,NotSchemefullySameEquivalent)506 TEST(SiteForCookiesTest, NotSchemefullySameEquivalent) {
507   SiteForCookies first =
508       SiteForCookies::FromUrl(GURL("https://www.example.com"));
509   SiteForCookies second =
510       SiteForCookies::FromUrl(GURL("https://www.example.com"));
511   // Smoke check that two SFCs should match when they're the same.
512   EXPECT_TRUE(first.IsEquivalent(second));
513   EXPECT_TRUE(second.IsEquivalent(first));
514 
515   // Two SFC should not be equivalent to each other when one of their
516   // schemefully_same_ flags is false, even if they're otherwise the same, when
517   // Schemeful Same-Site is enabled.
518   second.SetSchemefullySameForTesting(false);
519   EXPECT_FALSE(first.IsEquivalent(second));
520   EXPECT_FALSE(second.IsEquivalent(first));
521 
522   // However, they should match if both their schemefully_same_ flags are false.
523   // Because they're both considered null at that point.
524   first.SetSchemefullySameForTesting(false);
525   EXPECT_TRUE(first.IsEquivalent(second));
526   EXPECT_TRUE(second.IsEquivalent(first));
527 }
528 
529 }  // namespace
530 
TEST(SiteForCookiesTest,SameScheme)531 TEST(SiteForCookiesTest, SameScheme) {
532   struct TestCase {
533     const char* first;
534     const char* second;
535     bool expected_value;
536   };
537 
538   const TestCase kTestCases[] = {
539       {"http://a.com", "http://a.com", true},
540       {"https://a.com", "https://a.com", true},
541       {"ws://a.com", "ws://a.com", true},
542       {"wss://a.com", "wss://a.com", true},
543       {"https://a.com", "wss://a.com", true},
544       {"wss://a.com", "https://a.com", true},
545       {"http://a.com", "ws://a.com", true},
546       {"ws://a.com", "http://a.com", true},
547       {"file://a.com", "file://a.com", true},
548       {"file://folder1/folder2/file.txt", "file://folder1/folder2/file.txt",
549        true},
550       {"ftp://a.com", "ftp://a.com", true},
551       {"http://a.com", "file://a.com", false},
552       {"ws://a.com", "wss://a.com", false},
553       {"wss://a.com", "ws://a.com", false},
554       {"https://a.com", "http://a.com", false},
555       {"file://a.com", "https://a.com", false},
556       {"https://a.com", "file://a.com", false},
557       {"file://a.com", "ftp://a.com", false},
558       {"ftp://a.com", "file://a.com", false},
559   };
560 
561   for (const TestCase& t : kTestCases) {
562     SiteForCookies first = SiteForCookies::FromUrl(GURL(t.first));
563     SchemefulSite second(GURL(t.second));
564     EXPECT_FALSE(first.IsNull());
565     first.MarkIfCrossScheme(second);
566     EXPECT_EQ(first.schemefully_same(), t.expected_value);
567   }
568 }
569 
TEST(SiteForCookiesTest,SameSchemeOpaque)570 TEST(SiteForCookiesTest, SameSchemeOpaque) {
571   url::Origin not_opaque_secure =
572       url::Origin::Create(GURL("https://site.example"));
573   url::Origin not_opaque_nonsecure =
574       url::Origin::Create(GURL("http://site.example"));
575   // Check an opaque origin made from a triple origin and one from the default
576   // constructor.
577   const url::Origin kOpaqueOrigins[] = {
578       not_opaque_secure.DeriveNewOpaqueOrigin(),
579       not_opaque_nonsecure.DeriveNewOpaqueOrigin(), url::Origin()};
580 
581   for (const url::Origin& origin : kOpaqueOrigins) {
582     SiteForCookies secure_sfc = SiteForCookies::FromOrigin(not_opaque_secure);
583     EXPECT_FALSE(secure_sfc.IsNull());
584     SiteForCookies nonsecure_sfc =
585         SiteForCookies::FromOrigin(not_opaque_nonsecure);
586     EXPECT_FALSE(nonsecure_sfc.IsNull());
587 
588     SchemefulSite site(origin);
589 
590     EXPECT_TRUE(secure_sfc.schemefully_same());
591     secure_sfc.MarkIfCrossScheme(site);
592     EXPECT_FALSE(secure_sfc.schemefully_same());
593 
594     EXPECT_TRUE(nonsecure_sfc.schemefully_same());
595     nonsecure_sfc.MarkIfCrossScheme(site);
596     EXPECT_FALSE(nonsecure_sfc.schemefully_same());
597 
598     SiteForCookies opaque_sfc = SiteForCookies(site);
599     EXPECT_TRUE(opaque_sfc.IsNull());
600     // Slightly implementation detail specific as the value isn't relevant for
601     // null SFCs.
602     EXPECT_FALSE(nonsecure_sfc.schemefully_same());
603   }
604 }
605 
606 // Quick correctness check that the less-than operator works as expected.
TEST(SiteForCookiesTest,LessThan)607 TEST(SiteForCookiesTest, LessThan) {
608   SiteForCookies first = SiteForCookies::FromUrl(GURL("https://example.com"));
609   SiteForCookies second =
610       SiteForCookies::FromUrl(GURL("https://examplelonger.com"));
611   SiteForCookies third =
612       SiteForCookies::FromUrl(GURL("https://examplelongerstill.com"));
613 
614   SiteForCookies null1 = SiteForCookies();
615   SiteForCookies null2 =
616       SiteForCookies::FromUrl(GURL("https://examplelongerstillstill.com"));
617   null2.SetSchemefullySameForTesting(false);
618 
619   EXPECT_LT(first, second);
620   EXPECT_LT(second, third);
621   EXPECT_LT(first, third);
622   EXPECT_LT(null1, first);
623   EXPECT_LT(null2, first);
624 
625   EXPECT_FALSE(second < first);
626   EXPECT_FALSE(first < null1);
627   EXPECT_FALSE(first < null2);
628   EXPECT_FALSE(null1 < null2);
629   EXPECT_FALSE(null2 < null1);
630 }
631 
632 }  // namespace net
633