Home | History | Annotate | Download | only in base
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/base/filename_util.h"
      6 
      7 #include "base/file_util.h"
      8 #include "base/files/file_path.h"
      9 #include "base/strings/string_util.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "base/test/test_file_util.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 #include "url/gurl.h"
     14 
     15 namespace net {
     16 
     17 namespace {
     18 
     19 struct FileCase {
     20   const wchar_t* file;
     21   const char* url;
     22 };
     23 
     24 struct GenerateFilenameCase {
     25   int lineno;
     26   const char* url;
     27   const char* content_disp_header;
     28   const char* referrer_charset;
     29   const char* suggested_filename;
     30   const char* mime_type;
     31   const wchar_t* default_filename;
     32   const wchar_t* expected_filename;
     33 };
     34 
     35 void RunGenerateFileNameTestCase(const GenerateFilenameCase* test_case) {
     36   std::string default_filename(base::WideToUTF8(test_case->default_filename));
     37   base::FilePath file_path = GenerateFileName(
     38       GURL(test_case->url), test_case->content_disp_header,
     39       test_case->referrer_charset, test_case->suggested_filename,
     40       test_case->mime_type, default_filename);
     41   EXPECT_EQ(test_case->expected_filename,
     42             file_util::FilePathAsWString(file_path))
     43       << "test case at line number: " << test_case->lineno;
     44 }
     45 
     46 }  // namespace
     47 
     48 static const base::FilePath::CharType* kSafePortableBasenames[] = {
     49   FILE_PATH_LITERAL("a"),
     50   FILE_PATH_LITERAL("a.txt"),
     51   FILE_PATH_LITERAL("a b.txt"),
     52   FILE_PATH_LITERAL("a-b.txt"),
     53   FILE_PATH_LITERAL("My Computer"),
     54   FILE_PATH_LITERAL(" Computer"),
     55 };
     56 
     57 static const base::FilePath::CharType* kUnsafePortableBasenames[] = {
     58   FILE_PATH_LITERAL(""),
     59   FILE_PATH_LITERAL("."),
     60   FILE_PATH_LITERAL(".."),
     61   FILE_PATH_LITERAL("..."),
     62   FILE_PATH_LITERAL("con"),
     63   FILE_PATH_LITERAL("con.zip"),
     64   FILE_PATH_LITERAL("NUL"),
     65   FILE_PATH_LITERAL("NUL.zip"),
     66   FILE_PATH_LITERAL(".a"),
     67   FILE_PATH_LITERAL("a."),
     68   FILE_PATH_LITERAL("a\"a"),
     69   FILE_PATH_LITERAL("a<a"),
     70   FILE_PATH_LITERAL("a>a"),
     71   FILE_PATH_LITERAL("a?a"),
     72   FILE_PATH_LITERAL("a/"),
     73   FILE_PATH_LITERAL("a\\"),
     74   FILE_PATH_LITERAL("a "),
     75   FILE_PATH_LITERAL("a . ."),
     76   FILE_PATH_LITERAL("My Computer.{a}"),
     77   FILE_PATH_LITERAL("My Computer.{20D04FE0-3AEA-1069-A2D8-08002B30309D}"),
     78 #if !defined(OS_WIN)
     79   FILE_PATH_LITERAL("a\\a"),
     80 #endif
     81 };
     82 
     83 static const base::FilePath::CharType* kSafePortableRelativePaths[] = {
     84   FILE_PATH_LITERAL("a/a"),
     85 #if defined(OS_WIN)
     86   FILE_PATH_LITERAL("a\\a"),
     87 #endif
     88 };
     89 
     90 TEST(FilenameUtilTest, IsSafePortablePathComponent) {
     91   for (size_t i = 0 ; i < arraysize(kSafePortableBasenames); ++i) {
     92     EXPECT_TRUE(IsSafePortablePathComponent(base::FilePath(
     93         kSafePortableBasenames[i]))) << kSafePortableBasenames[i];
     94   }
     95   for (size_t i = 0 ; i < arraysize(kUnsafePortableBasenames); ++i) {
     96     EXPECT_FALSE(IsSafePortablePathComponent(base::FilePath(
     97         kUnsafePortableBasenames[i]))) << kUnsafePortableBasenames[i];
     98   }
     99   for (size_t i = 0 ; i < arraysize(kSafePortableRelativePaths); ++i) {
    100     EXPECT_FALSE(IsSafePortablePathComponent(base::FilePath(
    101         kSafePortableRelativePaths[i]))) << kSafePortableRelativePaths[i];
    102   }
    103 }
    104 
    105 TEST(FilenameUtilTest, IsSafePortableRelativePath) {
    106   base::FilePath safe_dirname(FILE_PATH_LITERAL("a"));
    107   for (size_t i = 0 ; i < arraysize(kSafePortableBasenames); ++i) {
    108     EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath(
    109         kSafePortableBasenames[i]))) << kSafePortableBasenames[i];
    110     EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname.Append(base::FilePath(
    111         kSafePortableBasenames[i])))) << kSafePortableBasenames[i];
    112   }
    113   for (size_t i = 0 ; i < arraysize(kSafePortableRelativePaths); ++i) {
    114     EXPECT_TRUE(IsSafePortableRelativePath(base::FilePath(
    115         kSafePortableRelativePaths[i]))) << kSafePortableRelativePaths[i];
    116     EXPECT_TRUE(IsSafePortableRelativePath(safe_dirname.Append(base::FilePath(
    117         kSafePortableRelativePaths[i])))) << kSafePortableRelativePaths[i];
    118   }
    119   for (size_t i = 0 ; i < arraysize(kUnsafePortableBasenames); ++i) {
    120     EXPECT_FALSE(IsSafePortableRelativePath(base::FilePath(
    121         kUnsafePortableBasenames[i]))) << kUnsafePortableBasenames[i];
    122     if (!base::FilePath::StringType(kUnsafePortableBasenames[i]).empty()) {
    123       EXPECT_FALSE(IsSafePortableRelativePath(safe_dirname.Append(
    124           base::FilePath(kUnsafePortableBasenames[i]))))
    125         << kUnsafePortableBasenames[i];
    126     }
    127   }
    128 }
    129 
    130 TEST(FilenameUtilTest, FileURLConversion) {
    131   // a list of test file names and the corresponding URLs
    132   const FileCase round_trip_cases[] = {
    133 #if defined(OS_WIN)
    134     {L"C:\\foo\\bar.txt", "file:///C:/foo/bar.txt"},
    135     {L"\\\\some computer\\foo\\bar.txt",
    136      "file://some%20computer/foo/bar.txt"}, // UNC
    137     {L"D:\\Name;with%some symbols*#",
    138      "file:///D:/Name%3Bwith%25some%20symbols*%23"},
    139     // issue 14153: To be tested with the OS default codepage other than 1252.
    140     {L"D:\\latin1\\caf\x00E9\x00DD.txt",
    141      "file:///D:/latin1/caf%C3%A9%C3%9D.txt"},
    142     {L"D:\\otherlatin\\caf\x0119.txt",
    143      "file:///D:/otherlatin/caf%C4%99.txt"},
    144     {L"D:\\greek\\\x03B1\x03B2\x03B3.txt",
    145      "file:///D:/greek/%CE%B1%CE%B2%CE%B3.txt"},
    146     {L"D:\\Chinese\\\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc",
    147      "file:///D:/Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD%91"
    148          "%E9%A1%B5.doc"},
    149     {L"D:\\plane1\\\xD835\xDC00\xD835\xDC01.txt",  // Math alphabet "AB"
    150      "file:///D:/plane1/%F0%9D%90%80%F0%9D%90%81.txt"},
    151 #elif defined(OS_POSIX)
    152     {L"/foo/bar.txt", "file:///foo/bar.txt"},
    153     {L"/foo/BAR.txt", "file:///foo/BAR.txt"},
    154     {L"/C:/foo/bar.txt", "file:///C:/foo/bar.txt"},
    155     {L"/foo/bar?.txt", "file:///foo/bar%3F.txt"},
    156     {L"/some computer/foo/bar.txt", "file:///some%20computer/foo/bar.txt"},
    157     {L"/Name;with%some symbols*#", "file:///Name%3Bwith%25some%20symbols*%23"},
    158     {L"/latin1/caf\x00E9\x00DD.txt", "file:///latin1/caf%C3%A9%C3%9D.txt"},
    159     {L"/otherlatin/caf\x0119.txt", "file:///otherlatin/caf%C4%99.txt"},
    160     {L"/greek/\x03B1\x03B2\x03B3.txt", "file:///greek/%CE%B1%CE%B2%CE%B3.txt"},
    161     {L"/Chinese/\x6240\x6709\x4e2d\x6587\x7f51\x9875.doc",
    162      "file:///Chinese/%E6%89%80%E6%9C%89%E4%B8%AD%E6%96%87%E7%BD"
    163          "%91%E9%A1%B5.doc"},
    164     {L"/plane1/\x1D400\x1D401.txt",  // Math alphabet "AB"
    165      "file:///plane1/%F0%9D%90%80%F0%9D%90%81.txt"},
    166 #endif
    167   };
    168 
    169   // First, we'll test that we can round-trip all of the above cases of URLs
    170   base::FilePath output;
    171   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(round_trip_cases); i++) {
    172     // convert to the file URL
    173     GURL file_url(FilePathToFileURL(
    174                       file_util::WStringAsFilePath(round_trip_cases[i].file)));
    175     EXPECT_EQ(round_trip_cases[i].url, file_url.spec());
    176 
    177     // Back to the filename.
    178     EXPECT_TRUE(FileURLToFilePath(file_url, &output));
    179     EXPECT_EQ(round_trip_cases[i].file, file_util::FilePathAsWString(output));
    180   }
    181 
    182   // Test that various file: URLs get decoded into the correct file type
    183   FileCase url_cases[] = {
    184 #if defined(OS_WIN)
    185     {L"C:\\foo\\bar.txt", "file:c|/foo\\bar.txt"},
    186     {L"C:\\foo\\bar.txt", "file:/c:/foo/bar.txt"},
    187     {L"\\\\foo\\bar.txt", "file://foo\\bar.txt"},
    188     {L"C:\\foo\\bar.txt", "file:///c:/foo/bar.txt"},
    189     {L"\\\\foo\\bar.txt", "file:////foo\\bar.txt"},
    190     {L"\\\\foo\\bar.txt", "file:/foo/bar.txt"},
    191     {L"\\\\foo\\bar.txt", "file://foo\\bar.txt"},
    192     {L"C:\\foo\\bar.txt", "file:\\\\\\c:/foo/bar.txt"},
    193 #elif defined(OS_POSIX)
    194     {L"/c:/foo/bar.txt", "file:/c:/foo/bar.txt"},
    195     {L"/c:/foo/bar.txt", "file:///c:/foo/bar.txt"},
    196     {L"/foo/bar.txt", "file:/foo/bar.txt"},
    197     {L"/c:/foo/bar.txt", "file:\\\\\\c:/foo/bar.txt"},
    198     {L"/foo/bar.txt", "file:foo/bar.txt"},
    199     {L"/bar.txt", "file://foo/bar.txt"},
    200     {L"/foo/bar.txt", "file:///foo/bar.txt"},
    201     {L"/foo/bar.txt", "file:////foo/bar.txt"},
    202     {L"/foo/bar.txt", "file:////foo//bar.txt"},
    203     {L"/foo/bar.txt", "file:////foo///bar.txt"},
    204     {L"/foo/bar.txt", "file:////foo////bar.txt"},
    205     {L"/c:/foo/bar.txt", "file:\\\\\\c:/foo/bar.txt"},
    206     {L"/c:/foo/bar.txt", "file:c:/foo/bar.txt"},
    207     // We get these wrong because GURL turns back slashes into forward
    208     // slashes.
    209     //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
    210     //{L"/c|/foo%5Cbar.txt", "file:c|/foo\\bar.txt"},
    211     //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
    212     //{L"/foo%5Cbar.txt", "file:////foo\\bar.txt"},
    213     //{L"/foo%5Cbar.txt", "file://foo\\bar.txt"},
    214 #endif
    215   };
    216   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(url_cases); i++) {
    217     FileURLToFilePath(GURL(url_cases[i].url), &output);
    218     EXPECT_EQ(url_cases[i].file, file_util::FilePathAsWString(output));
    219   }
    220 
    221   // Unfortunately, UTF8ToWide discards invalid UTF8 input.
    222 #ifdef BUG_878908_IS_FIXED
    223   // Test that no conversion happens if the UTF-8 input is invalid, and that
    224   // the input is preserved in UTF-8
    225   const char invalid_utf8[] = "file:///d:/Blah/\xff.doc";
    226   const wchar_t invalid_wide[] = L"D:\\Blah\\\xff.doc";
    227   EXPECT_TRUE(FileURLToFilePath(
    228       GURL(std::string(invalid_utf8)), &output));
    229   EXPECT_EQ(std::wstring(invalid_wide), output);
    230 #endif
    231 
    232   // Test that if a file URL is malformed, we get a failure
    233   EXPECT_FALSE(FileURLToFilePath(GURL("filefoobar"), &output));
    234 }
    235 
    236 #if defined(OS_WIN)
    237 #define JPEG_EXT L".jpg"
    238 #define HTML_EXT L".htm"
    239 #elif defined(OS_MACOSX)
    240 #define JPEG_EXT L".jpeg"
    241 #define HTML_EXT L".html"
    242 #else
    243 #define JPEG_EXT L".jpg"
    244 #define HTML_EXT L".html"
    245 #endif
    246 #define TXT_EXT L".txt"
    247 #define TAR_EXT L".tar"
    248 
    249 TEST(FilenameUtilTest, GenerateSafeFileName) {
    250   const struct {
    251     const char* mime_type;
    252     const base::FilePath::CharType* filename;
    253     const base::FilePath::CharType* expected_filename;
    254   } safe_tests[] = {
    255 #if defined(OS_WIN)
    256     {
    257       "text/html",
    258       FILE_PATH_LITERAL("C:\\foo\\bar.htm"),
    259       FILE_PATH_LITERAL("C:\\foo\\bar.htm")
    260     },
    261     {
    262       "text/html",
    263       FILE_PATH_LITERAL("C:\\foo\\bar.html"),
    264       FILE_PATH_LITERAL("C:\\foo\\bar.html")
    265     },
    266     {
    267       "text/html",
    268       FILE_PATH_LITERAL("C:\\foo\\bar"),
    269       FILE_PATH_LITERAL("C:\\foo\\bar.htm")
    270     },
    271     {
    272       "image/png",
    273       FILE_PATH_LITERAL("C:\\bar.html"),
    274       FILE_PATH_LITERAL("C:\\bar.html")
    275     },
    276     {
    277       "image/png",
    278       FILE_PATH_LITERAL("C:\\bar"),
    279       FILE_PATH_LITERAL("C:\\bar.png")
    280     },
    281     {
    282       "text/html",
    283       FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
    284       FILE_PATH_LITERAL("C:\\foo\\bar.exe")
    285     },
    286     {
    287       "image/gif",
    288       FILE_PATH_LITERAL("C:\\foo\\bar.exe"),
    289       FILE_PATH_LITERAL("C:\\foo\\bar.exe")
    290     },
    291     {
    292       "text/html",
    293       FILE_PATH_LITERAL("C:\\foo\\google.com"),
    294       FILE_PATH_LITERAL("C:\\foo\\google.com")
    295     },
    296     {
    297       "text/html",
    298       FILE_PATH_LITERAL("C:\\foo\\con.htm"),
    299       FILE_PATH_LITERAL("C:\\foo\\_con.htm")
    300     },
    301     {
    302       "text/html",
    303       FILE_PATH_LITERAL("C:\\foo\\con"),
    304       FILE_PATH_LITERAL("C:\\foo\\_con.htm")
    305     },
    306     {
    307       "text/html",
    308       FILE_PATH_LITERAL("C:\\foo\\harmless.{not-really-this-may-be-a-guid}"),
    309       FILE_PATH_LITERAL("C:\\foo\\harmless.download")
    310     },
    311     {
    312       "text/html",
    313       FILE_PATH_LITERAL("C:\\foo\\harmless.local"),
    314       FILE_PATH_LITERAL("C:\\foo\\harmless.download")
    315     },
    316     {
    317       "text/html",
    318       FILE_PATH_LITERAL("C:\\foo\\harmless.lnk"),
    319       FILE_PATH_LITERAL("C:\\foo\\harmless.download")
    320     },
    321     {
    322       "text/html",
    323       FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-"),
    324       FILE_PATH_LITERAL("C:\\foo\\harmless.{mismatched-")
    325     },
    326     // Allow extension synonyms.
    327     {
    328       "image/jpeg",
    329       FILE_PATH_LITERAL("C:\\foo\\bar.jpg"),
    330       FILE_PATH_LITERAL("C:\\foo\\bar.jpg")
    331     },
    332     {
    333       "image/jpeg",
    334       FILE_PATH_LITERAL("C:\\foo\\bar.jpeg"),
    335       FILE_PATH_LITERAL("C:\\foo\\bar.jpeg")
    336     },
    337 #else  // !defined(OS_WIN)
    338     {
    339       "text/html",
    340       FILE_PATH_LITERAL("/foo/bar.htm"),
    341       FILE_PATH_LITERAL("/foo/bar.htm")
    342     },
    343     {
    344       "text/html",
    345       FILE_PATH_LITERAL("/foo/bar.html"),
    346       FILE_PATH_LITERAL("/foo/bar.html")
    347     },
    348     {
    349       "text/html",
    350       FILE_PATH_LITERAL("/foo/bar"),
    351       FILE_PATH_LITERAL("/foo/bar.html")
    352     },
    353     {
    354       "image/png",
    355       FILE_PATH_LITERAL("/bar.html"),
    356       FILE_PATH_LITERAL("/bar.html")
    357     },
    358     {
    359       "image/png",
    360       FILE_PATH_LITERAL("/bar"),
    361       FILE_PATH_LITERAL("/bar.png")
    362     },
    363     {
    364       "image/gif",
    365       FILE_PATH_LITERAL("/foo/bar.exe"),
    366       FILE_PATH_LITERAL("/foo/bar.exe")
    367     },
    368     {
    369       "text/html",
    370       FILE_PATH_LITERAL("/foo/google.com"),
    371       FILE_PATH_LITERAL("/foo/google.com")
    372     },
    373     {
    374       "text/html",
    375       FILE_PATH_LITERAL("/foo/con.htm"),
    376       FILE_PATH_LITERAL("/foo/con.htm")
    377     },
    378     {
    379       "text/html",
    380       FILE_PATH_LITERAL("/foo/con"),
    381       FILE_PATH_LITERAL("/foo/con.html")
    382     },
    383     // Allow extension synonyms.
    384     {
    385       "image/jpeg",
    386       FILE_PATH_LITERAL("/bar.jpg"),
    387       FILE_PATH_LITERAL("/bar.jpg")
    388     },
    389     {
    390       "image/jpeg",
    391       FILE_PATH_LITERAL("/bar.jpeg"),
    392       FILE_PATH_LITERAL("/bar.jpeg")
    393     },
    394 #endif  // !defined(OS_WIN)
    395   };
    396 
    397   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(safe_tests); ++i) {
    398     base::FilePath file_path(safe_tests[i].filename);
    399     GenerateSafeFileName(safe_tests[i].mime_type, false, &file_path);
    400     EXPECT_EQ(safe_tests[i].expected_filename, file_path.value())
    401         << "Iteration " << i;
    402   }
    403 }
    404 
    405 TEST(FilenameUtilTest, GenerateFileName) {
    406 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
    407   // This test doesn't run when the locale is not UTF-8 because some of the
    408   // string conversions fail. This is OK (we have the default value) but they
    409   // don't match our expectations.
    410   std::string locale = setlocale(LC_CTYPE, NULL);
    411   StringToLowerASCII(&locale);
    412   EXPECT_TRUE(locale.find("utf-8") != std::string::npos ||
    413               locale.find("utf8") != std::string::npos)
    414       << "Your locale (" << locale << ") must be set to UTF-8 "
    415       << "for this test to pass!";
    416 #endif
    417 
    418   // Tests whether the correct filename is selected from the the given
    419   // parameters and that Content-Disposition headers are properly
    420   // handled including failovers when the header is malformed.
    421   const GenerateFilenameCase selection_tests[] = {
    422     {
    423       __LINE__,
    424       "http://www.google.com/",
    425       "attachment; filename=test.html",
    426       "",
    427       "",
    428       "",
    429       L"",
    430       L"test.html"
    431     },
    432     {
    433       __LINE__,
    434       "http://www.google.com/",
    435       "attachment; filename=\"test.html\"",
    436       "",
    437       "",
    438       "",
    439       L"",
    440       L"test.html"
    441     },
    442     {
    443       __LINE__,
    444       "http://www.google.com/",
    445       "attachment; filename= \"test.html\"",
    446       "",
    447       "",
    448       "",
    449       L"",
    450       L"test.html"
    451     },
    452     {
    453       __LINE__,
    454       "http://www.google.com/",
    455       "attachment; filename   =   \"test.html\"",
    456       "",
    457       "",
    458       "",
    459       L"",
    460       L"test.html"
    461     },
    462     { // filename is whitespace.  Should failover to URL host
    463       __LINE__,
    464       "http://www.google.com/",
    465       "attachment; filename=  ",
    466       "",
    467       "",
    468       "",
    469       L"",
    470       L"www.google.com"
    471     },
    472     { // No filename.
    473       __LINE__,
    474       "http://www.google.com/path/test.html",
    475       "attachment",
    476       "",
    477       "",
    478       "",
    479       L"",
    480       L"test.html"
    481     },
    482     { // Ditto
    483       __LINE__,
    484       "http://www.google.com/path/test.html",
    485       "attachment;",
    486       "",
    487       "",
    488       "",
    489       L"",
    490       L"test.html"
    491     },
    492     { // No C-D
    493       __LINE__,
    494       "http://www.google.com/",
    495       "",
    496       "",
    497       "",
    498       "",
    499       L"",
    500       L"www.google.com"
    501     },
    502     {
    503       __LINE__,
    504       "http://www.google.com/test.html",
    505       "",
    506       "",
    507       "",
    508       "",
    509       L"",
    510       L"test.html"
    511     },
    512     { // Now that we use src/url's ExtractFileName, this case falls back to
    513       // the hostname. If this behavior is not desirable, we'd better change
    514       // ExtractFileName (in url_parse.cc).
    515       __LINE__,
    516       "http://www.google.com/path/",
    517       "",
    518       "",
    519       "",
    520       "",
    521       L"",
    522       L"www.google.com"
    523     },
    524     {
    525       __LINE__,
    526       "http://www.google.com/path",
    527       "",
    528       "",
    529       "",
    530       "",
    531       L"",
    532       L"path"
    533     },
    534     {
    535       __LINE__,
    536       "file:///",
    537       "",
    538       "",
    539       "",
    540       "",
    541       L"",
    542       L"download"
    543     },
    544     {
    545       __LINE__,
    546       "file:///path/testfile",
    547       "",
    548       "",
    549       "",
    550       "",
    551       L"",
    552       L"testfile"
    553     },
    554     {
    555       __LINE__,
    556       "non-standard-scheme:",
    557       "",
    558       "",
    559       "",
    560       "",
    561       L"",
    562       L"download"
    563     },
    564     { // C-D should override default
    565       __LINE__,
    566       "http://www.google.com/",
    567       "attachment; filename =\"test.html\"",
    568       "",
    569       "",
    570       "",
    571       L"download",
    572       L"test.html"
    573     },
    574     { // But the URL shouldn't
    575       __LINE__,
    576       "http://www.google.com/",
    577       "",
    578       "",
    579       "",
    580       "",
    581       L"download",
    582       L"download"
    583     },
    584     {
    585       __LINE__,
    586       "http://www.google.com/",
    587       "attachment; filename=\"../test.html\"",
    588       "",
    589       "",
    590       "",
    591       L"",
    592       L"-test.html"
    593     },
    594     {
    595       __LINE__,
    596       "http://www.google.com/",
    597       "attachment; filename=\"..\\test.html\"",
    598       "",
    599       "",
    600       "",
    601       L"",
    602       L"test.html"
    603     },
    604     {
    605       __LINE__,
    606       "http://www.google.com/",
    607       "attachment; filename=\"..\\\\test.html\"",
    608       "",
    609       "",
    610       "",
    611       L"",
    612       L"-test.html"
    613     },
    614     { // Filename disappears after leading and trailing periods are removed.
    615       __LINE__,
    616       "http://www.google.com/",
    617       "attachment; filename=\"..\"",
    618       "",
    619       "",
    620       "",
    621       L"default",
    622       L"default"
    623     },
    624     { // C-D specified filename disappears.  Failover to final filename.
    625       __LINE__,
    626       "http://www.google.com/test.html",
    627       "attachment; filename=\"..\"",
    628       "",
    629       "",
    630       "",
    631       L"default",
    632       L"default"
    633     },
    634     // Below is a small subset of cases taken from HttpContentDisposition tests.
    635     {
    636       __LINE__,
    637       "http://www.google.com/",
    638       "attachment; filename=\"%EC%98%88%EC%88%A0%20"
    639       "%EC%98%88%EC%88%A0.jpg\"",
    640       "",
    641       "",
    642       "",
    643       L"",
    644       L"\uc608\uc220 \uc608\uc220.jpg"
    645     },
    646     {
    647       __LINE__,
    648       "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
    649       "",
    650       "",
    651       "",
    652       "",
    653       L"download",
    654       L"\uc608\uc220 \uc608\uc220.jpg"
    655     },
    656     {
    657       __LINE__,
    658       "http://www.google.com/",
    659       "attachment;",
    660       "",
    661       "",
    662       "",
    663       L"\uB2E4\uC6B4\uB85C\uB4DC",
    664       L"\uB2E4\uC6B4\uB85C\uB4DC"
    665     },
    666     {
    667       __LINE__,
    668       "http://www.google.com/",
    669       "attachment; filename=\"=?EUC-JP?Q?=B7=DD=BD="
    670       "D13=2Epng?=\"",
    671       "",
    672       "",
    673       "",
    674       L"download",
    675       L"\u82b8\u88533.png"
    676     },
    677     {
    678       __LINE__,
    679       "http://www.example.com/images?id=3",
    680       "attachment; filename=caf\xc3\xa9.png",
    681       "iso-8859-1",
    682       "",
    683       "",
    684       L"",
    685       L"caf\u00e9.png"
    686     },
    687     {
    688       __LINE__,
    689       "http://www.example.com/images?id=3",
    690       "attachment; filename=caf\xe5.png",
    691       "windows-1253",
    692       "",
    693       "",
    694       L"",
    695       L"caf\u03b5.png"
    696     },
    697     {
    698       __LINE__,
    699       "http://www.example.com/file?id=3",
    700       "attachment; name=\xcf\xc2\xd4\xd8.zip",
    701       "GBK",
    702       "",
    703       "",
    704       L"",
    705       L"\u4e0b\u8f7d.zip"
    706     },
    707     { // Invalid C-D header. Extracts filename from url.
    708       __LINE__,
    709       "http://www.google.com/test.html",
    710       "attachment; filename==?iiso88591?Q?caf=EG?=",
    711       "",
    712       "",
    713       "",
    714       L"",
    715       L"test.html"
    716     },
    717     // about: and data: URLs
    718     {
    719       __LINE__,
    720       "about:chrome",
    721       "",
    722       "",
    723       "",
    724       "",
    725       L"",
    726       L"download"
    727     },
    728     {
    729       __LINE__,
    730       "data:,looks/like/a.path",
    731       "",
    732       "",
    733       "",
    734       "",
    735       L"",
    736       L"download"
    737     },
    738     {
    739       __LINE__,
    740       "data:text/plain;base64,VG8gYmUgb3Igbm90IHRvIGJlLg=",
    741       "",
    742       "",
    743       "",
    744       "",
    745       L"",
    746       L"download"
    747     },
    748     {
    749       __LINE__,
    750       "data:,looks/like/a.path",
    751       "",
    752       "",
    753       "",
    754       "",
    755       L"default_filename_is_given",
    756       L"default_filename_is_given"
    757     },
    758     {
    759       __LINE__,
    760       "data:,looks/like/a.path",
    761       "",
    762       "",
    763       "",
    764       "",
    765       L"\u65e5\u672c\u8a9e",  // Japanese Kanji.
    766       L"\u65e5\u672c\u8a9e"
    767     },
    768     { // The filename encoding is specified by the referrer charset.
    769       __LINE__,
    770       "http://example.com/V%FDvojov%E1%20psychologie.doc",
    771       "",
    772       "iso-8859-1",
    773       "",
    774       "",
    775       L"",
    776       L"V\u00fdvojov\u00e1 psychologie.doc"
    777     },
    778     { // Suggested filename takes precedence over URL
    779       __LINE__,
    780       "http://www.google.com/test",
    781       "",
    782       "",
    783       "suggested",
    784       "",
    785       L"",
    786       L"suggested"
    787     },
    788     { // The content-disposition has higher precedence over the suggested name.
    789       __LINE__,
    790       "http://www.google.com/test",
    791       "attachment; filename=test.html",
    792       "",
    793       "suggested",
    794       "",
    795       L"",
    796       L"test.html"
    797     },
    798 #if 0
    799     { // The filename encoding doesn't match the referrer charset, the system
    800       // charset, or UTF-8.
    801       // TODO(jshin): we need to handle this case.
    802       __LINE__,
    803       "http://example.com/V%FDvojov%E1%20psychologie.doc",
    804       "",
    805       "utf-8",
    806       "",
    807       "",
    808       L"",
    809       L"V\u00fdvojov\u00e1 psychologie.doc",
    810     },
    811 #endif
    812     // Raw 8bit characters in C-D
    813     {
    814       __LINE__,
    815       "http://www.example.com/images?id=3",
    816       "attachment; filename=caf\xc3\xa9.png",
    817       "iso-8859-1",
    818       "",
    819       "image/png",
    820       L"",
    821       L"caf\u00e9.png"
    822     },
    823     {
    824       __LINE__,
    825       "http://www.example.com/images?id=3",
    826       "attachment; filename=caf\xe5.png",
    827       "windows-1253",
    828       "",
    829       "image/png",
    830       L"",
    831       L"caf\u03b5.png"
    832     },
    833     { // No 'filename' keyword in the disposition, use the URL
    834       __LINE__,
    835       "http://www.evil.com/my_download.txt",
    836       "a_file_name.txt",
    837       "",
    838       "",
    839       "text/plain",
    840       L"download",
    841       L"my_download.txt"
    842     },
    843     { // Spaces in the disposition file name
    844       __LINE__,
    845       "http://www.frontpagehacker.com/a_download.exe",
    846       "filename=My Downloaded File.exe",
    847       "",
    848       "",
    849       "application/octet-stream",
    850       L"download",
    851       L"My Downloaded File.exe"
    852     },
    853     { // % encoded
    854       __LINE__,
    855       "http://www.examples.com/",
    856       "attachment; "
    857       "filename=\"%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg\"",
    858       "",
    859       "",
    860       "image/jpeg",
    861       L"download",
    862       L"\uc608\uc220 \uc608\uc220.jpg"
    863     },
    864     { // name= parameter
    865       __LINE__,
    866       "http://www.examples.com/q.cgi?id=abc",
    867       "attachment; name=abc de.pdf",
    868       "",
    869       "",
    870       "application/octet-stream",
    871       L"download",
    872       L"abc de.pdf"
    873     },
    874     {
    875       __LINE__,
    876       "http://www.example.com/path",
    877       "filename=\"=?EUC-JP?Q?=B7=DD=BD=D13=2Epng?=\"",
    878       "",
    879       "",
    880       "image/png",
    881       L"download",
    882       L"\x82b8\x8853" L"3.png"
    883     },
    884     { // The following two have invalid CD headers and filenames come from the
    885       // URL.
    886       __LINE__,
    887       "http://www.example.com/test%20123",
    888       "attachment; filename==?iiso88591?Q?caf=EG?=",
    889       "",
    890       "",
    891       "image/jpeg",
    892       L"download",
    893       L"test 123" JPEG_EXT
    894     },
    895     {
    896       __LINE__,
    897       "http://www.google.com/%EC%98%88%EC%88%A0%20%EC%98%88%EC%88%A0.jpg",
    898       "malformed_disposition",
    899       "",
    900       "",
    901       "image/jpeg",
    902       L"download",
    903       L"\uc608\uc220 \uc608\uc220.jpg"
    904     },
    905     { // Invalid C-D. No filename from URL. Falls back to 'download'.
    906       __LINE__,
    907       "http://www.google.com/path1/path2/",
    908       "attachment; filename==?iso88591?Q?caf=E3?",
    909       "",
    910       "",
    911       "image/jpeg",
    912       L"download",
    913       L"download" JPEG_EXT
    914     },
    915   };
    916 
    917   // Tests filename generation.  Once the correct filename is
    918   // selected, they should be passed through the validation steps and
    919   // a correct extension should be added if necessary.
    920   const GenerateFilenameCase generation_tests[] = {
    921     // Dotfiles. Ensures preceeding period(s) stripped.
    922     {
    923       __LINE__,
    924       "http://www.google.com/.test.html",
    925       "",
    926       "",
    927       "",
    928       "",
    929       L"",
    930       L"test.html"
    931     },
    932     {
    933       __LINE__,
    934       "http://www.google.com/.test",
    935       "",
    936       "",
    937       "",
    938       "",
    939       L"",
    940       L"test"
    941     },
    942     {
    943       __LINE__,
    944       "http://www.google.com/..test",
    945       "",
    946       "",
    947       "",
    948       "",
    949       L"",
    950       L"test"
    951     },
    952     { // Disposition has relative paths, remove directory separators
    953       __LINE__,
    954       "http://www.evil.com/my_download.txt",
    955       "filename=../../../../././../a_file_name.txt",
    956       "",
    957       "",
    958       "text/plain",
    959       L"download",
    960       L"-..-..-..-.-.-..-a_file_name.txt"
    961     },
    962     { // Disposition has parent directories, remove directory separators
    963       __LINE__,
    964       "http://www.evil.com/my_download.txt",
    965       "filename=dir1/dir2/a_file_name.txt",
    966       "",
    967       "",
    968       "text/plain",
    969       L"download",
    970       L"dir1-dir2-a_file_name.txt"
    971     },
    972     { // Disposition has relative paths, remove directory separators
    973       __LINE__,
    974       "http://www.evil.com/my_download.txt",
    975       "filename=..\\..\\..\\..\\.\\.\\..\\a_file_name.txt",
    976       "",
    977       "",
    978       "text/plain",
    979       L"download",
    980       L"-..-..-..-.-.-..-a_file_name.txt"
    981     },
    982     { // Disposition has parent directories, remove directory separators
    983       __LINE__,
    984       "http://www.evil.com/my_download.txt",
    985       "filename=dir1\\dir2\\a_file_name.txt",
    986       "",
    987       "",
    988       "text/plain",
    989       L"download",
    990       L"dir1-dir2-a_file_name.txt"
    991     },
    992     { // No useful information in disposition or URL, use default
    993       __LINE__,
    994       "http://www.truncated.com/path/",
    995       "",
    996       "",
    997       "",
    998       "text/plain",
    999       L"download",
   1000       L"download" TXT_EXT
   1001     },
   1002     { // Filename looks like HTML?
   1003       __LINE__,
   1004       "http://www.evil.com/get/malware/here",
   1005       "filename=\"<blink>Hello kitty</blink>\"",
   1006       "",
   1007       "",
   1008       "text/plain",
   1009       L"default",
   1010       L"-blink-Hello kitty--blink-" TXT_EXT
   1011     },
   1012     { // A normal avi should get .avi and not .avi.avi
   1013       __LINE__,
   1014       "https://blah.google.com/misc/2.avi",
   1015       "",
   1016       "",
   1017       "",
   1018       "video/x-msvideo",
   1019       L"download",
   1020       L"2.avi"
   1021     },
   1022     { // Extension generation
   1023       __LINE__,
   1024       "http://www.example.com/my-cat",
   1025       "filename=my-cat",
   1026       "",
   1027       "",
   1028       "image/jpeg",
   1029       L"download",
   1030       L"my-cat" JPEG_EXT
   1031     },
   1032     {
   1033       __LINE__,
   1034       "http://www.example.com/my-cat",
   1035       "filename=my-cat",
   1036       "",
   1037       "",
   1038       "text/plain",
   1039       L"download",
   1040       L"my-cat.txt"
   1041     },
   1042     {
   1043       __LINE__,
   1044       "http://www.example.com/my-cat",
   1045       "filename=my-cat",
   1046       "",
   1047       "",
   1048       "text/html",
   1049       L"download",
   1050       L"my-cat" HTML_EXT
   1051     },
   1052     { // Unknown MIME type
   1053       __LINE__,
   1054       "http://www.example.com/my-cat",
   1055       "filename=my-cat",
   1056       "",
   1057       "",
   1058       "dance/party",
   1059       L"download",
   1060       L"my-cat"
   1061     },
   1062     {
   1063       __LINE__,
   1064       "http://www.example.com/my-cat.jpg",
   1065       "filename=my-cat.jpg",
   1066       "",
   1067       "",
   1068       "text/plain",
   1069       L"download",
   1070       L"my-cat.jpg"
   1071     },
   1072     // Windows specific tests
   1073 #if defined(OS_WIN)
   1074     {
   1075       __LINE__,
   1076       "http://www.goodguy.com/evil.exe",
   1077       "filename=evil.exe",
   1078       "",
   1079       "",
   1080       "image/jpeg",
   1081       L"download",
   1082       L"evil.exe"
   1083     },
   1084     {
   1085       __LINE__,
   1086       "http://www.goodguy.com/ok.exe",
   1087       "filename=ok.exe",
   1088       "",
   1089       "",
   1090       "binary/octet-stream",
   1091       L"download",
   1092       L"ok.exe"
   1093     },
   1094     {
   1095       __LINE__,
   1096       "http://www.goodguy.com/evil.dll",
   1097       "filename=evil.dll",
   1098       "",
   1099       "",
   1100       "dance/party",
   1101       L"download",
   1102       L"evil.dll"
   1103     },
   1104     {
   1105       __LINE__,
   1106       "http://www.goodguy.com/evil.exe",
   1107       "filename=evil",
   1108       "",
   1109       "",
   1110       "application/rss+xml",
   1111       L"download",
   1112       L"evil"
   1113     },
   1114     // Test truncation of trailing dots and spaces
   1115     {
   1116       __LINE__,
   1117       "http://www.goodguy.com/evil.exe ",
   1118       "filename=evil.exe ",
   1119       "",
   1120       "",
   1121       "binary/octet-stream",
   1122       L"download",
   1123       L"evil.exe"
   1124     },
   1125     {
   1126       __LINE__,
   1127       "http://www.goodguy.com/evil.exe.",
   1128       "filename=evil.exe.",
   1129       "",
   1130       "",
   1131       "binary/octet-stream",
   1132       L"download",
   1133       L"evil.exe-"
   1134     },
   1135     {
   1136       __LINE__,
   1137       "http://www.goodguy.com/evil.exe.  .  .",
   1138       "filename=evil.exe.  .  .",
   1139       "",
   1140       "",
   1141       "binary/octet-stream",
   1142       L"download",
   1143       L"evil.exe-------"
   1144     },
   1145     {
   1146       __LINE__,
   1147       "http://www.goodguy.com/evil.",
   1148       "filename=evil.",
   1149       "",
   1150       "",
   1151       "binary/octet-stream",
   1152       L"download",
   1153       L"evil-"
   1154     },
   1155     {
   1156       __LINE__,
   1157       "http://www.goodguy.com/. . . . .",
   1158       "filename=. . . . .",
   1159       "",
   1160       "",
   1161       "binary/octet-stream",
   1162       L"download",
   1163       L"download"
   1164     },
   1165     {
   1166       __LINE__,
   1167       "http://www.badguy.com/attachment?name=meh.exe%C2%A0",
   1168       "attachment; filename=\"meh.exe\xC2\xA0\"",
   1169       "",
   1170       "",
   1171       "binary/octet-stream",
   1172       L"",
   1173       L"meh.exe-"
   1174     },
   1175 #endif  // OS_WIN
   1176     {
   1177       __LINE__,
   1178       "http://www.goodguy.com/utils.js",
   1179       "filename=utils.js",
   1180       "",
   1181       "",
   1182       "application/x-javascript",
   1183       L"download",
   1184       L"utils.js"
   1185     },
   1186     {
   1187       __LINE__,
   1188       "http://www.goodguy.com/contacts.js",
   1189       "filename=contacts.js",
   1190       "",
   1191       "",
   1192       "application/json",
   1193       L"download",
   1194       L"contacts.js"
   1195     },
   1196     {
   1197       __LINE__,
   1198       "http://www.goodguy.com/utils.js",
   1199       "filename=utils.js",
   1200       "",
   1201       "",
   1202       "text/javascript",
   1203       L"download",
   1204       L"utils.js"
   1205     },
   1206     {
   1207       __LINE__,
   1208       "http://www.goodguy.com/utils.js",
   1209       "filename=utils.js",
   1210       "",
   1211       "",
   1212       "text/javascript;version=2",
   1213       L"download",
   1214       L"utils.js"
   1215     },
   1216     {
   1217       __LINE__,
   1218       "http://www.goodguy.com/utils.js",
   1219       "filename=utils.js",
   1220       "",
   1221       "",
   1222       "application/ecmascript",
   1223       L"download",
   1224       L"utils.js"
   1225     },
   1226     {
   1227       __LINE__,
   1228       "http://www.goodguy.com/utils.js",
   1229       "filename=utils.js",
   1230       "",
   1231       "",
   1232       "application/ecmascript;version=4",
   1233       L"download",
   1234       L"utils.js"
   1235     },
   1236     {
   1237       __LINE__,
   1238       "http://www.goodguy.com/program.exe",
   1239       "filename=program.exe",
   1240       "",
   1241       "",
   1242       "application/foo-bar",
   1243       L"download",
   1244       L"program.exe"
   1245     },
   1246     {
   1247       __LINE__,
   1248       "http://www.evil.com/../foo.txt",
   1249       "filename=../foo.txt",
   1250       "",
   1251       "",
   1252       "text/plain",
   1253       L"download",
   1254       L"-foo.txt"
   1255     },
   1256     {
   1257       __LINE__,
   1258       "http://www.evil.com/..\\foo.txt",
   1259       "filename=..\\foo.txt",
   1260       "",
   1261       "",
   1262       "text/plain",
   1263       L"download",
   1264       L"-foo.txt"
   1265     },
   1266     {
   1267       __LINE__,
   1268       "http://www.evil.com/.hidden",
   1269       "filename=.hidden",
   1270       "",
   1271       "",
   1272       "text/plain",
   1273       L"download",
   1274       L"hidden" TXT_EXT
   1275     },
   1276     {
   1277       __LINE__,
   1278       "http://www.evil.com/trailing.",
   1279       "filename=trailing.",
   1280       "",
   1281       "",
   1282       "dance/party",
   1283       L"download",
   1284 #if defined(OS_WIN)
   1285       L"trailing-"
   1286 #else
   1287       L"trailing"
   1288 #endif
   1289     },
   1290     {
   1291       __LINE__,
   1292       "http://www.evil.com/trailing.",
   1293       "filename=trailing.",
   1294       "",
   1295       "",
   1296       "text/plain",
   1297       L"download",
   1298 #if defined(OS_WIN)
   1299       L"trailing-" TXT_EXT
   1300 #else
   1301       L"trailing" TXT_EXT
   1302 #endif
   1303     },
   1304     {
   1305       __LINE__,
   1306       "http://www.evil.com/.",
   1307       "filename=.",
   1308       "",
   1309       "",
   1310       "dance/party",
   1311       L"download",
   1312       L"download"
   1313     },
   1314     {
   1315       __LINE__,
   1316       "http://www.evil.com/..",
   1317       "filename=..",
   1318       "",
   1319       "",
   1320       "dance/party",
   1321       L"download",
   1322       L"download"
   1323     },
   1324     {
   1325       __LINE__,
   1326       "http://www.evil.com/...",
   1327       "filename=...",
   1328       "",
   1329       "",
   1330       "dance/party",
   1331       L"download",
   1332       L"download"
   1333     },
   1334     { // Note that this one doesn't have "filename=" on it.
   1335       __LINE__,
   1336       "http://www.evil.com/",
   1337       "a_file_name.txt",
   1338       "",
   1339       "",
   1340       "image/jpeg",
   1341       L"download",
   1342       L"download" JPEG_EXT
   1343     },
   1344     {
   1345       __LINE__,
   1346       "http://www.evil.com/",
   1347       "filename=",
   1348       "",
   1349       "",
   1350       "image/jpeg",
   1351       L"download",
   1352       L"download" JPEG_EXT
   1353     },
   1354     {
   1355       __LINE__,
   1356       "http://www.example.com/simple",
   1357       "filename=simple",
   1358       "",
   1359       "",
   1360       "application/octet-stream",
   1361       L"download",
   1362       L"simple"
   1363     },
   1364     // Reserved words on Windows
   1365     {
   1366       __LINE__,
   1367       "http://www.goodguy.com/COM1",
   1368       "filename=COM1",
   1369       "",
   1370       "",
   1371       "application/foo-bar",
   1372       L"download",
   1373 #if defined(OS_WIN)
   1374       L"_COM1"
   1375 #else
   1376       L"COM1"
   1377 #endif
   1378     },
   1379     {
   1380       __LINE__,
   1381       "http://www.goodguy.com/COM4.txt",
   1382       "filename=COM4.txt",
   1383       "",
   1384       "",
   1385       "text/plain",
   1386       L"download",
   1387 #if defined(OS_WIN)
   1388       L"_COM4.txt"
   1389 #else
   1390       L"COM4.txt"
   1391 #endif
   1392     },
   1393     {
   1394       __LINE__,
   1395       "http://www.goodguy.com/lpt1.TXT",
   1396       "filename=lpt1.TXT",
   1397       "",
   1398       "",
   1399       "text/plain",
   1400       L"download",
   1401 #if defined(OS_WIN)
   1402       L"_lpt1.TXT"
   1403 #else
   1404       L"lpt1.TXT"
   1405 #endif
   1406     },
   1407     {
   1408       __LINE__,
   1409       "http://www.goodguy.com/clock$.txt",
   1410       "filename=clock$.txt",
   1411       "",
   1412       "",
   1413       "text/plain",
   1414       L"download",
   1415 #if defined(OS_WIN)
   1416       L"_clock$.txt"
   1417 #else
   1418       L"clock$.txt"
   1419 #endif
   1420     },
   1421     { // Validation should also apply to sugested name
   1422       __LINE__,
   1423       "http://www.goodguy.com/blah$.txt",
   1424       "filename=clock$.txt",
   1425       "",
   1426       "clock$.txt",
   1427       "text/plain",
   1428       L"download",
   1429 #if defined(OS_WIN)
   1430       L"_clock$.txt"
   1431 #else
   1432       L"clock$.txt"
   1433 #endif
   1434     },
   1435     {
   1436       __LINE__,
   1437       "http://www.goodguy.com/mycom1.foo",
   1438       "filename=mycom1.foo",
   1439       "",
   1440       "",
   1441       "text/plain",
   1442       L"download",
   1443       L"mycom1.foo"
   1444     },
   1445     {
   1446       __LINE__,
   1447       "http://www.badguy.com/Setup.exe.local",
   1448       "filename=Setup.exe.local",
   1449       "",
   1450       "",
   1451       "application/foo-bar",
   1452       L"download",
   1453 #if defined(OS_WIN)
   1454       L"Setup.exe.download"
   1455 #else
   1456       L"Setup.exe.local"
   1457 #endif
   1458     },
   1459     {
   1460       __LINE__,
   1461       "http://www.badguy.com/Setup.exe.local",
   1462       "filename=Setup.exe.local.local",
   1463       "",
   1464       "",
   1465       "application/foo-bar",
   1466       L"download",
   1467 #if defined(OS_WIN)
   1468       L"Setup.exe.local.download"
   1469 #else
   1470       L"Setup.exe.local.local"
   1471 #endif
   1472     },
   1473     {
   1474       __LINE__,
   1475       "http://www.badguy.com/Setup.exe.lnk",
   1476       "filename=Setup.exe.lnk",
   1477       "",
   1478       "",
   1479       "application/foo-bar",
   1480       L"download",
   1481 #if defined(OS_WIN)
   1482       L"Setup.exe.download"
   1483 #else
   1484       L"Setup.exe.lnk"
   1485 #endif
   1486     },
   1487     {
   1488       __LINE__,
   1489       "http://www.badguy.com/Desktop.ini",
   1490       "filename=Desktop.ini",
   1491       "",
   1492       "",
   1493       "application/foo-bar",
   1494       L"download",
   1495 #if defined(OS_WIN)
   1496       L"_Desktop.ini"
   1497 #else
   1498       L"Desktop.ini"
   1499 #endif
   1500     },
   1501     {
   1502       __LINE__,
   1503       "http://www.badguy.com/Thumbs.db",
   1504       "filename=Thumbs.db",
   1505       "",
   1506       "",
   1507       "application/foo-bar",
   1508       L"download",
   1509 #if defined(OS_WIN)
   1510       L"_Thumbs.db"
   1511 #else
   1512       L"Thumbs.db"
   1513 #endif
   1514     },
   1515     {
   1516       __LINE__,
   1517       "http://www.hotmail.com",
   1518       "filename=source.jpg",
   1519       "",
   1520       "",
   1521       "application/x-javascript",
   1522       L"download",
   1523       L"source.jpg"
   1524     },
   1525     { // http://crbug.com/5772.
   1526       __LINE__,
   1527       "http://www.example.com/foo.tar.gz",
   1528       "",
   1529       "",
   1530       "",
   1531       "application/x-tar",
   1532       L"download",
   1533       L"foo.tar.gz"
   1534     },
   1535     { // http://crbug.com/52250.
   1536       __LINE__,
   1537       "http://www.example.com/foo.tgz",
   1538       "",
   1539       "",
   1540       "",
   1541       "application/x-tar",
   1542       L"download",
   1543       L"foo.tgz"
   1544     },
   1545     { // http://crbug.com/7337.
   1546       __LINE__,
   1547       "http://maged.lordaeron.org/blank.reg",
   1548       "",
   1549       "",
   1550       "",
   1551       "text/x-registry",
   1552       L"download",
   1553       L"blank.reg"
   1554     },
   1555     {
   1556       __LINE__,
   1557       "http://www.example.com/bar.tar",
   1558       "",
   1559       "",
   1560       "",
   1561       "application/x-tar",
   1562       L"download",
   1563       L"bar.tar"
   1564     },
   1565     {
   1566       __LINE__,
   1567       "http://www.example.com/bar.bogus",
   1568       "",
   1569       "",
   1570       "",
   1571       "application/x-tar",
   1572       L"download",
   1573       L"bar.bogus"
   1574     },
   1575     { // http://crbug.com/20337
   1576       __LINE__,
   1577       "http://www.example.com/.download.txt",
   1578       "filename=.download.txt",
   1579       "",
   1580       "",
   1581       "text/plain",
   1582       L"-download",
   1583       L"download.txt"
   1584     },
   1585     { // http://crbug.com/56855.
   1586       __LINE__,
   1587       "http://www.example.com/bar.sh",
   1588       "",
   1589       "",
   1590       "",
   1591       "application/x-sh",
   1592       L"download",
   1593       L"bar.sh"
   1594     },
   1595     { // http://crbug.com/61571
   1596       __LINE__,
   1597       "http://www.example.com/npdf.php?fn=foobar.pdf",
   1598       "",
   1599       "",
   1600       "",
   1601       "text/plain",
   1602       L"download",
   1603       L"npdf" TXT_EXT
   1604     },
   1605     { // Shouldn't overwrite C-D specified extension.
   1606       __LINE__,
   1607       "http://www.example.com/npdf.php?fn=foobar.pdf",
   1608       "filename=foobar.jpg",
   1609       "",
   1610       "",
   1611       "text/plain",
   1612       L"download",
   1613       L"foobar.jpg"
   1614     },
   1615     { // http://crbug.com/87719
   1616       __LINE__,
   1617       "http://www.example.com/image.aspx?id=blargh",
   1618       "",
   1619       "",
   1620       "",
   1621       "image/jpeg",
   1622       L"download",
   1623       L"image" JPEG_EXT
   1624     },
   1625 #if defined(OS_CHROMEOS)
   1626     { // http://crosbug.com/26028
   1627       __LINE__,
   1628       "http://www.example.com/fooa%cc%88.txt",
   1629       "",
   1630       "",
   1631       "",
   1632       "image/jpeg",
   1633       L"foo\xe4",
   1634       L"foo\xe4.txt"
   1635     },
   1636 #endif
   1637   };
   1638 
   1639   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(selection_tests); ++i)
   1640     RunGenerateFileNameTestCase(&selection_tests[i]);
   1641 
   1642   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generation_tests); ++i)
   1643     RunGenerateFileNameTestCase(&generation_tests[i]);
   1644 
   1645   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generation_tests); ++i) {
   1646     GenerateFilenameCase test_case = generation_tests[i];
   1647     test_case.referrer_charset = "GBK";
   1648     RunGenerateFileNameTestCase(&test_case);
   1649   }
   1650 }
   1651 
   1652 }  // namespace net
   1653