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 11 matching lines...) Expand all Loading... | |
| 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/loader/resource_dispatcher_host_impl.h" | 28 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
| 29 #include "content/browser/renderer_host/render_process_host_impl.h" | 29 #include "content/browser/renderer_host/render_process_host_impl.h" |
| 30 #include "content/browser/renderer_host/render_view_host_delegate.h" | 30 #include "content/browser/renderer_host/render_view_host_delegate.h" |
| 31 #include "content/browser/renderer_host/render_view_host_impl.h" | 31 #include "content/browser/renderer_host/render_view_host_impl.h" |
| 32 #include "content/common/frame_messages.h" | |
| 32 #include "content/common/view_messages.h" | 33 #include "content/common/view_messages.h" |
| 33 #include "content/public/browser/browser_context.h" | 34 #include "content/public/browser/browser_context.h" |
| 34 #include "content/public/browser/browser_thread.h" | 35 #include "content/public/browser/browser_thread.h" |
| 35 #include "content/public/browser/content_browser_client.h" | 36 #include "content/public/browser/content_browser_client.h" |
| 36 #include "content/public/browser/download_manager_delegate.h" | 37 #include "content/public/browser/download_manager_delegate.h" |
| 37 #include "content/public/browser/navigation_entry.h" | 38 #include "content/public/browser/navigation_entry.h" |
| 38 #include "content/public/browser/notification_service.h" | 39 #include "content/public/browser/notification_service.h" |
| 39 #include "content/public/browser/notification_types.h" | 40 #include "content/public/browser/notification_types.h" |
| 40 #include "content/public/browser/render_frame_host.h" | 41 #include "content/public/browser/render_frame_host.h" |
| 41 #include "content/public/browser/resource_context.h" | 42 #include "content/public/browser/resource_context.h" |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 download_ = item; | 330 download_ = item; |
| 330 download_->AddObserver(this); | 331 download_->AddObserver(this); |
| 331 // Confirm above didn't delete the tab out from under us. | 332 // Confirm above didn't delete the tab out from under us. |
| 332 if (!download_created_callback.is_null()) | 333 if (!download_created_callback.is_null()) |
| 333 download_created_callback.Run(download_); | 334 download_created_callback.Run(download_); |
| 334 | 335 |
| 335 // Check save type and process the save page job. | 336 // Check save type and process the save page job. |
| 336 if (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML) { | 337 if (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML) { |
| 337 // Get directory | 338 // Get directory |
| 338 DCHECK(!saved_main_directory_path_.empty()); | 339 DCHECK(!saved_main_directory_path_.empty()); |
| 339 GetAllSavableResourceLinksForCurrentPage(); | 340 GetSavableResourceLinksForCurrentPage(); |
| 340 } else if (save_type_ == SAVE_PAGE_TYPE_AS_MHTML) { | 341 } else if (save_type_ == SAVE_PAGE_TYPE_AS_MHTML) { |
| 341 web_contents()->GenerateMHTML(saved_main_file_path_, base::Bind( | 342 web_contents()->GenerateMHTML(saved_main_file_path_, base::Bind( |
| 342 &SavePackage::OnMHTMLGenerated, this)); | 343 &SavePackage::OnMHTMLGenerated, this)); |
| 343 } else { | 344 } else { |
| 344 DCHECK_EQ(SAVE_PAGE_TYPE_AS_ONLY_HTML, save_type_) << save_type_; | 345 DCHECK_EQ(SAVE_PAGE_TYPE_AS_ONLY_HTML, save_type_) << save_type_; |
|
nasko
2015/09/02 23:45:55
A side note. Do we behave correctly when saving on
Łukasz Anforowicz
2015/09/03 16:59:57
I haven't tested html-only. I need to do this (ev
nasko
2015/09/03 18:17:01
MHTML is almost definitely going to be broken :).
| |
| 345 wait_state_ = NET_FILES; | 346 wait_state_ = NET_FILES; |
| 346 SaveFileCreateInfo::SaveFileSource save_source = page_url_.SchemeIsFile() ? | 347 SaveFileCreateInfo::SaveFileSource save_source = page_url_.SchemeIsFile() ? |
| 347 SaveFileCreateInfo::SAVE_FILE_FROM_FILE : | 348 SaveFileCreateInfo::SAVE_FILE_FROM_FILE : |
| 348 SaveFileCreateInfo::SAVE_FILE_FROM_NET; | 349 SaveFileCreateInfo::SAVE_FILE_FROM_NET; |
| 349 SaveItem* save_item = new SaveItem(page_url_, | 350 SaveItem* save_item = new SaveItem(page_url_, |
| 350 Referrer(), | 351 Referrer(), |
| 351 this, | 352 this, |
| 352 save_source); | 353 save_source); |
| 353 // Add this item to waiting list. | 354 // Add this item to waiting list. |
| 354 waiting_item_queue_.push(save_item); | 355 waiting_item_queue_.push(save_item); |
| (...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 996 if (waiting_item_queue_.size()) { | 997 if (waiting_item_queue_.size()) { |
| 997 DCHECK(all_save_items_count_ == waiting_item_queue_.size()); | 998 DCHECK(all_save_items_count_ == waiting_item_queue_.size()); |
| 998 SaveNextFile(false); | 999 SaveNextFile(false); |
| 999 } | 1000 } |
| 1000 } | 1001 } |
| 1001 } | 1002 } |
| 1002 | 1003 |
| 1003 bool SavePackage::OnMessageReceived(const IPC::Message& message) { | 1004 bool SavePackage::OnMessageReceived(const IPC::Message& message) { |
| 1004 bool handled = true; | 1005 bool handled = true; |
| 1005 IPC_BEGIN_MESSAGE_MAP(SavePackage, message) | 1006 IPC_BEGIN_MESSAGE_MAP(SavePackage, message) |
| 1006 IPC_MESSAGE_HANDLER(ViewHostMsg_SendCurrentPageAllSavableResourceLinks, | |
| 1007 OnReceivedSavableResourceLinksForCurrentPage) | |
| 1008 IPC_MESSAGE_HANDLER(ViewHostMsg_SendSerializedHtmlData, | 1007 IPC_MESSAGE_HANDLER(ViewHostMsg_SendSerializedHtmlData, |
| 1009 OnReceivedSerializedHtmlData) | 1008 OnReceivedSerializedHtmlData) |
| 1010 IPC_MESSAGE_UNHANDLED(handled = false) | 1009 IPC_MESSAGE_UNHANDLED(handled = false) |
| 1011 IPC_END_MESSAGE_MAP() | 1010 IPC_END_MESSAGE_MAP() |
| 1012 return handled; | 1011 return handled; |
| 1013 } | 1012 } |
| 1014 | 1013 |
| 1014 bool SavePackage::OnMessageReceived(const IPC::Message& message, | |
| 1015 RenderFrameHost* render_frame_host) { | |
| 1016 bool handled = true; | |
| 1017 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(SavePackage, message, render_frame_host) | |
| 1018 IPC_MESSAGE_HANDLER(FrameHostMsg_SavableResourceLinksResponse, | |
| 1019 OnReceivedSavableResourceLinksForFrame) | |
| 1020 IPC_MESSAGE_HANDLER(FrameHostMsg_NonSavableResponse, | |
| 1021 OnReceivedNonSavableFrameIndication) | |
| 1022 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 1023 IPC_END_MESSAGE_MAP() | |
| 1024 return handled; | |
| 1025 } | |
| 1026 | |
| 1015 // After finishing all SaveItems which need to get data from net. | 1027 // After finishing all SaveItems which need to get data from net. |
| 1016 // We collect all URLs which have local storage and send the | 1028 // We collect all URLs which have local storage and send the |
| 1017 // map:(originalURL:currentLocalPath) to render process (backend). | 1029 // map:(originalURL:currentLocalPath) to render process (backend). |
| 1018 // Then render process will serialize DOM and send data to us. | 1030 // Then render process will serialize DOM and send data to us. |
| 1019 void SavePackage::GetSerializedHtmlDataForCurrentPageWithLocalLinks() { | 1031 void SavePackage::GetSerializedHtmlDataForCurrentPageWithLocalLinks() { |
| 1020 if (wait_state_ != HTML_DATA) | 1032 if (wait_state_ != HTML_DATA) |
| 1021 return; | 1033 return; |
| 1022 std::vector<GURL> saved_links; | 1034 std::vector<GURL> saved_links; |
| 1023 std::vector<base::FilePath> saved_file_paths; | 1035 std::vector<base::FilePath> saved_file_paths; |
| 1024 int successful_started_items_count = 0; | 1036 int successful_started_items_count = 0; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1135 file_manager_, | 1147 file_manager_, |
| 1136 save_item->save_id(), | 1148 save_item->save_id(), |
| 1137 save_item->url(), | 1149 save_item->url(), |
| 1138 id, | 1150 id, |
| 1139 true)); | 1151 true)); |
| 1140 } | 1152 } |
| 1141 } | 1153 } |
| 1142 | 1154 |
| 1143 // Ask for all savable resource links from backend, include main frame and | 1155 // Ask for all savable resource links from backend, include main frame and |
| 1144 // sub-frame. | 1156 // sub-frame. |
| 1145 void SavePackage::GetAllSavableResourceLinksForCurrentPage() { | 1157 void SavePackage::GetSavableResourceLinksForCurrentPage() { |
| 1146 if (wait_state_ != START_PROCESS) | 1158 if (wait_state_ != START_PROCESS) |
| 1147 return; | 1159 return; |
| 1148 | 1160 |
| 1161 WebContents* web_contents = WebContentsObserver::web_contents(); | |
|
nasko
2015/09/02 23:45:55
This object is already WebContentsObserver, so no
Łukasz Anforowicz
2015/09/03 16:59:57
This is tricky. I need the prefix, because otherw
nasko
2015/09/03 18:17:01
Why do you need a local web_contents variable is t
Łukasz Anforowicz
2015/09/03 19:41:24
Oh, right... Done. :-)
| |
| 1162 if (!web_contents) { | |
| 1163 // Tab got closed - treat it as user cancel. | |
| 1164 Cancel(true); | |
| 1165 return; | |
| 1166 } | |
| 1167 | |
| 1149 wait_state_ = RESOURCES_LIST; | 1168 wait_state_ = RESOURCES_LIST; |
| 1150 Send(new ViewMsg_GetAllSavableResourceLinksForCurrentPage(routing_id(), | 1169 number_of_frames_with_pending_get_savable_resource_links_ = 0; |
| 1151 page_url_)); | 1170 web_contents->ForEachFrame(base::Bind( |
| 1171 &SavePackage::GetSavableResourceLinksForFrame, | |
| 1172 base::Unretained(this))); // Safe, because ForEachFrame is synchronous. | |
|
nasko
2015/09/02 23:45:55
Thanks for the comment!
Łukasz Anforowicz
2015/09/03 16:59:56
Acknowledged.
| |
| 1173 | |
| 1174 if (0 == number_of_frames_with_pending_get_savable_resource_links_) { | |
|
nasko
2015/09/02 23:45:55
Is this condition possible? If not, let's use a DC
Łukasz Anforowicz
2015/09/03 16:59:56
Done. I wasn't sure if WebContents is guaranteed
| |
| 1175 // No frames in the web contents - treat it as user cancel. | |
| 1176 Cancel(true); | |
| 1177 return; | |
| 1178 } | |
| 1152 } | 1179 } |
| 1153 | 1180 |
| 1154 // Give backend the lists which contain all resource links that have local | 1181 void SavePackage::GetSavableResourceLinksForFrame( |
| 1155 // storage, after which, render process will serialize DOM for generating | 1182 RenderFrameHost* render_frame_host) { |
| 1156 // HTML data. | 1183 number_of_frames_with_pending_get_savable_resource_links_++; |
| 1157 void SavePackage::OnReceivedSavableResourceLinksForCurrentPage( | 1184 Send(new FrameMsg_GetSavableResourceLinks(render_frame_host->GetRoutingID())); |
| 1185 } | |
| 1186 | |
| 1187 void SavePackage::OnReceivedSavableResourceLinksForFrame( | |
| 1188 RenderFrameHost* render_frame_host, | |
| 1158 const std::vector<GURL>& resources_list, | 1189 const std::vector<GURL>& resources_list, |
| 1159 const std::vector<Referrer>& referrers_list, | 1190 const std::vector<Referrer>& referrers_list) { |
| 1160 const std::vector<GURL>& frames_list) { | |
| 1161 if (wait_state_ != RESOURCES_LIST) | 1191 if (wait_state_ != RESOURCES_LIST) |
| 1162 return; | 1192 return; |
| 1163 | 1193 |
| 1164 if (resources_list.size() != referrers_list.size()) | 1194 if (resources_list.size() != referrers_list.size()) |
| 1165 return; | 1195 return; |
| 1166 | 1196 |
| 1167 all_save_items_count_ = static_cast<int>(resources_list.size()) + | 1197 // Add all sub-resources to wait list. |
| 1168 static_cast<int>(frames_list.size()); | 1198 for (int i = 0; i < static_cast<int>(resources_list.size()); ++i) { |
| 1199 const GURL& u = resources_list[i]; | |
| 1200 DCHECK(u.is_valid()); | |
| 1201 if (unique_urls_to_save_.count(u)) { | |
| 1202 continue; | |
| 1203 } | |
| 1204 unique_urls_to_save_.insert(u); | |
| 1205 | |
| 1206 SaveFileCreateInfo::SaveFileSource save_source = | |
| 1207 u.SchemeIsFile() ? SaveFileCreateInfo::SAVE_FILE_FROM_FILE | |
| 1208 : SaveFileCreateInfo::SAVE_FILE_FROM_NET; | |
| 1209 SaveItem* save_item = new SaveItem(u, referrers_list[i], this, save_source); | |
| 1210 waiting_item_queue_.push(save_item); | |
| 1211 } | |
| 1212 | |
| 1213 // Add the frame to wait list. | |
| 1214 GURL frame_url = render_frame_host->GetLastCommittedURL(); | |
|
nasko
2015/09/02 23:45:55
Hmm, I wonder if this can be racy. Might be useful
Łukasz Anforowicz
2015/09/03 16:59:56
Right. I tried to allude to this in the CL descri
| |
| 1215 DCHECK(frame_url.is_valid()); | |
| 1216 if (0 == unique_urls_to_save_.count(frame_url)) { | |
| 1217 unique_urls_to_save_.insert(frame_url); | |
| 1218 SaveItem* save_item = new SaveItem(frame_url, Referrer(), this, | |
| 1219 SaveFileCreateInfo::SAVE_FILE_FROM_DOM); | |
| 1220 waiting_item_queue_.push(save_item); | |
| 1221 } | |
| 1222 | |
| 1223 CompleteSavableResourceLinksResponseFromFrame(); | |
| 1224 } | |
| 1225 | |
| 1226 void SavePackage::OnReceivedNonSavableFrameIndication( | |
| 1227 RenderFrameHost* render_frame_host) { | |
| 1228 CompleteSavableResourceLinksResponseFromFrame(); | |
| 1229 } | |
| 1230 | |
| 1231 void SavePackage::CompleteSavableResourceLinksResponseFromFrame() { | |
| 1232 --number_of_frames_with_pending_get_savable_resource_links_; | |
| 1233 if (0 < number_of_frames_with_pending_get_savable_resource_links_) { | |
|
nasko
2015/09/02 23:45:55
We should never go negative, should we?
Łukasz Anforowicz
2015/09/03 16:59:57
Correct - we should never go negative. This is en
nasko
2015/09/03 18:17:01
If we never should go negative, then we shouldn't
Łukasz Anforowicz
2015/09/03 19:41:24
I rewrote the DCHECK and "if" to make it more obvi
| |
| 1234 return; | |
| 1235 } | |
| 1236 DCHECK_EQ(0, number_of_frames_with_pending_get_savable_resource_links_); | |
|
nasko
2015/09/02 23:45:55
It seems to me that this DCHECK can easily hit. Th
Łukasz Anforowicz
2015/09/03 16:59:56
If the number is not zero, then we will return on
nasko
2015/09/03 18:17:01
Since that if statement should disappear, the DCHE
Łukasz Anforowicz
2015/09/03 19:41:24
See the previous comment.
| |
| 1237 | |
| 1238 all_save_items_count_ = static_cast<int>(unique_urls_to_save_.size()); | |
| 1169 | 1239 |
| 1170 // We use total bytes as the total number of files we want to save. | 1240 // We use total bytes as the total number of files we want to save. |
| 1171 // Hack to avoid touching download_ after user cancel. | 1241 // Hack to avoid touching download_ after user cancel. |
| 1172 // TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem | 1242 // TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem |
| 1173 // with SavePackage flow. | 1243 // with SavePackage flow. |
| 1174 if (download_ && (download_->GetState() == DownloadItem::IN_PROGRESS)) | 1244 if (download_ && (download_->GetState() == DownloadItem::IN_PROGRESS)) |
| 1175 download_->SetTotalBytes(all_save_items_count_); | 1245 download_->SetTotalBytes(all_save_items_count_); |
| 1176 | 1246 |
| 1177 if (all_save_items_count_) { | 1247 if (all_save_items_count_) { |
| 1178 // Put all sub-resources to wait list. | |
| 1179 for (int i = 0; i < static_cast<int>(resources_list.size()); ++i) { | |
| 1180 const GURL& u = resources_list[i]; | |
| 1181 DCHECK(u.is_valid()); | |
| 1182 SaveFileCreateInfo::SaveFileSource save_source = u.SchemeIsFile() ? | |
| 1183 SaveFileCreateInfo::SAVE_FILE_FROM_FILE : | |
| 1184 SaveFileCreateInfo::SAVE_FILE_FROM_NET; | |
| 1185 SaveItem* save_item = new SaveItem(u, referrers_list[i], | |
| 1186 this, save_source); | |
| 1187 waiting_item_queue_.push(save_item); | |
| 1188 } | |
| 1189 // Put all HTML resources to wait list. | |
| 1190 for (int i = 0; i < static_cast<int>(frames_list.size()); ++i) { | |
| 1191 const GURL& u = frames_list[i]; | |
| 1192 DCHECK(u.is_valid()); | |
| 1193 SaveItem* save_item = new SaveItem( | |
| 1194 u, Referrer(), this, SaveFileCreateInfo::SAVE_FILE_FROM_DOM); | |
| 1195 waiting_item_queue_.push(save_item); | |
| 1196 } | |
| 1197 wait_state_ = NET_FILES; | 1248 wait_state_ = NET_FILES; |
| 1249 | |
| 1250 // Give backend the lists which contain all resource links that have local | |
| 1251 // storage, after which, render process will serialize DOM for generating | |
| 1252 // HTML data. | |
| 1198 DoSavingProcess(); | 1253 DoSavingProcess(); |
| 1199 } else { | 1254 } else { |
| 1200 // No resource files need to be saved, treat it as user cancel. | 1255 // No resource files need to be saved, treat it as user cancel. |
| 1201 Cancel(true); | 1256 Cancel(true); |
| 1202 } | 1257 } |
| 1203 } | 1258 } |
| 1204 | 1259 |
| 1205 base::FilePath SavePackage::GetSuggestedNameForSaveAs( | 1260 base::FilePath SavePackage::GetSuggestedNameForSaveAs( |
| 1206 bool can_save_as_complete, | 1261 bool can_save_as_complete, |
| 1207 const std::string& contents_mime_type, | 1262 const std::string& contents_mime_type, |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1437 | 1492 |
| 1438 void SavePackage::FinalizeDownloadEntry() { | 1493 void SavePackage::FinalizeDownloadEntry() { |
| 1439 DCHECK(download_); | 1494 DCHECK(download_); |
| 1440 DCHECK(download_manager_); | 1495 DCHECK(download_manager_); |
| 1441 | 1496 |
| 1442 download_manager_->OnSavePackageSuccessfullyFinished(download_); | 1497 download_manager_->OnSavePackageSuccessfullyFinished(download_); |
| 1443 StopObservation(); | 1498 StopObservation(); |
| 1444 } | 1499 } |
| 1445 | 1500 |
| 1446 } // namespace content | 1501 } // namespace content |
| OLD | NEW |