1 // Copyright 2013 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
7 #include "base/stl_util.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "url/gurl.h"
12 #include "url/origin.h"
13 #include "url/url_canon.h"
14 #include "url/url_test_utils.h"
15
16 namespace url {
17
18 namespace {
19
20 template<typename CHAR>
SetupReplacement(void (Replacements<CHAR>::* func)(const CHAR *,const Component &),Replacements<CHAR> * replacements,const CHAR * str)21 void SetupReplacement(
22 void (Replacements<CHAR>::*func)(const CHAR*, const Component&),
23 Replacements<CHAR>* replacements,
24 const CHAR* str) {
25 if (str) {
26 Component comp;
27 if (str[0])
28 comp.len = static_cast<int>(strlen(str));
29 (replacements->*func)(str, comp);
30 }
31 }
32
33 // Returns the canonicalized string for the given URL string for the
34 // GURLTest.Types test.
TypesTestCase(const char * src)35 std::string TypesTestCase(const char* src) {
36 GURL gurl(src);
37 return gurl.possibly_invalid_spec();
38 }
39
40 } // namespace
41
42 // Different types of URLs should be handled differently, and handed off to
43 // different canonicalizers.
TEST(GURLTest,Types)44 TEST(GURLTest, Types) {
45 // URLs with unknown schemes should be treated as path URLs, even when they
46 // have things like "://".
47 EXPECT_EQ("something:///HOSTNAME.com/",
48 TypesTestCase("something:///HOSTNAME.com/"));
49
50 // Conversely, URLs with known schemes should always trigger standard URL
51 // handling.
52 EXPECT_EQ("http://hostname.com/", TypesTestCase("http:HOSTNAME.com"));
53 EXPECT_EQ("http://hostname.com/", TypesTestCase("http:/HOSTNAME.com"));
54 EXPECT_EQ("http://hostname.com/", TypesTestCase("http://HOSTNAME.com"));
55 EXPECT_EQ("http://hostname.com/", TypesTestCase("http:///HOSTNAME.com"));
56
57 #ifdef WIN32
58 // URLs that look like Windows absolute path specs.
59 EXPECT_EQ("file:///C:/foo.txt", TypesTestCase("c:\\foo.txt"));
60 EXPECT_EQ("file:///Z:/foo.txt", TypesTestCase("Z|foo.txt"));
61 EXPECT_EQ("file://server/foo.txt", TypesTestCase("\\\\server\\foo.txt"));
62 EXPECT_EQ("file://server/foo.txt", TypesTestCase("//server/foo.txt"));
63 #endif
64 }
65
66 // Test the basic creation and querying of components in a GURL. We assume that
67 // the parser is already tested and works, so we are mostly interested if the
68 // object does the right thing with the results.
TEST(GURLTest,Components)69 TEST(GURLTest, Components) {
70 GURL empty_url(base::UTF8ToUTF16(""));
71 EXPECT_TRUE(empty_url.is_empty());
72 EXPECT_FALSE(empty_url.is_valid());
73
74 GURL url(base::UTF8ToUTF16("http://user:pass@google.com:99/foo;bar?q=a#ref"));
75 EXPECT_FALSE(url.is_empty());
76 EXPECT_TRUE(url.is_valid());
77 EXPECT_TRUE(url.SchemeIs("http"));
78 EXPECT_FALSE(url.SchemeIsFile());
79
80 // This is the narrow version of the URL, which should match the wide input.
81 EXPECT_EQ("http://user:pass@google.com:99/foo;bar?q=a#ref", url.spec());
82
83 EXPECT_EQ("http", url.scheme());
84 EXPECT_EQ("user", url.username());
85 EXPECT_EQ("pass", url.password());
86 EXPECT_EQ("google.com", url.host());
87 EXPECT_EQ("99", url.port());
88 EXPECT_EQ(99, url.IntPort());
89 EXPECT_EQ("/foo;bar", url.path());
90 EXPECT_EQ("q=a", url.query());
91 EXPECT_EQ("ref", url.ref());
92
93 // Test parsing userinfo with special characters.
94 GURL url_special_pass("http://user:%40!$&'()*+,;=:@google.com:12345");
95 EXPECT_TRUE(url_special_pass.is_valid());
96 // GURL canonicalizes some delimiters.
97 EXPECT_EQ("%40!$&%27()*+,%3B%3D%3A", url_special_pass.password());
98 EXPECT_EQ("google.com", url_special_pass.host());
99 EXPECT_EQ("12345", url_special_pass.port());
100 }
101
TEST(GURLTest,Empty)102 TEST(GURLTest, Empty) {
103 GURL url;
104 EXPECT_FALSE(url.is_valid());
105 EXPECT_EQ("", url.spec());
106
107 EXPECT_EQ("", url.scheme());
108 EXPECT_EQ("", url.username());
109 EXPECT_EQ("", url.password());
110 EXPECT_EQ("", url.host());
111 EXPECT_EQ("", url.port());
112 EXPECT_EQ(PORT_UNSPECIFIED, url.IntPort());
113 EXPECT_EQ("", url.path());
114 EXPECT_EQ("", url.query());
115 EXPECT_EQ("", url.ref());
116 }
117
TEST(GURLTest,Copy)118 TEST(GURLTest, Copy) {
119 GURL url(base::UTF8ToUTF16(
120 "http://user:pass@google.com:99/foo;bar?q=a#ref"));
121
122 GURL url2(url);
123 EXPECT_TRUE(url2.is_valid());
124
125 EXPECT_EQ("http://user:pass@google.com:99/foo;bar?q=a#ref", url2.spec());
126 EXPECT_EQ("http", url2.scheme());
127 EXPECT_EQ("user", url2.username());
128 EXPECT_EQ("pass", url2.password());
129 EXPECT_EQ("google.com", url2.host());
130 EXPECT_EQ("99", url2.port());
131 EXPECT_EQ(99, url2.IntPort());
132 EXPECT_EQ("/foo;bar", url2.path());
133 EXPECT_EQ("q=a", url2.query());
134 EXPECT_EQ("ref", url2.ref());
135
136 // Copying of invalid URL should be invalid
137 GURL invalid;
138 GURL invalid2(invalid);
139 EXPECT_FALSE(invalid2.is_valid());
140 EXPECT_EQ("", invalid2.spec());
141 EXPECT_EQ("", invalid2.scheme());
142 EXPECT_EQ("", invalid2.username());
143 EXPECT_EQ("", invalid2.password());
144 EXPECT_EQ("", invalid2.host());
145 EXPECT_EQ("", invalid2.port());
146 EXPECT_EQ(PORT_UNSPECIFIED, invalid2.IntPort());
147 EXPECT_EQ("", invalid2.path());
148 EXPECT_EQ("", invalid2.query());
149 EXPECT_EQ("", invalid2.ref());
150 }
151
TEST(GURLTest,Assign)152 TEST(GURLTest, Assign) {
153 GURL url(base::UTF8ToUTF16(
154 "http://user:pass@google.com:99/foo;bar?q=a#ref"));
155
156 GURL url2;
157 url2 = url;
158 EXPECT_TRUE(url2.is_valid());
159
160 EXPECT_EQ("http://user:pass@google.com:99/foo;bar?q=a#ref", url2.spec());
161 EXPECT_EQ("http", url2.scheme());
162 EXPECT_EQ("user", url2.username());
163 EXPECT_EQ("pass", url2.password());
164 EXPECT_EQ("google.com", url2.host());
165 EXPECT_EQ("99", url2.port());
166 EXPECT_EQ(99, url2.IntPort());
167 EXPECT_EQ("/foo;bar", url2.path());
168 EXPECT_EQ("q=a", url2.query());
169 EXPECT_EQ("ref", url2.ref());
170
171 // Assignment of invalid URL should be invalid
172 GURL invalid;
173 GURL invalid2;
174 invalid2 = invalid;
175 EXPECT_FALSE(invalid2.is_valid());
176 EXPECT_EQ("", invalid2.spec());
177 EXPECT_EQ("", invalid2.scheme());
178 EXPECT_EQ("", invalid2.username());
179 EXPECT_EQ("", invalid2.password());
180 EXPECT_EQ("", invalid2.host());
181 EXPECT_EQ("", invalid2.port());
182 EXPECT_EQ(PORT_UNSPECIFIED, invalid2.IntPort());
183 EXPECT_EQ("", invalid2.path());
184 EXPECT_EQ("", invalid2.query());
185 EXPECT_EQ("", invalid2.ref());
186 }
187
188 // This is a regression test for http://crbug.com/309975.
TEST(GURLTest,SelfAssign)189 TEST(GURLTest, SelfAssign) {
190 GURL a("filesystem:http://example.com/temporary/");
191 // This should not crash.
192 a = *&a; // The *& defeats Clang's -Wself-assign warning.
193 }
194
TEST(GURLTest,CopyFileSystem)195 TEST(GURLTest, CopyFileSystem) {
196 GURL url(base::UTF8ToUTF16(
197 "filesystem:https://user:pass@google.com:99/t/foo;bar?q=a#ref"));
198
199 GURL url2(url);
200 EXPECT_TRUE(url2.is_valid());
201
202 EXPECT_EQ("filesystem:https://google.com:99/t/foo;bar?q=a#ref", url2.spec());
203 EXPECT_EQ("filesystem", url2.scheme());
204 EXPECT_EQ("", url2.username());
205 EXPECT_EQ("", url2.password());
206 EXPECT_EQ("", url2.host());
207 EXPECT_EQ("", url2.port());
208 EXPECT_EQ(PORT_UNSPECIFIED, url2.IntPort());
209 EXPECT_EQ("/foo;bar", url2.path());
210 EXPECT_EQ("q=a", url2.query());
211 EXPECT_EQ("ref", url2.ref());
212
213 const GURL* inner = url2.inner_url();
214 ASSERT_TRUE(inner);
215 EXPECT_EQ("https", inner->scheme());
216 EXPECT_EQ("", inner->username());
217 EXPECT_EQ("", inner->password());
218 EXPECT_EQ("google.com", inner->host());
219 EXPECT_EQ("99", inner->port());
220 EXPECT_EQ(99, inner->IntPort());
221 EXPECT_EQ("/t", inner->path());
222 EXPECT_EQ("", inner->query());
223 EXPECT_EQ("", inner->ref());
224 }
225
TEST(GURLTest,IsValid)226 TEST(GURLTest, IsValid) {
227 const char* valid_cases[] = {
228 "http://google.com",
229 "unknown://google.com",
230 "http://user:pass@google.com",
231 "http://google.com:12345",
232 "http://google.com:0", // 0 is a valid port
233 "http://google.com/path",
234 "http://google.com//path",
235 "http://google.com?k=v#fragment",
236 "http://user:pass@google.com:12345/path?k=v#fragment",
237 "http:/path",
238 "http:path",
239 };
240 for (size_t i = 0; i < base::size(valid_cases); i++) {
241 EXPECT_TRUE(GURL(valid_cases[i]).is_valid())
242 << "Case: " << valid_cases[i];
243 }
244
245 const char* invalid_cases[] = {
246 "http://?k=v",
247 "http:://google.com",
248 "http//google.com",
249 "http://google.com:12three45",
250 "file://server:123", // file: URLs cannot have a port
251 "file://server:0",
252 "://google.com",
253 "path",
254 };
255 for (size_t i = 0; i < base::size(invalid_cases); i++) {
256 EXPECT_FALSE(GURL(invalid_cases[i]).is_valid())
257 << "Case: " << invalid_cases[i];
258 }
259 }
260
TEST(GURLTest,ExtraSlashesBeforeAuthority)261 TEST(GURLTest, ExtraSlashesBeforeAuthority) {
262 // According to RFC3986, the hierarchical part for URI with an authority
263 // must use only two slashes; GURL intentionally just ignores extra slashes
264 // if there are more than 2, and parses the following part as an authority.
265 GURL url("http:///host");
266 EXPECT_EQ("host", url.host());
267 EXPECT_EQ("/", url.path());
268 }
269
270 // Given an invalid URL, we should still get most of the components.
TEST(GURLTest,ComponentGettersWorkEvenForInvalidURL)271 TEST(GURLTest, ComponentGettersWorkEvenForInvalidURL) {
272 GURL url("http:google.com:foo");
273 EXPECT_FALSE(url.is_valid());
274 EXPECT_EQ("http://google.com:foo/", url.possibly_invalid_spec());
275
276 EXPECT_EQ("http", url.scheme());
277 EXPECT_EQ("", url.username());
278 EXPECT_EQ("", url.password());
279 EXPECT_EQ("google.com", url.host());
280 EXPECT_EQ("foo", url.port());
281 EXPECT_EQ(PORT_INVALID, url.IntPort());
282 EXPECT_EQ("/", url.path());
283 EXPECT_EQ("", url.query());
284 EXPECT_EQ("", url.ref());
285 }
286
TEST(GURLTest,Resolve)287 TEST(GURLTest, Resolve) {
288 // The tricky cases for relative URL resolving are tested in the
289 // canonicalizer unit test. Here, we just test that the GURL integration
290 // works properly.
291 struct ResolveCase {
292 const char* base;
293 const char* relative;
294 bool expected_valid;
295 const char* expected;
296 } resolve_cases[] = {
297 {"http://www.google.com/", "foo.html", true,
298 "http://www.google.com/foo.html"},
299 {"http://www.google.com/foo/", "bar", true,
300 "http://www.google.com/foo/bar"},
301 {"http://www.google.com/foo/", "/bar", true, "http://www.google.com/bar"},
302 {"http://www.google.com/foo", "bar", true, "http://www.google.com/bar"},
303 {"http://www.google.com/", "http://images.google.com/foo.html", true,
304 "http://images.google.com/foo.html"},
305 {"http://www.google.com/", "http://images.\tgoogle.\ncom/\rfoo.html",
306 true, "http://images.google.com/foo.html"},
307 {"http://www.google.com/blah/bloo?c#d", "../../../hello/./world.html?a#b",
308 true, "http://www.google.com/hello/world.html?a#b"},
309 {"http://www.google.com/foo#bar", "#com", true,
310 "http://www.google.com/foo#com"},
311 {"http://www.google.com/", "Https:images.google.com", true,
312 "https://images.google.com/"},
313 // A non-standard base can be replaced with a standard absolute URL.
314 {"data:blahblah", "http://google.com/", true, "http://google.com/"},
315 {"data:blahblah", "http:google.com", true, "http://google.com/"},
316 // Filesystem URLs have different paths to test.
317 {"filesystem:http://www.google.com/type/", "foo.html", true,
318 "filesystem:http://www.google.com/type/foo.html"},
319 {"filesystem:http://www.google.com/type/", "../foo.html", true,
320 "filesystem:http://www.google.com/type/foo.html"},
321 // https://crbug.com/530123 - scheme validation (e.g. are "10.0.0.7:"
322 // or "x1:" valid schemes) when deciding if |relative| is an absolute url.
323 {"file:///some/dir/ip-relative.html", "10.0.0.7:8080/foo.html", true,
324 "file:///some/dir/10.0.0.7:8080/foo.html"},
325 {"file:///some/dir/", "1://host", true, "file:///some/dir/1://host"},
326 {"file:///some/dir/", "x1://host", true, "x1://host"},
327 {"file:///some/dir/", "X1://host", true, "x1://host"},
328 {"file:///some/dir/", "x.://host", true, "x.://host"},
329 {"file:///some/dir/", "x+://host", true, "x+://host"},
330 {"file:///some/dir/", "x-://host", true, "x-://host"},
331 {"file:///some/dir/", "x!://host", true, "file:///some/dir/x!://host"},
332 {"file:///some/dir/", "://host", true, "file:///some/dir/://host"},
333 };
334
335 for (size_t i = 0; i < base::size(resolve_cases); i++) {
336 // 8-bit code path.
337 GURL input(resolve_cases[i].base);
338 GURL output = input.Resolve(resolve_cases[i].relative);
339 EXPECT_EQ(resolve_cases[i].expected_valid, output.is_valid()) << i;
340 EXPECT_EQ(resolve_cases[i].expected, output.spec()) << i;
341 EXPECT_EQ(output.SchemeIsFileSystem(), output.inner_url() != NULL);
342
343 // Wide code path.
344 GURL inputw(base::UTF8ToUTF16(resolve_cases[i].base));
345 GURL outputw =
346 input.Resolve(base::UTF8ToUTF16(resolve_cases[i].relative));
347 EXPECT_EQ(resolve_cases[i].expected_valid, outputw.is_valid()) << i;
348 EXPECT_EQ(resolve_cases[i].expected, outputw.spec()) << i;
349 EXPECT_EQ(outputw.SchemeIsFileSystem(), outputw.inner_url() != NULL);
350 }
351 }
352
TEST(GURLTest,GetOrigin)353 TEST(GURLTest, GetOrigin) {
354 struct TestCase {
355 const char* input;
356 const char* expected;
357 } cases[] = {
358 {"http://www.google.com", "http://www.google.com/"},
359 {"javascript:window.alert(\"hello,world\");", ""},
360 {"http://user:pass@www.google.com:21/blah#baz",
361 "http://www.google.com:21/"},
362 {"http://user@www.google.com", "http://www.google.com/"},
363 {"http://:pass@www.google.com", "http://www.google.com/"},
364 {"http://:@www.google.com", "http://www.google.com/"},
365 {"filesystem:http://www.google.com/temp/foo?q#b",
366 "http://www.google.com/"},
367 {"filesystem:http://user:pass@google.com:21/blah#baz",
368 "http://google.com:21/"},
369 {"blob:null/guid-goes-here", ""},
370 {"blob:http://origin/guid-goes-here", "" /* should be http://origin/ */},
371 };
372 for (size_t i = 0; i < base::size(cases); i++) {
373 GURL url(cases[i].input);
374 GURL origin = url.GetOrigin();
375 EXPECT_EQ(cases[i].expected, origin.spec());
376 }
377 }
378
TEST(GURLTest,GetAsReferrer)379 TEST(GURLTest, GetAsReferrer) {
380 struct TestCase {
381 const char* input;
382 const char* expected;
383 } cases[] = {
384 {"http://www.google.com", "http://www.google.com/"},
385 {"http://user:pass@www.google.com:21/blah#baz", "http://www.google.com:21/blah"},
386 {"http://user@www.google.com", "http://www.google.com/"},
387 {"http://:pass@www.google.com", "http://www.google.com/"},
388 {"http://:@www.google.com", "http://www.google.com/"},
389 {"http://www.google.com/temp/foo?q#b", "http://www.google.com/temp/foo?q"},
390 {"not a url", ""},
391 {"unknown-scheme://foo.html", ""},
392 {"file:///tmp/test.html", ""},
393 {"https://www.google.com", "https://www.google.com/"},
394 };
395 for (size_t i = 0; i < base::size(cases); i++) {
396 GURL url(cases[i].input);
397 GURL origin = url.GetAsReferrer();
398 EXPECT_EQ(cases[i].expected, origin.spec());
399 }
400 }
401
TEST(GURLTest,GetWithEmptyPath)402 TEST(GURLTest, GetWithEmptyPath) {
403 struct TestCase {
404 const char* input;
405 const char* expected;
406 } cases[] = {
407 {"http://www.google.com", "http://www.google.com/"},
408 {"javascript:window.alert(\"hello, world\");", ""},
409 {"http://www.google.com/foo/bar.html?baz=22", "http://www.google.com/"},
410 {"filesystem:http://www.google.com/temporary/bar.html?baz=22", "filesystem:http://www.google.com/temporary/"},
411 {"filesystem:file:///temporary/bar.html?baz=22", "filesystem:file:///temporary/"},
412 };
413
414 for (size_t i = 0; i < base::size(cases); i++) {
415 GURL url(cases[i].input);
416 GURL empty_path = url.GetWithEmptyPath();
417 EXPECT_EQ(cases[i].expected, empty_path.spec());
418 }
419 }
420
TEST(GURLTest,GetWithoutFilename)421 TEST(GURLTest, GetWithoutFilename) {
422 struct TestCase {
423 const char* input;
424 const char* expected;
425 } cases[] = {
426 // Common Standard URLs.
427 {"https://www.google.com", "https://www.google.com/"},
428 {"https://www.google.com/", "https://www.google.com/"},
429 {"https://www.google.com/maps.htm", "https://www.google.com/"},
430 {"https://www.google.com/maps/", "https://www.google.com/maps/"},
431 {"https://www.google.com/index.html", "https://www.google.com/"},
432 {"https://www.google.com/index.html?q=maps", "https://www.google.com/"},
433 {"https://www.google.com/index.html#maps/", "https://www.google.com/"},
434 {"https://foo:bar@www.google.com/maps.htm", "https://foo:bar@www.google.com/"},
435 {"https://www.google.com/maps/au/index.html", "https://www.google.com/maps/au/"},
436 {"https://www.google.com/maps/au/north", "https://www.google.com/maps/au/"},
437 {"https://www.google.com/maps/au/north/", "https://www.google.com/maps/au/north/"},
438 {"https://www.google.com/maps/au/index.html?q=maps#fragment/", "https://www.google.com/maps/au/"},
439 {"http://www.google.com:8000/maps/au/index.html?q=maps#fragment/", "http://www.google.com:8000/maps/au/"},
440 {"https://www.google.com/maps/au/north/?q=maps#fragment", "https://www.google.com/maps/au/north/"},
441 {"https://www.google.com/maps/au/north?q=maps#fragment", "https://www.google.com/maps/au/"},
442 // Less common standard URLs.
443 {"filesystem:http://www.google.com/temporary/bar.html?baz=22", "filesystem:http://www.google.com/temporary/"},
444 {"file:///temporary/bar.html?baz=22","file:///temporary/"},
445 {"ftp://foo/test/index.html", "ftp://foo/test/"},
446 {"gopher://foo/test/index.html", "gopher://foo/test/"},
447 {"ws://foo/test/index.html", "ws://foo/test/"},
448 // Non-standard, hierarchical URLs.
449 {"chrome://foo/bar.html", "chrome://foo/"},
450 {"httpa://foo/test/index.html", "httpa://foo/test/"},
451 // Non-standard, non-hierarchical URLs.
452 {"blob:https://foo.bar/test/index.html", ""},
453 {"about:blank", ""},
454 {"data:foobar", ""},
455 {"scheme:opaque_data", ""},
456 // Invalid URLs.
457 {"foobar", ""},
458 };
459
460 for (size_t i = 0; i < base::size(cases); i++) {
461 GURL url(cases[i].input);
462 GURL without_filename = url.GetWithoutFilename();
463 EXPECT_EQ(cases[i].expected, without_filename.spec()) << i;
464 }
465 }
466
TEST(GURLTest,Replacements)467 TEST(GURLTest, Replacements) {
468 // The URL canonicalizer replacement test will handle most of these case.
469 // The most important thing to do here is to check that the proper
470 // canonicalizer gets called based on the scheme of the input.
471 struct ReplaceCase {
472 const char* base;
473 const char* scheme;
474 const char* username;
475 const char* password;
476 const char* host;
477 const char* port;
478 const char* path;
479 const char* query;
480 const char* ref;
481 const char* expected;
482 } replace_cases[] = {
483 {"http://www.google.com/foo/bar.html?foo#bar", NULL, NULL, NULL, NULL,
484 NULL, "/", "", "", "http://www.google.com/"},
485 {"http://www.google.com/foo/bar.html?foo#bar", "javascript", "", "", "",
486 "", "window.open('foo');", "", "", "javascript:window.open('foo');"},
487 {"file:///C:/foo/bar.txt", "http", NULL, NULL, "www.google.com", "99",
488 "/foo", "search", "ref", "http://www.google.com:99/foo?search#ref"},
489 #ifdef WIN32
490 {"http://www.google.com/foo/bar.html?foo#bar", "file", "", "", "", "",
491 "c:\\", "", "", "file:///C:/"},
492 #endif
493 {"filesystem:http://www.google.com/foo/bar.html?foo#bar", NULL, NULL,
494 NULL, NULL, NULL, "/", "", "", "filesystem:http://www.google.com/foo/"},
495 // Lengthen the URL instead of shortening it, to test creation of
496 // inner_url.
497 {"filesystem:http://www.google.com/foo/", NULL, NULL, NULL, NULL, NULL,
498 "bar.html", "foo", "bar",
499 "filesystem:http://www.google.com/foo/bar.html?foo#bar"},
500 };
501
502 for (size_t i = 0; i < base::size(replace_cases); i++) {
503 const ReplaceCase& cur = replace_cases[i];
504 GURL url(cur.base);
505 GURL::Replacements repl;
506 SetupReplacement(&GURL::Replacements::SetScheme, &repl, cur.scheme);
507 SetupReplacement(&GURL::Replacements::SetUsername, &repl, cur.username);
508 SetupReplacement(&GURL::Replacements::SetPassword, &repl, cur.password);
509 SetupReplacement(&GURL::Replacements::SetHost, &repl, cur.host);
510 SetupReplacement(&GURL::Replacements::SetPort, &repl, cur.port);
511 SetupReplacement(&GURL::Replacements::SetPath, &repl, cur.path);
512 SetupReplacement(&GURL::Replacements::SetQuery, &repl, cur.query);
513 SetupReplacement(&GURL::Replacements::SetRef, &repl, cur.ref);
514 GURL output = url.ReplaceComponents(repl);
515
516 EXPECT_EQ(replace_cases[i].expected, output.spec());
517
518 EXPECT_EQ(output.SchemeIsFileSystem(), output.inner_url() != NULL);
519 if (output.SchemeIsFileSystem()) {
520 // TODO(mmenke): inner_url()->spec() is currently the same as the spec()
521 // for the GURL itself. This should be fixed.
522 // See https://crbug.com/619596
523 EXPECT_EQ(replace_cases[i].expected, output.inner_url()->spec());
524 }
525 }
526 }
527
TEST(GURLTest,ClearFragmentOnDataUrl)528 TEST(GURLTest, ClearFragmentOnDataUrl) {
529 // http://crbug.com/291747 - a data URL may legitimately have trailing
530 // whitespace in the spec after the ref is cleared. Test this does not trigger
531 // the Parsed importing validation DCHECK in GURL.
532 GURL url(" data: one ? two # three ");
533
534 // By default the trailing whitespace will have been stripped.
535 EXPECT_EQ("data: one ? two # three", url.spec());
536 GURL::Replacements repl;
537 repl.ClearRef();
538 GURL url_no_ref = url.ReplaceComponents(repl);
539
540 EXPECT_EQ("data: one ? two ", url_no_ref.spec());
541
542 // Importing a parsed URL via this constructor overload will retain trailing
543 // whitespace.
544 GURL import_url(url_no_ref.spec(),
545 url_no_ref.parsed_for_possibly_invalid_spec(),
546 url_no_ref.is_valid());
547 EXPECT_EQ(url_no_ref, import_url);
548 EXPECT_EQ(import_url.query(), " two ");
549 }
550
TEST(GURLTest,PathForRequest)551 TEST(GURLTest, PathForRequest) {
552 struct TestCase {
553 const char* input;
554 const char* expected;
555 const char* inner_expected;
556 } cases[] = {
557 {"http://www.google.com", "/", NULL},
558 {"http://www.google.com/", "/", NULL},
559 {"http://www.google.com/foo/bar.html?baz=22", "/foo/bar.html?baz=22", NULL},
560 {"http://www.google.com/foo/bar.html#ref", "/foo/bar.html", NULL},
561 {"http://www.google.com/foo/bar.html?query#ref", "/foo/bar.html?query", NULL},
562 {"filesystem:http://www.google.com/temporary/foo/bar.html?query#ref", "/foo/bar.html?query", "/temporary"},
563 {"filesystem:http://www.google.com/temporary/foo/bar.html?query", "/foo/bar.html?query", "/temporary"},
564 };
565
566 for (size_t i = 0; i < base::size(cases); i++) {
567 GURL url(cases[i].input);
568 EXPECT_EQ(cases[i].expected, url.PathForRequest());
569 EXPECT_EQ(cases[i].expected, url.PathForRequestPiece());
570 EXPECT_EQ(cases[i].inner_expected == NULL, url.inner_url() == NULL);
571 if (url.inner_url() && cases[i].inner_expected) {
572 EXPECT_EQ(cases[i].inner_expected, url.inner_url()->PathForRequest());
573 EXPECT_EQ(cases[i].inner_expected,
574 url.inner_url()->PathForRequestPiece());
575 }
576 }
577 }
578
TEST(GURLTest,EffectiveIntPort)579 TEST(GURLTest, EffectiveIntPort) {
580 struct PortTest {
581 const char* spec;
582 int expected_int_port;
583 } port_tests[] = {
584 // http
585 {"http://www.google.com/", 80},
586 {"http://www.google.com:80/", 80},
587 {"http://www.google.com:443/", 443},
588
589 // https
590 {"https://www.google.com/", 443},
591 {"https://www.google.com:443/", 443},
592 {"https://www.google.com:80/", 80},
593
594 // ftp
595 {"ftp://www.google.com/", 21},
596 {"ftp://www.google.com:21/", 21},
597 {"ftp://www.google.com:80/", 80},
598
599 // file - no port
600 {"file://www.google.com/", PORT_UNSPECIFIED},
601 {"file://www.google.com:443/", PORT_UNSPECIFIED},
602
603 // data - no port
604 {"data:www.google.com:90", PORT_UNSPECIFIED},
605 {"data:www.google.com", PORT_UNSPECIFIED},
606
607 // filesystem - no port
608 {"filesystem:http://www.google.com:90/t/foo", PORT_UNSPECIFIED},
609 {"filesystem:file:///t/foo", PORT_UNSPECIFIED},
610 };
611
612 for (size_t i = 0; i < base::size(port_tests); i++) {
613 GURL url(port_tests[i].spec);
614 EXPECT_EQ(port_tests[i].expected_int_port, url.EffectiveIntPort());
615 }
616 }
617
TEST(GURLTest,IPAddress)618 TEST(GURLTest, IPAddress) {
619 struct IPTest {
620 const char* spec;
621 bool expected_ip;
622 } ip_tests[] = {
623 {"http://www.google.com/", false},
624 {"http://192.168.9.1/", true},
625 {"http://192.168.9.1.2/", false},
626 {"http://192.168.m.1/", false},
627 {"http://2001:db8::1/", false},
628 {"http://[2001:db8::1]/", true},
629 {"", false},
630 {"some random input!", false},
631 };
632
633 for (size_t i = 0; i < base::size(ip_tests); i++) {
634 GURL url(ip_tests[i].spec);
635 EXPECT_EQ(ip_tests[i].expected_ip, url.HostIsIPAddress());
636 }
637 }
638
TEST(GURLTest,HostNoBrackets)639 TEST(GURLTest, HostNoBrackets) {
640 struct TestCase {
641 const char* input;
642 const char* expected_host;
643 const char* expected_plainhost;
644 } cases[] = {
645 {"http://www.google.com", "www.google.com", "www.google.com"},
646 {"http://[2001:db8::1]/", "[2001:db8::1]", "2001:db8::1"},
647 {"http://[::]/", "[::]", "::"},
648
649 // Don't require a valid URL, but don't crash either.
650 {"http://[]/", "[]", ""},
651 {"http://[x]/", "[x]", "x"},
652 {"http://[x/", "[x", "[x"},
653 {"http://x]/", "x]", "x]"},
654 {"http://[/", "[", "["},
655 {"http://]/", "]", "]"},
656 {"", "", ""},
657 };
658 for (size_t i = 0; i < base::size(cases); i++) {
659 GURL url(cases[i].input);
660 EXPECT_EQ(cases[i].expected_host, url.host());
661 EXPECT_EQ(cases[i].expected_plainhost, url.HostNoBrackets());
662 EXPECT_EQ(cases[i].expected_plainhost, url.HostNoBracketsPiece());
663 }
664 }
665
TEST(GURLTest,DomainIs)666 TEST(GURLTest, DomainIs) {
667 GURL url_1("http://google.com/foo");
668 EXPECT_TRUE(url_1.DomainIs("google.com"));
669
670 // Subdomain and port are ignored.
671 GURL url_2("http://www.google.com:99/foo");
672 EXPECT_TRUE(url_2.DomainIs("google.com"));
673
674 // Different top-level domain.
675 GURL url_3("http://www.google.com.cn/foo");
676 EXPECT_FALSE(url_3.DomainIs("google.com"));
677
678 // Different host name.
679 GURL url_4("http://www.iamnotgoogle.com/foo");
680 EXPECT_FALSE(url_4.DomainIs("google.com"));
681
682 // The input must be lower-cased otherwise DomainIs returns false.
683 GURL url_5("http://www.google.com/foo");
684 EXPECT_FALSE(url_5.DomainIs("Google.com"));
685
686 // If the URL is invalid, DomainIs returns false.
687 GURL invalid_url("google.com");
688 EXPECT_FALSE(invalid_url.is_valid());
689 EXPECT_FALSE(invalid_url.DomainIs("google.com"));
690
691 GURL url_with_escape_chars("https://www.,.test");
692 EXPECT_TRUE(url_with_escape_chars.is_valid());
693 EXPECT_EQ(url_with_escape_chars.host(), "www.%2C.test");
694 EXPECT_TRUE(url_with_escape_chars.DomainIs("%2C.test"));
695 }
696
TEST(GURLTest,DomainIsTerminatingDotBehavior)697 TEST(GURLTest, DomainIsTerminatingDotBehavior) {
698 // If the host part ends with a dot, it matches input domains
699 // with or without a dot.
700 GURL url_with_dot("http://www.google.com./foo");
701 EXPECT_TRUE(url_with_dot.DomainIs("google.com"));
702 EXPECT_TRUE(url_with_dot.DomainIs("google.com."));
703 EXPECT_TRUE(url_with_dot.DomainIs(".com"));
704 EXPECT_TRUE(url_with_dot.DomainIs(".com."));
705
706 // But, if the host name doesn't end with a dot and the input
707 // domain does, then it's considered to not match.
708 GURL url_without_dot("http://google.com/foo");
709 EXPECT_FALSE(url_without_dot.DomainIs("google.com."));
710
711 // If the URL ends with two dots, it doesn't match.
712 GURL url_with_two_dots("http://www.google.com../foo");
713 EXPECT_FALSE(url_with_two_dots.DomainIs("google.com"));
714 }
715
TEST(GURLTest,DomainIsWithFilesystemScheme)716 TEST(GURLTest, DomainIsWithFilesystemScheme) {
717 GURL url_1("filesystem:http://www.google.com:99/foo/");
718 EXPECT_TRUE(url_1.DomainIs("google.com"));
719
720 GURL url_2("filesystem:http://www.iamnotgoogle.com/foo/");
721 EXPECT_FALSE(url_2.DomainIs("google.com"));
722 }
723
724 // Newlines should be stripped from inputs.
TEST(GURLTest,Newlines)725 TEST(GURLTest, Newlines) {
726 // Constructor.
727 GURL url_1(" \t ht\ntp://\twww.goo\rgle.com/as\ndf \n ");
728 EXPECT_EQ("http://www.google.com/asdf", url_1.spec());
729 EXPECT_FALSE(
730 url_1.parsed_for_possibly_invalid_spec().potentially_dangling_markup);
731
732 // Relative path resolver.
733 GURL url_2 = url_1.Resolve(" \n /fo\to\r ");
734 EXPECT_EQ("http://www.google.com/foo", url_2.spec());
735 EXPECT_FALSE(
736 url_2.parsed_for_possibly_invalid_spec().potentially_dangling_markup);
737
738 // Constructor.
739 GURL url_3(" \t ht\ntp://\twww.goo\rgle.com/as\ndf< \n ");
740 EXPECT_EQ("http://www.google.com/asdf%3C", url_3.spec());
741 EXPECT_TRUE(
742 url_3.parsed_for_possibly_invalid_spec().potentially_dangling_markup);
743
744 // Relative path resolver.
745 GURL url_4 = url_1.Resolve(" \n /fo\to<\r ");
746 EXPECT_EQ("http://www.google.com/foo%3C", url_4.spec());
747 EXPECT_TRUE(
748 url_4.parsed_for_possibly_invalid_spec().potentially_dangling_markup);
749
750 // Note that newlines are NOT stripped from ReplaceComponents.
751 }
752
TEST(GURLTest,IsStandard)753 TEST(GURLTest, IsStandard) {
754 GURL a("http:foo/bar");
755 EXPECT_TRUE(a.IsStandard());
756
757 GURL b("foo:bar/baz");
758 EXPECT_FALSE(b.IsStandard());
759
760 GURL c("foo://bar/baz");
761 EXPECT_FALSE(c.IsStandard());
762
763 GURL d("cid:bar@baz");
764 EXPECT_FALSE(d.IsStandard());
765 }
766
TEST(GURLTest,SchemeIsHTTPOrHTTPS)767 TEST(GURLTest, SchemeIsHTTPOrHTTPS) {
768 EXPECT_TRUE(GURL("http://bar/").SchemeIsHTTPOrHTTPS());
769 EXPECT_TRUE(GURL("HTTPS://BAR").SchemeIsHTTPOrHTTPS());
770 EXPECT_FALSE(GURL("ftp://bar/").SchemeIsHTTPOrHTTPS());
771 }
772
TEST(GURLTest,SchemeIsWSOrWSS)773 TEST(GURLTest, SchemeIsWSOrWSS) {
774 EXPECT_TRUE(GURL("WS://BAR/").SchemeIsWSOrWSS());
775 EXPECT_TRUE(GURL("wss://bar/").SchemeIsWSOrWSS());
776 EXPECT_FALSE(GURL("http://bar/").SchemeIsWSOrWSS());
777 }
778
TEST(GURLTest,SchemeIsCryptographic)779 TEST(GURLTest, SchemeIsCryptographic) {
780 EXPECT_TRUE(GURL("https://foo.bar.com/").SchemeIsCryptographic());
781 EXPECT_TRUE(GURL("HTTPS://foo.bar.com/").SchemeIsCryptographic());
782 EXPECT_TRUE(GURL("HtTpS://foo.bar.com/").SchemeIsCryptographic());
783
784 EXPECT_TRUE(GURL("wss://foo.bar.com/").SchemeIsCryptographic());
785 EXPECT_TRUE(GURL("WSS://foo.bar.com/").SchemeIsCryptographic());
786 EXPECT_TRUE(GURL("WsS://foo.bar.com/").SchemeIsCryptographic());
787
788 EXPECT_FALSE(GURL("http://foo.bar.com/").SchemeIsCryptographic());
789 EXPECT_FALSE(GURL("ws://foo.bar.com/").SchemeIsCryptographic());
790 }
791
TEST(GURLTest,SchemeIsCryptographicStatic)792 TEST(GURLTest, SchemeIsCryptographicStatic) {
793 EXPECT_TRUE(GURL::SchemeIsCryptographic("https"));
794 EXPECT_TRUE(GURL::SchemeIsCryptographic("wss"));
795 EXPECT_FALSE(GURL::SchemeIsCryptographic("http"));
796 EXPECT_FALSE(GURL::SchemeIsCryptographic("ws"));
797 EXPECT_FALSE(GURL::SchemeIsCryptographic("ftp"));
798 }
799
TEST(GURLTest,SchemeIsBlob)800 TEST(GURLTest, SchemeIsBlob) {
801 EXPECT_TRUE(GURL("BLOB://BAR/").SchemeIsBlob());
802 EXPECT_TRUE(GURL("blob://bar/").SchemeIsBlob());
803 EXPECT_FALSE(GURL("http://bar/").SchemeIsBlob());
804 }
805
806 // Tests that the 'content' of the URL is properly extracted. This can be
807 // complex in cases such as multiple schemes (view-source:http:) or for
808 // javascript URLs. See GURL::GetContent for more details.
TEST(GURLTest,ContentForNonStandardURLs)809 TEST(GURLTest, ContentForNonStandardURLs) {
810 struct TestCase {
811 const char* url;
812 const char* expected;
813 } cases[] = {
814 {"null", ""},
815 {"not-a-standard-scheme:this is arbitrary content",
816 "this is arbitrary content"},
817
818 // When there are multiple schemes, only the first is excluded from the
819 // content. Note also that for e.g. 'http://', the '//' is part of the
820 // content not the scheme.
821 {"view-source:http://example.com/path", "http://example.com/path"},
822 {"blob:http://example.com/GUID", "http://example.com/GUID"},
823 {"blob://http://example.com/GUID", "//http://example.com/GUID"},
824 {"blob:http://user:password@example.com/GUID",
825 "http://user:password@example.com/GUID"},
826
827 // The octothorpe character ('#') marks the end of the URL content, and
828 // the start of the fragment. It should not be included in the content.
829 {"http://www.example.com/GUID#ref", "www.example.com/GUID"},
830 {"http://me:secret@example.com/GUID/#ref", "me:secret@example.com/GUID/"},
831 {"data:text/html,Question?<div style=\"color: #bad\">idea</div>",
832 "text/html,Question?<div style=\"color: "},
833
834 // TODO(mkwst): This seems like a bug. https://crbug.com/513600
835 {"filesystem:http://example.com/path", "/"},
836
837 // Javascript URLs include '#' symbols in their content.
838 {"javascript:#", "#"},
839 {"javascript:alert('#');", "alert('#');"},
840 };
841
842 for (const auto& test : cases) {
843 GURL url(test.url);
844 EXPECT_EQ(test.expected, url.GetContent()) << test.url;
845 }
846 }
847
848 // Tests that the URL path is properly extracted for unusual URLs. This can be
849 // complex in cases such as multiple schemes (view-source:http:) or when
850 // octothorpes ('#') are involved.
TEST(GURLTest,PathForNonStandardURLs)851 TEST(GURLTest, PathForNonStandardURLs) {
852 struct TestCase {
853 const char* url;
854 const char* expected;
855 } cases[] = {
856 {"null", ""},
857 {"not-a-standard-scheme:this is arbitrary content",
858 "this is arbitrary content"},
859 {"view-source:http://example.com/path", "http://example.com/path"},
860 {"blob:http://example.com/GUID", "http://example.com/GUID"},
861 {"blob://http://example.com/GUID", "//http://example.com/GUID"},
862 {"blob:http://user:password@example.com/GUID",
863 "http://user:password@example.com/GUID"},
864
865 {"http://www.example.com/GUID#ref", "/GUID"},
866 {"http://me:secret@example.com/GUID/#ref", "/GUID/"},
867 {"data:text/html,Question?<div style=\"color: #bad\">idea</div>",
868 "text/html,Question"},
869
870 // TODO(mkwst): This seems like a bug. https://crbug.com/513600
871 {"filesystem:http://example.com/path", "/"},
872 };
873
874 for (const auto& test : cases) {
875 GURL url(test.url);
876 EXPECT_EQ(test.expected, url.path()) << test.url;
877 }
878 }
879
TEST(GURLTest,IsAboutBlank)880 TEST(GURLTest, IsAboutBlank) {
881 const std::string kAboutBlankUrls[] = {"about:blank", "about:blank?foo",
882 "about:blank/#foo",
883 "about:blank?foo#foo"};
884 for (const auto& url : kAboutBlankUrls)
885 EXPECT_TRUE(GURL(url).IsAboutBlank()) << url;
886
887 const std::string kNotAboutBlankUrls[] = {
888 "http:blank", "about:blan", "about://blank",
889 "about:blank/foo", "about://:8000/blank", "about://foo:foo@/blank",
890 "foo@about:blank", "foo:bar@about:blank", "about:blank:8000",
891 "about:blANk"};
892 for (const auto& url : kNotAboutBlankUrls)
893 EXPECT_FALSE(GURL(url).IsAboutBlank()) << url;
894 }
895
TEST(GURLTest,IsAboutSrcdoc)896 TEST(GURLTest, IsAboutSrcdoc) {
897 const std::string kAboutSrcdocUrls[] = {
898 "about:srcdoc", "about:srcdoc/", "about:srcdoc?foo", "about:srcdoc/#foo",
899 "about:srcdoc?foo#foo"};
900 for (const auto& url : kAboutSrcdocUrls)
901 EXPECT_TRUE(GURL(url).IsAboutSrcdoc()) << url;
902
903 const std::string kNotAboutSrcdocUrls[] = {"http:srcdoc",
904 "about:srcdo",
905 "about://srcdoc",
906 "about://srcdoc\\",
907 "about:srcdoc/foo",
908 "about://:8000/srcdoc",
909 "about://foo:foo@/srcdoc",
910 "foo@about:srcdoc",
911 "foo:bar@about:srcdoc",
912 "about:srcdoc:8000",
913 "about:srCDOc"};
914 for (const auto& url : kNotAboutSrcdocUrls)
915 EXPECT_FALSE(GURL(url).IsAboutSrcdoc()) << url;
916 }
917
TEST(GURLTest,EqualsIgnoringRef)918 TEST(GURLTest, EqualsIgnoringRef) {
919 const struct {
920 const char* url_a;
921 const char* url_b;
922 bool are_equals;
923 } kTestCases[] = {
924 // No ref.
925 {"http://a.com", "http://a.com", true},
926 {"http://a.com", "http://b.com", false},
927
928 // Same Ref.
929 {"http://a.com#foo", "http://a.com#foo", true},
930 {"http://a.com#foo", "http://b.com#foo", false},
931
932 // Different Refs.
933 {"http://a.com#foo", "http://a.com#bar", true},
934 {"http://a.com#foo", "http://b.com#bar", false},
935
936 // One has a ref, the other doesn't.
937 {"http://a.com#foo", "http://a.com", true},
938 {"http://a.com#foo", "http://b.com", false},
939
940 // Empty refs.
941 {"http://a.com#", "http://a.com#", true},
942 {"http://a.com#", "http://a.com", true},
943
944 // URLs that differ only by their last character.
945 {"http://aaa", "http://aab", false},
946 {"http://aaa#foo", "http://aab#foo", false},
947
948 // Different size of the part before the ref.
949 {"http://123#a", "http://123456#a", false},
950
951 // Blob URLs
952 {"blob:http://a.com#foo", "blob:http://a.com#foo", true},
953 {"blob:http://a.com#foo", "blob:http://a.com#bar", true},
954 {"blob:http://a.com#foo", "blob:http://b.com#bar", false},
955
956 // Filesystem URLs
957 {"filesystem:http://a.com#foo", "filesystem:http://a.com#foo", true},
958 {"filesystem:http://a.com#foo", "filesystem:http://a.com#bar", true},
959 {"filesystem:http://a.com#foo", "filesystem:http://b.com#bar", false},
960
961 // Data URLs
962 {"data:text/html,a#foo", "data:text/html,a#bar", true},
963 {"data:text/html,a#foo", "data:text/html,a#foo", true},
964 {"data:text/html,a#foo", "data:text/html,b#foo", false},
965 };
966
967 for (const auto& test_case : kTestCases) {
968 SCOPED_TRACE(testing::Message()
969 << std::endl
970 << "url_a = " << test_case.url_a << std::endl
971 << "url_b = " << test_case.url_b << std::endl);
972 // A versus B.
973 EXPECT_EQ(test_case.are_equals,
974 GURL(test_case.url_a).EqualsIgnoringRef(GURL(test_case.url_b)));
975 // B versus A.
976 EXPECT_EQ(test_case.are_equals,
977 GURL(test_case.url_b).EqualsIgnoringRef(GURL(test_case.url_a)));
978 }
979 }
980
TEST(GURLTest,DebugAlias)981 TEST(GURLTest, DebugAlias) {
982 GURL url("https://foo.com/bar");
983 DEBUG_ALIAS_FOR_GURL(url_debug_alias, url);
984 EXPECT_STREQ("https://foo.com/bar", url_debug_alias);
985 }
986
TEST(GURLTest,PortZero)987 TEST(GURLTest, PortZero) {
988 GURL port_zero_url("http://127.0.0.1:0/blah");
989
990 // https://url.spec.whatwg.org/#port-state says that the port 1) consists of
991 // ASCII digits (this excludes negative numbers) and 2) cannot be greater than
992 // 2^16-1. This means that port=0 should be valid.
993 EXPECT_TRUE(port_zero_url.is_valid());
994 EXPECT_EQ("0", port_zero_url.port());
995 EXPECT_EQ("127.0.0.1", port_zero_url.host());
996 EXPECT_EQ("http", port_zero_url.scheme());
997
998 // https://crbug.com/1065532: SchemeHostPort would previously incorrectly
999 // consider port=0 to be invalid.
1000 SchemeHostPort scheme_host_port(port_zero_url);
1001 EXPECT_TRUE(scheme_host_port.IsValid());
1002 EXPECT_EQ(port_zero_url.scheme(), scheme_host_port.scheme());
1003 EXPECT_EQ(port_zero_url.host(), scheme_host_port.host());
1004 EXPECT_EQ(port_zero_url.port(),
1005 base::NumberToString(scheme_host_port.port()));
1006
1007 // https://crbug.com/1065532: The SchemeHostPort problem above would lead to
1008 // bizarre results below - resolved origin would incorrectly be returned as an
1009 // opaque origin derived from |another_origin|.
1010 url::Origin another_origin = url::Origin::Create(GURL("http://other.com"));
1011 url::Origin resolved_origin =
1012 url::Origin::Resolve(port_zero_url, another_origin);
1013 EXPECT_FALSE(resolved_origin.opaque());
1014 EXPECT_EQ(port_zero_url.scheme(), resolved_origin.scheme());
1015 EXPECT_EQ(port_zero_url.host(), resolved_origin.host());
1016 EXPECT_EQ(port_zero_url.port(), base::NumberToString(resolved_origin.port()));
1017
1018 // port=0 and default HTTP port are different.
1019 GURL default_port("http://127.0.0.1/foo");
1020 EXPECT_EQ(0, SchemeHostPort(port_zero_url).port());
1021 EXPECT_EQ(80, SchemeHostPort(default_port).port());
1022 url::Origin default_port_origin = url::Origin::Create(default_port);
1023 EXPECT_FALSE(default_port_origin.IsSameOriginWith(resolved_origin));
1024 }
1025
1026 } // namespace url
1027