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..bdc34933a74a9e394b55f3edd71b5fd346524d5e 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" |
@@ -140,6 +141,7 @@ SavePackage::SavePackage(WebContents* web_contents, |
const base::FilePath& file_full_path, |
const base::FilePath& directory_full_path) |
: WebContentsObserver(web_contents), |
+ number_of_frames_pending_response_(0), |
file_manager_(NULL), |
download_manager_(NULL), |
download_(NULL), |
@@ -173,6 +175,7 @@ SavePackage::SavePackage(WebContents* web_contents, |
SavePackage::SavePackage(WebContents* web_contents) |
: WebContentsObserver(web_contents), |
+ number_of_frames_pending_response_(0), |
file_manager_(NULL), |
download_manager_(NULL), |
download_(NULL), |
@@ -336,7 +339,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 +1006,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 +1013,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 +1156,87 @@ 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; |
wait_state_ = RESOURCES_LIST; |
- Send(new ViewMsg_GetAllSavableResourceLinksForCurrentPage(routing_id(), |
- page_url_)); |
+ |
+ DCHECK_EQ(0, number_of_frames_pending_response_); |
+ web_contents()->ForEachFrame(base::Bind( |
+ &SavePackage::GetSavableResourceLinksForFrame, |
+ base::Unretained(this))); // Safe, because ForEachFrame is synchronous. |
+ DCHECK_LT(0, number_of_frames_pending_response_); |
+} |
+ |
+void SavePackage::GetSavableResourceLinksForFrame(RenderFrameHost* target) { |
+ number_of_frames_pending_response_++; |
+ target->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* sender, |
+ const GURL& frame_url, |
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]; |
+ if (!u.is_valid()) { |
nasko
2015/09/17 21:18:24
nit: no {} for one line if statements (this one an
Łukasz Anforowicz
2015/09/18 18:44:18
Done - I see that the rest of the file indeed cons
|
+ continue; |
+ } |
+ 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); |
+ } |
+ |
+ // Store savable frame_url for later processing. |
+ if (frame_url.is_valid()) { |
+ frame_urls_to_save_.push_back(frame_url); |
+ } |
+ |
+ CompleteSavableResourceLinksResponseFromFrame(); |
+} |
+ |
+void SavePackage::OnSavableResourceLinksError(RenderFrameHost* sender) { |
+ CompleteSavableResourceLinksResponseFromFrame(); |
+} |
+ |
+void SavePackage::CompleteSavableResourceLinksResponseFromFrame() { |
+ --number_of_frames_pending_response_; |
+ DCHECK_LE(0, number_of_frames_pending_response_); |
+ if (number_of_frames_pending_response_ != 0) { |
+ return; // Need to wait for more responses from RenderFrames. |
+ } |
+ |
+ // Add frame urls to the waiting_item_queue_. This is done *after* processing |
+ // all savable resource links (i.e. in OnSavableResourceLinksResponse), to |
+ // prefer their referrers in cases where the frame url has already been |
+ // covered by savable resource links. |
+ for (auto& frame_url : frame_urls_to_save_) { |
+ 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); |
+ } |
+ } |
+ |
+ all_save_items_count_ = static_cast<int>(waiting_item_queue_.size()); |
// We use total bytes as the total number of files we want to save. |
// Hack to avoid touching download_ after user cancel. |
@@ -1175,29 +1246,14 @@ 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. |
+ // No savable frames and/or resources - treat it as user cancel. |
Cancel(true); |
} |
} |