Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/file_path.h" | 9 #include "base/file_path.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| 11 #include "base/i18n/file_util_icu.h" | 11 #include "base/i18n/file_util_icu.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
| 14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 15 #include "base/string_piece.h" | 15 #include "base/string_piece.h" |
| 16 #include "base/string_split.h" | 16 #include "base/string_split.h" |
| 17 #include "base/sys_string_conversions.h" | 17 #include "base/sys_string_conversions.h" |
| 18 #include "base/task.h" | 18 #include "base/task.h" |
| 19 #include "base/threading/thread.h" | 19 #include "base/threading/thread.h" |
| 20 #include "base/utf_string_conversions.h" | 20 #include "base/utf_string_conversions.h" |
| 21 #include "chrome/browser/download/download_history.h" | |
| 21 #include "chrome/browser/download/download_item.h" | 22 #include "chrome/browser/download/download_item.h" |
| 22 #include "chrome/browser/download/download_item_model.h" | 23 #include "chrome/browser/download/download_item_model.h" |
| 23 #include "chrome/browser/download/download_manager.h" | 24 #include "chrome/browser/download/download_manager.h" |
| 24 #include "chrome/browser/download/download_util.h" | 25 #include "chrome/browser/download/download_util.h" |
| 25 #include "chrome/browser/prefs/pref_member.h" | 26 #include "chrome/browser/prefs/pref_member.h" |
| 26 #include "chrome/browser/prefs/pref_service.h" | 27 #include "chrome/browser/prefs/pref_service.h" |
| 27 #include "chrome/browser/profiles/profile.h" | 28 #include "chrome/browser/profiles/profile.h" |
| 28 #include "chrome/common/pref_names.h" | 29 #include "chrome/common/pref_names.h" |
| 29 #include "content/browser/browser_thread.h" | 30 #include "content/browser/browser_thread.h" |
| 30 #include "content/browser/content_browser_client.h" | 31 #include "content/browser/content_browser_client.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 44 #include "net/base/mime_util.h" | 45 #include "net/base/mime_util.h" |
| 45 #include "net/base/net_util.h" | 46 #include "net/base/net_util.h" |
| 46 #include "net/url_request/url_request_context.h" | 47 #include "net/url_request/url_request_context.h" |
| 47 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPageSerializerClie nt.h" | 48 #include "third_party/WebKit/Source/WebKit/chromium/public/WebPageSerializerClie nt.h" |
| 48 | 49 |
| 49 using base::Time; | 50 using base::Time; |
| 50 using WebKit::WebPageSerializerClient; | 51 using WebKit::WebPageSerializerClient; |
| 51 | 52 |
| 52 namespace { | 53 namespace { |
| 53 | 54 |
| 55 /* | |
| 56 Race analysis: | |
|
Paweł Hajdan Jr.
2011/07/27 16:53:51
I'm not sure about adding this as a comment in the
Randy Smith (Not in Mondays)
2011/07/27 21:08:35
Yeah. Another take on this is that if we need thi
achuithb
2011/07/28 00:45:58
I've moved the comments to the end of download_man
| |
| 57 + The actions that can race against each other are: | |
| 58 * History callback | |
| 59 * Completion (save page as finishes) | |
| 60 * Cancel (SavePackage::Stop()) | |
| 61 * Shutdown | |
| 62 * Remove | |
| 63 + Cancel and completion can be considered equivalent for race | |
| 64 processing, as they have the same effect on the download manager, and | |
| 65 SavePackage won't produce any more events after either of them. I'll | |
| 66 refer to the OR of these two events as "Finishing". | |
| 67 + Anything that occurs after both History callback and Finishing is | |
| 68 uninteresting, as there won't be anything in the queues anymore. | |
| 69 + Only the History Callback or Remove can occur after Shutdown (the | |
| 70 SavePackage system won't produce any more events after these two). | |
| 71 + Remove does not cancel (probably not a mistake you'd make, but it | |
| 72 does on downloads, so I'm noting it for myself). | |
| 73 + Shutdown can only occur after Finishing(Cancel) (destroying a | |
| 74 profile happens strictly after destroying all TabContents associated | |
| 75 with the profile). | |
| 76 + Remove can only occur after the History Callback. | |
| 77 | |
| 78 This leads to the following possible orders of events: | |
| 79 -- Finishing, History Callback | |
| 80 Variations on the basic one. Ok. | |
| 81 -- Finishing(Cancel), Shutdown, History Callback | |
| 82 The cancel leaves the DI in the queue, shutdown removes and deletes | |
| 83 it, and the history callback doesn't find it, leaving it in the DB | |
| 84 as IN_PROGRESS, which will be turned into Cancelled on next load. | |
| 85 Ok. | |
| 86 -- History Callback, Finishing | |
| 87 The basic order. Ok. | |
| 88 -- History Callback, Remove, Finishing | |
| 89 This results in a lack of update of the database to indicate | |
| 90 that the download has completed (if the finishing action is | |
| 91 completed), but that's not solvable until we cancel on Remove | |
| 92 (which would update the DB). | |
| 93 */ | |
| 94 | |
| 54 // A counter for uniquely identifying each save package. | 95 // A counter for uniquely identifying each save package. |
| 55 int g_save_package_id = 0; | 96 int g_save_package_id = 0; |
| 56 | 97 |
| 57 // Default name which will be used when we can not get proper name from | 98 // Default name which will be used when we can not get proper name from |
| 58 // resource URL. | 99 // resource URL. |
| 59 const char kDefaultSaveName[] = "saved_resource"; | 100 const char kDefaultSaveName[] = "saved_resource"; |
| 60 | 101 |
| 61 // Maximum number of file ordinal number. I think it's big enough for resolving | 102 // Maximum number of file ordinal number. I think it's big enough for resolving |
| 62 // name-conflict files which has same base file name. | 103 // name-conflict files which has same base file name. |
| 63 const int32 kMaxFileOrdinalNumber = 9999; | 104 const int32 kMaxFileOrdinalNumber = 9999; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 113 #else | 154 #else |
| 114 FILE_PATH_LITERAL("html"); | 155 FILE_PATH_LITERAL("html"); |
| 115 #endif | 156 #endif |
| 116 | 157 |
| 117 SavePackage::SavePackage(TabContents* tab_contents, | 158 SavePackage::SavePackage(TabContents* tab_contents, |
| 118 SavePackageType save_type, | 159 SavePackageType save_type, |
| 119 const FilePath& file_full_path, | 160 const FilePath& file_full_path, |
| 120 const FilePath& directory_full_path) | 161 const FilePath& directory_full_path) |
| 121 : TabContentsObserver(tab_contents), | 162 : TabContentsObserver(tab_contents), |
| 122 file_manager_(NULL), | 163 file_manager_(NULL), |
| 164 download_manager_(NULL), | |
| 123 download_(NULL), | 165 download_(NULL), |
| 124 page_url_(GetUrlToBeSaved()), | 166 page_url_(GetUrlToBeSaved()), |
| 125 saved_main_file_path_(file_full_path), | 167 saved_main_file_path_(file_full_path), |
| 126 saved_main_directory_path_(directory_full_path), | 168 saved_main_directory_path_(directory_full_path), |
| 127 title_(tab_contents->GetTitle()), | 169 title_(tab_contents->GetTitle()), |
| 128 finished_(false), | 170 finished_(false), |
| 129 user_canceled_(false), | 171 user_canceled_(false), |
| 130 disk_error_occurred_(false), | 172 disk_error_occurred_(false), |
| 131 save_type_(save_type), | 173 save_type_(save_type), |
| 132 all_save_items_count_(0), | 174 all_save_items_count_(0), |
| 133 wait_state_(INITIALIZE), | 175 wait_state_(INITIALIZE), |
| 134 tab_id_(tab_contents->GetRenderProcessHost()->id()), | 176 tab_id_(tab_contents->GetRenderProcessHost()->id()), |
| 135 unique_id_(g_save_package_id++), | 177 unique_id_(g_save_package_id++), |
| 136 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { | 178 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { |
| 137 DCHECK(page_url_.is_valid()); | 179 DCHECK(page_url_.is_valid()); |
| 138 DCHECK(save_type_ == SAVE_AS_ONLY_HTML || | 180 DCHECK(save_type_ == SAVE_AS_ONLY_HTML || |
| 139 save_type_ == SAVE_AS_COMPLETE_HTML); | 181 save_type_ == SAVE_AS_COMPLETE_HTML); |
| 140 DCHECK(!saved_main_file_path_.empty() && | 182 DCHECK(!saved_main_file_path_.empty() && |
| 141 saved_main_file_path_.value().length() <= kMaxFilePathLength); | 183 saved_main_file_path_.value().length() <= kMaxFilePathLength); |
| 142 DCHECK(!saved_main_directory_path_.empty() && | 184 DCHECK(!saved_main_directory_path_.empty() && |
| 143 saved_main_directory_path_.value().length() < kMaxFilePathLength); | 185 saved_main_directory_path_.value().length() < kMaxFilePathLength); |
| 144 InternalInit(); | 186 InternalInit(); |
| 145 } | 187 } |
| 146 | 188 |
| 147 SavePackage::SavePackage(TabContents* tab_contents) | 189 SavePackage::SavePackage(TabContents* tab_contents) |
| 148 : TabContentsObserver(tab_contents), | 190 : TabContentsObserver(tab_contents), |
| 149 file_manager_(NULL), | 191 file_manager_(NULL), |
| 192 download_manager_(NULL), | |
| 150 download_(NULL), | 193 download_(NULL), |
| 151 page_url_(GetUrlToBeSaved()), | 194 page_url_(GetUrlToBeSaved()), |
| 152 title_(tab_contents->GetTitle()), | 195 title_(tab_contents->GetTitle()), |
| 153 finished_(false), | 196 finished_(false), |
| 154 user_canceled_(false), | 197 user_canceled_(false), |
| 155 disk_error_occurred_(false), | 198 disk_error_occurred_(false), |
| 156 save_type_(SAVE_TYPE_UNKNOWN), | 199 save_type_(SAVE_TYPE_UNKNOWN), |
| 157 all_save_items_count_(0), | 200 all_save_items_count_(0), |
| 158 wait_state_(INITIALIZE), | 201 wait_state_(INITIALIZE), |
| 159 tab_id_(tab_contents->GetRenderProcessHost()->id()), | 202 tab_id_(tab_contents->GetRenderProcessHost()->id()), |
| 160 unique_id_(g_save_package_id++), | 203 unique_id_(g_save_package_id++), |
| 161 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { | 204 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { |
| 162 DCHECK(page_url_.is_valid()); | 205 DCHECK(page_url_.is_valid()); |
| 163 InternalInit(); | 206 InternalInit(); |
| 164 } | 207 } |
| 165 | 208 |
| 166 // This is for testing use. Set |finished_| as true because we don't want | 209 // This is for testing use. Set |finished_| as true because we don't want |
| 167 // method Cancel to be be called in destructor in test mode. | 210 // method Cancel to be be called in destructor in test mode. |
| 168 // We also don't call InternalInit(). | 211 // We also don't call InternalInit(). |
| 169 SavePackage::SavePackage(TabContents* tab_contents, | 212 SavePackage::SavePackage(TabContents* tab_contents, |
| 170 const FilePath& file_full_path, | 213 const FilePath& file_full_path, |
| 171 const FilePath& directory_full_path) | 214 const FilePath& directory_full_path) |
| 172 : TabContentsObserver(tab_contents), | 215 : TabContentsObserver(tab_contents), |
| 173 file_manager_(NULL), | 216 file_manager_(NULL), |
| 217 download_manager_(NULL), | |
| 174 download_(NULL), | 218 download_(NULL), |
| 175 saved_main_file_path_(file_full_path), | 219 saved_main_file_path_(file_full_path), |
| 176 saved_main_directory_path_(directory_full_path), | 220 saved_main_directory_path_(directory_full_path), |
| 177 finished_(true), | 221 finished_(true), |
| 178 user_canceled_(false), | 222 user_canceled_(false), |
| 179 disk_error_occurred_(false), | 223 disk_error_occurred_(false), |
| 180 save_type_(SAVE_TYPE_UNKNOWN), | 224 save_type_(SAVE_TYPE_UNKNOWN), |
| 181 all_save_items_count_(0), | 225 all_save_items_count_(0), |
| 182 wait_state_(INITIALIZE), | 226 wait_state_(INITIALIZE), |
| 183 tab_id_(0), | 227 tab_id_(0), |
| 184 unique_id_(g_save_package_id++), | 228 unique_id_(g_save_package_id++), |
| 185 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { | 229 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { |
| 186 } | 230 } |
| 187 | 231 |
| 188 SavePackage::~SavePackage() { | 232 SavePackage::~SavePackage() { |
| 189 // Stop receiving saving job's updates | 233 // Stop receiving saving job's updates |
| 190 if (!finished_ && !canceled()) { | 234 if (!finished_ && !canceled()) { |
| 191 // Unexpected quit. | 235 // Unexpected quit. |
| 192 Cancel(true); | 236 Cancel(true); |
| 193 } | 237 } |
| 194 | 238 |
| 239 // We should no longer be observing the DownloadManager at this point. | |
| 240 CHECK(!download_manager_); | |
| 241 CHECK(!download_); | |
| 242 | |
| 195 DCHECK(all_save_items_count_ == (waiting_item_queue_.size() + | 243 DCHECK(all_save_items_count_ == (waiting_item_queue_.size() + |
| 196 completed_count() + | 244 completed_count() + |
| 197 in_process_count())); | 245 in_process_count())); |
| 198 // Free all SaveItems. | 246 // Free all SaveItems. |
| 199 while (!waiting_item_queue_.empty()) { | 247 while (!waiting_item_queue_.empty()) { |
| 200 // We still have some items which are waiting for start to save. | 248 // We still have some items which are waiting for start to save. |
| 201 SaveItem* save_item = waiting_item_queue_.front(); | 249 SaveItem* save_item = waiting_item_queue_.front(); |
| 202 waiting_item_queue_.pop(); | 250 waiting_item_queue_.pop(); |
| 203 delete save_item; | 251 delete save_item; |
| 204 } | 252 } |
| 205 | 253 |
| 206 STLDeleteValues(&saved_success_items_); | 254 STLDeleteValues(&saved_success_items_); |
| 207 STLDeleteValues(&in_progress_items_); | 255 STLDeleteValues(&in_progress_items_); |
| 208 STLDeleteValues(&saved_failed_items_); | 256 STLDeleteValues(&saved_failed_items_); |
| 209 | 257 |
| 210 // The DownloadItem is owned by DownloadManager. | |
| 211 download_ = NULL; | |
| 212 | |
| 213 file_manager_ = NULL; | 258 file_manager_ = NULL; |
| 214 } | 259 } |
| 215 | 260 |
| 216 GURL SavePackage::GetUrlToBeSaved() { | 261 GURL SavePackage::GetUrlToBeSaved() { |
| 217 // Instead of using tab_contents_.GetURL here, we use url() | 262 // Instead of using tab_contents_.GetURL here, we use url() |
| 218 // (which is the "real" url of the page) | 263 // (which is the "real" url of the page) |
| 219 // from the NavigationEntry because it reflects its' origin | 264 // from the NavigationEntry because it reflects its' origin |
| 220 // rather than the displayed one (returned by GetURL) which may be | 265 // rather than the displayed one (returned by GetURL) which may be |
| 221 // different (like having "view-source:" on the front). | 266 // different (like having "view-source:" on the front). |
| 222 NavigationEntry* active_entry = | 267 NavigationEntry* active_entry = |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 258 | 303 |
| 259 wait_state_ = START_PROCESS; | 304 wait_state_ = START_PROCESS; |
| 260 | 305 |
| 261 // Initialize the request context and resource dispatcher. | 306 // Initialize the request context and resource dispatcher. |
| 262 Profile* profile = tab_contents()->profile(); | 307 Profile* profile = tab_contents()->profile(); |
| 263 if (!profile) { | 308 if (!profile) { |
| 264 NOTREACHED(); | 309 NOTREACHED(); |
| 265 return false; | 310 return false; |
| 266 } | 311 } |
| 267 | 312 |
| 268 // Create the fake DownloadItem and display the view. | 313 // Get the download manager and add ourselves as an observer. |
| 269 DownloadManager* download_manager = | 314 download_manager_ = tab_contents()->profile()->GetDownloadManager(); |
| 270 tab_contents()->profile()->GetDownloadManager(); | 315 if (!download_manager_) { |
| 271 download_ = new DownloadItem(download_manager, | 316 NOTREACHED(); |
| 317 return false; | |
| 318 } | |
| 319 | |
| 320 // Create the download item. | |
| 321 download_ = new DownloadItem(download_manager_, | |
| 272 saved_main_file_path_, | 322 saved_main_file_path_, |
| 273 page_url_, | 323 page_url_, |
| 274 profile->IsOffTheRecord()); | 324 profile->IsOffTheRecord()); |
| 325 download_->AddObserver(this); | |
| 275 | 326 |
| 276 // Transfer the ownership to the download manager. We need the DownloadItem | 327 // Transfer ownership to the download manager. |
| 277 // to be alive as long as the Profile is alive. | 328 download_manager_->SavePageDownloadStarted(download_); |
| 278 download_manager->SavePageAsDownloadStarted(download_); | |
| 279 | |
| 280 tab_contents()->OnStartDownload(download_); | |
| 281 | 329 |
| 282 // Check save type and process the save page job. | 330 // Check save type and process the save page job. |
| 283 if (save_type_ == SAVE_AS_COMPLETE_HTML) { | 331 if (save_type_ == SAVE_AS_COMPLETE_HTML) { |
| 284 // Get directory | 332 // Get directory |
| 285 DCHECK(!saved_main_directory_path_.empty()); | 333 DCHECK(!saved_main_directory_path_.empty()); |
| 286 GetAllSavableResourceLinksForCurrentPage(); | 334 GetAllSavableResourceLinksForCurrentPage(); |
| 287 } else { | 335 } else { |
| 288 wait_state_ = NET_FILES; | 336 wait_state_ = NET_FILES; |
| 289 SaveFileCreateInfo::SaveFileSource save_source = page_url_.SchemeIsFile() ? | 337 SaveFileCreateInfo::SaveFileSource save_source = page_url_.SchemeIsFile() ? |
| 290 SaveFileCreateInfo::SAVE_FILE_FROM_FILE : | 338 SaveFileCreateInfo::SAVE_FILE_FROM_FILE : |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 632 BrowserThread::PostTask( | 680 BrowserThread::PostTask( |
| 633 BrowserThread::FILE, FROM_HERE, | 681 BrowserThread::FILE, FROM_HERE, |
| 634 NewRunnableMethod(file_manager_, | 682 NewRunnableMethod(file_manager_, |
| 635 &SaveFileManager::RemoveSavedFileFromFileMap, | 683 &SaveFileManager::RemoveSavedFileFromFileMap, |
| 636 save_ids)); | 684 save_ids)); |
| 637 | 685 |
| 638 finished_ = true; | 686 finished_ = true; |
| 639 wait_state_ = FAILED; | 687 wait_state_ = FAILED; |
| 640 | 688 |
| 641 // Inform the DownloadItem we have canceled whole save page job. | 689 // Inform the DownloadItem we have canceled whole save page job. |
| 642 download_->Cancel(false); | 690 if (download_) { |
| 691 download_->Cancel(false); | |
| 692 FinalizeDownloadEntry(); | |
| 693 } | |
| 643 } | 694 } |
| 644 | 695 |
| 645 void SavePackage::CheckFinish() { | 696 void SavePackage::CheckFinish() { |
| 646 if (in_process_count() || finished_) | 697 if (in_process_count() || finished_) |
| 647 return; | 698 return; |
| 648 | 699 |
| 649 FilePath dir = (save_type_ == SAVE_AS_COMPLETE_HTML && | 700 FilePath dir = (save_type_ == SAVE_AS_COMPLETE_HTML && |
| 650 saved_success_items_.size() > 1) ? | 701 saved_success_items_.size() > 1) ? |
| 651 saved_main_directory_path_ : FilePath(); | 702 saved_main_directory_path_ : FilePath(); |
| 652 | 703 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 685 for (SaveUrlItemMap::iterator it = saved_failed_items_.begin(); | 736 for (SaveUrlItemMap::iterator it = saved_failed_items_.begin(); |
| 686 it != saved_failed_items_.end(); ++it) | 737 it != saved_failed_items_.end(); ++it) |
| 687 save_ids.push_back(it->second->save_id()); | 738 save_ids.push_back(it->second->save_id()); |
| 688 | 739 |
| 689 BrowserThread::PostTask( | 740 BrowserThread::PostTask( |
| 690 BrowserThread::FILE, FROM_HERE, | 741 BrowserThread::FILE, FROM_HERE, |
| 691 NewRunnableMethod(file_manager_, | 742 NewRunnableMethod(file_manager_, |
| 692 &SaveFileManager::RemoveSavedFileFromFileMap, | 743 &SaveFileManager::RemoveSavedFileFromFileMap, |
| 693 save_ids)); | 744 save_ids)); |
| 694 | 745 |
| 695 download_->OnAllDataSaved(all_save_items_count_); | 746 if (download_) { |
| 696 download_->MarkAsComplete(); | 747 download_->OnAllDataSaved(all_save_items_count_); |
| 748 download_->MarkAsComplete(); | |
| 749 FinalizeDownloadEntry(); | |
| 750 } | |
| 697 | 751 |
| 698 NotificationService::current()->Notify( | 752 NotificationService::current()->Notify( |
| 699 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, | 753 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, |
| 700 Source<SavePackage>(this), | 754 Source<SavePackage>(this), |
| 701 Details<GURL>(&page_url_)); | 755 Details<GURL>(&page_url_)); |
| 702 } | 756 } |
| 703 | 757 |
| 704 // Called for updating end state. | 758 // Called for updating end state. |
| 705 void SavePackage::SaveFinished(int32 save_id, int64 size, bool is_success) { | 759 void SavePackage::SaveFinished(int32 save_id, int64 size, bool is_success) { |
| 706 // Because we might have canceled this saving job before, | 760 // Because we might have canceled this saving job before, |
| 707 // so we might not find corresponding SaveItem. Just ignore it. | 761 // so we might not find corresponding SaveItem. Just ignore it. |
| 708 SaveItem* save_item = LookupItemInProcessBySaveId(save_id); | 762 SaveItem* save_item = LookupItemInProcessBySaveId(save_id); |
| 709 if (!save_item) | 763 if (!save_item) |
| 710 return; | 764 return; |
| 711 | 765 |
| 712 // Let SaveItem set end state. | 766 // Let SaveItem set end state. |
| 713 save_item->Finish(size, is_success); | 767 save_item->Finish(size, is_success); |
| 714 // Remove the associated save id and SavePackage. | 768 // Remove the associated save id and SavePackage. |
| 715 file_manager_->RemoveSaveFile(save_id, save_item->url(), this); | 769 file_manager_->RemoveSaveFile(save_id, save_item->url(), this); |
| 716 | 770 |
| 717 PutInProgressItemToSavedMap(save_item); | 771 PutInProgressItemToSavedMap(save_item); |
| 718 | 772 |
| 719 // Inform the DownloadItem to update UI. | 773 // Inform the DownloadItem to update UI. |
| 720 // We use the received bytes as number of saved files. | 774 // We use the received bytes as number of saved files. |
| 721 download_->Update(completed_count()); | 775 if (download_) |
| 776 download_->Update(completed_count()); | |
| 722 | 777 |
| 723 if (save_item->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_DOM && | 778 if (save_item->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_DOM && |
| 724 save_item->url() == page_url_ && !save_item->received_bytes()) { | 779 save_item->url() == page_url_ && !save_item->received_bytes()) { |
| 725 // If size of main HTML page is 0, treat it as disk error. | 780 // If size of main HTML page is 0, treat it as disk error. |
| 726 Cancel(false); | 781 Cancel(false); |
| 727 return; | 782 return; |
| 728 } | 783 } |
| 729 | 784 |
| 730 if (canceled()) { | 785 if (canceled()) { |
| 731 DCHECK(finished_); | 786 DCHECK(finished_); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 752 return; | 807 return; |
| 753 } | 808 } |
| 754 SaveItem* save_item = it->second; | 809 SaveItem* save_item = it->second; |
| 755 | 810 |
| 756 save_item->Finish(0, false); | 811 save_item->Finish(0, false); |
| 757 | 812 |
| 758 PutInProgressItemToSavedMap(save_item); | 813 PutInProgressItemToSavedMap(save_item); |
| 759 | 814 |
| 760 // Inform the DownloadItem to update UI. | 815 // Inform the DownloadItem to update UI. |
| 761 // We use the received bytes as number of saved files. | 816 // We use the received bytes as number of saved files. |
| 762 download_->Update(completed_count()); | 817 if (download_) |
| 818 download_->Update(completed_count()); | |
| 763 | 819 |
| 764 if (save_type_ == SAVE_AS_ONLY_HTML || | 820 if (save_type_ == SAVE_AS_ONLY_HTML || |
| 765 save_item->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_DOM) { | 821 save_item->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_DOM) { |
| 766 // We got error when saving page. Treat it as disk error. | 822 // We got error when saving page. Treat it as disk error. |
| 767 Cancel(true); | 823 Cancel(true); |
| 768 } | 824 } |
| 769 | 825 |
| 770 if (canceled()) { | 826 if (canceled()) { |
| 771 DCHECK(finished_); | 827 DCHECK(finished_); |
| 772 return; | 828 return; |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1016 const std::vector<GURL>& referrers_list, | 1072 const std::vector<GURL>& referrers_list, |
| 1017 const std::vector<GURL>& frames_list) { | 1073 const std::vector<GURL>& frames_list) { |
| 1018 if (wait_state_ != RESOURCES_LIST) | 1074 if (wait_state_ != RESOURCES_LIST) |
| 1019 return; | 1075 return; |
| 1020 | 1076 |
| 1021 DCHECK(resources_list.size() == referrers_list.size()); | 1077 DCHECK(resources_list.size() == referrers_list.size()); |
| 1022 all_save_items_count_ = static_cast<int>(resources_list.size()) + | 1078 all_save_items_count_ = static_cast<int>(resources_list.size()) + |
| 1023 static_cast<int>(frames_list.size()); | 1079 static_cast<int>(frames_list.size()); |
| 1024 | 1080 |
| 1025 // We use total bytes as the total number of files we want to save. | 1081 // We use total bytes as the total number of files we want to save. |
| 1026 download_->set_total_bytes(all_save_items_count_); | 1082 if (download_) |
| 1083 download_->set_total_bytes(all_save_items_count_); | |
| 1027 | 1084 |
| 1028 if (all_save_items_count_) { | 1085 if (all_save_items_count_) { |
| 1029 // Put all sub-resources to wait list. | 1086 // Put all sub-resources to wait list. |
| 1030 for (int i = 0; i < static_cast<int>(resources_list.size()); ++i) { | 1087 for (int i = 0; i < static_cast<int>(resources_list.size()); ++i) { |
| 1031 const GURL& u = resources_list[i]; | 1088 const GURL& u = resources_list[i]; |
| 1032 DCHECK(u.is_valid()); | 1089 DCHECK(u.is_valid()); |
| 1033 SaveFileCreateInfo::SaveFileSource save_source = u.SchemeIsFile() ? | 1090 SaveFileCreateInfo::SaveFileSource save_source = u.SchemeIsFile() ? |
| 1034 SaveFileCreateInfo::SAVE_FILE_FROM_FILE : | 1091 SaveFileCreateInfo::SAVE_FILE_FROM_FILE : |
| 1035 SaveFileCreateInfo::SAVE_FILE_FROM_NET; | 1092 SaveFileCreateInfo::SAVE_FILE_FROM_NET; |
| 1036 SaveItem* save_item = new SaveItem(u, referrers_list[i], | 1093 SaveItem* save_item = new SaveItem(u, referrers_list[i], |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1304 bool SavePackage::IsSavableContents(const std::string& contents_mime_type) { | 1361 bool SavePackage::IsSavableContents(const std::string& contents_mime_type) { |
| 1305 // WebKit creates Document object when MIME type is application/xhtml+xml, | 1362 // WebKit creates Document object when MIME type is application/xhtml+xml, |
| 1306 // so we also support this MIME type. | 1363 // so we also support this MIME type. |
| 1307 return contents_mime_type == "text/html" || | 1364 return contents_mime_type == "text/html" || |
| 1308 contents_mime_type == "text/xml" || | 1365 contents_mime_type == "text/xml" || |
| 1309 contents_mime_type == "application/xhtml+xml" || | 1366 contents_mime_type == "application/xhtml+xml" || |
| 1310 contents_mime_type == "text/plain" || | 1367 contents_mime_type == "text/plain" || |
| 1311 contents_mime_type == "text/css" || | 1368 contents_mime_type == "text/css" || |
| 1312 net::IsSupportedJavascriptMimeType(contents_mime_type.c_str()); | 1369 net::IsSupportedJavascriptMimeType(contents_mime_type.c_str()); |
| 1313 } | 1370 } |
| 1371 | |
| 1372 void SavePackage::StopObservation() { | |
| 1373 DCHECK(download_); | |
| 1374 DCHECK(download_manager_); | |
| 1375 | |
| 1376 download_->RemoveObserver(this); | |
| 1377 download_ = NULL; | |
| 1378 download_manager_ = NULL; | |
| 1379 } | |
| 1380 | |
| 1381 void SavePackage::OnDownloadUpdated(DownloadItem* download) { | |
| 1382 DCHECK(download_); | |
| 1383 DCHECK(download_ == download); | |
| 1384 DCHECK(download_manager_); | |
| 1385 | |
| 1386 // Check for removal. | |
| 1387 if (download->state() == DownloadItem::REMOVING) | |
| 1388 StopObservation(); | |
| 1389 } | |
| 1390 | |
| 1391 void SavePackage::FinalizeDownloadEntry() { | |
| 1392 DCHECK(download_); | |
| 1393 DCHECK(download_manager_); | |
| 1394 | |
| 1395 download_manager_->SavePageDownloadFinished(download_); | |
| 1396 StopObservation(); | |
| 1397 } | |
| OLD | NEW |