xref: /aosp_15_r20/external/cronet/net/base/schemeful_site_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 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/base/schemeful_site.h"
6 
7 #include "base/test/metrics/histogram_tester.h"
8 #include "net/base/url_util.h"
9 #include "testing/gmock/include/gmock/gmock-matchers.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "url/gurl.h"
12 #include "url/origin.h"
13 #include "url/url_util.h"
14 
15 namespace net {
16 
TEST(SchemefulSiteTest,DifferentOriginSameRegisterableDomain)17 TEST(SchemefulSiteTest, DifferentOriginSameRegisterableDomain) {
18   // List of origins which should all share a schemeful site.
19   url::Origin kTestOrigins[] = {
20       url::Origin::Create(GURL("http://a.foo.test")),
21       url::Origin::Create(GURL("http://b.foo.test")),
22       url::Origin::Create(GURL("http://foo.test")),
23       url::Origin::Create(GURL("http://a.b.foo.test"))};
24 
25   for (const auto& origin_a : kTestOrigins) {
26     for (const auto& origin_b : kTestOrigins) {
27       EXPECT_EQ(SchemefulSite(origin_a), SchemefulSite(origin_b));
28     }
29   }
30 }
31 
TEST(SchemefulSiteTest,Operators)32 TEST(SchemefulSiteTest, Operators) {
33   // Create a list of origins that should all have different schemeful sites.
34   // These are in ascending order.
35   url::Origin kTestOrigins[] = {
36       url::Origin::Create(GURL("data:text/html,<body>Hello World</body>")),
37       url::Origin::Create(GURL("file://foo")),
38       url::Origin::Create(GURL("http://a.bar.test")),
39       url::Origin::Create(GURL("http://c.test")),
40       url::Origin::Create(GURL("http://d.test")),
41       url::Origin::Create(GURL("http://a.foo.test")),
42       url::Origin::Create(GURL("https://a.bar.test")),
43       url::Origin::Create(GURL("https://c.test")),
44       url::Origin::Create(GURL("https://d.test")),
45       url::Origin::Create(GURL("https://a.foo.test"))};
46 
47   // Compare each origin to every other origin and ensure the operators work as
48   // expected.
49   for (size_t first = 0; first < std::size(kTestOrigins); ++first) {
50     SchemefulSite site1 = SchemefulSite(kTestOrigins[first]);
51     SCOPED_TRACE(site1.GetDebugString());
52 
53     EXPECT_EQ(site1, site1);
54     EXPECT_FALSE(site1 < site1);
55 
56     // Check the operators work on copies.
57     SchemefulSite site1_copy = site1;
58     EXPECT_EQ(site1, site1_copy);
59     EXPECT_FALSE(site1 < site1_copy);
60 
61     for (size_t second = first + 1; second < std::size(kTestOrigins);
62          ++second) {
63       SchemefulSite site2 = SchemefulSite(kTestOrigins[second]);
64       SCOPED_TRACE(site2.GetDebugString());
65 
66       EXPECT_TRUE(site1 < site2);
67       EXPECT_FALSE(site2 < site1);
68       EXPECT_FALSE(site1 == site2);
69       EXPECT_FALSE(site2 == site1);
70     }
71   }
72 }
73 
TEST(SchemefulSiteTest,SchemeUsed)74 TEST(SchemefulSiteTest, SchemeUsed) {
75   url::Origin origin_a = url::Origin::Create(GURL("https://foo.test"));
76   url::Origin origin_b = url::Origin::Create(GURL("http://foo.test"));
77   EXPECT_NE(SchemefulSite(origin_a), SchemefulSite(origin_b));
78 }
79 
TEST(SchemefulSiteTest,PortIgnored)80 TEST(SchemefulSiteTest, PortIgnored) {
81   // Both origins are non-opaque.
82   url::Origin origin_a = url::Origin::Create(GURL("https://foo.test:80"));
83   url::Origin origin_b = url::Origin::Create(GURL("https://foo.test:2395"));
84 
85   EXPECT_EQ(SchemefulSite(origin_a), SchemefulSite(origin_b));
86 }
87 
TEST(SchemefulSiteTest,TopLevelDomainsNotModified)88 TEST(SchemefulSiteTest, TopLevelDomainsNotModified) {
89   url::Origin origin_tld = url::Origin::Create(GURL("https://com"));
90   EXPECT_EQ(url::Origin::Create(GURL("https://com")),
91             SchemefulSite(origin_tld).GetInternalOriginForTesting());
92 
93   // Unknown TLD's should not be modified.
94   url::Origin origin_tld_unknown =
95       url::Origin::Create(GURL("https://bar:1234"));
96   EXPECT_EQ(url::Origin::Create(GURL("https://bar")),
97             SchemefulSite(origin_tld_unknown).GetInternalOriginForTesting());
98 
99   // Check for two-part TLDs.
100   url::Origin origin_two_part_tld = url::Origin::Create(GURL("http://a.co.uk"));
101   EXPECT_EQ(url::Origin::Create(GURL("http://a.co.uk")),
102             SchemefulSite(origin_two_part_tld).GetInternalOriginForTesting());
103 }
104 
TEST(SchemefulSiteTest,NonStandardScheme)105 TEST(SchemefulSiteTest, NonStandardScheme) {
106   url::ScopedSchemeRegistryForTests scoped_registry;
107   url::AddStandardScheme("foo", url::SCHEME_WITH_HOST);
108   url::Origin origin = url::Origin::Create(GURL("foo://a.b.test"));
109   EXPECT_FALSE(origin.opaque());
110 
111   // We should not use registerable domains for non-standard schemes, even if
112   // one exists for the host.
113   EXPECT_EQ(url::Origin::Create(GURL("foo://a.b.test")),
114             SchemefulSite(origin).GetInternalOriginForTesting());
115 }
116 
TEST(SchemefulSiteTest,IPBasedOriginsRemovePort)117 TEST(SchemefulSiteTest, IPBasedOriginsRemovePort) {
118   // IPv4 and IPv6 origins should not be modified, except for removing their
119   // ports.
120   url::Origin origin_ipv4_a =
121       url::Origin::Create(GURL("http://127.0.0.1:1234"));
122   url::Origin origin_ipv4_b = url::Origin::Create(GURL("http://127.0.0.1"));
123   EXPECT_EQ(url::Origin::Create(GURL("http://127.0.0.1")),
124             SchemefulSite(origin_ipv4_a).GetInternalOriginForTesting());
125   EXPECT_EQ(SchemefulSite(origin_ipv4_a), SchemefulSite(origin_ipv4_b));
126 
127   url::Origin origin_ipv6 = url::Origin::Create(GURL("https://[::1]"));
128   EXPECT_EQ(url::Origin::Create(GURL("https://[::1]")),
129             SchemefulSite(origin_ipv6).GetInternalOriginForTesting());
130 }
131 
TEST(SchemefulSiteTest,LocalhostOriginsRemovePort)132 TEST(SchemefulSiteTest, LocalhostOriginsRemovePort) {
133   // Localhost origins should not be modified, except for removing their ports.
134   url::Origin localhost_http =
135       url::Origin::Create(GURL("http://localhost:1234"));
136   EXPECT_EQ(url::Origin::Create(GURL("http://localhost")),
137             SchemefulSite(localhost_http).GetInternalOriginForTesting());
138 
139   url::Origin localhost_https =
140       url::Origin::Create(GURL("https://localhost:1234"));
141   EXPECT_EQ(url::Origin::Create(GURL("https://localhost")),
142             SchemefulSite(localhost_https).GetInternalOriginForTesting());
143 }
144 
TEST(SchemefulSiteTest,OpaqueOrigins)145 TEST(SchemefulSiteTest, OpaqueOrigins) {
146   url::Origin opaque_origin_a =
147       url::Origin::Create(GURL("data:text/html,<body>Hello World</body>"));
148 
149   // The schemeful site of an opaque origin should always equal other schemeful
150   // site instances of the same origin.
151   EXPECT_EQ(SchemefulSite(opaque_origin_a), SchemefulSite(opaque_origin_a));
152 
153   url::Origin opaque_origin_b =
154       url::Origin::Create(GURL("data:text/html,<body>Hello World</body>"));
155 
156   // Two different opaque origins should never have the same SchemefulSite.
157   EXPECT_NE(SchemefulSite(opaque_origin_a), SchemefulSite(opaque_origin_b));
158 }
159 
TEST(SchemefulSiteTest,FileOriginWithoutHostname)160 TEST(SchemefulSiteTest, FileOriginWithoutHostname) {
161   SchemefulSite site1(url::Origin::Create(GURL("file:///")));
162   SchemefulSite site2(url::Origin::Create(GURL("file:///path/")));
163 
164   EXPECT_EQ(site1, site2);
165   EXPECT_TRUE(site1.GetInternalOriginForTesting().host().empty());
166 }
167 
TEST(SchemefulSiteTest,SchemeWithNetworkHost)168 TEST(SchemefulSiteTest, SchemeWithNetworkHost) {
169   url::ScopedSchemeRegistryForTests scheme_registry;
170   AddStandardScheme("network", url::SCHEME_WITH_HOST_PORT_AND_USER_INFORMATION);
171   AddStandardScheme("non-network", url::SCHEME_WITH_HOST);
172 
173   ASSERT_TRUE(IsStandardSchemeWithNetworkHost("network"));
174   ASSERT_FALSE(IsStandardSchemeWithNetworkHost("non-network"));
175 
176   std::optional<SchemefulSite> network_host_site =
177       SchemefulSite::CreateIfHasRegisterableDomain(
178           url::Origin::Create(GURL("network://site.example.test:1337")));
179   EXPECT_TRUE(network_host_site.has_value());
180   EXPECT_EQ("network",
181             network_host_site->GetInternalOriginForTesting().scheme());
182   EXPECT_EQ("example.test",
183             network_host_site->GetInternalOriginForTesting().host());
184 
185   std::optional<SchemefulSite> non_network_host_site_null =
186       SchemefulSite::CreateIfHasRegisterableDomain(
187           url::Origin::Create(GURL("non-network://site.example.test")));
188   EXPECT_FALSE(non_network_host_site_null.has_value());
189   SchemefulSite non_network_host_site(GURL("non-network://site.example.test"));
190   EXPECT_EQ("non-network",
191             non_network_host_site.GetInternalOriginForTesting().scheme());
192   // The host is used as-is, without attempting to get a registrable domain.
193   EXPECT_EQ("site.example.test",
194             non_network_host_site.GetInternalOriginForTesting().host());
195 }
196 
TEST(SchemefulSiteTest,FileSchemeHasRegistrableDomain)197 TEST(SchemefulSiteTest, FileSchemeHasRegistrableDomain) {
198   // Test file origin without host.
199   url::Origin origin_file =
200       url::Origin::Create(GURL("file:///dir1/dir2/file.txt"));
201   EXPECT_TRUE(origin_file.host().empty());
202   SchemefulSite site_file(origin_file);
203   EXPECT_EQ(url::Origin::Create(GURL("file:///")),
204             site_file.GetInternalOriginForTesting());
205 
206   // Test file origin with host (with registrable domain).
207   url::Origin origin_file_with_host =
208       url::Origin::Create(GURL("file://host.example.test/file"));
209   ASSERT_EQ("host.example.test", origin_file_with_host.host());
210   SchemefulSite site_file_with_host(origin_file_with_host);
211   EXPECT_EQ(url::Origin::Create(GURL("file://example.test")),
212             site_file_with_host.GetInternalOriginForTesting());
213 
214   // Test file origin with host same as registrable domain.
215   url::Origin origin_file_registrable_domain =
216       url::Origin::Create(GURL("file://example.test/file"));
217   ASSERT_EQ("example.test", origin_file_registrable_domain.host());
218   SchemefulSite site_file_registrable_domain(origin_file_registrable_domain);
219   EXPECT_EQ(url::Origin::Create(GURL("file://example.test")),
220             site_file_registrable_domain.GetInternalOriginForTesting());
221 
222   EXPECT_NE(site_file, site_file_with_host);
223   EXPECT_NE(site_file, site_file_registrable_domain);
224   EXPECT_EQ(site_file_with_host, site_file_registrable_domain);
225 }
226 
TEST(SchemefulSiteTest,SerializationConsistent)227 TEST(SchemefulSiteTest, SerializationConsistent) {
228   url::ScopedSchemeRegistryForTests scoped_registry;
229   url::AddStandardScheme("chrome", url::SCHEME_WITH_HOST);
230 
231   // List of origins which should all share a schemeful site.
232   SchemefulSite kTestSites[] = {
233       SchemefulSite(url::Origin::Create(GURL("http://a.foo.test"))),
234       SchemefulSite(url::Origin::Create(GURL("https://b.foo.test"))),
235       SchemefulSite(url::Origin::Create(GURL("http://b.foo.test"))),
236       SchemefulSite(url::Origin::Create(GURL("http://a.b.foo.test"))),
237       SchemefulSite(url::Origin::Create(GURL("chrome://a.b.test")))};
238 
239   for (const auto& site : kTestSites) {
240     SCOPED_TRACE(site.GetDebugString());
241     EXPECT_FALSE(site.GetInternalOriginForTesting().opaque());
242 
243     std::optional<SchemefulSite> deserialized_site =
244         SchemefulSite::Deserialize(site.Serialize());
245     EXPECT_TRUE(deserialized_site);
246     EXPECT_EQ(site, deserialized_site);
247   }
248 }
249 
TEST(SchemefulSiteTest,SerializationFileSiteWithHost)250 TEST(SchemefulSiteTest, SerializationFileSiteWithHost) {
251   const struct {
252     SchemefulSite site;
253     std::string expected;
254   } kTestCases[] = {
255       {SchemefulSite(GURL("file:///etc/passwd")), "file://"},
256       {SchemefulSite(GURL("file://example.com/etc/passwd")),
257        "file://example.com"},
258       {SchemefulSite(GURL("file://example.com")), "file://example.com"},
259   };
260 
261   for (const auto& test_case : kTestCases) {
262     SCOPED_TRACE(test_case.site.GetDebugString());
263     std::string serialized_site = test_case.site.SerializeFileSiteWithHost();
264     EXPECT_EQ(test_case.expected, serialized_site);
265     std::optional<SchemefulSite> deserialized_site =
266         SchemefulSite::Deserialize(serialized_site);
267     EXPECT_TRUE(deserialized_site);
268     EXPECT_EQ(test_case.site, deserialized_site);
269   }
270 }
271 
TEST(SchemefulSiteTest,FileURLWithHostEquality)272 TEST(SchemefulSiteTest, FileURLWithHostEquality) {
273   // Two file URLs with different hosts should result in unequal SchemefulSites.
274   SchemefulSite site1(GURL("file://foo/some/path.txt"));
275   SchemefulSite site2(GURL("file://bar/some/path.txt"));
276   EXPECT_NE(site1, site2);
277 
278   // Two file URLs with the same host should result in equal SchemefulSites.
279   SchemefulSite site3(GURL("file://foo/another/path.pdf"));
280   EXPECT_EQ(site1, site3);
281 }
282 
TEST(SchemefulSiteTest,OpaqueSerialization)283 TEST(SchemefulSiteTest, OpaqueSerialization) {
284   // List of origins which should all share a schemeful site.
285   SchemefulSite kTestSites[] = {
286       SchemefulSite(), SchemefulSite(url::Origin()),
287       SchemefulSite(GURL("data:text/html,<body>Hello World</body>"))};
288 
289   for (auto& site : kTestSites) {
290     std::optional<SchemefulSite> deserialized_site =
291         SchemefulSite::DeserializeWithNonce(*site.SerializeWithNonce());
292     EXPECT_TRUE(deserialized_site);
293     EXPECT_EQ(site, *deserialized_site);
294   }
295 }
296 
TEST(SchemefulSiteTest,FromWire)297 TEST(SchemefulSiteTest, FromWire) {
298   SchemefulSite out;
299 
300   // Opaque origin.
301   EXPECT_TRUE(SchemefulSite::FromWire(url::Origin(), &out));
302   EXPECT_TRUE(out.opaque());
303 
304   // Valid origin.
305   EXPECT_TRUE(SchemefulSite::FromWire(
306       url::Origin::Create(GURL("https://example.test")), &out));
307   EXPECT_EQ(SchemefulSite(url::Origin::Create(GURL("https://example.test"))),
308             out);
309 
310   // Invalid origin (not a registrable domain).
311   EXPECT_FALSE(SchemefulSite::FromWire(
312       url::Origin::Create(GURL("https://sub.example.test")), &out));
313 
314   // Invalid origin (non-default port).
315   EXPECT_FALSE(SchemefulSite::FromWire(
316       url::Origin::Create(GURL("https://example.test:1337")), &out));
317 }
318 
TEST(SchemefulSiteTest,CreateIfHasRegisterableDomain)319 TEST(SchemefulSiteTest, CreateIfHasRegisterableDomain) {
320   for (const auto& site : std::initializer_list<std::string>{
321            "http://a.bar.test",
322            "http://c.test",
323            "http://a.foo.test",
324            "https://a.bar.test",
325            "https://c.test",
326            "https://a.foo.test",
327        }) {
328     url::Origin origin = url::Origin::Create(GURL(site));
329     EXPECT_THAT(SchemefulSite::CreateIfHasRegisterableDomain(origin),
330                 testing::Optional(SchemefulSite(origin)))
331         << "site = \"" << site << "\"";
332   }
333 
334   for (const auto& site : std::initializer_list<std::string>{
335            "data:text/html,<body>Hello World</body>",
336            "file:///",
337            "file://foo",
338            "http://127.0.0.1:1234",
339            "https://127.0.0.1:1234",
340        }) {
341     url::Origin origin = url::Origin::Create(GURL(site));
342     EXPECT_EQ(SchemefulSite::CreateIfHasRegisterableDomain(origin),
343               std::nullopt)
344         << "site = \"" << site << "\"";
345   }
346 }
347 
TEST(SchemefulSiteTest,ConvertWebSocketToHttp)348 TEST(SchemefulSiteTest, ConvertWebSocketToHttp) {
349   SchemefulSite ws_site(url::Origin::Create(GURL("ws://site.example.test")));
350   SchemefulSite http_site(
351       url::Origin::Create(GURL("http://site.example.test")));
352   SchemefulSite wss_site(url::Origin::Create(GURL("wss://site.example.test")));
353   SchemefulSite https_site(
354       url::Origin::Create(GURL("https://site.example.test")));
355 
356   ASSERT_NE(ws_site, wss_site);
357   ASSERT_NE(ws_site, http_site);
358   ASSERT_NE(ws_site, https_site);
359   ASSERT_NE(wss_site, http_site);
360   ASSERT_NE(wss_site, https_site);
361 
362   ws_site.ConvertWebSocketToHttp();
363   wss_site.ConvertWebSocketToHttp();
364 
365   EXPECT_EQ(ws_site, http_site);
366   EXPECT_EQ(wss_site, https_site);
367 
368   // Does not change non-WebSocket sites.
369   SchemefulSite http_site_copy(http_site);
370   http_site_copy.ConvertWebSocketToHttp();
371   EXPECT_EQ(http_site, http_site_copy);
372   EXPECT_EQ(url::kHttpScheme,
373             http_site_copy.GetInternalOriginForTesting().scheme());
374 
375   SchemefulSite file_site(url::Origin::Create(GURL("file:///")));
376   file_site.ConvertWebSocketToHttp();
377   EXPECT_EQ(url::kFileScheme, file_site.GetInternalOriginForTesting().scheme());
378 }
379 
TEST(SchemefulSiteTest,GetGURL)380 TEST(SchemefulSiteTest, GetGURL) {
381   struct {
382     url::Origin origin;
383     GURL wantGURL;
384   } kTestCases[] = {
385       {
386           url::Origin::Create(GURL("data:text/html,<body>Hello World</body>")),
387           GURL(),
388       },
389       {url::Origin::Create(GURL("file://foo")), GURL("file:///")},
390       {url::Origin::Create(GURL("http://a.bar.test")), GURL("http://bar.test")},
391       {url::Origin::Create(GURL("http://c.test")), GURL("http://c.test")},
392       {url::Origin::Create(GURL("http://c.test:8000")), GURL("http://c.test")},
393       {
394           url::Origin::Create(GURL("https://a.bar.test")),
395           GURL("https://bar.test"),
396       },
397       {
398           url::Origin::Create(GURL("https://c.test")),
399           GURL("https://c.test"),
400       },
401       {
402           url::Origin::Create(GURL("https://c.test:1337")),
403           GURL("https://c.test"),
404       },
405   };
406 
407   for (const auto& testcase : kTestCases) {
408     SchemefulSite site(testcase.origin);
409     EXPECT_EQ(site.GetURL(), testcase.wantGURL);
410   }
411 }
412 
TEST(SchemefulSiteTest,InternalValue)413 TEST(SchemefulSiteTest, InternalValue) {
414   url::Origin origin = url::Origin::Create(GURL("https://example.com"));
415   SchemefulSite site(origin);
416   EXPECT_EQ(site.internal_value(), origin);
417   url::Origin opaque_origin;
418   SchemefulSite opaque_site(opaque_origin);
419   EXPECT_EQ(opaque_site.internal_value(), opaque_origin);
420 }
421 
422 }  // namespace net
423