1 // Copyright (c) 2012 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.
5 #include "net/base/net_util.h"
11 #include "base/files/file_path.h"
12 #include "base/format_macros.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/strings/sys_string_conversions.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/sys_byteorder.h"
19 #include "base/test/test_file_util.h"
20 #include "base/time/time.h"
21 #include "testing/gtest/include/gtest/gtest.h"
28 static const size_t kNpos
= base::string16::npos
;
36 const char* header_name
;
40 struct HeaderParamCase
{
41 const char* header_name
;
42 const char* param_name
;
46 struct FileNameCDCase
{
47 const char* header_field
;
48 const char* referrer_charset
;
49 const wchar_t* expected
;
52 const char* kLanguages
[] = {
53 "", "en", "zh-CN", "ja", "ko",
54 "he", "ar", "ru", "el", "fr",
55 "de", "pt", "sv", "th", "hi",
56 "de,en", "el,en", "zh-TW,en", "ko,ja", "he,ru,en",
62 const wchar_t* unicode_output
;
63 const bool unicode_allowed
[arraysize(kLanguages
)];
66 // TODO(jungshik) This is just a random sample of languages and is far
67 // from exhaustive. We may have to generate all the combinations
68 // of languages (powerset of a set of all the languages).
69 const IDNTestCase idn_cases
[] = {
71 {"www.google.com", L
"www.google.com",
72 {true, true, true, true, true,
73 true, true, true, true, true,
74 true, true, true, true, true,
75 true, true, true, true, true,
77 {"www.google.com.", L
"www.google.com.",
78 {true, true, true, true, true,
79 true, true, true, true, true,
80 true, true, true, true, true,
81 true, true, true, true, true,
84 {true, true, true, true, true,
85 true, true, true, true, true,
86 true, true, true, true, true,
87 true, true, true, true, true,
90 {true, true, true, true, true,
91 true, true, true, true, true,
92 true, true, true, true, true,
93 true, true, true, true, true,
96 // Hanzi (Traditional Chinese)
97 {"xn--1lq90ic7f1rc.cn", L
"\x5317\x4eac\x5927\x5b78.cn",
98 {true, false, true, true, false,
99 false, false, false, false, false,
100 false, false, false, false, false,
101 false, false, true, true, false,
103 // Hanzi ('video' in Simplified Chinese : will pass only in zh-CN,zh)
104 {"xn--cy2a840a.com", L
"\x89c6\x9891.com",
105 {true, false, true, false, false,
106 false, false, false, false, false,
107 false, false, false, false, false,
108 false, false, false, false, false,
111 {"www.xn--123-p18d.com", L
"www.\x4e00" L
"123.com",
112 {true, false, true, true, false,
113 false, false, false, false, false,
114 false, false, false, false, false,
115 false, false, true, true, false,
117 // Hanzi + Latin : U+56FD is simplified and is regarded
118 // as not supported in zh-TW.
119 {"www.xn--hello-9n1hm04c.com", L
"www.hello\x4e2d\x56fd.com",
120 {false, false, true, true, false,
121 false, false, false, false, false,
122 false, false, false, false, false,
123 false, false, false, true, false,
125 // Kanji + Kana (Japanese)
126 {"xn--l8jvb1ey91xtjb.jp", L
"\x671d\x65e5\x3042\x3055\x3072.jp",
127 {true, false, false, true, false,
128 false, false, false, false, false,
129 false, false, false, false, false,
130 false, false, false, true, false,
132 // Katakana including U+30FC
133 {"xn--tckm4i2e.jp", L
"\x30b3\x30de\x30fc\x30b9.jp",
134 {true, false, false, true, false,
135 false, false, false, false, false,
136 false, false, false, false, false,
137 false, false, false, true, false,
139 {"xn--3ck7a7g.jp", L
"\u30ce\u30f3\u30bd.jp",
140 {true, false, false, true, false,
141 false, false, false, false, false,
142 false, false, false, false, false,
143 false, false, false, true, false,
145 // Katakana + Latin (Japanese)
146 // TODO(jungshik): Change 'false' in the first element to 'true'
147 // after upgrading to ICU 4.2.1 to use new uspoof_* APIs instead
148 // of our IsIDNComponentInSingleScript().
149 {"xn--e-efusa1mzf.jp", L
"e\x30b3\x30de\x30fc\x30b9.jp",
150 {false, false, false, true, false,
151 false, false, false, false, false,
152 false, false, false, false, false,
153 false, false, false, true, false,
155 {"xn--3bkxe.jp", L
"\x30c8\x309a.jp",
156 {false, false, false, true, false,
157 false, false, false, false, false,
158 false, false, false, false, false,
159 false, false, false, true, false,
162 {"www.xn--or3b17p6jjc.kr", L
"www.\xc804\xc790\xc815\xbd80.kr",
163 {true, false, false, false, true,
164 false, false, false, false, false,
165 false, false, false, false, false,
166 false, false, false, true, false,
168 // b<u-umlaut>cher (German)
169 {"xn--bcher-kva.de", L
"b\x00fc" L
"cher.de",
170 {true, false, false, false, false,
171 false, false, false, false, true,
172 true, false, false, false, false,
173 true, false, false, false, false,
176 {"www.xn--frgbolaget-q5a.se", L
"www.f\x00e4rgbolaget.se",
177 {true, false, false, false, false,
178 false, false, false, false, false,
179 true, false, true, false, false,
180 true, false, false, false, false,
182 // c-cedilla (French)
183 {"www.xn--alliancefranaise-npb.fr", L
"www.alliancefran\x00e7" L
"aise.fr",
184 {true, false, false, false, false,
185 false, false, false, false, true,
186 false, true, false, false, false,
187 false, false, false, false, false,
189 // caf'e with acute accent' (French)
190 {"xn--caf-dma.fr", L
"caf\x00e9.fr",
191 {true, false, false, false, false,
192 false, false, false, false, true,
193 false, true, true, false, false,
194 false, false, false, false, false,
196 // c-cedillla and a with tilde (Portuguese)
197 {"xn--poema-9qae5a.com.br", L
"p\x00e3oema\x00e7\x00e3.com.br",
198 {true, false, false, false, false,
199 false, false, false, false, false,
200 false, true, false, false, false,
201 false, false, false, false, false,
204 {"xn--achy-f6a.com", L
"\x0161" L
"achy.com",
205 {true, false, false, false, false,
206 false, false, false, false, false,
207 false, false, false, false, false,
208 false, false, false, false, false,
210 // TODO(jungshik) : Add examples with Cyrillic letters
211 // only used in some languages written in Cyrillic.
213 {"xn--kxae4bafwg.gr", L
"\x03bf\x03c5\x03c4\x03bf\x03c0\x03af\x03b1.gr",
214 {true, false, false, false, false,
215 false, false, false, true, false,
216 false, false, false, false, false,
217 false, true, false, false, false,
219 // Eutopia + 123 (Greek)
220 {"xn---123-pldm0haj2bk.gr",
221 L
"\x03bf\x03c5\x03c4\x03bf\x03c0\x03af\x03b1-123.gr",
222 {true, false, false, false, false,
223 false, false, false, true, false,
224 false, false, false, false, false,
225 false, true, false, false, false,
227 // Cyrillic (Russian)
228 {"xn--n1aeec9b.ru", L
"\x0442\x043e\x0440\x0442\x044b.ru",
229 {true, false, false, false, false,
230 false, false, true, false, false,
231 false, false, false, false, false,
232 false, false, false, false, true,
234 // Cyrillic + 123 (Russian)
235 {"xn---123-45dmmc5f.ru", L
"\x0442\x043e\x0440\x0442\x044b-123.ru",
236 {true, false, false, false, false,
237 false, false, true, false, false,
238 false, false, false, false, false,
239 false, false, false, false, true,
242 {"xn--mgba1fmg.ar", L
"\x0627\x0641\x0644\x0627\x0645.ar",
243 {true, false, false, false, false,
244 false, true, false, false, false,
245 false, false, false, false, false,
246 false, false, false, false, false,
249 {"xn--4dbib.he", L
"\x05d5\x05d0\x05d4.he",
250 {true, false, false, false, false,
251 true, false, false, false, false,
252 false, false, false, false, false,
253 false, false, false, false, true,
256 {"xn--12c2cc4ag3b4ccu.th",
257 L
"\x0e2a\x0e32\x0e22\x0e01\x0e32\x0e23\x0e1a\x0e34\x0e19.th",
258 {true, false, false, false, false,
259 false, false, false, false, false,
260 false, false, false, true, false,
261 false, false, false, false, false,
264 {"www.xn--l1b6a9e1b7c.in", L
"www.\x0905\x0915\x094b\x0932\x093e.in",
265 {true, false, false, false, false,
266 false, false, false, false, false,
267 false, false, false, false, true,
268 false, false, false, false, false,
271 {"xn--hello?world.com", NULL
,
272 {false, false, false, false, false,
273 false, false, false, false, false,
274 false, false, false, false, false,
275 false, false, false, false, false,
278 // "payp<alpha>l.com"
279 {"www.xn--paypl-g9d.com", L
"payp\x03b1l.com",
280 {false, false, false, false, false,
281 false, false, false, false, false,
282 false, false, false, false, false,
283 false, false, false, false, false,
285 // google.gr with Greek omicron and epsilon
286 {"xn--ggl-6xc1ca.gr", L
"g\x03bf\x03bfgl\x03b5.gr",
287 {false, false, false, false, false,
288 false, false, false, false, false,
289 false, false, false, false, false,
290 false, false, false, false, false,
292 // google.ru with Cyrillic o
293 {"xn--ggl-tdd6ba.ru", L
"g\x043e\x043egl\x0435.ru",
294 {false, false, false, false, false,
295 false, false, false, false, false,
296 false, false, false, false, false,
297 false, false, false, false, false,
299 // h<e with acute>llo<China in Han>.cn
300 {"xn--hllo-bpa7979ih5m.cn", L
"h\x00e9llo\x4e2d\x56fd.cn",
301 {false, false, false, false, false,
302 false, false, false, false, false,
303 false, false, false, false, false,
304 false, false, false, false, false,
306 // <Greek rho><Cyrillic a><Cyrillic u>.ru
307 {"xn--2xa6t2b.ru", L
"\x03c1\x0430\x0443.ru",
308 {false, false, false, false, false,
309 false, false, false, false, false,
310 false, false, false, false, false,
311 false, false, false, false, false,
313 // One that's really long that will force a buffer realloc
314 {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
316 L
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
318 {true, true, true, true, true,
319 true, true, true, true, true,
320 true, true, true, true, true,
321 true, true, true, true, true,
323 // Test cases for characters we blacklisted although allowed in IDN.
324 // Embedded spaces will be turned to %20 in the display.
325 // TODO(jungshik): We need to have more cases. This is a typical
326 // data-driven trap. The following test cases need to be separated
327 // and tested only for a couple of languages.
328 {"xn--osd3820f24c.kr", L
"\xac00\xb098\x115f.kr",
329 {false, false, false, false, false,
330 false, false, false, false, false,
331 false, false, false, false, false,
332 false, false, false, false, false,
334 {"www.xn--google-ho0coa.com", L
"www.\x2039google\x203a.com",
335 {false, false, false, false, false,
336 false, false, false, false, false,
337 false, false, false, false, false,
338 false, false, false, false, false,
340 {"google.xn--comabc-k8d", L
"google.com\x0338" L
"abc",
341 {false, false, false, false, false,
342 false, false, false, false, false,
343 false, false, false, false, false,
344 false, false, false, false, false,
346 {"google.xn--com-oh4ba.evil.jp", L
"google.com\x309a\x309a.evil.jp",
347 {false, false, false, false, false,
348 false, false, false, false, false,
349 false, false, false, false, false,
350 false, false, false, false, false,
352 {"google.xn--comevil-v04f.jp", L
"google.com\x30ce" L
"evil.jp",
353 {false, false, false, false, false,
354 false, false, false, false, false,
355 false, false, false, false, false,
356 false, false, false, false, false,
359 // These two cases are special. We need a separate test.
360 // U+3000 and U+3002 are normalized to ASCII space and dot.
361 {"xn-- -kq6ay5z.cn", L
"\x4e2d\x56fd\x3000.cn",
362 {false, false, true, false, false,
363 false, false, false, false, false,
364 false, false, false, false, false,
365 false, false, true, false, false,
367 {"xn--fiqs8s.cn", L
"\x4e2d\x56fd\x3002" L
"cn",
368 {false, false, true, false, false,
369 false, false, false, false, false,
370 false, false, false, false, false,
371 false, false, true, false, false,
376 struct AdjustOffsetCase
{
378 size_t output_offset
;
381 struct CompliantHostCase
{
383 const char* desired_tld
;
384 bool expected_output
;
387 struct GenerateFilenameCase
{
390 const char* content_disp_header
;
391 const char* referrer_charset
;
392 const char* suggested_filename
;
393 const char* mime_type
;
394 const wchar_t* default_filename
;
395 const wchar_t* expected_filename
;
399 const char* description
;
401 const char* languages
;
402 FormatUrlTypes format_types
;
403 UnescapeRule::Type escape_rules
;
404 const wchar_t* output
; // Use |wchar_t| to handle Unicode constants easily.
408 // Fills in sockaddr for the given 32-bit address (IPv4.)
409 // |bytes| should be an array of length 4.
410 void MakeIPv4Address(const uint8
* bytes
, int port
, SockaddrStorage
* storage
) {
411 memset(&storage
->addr_storage
, 0, sizeof(storage
->addr_storage
));
412 storage
->addr_len
= sizeof(struct sockaddr_in
);
413 struct sockaddr_in
* addr4
= reinterpret_cast<sockaddr_in
*>(storage
->addr
);
414 addr4
->sin_port
= base::HostToNet16(port
);
415 addr4
->sin_family
= AF_INET
;
416 memcpy(&addr4
->sin_addr
, bytes
, 4);
419 // Fills in sockaddr for the given 128-bit address (IPv6.)
420 // |bytes| should be an array of length 16.
421 void MakeIPv6Address(const uint8
* bytes
, int port
, SockaddrStorage
* storage
) {
422 memset(&storage
->addr_storage
, 0, sizeof(storage
->addr_storage
));
423 storage
->addr_len
= sizeof(struct sockaddr_in6
);
424 struct sockaddr_in6
* addr6
= reinterpret_cast<sockaddr_in6
*>(storage
->addr
);
425 addr6
->sin6_port
= base::HostToNet16(port
);
426 addr6
->sin6_family
= AF_INET6
;
427 memcpy(&addr6
->sin6_addr
, bytes
, 16);
430 // A helper for IDN*{Fast,Slow}.
431 // Append "::<language list>" to |expected| and |actual| to make it
432 // easy to tell which sub-case fails without debugging.
433 void AppendLanguagesToOutputs(const char* languages
,
434 base::string16
* expected
,
435 base::string16
* actual
) {
436 base::string16 to_append
= ASCIIToUTF16("::") + ASCIIToUTF16(languages
);
437 expected
->append(to_append
);
438 actual
->append(to_append
);
441 // A pair of helpers for the FormatUrlWithOffsets() test.
442 void VerboseExpect(size_t expected
,
444 const std::string
& original_url
,
446 const base::string16
& formatted_url
) {
447 EXPECT_EQ(expected
, actual
) << "Original URL: " << original_url
448 << " (at char " << position
<< ")\nFormatted URL: " << formatted_url
;
451 void CheckAdjustedOffsets(const std::string
& url_string
,
452 const std::string
& languages
,
453 FormatUrlTypes format_types
,
454 UnescapeRule::Type unescape_rules
,
455 const AdjustOffsetCase
* cases
,
457 const size_t* all_offsets
) {
458 GURL
url(url_string
);
459 for (size_t i
= 0; i
< num_cases
; ++i
) {
460 size_t offset
= cases
[i
].input_offset
;
461 base::string16 formatted_url
= FormatUrl(url
, languages
, format_types
,
462 unescape_rules
, NULL
, NULL
, &offset
);
463 VerboseExpect(cases
[i
].output_offset
, offset
, url_string
, i
, formatted_url
);
466 size_t url_size
= url_string
.length();
467 std::vector
<size_t> offsets
;
468 for (size_t i
= 0; i
< url_size
+ 1; ++i
)
469 offsets
.push_back(i
);
470 base::string16 formatted_url
= FormatUrlWithOffsets(url
, languages
,
471 format_types
, unescape_rules
, NULL
, NULL
, &offsets
);
472 for (size_t i
= 0; i
< url_size
; ++i
)
473 VerboseExpect(all_offsets
[i
], offsets
[i
], url_string
, i
, formatted_url
);
474 VerboseExpect(kNpos
, offsets
[url_size
], url_string
, url_size
, formatted_url
);
477 // Helper to strignize an IP number (used to define expectations).
478 std::string
DumpIPNumber(const IPAddressNumber
& v
) {
480 for (size_t i
= 0; i
< v
.size(); ++i
) {
483 out
.append(base::IntToString(static_cast<int>(v
[i
])));
488 void RunGenerateFileNameTestCase(const GenerateFilenameCase
* test_case
) {
489 std::string
default_filename(WideToUTF8(test_case
->default_filename
));
490 base::FilePath file_path
= GenerateFileName(
491 GURL(test_case
->url
), test_case
->content_disp_header
,
492 test_case
->referrer_charset
, test_case
->suggested_filename
,
493 test_case
->mime_type
, default_filename
);
494 EXPECT_EQ(test_case
->expected_filename
,
495 file_util::FilePathAsWString(file_path
))
496 << "test case at line number: " << test_case
->lineno
;
499 } // anonymous namespace
501 TEST(NetUtilTest
, FileURLConversion
) {
502 // a list of test file names and the corresponding URLs
503 const FileCase round_trip_cases
[] = {
505 {L
"C:\\foo\\bar.txt", "file:///C:/foo/bar.txt"},
506 {L
"\\\\some computer\\foo\\bar.txt",
507 "file://some%20computer/foo/bar.txt"}, // UNC
508 {L
"D:\\Name;with%some symbols*#",
509 "file:///D:/Name%3Bwith%25some%20symbols*%23"},
510 // issue 14153: To be tested with the OS default codepage other than 1252.
511 {L
"D:\\latin1\\caf\x00E9\x00DD.txt",
512 "file:///D:/latin1/caf%C3%A9%C3%9D.txt"},
513 {L
"D:\\otherlatin\\caf\x0119.txt",
514 "file:///D:/otherlatin/caf%C4%99.txt"},
515 {L
"D:\\greek\\\x03B1\x03B2\x03B3.txt",
516 "file:///D:/greek/%CE%B1%CE%B2%CE%B3.txt"},
517 {L
"D:\\Chinese\\\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc",
518 "file:///D:/Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD%91"
520 {L
"D:\\plane1\\\xD835\xDC00\xD835\xDC01.txt", // Math alphabet "AB"
521 "file:///D:/plane1/%F0%9D%90%80%F0%9D%90%81.txt"},
522 #elif defined(OS_POSIX)
523 {L
"/foo/bar.txt", "file:///foo/bar.txt"},
524 {L
"/foo/BAR.txt", "file:///foo/BAR.txt"},
525 {L
"/C:/foo/bar.txt", "file:///C:/foo/bar.txt"},
526 {L
"/foo/bar?.txt", "file:///foo/bar%3F.txt"},
527 {L
"/some computer/foo/bar.txt", "file:///some%20computer/foo/bar.txt"},
528 {L
"/Name;with%some symbols*#", "file:///Name%3Bwith%25some%20symbols*%23"},
529 {L
"/latin1/caf\x00E9\x00DD.txt", "file:///latin1/caf%C3%A9%C3%9D.txt"},
530 {L
"/otherlatin/caf\x0119.txt", "file:///otherlatin/caf%C4%99.txt"},
531 {L
"/greek/\x03B1\x03B2\x03B3.txt", "file:///greek/%CE%B1%CE%B2%CE%B3.txt"},
532 {L
"/Chinese/\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc",
533 "file:///Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD"
535 {L
"/plane1/\x1D400\x1D401.txt", // Math alphabet "AB"
536 "file:///plane1/%F0%9D%90%80%F0%9D%90%81.txt"},
540 // First, we'll test that we can round-trip all of the above cases of URLs
541 base::FilePath output
;
542 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(round_trip_cases
); i
++) {
543 // convert to the file URL
544 GURL
file_url(FilePathToFileURL(
545 file_util::WStringAsFilePath(round_trip_cases
[i
].file
)));
546 EXPECT_EQ(round_trip_cases
[i
].url
, file_url
.spec());
548 // Back to the filename.
549 EXPECT_TRUE(FileURLToFilePath(file_url
, &output
));
550 EXPECT_EQ(round_trip_cases
[i
].file
, file_util::FilePathAsWString(output
));
553 // Test that various file: URLs get decoded into the correct file type
554 FileCase url_cases
[] = {
556 {L
"C:\\foo\\bar.txt", "file:c|/foo\\bar.txt"},
557 {L
"C:\\foo\\bar.txt", "file:/c:/foo/bar.txt"},
558 {L
"\\\\foo\\bar.txt", "file://foo\\bar.txt"},
559 {L
"C:\\foo\\bar.txt", "file:///c:/foo/bar.txt"},
560 {L
"\\\\foo\\bar.txt", "file:////foo\\bar.txt"},
561 {L
"\\\\foo\\bar.txt", "file:/foo/bar.txt"},
562 {L
"\\\\foo\\bar.txt", "file://foo\\bar.txt"},
563 {L
"C:\\foo\\bar.txt", "file:\\\\\\c:/foo/bar.txt"},
564 #elif defined(OS_POSIX)
565 {L
"/c:/foo/bar.txt", "file:/c:/foo/bar.txt"},
566 {L
"/c:/foo/bar.txt", "file:///c:/foo/bar.txt"},
567 {L
"/foo/bar.txt", "file:/foo/bar.txt"},
568 {L
"/c:/foo/bar.txt", "file:\\\\\\c:/foo/bar.txt"},
569 {L
"/foo/bar.txt", "file:foo/bar.txt"},
570 {L
"/bar.txt", "file://foo/bar.txt"},
571 {L
"/foo/bar.txt", "file:///foo/bar.txt"},
572 {L
"/foo/bar.txt", "file:////foo/bar.txt"},
573 {L
"/foo/bar.txt", "file:////foo//bar.txt"},
574 {L
"/foo/bar.txt", "file:////foo///bar.txt"},
575 {L
"/foo/bar.txt", "file:////foo////bar.txt"},
576 {L
"/c:/foo/bar.txt", "file:\\\\\\c:/foo/bar.txt"},
577 {L
"/c:/foo/bar.txt", "file:c:/foo/bar.txt"},
578 // We get these wrong because GURL turns back slashes into forward
580 //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
581 //{L"/c|/foo%5Cbar.txt", "file:c|/foo\\bar.txt"},
582 //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
583 //{L"/foo%5Cbar.txt", "file:////foo\\bar.txt"},
584 //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
587 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(url_cases
); i
++) {
588 FileURLToFilePath(GURL(url_cases
[i
].url
), &output
);
589 EXPECT_EQ(url_cases
[i
].file
, file_util::FilePathAsWString(output
));
592 // Unfortunately, UTF8ToWide discards invalid UTF8 input.
593 #ifdef BUG_878908_IS_FIXED
594 // Test that no conversion happens if the UTF-8 input is invalid, and that
595 // the input is preserved in UTF-8
596 const char invalid_utf8
[] = "file:///d:/Blah/\xff.doc";
597 const wchar_t invalid_wide
[] = L
"D:\\Blah\\\xff.doc";
598 EXPECT_TRUE(FileURLToFilePath(
599 GURL(std::string(invalid_utf8
)), &output
));
600 EXPECT_EQ(std::wstring(invalid_wide
), output
);
603 // Test that if a file URL is malformed, we get a failure
604 EXPECT_FALSE(FileURLToFilePath(GURL("filefoobar"), &output
));
607 TEST(NetUtilTest
, GetIdentityFromURL
) {
609 const char* input_url
;
610 const char* expected_username
;
611 const char* expected_password
;
614 "http://username:password@google.com",
618 { // Test for http://crbug.com/19200
619 "http://username:p@ssword@google.com",
623 { // Special URL characters should be unescaped.
624 "http://username:p%3fa%26s%2fs%23@google.com",
628 { // Username contains %20.
629 "http://use rname:password@google.com",
634 "http://use%00rname:password@google.com",
638 { // Use a '+' in the username.
639 "http://use+rname:password@google.com",
643 { // Use a '&' in the password.
644 "http://username:p&ssword@google.com",
649 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
650 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS
"]: %s", i
,
651 tests
[i
].input_url
));
652 GURL
url(tests
[i
].input_url
);
654 base::string16 username
, password
;
655 GetIdentityFromURL(url
, &username
, &password
);
657 EXPECT_EQ(ASCIIToUTF16(tests
[i
].expected_username
), username
);
658 EXPECT_EQ(ASCIIToUTF16(tests
[i
].expected_password
), password
);
662 // Try extracting a username which was encoded with UTF8.
663 TEST(NetUtilTest
, GetIdentityFromURL_UTF8
) {
664 GURL
url(WideToUTF16(L
"http://foo:\x4f60\x597d@blah.com"));
666 EXPECT_EQ("foo", url
.username());
667 EXPECT_EQ("%E4%BD%A0%E5%A5%BD", url
.password());
669 // Extract the unescaped identity.
670 base::string16 username
, password
;
671 GetIdentityFromURL(url
, &username
, &password
);
673 // Verify that it was decoded as UTF8.
674 EXPECT_EQ(ASCIIToUTF16("foo"), username
);
675 EXPECT_EQ(WideToUTF16(L
"\x4f60\x597d"), password
);
678 // Just a bunch of fake headers.
679 const char* google_headers
=
681 "Content-TYPE: text/html; charset=utf-8\n"
682 "Content-disposition: attachment; filename=\"download.pdf\"\n"
683 "Content-Length: 378557\n"
684 "X-Google-Google1: 314159265\n"
685 "X-Google-Google2: aaaa2:7783,bbb21:9441\n"
686 "X-Google-Google4: home\n"
687 "Transfer-Encoding: chunked\n"
688 "Set-Cookie: HEHE_AT=6666x66beef666x6-66xx6666x66; Path=/mail\n"
689 "Set-Cookie: HEHE_HELP=owned:0;Path=/\n"
690 "Set-Cookie: S=gmail=Xxx-beefbeefbeef_beefb:gmail_yj=beefbeef000beefbee"
691 "fbee:gmproxy=bee-fbeefbe; Domain=.google.com; Path=/\n"
692 "X-Google-Google2: /one/two/three/four/five/six/seven-height/nine:9411\n"
694 "Transfer-Encoding: chunked\n"
695 "Date: Mon, 13 Nov 2006 21:38:09 GMT\n"
696 "Expires: Tue, 14 Nov 2006 19:23:58 GMT\n"
697 "X-Malformed: bla; arg=test\"\n"
698 "X-Malformed2: bla; arg=\n"
699 "X-Test: bla; arg1=val1; arg2=val2";
701 TEST(NetUtilTest
, GetSpecificHeader
) {
702 const HeaderCase tests
[] = {
703 {"content-type", "text/html; charset=utf-8"},
704 {"CONTENT-LENGTH", "378557"},
705 {"Date", "Mon, 13 Nov 2006 21:38:09 GMT"},
710 // Test first with google_headers.
711 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
713 GetSpecificHeader(google_headers
, tests
[i
].header_name
);
714 EXPECT_EQ(result
, tests
[i
].expected
);
717 // Test again with empty headers.
718 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
719 std::string result
= GetSpecificHeader(std::string(), tests
[i
].header_name
);
720 EXPECT_EQ(result
, std::string());
724 TEST(NetUtilTest
, IDNToUnicodeFast
) {
725 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(idn_cases
); i
++) {
726 for (size_t j
= 0; j
< arraysize(kLanguages
); j
++) {
727 // ja || zh-TW,en || ko,ja -> IDNToUnicodeSlow
728 if (j
== 3 || j
== 17 || j
== 18)
730 base::string16
output(IDNToUnicode(idn_cases
[i
].input
, kLanguages
[j
]));
731 base::string16
expected(idn_cases
[i
].unicode_allowed
[j
] ?
732 WideToUTF16(idn_cases
[i
].unicode_output
) :
733 ASCIIToUTF16(idn_cases
[i
].input
));
734 AppendLanguagesToOutputs(kLanguages
[j
], &expected
, &output
);
735 EXPECT_EQ(expected
, output
);
740 TEST(NetUtilTest
, IDNToUnicodeSlow
) {
741 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(idn_cases
); i
++) {
742 for (size_t j
= 0; j
< arraysize(kLanguages
); j
++) {
743 // !(ja || zh-TW,en || ko,ja) -> IDNToUnicodeFast
744 if (!(j
== 3 || j
== 17 || j
== 18))
746 base::string16
output(IDNToUnicode(idn_cases
[i
].input
, kLanguages
[j
]));
747 base::string16
expected(idn_cases
[i
].unicode_allowed
[j
] ?
748 WideToUTF16(idn_cases
[i
].unicode_output
) :
749 ASCIIToUTF16(idn_cases
[i
].input
));
750 AppendLanguagesToOutputs(kLanguages
[j
], &expected
, &output
);
751 EXPECT_EQ(expected
, output
);
756 TEST(NetUtilTest
, CompliantHost
) {
757 const CompliantHostCase compliant_host_cases
[] = {
772 {"a.-a9", "", false},
775 {"1-.a-b", "", true},
776 {"1_.a-b", "", false},
777 {"1-2.a_b", "", true},
778 {"a.b.c.d.e", "", true},
779 {"1.2.3.4.5", "", true},
780 {"1.2.3.4.5.", "", true},
783 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(compliant_host_cases
); ++i
) {
784 EXPECT_EQ(compliant_host_cases
[i
].expected_output
,
785 IsCanonicalizedHostCompliant(compliant_host_cases
[i
].host
,
786 compliant_host_cases
[i
].desired_tld
));
790 TEST(NetUtilTest
, StripWWW
) {
791 EXPECT_EQ(base::string16(), StripWWW(base::string16()));
792 EXPECT_EQ(base::string16(), StripWWW(ASCIIToUTF16("www.")));
793 EXPECT_EQ(ASCIIToUTF16("blah"), StripWWW(ASCIIToUTF16("www.blah")));
794 EXPECT_EQ(ASCIIToUTF16("blah"), StripWWW(ASCIIToUTF16("blah")));
798 #define JPEG_EXT L".jpg"
799 #define HTML_EXT L".htm"
800 #elif defined(OS_MACOSX)
801 #define JPEG_EXT L".jpeg"
802 #define HTML_EXT L".html"
804 #define JPEG_EXT L".jpg"
805 #define HTML_EXT L".html"
807 #define TXT_EXT L".txt"
808 #define TAR_EXT L".tar"
810 TEST(NetUtilTest
, GenerateSafeFileName
) {
812 const char* mime_type
;
813 const base::FilePath::CharType
* filename
;
814 const base::FilePath::CharType
* expected_filename
;
819 FILE_PATH_LITERAL("C:\\foo\\bar.htm"),
820 FILE_PATH_LITERAL("C:\\foo\\bar.htm")
824 FILE_PATH_LITERAL("C:\\foo\\bar.html"),
825 FILE_PATH_LITERAL("C:\\foo\\bar.html")
829 FILE_PATH_LITERAL("C:\\foo\\bar"),
830 FILE_PATH_LITERAL("C:\\foo\\bar.htm")
834 FILE_PATH_LITERAL("C:\\bar.html"),
835 FILE_PATH_LITERAL("C:\\bar.html")
839 FILE_PATH_LITERAL("C:\\bar"),
840 FILE_PATH_LITERAL("C:\\bar.png")
844 FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
845 FILE_PATH_LITERAL("C:\\foo\\bar.exe")
849 FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
850 FILE_PATH_LITERAL("C:\\foo\\bar.exe")
854 FILE_PATH_LITERAL("C:\\foo\\google.com"),
855 FILE_PATH_LITERAL("C:\\foo\\google.com")
859 FILE_PATH_LITERAL("C:\\foo\\con.htm"),
860 FILE_PATH_LITERAL("C:\\foo\\_con.htm")
864 FILE_PATH_LITERAL("C:\\foo\\con"),
865 FILE_PATH_LITERAL("C:\\foo\\_con.htm")
869 FILE_PATH_LITERAL("C:\\foo\\harmless.{not-really-this-may-be-a-guid}"),
870 FILE_PATH_LITERAL("C:\\foo\\harmless.download")
874 FILE_PATH_LITERAL("C:\\foo\\harmless.local"),
875 FILE_PATH_LITERAL("C:\\foo\\harmless.download")
879 FILE_PATH_LITERAL("C:\\foo\\harmless.lnk"),
880 FILE_PATH_LITERAL("C:\\foo\\harmless.download")
884 FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-"),
885 FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-")
887 // Allow extension synonyms.
890 FILE_PATH_LITERAL("C:\\foo\\bar.jpg"),
891 FILE_PATH_LITERAL("C:\\foo\\bar.jpg")
895 FILE_PATH_LITERAL("C:\\foo\\bar.jpeg"),
896 FILE_PATH_LITERAL("C:\\foo\\bar.jpeg")
898 #else // !defined(OS_WIN)
901 FILE_PATH_LITERAL("/foo/bar.htm"),
902 FILE_PATH_LITERAL("/foo/bar.htm")
906 FILE_PATH_LITERAL("/foo/bar.html"),
907 FILE_PATH_LITERAL("/foo/bar.html")
911 FILE_PATH_LITERAL("/foo/bar"),
912 FILE_PATH_LITERAL("/foo/bar.html")
916 FILE_PATH_LITERAL("/bar.html"),
917 FILE_PATH_LITERAL("/bar.html")
921 FILE_PATH_LITERAL("/bar"),
922 FILE_PATH_LITERAL("/bar.png")
926 FILE_PATH_LITERAL("/foo/bar.exe"),
927 FILE_PATH_LITERAL("/foo/bar.exe")
931 FILE_PATH_LITERAL("/foo/google.com"),
932 FILE_PATH_LITERAL("/foo/google.com")
936 FILE_PATH_LITERAL("/foo/con.htm"),
937 FILE_PATH_LITERAL("/foo/con.htm")
941 FILE_PATH_LITERAL("/foo/con"),
942 FILE_PATH_LITERAL("/foo/con.html")
944 // Allow extension synonyms.
947 FILE_PATH_LITERAL("/bar.jpg"),
948 FILE_PATH_LITERAL("/bar.jpg")
952 FILE_PATH_LITERAL("/bar.jpeg"),
953 FILE_PATH_LITERAL("/bar.jpeg")
955 #endif // !defined(OS_WIN)
958 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(safe_tests
); ++i
) {
959 base::FilePath
file_path(safe_tests
[i
].filename
);
960 GenerateSafeFileName(safe_tests
[i
].mime_type
, false, &file_path
);
961 EXPECT_EQ(safe_tests
[i
].expected_filename
, file_path
.value())
962 << "Iteration " << i
;
966 TEST(NetUtilTest
, GenerateFileName
) {
967 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
968 // This test doesn't run when the locale is not UTF-8 because some of the
969 // string conversions fail. This is OK (we have the default value) but they
970 // don't match our expectations.
971 std::string locale
= setlocale(LC_CTYPE
, NULL
);
972 StringToLowerASCII(&locale
);
973 EXPECT_TRUE(locale
.find("utf-8") != std::string::npos
||
974 locale
.find("utf8") != std::string::npos
)
975 << "Your locale (" << locale
<< ") must be set to UTF-8 "
976 << "for this test to pass!";
979 // Tests whether the correct filename is selected from the the given
980 // parameters and that Content-Disposition headers are properly
981 // handled including failovers when the header is malformed.
982 const GenerateFilenameCase selection_tests
[] = {
985 "http://www.google.com/",
986 "attachment; filename=test.html",
995 "http://www.google.com/",
996 "attachment; filename=\"test.html\"",
1005 "http://www.google.com/",
1006 "attachment; filename= \"test.html\"",
1015 "http://www.google.com/",
1016 "attachment; filename = \"test.html\"",
1023 { // filename is whitespace. Should failover to URL host
1025 "http://www.google.com/",
1026 "attachment; filename= ",
1035 "http://www.google.com/path/test.html",
1045 "http://www.google.com/path/test.html",
1055 "http://www.google.com/",
1065 "http://www.google.com/test.html",
1073 { // Now that we use src/url's ExtractFileName, this case falls back to
1074 // the hostname. If this behavior is not desirable, we'd better change
1075 // ExtractFileName (in url_parse).
1077 "http://www.google.com/path/",
1087 "http://www.google.com/path",
1107 "file:///path/testfile",
1117 "non-standard-scheme:",
1125 { // C-D should override default
1127 "http://www.google.com/",
1128 "attachment; filename =\"test.html\"",
1135 { // But the URL shouldn't
1137 "http://www.google.com/",
1147 "http://www.google.com/",
1148 "attachment; filename=\"../test.html\"",
1157 "http://www.google.com/",
1158 "attachment; filename=\"..\\test.html\"",
1167 "http://www.google.com/",
1168 "attachment; filename=\"..\\\\test.html\"",
1175 { // Filename disappears after leading and trailing periods are removed.
1177 "http://www.google.com/",
1178 "attachment; filename=\"..\"",
1185 { // C-D specified filename disappears. Failover to final filename.
1187 "http://www.google.com/test.html",
1188 "attachment; filename=\"..\"",
1195 // Below is a small subset of cases taken from HttpContentDisposition tests.
1198 "http://www.google.com/",
1199 "attachment; filename=\"%EC%98%88%EC%88%A0%20"
1200 "%EC%98%88%EC%88%A0.jpg\"",
1205 L
"\uc608\uc220 \uc608\uc220.jpg"
1209 "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
1215 L
"\uc608\uc220 \uc608\uc220.jpg"
1219 "http://www.google.com/",
1224 L
"\uB2E4\uC6B4\uB85C\uB4DC",
1225 L
"\uB2E4\uC6B4\uB85C\uB4DC"
1229 "http://www.google.com/",
1230 "attachment; filename=\"=?EUC-JP?Q?=B7=DD=BD="
1236 L
"\u82b8\u88533.png"
1240 "http://www.example.com/images?id=3",
1241 "attachment; filename=caf\xc3\xa9.png",
1250 "http://www.example.com/images?id=3",
1251 "attachment; filename=caf\xe5.png",
1260 "http://www.example.com/file?id=3",
1261 "attachment; name=\xcf\xc2\xd4\xd8.zip",
1268 { // Invalid C-D header. Extracts filename from url.
1270 "http://www.google.com/test.html",
1271 "attachment; filename==?iiso88591?Q?caf=EG?=",
1278 // about: and data: URLs
1291 "data:,looks/like/a.path",
1301 "data:text/plain;base64,VG8gYmUgb3Igbm90IHRvIGJlLg=",
1311 "data:,looks/like/a.path",
1316 L
"default_filename_is_given",
1317 L
"default_filename_is_given"
1321 "data:,looks/like/a.path",
1326 L
"\u65e5\u672c\u8a9e", // Japanese Kanji.
1327 L
"\u65e5\u672c\u8a9e"
1329 { // The filename encoding is specified by the referrer charset.
1331 "http://example.com/V%FDvojov%E1%20psychologie.doc",
1337 L
"V\u00fdvojov\u00e1 psychologie.doc"
1339 { // Suggested filename takes precedence over URL
1341 "http://www.google.com/test",
1349 { // The content-disposition has higher precedence over the suggested name.
1351 "http://www.google.com/test",
1352 "attachment; filename=test.html",
1360 { // The filename encoding doesn't match the referrer charset, the system
1361 // charset, or UTF-8.
1362 // TODO(jshin): we need to handle this case.
1364 "http://example.com/V%FDvojov%E1%20psychologie.doc",
1370 L
"V\u00fdvojov\u00e1 psychologie.doc",
1373 // Raw 8bit characters in C-D
1376 "http://www.example.com/images?id=3",
1377 "attachment; filename=caf\xc3\xa9.png",
1386 "http://www.example.com/images?id=3",
1387 "attachment; filename=caf\xe5.png",
1394 { // No 'filename' keyword in the disposition, use the URL
1396 "http://www.evil.com/my_download.txt",
1404 { // Spaces in the disposition file name
1406 "http://www.frontpagehacker.com/a_download.exe",
1407 "filename=My Downloaded File.exe",
1410 "application/octet-stream",
1412 L
"My Downloaded File.exe"
1416 "http://www.examples.com/",
1418 "filename=\"%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg\"",
1423 L
"\uc608\uc220 \uc608\uc220.jpg"
1425 { // name= parameter
1427 "http://www.examples.com/q.cgi?id=abc",
1428 "attachment; name=abc de.pdf",
1431 "application/octet-stream",
1437 "http://www.example.com/path",
1438 "filename=\"=?EUC-JP?Q?=B7=DD=BD=D13=2Epng?=\"",
1443 L
"\x82b8\x8853" L
"3.png"
1445 { // The following two have invalid CD headers and filenames come from the
1448 "http://www.example.com/test%20123",
1449 "attachment; filename==?iiso88591?Q?caf=EG?=",
1454 L
"test 123" JPEG_EXT
1458 "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
1459 "malformed_disposition",
1464 L
"\uc608\uc220 \uc608\uc220.jpg"
1466 { // Invalid C-D. No filename from URL. Falls back to 'download'.
1468 "http://www.google.com/path1/path2/",
1469 "attachment; filename==?iso88591?Q?caf=E3?",
1474 L
"download" JPEG_EXT
1478 // Tests filename generation. Once the correct filename is
1479 // selected, they should be passed through the validation steps and
1480 // a correct extension should be added if necessary.
1481 const GenerateFilenameCase generation_tests
[] = {
1482 // Dotfiles. Ensures preceeding period(s) stripped.
1485 "http://www.google.com/.test.html",
1495 "http://www.google.com/.test",
1505 "http://www.google.com/..test",
1513 { // Disposition has relative paths, remove directory separators
1515 "http://www.evil.com/my_download.txt",
1516 "filename=../../../../././../a_file_name.txt",
1521 L
"-..-..-..-.-.-..-a_file_name.txt"
1523 { // Disposition has parent directories, remove directory separators
1525 "http://www.evil.com/my_download.txt",
1526 "filename=dir1/dir2/a_file_name.txt",
1531 L
"dir1-dir2-a_file_name.txt"
1533 { // Disposition has relative paths, remove directory separators
1535 "http://www.evil.com/my_download.txt",
1536 "filename=..\\..\\..\\..\\.\\.\\..\\a_file_name.txt",
1541 L
"-..-..-..-.-.-..-a_file_name.txt"
1543 { // Disposition has parent directories, remove directory separators
1545 "http://www.evil.com/my_download.txt",
1546 "filename=dir1\\dir2\\a_file_name.txt",
1551 L
"dir1-dir2-a_file_name.txt"
1553 { // No useful information in disposition or URL, use default
1555 "http://www.truncated.com/path/",
1563 { // Filename looks like HTML?
1565 "http://www.evil.com/get/malware/here",
1566 "filename=\"<blink>Hello kitty</blink>\"",
1571 L
"-blink-Hello kitty--blink-" TXT_EXT
1573 { // A normal avi should get .avi and not .avi.avi
1575 "https://blah.google.com/misc/2.avi",
1583 { // Extension generation
1585 "http://www.example.com/my-cat",
1595 "http://www.example.com/my-cat",
1605 "http://www.example.com/my-cat",
1613 { // Unknown MIME type
1615 "http://www.example.com/my-cat",
1625 "http://www.example.com/my-cat.jpg",
1626 "filename=my-cat.jpg",
1633 // Windows specific tests
1637 "http://www.goodguy.com/evil.exe",
1638 "filename=evil.exe",
1647 "http://www.goodguy.com/ok.exe",
1651 "binary/octet-stream",
1657 "http://www.goodguy.com/evil.dll",
1658 "filename=evil.dll",
1667 "http://www.goodguy.com/evil.exe",
1671 "application/rss+xml",
1675 // Test truncation of trailing dots and spaces
1678 "http://www.goodguy.com/evil.exe ",
1679 "filename=evil.exe ",
1682 "binary/octet-stream",
1688 "http://www.goodguy.com/evil.exe.",
1689 "filename=evil.exe.",
1692 "binary/octet-stream",
1698 "http://www.goodguy.com/evil.exe. . .",
1699 "filename=evil.exe. . .",
1702 "binary/octet-stream",
1708 "http://www.goodguy.com/evil.",
1712 "binary/octet-stream",
1718 "http://www.goodguy.com/. . . . .",
1719 "filename=. . . . .",
1722 "binary/octet-stream",
1728 "http://www.badguy.com/attachment?name=meh.exe%C2%A0",
1729 "attachment; filename=\"meh.exe\xC2\xA0\"",
1732 "binary/octet-stream",
1739 "http://www.goodguy.com/utils.js",
1740 "filename=utils.js",
1743 "application/x-javascript",
1749 "http://www.goodguy.com/contacts.js",
1750 "filename=contacts.js",
1759 "http://www.goodguy.com/utils.js",
1760 "filename=utils.js",
1769 "http://www.goodguy.com/utils.js",
1770 "filename=utils.js",
1773 "text/javascript;version=2",
1779 "http://www.goodguy.com/utils.js",
1780 "filename=utils.js",
1783 "application/ecmascript",
1789 "http://www.goodguy.com/utils.js",
1790 "filename=utils.js",
1793 "application/ecmascript;version=4",
1799 "http://www.goodguy.com/program.exe",
1800 "filename=program.exe",
1803 "application/foo-bar",
1809 "http://www.evil.com/../foo.txt",
1810 "filename=../foo.txt",
1819 "http://www.evil.com/..\\foo.txt",
1820 "filename=..\\foo.txt",
1829 "http://www.evil.com/.hidden",
1839 "http://www.evil.com/trailing.",
1840 "filename=trailing.",
1853 "http://www.evil.com/trailing.",
1854 "filename=trailing.",
1860 L
"trailing-" TXT_EXT
1867 "http://www.evil.com/.",
1877 "http://www.evil.com/..",
1887 "http://www.evil.com/...",
1895 { // Note that this one doesn't have "filename=" on it.
1897 "http://www.evil.com/",
1903 L
"download" JPEG_EXT
1907 "http://www.evil.com/",
1913 L
"download" JPEG_EXT
1917 "http://www.example.com/simple",
1921 "application/octet-stream",
1925 // Reserved words on Windows
1928 "http://www.goodguy.com/COM1",
1932 "application/foo-bar",
1942 "http://www.goodguy.com/COM4.txt",
1943 "filename=COM4.txt",
1956 "http://www.goodguy.com/lpt1.TXT",
1957 "filename=lpt1.TXT",
1970 "http://www.goodguy.com/clock$.txt",
1971 "filename=clock$.txt",
1982 { // Validation should also apply to sugested name
1984 "http://www.goodguy.com/blah$.txt",
1985 "filename=clock$.txt",
1998 "http://www.goodguy.com/mycom1.foo",
1999 "filename=mycom1.foo",
2008 "http://www.badguy.com/Setup.exe.local",
2009 "filename=Setup.exe.local",
2012 "application/foo-bar",
2015 L
"Setup.exe.download"
2022 "http://www.badguy.com/Setup.exe.local",
2023 "filename=Setup.exe.local.local",
2026 "application/foo-bar",
2029 L
"Setup.exe.local.download"
2031 L
"Setup.exe.local.local"
2036 "http://www.badguy.com/Setup.exe.lnk",
2037 "filename=Setup.exe.lnk",
2040 "application/foo-bar",
2043 L
"Setup.exe.download"
2050 "http://www.badguy.com/Desktop.ini",
2051 "filename=Desktop.ini",
2054 "application/foo-bar",
2064 "http://www.badguy.com/Thumbs.db",
2065 "filename=Thumbs.db",
2068 "application/foo-bar",
2078 "http://www.hotmail.com",
2079 "filename=source.jpg",
2082 "application/x-javascript",
2086 { // http://crbug.com/5772.
2088 "http://www.example.com/foo.tar.gz",
2092 "application/x-tar",
2096 { // http://crbug.com/52250.
2098 "http://www.example.com/foo.tgz",
2102 "application/x-tar",
2106 { // http://crbug.com/7337.
2108 "http://maged.lordaeron.org/blank.reg",
2118 "http://www.example.com/bar.tar",
2122 "application/x-tar",
2128 "http://www.example.com/bar.bogus",
2132 "application/x-tar",
2136 { // http://crbug.com/20337
2138 "http://www.example.com/.download.txt",
2139 "filename=.download.txt",
2146 { // http://crbug.com/56855.
2148 "http://www.example.com/bar.sh",
2156 { // http://crbug.com/61571
2158 "http://www.example.com/npdf.php?fn=foobar.pdf",
2166 { // Shouldn't overwrite C-D specified extension.
2168 "http://www.example.com/npdf.php?fn=foobar.pdf",
2169 "filename=foobar.jpg",
2176 { // http://crbug.com/87719
2178 "http://www.example.com/image.aspx?id=blargh",
2186 #if defined(OS_CHROMEOS)
2187 { // http://crosbug.com/26028
2189 "http://www.example.com/fooa%cc%88.txt",
2200 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(selection_tests
); ++i
)
2201 RunGenerateFileNameTestCase(&selection_tests
[i
]);
2203 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(generation_tests
); ++i
)
2204 RunGenerateFileNameTestCase(&generation_tests
[i
]);
2206 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(generation_tests
); ++i
) {
2207 GenerateFilenameCase test_case
= generation_tests
[i
];
2208 test_case
.referrer_charset
= "GBK";
2209 RunGenerateFileNameTestCase(&test_case
);
2213 // This is currently a windows specific function.
2217 struct GetDirectoryListingEntryCase
{
2218 const wchar_t* name
;
2219 const char* raw_bytes
;
2223 const char* expected
;
2227 TEST(NetUtilTest
, GetDirectoryListingEntry
) {
2228 const GetDirectoryListingEntryCase test_cases
[] = {
2234 "<script>addRow(\"Foo\",\"Foo\",0,\"9.8 kB\",\"\");</script>\n"},
2240 "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,\"9.8 kB\",\"\");</script>"
2247 "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,\"9.8 kB\",\"\");</script>"
2249 // U+D55C0 U+AE00. raw_bytes is empty (either a local file with
2250 // UTF-8/UTF-16 encoding or a remote file on an ftp server using UTF-8
2251 {L
"\xD55C\xAE00.txt",
2256 "<script>addRow(\"\\uD55C\\uAE00.txt\",\"%ED%95%9C%EA%B8%80.txt\""
2257 ",0,\"9.8 kB\",\"\");</script>\n"},
2258 // U+D55C0 U+AE00. raw_bytes is the corresponding EUC-KR sequence:
2259 // a local or remote file in EUC-KR.
2260 {L
"\xD55C\xAE00.txt",
2261 "\xC7\xD1\xB1\xDB.txt",
2265 "<script>addRow(\"\\uD55C\\uAE00.txt\",\"%C7%D1%B1%DB.txt\""
2266 ",0,\"9.8 kB\",\"\");</script>\n"},
2269 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_cases
); ++i
) {
2270 const std::string results
= GetDirectoryListingEntry(
2271 WideToUTF16(test_cases
[i
].name
),
2272 test_cases
[i
].raw_bytes
,
2273 test_cases
[i
].is_dir
,
2274 test_cases
[i
].filesize
,
2275 test_cases
[i
].time
);
2276 EXPECT_EQ(test_cases
[i
].expected
, results
);
2282 TEST(NetUtilTest
, ParseHostAndPort
) {
2286 const char* expected_host
;
2290 {"foo:10", true, "foo", 10},
2291 {"foo", true, "foo", -1},
2293 "[1080:0:0:0:8:800:200C:4171]:11",
2295 "[1080:0:0:0:8:800:200C:4171]",
2299 {"foo:bar", false, "", -1},
2300 {"foo:", false, "", -1},
2301 {":", false, "", -1},
2302 {":80", false, "", -1},
2303 {"", false, "", -1},
2304 {"porttoolong:300000", false, "", -1},
2305 {"usrname@host", false, "", -1},
2306 {"usrname:password@host", false, "", -1},
2307 {":password@host", false, "", -1},
2308 {":password@host:80", false, "", -1},
2309 {":password@host", false, "", -1},
2310 {"@host", false, "", -1},
2313 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
2316 bool ok
= ParseHostAndPort(tests
[i
].input
, &host
, &port
);
2318 EXPECT_EQ(tests
[i
].success
, ok
);
2320 if (tests
[i
].success
) {
2321 EXPECT_EQ(tests
[i
].expected_host
, host
);
2322 EXPECT_EQ(tests
[i
].expected_port
, port
);
2327 TEST(NetUtilTest
, GetHostAndPort
) {
2330 const char* expected_host_and_port
;
2332 { GURL("http://www.foo.com/x"), "www.foo.com:80"},
2333 { GURL("http://www.foo.com:21/x"), "www.foo.com:21"},
2335 // For IPv6 literals should always include the brackets.
2336 { GURL("http://[1::2]/x"), "[1::2]:80"},
2337 { GURL("http://[::a]:33/x"), "[::a]:33"},
2339 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
2340 std::string host_and_port
= GetHostAndPort(tests
[i
].url
);
2341 EXPECT_EQ(std::string(tests
[i
].expected_host_and_port
), host_and_port
);
2345 TEST(NetUtilTest
, GetHostAndOptionalPort
) {
2348 const char* expected_host_and_port
;
2350 { GURL("http://www.foo.com/x"), "www.foo.com"},
2351 { GURL("http://www.foo.com:21/x"), "www.foo.com:21"},
2353 // For IPv6 literals should always include the brackets.
2354 { GURL("http://[1::2]/x"), "[1::2]"},
2355 { GURL("http://[::a]:33/x"), "[::a]:33"},
2357 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
2358 std::string host_and_port
= GetHostAndOptionalPort(tests
[i
].url
);
2359 EXPECT_EQ(std::string(tests
[i
].expected_host_and_port
), host_and_port
);
2363 TEST(NetUtilTest
, IPAddressToString
) {
2364 uint8 addr1
[4] = {0, 0, 0, 0};
2365 EXPECT_EQ("0.0.0.0", IPAddressToString(addr1
, sizeof(addr1
)));
2367 uint8 addr2
[4] = {192, 168, 0, 1};
2368 EXPECT_EQ("192.168.0.1", IPAddressToString(addr2
, sizeof(addr2
)));
2370 uint8 addr3
[16] = {0xFE, 0xDC, 0xBA, 0x98};
2371 EXPECT_EQ("fedc:ba98::", IPAddressToString(addr3
, sizeof(addr3
)));
2374 TEST(NetUtilTest
, IPAddressToStringWithPort
) {
2375 uint8 addr1
[4] = {0, 0, 0, 0};
2376 EXPECT_EQ("0.0.0.0:3", IPAddressToStringWithPort(addr1
, sizeof(addr1
), 3));
2378 uint8 addr2
[4] = {192, 168, 0, 1};
2379 EXPECT_EQ("192.168.0.1:99",
2380 IPAddressToStringWithPort(addr2
, sizeof(addr2
), 99));
2382 uint8 addr3
[16] = {0xFE, 0xDC, 0xBA, 0x98};
2383 EXPECT_EQ("[fedc:ba98::]:8080",
2384 IPAddressToStringWithPort(addr3
, sizeof(addr3
), 8080));
2387 TEST(NetUtilTest
, NetAddressToString_IPv4
) {
2392 {{0, 0, 0, 0}, "0.0.0.0"},
2393 {{127, 0, 0, 1}, "127.0.0.1"},
2394 {{192, 168, 0, 1}, "192.168.0.1"},
2397 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
2398 SockaddrStorage storage
;
2399 MakeIPv4Address(tests
[i
].addr
, 80, &storage
);
2400 std::string result
= NetAddressToString(storage
.addr
, storage
.addr_len
);
2401 EXPECT_EQ(std::string(tests
[i
].result
), result
);
2405 TEST(NetUtilTest
, NetAddressToString_IPv6
) {
2410 {{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA,
2411 0x98, 0x76, 0x54, 0x32, 0x10},
2412 "fedc:ba98:7654:3210:fedc:ba98:7654:3210"},
2415 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
2416 SockaddrStorage storage
;
2417 MakeIPv6Address(tests
[i
].addr
, 80, &storage
);
2418 EXPECT_EQ(std::string(tests
[i
].result
),
2419 NetAddressToString(storage
.addr
, storage
.addr_len
));
2423 TEST(NetUtilTest
, NetAddressToStringWithPort_IPv4
) {
2424 uint8 addr
[] = {127, 0, 0, 1};
2425 SockaddrStorage storage
;
2426 MakeIPv4Address(addr
, 166, &storage
);
2427 std::string result
= NetAddressToStringWithPort(storage
.addr
,
2429 EXPECT_EQ("127.0.0.1:166", result
);
2432 TEST(NetUtilTest
, NetAddressToStringWithPort_IPv6
) {
2434 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA,
2435 0x98, 0x76, 0x54, 0x32, 0x10
2437 SockaddrStorage storage
;
2438 MakeIPv6Address(addr
, 361, &storage
);
2439 std::string result
= NetAddressToStringWithPort(storage
.addr
,
2442 // May fail on systems that don't support IPv6.
2443 if (!result
.empty())
2444 EXPECT_EQ("[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:361", result
);
2447 TEST(NetUtilTest
, GetHostName
) {
2448 // We can't check the result of GetHostName() directly, since the result
2449 // will differ across machines. Our goal here is to simply exercise the
2450 // code path, and check that things "look about right".
2451 std::string hostname
= GetHostName();
2452 EXPECT_FALSE(hostname
.empty());
2455 TEST(NetUtilTest
, FormatUrl
) {
2456 FormatUrlTypes default_format_type
= kFormatUrlOmitUsernamePassword
;
2457 const UrlTestData tests
[] = {
2458 {"Empty URL", "", "", default_format_type
, UnescapeRule::NORMAL
, L
"", 0},
2461 "http://www.google.com/", "", default_format_type
, UnescapeRule::NORMAL
,
2462 L
"http://www.google.com/", 7},
2464 {"With a port number and a reference",
2465 "http://www.google.com:8080/#\xE3\x82\xB0", "", default_format_type
,
2466 UnescapeRule::NORMAL
,
2467 L
"http://www.google.com:8080/#\x30B0", 7},
2469 // -------- IDN tests --------
2470 {"Japanese IDN with ja",
2471 "http://xn--l8jvb1ey91xtjb.jp", "ja", default_format_type
,
2472 UnescapeRule::NORMAL
, L
"http://\x671d\x65e5\x3042\x3055\x3072.jp/", 7},
2474 {"Japanese IDN with en",
2475 "http://xn--l8jvb1ey91xtjb.jp", "en", default_format_type
,
2476 UnescapeRule::NORMAL
, L
"http://xn--l8jvb1ey91xtjb.jp/", 7},
2478 {"Japanese IDN without any languages",
2479 "http://xn--l8jvb1ey91xtjb.jp", "", default_format_type
,
2480 UnescapeRule::NORMAL
,
2481 // Single script is safe for empty languages.
2482 L
"http://\x671d\x65e5\x3042\x3055\x3072.jp/", 7},
2484 {"mailto: with Japanese IDN",
2485 "mailto:foo@xn--l8jvb1ey91xtjb.jp", "ja", default_format_type
,
2486 UnescapeRule::NORMAL
,
2487 // GURL doesn't assume an email address's domain part as a host name.
2488 L
"mailto:foo@xn--l8jvb1ey91xtjb.jp", 7},
2490 {"file: with Japanese IDN",
2491 "file://xn--l8jvb1ey91xtjb.jp/config.sys", "ja", default_format_type
,
2492 UnescapeRule::NORMAL
,
2493 L
"file://\x671d\x65e5\x3042\x3055\x3072.jp/config.sys", 7},
2495 {"ftp: with Japanese IDN",
2496 "ftp://xn--l8jvb1ey91xtjb.jp/config.sys", "ja", default_format_type
,
2497 UnescapeRule::NORMAL
,
2498 L
"ftp://\x671d\x65e5\x3042\x3055\x3072.jp/config.sys", 6},
2500 // -------- omit_username_password flag tests --------
2501 {"With username and password, omit_username_password=false",
2502 "http://user:passwd@example.com/foo", "",
2503 kFormatUrlOmitNothing
, UnescapeRule::NORMAL
,
2504 L
"http://user:passwd@example.com/foo", 19},
2506 {"With username and password, omit_username_password=true",
2507 "http://user:passwd@example.com/foo", "", default_format_type
,
2508 UnescapeRule::NORMAL
, L
"http://example.com/foo", 7},
2510 {"With username and no password",
2511 "http://user@example.com/foo", "", default_format_type
,
2512 UnescapeRule::NORMAL
, L
"http://example.com/foo", 7},
2514 {"Just '@' without username and password",
2515 "http://@example.com/foo", "", default_format_type
, UnescapeRule::NORMAL
,
2516 L
"http://example.com/foo", 7},
2518 // GURL doesn't think local-part of an email address is username for URL.
2519 {"mailto:, omit_username_password=true",
2520 "mailto:foo@example.com", "", default_format_type
, UnescapeRule::NORMAL
,
2521 L
"mailto:foo@example.com", 7},
2523 // -------- unescape flag tests --------
2525 "http://%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB.jp/"
2526 "%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB"
2527 "?q=%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB", "en", default_format_type
,
2529 // GURL parses %-encoded hostnames into Punycode.
2530 L
"http://xn--qcka1pmc.jp/%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB"
2531 L
"?q=%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB", 7},
2533 {"Unescape normally",
2534 "http://%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB.jp/"
2535 "%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB"
2536 "?q=%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB", "en", default_format_type
,
2537 UnescapeRule::NORMAL
,
2538 L
"http://xn--qcka1pmc.jp/\x30B0\x30FC\x30B0\x30EB"
2539 L
"?q=\x30B0\x30FC\x30B0\x30EB", 7},
2541 {"Unescape normally including unescape spaces",
2542 "http://www.google.com/search?q=Hello%20World", "en", default_format_type
,
2543 UnescapeRule::SPACES
, L
"http://www.google.com/search?q=Hello World", 7},
2546 {"unescape=true with some special characters",
2547 "http://user%3A:%40passwd@example.com/foo%3Fbar?q=b%26z", "",
2548 kFormatUrlOmitNothing, UnescapeRule::NORMAL,
2549 L"http://user%3A:%40passwd@example.com/foo%3Fbar?q=b%26z", 25},
2551 // Disabled: the resultant URL becomes "...user%253A:%2540passwd...".
2553 // -------- omit http: --------
2554 {"omit http with user name",
2555 "http://user@example.com/foo", "", kFormatUrlOmitAll
,
2556 UnescapeRule::NORMAL
, L
"example.com/foo", 0},
2559 "http://www.google.com/", "en", kFormatUrlOmitHTTP
,
2560 UnescapeRule::NORMAL
, L
"www.google.com/",
2563 {"omit http with https",
2564 "https://www.google.com/", "en", kFormatUrlOmitHTTP
,
2565 UnescapeRule::NORMAL
, L
"https://www.google.com/",
2568 {"omit http starts with ftp.",
2569 "http://ftp.google.com/", "en", kFormatUrlOmitHTTP
,
2570 UnescapeRule::NORMAL
, L
"http://ftp.google.com/",
2573 // -------- omit trailing slash on bare hostname --------
2574 {"omit slash when it's the entire path",
2575 "http://www.google.com/", "en",
2576 kFormatUrlOmitTrailingSlashOnBareHostname
, UnescapeRule::NORMAL
,
2577 L
"http://www.google.com", 7},
2578 {"omit slash when there's a ref",
2579 "http://www.google.com/#ref", "en",
2580 kFormatUrlOmitTrailingSlashOnBareHostname
, UnescapeRule::NORMAL
,
2581 L
"http://www.google.com/#ref", 7},
2582 {"omit slash when there's a query",
2583 "http://www.google.com/?", "en",
2584 kFormatUrlOmitTrailingSlashOnBareHostname
, UnescapeRule::NORMAL
,
2585 L
"http://www.google.com/?", 7},
2586 {"omit slash when it's not the entire path",
2587 "http://www.google.com/foo", "en",
2588 kFormatUrlOmitTrailingSlashOnBareHostname
, UnescapeRule::NORMAL
,
2589 L
"http://www.google.com/foo", 7},
2590 {"omit slash for nonstandard URLs",
2591 "data:/", "en", kFormatUrlOmitTrailingSlashOnBareHostname
,
2592 UnescapeRule::NORMAL
, L
"data:/", 5},
2593 {"omit slash for file URLs",
2594 "file:///", "en", kFormatUrlOmitTrailingSlashOnBareHostname
,
2595 UnescapeRule::NORMAL
, L
"file:///", 7},
2597 // -------- view-source: --------
2599 "view-source:http://xn--qcka1pmc.jp/", "ja", default_format_type
,
2600 UnescapeRule::NORMAL
, L
"view-source:http://\x30B0\x30FC\x30B0\x30EB.jp/",
2603 {"view-source of view-source",
2604 "view-source:view-source:http://xn--qcka1pmc.jp/", "ja",
2605 default_format_type
, UnescapeRule::NORMAL
,
2606 L
"view-source:view-source:http://xn--qcka1pmc.jp/", 12},
2608 // view-source should omit http and trailing slash where non-view-source
2610 {"view-source omit http",
2611 "view-source:http://a.b/c", "en", kFormatUrlOmitAll
,
2612 UnescapeRule::NORMAL
, L
"view-source:a.b/c",
2614 {"view-source omit http starts with ftp.",
2615 "view-source:http://ftp.b/c", "en", kFormatUrlOmitAll
,
2616 UnescapeRule::NORMAL
, L
"view-source:http://ftp.b/c",
2618 {"view-source omit slash when it's the entire path",
2619 "view-source:http://a.b/", "en", kFormatUrlOmitAll
,
2620 UnescapeRule::NORMAL
, L
"view-source:a.b",
2624 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
2626 base::string16 formatted
= FormatUrl(
2627 GURL(tests
[i
].input
), tests
[i
].languages
, tests
[i
].format_types
,
2628 tests
[i
].escape_rules
, NULL
, &prefix_len
, NULL
);
2629 EXPECT_EQ(WideToUTF16(tests
[i
].output
), formatted
) << tests
[i
].description
;
2630 EXPECT_EQ(tests
[i
].prefix_len
, prefix_len
) << tests
[i
].description
;
2634 TEST(NetUtilTest
, FormatUrlParsed
) {
2635 // No unescape case.
2636 url_parse::Parsed parsed
;
2637 base::string16 formatted
= FormatUrl(
2638 GURL("http://\xE3\x82\xB0:\xE3\x83\xBC@xn--qcka1pmc.jp:8080/"
2639 "%E3%82%B0/?q=%E3%82%B0#\xE3\x82\xB0"),
2640 "ja", kFormatUrlOmitNothing
, UnescapeRule::NONE
, &parsed
, NULL
,
2642 EXPECT_EQ(WideToUTF16(
2643 L
"http://%E3%82%B0:%E3%83%BC@\x30B0\x30FC\x30B0\x30EB.jp:8080"
2644 L
"/%E3%82%B0/?q=%E3%82%B0#\x30B0"), formatted
);
2645 EXPECT_EQ(WideToUTF16(L
"%E3%82%B0"),
2646 formatted
.substr(parsed
.username
.begin
, parsed
.username
.len
));
2647 EXPECT_EQ(WideToUTF16(L
"%E3%83%BC"),
2648 formatted
.substr(parsed
.password
.begin
, parsed
.password
.len
));
2649 EXPECT_EQ(WideToUTF16(L
"\x30B0\x30FC\x30B0\x30EB.jp"),
2650 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
2651 EXPECT_EQ(WideToUTF16(L
"8080"),
2652 formatted
.substr(parsed
.port
.begin
, parsed
.port
.len
));
2653 EXPECT_EQ(WideToUTF16(L
"/%E3%82%B0/"),
2654 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
2655 EXPECT_EQ(WideToUTF16(L
"q=%E3%82%B0"),
2656 formatted
.substr(parsed
.query
.begin
, parsed
.query
.len
));
2657 EXPECT_EQ(WideToUTF16(L
"\x30B0"),
2658 formatted
.substr(parsed
.ref
.begin
, parsed
.ref
.len
));
2661 formatted
= FormatUrl(
2662 GURL("http://\xE3\x82\xB0:\xE3\x83\xBC@xn--qcka1pmc.jp:8080/"
2663 "%E3%82%B0/?q=%E3%82%B0#\xE3\x82\xB0"),
2664 "ja", kFormatUrlOmitNothing
, UnescapeRule::NORMAL
, &parsed
, NULL
,
2666 EXPECT_EQ(WideToUTF16(L
"http://\x30B0:\x30FC@\x30B0\x30FC\x30B0\x30EB.jp:8080"
2667 L
"/\x30B0/?q=\x30B0#\x30B0"), formatted
);
2668 EXPECT_EQ(WideToUTF16(L
"\x30B0"),
2669 formatted
.substr(parsed
.username
.begin
, parsed
.username
.len
));
2670 EXPECT_EQ(WideToUTF16(L
"\x30FC"),
2671 formatted
.substr(parsed
.password
.begin
, parsed
.password
.len
));
2672 EXPECT_EQ(WideToUTF16(L
"\x30B0\x30FC\x30B0\x30EB.jp"),
2673 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
2674 EXPECT_EQ(WideToUTF16(L
"8080"),
2675 formatted
.substr(parsed
.port
.begin
, parsed
.port
.len
));
2676 EXPECT_EQ(WideToUTF16(L
"/\x30B0/"),
2677 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
2678 EXPECT_EQ(WideToUTF16(L
"q=\x30B0"),
2679 formatted
.substr(parsed
.query
.begin
, parsed
.query
.len
));
2680 EXPECT_EQ(WideToUTF16(L
"\x30B0"),
2681 formatted
.substr(parsed
.ref
.begin
, parsed
.ref
.len
));
2683 // Omit_username_password + unescape case.
2684 formatted
= FormatUrl(
2685 GURL("http://\xE3\x82\xB0:\xE3\x83\xBC@xn--qcka1pmc.jp:8080/"
2686 "%E3%82%B0/?q=%E3%82%B0#\xE3\x82\xB0"),
2687 "ja", kFormatUrlOmitUsernamePassword
, UnescapeRule::NORMAL
, &parsed
,
2689 EXPECT_EQ(WideToUTF16(L
"http://\x30B0\x30FC\x30B0\x30EB.jp:8080"
2690 L
"/\x30B0/?q=\x30B0#\x30B0"), formatted
);
2691 EXPECT_FALSE(parsed
.username
.is_valid());
2692 EXPECT_FALSE(parsed
.password
.is_valid());
2693 EXPECT_EQ(WideToUTF16(L
"\x30B0\x30FC\x30B0\x30EB.jp"),
2694 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
2695 EXPECT_EQ(WideToUTF16(L
"8080"),
2696 formatted
.substr(parsed
.port
.begin
, parsed
.port
.len
));
2697 EXPECT_EQ(WideToUTF16(L
"/\x30B0/"),
2698 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
2699 EXPECT_EQ(WideToUTF16(L
"q=\x30B0"),
2700 formatted
.substr(parsed
.query
.begin
, parsed
.query
.len
));
2701 EXPECT_EQ(WideToUTF16(L
"\x30B0"),
2702 formatted
.substr(parsed
.ref
.begin
, parsed
.ref
.len
));
2704 // View-source case.
2706 FormatUrl(GURL("view-source:http://user:passwd@host:81/path?query#ref"),
2708 kFormatUrlOmitUsernamePassword
,
2709 UnescapeRule::NORMAL
,
2713 EXPECT_EQ(WideToUTF16(L
"view-source:http://host:81/path?query#ref"),
2715 EXPECT_EQ(WideToUTF16(L
"view-source:http"),
2716 formatted
.substr(parsed
.scheme
.begin
, parsed
.scheme
.len
));
2717 EXPECT_FALSE(parsed
.username
.is_valid());
2718 EXPECT_FALSE(parsed
.password
.is_valid());
2719 EXPECT_EQ(WideToUTF16(L
"host"),
2720 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
2721 EXPECT_EQ(WideToUTF16(L
"81"),
2722 formatted
.substr(parsed
.port
.begin
, parsed
.port
.len
));
2723 EXPECT_EQ(WideToUTF16(L
"/path"),
2724 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
2725 EXPECT_EQ(WideToUTF16(L
"query"),
2726 formatted
.substr(parsed
.query
.begin
, parsed
.query
.len
));
2727 EXPECT_EQ(WideToUTF16(L
"ref"),
2728 formatted
.substr(parsed
.ref
.begin
, parsed
.ref
.len
));
2731 formatted
= FormatUrl(GURL("http://host:8000/a?b=c#d"),
2734 UnescapeRule::NORMAL
,
2738 EXPECT_EQ(WideToUTF16(L
"host:8000/a?b=c#d"), formatted
);
2739 EXPECT_FALSE(parsed
.scheme
.is_valid());
2740 EXPECT_FALSE(parsed
.username
.is_valid());
2741 EXPECT_FALSE(parsed
.password
.is_valid());
2742 EXPECT_EQ(WideToUTF16(L
"host"),
2743 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
2744 EXPECT_EQ(WideToUTF16(L
"8000"),
2745 formatted
.substr(parsed
.port
.begin
, parsed
.port
.len
));
2746 EXPECT_EQ(WideToUTF16(L
"/a"),
2747 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
2748 EXPECT_EQ(WideToUTF16(L
"b=c"),
2749 formatted
.substr(parsed
.query
.begin
, parsed
.query
.len
));
2750 EXPECT_EQ(WideToUTF16(L
"d"),
2751 formatted
.substr(parsed
.ref
.begin
, parsed
.ref
.len
));
2753 // omit http starts with ftp case.
2754 formatted
= FormatUrl(GURL("http://ftp.host:8000/a?b=c#d"),
2757 UnescapeRule::NORMAL
,
2761 EXPECT_EQ(WideToUTF16(L
"http://ftp.host:8000/a?b=c#d"), formatted
);
2762 EXPECT_TRUE(parsed
.scheme
.is_valid());
2763 EXPECT_FALSE(parsed
.username
.is_valid());
2764 EXPECT_FALSE(parsed
.password
.is_valid());
2765 EXPECT_EQ(WideToUTF16(L
"http"),
2766 formatted
.substr(parsed
.scheme
.begin
, parsed
.scheme
.len
));
2767 EXPECT_EQ(WideToUTF16(L
"ftp.host"),
2768 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
2769 EXPECT_EQ(WideToUTF16(L
"8000"),
2770 formatted
.substr(parsed
.port
.begin
, parsed
.port
.len
));
2771 EXPECT_EQ(WideToUTF16(L
"/a"),
2772 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
2773 EXPECT_EQ(WideToUTF16(L
"b=c"),
2774 formatted
.substr(parsed
.query
.begin
, parsed
.query
.len
));
2775 EXPECT_EQ(WideToUTF16(L
"d"),
2776 formatted
.substr(parsed
.ref
.begin
, parsed
.ref
.len
));
2778 // omit http starts with 'f' case.
2779 formatted
= FormatUrl(GURL("http://f/"),
2782 UnescapeRule::NORMAL
,
2786 EXPECT_EQ(WideToUTF16(L
"f/"), formatted
);
2787 EXPECT_FALSE(parsed
.scheme
.is_valid());
2788 EXPECT_FALSE(parsed
.username
.is_valid());
2789 EXPECT_FALSE(parsed
.password
.is_valid());
2790 EXPECT_FALSE(parsed
.port
.is_valid());
2791 EXPECT_TRUE(parsed
.path
.is_valid());
2792 EXPECT_FALSE(parsed
.query
.is_valid());
2793 EXPECT_FALSE(parsed
.ref
.is_valid());
2794 EXPECT_EQ(WideToUTF16(L
"f"),
2795 formatted
.substr(parsed
.host
.begin
, parsed
.host
.len
));
2796 EXPECT_EQ(WideToUTF16(L
"/"),
2797 formatted
.substr(parsed
.path
.begin
, parsed
.path
.len
));
2800 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
2801 // results in the original GURL, for each ASCII character in the path.
2802 TEST(NetUtilTest
, FormatUrlRoundTripPathASCII
) {
2803 for (unsigned char test_char
= 32; test_char
< 128; ++test_char
) {
2804 GURL
url(std::string("http://www.google.com/") +
2805 static_cast<char>(test_char
));
2807 base::string16 formatted
= FormatUrl(url
,
2809 kFormatUrlOmitUsernamePassword
,
2810 UnescapeRule::NORMAL
,
2814 EXPECT_EQ(url
.spec(), GURL(formatted
).spec());
2818 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
2819 // results in the original GURL, for each escaped ASCII character in the path.
2820 TEST(NetUtilTest
, FormatUrlRoundTripPathEscaped
) {
2821 for (unsigned char test_char
= 32; test_char
< 128; ++test_char
) {
2822 std::string
original_url("http://www.google.com/");
2823 original_url
.push_back('%');
2824 original_url
.append(base::HexEncode(&test_char
, 1));
2826 GURL
url(original_url
);
2828 base::string16 formatted
= FormatUrl(url
,
2830 kFormatUrlOmitUsernamePassword
,
2831 UnescapeRule::NORMAL
,
2835 EXPECT_EQ(url
.spec(), GURL(formatted
).spec());
2839 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
2840 // results in the original GURL, for each ASCII character in the query.
2841 TEST(NetUtilTest
, FormatUrlRoundTripQueryASCII
) {
2842 for (unsigned char test_char
= 32; test_char
< 128; ++test_char
) {
2843 GURL
url(std::string("http://www.google.com/?") +
2844 static_cast<char>(test_char
));
2846 base::string16 formatted
= FormatUrl(url
,
2848 kFormatUrlOmitUsernamePassword
,
2849 UnescapeRule::NORMAL
,
2853 EXPECT_EQ(url
.spec(), GURL(formatted
).spec());
2857 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
2858 // only results in a different GURL for certain characters.
2859 TEST(NetUtilTest
, FormatUrlRoundTripQueryEscaped
) {
2860 // A full list of characters which FormatURL should unescape and GURL should
2861 // not escape again, when they appear in a query string.
2862 const char* kUnescapedCharacters
=
2863 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_~";
2864 for (unsigned char test_char
= 0; test_char
< 128; ++test_char
) {
2865 std::string
original_url("http://www.google.com/?");
2866 original_url
.push_back('%');
2867 original_url
.append(base::HexEncode(&test_char
, 1));
2869 GURL
url(original_url
);
2871 base::string16 formatted
= FormatUrl(url
,
2873 kFormatUrlOmitUsernamePassword
,
2874 UnescapeRule::NORMAL
,
2880 strchr(kUnescapedCharacters
, static_cast<char>(test_char
))) {
2881 EXPECT_NE(url
.spec(), GURL(formatted
).spec());
2883 EXPECT_EQ(url
.spec(), GURL(formatted
).spec());
2888 TEST(NetUtilTest
, FormatUrlWithOffsets
) {
2889 const AdjustOffsetCase null_cases
[] = {
2890 {0, base::string16::npos
},
2892 CheckAdjustedOffsets(std::string(), "en", kFormatUrlOmitNothing
,
2893 UnescapeRule::NORMAL
, null_cases
, arraysize(null_cases
), NULL
);
2895 const AdjustOffsetCase basic_cases
[] = {
2905 {26, base::string16::npos
},
2906 {500000, base::string16::npos
},
2907 {base::string16::npos
, base::string16::npos
},
2909 const size_t basic_offsets
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
2910 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};
2911 CheckAdjustedOffsets("http://www.google.com/foo/", "en",
2912 kFormatUrlOmitNothing
, UnescapeRule::NORMAL
, basic_cases
,
2913 arraysize(basic_cases
), basic_offsets
);
2915 const AdjustOffsetCase omit_auth_cases_1
[] = {
2917 {7, base::string16::npos
},
2918 {8, base::string16::npos
},
2919 {10, base::string16::npos
},
2920 {12, base::string16::npos
},
2921 {14, base::string16::npos
},
2925 const size_t omit_auth_offsets_1
[] = {0, 1, 2, 3, 4, 5, 6, kNpos
, kNpos
,
2926 kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2927 16, 17, 18, 19, 20, 21};
2928 CheckAdjustedOffsets("http://foo:bar@www.google.com/", "en",
2929 kFormatUrlOmitUsernamePassword
, UnescapeRule::NORMAL
, omit_auth_cases_1
,
2930 arraysize(omit_auth_cases_1
), omit_auth_offsets_1
);
2932 const AdjustOffsetCase omit_auth_cases_2
[] = {
2933 {9, base::string16::npos
},
2936 const size_t omit_auth_offsets_2
[] = {0, 1, 2, 3, 4, 5, 6, kNpos
, kNpos
,
2937 kNpos
, kNpos
, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
2938 CheckAdjustedOffsets("http://foo@www.google.com/", "en",
2939 kFormatUrlOmitUsernamePassword
, UnescapeRule::NORMAL
, omit_auth_cases_2
,
2940 arraysize(omit_auth_cases_2
), omit_auth_offsets_2
);
2942 // "http://foo\x30B0:\x30B0bar@www.google.com"
2943 const AdjustOffsetCase dont_omit_auth_cases
[] = {
2945 /*{3, base::string16::npos},
2948 {12, base::string16::npos},
2952 const size_t dont_omit_auth_offsets
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2953 kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 11, 12, kNpos
,
2954 kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 13, 14, 15, 16, 17, 18,
2955 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
2956 CheckAdjustedOffsets("http://foo%E3%82%B0:%E3%82%B0bar@www.google.com/", "en",
2957 kFormatUrlOmitNothing
, UnescapeRule::NORMAL
, dont_omit_auth_cases
,
2958 arraysize(dont_omit_auth_cases
), dont_omit_auth_offsets
);
2960 const AdjustOffsetCase view_source_cases
[] = {
2967 {19, base::string16::npos
},
2968 {20, base::string16::npos
},
2971 {base::string16::npos
, base::string16::npos
},
2973 const size_t view_source_offsets
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
2974 12, 13, 14, 15, 16, 17, 18, kNpos
, kNpos
, kNpos
, kNpos
, 19, 20, 21, 22,
2975 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33};
2976 CheckAdjustedOffsets("view-source:http://foo@www.google.com/", "en",
2977 kFormatUrlOmitUsernamePassword
, UnescapeRule::NORMAL
, view_source_cases
,
2978 arraysize(view_source_cases
), view_source_offsets
);
2980 // "http://\x671d\x65e5\x3042\x3055\x3072.jp/foo/"
2981 const AdjustOffsetCase idn_hostname_cases_1
[] = {
2982 {8, base::string16::npos
},
2983 {16, base::string16::npos
},
2984 {24, base::string16::npos
},
2988 const size_t idn_hostname_offsets_1
[] = {0, 1, 2, 3, 4, 5, 6, 7, kNpos
, kNpos
,
2989 kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
,
2990 kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 12, 13, 14, 15, 16, 17, 18, 19};
2991 CheckAdjustedOffsets("http://xn--l8jvb1ey91xtjb.jp/foo/", "ja",
2992 kFormatUrlOmitNothing
, UnescapeRule::NORMAL
, idn_hostname_cases_1
,
2993 arraysize(idn_hostname_cases_1
), idn_hostname_offsets_1
);
2995 // "http://test.\x89c6\x9891.\x5317\x4eac\x5927\x5b78.test/"
2996 const AdjustOffsetCase idn_hostname_cases_2
[] = {
3001 {13, base::string16::npos
},
3002 {23, base::string16::npos
},
3005 {26, base::string16::npos
},
3006 {32, base::string16::npos
},
3011 {47, base::string16::npos
},
3012 {base::string16::npos
, base::string16::npos
},
3014 const size_t idn_hostname_offsets_2
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
3015 12, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
,
3016 kNpos
, 14, 15, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
,
3017 kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 19, 20, 21, 22, 23, 24};
3018 CheckAdjustedOffsets("http://test.xn--cy2a840a.xn--1lq90ic7f1rc.test/",
3019 "zh-CN", kFormatUrlOmitNothing
, UnescapeRule::NORMAL
,
3020 idn_hostname_cases_2
, arraysize(idn_hostname_cases_2
),
3021 idn_hostname_offsets_2
);
3023 // "http://www.google.com/foo bar/\x30B0\x30FC\x30B0\x30EB"
3024 const AdjustOffsetCase unescape_cases
[] = {
3026 {26, base::string16::npos
},
3027 {27, base::string16::npos
},
3029 {35, base::string16::npos
},
3032 {60, base::string16::npos
},
3033 {67, base::string16::npos
},
3034 {68, base::string16::npos
},
3036 const size_t unescape_offsets
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
3037 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, kNpos
, kNpos
, 26, 27,
3038 28, 29, 30, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 31,
3039 kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 32, kNpos
, kNpos
,
3040 kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 33, kNpos
, kNpos
, kNpos
, kNpos
,
3041 kNpos
, kNpos
, kNpos
, kNpos
};
3042 CheckAdjustedOffsets(
3043 "http://www.google.com/foo%20bar/%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB",
3044 "en", kFormatUrlOmitNothing
, UnescapeRule::SPACES
, unescape_cases
,
3045 arraysize(unescape_cases
), unescape_offsets
);
3047 // "http://www.google.com/foo.html#\x30B0\x30B0z"
3048 const AdjustOffsetCase ref_cases
[] = {
3051 {32, base::string16::npos
},
3053 {35, base::string16::npos
},
3055 {38, base::string16::npos
},
3057 const size_t ref_offsets
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
3058 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
3059 kNpos
, kNpos
, 32, kNpos
, kNpos
, 33};
3060 CheckAdjustedOffsets(
3061 "http://www.google.com/foo.html#\xE3\x82\xB0\xE3\x82\xB0z", "en",
3062 kFormatUrlOmitNothing
, UnescapeRule::NORMAL
, ref_cases
,
3063 arraysize(ref_cases
), ref_offsets
);
3065 const AdjustOffsetCase omit_http_cases
[] = {
3066 {0, base::string16::npos
},
3067 {3, base::string16::npos
},
3071 const size_t omit_http_offsets
[] = {kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
,
3072 kNpos
, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
3073 CheckAdjustedOffsets("http://www.google.com/", "en",
3074 kFormatUrlOmitHTTP
, UnescapeRule::NORMAL
, omit_http_cases
,
3075 arraysize(omit_http_cases
), omit_http_offsets
);
3077 const AdjustOffsetCase omit_http_start_with_ftp_cases
[] = {
3082 const size_t omit_http_start_with_ftp_offsets
[] = {0, 1, 2, 3, 4, 5, 6, 7, 8,
3083 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21};
3084 CheckAdjustedOffsets("http://ftp.google.com/", "en", kFormatUrlOmitHTTP
,
3085 UnescapeRule::NORMAL
, omit_http_start_with_ftp_cases
,
3086 arraysize(omit_http_start_with_ftp_cases
),
3087 omit_http_start_with_ftp_offsets
);
3089 const AdjustOffsetCase omit_all_cases
[] = {
3092 {0, base::string16::npos
},
3093 {3, base::string16::npos
},
3095 const size_t omit_all_offsets
[] = {kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
,
3096 kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, kNpos
, 0, 1, 2, 3, 4, 5, 6, kNpos
};
3097 CheckAdjustedOffsets("http://user@foo.com/", "en", kFormatUrlOmitAll
,
3098 UnescapeRule::NORMAL
, omit_all_cases
,
3099 arraysize(omit_all_cases
), omit_all_offsets
);
3102 TEST(NetUtilTest
, SimplifyUrlForRequest
) {
3104 const char* input_url
;
3105 const char* expected_simplified_url
;
3108 // Reference section should be stripped.
3109 "http://www.google.com:78/foobar?query=1#hash",
3110 "http://www.google.com:78/foobar?query=1",
3113 // Reference section can itself contain #.
3114 "http://192.168.0.1?query=1#hash#10#11#13#14",
3115 "http://192.168.0.1?query=1",
3117 { // Strip username/password.
3118 "http://user:pass@google.com",
3119 "http://google.com/",
3121 { // Strip both the reference and the username/password.
3122 "http://user:pass@google.com:80/sup?yo#X#X",
3123 "http://google.com/sup?yo",
3125 { // Try an HTTPS URL -- strip both the reference and the username/password.
3126 "https://user:pass@google.com:80/sup?yo#X#X",
3127 "https://google.com:80/sup?yo",
3129 { // Try an FTP URL -- strip both the reference and the username/password.
3130 "ftp://user:pass@google.com:80/sup?yo#X#X",
3131 "ftp://google.com:80/sup?yo",
3133 { // Try an nonstandard URL
3134 "foobar://user:pass@google.com:80/sup?yo#X#X",
3135 "foobar://user:pass@google.com:80/sup?yo#X#X",
3138 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
3139 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS
"]: %s", i
,
3140 tests
[i
].input_url
));
3141 GURL
input_url(GURL(tests
[i
].input_url
));
3142 GURL
expected_url(GURL(tests
[i
].expected_simplified_url
));
3143 EXPECT_EQ(expected_url
, SimplifyUrlForRequest(input_url
));
3147 TEST(NetUtilTest
, SetExplicitlyAllowedPortsTest
) {
3148 std::string invalid
[] = { "1,2,a", "'1','2'", "1, 2, 3", "1 0,11,12" };
3149 std::string valid
[] = { "", "1", "1,2", "1,2,3", "10,11,12,13" };
3151 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(invalid
); ++i
) {
3152 SetExplicitlyAllowedPorts(invalid
[i
]);
3153 EXPECT_EQ(0, static_cast<int>(GetCountOfExplicitlyAllowedPorts()));
3156 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(valid
); ++i
) {
3157 SetExplicitlyAllowedPorts(valid
[i
]);
3158 EXPECT_EQ(i
, GetCountOfExplicitlyAllowedPorts());
3162 TEST(NetUtilTest
, GetHostOrSpecFromURL
) {
3163 EXPECT_EQ("example.com",
3164 GetHostOrSpecFromURL(GURL("http://example.com/test")));
3165 EXPECT_EQ("example.com",
3166 GetHostOrSpecFromURL(GURL("http://example.com./test")));
3167 EXPECT_EQ("file:///tmp/test.html",
3168 GetHostOrSpecFromURL(GURL("file:///tmp/test.html")));
3171 TEST(NetUtilTest
, GetAddressFamily
) {
3172 IPAddressNumber number
;
3173 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &number
));
3174 EXPECT_EQ(ADDRESS_FAMILY_IPV4
, GetAddressFamily(number
));
3175 EXPECT_TRUE(ParseIPLiteralToNumber("1:abcd::3:4:ff", &number
));
3176 EXPECT_EQ(ADDRESS_FAMILY_IPV6
, GetAddressFamily(number
));
3179 // Test that invalid IP literals fail to parse.
3180 TEST(NetUtilTest
, ParseIPLiteralToNumber_FailParse
) {
3181 IPAddressNumber number
;
3183 EXPECT_FALSE(ParseIPLiteralToNumber("bad value", &number
));
3184 EXPECT_FALSE(ParseIPLiteralToNumber("bad:value", &number
));
3185 EXPECT_FALSE(ParseIPLiteralToNumber(std::string(), &number
));
3186 EXPECT_FALSE(ParseIPLiteralToNumber("192.168.0.1:30", &number
));
3187 EXPECT_FALSE(ParseIPLiteralToNumber(" 192.168.0.1 ", &number
));
3188 EXPECT_FALSE(ParseIPLiteralToNumber("[::1]", &number
));
3191 // Test parsing an IPv4 literal.
3192 TEST(NetUtilTest
, ParseIPLiteralToNumber_IPv4
) {
3193 IPAddressNumber number
;
3194 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &number
));
3195 EXPECT_EQ("192,168,0,1", DumpIPNumber(number
));
3196 EXPECT_EQ("192.168.0.1", IPAddressToString(number
));
3199 // Test parsing an IPv6 literal.
3200 TEST(NetUtilTest
, ParseIPLiteralToNumber_IPv6
) {
3201 IPAddressNumber number
;
3202 EXPECT_TRUE(ParseIPLiteralToNumber("1:abcd::3:4:ff", &number
));
3203 EXPECT_EQ("0,1,171,205,0,0,0,0,0,0,0,3,0,4,0,255", DumpIPNumber(number
));
3204 EXPECT_EQ("1:abcd::3:4:ff", IPAddressToString(number
));
3207 // Test mapping an IPv4 address to an IPv6 address.
3208 TEST(NetUtilTest
, ConvertIPv4NumberToIPv6Number
) {
3209 IPAddressNumber ipv4_number
;
3210 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &ipv4_number
));
3212 IPAddressNumber ipv6_number
=
3213 ConvertIPv4NumberToIPv6Number(ipv4_number
);
3215 // ::ffff:192.168.0.1
3216 EXPECT_EQ("0,0,0,0,0,0,0,0,0,0,255,255,192,168,0,1",
3217 DumpIPNumber(ipv6_number
));
3218 EXPECT_EQ("::ffff:c0a8:1", IPAddressToString(ipv6_number
));
3221 TEST(NetUtilTest
, IsIPv4Mapped
) {
3222 IPAddressNumber ipv4_number
;
3223 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &ipv4_number
));
3224 EXPECT_FALSE(IsIPv4Mapped(ipv4_number
));
3226 IPAddressNumber ipv6_number
;
3227 EXPECT_TRUE(ParseIPLiteralToNumber("::1", &ipv4_number
));
3228 EXPECT_FALSE(IsIPv4Mapped(ipv6_number
));
3230 IPAddressNumber ipv4mapped_number
;
3231 EXPECT_TRUE(ParseIPLiteralToNumber("::ffff:0101:1", &ipv4mapped_number
));
3232 EXPECT_TRUE(IsIPv4Mapped(ipv4mapped_number
));
3235 TEST(NetUtilTest
, ConvertIPv4MappedToIPv4
) {
3236 IPAddressNumber ipv4mapped_number
;
3237 EXPECT_TRUE(ParseIPLiteralToNumber("::ffff:0101:1", &ipv4mapped_number
));
3238 IPAddressNumber expected
;
3239 EXPECT_TRUE(ParseIPLiteralToNumber("1.1.0.1", &expected
));
3240 IPAddressNumber result
= ConvertIPv4MappedToIPv4(ipv4mapped_number
);
3241 EXPECT_EQ(expected
, result
);
3244 // Test parsing invalid CIDR notation literals.
3245 TEST(NetUtilTest
, ParseCIDRBlock_Invalid
) {
3246 const char* bad_literals
[] = {
3262 for (size_t i
= 0; i
< arraysize(bad_literals
); ++i
) {
3263 IPAddressNumber ip_number
;
3264 size_t prefix_length_in_bits
;
3266 EXPECT_FALSE(ParseCIDRBlock(bad_literals
[i
],
3268 &prefix_length_in_bits
));
3272 // Test parsing a valid CIDR notation literal.
3273 TEST(NetUtilTest
, ParseCIDRBlock_Valid
) {
3274 IPAddressNumber ip_number
;
3275 size_t prefix_length_in_bits
;
3277 EXPECT_TRUE(ParseCIDRBlock("192.168.0.1/11",
3279 &prefix_length_in_bits
));
3281 EXPECT_EQ("192,168,0,1", DumpIPNumber(ip_number
));
3282 EXPECT_EQ(11u, prefix_length_in_bits
);
3285 TEST(NetUtilTest
, IPNumberMatchesPrefix
) {
3287 const char* cidr_literal
;
3288 const char* ip_literal
;
3289 bool expected_to_match
;
3291 // IPv4 prefix with IPv4 inputs.
3308 // IPv6 prefix with IPv6 inputs.
3320 // IPv6 prefix with IPv4 inputs.
3327 "::ffff:192.168.0.1/112",
3332 // IPv4 prefix with IPv6 inputs.
3340 "::ffff:10.12.33.44",
3344 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
3345 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS
"]: %s, %s", i
,
3346 tests
[i
].cidr_literal
,
3347 tests
[i
].ip_literal
));
3349 IPAddressNumber ip_number
;
3350 EXPECT_TRUE(ParseIPLiteralToNumber(tests
[i
].ip_literal
, &ip_number
));
3352 IPAddressNumber ip_prefix
;
3353 size_t prefix_length_in_bits
;
3355 EXPECT_TRUE(ParseCIDRBlock(tests
[i
].cidr_literal
,
3357 &prefix_length_in_bits
));
3359 EXPECT_EQ(tests
[i
].expected_to_match
,
3360 IPNumberMatchesPrefix(ip_number
,
3362 prefix_length_in_bits
));
3366 TEST(NetUtilTest
, IsLocalhost
) {
3367 EXPECT_TRUE(net::IsLocalhost("localhost"));
3368 EXPECT_TRUE(net::IsLocalhost("localhost.localdomain"));
3369 EXPECT_TRUE(net::IsLocalhost("localhost6"));
3370 EXPECT_TRUE(net::IsLocalhost("localhost6.localdomain6"));
3371 EXPECT_TRUE(net::IsLocalhost("127.0.0.1"));
3372 EXPECT_TRUE(net::IsLocalhost("127.0.1.0"));
3373 EXPECT_TRUE(net::IsLocalhost("127.1.0.0"));
3374 EXPECT_TRUE(net::IsLocalhost("127.0.0.255"));
3375 EXPECT_TRUE(net::IsLocalhost("127.0.255.0"));
3376 EXPECT_TRUE(net::IsLocalhost("127.255.0.0"));
3377 EXPECT_TRUE(net::IsLocalhost("::1"));
3378 EXPECT_TRUE(net::IsLocalhost("0:0:0:0:0:0:0:1"));
3380 EXPECT_FALSE(net::IsLocalhost("localhostx"));
3381 EXPECT_FALSE(net::IsLocalhost("foo.localdomain"));
3382 EXPECT_FALSE(net::IsLocalhost("localhost6x"));
3383 EXPECT_FALSE(net::IsLocalhost("localhost.localdomain6"));
3384 EXPECT_FALSE(net::IsLocalhost("localhost6.localdomain"));
3385 EXPECT_FALSE(net::IsLocalhost("127.0.0.1.1"));
3386 EXPECT_FALSE(net::IsLocalhost(".127.0.0.255"));
3387 EXPECT_FALSE(net::IsLocalhost("::2"));
3388 EXPECT_FALSE(net::IsLocalhost("::1:1"));
3389 EXPECT_FALSE(net::IsLocalhost("0:0:0:0:1:0:0:1"));
3390 EXPECT_FALSE(net::IsLocalhost("::1:1"));
3391 EXPECT_FALSE(net::IsLocalhost("0:0:0:0:0:0:0:0:1"));
3394 // Verify GetNetworkList().
3395 TEST(NetUtilTest
, GetNetworkList
) {
3396 NetworkInterfaceList list
;
3397 ASSERT_TRUE(GetNetworkList(&list
));
3399 for (NetworkInterfaceList::iterator it
= list
.begin();
3400 it
!= list
.end(); ++it
) {
3401 // Verify that the name is not empty.
3402 EXPECT_FALSE(it
->name
.empty());
3404 // Verify that the address is correct.
3405 EXPECT_TRUE(it
->address
.size() == kIPv4AddressSize
||
3406 it
->address
.size() == kIPv6AddressSize
)
3407 << "Invalid address of size " << it
->address
.size();
3408 bool all_zeroes
= true;
3409 for (size_t i
= 0; i
< it
->address
.size(); ++i
) {
3410 if (it
->address
[i
] != 0) {
3415 EXPECT_FALSE(all_zeroes
);
3419 static const base::FilePath::CharType
* kSafePortableBasenames
[] = {
3420 FILE_PATH_LITERAL("a"),
3421 FILE_PATH_LITERAL("a.txt"),
3422 FILE_PATH_LITERAL("a b.txt"),
3423 FILE_PATH_LITERAL("a-b.txt"),
3424 FILE_PATH_LITERAL("My Computer"),
3425 FILE_PATH_LITERAL(" Computer"),
3428 static const base::FilePath::CharType
* kUnsafePortableBasenames
[] = {
3429 FILE_PATH_LITERAL(""),
3430 FILE_PATH_LITERAL("."),
3431 FILE_PATH_LITERAL(".."),
3432 FILE_PATH_LITERAL("..."),
3433 FILE_PATH_LITERAL("con"),
3434 FILE_PATH_LITERAL("con.zip"),
3435 FILE_PATH_LITERAL("NUL"),
3436 FILE_PATH_LITERAL("NUL.zip"),
3437 FILE_PATH_LITERAL(".a"),
3438 FILE_PATH_LITERAL("a."),
3439 FILE_PATH_LITERAL("a\"a"),
3440 FILE_PATH_LITERAL("a<a"),
3441 FILE_PATH_LITERAL("a>a"),
3442 FILE_PATH_LITERAL("a?a"),
3443 FILE_PATH_LITERAL("a/"),
3444 FILE_PATH_LITERAL("a\\"),
3445 FILE_PATH_LITERAL("a "),
3446 FILE_PATH_LITERAL("a . ."),
3447 FILE_PATH_LITERAL("My Computer.{a}"),
3448 FILE_PATH_LITERAL("My Computer.{20D04FE0-3AEA-1069-A2D8-08002B30309D}"),
3449 #if !defined(OS_WIN)
3450 FILE_PATH_LITERAL("a\\a"),
3454 static const base::FilePath::CharType
* kSafePortableRelativePaths
[] = {
3455 FILE_PATH_LITERAL("a/a"),
3457 FILE_PATH_LITERAL("a\\a"),
3461 TEST(NetUtilTest
, IsSafePortableBasename
) {
3462 for (size_t i
= 0 ; i
< arraysize(kSafePortableBasenames
); ++i
) {
3463 EXPECT_TRUE(IsSafePortableBasename(base::FilePath(
3464 kSafePortableBasenames
[i
]))) << kSafePortableBasenames
[i
];
3466 for (size_t i
= 0 ; i
< arraysize(kUnsafePortableBasenames
); ++i
) {
3467 EXPECT_FALSE(IsSafePortableBasename(base::FilePath(
3468 kUnsafePortableBasenames
[i
]))) << kUnsafePortableBasenames
[i
];
3470 for (size_t i
= 0 ; i
< arraysize(kSafePortableRelativePaths
); ++i
) {
3471 EXPECT_FALSE(IsSafePortableBasename(base::FilePath(
3472 kSafePortableRelativePaths
[i
]))) << kSafePortableRelativePaths
[i
];
3476 TEST(NetUtilTest
, IsSafePortableRelativePath
) {
3477 base::FilePath
safe_dirname(FILE_PATH_LITERAL("a"));
3478 for (size_t i
= 0 ; i
< arraysize(kSafePortableBasenames
); ++i
) {
3479 EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath(
3480 kSafePortableBasenames
[i
]))) << kSafePortableBasenames
[i
];
3481 EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname
.Append(base::FilePath(
3482 kSafePortableBasenames
[i
])))) << kSafePortableBasenames
[i
];
3484 for (size_t i
= 0 ; i
< arraysize(kSafePortableRelativePaths
); ++i
) {
3485 EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath(
3486 kSafePortableRelativePaths
[i
]))) << kSafePortableRelativePaths
[i
];
3487 EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname
.Append(base::FilePath(
3488 kSafePortableRelativePaths
[i
])))) << kSafePortableRelativePaths
[i
];
3490 for (size_t i
= 0 ; i
< arraysize(kUnsafePortableBasenames
); ++i
) {
3491 EXPECT_FALSE(IsSafePortableRelativePath(base::FilePath(
3492 kUnsafePortableBasenames
[i
]))) << kUnsafePortableBasenames
[i
];
3493 if (!base::FilePath::StringType(kUnsafePortableBasenames
[i
]).empty()) {
3494 EXPECT_FALSE(IsSafePortableRelativePath(safe_dirname
.Append(
3495 base::FilePath(kUnsafePortableBasenames
[i
]))))
3496 << kUnsafePortableBasenames
[i
];
3501 struct NonUniqueNameTestData
{
3503 const char* hostname
;
3506 // Google Test pretty-printer.
3507 void PrintTo(const NonUniqueNameTestData
& data
, std::ostream
* os
) {
3508 ASSERT_TRUE(data
.hostname
);
3509 *os
<< " hostname: " << testing::PrintToString(data
.hostname
)
3510 << "; is_unique: " << testing::PrintToString(data
.is_unique
);
3513 const NonUniqueNameTestData kNonUniqueNameTestData
[] = {
3514 // Domains under ICANN-assigned domains.
3515 { true, "google.com" },
3516 { true, "google.co.uk" },
3517 // Domains under private registries.
3518 { true, "appspot.com" },
3519 { true, "test.appspot.com" },
3520 // Unreserved IPv4 addresses (in various forms).
3521 { true, "8.8.8.8" },
3522 { true, "99.64.0.0" },
3523 { true, "212.15.0.0" },
3525 { true, "212.15.0" },
3526 { true, "3557752832" },
3527 // Reserved IPv4 addresses (in various forms).
3528 { false, "192.168.0.0" },
3529 { false, "192.168.0.6" },
3530 { false, "10.0.0.5" },
3532 { false, "10.0.0" },
3533 { false, "3232235526" },
3534 // Unreserved IPv6 addresses.
3535 { true, "FFC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
3536 { true, "2000:ba98:7654:2301:EFCD:BA98:7654:3210" },
3537 // Reserved IPv6 addresses.
3538 { false, "::192.9.5.5" },
3539 { false, "FEED::BEEF" },
3540 { false, "FEC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
3541 // 'internal'/non-IANA assigned domains.
3542 { false, "intranet" },
3543 { false, "intranet." },
3544 { false, "intranet.example" },
3545 { false, "host.intranet.example" },
3546 // gTLDs under discussion, but not yet assigned.
3547 { false, "intranet.corp" },
3548 { false, "example.tech" },
3549 { false, "intranet.internal" },
3550 // Invalid host names are treated as unique - but expected to be
3551 // filtered out before then.
3552 { true, "junk)(£)$*!@~#" },
3553 { true, "w$w.example.com" },
3554 { true, "nocolonsallowed:example" },
3555 { true, "[::4.5.6.9]" },
3558 class NetUtilNonUniqueNameTest
3559 : public testing::TestWithParam
<NonUniqueNameTestData
> {
3561 virtual ~NetUtilNonUniqueNameTest() {}
3564 bool IsUnique(const std::string
& hostname
) {
3565 return !IsHostnameNonUnique(hostname
);
3569 // Test that internal/non-unique names are properly identified as such, but
3570 // that IP addresses and hosts beneath registry-controlled domains are flagged
3572 TEST_P(NetUtilNonUniqueNameTest
, IsHostnameNonUnique
) {
3573 const NonUniqueNameTestData
& test_data
= GetParam();
3575 EXPECT_EQ(test_data
.is_unique
, IsUnique(test_data
.hostname
));
3578 INSTANTIATE_TEST_CASE_P(, NetUtilNonUniqueNameTest
,
3579 testing::ValuesIn(kNonUniqueNameTestData
));