Upload upstream chromium 67.0.3396
[platform/framework/web/chromium-efl.git] / url / origin_unittest.cc
1 // Copyright 2015 The Chromium Authors. All rights reserved.
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 <stddef.h>
6 #include <stdint.h>
7
8 #include "base/logging.h"
9 #include "base/macros.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "url/gurl.h"
12 #include "url/origin.h"
13
14 namespace {
15
16 void ExpectParsedUrlsEqual(const GURL& a, const GURL& b) {
17   EXPECT_EQ(a, b);
18   const url::Parsed& a_parsed = a.parsed_for_possibly_invalid_spec();
19   const url::Parsed& b_parsed = b.parsed_for_possibly_invalid_spec();
20   EXPECT_EQ(a_parsed.scheme.begin, b_parsed.scheme.begin);
21   EXPECT_EQ(a_parsed.scheme.len, b_parsed.scheme.len);
22   EXPECT_EQ(a_parsed.username.begin, b_parsed.username.begin);
23   EXPECT_EQ(a_parsed.username.len, b_parsed.username.len);
24   EXPECT_EQ(a_parsed.password.begin, b_parsed.password.begin);
25   EXPECT_EQ(a_parsed.password.len, b_parsed.password.len);
26   EXPECT_EQ(a_parsed.host.begin, b_parsed.host.begin);
27   EXPECT_EQ(a_parsed.host.len, b_parsed.host.len);
28   EXPECT_EQ(a_parsed.port.begin, b_parsed.port.begin);
29   EXPECT_EQ(a_parsed.port.len, b_parsed.port.len);
30   EXPECT_EQ(a_parsed.path.begin, b_parsed.path.begin);
31   EXPECT_EQ(a_parsed.path.len, b_parsed.path.len);
32   EXPECT_EQ(a_parsed.query.begin, b_parsed.query.begin);
33   EXPECT_EQ(a_parsed.query.len, b_parsed.query.len);
34   EXPECT_EQ(a_parsed.ref.begin, b_parsed.ref.begin);
35   EXPECT_EQ(a_parsed.ref.len, b_parsed.ref.len);
36 }
37
38 TEST(OriginTest, UniqueOriginComparison) {
39   url::Origin unique_origin;
40   EXPECT_EQ("", unique_origin.scheme());
41   EXPECT_EQ("", unique_origin.host());
42   EXPECT_EQ(0, unique_origin.port());
43   EXPECT_TRUE(unique_origin.unique());
44   EXPECT_FALSE(unique_origin.IsSameOriginWith(unique_origin));
45
46   const char* const urls[] = {"data:text/html,Hello!",
47                               "javascript:alert(1)",
48                               "file://example.com:443/etc/passwd",
49                               "yay",
50                               "http::///invalid.example.com/"};
51
52   for (auto* test_url : urls) {
53     SCOPED_TRACE(test_url);
54     GURL url(test_url);
55     url::Origin origin = url::Origin::Create(url);
56     EXPECT_EQ("", origin.scheme());
57     EXPECT_EQ("", origin.host());
58     EXPECT_EQ(0, origin.port());
59     EXPECT_TRUE(origin.unique());
60     EXPECT_FALSE(origin.IsSameOriginWith(origin));
61     EXPECT_FALSE(unique_origin.IsSameOriginWith(origin));
62     EXPECT_FALSE(origin.IsSameOriginWith(unique_origin));
63
64     ExpectParsedUrlsEqual(GURL(origin.Serialize()), origin.GetURL());
65   }
66 }
67
68 TEST(OriginTest, ConstructFromTuple) {
69   struct TestCases {
70     const char* const scheme;
71     const char* const host;
72     const uint16_t port;
73   } cases[] = {
74       {"http", "example.com", 80},
75       {"http", "example.com", 123},
76       {"https", "example.com", 443},
77   };
78
79   for (const auto& test_case : cases) {
80     testing::Message scope_message;
81     scope_message << test_case.scheme << "://" << test_case.host << ":"
82                   << test_case.port;
83     SCOPED_TRACE(scope_message);
84     url::Origin origin = url::Origin::CreateFromNormalizedTuple(
85         test_case.scheme, test_case.host, test_case.port);
86
87     EXPECT_EQ(test_case.scheme, origin.scheme());
88     EXPECT_EQ(test_case.host, origin.host());
89     EXPECT_EQ(test_case.port, origin.port());
90   }
91 }
92
93 TEST(OriginTest, ConstructFromGURL) {
94   url::Origin different_origin =
95       url::Origin::Create(GURL("https://not-in-the-list.test/"));
96
97   struct TestCases {
98     const char* const url;
99     const char* const expected_scheme;
100     const char* const expected_host;
101     const uint16_t expected_port;
102   } cases[] = {
103       // IP Addresses
104       {"http://192.168.9.1/", "http", "192.168.9.1", 80},
105       {"http://[2001:db8::1]/", "http", "[2001:db8::1]", 80},
106
107       // Punycode
108       {"http://☃.net/", "http", "xn--n3h.net", 80},
109       {"blob:http://☃.net/", "http", "xn--n3h.net", 80},
110
111       // Generic URLs
112       {"http://example.com/", "http", "example.com", 80},
113       {"http://example.com:123/", "http", "example.com", 123},
114       {"https://example.com/", "https", "example.com", 443},
115       {"https://example.com:123/", "https", "example.com", 123},
116       {"http://user:pass@example.com/", "http", "example.com", 80},
117       {"http://example.com:123/?query", "http", "example.com", 123},
118       {"https://example.com/#1234", "https", "example.com", 443},
119       {"https://u:p@example.com:123/?query#1234", "https", "example.com", 123},
120
121       // Registered URLs
122       {"ftp://example.com/", "ftp", "example.com", 21},
123       {"gopher://example.com/", "gopher", "example.com", 70},
124       {"ws://example.com/", "ws", "example.com", 80},
125       {"wss://example.com/", "wss", "example.com", 443},
126
127       // file: URLs
128       {"file:///etc/passwd", "file", "", 0},
129       {"file://example.com/etc/passwd", "file", "example.com", 0},
130
131       // Filesystem:
132       {"filesystem:http://example.com/type/", "http", "example.com", 80},
133       {"filesystem:http://example.com:123/type/", "http", "example.com", 123},
134       {"filesystem:https://example.com/type/", "https", "example.com", 443},
135       {"filesystem:https://example.com:123/type/", "https", "example.com", 123},
136
137       // Blob:
138       {"blob:http://example.com/guid-goes-here", "http", "example.com", 80},
139       {"blob:http://example.com:123/guid-goes-here", "http", "example.com", 123},
140       {"blob:https://example.com/guid-goes-here", "https", "example.com", 443},
141       {"blob:http://u:p@example.com/guid-goes-here", "http", "example.com", 80},
142   };
143
144   for (const auto& test_case : cases) {
145     SCOPED_TRACE(test_case.url);
146     GURL url(test_case.url);
147     EXPECT_TRUE(url.is_valid());
148     url::Origin origin = url::Origin::Create(url);
149     EXPECT_EQ(test_case.expected_scheme, origin.scheme());
150     EXPECT_EQ(test_case.expected_host, origin.host());
151     EXPECT_EQ(test_case.expected_port, origin.port());
152     EXPECT_FALSE(origin.unique());
153     EXPECT_TRUE(origin.IsSameOriginWith(origin));
154     EXPECT_FALSE(different_origin.IsSameOriginWith(origin));
155     EXPECT_FALSE(origin.IsSameOriginWith(different_origin));
156
157     ExpectParsedUrlsEqual(GURL(origin.Serialize()), origin.GetURL());
158   }
159 }
160
161 TEST(OriginTest, Serialization) {
162   struct TestCases {
163     const char* const url;
164     const char* const expected;
165   } cases[] = {
166       {"http://192.168.9.1/", "http://192.168.9.1"},
167       {"http://[2001:db8::1]/", "http://[2001:db8::1]"},
168       {"http://☃.net/", "http://xn--n3h.net"},
169       {"http://example.com/", "http://example.com"},
170       {"http://example.com:123/", "http://example.com:123"},
171       {"https://example.com/", "https://example.com"},
172       {"https://example.com:123/", "https://example.com:123"},
173       {"file:///etc/passwd", "file://"},
174       {"file://example.com/etc/passwd", "file://"},
175   };
176
177   for (const auto& test_case : cases) {
178     SCOPED_TRACE(test_case.url);
179     GURL url(test_case.url);
180     EXPECT_TRUE(url.is_valid());
181     url::Origin origin = url::Origin::Create(url);
182     std::string serialized = origin.Serialize();
183     ExpectParsedUrlsEqual(GURL(serialized), origin.GetURL());
184
185     EXPECT_EQ(test_case.expected, serialized);
186
187     // The '<<' operator should produce the same serialization as Serialize().
188     std::stringstream out;
189     out << origin;
190     EXPECT_EQ(test_case.expected, out.str());
191   }
192 }
193
194 TEST(OriginTest, Comparison) {
195   // These URLs are arranged in increasing order:
196   const char* const urls[] = {
197       "data:uniqueness",
198       "http://a:80",
199       "http://b:80",
200       "https://a:80",
201       "https://b:80",
202       "http://a:81",
203       "http://b:81",
204       "https://a:81",
205       "https://b:81",
206   };
207
208   for (size_t i = 0; i < arraysize(urls); i++) {
209     GURL current_url(urls[i]);
210     url::Origin current = url::Origin::Create(current_url);
211     for (size_t j = i; j < arraysize(urls); j++) {
212       GURL compare_url(urls[j]);
213       url::Origin to_compare = url::Origin::Create(compare_url);
214       EXPECT_EQ(i < j, current < to_compare) << i << " < " << j;
215       EXPECT_EQ(j < i, to_compare < current) << j << " < " << i;
216     }
217   }
218 }
219
220 TEST(OriginTest, UnsafelyCreate) {
221   struct TestCase {
222     const char* scheme;
223     const char* host;
224     uint16_t port;
225   } cases[] = {
226       {"http", "example.com", 80},
227       {"http", "example.com", 123},
228       {"https", "example.com", 443},
229       {"https", "example.com", 123},
230       {"file", "", 0},
231       {"file", "example.com", 0},
232   };
233
234   for (const auto& test : cases) {
235     SCOPED_TRACE(testing::Message() << test.scheme << "://" << test.host << ":"
236                                     << test.port);
237     url::Origin origin = url::Origin::UnsafelyCreateOriginWithoutNormalization(
238         test.scheme, test.host, test.port);
239     EXPECT_EQ(test.scheme, origin.scheme());
240     EXPECT_EQ(test.host, origin.host());
241     EXPECT_EQ(test.port, origin.port());
242     EXPECT_FALSE(origin.unique());
243     EXPECT_TRUE(origin.IsSameOriginWith(origin));
244
245     ExpectParsedUrlsEqual(GURL(origin.Serialize()), origin.GetURL());
246   }
247 }
248
249 TEST(OriginTest, UnsafelyCreateUniqueOnInvalidInput) {
250   struct TestCases {
251     const char* scheme;
252     const char* host;
253     uint16_t port = 80;
254   } cases[] = {{"", "", 0},
255                {"data", "", 0},
256                {"blob", "", 0},
257                {"filesystem", "", 0},
258                {"data", "example.com"},
259                {"http", "☃.net"},
260                {"http\nmore", "example.com"},
261                {"http\rmore", "example.com"},
262                {"http\n", "example.com"},
263                {"http\r", "example.com"},
264                {"http", "example.com\nnot-example.com"},
265                {"http", "example.com\rnot-example.com"},
266                {"http", "example.com\n"},
267                {"http", "example.com\r"},
268                {"http", "example.com", 0},
269                {"file", ""}};
270
271   for (const auto& test : cases) {
272     SCOPED_TRACE(testing::Message() << test.scheme << "://" << test.host << ":"
273                                     << test.port);
274     url::Origin origin = url::Origin::UnsafelyCreateOriginWithoutNormalization(
275         test.scheme, test.host, test.port);
276     EXPECT_EQ("", origin.scheme());
277     EXPECT_EQ("", origin.host());
278     EXPECT_EQ(0, origin.port());
279     EXPECT_TRUE(origin.unique());
280     EXPECT_FALSE(origin.IsSameOriginWith(origin));
281
282     ExpectParsedUrlsEqual(GURL(origin.Serialize()), origin.GetURL());
283   }
284 }
285
286 TEST(OriginTest, UnsafelyCreateUniqueViaEmbeddedNulls) {
287   struct TestCases {
288     const char* scheme;
289     size_t scheme_length;
290     const char* host;
291     size_t host_length;
292     uint16_t port = 80;
293   } cases[] = {{"http\0more", 9, "example.com", 11},
294                {"http\0", 5, "example.com", 11},
295                {"\0http", 5, "example.com", 11},
296                {"http", 4, "example.com\0not-example.com", 27},
297                {"http", 4, "example.com\0", 12},
298                {"http", 4, "\0example.com", 12}};
299
300   for (const auto& test : cases) {
301     SCOPED_TRACE(testing::Message() << test.scheme << "://" << test.host << ":"
302                                     << test.port);
303     url::Origin origin = url::Origin::UnsafelyCreateOriginWithoutNormalization(
304         std::string(test.scheme, test.scheme_length),
305         std::string(test.host, test.host_length), test.port);
306     EXPECT_EQ("", origin.scheme());
307     EXPECT_EQ("", origin.host());
308     EXPECT_EQ(0, origin.port());
309     EXPECT_TRUE(origin.unique());
310     EXPECT_FALSE(origin.IsSameOriginWith(origin));
311
312     ExpectParsedUrlsEqual(GURL(origin.Serialize()), origin.GetURL());
313   }
314 }
315
316 TEST(OriginTest, DomainIs) {
317   const struct {
318     const char* url;
319     const char* lower_ascii_domain;
320     bool expected_domain_is;
321   } kTestCases[] = {
322       {"http://google.com/foo", "google.com", true},
323       {"http://www.google.com:99/foo", "google.com", true},
324       {"http://www.google.com.cn/foo", "google.com", false},
325       {"http://www.google.comm", "google.com", false},
326       {"http://www.iamnotgoogle.com/foo", "google.com", false},
327       {"http://www.google.com/foo", "Google.com", false},
328
329       // If the host ends with a dot, it matches domains with or without a dot.
330       {"http://www.google.com./foo", "google.com", true},
331       {"http://www.google.com./foo", "google.com.", true},
332       {"http://www.google.com./foo", ".com", true},
333       {"http://www.google.com./foo", ".com.", true},
334
335       // But, if the host doesn't end with a dot and the input domain does, then
336       // it's considered to not match.
337       {"http://google.com/foo", "google.com.", false},
338
339       // If the host ends with two dots, it doesn't match.
340       {"http://www.google.com../foo", "google.com", false},
341
342       // Filesystem scheme.
343       {"filesystem:http://www.google.com:99/foo/", "google.com", true},
344       {"filesystem:http://www.iamnotgoogle.com/foo/", "google.com", false},
345
346       // File scheme.
347       {"file:///home/user/text.txt", "", false},
348       {"file:///home/user/text.txt", "txt", false},
349   };
350
351   for (const auto& test_case : kTestCases) {
352     SCOPED_TRACE(testing::Message() << "(url, domain): (" << test_case.url
353                                     << ", " << test_case.lower_ascii_domain
354                                     << ")");
355     GURL url(test_case.url);
356     ASSERT_TRUE(url.is_valid());
357     url::Origin origin = url::Origin::Create(url);
358
359     EXPECT_EQ(test_case.expected_domain_is,
360               origin.DomainIs(test_case.lower_ascii_domain));
361   }
362
363   // If the URL is invalid, DomainIs returns false.
364   GURL invalid_url("google.com");
365   ASSERT_FALSE(invalid_url.is_valid());
366   EXPECT_FALSE(url::Origin::Create(invalid_url).DomainIs("google.com"));
367
368   // Unique origins.
369   EXPECT_FALSE(url::Origin().DomainIs(""));
370   EXPECT_FALSE(url::Origin().DomainIs("com"));
371 }
372
373 TEST(OriginTest, DebugAlias) {
374   url::Origin origin1 = url::Origin::Create(GURL("https://foo.com/bar"));
375   DEBUG_ALIAS_FOR_ORIGIN(origin1_debug_alias, origin1);
376   EXPECT_STREQ("https://foo.com", origin1_debug_alias);
377 }
378
379 }  // namespace