Index: content/browser/download/save_package.cc |
diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc |
index 36c6be64a0f3c066ef2a766a72f57240dae0bbac..dfd06fd3c09d5770a593e629d2403cf09a38f68f 100644 |
--- a/content/browser/download/save_package.cc |
+++ b/content/browser/download/save_package.cc |
@@ -29,6 +29,7 @@ |
#include "content/browser/renderer_host/render_process_host_impl.h" |
#include "content/browser/renderer_host/render_view_host_delegate.h" |
#include "content/browser/renderer_host/render_view_host_impl.h" |
+#include "content/common/frame_messages.h" |
#include "content/common/view_messages.h" |
#include "content/public/browser/browser_context.h" |
#include "content/public/browser/browser_thread.h" |
@@ -336,7 +337,7 @@ void SavePackage::InitWithDownloadItem( |
if (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML) { |
// Get directory |
DCHECK(!saved_main_directory_path_.empty()); |
- GetAllSavableResourceLinksForCurrentPage(); |
+ GetSavableResourceLinksForCurrentPage(); |
} else if (save_type_ == SAVE_PAGE_TYPE_AS_MHTML) { |
web_contents()->GenerateMHTML(saved_main_file_path_, base::Bind( |
&SavePackage::OnMHTMLGenerated, this)); |
@@ -1003,8 +1004,6 @@ void SavePackage::DoSavingProcess() { |
bool SavePackage::OnMessageReceived(const IPC::Message& message) { |
bool handled = true; |
IPC_BEGIN_MESSAGE_MAP(SavePackage, message) |
- IPC_MESSAGE_HANDLER(ViewHostMsg_SendCurrentPageAllSavableResourceLinks, |
- OnReceivedSavableResourceLinksForCurrentPage) |
IPC_MESSAGE_HANDLER(ViewHostMsg_SendSerializedHtmlData, |
OnReceivedSerializedHtmlData) |
IPC_MESSAGE_UNHANDLED(handled = false) |
@@ -1012,6 +1011,19 @@ bool SavePackage::OnMessageReceived(const IPC::Message& message) { |
return handled; |
} |
+bool SavePackage::OnMessageReceived(const IPC::Message& message, |
+ RenderFrameHost* render_frame_host) { |
+ bool handled = true; |
+ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(SavePackage, message, render_frame_host) |
+ IPC_MESSAGE_HANDLER(FrameHostMsg_SavableResourceLinksResponse, |
+ OnSavableResourceLinksResponse) |
+ IPC_MESSAGE_HANDLER(FrameHostMsg_SavableResourceLinksError, |
+ OnSavableResourceLinksError) |
+ IPC_MESSAGE_UNHANDLED(handled = false) |
+ IPC_END_MESSAGE_MAP() |
+ return handled; |
+} |
+ |
// After finishing all SaveItems which need to get data from net. |
// We collect all URLs which have local storage and send the |
// map:(originalURL:currentLocalPath) to render process (backend). |
@@ -1142,30 +1154,81 @@ void SavePackage::OnReceivedSerializedHtmlData(const GURL& frame_url, |
// Ask for all savable resource links from backend, include main frame and |
// sub-frame. |
-void SavePackage::GetAllSavableResourceLinksForCurrentPage() { |
+void SavePackage::GetSavableResourceLinksForCurrentPage() { |
if (wait_state_ != START_PROCESS) |
return; |
+ WebContents* web_contents = WebContentsObserver::web_contents(); |
+ if (!web_contents) { |
+ // Tab got closed - treat it as user cancel. |
+ Cancel(true); |
+ return; |
+ } |
+ |
wait_state_ = RESOURCES_LIST; |
- Send(new ViewMsg_GetAllSavableResourceLinksForCurrentPage(routing_id(), |
- page_url_)); |
+ number_of_frames_with_pending_get_savable_resource_links_ = 0; |
+ web_contents->ForEachFrame(base::Bind( |
+ &SavePackage::GetSavableResourceLinksForFrame, |
+ base::Unretained(this))); // Safe, because ForEachFrame is synchronous. |
+ DCHECK_LT(0, number_of_frames_with_pending_get_savable_resource_links_); |
+} |
+ |
+void SavePackage::GetSavableResourceLinksForFrame(RenderFrameHost* target) { |
+ number_of_frames_with_pending_get_savable_resource_links_++; |
+ Send(new FrameMsg_GetSavableResourceLinks(target->GetRoutingID())); |
} |
-// Give backend the lists which contain all resource links that have local |
-// storage, after which, render process will serialize DOM for generating |
-// HTML data. |
-void SavePackage::OnReceivedSavableResourceLinksForCurrentPage( |
+void SavePackage::OnSavableResourceLinksResponse( |
+ RenderFrameHost* source, |
const std::vector<GURL>& resources_list, |
- const std::vector<Referrer>& referrers_list, |
- const std::vector<GURL>& frames_list) { |
+ const std::vector<Referrer>& referrers_list) { |
if (wait_state_ != RESOURCES_LIST) |
return; |
if (resources_list.size() != referrers_list.size()) |
return; |
- all_save_items_count_ = static_cast<int>(resources_list.size()) + |
- static_cast<int>(frames_list.size()); |
+ // Add all sub-resources to wait list. |
+ for (int i = 0; i < static_cast<int>(resources_list.size()); ++i) { |
+ const GURL& u = resources_list[i]; |
+ DCHECK(u.is_valid()); |
+ if (unique_urls_to_save_.count(u)) { |
+ continue; |
+ } |
+ unique_urls_to_save_.insert(u); |
+ |
+ SaveFileCreateInfo::SaveFileSource save_source = |
+ u.SchemeIsFile() ? SaveFileCreateInfo::SAVE_FILE_FROM_FILE |
+ : SaveFileCreateInfo::SAVE_FILE_FROM_NET; |
+ SaveItem* save_item = new SaveItem(u, referrers_list[i], this, save_source); |
+ waiting_item_queue_.push(save_item); |
+ } |
+ |
+ // Add the frame to wait list. |
+ GURL frame_url = source->GetLastCommittedURL(); |
+ DCHECK(frame_url.is_valid()); |
+ if (0 == unique_urls_to_save_.count(frame_url)) { |
+ unique_urls_to_save_.insert(frame_url); |
+ SaveItem* save_item = new SaveItem(frame_url, Referrer(), this, |
+ SaveFileCreateInfo::SAVE_FILE_FROM_DOM); |
+ waiting_item_queue_.push(save_item); |
+ } |
+ |
+ CompleteSavableResourceLinksResponseFromFrame(); |
+} |
+ |
+void SavePackage::OnSavableResourceLinksError(RenderFrameHost* source) { |
+ CompleteSavableResourceLinksResponseFromFrame(); |
+} |
+ |
+void SavePackage::CompleteSavableResourceLinksResponseFromFrame() { |
+ --number_of_frames_with_pending_get_savable_resource_links_; |
+ if (0 < number_of_frames_with_pending_get_savable_resource_links_) { |
+ return; |
+ } |
+ DCHECK_EQ(0, number_of_frames_with_pending_get_savable_resource_links_); |
+ |
+ all_save_items_count_ = static_cast<int>(unique_urls_to_save_.size()); |
// We use total bytes as the total number of files we want to save. |
// Hack to avoid touching download_ after user cancel. |
@@ -1175,26 +1238,11 @@ void SavePackage::OnReceivedSavableResourceLinksForCurrentPage( |
download_->SetTotalBytes(all_save_items_count_); |
if (all_save_items_count_) { |
- // Put all sub-resources to wait list. |
- for (int i = 0; i < static_cast<int>(resources_list.size()); ++i) { |
- const GURL& u = resources_list[i]; |
- DCHECK(u.is_valid()); |
- SaveFileCreateInfo::SaveFileSource save_source = u.SchemeIsFile() ? |
- SaveFileCreateInfo::SAVE_FILE_FROM_FILE : |
- SaveFileCreateInfo::SAVE_FILE_FROM_NET; |
- SaveItem* save_item = new SaveItem(u, referrers_list[i], |
- this, save_source); |
- waiting_item_queue_.push(save_item); |
- } |
- // Put all HTML resources to wait list. |
- for (int i = 0; i < static_cast<int>(frames_list.size()); ++i) { |
- const GURL& u = frames_list[i]; |
- DCHECK(u.is_valid()); |
- SaveItem* save_item = new SaveItem( |
- u, Referrer(), this, SaveFileCreateInfo::SAVE_FILE_FROM_DOM); |
- waiting_item_queue_.push(save_item); |
- } |
wait_state_ = NET_FILES; |
+ |
+ // Give backend the lists which contain all resource links that have local |
+ // storage, after which, render process will serialize DOM for generating |
+ // HTML data. |
DoSavingProcess(); |
} else { |
// No resource files need to be saved, treat it as user cancel. |