• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,OpaqueOrigins)132 TEST(SchemefulSiteTest, OpaqueOrigins) {
133   url::Origin opaque_origin_a =
134       url::Origin::Create(GURL("data:text/html,<body>Hello World</body>"));
135 
136   // The schemeful site of an opaque origin should always equal other schemeful
137   // site instances of the same origin.
138   EXPECT_EQ(SchemefulSite(opaque_origin_a), SchemefulSite(opaque_origin_a));
139 
140   url::Origin opaque_origin_b =
141       url::Origin::Create(GURL("data:text/html,<body>Hello World</body>"));
142 
143   // Two different opaque origins should never have the same SchemefulSite.
144   EXPECT_NE(SchemefulSite(opaque_origin_a), SchemefulSite(opaque_origin_b));
145 }
146 
TEST(SchemefulSiteTest,FileOriginWithoutHostname)147 TEST(SchemefulSiteTest, FileOriginWithoutHostname) {
148   SchemefulSite site1(url::Origin::Create(GURL("file:///")));
149   SchemefulSite site2(url::Origin::Create(GURL("file:///path/")));
150 
151   EXPECT_EQ(site1, site2);
152   EXPECT_TRUE(site1.GetInternalOriginForTesting().host().empty());
153 }
154 
TEST(SchemefulSiteTest,SchemeWithNetworkHost)155 TEST(SchemefulSiteTest, SchemeWithNetworkHost) {
156   url::ScopedSchemeRegistryForTests scheme_registry;
157   AddStandardScheme("network", url::SCHEME_WITH_HOST_PORT_AND_USER_INFORMATION);
158   AddStandardScheme("non-network", url::SCHEME_WITH_HOST);
159 
160   ASSERT_TRUE(IsStandardSchemeWithNetworkHost("network"));
161   ASSERT_FALSE(IsStandardSchemeWithNetworkHost("non-network"));
162 
163   absl::optional<SchemefulSite> network_host_site =
164       SchemefulSite::CreateIfHasRegisterableDomain(
165           url::Origin::Create(GURL("network://site.example.test:1337")));
166   EXPECT_TRUE(network_host_site.has_value());
167   EXPECT_EQ("network",
168             network_host_site->GetInternalOriginForTesting().scheme());
169   EXPECT_EQ("example.test",
170             network_host_site->GetInternalOriginForTesting().host());
171 
172   absl::optional<SchemefulSite> non_network_host_site_null =
173       SchemefulSite::CreateIfHasRegisterableDomain(
174           url::Origin::Create(GURL("non-network://site.example.test")));
175   EXPECT_FALSE(non_network_host_site_null.has_value());
176   SchemefulSite non_network_host_site(GURL("non-network://site.example.test"));
177   EXPECT_EQ("non-network",
178             non_network_host_site.GetInternalOriginForTesting().scheme());
179   // The host is used as-is, without attempting to get a registrable domain.
180   EXPECT_EQ("site.example.test",
181             non_network_host_site.GetInternalOriginForTesting().host());
182 }
183 
TEST(SchemefulSiteTest,FileSchemeHasRegistrableDomain)184 TEST(SchemefulSiteTest, FileSchemeHasRegistrableDomain) {
185   // Test file origin without host.
186   url::Origin origin_file =
187       url::Origin::Create(GURL("file:///dir1/dir2/file.txt"));
188   EXPECT_TRUE(origin_file.host().empty());
189   SchemefulSite site_file(origin_file);
190   EXPECT_EQ(url::Origin::Create(GURL("file:///")),
191             site_file.GetInternalOriginForTesting());
192 
193   // Test file origin with host (with registrable domain).
194   url::Origin origin_file_with_host =
195       url::Origin::Create(GURL("file://host.example.test/file"));
196   ASSERT_EQ("host.example.test", origin_file_with_host.host());
197   SchemefulSite site_file_with_host(origin_file_with_host);
198   EXPECT_EQ(url::Origin::Create(GURL("file://example.test")),
199             site_file_with_host.GetInternalOriginForTesting());
200 
201   // Test file origin with host same as registrable domain.
202   url::Origin origin_file_registrable_domain =
203       url::Origin::Create(GURL("file://example.test/file"));
204   ASSERT_EQ("example.test", origin_file_registrable_domain.host());
205   SchemefulSite site_file_registrable_domain(origin_file_registrable_domain);
206   EXPECT_EQ(url::Origin::Create(GURL("file://example.test")),
207             site_file_registrable_domain.GetInternalOriginForTesting());
208 
209   EXPECT_NE(site_file, site_file_with_host);
210   EXPECT_NE(site_file, site_file_registrable_domain);
211   EXPECT_EQ(site_file_with_host, site_file_registrable_domain);
212 }
213 
TEST(SchemefulSiteTest,SerializationConsistent)214 TEST(SchemefulSiteTest, SerializationConsistent) {
215   url::ScopedSchemeRegistryForTests scoped_registry;
216   url::AddStandardScheme("chrome", url::SCHEME_WITH_HOST);
217 
218   // List of origins which should all share a schemeful site.
219   SchemefulSite kTestSites[] = {
220       SchemefulSite(url::Origin::Create(GURL("http://a.foo.test"))),
221       SchemefulSite(url::Origin::Create(GURL("https://b.foo.test"))),
222       SchemefulSite(url::Origin::Create(GURL("http://b.foo.test"))),
223       SchemefulSite(url::Origin::Create(GURL("http://a.b.foo.test"))),
224       SchemefulSite(url::Origin::Create(GURL("chrome://a.b.test")))};
225 
226   for (const auto& site : kTestSites) {
227     SCOPED_TRACE(site.GetDebugString());
228     EXPECT_FALSE(site.GetInternalOriginForTesting().opaque());
229 
230     absl::optional<SchemefulSite> deserialized_site =
231         SchemefulSite::Deserialize(site.Serialize());
232     EXPECT_TRUE(deserialized_site);
233     EXPECT_EQ(site, deserialized_site);
234   }
235 }
236 
TEST(SchemefulSiteTest,SerializationFileSiteWithHost)237 TEST(SchemefulSiteTest, SerializationFileSiteWithHost) {
238   const struct {
239     SchemefulSite site;
240     std::string expected;
241   } kTestCases[] = {
242       {SchemefulSite(GURL("file:///etc/passwd")), "file://"},
243       {SchemefulSite(GURL("file://example.com/etc/passwd")),
244        "file://example.com"},
245       {SchemefulSite(GURL("file://example.com")), "file://example.com"},
246   };
247 
248   for (const auto& test_case : kTestCases) {
249     SCOPED_TRACE(test_case.site.GetDebugString());
250     std::string serialized_site = test_case.site.SerializeFileSiteWithHost();
251     EXPECT_EQ(test_case.expected, serialized_site);
252     absl::optional<SchemefulSite> deserialized_site =
253         SchemefulSite::Deserialize(serialized_site);
254     EXPECT_TRUE(deserialized_site);
255     EXPECT_EQ(test_case.site, deserialized_site);
256   }
257 }
258 
TEST(SchemefulSiteTest,FileURLWithHostEquality)259 TEST(SchemefulSiteTest, FileURLWithHostEquality) {
260   // Two file URLs with different hosts should result in unequal SchemefulSites.
261   SchemefulSite site1(GURL("file://foo/some/path.txt"));
262   SchemefulSite site2(GURL("file://bar/some/path.txt"));
263   EXPECT_NE(site1, site2);
264 
265   // Two file URLs with the same host should result in equal SchemefulSites.
266   SchemefulSite site3(GURL("file://foo/another/path.pdf"));
267   EXPECT_EQ(site1, site3);
268 }
269 
TEST(SchemefulSiteTest,OpaqueSerialization)270 TEST(SchemefulSiteTest, OpaqueSerialization) {
271   // List of origins which should all share a schemeful site.
272   SchemefulSite kTestSites[] = {
273       SchemefulSite(), SchemefulSite(url::Origin()),
274       SchemefulSite(GURL("data:text/html,<body>Hello World</body>"))};
275 
276   for (auto& site : kTestSites) {
277     absl::optional<SchemefulSite> deserialized_site =
278         SchemefulSite::DeserializeWithNonce(*site.SerializeWithNonce());
279     EXPECT_TRUE(deserialized_site);
280     EXPECT_EQ(site, *deserialized_site);
281   }
282 }
283 
TEST(SchemefulSiteTest,FromWire)284 TEST(SchemefulSiteTest, FromWire) {
285   SchemefulSite out;
286 
287   // Opaque origin.
288   EXPECT_TRUE(SchemefulSite::FromWire(url::Origin(), &out));
289   EXPECT_TRUE(out.opaque());
290 
291   // Valid origin.
292   EXPECT_TRUE(SchemefulSite::FromWire(
293       url::Origin::Create(GURL("https://example.test")), &out));
294   EXPECT_EQ(SchemefulSite(url::Origin::Create(GURL("https://example.test"))),
295             out);
296 
297   // Invalid origin (not a registrable domain).
298   EXPECT_FALSE(SchemefulSite::FromWire(
299       url::Origin::Create(GURL("https://sub.example.test")), &out));
300 
301   // Invalid origin (non-default port).
302   EXPECT_FALSE(SchemefulSite::FromWire(
303       url::Origin::Create(GURL("https://example.test:1337")), &out));
304 }
305 
TEST(SchemefulSiteTest,CreateIfHasRegisterableDomain)306 TEST(SchemefulSiteTest, CreateIfHasRegisterableDomain) {
307   for (const auto& site : std::initializer_list<std::string>{
308            "http://a.bar.test",
309            "http://c.test",
310            "http://a.foo.test",
311            "https://a.bar.test",
312            "https://c.test",
313            "https://a.foo.test",
314        }) {
315     url::Origin origin = url::Origin::Create(GURL(site));
316     EXPECT_THAT(SchemefulSite::CreateIfHasRegisterableDomain(origin),
317                 testing::Optional(SchemefulSite(origin)))
318         << "site = \"" << site << "\"";
319   }
320 
321   for (const auto& site : std::initializer_list<std::string>{
322            "data:text/html,<body>Hello World</body>",
323            "file:///",
324            "file://foo",
325            "http://127.0.0.1:1234",
326            "https://127.0.0.1:1234",
327        }) {
328     url::Origin origin = url::Origin::Create(GURL(site));
329     EXPECT_EQ(SchemefulSite::CreateIfHasRegisterableDomain(origin),
330               absl::nullopt)
331         << "site = \"" << site << "\"";
332   }
333 }
334 
TEST(SchemefulSiteTest,ConvertWebSocketToHttp)335 TEST(SchemefulSiteTest, ConvertWebSocketToHttp) {
336   SchemefulSite ws_site(url::Origin::Create(GURL("ws://site.example.test")));
337   SchemefulSite http_site(
338       url::Origin::Create(GURL("http://site.example.test")));
339   SchemefulSite wss_site(url::Origin::Create(GURL("wss://site.example.test")));
340   SchemefulSite https_site(
341       url::Origin::Create(GURL("https://site.example.test")));
342 
343   ASSERT_NE(ws_site, wss_site);
344   ASSERT_NE(ws_site, http_site);
345   ASSERT_NE(ws_site, https_site);
346   ASSERT_NE(wss_site, http_site);
347   ASSERT_NE(wss_site, https_site);
348 
349   ws_site.ConvertWebSocketToHttp();
350   wss_site.ConvertWebSocketToHttp();
351 
352   EXPECT_EQ(ws_site, http_site);
353   EXPECT_EQ(wss_site, https_site);
354 
355   // Does not change non-WebSocket sites.
356   SchemefulSite http_site_copy(http_site);
357   http_site_copy.ConvertWebSocketToHttp();
358   EXPECT_EQ(http_site, http_site_copy);
359   EXPECT_EQ(url::kHttpScheme,
360             http_site_copy.GetInternalOriginForTesting().scheme());
361 
362   SchemefulSite file_site(url::Origin::Create(GURL("file:///")));
363   file_site.ConvertWebSocketToHttp();
364   EXPECT_EQ(url::kFileScheme, file_site.GetInternalOriginForTesting().scheme());
365 }
366 
TEST(SchemefulSiteTest,GetGURL)367 TEST(SchemefulSiteTest, GetGURL) {
368   struct {
369     url::Origin origin;
370     GURL wantGURL;
371   } kTestCases[] = {
372       {
373           url::Origin::Create(GURL("data:text/html,<body>Hello World</body>")),
374           GURL(),
375       },
376       {url::Origin::Create(GURL("file://foo")), GURL("file:///")},
377       {url::Origin::Create(GURL("http://a.bar.test")), GURL("http://bar.test")},
378       {url::Origin::Create(GURL("http://c.test")), GURL("http://c.test")},
379       {url::Origin::Create(GURL("http://c.test:8000")), GURL("http://c.test")},
380       {
381           url::Origin::Create(GURL("https://a.bar.test")),
382           GURL("https://bar.test"),
383       },
384       {
385           url::Origin::Create(GURL("https://c.test")),
386           GURL("https://c.test"),
387       },
388       {
389           url::Origin::Create(GURL("https://c.test:1337")),
390           GURL("https://c.test"),
391       },
392   };
393 
394   for (const auto& testcase : kTestCases) {
395     SchemefulSite site(testcase.origin);
396     EXPECT_EQ(site.GetURL(), testcase.wantGURL);
397   }
398 }
399 
TEST(SchemefulSiteTest,InternalValue)400 TEST(SchemefulSiteTest, InternalValue) {
401   url::Origin origin = url::Origin::Create(GURL("https://example.com"));
402   SchemefulSite site(origin);
403   EXPECT_EQ(site.internal_value(), origin);
404   url::Origin opaque_origin;
405   SchemefulSite opaque_site(opaque_origin);
406   EXPECT_EQ(opaque_site.internal_value(), opaque_origin);
407 }
408 
409 }  // namespace net
410