OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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 <stdlib.h> |
| 6 |
| 7 #include "base/base_paths.h" |
| 8 #include "base/basictypes.h" |
| 9 #include "base/files/file_path.h" |
| 10 #include "base/files/file_util.h" |
| 11 #include "base/files/scoped_temp_dir.h" |
| 12 #include "base/strings/string_util.h" |
| 13 #include "base/strings/utf_string_conversions.h" |
| 14 #include "components/url_fixer/url_fixer.h" |
| 15 #include "net/base/filename_util.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" |
| 17 #include "url/gurl.h" |
| 18 #include "url/third_party/mozilla/url_parse.h" |
| 19 |
| 20 namespace url { |
| 21 |
| 22 std::ostream& operator<<(std::ostream& os, const Component& part) { |
| 23 return os << "(begin=" << part.begin << ", len=" << part.len << ")"; |
| 24 } |
| 25 |
| 26 } // namespace url |
| 27 |
| 28 struct SegmentCase { |
| 29 const std::string input; |
| 30 const std::string result; |
| 31 const url::Component scheme; |
| 32 const url::Component username; |
| 33 const url::Component password; |
| 34 const url::Component host; |
| 35 const url::Component port; |
| 36 const url::Component path; |
| 37 const url::Component query; |
| 38 const url::Component ref; |
| 39 }; |
| 40 |
| 41 static const SegmentCase segment_cases[] = { |
| 42 { "http://www.google.com/", "http", |
| 43 url::Component(0, 4), // scheme |
| 44 url::Component(), // username |
| 45 url::Component(), // password |
| 46 url::Component(7, 14), // host |
| 47 url::Component(), // port |
| 48 url::Component(21, 1), // path |
| 49 url::Component(), // query |
| 50 url::Component(), // ref |
| 51 }, |
| 52 { "aBoUt:vErSiOn", "about", |
| 53 url::Component(0, 5), // scheme |
| 54 url::Component(), // username |
| 55 url::Component(), // password |
| 56 url::Component(6, 7), // host |
| 57 url::Component(), // port |
| 58 url::Component(), // path |
| 59 url::Component(), // query |
| 60 url::Component(), // ref |
| 61 }, |
| 62 { "about:host/path?query#ref", "about", |
| 63 url::Component(0, 5), // scheme |
| 64 url::Component(), // username |
| 65 url::Component(), // password |
| 66 url::Component(6, 4), // host |
| 67 url::Component(), // port |
| 68 url::Component(10, 5), // path |
| 69 url::Component(16, 5), // query |
| 70 url::Component(22, 3), // ref |
| 71 }, |
| 72 { "about://host/path?query#ref", "about", |
| 73 url::Component(0, 5), // scheme |
| 74 url::Component(), // username |
| 75 url::Component(), // password |
| 76 url::Component(8, 4), // host |
| 77 url::Component(), // port |
| 78 url::Component(12, 5), // path |
| 79 url::Component(18, 5), // query |
| 80 url::Component(24, 3), // ref |
| 81 }, |
| 82 { "chrome:host/path?query#ref", "chrome", |
| 83 url::Component(0, 6), // scheme |
| 84 url::Component(), // username |
| 85 url::Component(), // password |
| 86 url::Component(7, 4), // host |
| 87 url::Component(), // port |
| 88 url::Component(11, 5), // path |
| 89 url::Component(17, 5), // query |
| 90 url::Component(23, 3), // ref |
| 91 }, |
| 92 { "chrome://host/path?query#ref", "chrome", |
| 93 url::Component(0, 6), // scheme |
| 94 url::Component(), // username |
| 95 url::Component(), // password |
| 96 url::Component(9, 4), // host |
| 97 url::Component(), // port |
| 98 url::Component(13, 5), // path |
| 99 url::Component(19, 5), // query |
| 100 url::Component(25, 3), // ref |
| 101 }, |
| 102 { " www.google.com:124?foo#", "http", |
| 103 url::Component(), // scheme |
| 104 url::Component(), // username |
| 105 url::Component(), // password |
| 106 url::Component(4, 14), // host |
| 107 url::Component(19, 3), // port |
| 108 url::Component(), // path |
| 109 url::Component(23, 3), // query |
| 110 url::Component(27, 0), // ref |
| 111 }, |
| 112 { "user@www.google.com", "http", |
| 113 url::Component(), // scheme |
| 114 url::Component(0, 4), // username |
| 115 url::Component(), // password |
| 116 url::Component(5, 14), // host |
| 117 url::Component(), // port |
| 118 url::Component(), // path |
| 119 url::Component(), // query |
| 120 url::Component(), // ref |
| 121 }, |
| 122 { "ftp:/user:P:a$$Wd@..ftp.google.com...::23///pub?foo#bar", "ftp", |
| 123 url::Component(0, 3), // scheme |
| 124 url::Component(5, 4), // username |
| 125 url::Component(10, 7), // password |
| 126 url::Component(18, 20), // host |
| 127 url::Component(39, 2), // port |
| 128 url::Component(41, 6), // path |
| 129 url::Component(48, 3), // query |
| 130 url::Component(52, 3), // ref |
| 131 }, |
| 132 { "[2001:db8::1]/path", "http", |
| 133 url::Component(), // scheme |
| 134 url::Component(), // username |
| 135 url::Component(), // password |
| 136 url::Component(0, 13), // host |
| 137 url::Component(), // port |
| 138 url::Component(13, 5), // path |
| 139 url::Component(), // query |
| 140 url::Component(), // ref |
| 141 }, |
| 142 { "[::1]", "http", |
| 143 url::Component(), // scheme |
| 144 url::Component(), // username |
| 145 url::Component(), // password |
| 146 url::Component(0, 5), // host |
| 147 url::Component(), // port |
| 148 url::Component(), // path |
| 149 url::Component(), // query |
| 150 url::Component(), // ref |
| 151 }, |
| 152 // Incomplete IPv6 addresses (will not canonicalize). |
| 153 { "[2001:4860:", "http", |
| 154 url::Component(), // scheme |
| 155 url::Component(), // username |
| 156 url::Component(), // password |
| 157 url::Component(0, 11), // host |
| 158 url::Component(), // port |
| 159 url::Component(), // path |
| 160 url::Component(), // query |
| 161 url::Component(), // ref |
| 162 }, |
| 163 { "[2001:4860:/foo", "http", |
| 164 url::Component(), // scheme |
| 165 url::Component(), // username |
| 166 url::Component(), // password |
| 167 url::Component(0, 11), // host |
| 168 url::Component(), // port |
| 169 url::Component(11, 4), // path |
| 170 url::Component(), // query |
| 171 url::Component(), // ref |
| 172 }, |
| 173 { "http://:b005::68]", "http", |
| 174 url::Component(0, 4), // scheme |
| 175 url::Component(), // username |
| 176 url::Component(), // password |
| 177 url::Component(7, 10), // host |
| 178 url::Component(), // port |
| 179 url::Component(), // path |
| 180 url::Component(), // query |
| 181 url::Component(), // ref |
| 182 }, |
| 183 // Can't do anything useful with this. |
| 184 { ":b005::68]", "", |
| 185 url::Component(0, 0), // scheme |
| 186 url::Component(), // username |
| 187 url::Component(), // password |
| 188 url::Component(), // host |
| 189 url::Component(), // port |
| 190 url::Component(), // path |
| 191 url::Component(), // query |
| 192 url::Component(), // ref |
| 193 }, |
| 194 }; |
| 195 |
| 196 typedef testing::Test URLFixerTest; |
| 197 |
| 198 TEST(URLFixerTest, SegmentURL) { |
| 199 std::string result; |
| 200 url::Parsed parts; |
| 201 |
| 202 for (size_t i = 0; i < arraysize(segment_cases); ++i) { |
| 203 SegmentCase value = segment_cases[i]; |
| 204 result = url_fixer::SegmentURL(value.input, &parts); |
| 205 EXPECT_EQ(value.result, result); |
| 206 EXPECT_EQ(value.scheme, parts.scheme); |
| 207 EXPECT_EQ(value.username, parts.username); |
| 208 EXPECT_EQ(value.password, parts.password); |
| 209 EXPECT_EQ(value.host, parts.host); |
| 210 EXPECT_EQ(value.port, parts.port); |
| 211 EXPECT_EQ(value.path, parts.path); |
| 212 EXPECT_EQ(value.query, parts.query); |
| 213 EXPECT_EQ(value.ref, parts.ref); |
| 214 } |
| 215 } |
| 216 |
| 217 // Creates a file and returns its full name as well as the decomposed |
| 218 // version. Example: |
| 219 // full_path = "c:\foo\bar.txt" |
| 220 // dir = "c:\foo" |
| 221 // file_name = "bar.txt" |
| 222 static bool MakeTempFile(const base::FilePath& dir, |
| 223 const base::FilePath& file_name, |
| 224 base::FilePath* full_path) { |
| 225 *full_path = dir.Append(file_name); |
| 226 return base::WriteFile(*full_path, "", 0) == 0; |
| 227 } |
| 228 |
| 229 // Returns true if the given URL is a file: URL that matches the given file |
| 230 static bool IsMatchingFileURL(const std::string& url, |
| 231 const base::FilePath& full_file_path) { |
| 232 if (url.length() <= 8) |
| 233 return false; |
| 234 if (std::string("file:///") != url.substr(0, 8)) |
| 235 return false; // no file:/// prefix |
| 236 if (url.find('\\') != std::string::npos) |
| 237 return false; // contains backslashes |
| 238 |
| 239 base::FilePath derived_path; |
| 240 net::FileURLToFilePath(GURL(url), &derived_path); |
| 241 |
| 242 return base::FilePath::CompareEqualIgnoreCase(derived_path.value(), |
| 243 full_file_path.value()); |
| 244 } |
| 245 |
| 246 struct FixupCase { |
| 247 const std::string input; |
| 248 const std::string output; |
| 249 } fixup_cases[] = { |
| 250 {"www.google.com", "http://www.google.com/"}, |
| 251 {" www.google.com ", "http://www.google.com/"}, |
| 252 {" foo.com/asdf bar", "http://foo.com/asdf%20%20bar"}, |
| 253 {"..www.google.com..", "http://www.google.com./"}, |
| 254 {"http://......", "http://....../"}, |
| 255 {"http://host.com:ninety-two/", "http://host.com:ninety-two/"}, |
| 256 {"http://host.com:ninety-two?foo", "http://host.com:ninety-two/?foo"}, |
| 257 {"google.com:123", "http://google.com:123/"}, |
| 258 {"about:", "chrome://version/"}, |
| 259 {"about:foo", "chrome://foo/"}, |
| 260 {"about:version", "chrome://version/"}, |
| 261 {"about:blank", "about:blank"}, |
| 262 {"about:usr:pwd@hst/pth?qry#ref", "chrome://usr:pwd@hst/pth?qry#ref"}, |
| 263 {"about://usr:pwd@hst/pth?qry#ref", "chrome://usr:pwd@hst/pth?qry#ref"}, |
| 264 {"chrome:usr:pwd@hst/pth?qry#ref", "chrome://usr:pwd@hst/pth?qry#ref"}, |
| 265 {"chrome://usr:pwd@hst/pth?qry#ref", "chrome://usr:pwd@hst/pth?qry#ref"}, |
| 266 {"www:123", "http://www:123/"}, |
| 267 {" www:123", "http://www:123/"}, |
| 268 {"www.google.com?foo", "http://www.google.com/?foo"}, |
| 269 {"www.google.com#foo", "http://www.google.com/#foo"}, |
| 270 {"www.google.com?", "http://www.google.com/?"}, |
| 271 {"www.google.com#", "http://www.google.com/#"}, |
| 272 {"www.google.com:123?foo#bar", "http://www.google.com:123/?foo#bar"}, |
| 273 {"user@www.google.com", "http://user@www.google.com/"}, |
| 274 {"\xE6\xB0\xB4.com", "http://xn--1rw.com/"}, |
| 275 // It would be better if this next case got treated as http, but I don't see |
| 276 // a clean way to guess this isn't the new-and-exciting "user" scheme. |
| 277 {"user:passwd@www.google.com:8080/", "user:passwd@www.google.com:8080/"}, |
| 278 // {"file:///c:/foo/bar%20baz.txt", "file:///C:/foo/bar%20baz.txt"}, |
| 279 {"ftp.google.com", "ftp://ftp.google.com/"}, |
| 280 {" ftp.google.com", "ftp://ftp.google.com/"}, |
| 281 {"FTP.GooGle.com", "ftp://ftp.google.com/"}, |
| 282 {"ftpblah.google.com", "http://ftpblah.google.com/"}, |
| 283 {"ftp", "http://ftp/"}, |
| 284 {"google.ftp.com", "http://google.ftp.com/"}, |
| 285 // URLs which end with 0x85 (NEL in ISO-8859). |
| 286 {"http://foo.com/s?q=\xd0\x85", "http://foo.com/s?q=%D0%85"}, |
| 287 {"http://foo.com/s?q=\xec\x97\x85", "http://foo.com/s?q=%EC%97%85"}, |
| 288 {"http://foo.com/s?q=\xf0\x90\x80\x85", "http://foo.com/s?q=%F0%90%80%85"}, |
| 289 // URLs which end with 0xA0 (non-break space in ISO-8859). |
| 290 {"http://foo.com/s?q=\xd0\xa0", "http://foo.com/s?q=%D0%A0"}, |
| 291 {"http://foo.com/s?q=\xec\x97\xa0", "http://foo.com/s?q=%EC%97%A0"}, |
| 292 {"http://foo.com/s?q=\xf0\x90\x80\xa0", "http://foo.com/s?q=%F0%90%80%A0"}, |
| 293 // URLs containing IPv6 literals. |
| 294 {"[2001:db8::2]", "http://[2001:db8::2]/"}, |
| 295 {"[::]:80", "http://[::]/"}, |
| 296 {"[::]:80/path", "http://[::]/path"}, |
| 297 {"[::]:180/path", "http://[::]:180/path"}, |
| 298 // TODO(pmarks): Maybe we should parse bare IPv6 literals someday. |
| 299 {"::1", "::1"}, |
| 300 // Semicolon as scheme separator for standard schemes. |
| 301 {"http;//www.google.com/", "http://www.google.com/"}, |
| 302 {"about;chrome", "chrome://chrome/"}, |
| 303 // Semicolon left as-is for non-standard schemes. |
| 304 {"whatsup;//fool", "whatsup://fool"}, |
| 305 // Semicolon left as-is in URL itself. |
| 306 {"http://host/port?query;moar", "http://host/port?query;moar"}, |
| 307 // Fewer slashes than expected. |
| 308 {"http;www.google.com/", "http://www.google.com/"}, |
| 309 {"http;/www.google.com/", "http://www.google.com/"}, |
| 310 // Semicolon at start. |
| 311 {";http://www.google.com/", "http://%3Bhttp//www.google.com/"}, |
| 312 }; |
| 313 |
| 314 TEST(URLFixerTest, FixupURL) { |
| 315 for (size_t i = 0; i < arraysize(fixup_cases); ++i) { |
| 316 FixupCase value = fixup_cases[i]; |
| 317 EXPECT_EQ(value.output, |
| 318 url_fixer::FixupURL(value.input, "").possibly_invalid_spec()) |
| 319 << "input: " << value.input; |
| 320 } |
| 321 |
| 322 // Check the TLD-appending functionality. |
| 323 FixupCase tld_cases[] = { |
| 324 {"somedomainthatwillnotbeagtld", |
| 325 "http://www.somedomainthatwillnotbeagtld.com/"}, |
| 326 {"somedomainthatwillnotbeagtld.", |
| 327 "http://www.somedomainthatwillnotbeagtld.com/"}, |
| 328 {"somedomainthatwillnotbeagtld..", |
| 329 "http://www.somedomainthatwillnotbeagtld.com/"}, |
| 330 {".somedomainthatwillnotbeagtld", |
| 331 "http://www.somedomainthatwillnotbeagtld.com/"}, |
| 332 {"www.somedomainthatwillnotbeagtld", |
| 333 "http://www.somedomainthatwillnotbeagtld.com/"}, |
| 334 {"somedomainthatwillnotbeagtld.com", |
| 335 "http://somedomainthatwillnotbeagtld.com/"}, |
| 336 {"http://somedomainthatwillnotbeagtld", |
| 337 "http://www.somedomainthatwillnotbeagtld.com/"}, |
| 338 {"..somedomainthatwillnotbeagtld..", |
| 339 "http://www.somedomainthatwillnotbeagtld.com/"}, |
| 340 {"http://www.somedomainthatwillnotbeagtld", |
| 341 "http://www.somedomainthatwillnotbeagtld.com/"}, |
| 342 {"9999999999999999", "http://www.9999999999999999.com/"}, |
| 343 {"somedomainthatwillnotbeagtld/foo", |
| 344 "http://www.somedomainthatwillnotbeagtld.com/foo"}, |
| 345 {"somedomainthatwillnotbeagtld.com/foo", |
| 346 "http://somedomainthatwillnotbeagtld.com/foo"}, |
| 347 {"somedomainthatwillnotbeagtld/?foo=.com", |
| 348 "http://www.somedomainthatwillnotbeagtld.com/?foo=.com"}, |
| 349 {"www.somedomainthatwillnotbeagtld/?foo=www.", |
| 350 "http://www.somedomainthatwillnotbeagtld.com/?foo=www."}, |
| 351 {"somedomainthatwillnotbeagtld.com/?foo=.com", |
| 352 "http://somedomainthatwillnotbeagtld.com/?foo=.com"}, |
| 353 {"http://www.somedomainthatwillnotbeagtld.com", |
| 354 "http://www.somedomainthatwillnotbeagtld.com/"}, |
| 355 {"somedomainthatwillnotbeagtld:123", |
| 356 "http://www.somedomainthatwillnotbeagtld.com:123/"}, |
| 357 {"http://somedomainthatwillnotbeagtld:123", |
| 358 "http://www.somedomainthatwillnotbeagtld.com:123/"}, |
| 359 }; |
| 360 for (size_t i = 0; i < arraysize(tld_cases); ++i) { |
| 361 FixupCase value = tld_cases[i]; |
| 362 EXPECT_EQ(value.output, |
| 363 url_fixer::FixupURL(value.input, "com").possibly_invalid_spec()); |
| 364 } |
| 365 } |
| 366 |
| 367 // Test different types of file inputs to URIFixerUpper::FixupURL. This |
| 368 // doesn't go into the nice array of fixups above since the file input |
| 369 // has to exist. |
| 370 TEST(URLFixerTest, FixupFile) { |
| 371 // this "original" filename is the one we tweak to get all the variations |
| 372 base::ScopedTempDir temp_dir_; |
| 373 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 374 base::FilePath original; |
| 375 ASSERT_TRUE(MakeTempFile( |
| 376 temp_dir_.path(), |
| 377 base::FilePath(FILE_PATH_LITERAL("url fixer upper existing file.txt")), |
| 378 &original)); |
| 379 |
| 380 // reference path |
| 381 GURL golden(net::FilePathToFileURL(original)); |
| 382 |
| 383 // c:\foo\bar.txt -> file:///c:/foo/bar.txt (basic) |
| 384 GURL fixedup(url_fixer::FixupURL(original.AsUTF8Unsafe(), std::string())); |
| 385 EXPECT_EQ(golden, fixedup); |
| 386 |
| 387 // TODO(port): Make some equivalent tests for posix. |
| 388 #if defined(OS_WIN) |
| 389 // c|/foo\bar.txt -> file:///c:/foo/bar.txt (pipe allowed instead of colon) |
| 390 std::string cur(base::WideToUTF8(original.value())); |
| 391 EXPECT_EQ(':', cur[1]); |
| 392 cur[1] = '|'; |
| 393 EXPECT_EQ(golden, url_fixer::FixupURL(cur, std::string())); |
| 394 |
| 395 FixupCase cases[] = { |
| 396 {"c:\\Non-existent%20file.txt", "file:///C:/Non-existent%2520file.txt"}, |
| 397 |
| 398 // \\foo\bar.txt -> file://foo/bar.txt |
| 399 // UNC paths, this file won't exist, but since there are no escapes, it |
| 400 // should be returned just converted to a file: URL. |
| 401 {"\\\\NonexistentHost\\foo\\bar.txt", "file://nonexistenthost/foo/bar.txt"}, |
| 402 // We do this strictly, like IE8, which only accepts this form using |
| 403 // backslashes and not forward ones. Turning "//foo" into "http" matches |
| 404 // Firefox and IE, silly though it may seem (it falls out of adding "http" |
| 405 // as the default protocol if you haven't entered one). |
| 406 {"//NonexistentHost\\foo/bar.txt", "http://nonexistenthost/foo/bar.txt"}, |
| 407 {"file:///C:/foo/bar", "file:///C:/foo/bar"}, |
| 408 |
| 409 // Much of the work here comes from GURL's canonicalization stage. |
| 410 {"file://C:/foo/bar", "file:///C:/foo/bar"}, |
| 411 {"file:c:", "file:///C:/"}, |
| 412 {"file:c:WINDOWS", "file:///C:/WINDOWS"}, |
| 413 {"file:c|Program Files", "file:///C:/Program%20Files"}, |
| 414 {"file:/file", "file://file/"}, |
| 415 {"file:////////c:\\foo", "file:///C:/foo"}, |
| 416 {"file://server/folder/file", "file://server/folder/file"}, |
| 417 |
| 418 // These are fixups we don't do, but could consider: |
| 419 // {"file:///foo:/bar", "file://foo/bar"}, |
| 420 // {"file:/\\/server\\folder/file", "file://server/folder/file"}, |
| 421 }; |
| 422 #elif defined(OS_POSIX) |
| 423 |
| 424 #if defined(OS_MACOSX) |
| 425 #define HOME "/Users/" |
| 426 #else |
| 427 #define HOME "/home/" |
| 428 #endif |
| 429 url_fixer::home_directory_override = "/foo"; |
| 430 FixupCase cases[] = { |
| 431 // File URLs go through GURL, which tries to escape intelligently. |
| 432 {"/A%20non-existent file.txt", "file:///A%2520non-existent%20file.txt"}, |
| 433 // A plain "/" refers to the root. |
| 434 {"/", "file:///"}, |
| 435 |
| 436 // These rely on the above home_directory_override. |
| 437 {"~", "file:///foo"}, |
| 438 {"~/bar", "file:///foo/bar"}, |
| 439 |
| 440 // References to other users' homedirs. |
| 441 {"~foo", "file://" HOME "foo"}, |
| 442 {"~x/blah", "file://" HOME "x/blah"}, |
| 443 }; |
| 444 #endif |
| 445 |
| 446 for (size_t i = 0; i < arraysize(cases); i++) { |
| 447 EXPECT_EQ(cases[i].output, |
| 448 url_fixer::FixupURL(cases[i].input, "").possibly_invalid_spec()); |
| 449 } |
| 450 |
| 451 EXPECT_TRUE(base::DeleteFile(original, false)); |
| 452 } |
| 453 |
| 454 TEST(URLFixerTest, FixupRelativeFile) { |
| 455 base::FilePath full_path; |
| 456 base::FilePath file_part( |
| 457 FILE_PATH_LITERAL("url_fixer_upper_existing_file.txt")); |
| 458 base::ScopedTempDir temp_dir_; |
| 459 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| 460 ASSERT_TRUE(MakeTempFile(temp_dir_.path(), file_part, &full_path)); |
| 461 full_path = base::MakeAbsoluteFilePath(full_path); |
| 462 ASSERT_FALSE(full_path.empty()); |
| 463 |
| 464 // make sure we pass through good URLs |
| 465 for (size_t i = 0; i < arraysize(fixup_cases); ++i) { |
| 466 FixupCase value = fixup_cases[i]; |
| 467 base::FilePath input = base::FilePath::FromUTF8Unsafe(value.input); |
| 468 EXPECT_EQ(value.output, |
| 469 url_fixer::FixupRelativeFile(temp_dir_.path(), |
| 470 input).possibly_invalid_spec()); |
| 471 } |
| 472 |
| 473 // make sure the existing file got fixed-up to a file URL, and that there |
| 474 // are no backslashes |
| 475 EXPECT_TRUE(IsMatchingFileURL( |
| 476 url_fixer::FixupRelativeFile(temp_dir_.path(), |
| 477 file_part).possibly_invalid_spec(), full_path)); |
| 478 EXPECT_TRUE(base::DeleteFile(full_path, false)); |
| 479 |
| 480 // create a filename we know doesn't exist and make sure it doesn't get |
| 481 // fixed up to a file URL |
| 482 base::FilePath nonexistent_file( |
| 483 FILE_PATH_LITERAL("url_fixer_upper_nonexistent_file.txt")); |
| 484 std::string fixedup(url_fixer::FixupRelativeFile( |
| 485 temp_dir_.path(), nonexistent_file).possibly_invalid_spec()); |
| 486 EXPECT_NE(std::string("file:///"), fixedup.substr(0, 8)); |
| 487 EXPECT_FALSE(IsMatchingFileURL(fixedup, nonexistent_file)); |
| 488 |
| 489 // make a subdir to make sure relative paths with directories work, also |
| 490 // test spaces: |
| 491 // "app_dir\url fixer-upper dir\url fixer-upper existing file.txt" |
| 492 base::FilePath sub_dir(FILE_PATH_LITERAL("url fixer-upper dir")); |
| 493 base::FilePath sub_file( |
| 494 FILE_PATH_LITERAL("url fixer-upper existing file.txt")); |
| 495 base::FilePath new_dir = temp_dir_.path().Append(sub_dir); |
| 496 base::CreateDirectory(new_dir); |
| 497 ASSERT_TRUE(MakeTempFile(new_dir, sub_file, &full_path)); |
| 498 full_path = base::MakeAbsoluteFilePath(full_path); |
| 499 ASSERT_FALSE(full_path.empty()); |
| 500 |
| 501 // test file in the subdir |
| 502 base::FilePath relative_file = sub_dir.Append(sub_file); |
| 503 EXPECT_TRUE(IsMatchingFileURL( |
| 504 url_fixer::FixupRelativeFile(temp_dir_.path(), |
| 505 relative_file).possibly_invalid_spec(), full_path)); |
| 506 |
| 507 // test file in the subdir with different slashes and escaping. |
| 508 base::FilePath::StringType relative_file_str = sub_dir.value() + |
| 509 FILE_PATH_LITERAL("/") + sub_file.value(); |
| 510 base::ReplaceSubstringsAfterOffset(&relative_file_str, 0, |
| 511 FILE_PATH_LITERAL(" "), FILE_PATH_LITERAL("%20")); |
| 512 EXPECT_TRUE(IsMatchingFileURL( |
| 513 url_fixer::FixupRelativeFile(temp_dir_.path(), |
| 514 base::FilePath(relative_file_str)).possibly_invalid_spec(), |
| 515 full_path)); |
| 516 |
| 517 // test relative directories and duplicate slashes |
| 518 // (should resolve to the same file as above) |
| 519 relative_file_str = sub_dir.value() + FILE_PATH_LITERAL("/../") + |
| 520 sub_dir.value() + FILE_PATH_LITERAL("///./") + sub_file.value(); |
| 521 EXPECT_TRUE(IsMatchingFileURL( |
| 522 url_fixer::FixupRelativeFile(temp_dir_.path(), |
| 523 base::FilePath(relative_file_str)).possibly_invalid_spec(), |
| 524 full_path)); |
| 525 |
| 526 // done with the subdir |
| 527 EXPECT_TRUE(base::DeleteFile(full_path, false)); |
| 528 EXPECT_TRUE(base::DeleteFile(new_dir, true)); |
| 529 |
| 530 // Test that an obvious HTTP URL isn't accidentally treated as an absolute |
| 531 // file path (on account of system-specific craziness). |
| 532 base::FilePath empty_path; |
| 533 base::FilePath http_url_path(FILE_PATH_LITERAL("http://../")); |
| 534 EXPECT_TRUE( |
| 535 url_fixer::FixupRelativeFile(empty_path, http_url_path).SchemeIs("http")); |
| 536 } |
OLD | NEW |