Remove PlatformFile from profile_browsertest
[chromium-blink-merge.git] / net / base / net_util_unittest.cc
blobe62a64477bc0dbf617a9a8b0ef0c67e4e9bd72de
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"
7 #include <string.h>
9 #include <algorithm>
11 #include "base/files/file_path.h"
12 #include "base/format_macros.h"
13 #include "base/scoped_native_library.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/strings/sys_string_conversions.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/sys_byteorder.h"
20 #include "base/test/test_file_util.h"
21 #include "base/time/time.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "url/gurl.h"
25 #if defined(OS_WIN)
26 #include <iphlpapi.h>
27 #include <objbase.h>
28 #include "base/win/windows_version.h"
29 #elif !defined(OS_ANDROID)
30 #include <net/if.h>
31 #endif // OS_WIN
33 using base::ASCIIToUTF16;
34 using base::WideToUTF16;
36 namespace net {
38 namespace {
40 static const size_t kNpos = base::string16::npos;
42 struct FileCase {
43 const wchar_t* file;
44 const char* url;
47 struct HeaderCase {
48 const char* header_name;
49 const char* expected;
52 struct HeaderParamCase {
53 const char* header_name;
54 const char* param_name;
55 const char* expected;
58 struct FileNameCDCase {
59 const char* header_field;
60 const char* referrer_charset;
61 const wchar_t* expected;
64 const char* kLanguages[] = {
65 "", "en", "zh-CN", "ja", "ko",
66 "he", "ar", "ru", "el", "fr",
67 "de", "pt", "sv", "th", "hi",
68 "de,en", "el,en", "zh-TW,en", "ko,ja", "he,ru,en",
69 "zh,ru,en"
72 struct IDNTestCase {
73 const char* input;
74 const wchar_t* unicode_output;
75 const bool unicode_allowed[arraysize(kLanguages)];
78 // TODO(jungshik) This is just a random sample of languages and is far
79 // from exhaustive. We may have to generate all the combinations
80 // of languages (powerset of a set of all the languages).
81 const IDNTestCase idn_cases[] = {
82 // No IDN
83 {"www.google.com", L"www.google.com",
84 {true, true, true, true, true,
85 true, true, true, true, true,
86 true, true, true, true, true,
87 true, true, true, true, true,
88 true}},
89 {"www.google.com.", L"www.google.com.",
90 {true, true, true, true, true,
91 true, true, true, true, true,
92 true, true, true, true, true,
93 true, true, true, true, true,
94 true}},
95 {".", L".",
96 {true, true, true, true, true,
97 true, true, true, true, true,
98 true, true, true, true, true,
99 true, true, true, true, true,
100 true}},
101 {"", L"",
102 {true, true, true, true, true,
103 true, true, true, true, true,
104 true, true, true, true, true,
105 true, true, true, true, true,
106 true}},
107 // IDN
108 // Hanzi (Traditional Chinese)
109 {"xn--1lq90ic7f1rc.cn", L"\x5317\x4eac\x5927\x5b78.cn",
110 {true, false, true, true, false,
111 false, false, false, false, false,
112 false, false, false, false, false,
113 false, false, true, true, false,
114 true}},
115 // Hanzi ('video' in Simplified Chinese : will pass only in zh-CN,zh)
116 {"xn--cy2a840a.com", L"\x89c6\x9891.com",
117 {true, false, true, false, false,
118 false, false, false, false, false,
119 false, false, false, false, false,
120 false, false, false, false, false,
121 true}},
122 // Hanzi + '123'
123 {"www.xn--123-p18d.com", L"www.\x4e00" L"123.com",
124 {true, false, true, true, false,
125 false, false, false, false, false,
126 false, false, false, false, false,
127 false, false, true, true, false,
128 true}},
129 // Hanzi + Latin : U+56FD is simplified and is regarded
130 // as not supported in zh-TW.
131 {"www.xn--hello-9n1hm04c.com", L"www.hello\x4e2d\x56fd.com",
132 {false, false, true, true, false,
133 false, false, false, false, false,
134 false, false, false, false, false,
135 false, false, false, true, false,
136 true}},
137 // Kanji + Kana (Japanese)
138 {"xn--l8jvb1ey91xtjb.jp", L"\x671d\x65e5\x3042\x3055\x3072.jp",
139 {true, false, false, true, false,
140 false, false, false, false, false,
141 false, false, false, false, false,
142 false, false, false, true, false,
143 false}},
144 // Katakana including U+30FC
145 {"xn--tckm4i2e.jp", L"\x30b3\x30de\x30fc\x30b9.jp",
146 {true, false, false, true, false,
147 false, false, false, false, false,
148 false, false, false, false, false,
149 false, false, false, true, false,
151 {"xn--3ck7a7g.jp", L"\u30ce\u30f3\u30bd.jp",
152 {true, false, false, true, false,
153 false, false, false, false, false,
154 false, false, false, false, false,
155 false, false, false, true, false,
157 // Katakana + Latin (Japanese)
158 // TODO(jungshik): Change 'false' in the first element to 'true'
159 // after upgrading to ICU 4.2.1 to use new uspoof_* APIs instead
160 // of our IsIDNComponentInSingleScript().
161 {"xn--e-efusa1mzf.jp", L"e\x30b3\x30de\x30fc\x30b9.jp",
162 {false, false, false, true, false,
163 false, false, false, false, false,
164 false, false, false, false, false,
165 false, false, false, true, false,
167 {"xn--3bkxe.jp", L"\x30c8\x309a.jp",
168 {false, false, false, true, false,
169 false, false, false, false, false,
170 false, false, false, false, false,
171 false, false, false, true, false,
173 // Hangul (Korean)
174 {"www.xn--or3b17p6jjc.kr", L"www.\xc804\xc790\xc815\xbd80.kr",
175 {true, false, false, false, true,
176 false, false, false, false, false,
177 false, false, false, false, false,
178 false, false, false, true, false,
179 false}},
180 // b<u-umlaut>cher (German)
181 {"xn--bcher-kva.de", L"b\x00fc" L"cher.de",
182 {true, false, false, false, false,
183 false, false, false, false, true,
184 true, false, false, false, false,
185 true, false, false, false, false,
186 false}},
187 // a with diaeresis
188 {"www.xn--frgbolaget-q5a.se", L"www.f\x00e4rgbolaget.se",
189 {true, false, false, false, false,
190 false, false, false, false, false,
191 true, false, true, false, false,
192 true, false, false, false, false,
193 false}},
194 // c-cedilla (French)
195 {"www.xn--alliancefranaise-npb.fr", L"www.alliancefran\x00e7" L"aise.fr",
196 {true, false, false, false, false,
197 false, false, false, false, true,
198 false, true, false, false, false,
199 false, false, false, false, false,
200 false}},
201 // caf'e with acute accent' (French)
202 {"xn--caf-dma.fr", L"caf\x00e9.fr",
203 {true, false, false, false, false,
204 false, false, false, false, true,
205 false, true, true, false, false,
206 false, false, false, false, false,
207 false}},
208 // c-cedillla and a with tilde (Portuguese)
209 {"xn--poema-9qae5a.com.br", L"p\x00e3oema\x00e7\x00e3.com.br",
210 {true, false, false, false, false,
211 false, false, false, false, false,
212 false, true, false, false, false,
213 false, false, false, false, false,
214 false}},
215 // s with caron
216 {"xn--achy-f6a.com", L"\x0161" L"achy.com",
217 {true, false, false, false, false,
218 false, false, false, false, false,
219 false, false, false, false, false,
220 false, false, false, false, false,
221 false}},
222 // TODO(jungshik) : Add examples with Cyrillic letters
223 // only used in some languages written in Cyrillic.
224 // Eutopia (Greek)
225 {"xn--kxae4bafwg.gr", L"\x03bf\x03c5\x03c4\x03bf\x03c0\x03af\x03b1.gr",
226 {true, false, false, false, false,
227 false, false, false, true, false,
228 false, false, false, false, false,
229 false, true, false, false, false,
230 false}},
231 // Eutopia + 123 (Greek)
232 {"xn---123-pldm0haj2bk.gr",
233 L"\x03bf\x03c5\x03c4\x03bf\x03c0\x03af\x03b1-123.gr",
234 {true, false, false, false, false,
235 false, false, false, true, false,
236 false, false, false, false, false,
237 false, true, false, false, false,
238 false}},
239 // Cyrillic (Russian)
240 {"xn--n1aeec9b.ru", L"\x0442\x043e\x0440\x0442\x044b.ru",
241 {true, false, false, false, false,
242 false, false, true, false, false,
243 false, false, false, false, false,
244 false, false, false, false, true,
245 true}},
246 // Cyrillic + 123 (Russian)
247 {"xn---123-45dmmc5f.ru", L"\x0442\x043e\x0440\x0442\x044b-123.ru",
248 {true, false, false, false, false,
249 false, false, true, false, false,
250 false, false, false, false, false,
251 false, false, false, false, true,
252 true}},
253 // Arabic
254 {"xn--mgba1fmg.ar", L"\x0627\x0641\x0644\x0627\x0645.ar",
255 {true, false, false, false, false,
256 false, true, false, false, false,
257 false, false, false, false, false,
258 false, false, false, false, false,
259 false}},
260 // Hebrew
261 {"xn--4dbib.he", L"\x05d5\x05d0\x05d4.he",
262 {true, false, false, false, false,
263 true, false, false, false, false,
264 false, false, false, false, false,
265 false, false, false, false, true,
266 false}},
267 // Thai
268 {"xn--12c2cc4ag3b4ccu.th",
269 L"\x0e2a\x0e32\x0e22\x0e01\x0e32\x0e23\x0e1a\x0e34\x0e19.th",
270 {true, false, false, false, false,
271 false, false, false, false, false,
272 false, false, false, true, false,
273 false, false, false, false, false,
274 false}},
275 // Devangari (Hindi)
276 {"www.xn--l1b6a9e1b7c.in", L"www.\x0905\x0915\x094b\x0932\x093e.in",
277 {true, false, false, false, false,
278 false, false, false, false, false,
279 false, false, false, false, true,
280 false, false, false, false, false,
281 false}},
282 // Invalid IDN
283 {"xn--hello?world.com", NULL,
284 {false, false, false, false, false,
285 false, false, false, false, false,
286 false, false, false, false, false,
287 false, false, false, false, false,
288 false}},
289 // Unsafe IDNs
290 // "payp<alpha>l.com"
291 {"www.xn--paypl-g9d.com", L"payp\x03b1l.com",
292 {false, false, false, false, false,
293 false, false, false, false, false,
294 false, false, false, false, false,
295 false, false, false, false, false,
296 false}},
297 // google.gr with Greek omicron and epsilon
298 {"xn--ggl-6xc1ca.gr", L"g\x03bf\x03bfgl\x03b5.gr",
299 {false, false, false, false, false,
300 false, false, false, false, false,
301 false, false, false, false, false,
302 false, false, false, false, false,
303 false}},
304 // google.ru with Cyrillic o
305 {"xn--ggl-tdd6ba.ru", L"g\x043e\x043egl\x0435.ru",
306 {false, false, false, false, false,
307 false, false, false, false, false,
308 false, false, false, false, false,
309 false, false, false, false, false,
310 false}},
311 // h<e with acute>llo<China in Han>.cn
312 {"xn--hllo-bpa7979ih5m.cn", L"h\x00e9llo\x4e2d\x56fd.cn",
313 {false, false, false, false, false,
314 false, false, false, false, false,
315 false, false, false, false, false,
316 false, false, false, false, false,
317 false}},
318 // <Greek rho><Cyrillic a><Cyrillic u>.ru
319 {"xn--2xa6t2b.ru", L"\x03c1\x0430\x0443.ru",
320 {false, false, false, false, false,
321 false, false, false, false, false,
322 false, false, false, false, false,
323 false, false, false, false, false,
324 false}},
325 // One that's really long that will force a buffer realloc
326 {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
327 "aaaaaaa",
328 L"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
329 L"aaaaaaaa",
330 {true, true, true, true, true,
331 true, true, true, true, true,
332 true, true, true, true, true,
333 true, true, true, true, true,
334 true}},
335 // Test cases for characters we blacklisted although allowed in IDN.
336 // Embedded spaces will be turned to %20 in the display.
337 // TODO(jungshik): We need to have more cases. This is a typical
338 // data-driven trap. The following test cases need to be separated
339 // and tested only for a couple of languages.
340 {"xn--osd3820f24c.kr", L"\xac00\xb098\x115f.kr",
341 {false, false, false, false, false,
342 false, false, false, false, false,
343 false, false, false, false, false,
344 false, false, false, false, false,
345 false}},
346 {"www.xn--google-ho0coa.com", L"www.\x2039google\x203a.com",
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--comabc-k8d", L"google.com\x0338" L"abc",
353 {false, false, false, false, false,
354 false, false, false, false, false,
355 false, false, false, false, false,
356 false, false, false, false, false,
358 {"google.xn--com-oh4ba.evil.jp", L"google.com\x309a\x309a.evil.jp",
359 {false, false, false, false, false,
360 false, false, false, false, false,
361 false, false, false, false, false,
362 false, false, false, false, false,
364 {"google.xn--comevil-v04f.jp", L"google.com\x30ce" L"evil.jp",
365 {false, false, false, false, false,
366 false, false, false, false, false,
367 false, false, false, false, false,
368 false, false, false, false, false,
370 #if 0
371 // These two cases are special. We need a separate test.
372 // U+3000 and U+3002 are normalized to ASCII space and dot.
373 {"xn-- -kq6ay5z.cn", L"\x4e2d\x56fd\x3000.cn",
374 {false, false, true, false, false,
375 false, false, false, false, false,
376 false, false, false, false, false,
377 false, false, true, false, false,
378 true}},
379 {"xn--fiqs8s.cn", L"\x4e2d\x56fd\x3002" L"cn",
380 {false, false, true, false, false,
381 false, false, false, false, false,
382 false, false, false, false, false,
383 false, false, true, false, false,
384 true}},
385 #endif
388 struct AdjustOffsetCase {
389 size_t input_offset;
390 size_t output_offset;
393 struct CompliantHostCase {
394 const char* host;
395 const char* desired_tld;
396 bool expected_output;
399 struct GenerateFilenameCase {
400 int lineno;
401 const char* url;
402 const char* content_disp_header;
403 const char* referrer_charset;
404 const char* suggested_filename;
405 const char* mime_type;
406 const wchar_t* default_filename;
407 const wchar_t* expected_filename;
410 struct UrlTestData {
411 const char* description;
412 const char* input;
413 const char* languages;
414 FormatUrlTypes format_types;
415 UnescapeRule::Type escape_rules;
416 const wchar_t* output; // Use |wchar_t| to handle Unicode constants easily.
417 size_t prefix_len;
420 // Fills in sockaddr for the given 32-bit address (IPv4.)
421 // |bytes| should be an array of length 4.
422 void MakeIPv4Address(const uint8* bytes, int port, SockaddrStorage* storage) {
423 memset(&storage->addr_storage, 0, sizeof(storage->addr_storage));
424 storage->addr_len = sizeof(struct sockaddr_in);
425 struct sockaddr_in* addr4 = reinterpret_cast<sockaddr_in*>(storage->addr);
426 addr4->sin_port = base::HostToNet16(port);
427 addr4->sin_family = AF_INET;
428 memcpy(&addr4->sin_addr, bytes, 4);
431 // Fills in sockaddr for the given 128-bit address (IPv6.)
432 // |bytes| should be an array of length 16.
433 void MakeIPv6Address(const uint8* bytes, int port, SockaddrStorage* storage) {
434 memset(&storage->addr_storage, 0, sizeof(storage->addr_storage));
435 storage->addr_len = sizeof(struct sockaddr_in6);
436 struct sockaddr_in6* addr6 = reinterpret_cast<sockaddr_in6*>(storage->addr);
437 addr6->sin6_port = base::HostToNet16(port);
438 addr6->sin6_family = AF_INET6;
439 memcpy(&addr6->sin6_addr, bytes, 16);
442 // A helper for IDN*{Fast,Slow}.
443 // Append "::<language list>" to |expected| and |actual| to make it
444 // easy to tell which sub-case fails without debugging.
445 void AppendLanguagesToOutputs(const char* languages,
446 base::string16* expected,
447 base::string16* actual) {
448 base::string16 to_append = ASCIIToUTF16("::") + ASCIIToUTF16(languages);
449 expected->append(to_append);
450 actual->append(to_append);
453 // A pair of helpers for the FormatUrlWithOffsets() test.
454 void VerboseExpect(size_t expected,
455 size_t actual,
456 const std::string& original_url,
457 size_t position,
458 const base::string16& formatted_url) {
459 EXPECT_EQ(expected, actual) << "Original URL: " << original_url
460 << " (at char " << position << ")\nFormatted URL: " << formatted_url;
463 void CheckAdjustedOffsets(const std::string& url_string,
464 const std::string& languages,
465 FormatUrlTypes format_types,
466 UnescapeRule::Type unescape_rules,
467 const size_t* output_offsets) {
468 GURL url(url_string);
469 size_t url_length = url_string.length();
470 std::vector<size_t> offsets;
471 for (size_t i = 0; i <= url_length + 1; ++i)
472 offsets.push_back(i);
473 offsets.push_back(500000); // Something larger than any input length.
474 offsets.push_back(std::string::npos);
475 base::string16 formatted_url = FormatUrlWithOffsets(url, languages,
476 format_types, unescape_rules, NULL, NULL, &offsets);
477 for (size_t i = 0; i < url_length; ++i)
478 VerboseExpect(output_offsets[i], offsets[i], url_string, i, formatted_url);
479 VerboseExpect(formatted_url.length(), offsets[url_length], url_string,
480 url_length, formatted_url);
481 VerboseExpect(base::string16::npos, offsets[url_length + 1], url_string,
482 500000, formatted_url);
483 VerboseExpect(base::string16::npos, offsets[url_length + 2], url_string,
484 std::string::npos, formatted_url);
487 // Helper to strignize an IP number (used to define expectations).
488 std::string DumpIPNumber(const IPAddressNumber& v) {
489 std::string out;
490 for (size_t i = 0; i < v.size(); ++i) {
491 if (i != 0)
492 out.append(",");
493 out.append(base::IntToString(static_cast<int>(v[i])));
495 return out;
498 void RunGenerateFileNameTestCase(const GenerateFilenameCase* test_case) {
499 std::string default_filename(base::WideToUTF8(test_case->default_filename));
500 base::FilePath file_path = GenerateFileName(
501 GURL(test_case->url), test_case->content_disp_header,
502 test_case->referrer_charset, test_case->suggested_filename,
503 test_case->mime_type, default_filename);
504 EXPECT_EQ(test_case->expected_filename,
505 file_util::FilePathAsWString(file_path))
506 << "test case at line number: " << test_case->lineno;
509 } // anonymous namespace
511 TEST(NetUtilTest, FileURLConversion) {
512 // a list of test file names and the corresponding URLs
513 const FileCase round_trip_cases[] = {
514 #if defined(OS_WIN)
515 {L"C:\\foo\\bar.txt", "file:///C:/foo/bar.txt"},
516 {L"\\\\some computer\\foo\\bar.txt",
517 "file://some%20computer/foo/bar.txt"}, // UNC
518 {L"D:\\Name;with%some symbols*#",
519 "file:///D:/Name%3Bwith%25some%20symbols*%23"},
520 // issue 14153: To be tested with the OS default codepage other than 1252.
521 {L"D:\\latin1\\caf\x00E9\x00DD.txt",
522 "file:///D:/latin1/caf%C3%A9%C3%9D.txt"},
523 {L"D:\\otherlatin\\caf\x0119.txt",
524 "file:///D:/otherlatin/caf%C4%99.txt"},
525 {L"D:\\greek\\\x03B1\x03B2\x03B3.txt",
526 "file:///D:/greek/%CE%B1%CE%B2%CE%B3.txt"},
527 {L"D:\\Chinese\\\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc",
528 "file:///D:/Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD%91"
529 "%E9%A1%B5.doc"},
530 {L"D:\\plane1\\\xD835\xDC00\xD835\xDC01.txt", // Math alphabet "AB"
531 "file:///D:/plane1/%F0%9D%90%80%F0%9D%90%81.txt"},
532 #elif defined(OS_POSIX)
533 {L"/foo/bar.txt", "file:///foo/bar.txt"},
534 {L"/foo/BAR.txt", "file:///foo/BAR.txt"},
535 {L"/C:/foo/bar.txt", "file:///C:/foo/bar.txt"},
536 {L"/foo/bar?.txt", "file:///foo/bar%3F.txt"},
537 {L"/some computer/foo/bar.txt", "file:///some%20computer/foo/bar.txt"},
538 {L"/Name;with%some symbols*#", "file:///Name%3Bwith%25some%20symbols*%23"},
539 {L"/latin1/caf\x00E9\x00DD.txt", "file:///latin1/caf%C3%A9%C3%9D.txt"},
540 {L"/otherlatin/caf\x0119.txt", "file:///otherlatin/caf%C4%99.txt"},
541 {L"/greek/\x03B1\x03B2\x03B3.txt", "file:///greek/%CE%B1%CE%B2%CE%B3.txt"},
542 {L"/Chinese/\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc",
543 "file:///Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD"
544 "%91%E9%A1%B5.doc"},
545 {L"/plane1/\x1D400\x1D401.txt", // Math alphabet "AB"
546 "file:///plane1/%F0%9D%90%80%F0%9D%90%81.txt"},
547 #endif
550 // First, we'll test that we can round-trip all of the above cases of URLs
551 base::FilePath output;
552 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(round_trip_cases); i++) {
553 // convert to the file URL
554 GURL file_url(FilePathToFileURL(
555 file_util::WStringAsFilePath(round_trip_cases[i].file)));
556 EXPECT_EQ(round_trip_cases[i].url, file_url.spec());
558 // Back to the filename.
559 EXPECT_TRUE(FileURLToFilePath(file_url, &output));
560 EXPECT_EQ(round_trip_cases[i].file, file_util::FilePathAsWString(output));
563 // Test that various file: URLs get decoded into the correct file type
564 FileCase url_cases[] = {
565 #if defined(OS_WIN)
566 {L"C:\\foo\\bar.txt", "file:c|/foo\\bar.txt"},
567 {L"C:\\foo\\bar.txt", "file:/c:/foo/bar.txt"},
568 {L"\\\\foo\\bar.txt", "file://foo\\bar.txt"},
569 {L"C:\\foo\\bar.txt", "file:///c:/foo/bar.txt"},
570 {L"\\\\foo\\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"C:\\foo\\bar.txt", "file:\\\\\\c:/foo/bar.txt"},
574 #elif defined(OS_POSIX)
575 {L"/c:/foo/bar.txt", "file:/c:/foo/bar.txt"},
576 {L"/c:/foo/bar.txt", "file:///c:/foo/bar.txt"},
577 {L"/foo/bar.txt", "file:/foo/bar.txt"},
578 {L"/c:/foo/bar.txt", "file:\\\\\\c:/foo/bar.txt"},
579 {L"/foo/bar.txt", "file:foo/bar.txt"},
580 {L"/bar.txt", "file://foo/bar.txt"},
581 {L"/foo/bar.txt", "file:///foo/bar.txt"},
582 {L"/foo/bar.txt", "file:////foo/bar.txt"},
583 {L"/foo/bar.txt", "file:////foo//bar.txt"},
584 {L"/foo/bar.txt", "file:////foo///bar.txt"},
585 {L"/foo/bar.txt", "file:////foo////bar.txt"},
586 {L"/c:/foo/bar.txt", "file:\\\\\\c:/foo/bar.txt"},
587 {L"/c:/foo/bar.txt", "file:c:/foo/bar.txt"},
588 // We get these wrong because GURL turns back slashes into forward
589 // slashes.
590 //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
591 //{L"/c|/foo%5Cbar.txt", "file:c|/foo\\bar.txt"},
592 //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
593 //{L"/foo%5Cbar.txt", "file:////foo\\bar.txt"},
594 //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
595 #endif
597 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(url_cases); i++) {
598 FileURLToFilePath(GURL(url_cases[i].url), &output);
599 EXPECT_EQ(url_cases[i].file, file_util::FilePathAsWString(output));
602 // Unfortunately, UTF8ToWide discards invalid UTF8 input.
603 #ifdef BUG_878908_IS_FIXED
604 // Test that no conversion happens if the UTF-8 input is invalid, and that
605 // the input is preserved in UTF-8
606 const char invalid_utf8[] = "file:///d:/Blah/\xff.doc";
607 const wchar_t invalid_wide[] = L"D:\\Blah\\\xff.doc";
608 EXPECT_TRUE(FileURLToFilePath(
609 GURL(std::string(invalid_utf8)), &output));
610 EXPECT_EQ(std::wstring(invalid_wide), output);
611 #endif
613 // Test that if a file URL is malformed, we get a failure
614 EXPECT_FALSE(FileURLToFilePath(GURL("filefoobar"), &output));
617 TEST(NetUtilTest, GetIdentityFromURL) {
618 struct {
619 const char* input_url;
620 const char* expected_username;
621 const char* expected_password;
622 } tests[] = {
624 "http://username:password@google.com",
625 "username",
626 "password",
628 { // Test for http://crbug.com/19200
629 "http://username:p@ssword@google.com",
630 "username",
631 "p@ssword",
633 { // Special URL characters should be unescaped.
634 "http://username:p%3fa%26s%2fs%23@google.com",
635 "username",
636 "p?a&s/s#",
638 { // Username contains %20.
639 "http://use rname:password@google.com",
640 "use rname",
641 "password",
643 { // Keep %00 as is.
644 "http://use%00rname:password@google.com",
645 "use%00rname",
646 "password",
648 { // Use a '+' in the username.
649 "http://use+rname:password@google.com",
650 "use+rname",
651 "password",
653 { // Use a '&' in the password.
654 "http://username:p&ssword@google.com",
655 "username",
656 "p&ssword",
659 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
660 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i,
661 tests[i].input_url));
662 GURL url(tests[i].input_url);
664 base::string16 username, password;
665 GetIdentityFromURL(url, &username, &password);
667 EXPECT_EQ(ASCIIToUTF16(tests[i].expected_username), username);
668 EXPECT_EQ(ASCIIToUTF16(tests[i].expected_password), password);
672 // Try extracting a username which was encoded with UTF8.
673 TEST(NetUtilTest, GetIdentityFromURL_UTF8) {
674 GURL url(WideToUTF16(L"http://foo:\x4f60\x597d@blah.com"));
676 EXPECT_EQ("foo", url.username());
677 EXPECT_EQ("%E4%BD%A0%E5%A5%BD", url.password());
679 // Extract the unescaped identity.
680 base::string16 username, password;
681 GetIdentityFromURL(url, &username, &password);
683 // Verify that it was decoded as UTF8.
684 EXPECT_EQ(ASCIIToUTF16("foo"), username);
685 EXPECT_EQ(WideToUTF16(L"\x4f60\x597d"), password);
688 // Just a bunch of fake headers.
689 const char* google_headers =
690 "HTTP/1.1 200 OK\n"
691 "Content-TYPE: text/html; charset=utf-8\n"
692 "Content-disposition: attachment; filename=\"download.pdf\"\n"
693 "Content-Length: 378557\n"
694 "X-Google-Google1: 314159265\n"
695 "X-Google-Google2: aaaa2:7783,bbb21:9441\n"
696 "X-Google-Google4: home\n"
697 "Transfer-Encoding: chunked\n"
698 "Set-Cookie: HEHE_AT=6666x66beef666x6-66xx6666x66; Path=/mail\n"
699 "Set-Cookie: HEHE_HELP=owned:0;Path=/\n"
700 "Set-Cookie: S=gmail=Xxx-beefbeefbeef_beefb:gmail_yj=beefbeef000beefbee"
701 "fbee:gmproxy=bee-fbeefbe; Domain=.google.com; Path=/\n"
702 "X-Google-Google2: /one/two/three/four/five/six/seven-height/nine:9411\n"
703 "Server: GFE/1.3\n"
704 "Transfer-Encoding: chunked\n"
705 "Date: Mon, 13 Nov 2006 21:38:09 GMT\n"
706 "Expires: Tue, 14 Nov 2006 19:23:58 GMT\n"
707 "X-Malformed: bla; arg=test\"\n"
708 "X-Malformed2: bla; arg=\n"
709 "X-Test: bla; arg1=val1; arg2=val2";
711 TEST(NetUtilTest, GetSpecificHeader) {
712 const HeaderCase tests[] = {
713 {"content-type", "text/html; charset=utf-8"},
714 {"CONTENT-LENGTH", "378557"},
715 {"Date", "Mon, 13 Nov 2006 21:38:09 GMT"},
716 {"Bad-Header", ""},
717 {"", ""},
720 // Test first with google_headers.
721 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
722 std::string result =
723 GetSpecificHeader(google_headers, tests[i].header_name);
724 EXPECT_EQ(result, tests[i].expected);
727 // Test again with empty headers.
728 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
729 std::string result = GetSpecificHeader(std::string(), tests[i].header_name);
730 EXPECT_EQ(result, std::string());
734 TEST(NetUtilTest, IDNToUnicodeFast) {
735 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(idn_cases); i++) {
736 for (size_t j = 0; j < arraysize(kLanguages); j++) {
737 // ja || zh-TW,en || ko,ja -> IDNToUnicodeSlow
738 if (j == 3 || j == 17 || j == 18)
739 continue;
740 base::string16 output(IDNToUnicode(idn_cases[i].input, kLanguages[j]));
741 base::string16 expected(idn_cases[i].unicode_allowed[j] ?
742 WideToUTF16(idn_cases[i].unicode_output) :
743 ASCIIToUTF16(idn_cases[i].input));
744 AppendLanguagesToOutputs(kLanguages[j], &expected, &output);
745 EXPECT_EQ(expected, output);
750 TEST(NetUtilTest, IDNToUnicodeSlow) {
751 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(idn_cases); i++) {
752 for (size_t j = 0; j < arraysize(kLanguages); j++) {
753 // !(ja || zh-TW,en || ko,ja) -> IDNToUnicodeFast
754 if (!(j == 3 || j == 17 || j == 18))
755 continue;
756 base::string16 output(IDNToUnicode(idn_cases[i].input, kLanguages[j]));
757 base::string16 expected(idn_cases[i].unicode_allowed[j] ?
758 WideToUTF16(idn_cases[i].unicode_output) :
759 ASCIIToUTF16(idn_cases[i].input));
760 AppendLanguagesToOutputs(kLanguages[j], &expected, &output);
761 EXPECT_EQ(expected, output);
766 TEST(NetUtilTest, CompliantHost) {
767 const CompliantHostCase compliant_host_cases[] = {
768 {"", "", false},
769 {"a", "", true},
770 {"-", "", false},
771 {".", "", false},
772 {"9", "", true},
773 {"9a", "", true},
774 {"a.", "", true},
775 {"a.a", "", true},
776 {"9.a", "", true},
777 {"a.9", "", true},
778 {"_9a", "", false},
779 {"-9a", "", false},
780 {"-9a", "a", true},
781 {"a.a9", "", true},
782 {"a.-a9", "", false},
783 {"a+9a", "", false},
784 {"-a.a9", "", true},
785 {"1-.a-b", "", true},
786 {"1_.a-b", "", false},
787 {"1-2.a_b", "", true},
788 {"a.b.c.d.e", "", true},
789 {"1.2.3.4.5", "", true},
790 {"1.2.3.4.5.", "", true},
793 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(compliant_host_cases); ++i) {
794 EXPECT_EQ(compliant_host_cases[i].expected_output,
795 IsCanonicalizedHostCompliant(compliant_host_cases[i].host,
796 compliant_host_cases[i].desired_tld));
800 TEST(NetUtilTest, StripWWW) {
801 EXPECT_EQ(base::string16(), StripWWW(base::string16()));
802 EXPECT_EQ(base::string16(), StripWWW(ASCIIToUTF16("www.")));
803 EXPECT_EQ(ASCIIToUTF16("blah"), StripWWW(ASCIIToUTF16("www.blah")));
804 EXPECT_EQ(ASCIIToUTF16("blah"), StripWWW(ASCIIToUTF16("blah")));
807 #if defined(OS_WIN)
808 #define JPEG_EXT L".jpg"
809 #define HTML_EXT L".htm"
810 #elif defined(OS_MACOSX)
811 #define JPEG_EXT L".jpeg"
812 #define HTML_EXT L".html"
813 #else
814 #define JPEG_EXT L".jpg"
815 #define HTML_EXT L".html"
816 #endif
817 #define TXT_EXT L".txt"
818 #define TAR_EXT L".tar"
820 TEST(NetUtilTest, GenerateSafeFileName) {
821 const struct {
822 const char* mime_type;
823 const base::FilePath::CharType* filename;
824 const base::FilePath::CharType* expected_filename;
825 } safe_tests[] = {
826 #if defined(OS_WIN)
828 "text/html",
829 FILE_PATH_LITERAL("C:\\foo\\bar.htm"),
830 FILE_PATH_LITERAL("C:\\foo\\bar.htm")
833 "text/html",
834 FILE_PATH_LITERAL("C:\\foo\\bar.html"),
835 FILE_PATH_LITERAL("C:\\foo\\bar.html")
838 "text/html",
839 FILE_PATH_LITERAL("C:\\foo\\bar"),
840 FILE_PATH_LITERAL("C:\\foo\\bar.htm")
843 "image/png",
844 FILE_PATH_LITERAL("C:\\bar.html"),
845 FILE_PATH_LITERAL("C:\\bar.html")
848 "image/png",
849 FILE_PATH_LITERAL("C:\\bar"),
850 FILE_PATH_LITERAL("C:\\bar.png")
853 "text/html",
854 FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
855 FILE_PATH_LITERAL("C:\\foo\\bar.exe")
858 "image/gif",
859 FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
860 FILE_PATH_LITERAL("C:\\foo\\bar.exe")
863 "text/html",
864 FILE_PATH_LITERAL("C:\\foo\\google.com"),
865 FILE_PATH_LITERAL("C:\\foo\\google.com")
868 "text/html",
869 FILE_PATH_LITERAL("C:\\foo\\con.htm"),
870 FILE_PATH_LITERAL("C:\\foo\\_con.htm")
873 "text/html",
874 FILE_PATH_LITERAL("C:\\foo\\con"),
875 FILE_PATH_LITERAL("C:\\foo\\_con.htm")
878 "text/html",
879 FILE_PATH_LITERAL("C:\\foo\\harmless.{not-really-this-may-be-a-guid}"),
880 FILE_PATH_LITERAL("C:\\foo\\harmless.download")
883 "text/html",
884 FILE_PATH_LITERAL("C:\\foo\\harmless.local"),
885 FILE_PATH_LITERAL("C:\\foo\\harmless.download")
888 "text/html",
889 FILE_PATH_LITERAL("C:\\foo\\harmless.lnk"),
890 FILE_PATH_LITERAL("C:\\foo\\harmless.download")
893 "text/html",
894 FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-"),
895 FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-")
897 // Allow extension synonyms.
899 "image/jpeg",
900 FILE_PATH_LITERAL("C:\\foo\\bar.jpg"),
901 FILE_PATH_LITERAL("C:\\foo\\bar.jpg")
904 "image/jpeg",
905 FILE_PATH_LITERAL("C:\\foo\\bar.jpeg"),
906 FILE_PATH_LITERAL("C:\\foo\\bar.jpeg")
908 #else // !defined(OS_WIN)
910 "text/html",
911 FILE_PATH_LITERAL("/foo/bar.htm"),
912 FILE_PATH_LITERAL("/foo/bar.htm")
915 "text/html",
916 FILE_PATH_LITERAL("/foo/bar.html"),
917 FILE_PATH_LITERAL("/foo/bar.html")
920 "text/html",
921 FILE_PATH_LITERAL("/foo/bar"),
922 FILE_PATH_LITERAL("/foo/bar.html")
925 "image/png",
926 FILE_PATH_LITERAL("/bar.html"),
927 FILE_PATH_LITERAL("/bar.html")
930 "image/png",
931 FILE_PATH_LITERAL("/bar"),
932 FILE_PATH_LITERAL("/bar.png")
935 "image/gif",
936 FILE_PATH_LITERAL("/foo/bar.exe"),
937 FILE_PATH_LITERAL("/foo/bar.exe")
940 "text/html",
941 FILE_PATH_LITERAL("/foo/google.com"),
942 FILE_PATH_LITERAL("/foo/google.com")
945 "text/html",
946 FILE_PATH_LITERAL("/foo/con.htm"),
947 FILE_PATH_LITERAL("/foo/con.htm")
950 "text/html",
951 FILE_PATH_LITERAL("/foo/con"),
952 FILE_PATH_LITERAL("/foo/con.html")
954 // Allow extension synonyms.
956 "image/jpeg",
957 FILE_PATH_LITERAL("/bar.jpg"),
958 FILE_PATH_LITERAL("/bar.jpg")
961 "image/jpeg",
962 FILE_PATH_LITERAL("/bar.jpeg"),
963 FILE_PATH_LITERAL("/bar.jpeg")
965 #endif // !defined(OS_WIN)
968 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(safe_tests); ++i) {
969 base::FilePath file_path(safe_tests[i].filename);
970 GenerateSafeFileName(safe_tests[i].mime_type, false, &file_path);
971 EXPECT_EQ(safe_tests[i].expected_filename, file_path.value())
972 << "Iteration " << i;
976 TEST(NetUtilTest, GenerateFileName) {
977 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
978 // This test doesn't run when the locale is not UTF-8 because some of the
979 // string conversions fail. This is OK (we have the default value) but they
980 // don't match our expectations.
981 std::string locale = setlocale(LC_CTYPE, NULL);
982 StringToLowerASCII(&locale);
983 EXPECT_TRUE(locale.find("utf-8") != std::string::npos ||
984 locale.find("utf8") != std::string::npos)
985 << "Your locale (" << locale << ") must be set to UTF-8 "
986 << "for this test to pass!";
987 #endif
989 // Tests whether the correct filename is selected from the the given
990 // parameters and that Content-Disposition headers are properly
991 // handled including failovers when the header is malformed.
992 const GenerateFilenameCase selection_tests[] = {
994 __LINE__,
995 "http://www.google.com/",
996 "attachment; filename=test.html",
1000 L"",
1001 L"test.html"
1004 __LINE__,
1005 "http://www.google.com/",
1006 "attachment; filename=\"test.html\"",
1010 L"",
1011 L"test.html"
1014 __LINE__,
1015 "http://www.google.com/",
1016 "attachment; filename= \"test.html\"",
1020 L"",
1021 L"test.html"
1024 __LINE__,
1025 "http://www.google.com/",
1026 "attachment; filename = \"test.html\"",
1030 L"",
1031 L"test.html"
1033 { // filename is whitespace. Should failover to URL host
1034 __LINE__,
1035 "http://www.google.com/",
1036 "attachment; filename= ",
1040 L"",
1041 L"www.google.com"
1043 { // No filename.
1044 __LINE__,
1045 "http://www.google.com/path/test.html",
1046 "attachment",
1050 L"",
1051 L"test.html"
1053 { // Ditto
1054 __LINE__,
1055 "http://www.google.com/path/test.html",
1056 "attachment;",
1060 L"",
1061 L"test.html"
1063 { // No C-D
1064 __LINE__,
1065 "http://www.google.com/",
1070 L"",
1071 L"www.google.com"
1074 __LINE__,
1075 "http://www.google.com/test.html",
1080 L"",
1081 L"test.html"
1083 { // Now that we use src/url's ExtractFileName, this case falls back to
1084 // the hostname. If this behavior is not desirable, we'd better change
1085 // ExtractFileName (in url_parse).
1086 __LINE__,
1087 "http://www.google.com/path/",
1092 L"",
1093 L"www.google.com"
1096 __LINE__,
1097 "http://www.google.com/path",
1102 L"",
1103 L"path"
1106 __LINE__,
1107 "file:///",
1112 L"",
1113 L"download"
1116 __LINE__,
1117 "file:///path/testfile",
1122 L"",
1123 L"testfile"
1126 __LINE__,
1127 "non-standard-scheme:",
1132 L"",
1133 L"download"
1135 { // C-D should override default
1136 __LINE__,
1137 "http://www.google.com/",
1138 "attachment; filename =\"test.html\"",
1142 L"download",
1143 L"test.html"
1145 { // But the URL shouldn't
1146 __LINE__,
1147 "http://www.google.com/",
1152 L"download",
1153 L"download"
1156 __LINE__,
1157 "http://www.google.com/",
1158 "attachment; filename=\"../test.html\"",
1162 L"",
1163 L"-test.html"
1166 __LINE__,
1167 "http://www.google.com/",
1168 "attachment; filename=\"..\\test.html\"",
1172 L"",
1173 L"test.html"
1176 __LINE__,
1177 "http://www.google.com/",
1178 "attachment; filename=\"..\\\\test.html\"",
1182 L"",
1183 L"-test.html"
1185 { // Filename disappears after leading and trailing periods are removed.
1186 __LINE__,
1187 "http://www.google.com/",
1188 "attachment; filename=\"..\"",
1192 L"default",
1193 L"default"
1195 { // C-D specified filename disappears. Failover to final filename.
1196 __LINE__,
1197 "http://www.google.com/test.html",
1198 "attachment; filename=\"..\"",
1202 L"default",
1203 L"default"
1205 // Below is a small subset of cases taken from HttpContentDisposition tests.
1207 __LINE__,
1208 "http://www.google.com/",
1209 "attachment; filename=\"%EC%98%88%EC%88%A0%20"
1210 "%EC%98%88%EC%88%A0.jpg\"",
1214 L"",
1215 L"\uc608\uc220 \uc608\uc220.jpg"
1218 __LINE__,
1219 "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
1224 L"download",
1225 L"\uc608\uc220 \uc608\uc220.jpg"
1228 __LINE__,
1229 "http://www.google.com/",
1230 "attachment;",
1234 L"\uB2E4\uC6B4\uB85C\uB4DC",
1235 L"\uB2E4\uC6B4\uB85C\uB4DC"
1238 __LINE__,
1239 "http://www.google.com/",
1240 "attachment; filename=\"=?EUC-JP?Q?=B7=DD=BD="
1241 "D13=2Epng?=\"",
1245 L"download",
1246 L"\u82b8\u88533.png"
1249 __LINE__,
1250 "http://www.example.com/images?id=3",
1251 "attachment; filename=caf\xc3\xa9.png",
1252 "iso-8859-1",
1255 L"",
1256 L"caf\u00e9.png"
1259 __LINE__,
1260 "http://www.example.com/images?id=3",
1261 "attachment; filename=caf\xe5.png",
1262 "windows-1253",
1265 L"",
1266 L"caf\u03b5.png"
1269 __LINE__,
1270 "http://www.example.com/file?id=3",
1271 "attachment; name=\xcf\xc2\xd4\xd8.zip",
1272 "GBK",
1275 L"",
1276 L"\u4e0b\u8f7d.zip"
1278 { // Invalid C-D header. Extracts filename from url.
1279 __LINE__,
1280 "http://www.google.com/test.html",
1281 "attachment; filename==?iiso88591?Q?caf=EG?=",
1285 L"",
1286 L"test.html"
1288 // about: and data: URLs
1290 __LINE__,
1291 "about:chrome",
1296 L"",
1297 L"download"
1300 __LINE__,
1301 "data:,looks/like/a.path",
1306 L"",
1307 L"download"
1310 __LINE__,
1311 "data:text/plain;base64,VG8gYmUgb3Igbm90IHRvIGJlLg=",
1316 L"",
1317 L"download"
1320 __LINE__,
1321 "data:,looks/like/a.path",
1326 L"default_filename_is_given",
1327 L"default_filename_is_given"
1330 __LINE__,
1331 "data:,looks/like/a.path",
1336 L"\u65e5\u672c\u8a9e", // Japanese Kanji.
1337 L"\u65e5\u672c\u8a9e"
1339 { // The filename encoding is specified by the referrer charset.
1340 __LINE__,
1341 "http://example.com/V%FDvojov%E1%20psychologie.doc",
1343 "iso-8859-1",
1346 L"",
1347 L"V\u00fdvojov\u00e1 psychologie.doc"
1349 { // Suggested filename takes precedence over URL
1350 __LINE__,
1351 "http://www.google.com/test",
1354 "suggested",
1356 L"",
1357 L"suggested"
1359 { // The content-disposition has higher precedence over the suggested name.
1360 __LINE__,
1361 "http://www.google.com/test",
1362 "attachment; filename=test.html",
1364 "suggested",
1366 L"",
1367 L"test.html"
1369 #if 0
1370 { // The filename encoding doesn't match the referrer charset, the system
1371 // charset, or UTF-8.
1372 // TODO(jshin): we need to handle this case.
1373 __LINE__,
1374 "http://example.com/V%FDvojov%E1%20psychologie.doc",
1376 "utf-8",
1379 L"",
1380 L"V\u00fdvojov\u00e1 psychologie.doc",
1382 #endif
1383 // Raw 8bit characters in C-D
1385 __LINE__,
1386 "http://www.example.com/images?id=3",
1387 "attachment; filename=caf\xc3\xa9.png",
1388 "iso-8859-1",
1390 "image/png",
1391 L"",
1392 L"caf\u00e9.png"
1395 __LINE__,
1396 "http://www.example.com/images?id=3",
1397 "attachment; filename=caf\xe5.png",
1398 "windows-1253",
1400 "image/png",
1401 L"",
1402 L"caf\u03b5.png"
1404 { // No 'filename' keyword in the disposition, use the URL
1405 __LINE__,
1406 "http://www.evil.com/my_download.txt",
1407 "a_file_name.txt",
1410 "text/plain",
1411 L"download",
1412 L"my_download.txt"
1414 { // Spaces in the disposition file name
1415 __LINE__,
1416 "http://www.frontpagehacker.com/a_download.exe",
1417 "filename=My Downloaded File.exe",
1420 "application/octet-stream",
1421 L"download",
1422 L"My Downloaded File.exe"
1424 { // % encoded
1425 __LINE__,
1426 "http://www.examples.com/",
1427 "attachment; "
1428 "filename=\"%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg\"",
1431 "image/jpeg",
1432 L"download",
1433 L"\uc608\uc220 \uc608\uc220.jpg"
1435 { // name= parameter
1436 __LINE__,
1437 "http://www.examples.com/q.cgi?id=abc",
1438 "attachment; name=abc de.pdf",
1441 "application/octet-stream",
1442 L"download",
1443 L"abc de.pdf"
1446 __LINE__,
1447 "http://www.example.com/path",
1448 "filename=\"=?EUC-JP?Q?=B7=DD=BD=D13=2Epng?=\"",
1451 "image/png",
1452 L"download",
1453 L"\x82b8\x8853" L"3.png"
1455 { // The following two have invalid CD headers and filenames come from the
1456 // URL.
1457 __LINE__,
1458 "http://www.example.com/test%20123",
1459 "attachment; filename==?iiso88591?Q?caf=EG?=",
1462 "image/jpeg",
1463 L"download",
1464 L"test 123" JPEG_EXT
1467 __LINE__,
1468 "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
1469 "malformed_disposition",
1472 "image/jpeg",
1473 L"download",
1474 L"\uc608\uc220 \uc608\uc220.jpg"
1476 { // Invalid C-D. No filename from URL. Falls back to 'download'.
1477 __LINE__,
1478 "http://www.google.com/path1/path2/",
1479 "attachment; filename==?iso88591?Q?caf=E3?",
1482 "image/jpeg",
1483 L"download",
1484 L"download" JPEG_EXT
1488 // Tests filename generation. Once the correct filename is
1489 // selected, they should be passed through the validation steps and
1490 // a correct extension should be added if necessary.
1491 const GenerateFilenameCase generation_tests[] = {
1492 // Dotfiles. Ensures preceeding period(s) stripped.
1494 __LINE__,
1495 "http://www.google.com/.test.html",
1500 L"",
1501 L"test.html"
1504 __LINE__,
1505 "http://www.google.com/.test",
1510 L"",
1511 L"test"
1514 __LINE__,
1515 "http://www.google.com/..test",
1520 L"",
1521 L"test"
1523 { // Disposition has relative paths, remove directory separators
1524 __LINE__,
1525 "http://www.evil.com/my_download.txt",
1526 "filename=../../../../././../a_file_name.txt",
1529 "text/plain",
1530 L"download",
1531 L"-..-..-..-.-.-..-a_file_name.txt"
1533 { // Disposition has parent directories, remove directory separators
1534 __LINE__,
1535 "http://www.evil.com/my_download.txt",
1536 "filename=dir1/dir2/a_file_name.txt",
1539 "text/plain",
1540 L"download",
1541 L"dir1-dir2-a_file_name.txt"
1543 { // Disposition has relative paths, remove directory separators
1544 __LINE__,
1545 "http://www.evil.com/my_download.txt",
1546 "filename=..\\..\\..\\..\\.\\.\\..\\a_file_name.txt",
1549 "text/plain",
1550 L"download",
1551 L"-..-..-..-.-.-..-a_file_name.txt"
1553 { // Disposition has parent directories, remove directory separators
1554 __LINE__,
1555 "http://www.evil.com/my_download.txt",
1556 "filename=dir1\\dir2\\a_file_name.txt",
1559 "text/plain",
1560 L"download",
1561 L"dir1-dir2-a_file_name.txt"
1563 { // No useful information in disposition or URL, use default
1564 __LINE__,
1565 "http://www.truncated.com/path/",
1569 "text/plain",
1570 L"download",
1571 L"download" TXT_EXT
1573 { // Filename looks like HTML?
1574 __LINE__,
1575 "http://www.evil.com/get/malware/here",
1576 "filename=\"<blink>Hello kitty</blink>\"",
1579 "text/plain",
1580 L"default",
1581 L"-blink-Hello kitty--blink-" TXT_EXT
1583 { // A normal avi should get .avi and not .avi.avi
1584 __LINE__,
1585 "https://blah.google.com/misc/2.avi",
1589 "video/x-msvideo",
1590 L"download",
1591 L"2.avi"
1593 { // Extension generation
1594 __LINE__,
1595 "http://www.example.com/my-cat",
1596 "filename=my-cat",
1599 "image/jpeg",
1600 L"download",
1601 L"my-cat" JPEG_EXT
1604 __LINE__,
1605 "http://www.example.com/my-cat",
1606 "filename=my-cat",
1609 "text/plain",
1610 L"download",
1611 L"my-cat.txt"
1614 __LINE__,
1615 "http://www.example.com/my-cat",
1616 "filename=my-cat",
1619 "text/html",
1620 L"download",
1621 L"my-cat" HTML_EXT
1623 { // Unknown MIME type
1624 __LINE__,
1625 "http://www.example.com/my-cat",
1626 "filename=my-cat",
1629 "dance/party",
1630 L"download",
1631 L"my-cat"
1634 __LINE__,
1635 "http://www.example.com/my-cat.jpg",
1636 "filename=my-cat.jpg",
1639 "text/plain",
1640 L"download",
1641 L"my-cat.jpg"
1643 // Windows specific tests
1644 #if defined(OS_WIN)
1646 __LINE__,
1647 "http://www.goodguy.com/evil.exe",
1648 "filename=evil.exe",
1651 "image/jpeg",
1652 L"download",
1653 L"evil.exe"
1656 __LINE__,
1657 "http://www.goodguy.com/ok.exe",
1658 "filename=ok.exe",
1661 "binary/octet-stream",
1662 L"download",
1663 L"ok.exe"
1666 __LINE__,
1667 "http://www.goodguy.com/evil.dll",
1668 "filename=evil.dll",
1671 "dance/party",
1672 L"download",
1673 L"evil.dll"
1676 __LINE__,
1677 "http://www.goodguy.com/evil.exe",
1678 "filename=evil",
1681 "application/rss+xml",
1682 L"download",
1683 L"evil"
1685 // Test truncation of trailing dots and spaces
1687 __LINE__,
1688 "http://www.goodguy.com/evil.exe ",
1689 "filename=evil.exe ",
1692 "binary/octet-stream",
1693 L"download",
1694 L"evil.exe"
1697 __LINE__,
1698 "http://www.goodguy.com/evil.exe.",
1699 "filename=evil.exe.",
1702 "binary/octet-stream",
1703 L"download",
1704 L"evil.exe-"
1707 __LINE__,
1708 "http://www.goodguy.com/evil.exe. . .",
1709 "filename=evil.exe. . .",
1712 "binary/octet-stream",
1713 L"download",
1714 L"evil.exe-------"
1717 __LINE__,
1718 "http://www.goodguy.com/evil.",
1719 "filename=evil.",
1722 "binary/octet-stream",
1723 L"download",
1724 L"evil-"
1727 __LINE__,
1728 "http://www.goodguy.com/. . . . .",
1729 "filename=. . . . .",
1732 "binary/octet-stream",
1733 L"download",
1734 L"download"
1737 __LINE__,
1738 "http://www.badguy.com/attachment?name=meh.exe%C2%A0",
1739 "attachment; filename=\"meh.exe\xC2\xA0\"",
1742 "binary/octet-stream",
1743 L"",
1744 L"meh.exe-"
1746 #endif // OS_WIN
1748 __LINE__,
1749 "http://www.goodguy.com/utils.js",
1750 "filename=utils.js",
1753 "application/x-javascript",
1754 L"download",
1755 L"utils.js"
1758 __LINE__,
1759 "http://www.goodguy.com/contacts.js",
1760 "filename=contacts.js",
1763 "application/json",
1764 L"download",
1765 L"contacts.js"
1768 __LINE__,
1769 "http://www.goodguy.com/utils.js",
1770 "filename=utils.js",
1773 "text/javascript",
1774 L"download",
1775 L"utils.js"
1778 __LINE__,
1779 "http://www.goodguy.com/utils.js",
1780 "filename=utils.js",
1783 "text/javascript;version=2",
1784 L"download",
1785 L"utils.js"
1788 __LINE__,
1789 "http://www.goodguy.com/utils.js",
1790 "filename=utils.js",
1793 "application/ecmascript",
1794 L"download",
1795 L"utils.js"
1798 __LINE__,
1799 "http://www.goodguy.com/utils.js",
1800 "filename=utils.js",
1803 "application/ecmascript;version=4",
1804 L"download",
1805 L"utils.js"
1808 __LINE__,
1809 "http://www.goodguy.com/program.exe",
1810 "filename=program.exe",
1813 "application/foo-bar",
1814 L"download",
1815 L"program.exe"
1818 __LINE__,
1819 "http://www.evil.com/../foo.txt",
1820 "filename=../foo.txt",
1823 "text/plain",
1824 L"download",
1825 L"-foo.txt"
1828 __LINE__,
1829 "http://www.evil.com/..\\foo.txt",
1830 "filename=..\\foo.txt",
1833 "text/plain",
1834 L"download",
1835 L"-foo.txt"
1838 __LINE__,
1839 "http://www.evil.com/.hidden",
1840 "filename=.hidden",
1843 "text/plain",
1844 L"download",
1845 L"hidden" TXT_EXT
1848 __LINE__,
1849 "http://www.evil.com/trailing.",
1850 "filename=trailing.",
1853 "dance/party",
1854 L"download",
1855 #if defined(OS_WIN)
1856 L"trailing-"
1857 #else
1858 L"trailing"
1859 #endif
1862 __LINE__,
1863 "http://www.evil.com/trailing.",
1864 "filename=trailing.",
1867 "text/plain",
1868 L"download",
1869 #if defined(OS_WIN)
1870 L"trailing-" TXT_EXT
1871 #else
1872 L"trailing" TXT_EXT
1873 #endif
1876 __LINE__,
1877 "http://www.evil.com/.",
1878 "filename=.",
1881 "dance/party",
1882 L"download",
1883 L"download"
1886 __LINE__,
1887 "http://www.evil.com/..",
1888 "filename=..",
1891 "dance/party",
1892 L"download",
1893 L"download"
1896 __LINE__,
1897 "http://www.evil.com/...",
1898 "filename=...",
1901 "dance/party",
1902 L"download",
1903 L"download"
1905 { // Note that this one doesn't have "filename=" on it.
1906 __LINE__,
1907 "http://www.evil.com/",
1908 "a_file_name.txt",
1911 "image/jpeg",
1912 L"download",
1913 L"download" JPEG_EXT
1916 __LINE__,
1917 "http://www.evil.com/",
1918 "filename=",
1921 "image/jpeg",
1922 L"download",
1923 L"download" JPEG_EXT
1926 __LINE__,
1927 "http://www.example.com/simple",
1928 "filename=simple",
1931 "application/octet-stream",
1932 L"download",
1933 L"simple"
1935 // Reserved words on Windows
1937 __LINE__,
1938 "http://www.goodguy.com/COM1",
1939 "filename=COM1",
1942 "application/foo-bar",
1943 L"download",
1944 #if defined(OS_WIN)
1945 L"_COM1"
1946 #else
1947 L"COM1"
1948 #endif
1951 __LINE__,
1952 "http://www.goodguy.com/COM4.txt",
1953 "filename=COM4.txt",
1956 "text/plain",
1957 L"download",
1958 #if defined(OS_WIN)
1959 L"_COM4.txt"
1960 #else
1961 L"COM4.txt"
1962 #endif
1965 __LINE__,
1966 "http://www.goodguy.com/lpt1.TXT",
1967 "filename=lpt1.TXT",
1970 "text/plain",
1971 L"download",
1972 #if defined(OS_WIN)
1973 L"_lpt1.TXT"
1974 #else
1975 L"lpt1.TXT"
1976 #endif
1979 __LINE__,
1980 "http://www.goodguy.com/clock$.txt",
1981 "filename=clock$.txt",
1984 "text/plain",
1985 L"download",
1986 #if defined(OS_WIN)
1987 L"_clock$.txt"
1988 #else
1989 L"clock$.txt"
1990 #endif
1992 { // Validation should also apply to sugested name
1993 __LINE__,
1994 "http://www.goodguy.com/blah$.txt",
1995 "filename=clock$.txt",
1997 "clock$.txt",
1998 "text/plain",
1999 L"download",
2000 #if defined(OS_WIN)
2001 L"_clock$.txt"
2002 #else
2003 L"clock$.txt"
2004 #endif
2007 __LINE__,
2008 "http://www.goodguy.com/mycom1.foo",
2009 "filename=mycom1.foo",
2012 "text/plain",
2013 L"download",
2014 L"mycom1.foo"
2017 __LINE__,
2018 "http://www.badguy.com/Setup.exe.local",
2019 "filename=Setup.exe.local",
2022 "application/foo-bar",
2023 L"download",
2024 #if defined(OS_WIN)
2025 L"Setup.exe.download"
2026 #else
2027 L"Setup.exe.local"
2028 #endif
2031 __LINE__,
2032 "http://www.badguy.com/Setup.exe.local",
2033 "filename=Setup.exe.local.local",
2036 "application/foo-bar",
2037 L"download",
2038 #if defined(OS_WIN)
2039 L"Setup.exe.local.download"
2040 #else
2041 L"Setup.exe.local.local"
2042 #endif
2045 __LINE__,
2046 "http://www.badguy.com/Setup.exe.lnk",
2047 "filename=Setup.exe.lnk",
2050 "application/foo-bar",
2051 L"download",
2052 #if defined(OS_WIN)
2053 L"Setup.exe.download"
2054 #else
2055 L"Setup.exe.lnk"
2056 #endif
2059 __LINE__,
2060 "http://www.badguy.com/Desktop.ini",
2061 "filename=Desktop.ini",
2064 "application/foo-bar",
2065 L"download",
2066 #if defined(OS_WIN)
2067 L"_Desktop.ini"
2068 #else
2069 L"Desktop.ini"
2070 #endif
2073 __LINE__,
2074 "http://www.badguy.com/Thumbs.db",
2075 "filename=Thumbs.db",
2078 "application/foo-bar",
2079 L"download",
2080 #if defined(OS_WIN)
2081 L"_Thumbs.db"
2082 #else
2083 L"Thumbs.db"
2084 #endif
2087 __LINE__,
2088 "http://www.hotmail.com",
2089 "filename=source.jpg",
2092 "application/x-javascript",
2093 L"download",
2094 L"source.jpg"
2096 { // http://crbug.com/5772.
2097 __LINE__,
2098 "http://www.example.com/foo.tar.gz",
2102 "application/x-tar",
2103 L"download",
2104 L"foo.tar.gz"
2106 { // http://crbug.com/52250.
2107 __LINE__,
2108 "http://www.example.com/foo.tgz",
2112 "application/x-tar",
2113 L"download",
2114 L"foo.tgz"
2116 { // http://crbug.com/7337.
2117 __LINE__,
2118 "http://maged.lordaeron.org/blank.reg",
2122 "text/x-registry",
2123 L"download",
2124 L"blank.reg"
2127 __LINE__,
2128 "http://www.example.com/bar.tar",
2132 "application/x-tar",
2133 L"download",
2134 L"bar.tar"
2137 __LINE__,
2138 "http://www.example.com/bar.bogus",
2142 "application/x-tar",
2143 L"download",
2144 L"bar.bogus"
2146 { // http://crbug.com/20337
2147 __LINE__,
2148 "http://www.example.com/.download.txt",
2149 "filename=.download.txt",
2152 "text/plain",
2153 L"-download",
2154 L"download.txt"
2156 { // http://crbug.com/56855.
2157 __LINE__,
2158 "http://www.example.com/bar.sh",
2162 "application/x-sh",
2163 L"download",
2164 L"bar.sh"
2166 { // http://crbug.com/61571
2167 __LINE__,
2168 "http://www.example.com/npdf.php?fn=foobar.pdf",
2172 "text/plain",
2173 L"download",
2174 L"npdf" TXT_EXT
2176 { // Shouldn't overwrite C-D specified extension.
2177 __LINE__,
2178 "http://www.example.com/npdf.php?fn=foobar.pdf",
2179 "filename=foobar.jpg",
2182 "text/plain",
2183 L"download",
2184 L"foobar.jpg"
2186 { // http://crbug.com/87719
2187 __LINE__,
2188 "http://www.example.com/image.aspx?id=blargh",
2192 "image/jpeg",
2193 L"download",
2194 L"image" JPEG_EXT
2196 #if defined(OS_CHROMEOS)
2197 { // http://crosbug.com/26028
2198 __LINE__,
2199 "http://www.example.com/fooa%cc%88.txt",
2203 "image/jpeg",
2204 L"foo\xe4",
2205 L"foo\xe4.txt"
2207 #endif
2210 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(selection_tests); ++i)
2211 RunGenerateFileNameTestCase(&selection_tests[i]);
2213 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generation_tests); ++i)
2214 RunGenerateFileNameTestCase(&generation_tests[i]);
2216 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generation_tests); ++i) {
2217 GenerateFilenameCase test_case = generation_tests[i];
2218 test_case.referrer_charset = "GBK";
2219 RunGenerateFileNameTestCase(&test_case);
2223 // This is currently a windows specific function.
2224 #if defined(OS_WIN)
2225 namespace {
2227 struct GetDirectoryListingEntryCase {
2228 const wchar_t* name;
2229 const char* raw_bytes;
2230 bool is_dir;
2231 int64 filesize;
2232 base::Time time;
2233 const char* expected;
2236 } // namespace
2237 TEST(NetUtilTest, GetDirectoryListingEntry) {
2238 const GetDirectoryListingEntryCase test_cases[] = {
2239 {L"Foo",
2241 false,
2242 10000,
2243 base::Time(),
2244 "<script>addRow(\"Foo\",\"Foo\",0,\"9.8 kB\",\"\");</script>\n"},
2245 {L"quo\"tes",
2247 false,
2248 10000,
2249 base::Time(),
2250 "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,\"9.8 kB\",\"\");</script>"
2251 "\n"},
2252 {L"quo\"tes",
2253 "quo\"tes",
2254 false,
2255 10000,
2256 base::Time(),
2257 "<script>addRow(\"quo\\\"tes\",\"quo%22tes\",0,\"9.8 kB\",\"\");</script>"
2258 "\n"},
2259 // U+D55C0 U+AE00. raw_bytes is empty (either a local file with
2260 // UTF-8/UTF-16 encoding or a remote file on an ftp server using UTF-8
2261 {L"\xD55C\xAE00.txt",
2263 false,
2264 10000,
2265 base::Time(),
2266 "<script>addRow(\"\xED\x95\x9C\xEA\xB8\x80.txt\","
2267 "\"%ED%95%9C%EA%B8%80.txt\",0,\"9.8 kB\",\"\");</script>\n"},
2268 // U+D55C0 U+AE00. raw_bytes is the corresponding EUC-KR sequence:
2269 // a local or remote file in EUC-KR.
2270 {L"\xD55C\xAE00.txt",
2271 "\xC7\xD1\xB1\xDB.txt",
2272 false,
2273 10000,
2274 base::Time(),
2275 "<script>addRow(\"\xED\x95\x9C\xEA\xB8\x80.txt\",\"%C7%D1%B1%DB.txt\""
2276 ",0,\"9.8 kB\",\"\");</script>\n"},
2279 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
2280 const std::string results = GetDirectoryListingEntry(
2281 WideToUTF16(test_cases[i].name),
2282 test_cases[i].raw_bytes,
2283 test_cases[i].is_dir,
2284 test_cases[i].filesize,
2285 test_cases[i].time);
2286 EXPECT_EQ(test_cases[i].expected, results);
2290 #endif
2292 TEST(NetUtilTest, ParseHostAndPort) {
2293 const struct {
2294 const char* input;
2295 bool success;
2296 const char* expected_host;
2297 int expected_port;
2298 } tests[] = {
2299 // Valid inputs:
2300 {"foo:10", true, "foo", 10},
2301 {"foo", true, "foo", -1},
2303 "[1080:0:0:0:8:800:200C:4171]:11",
2304 true,
2305 "[1080:0:0:0:8:800:200C:4171]",
2308 // Invalid inputs:
2309 {"foo:bar", false, "", -1},
2310 {"foo:", false, "", -1},
2311 {":", false, "", -1},
2312 {":80", false, "", -1},
2313 {"", false, "", -1},
2314 {"porttoolong:300000", false, "", -1},
2315 {"usrname@host", false, "", -1},
2316 {"usrname:password@host", false, "", -1},
2317 {":password@host", false, "", -1},
2318 {":password@host:80", false, "", -1},
2319 {":password@host", false, "", -1},
2320 {"@host", false, "", -1},
2323 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
2324 std::string host;
2325 int port;
2326 bool ok = ParseHostAndPort(tests[i].input, &host, &port);
2328 EXPECT_EQ(tests[i].success, ok);
2330 if (tests[i].success) {
2331 EXPECT_EQ(tests[i].expected_host, host);
2332 EXPECT_EQ(tests[i].expected_port, port);
2337 TEST(NetUtilTest, GetHostAndPort) {
2338 const struct {
2339 GURL url;
2340 const char* expected_host_and_port;
2341 } tests[] = {
2342 { GURL("http://www.foo.com/x"), "www.foo.com:80"},
2343 { GURL("http://www.foo.com:21/x"), "www.foo.com:21"},
2345 // For IPv6 literals should always include the brackets.
2346 { GURL("http://[1::2]/x"), "[1::2]:80"},
2347 { GURL("http://[::a]:33/x"), "[::a]:33"},
2349 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
2350 std::string host_and_port = GetHostAndPort(tests[i].url);
2351 EXPECT_EQ(std::string(tests[i].expected_host_and_port), host_and_port);
2355 TEST(NetUtilTest, GetHostAndOptionalPort) {
2356 const struct {
2357 GURL url;
2358 const char* expected_host_and_port;
2359 } tests[] = {
2360 { GURL("http://www.foo.com/x"), "www.foo.com"},
2361 { GURL("http://www.foo.com:21/x"), "www.foo.com:21"},
2363 // For IPv6 literals should always include the brackets.
2364 { GURL("http://[1::2]/x"), "[1::2]"},
2365 { GURL("http://[::a]:33/x"), "[::a]:33"},
2367 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
2368 std::string host_and_port = GetHostAndOptionalPort(tests[i].url);
2369 EXPECT_EQ(std::string(tests[i].expected_host_and_port), host_and_port);
2373 TEST(NetUtilTest, IPAddressToString) {
2374 uint8 addr1[4] = {0, 0, 0, 0};
2375 EXPECT_EQ("0.0.0.0", IPAddressToString(addr1, sizeof(addr1)));
2377 uint8 addr2[4] = {192, 168, 0, 1};
2378 EXPECT_EQ("192.168.0.1", IPAddressToString(addr2, sizeof(addr2)));
2380 uint8 addr3[16] = {0xFE, 0xDC, 0xBA, 0x98};
2381 EXPECT_EQ("fedc:ba98::", IPAddressToString(addr3, sizeof(addr3)));
2384 TEST(NetUtilTest, IPAddressToStringWithPort) {
2385 uint8 addr1[4] = {0, 0, 0, 0};
2386 EXPECT_EQ("0.0.0.0:3", IPAddressToStringWithPort(addr1, sizeof(addr1), 3));
2388 uint8 addr2[4] = {192, 168, 0, 1};
2389 EXPECT_EQ("192.168.0.1:99",
2390 IPAddressToStringWithPort(addr2, sizeof(addr2), 99));
2392 uint8 addr3[16] = {0xFE, 0xDC, 0xBA, 0x98};
2393 EXPECT_EQ("[fedc:ba98::]:8080",
2394 IPAddressToStringWithPort(addr3, sizeof(addr3), 8080));
2397 TEST(NetUtilTest, NetAddressToString_IPv4) {
2398 const struct {
2399 uint8 addr[4];
2400 const char* result;
2401 } tests[] = {
2402 {{0, 0, 0, 0}, "0.0.0.0"},
2403 {{127, 0, 0, 1}, "127.0.0.1"},
2404 {{192, 168, 0, 1}, "192.168.0.1"},
2407 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
2408 SockaddrStorage storage;
2409 MakeIPv4Address(tests[i].addr, 80, &storage);
2410 std::string result = NetAddressToString(storage.addr, storage.addr_len);
2411 EXPECT_EQ(std::string(tests[i].result), result);
2415 TEST(NetUtilTest, NetAddressToString_IPv6) {
2416 const struct {
2417 uint8 addr[16];
2418 const char* result;
2419 } tests[] = {
2420 {{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA,
2421 0x98, 0x76, 0x54, 0x32, 0x10},
2422 "fedc:ba98:7654:3210:fedc:ba98:7654:3210"},
2425 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
2426 SockaddrStorage storage;
2427 MakeIPv6Address(tests[i].addr, 80, &storage);
2428 EXPECT_EQ(std::string(tests[i].result),
2429 NetAddressToString(storage.addr, storage.addr_len));
2433 TEST(NetUtilTest, NetAddressToStringWithPort_IPv4) {
2434 uint8 addr[] = {127, 0, 0, 1};
2435 SockaddrStorage storage;
2436 MakeIPv4Address(addr, 166, &storage);
2437 std::string result = NetAddressToStringWithPort(storage.addr,
2438 storage.addr_len);
2439 EXPECT_EQ("127.0.0.1:166", result);
2442 TEST(NetUtilTest, NetAddressToStringWithPort_IPv6) {
2443 uint8 addr[] = {
2444 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA,
2445 0x98, 0x76, 0x54, 0x32, 0x10
2447 SockaddrStorage storage;
2448 MakeIPv6Address(addr, 361, &storage);
2449 std::string result = NetAddressToStringWithPort(storage.addr,
2450 storage.addr_len);
2452 // May fail on systems that don't support IPv6.
2453 if (!result.empty())
2454 EXPECT_EQ("[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:361", result);
2457 TEST(NetUtilTest, GetHostName) {
2458 // We can't check the result of GetHostName() directly, since the result
2459 // will differ across machines. Our goal here is to simply exercise the
2460 // code path, and check that things "look about right".
2461 std::string hostname = GetHostName();
2462 EXPECT_FALSE(hostname.empty());
2465 TEST(NetUtilTest, FormatUrl) {
2466 FormatUrlTypes default_format_type = kFormatUrlOmitUsernamePassword;
2467 const UrlTestData tests[] = {
2468 {"Empty URL", "", "", default_format_type, UnescapeRule::NORMAL, L"", 0},
2470 {"Simple URL",
2471 "http://www.google.com/", "", default_format_type, UnescapeRule::NORMAL,
2472 L"http://www.google.com/", 7},
2474 {"With a port number and a reference",
2475 "http://www.google.com:8080/#\xE3\x82\xB0", "", default_format_type,
2476 UnescapeRule::NORMAL,
2477 L"http://www.google.com:8080/#\x30B0", 7},
2479 // -------- IDN tests --------
2480 {"Japanese IDN with ja",
2481 "http://xn--l8jvb1ey91xtjb.jp", "ja", default_format_type,
2482 UnescapeRule::NORMAL, L"http://\x671d\x65e5\x3042\x3055\x3072.jp/", 7},
2484 {"Japanese IDN with en",
2485 "http://xn--l8jvb1ey91xtjb.jp", "en", default_format_type,
2486 UnescapeRule::NORMAL, L"http://xn--l8jvb1ey91xtjb.jp/", 7},
2488 {"Japanese IDN without any languages",
2489 "http://xn--l8jvb1ey91xtjb.jp", "", default_format_type,
2490 UnescapeRule::NORMAL,
2491 // Single script is safe for empty languages.
2492 L"http://\x671d\x65e5\x3042\x3055\x3072.jp/", 7},
2494 {"mailto: with Japanese IDN",
2495 "mailto:foo@xn--l8jvb1ey91xtjb.jp", "ja", default_format_type,
2496 UnescapeRule::NORMAL,
2497 // GURL doesn't assume an email address's domain part as a host name.
2498 L"mailto:foo@xn--l8jvb1ey91xtjb.jp", 7},
2500 {"file: with Japanese IDN",
2501 "file://xn--l8jvb1ey91xtjb.jp/config.sys", "ja", default_format_type,
2502 UnescapeRule::NORMAL,
2503 L"file://\x671d\x65e5\x3042\x3055\x3072.jp/config.sys", 7},
2505 {"ftp: with Japanese IDN",
2506 "ftp://xn--l8jvb1ey91xtjb.jp/config.sys", "ja", default_format_type,
2507 UnescapeRule::NORMAL,
2508 L"ftp://\x671d\x65e5\x3042\x3055\x3072.jp/config.sys", 6},
2510 // -------- omit_username_password flag tests --------
2511 {"With username and password, omit_username_password=false",
2512 "http://user:passwd@example.com/foo", "",
2513 kFormatUrlOmitNothing, UnescapeRule::NORMAL,
2514 L"http://user:passwd@example.com/foo", 19},
2516 {"With username and password, omit_username_password=true",
2517 "http://user:passwd@example.com/foo", "", default_format_type,
2518 UnescapeRule::NORMAL, L"http://example.com/foo", 7},
2520 {"With username and no password",
2521 "http://user@example.com/foo", "", default_format_type,
2522 UnescapeRule::NORMAL, L"http://example.com/foo", 7},
2524 {"Just '@' without username and password",
2525 "http://@example.com/foo", "", default_format_type, UnescapeRule::NORMAL,
2526 L"http://example.com/foo", 7},
2528 // GURL doesn't think local-part of an email address is username for URL.
2529 {"mailto:, omit_username_password=true",
2530 "mailto:foo@example.com", "", default_format_type, UnescapeRule::NORMAL,
2531 L"mailto:foo@example.com", 7},
2533 // -------- unescape flag tests --------
2534 {"Do not unescape",
2535 "http://%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB.jp/"
2536 "%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB"
2537 "?q=%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB", "en", default_format_type,
2538 UnescapeRule::NONE,
2539 // GURL parses %-encoded hostnames into Punycode.
2540 L"http://xn--qcka1pmc.jp/%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB"
2541 L"?q=%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB", 7},
2543 {"Unescape normally",
2544 "http://%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB.jp/"
2545 "%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB"
2546 "?q=%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB", "en", default_format_type,
2547 UnescapeRule::NORMAL,
2548 L"http://xn--qcka1pmc.jp/\x30B0\x30FC\x30B0\x30EB"
2549 L"?q=\x30B0\x30FC\x30B0\x30EB", 7},
2551 {"Unescape normally with BiDi control character",
2552 "http://example.com/%E2%80%AEabc?q=%E2%80%8Fxy", "en", default_format_type,
2553 UnescapeRule::NORMAL, L"http://example.com/%E2%80%AEabc?q=%E2%80%8Fxy", 7},
2555 {"Unescape normally including unescape spaces",
2556 "http://www.google.com/search?q=Hello%20World", "en", default_format_type,
2557 UnescapeRule::SPACES, L"http://www.google.com/search?q=Hello World", 7},
2560 {"unescape=true with some special characters",
2561 "http://user%3A:%40passwd@example.com/foo%3Fbar?q=b%26z", "",
2562 kFormatUrlOmitNothing, UnescapeRule::NORMAL,
2563 L"http://user%3A:%40passwd@example.com/foo%3Fbar?q=b%26z", 25},
2565 // Disabled: the resultant URL becomes "...user%253A:%2540passwd...".
2567 // -------- omit http: --------
2568 {"omit http with user name",
2569 "http://user@example.com/foo", "", kFormatUrlOmitAll,
2570 UnescapeRule::NORMAL, L"example.com/foo", 0},
2572 {"omit http",
2573 "http://www.google.com/", "en", kFormatUrlOmitHTTP,
2574 UnescapeRule::NORMAL, L"www.google.com/",
2577 {"omit http with https",
2578 "https://www.google.com/", "en", kFormatUrlOmitHTTP,
2579 UnescapeRule::NORMAL, L"https://www.google.com/",
2582 {"omit http starts with ftp.",
2583 "http://ftp.google.com/", "en", kFormatUrlOmitHTTP,
2584 UnescapeRule::NORMAL, L"http://ftp.google.com/",
2587 // -------- omit trailing slash on bare hostname --------
2588 {"omit slash when it's the entire path",
2589 "http://www.google.com/", "en",
2590 kFormatUrlOmitTrailingSlashOnBareHostname, UnescapeRule::NORMAL,
2591 L"http://www.google.com", 7},
2592 {"omit slash when there's a ref",
2593 "http://www.google.com/#ref", "en",
2594 kFormatUrlOmitTrailingSlashOnBareHostname, UnescapeRule::NORMAL,
2595 L"http://www.google.com/#ref", 7},
2596 {"omit slash when there's a query",
2597 "http://www.google.com/?", "en",
2598 kFormatUrlOmitTrailingSlashOnBareHostname, UnescapeRule::NORMAL,
2599 L"http://www.google.com/?", 7},
2600 {"omit slash when it's not the entire path",
2601 "http://www.google.com/foo", "en",
2602 kFormatUrlOmitTrailingSlashOnBareHostname, UnescapeRule::NORMAL,
2603 L"http://www.google.com/foo", 7},
2604 {"omit slash for nonstandard URLs",
2605 "data:/", "en", kFormatUrlOmitTrailingSlashOnBareHostname,
2606 UnescapeRule::NORMAL, L"data:/", 5},
2607 {"omit slash for file URLs",
2608 "file:///", "en", kFormatUrlOmitTrailingSlashOnBareHostname,
2609 UnescapeRule::NORMAL, L"file:///", 7},
2611 // -------- view-source: --------
2612 {"view-source",
2613 "view-source:http://xn--qcka1pmc.jp/", "ja", default_format_type,
2614 UnescapeRule::NORMAL, L"view-source:http://\x30B0\x30FC\x30B0\x30EB.jp/",
2615 19},
2617 {"view-source of view-source",
2618 "view-source:view-source:http://xn--qcka1pmc.jp/", "ja",
2619 default_format_type, UnescapeRule::NORMAL,
2620 L"view-source:view-source:http://xn--qcka1pmc.jp/", 12},
2622 // view-source should omit http and trailing slash where non-view-source
2623 // would.
2624 {"view-source omit http",
2625 "view-source:http://a.b/c", "en", kFormatUrlOmitAll,
2626 UnescapeRule::NORMAL, L"view-source:a.b/c",
2627 12},
2628 {"view-source omit http starts with ftp.",
2629 "view-source:http://ftp.b/c", "en", kFormatUrlOmitAll,
2630 UnescapeRule::NORMAL, L"view-source:http://ftp.b/c",
2631 19},
2632 {"view-source omit slash when it's the entire path",
2633 "view-source:http://a.b/", "en", kFormatUrlOmitAll,
2634 UnescapeRule::NORMAL, L"view-source:a.b",
2635 12},
2638 for (size_t i = 0; i < arraysize(tests); ++i) {
2639 size_t prefix_len;
2640 base::string16 formatted = FormatUrl(
2641 GURL(tests[i].input), tests[i].languages, tests[i].format_types,
2642 tests[i].escape_rules, NULL, &prefix_len, NULL);
2643 EXPECT_EQ(WideToUTF16(tests[i].output), formatted) << tests[i].description;
2644 EXPECT_EQ(tests[i].prefix_len, prefix_len) << tests[i].description;
2648 TEST(NetUtilTest, FormatUrlParsed) {
2649 // No unescape case.
2650 url_parse::Parsed parsed;
2651 base::string16 formatted = FormatUrl(
2652 GURL("http://\xE3\x82\xB0:\xE3\x83\xBC@xn--qcka1pmc.jp:8080/"
2653 "%E3%82%B0/?q=%E3%82%B0#\xE3\x82\xB0"),
2654 "ja", kFormatUrlOmitNothing, UnescapeRule::NONE, &parsed, NULL,
2655 NULL);
2656 EXPECT_EQ(WideToUTF16(
2657 L"http://%E3%82%B0:%E3%83%BC@\x30B0\x30FC\x30B0\x30EB.jp:8080"
2658 L"/%E3%82%B0/?q=%E3%82%B0#\x30B0"), formatted);
2659 EXPECT_EQ(WideToUTF16(L"%E3%82%B0"),
2660 formatted.substr(parsed.username.begin, parsed.username.len));
2661 EXPECT_EQ(WideToUTF16(L"%E3%83%BC"),
2662 formatted.substr(parsed.password.begin, parsed.password.len));
2663 EXPECT_EQ(WideToUTF16(L"\x30B0\x30FC\x30B0\x30EB.jp"),
2664 formatted.substr(parsed.host.begin, parsed.host.len));
2665 EXPECT_EQ(WideToUTF16(L"8080"),
2666 formatted.substr(parsed.port.begin, parsed.port.len));
2667 EXPECT_EQ(WideToUTF16(L"/%E3%82%B0/"),
2668 formatted.substr(parsed.path.begin, parsed.path.len));
2669 EXPECT_EQ(WideToUTF16(L"q=%E3%82%B0"),
2670 formatted.substr(parsed.query.begin, parsed.query.len));
2671 EXPECT_EQ(WideToUTF16(L"\x30B0"),
2672 formatted.substr(parsed.ref.begin, parsed.ref.len));
2674 // Unescape case.
2675 formatted = FormatUrl(
2676 GURL("http://\xE3\x82\xB0:\xE3\x83\xBC@xn--qcka1pmc.jp:8080/"
2677 "%E3%82%B0/?q=%E3%82%B0#\xE3\x82\xB0"),
2678 "ja", kFormatUrlOmitNothing, UnescapeRule::NORMAL, &parsed, NULL,
2679 NULL);
2680 EXPECT_EQ(WideToUTF16(L"http://\x30B0:\x30FC@\x30B0\x30FC\x30B0\x30EB.jp:8080"
2681 L"/\x30B0/?q=\x30B0#\x30B0"), formatted);
2682 EXPECT_EQ(WideToUTF16(L"\x30B0"),
2683 formatted.substr(parsed.username.begin, parsed.username.len));
2684 EXPECT_EQ(WideToUTF16(L"\x30FC"),
2685 formatted.substr(parsed.password.begin, parsed.password.len));
2686 EXPECT_EQ(WideToUTF16(L"\x30B0\x30FC\x30B0\x30EB.jp"),
2687 formatted.substr(parsed.host.begin, parsed.host.len));
2688 EXPECT_EQ(WideToUTF16(L"8080"),
2689 formatted.substr(parsed.port.begin, parsed.port.len));
2690 EXPECT_EQ(WideToUTF16(L"/\x30B0/"),
2691 formatted.substr(parsed.path.begin, parsed.path.len));
2692 EXPECT_EQ(WideToUTF16(L"q=\x30B0"),
2693 formatted.substr(parsed.query.begin, parsed.query.len));
2694 EXPECT_EQ(WideToUTF16(L"\x30B0"),
2695 formatted.substr(parsed.ref.begin, parsed.ref.len));
2697 // Omit_username_password + unescape case.
2698 formatted = FormatUrl(
2699 GURL("http://\xE3\x82\xB0:\xE3\x83\xBC@xn--qcka1pmc.jp:8080/"
2700 "%E3%82%B0/?q=%E3%82%B0#\xE3\x82\xB0"),
2701 "ja", kFormatUrlOmitUsernamePassword, UnescapeRule::NORMAL, &parsed,
2702 NULL, NULL);
2703 EXPECT_EQ(WideToUTF16(L"http://\x30B0\x30FC\x30B0\x30EB.jp:8080"
2704 L"/\x30B0/?q=\x30B0#\x30B0"), formatted);
2705 EXPECT_FALSE(parsed.username.is_valid());
2706 EXPECT_FALSE(parsed.password.is_valid());
2707 EXPECT_EQ(WideToUTF16(L"\x30B0\x30FC\x30B0\x30EB.jp"),
2708 formatted.substr(parsed.host.begin, parsed.host.len));
2709 EXPECT_EQ(WideToUTF16(L"8080"),
2710 formatted.substr(parsed.port.begin, parsed.port.len));
2711 EXPECT_EQ(WideToUTF16(L"/\x30B0/"),
2712 formatted.substr(parsed.path.begin, parsed.path.len));
2713 EXPECT_EQ(WideToUTF16(L"q=\x30B0"),
2714 formatted.substr(parsed.query.begin, parsed.query.len));
2715 EXPECT_EQ(WideToUTF16(L"\x30B0"),
2716 formatted.substr(parsed.ref.begin, parsed.ref.len));
2718 // View-source case.
2719 formatted =
2720 FormatUrl(GURL("view-source:http://user:passwd@host:81/path?query#ref"),
2721 std::string(),
2722 kFormatUrlOmitUsernamePassword,
2723 UnescapeRule::NORMAL,
2724 &parsed,
2725 NULL,
2726 NULL);
2727 EXPECT_EQ(WideToUTF16(L"view-source:http://host:81/path?query#ref"),
2728 formatted);
2729 EXPECT_EQ(WideToUTF16(L"view-source:http"),
2730 formatted.substr(parsed.scheme.begin, parsed.scheme.len));
2731 EXPECT_FALSE(parsed.username.is_valid());
2732 EXPECT_FALSE(parsed.password.is_valid());
2733 EXPECT_EQ(WideToUTF16(L"host"),
2734 formatted.substr(parsed.host.begin, parsed.host.len));
2735 EXPECT_EQ(WideToUTF16(L"81"),
2736 formatted.substr(parsed.port.begin, parsed.port.len));
2737 EXPECT_EQ(WideToUTF16(L"/path"),
2738 formatted.substr(parsed.path.begin, parsed.path.len));
2739 EXPECT_EQ(WideToUTF16(L"query"),
2740 formatted.substr(parsed.query.begin, parsed.query.len));
2741 EXPECT_EQ(WideToUTF16(L"ref"),
2742 formatted.substr(parsed.ref.begin, parsed.ref.len));
2744 // omit http case.
2745 formatted = FormatUrl(GURL("http://host:8000/a?b=c#d"),
2746 std::string(),
2747 kFormatUrlOmitHTTP,
2748 UnescapeRule::NORMAL,
2749 &parsed,
2750 NULL,
2751 NULL);
2752 EXPECT_EQ(WideToUTF16(L"host:8000/a?b=c#d"), formatted);
2753 EXPECT_FALSE(parsed.scheme.is_valid());
2754 EXPECT_FALSE(parsed.username.is_valid());
2755 EXPECT_FALSE(parsed.password.is_valid());
2756 EXPECT_EQ(WideToUTF16(L"host"),
2757 formatted.substr(parsed.host.begin, parsed.host.len));
2758 EXPECT_EQ(WideToUTF16(L"8000"),
2759 formatted.substr(parsed.port.begin, parsed.port.len));
2760 EXPECT_EQ(WideToUTF16(L"/a"),
2761 formatted.substr(parsed.path.begin, parsed.path.len));
2762 EXPECT_EQ(WideToUTF16(L"b=c"),
2763 formatted.substr(parsed.query.begin, parsed.query.len));
2764 EXPECT_EQ(WideToUTF16(L"d"),
2765 formatted.substr(parsed.ref.begin, parsed.ref.len));
2767 // omit http starts with ftp case.
2768 formatted = FormatUrl(GURL("http://ftp.host:8000/a?b=c#d"),
2769 std::string(),
2770 kFormatUrlOmitHTTP,
2771 UnescapeRule::NORMAL,
2772 &parsed,
2773 NULL,
2774 NULL);
2775 EXPECT_EQ(WideToUTF16(L"http://ftp.host:8000/a?b=c#d"), formatted);
2776 EXPECT_TRUE(parsed.scheme.is_valid());
2777 EXPECT_FALSE(parsed.username.is_valid());
2778 EXPECT_FALSE(parsed.password.is_valid());
2779 EXPECT_EQ(WideToUTF16(L"http"),
2780 formatted.substr(parsed.scheme.begin, parsed.scheme.len));
2781 EXPECT_EQ(WideToUTF16(L"ftp.host"),
2782 formatted.substr(parsed.host.begin, parsed.host.len));
2783 EXPECT_EQ(WideToUTF16(L"8000"),
2784 formatted.substr(parsed.port.begin, parsed.port.len));
2785 EXPECT_EQ(WideToUTF16(L"/a"),
2786 formatted.substr(parsed.path.begin, parsed.path.len));
2787 EXPECT_EQ(WideToUTF16(L"b=c"),
2788 formatted.substr(parsed.query.begin, parsed.query.len));
2789 EXPECT_EQ(WideToUTF16(L"d"),
2790 formatted.substr(parsed.ref.begin, parsed.ref.len));
2792 // omit http starts with 'f' case.
2793 formatted = FormatUrl(GURL("http://f/"),
2794 std::string(),
2795 kFormatUrlOmitHTTP,
2796 UnescapeRule::NORMAL,
2797 &parsed,
2798 NULL,
2799 NULL);
2800 EXPECT_EQ(WideToUTF16(L"f/"), formatted);
2801 EXPECT_FALSE(parsed.scheme.is_valid());
2802 EXPECT_FALSE(parsed.username.is_valid());
2803 EXPECT_FALSE(parsed.password.is_valid());
2804 EXPECT_FALSE(parsed.port.is_valid());
2805 EXPECT_TRUE(parsed.path.is_valid());
2806 EXPECT_FALSE(parsed.query.is_valid());
2807 EXPECT_FALSE(parsed.ref.is_valid());
2808 EXPECT_EQ(WideToUTF16(L"f"),
2809 formatted.substr(parsed.host.begin, parsed.host.len));
2810 EXPECT_EQ(WideToUTF16(L"/"),
2811 formatted.substr(parsed.path.begin, parsed.path.len));
2814 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
2815 // results in the original GURL, for each ASCII character in the path.
2816 TEST(NetUtilTest, FormatUrlRoundTripPathASCII) {
2817 for (unsigned char test_char = 32; test_char < 128; ++test_char) {
2818 GURL url(std::string("http://www.google.com/") +
2819 static_cast<char>(test_char));
2820 size_t prefix_len;
2821 base::string16 formatted = FormatUrl(url,
2822 std::string(),
2823 kFormatUrlOmitUsernamePassword,
2824 UnescapeRule::NORMAL,
2825 NULL,
2826 &prefix_len,
2827 NULL);
2828 EXPECT_EQ(url.spec(), GURL(formatted).spec());
2832 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
2833 // results in the original GURL, for each escaped ASCII character in the path.
2834 TEST(NetUtilTest, FormatUrlRoundTripPathEscaped) {
2835 for (unsigned char test_char = 32; test_char < 128; ++test_char) {
2836 std::string original_url("http://www.google.com/");
2837 original_url.push_back('%');
2838 original_url.append(base::HexEncode(&test_char, 1));
2840 GURL url(original_url);
2841 size_t prefix_len;
2842 base::string16 formatted = FormatUrl(url,
2843 std::string(),
2844 kFormatUrlOmitUsernamePassword,
2845 UnescapeRule::NORMAL,
2846 NULL,
2847 &prefix_len,
2848 NULL);
2849 EXPECT_EQ(url.spec(), GURL(formatted).spec());
2853 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
2854 // results in the original GURL, for each ASCII character in the query.
2855 TEST(NetUtilTest, FormatUrlRoundTripQueryASCII) {
2856 for (unsigned char test_char = 32; test_char < 128; ++test_char) {
2857 GURL url(std::string("http://www.google.com/?") +
2858 static_cast<char>(test_char));
2859 size_t prefix_len;
2860 base::string16 formatted = FormatUrl(url,
2861 std::string(),
2862 kFormatUrlOmitUsernamePassword,
2863 UnescapeRule::NORMAL,
2864 NULL,
2865 &prefix_len,
2866 NULL);
2867 EXPECT_EQ(url.spec(), GURL(formatted).spec());
2871 // Make sure that calling FormatUrl on a GURL and then converting back to a GURL
2872 // only results in a different GURL for certain characters.
2873 TEST(NetUtilTest, FormatUrlRoundTripQueryEscaped) {
2874 // A full list of characters which FormatURL should unescape and GURL should
2875 // not escape again, when they appear in a query string.
2876 const char* kUnescapedCharacters =
2877 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_~";
2878 for (unsigned char test_char = 0; test_char < 128; ++test_char) {
2879 std::string original_url("http://www.google.com/?");
2880 original_url.push_back('%');
2881 original_url.append(base::HexEncode(&test_char, 1));
2883 GURL url(original_url);
2884 size_t prefix_len;
2885 base::string16 formatted = FormatUrl(url,
2886 std::string(),
2887 kFormatUrlOmitUsernamePassword,
2888 UnescapeRule::NORMAL,
2889 NULL,
2890 &prefix_len,
2891 NULL);
2893 if (test_char &&
2894 strchr(kUnescapedCharacters, static_cast<char>(test_char))) {
2895 EXPECT_NE(url.spec(), GURL(formatted).spec());
2896 } else {
2897 EXPECT_EQ(url.spec(), GURL(formatted).spec());
2902 TEST(NetUtilTest, FormatUrlWithOffsets) {
2903 CheckAdjustedOffsets(std::string(), "en", kFormatUrlOmitNothing,
2904 UnescapeRule::NORMAL, NULL);
2906 const size_t basic_offsets[] = {
2907 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
2908 21, 22, 23, 24, 25
2910 CheckAdjustedOffsets("http://www.google.com/foo/", "en",
2911 kFormatUrlOmitNothing, UnescapeRule::NORMAL,
2912 basic_offsets);
2914 const size_t omit_auth_offsets_1[] = {
2915 0, 1, 2, 3, 4, 5, 6, 7, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 7,
2916 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
2918 CheckAdjustedOffsets("http://foo:bar@www.google.com/", "en",
2919 kFormatUrlOmitUsernamePassword, UnescapeRule::NORMAL,
2920 omit_auth_offsets_1);
2922 const size_t omit_auth_offsets_2[] = {
2923 0, 1, 2, 3, 4, 5, 6, 7, kNpos, kNpos, kNpos, 7, 8, 9, 10, 11, 12, 13, 14,
2924 15, 16, 17, 18, 19, 20, 21
2926 CheckAdjustedOffsets("http://foo@www.google.com/", "en",
2927 kFormatUrlOmitUsernamePassword, UnescapeRule::NORMAL,
2928 omit_auth_offsets_2);
2930 const size_t dont_omit_auth_offsets[] = {
2931 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos,
2932 kNpos, kNpos, 11, 12, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos,
2933 kNpos, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
2934 30, 31
2936 // Unescape to "http://foo\x30B0:\x30B0bar@www.google.com".
2937 CheckAdjustedOffsets("http://foo%E3%82%B0:%E3%82%B0bar@www.google.com/", "en",
2938 kFormatUrlOmitNothing, UnescapeRule::NORMAL,
2939 dont_omit_auth_offsets);
2941 const size_t view_source_offsets[] = {
2942 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, kNpos,
2943 kNpos, kNpos, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33
2945 CheckAdjustedOffsets("view-source:http://foo@www.google.com/", "en",
2946 kFormatUrlOmitUsernamePassword, UnescapeRule::NORMAL,
2947 view_source_offsets);
2949 const size_t idn_hostname_offsets_1[] = {
2950 0, 1, 2, 3, 4, 5, 6, 7, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos,
2951 kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 12,
2952 13, 14, 15, 16, 17, 18, 19
2954 // Convert punycode to "http://\x671d\x65e5\x3042\x3055\x3072.jp/foo/".
2955 CheckAdjustedOffsets("http://xn--l8jvb1ey91xtjb.jp/foo/", "ja",
2956 kFormatUrlOmitNothing, UnescapeRule::NORMAL,
2957 idn_hostname_offsets_1);
2959 const size_t idn_hostname_offsets_2[] = {
2960 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, kNpos, kNpos, kNpos, kNpos, kNpos,
2961 kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 14, 15, kNpos, kNpos, kNpos,
2962 kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos,
2963 kNpos, 19, 20, 21, 22, 23, 24
2965 // Convert punycode to
2966 // "http://test.\x89c6\x9891.\x5317\x4eac\x5927\x5b78.test/".
2967 CheckAdjustedOffsets("http://test.xn--cy2a840a.xn--1lq90ic7f1rc.test/",
2968 "zh-CN", kFormatUrlOmitNothing, UnescapeRule::NORMAL,
2969 idn_hostname_offsets_2);
2971 const size_t unescape_offsets[] = {
2972 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
2973 21, 22, 23, 24, 25, kNpos, kNpos, 26, 27, 28, 29, 30, kNpos, kNpos, kNpos,
2974 kNpos, kNpos, kNpos, kNpos, kNpos, 31, kNpos, kNpos, kNpos, kNpos, kNpos,
2975 kNpos, kNpos, kNpos, 32, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos,
2976 kNpos, 33, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos
2978 // Unescape to "http://www.google.com/foo bar/\x30B0\x30FC\x30B0\x30EB".
2979 CheckAdjustedOffsets(
2980 "http://www.google.com/foo%20bar/%E3%82%B0%E3%83%BC%E3%82%B0%E3%83%AB",
2981 "en", kFormatUrlOmitNothing, UnescapeRule::SPACES, unescape_offsets);
2983 const size_t ref_offsets[] = {
2984 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
2985 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, kNpos, kNpos, 32, kNpos, kNpos,
2988 // Unescape to "http://www.google.com/foo.html#\x30B0\x30B0z".
2989 CheckAdjustedOffsets(
2990 "http://www.google.com/foo.html#\xE3\x82\xB0\xE3\x82\xB0z", "en",
2991 kFormatUrlOmitNothing, UnescapeRule::NORMAL, ref_offsets);
2993 const size_t omit_http_offsets[] = {
2994 0, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
2995 10, 11, 12, 13, 14
2997 CheckAdjustedOffsets("http://www.google.com/", "en", kFormatUrlOmitHTTP,
2998 UnescapeRule::NORMAL, omit_http_offsets);
3000 const size_t omit_http_start_with_ftp_offsets[] = {
3001 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
3003 CheckAdjustedOffsets("http://ftp.google.com/", "en", kFormatUrlOmitHTTP,
3004 UnescapeRule::NORMAL, omit_http_start_with_ftp_offsets);
3006 const size_t omit_all_offsets[] = {
3007 0, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 0, kNpos, kNpos, kNpos, kNpos,
3008 0, 1, 2, 3, 4, 5, 6, 7
3010 CheckAdjustedOffsets("http://user@foo.com/", "en", kFormatUrlOmitAll,
3011 UnescapeRule::NORMAL, omit_all_offsets);
3014 TEST(NetUtilTest, SimplifyUrlForRequest) {
3015 struct {
3016 const char* input_url;
3017 const char* expected_simplified_url;
3018 } tests[] = {
3020 // Reference section should be stripped.
3021 "http://www.google.com:78/foobar?query=1#hash",
3022 "http://www.google.com:78/foobar?query=1",
3025 // Reference section can itself contain #.
3026 "http://192.168.0.1?query=1#hash#10#11#13#14",
3027 "http://192.168.0.1?query=1",
3029 { // Strip username/password.
3030 "http://user:pass@google.com",
3031 "http://google.com/",
3033 { // Strip both the reference and the username/password.
3034 "http://user:pass@google.com:80/sup?yo#X#X",
3035 "http://google.com/sup?yo",
3037 { // Try an HTTPS URL -- strip both the reference and the username/password.
3038 "https://user:pass@google.com:80/sup?yo#X#X",
3039 "https://google.com:80/sup?yo",
3041 { // Try an FTP URL -- strip both the reference and the username/password.
3042 "ftp://user:pass@google.com:80/sup?yo#X#X",
3043 "ftp://google.com:80/sup?yo",
3045 { // Try a nonstandard URL
3046 "foobar://user:pass@google.com:80/sup?yo#X#X",
3047 "foobar://user:pass@google.com:80/sup?yo",
3050 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3051 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s", i,
3052 tests[i].input_url));
3053 GURL input_url(GURL(tests[i].input_url));
3054 GURL expected_url(GURL(tests[i].expected_simplified_url));
3055 EXPECT_EQ(expected_url, SimplifyUrlForRequest(input_url));
3059 TEST(NetUtilTest, SetExplicitlyAllowedPortsTest) {
3060 std::string invalid[] = { "1,2,a", "'1','2'", "1, 2, 3", "1 0,11,12" };
3061 std::string valid[] = { "", "1", "1,2", "1,2,3", "10,11,12,13" };
3063 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(invalid); ++i) {
3064 SetExplicitlyAllowedPorts(invalid[i]);
3065 EXPECT_EQ(0, static_cast<int>(GetCountOfExplicitlyAllowedPorts()));
3068 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(valid); ++i) {
3069 SetExplicitlyAllowedPorts(valid[i]);
3070 EXPECT_EQ(i, GetCountOfExplicitlyAllowedPorts());
3074 TEST(NetUtilTest, GetHostOrSpecFromURL) {
3075 EXPECT_EQ("example.com",
3076 GetHostOrSpecFromURL(GURL("http://example.com/test")));
3077 EXPECT_EQ("example.com",
3078 GetHostOrSpecFromURL(GURL("http://example.com./test")));
3079 EXPECT_EQ("file:///tmp/test.html",
3080 GetHostOrSpecFromURL(GURL("file:///tmp/test.html")));
3083 TEST(NetUtilTest, GetAddressFamily) {
3084 IPAddressNumber number;
3085 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &number));
3086 EXPECT_EQ(ADDRESS_FAMILY_IPV4, GetAddressFamily(number));
3087 EXPECT_TRUE(ParseIPLiteralToNumber("1:abcd::3:4:ff", &number));
3088 EXPECT_EQ(ADDRESS_FAMILY_IPV6, GetAddressFamily(number));
3091 // Test that invalid IP literals fail to parse.
3092 TEST(NetUtilTest, ParseIPLiteralToNumber_FailParse) {
3093 IPAddressNumber number;
3095 EXPECT_FALSE(ParseIPLiteralToNumber("bad value", &number));
3096 EXPECT_FALSE(ParseIPLiteralToNumber("bad:value", &number));
3097 EXPECT_FALSE(ParseIPLiteralToNumber(std::string(), &number));
3098 EXPECT_FALSE(ParseIPLiteralToNumber("192.168.0.1:30", &number));
3099 EXPECT_FALSE(ParseIPLiteralToNumber(" 192.168.0.1 ", &number));
3100 EXPECT_FALSE(ParseIPLiteralToNumber("[::1]", &number));
3103 // Test parsing an IPv4 literal.
3104 TEST(NetUtilTest, ParseIPLiteralToNumber_IPv4) {
3105 IPAddressNumber number;
3106 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &number));
3107 EXPECT_EQ("192,168,0,1", DumpIPNumber(number));
3108 EXPECT_EQ("192.168.0.1", IPAddressToString(number));
3111 // Test parsing an IPv6 literal.
3112 TEST(NetUtilTest, ParseIPLiteralToNumber_IPv6) {
3113 IPAddressNumber number;
3114 EXPECT_TRUE(ParseIPLiteralToNumber("1:abcd::3:4:ff", &number));
3115 EXPECT_EQ("0,1,171,205,0,0,0,0,0,0,0,3,0,4,0,255", DumpIPNumber(number));
3116 EXPECT_EQ("1:abcd::3:4:ff", IPAddressToString(number));
3119 // Test mapping an IPv4 address to an IPv6 address.
3120 TEST(NetUtilTest, ConvertIPv4NumberToIPv6Number) {
3121 IPAddressNumber ipv4_number;
3122 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &ipv4_number));
3124 IPAddressNumber ipv6_number =
3125 ConvertIPv4NumberToIPv6Number(ipv4_number);
3127 // ::ffff:192.168.0.1
3128 EXPECT_EQ("0,0,0,0,0,0,0,0,0,0,255,255,192,168,0,1",
3129 DumpIPNumber(ipv6_number));
3130 EXPECT_EQ("::ffff:c0a8:1", IPAddressToString(ipv6_number));
3133 TEST(NetUtilTest, IsIPv4Mapped) {
3134 IPAddressNumber ipv4_number;
3135 EXPECT_TRUE(ParseIPLiteralToNumber("192.168.0.1", &ipv4_number));
3136 EXPECT_FALSE(IsIPv4Mapped(ipv4_number));
3138 IPAddressNumber ipv6_number;
3139 EXPECT_TRUE(ParseIPLiteralToNumber("::1", &ipv4_number));
3140 EXPECT_FALSE(IsIPv4Mapped(ipv6_number));
3142 IPAddressNumber ipv4mapped_number;
3143 EXPECT_TRUE(ParseIPLiteralToNumber("::ffff:0101:1", &ipv4mapped_number));
3144 EXPECT_TRUE(IsIPv4Mapped(ipv4mapped_number));
3147 TEST(NetUtilTest, ConvertIPv4MappedToIPv4) {
3148 IPAddressNumber ipv4mapped_number;
3149 EXPECT_TRUE(ParseIPLiteralToNumber("::ffff:0101:1", &ipv4mapped_number));
3150 IPAddressNumber expected;
3151 EXPECT_TRUE(ParseIPLiteralToNumber("1.1.0.1", &expected));
3152 IPAddressNumber result = ConvertIPv4MappedToIPv4(ipv4mapped_number);
3153 EXPECT_EQ(expected, result);
3156 // Test parsing invalid CIDR notation literals.
3157 TEST(NetUtilTest, ParseCIDRBlock_Invalid) {
3158 const char* bad_literals[] = {
3159 "foobar",
3161 "192.168.0.1",
3162 "::1",
3163 "/",
3164 "/1",
3165 "1",
3166 "192.168.1.1/-1",
3167 "192.168.1.1/33",
3168 "::1/-3",
3169 "a::3/129",
3170 "::1/x",
3171 "192.168.0.1//11"
3174 for (size_t i = 0; i < arraysize(bad_literals); ++i) {
3175 IPAddressNumber ip_number;
3176 size_t prefix_length_in_bits;
3178 EXPECT_FALSE(ParseCIDRBlock(bad_literals[i],
3179 &ip_number,
3180 &prefix_length_in_bits));
3184 // Test parsing a valid CIDR notation literal.
3185 TEST(NetUtilTest, ParseCIDRBlock_Valid) {
3186 IPAddressNumber ip_number;
3187 size_t prefix_length_in_bits;
3189 EXPECT_TRUE(ParseCIDRBlock("192.168.0.1/11",
3190 &ip_number,
3191 &prefix_length_in_bits));
3193 EXPECT_EQ("192,168,0,1", DumpIPNumber(ip_number));
3194 EXPECT_EQ(11u, prefix_length_in_bits);
3197 TEST(NetUtilTest, IPNumberMatchesPrefix) {
3198 struct {
3199 const char* cidr_literal;
3200 const char* ip_literal;
3201 bool expected_to_match;
3202 } tests[] = {
3203 // IPv4 prefix with IPv4 inputs.
3205 "10.10.1.32/27",
3206 "10.10.1.44",
3207 true
3210 "10.10.1.32/27",
3211 "10.10.1.90",
3212 false
3215 "10.10.1.32/27",
3216 "10.10.1.90",
3217 false
3220 // IPv6 prefix with IPv6 inputs.
3222 "2001:db8::/32",
3223 "2001:DB8:3:4::5",
3224 true
3227 "2001:db8::/32",
3228 "2001:c8::",
3229 false
3232 // IPv6 prefix with IPv4 inputs.
3234 "2001:db8::/33",
3235 "192.168.0.1",
3236 false
3239 "::ffff:192.168.0.1/112",
3240 "192.168.33.77",
3241 true
3244 // IPv4 prefix with IPv6 inputs.
3246 "10.11.33.44/16",
3247 "::ffff:0a0b:89",
3248 true
3251 "10.11.33.44/16",
3252 "::ffff:10.12.33.44",
3253 false
3256 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3257 SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s, %s", i,
3258 tests[i].cidr_literal,
3259 tests[i].ip_literal));
3261 IPAddressNumber ip_number;
3262 EXPECT_TRUE(ParseIPLiteralToNumber(tests[i].ip_literal, &ip_number));
3264 IPAddressNumber ip_prefix;
3265 size_t prefix_length_in_bits;
3267 EXPECT_TRUE(ParseCIDRBlock(tests[i].cidr_literal,
3268 &ip_prefix,
3269 &prefix_length_in_bits));
3271 EXPECT_EQ(tests[i].expected_to_match,
3272 IPNumberMatchesPrefix(ip_number,
3273 ip_prefix,
3274 prefix_length_in_bits));
3278 TEST(NetUtilTest, IsLocalhost) {
3279 EXPECT_TRUE(net::IsLocalhost("localhost"));
3280 EXPECT_TRUE(net::IsLocalhost("localhost.localdomain"));
3281 EXPECT_TRUE(net::IsLocalhost("localhost6"));
3282 EXPECT_TRUE(net::IsLocalhost("localhost6.localdomain6"));
3283 EXPECT_TRUE(net::IsLocalhost("127.0.0.1"));
3284 EXPECT_TRUE(net::IsLocalhost("127.0.1.0"));
3285 EXPECT_TRUE(net::IsLocalhost("127.1.0.0"));
3286 EXPECT_TRUE(net::IsLocalhost("127.0.0.255"));
3287 EXPECT_TRUE(net::IsLocalhost("127.0.255.0"));
3288 EXPECT_TRUE(net::IsLocalhost("127.255.0.0"));
3289 EXPECT_TRUE(net::IsLocalhost("::1"));
3290 EXPECT_TRUE(net::IsLocalhost("0:0:0:0:0:0:0:1"));
3292 EXPECT_FALSE(net::IsLocalhost("localhostx"));
3293 EXPECT_FALSE(net::IsLocalhost("foo.localdomain"));
3294 EXPECT_FALSE(net::IsLocalhost("localhost6x"));
3295 EXPECT_FALSE(net::IsLocalhost("localhost.localdomain6"));
3296 EXPECT_FALSE(net::IsLocalhost("localhost6.localdomain"));
3297 EXPECT_FALSE(net::IsLocalhost("127.0.0.1.1"));
3298 EXPECT_FALSE(net::IsLocalhost(".127.0.0.255"));
3299 EXPECT_FALSE(net::IsLocalhost("::2"));
3300 EXPECT_FALSE(net::IsLocalhost("::1:1"));
3301 EXPECT_FALSE(net::IsLocalhost("0:0:0:0:1:0:0:1"));
3302 EXPECT_FALSE(net::IsLocalhost("::1:1"));
3303 EXPECT_FALSE(net::IsLocalhost("0:0:0:0:0:0:0:0:1"));
3306 // Verify GetNetworkList().
3307 TEST(NetUtilTest, GetNetworkList) {
3308 NetworkInterfaceList list;
3309 ASSERT_TRUE(GetNetworkList(&list, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES));
3310 for (NetworkInterfaceList::iterator it = list.begin();
3311 it != list.end(); ++it) {
3312 // Verify that the names are not empty.
3313 EXPECT_FALSE(it->name.empty());
3314 EXPECT_FALSE(it->friendly_name.empty());
3316 // Verify that the address is correct.
3317 EXPECT_TRUE(it->address.size() == kIPv4AddressSize ||
3318 it->address.size() == kIPv6AddressSize)
3319 << "Invalid address of size " << it->address.size();
3320 bool all_zeroes = true;
3321 for (size_t i = 0; i < it->address.size(); ++i) {
3322 if (it->address[i] != 0) {
3323 all_zeroes = false;
3324 break;
3327 EXPECT_FALSE(all_zeroes);
3328 EXPECT_GT(it->network_prefix, 1u);
3329 EXPECT_LE(it->network_prefix, it->address.size() * 8);
3331 #if defined(OS_WIN)
3332 // On Windows |name| is NET_LUID.
3333 base::ScopedNativeLibrary phlpapi_lib(
3334 base::FilePath(FILE_PATH_LITERAL("iphlpapi.dll")));
3335 ASSERT_TRUE(phlpapi_lib.is_valid());
3336 typedef NETIO_STATUS (WINAPI* ConvertInterfaceIndexToLuid)(NET_IFINDEX,
3337 PNET_LUID);
3338 ConvertInterfaceIndexToLuid interface_to_luid =
3339 reinterpret_cast<ConvertInterfaceIndexToLuid>(
3340 phlpapi_lib.GetFunctionPointer("ConvertInterfaceIndexToLuid"));
3342 typedef NETIO_STATUS (WINAPI* ConvertInterfaceLuidToGuid)(NET_LUID*,
3343 GUID*);
3344 ConvertInterfaceLuidToGuid luid_to_guid =
3345 reinterpret_cast<ConvertInterfaceLuidToGuid>(
3346 phlpapi_lib.GetFunctionPointer("ConvertInterfaceLuidToGuid"));
3348 if (interface_to_luid && luid_to_guid) {
3349 NET_LUID luid;
3350 EXPECT_EQ(interface_to_luid(it->interface_index, &luid), NO_ERROR);
3351 GUID guid;
3352 EXPECT_EQ(luid_to_guid(&luid, &guid), NO_ERROR);
3353 LPOLESTR name;
3354 StringFromCLSID(guid, &name);
3355 EXPECT_STREQ(base::UTF8ToWide(it->name).c_str(), name);
3356 CoTaskMemFree(name);
3357 continue;
3358 } else {
3359 EXPECT_LT(base::win::GetVersion(), base::win::VERSION_VISTA);
3360 EXPECT_LT(it->interface_index, 1u << 24u); // Must fit 0.x.x.x.
3361 EXPECT_NE(it->interface_index, 0u); // 0 means to use default.
3363 #elif !defined(OS_ANDROID)
3364 char name[IF_NAMESIZE];
3365 EXPECT_TRUE(if_indextoname(it->interface_index, name));
3366 EXPECT_STREQ(it->name.c_str(), name);
3367 #endif
3371 static const base::FilePath::CharType* kSafePortableBasenames[] = {
3372 FILE_PATH_LITERAL("a"),
3373 FILE_PATH_LITERAL("a.txt"),
3374 FILE_PATH_LITERAL("a b.txt"),
3375 FILE_PATH_LITERAL("a-b.txt"),
3376 FILE_PATH_LITERAL("My Computer"),
3377 FILE_PATH_LITERAL(" Computer"),
3380 static const base::FilePath::CharType* kUnsafePortableBasenames[] = {
3381 FILE_PATH_LITERAL(""),
3382 FILE_PATH_LITERAL("."),
3383 FILE_PATH_LITERAL(".."),
3384 FILE_PATH_LITERAL("..."),
3385 FILE_PATH_LITERAL("con"),
3386 FILE_PATH_LITERAL("con.zip"),
3387 FILE_PATH_LITERAL("NUL"),
3388 FILE_PATH_LITERAL("NUL.zip"),
3389 FILE_PATH_LITERAL(".a"),
3390 FILE_PATH_LITERAL("a."),
3391 FILE_PATH_LITERAL("a\"a"),
3392 FILE_PATH_LITERAL("a<a"),
3393 FILE_PATH_LITERAL("a>a"),
3394 FILE_PATH_LITERAL("a?a"),
3395 FILE_PATH_LITERAL("a/"),
3396 FILE_PATH_LITERAL("a\\"),
3397 FILE_PATH_LITERAL("a "),
3398 FILE_PATH_LITERAL("a . ."),
3399 FILE_PATH_LITERAL("My Computer.{a}"),
3400 FILE_PATH_LITERAL("My Computer.{20D04FE0-3AEA-1069-A2D8-08002B30309D}"),
3401 #if !defined(OS_WIN)
3402 FILE_PATH_LITERAL("a\\a"),
3403 #endif
3406 static const base::FilePath::CharType* kSafePortableRelativePaths[] = {
3407 FILE_PATH_LITERAL("a/a"),
3408 #if defined(OS_WIN)
3409 FILE_PATH_LITERAL("a\\a"),
3410 #endif
3413 TEST(NetUtilTest, IsSafePortablePathComponent) {
3414 for (size_t i = 0 ; i < arraysize(kSafePortableBasenames); ++i) {
3415 EXPECT_TRUE(IsSafePortablePathComponent(base::FilePath(
3416 kSafePortableBasenames[i]))) << kSafePortableBasenames[i];
3418 for (size_t i = 0 ; i < arraysize(kUnsafePortableBasenames); ++i) {
3419 EXPECT_FALSE(IsSafePortablePathComponent(base::FilePath(
3420 kUnsafePortableBasenames[i]))) << kUnsafePortableBasenames[i];
3422 for (size_t i = 0 ; i < arraysize(kSafePortableRelativePaths); ++i) {
3423 EXPECT_FALSE(IsSafePortablePathComponent(base::FilePath(
3424 kSafePortableRelativePaths[i]))) << kSafePortableRelativePaths[i];
3428 TEST(NetUtilTest, IsSafePortableRelativePath) {
3429 base::FilePath safe_dirname(FILE_PATH_LITERAL("a"));
3430 for (size_t i = 0 ; i < arraysize(kSafePortableBasenames); ++i) {
3431 EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath(
3432 kSafePortableBasenames[i]))) << kSafePortableBasenames[i];
3433 EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname.Append(base::FilePath(
3434 kSafePortableBasenames[i])))) << kSafePortableBasenames[i];
3436 for (size_t i = 0 ; i < arraysize(kSafePortableRelativePaths); ++i) {
3437 EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath(
3438 kSafePortableRelativePaths[i]))) << kSafePortableRelativePaths[i];
3439 EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname.Append(base::FilePath(
3440 kSafePortableRelativePaths[i])))) << kSafePortableRelativePaths[i];
3442 for (size_t i = 0 ; i < arraysize(kUnsafePortableBasenames); ++i) {
3443 EXPECT_FALSE(IsSafePortableRelativePath(base::FilePath(
3444 kUnsafePortableBasenames[i]))) << kUnsafePortableBasenames[i];
3445 if (!base::FilePath::StringType(kUnsafePortableBasenames[i]).empty()) {
3446 EXPECT_FALSE(IsSafePortableRelativePath(safe_dirname.Append(
3447 base::FilePath(kUnsafePortableBasenames[i]))))
3448 << kUnsafePortableBasenames[i];
3453 struct NonUniqueNameTestData {
3454 bool is_unique;
3455 const char* hostname;
3458 // Google Test pretty-printer.
3459 void PrintTo(const NonUniqueNameTestData& data, std::ostream* os) {
3460 ASSERT_TRUE(data.hostname);
3461 *os << " hostname: " << testing::PrintToString(data.hostname)
3462 << "; is_unique: " << testing::PrintToString(data.is_unique);
3465 const NonUniqueNameTestData kNonUniqueNameTestData[] = {
3466 // Domains under ICANN-assigned domains.
3467 { true, "google.com" },
3468 { true, "google.co.uk" },
3469 // Domains under private registries.
3470 { true, "appspot.com" },
3471 { true, "test.appspot.com" },
3472 // Unreserved IPv4 addresses (in various forms).
3473 { true, "8.8.8.8" },
3474 { true, "99.64.0.0" },
3475 { true, "212.15.0.0" },
3476 { true, "212.15" },
3477 { true, "212.15.0" },
3478 { true, "3557752832" },
3479 // Reserved IPv4 addresses (in various forms).
3480 { false, "192.168.0.0" },
3481 { false, "192.168.0.6" },
3482 { false, "10.0.0.5" },
3483 { false, "10.0" },
3484 { false, "10.0.0" },
3485 { false, "3232235526" },
3486 // Unreserved IPv6 addresses.
3487 { true, "FFC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
3488 { true, "2000:ba98:7654:2301:EFCD:BA98:7654:3210" },
3489 // Reserved IPv6 addresses.
3490 { false, "::192.9.5.5" },
3491 { false, "FEED::BEEF" },
3492 { false, "FEC0:ba98:7654:3210:FEDC:BA98:7654:3210" },
3493 // 'internal'/non-IANA assigned domains.
3494 { false, "intranet" },
3495 { false, "intranet." },
3496 { false, "intranet.example" },
3497 { false, "host.intranet.example" },
3498 // gTLDs under discussion, but not yet assigned.
3499 { false, "intranet.corp" },
3500 { false, "example.tech" },
3501 { false, "intranet.internal" },
3502 // Invalid host names are treated as unique - but expected to be
3503 // filtered out before then.
3504 { true, "junk)(£)$*!@~#" },
3505 { true, "w$w.example.com" },
3506 { true, "nocolonsallowed:example" },
3507 { true, "[::4.5.6.9]" },
3510 class NetUtilNonUniqueNameTest
3511 : public testing::TestWithParam<NonUniqueNameTestData> {
3512 public:
3513 virtual ~NetUtilNonUniqueNameTest() {}
3515 protected:
3516 bool IsUnique(const std::string& hostname) {
3517 return !IsHostnameNonUnique(hostname);
3521 // Test that internal/non-unique names are properly identified as such, but
3522 // that IP addresses and hosts beneath registry-controlled domains are flagged
3523 // as unique names.
3524 TEST_P(NetUtilNonUniqueNameTest, IsHostnameNonUnique) {
3525 const NonUniqueNameTestData& test_data = GetParam();
3527 EXPECT_EQ(test_data.is_unique, IsUnique(test_data.hostname));
3530 INSTANTIATE_TEST_CASE_P(, NetUtilNonUniqueNameTest,
3531 testing::ValuesIn(kNonUniqueNameTestData));
3533 } // namespace net