OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "content/browser/download/save_package.h" | 5 #include "content/browser/download/save_package.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/file_path.h" | 10 #include "base/file_path.h" |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 // The parameter |dir_path| specifies directory part of the specified | 378 // The parameter |dir_path| specifies directory part of the specified |
379 // file path. The parameter |file_name_ext| specifies file extension | 379 // file path. The parameter |file_name_ext| specifies file extension |
380 // name part of the specified file path (including start dot). The parameter | 380 // name part of the specified file path (including start dot). The parameter |
381 // |max_file_path_len| specifies maximum length of the specified file path. | 381 // |max_file_path_len| specifies maximum length of the specified file path. |
382 // The parameter |pure_file_name| input pure file name part of the specified | 382 // The parameter |pure_file_name| input pure file name part of the specified |
383 // file path. If the length of specified file path is great than | 383 // file path. If the length of specified file path is great than |
384 // |max_file_path_len|, the |pure_file_name| will output new pure file name | 384 // |max_file_path_len|, the |pure_file_name| will output new pure file name |
385 // part for making sure the length of specified file path is less than | 385 // part for making sure the length of specified file path is less than |
386 // specified maximum length of file path. Return false if the function can | 386 // specified maximum length of file path. Return false if the function can |
387 // not get a safe pure file name, otherwise it returns true. | 387 // not get a safe pure file name, otherwise it returns true. |
388 bool SavePackage::GetSafePureFileName(const FilePath& dir_path, | 388 bool SavePackage::GetSafePureFileName( |
389 const FilePath::StringType& file_name_ext, | 389 const base::FilePath& dir_path, |
390 uint32 max_file_path_len, | 390 const base::FilePath::StringType& file_name_ext, |
391 FilePath::StringType* pure_file_name) { | 391 uint32 max_file_path_len, |
| 392 base::FilePath::StringType* pure_file_name) { |
392 DCHECK(!pure_file_name->empty()); | 393 DCHECK(!pure_file_name->empty()); |
393 int available_length = static_cast<int>(max_file_path_len - | 394 int available_length = static_cast<int>(max_file_path_len - |
394 dir_path.value().length() - | 395 dir_path.value().length() - |
395 file_name_ext.length()); | 396 file_name_ext.length()); |
396 // Need an extra space for the separator. | 397 // Need an extra space for the separator. |
397 if (!file_util::EndsWithSeparator(dir_path)) | 398 if (!file_util::EndsWithSeparator(dir_path)) |
398 --available_length; | 399 --available_length; |
399 | 400 |
400 // Plenty of room. | 401 // Plenty of room. |
401 if (static_cast<int>(pure_file_name->length()) <= available_length) | 402 if (static_cast<int>(pure_file_name->length()) <= available_length) |
402 return true; | 403 return true; |
403 | 404 |
404 // Limited room. Truncate |pure_file_name| to fit. | 405 // Limited room. Truncate |pure_file_name| to fit. |
405 if (available_length > 0) { | 406 if (available_length > 0) { |
406 *pure_file_name = pure_file_name->substr(0, available_length); | 407 *pure_file_name = pure_file_name->substr(0, available_length); |
407 return true; | 408 return true; |
408 } | 409 } |
409 | 410 |
410 // Not enough room to even use a shortened |pure_file_name|. | 411 // Not enough room to even use a shortened |pure_file_name|. |
411 pure_file_name->clear(); | 412 pure_file_name->clear(); |
412 return false; | 413 return false; |
413 } | 414 } |
414 | 415 |
415 // Generate name for saving resource. | 416 // Generate name for saving resource. |
416 bool SavePackage::GenerateFileName(const std::string& disposition, | 417 bool SavePackage::GenerateFileName(const std::string& disposition, |
417 const GURL& url, | 418 const GURL& url, |
418 bool need_html_ext, | 419 bool need_html_ext, |
419 FilePath::StringType* generated_name) { | 420 base::FilePath::StringType* generated_name) { |
420 // TODO(jungshik): Figure out the referrer charset when having one | 421 // TODO(jungshik): Figure out the referrer charset when having one |
421 // makes sense and pass it to GenerateFileName. | 422 // makes sense and pass it to GenerateFileName. |
422 FilePath file_path = net::GenerateFileName(url, disposition, "", "", "", | 423 base::FilePath file_path = net::GenerateFileName(url, disposition, "", "", "", |
423 kDefaultSaveName); | 424 kDefaultSaveName); |
424 | 425 |
425 DCHECK(!file_path.empty()); | 426 DCHECK(!file_path.empty()); |
426 FilePath::StringType pure_file_name = | 427 base::FilePath::StringType pure_file_name = |
427 file_path.RemoveExtension().BaseName().value(); | 428 file_path.RemoveExtension().BaseName().value(); |
428 FilePath::StringType file_name_ext = file_path.Extension(); | 429 base::FilePath::StringType file_name_ext = file_path.Extension(); |
429 | 430 |
430 // If it is HTML resource, use ".htm{l,}" as its extension. | 431 // If it is HTML resource, use ".htm{l,}" as its extension. |
431 if (need_html_ext) { | 432 if (need_html_ext) { |
432 file_name_ext = FILE_PATH_LITERAL("."); | 433 file_name_ext = FILE_PATH_LITERAL("."); |
433 file_name_ext.append(kDefaultHtmlExtension); | 434 file_name_ext.append(kDefaultHtmlExtension); |
434 } | 435 } |
435 | 436 |
436 // Need to make sure the suggested file name is not too long. | 437 // Need to make sure the suggested file name is not too long. |
437 uint32 max_path = GetMaxPathLengthForDirectory(saved_main_directory_path_); | 438 uint32 max_path = GetMaxPathLengthForDirectory(saved_main_directory_path_); |
438 | 439 |
439 // Get safe pure file name. | 440 // Get safe pure file name. |
440 if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext, | 441 if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext, |
441 max_path, &pure_file_name)) | 442 max_path, &pure_file_name)) |
442 return false; | 443 return false; |
443 | 444 |
444 FilePath::StringType file_name = pure_file_name + file_name_ext; | 445 base::FilePath::StringType file_name = pure_file_name + file_name_ext; |
445 | 446 |
446 // Check whether we already have same name in a case insensitive manner. | 447 // Check whether we already have same name in a case insensitive manner. |
447 FileNameSet::const_iterator iter = file_name_set_.find(file_name); | 448 FileNameSet::const_iterator iter = file_name_set_.find(file_name); |
448 if (iter == file_name_set_.end()) { | 449 if (iter == file_name_set_.end()) { |
449 file_name_set_.insert(file_name); | 450 file_name_set_.insert(file_name); |
450 } else { | 451 } else { |
451 // Found same name, increase the ordinal number for the file name. | 452 // Found same name, increase the ordinal number for the file name. |
452 pure_file_name = | 453 pure_file_name = |
453 FilePath(*iter).RemoveExtension().BaseName().value(); | 454 base::FilePath(*iter).RemoveExtension().BaseName().value(); |
454 FilePath::StringType base_file_name = StripOrdinalNumber(pure_file_name); | 455 base::FilePath::StringType base_file_name = |
| 456 StripOrdinalNumber(pure_file_name); |
455 | 457 |
456 // We need to make sure the length of base file name plus maximum ordinal | 458 // We need to make sure the length of base file name plus maximum ordinal |
457 // number path will be less than or equal to kMaxFilePathLength. | 459 // number path will be less than or equal to kMaxFilePathLength. |
458 if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext, | 460 if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext, |
459 max_path - kMaxFileOrdinalNumberPartLength, &base_file_name)) | 461 max_path - kMaxFileOrdinalNumberPartLength, &base_file_name)) |
460 return false; | 462 return false; |
461 | 463 |
462 // Prepare the new ordinal number. | 464 // Prepare the new ordinal number. |
463 uint32 ordinal_number; | 465 uint32 ordinal_number; |
464 FileNameCountMap::iterator it = file_name_count_map_.find(base_file_name); | 466 FileNameCountMap::iterator it = file_name_count_map_.find(base_file_name); |
465 if (it == file_name_count_map_.end()) { | 467 if (it == file_name_count_map_.end()) { |
466 // First base-name-conflict resolving, use 1 as initial ordinal number. | 468 // First base-name-conflict resolving, use 1 as initial ordinal number. |
467 file_name_count_map_[base_file_name] = 1; | 469 file_name_count_map_[base_file_name] = 1; |
468 ordinal_number = 1; | 470 ordinal_number = 1; |
469 } else { | 471 } else { |
470 // We have met same base-name conflict, use latest ordinal number. | 472 // We have met same base-name conflict, use latest ordinal number. |
471 ordinal_number = it->second; | 473 ordinal_number = it->second; |
472 } | 474 } |
473 | 475 |
474 if (ordinal_number > (kMaxFileOrdinalNumber - 1)) { | 476 if (ordinal_number > (kMaxFileOrdinalNumber - 1)) { |
475 // Use a random file from temporary file. | 477 // Use a random file from temporary file. |
476 FilePath temp_file; | 478 base::FilePath temp_file; |
477 file_util::CreateTemporaryFile(&temp_file); | 479 file_util::CreateTemporaryFile(&temp_file); |
478 file_name = temp_file.RemoveExtension().BaseName().value(); | 480 file_name = temp_file.RemoveExtension().BaseName().value(); |
479 // Get safe pure file name. | 481 // Get safe pure file name. |
480 if (!GetSafePureFileName(saved_main_directory_path_, | 482 if (!GetSafePureFileName(saved_main_directory_path_, |
481 FilePath::StringType(), | 483 base::FilePath::StringType(), |
482 max_path, &file_name)) | 484 max_path, &file_name)) |
483 return false; | 485 return false; |
484 } else { | 486 } else { |
485 for (int i = ordinal_number; i < kMaxFileOrdinalNumber; ++i) { | 487 for (int i = ordinal_number; i < kMaxFileOrdinalNumber; ++i) { |
486 FilePath::StringType new_name = base_file_name + | 488 base::FilePath::StringType new_name = base_file_name + |
487 StringPrintf(FILE_PATH_LITERAL("(%d)"), i) + file_name_ext; | 489 StringPrintf(FILE_PATH_LITERAL("(%d)"), i) + file_name_ext; |
488 if (file_name_set_.find(new_name) == file_name_set_.end()) { | 490 if (file_name_set_.find(new_name) == file_name_set_.end()) { |
489 // Resolved name conflict. | 491 // Resolved name conflict. |
490 file_name = new_name; | 492 file_name = new_name; |
491 file_name_count_map_[base_file_name] = ++i; | 493 file_name_count_map_[base_file_name] = ++i; |
492 break; | 494 break; |
493 } | 495 } |
494 } | 496 } |
495 } | 497 } |
496 | 498 |
(...skipping 21 matching lines...) Expand all Loading... |
518 | 520 |
519 DCHECK(!saved_main_file_path_.empty()); | 521 DCHECK(!saved_main_file_path_.empty()); |
520 | 522 |
521 save_item->SetSaveId(info->save_id); | 523 save_item->SetSaveId(info->save_id); |
522 save_item->SetTotalBytes(info->total_bytes); | 524 save_item->SetTotalBytes(info->total_bytes); |
523 | 525 |
524 // Determine the proper path for a saving job, by choosing either the default | 526 // Determine the proper path for a saving job, by choosing either the default |
525 // save directory, or prompting the user. | 527 // save directory, or prompting the user. |
526 DCHECK(!save_item->has_final_name()); | 528 DCHECK(!save_item->has_final_name()); |
527 if (info->url != page_url_) { | 529 if (info->url != page_url_) { |
528 FilePath::StringType generated_name; | 530 base::FilePath::StringType generated_name; |
529 // For HTML resource file, make sure it will have .htm as extension name, | 531 // For HTML resource file, make sure it will have .htm as extension name, |
530 // otherwise, when you open the saved page in Chrome again, download | 532 // otherwise, when you open the saved page in Chrome again, download |
531 // file manager will treat it as downloadable resource, and download it | 533 // file manager will treat it as downloadable resource, and download it |
532 // instead of opening it as HTML. | 534 // instead of opening it as HTML. |
533 bool need_html_ext = | 535 bool need_html_ext = |
534 info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_DOM; | 536 info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_DOM; |
535 if (!GenerateFileName(info->content_disposition, | 537 if (!GenerateFileName(info->content_disposition, |
536 GURL(info->url), | 538 GURL(info->url), |
537 need_html_ext, | 539 need_html_ext, |
538 &generated_name)) { | 540 &generated_name)) { |
(...skipping 10 matching lines...) Expand all Loading... |
549 return; | 551 return; |
550 } | 552 } |
551 | 553 |
552 // When saving page as only-HTML, we only have a SaveItem whose url | 554 // When saving page as only-HTML, we only have a SaveItem whose url |
553 // must be page_url_. | 555 // must be page_url_. |
554 DCHECK(save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML); | 556 DCHECK(save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML); |
555 DCHECK(!saved_main_directory_path_.empty()); | 557 DCHECK(!saved_main_directory_path_.empty()); |
556 | 558 |
557 // Now we get final name retrieved from GenerateFileName, we will use it | 559 // Now we get final name retrieved from GenerateFileName, we will use it |
558 // rename the SaveItem. | 560 // rename the SaveItem. |
559 FilePath final_name = saved_main_directory_path_.Append(generated_name); | 561 base::FilePath final_name = |
| 562 saved_main_directory_path_.Append(generated_name); |
560 save_item->Rename(final_name); | 563 save_item->Rename(final_name); |
561 } else { | 564 } else { |
562 // It is the main HTML file, use the name chosen by the user. | 565 // It is the main HTML file, use the name chosen by the user. |
563 save_item->Rename(saved_main_file_path_); | 566 save_item->Rename(saved_main_file_path_); |
564 } | 567 } |
565 | 568 |
566 // If the save source is from file system, inform SaveFileManager to copy | 569 // If the save source is from file system, inform SaveFileManager to copy |
567 // corresponding file to the file path which this SaveItem specifies. | 570 // corresponding file to the file path which this SaveItem specifies. |
568 if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_FILE) { | 571 if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_FILE) { |
569 BrowserThread::PostTask( | 572 BrowserThread::PostTask( |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 if (download_) { | 688 if (download_) { |
686 download_->Cancel(false); | 689 download_->Cancel(false); |
687 FinalizeDownloadEntry(); | 690 FinalizeDownloadEntry(); |
688 } | 691 } |
689 } | 692 } |
690 | 693 |
691 void SavePackage::CheckFinish() { | 694 void SavePackage::CheckFinish() { |
692 if (in_process_count() || finished_) | 695 if (in_process_count() || finished_) |
693 return; | 696 return; |
694 | 697 |
695 FilePath dir = (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML && | 698 base::FilePath dir = (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML && |
696 saved_success_items_.size() > 1) ? | 699 saved_success_items_.size() > 1) ? |
697 saved_main_directory_path_ : FilePath(); | 700 saved_main_directory_path_ : base::FilePath(); |
698 | 701 |
699 // This vector contains the final names of all the successfully saved files | 702 // This vector contains the final names of all the successfully saved files |
700 // along with their save ids. It will be passed to SaveFileManager to do the | 703 // along with their save ids. It will be passed to SaveFileManager to do the |
701 // renaming job. | 704 // renaming job. |
702 FinalNameList final_names; | 705 FinalNameList final_names; |
703 for (SavedItemMap::iterator it = saved_success_items_.begin(); | 706 for (SavedItemMap::iterator it = saved_success_items_.begin(); |
704 it != saved_success_items_.end(); ++it) | 707 it != saved_success_items_.end(); ++it) |
705 final_names.push_back(std::make_pair(it->first, | 708 final_names.push_back(std::make_pair(it->first, |
706 it->second->full_path())); | 709 it->second->full_path())); |
707 | 710 |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
965 } | 968 } |
966 | 969 |
967 // After finishing all SaveItems which need to get data from net. | 970 // After finishing all SaveItems which need to get data from net. |
968 // We collect all URLs which have local storage and send the | 971 // We collect all URLs which have local storage and send the |
969 // map:(originalURL:currentLocalPath) to render process (backend). | 972 // map:(originalURL:currentLocalPath) to render process (backend). |
970 // Then render process will serialize DOM and send data to us. | 973 // Then render process will serialize DOM and send data to us. |
971 void SavePackage::GetSerializedHtmlDataForCurrentPageWithLocalLinks() { | 974 void SavePackage::GetSerializedHtmlDataForCurrentPageWithLocalLinks() { |
972 if (wait_state_ != HTML_DATA) | 975 if (wait_state_ != HTML_DATA) |
973 return; | 976 return; |
974 std::vector<GURL> saved_links; | 977 std::vector<GURL> saved_links; |
975 std::vector<FilePath> saved_file_paths; | 978 std::vector<base::FilePath> saved_file_paths; |
976 int successful_started_items_count = 0; | 979 int successful_started_items_count = 0; |
977 | 980 |
978 // Collect all saved items which have local storage. | 981 // Collect all saved items which have local storage. |
979 // First collect the status of all the resource files and check whether they | 982 // First collect the status of all the resource files and check whether they |
980 // have created local files although they have not been completely saved. | 983 // have created local files although they have not been completely saved. |
981 // If yes, the file can be saved. Otherwise, there is a disk error, so we | 984 // If yes, the file can be saved. Otherwise, there is a disk error, so we |
982 // need to cancel the page saving job. | 985 // need to cancel the page saving job. |
983 for (SaveUrlItemMap::iterator it = in_progress_items_.begin(); | 986 for (SaveUrlItemMap::iterator it = in_progress_items_.begin(); |
984 it != in_progress_items_.end(); ++it) { | 987 it != in_progress_items_.end(); ++it) { |
985 DCHECK(it->second->save_source() == | 988 DCHECK(it->second->save_source() == |
(...skipping 10 matching lines...) Expand all Loading... |
996 | 999 |
997 // Collect all saved success items. | 1000 // Collect all saved success items. |
998 for (SavedItemMap::iterator it = saved_success_items_.begin(); | 1001 for (SavedItemMap::iterator it = saved_success_items_.begin(); |
999 it != saved_success_items_.end(); ++it) { | 1002 it != saved_success_items_.end(); ++it) { |
1000 DCHECK(it->second->has_final_name()); | 1003 DCHECK(it->second->has_final_name()); |
1001 saved_links.push_back(it->second->url()); | 1004 saved_links.push_back(it->second->url()); |
1002 saved_file_paths.push_back(it->second->file_name()); | 1005 saved_file_paths.push_back(it->second->file_name()); |
1003 } | 1006 } |
1004 | 1007 |
1005 // Get the relative directory name. | 1008 // Get the relative directory name. |
1006 FilePath relative_dir_name = saved_main_directory_path_.BaseName(); | 1009 base::FilePath relative_dir_name = saved_main_directory_path_.BaseName(); |
1007 | 1010 |
1008 Send(new ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks( | 1011 Send(new ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks( |
1009 routing_id(), saved_links, saved_file_paths, relative_dir_name)); | 1012 routing_id(), saved_links, saved_file_paths, relative_dir_name)); |
1010 } | 1013 } |
1011 | 1014 |
1012 // Process the serialized HTML content data of a specified web page | 1015 // Process the serialized HTML content data of a specified web page |
1013 // retrieved from render process. | 1016 // retrieved from render process. |
1014 void SavePackage::OnReceivedSerializedHtmlData(const GURL& frame_url, | 1017 void SavePackage::OnReceivedSerializedHtmlData(const GURL& frame_url, |
1015 const std::string& data, | 1018 const std::string& data, |
1016 int32 status) { | 1019 int32 status) { |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1147 waiting_item_queue_.push(save_item); | 1150 waiting_item_queue_.push(save_item); |
1148 } | 1151 } |
1149 wait_state_ = NET_FILES; | 1152 wait_state_ = NET_FILES; |
1150 DoSavingProcess(); | 1153 DoSavingProcess(); |
1151 } else { | 1154 } else { |
1152 // No resource files need to be saved, treat it as user cancel. | 1155 // No resource files need to be saved, treat it as user cancel. |
1153 Cancel(true); | 1156 Cancel(true); |
1154 } | 1157 } |
1155 } | 1158 } |
1156 | 1159 |
1157 FilePath SavePackage::GetSuggestedNameForSaveAs( | 1160 base::FilePath SavePackage::GetSuggestedNameForSaveAs( |
1158 bool can_save_as_complete, | 1161 bool can_save_as_complete, |
1159 const std::string& contents_mime_type, | 1162 const std::string& contents_mime_type, |
1160 const std::string& accept_langs) { | 1163 const std::string& accept_langs) { |
1161 FilePath name_with_proper_ext = | 1164 base::FilePath name_with_proper_ext = |
1162 FilePath::FromWStringHack(UTF16ToWideHack(title_)); | 1165 base::FilePath::FromWStringHack(UTF16ToWideHack(title_)); |
1163 | 1166 |
1164 // If the page's title matches its URL, use the URL. Try to use the last path | 1167 // If the page's title matches its URL, use the URL. Try to use the last path |
1165 // component or if there is none, the domain as the file name. | 1168 // component or if there is none, the domain as the file name. |
1166 // Normally we want to base the filename on the page title, or if it doesn't | 1169 // Normally we want to base the filename on the page title, or if it doesn't |
1167 // exist, on the URL. It's not easy to tell if the page has no title, because | 1170 // exist, on the URL. It's not easy to tell if the page has no title, because |
1168 // if the page has no title, WebContents::GetTitle() will return the page's | 1171 // if the page has no title, WebContents::GetTitle() will return the page's |
1169 // URL (adjusted for display purposes). Therefore, we convert the "title" | 1172 // URL (adjusted for display purposes). Therefore, we convert the "title" |
1170 // back to a URL, and if it matches the original page URL, we know the page | 1173 // back to a URL, and if it matches the original page URL, we know the page |
1171 // had no title (or had a title equal to its URL, which is fine to treat | 1174 // had no title (or had a title equal to its URL, which is fine to treat |
1172 // similarly). | 1175 // similarly). |
1173 if (title_ == net::FormatUrl(page_url_, accept_langs)) { | 1176 if (title_ == net::FormatUrl(page_url_, accept_langs)) { |
1174 std::string url_path; | 1177 std::string url_path; |
1175 if (!page_url_.SchemeIs(chrome::kDataScheme)) { | 1178 if (!page_url_.SchemeIs(chrome::kDataScheme)) { |
1176 std::vector<std::string> url_parts; | 1179 std::vector<std::string> url_parts; |
1177 base::SplitString(page_url_.path(), '/', &url_parts); | 1180 base::SplitString(page_url_.path(), '/', &url_parts); |
1178 if (!url_parts.empty()) { | 1181 if (!url_parts.empty()) { |
1179 for (int i = static_cast<int>(url_parts.size()) - 1; i >= 0; --i) { | 1182 for (int i = static_cast<int>(url_parts.size()) - 1; i >= 0; --i) { |
1180 url_path = url_parts[i]; | 1183 url_path = url_parts[i]; |
1181 if (!url_path.empty()) | 1184 if (!url_path.empty()) |
1182 break; | 1185 break; |
1183 } | 1186 } |
1184 } | 1187 } |
1185 if (url_path.empty()) | 1188 if (url_path.empty()) |
1186 url_path = page_url_.host(); | 1189 url_path = page_url_.host(); |
1187 } else { | 1190 } else { |
1188 url_path = "dataurl"; | 1191 url_path = "dataurl"; |
1189 } | 1192 } |
1190 name_with_proper_ext = FilePath::FromWStringHack(UTF8ToWide(url_path)); | 1193 name_with_proper_ext = |
| 1194 base::FilePath::FromWStringHack(UTF8ToWide(url_path)); |
1191 } | 1195 } |
1192 | 1196 |
1193 // Ask user for getting final saving name. | 1197 // Ask user for getting final saving name. |
1194 name_with_proper_ext = EnsureMimeExtension(name_with_proper_ext, | 1198 name_with_proper_ext = EnsureMimeExtension(name_with_proper_ext, |
1195 contents_mime_type); | 1199 contents_mime_type); |
1196 // Adjust extension for complete types. | 1200 // Adjust extension for complete types. |
1197 if (can_save_as_complete) | 1201 if (can_save_as_complete) |
1198 name_with_proper_ext = EnsureHtmlExtension(name_with_proper_ext); | 1202 name_with_proper_ext = EnsureHtmlExtension(name_with_proper_ext); |
1199 | 1203 |
1200 FilePath::StringType file_name = name_with_proper_ext.value(); | 1204 base::FilePath::StringType file_name = name_with_proper_ext.value(); |
1201 file_util::ReplaceIllegalCharactersInPath(&file_name, ' '); | 1205 file_util::ReplaceIllegalCharactersInPath(&file_name, ' '); |
1202 return FilePath(file_name); | 1206 return base::FilePath(file_name); |
1203 } | 1207 } |
1204 | 1208 |
1205 FilePath SavePackage::EnsureHtmlExtension(const FilePath& name) { | 1209 base::FilePath SavePackage::EnsureHtmlExtension(const base::FilePath& name) { |
1206 // If the file name doesn't have an extension suitable for HTML files, | 1210 // If the file name doesn't have an extension suitable for HTML files, |
1207 // append one. | 1211 // append one. |
1208 FilePath::StringType ext = name.Extension(); | 1212 base::FilePath::StringType ext = name.Extension(); |
1209 if (!ext.empty()) | 1213 if (!ext.empty()) |
1210 ext.erase(ext.begin()); // Erase preceding '.'. | 1214 ext.erase(ext.begin()); // Erase preceding '.'. |
1211 std::string mime_type; | 1215 std::string mime_type; |
1212 if (!net::GetMimeTypeFromExtension(ext, &mime_type) || | 1216 if (!net::GetMimeTypeFromExtension(ext, &mime_type) || |
1213 !CanSaveAsComplete(mime_type)) { | 1217 !CanSaveAsComplete(mime_type)) { |
1214 return FilePath(name.value() + FILE_PATH_LITERAL(".") + | 1218 return base::FilePath(name.value() + FILE_PATH_LITERAL(".") + |
1215 kDefaultHtmlExtension); | 1219 kDefaultHtmlExtension); |
1216 } | 1220 } |
1217 return name; | 1221 return name; |
1218 } | 1222 } |
1219 | 1223 |
1220 FilePath SavePackage::EnsureMimeExtension(const FilePath& name, | 1224 base::FilePath SavePackage::EnsureMimeExtension(const base::FilePath& name, |
1221 const std::string& contents_mime_type) { | 1225 const std::string& contents_mime_type) { |
1222 // Start extension at 1 to skip over period if non-empty. | 1226 // Start extension at 1 to skip over period if non-empty. |
1223 FilePath::StringType ext = name.Extension().length() ? | 1227 base::FilePath::StringType ext = name.Extension().length() ? |
1224 name.Extension().substr(1) : name.Extension(); | 1228 name.Extension().substr(1) : name.Extension(); |
1225 FilePath::StringType suggested_extension = | 1229 base::FilePath::StringType suggested_extension = |
1226 ExtensionForMimeType(contents_mime_type); | 1230 ExtensionForMimeType(contents_mime_type); |
1227 std::string mime_type; | 1231 std::string mime_type; |
1228 if (!suggested_extension.empty() && | 1232 if (!suggested_extension.empty() && |
1229 !net::GetMimeTypeFromExtension(ext, &mime_type)) { | 1233 !net::GetMimeTypeFromExtension(ext, &mime_type)) { |
1230 // Extension is absent or needs to be updated. | 1234 // Extension is absent or needs to be updated. |
1231 return FilePath(name.value() + FILE_PATH_LITERAL(".") + | 1235 return base::FilePath(name.value() + FILE_PATH_LITERAL(".") + |
1232 suggested_extension); | 1236 suggested_extension); |
1233 } | 1237 } |
1234 return name; | 1238 return name; |
1235 } | 1239 } |
1236 | 1240 |
1237 const FilePath::CharType* SavePackage::ExtensionForMimeType( | 1241 const base::FilePath::CharType* SavePackage::ExtensionForMimeType( |
1238 const std::string& contents_mime_type) { | 1242 const std::string& contents_mime_type) { |
1239 static const struct { | 1243 static const struct { |
1240 const FilePath::CharType *mime_type; | 1244 const base::FilePath::CharType *mime_type; |
1241 const FilePath::CharType *suggested_extension; | 1245 const base::FilePath::CharType *suggested_extension; |
1242 } extensions[] = { | 1246 } extensions[] = { |
1243 { FILE_PATH_LITERAL("text/html"), kDefaultHtmlExtension }, | 1247 { FILE_PATH_LITERAL("text/html"), kDefaultHtmlExtension }, |
1244 { FILE_PATH_LITERAL("text/xml"), FILE_PATH_LITERAL("xml") }, | 1248 { FILE_PATH_LITERAL("text/xml"), FILE_PATH_LITERAL("xml") }, |
1245 { FILE_PATH_LITERAL("application/xhtml+xml"), FILE_PATH_LITERAL("xhtml") }, | 1249 { FILE_PATH_LITERAL("application/xhtml+xml"), FILE_PATH_LITERAL("xhtml") }, |
1246 { FILE_PATH_LITERAL("text/plain"), FILE_PATH_LITERAL("txt") }, | 1250 { FILE_PATH_LITERAL("text/plain"), FILE_PATH_LITERAL("txt") }, |
1247 { FILE_PATH_LITERAL("text/css"), FILE_PATH_LITERAL("css") }, | 1251 { FILE_PATH_LITERAL("text/css"), FILE_PATH_LITERAL("css") }, |
1248 }; | 1252 }; |
1249 #if defined(OS_POSIX) | 1253 #if defined(OS_POSIX) |
1250 FilePath::StringType mime_type(contents_mime_type); | 1254 base::FilePath::StringType mime_type(contents_mime_type); |
1251 #elif defined(OS_WIN) | 1255 #elif defined(OS_WIN) |
1252 FilePath::StringType mime_type(UTF8ToWide(contents_mime_type)); | 1256 base::FilePath::StringType mime_type(UTF8ToWide(contents_mime_type)); |
1253 #endif // OS_WIN | 1257 #endif // OS_WIN |
1254 for (uint32 i = 0; i < ARRAYSIZE_UNSAFE(extensions); ++i) { | 1258 for (uint32 i = 0; i < ARRAYSIZE_UNSAFE(extensions); ++i) { |
1255 if (mime_type == extensions[i].mime_type) | 1259 if (mime_type == extensions[i].mime_type) |
1256 return extensions[i].suggested_extension; | 1260 return extensions[i].suggested_extension; |
1257 } | 1261 } |
1258 return FILE_PATH_LITERAL(""); | 1262 return FILE_PATH_LITERAL(""); |
1259 } | 1263 } |
1260 | 1264 |
1261 WebContents* SavePackage::web_contents() const { | 1265 WebContents* SavePackage::web_contents() const { |
1262 return WebContentsObserver::web_contents(); | 1266 return WebContentsObserver::web_contents(); |
1263 } | 1267 } |
1264 | 1268 |
1265 void SavePackage::GetSaveInfo() { | 1269 void SavePackage::GetSaveInfo() { |
1266 // Can't use web_contents_ in the file thread, so get the data that we need | 1270 // Can't use web_contents_ in the file thread, so get the data that we need |
1267 // before calling to it. | 1271 // before calling to it. |
1268 FilePath website_save_dir, download_save_dir; | 1272 base::FilePath website_save_dir, download_save_dir; |
1269 bool skip_dir_check; | 1273 bool skip_dir_check; |
1270 DCHECK(download_manager_); | 1274 DCHECK(download_manager_); |
1271 if (download_manager_->GetDelegate()) { | 1275 if (download_manager_->GetDelegate()) { |
1272 download_manager_->GetDelegate()->GetSaveDir( | 1276 download_manager_->GetDelegate()->GetSaveDir( |
1273 web_contents()->GetBrowserContext(), &website_save_dir, | 1277 web_contents()->GetBrowserContext(), &website_save_dir, |
1274 &download_save_dir, &skip_dir_check); | 1278 &download_save_dir, &skip_dir_check); |
1275 } | 1279 } |
1276 std::string mime_type = web_contents()->GetContentsMimeType(); | 1280 std::string mime_type = web_contents()->GetContentsMimeType(); |
1277 std::string accept_languages = | 1281 std::string accept_languages = |
1278 GetContentClient()->browser()->GetAcceptLangs( | 1282 GetContentClient()->browser()->GetAcceptLangs( |
1279 web_contents()->GetBrowserContext()); | 1283 web_contents()->GetBrowserContext()); |
1280 | 1284 |
1281 BrowserThread::PostTask( | 1285 BrowserThread::PostTask( |
1282 BrowserThread::FILE, FROM_HERE, | 1286 BrowserThread::FILE, FROM_HERE, |
1283 base::Bind(&SavePackage::CreateDirectoryOnFileThread, this, | 1287 base::Bind(&SavePackage::CreateDirectoryOnFileThread, this, |
1284 website_save_dir, download_save_dir, skip_dir_check, | 1288 website_save_dir, download_save_dir, skip_dir_check, |
1285 mime_type, accept_languages)); | 1289 mime_type, accept_languages)); |
1286 } | 1290 } |
1287 | 1291 |
1288 void SavePackage::CreateDirectoryOnFileThread( | 1292 void SavePackage::CreateDirectoryOnFileThread( |
1289 const FilePath& website_save_dir, | 1293 const base::FilePath& website_save_dir, |
1290 const FilePath& download_save_dir, | 1294 const base::FilePath& download_save_dir, |
1291 bool skip_dir_check, | 1295 bool skip_dir_check, |
1292 const std::string& mime_type, | 1296 const std::string& mime_type, |
1293 const std::string& accept_langs) { | 1297 const std::string& accept_langs) { |
1294 FilePath save_dir; | 1298 base::FilePath save_dir; |
1295 // If the default html/websites save folder doesn't exist... | 1299 // If the default html/websites save folder doesn't exist... |
1296 // We skip the directory check for gdata directories on ChromeOS. | 1300 // We skip the directory check for gdata directories on ChromeOS. |
1297 if (!skip_dir_check && !file_util::DirectoryExists(website_save_dir)) { | 1301 if (!skip_dir_check && !file_util::DirectoryExists(website_save_dir)) { |
1298 // If the default download dir doesn't exist, create it. | 1302 // If the default download dir doesn't exist, create it. |
1299 if (!file_util::DirectoryExists(download_save_dir)) { | 1303 if (!file_util::DirectoryExists(download_save_dir)) { |
1300 bool res = file_util::CreateDirectory(download_save_dir); | 1304 bool res = file_util::CreateDirectory(download_save_dir); |
1301 DCHECK(res); | 1305 DCHECK(res); |
1302 } | 1306 } |
1303 save_dir = download_save_dir; | 1307 save_dir = download_save_dir; |
1304 } else { | 1308 } else { |
1305 // If it does exist, use the default save dir param. | 1309 // If it does exist, use the default save dir param. |
1306 save_dir = website_save_dir; | 1310 save_dir = website_save_dir; |
1307 } | 1311 } |
1308 | 1312 |
1309 bool can_save_as_complete = CanSaveAsComplete(mime_type); | 1313 bool can_save_as_complete = CanSaveAsComplete(mime_type); |
1310 FilePath suggested_filename = GetSuggestedNameForSaveAs( | 1314 base::FilePath suggested_filename = GetSuggestedNameForSaveAs( |
1311 can_save_as_complete, mime_type, accept_langs); | 1315 can_save_as_complete, mime_type, accept_langs); |
1312 FilePath::StringType pure_file_name = | 1316 base::FilePath::StringType pure_file_name = |
1313 suggested_filename.RemoveExtension().BaseName().value(); | 1317 suggested_filename.RemoveExtension().BaseName().value(); |
1314 FilePath::StringType file_name_ext = suggested_filename.Extension(); | 1318 base::FilePath::StringType file_name_ext = suggested_filename.Extension(); |
1315 | 1319 |
1316 // Need to make sure the suggested file name is not too long. | 1320 // Need to make sure the suggested file name is not too long. |
1317 uint32 max_path = GetMaxPathLengthForDirectory(save_dir); | 1321 uint32 max_path = GetMaxPathLengthForDirectory(save_dir); |
1318 | 1322 |
1319 if (GetSafePureFileName(save_dir, file_name_ext, max_path, &pure_file_name)) { | 1323 if (GetSafePureFileName(save_dir, file_name_ext, max_path, &pure_file_name)) { |
1320 save_dir = save_dir.Append(pure_file_name + file_name_ext); | 1324 save_dir = save_dir.Append(pure_file_name + file_name_ext); |
1321 } else { | 1325 } else { |
1322 // Cannot create a shorter filename. This will cause the save as operation | 1326 // Cannot create a shorter filename. This will cause the save as operation |
1323 // to fail unless the user pick a shorter name. Continuing even though it | 1327 // to fail unless the user pick a shorter name. Continuing even though it |
1324 // will fail because returning means no save as popup for the user, which | 1328 // will fail because returning means no save as popup for the user, which |
1325 // is even more confusing. This case should be rare though. | 1329 // is even more confusing. This case should be rare though. |
1326 save_dir = save_dir.Append(suggested_filename); | 1330 save_dir = save_dir.Append(suggested_filename); |
1327 } | 1331 } |
1328 | 1332 |
1329 BrowserThread::PostTask( | 1333 BrowserThread::PostTask( |
1330 BrowserThread::UI, FROM_HERE, | 1334 BrowserThread::UI, FROM_HERE, |
1331 base::Bind(&SavePackage::ContinueGetSaveInfo, this, save_dir, | 1335 base::Bind(&SavePackage::ContinueGetSaveInfo, this, save_dir, |
1332 can_save_as_complete)); | 1336 can_save_as_complete)); |
1333 } | 1337 } |
1334 | 1338 |
1335 void SavePackage::ContinueGetSaveInfo(const FilePath& suggested_path, | 1339 void SavePackage::ContinueGetSaveInfo(const base::FilePath& suggested_path, |
1336 bool can_save_as_complete) { | 1340 bool can_save_as_complete) { |
1337 | 1341 |
1338 // The WebContents which owns this SavePackage may have disappeared during | 1342 // The WebContents which owns this SavePackage may have disappeared during |
1339 // the UI->FILE->UI thread hop of | 1343 // the UI->FILE->UI thread hop of |
1340 // GetSaveInfo->CreateDirectoryOnFileThread->ContinueGetSaveInfo. | 1344 // GetSaveInfo->CreateDirectoryOnFileThread->ContinueGetSaveInfo. |
1341 if (!web_contents() || !download_manager_->GetDelegate()) | 1345 if (!web_contents() || !download_manager_->GetDelegate()) |
1342 return; | 1346 return; |
1343 | 1347 |
1344 FilePath::StringType default_extension; | 1348 base::FilePath::StringType default_extension; |
1345 if (can_save_as_complete) | 1349 if (can_save_as_complete) |
1346 default_extension = kDefaultHtmlExtension; | 1350 default_extension = kDefaultHtmlExtension; |
1347 | 1351 |
1348 download_manager_->GetDelegate()->ChooseSavePath( | 1352 download_manager_->GetDelegate()->ChooseSavePath( |
1349 web_contents(), | 1353 web_contents(), |
1350 suggested_path, | 1354 suggested_path, |
1351 default_extension, | 1355 default_extension, |
1352 can_save_as_complete, | 1356 can_save_as_complete, |
1353 base::Bind(&SavePackage::OnPathPicked, AsWeakPtr())); | 1357 base::Bind(&SavePackage::OnPathPicked, AsWeakPtr())); |
1354 } | 1358 } |
1355 | 1359 |
1356 void SavePackage::OnPathPicked( | 1360 void SavePackage::OnPathPicked( |
1357 const FilePath& final_name, | 1361 const base::FilePath& final_name, |
1358 SavePageType type, | 1362 SavePageType type, |
1359 const SavePackageDownloadCreatedCallback& download_created_callback) { | 1363 const SavePackageDownloadCreatedCallback& download_created_callback) { |
1360 // Ensure the filename is safe. | 1364 // Ensure the filename is safe. |
1361 saved_main_file_path_ = final_name; | 1365 saved_main_file_path_ = final_name; |
1362 // TODO(asanka): This call may block on IO and shouldn't be made | 1366 // TODO(asanka): This call may block on IO and shouldn't be made |
1363 // from the UI thread. See http://crbug.com/61827. | 1367 // from the UI thread. See http://crbug.com/61827. |
1364 net::GenerateSafeFileName(web_contents()->GetContentsMimeType(), false, | 1368 net::GenerateSafeFileName(web_contents()->GetContentsMimeType(), false, |
1365 &saved_main_file_path_); | 1369 &saved_main_file_path_); |
1366 | 1370 |
1367 saved_main_directory_path_ = saved_main_file_path_.DirName(); | 1371 saved_main_directory_path_ = saved_main_file_path_.DirName(); |
(...skipping 23 matching lines...) Expand all Loading... |
1391 | 1395 |
1392 void SavePackage::FinalizeDownloadEntry() { | 1396 void SavePackage::FinalizeDownloadEntry() { |
1393 DCHECK(download_); | 1397 DCHECK(download_); |
1394 DCHECK(download_manager_); | 1398 DCHECK(download_manager_); |
1395 | 1399 |
1396 download_manager_->OnSavePackageSuccessfullyFinished(download_); | 1400 download_manager_->OnSavePackageSuccessfullyFinished(download_); |
1397 StopObservation(); | 1401 StopObservation(); |
1398 } | 1402 } |
1399 | 1403 |
1400 } // namespace content | 1404 } // namespace content |
OLD | NEW |