Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: content/browser/download/save_package.cc

Issue 1484093002: Allowing multiple SaveItems to have same URLs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@nested-frames-more-involved-fix
Patch Set: Rebasing... Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/files/file_path.h" 10 #include "base/files/file_path.h"
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 generated_name->assign(file_name); 544 generated_name->assign(file_name);
545 545
546 return true; 546 return true;
547 } 547 }
548 548
549 // We have received a message from SaveFileManager about a new saving job. We 549 // We have received a message from SaveFileManager about a new saving job. We
550 // create a SaveItem and store it in our in_progress list. 550 // create a SaveItem and store it in our in_progress list.
551 void SavePackage::StartSave(const SaveFileCreateInfo* info) { 551 void SavePackage::StartSave(const SaveFileCreateInfo* info) {
552 DCHECK(info && !info->url.is_empty()); 552 DCHECK(info && !info->url.is_empty());
553 553
554 SaveUrlItemMap::iterator it = in_progress_items_.find(info->url.spec()); 554 SaveItemIdMap::iterator it = in_progress_items_.find(info->save_item_id);
555 if (it == in_progress_items_.end()) { 555 if (it == in_progress_items_.end()) {
556 // If not found, we must have cancel action. 556 // If not found, we must have cancel action.
557 DCHECK(canceled()); 557 DCHECK(canceled());
558 return; 558 return;
559 } 559 }
560 SaveItem* save_item = it->second; 560 SaveItem* save_item = it->second;
561 561
562 DCHECK(!saved_main_file_path_.empty()); 562 DCHECK(!saved_main_file_path_.empty());
563 563
564 save_item->SetSaveId(info->save_id);
565 save_item->SetTotalBytes(info->total_bytes); 564 save_item->SetTotalBytes(info->total_bytes);
566 565
567 // Determine the proper path for a saving job, by choosing either the default 566 // Determine the proper path for a saving job, by choosing either the default
568 // save directory, or prompting the user. 567 // save directory, or prompting the user.
569 DCHECK(!save_item->has_final_name()); 568 DCHECK(!save_item->has_final_name());
570 if (info->url != page_url_) { 569 if (info->url != page_url_) {
571 base::FilePath::StringType generated_name; 570 base::FilePath::StringType generated_name;
572 // For HTML resource file, make sure it will have .htm as extension name, 571 // For HTML resource file, make sure it will have .htm as extension name,
573 // otherwise, when you open the saved page in Chrome again, download 572 // otherwise, when you open the saved page in Chrome again, download
574 // file manager will treat it as downloadable resource, and download it 573 // file manager will treat it as downloadable resource, and download it
575 // instead of opening it as HTML. 574 // instead of opening it as HTML.
576 bool need_html_ext = 575 bool need_html_ext =
577 info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_DOM; 576 info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_DOM;
578 if (!GenerateFileName(info->content_disposition, 577 if (!GenerateFileName(info->content_disposition,
579 GURL(info->url), 578 GURL(info->url),
580 need_html_ext, 579 need_html_ext,
581 &generated_name)) { 580 &generated_name)) {
582 // We can not generate file name for this SaveItem, so we cancel the 581 // We can not generate file name for this SaveItem, so we cancel the
583 // saving page job if the save source is from serialized DOM data. 582 // saving page job if the save source is from serialized DOM data.
584 // Otherwise, it means this SaveItem is sub-resource type, we treat it 583 // Otherwise, it means this SaveItem is sub-resource type, we treat it
585 // as an error happened on saving. We can ignore this type error for 584 // as an error happened on saving. We can ignore this type error for
586 // sub-resource links which will be resolved as absolute links instead 585 // sub-resource links which will be resolved as absolute links instead
587 // of local links in final saved contents. 586 // of local links in final saved contents.
588 if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_DOM) 587 if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_DOM)
589 Cancel(true); 588 Cancel(true);
590 else 589 else
591 SaveFinished(save_item->save_id(), 0, false); 590 SaveFinished(save_item->id(), 0, false);
592 return; 591 return;
593 } 592 }
594 593
595 // When saving page as only-HTML, we only have a SaveItem whose url 594 // When saving page as only-HTML, we only have a SaveItem whose url
596 // must be page_url_. 595 // must be page_url_.
597 DCHECK_EQ(SAVE_PAGE_TYPE_AS_COMPLETE_HTML, save_type_); 596 DCHECK_EQ(SAVE_PAGE_TYPE_AS_COMPLETE_HTML, save_type_);
598 DCHECK(!saved_main_directory_path_.empty()); 597 DCHECK(!saved_main_directory_path_.empty());
599 598
600 // Now we get final name retrieved from GenerateFileName, we will use it 599 // Now we get final name retrieved from GenerateFileName, we will use it
601 // rename the SaveItem. 600 // rename the SaveItem.
602 base::FilePath final_name = 601 base::FilePath final_name =
603 saved_main_directory_path_.Append(generated_name); 602 saved_main_directory_path_.Append(generated_name);
604 save_item->Rename(final_name); 603 save_item->Rename(final_name);
605 } else { 604 } else {
606 // It is the main HTML file, use the name chosen by the user. 605 // It is the main HTML file, use the name chosen by the user.
607 save_item->Rename(saved_main_file_path_); 606 save_item->Rename(saved_main_file_path_);
608 } 607 }
609 608
610 // If the save source is from file system, inform SaveFileManager to copy 609 // If the save source is from file system, inform SaveFileManager to copy
611 // corresponding file to the file path which this SaveItem specifies. 610 // corresponding file to the file path which this SaveItem specifies.
612 if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_FILE) { 611 if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_FILE) {
613 BrowserThread::PostTask( 612 BrowserThread::PostTask(
614 BrowserThread::FILE, FROM_HERE, 613 BrowserThread::FILE, FROM_HERE,
615 base::Bind(&SaveFileManager::SaveLocalFile, file_manager_, 614 base::Bind(&SaveFileManager::SaveLocalFile, file_manager_,
616 save_item->url(), save_item->save_id(), id())); 615 save_item->url(), save_item->id(), id()));
617 return; 616 return;
618 } 617 }
619 618
620 // Check whether we begin to require serialized HTML data. 619 // Check whether we begin to require serialized HTML data.
621 if (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML && 620 if (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML &&
622 wait_state_ == HTML_DATA) { 621 wait_state_ == HTML_DATA) {
623 // Inform backend to serialize the all frames' DOM and send serialized 622 // Inform backend to serialize the all frames' DOM and send serialized
624 // HTML data back. 623 // HTML data back.
625 GetSerializedHtmlWithLocalLinks(); 624 GetSerializedHtmlWithLocalLinks();
626 } 625 }
627 } 626 }
628 627
629 SaveItem* SavePackage::LookupItemInProcessBySaveId(int32 save_id) { 628 SaveItem* SavePackage::LookupSaveItemInProcess(int32 save_item_id) {
630 if (in_process_count()) { 629 auto it = in_progress_items_.find(save_item_id);
631 for (SaveUrlItemMap::iterator it = in_progress_items_.begin(); 630 if (it != in_progress_items_.end()) {
632 it != in_progress_items_.end(); ++it) { 631 SaveItem* save_item = it->second;
633 SaveItem* save_item = it->second; 632 DCHECK_EQ(SaveItem::IN_PROGRESS, save_item->state());
634 DCHECK_EQ(SaveItem::IN_PROGRESS, save_item->state()); 633 return save_item;
635 if (save_item->save_id() == save_id)
636 return save_item;
637 }
638 } 634 }
639 return NULL; 635 return nullptr;
640 } 636 }
641 637
642 void SavePackage::PutInProgressItemToSavedMap(SaveItem* save_item) { 638 void SavePackage::PutInProgressItemToSavedMap(SaveItem* save_item) {
643 SaveUrlItemMap::iterator it = in_progress_items_.find( 639 SaveItemIdMap::iterator it = in_progress_items_.find(save_item->id());
644 save_item->url().spec());
645 DCHECK(it != in_progress_items_.end()); 640 DCHECK(it != in_progress_items_.end());
646 DCHECK(save_item == it->second); 641 DCHECK(save_item == it->second);
647 in_progress_items_.erase(it); 642 in_progress_items_.erase(it);
648 643
649 if (save_item->success()) { 644 if (save_item->success()) {
650 // Add it to saved_success_items_. 645 // Add it to saved_success_items_.
651 DCHECK(saved_success_items_.find(save_item->save_id()) == 646 DCHECK(saved_success_items_.find(save_item->id()) ==
652 saved_success_items_.end()); 647 saved_success_items_.end());
653 saved_success_items_[save_item->save_id()] = save_item; 648 saved_success_items_[save_item->id()] = save_item;
654 } else { 649 } else {
655 // Add it to saved_failed_items_. 650 // Add it to saved_failed_items_.
656 DCHECK(saved_failed_items_.find(save_item->url().spec()) == 651 DCHECK(saved_failed_items_.find(save_item->id()) ==
657 saved_failed_items_.end()); 652 saved_failed_items_.end());
658 saved_failed_items_[save_item->url().spec()] = save_item; 653 saved_failed_items_[save_item->id()] = save_item;
659 } 654 }
660 } 655 }
661 656
662 // Called for updating saving state. 657 // Called for updating saving state.
663 bool SavePackage::UpdateSaveProgress(int32 save_id, 658 bool SavePackage::UpdateSaveProgress(int32 save_item_id,
664 int64 size, 659 int64 size,
665 bool write_success) { 660 bool write_success) {
666 // Because we might have canceled this saving job before, 661 // Because we might have canceled this saving job before,
667 // so we might not find corresponding SaveItem. 662 // so we might not find corresponding SaveItem.
668 SaveItem* save_item = LookupItemInProcessBySaveId(save_id); 663 SaveItem* save_item = LookupSaveItemInProcess(save_item_id);
669 if (!save_item) 664 if (!save_item)
670 return false; 665 return false;
671 666
672 save_item->Update(size); 667 save_item->Update(size);
673 668
674 // If we got disk error, cancel whole save page job. 669 // If we got disk error, cancel whole save page job.
675 if (!write_success) { 670 if (!write_success) {
676 // Cancel job with reason of disk error. 671 // Cancel job with reason of disk error.
677 Cancel(false); 672 Cancel(false);
678 } 673 }
679 return true; 674 return true;
680 } 675 }
681 676
682 // Stop all page saving jobs that are in progress and instruct the file thread 677 // Stop all page saving jobs that are in progress and instruct the file thread
683 // to delete all saved files. 678 // to delete all saved files.
684 void SavePackage::Stop() { 679 void SavePackage::Stop() {
685 // If we haven't moved out of the initial state, there's nothing to cancel and 680 // If we haven't moved out of the initial state, there's nothing to cancel and
686 // there won't be valid pointers for file_manager_ or download_. 681 // there won't be valid pointers for file_manager_ or download_.
687 if (wait_state_ == INITIALIZE) 682 if (wait_state_ == INITIALIZE)
688 return; 683 return;
689 684
690 // When stopping, if it still has some items in in_progress, cancel them. 685 // When stopping, if it still has some items in in_progress, cancel them.
691 DCHECK(canceled()); 686 DCHECK(canceled());
692 if (in_process_count()) { 687 if (in_process_count()) {
693 SaveUrlItemMap::iterator it = in_progress_items_.begin(); 688 SaveItemIdMap::iterator it = in_progress_items_.begin();
694 for (; it != in_progress_items_.end(); ++it) { 689 for (; it != in_progress_items_.end(); ++it) {
695 SaveItem* save_item = it->second; 690 SaveItem* save_item = it->second;
696 DCHECK_EQ(SaveItem::IN_PROGRESS, save_item->state()); 691 DCHECK_EQ(SaveItem::IN_PROGRESS, save_item->state());
697 save_item->Cancel(); 692 save_item->Cancel();
698 } 693 }
699 // Remove all in progress item to saved map. For failed items, they will 694 // Remove all in progress item to saved map. For failed items, they will
700 // be put into saved_failed_items_, for successful item, they will be put 695 // be put into saved_failed_items_, for successful item, they will be put
701 // into saved_success_items_. 696 // into saved_success_items_.
702 while (in_process_count()) 697 while (in_process_count())
703 PutInProgressItemToSavedMap(in_progress_items_.begin()->second); 698 PutInProgressItemToSavedMap(in_progress_items_.begin()->second);
704 } 699 }
705 700
706 // This vector contains the save ids of the save files which SaveFileManager 701 // This vector contains the save ids of the save files which SaveFileManager
707 // needs to remove from its save_file_map_. 702 // needs to remove from its save_file_map_.
708 SaveIDList save_ids; 703 std::vector<int> save_item_ids;
709 for (SavedItemMap::iterator it = saved_success_items_.begin(); 704 for (const auto& it : saved_success_items_)
710 it != saved_success_items_.end(); ++it) 705 save_item_ids.push_back(it.first);
711 save_ids.push_back(it->first); 706 for (const auto& it : saved_failed_items_)
712 for (SaveUrlItemMap::iterator it = saved_failed_items_.begin(); 707 save_item_ids.push_back(it.first);
713 it != saved_failed_items_.end(); ++it)
714 save_ids.push_back(it->second->save_id());
715 708
716 BrowserThread::PostTask( 709 BrowserThread::PostTask(
717 BrowserThread::FILE, FROM_HERE, 710 BrowserThread::FILE, FROM_HERE,
718 base::Bind(&SaveFileManager::RemoveSavedFileFromFileMap, 711 base::Bind(&SaveFileManager::RemoveSavedFileFromFileMap, file_manager_,
719 file_manager_, 712 save_item_ids));
720 save_ids));
721 713
722 finished_ = true; 714 finished_ = true;
723 wait_state_ = FAILED; 715 wait_state_ = FAILED;
724 716
725 // Inform the DownloadItem we have canceled whole save page job. 717 // Inform the DownloadItem we have canceled whole save page job.
726 if (download_) { 718 if (download_) {
727 download_->Cancel(false); 719 download_->Cancel(false);
728 FinalizeDownloadEntry(); 720 FinalizeDownloadEntry();
729 } 721 }
730 } 722 }
731 723
732 void SavePackage::CheckFinish() { 724 void SavePackage::CheckFinish() {
733 if (in_process_count() || finished_) 725 if (in_process_count() || finished_)
734 return; 726 return;
735 727
736 base::FilePath dir = (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML && 728 base::FilePath dir = (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML &&
737 saved_success_items_.size() > 1) ? 729 saved_success_items_.size() > 1) ?
738 saved_main_directory_path_ : base::FilePath(); 730 saved_main_directory_path_ : base::FilePath();
739 731
740 // This vector contains the final names of all the successfully saved files 732 FinalNamesMap final_names;
741 // along with their save ids. It will be passed to SaveFileManager to do the 733 for (const auto& it : saved_success_items_)
742 // renaming job. 734 final_names.insert(std::make_pair(it.first, it.second->full_path()));
743 FinalNameList final_names;
744 for (SavedItemMap::iterator it = saved_success_items_.begin();
745 it != saved_success_items_.end(); ++it)
746 final_names.push_back(std::make_pair(it->first,
747 it->second->full_path()));
748 735
749 BrowserThread::PostTask( 736 BrowserThread::PostTask(
750 BrowserThread::FILE, FROM_HERE, 737 BrowserThread::FILE, FROM_HERE,
751 base::Bind(&SaveFileManager::RenameAllFiles, 738 base::Bind(&SaveFileManager::RenameAllFiles,
752 file_manager_, 739 file_manager_,
753 final_names, 740 final_names,
754 dir, 741 dir,
755 web_contents()->GetRenderProcessHost()->GetID(), 742 web_contents()->GetRenderProcessHost()->GetID(),
756 web_contents()->GetMainFrame()->GetRoutingID(), 743 web_contents()->GetMainFrame()->GetRoutingID(),
757 id())); 744 id()));
758 } 745 }
759 746
760 // Successfully finished all items of this SavePackage. 747 // Successfully finished all items of this SavePackage.
761 void SavePackage::Finish() { 748 void SavePackage::Finish() {
762 // User may cancel the job when we're moving files to the final directory. 749 // User may cancel the job when we're moving files to the final directory.
763 if (canceled()) 750 if (canceled())
764 return; 751 return;
765 752
766 wait_state_ = SUCCESSFUL; 753 wait_state_ = SUCCESSFUL;
767 finished_ = true; 754 finished_ = true;
768 755
769 // Record finish. 756 // Record finish.
770 RecordSavePackageEvent(SAVE_PACKAGE_FINISHED); 757 RecordSavePackageEvent(SAVE_PACKAGE_FINISHED);
771 758
772 // Record any errors that occurred. 759 // Record any errors that occurred.
773 if (wrote_to_completed_file_) { 760 if (wrote_to_completed_file_)
774 RecordSavePackageEvent(SAVE_PACKAGE_WRITE_TO_COMPLETED); 761 RecordSavePackageEvent(SAVE_PACKAGE_WRITE_TO_COMPLETED);
775 }
776 762
777 if (wrote_to_failed_file_) { 763 if (wrote_to_failed_file_)
778 RecordSavePackageEvent(SAVE_PACKAGE_WRITE_TO_FAILED); 764 RecordSavePackageEvent(SAVE_PACKAGE_WRITE_TO_FAILED);
779 }
780 765
781 // This vector contains the save ids of the save files which SaveFileManager 766 // This vector contains the save ids of the save files which SaveFileManager
782 // needs to remove from its save_file_map_. 767 // needs to remove from its save_file_map_.
783 SaveIDList save_ids; 768 std::vector<int> save_item_ids;
Randy Smith (Not in Mondays) 2015/12/03 20:58:28 nit, suggestion, not a from this CL: Use a name th
Łukasz Anforowicz 2015/12/04 21:16:45 Good idea. Done. The only thing I dislike is hav
Randy Smith (Not in Mondays) 2015/12/07 19:57:14 Acknowledged.
784 for (SaveUrlItemMap::iterator it = saved_failed_items_.begin(); 769 for (const auto& it : saved_failed_items_)
785 it != saved_failed_items_.end(); ++it) 770 save_item_ids.push_back(it.first);
786 save_ids.push_back(it->second->save_id());
787 771
788 BrowserThread::PostTask( 772 BrowserThread::PostTask(
789 BrowserThread::FILE, FROM_HERE, 773 BrowserThread::FILE, FROM_HERE,
790 base::Bind(&SaveFileManager::RemoveSavedFileFromFileMap, 774 base::Bind(&SaveFileManager::RemoveSavedFileFromFileMap, file_manager_,
791 file_manager_, 775 save_item_ids));
792 save_ids));
793 776
794 if (download_) { 777 if (download_) {
795 // Hack to avoid touching download_ after user cancel. 778 // Hack to avoid touching download_ after user cancel.
796 // TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem 779 // TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem
797 // with SavePackage flow. 780 // with SavePackage flow.
798 if (download_->GetState() == DownloadItem::IN_PROGRESS) { 781 if (download_->GetState() == DownloadItem::IN_PROGRESS) {
799 if (save_type_ != SAVE_PAGE_TYPE_AS_MHTML) { 782 if (save_type_ != SAVE_PAGE_TYPE_AS_MHTML) {
800 download_->DestinationUpdate( 783 download_->DestinationUpdate(
801 all_save_items_count_, CurrentSpeed(), std::string()); 784 all_save_items_count_, CurrentSpeed(), std::string());
802 download_->OnAllDataSaved(DownloadItem::kEmptyFileHash); 785 download_->OnAllDataSaved(DownloadItem::kEmptyFileHash);
803 } 786 }
804 download_->MarkAsComplete(); 787 download_->MarkAsComplete();
805 } 788 }
806 FinalizeDownloadEntry(); 789 FinalizeDownloadEntry();
807 } 790 }
808 } 791 }
809 792
810 // Called for updating end state. 793 // Called for updating end state.
811 void SavePackage::SaveFinished(int32 save_id, int64 size, bool is_success) { 794 void SavePackage::SaveFinished(int32 save_item_id,
795 int64 size,
796 bool is_success) {
812 // Because we might have canceled this saving job before, 797 // Because we might have canceled this saving job before,
813 // so we might not find corresponding SaveItem. Just ignore it. 798 // so we might not find corresponding SaveItem. Just ignore it.
814 SaveItem* save_item = LookupItemInProcessBySaveId(save_id); 799 SaveItem* save_item = LookupSaveItemInProcess(save_item_id);
815 if (!save_item) 800 if (!save_item)
816 return; 801 return;
817 802
818 // Let SaveItem set end state. 803 // Let SaveItem set end state.
819 save_item->Finish(size, is_success); 804 save_item->Finish(size, is_success);
820 // Remove the associated save id and SavePackage. 805 // Remove the associated save id and SavePackage.
821 file_manager_->RemoveSaveFile(save_id, save_item->url(), this); 806 file_manager_->RemoveSaveFile(save_item->id(), this);
822 807
823 PutInProgressItemToSavedMap(save_item); 808 PutInProgressItemToSavedMap(save_item);
824 809
825 // Inform the DownloadItem to update UI. 810 // Inform the DownloadItem to update UI.
826 // We use the received bytes as number of saved files. 811 // We use the received bytes as number of saved files.
827 // Hack to avoid touching download_ after user cancel. 812 // Hack to avoid touching download_ after user cancel.
828 // TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem 813 // TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem
829 // with SavePackage flow. 814 // with SavePackage flow.
830 if (download_ && (download_->GetState() == DownloadItem::IN_PROGRESS)) { 815 if (download_ && (download_->GetState() == DownloadItem::IN_PROGRESS)) {
831 download_->DestinationUpdate( 816 download_->DestinationUpdate(
(...skipping 12 matching lines...) Expand all
844 return; 829 return;
845 } 830 }
846 831
847 // Continue processing the save page job. 832 // Continue processing the save page job.
848 DoSavingProcess(); 833 DoSavingProcess();
849 834
850 // Check whether we can successfully finish whole job. 835 // Check whether we can successfully finish whole job.
851 CheckFinish(); 836 CheckFinish();
852 } 837 }
853 838
854 // Sometimes, the net io will only call SaveFileManager::SaveFinished with
855 // save id -1 when it encounters error. Since in this case, save id will be
856 // -1, so we can only use URL to find which SaveItem is associated with
857 // this error.
858 // Saving an item failed. If it's a sub-resource, ignore it. If the error comes
859 // from serializing HTML data, then cancel saving page.
860 void SavePackage::SaveFailed(const GURL& save_url) {
861 SaveUrlItemMap::iterator it = in_progress_items_.find(save_url.spec());
862 if (it == in_progress_items_.end()) {
863 NOTREACHED(); // Should not exist!
864 return;
865 }
866 SaveItem* save_item = it->second;
867
868 save_item->Finish(0, false);
869
870 PutInProgressItemToSavedMap(save_item);
871
872 // Inform the DownloadItem to update UI.
873 // We use the received bytes as number of saved files.
874 // Hack to avoid touching download_ after user cancel.
875 // TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem
876 // with SavePackage flow.
877 if (download_ && (download_->GetState() == DownloadItem::IN_PROGRESS)) {
878 download_->DestinationUpdate(
879 completed_count(), CurrentSpeed(), std::string());
880 }
881
882 if ((save_type_ == SAVE_PAGE_TYPE_AS_ONLY_HTML) ||
883 (save_type_ == SAVE_PAGE_TYPE_AS_MHTML) ||
884 (save_item->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_DOM)) {
885 // We got error when saving page. Treat it as disk error.
886 Cancel(true);
887 }
888
889 if (canceled()) {
890 DCHECK(finished_);
891 return;
892 }
893
894 // Continue processing the save page job.
895 DoSavingProcess();
896
897 CheckFinish();
898 }
899
900 void SavePackage::SaveCanceled(SaveItem* save_item) { 839 void SavePackage::SaveCanceled(SaveItem* save_item) {
901 // Call the RemoveSaveFile in UI thread. 840 // Call the RemoveSaveFile in UI thread.
902 file_manager_->RemoveSaveFile(save_item->save_id(), 841 file_manager_->RemoveSaveFile(save_item->id(), this);
903 save_item->url(), 842 BrowserThread::PostTask(
904 this); 843 BrowserThread::FILE, FROM_HERE,
905 if (save_item->save_id() != -1) 844 base::Bind(&SaveFileManager::CancelSave, file_manager_, save_item->id()));
906 BrowserThread::PostTask(
907 BrowserThread::FILE, FROM_HERE,
908 base::Bind(&SaveFileManager::CancelSave,
909 file_manager_,
910 save_item->save_id()));
911 } 845 }
912 846
913 // Initiate a saving job of a specific URL. We send the request to 847 // Initiate a saving job of a specific URL. We send the request to
914 // SaveFileManager, which will dispatch it to different approach according to 848 // SaveFileManager, which will dispatch it to different approach according to
915 // the save source. Parameter process_all_remaining_items indicates whether 849 // the save source. Parameter process_all_remaining_items indicates whether
916 // we need to save all remaining items. 850 // we need to save all remaining items.
917 void SavePackage::SaveNextFile(bool process_all_remaining_items) { 851 void SavePackage::SaveNextFile(bool process_all_remaining_items) {
918 DCHECK(web_contents()); 852 DCHECK(web_contents());
919 DCHECK(waiting_item_queue_.size()); 853 DCHECK(waiting_item_queue_.size());
920 854
921 do { 855 do {
922 // Pop SaveItem from waiting list. 856 // Pop SaveItem from waiting list.
923 SaveItem* save_item = waiting_item_queue_.front(); 857 SaveItem* save_item = waiting_item_queue_.front();
924 waiting_item_queue_.pop_front(); 858 waiting_item_queue_.pop_front();
925 859
926 // Add the item to in_progress_items_. 860 // Add the item to in_progress_items_.
927 SaveUrlItemMap::iterator it = in_progress_items_.find( 861 SaveItemIdMap::iterator it = in_progress_items_.find(save_item->id());
928 save_item->url().spec());
929 DCHECK(it == in_progress_items_.end()); 862 DCHECK(it == in_progress_items_.end());
930 in_progress_items_[save_item->url().spec()] = save_item; 863 in_progress_items_[save_item->id()] = save_item;
931 save_item->Start(); 864 save_item->Start();
932 file_manager_->SaveURL(save_item->url(), 865 file_manager_->SaveURL(
933 save_item->referrer(), 866 save_item->id(), save_item->url(), save_item->referrer(),
934 web_contents()->GetRenderProcessHost()->GetID(), 867 web_contents()->GetRenderProcessHost()->GetID(), routing_id(),
935 routing_id(), 868 web_contents()->GetMainFrame()->GetRoutingID(),
936 web_contents()->GetMainFrame()->GetRoutingID(), 869 save_item->save_source(), save_item->full_path(),
937 save_item->save_source(), 870 web_contents()->GetBrowserContext()->GetResourceContext(), this);
938 save_item->full_path(),
939 web_contents()->
940 GetBrowserContext()->GetResourceContext(),
941 this);
942 } while (process_all_remaining_items && waiting_item_queue_.size()); 871 } while (process_all_remaining_items && waiting_item_queue_.size());
943 } 872 }
944 873
945 // Calculate the percentage of whole save page job. 874 // Calculate the percentage of whole save page job.
946 int SavePackage::PercentComplete() { 875 int SavePackage::PercentComplete() {
947 if (!all_save_items_count_) 876 if (!all_save_items_count_)
948 return 0; 877 return 0;
949 else if (!in_process_count()) 878 else if (!in_process_count())
950 return 100; 879 return 100;
951 else 880 else
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
1111 DCHECK_EQ(SaveFileCreateInfo::SAVE_FILE_FROM_DOM, save_item->save_source()); 1040 DCHECK_EQ(SaveFileCreateInfo::SAVE_FILE_FROM_DOM, save_item->save_source());
1112 if (save_item->state() != SaveItem::IN_PROGRESS) { 1041 if (save_item->state() != SaveItem::IN_PROGRESS) {
1113 for (SavedItemMap::iterator saved_it = saved_success_items_.begin(); 1042 for (SavedItemMap::iterator saved_it = saved_success_items_.begin();
1114 saved_it != saved_success_items_.end(); ++saved_it) { 1043 saved_it != saved_success_items_.end(); ++saved_it) {
1115 if (saved_it->second->url() == save_item->url()) { 1044 if (saved_it->second->url() == save_item->url()) {
1116 wrote_to_completed_file_ = true; 1045 wrote_to_completed_file_ = true;
1117 break; 1046 break;
1118 } 1047 }
1119 } 1048 }
1120 1049
1121 auto it2 = saved_failed_items_.find(save_item->url().spec()); 1050 auto it2 = saved_failed_items_.find(save_item->id());
1122 if (it2 != saved_failed_items_.end()) 1051 if (it2 != saved_failed_items_.end())
1123 wrote_to_failed_file_ = true; 1052 wrote_to_failed_file_ = true;
1124 1053
1125 return; 1054 return;
1126 } 1055 }
1127 1056
1128 if (!data.empty()) { 1057 if (!data.empty()) {
1129 // Prepare buffer for saving HTML data. 1058 // Prepare buffer for saving HTML data.
1130 scoped_refptr<net::IOBuffer> new_data(new net::IOBuffer(data.size())); 1059 scoped_refptr<net::IOBuffer> new_data(new net::IOBuffer(data.size()));
1131 memcpy(new_data->data(), data.data(), data.size()); 1060 memcpy(new_data->data(), data.data(), data.size());
1132 1061
1133 // Call write file functionality in file thread. 1062 // Call write file functionality in file thread.
1134 BrowserThread::PostTask( 1063 BrowserThread::PostTask(
1135 BrowserThread::FILE, FROM_HERE, 1064 BrowserThread::FILE, FROM_HERE,
1136 base::Bind(&SaveFileManager::UpdateSaveProgress, 1065 base::Bind(&SaveFileManager::UpdateSaveProgress, file_manager_,
1137 file_manager_, 1066 save_item->id(), new_data, static_cast<int>(data.size())));
1138 save_item->save_id(),
1139 new_data,
1140 static_cast<int>(data.size())));
1141 } 1067 }
1142 1068
1143 // Current frame is completed saving, call finish in file thread. 1069 // Current frame is completed saving, call finish in file thread.
1144 if (end_of_data) { 1070 if (end_of_data) {
1145 DVLOG(20) << " " << __FUNCTION__ << "()" 1071 DVLOG(20) << " " << __FUNCTION__ << "()"
1146 << " save_id = " << save_item->save_id() 1072 << " save_item_id = " << save_item->id() << " url = \""
1147 << " url = \"" << save_item->url().spec() << "\""; 1073 << save_item->url().spec() << "\"";
1148 BrowserThread::PostTask( 1074 BrowserThread::PostTask(
1149 BrowserThread::FILE, FROM_HERE, 1075 BrowserThread::FILE, FROM_HERE,
1150 base::Bind(&SaveFileManager::SaveFinished, file_manager_, 1076 base::Bind(&SaveFileManager::SaveFinished, file_manager_,
1151 save_item->save_id(), save_item->url(), id(), true)); 1077 save_item->id(), id(), true));
1152 number_of_frames_pending_response_--; 1078 number_of_frames_pending_response_--;
1153 DCHECK_LE(0, number_of_frames_pending_response_); 1079 DCHECK_LE(0, number_of_frames_pending_response_);
1154 } 1080 }
1155
1156 // If all frames are finished saving, we need to close the remaining
1157 // SaveItems.
Randy Smith (Not in Mondays) 2015/12/03 20:58:28 So I'm not understanding why this code was here in
Łukasz Anforowicz 2015/12/04 21:16:45 I also don't understand why this code was needed i
Randy Smith (Not in Mondays) 2015/12/07 19:57:14 Reasonable. I certainly don't believe in the pre-
1158 if (number_of_frames_pending_response_ == 0) {
1159 for (SaveUrlItemMap::iterator it = in_progress_items_.begin();
1160 it != in_progress_items_.end(); ++it) {
1161 DVLOG(20) << " " << __FUNCTION__ << "()"
1162 << " save_id = " << it->second->save_id() << " url = \""
1163 << it->second->url().spec() << "\"";
1164 BrowserThread::PostTask(
1165 BrowserThread::FILE, FROM_HERE,
1166 base::Bind(&SaveFileManager::SaveFinished, file_manager_,
1167 it->second->save_id(), it->second->url(), id(), true));
1168 }
1169 }
1170 } 1081 }
1171 1082
1172 // Ask for all savable resource links from backend, include main frame and 1083 // Ask for all savable resource links from backend, include main frame and
1173 // sub-frame. 1084 // sub-frame.
1174 void SavePackage::GetSavableResourceLinks() { 1085 void SavePackage::GetSavableResourceLinks() {
1175 if (wait_state_ != START_PROCESS) 1086 if (wait_state_ != START_PROCESS)
1176 return; 1087 return;
1177 1088
1178 wait_state_ = RESOURCES_LIST; 1089 wait_state_ = RESOURCES_LIST;
1179 1090
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1225 } 1136 }
1226 1137
1227 EnqueueFrame(container_frame_tree_node_id, 1138 EnqueueFrame(container_frame_tree_node_id,
1228 subframe_tree_node->frame_tree_node_id(), 1139 subframe_tree_node->frame_tree_node_id(),
1229 subframe.original_url); 1140 subframe.original_url);
1230 } 1141 }
1231 1142
1232 CompleteSavableResourceLinksResponse(); 1143 CompleteSavableResourceLinksResponse();
1233 } 1144 }
1234 1145
1235 SaveItem* SavePackage::FindOrCreatePendingSaveItem( 1146 SaveItem* SavePackage::CreatePendingSaveItem(
1236 int container_frame_tree_node_id, 1147 int container_frame_tree_node_id,
1237 const GURL& url, 1148 const GURL& url,
1238 const Referrer& referrer, 1149 const Referrer& referrer,
1150 SaveFileCreateInfo::SaveFileSource save_source) {
1151 DCHECK(url.is_valid()); // |url| should be validated by the callers.
1152
1153 SaveItem* save_item;
1154 Referrer sanitized_referrer = Referrer::SanitizeForRequest(url, referrer);
1155 save_item = new SaveItem(url, sanitized_referrer, this, save_source);
1156 waiting_item_queue_.push_back(save_item);
1157 url_to_save_item_[url] = save_item; // Ok to clobber existing entries
1158 // (in case of duplicated URIs).
Randy Smith (Not in Mondays) 2015/12/03 20:58:28 Hmmm. I find myself wondering about assertion opp
Łukasz Anforowicz 2015/12/04 21:16:45 Thanks for mentioning that - I should have thought
Łukasz Anforowicz 2015/12/04 21:21:06 I should have explained why I think this is import
Randy Smith (Not in Mondays) 2015/12/07 19:57:14 Thanks for the detailed exploration. I agree keep
Łukasz Anforowicz 2015/12/07 20:32:31 The main reason why I didn't rename is the fact th
1159
1160 frame_tree_node_id_to_contained_save_items_[container_frame_tree_node_id]
1161 .push_back(save_item);
1162 return save_item;
1163 }
1164
1165 SaveItem* SavePackage::CreatePendingSaveItemDeduplicatingByUrl(
1166 int container_frame_tree_node_id,
1167 const GURL& url,
1168 const Referrer& referrer,
1239 SaveFileCreateInfo::SaveFileSource save_source) { 1169 SaveFileCreateInfo::SaveFileSource save_source) {
1240 DCHECK(url.is_valid()); // |url| should be validated by the callers. 1170 DCHECK(url.is_valid()); // |url| should be validated by the callers.
1241 1171
1242 SaveItem* save_item; 1172 SaveItem* save_item;
1243 auto it = url_to_save_item_.find(url); 1173 auto it = url_to_save_item_.find(url);
1244 if (it != url_to_save_item_.end()) { 1174 if (it != url_to_save_item_.end()) {
1245 save_item = it->second; 1175 save_item = it->second;
1176 frame_tree_node_id_to_contained_save_items_[container_frame_tree_node_id]
1177 .push_back(save_item);
1246 } else { 1178 } else {
1247 Referrer sanitized_referrer = Referrer::SanitizeForRequest(url, referrer); 1179 save_item = CreatePendingSaveItem(container_frame_tree_node_id, url,
1248 save_item = new SaveItem(url, sanitized_referrer, this, save_source); 1180 referrer, save_source);
1249 waiting_item_queue_.push_back(save_item);
1250 url_to_save_item_[url] = save_item;
1251 } 1181 }
1252 1182
1253 frame_tree_node_id_to_contained_save_items_[container_frame_tree_node_id]
1254 .push_back(save_item);
1255 return save_item; 1183 return save_item;
1256 } 1184 }
1257 1185
1258 void SavePackage::EnqueueSavableResource(int container_frame_tree_node_id, 1186 void SavePackage::EnqueueSavableResource(int container_frame_tree_node_id,
1259 const GURL& url, 1187 const GURL& url,
1260 const Referrer& referrer) { 1188 const Referrer& referrer) {
1261 if (!url.is_valid()) 1189 if (!url.is_valid())
1262 return; 1190 return;
1263 1191
1264 SaveFileCreateInfo::SaveFileSource save_source = 1192 SaveFileCreateInfo::SaveFileSource save_source =
1265 url.SchemeIsFile() ? SaveFileCreateInfo::SAVE_FILE_FROM_FILE 1193 url.SchemeIsFile() ? SaveFileCreateInfo::SAVE_FILE_FROM_FILE
1266 : SaveFileCreateInfo::SAVE_FILE_FROM_NET; 1194 : SaveFileCreateInfo::SAVE_FILE_FROM_NET;
1267 FindOrCreatePendingSaveItem(container_frame_tree_node_id, url, referrer, 1195 CreatePendingSaveItemDeduplicatingByUrl(container_frame_tree_node_id, url,
1268 save_source); 1196 referrer, save_source);
1269 } 1197 }
1270 1198
1271 void SavePackage::EnqueueFrame(int container_frame_tree_node_id, 1199 void SavePackage::EnqueueFrame(int container_frame_tree_node_id,
1272 int frame_tree_node_id, 1200 int frame_tree_node_id,
1273 const GURL& frame_original_url) { 1201 const GURL& frame_original_url) {
1274 if (!frame_original_url.is_valid()) 1202 if (!frame_original_url.is_valid())
1275 return; 1203 return;
1276 1204
1277 SaveItem* save_item = FindOrCreatePendingSaveItem( 1205 SaveItem* save_item =
1278 container_frame_tree_node_id, frame_original_url, Referrer(), 1206 CreatePendingSaveItem(container_frame_tree_node_id, frame_original_url,
1279 SaveFileCreateInfo::SAVE_FILE_FROM_DOM); 1207 Referrer(), SaveFileCreateInfo::SAVE_FILE_FROM_DOM);
1280 DCHECK(save_item); 1208 DCHECK(save_item);
1281 frame_tree_node_id_to_save_item_[frame_tree_node_id] = save_item; 1209 frame_tree_node_id_to_save_item_[frame_tree_node_id] = save_item;
1282 } 1210 }
1283 1211
1284 void SavePackage::OnSavableResourceLinksError(RenderFrameHostImpl* sender) { 1212 void SavePackage::OnSavableResourceLinksError(RenderFrameHostImpl* sender) {
1285 CompleteSavableResourceLinksResponse(); 1213 CompleteSavableResourceLinksResponse();
1286 } 1214 }
1287 1215
1288 void SavePackage::CompleteSavableResourceLinksResponse() { 1216 void SavePackage::CompleteSavableResourceLinksResponse() {
1289 --number_of_frames_pending_response_; 1217 --number_of_frames_pending_response_;
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
1559 1487
1560 void SavePackage::FinalizeDownloadEntry() { 1488 void SavePackage::FinalizeDownloadEntry() {
1561 DCHECK(download_); 1489 DCHECK(download_);
1562 DCHECK(download_manager_); 1490 DCHECK(download_manager_);
1563 1491
1564 download_manager_->OnSavePackageSuccessfullyFinished(download_); 1492 download_manager_->OnSavePackageSuccessfullyFinished(download_);
1565 StopObservation(); 1493 StopObservation();
1566 } 1494 }
1567 1495
1568 } // namespace content 1496 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698