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

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

Issue 10704052: Download filename determination refactor (3/3) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use a callback with DetermineDownloadTarget(). Created 8 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) 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/download_manager_impl.h" 5 #include "content/browser/download/download_manager_impl.h"
6 6
7 #include <iterator> 7 #include <iterator>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 if (delegate_) 214 if (delegate_)
215 id = delegate_->GetNextId(); 215 id = delegate_->GetNextId();
216 if (!id.IsValid()) { 216 if (!id.IsValid()) {
217 static int next_id; 217 static int next_id;
218 id = DownloadId(browser_context_, ++next_id); 218 id = DownloadId(browser_context_, ++next_id);
219 } 219 }
220 220
221 return id; 221 return id;
222 } 222 }
223 223
224 DownloadFileManager* DownloadManagerImpl::GetDownloadFileManager() {
225 return file_manager_;
226 }
227
224 bool DownloadManagerImpl::ShouldOpenDownload(DownloadItem* item) { 228 bool DownloadManagerImpl::ShouldOpenDownload(DownloadItem* item) {
225 if (!delegate_) 229 if (!delegate_)
226 return true; 230 return true;
227 231
228 return delegate_->ShouldOpenDownload(item); 232 return delegate_->ShouldOpenDownload(item);
229 } 233 }
230 234
231 bool DownloadManagerImpl::ShouldOpenFileBasedOnExtension(const FilePath& path) { 235 bool DownloadManagerImpl::ShouldOpenFileBasedOnExtension(const FilePath& path) {
232 if (!delegate_) 236 if (!delegate_)
233 return false; 237 return false;
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 OnDownloadInterrupted(download_id, 0, "", reason); 414 OnDownloadInterrupted(download_id, 0, "", reason);
411 // TODO(rdsmith): It makes no sense to continue along the 415 // TODO(rdsmith): It makes no sense to continue along the
412 // regular download path after we've gotten an error. But it's 416 // regular download path after we've gotten an error. But it's
413 // the way the code has historically worked, and this allows us 417 // the way the code has historically worked, and this allows us
414 // to get the download persisted and observers of the download manager 418 // to get the download persisted and observers of the download manager
415 // notified, so tests work. When we execute all side effects of cancel 419 // notified, so tests work. When we execute all side effects of cancel
416 // (including queue removal) immedately rather than waiting for 420 // (including queue removal) immedately rather than waiting for
417 // persistence we should replace this comment with a "return;". 421 // persistence we should replace this comment with a "return;".
418 } 422 }
419 423
420 if (!delegate_ || delegate_->ShouldStartDownload(download_id)) 424 DownloadItem* download = GetActiveDownloadItem(download_id);
421 RestartDownload(download_id); 425 if (!download)
426 return;
427
428 content::DownloadTargetCallback callback =
429 base::Bind(&DownloadManagerImpl::OnDownloadTargetDetermined,
430 this, download_id);
431 if (!delegate_ || !delegate_->DetermineDownloadTarget(download, callback)) {
432 FilePath target_path = download->GetForcedFilePath();
433 // TODO(asanka): Determine a useful path if |target_path| is empty.
434 callback.Run(target_path,
435 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
436 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
437 target_path);
438 }
439 // Once DownloadItem::OnDownloadTargetDetermined() is called, we expect a
440 // DownloadRenamedToIntermediateName() callback. This is necessary for the
441 // download to proceed.
Randy Smith (Not in Mondays) 2012/07/10 18:33:09 nit: Wouldn't the best place for this comment be a
asanka 2012/07/11 20:03:32 Done.
442 }
443
444 void DownloadManagerImpl::OnDownloadTargetDetermined(
445 int32 download_id,
446 const FilePath& target_path,
447 DownloadItem::TargetDisposition disposition,
448 content::DownloadDangerType danger_type,
449 const FilePath& intermediate_path) {
450 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
451 DownloadItem* download = GetActiveDownloadItem(download_id);
452 if (!download)
453 return;
454
455 download->OnDownloadTargetDetermined(target_path, disposition, danger_type,
456 intermediate_path);
422 } 457 }
423 458
424 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { 459 void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 460 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
426 for (DownloadMap::iterator it = downloads_.begin(); 461 for (DownloadMap::iterator it = downloads_.begin();
427 it != downloads_.end(); ++it) { 462 it != downloads_.end(); ++it) {
428 DownloadItem* item = it->second; 463 DownloadItem* item = it->second;
429 if (item->IsPersisted()) 464 if (item->IsPersisted())
430 CheckForFileRemoval(item); 465 CheckForFileRemoval(item);
431 } 466 }
(...skipping 23 matching lines...) Expand all
455 } 490 }
456 } 491 }
457 492
458 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) { 493 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) {
459 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 494 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
460 DownloadItem* download = GetDownload(download_id); 495 DownloadItem* download = GetDownload(download_id);
461 if (download) 496 if (download)
462 download->OnDownloadedFileRemoved(); 497 download->OnDownloadedFileRemoved();
463 } 498 }
464 499
465 void DownloadManagerImpl::RestartDownload(int32 download_id) {
466 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
467
468 DownloadItem* download = GetActiveDownloadItem(download_id);
469 if (!download)
470 return;
471
472 VLOG(20) << __FUNCTION__ << "()"
473 << " download = " << download->DebugString(true);
474
475 if (download->GetTargetDisposition() ==
476 DownloadItem::TARGET_DISPOSITION_PROMPT) {
477 // We must ask the user for the place to put the download.
478 if (delegate_) {
479 delegate_->ChooseDownloadPath(download);
480 FOR_EACH_OBSERVER(Observer, observers_,
481 SelectFileDialogDisplayed(this, download_id));
482 } else {
483 FileSelectionCanceled(download_id);
484 }
485 } else {
486 // No prompting for download, just continue with the current target path.
487 OnTargetPathAvailable(download);
488 }
489 }
490
491 content::BrowserContext* DownloadManagerImpl::GetBrowserContext() const { 500 content::BrowserContext* DownloadManagerImpl::GetBrowserContext() const {
492 return browser_context_; 501 return browser_context_;
493 } 502 }
494 503
495 FilePath DownloadManagerImpl::LastDownloadPath() {
496 return last_download_path_;
497 }
498
499 net::BoundNetLog DownloadManagerImpl::CreateDownloadItem( 504 net::BoundNetLog DownloadManagerImpl::CreateDownloadItem(
500 DownloadCreateInfo* info) { 505 DownloadCreateInfo* info) {
501 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 506 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
502 507
503 net::BoundNetLog bound_net_log = 508 net::BoundNetLog bound_net_log =
504 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); 509 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
505 if (!info->download_id.IsValid()) 510 if (!info->download_id.IsValid())
506 info->download_id = GetNextId(); 511 info->download_id = GetNextId();
507 DownloadItem* download = factory_->CreateActiveItem( 512 DownloadItem* download = factory_->CreateActiveItem(
508 this, *info, 513 this, *info,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 DCHECK(!ContainsKey(save_page_downloads_, download->GetId())); 547 DCHECK(!ContainsKey(save_page_downloads_, download->GetId()));
543 save_page_downloads_[download->GetId()] = download; 548 save_page_downloads_[download->GetId()] = download;
544 549
545 // Will notify the observer in the callback. 550 // Will notify the observer in the callback.
546 if (delegate_) 551 if (delegate_)
547 delegate_->AddItemToPersistentStore(download); 552 delegate_->AddItemToPersistentStore(download);
548 553
549 return download; 554 return download;
550 } 555 }
551 556
552 // The target path for the download item is now valid. We proceed with the
553 // determination of an intermediate path.
554 void DownloadManagerImpl::OnTargetPathAvailable(DownloadItem* download) {
555 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
556 DCHECK(download);
557 DCHECK(ContainsKey(downloads_, download->GetId()));
558 DCHECK(ContainsKey(active_downloads_, download->GetId()));
559
560 VLOG(20) << __FUNCTION__ << "()"
561 << " download = " << download->DebugString(true);
562
563 // Rename to intermediate name.
564 // TODO(asanka): Skip this rename if download->AllDataSaved() is true. This
565 // avoids a spurious rename when we can just rename to the final
566 // filename. Unnecessary renames may cause bugs like
567 // http://crbug.com/74187.
568 FilePath intermediate_path;
569 if (delegate_)
570 intermediate_path = delegate_->GetIntermediatePath(*download);
571 else
572 intermediate_path = download->GetTargetFilePath();
573
574 // We want the intermediate and target paths to refer to the same directory so
575 // that they are both on the same device and subject to same
576 // space/permission/availability constraints.
577 DCHECK(intermediate_path.DirName() ==
578 download->GetTargetFilePath().DirName());
579 download->OnIntermediatePathDetermined(file_manager_, intermediate_path);
580 }
581
582 void DownloadManagerImpl::UpdateDownload(int32 download_id, 557 void DownloadManagerImpl::UpdateDownload(int32 download_id,
583 int64 bytes_so_far, 558 int64 bytes_so_far,
584 int64 bytes_per_sec, 559 int64 bytes_per_sec,
585 const std::string& hash_state) { 560 const std::string& hash_state) {
586 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 561 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
587 DownloadMap::iterator it = active_downloads_.find(download_id); 562 DownloadMap::iterator it = active_downloads_.find(download_id);
588 if (it != active_downloads_.end()) { 563 if (it != active_downloads_.end()) {
589 DownloadItem* download = it->second; 564 DownloadItem* download = it->second;
590 if (download->IsInProgress()) { 565 if (download->IsInProgress()) {
591 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state); 566 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state);
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 // TODO: It is the responsibility of the observers to query the 859 // TODO: It is the responsibility of the observers to query the
885 // DownloadManager. Remove the following call from here and update all 860 // DownloadManager. Remove the following call from here and update all
886 // observers. 861 // observers.
887 observer->ModelChanged(this); 862 observer->ModelChanged(this);
888 } 863 }
889 864
890 void DownloadManagerImpl::RemoveObserver(Observer* observer) { 865 void DownloadManagerImpl::RemoveObserver(Observer* observer) {
891 observers_.RemoveObserver(observer); 866 observers_.RemoveObserver(observer);
892 } 867 }
893 868
894 void DownloadManagerImpl::FileSelected(const FilePath& path,
895 int32 download_id) {
896 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
897 DCHECK(!path.empty());
898
899 DownloadItem* download = GetActiveDownloadItem(download_id);
900 if (!download)
901 return;
902 VLOG(20) << __FUNCTION__ << "()" << " path = \"" << path.value() << "\""
903 << " download = " << download->DebugString(true);
904
905 // Retain the last directory. Exclude temporary downloads since the path
906 // likely points at the location of a temporary file.
907 if (!download->IsTemporary())
908 last_download_path_ = path.DirName();
909
910 // Make sure the initial file name is set only once.
911 download->OnTargetPathSelected(path);
912 OnTargetPathAvailable(download);
913 }
914
915 void DownloadManagerImpl::FileSelectionCanceled(int32 download_id) {
916 // The user didn't pick a place to save the file, so need to cancel the
917 // download that's already in progress to the temporary location.
918 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
919
920 DownloadItem* download = GetActiveDownloadItem(download_id);
921 if (!download)
922 return;
923
924 VLOG(20) << __FUNCTION__ << "()"
925 << " download = " << download->DebugString(true);
926
927 download->Cancel(true);
928 }
929
930 // Operations posted to us from the history service ---------------------------- 869 // Operations posted to us from the history service ----------------------------
931 870
932 // The history service has retrieved all download entries. 'entries' contains 871 // The history service has retrieved all download entries. 'entries' contains
933 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time). 872 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time).
934 void DownloadManagerImpl::OnPersistentStoreQueryComplete( 873 void DownloadManagerImpl::OnPersistentStoreQueryComplete(
935 std::vector<DownloadPersistentStoreInfo>* entries) { 874 std::vector<DownloadPersistentStoreInfo>* entries) {
936 history_size_ = entries->size(); 875 history_size_ = entries->size();
937 for (size_t i = 0; i < entries->size(); ++i) { 876 for (size_t i = 0; i < entries->size(); ++i) {
938 int64 db_handle = entries->at(i).db_handle; 877 int64 db_handle = entries->at(i).db_handle;
939 base::debug::Alias(&db_handle); 878 base::debug::Alias(&db_handle);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 for (DownloadMap::const_iterator it = active_downloads_.begin(); 980 for (DownloadMap::const_iterator it = active_downloads_.begin();
1042 it != active_downloads_.end(); ++it) { 981 it != active_downloads_.end(); ++it) {
1043 DownloadItem* item = it->second; 982 DownloadItem* item = it->second;
1044 if (item->IsInProgress()) 983 if (item->IsInProgress())
1045 ++count; 984 ++count;
1046 } 985 }
1047 return count; 986 return count;
1048 } 987 }
1049 988
1050 // Clears the last download path, used to initialize "save as" dialogs. 989 // Clears the last download path, used to initialize "save as" dialogs.
1051 void DownloadManagerImpl::ClearLastDownloadPath() { 990 void DownloadManagerImpl::ClearTransientState() {
1052 last_download_path_ = FilePath(); 991 if (delegate_)
992 delegate_->ClearTransientState();
1053 } 993 }
1054 994
1055 void DownloadManagerImpl::NotifyModelChanged() { 995 void DownloadManagerImpl::NotifyModelChanged() {
1056 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this)); 996 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this));
1057 } 997 }
1058 998
1059 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) { 999 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) {
1060 DownloadItem* download = GetDownload(download_id); 1000 DownloadItem* download = GetDownload(download_id);
1061 return (download && download->IsPersisted()) ? download : NULL; 1001 return (download && download->IsPersisted()) ? download : NULL;
1062 } 1002 }
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1168 if (item->IsComplete() && 1108 if (item->IsComplete() &&
1169 !item->GetOpened()) 1109 !item->GetOpened())
1170 ++num_unopened; 1110 ++num_unopened;
1171 } 1111 }
1172 download_stats::RecordOpensOutstanding(num_unopened); 1112 download_stats::RecordOpensOutstanding(num_unopened);
1173 } 1113 }
1174 1114
1175 void DownloadManagerImpl::DownloadRenamedToIntermediateName( 1115 void DownloadManagerImpl::DownloadRenamedToIntermediateName(
1176 DownloadItem* download) { 1116 DownloadItem* download) {
1177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1178 // If the rename failed, we receive an OnDownloadInterrupted() call before we 1118 // download->GetFullPath() is only expected to be meaningful after this
1179 // receive the DownloadRenamedToIntermediateName() call. 1119 // callback is received. Therefore we can now add the download to a persistent
1180 if (delegate_) 1120 // store. If the rename failed, we receive an OnDownloadInterrupted() call
1121 // before we receive the DownloadRenamedToIntermediateName() call.
1122 if (delegate_) {
1181 delegate_->AddItemToPersistentStore(download); 1123 delegate_->AddItemToPersistentStore(download);
1124 } else {
1125 OnItemAddedToPersistentStore(download->GetId(),
1126 DownloadItem::kUninitializedHandle);
1127 }
1182 } 1128 }
1183 1129
1184 void DownloadManagerImpl::DownloadRenamedToFinalName( 1130 void DownloadManagerImpl::DownloadRenamedToFinalName(
1185 DownloadItem* download) { 1131 DownloadItem* download) {
1186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1187 // If the rename failed, we receive an OnDownloadInterrupted() call before we 1133 // If the rename failed, we receive an OnDownloadInterrupted() call before we
1188 // receive the DownloadRenamedToFinalName() call. 1134 // receive the DownloadRenamedToFinalName() call.
1189 if (delegate_) { 1135 if (delegate_) {
1190 delegate_->UpdatePathForItemInPersistentStore( 1136 delegate_->UpdatePathForItemInPersistentStore(
1191 download, download->GetFullPath()); 1137 download, download->GetFullPath());
1192 } 1138 }
1193 } 1139 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698