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