| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/filename_util.h" | 5 #include "net/base/filename_util.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/i18n/file_util_icu.h" | 9 #include "base/i18n/file_util_icu.h" |
| 10 #include "base/path_service.h" | 10 #include "base/path_service.h" |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 url.ExtractFileName(), | 70 url.ExtractFileName(), |
| 71 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); | 71 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); |
| 72 | 72 |
| 73 // The URL's path should be escaped UTF-8, but may not be. | 73 // The URL's path should be escaped UTF-8, but may not be. |
| 74 std::string decoded_filename = unescaped_url_filename; | 74 std::string decoded_filename = unescaped_url_filename; |
| 75 if (!IsStringUTF8(decoded_filename)) { | 75 if (!IsStringUTF8(decoded_filename)) { |
| 76 // TODO(jshin): this is probably not robust enough. To be sure, we need | 76 // TODO(jshin): this is probably not robust enough. To be sure, we need |
| 77 // encoding detection. | 77 // encoding detection. |
| 78 base::string16 utf16_output; | 78 base::string16 utf16_output; |
| 79 if (!referrer_charset.empty() && | 79 if (!referrer_charset.empty() && |
| 80 net::ConvertToUTF16(unescaped_url_filename, | 80 net::ConvertToUTF16( |
| 81 referrer_charset.c_str(), | 81 unescaped_url_filename, referrer_charset.c_str(), &utf16_output)) { |
| 82 &utf16_output)) { | |
| 83 decoded_filename = base::UTF16ToUTF8(utf16_output); | 82 decoded_filename = base::UTF16ToUTF8(utf16_output); |
| 84 } else { | 83 } else { |
| 85 decoded_filename = base::WideToUTF8( | 84 decoded_filename = |
| 86 base::SysNativeMBToWide(unescaped_url_filename)); | 85 base::WideToUTF8(base::SysNativeMBToWide(unescaped_url_filename)); |
| 87 } | 86 } |
| 88 } | 87 } |
| 89 // If the URL contains a (possibly empty) query, assume it is a generator, and | 88 // If the URL contains a (possibly empty) query, assume it is a generator, and |
| 90 // allow the determined extension to be overwritten. | 89 // allow the determined extension to be overwritten. |
| 91 *should_overwrite_extension = !decoded_filename.empty() && url.has_query(); | 90 *should_overwrite_extension = !decoded_filename.empty() && url.has_query(); |
| 92 | 91 |
| 93 return decoded_filename; | 92 return decoded_filename; |
| 94 } | 93 } |
| 95 | 94 |
| 96 // Returns whether the specified extension is automatically integrated into the | 95 // Returns whether the specified extension is automatically integrated into the |
| (...skipping 18 matching lines...) Expand all Loading... |
| 115 | 114 |
| 116 // Returns whether the specified file name is a reserved name on windows. | 115 // Returns whether the specified file name is a reserved name on windows. |
| 117 // This includes names like "com2.zip" (which correspond to devices) and | 116 // This includes names like "com2.zip" (which correspond to devices) and |
| 118 // desktop.ini and thumbs.db which have special meaning to the windows shell. | 117 // desktop.ini and thumbs.db which have special meaning to the windows shell. |
| 119 bool IsReservedName(const base::FilePath::StringType& filename) { | 118 bool IsReservedName(const base::FilePath::StringType& filename) { |
| 120 // This list is taken from the MSDN article "Naming a file" | 119 // This list is taken from the MSDN article "Naming a file" |
| 121 // http://msdn2.microsoft.com/en-us/library/aa365247(VS.85).aspx | 120 // http://msdn2.microsoft.com/en-us/library/aa365247(VS.85).aspx |
| 122 // I also added clock$ because GetSaveFileName seems to consider it as a | 121 // I also added clock$ because GetSaveFileName seems to consider it as a |
| 123 // reserved name too. | 122 // reserved name too. |
| 124 static const char* const known_devices[] = { | 123 static const char* const known_devices[] = { |
| 125 "con", "prn", "aux", "nul", "com1", "com2", "com3", "com4", "com5", | 124 "con", "prn", "aux", "nul", "com1", "com2", "com3", "com4", |
| 126 "com6", "com7", "com8", "com9", "lpt1", "lpt2", "lpt3", "lpt4", | 125 "com5", "com6", "com7", "com8", "com9", "lpt1", "lpt2", "lpt3", |
| 127 "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "clock$" | 126 "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "clock$"}; |
| 128 }; | |
| 129 #if defined(OS_WIN) | 127 #if defined(OS_WIN) |
| 130 std::string filename_lower = StringToLowerASCII(base::WideToUTF8(filename)); | 128 std::string filename_lower = StringToLowerASCII(base::WideToUTF8(filename)); |
| 131 #elif defined(OS_POSIX) | 129 #elif defined(OS_POSIX) |
| 132 std::string filename_lower = StringToLowerASCII(filename); | 130 std::string filename_lower = StringToLowerASCII(filename); |
| 133 #endif | 131 #endif |
| 134 | 132 |
| 135 for (size_t i = 0; i < arraysize(known_devices); ++i) { | 133 for (size_t i = 0; i < arraysize(known_devices); ++i) { |
| 136 // Exact match. | 134 // Exact match. |
| 137 if (filename_lower == known_devices[i]) | 135 if (filename_lower == known_devices[i]) |
| 138 return true; | 136 return true; |
| 139 // Starts with "DEVICE.". | 137 // Starts with "DEVICE.". |
| 140 if (filename_lower.find(std::string(known_devices[i]) + ".") == 0) | 138 if (filename_lower.find(std::string(known_devices[i]) + ".") == 0) |
| 141 return true; | 139 return true; |
| 142 } | 140 } |
| 143 | 141 |
| 144 static const char* const magic_names[] = { | 142 static const char* const magic_names[] = {// These file names are used by the |
| 145 // These file names are used by the "Customize folder" feature of the shell. | 143 // "Customize folder" feature of the |
| 146 "desktop.ini", | 144 // shell. |
| 147 "thumbs.db", | 145 "desktop.ini", "thumbs.db", |
| 148 }; | 146 }; |
| 149 | 147 |
| 150 for (size_t i = 0; i < arraysize(magic_names); ++i) { | 148 for (size_t i = 0; i < arraysize(magic_names); ++i) { |
| 151 if (filename_lower == magic_names[i]) | 149 if (filename_lower == magic_names[i]) |
| 152 return true; | 150 return true; |
| 153 } | 151 } |
| 154 | 152 |
| 155 return false; | 153 return false; |
| 156 } | 154 } |
| 157 | 155 |
| 158 | |
| 159 // Examines the current extension in |file_name| and modifies it if necessary in | 156 // Examines the current extension in |file_name| and modifies it if necessary in |
| 160 // order to ensure the filename is safe. If |file_name| doesn't contain an | 157 // order to ensure the filename is safe. If |file_name| doesn't contain an |
| 161 // extension or if |ignore_extension| is true, then a new extension will be | 158 // extension or if |ignore_extension| is true, then a new extension will be |
| 162 // constructed based on the |mime_type|. | 159 // constructed based on the |mime_type|. |
| 163 // | 160 // |
| 164 // We're addressing two things here: | 161 // We're addressing two things here: |
| 165 // | 162 // |
| 166 // 1) Usability. If there is no reliable file extension, we want to guess a | 163 // 1) Usability. If there is no reliable file extension, we want to guess a |
| 167 // reasonable file extension based on the content type. | 164 // reasonable file extension based on the content type. |
| 168 // | 165 // |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 url_string.push_back(base::FilePath::kSeparators[0]); | 236 url_string.push_back(base::FilePath::kSeparators[0]); |
| 240 } | 237 } |
| 241 url_string.append(path.value()); | 238 url_string.append(path.value()); |
| 242 | 239 |
| 243 // Now do replacement of some characters. Since we assume the input is a | 240 // Now do replacement of some characters. Since we assume the input is a |
| 244 // literal filename, anything the URL parser might consider special should | 241 // literal filename, anything the URL parser might consider special should |
| 245 // be escaped here. | 242 // be escaped here. |
| 246 | 243 |
| 247 // must be the first substitution since others will introduce percents as the | 244 // must be the first substitution since others will introduce percents as the |
| 248 // escape character | 245 // escape character |
| 249 ReplaceSubstringsAfterOffset(&url_string, 0, | 246 ReplaceSubstringsAfterOffset( |
| 250 FILE_PATH_LITERAL("%"), FILE_PATH_LITERAL("%25")); | 247 &url_string, 0, FILE_PATH_LITERAL("%"), FILE_PATH_LITERAL("%25")); |
| 251 | 248 |
| 252 // semicolon is supposed to be some kind of separator according to RFC 2396 | 249 // semicolon is supposed to be some kind of separator according to RFC 2396 |
| 253 ReplaceSubstringsAfterOffset(&url_string, 0, | 250 ReplaceSubstringsAfterOffset( |
| 254 FILE_PATH_LITERAL(";"), FILE_PATH_LITERAL("%3B")); | 251 &url_string, 0, FILE_PATH_LITERAL(";"), FILE_PATH_LITERAL("%3B")); |
| 255 | 252 |
| 256 ReplaceSubstringsAfterOffset(&url_string, 0, | 253 ReplaceSubstringsAfterOffset( |
| 257 FILE_PATH_LITERAL("#"), FILE_PATH_LITERAL("%23")); | 254 &url_string, 0, FILE_PATH_LITERAL("#"), FILE_PATH_LITERAL("%23")); |
| 258 | 255 |
| 259 ReplaceSubstringsAfterOffset(&url_string, 0, | 256 ReplaceSubstringsAfterOffset( |
| 260 FILE_PATH_LITERAL("?"), FILE_PATH_LITERAL("%3F")); | 257 &url_string, 0, FILE_PATH_LITERAL("?"), FILE_PATH_LITERAL("%3F")); |
| 261 | 258 |
| 262 #if defined(OS_POSIX) | 259 #if defined(OS_POSIX) |
| 263 ReplaceSubstringsAfterOffset(&url_string, 0, | 260 ReplaceSubstringsAfterOffset( |
| 264 FILE_PATH_LITERAL("\\"), FILE_PATH_LITERAL("%5C")); | 261 &url_string, 0, FILE_PATH_LITERAL("\\"), FILE_PATH_LITERAL("%5C")); |
| 265 #endif | 262 #endif |
| 266 | 263 |
| 267 return GURL(url_string); | 264 return GURL(url_string); |
| 268 } | 265 } |
| 269 | 266 |
| 270 bool FileURLToFilePath(const GURL& url, base::FilePath* file_path) { | 267 bool FileURLToFilePath(const GURL& url, base::FilePath* file_path) { |
| 271 *file_path = base::FilePath(); | 268 *file_path = base::FilePath(); |
| 272 base::FilePath::StringType& file_path_str = | 269 base::FilePath::StringType& file_path_str = |
| 273 const_cast<base::FilePath::StringType&>(file_path->value()); | 270 const_cast<base::FilePath::StringType&>(file_path->value()); |
| 274 file_path_str.clear(); | 271 file_path_str.clear(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 288 if (first_non_slash != std::string::npos && first_non_slash > 0) | 285 if (first_non_slash != std::string::npos && first_non_slash > 0) |
| 289 path.erase(0, first_non_slash); | 286 path.erase(0, first_non_slash); |
| 290 } else { | 287 } else { |
| 291 // URL contains a host: this means it's UNC. We keep the preceeding slash | 288 // URL contains a host: this means it's UNC. We keep the preceeding slash |
| 292 // on the path. | 289 // on the path. |
| 293 path = "\\\\"; | 290 path = "\\\\"; |
| 294 path.append(host); | 291 path.append(host); |
| 295 path.append(url.path()); | 292 path.append(url.path()); |
| 296 } | 293 } |
| 297 std::replace(path.begin(), path.end(), '/', '\\'); | 294 std::replace(path.begin(), path.end(), '/', '\\'); |
| 298 #else // defined(OS_WIN) | 295 #else // defined(OS_WIN) |
| 299 // Firefox seems to ignore the "host" of a file url if there is one. That is, | 296 // Firefox seems to ignore the "host" of a file url if there is one. That is, |
| 300 // file://foo/bar.txt maps to /bar.txt. | 297 // file://foo/bar.txt maps to /bar.txt. |
| 301 // TODO(dhg): This should probably take into account UNCs which could | 298 // TODO(dhg): This should probably take into account UNCs which could |
| 302 // include a hostname other than localhost or blank | 299 // include a hostname other than localhost or blank |
| 303 std::string path = url.path(); | 300 std::string path = url.path(); |
| 304 #endif // !defined(OS_WIN) | 301 #endif // !defined(OS_WIN) |
| 305 | 302 |
| 306 if (path.empty()) | 303 if (path.empty()) |
| 307 return false; | 304 return false; |
| 308 | 305 |
| 309 // GURL stores strings as percent-encoded 8-bit, this will undo if possible. | 306 // GURL stores strings as percent-encoded 8-bit, this will undo if possible. |
| 310 path = UnescapeURLComponent(path, | 307 path = UnescapeURLComponent( |
| 311 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); | 308 path, UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); |
| 312 | 309 |
| 313 #if defined(OS_WIN) | 310 #if defined(OS_WIN) |
| 314 if (IsStringUTF8(path)) { | 311 if (IsStringUTF8(path)) { |
| 315 file_path_str.assign(base::UTF8ToWide(path)); | 312 file_path_str.assign(base::UTF8ToWide(path)); |
| 316 // We used to try too hard and see if |path| made up entirely of | 313 // We used to try too hard and see if |path| made up entirely of |
| 317 // the 1st 256 characters in the Unicode was a zero-extended UTF-16. | 314 // the 1st 256 characters in the Unicode was a zero-extended UTF-16. |
| 318 // If so, we converted it to 'Latin-1' and checked if the result was UTF-8. | 315 // If so, we converted it to 'Latin-1' and checked if the result was UTF-8. |
| 319 // If the check passed, we converted the result to UTF-8. | 316 // If the check passed, we converted the result to UTF-8. |
| 320 // Otherwise, we treated the result as the native OS encoding. | 317 // Otherwise, we treated the result as the native OS encoding. |
| 321 // However, that led to http://crbug.com/4619 and http://crbug.com/14153 | 318 // However, that led to http://crbug.com/4619 and http://crbug.com/14153 |
| 322 } else { | 319 } else { |
| 323 // Not UTF-8, assume encoding is native codepage and we're done. We know we | 320 // Not UTF-8, assume encoding is native codepage and we're done. We know we |
| 324 // are giving the conversion function a nonempty string, and it may fail if | 321 // are giving the conversion function a nonempty string, and it may fail if |
| 325 // the given string is not in the current encoding and give us an empty | 322 // the given string is not in the current encoding and give us an empty |
| 326 // string back. We detect this and report failure. | 323 // string back. We detect this and report failure. |
| 327 file_path_str = base::SysNativeMBToWide(path); | 324 file_path_str = base::SysNativeMBToWide(path); |
| 328 } | 325 } |
| 329 #else // defined(OS_WIN) | 326 #else // defined(OS_WIN) |
| 330 // Collapse multiple path slashes into a single path slash. | 327 // Collapse multiple path slashes into a single path slash. |
| 331 std::string new_path; | 328 std::string new_path; |
| 332 do { | 329 do { |
| 333 new_path = path; | 330 new_path = path; |
| 334 ReplaceSubstringsAfterOffset(&new_path, 0, "//", "/"); | 331 ReplaceSubstringsAfterOffset(&new_path, 0, "//", "/"); |
| 335 path.swap(new_path); | 332 path.swap(new_path); |
| 336 } while (new_path != path); | 333 } while (new_path != path); |
| 337 | 334 |
| 338 file_path_str.assign(path); | 335 file_path_str.assign(path); |
| 339 #endif // !defined(OS_WIN) | 336 #endif // !defined(OS_WIN) |
| 340 | 337 |
| 341 return !file_path_str.empty(); | 338 return !file_path_str.empty(); |
| 342 } | 339 } |
| 343 | 340 |
| 344 bool IsSafePortablePathComponent(const base::FilePath& component) { | 341 bool IsSafePortablePathComponent(const base::FilePath& component) { |
| 345 base::string16 component16; | 342 base::string16 component16; |
| 346 base::FilePath::StringType sanitized = component.value(); | 343 base::FilePath::StringType sanitized = component.value(); |
| 347 SanitizeGeneratedFileName(&sanitized, true); | 344 SanitizeGeneratedFileName(&sanitized, true); |
| 348 base::FilePath::StringType extension = component.Extension(); | 345 base::FilePath::StringType extension = component.Extension(); |
| 349 if (!extension.empty()) | 346 if (!extension.empty()) |
| 350 extension.erase(extension.begin()); // Erase preceding '.'. | 347 extension.erase(extension.begin()); // Erase preceding '.'. |
| 351 return !component.empty() && | 348 return !component.empty() && (component == component.BaseName()) && |
| 352 (component == component.BaseName()) && | |
| 353 (component == component.StripTrailingSeparators()) && | 349 (component == component.StripTrailingSeparators()) && |
| 354 FilePathToString16(component, &component16) && | 350 FilePathToString16(component, &component16) && |
| 355 file_util::IsFilenameLegal(component16) && | 351 file_util::IsFilenameLegal(component16) && |
| 356 !IsShellIntegratedExtension(extension) && | 352 !IsShellIntegratedExtension(extension) && |
| 357 (sanitized == component.value()) && | 353 (sanitized == component.value()) && !IsReservedName(component.value()); |
| 358 !IsReservedName(component.value()); | |
| 359 } | 354 } |
| 360 | 355 |
| 361 bool IsSafePortableRelativePath(const base::FilePath& path) { | 356 bool IsSafePortableRelativePath(const base::FilePath& path) { |
| 362 if (path.empty() || path.IsAbsolute() || path.EndsWithSeparator()) | 357 if (path.empty() || path.IsAbsolute() || path.EndsWithSeparator()) |
| 363 return false; | 358 return false; |
| 364 std::vector<base::FilePath::StringType> components; | 359 std::vector<base::FilePath::StringType> components; |
| 365 path.GetComponents(&components); | 360 path.GetComponents(&components); |
| 366 if (components.empty()) | 361 if (components.empty()) |
| 367 return false; | 362 return false; |
| 368 for (size_t i = 0; i < components.size() - 1; ++i) { | 363 for (size_t i = 0; i < components.size() - 1; ++i) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 399 const std::string& referrer_charset, | 394 const std::string& referrer_charset, |
| 400 const std::string& suggested_name, | 395 const std::string& suggested_name, |
| 401 const std::string& mime_type, | 396 const std::string& mime_type, |
| 402 const std::string& default_name) { | 397 const std::string& default_name) { |
| 403 // TODO: this function to be updated to match the httpbis recommendations. | 398 // TODO: this function to be updated to match the httpbis recommendations. |
| 404 // Talk to abarth for the latest news. | 399 // Talk to abarth for the latest news. |
| 405 | 400 |
| 406 // We don't translate this fallback string, "download". If localization is | 401 // We don't translate this fallback string, "download". If localization is |
| 407 // needed, the caller should provide localized fallback in |default_name|. | 402 // needed, the caller should provide localized fallback in |default_name|. |
| 408 static const base::FilePath::CharType kFinalFallbackName[] = | 403 static const base::FilePath::CharType kFinalFallbackName[] = |
| 409 FILE_PATH_LITERAL("download"); | 404 FILE_PATH_LITERAL("download"); |
| 410 std::string filename; // In UTF-8 | 405 std::string filename; // In UTF-8 |
| 411 bool overwrite_extension = false; | 406 bool overwrite_extension = false; |
| 412 | 407 |
| 413 // Try to extract a filename from content-disposition first. | 408 // Try to extract a filename from content-disposition first. |
| 414 if (!content_disposition.empty()) { | 409 if (!content_disposition.empty()) { |
| 415 HttpContentDisposition header(content_disposition, referrer_charset); | 410 HttpContentDisposition header(content_disposition, referrer_charset); |
| 416 filename = header.filename(); | 411 filename = header.filename(); |
| 417 } | 412 } |
| 418 | 413 |
| 419 // Then try to use the suggested name. | 414 // Then try to use the suggested name. |
| 420 if (filename.empty() && !suggested_name.empty()) | 415 if (filename.empty() && !suggested_name.empty()) |
| 421 filename = suggested_name; | 416 filename = suggested_name; |
| 422 | 417 |
| 423 // Now try extracting the filename from the URL. GetFileNameFromURL() only | 418 // Now try extracting the filename from the URL. GetFileNameFromURL() only |
| 424 // looks at the last component of the URL and doesn't return the hostname as a | 419 // looks at the last component of the URL and doesn't return the hostname as a |
| 425 // failover. | 420 // failover. |
| 426 if (filename.empty()) | 421 if (filename.empty()) |
| 427 filename = GetFileNameFromURL(url, referrer_charset, &overwrite_extension); | 422 filename = GetFileNameFromURL(url, referrer_charset, &overwrite_extension); |
| 428 | 423 |
| 429 // Finally try the URL hostname, but only if there's no default specified in | 424 // Finally try the URL hostname, but only if there's no default specified in |
| 430 // |default_name|. Some schemes (e.g.: file:, about:, data:) do not have a | 425 // |default_name|. Some schemes (e.g.: file:, about:, data:) do not have a |
| 431 // host name. | 426 // host name. |
| 432 if (filename.empty() && | 427 if (filename.empty() && default_name.empty() && url.is_valid() && |
| 433 default_name.empty() && | |
| 434 url.is_valid() && | |
| 435 !url.host().empty()) { | 428 !url.host().empty()) { |
| 436 // TODO(jungshik) : Decode a 'punycoded' IDN hostname. (bug 1264451) | 429 // TODO(jungshik) : Decode a 'punycoded' IDN hostname. (bug 1264451) |
| 437 filename = url.host(); | 430 filename = url.host(); |
| 438 } | 431 } |
| 439 | 432 |
| 440 bool replace_trailing = false; | 433 bool replace_trailing = false; |
| 441 base::FilePath::StringType result_str, default_name_str; | 434 base::FilePath::StringType result_str, default_name_str; |
| 442 #if defined(OS_WIN) | 435 #if defined(OS_WIN) |
| 443 replace_trailing = true; | 436 replace_trailing = true; |
| 444 result_str = base::UTF8ToUTF16(filename); | 437 result_str = base::UTF8ToUTF16(filename); |
| 445 default_name_str = base::UTF8ToUTF16(default_name); | 438 default_name_str = base::UTF8ToUTF16(default_name); |
| 446 #else | 439 #else |
| 447 result_str = filename; | 440 result_str = filename; |
| 448 default_name_str = default_name; | 441 default_name_str = default_name; |
| 449 #endif | 442 #endif |
| 450 SanitizeGeneratedFileName(&result_str, replace_trailing); | 443 SanitizeGeneratedFileName(&result_str, replace_trailing); |
| 451 if (result_str.find_last_not_of(FILE_PATH_LITERAL("-_")) == | 444 if (result_str.find_last_not_of(FILE_PATH_LITERAL("-_")) == |
| 452 base::FilePath::StringType::npos) { | 445 base::FilePath::StringType::npos) { |
| 453 result_str = !default_name_str.empty() ? default_name_str : | 446 result_str = !default_name_str.empty() |
| 454 base::FilePath::StringType(kFinalFallbackName); | 447 ? default_name_str |
| 448 : base::FilePath::StringType(kFinalFallbackName); |
| 455 overwrite_extension = false; | 449 overwrite_extension = false; |
| 456 } | 450 } |
| 457 file_util::ReplaceIllegalCharactersInPath(&result_str, '-'); | 451 file_util::ReplaceIllegalCharactersInPath(&result_str, '-'); |
| 458 base::FilePath result(result_str); | 452 base::FilePath result(result_str); |
| 459 GenerateSafeFileName(mime_type, overwrite_extension, &result); | 453 GenerateSafeFileName(mime_type, overwrite_extension, &result); |
| 460 | 454 |
| 461 base::string16 result16; | 455 base::string16 result16; |
| 462 if (!FilePathToString16(result, &result16)) { | 456 if (!FilePathToString16(result, &result16)) { |
| 463 result = base::FilePath(default_name_str); | 457 result = base::FilePath(default_name_str); |
| 464 if (!FilePathToString16(result, &result16)) { | 458 if (!FilePathToString16(result, &result16)) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 // utf8 encoded characters in name. | 490 // utf8 encoded characters in name. |
| 497 file_util::NormalizeFileNameEncoding(&generated_name); | 491 file_util::NormalizeFileNameEncoding(&generated_name); |
| 498 #endif | 492 #endif |
| 499 | 493 |
| 500 DCHECK(!generated_name.empty()); | 494 DCHECK(!generated_name.empty()); |
| 501 | 495 |
| 502 return generated_name; | 496 return generated_name; |
| 503 } | 497 } |
| 504 | 498 |
| 505 } // namespace net | 499 } // namespace net |
| OLD | NEW |