1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "url/url_canon.h" 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "url/url_canon_stdstring.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "url/url_parse.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "url/url_test_utils.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "url/url_util.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochnamespace url { 130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(URLUtilTest, FindAndCompareScheme) { 150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Component found_scheme; 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Simple case where the scheme is found and matches. 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char kStr1[] = "http://www.com/"; 190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(FindAndCompareScheme( 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kStr1, static_cast<int>(strlen(kStr1)), "http", NULL)); 210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(FindAndCompareScheme( 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kStr1, static_cast<int>(strlen(kStr1)), "http", &found_scheme)); 230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(found_scheme == Component(0, 4)); 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // A case where the scheme is found and doesn't match. 260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_FALSE(FindAndCompareScheme( 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kStr1, static_cast<int>(strlen(kStr1)), "https", &found_scheme)); 280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(found_scheme == Component(0, 4)); 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // A case where there is no scheme. 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char kStr2[] = "httpfoobar"; 320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_FALSE(FindAndCompareScheme( 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kStr2, static_cast<int>(strlen(kStr2)), "http", &found_scheme)); 340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(found_scheme == Component()); 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // When there is an empty scheme, it should match the empty scheme. 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char kStr3[] = ":foo.com/"; 380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(FindAndCompareScheme( 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kStr3, static_cast<int>(strlen(kStr3)), "", &found_scheme)); 400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(found_scheme == Component(0, 0)); 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // But when there is no scheme, it should fail. 430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_FALSE(FindAndCompareScheme("", 0, "", &found_scheme)); 440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(found_scheme == Component()); 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // When there is a whitespace char in scheme, it should canonicalize the url 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // before comparison. 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char whtspc_str[] = " \r\n\tjav\ra\nscri\tpt:alert(1)"; 490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(FindAndCompareScheme(whtspc_str, 500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch static_cast<int>(strlen(whtspc_str)), 510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch "javascript", &found_scheme)); 520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(found_scheme == Component(1, 10)); 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Control characters should be stripped out on the ends, and kept in the 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // middle. 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char ctrl_str[] = "\02jav\02scr\03ipt:alert(1)"; 570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_FALSE(FindAndCompareScheme(ctrl_str, 580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch static_cast<int>(strlen(ctrl_str)), 590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch "javascript", &found_scheme)); 600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_TRUE(found_scheme == Component(1, 11)); 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(URLUtilTest, ReplaceComponents) { 640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Parsed parsed; 650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RawCanonOutputT<char> output; 660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Parsed new_parsed; 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check that the following calls do not cause crash 690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Replacements<char> replacements; 700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch replacements.SetRef("test", Component(0, 4)); 710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReplaceComponents(NULL, 0, parsed, replacements, NULL, &output, &new_parsed); 720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReplaceComponents("", 0, parsed, replacements, NULL, &output, &new_parsed); 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replacements.ClearRef(); 740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch replacements.SetHost("test", Component(0, 4)); 750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReplaceComponents(NULL, 0, parsed, replacements, NULL, &output, &new_parsed); 760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReplaceComponents("", 0, parsed, replacements, NULL, &output, &new_parsed); 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replacements.ClearHost(); 790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReplaceComponents(NULL, 0, parsed, replacements, NULL, &output, &new_parsed); 800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReplaceComponents("", 0, parsed, replacements, NULL, &output, &new_parsed); 810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReplaceComponents(NULL, 0, parsed, replacements, NULL, &output, &new_parsed); 820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReplaceComponents("", 0, parsed, replacements, NULL, &output, &new_parsed); 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static std::string CheckReplaceScheme(const char* base_url, 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* scheme) { 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Make sure the input is canonicalized. 880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RawCanonOutput<32> original; 890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Parsed original_parsed; 900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Canonicalize(base_url, strlen(base_url), true, NULL, &original, 910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &original_parsed); 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Replacements<char> replacements; 940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch replacements.SetScheme(scheme, Component(0, strlen(scheme))); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string output_string; 970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch StdStringCanonOutput output(&output_string); 980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Parsed output_parsed; 990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ReplaceComponents(original.data(), original.length(), original_parsed, 1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch replacements, NULL, &output, &output_parsed); 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output.Complete(); 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return output_string; 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(URLUtilTest, ReplaceScheme) { 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ("https://google.com/", 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckReplaceScheme("http://google.com/", "https")); 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ("file://google.com/", 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckReplaceScheme("http://google.com/", "file")); 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ("http://home/Build", 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckReplaceScheme("file:///Home/Build", "http")); 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ("javascript:foo", 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckReplaceScheme("about:foo", "javascript")); 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ("://google.com/", 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckReplaceScheme("http://google.com/", "")); 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ("http://google.com/", 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckReplaceScheme("about:google.com", "http")); 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ("http:", CheckReplaceScheme("", "http")); 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef WIN32 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Magic Windows drive letter behavior when converting to a file URL. 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ("file:///E:/foo/", 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckReplaceScheme("http://localhost/e:foo/", "file")); 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // This will probably change to "about://google.com/" when we fix 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // http://crbug.com/160 which should also be an acceptable result. 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ("about://google.com/", 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckReplaceScheme("http://google.com/", "about")); 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_EQ("http://example.com/%20hello%20# world", 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CheckReplaceScheme("myscheme:example.com/ hello # world ", "http")); 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(URLUtilTest, DecodeURLEscapeSequences) { 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) struct DecodeCase { 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* input; 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* output; 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } decode_cases[] = { 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"hello, world", "hello, world"}, 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"%01%02%03%04%05%06%07%08%09%0a%0B%0C%0D%0e%0f/", 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0B\x0C\x0D\x0e\x0f/"}, 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"%10%11%12%13%14%15%16%17%18%19%1a%1B%1C%1D%1e%1f/", 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1B\x1C\x1D\x1e\x1f/"}, 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"%20%21%22%23%24%25%26%27%28%29%2a%2B%2C%2D%2e%2f/", 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) " !\"#$%&'()*+,-.//"}, 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"%30%31%32%33%34%35%36%37%38%39%3a%3B%3C%3D%3e%3f/", 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "0123456789:;<=>?/"}, 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"%40%41%42%43%44%45%46%47%48%49%4a%4B%4C%4D%4e%4f/", 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "@ABCDEFGHIJKLMNO/"}, 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"%50%51%52%53%54%55%56%57%58%59%5a%5B%5C%5D%5e%5f/", 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "PQRSTUVWXYZ[\\]^_/"}, 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"%60%61%62%63%64%65%66%67%68%69%6a%6B%6C%6D%6e%6f/", 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "`abcdefghijklmno/"}, 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"%70%71%72%73%74%75%76%77%78%79%7a%7B%7C%7D%7e%7f/", 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "pqrstuvwxyz{|}~\x7f/"}, 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Test un-UTF-8-ization. 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"%e4%bd%a0%e5%a5%bd", "\xe4\xbd\xa0\xe5\xa5\xbd"}, 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < ARRAYSIZE_UNSAFE(decode_cases); i++) { 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* input = decode_cases[i].input; 1640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RawCanonOutputT<base::char16> output; 1650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DecodeURLEscapeSequences(input, strlen(input), &output); 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(decode_cases[i].output, 1670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch test_utils::ConvertUTF16ToUTF8(base::string16(output.data(), 1680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch output.length()))); 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Our decode should decode %00 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char zero_input[] = "%00"; 1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RawCanonOutputT<base::char16> zero_output; 1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DecodeURLEscapeSequences(zero_input, strlen(zero_input), &zero_output); 1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EXPECT_NE("%00", test_utils::ConvertUTF16ToUTF8( 1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base::string16(zero_output.data(), zero_output.length()))); 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Test the error behavior for invalid UTF-8. 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char invalid_input[] = "%e4%a0%e5%a5%bd"; 1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::char16 invalid_expected[4] = {0x00e4, 0x00a0, 0x597d, 0}; 1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RawCanonOutputT<base::char16> invalid_output; 1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DecodeURLEscapeSequences(invalid_input, strlen(invalid_input), 1830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &invalid_output); 1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EXPECT_EQ(base::string16(invalid_expected), 1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::string16(invalid_output.data(), invalid_output.length())); 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(URLUtilTest, TestEncodeURIComponent) { 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) struct EncodeCase { 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* input; 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* output; 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } encode_cases[] = { 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"hello, world", "hello%2C%20world"}, 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F"}, 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F"}, 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {" !\"#$%&'()*+,-./", 19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) "%20!%22%23%24%25%26%27()*%2B%2C-.%2F"}, 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"0123456789:;<=>?", 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "0123456789%3A%3B%3C%3D%3E%3F"}, 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"@ABCDEFGHIJKLMNO", 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "%40ABCDEFGHIJKLMNO"}, 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"PQRSTUVWXYZ[\\]^_", 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "PQRSTUVWXYZ%5B%5C%5D%5E_"}, 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"`abcdefghijklmno", 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "%60abcdefghijklmno"}, 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"pqrstuvwxyz{|}~\x7f", 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "pqrstuvwxyz%7B%7C%7D~%7F"}, 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < ARRAYSIZE_UNSAFE(encode_cases); i++) { 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* input = encode_cases[i].input; 2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RawCanonOutputT<char> buffer; 2150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch EncodeURIComponent(input, strlen(input), &buffer); 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string output(buffer.data(), buffer.length()); 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(encode_cases[i].output, output); 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST(URLUtilTest, TestResolveRelativeWithNonStandardBase) { 2220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // This tests non-standard (in the sense that GIsStandard() == false) 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // hierarchical schemes. 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) struct ResolveRelativeCase { 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* base; 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* rel; 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool is_valid; 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* out; 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } resolve_non_standard_cases[] = { 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Resolving a relative path against a non-hierarchical URL should fail. 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"scheme:opaque_data", "/path", false, ""}, 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Resolving a relative path against a non-standard authority-based base 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // URL doesn't alter the authority section. 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"scheme://Authority/", "../path", true, "scheme://Authority/path"}, 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // A non-standard hierarchical base is resolved with path URL 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // canoncialization rules. 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"data:/Blah:Blah/", "file.html", true, "data:/Blah:Blah/file.html"}, 2383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {"data:/Path/../part/part2", "file.html", true, 2393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "data:/Path/../part/file.html"}, 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Path URL canonicalization rules also apply to non-standard authority- 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // based URLs. 2423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {"custom://Authority/", "file.html", true, 2433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "custom://Authority/file.html"}, 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"custom://Authority/", "other://Auth/", true, "other://Auth/"}, 2453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {"custom://Authority/", "../../file.html", true, 2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "custom://Authority/file.html"}, 2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {"custom://Authority/path/", "file.html", true, 2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "custom://Authority/path/file.html"}, 2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {"custom://Authority:NoCanon/path/", "file.html", true, 2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "custom://Authority:NoCanon/path/file.html"}, 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // It's still possible to get an invalid path URL. 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"custom://Invalid:!#Auth/", "file.html", false, ""}, 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // A path with an authority section gets canonicalized under standard URL 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // rules, even though the base was non-standard. 2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {"content://content.Provider/", "//other.Provider", true, 2563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "content://other.provider/"}, 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Resolving an absolute URL doesn't cause canonicalization of the 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // result. 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"about:blank", "custom://Authority", true, "custom://Authority"}, 2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Fragment URLs can be resolved against a non-standard base. 2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {"scheme://Authority/path", "#fragment", true, 2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "scheme://Authority/path#fragment"}, 2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) {"scheme://Authority/", "#fragment", true, "scheme://Authority/#fragment"}, 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Resolving should fail if the base URL is authority-based but is 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // missing a path component (the '/' at the end). 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) {"scheme://Authority", "path", false, ""}, 267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Test resolving a fragment (only) against any kind of base-URL. 268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {"about:blank", "#id42", true, "about:blank#id42" }, 269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {"about:blank", " #id42", true, "about:blank#id42" }, 270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {"about:blank#oldfrag", "#newfrag", true, "about:blank#newfrag" }, 271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // A surprising side effect of allowing fragments to resolve against 272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // any URL scheme is we might break javascript: URLs by doing so... 273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {"javascript:alert('foo#bar')", "#badfrag", true, 274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "javascript:alert('foo#badfrag" }, 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < ARRAYSIZE_UNSAFE(resolve_non_standard_cases); i++) { 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ResolveRelativeCase& test_data = resolve_non_standard_cases[i]; 2790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Parsed base_parsed; 2800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ParsePathURL(test_data.base, strlen(test_data.base), false, &base_parsed); 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string resolved; 2830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch StdStringCanonOutput output(&resolved); 2840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Parsed resolved_parsed; 2850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool valid = ResolveRelative(test_data.base, strlen(test_data.base), 2860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch base_parsed, test_data.rel, 2870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch strlen(test_data.rel), NULL, &output, 2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &resolved_parsed); 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output.Complete(); 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(test_data.is_valid, valid) << i; 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (test_data.is_valid && valid) 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(test_data.out, resolved) << i; 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 2960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} // namespace url 298