Chromium Code Reviews| 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/files/file_path.h" | 10 #include "base/files/file_path.h" |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |