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 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
12 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
13 #include "base/guid.h" | |
13 #include "base/i18n/file_util_icu.h" | 14 #include "base/i18n/file_util_icu.h" |
14 #include "base/logging.h" | 15 #include "base/logging.h" |
15 #include "base/macros.h" | 16 #include "base/macros.h" |
16 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
17 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
18 #include "base/strings/string_piece.h" | 19 #include "base/strings/string_piece.h" |
19 #include "base/strings/string_split.h" | 20 #include "base/strings/string_split.h" |
20 #include "base/strings/sys_string_conversions.h" | 21 #include "base/strings/sys_string_conversions.h" |
21 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
22 #include "base/threading/thread.h" | 23 #include "base/threading/thread.h" |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
342 DCHECK(!saved_main_directory_path_.empty()); | 343 DCHECK(!saved_main_directory_path_.empty()); |
343 GetSavableResourceLinks(); | 344 GetSavableResourceLinks(); |
344 } else if (save_type_ == SAVE_PAGE_TYPE_AS_MHTML) { | 345 } else if (save_type_ == SAVE_PAGE_TYPE_AS_MHTML) { |
345 MHTMLGenerationParams mhtml_generation_params(saved_main_file_path_); | 346 MHTMLGenerationParams mhtml_generation_params(saved_main_file_path_); |
346 web_contents()->GenerateMHTML( | 347 web_contents()->GenerateMHTML( |
347 mhtml_generation_params, | 348 mhtml_generation_params, |
348 base::Bind(&SavePackage::OnMHTMLGenerated, this)); | 349 base::Bind(&SavePackage::OnMHTMLGenerated, this)); |
349 } else { | 350 } else { |
350 DCHECK_EQ(SAVE_PAGE_TYPE_AS_ONLY_HTML, save_type_); | 351 DCHECK_EQ(SAVE_PAGE_TYPE_AS_ONLY_HTML, save_type_); |
351 wait_state_ = NET_FILES; | 352 wait_state_ = NET_FILES; |
352 SaveFileCreateInfo::SaveFileSource save_source = page_url_.SchemeIsFile() ? | |
353 SaveFileCreateInfo::SAVE_FILE_FROM_FILE : | |
354 SaveFileCreateInfo::SAVE_FILE_FROM_NET; | |
355 // Add this item to waiting list. | 353 // Add this item to waiting list. |
356 waiting_item_queue_.push_back( | 354 waiting_item_queue_.push_back(new SaveItem( |
357 new SaveItem(page_url_, Referrer(), this, save_source, | 355 page_url_, Referrer(), this, SaveFileCreateInfo::SAVE_FILE_FROM_NET, |
358 FrameTreeNode::kFrameTreeNodeInvalidId)); | 356 FrameTreeNode::kFrameTreeNodeInvalidId)); |
359 all_save_items_count_ = 1; | 357 all_save_items_count_ = 1; |
360 download_->SetTotalBytes(1); | 358 download_->SetTotalBytes(1); |
361 | 359 |
362 DoSavingProcess(); | 360 DoSavingProcess(); |
363 } | 361 } |
364 } | 362 } |
365 | 363 |
366 void SavePackage::OnMHTMLGenerated(int64_t size) { | 364 void SavePackage::OnMHTMLGenerated(int64_t size) { |
367 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 365 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
368 if (size <= 0) { | 366 if (size <= 0) { |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
583 // Now we get final name retrieved from GenerateFileName, we will use it | 581 // Now we get final name retrieved from GenerateFileName, we will use it |
584 // rename the SaveItem. | 582 // rename the SaveItem. |
585 base::FilePath final_name = | 583 base::FilePath final_name = |
586 saved_main_directory_path_.Append(generated_name); | 584 saved_main_directory_path_.Append(generated_name); |
587 save_item->SetTargetPath(final_name); | 585 save_item->SetTargetPath(final_name); |
588 } else { | 586 } else { |
589 // It is the main HTML file, use the name chosen by the user. | 587 // It is the main HTML file, use the name chosen by the user. |
590 save_item->SetTargetPath(saved_main_file_path_); | 588 save_item->SetTargetPath(saved_main_file_path_); |
591 } | 589 } |
592 | 590 |
593 // If the save source is from file system, inform SaveFileManager to copy | |
594 // corresponding file to the file path which this SaveItem specifies. | |
595 if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_FILE) { | |
596 BrowserThread::PostTask( | |
597 BrowserThread::FILE, FROM_HERE, | |
598 base::Bind(&SaveFileManager::SaveLocalFile, file_manager_, | |
599 save_item->url(), save_item->id(), id())); | |
600 return; | |
601 } | |
602 | |
603 // Check whether we begin to require serialized HTML data. | 591 // Check whether we begin to require serialized HTML data. |
604 if (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML && | 592 if (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML && |
605 wait_state_ == HTML_DATA) { | 593 wait_state_ == HTML_DATA) { |
606 // Inform backend to serialize the all frames' DOM and send serialized | 594 // Inform backend to serialize the all frames' DOM and send serialized |
607 // HTML data back. | 595 // HTML data back. |
608 GetSerializedHtmlWithLocalLinks(); | 596 GetSerializedHtmlWithLocalLinks(); |
609 } | 597 } |
610 } | 598 } |
611 | 599 |
612 SaveItem* SavePackage::LookupInProgressSaveItem(SaveItemId save_item_id) { | 600 SaveItem* SavePackage::LookupInProgressSaveItem(SaveItemId save_item_id) { |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
835 | 823 |
836 do { | 824 do { |
837 // Pop SaveItem from waiting list. | 825 // Pop SaveItem from waiting list. |
838 SaveItem* save_item = waiting_item_queue_.front(); | 826 SaveItem* save_item = waiting_item_queue_.front(); |
839 waiting_item_queue_.pop_front(); | 827 waiting_item_queue_.pop_front(); |
840 | 828 |
841 // Add the item to |in_progress_items_|. | 829 // Add the item to |in_progress_items_|. |
842 DCHECK(!ContainsKey(in_progress_items_, save_item->id())); | 830 DCHECK(!ContainsKey(in_progress_items_, save_item->id())); |
843 in_progress_items_[save_item->id()] = save_item; | 831 in_progress_items_[save_item->id()] = save_item; |
844 save_item->Start(); | 832 save_item->Start(); |
833 | |
834 // TODO(lukasza): https://crbug.com/616429: Pass the correct child process | |
835 // id instead of always passing main frame's process id. Correctness of | |
836 // security checks in ResourceDispatcherHostImpl::BeginSave depends on it | |
837 // (OTOH, this only matters if OOPIFs are present). | |
Łukasz Anforowicz
2016/06/18 00:37:20
I need to double-check how process_id/child_id and
asanka
2016/06/20 20:24:18
Thanks for calling this out. In addition to the tw
Łukasz Anforowicz
2016/06/21 16:39:34
Ack.
| |
845 file_manager_->SaveURL( | 838 file_manager_->SaveURL( |
846 save_item->id(), save_item->url(), save_item->referrer(), | 839 save_item->id(), save_item->url(), save_item->referrer(), |
847 web_contents()->GetRenderProcessHost()->GetID(), routing_id(), | 840 web_contents()->GetRenderProcessHost()->GetID(), routing_id(), |
848 web_contents()->GetMainFrame()->GetRoutingID(), | 841 web_contents()->GetMainFrame()->GetRoutingID(), |
849 save_item->save_source(), save_item->full_path(), | 842 save_item->save_source(), save_item->full_path(), |
850 web_contents()->GetBrowserContext()->GetResourceContext(), this); | 843 web_contents()->GetBrowserContext()->GetResourceContext(), this); |
851 } while (process_all_remaining_items && !waiting_item_queue_.empty()); | 844 } while (process_all_remaining_items && !waiting_item_queue_.empty()); |
852 } | 845 } |
853 | 846 |
854 int SavePackage::PercentComplete() { | 847 int SavePackage::PercentComplete() { |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
986 // Collect all saved success items. | 979 // Collect all saved success items. |
987 // SECURITY NOTE: We don't send *all* urls / local paths, but only | 980 // SECURITY NOTE: We don't send *all* urls / local paths, but only |
988 // those that the given frame had access to already (because it contained | 981 // those that the given frame had access to already (because it contained |
989 // the savable resources / subframes associated with save items). | 982 // the savable resources / subframes associated with save items). |
990 std::map<GURL, base::FilePath> url_to_local_path; | 983 std::map<GURL, base::FilePath> url_to_local_path; |
991 std::map<int, base::FilePath> routing_id_to_local_path; | 984 std::map<int, base::FilePath> routing_id_to_local_path; |
992 auto it = frame_tree_node_id_to_contained_save_items_.find( | 985 auto it = frame_tree_node_id_to_contained_save_items_.find( |
993 target_frame_tree_node_id); | 986 target_frame_tree_node_id); |
994 if (it != frame_tree_node_id_to_contained_save_items_.end()) { | 987 if (it != frame_tree_node_id_to_contained_save_items_.end()) { |
995 for (const SaveItem* save_item : it->second) { | 988 for (const SaveItem* save_item : it->second) { |
996 // Skip items that failed to save. | |
997 if (!save_item->has_final_name()) { | |
998 DCHECK_EQ(SaveItem::SaveState::COMPLETE, save_item->state()); | |
999 DCHECK(!save_item->success()); | |
1000 continue; | |
1001 } | |
Łukasz Anforowicz
2016/06/18 00:37:20
I've added these checks in https://codereview.chro
asanka
2016/06/20 20:24:18
Acknowledged.
| |
1002 | |
1003 // Calculate the relative path for referring to the |save_item|. | 989 // Calculate the relative path for referring to the |save_item|. |
1004 base::FilePath local_path(base::FilePath::kCurrentDirectory); | 990 base::FilePath local_path(base::FilePath::kCurrentDirectory); |
1005 if (target_tree_node->IsMainFrame()) { | 991 if (target_tree_node->IsMainFrame()) { |
1006 local_path = local_path.Append(saved_main_directory_path_.BaseName()); | 992 local_path = local_path.Append(saved_main_directory_path_.BaseName()); |
1007 } | 993 } |
1008 local_path = local_path.Append(save_item->full_path().BaseName()); | 994 if (save_item->has_final_name()) { |
995 local_path = local_path.Append(save_item->full_path().BaseName()); | |
996 } else { | |
997 // Skip items that failed to save. | |
998 DCHECK_EQ(SaveItem::SaveState::COMPLETE, save_item->state()); | |
999 DCHECK(!save_item->success()); | |
1000 local_path = local_path.Append(base::FilePath::FromUTF8Unsafe( | |
1001 "resource-failed-to-save-" + base::GenerateGUID() + ".txt")); | |
Łukasz Anforowicz
2016/06/18 00:37:20
This is tricky. We could analyze this with an exa
asanka
2016/06/20 20:24:18
As long as we are talking about subresources, I'm
Łukasz Anforowicz
2016/06/21 16:39:34
Yes - propagating origin-specific restrictions int
| |
1002 } | |
1009 | 1003 |
1010 // Insert the link into |url_to_local_path| or |routing_id_to_local_path|. | 1004 // Insert the link into |url_to_local_path| or |routing_id_to_local_path|. |
1011 if (save_item->save_source() != SaveFileCreateInfo::SAVE_FILE_FROM_DOM) { | 1005 if (save_item->save_source() != SaveFileCreateInfo::SAVE_FILE_FROM_DOM) { |
1012 DCHECK_EQ(FrameTreeNode::kFrameTreeNodeInvalidId, | 1006 DCHECK_EQ(FrameTreeNode::kFrameTreeNodeInvalidId, |
1013 save_item->frame_tree_node_id()); | 1007 save_item->frame_tree_node_id()); |
1014 url_to_local_path[save_item->url()] = local_path; | 1008 url_to_local_path[save_item->url()] = local_path; |
1015 } else { | 1009 } else { |
1016 FrameTreeNode* save_item_frame_tree_node = | 1010 FrameTreeNode* save_item_frame_tree_node = |
1017 target_tree_node->frame_tree()->FindByID( | 1011 target_tree_node->frame_tree()->FindByID( |
1018 save_item->frame_tree_node_id()); | 1012 save_item->frame_tree_node_id()); |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1207 return save_item; | 1201 return save_item; |
1208 } | 1202 } |
1209 | 1203 |
1210 void SavePackage::EnqueueSavableResource(int container_frame_tree_node_id, | 1204 void SavePackage::EnqueueSavableResource(int container_frame_tree_node_id, |
1211 const GURL& url, | 1205 const GURL& url, |
1212 const Referrer& referrer) { | 1206 const Referrer& referrer) { |
1213 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1207 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
1214 if (!url.is_valid()) | 1208 if (!url.is_valid()) |
1215 return; | 1209 return; |
1216 | 1210 |
1217 SaveFileCreateInfo::SaveFileSource save_source = | |
1218 url.SchemeIsFile() ? SaveFileCreateInfo::SAVE_FILE_FROM_FILE | |
1219 : SaveFileCreateInfo::SAVE_FILE_FROM_NET; | |
1220 CreatePendingSaveItemDeduplicatingByUrl( | 1211 CreatePendingSaveItemDeduplicatingByUrl( |
1221 container_frame_tree_node_id, FrameTreeNode::kFrameTreeNodeInvalidId, url, | 1212 container_frame_tree_node_id, FrameTreeNode::kFrameTreeNodeInvalidId, url, |
1222 referrer, save_source); | 1213 referrer, SaveFileCreateInfo::SAVE_FILE_FROM_NET); |
1223 } | 1214 } |
1224 | 1215 |
1225 void SavePackage::EnqueueFrame(int container_frame_tree_node_id, | 1216 void SavePackage::EnqueueFrame(int container_frame_tree_node_id, |
1226 int frame_tree_node_id, | 1217 int frame_tree_node_id, |
1227 const GURL& frame_original_url) { | 1218 const GURL& frame_original_url) { |
1228 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1219 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
1229 SaveItem* save_item = CreatePendingSaveItem( | 1220 SaveItem* save_item = CreatePendingSaveItem( |
1230 container_frame_tree_node_id, frame_tree_node_id, frame_original_url, | 1221 container_frame_tree_node_id, frame_tree_node_id, frame_original_url, |
1231 Referrer(), SaveFileCreateInfo::SAVE_FILE_FROM_DOM); | 1222 Referrer(), SaveFileCreateInfo::SAVE_FILE_FROM_DOM); |
1232 DCHECK(save_item); | 1223 DCHECK(save_item); |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1508 } | 1499 } |
1509 | 1500 |
1510 void SavePackage::FinalizeDownloadEntry() { | 1501 void SavePackage::FinalizeDownloadEntry() { |
1511 DCHECK(download_); | 1502 DCHECK(download_); |
1512 | 1503 |
1513 download_manager_->OnSavePackageSuccessfullyFinished(download_); | 1504 download_manager_->OnSavePackageSuccessfullyFinished(download_); |
1514 RemoveObservers(); | 1505 RemoveObservers(); |
1515 } | 1506 } |
1516 | 1507 |
1517 } // namespace content | 1508 } // namespace content |
OLD | NEW |