| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "url/url_parse.h" | 5 #include "url/third_party/mozilla/url_parse.h" |
| 6 | 6 |
| 7 #include "base/macros.h" | 7 #include "base/macros.h" |
| 8 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
| 9 #include "url/url_parse.h" | 9 #include "url/third_party/mozilla/url_parse.h" |
| 10 | 10 |
| 11 // Interesting IE file:isms... | 11 // Interesting IE file:isms... |
| 12 // | 12 // |
| 13 // file:/foo/bar file:///foo/bar | 13 // file:/foo/bar file:///foo/bar |
| 14 // The result here seems totally invalid!?!? This isn't UNC. | 14 // The result here seems totally invalid!?!? This isn't UNC. |
| 15 // | 15 // |
| 16 // file:/ | 16 // file:/ |
| 17 // file:// or any other number of slashes | 17 // file:// or any other number of slashes |
| 18 // IE6 doesn't do anything at all if you click on this link. No error: | 18 // IE6 doesn't do anything at all if you click on this link. No error: |
| 19 // nothing. IE6's history system seems to always color this link, so I'm | 19 // nothing. IE6's history system seems to always color this link, so I'm |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 int inner_port; | 83 int inner_port; |
| 84 const char* inner_path; | 84 const char* inner_path; |
| 85 const char* path; | 85 const char* path; |
| 86 const char* query; | 86 const char* query; |
| 87 const char* ref; | 87 const char* ref; |
| 88 }; | 88 }; |
| 89 | 89 |
| 90 bool ComponentMatches(const char* input, | 90 bool ComponentMatches(const char* input, |
| 91 const char* reference, | 91 const char* reference, |
| 92 const Component& component) { | 92 const Component& component) { |
| 93 // If the component is nonexistant (length == -1), it should begin at 0. | 93 // If the component is nonexistent (length == -1), it should begin at 0. |
| 94 EXPECT_TRUE(component.len >= 0 || component.len == -1); | 94 EXPECT_TRUE(component.len >= 0 || component.len == -1); |
| 95 | 95 |
| 96 // Begin should be valid. | 96 // Begin should be valid. |
| 97 EXPECT_LE(0, component.begin); | 97 EXPECT_LE(0, component.begin); |
| 98 | 98 |
| 99 // A NULL reference means the component should be nonexistant. | 99 // A NULL reference means the component should be nonexistent. |
| 100 if (!reference) | 100 if (!reference) |
| 101 return component.len == -1; | 101 return component.len == -1; |
| 102 if (component.len < 0) | 102 if (component.len < 0) |
| 103 return false; // Reference is not NULL but we don't have anything | 103 return false; // Reference is not NULL but we don't have anything |
| 104 | 104 |
| 105 if (strlen(reference) != static_cast<size_t>(component.len)) | 105 if (strlen(reference) != static_cast<size_t>(component.len)) |
| 106 return false; // Lengths don't match | 106 return false; // Lengths don't match |
| 107 | 107 |
| 108 // Now check the actual characters. | 108 // Now check the actual characters. |
| 109 return strncmp(reference, &input[component.begin], component.len) == 0; | 109 return strncmp(reference, &input[component.begin], component.len) == 0; |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 {"/", NULL, "/"}, | 338 {"/", NULL, "/"}, |
| 339 {" This is \\interesting// \t", NULL, "This is \\interestin
g// \t"}, | 339 {" This is \\interesting// \t", NULL, "This is \\interestin
g// \t"}, |
| 340 {"about:", "about", NULL}, | 340 {"about:", "about", NULL}, |
| 341 {"about:blank", "about", "blank"}, | 341 {"about:blank", "about", "blank"}, |
| 342 {" about: blank ", "about", " blank "}, | 342 {" about: blank ", "about", " blank "}, |
| 343 {"javascript :alert(\"He:/l\\l#o?foo\"); ", "javascript ", "alert(\"He:/l\\l#o?f
oo\"); "}, | 343 {"javascript :alert(\"He:/l\\l#o?foo\"); ", "javascript ", "alert(\"He:/l\\l#o?f
oo\"); "}, |
| 344 }; | 344 }; |
| 345 | 345 |
| 346 TEST(URLParser, PathURL) { | 346 TEST(URLParser, PathURL) { |
| 347 // Declared outside for loop to try to catch cases in init() where we forget | 347 // Declared outside for loop to try to catch cases in init() where we forget |
| 348 // to reset something that is reset by the construtor. | 348 // to reset something that is reset by the constructor. |
| 349 Parsed parsed; | 349 Parsed parsed; |
| 350 for (size_t i = 0; i < arraysize(path_cases); i++) { | 350 for (size_t i = 0; i < arraysize(path_cases); i++) { |
| 351 const char* url = path_cases[i].input; | 351 const char* url = path_cases[i].input; |
| 352 ParsePathURL(url, static_cast<int>(strlen(url)), false, &parsed); | 352 ParsePathURL(url, static_cast<int>(strlen(url)), false, &parsed); |
| 353 | 353 |
| 354 EXPECT_TRUE(ComponentMatches(url, path_cases[i].scheme, parsed.scheme)) | 354 EXPECT_TRUE(ComponentMatches(url, path_cases[i].scheme, parsed.scheme)) |
| 355 << i; | 355 << i; |
| 356 EXPECT_TRUE(ComponentMatches(url, path_cases[i].path, parsed.GetContent())) | 356 EXPECT_TRUE(ComponentMatches(url, path_cases[i].path, parsed.GetContent())) |
| 357 << i; | 357 << i; |
| 358 | 358 |
| 359 // The remaining components are never used for path urls. | 359 // The remaining components are never used for path URLs. |
| 360 ExpectInvalidComponent(parsed.username); | 360 ExpectInvalidComponent(parsed.username); |
| 361 ExpectInvalidComponent(parsed.password); | 361 ExpectInvalidComponent(parsed.password); |
| 362 ExpectInvalidComponent(parsed.host); | 362 ExpectInvalidComponent(parsed.host); |
| 363 ExpectInvalidComponent(parsed.port); | 363 ExpectInvalidComponent(parsed.port); |
| 364 } | 364 } |
| 365 } | 365 } |
| 366 | 366 |
| 367 // Various incarnations of file URLs. | 367 // Various incarnations of file URLs. |
| 368 static URLParseCase file_cases[] = { | 368 static URLParseCase file_cases[] = { |
| 369 #ifdef WIN32 | 369 #ifdef WIN32 |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 const char* expected_value) { | 530 const char* expected_value) { |
| 531 Parsed parsed; | 531 Parsed parsed; |
| 532 ParseStandardURL(url, static_cast<int>(strlen(url)), &parsed); | 532 ParseStandardURL(url, static_cast<int>(strlen(url)), &parsed); |
| 533 | 533 |
| 534 Component query = parsed.query; | 534 Component query = parsed.query; |
| 535 | 535 |
| 536 for (int i = 1; i <= parameter; i++) { | 536 for (int i = 1; i <= parameter; i++) { |
| 537 Component key, value; | 537 Component key, value; |
| 538 if (!ExtractQueryKeyValue(url, &query, &key, &value)) { | 538 if (!ExtractQueryKeyValue(url, &query, &key, &value)) { |
| 539 if (parameter >= i && !expected_key) | 539 if (parameter >= i && !expected_key) |
| 540 return true; // Expected nonexistant key, got one. | 540 return true; // Expected nonexistent key, got one. |
| 541 return false; // Not enough keys. | 541 return false; // Not enough keys. |
| 542 } | 542 } |
| 543 | 543 |
| 544 if (i == parameter) { | 544 if (i == parameter) { |
| 545 if (!expected_key) | 545 if (!expected_key) |
| 546 return false; | 546 return false; |
| 547 | 547 |
| 548 if (strncmp(&url[key.begin], expected_key, key.len) != 0) | 548 if (strncmp(&url[key.begin], expected_key, key.len) != 0) |
| 549 return false; | 549 return false; |
| 550 if (strncmp(&url[value.begin], expected_value, value.len) != 0) | 550 if (strncmp(&url[value.begin], expected_value, value.len) != 0) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 {"mailto:addr1:addr2 ", "mailto", "addr1:addr2", NULL}, | 606 {"mailto:addr1:addr2 ", "mailto", "addr1:addr2", NULL}, |
| 607 {"mailto:?to=addr1,addr2", "mailto", NULL, "to=addr1,addr2"}, | 607 {"mailto:?to=addr1,addr2", "mailto", NULL, "to=addr1,addr2"}, |
| 608 {"mailto:?to=addr1%2C%20addr2", "mailto", NULL, "to=addr1%2C%20add
r2"}, | 608 {"mailto:?to=addr1%2C%20addr2", "mailto", NULL, "to=addr1%2C%20add
r2"}, |
| 609 {"mailto:addr1?to=addr2", "mailto", "addr1", "to=addr2"}, | 609 {"mailto:addr1?to=addr2", "mailto", "addr1", "to=addr2"}, |
| 610 {"mailto:?body=#foobar#", "mailto", NULL, "body=#foobar#",}, | 610 {"mailto:?body=#foobar#", "mailto", NULL, "body=#foobar#",}, |
| 611 {"mailto:#?body=#foobar#", "mailto", "#", "body=#foobar#"}, | 611 {"mailto:#?body=#foobar#", "mailto", "#", "body=#foobar#"}, |
| 612 }; | 612 }; |
| 613 | 613 |
| 614 TEST(URLParser, MailtoUrl) { | 614 TEST(URLParser, MailtoUrl) { |
| 615 // Declared outside for loop to try to catch cases in init() where we forget | 615 // Declared outside for loop to try to catch cases in init() where we forget |
| 616 // to reset something that is reset by the construtor. | 616 // to reset something that is reset by the constructor. |
| 617 Parsed parsed; | 617 Parsed parsed; |
| 618 for (size_t i = 0; i < arraysize(mailto_cases); ++i) { | 618 for (size_t i = 0; i < arraysize(mailto_cases); ++i) { |
| 619 const char* url = mailto_cases[i].input; | 619 const char* url = mailto_cases[i].input; |
| 620 ParseMailtoURL(url, static_cast<int>(strlen(url)), &parsed); | 620 ParseMailtoURL(url, static_cast<int>(strlen(url)), &parsed); |
| 621 int port = ParsePort(url, parsed.port); | 621 int port = ParsePort(url, parsed.port); |
| 622 | 622 |
| 623 EXPECT_TRUE(ComponentMatches(url, mailto_cases[i].scheme, parsed.scheme)); | 623 EXPECT_TRUE(ComponentMatches(url, mailto_cases[i].scheme, parsed.scheme)); |
| 624 EXPECT_TRUE(ComponentMatches(url, mailto_cases[i].path, parsed.path)); | 624 EXPECT_TRUE(ComponentMatches(url, mailto_cases[i].path, parsed.path)); |
| 625 EXPECT_TRUE(ComponentMatches(url, mailto_cases[i].query, parsed.query)); | 625 EXPECT_TRUE(ComponentMatches(url, mailto_cases[i].query, parsed.query)); |
| 626 EXPECT_EQ(PORT_UNSPECIFIED, port); | 626 EXPECT_EQ(PORT_UNSPECIFIED, port); |
| 627 | 627 |
| 628 // The remaining components are never used for mailto urls. | 628 // The remaining components are never used for mailto URLs. |
| 629 ExpectInvalidComponent(parsed.username); | 629 ExpectInvalidComponent(parsed.username); |
| 630 ExpectInvalidComponent(parsed.password); | 630 ExpectInvalidComponent(parsed.password); |
| 631 ExpectInvalidComponent(parsed.port); | 631 ExpectInvalidComponent(parsed.port); |
| 632 ExpectInvalidComponent(parsed.ref); | 632 ExpectInvalidComponent(parsed.ref); |
| 633 } | 633 } |
| 634 } | 634 } |
| 635 | 635 |
| 636 // Various incarnations of filesystem URLs. | 636 // Various incarnations of filesystem URLs. |
| 637 static FileSystemURLParseCase filesystem_cases[] = { | 637 static FileSystemURLParseCase filesystem_cases[] = { |
| 638 // Regular URL with all the parts | 638 // Regular URL with all the parts |
| 639 {"filesystem:http://user:pass@foo:21/temporary/bar;par?b#c", "http", "user", "p
ass", "foo", 21, "/temporary", "/bar;par", "b", "c"}, | 639 {"filesystem:http://user:pass@foo:21/temporary/bar;par?b#c", "http", "user", "p
ass", "foo", 21, "/temporary", "/bar;par", "b", "c"}, |
| 640 {"filesystem:https://foo/persistent/bar;par/", "https", NULL, NU
LL, "foo", -1, "/persistent", "/bar;par/", NULL, NULL}, | 640 {"filesystem:https://foo/persistent/bar;par/", "https", NULL, NU
LL, "foo", -1, "/persistent", "/bar;par/", NULL, NULL}, |
| 641 {"filesystem:file:///persistent/bar;par/", "file", NULL, NU
LL, NULL, -1, "/persistent", "/bar;par/", NULL, NULL}, | 641 {"filesystem:file:///persistent/bar;par/", "file", NULL, NU
LL, NULL, -1, "/persistent", "/bar;par/", NULL, NULL}, |
| 642 {"filesystem:file:///persistent/bar;par/?query#ref", "file", N
ULL, NULL, NULL, -1, "/persistent", "/bar;par/", "query", "ref"}, | 642 {"filesystem:file:///persistent/bar;par/?query#ref", "file", N
ULL, NULL, NULL, -1, "/persistent", "/bar;par/", "query", "ref"}, |
| 643 {"filesystem:file:///persistent", "file", NULL, NU
LL, NULL, -1, "/persistent", "", NULL, NULL}, | 643 {"filesystem:file:///persistent", "file", NULL, NU
LL, NULL, -1, "/persistent", "", NULL, NULL}, |
| 644 }; | 644 }; |
| 645 | 645 |
| 646 TEST(URLParser, FileSystemURL) { | 646 TEST(URLParser, FileSystemURL) { |
| 647 // Declared outside for loop to try to catch cases in init() where we forget | 647 // Declared outside for loop to try to catch cases in init() where we forget |
| 648 // to reset something that is reset by the construtor. | 648 // to reset something that is reset by the constructor. |
| 649 Parsed parsed; | 649 Parsed parsed; |
| 650 for (size_t i = 0; i < arraysize(filesystem_cases); i++) { | 650 for (size_t i = 0; i < arraysize(filesystem_cases); i++) { |
| 651 const FileSystemURLParseCase* parsecase = &filesystem_cases[i]; | 651 const FileSystemURLParseCase* parsecase = &filesystem_cases[i]; |
| 652 const char* url = parsecase->input; | 652 const char* url = parsecase->input; |
| 653 ParseFileSystemURL(url, static_cast<int>(strlen(url)), &parsed); | 653 ParseFileSystemURL(url, static_cast<int>(strlen(url)), &parsed); |
| 654 | 654 |
| 655 EXPECT_TRUE(ComponentMatches(url, "filesystem", parsed.scheme)); | 655 EXPECT_TRUE(ComponentMatches(url, "filesystem", parsed.scheme)); |
| 656 EXPECT_EQ(!parsecase->inner_scheme, !parsed.inner_parsed()); | 656 EXPECT_EQ(!parsecase->inner_scheme, !parsed.inner_parsed()); |
| 657 // Only check the inner_parsed if there is one. | 657 // Only check the inner_parsed if there is one. |
| 658 if (parsed.inner_parsed()) { | 658 if (parsed.inner_parsed()) { |
| 659 EXPECT_TRUE(ComponentMatches(url, parsecase->inner_scheme, | 659 EXPECT_TRUE(ComponentMatches(url, parsecase->inner_scheme, |
| 660 parsed.inner_parsed()->scheme)); | 660 parsed.inner_parsed()->scheme)); |
| 661 EXPECT_TRUE(ComponentMatches(url, parsecase->inner_username, | 661 EXPECT_TRUE(ComponentMatches(url, parsecase->inner_username, |
| 662 parsed.inner_parsed()->username)); | 662 parsed.inner_parsed()->username)); |
| 663 EXPECT_TRUE(ComponentMatches(url, parsecase->inner_password, | 663 EXPECT_TRUE(ComponentMatches(url, parsecase->inner_password, |
| 664 parsed.inner_parsed()->password)); | 664 parsed.inner_parsed()->password)); |
| 665 EXPECT_TRUE(ComponentMatches(url, parsecase->inner_host, | 665 EXPECT_TRUE(ComponentMatches(url, parsecase->inner_host, |
| 666 parsed.inner_parsed()->host)); | 666 parsed.inner_parsed()->host)); |
| 667 int port = ParsePort(url, parsed.inner_parsed()->port); | 667 int port = ParsePort(url, parsed.inner_parsed()->port); |
| 668 EXPECT_EQ(parsecase->inner_port, port); | 668 EXPECT_EQ(parsecase->inner_port, port); |
| 669 | 669 |
| 670 // The remaining components are never used for filesystem urls. | 670 // The remaining components are never used for filesystem URLs. |
| 671 ExpectInvalidComponent(parsed.inner_parsed()->query); | 671 ExpectInvalidComponent(parsed.inner_parsed()->query); |
| 672 ExpectInvalidComponent(parsed.inner_parsed()->ref); | 672 ExpectInvalidComponent(parsed.inner_parsed()->ref); |
| 673 } | 673 } |
| 674 | 674 |
| 675 EXPECT_TRUE(ComponentMatches(url, parsecase->path, parsed.path)); | 675 EXPECT_TRUE(ComponentMatches(url, parsecase->path, parsed.path)); |
| 676 EXPECT_TRUE(ComponentMatches(url, parsecase->query, parsed.query)); | 676 EXPECT_TRUE(ComponentMatches(url, parsecase->query, parsed.query)); |
| 677 EXPECT_TRUE(ComponentMatches(url, parsecase->ref, parsed.ref)); | 677 EXPECT_TRUE(ComponentMatches(url, parsecase->ref, parsed.ref)); |
| 678 | 678 |
| 679 // The remaining components are never used for filesystem urls. | 679 // The remaining components are never used for filesystem URLs. |
| 680 ExpectInvalidComponent(parsed.username); | 680 ExpectInvalidComponent(parsed.username); |
| 681 ExpectInvalidComponent(parsed.password); | 681 ExpectInvalidComponent(parsed.password); |
| 682 ExpectInvalidComponent(parsed.host); | 682 ExpectInvalidComponent(parsed.host); |
| 683 ExpectInvalidComponent(parsed.port); | 683 ExpectInvalidComponent(parsed.port); |
| 684 } | 684 } |
| 685 } | 685 } |
| 686 | 686 |
| 687 } // namespace | 687 } // namespace |
| 688 } // namespace url | 688 } // namespace url |
| OLD | NEW |