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

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

Issue 1373573002: ABANDONED: OOPIFs: Moving stitching of local paths from renderer to browser process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@page-serialization-recursive-begone
Patch Set: Rebasing... Created 5 years, 2 months 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"
11 #include "base/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/i18n/file_util_icu.h" 12 #include "base/i18n/file_util_icu.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/message_loop/message_loop.h" 14 #include "base/message_loop/message_loop.h"
15 #include "base/stl_util.h" 15 #include "base/stl_util.h"
16 #include "base/strings/string_piece.h" 16 #include "base/strings/string_piece.h"
17 #include "base/strings/string_split.h" 17 #include "base/strings/string_split.h"
18 #include "base/strings/sys_string_conversions.h" 18 #include "base/strings/sys_string_conversions.h"
19 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
20 #include "base/threading/thread.h" 20 #include "base/threading/thread.h"
21 #include "components/url_formatter/url_formatter.h" 21 #include "components/url_formatter/url_formatter.h"
22 #include "content/browser/download/download_item_impl.h" 22 #include "content/browser/download/download_item_impl.h"
23 #include "content/browser/download/download_manager_impl.h" 23 #include "content/browser/download/download_manager_impl.h"
24 #include "content/browser/download/download_stats.h" 24 #include "content/browser/download/download_stats.h"
25 #include "content/browser/download/save_file.h" 25 #include "content/browser/download/save_file.h"
26 #include "content/browser/download/save_file_manager.h" 26 #include "content/browser/download/save_file_manager.h"
27 #include "content/browser/download/save_item.h" 27 #include "content/browser/download/save_item.h"
28 #include "content/browser/frame_host/frame_tree.h"
29 #include "content/browser/frame_host/frame_tree_node.h"
28 #include "content/browser/loader/resource_dispatcher_host_impl.h" 30 #include "content/browser/loader/resource_dispatcher_host_impl.h"
29 #include "content/browser/renderer_host/render_process_host_impl.h" 31 #include "content/browser/renderer_host/render_process_host_impl.h"
30 #include "content/browser/renderer_host/render_view_host_delegate.h" 32 #include "content/browser/renderer_host/render_view_host_delegate.h"
31 #include "content/browser/renderer_host/render_view_host_impl.h" 33 #include "content/browser/renderer_host/render_view_host_impl.h"
34 #include "content/browser/web_contents/web_contents_impl.h"
32 #include "content/common/frame_messages.h" 35 #include "content/common/frame_messages.h"
33 #include "content/common/view_messages.h"
34 #include "content/public/browser/browser_context.h" 36 #include "content/public/browser/browser_context.h"
35 #include "content/public/browser/browser_thread.h" 37 #include "content/public/browser/browser_thread.h"
36 #include "content/public/browser/content_browser_client.h" 38 #include "content/public/browser/content_browser_client.h"
37 #include "content/public/browser/download_manager_delegate.h" 39 #include "content/public/browser/download_manager_delegate.h"
38 #include "content/public/browser/navigation_entry.h" 40 #include "content/public/browser/navigation_entry.h"
39 #include "content/public/browser/notification_service.h" 41 #include "content/public/browser/notification_service.h"
40 #include "content/public/browser/notification_types.h" 42 #include "content/public/browser/notification_types.h"
41 #include "content/public/browser/render_frame_host.h" 43 #include "content/public/browser/render_frame_host.h"
42 #include "content/public/browser/resource_context.h" 44 #include "content/public/browser/resource_context.h"
43 #include "content/public/browser/web_contents.h" 45 #include "content/public/browser/web_contents.h"
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 void ResumeRequest() const override {} 126 void ResumeRequest() const override {}
125 void CancelRequest() const override {} 127 void CancelRequest() const override {}
126 std::string DebugString() const override { 128 std::string DebugString() const override {
127 return "SavePackage DownloadRequestHandle"; 129 return "SavePackage DownloadRequestHandle";
128 } 130 }
129 131
130 private: 132 private:
131 base::WeakPtr<SavePackage> save_package_; 133 base::WeakPtr<SavePackage> save_package_;
132 }; 134 };
133 135
136 int GetFrameTreeNodeId(RenderFrameHost* render_frame_host) {
137 auto rfhi = static_cast<RenderFrameHostImpl*>(render_frame_host);
dcheng 2015/10/05 07:53:08 Nit: my personal preference is to annotate autos h
Łukasz Anforowicz 2015/10/05 17:57:56 Done.
138 return rfhi->frame_tree_node()->frame_tree_node_id();
139 }
140
134 } // namespace 141 } // namespace
135 142
136 const base::FilePath::CharType SavePackage::kDefaultHtmlExtension[] = 143 const base::FilePath::CharType SavePackage::kDefaultHtmlExtension[] =
137 FILE_PATH_LITERAL("html"); 144 FILE_PATH_LITERAL("html");
138 145
139 SavePackage::SavePackage(WebContents* web_contents, 146 SavePackage::SavePackage(WebContents* web_contents,
140 SavePageType save_type, 147 SavePageType save_type,
141 const base::FilePath& file_full_path, 148 const base::FilePath& file_full_path,
142 const base::FilePath& directory_full_path) 149 const base::FilePath& directory_full_path)
143 : WebContentsObserver(web_contents), 150 : WebContentsObserver(web_contents),
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 Cancel(true); 239 Cancel(true);
233 } 240 }
234 241
235 // We should no longer be observing the DownloadItem at this point. 242 // We should no longer be observing the DownloadItem at this point.
236 CHECK(!download_); 243 CHECK(!download_);
237 244
238 DCHECK(all_save_items_count_ == (waiting_item_queue_.size() + 245 DCHECK(all_save_items_count_ == (waiting_item_queue_.size() +
239 completed_count() + 246 completed_count() +
240 in_process_count())); 247 in_process_count()));
241 // Free all SaveItems. 248 // Free all SaveItems.
242 while (!waiting_item_queue_.empty()) { 249 STLDeleteElements(&waiting_item_queue_);
243 // We still have some items which are waiting for start to save. 250 STLDeleteValues(&in_progress_items_);
244 SaveItem* save_item = waiting_item_queue_.front();
245 waiting_item_queue_.pop();
246 delete save_item;
247 }
248
249 STLDeleteValues(&saved_success_items_); 251 STLDeleteValues(&saved_success_items_);
250 STLDeleteValues(&in_progress_items_);
251 STLDeleteValues(&saved_failed_items_); 252 STLDeleteValues(&saved_failed_items_);
252 253
253 file_manager_ = NULL; 254 file_manager_ = NULL;
254 } 255 }
255 256
256 GURL SavePackage::GetUrlToBeSaved() { 257 GURL SavePackage::GetUrlToBeSaved() {
257 // Instead of using web_contents_.GetURL here, we use url() (which is the 258 // Instead of using web_contents_.GetURL here, we use url() (which is the
258 // "real" url of the page) from the NavigationEntry because it reflects its 259 // "real" url of the page) from the NavigationEntry because it reflects its
259 // origin rather than the displayed one (returned by GetURL) which may be 260 // origin rather than the displayed one (returned by GetURL) which may be
260 // different (like having "view-source:" on the front). 261 // different (like having "view-source:" on the front).
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 GetSavableResourceLinks(); 343 GetSavableResourceLinks();
343 } else if (save_type_ == SAVE_PAGE_TYPE_AS_MHTML) { 344 } else if (save_type_ == SAVE_PAGE_TYPE_AS_MHTML) {
344 web_contents()->GenerateMHTML(saved_main_file_path_, base::Bind( 345 web_contents()->GenerateMHTML(saved_main_file_path_, base::Bind(
345 &SavePackage::OnMHTMLGenerated, this)); 346 &SavePackage::OnMHTMLGenerated, this));
346 } else { 347 } else {
347 DCHECK_EQ(SAVE_PAGE_TYPE_AS_ONLY_HTML, save_type_) << save_type_; 348 DCHECK_EQ(SAVE_PAGE_TYPE_AS_ONLY_HTML, save_type_) << save_type_;
348 wait_state_ = NET_FILES; 349 wait_state_ = NET_FILES;
349 SaveFileCreateInfo::SaveFileSource save_source = page_url_.SchemeIsFile() ? 350 SaveFileCreateInfo::SaveFileSource save_source = page_url_.SchemeIsFile() ?
350 SaveFileCreateInfo::SAVE_FILE_FROM_FILE : 351 SaveFileCreateInfo::SAVE_FILE_FROM_FILE :
351 SaveFileCreateInfo::SAVE_FILE_FROM_NET; 352 SaveFileCreateInfo::SAVE_FILE_FROM_NET;
352 SaveItem* save_item = new SaveItem(page_url_, 353 SaveItem* save_item = new SaveItem(page_url_, this, save_source);
353 Referrer(),
354 this,
355 save_source);
356 // Add this item to waiting list. 354 // Add this item to waiting list.
357 waiting_item_queue_.push(save_item); 355 waiting_item_queue_.push_back(save_item);
358 all_save_items_count_ = 1; 356 all_save_items_count_ = 1;
359 download_->SetTotalBytes(1); 357 download_->SetTotalBytes(1);
360 358
361 DoSavingProcess(); 359 DoSavingProcess();
362 } 360 }
363 } 361 }
364 362
365 void SavePackage::OnMHTMLGenerated(int64 size) { 363 void SavePackage::OnMHTMLGenerated(int64 size) {
366 if (size <= 0) { 364 if (size <= 0) {
367 Cancel(false); 365 Cancel(false);
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 // SaveFileManager, which will dispatch it to different approach according to 916 // SaveFileManager, which will dispatch it to different approach according to
919 // the save source. Parameter process_all_remaining_items indicates whether 917 // the save source. Parameter process_all_remaining_items indicates whether
920 // we need to save all remaining items. 918 // we need to save all remaining items.
921 void SavePackage::SaveNextFile(bool process_all_remaining_items) { 919 void SavePackage::SaveNextFile(bool process_all_remaining_items) {
922 DCHECK(web_contents()); 920 DCHECK(web_contents());
923 DCHECK(waiting_item_queue_.size()); 921 DCHECK(waiting_item_queue_.size());
924 922
925 do { 923 do {
926 // Pop SaveItem from waiting list. 924 // Pop SaveItem from waiting list.
927 SaveItem* save_item = waiting_item_queue_.front(); 925 SaveItem* save_item = waiting_item_queue_.front();
928 waiting_item_queue_.pop(); 926 waiting_item_queue_.pop_front();
929 927
930 // Add the item to in_progress_items_. 928 // Add the item to in_progress_items_.
931 SaveUrlItemMap::iterator it = in_progress_items_.find( 929 SaveUrlItemMap::iterator it = in_progress_items_.find(
932 save_item->url().spec()); 930 save_item->url().spec());
933 DCHECK(it == in_progress_items_.end()); 931 DCHECK(it == in_progress_items_.end());
934 in_progress_items_[save_item->url().spec()] = save_item; 932 in_progress_items_[save_item->url().spec()] = save_item;
935 save_item->Start(); 933 save_item->Start();
936 file_manager_->SaveURL(save_item->url(), 934 file_manager_->SaveURL(save_item->url(),
937 save_item->referrer(), 935 save_item->referrer(),
938 web_contents()->GetRenderProcessHost()->GetID(), 936 web_contents()->GetRenderProcessHost()->GetID(),
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 } 1002 }
1005 1003
1006 bool SavePackage::OnMessageReceived(const IPC::Message& message, 1004 bool SavePackage::OnMessageReceived(const IPC::Message& message,
1007 RenderFrameHost* render_frame_host) { 1005 RenderFrameHost* render_frame_host) {
1008 bool handled = true; 1006 bool handled = true;
1009 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(SavePackage, message, render_frame_host) 1007 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(SavePackage, message, render_frame_host)
1010 IPC_MESSAGE_HANDLER(FrameHostMsg_SavableResourceLinksResponse, 1008 IPC_MESSAGE_HANDLER(FrameHostMsg_SavableResourceLinksResponse,
1011 OnSavableResourceLinksResponse) 1009 OnSavableResourceLinksResponse)
1012 IPC_MESSAGE_HANDLER(FrameHostMsg_SavableResourceLinksError, 1010 IPC_MESSAGE_HANDLER(FrameHostMsg_SavableResourceLinksError,
1013 OnSavableResourceLinksError) 1011 OnSavableResourceLinksError)
1014 IPC_MESSAGE_HANDLER(FrameHostMsg_SerializedHtmlWithLocalLinksResponse, 1012 IPC_MESSAGE_HANDLER(FrameHostMsg_SerializedHtmlFragment,
1015 OnSerializedHtmlWithLocalLinksResponse) 1013 OnSerializedHtmlFragment)
1014 IPC_MESSAGE_HANDLER(FrameHostMsg_SerializedLocalPathForSubFrame,
1015 OnSerializedLocalPathForSubFrame)
1016 IPC_MESSAGE_HANDLER(FrameHostMsg_SerializedLocalPathForSavableResource,
1017 OnSerializedLocalPathForSavableResource)
1018 IPC_MESSAGE_HANDLER(FrameHostMsg_SerializedEndOfFrame,
1019 OnSerializedEndOfFrame)
1016 IPC_MESSAGE_UNHANDLED(handled = false) 1020 IPC_MESSAGE_UNHANDLED(handled = false)
1017 IPC_END_MESSAGE_MAP() 1021 IPC_END_MESSAGE_MAP()
1018 return handled; 1022 return handled;
1019 } 1023 }
1020 1024
1021 // After finishing all SaveItems which need to get data from net. 1025 // After finishing all SaveItems which need to get data from net.
1022 // We collect all URLs which have local storage and send the 1026 // We collect all URLs which have local storage and send the
1023 // map:(originalURL:currentLocalPath) to render process (backend). 1027 // map:(originalURL:currentLocalPath) to render process (backend).
1024 // Then render process will serialize DOM and send data to us. 1028 // Then render process will serialize DOM and send data to us.
1025 void SavePackage::GetSerializedHtmlWithLocalLinks() { 1029 void SavePackage::GetSerializedHtmlWithLocalLinks() {
1026 if (wait_state_ != HTML_DATA) 1030 if (wait_state_ != HTML_DATA)
1027 return; 1031 return;
1028 std::vector<GURL> saved_links;
1029 std::vector<base::FilePath> saved_file_paths;
1030 int successful_started_items_count = 0; 1032 int successful_started_items_count = 0;
1031 1033
1032 // Collect all saved items which have local storage. 1034 // Count all saved items which have local storage.
1033 // First collect the status of all the resource files and check whether they 1035 for (const auto& it : in_progress_items_) {
1034 // have created local files although they have not been completely saved. 1036 DCHECK_EQ(it.second->save_source(), SaveFileCreateInfo::SAVE_FILE_FROM_DOM);
dcheng 2015/10/05 07:53:08 Nit: there's a weak convention of DCHECK_EQ(expect
Łukasz Anforowicz 2015/10/05 17:57:56 Thanks for catching this. I knew about this conve
1035 // If yes, the file can be saved. Otherwise, there is a disk error, so we 1037 if (it.second->has_final_name())
1036 // need to cancel the page saving job.
1037 for (SaveUrlItemMap::iterator it = in_progress_items_.begin();
1038 it != in_progress_items_.end(); ++it) {
1039 DCHECK(it->second->save_source() ==
1040 SaveFileCreateInfo::SAVE_FILE_FROM_DOM);
1041 if (it->second->has_final_name())
1042 successful_started_items_count++; 1038 successful_started_items_count++;
1043 saved_links.push_back(it->second->url());
1044 saved_file_paths.push_back(it->second->file_name());
1045 } 1039 }
1046 1040
1047 // If not all file of HTML resource have been started, then wait. 1041 // If not all file of HTML resource have been started, then wait.
1048 if (successful_started_items_count != in_process_count()) 1042 if (successful_started_items_count != in_process_count())
1049 return; 1043 return;
1050 1044
1051 // Collect all saved success items.
1052 for (SavedItemMap::iterator it = saved_success_items_.begin();
1053 it != saved_success_items_.end(); ++it) {
1054 DCHECK(it->second->has_final_name());
1055 saved_links.push_back(it->second->url());
1056 saved_file_paths.push_back(it->second->file_name());
1057 }
1058
1059 // Get the relative directory name.
1060 base::FilePath relative_dir_name = saved_main_directory_path_.BaseName();
1061
1062 // Ask all frames for their serialized data. 1045 // Ask all frames for their serialized data.
1063 DCHECK_EQ(0, number_of_frames_pending_response_); 1046 DCHECK_EQ(0, number_of_frames_pending_response_);
1064 web_contents()->ForEachFrame(base::Bind( 1047 web_contents()->ForEachFrame(base::Bind(
1065 &SavePackage::GetSerializedHtmlWithLocalLinksForFrame, 1048 &SavePackage::GetSerializedHtmlWithLocalLinksForFrame,
1066 base::Unretained(this), // Safe, because ForEachFrame is synchronous. 1049 base::Unretained(this))); // Safe, because ForEachFrame is synchronous.
1067 saved_links, saved_file_paths, relative_dir_name));
1068 DCHECK_LT(0, number_of_frames_pending_response_); 1050 DCHECK_LT(0, number_of_frames_pending_response_);
1069 } 1051 }
1070 1052
1071 void SavePackage::GetSerializedHtmlWithLocalLinksForFrame( 1053 void SavePackage::GetSerializedHtmlWithLocalLinksForFrame(
1072 const std::vector<GURL>& saved_links,
1073 const std::vector<base::FilePath>& saved_file_paths,
1074 const base::FilePath& relative_dir_name,
1075 RenderFrameHost* target) { 1054 RenderFrameHost* target) {
1076 number_of_frames_pending_response_++; 1055 number_of_frames_pending_response_++;
1077 target->Send(new FrameMsg_GetSerializedHtmlWithLocalLinks( 1056 target->Send(
1078 target->GetRoutingID(), saved_links, saved_file_paths, 1057 new FrameMsg_GetSerializedHtmlWithLocalLinks(target->GetRoutingID()));
1079 relative_dir_name));
1080 } 1058 }
1081 1059
1082 // Process the serialized HTML content data of a specified frame 1060 void SavePackage::OnSerializedHtmlFragment(RenderFrameHost* sender,
1083 // retrieved from the renderer process. 1061 const std::string& data) {
1084 void SavePackage::OnSerializedHtmlWithLocalLinksResponse(
1085 RenderFrameHost* sender,
1086 const GURL& frame_url,
1087 const std::string& data,
1088 int32 status) {
1089 WebPageSerializerClient::PageSerializationStatus flag =
1090 static_cast<WebPageSerializerClient::PageSerializationStatus>(status);
1091
1092 // When calling WebPageSerializer::serialize in non-recursive mode, the
1093 // AllFramesAreFinished is redundant - it is sent by each frame right after
1094 // CurrentFrameIsFinished. Therefore we ignore AllFramesAreFinished and
1095 // instead track pending frames in |number_of_frames_pending_response_|.
1096 if (flag == WebPageSerializerClient::AllFramesAreFinished)
1097 return;
1098
1099 // Check current state.
1100 if (wait_state_ != HTML_DATA) 1062 if (wait_state_ != HTML_DATA)
1101 return; 1063 return;
1102 1064
1103 int id = contents_id(); 1065 int frame_tree_node_id = GetFrameTreeNodeId(sender);
1104 1066 SaveItem* save_item = frame_tree_node_id_to_save_item_[frame_tree_node_id];
1105 SaveUrlItemMap::iterator it = in_progress_items_.find(frame_url.spec()); 1067 if (save_item->state() != SaveItem::IN_PROGRESS) {
1106 if (it == in_progress_items_.end()) { 1068 LogWriteToAlreadyCompletedOrFailedSaveItem(save_item);
1107 for (SavedItemMap::iterator saved_it = saved_success_items_.begin();
1108 saved_it != saved_success_items_.end(); ++saved_it) {
1109 if (saved_it->second->url() == frame_url) {
1110 wrote_to_completed_file_ = true;
1111 break;
1112 }
1113 }
1114
1115 it = saved_failed_items_.find(frame_url.spec());
1116 if (it != saved_failed_items_.end())
1117 wrote_to_failed_file_ = true;
1118
1119 return; 1069 return;
1120 } 1070 }
1121 1071
1122 SaveItem* save_item = it->second;
1123 DCHECK(save_item->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_DOM); 1072 DCHECK(save_item->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_DOM);
1124
1125 if (!data.empty()) { 1073 if (!data.empty()) {
1126 // Prepare buffer for saving HTML data. 1074 // Prepare buffer for saving HTML data.
1127 scoped_refptr<net::IOBuffer> new_data(new net::IOBuffer(data.size())); 1075 scoped_refptr<net::IOBuffer> new_data(new net::IOBuffer(data.size()));
1128 memcpy(new_data->data(), data.data(), data.size()); 1076 memcpy(new_data->data(), data.data(), data.size());
1129 1077
1130 // Call write file functionality in file thread. 1078 // Call write file functionality in file thread.
1131 BrowserThread::PostTask( 1079 BrowserThread::PostTask(
1132 BrowserThread::FILE, FROM_HERE, 1080 BrowserThread::FILE, FROM_HERE,
1133 base::Bind(&SaveFileManager::UpdateSaveProgress, 1081 base::Bind(&SaveFileManager::UpdateSaveProgress, file_manager_,
1134 file_manager_, 1082 save_item->save_id(), new_data,
1135 save_item->save_id(),
1136 new_data,
1137 static_cast<int>(data.size()))); 1083 static_cast<int>(data.size())));
1138 } 1084 }
1085 }
1086
1087 void SavePackage::OnSerializedLocalPathForSubFrame(
1088 RenderFrameHost* sender,
1089 int render_frame_or_proxy_routing_id) {
1090 if (wait_state_ != HTML_DATA)
1091 return;
1092
1093 FrameTreeNode* frame_tree_node =
1094 static_cast<WebContentsImpl*>(web_contents())
1095 ->GetFrameTree()
1096 ->FindByRoutingID(sender->GetProcess()->GetID(),
1097 render_frame_or_proxy_routing_id);
1098 if (!frame_tree_node)
1099 return;
1100
1101 SaveItem* save_item =
1102 frame_tree_node_id_to_save_item_[frame_tree_node->frame_tree_node_id()];
1103 SerializeLocalPathForSaveItem(sender, save_item,
1104 frame_tree_node->current_url());
1105 }
1106
1107 void SavePackage::OnSerializedLocalPathForSavableResource(
1108 RenderFrameHost* sender,
1109 const GURL& savable_resource) {
1110 if (wait_state_ != HTML_DATA)
1111 return;
1112 if (!savable_resource.is_valid())
1113 return;
1114
1115 SaveItem* save_item = url_to_save_item_[savable_resource];
1116 SerializeLocalPathForSaveItem(sender, save_item, savable_resource);
1117 }
1118
1119 void SavePackage::OnSerializedEndOfFrame(RenderFrameHost* sender) {
1120 if (wait_state_ != HTML_DATA)
1121 return;
1122
1123 int frame_tree_node_id = GetFrameTreeNodeId(sender);
1124 SaveItem* save_item = frame_tree_node_id_to_save_item_[frame_tree_node_id];
1125 if (save_item->state() != SaveItem::IN_PROGRESS) {
1126 LogWriteToAlreadyCompletedOrFailedSaveItem(save_item);
1127 return;
1128 }
1129
1130 int id = contents_id();
1139 1131
1140 // Current frame is completed saving, call finish in file thread. 1132 // Current frame is completed saving, call finish in file thread.
1141 if (flag == WebPageSerializerClient::CurrentFrameIsFinished) { 1133 DVLOG(20) << " " << __FUNCTION__ << "()"
1142 DVLOG(20) << " " << __FUNCTION__ << "()" 1134 << " save_id = " << save_item->save_id() << " url = \""
1143 << " save_id = " << save_item->save_id() 1135 << save_item->url().spec() << "\"";
1144 << " url = \"" << save_item->url().spec() << "\""; 1136 BrowserThread::PostTask(
1145 BrowserThread::PostTask( 1137 BrowserThread::FILE, FROM_HERE,
1146 BrowserThread::FILE, FROM_HERE, 1138 base::Bind(&SaveFileManager::SaveFinished, file_manager_,
1147 base::Bind(&SaveFileManager::SaveFinished, 1139 save_item->save_id(), save_item->url(), id, true));
1148 file_manager_, 1140 number_of_frames_pending_response_--;
1149 save_item->save_id(), 1141 DCHECK_LE(0, number_of_frames_pending_response_);
1150 save_item->url(),
1151 id,
1152 true));
1153 number_of_frames_pending_response_--;
1154 DCHECK_LE(0, number_of_frames_pending_response_);
1155 }
1156 1142
1157 // If all frames are finished saving, we need to close the remaining 1143 // If the all frames are finished saving, we need to close the
1158 // SaveItems. 1144 // remaining SaveItems.
1159 if (number_of_frames_pending_response_ == 0) { 1145 if (number_of_frames_pending_response_ == 0) {
1160 for (SaveUrlItemMap::iterator it = in_progress_items_.begin(); 1146 for (const auto& pair : in_progress_items_) {
1161 it != in_progress_items_.end(); ++it) {
1162 DVLOG(20) << " " << __FUNCTION__ << "()" 1147 DVLOG(20) << " " << __FUNCTION__ << "()"
1163 << " save_id = " << it->second->save_id() << " url = \"" 1148 << " save_id = " << pair.second->save_id() << " url = \""
1164 << it->second->url().spec() << "\""; 1149 << pair.second->url().spec() << "\"";
1165 BrowserThread::PostTask( 1150 BrowserThread::PostTask(
1166 BrowserThread::FILE, FROM_HERE, 1151 BrowserThread::FILE, FROM_HERE,
1167 base::Bind(&SaveFileManager::SaveFinished, file_manager_, 1152 base::Bind(&SaveFileManager::SaveFinished, file_manager_,
1168 it->second->save_id(), it->second->url(), id, true)); 1153 pair.second->save_id(), pair.second->url(), id, true));
1169 } 1154 }
1170 } 1155 }
1171 } 1156 }
1172 1157
1158 void SavePackage::SerializeLocalPathForSaveItem(RenderFrameHost* sender,
1159 SaveItem* save_item,
1160 const GURL& fallback_url) {
1161 std::string attr_value;
1162 if (save_item) {
1163 base::FilePath relative_path =
1164 base::FilePath(FILE_PATH_LITERAL("."))
1165 .Append(saved_main_directory_path_.BaseName())
1166 .Append(save_item->file_name())
1167 .NormalizePathSeparatorsTo(FILE_PATH_LITERAL('/'));
1168 attr_value = relative_path.AsUTF8Unsafe();
1169 } else {
1170 attr_value = fallback_url.spec();
1171 }
1172
1173 // TODO(lukasza): Escape attr_value (&quot; + &amp;).
1174 OnSerializedHtmlFragment(sender, attr_value);
1175 }
1176
1177 void SavePackage::LogWriteToAlreadyCompletedOrFailedSaveItem(
1178 SaveItem* save_item) {
1179 auto already_completed_it =
1180 std::find_if(saved_success_items_.begin(), saved_success_items_.end(),
1181 [save_item](const SavedItemMap::value_type& v) {
1182 return v.second->url() == save_item->url();
1183 });
1184 if (already_completed_it != saved_success_items_.end())
1185 wrote_to_completed_file_ = true;
1186
1187 auto failed_it =
1188 std::find_if(saved_failed_items_.begin(), saved_failed_items_.end(),
1189 [save_item](const SaveUrlItemMap::value_type& v) {
1190 DCHECK(v.second->has_final_name());
1191 return v.second->url() == save_item->url();
1192 });
1193 if (failed_it != saved_failed_items_.end())
1194 wrote_to_failed_file_ = true;
1195 }
1196
1173 // Ask for all savable resource links from backend, include main frame and 1197 // Ask for all savable resource links from backend, include main frame and
1174 // sub-frame. 1198 // sub-frame.
1175 void SavePackage::GetSavableResourceLinks() { 1199 void SavePackage::GetSavableResourceLinks() {
1176 if (wait_state_ != START_PROCESS) 1200 if (wait_state_ != START_PROCESS)
1177 return; 1201 return;
1178 1202
1179 wait_state_ = RESOURCES_LIST; 1203 wait_state_ = RESOURCES_LIST;
1180 1204
1181 DCHECK_EQ(0, number_of_frames_pending_response_); 1205 DCHECK_EQ(0, number_of_frames_pending_response_);
1182 web_contents()->ForEachFrame(base::Bind( 1206 web_contents()->ForEachFrame(base::Bind(
(...skipping 16 matching lines...) Expand all
1199 return; 1223 return;
1200 1224
1201 if (resources_list.size() != referrers_list.size()) 1225 if (resources_list.size() != referrers_list.size())
1202 return; 1226 return;
1203 1227
1204 // Add all sub-resources to wait list. 1228 // Add all sub-resources to wait list.
1205 for (int i = 0; i < static_cast<int>(resources_list.size()); ++i) { 1229 for (int i = 0; i < static_cast<int>(resources_list.size()); ++i) {
1206 const GURL& u = resources_list[i]; 1230 const GURL& u = resources_list[i];
1207 if (!u.is_valid()) 1231 if (!u.is_valid())
1208 continue; 1232 continue;
1209 if (unique_urls_to_save_.count(u))
1210 continue;
1211 unique_urls_to_save_.insert(u);
1212 1233
1213 SaveFileCreateInfo::SaveFileSource save_source = 1234 SaveItem* save_item = url_to_save_item_[u];
1214 u.SchemeIsFile() ? SaveFileCreateInfo::SAVE_FILE_FROM_FILE 1235 if (save_item == nullptr) {
1215 : SaveFileCreateInfo::SAVE_FILE_FROM_NET; 1236 SaveFileCreateInfo::SaveFileSource save_source =
1216 SaveItem* save_item = new SaveItem(u, referrers_list[i], this, save_source); 1237 u.SchemeIsFile() ? SaveFileCreateInfo::SAVE_FILE_FROM_FILE
1217 waiting_item_queue_.push(save_item); 1238 : SaveFileCreateInfo::SAVE_FILE_FROM_NET;
1239 url_to_save_item_[u] = save_item = new SaveItem(u, this, save_source);
1240 waiting_item_queue_.push_back(save_item);
1241 }
1242 save_item->set_referrer(referrers_list[i]);
1218 } 1243 }
1219 1244
1220 // Store savable frame_url for later processing. 1245 // Add the frame to wait list.
1221 if (frame_url.is_valid()) 1246 // TODO(lukasza): Do not dedupe subframes based on url (see crbug.com/538188).
dcheng 2015/10/05 07:53:08 It seems like we don't have this check anymore?
Łukasz Anforowicz 2015/10/05 17:57:56 Thanks for catching this. I am not sure how this
1222 frame_urls_to_save_.push_back(frame_url); 1247 SaveItem* save_item = url_to_save_item_[frame_url];
1248 if (save_item == nullptr) {
1249 url_to_save_item_[frame_url] = save_item =
1250 new SaveItem(frame_url, this, SaveFileCreateInfo::SAVE_FILE_FROM_DOM);
1251 waiting_item_queue_.push_back(save_item);
1252 }
1253 frame_tree_node_id_to_save_item_[GetFrameTreeNodeId(sender)] = save_item;
1223 1254
1224 CompleteSavableResourceLinksResponse(); 1255 CompleteSavableResourceLinksResponse();
1225 } 1256 }
1226 1257
1227 void SavePackage::OnSavableResourceLinksError(RenderFrameHost* sender) { 1258 void SavePackage::OnSavableResourceLinksError(RenderFrameHost* sender) {
1228 CompleteSavableResourceLinksResponse(); 1259 CompleteSavableResourceLinksResponse();
1229 } 1260 }
1230 1261
1231 void SavePackage::CompleteSavableResourceLinksResponse() { 1262 void SavePackage::CompleteSavableResourceLinksResponse() {
1232 --number_of_frames_pending_response_; 1263 --number_of_frames_pending_response_;
1233 DCHECK_LE(0, number_of_frames_pending_response_); 1264 DCHECK_LE(0, number_of_frames_pending_response_);
1234 if (number_of_frames_pending_response_ != 0) 1265 if (number_of_frames_pending_response_ != 0)
1235 return; // Need to wait for more responses from RenderFrames. 1266 return; // Need to wait for more responses from RenderFrames.
1236 1267
1237 // Add frame urls to the waiting_item_queue_. This is done *after* processing 1268 // Sort |waiting_item_queue_| so that frames go last.
1238 // all savable resource links (i.e. in OnSavableResourceLinksResponse), to 1269 std::sort(
1239 // prefer their referrers in cases where the frame url has already been 1270 waiting_item_queue_.begin(), waiting_item_queue_.end(),
1240 // covered by savable resource links. 1271 [](SaveItem* x, SaveItem* y) {
1241 for (auto& frame_url : frame_urls_to_save_) { 1272 DCHECK(x);
1242 DCHECK(frame_url.is_valid()); 1273 DCHECK(y);
1243 if (0 == unique_urls_to_save_.count(frame_url)) { 1274 return (x->save_source() != SaveFileCreateInfo::SAVE_FILE_FROM_DOM) &&
1244 unique_urls_to_save_.insert(frame_url); 1275 (y->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_DOM);
1245 SaveItem* save_item = new SaveItem( 1276 });
1246 frame_url, Referrer(), this, SaveFileCreateInfo::SAVE_FILE_FROM_DOM);
1247 waiting_item_queue_.push(save_item);
1248 }
1249 }
1250
1251 all_save_items_count_ = static_cast<int>(waiting_item_queue_.size()); 1277 all_save_items_count_ = static_cast<int>(waiting_item_queue_.size());
1252 1278
1253 // We use total bytes as the total number of files we want to save. 1279 // We use total bytes as the total number of files we want to save.
1254 // Hack to avoid touching download_ after user cancel. 1280 // Hack to avoid touching download_ after user cancel.
1255 // TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem 1281 // TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem
1256 // with SavePackage flow. 1282 // with SavePackage flow.
1257 if (download_ && (download_->GetState() == DownloadItem::IN_PROGRESS)) 1283 if (download_ && (download_->GetState() == DownloadItem::IN_PROGRESS))
1258 download_->SetTotalBytes(all_save_items_count_); 1284 download_->SetTotalBytes(all_save_items_count_);
1259 1285
1260 if (all_save_items_count_) { 1286 if (all_save_items_count_) {
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
1505 1531
1506 void SavePackage::FinalizeDownloadEntry() { 1532 void SavePackage::FinalizeDownloadEntry() {
1507 DCHECK(download_); 1533 DCHECK(download_);
1508 DCHECK(download_manager_); 1534 DCHECK(download_manager_);
1509 1535
1510 download_manager_->OnSavePackageSuccessfullyFinished(download_); 1536 download_manager_->OnSavePackageSuccessfullyFinished(download_);
1511 StopObservation(); 1537 StopObservation();
1512 } 1538 }
1513 1539
1514 } // namespace content 1540 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698