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

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

Issue 7277073: Support for adding save page download items into downloads history. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 5 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 | Annotate | Revision Log
OLDNEW
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 "chrome/browser/download/save_package.h" 5 #include "chrome/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-inl.h" 14 #include "base/stl_util-inl.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/browser_process.h" 21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/download/download_item.h" 22 #include "chrome/browser/download/download_item.h"
23 #include "chrome/browser/download/download_item_model.h" 23 #include "chrome/browser/download/download_item_model.h"
24 #include "chrome/browser/download/download_history.h"
24 #include "chrome/browser/download/download_manager.h" 25 #include "chrome/browser/download/download_manager.h"
25 #include "chrome/browser/download/download_prefs.h" 26 #include "chrome/browser/download/download_prefs.h"
26 #include "chrome/browser/download/download_util.h" 27 #include "chrome/browser/download/download_util.h"
27 #include "chrome/browser/download/save_file.h" 28 #include "chrome/browser/download/save_file.h"
28 #include "chrome/browser/download/save_file_manager.h" 29 #include "chrome/browser/download/save_file_manager.h"
29 #include "chrome/browser/download/save_item.h" 30 #include "chrome/browser/download/save_item.h"
30 #include "chrome/browser/net/url_fixer_upper.h" 31 #include "chrome/browser/net/url_fixer_upper.h"
31 #include "chrome/browser/platform_util.h" 32 #include "chrome/browser/platform_util.h"
32 #include "chrome/browser/prefs/pref_member.h" 33 #include "chrome/browser/prefs/pref_member.h"
33 #include "chrome/browser/prefs/pref_service.h" 34 #include "chrome/browser/prefs/pref_service.h"
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 saved_main_directory_path_(directory_full_path), 167 saved_main_directory_path_(directory_full_path),
167 title_(tab_contents()->GetTitle()), 168 title_(tab_contents()->GetTitle()),
168 finished_(false), 169 finished_(false),
169 user_canceled_(false), 170 user_canceled_(false),
170 disk_error_occurred_(false), 171 disk_error_occurred_(false),
171 save_type_(save_type), 172 save_type_(save_type),
172 all_save_items_count_(0), 173 all_save_items_count_(0),
173 wait_state_(INITIALIZE), 174 wait_state_(INITIALIZE),
174 tab_id_(tab_contents()->GetRenderProcessHost()->id()), 175 tab_id_(tab_contents()->GetRenderProcessHost()->id()),
175 unique_id_(g_save_package_id++), 176 unique_id_(g_save_package_id++),
177 download_manager_(NULL),
176 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { 178 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
177 DCHECK(page_url_.is_valid()); 179 DCHECK(page_url_.is_valid());
178 DCHECK(save_type_ == SAVE_AS_ONLY_HTML || 180 DCHECK(save_type_ == SAVE_AS_ONLY_HTML ||
179 save_type_ == SAVE_AS_COMPLETE_HTML); 181 save_type_ == SAVE_AS_COMPLETE_HTML);
180 DCHECK(!saved_main_file_path_.empty() && 182 DCHECK(!saved_main_file_path_.empty() &&
181 saved_main_file_path_.value().length() <= kMaxFilePathLength); 183 saved_main_file_path_.value().length() <= kMaxFilePathLength);
182 DCHECK(!saved_main_directory_path_.empty() && 184 DCHECK(!saved_main_directory_path_.empty() &&
183 saved_main_directory_path_.value().length() < kMaxFilePathLength); 185 saved_main_directory_path_.value().length() < kMaxFilePathLength);
184 InternalInit(); 186 InternalInit();
185 } 187 }
186 188
187 SavePackage::SavePackage(TabContentsWrapper* wrapper) 189 SavePackage::SavePackage(TabContentsWrapper* wrapper)
188 : TabContentsObserver(wrapper->tab_contents()), 190 : TabContentsObserver(wrapper->tab_contents()),
189 wrapper_(wrapper), 191 wrapper_(wrapper),
190 file_manager_(NULL), 192 file_manager_(NULL),
191 download_(NULL), 193 download_(NULL),
192 page_url_(GetUrlToBeSaved()), 194 page_url_(GetUrlToBeSaved()),
193 title_(tab_contents()->GetTitle()), 195 title_(tab_contents()->GetTitle()),
194 finished_(false), 196 finished_(false),
195 user_canceled_(false), 197 user_canceled_(false),
196 disk_error_occurred_(false), 198 disk_error_occurred_(false),
197 save_type_(SAVE_TYPE_UNKNOWN), 199 save_type_(SAVE_TYPE_UNKNOWN),
198 all_save_items_count_(0), 200 all_save_items_count_(0),
199 wait_state_(INITIALIZE), 201 wait_state_(INITIALIZE),
200 tab_id_(tab_contents()->GetRenderProcessHost()->id()), 202 tab_id_(tab_contents()->GetRenderProcessHost()->id()),
201 unique_id_(g_save_package_id++), 203 unique_id_(g_save_package_id++),
204 download_manager_(NULL),
202 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { 205 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
203 DCHECK(page_url_.is_valid()); 206 DCHECK(page_url_.is_valid());
204 InternalInit(); 207 InternalInit();
205 } 208 }
206 209
207 // This is for testing use. Set |finished_| as true because we don't want 210 // This is for testing use. Set |finished_| as true because we don't want
208 // method Cancel to be be called in destructor in test mode. 211 // method Cancel to be be called in destructor in test mode.
209 // We also don't call InternalInit(). 212 // We also don't call InternalInit().
210 SavePackage::SavePackage(TabContentsWrapper* wrapper, 213 SavePackage::SavePackage(TabContentsWrapper* wrapper,
211 const FilePath& file_full_path, 214 const FilePath& file_full_path,
212 const FilePath& directory_full_path) 215 const FilePath& directory_full_path)
213 : TabContentsObserver(wrapper->tab_contents()), 216 : TabContentsObserver(wrapper->tab_contents()),
214 wrapper_(wrapper), 217 wrapper_(wrapper),
215 file_manager_(NULL), 218 file_manager_(NULL),
216 download_(NULL), 219 download_(NULL),
217 saved_main_file_path_(file_full_path), 220 saved_main_file_path_(file_full_path),
218 saved_main_directory_path_(directory_full_path), 221 saved_main_directory_path_(directory_full_path),
219 finished_(true), 222 finished_(true),
220 user_canceled_(false), 223 user_canceled_(false),
221 disk_error_occurred_(false), 224 disk_error_occurred_(false),
222 save_type_(SAVE_TYPE_UNKNOWN), 225 save_type_(SAVE_TYPE_UNKNOWN),
223 all_save_items_count_(0), 226 all_save_items_count_(0),
224 wait_state_(INITIALIZE), 227 wait_state_(INITIALIZE),
225 tab_id_(0), 228 tab_id_(0),
226 unique_id_(g_save_package_id++), 229 unique_id_(g_save_package_id++),
230 download_manager_(NULL),
227 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { 231 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
228 } 232 }
229 233
230 SavePackage::~SavePackage() { 234 SavePackage::~SavePackage() {
231 // Stop receiving saving job's updates 235 // Stop receiving saving job's updates
232 if (!finished_ && !canceled()) { 236 if (!finished_ && !canceled()) {
233 // Unexpected quit. 237 // Unexpected quit.
234 Cancel(true); 238 Cancel(true);
235 } 239 }
236 240
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 311
308 wait_state_ = START_PROCESS; 312 wait_state_ = START_PROCESS;
309 313
310 // Initialize the request context and resource dispatcher. 314 // Initialize the request context and resource dispatcher.
311 Profile* profile = tab_contents()->profile(); 315 Profile* profile = tab_contents()->profile();
312 if (!profile) { 316 if (!profile) {
313 NOTREACHED(); 317 NOTREACHED();
314 return false; 318 return false;
315 } 319 }
316 320
321 // Get the download manager and add ourselves as an observer.
322 download_manager_ = tab_contents()->profile()->GetDownloadManager();
323 if (!download_manager_) {
324 NOTREACHED();
325 return false;
326 }
327 download_manager_->AddObserver(this);
328
317 // Create the fake DownloadItem and display the view. 329 // Create the fake DownloadItem and display the view.
318 DownloadManager* download_manager = 330 download_ = new DownloadItem(download_manager_,
319 tab_contents()->profile()->GetDownloadManager();
320 download_ = new DownloadItem(download_manager,
321 saved_main_file_path_, 331 saved_main_file_path_,
322 page_url_, 332 page_url_,
323 profile->IsOffTheRecord()); 333 profile->IsOffTheRecord());
324 334
325 // Transfer the ownership to the download manager. We need the DownloadItem 335 // Transfer the ownership to the download manager. We need the DownloadItem
326 // to be alive as long as the Profile is alive. 336 // to be alive as long as the Profile is alive.
327 download_manager->SavePageAsDownloadStarted(download_); 337 download_manager_->SavePageAsDownloadStarted(download_);
328 338
329 wrapper_->download_tab_helper()->OnStartDownload(download_); 339 // Add this entry to the history service, which also notifies the UI.
Randy Smith (Not in Mondays) 2011/07/10 19:37:40 I think it's worthwhile making clear that the UI i
achuithb 2011/07/13 21:48:16 Done.
340 download_manager_->download_history()->AddEntry(download_,
341 NewCallback(this, &SavePackage::OnDownloadEntryAdded));
Randy Smith (Not in Mondays) 2011/07/10 19:37:40 I'm not an expert on this, but I think that NewCal
achuithb 2011/07/13 21:48:16 I decided to move this code into download_manager.
330 342
331 // Check save type and process the save page job. 343 // Check save type and process the save page job.
332 if (save_type_ == SAVE_AS_COMPLETE_HTML) { 344 if (save_type_ == SAVE_AS_COMPLETE_HTML) {
333 // Get directory 345 // Get directory
334 DCHECK(!saved_main_directory_path_.empty()); 346 DCHECK(!saved_main_directory_path_.empty());
335 GetAllSavableResourceLinksForCurrentPage(); 347 GetAllSavableResourceLinksForCurrentPage();
336 } else { 348 } else {
337 wait_state_ = NET_FILES; 349 wait_state_ = NET_FILES;
338 SaveFileCreateInfo::SaveFileSource save_source = page_url_.SchemeIsFile() ? 350 SaveFileCreateInfo::SaveFileSource save_source = page_url_.SchemeIsFile() ?
339 SaveFileCreateInfo::SAVE_FILE_FROM_FILE : 351 SaveFileCreateInfo::SAVE_FILE_FROM_FILE :
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 BrowserThread::FILE, FROM_HERE, 696 BrowserThread::FILE, FROM_HERE,
685 NewRunnableMethod(file_manager_, 697 NewRunnableMethod(file_manager_,
686 &SaveFileManager::RemoveSavedFileFromFileMap, 698 &SaveFileManager::RemoveSavedFileFromFileMap,
687 save_ids)); 699 save_ids));
688 700
689 finished_ = true; 701 finished_ = true;
690 wait_state_ = FAILED; 702 wait_state_ = FAILED;
691 703
692 // Inform the DownloadItem we have canceled whole save page job. 704 // Inform the DownloadItem we have canceled whole save page job.
693 download_->Cancel(false); 705 download_->Cancel(false);
706 FinalizeDownloadEntry();
694 } 707 }
695 708
696 void SavePackage::CheckFinish() { 709 void SavePackage::CheckFinish() {
697 if (in_process_count() || finished_) 710 if (in_process_count() || finished_)
698 return; 711 return;
699 712
700 FilePath dir = (save_type_ == SAVE_AS_COMPLETE_HTML && 713 FilePath dir = (save_type_ == SAVE_AS_COMPLETE_HTML &&
701 saved_success_items_.size() > 1) ? 714 saved_success_items_.size() > 1) ?
702 saved_main_directory_path_ : FilePath(); 715 saved_main_directory_path_ : FilePath();
703 716
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 save_ids.push_back(it->second->save_id()); 751 save_ids.push_back(it->second->save_id());
739 752
740 BrowserThread::PostTask( 753 BrowserThread::PostTask(
741 BrowserThread::FILE, FROM_HERE, 754 BrowserThread::FILE, FROM_HERE,
742 NewRunnableMethod(file_manager_, 755 NewRunnableMethod(file_manager_,
743 &SaveFileManager::RemoveSavedFileFromFileMap, 756 &SaveFileManager::RemoveSavedFileFromFileMap,
744 save_ids)); 757 save_ids));
745 758
746 download_->OnAllDataSaved(all_save_items_count_); 759 download_->OnAllDataSaved(all_save_items_count_);
747 download_->MarkAsComplete(); 760 download_->MarkAsComplete();
761 FinalizeDownloadEntry();
748 762
749 NotificationService::current()->Notify( 763 NotificationService::current()->Notify(
750 NotificationType::SAVE_PACKAGE_SUCCESSFULLY_FINISHED, 764 NotificationType::SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
751 Source<SavePackage>(this), 765 Source<SavePackage>(this),
752 Details<GURL>(&page_url_)); 766 Details<GURL>(&page_url_));
753 } 767 }
754 768
755 // Called for updating end state. 769 // Called for updating end state.
756 void SavePackage::SaveFinished(int32 save_id, int64 size, bool is_success) { 770 void SavePackage::SaveFinished(int32 save_id, int64 size, bool is_success) {
757 // Because we might have canceled this saving job before, 771 // Because we might have canceled this saving job before,
(...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after
1467 } 1481 }
1468 1482
1469 // SelectFileDialog::Listener interface. 1483 // SelectFileDialog::Listener interface.
1470 void SavePackage::FileSelected(const FilePath& path, 1484 void SavePackage::FileSelected(const FilePath& path,
1471 int index, void* params) { 1485 int index, void* params) {
1472 ContinueSave(path, index); 1486 ContinueSave(path, index);
1473 } 1487 }
1474 1488
1475 void SavePackage::FileSelectionCanceled(void* params) { 1489 void SavePackage::FileSelectionCanceled(void* params) {
1476 } 1490 }
1491
1492 void SavePackage::ManagerGoingDown() {
1493 download_manager_ = NULL;
1494 }
1495
1496 void SavePackage::OnDownloadEntryAdded(int32 download_id, int64 db_handle) {
1497 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1498 // download_manager_ can be null if Finalize got called before this callback.
1499 // In that case, this item would not get added to the history db.
Randy Smith (Not in Mondays) 2011/07/10 19:37:40 Nope, it's been added to the DB, it just won't be
achuithb 2011/07/13 21:48:16 This code is now in DownloadManager.
1500 DCHECK(download_manager_);
Randy Smith (Not in Mondays) 2011/07/10 19:37:40 This is the one case in which I think download_man
achuithb 2011/07/13 21:48:16 This code is now in DownloadManager.
1501 if (download_manager_)
1502 download_manager_->AddDownloadItemToHistory(download_, db_handle);
1503 }
1504
1505 void SavePackage::FinalizeDownloadEntry() {
1506 DCHECK(download_manager_);
1507 if (download_manager_) {
1508 download_manager_->download_history()->UpdateEntry(download_);
Randy Smith (Not in Mondays) 2011/07/10 19:37:40 So there's a pretty subtle but important differenc
Randy Smith (Not in Mondays) 2011/07/10 19:37:40 If you could also take a look at how hard it would
achuithb 2011/07/13 21:48:16 I'm now handling the race between completion and h
achuithb 2011/07/13 21:48:16 I think adding a test for the races should be doab
1509 download_manager_->RemoveObserver(this);
1510 download_manager_ = NULL;
Randy Smith (Not in Mondays) 2011/07/10 19:37:40 I'd like a CHECK() in the destructor that the down
achuithb 2011/07/13 21:48:16 Done.
1511 }
1512 }
1513
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698