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