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

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: Merge with r147256 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 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 if (delegate_) 237 if (delegate_)
238 id = delegate_->GetNextId(); 238 id = delegate_->GetNextId();
239 if (!id.IsValid()) { 239 if (!id.IsValid()) {
240 static int next_id; 240 static int next_id;
241 id = DownloadId(browser_context_, ++next_id); 241 id = DownloadId(browser_context_, ++next_id);
242 } 242 }
243 243
244 return id; 244 return id;
245 } 245 }
246 246
247 DownloadFileManager* DownloadManagerImpl::GetDownloadFileManager() {
248 return file_manager_;
249 }
250
247 bool DownloadManagerImpl::ShouldOpenDownload(DownloadItemImpl* item) { 251 bool DownloadManagerImpl::ShouldOpenDownload(DownloadItemImpl* item) {
248 if (!delegate_) 252 if (!delegate_)
249 return true; 253 return true;
250 254
251 return delegate_->ShouldOpenDownload(item); 255 return delegate_->ShouldOpenDownload(item);
252 } 256 }
253 257
254 bool DownloadManagerImpl::ShouldOpenFileBasedOnExtension(const FilePath& path) { 258 bool DownloadManagerImpl::ShouldOpenFileBasedOnExtension(const FilePath& path) {
255 if (!delegate_) 259 if (!delegate_)
256 return false; 260 return false;
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 OnDownloadInterrupted(download_id, reason); 435 OnDownloadInterrupted(download_id, reason);
432 // TODO(rdsmith): It makes no sense to continue along the 436 // TODO(rdsmith): It makes no sense to continue along the
433 // regular download path after we've gotten an error. But it's 437 // regular download path after we've gotten an error. But it's
434 // the way the code has historically worked, and this allows us 438 // the way the code has historically worked, and this allows us
435 // to get the download persisted and observers of the download manager 439 // to get the download persisted and observers of the download manager
436 // notified, so tests work. When we execute all side effects of cancel 440 // notified, so tests work. When we execute all side effects of cancel
437 // (including queue removal) immedately rather than waiting for 441 // (including queue removal) immedately rather than waiting for
438 // persistence we should replace this comment with a "return;". 442 // persistence we should replace this comment with a "return;".
439 } 443 }
440 444
441 if (!delegate_ || delegate_->ShouldStartDownload(download_id)) 445 DownloadMap::iterator download_iter = active_downloads_.find(download_id);
442 RestartDownload(download_id); 446 if (download_iter == active_downloads_.end())
447 return;
448
449 DownloadItemImpl* download = download_iter->second;
450 content::DownloadTargetCallback callback =
451 base::Bind(&DownloadManagerImpl::OnDownloadTargetDetermined,
452 this, download_id);
453 if (!delegate_ || !delegate_->DetermineDownloadTarget(download, callback)) {
454 FilePath target_path = download->GetForcedFilePath();
455 // TODO(asanka): Determine a useful path if |target_path| is empty.
456 callback.Run(target_path,
457 DownloadItem::TARGET_DISPOSITION_OVERWRITE,
458 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
459 target_path);
460 }
461 }
462
463 void DownloadManagerImpl::OnDownloadTargetDetermined(
464 int32 download_id,
465 const FilePath& target_path,
466 DownloadItem::TargetDisposition disposition,
467 content::DownloadDangerType danger_type,
468 const FilePath& intermediate_path) {
469 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
470 DownloadMap::iterator download_iter = active_downloads_.find(download_id);
471 if (download_iter != active_downloads_.end()) {
472 // Once DownloadItem::OnDownloadTargetDetermined() is called, we expect a
473 // DownloadRenamedToIntermediateName() callback. This is necessary for the
474 // download to proceed.
475 download_iter->second->OnDownloadTargetDetermined(
476 target_path, disposition, danger_type, intermediate_path);
477 }
443 } 478 }
444 479
445 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { 480 void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
446 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 481 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
447 for (DownloadMap::iterator it = downloads_.begin(); 482 for (DownloadMap::iterator it = downloads_.begin();
448 it != downloads_.end(); ++it) { 483 it != downloads_.end(); ++it) {
449 DownloadItemImpl* item = it->second; 484 DownloadItemImpl* item = it->second;
450 if (item->IsPersisted()) 485 if (item->IsPersisted())
451 CheckForFileRemoval(item); 486 CheckForFileRemoval(item);
452 } 487 }
(...skipping 22 matching lines...) Expand all
475 download_id)); 510 download_id));
476 } 511 }
477 } 512 }
478 513
479 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) { 514 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) {
480 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 515 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
481 if (ContainsKey(downloads_, download_id)) 516 if (ContainsKey(downloads_, download_id))
482 downloads_[download_id]->OnDownloadedFileRemoved(); 517 downloads_[download_id]->OnDownloadedFileRemoved();
483 } 518 }
484 519
485 void DownloadManagerImpl::RestartDownload(int32 download_id) {
486 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
487
488 if (!ContainsKey(active_downloads_, download_id))
489 return;
490 DownloadItemImpl* download = active_downloads_[download_id];
491
492 VLOG(20) << __FUNCTION__ << "()"
493 << " download = " << download->DebugString(true);
494
495 if (download->GetTargetDisposition() ==
496 DownloadItem::TARGET_DISPOSITION_PROMPT) {
497 // We must ask the user for the place to put the download.
498 if (delegate_) {
499 delegate_->ChooseDownloadPath(download);
500 FOR_EACH_OBSERVER(Observer, observers_,
501 SelectFileDialogDisplayed(this, download_id));
502 } else {
503 FileSelectionCanceled(download_id);
504 }
505 } else {
506 // No prompting for download, just continue with the current target path.
507 OnTargetPathAvailable(download);
508 }
509 }
510
511 content::BrowserContext* DownloadManagerImpl::GetBrowserContext() const { 520 content::BrowserContext* DownloadManagerImpl::GetBrowserContext() const {
512 return browser_context_; 521 return browser_context_;
513 } 522 }
514 523
515 FilePath DownloadManagerImpl::LastDownloadPath() {
516 return last_download_path_;
517 }
518
519 net::BoundNetLog DownloadManagerImpl::CreateDownloadItem( 524 net::BoundNetLog DownloadManagerImpl::CreateDownloadItem(
520 DownloadCreateInfo* info) { 525 DownloadCreateInfo* info) {
521 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 526 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
522 527
523 net::BoundNetLog bound_net_log = 528 net::BoundNetLog bound_net_log =
524 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); 529 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
525 if (!info->download_id.IsValid()) 530 if (!info->download_id.IsValid())
526 info->download_id = GetNextId(); 531 info->download_id = GetNextId();
527 DownloadItemImpl* download = factory_->CreateActiveItem( 532 DownloadItemImpl* download = factory_->CreateActiveItem(
528 this, *info, 533 this, *info,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 new SavePageExternalData(download); 568 new SavePageExternalData(download);
564 DCHECK(SavePageExternalData::Get(download)); 569 DCHECK(SavePageExternalData::Get(download));
565 570
566 // Will notify the observer in the callback. 571 // Will notify the observer in the callback.
567 if (delegate_) 572 if (delegate_)
568 delegate_->AddItemToPersistentStore(download); 573 delegate_->AddItemToPersistentStore(download);
569 574
570 return download; 575 return download;
571 } 576 }
572 577
573 // The target path for the download item is now valid. We proceed with the
574 // determination of an intermediate path.
575 void DownloadManagerImpl::OnTargetPathAvailable(DownloadItemImpl* download) {
576 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
577 DCHECK(download);
578 DCHECK(ContainsKey(downloads_, download->GetId()));
579 DCHECK(ContainsKey(active_downloads_, download->GetId()));
580
581 VLOG(20) << __FUNCTION__ << "()"
582 << " download = " << download->DebugString(true);
583
584 // Rename to intermediate name.
585 // TODO(asanka): Skip this rename if download->AllDataSaved() is true. This
586 // avoids a spurious rename when we can just rename to the final
587 // filename. Unnecessary renames may cause bugs like
588 // http://crbug.com/74187.
589 FilePath intermediate_path;
590 if (delegate_)
591 intermediate_path = delegate_->GetIntermediatePath(*download);
592 else
593 intermediate_path = download->GetTargetFilePath();
594
595 // We want the intermediate and target paths to refer to the same directory so
596 // that they are both on the same device and subject to same
597 // space/permission/availability constraints.
598 DCHECK(intermediate_path.DirName() ==
599 download->GetTargetFilePath().DirName());
600 download->OnIntermediatePathDetermined(file_manager_, intermediate_path);
601 }
602
603 void DownloadManagerImpl::UpdateDownload(int32 download_id, 578 void DownloadManagerImpl::UpdateDownload(int32 download_id,
604 int64 bytes_so_far, 579 int64 bytes_so_far,
605 int64 bytes_per_sec, 580 int64 bytes_per_sec,
606 const std::string& hash_state) { 581 const std::string& hash_state) {
607 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 582 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
608 DownloadMap::iterator it = active_downloads_.find(download_id); 583 DownloadMap::iterator it = active_downloads_.find(download_id);
609 if (it != active_downloads_.end()) { 584 if (it != active_downloads_.end()) {
610 DownloadItemImpl* download = it->second; 585 DownloadItemImpl* download = it->second;
611 if (download->IsInProgress()) { 586 if (download->IsInProgress()) {
612 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state); 587 download->UpdateProgress(bytes_so_far, bytes_per_sec, hash_state);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 if (delegate_ && !delegate_->ShouldCompleteDownload(download, base::Bind( 696 if (delegate_ && !delegate_->ShouldCompleteDownload(download, base::Bind(
722 &DownloadManagerImpl::MaybeCompleteDownloadById, 697 &DownloadManagerImpl::MaybeCompleteDownloadById,
723 this, download->GetId()))) 698 this, download->GetId())))
724 return; 699 return;
725 700
726 VLOG(20) << __FUNCTION__ << "()" << " executing: download = " 701 VLOG(20) << __FUNCTION__ << "()" << " executing: download = "
727 << download->DebugString(false); 702 << download->DebugString(false);
728 703
729 if (delegate_) 704 if (delegate_)
730 delegate_->UpdateItemInPersistentStore(download); 705 delegate_->UpdateItemInPersistentStore(download);
731 download->OnDownloadCompleting(file_manager_); 706 download->OnDownloadCompleting();
732 } 707 }
733 708
734 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) { 709 void DownloadManagerImpl::MaybeCompleteDownloadById(int download_id) {
735 if (ContainsKey(active_downloads_, download_id)) 710 if (ContainsKey(active_downloads_, download_id))
736 MaybeCompleteDownload(active_downloads_[download_id]); 711 MaybeCompleteDownload(active_downloads_[download_id]);
737 } 712 }
738 713
739 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) { 714 void DownloadManagerImpl::DownloadCompleted(DownloadItemImpl* download) {
740 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 715 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
741 DCHECK(download); 716 DCHECK(download);
(...skipping 15 matching lines...) Expand all
757 732
758 VLOG(20) << __FUNCTION__ << "()" 733 VLOG(20) << __FUNCTION__ << "()"
759 << " download = " << download->DebugString(true); 734 << " download = " << download->DebugString(true);
760 735
761 RemoveFromActiveList(download); 736 RemoveFromActiveList(download);
762 // This function is called from the DownloadItem, so DI state 737 // This function is called from the DownloadItem, so DI state
763 // should already have been updated. 738 // should already have been updated.
764 AssertStateConsistent(download); 739 AssertStateConsistent(download);
765 740
766 DCHECK(file_manager_); 741 DCHECK(file_manager_);
767 download->OffThreadCancel(file_manager_); 742 download->OffThreadCancel();
768 } 743 }
769 744
770 void DownloadManagerImpl::OnDownloadInterrupted( 745 void DownloadManagerImpl::OnDownloadInterrupted(
771 int32 download_id, 746 int32 download_id,
772 content::DownloadInterruptReason reason) { 747 content::DownloadInterruptReason reason) {
773 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 748 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
774 749
775 if (!ContainsKey(active_downloads_, download_id)) 750 if (!ContainsKey(active_downloads_, download_id))
776 return; 751 return;
777 active_downloads_[download_id]->Interrupt(reason); 752 active_downloads_[download_id]->Interrupt(reason);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
886 // TODO: It is the responsibility of the observers to query the 861 // TODO: It is the responsibility of the observers to query the
887 // DownloadManager. Remove the following call from here and update all 862 // DownloadManager. Remove the following call from here and update all
888 // observers. 863 // observers.
889 observer->ModelChanged(this); 864 observer->ModelChanged(this);
890 } 865 }
891 866
892 void DownloadManagerImpl::RemoveObserver(Observer* observer) { 867 void DownloadManagerImpl::RemoveObserver(Observer* observer) {
893 observers_.RemoveObserver(observer); 868 observers_.RemoveObserver(observer);
894 } 869 }
895 870
896 void DownloadManagerImpl::FileSelected(const FilePath& path,
897 int32 download_id) {
898 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
899 DCHECK(!path.empty());
900
901 if (!ContainsKey(active_downloads_, download_id))
902 return;
903 DownloadItemImpl* download = active_downloads_[download_id];
904
905 VLOG(20) << __FUNCTION__ << "()" << " path = \"" << path.value() << "\""
906 << " download = " << download->DebugString(true);
907
908 // Retain the last directory. Exclude temporary downloads since the path
909 // likely points at the location of a temporary file.
910 if (!download->IsTemporary())
911 last_download_path_ = path.DirName();
912
913 // Make sure the initial file name is set only once.
914 download->OnTargetPathSelected(path);
915 OnTargetPathAvailable(download);
916 }
917
918 void DownloadManagerImpl::FileSelectionCanceled(int32 download_id) {
919 // The user didn't pick a place to save the file, so need to cancel the
920 // download that's already in progress to the temporary location.
921 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
922
923 if (!ContainsKey(active_downloads_, download_id))
924 return;
925 DownloadItemImpl* download = active_downloads_[download_id];
926
927 VLOG(20) << __FUNCTION__ << "()"
928 << " download = " << download->DebugString(true);
929
930 download->Cancel(true);
931 }
932
933 // Operations posted to us from the history service ---------------------------- 871 // Operations posted to us from the history service ----------------------------
934 872
935 // The history service has retrieved all download entries. 'entries' contains 873 // The history service has retrieved all download entries. 'entries' contains
936 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time). 874 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time).
937 void DownloadManagerImpl::OnPersistentStoreQueryComplete( 875 void DownloadManagerImpl::OnPersistentStoreQueryComplete(
938 std::vector<DownloadPersistentStoreInfo>* entries) { 876 std::vector<DownloadPersistentStoreInfo>* entries) {
939 history_size_ = entries->size(); 877 history_size_ = entries->size();
940 for (size_t i = 0; i < entries->size(); ++i) { 878 for (size_t i = 0; i < entries->size(); ++i) {
941 int64 db_handle = entries->at(i).db_handle; 879 int64 db_handle = entries->at(i).db_handle;
942 base::debug::Alias(&db_handle); 880 base::debug::Alias(&db_handle);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1042 int count = 0; 980 int count = 0;
1043 for (DownloadMap::const_iterator it = active_downloads_.begin(); 981 for (DownloadMap::const_iterator it = active_downloads_.begin();
1044 it != active_downloads_.end(); ++it) { 982 it != active_downloads_.end(); ++it) {
1045 DownloadItemImpl* item = it->second; 983 DownloadItemImpl* item = it->second;
1046 if (item->IsInProgress()) 984 if (item->IsInProgress())
1047 ++count; 985 ++count;
1048 } 986 }
1049 return count; 987 return count;
1050 } 988 }
1051 989
1052 // Clears the last download path, used to initialize "save as" dialogs.
1053 void DownloadManagerImpl::ClearLastDownloadPath() {
1054 last_download_path_ = FilePath();
1055 }
1056
1057 void DownloadManagerImpl::NotifyModelChanged() { 990 void DownloadManagerImpl::NotifyModelChanged() {
1058 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this)); 991 FOR_EACH_OBSERVER(Observer, observers_, ModelChanged(this));
1059 } 992 }
1060 993
1061 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) { 994 DownloadItem* DownloadManagerImpl::GetDownloadItem(int download_id) {
1062 DownloadItem* download = GetDownload(download_id); 995 DownloadItem* download = GetDownload(download_id);
1063 return (download && download->IsPersisted()) ? download : NULL; 996 return (download && download->IsPersisted()) ? download : NULL;
1064 } 997 }
1065 998
1066 DownloadItem* DownloadManagerImpl::GetDownload(int download_id) { 999 DownloadItem* DownloadManagerImpl::GetDownload(int download_id) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 if (item->IsComplete() && 1086 if (item->IsComplete() &&
1154 !item->GetOpened()) 1087 !item->GetOpened())
1155 ++num_unopened; 1088 ++num_unopened;
1156 } 1089 }
1157 download_stats::RecordOpensOutstanding(num_unopened); 1090 download_stats::RecordOpensOutstanding(num_unopened);
1158 } 1091 }
1159 1092
1160 void DownloadManagerImpl::DownloadRenamedToIntermediateName( 1093 void DownloadManagerImpl::DownloadRenamedToIntermediateName(
1161 DownloadItemImpl* download) { 1094 DownloadItemImpl* download) {
1162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1095 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1163 // If the rename failed, we receive an OnDownloadInterrupted() call before we 1096 // download->GetFullPath() is only expected to be meaningful after this
1164 // receive the DownloadRenamedToIntermediateName() call. 1097 // callback is received. Therefore we can now add the download to a persistent
1165 if (delegate_) 1098 // store. If the rename failed, we receive an OnDownloadInterrupted() call
1099 // before we receive the DownloadRenamedToIntermediateName() call.
1100 if (delegate_) {
1166 delegate_->AddItemToPersistentStore(download); 1101 delegate_->AddItemToPersistentStore(download);
1102 } else {
1103 OnItemAddedToPersistentStore(download->GetId(),
1104 DownloadItem::kUninitializedHandle);
1105 }
1167 } 1106 }
1168 1107
1169 void DownloadManagerImpl::DownloadRenamedToFinalName( 1108 void DownloadManagerImpl::DownloadRenamedToFinalName(
1170 DownloadItemImpl* download) { 1109 DownloadItemImpl* download) {
1171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1172 // If the rename failed, we receive an OnDownloadInterrupted() call before we 1111 // If the rename failed, we receive an OnDownloadInterrupted() call before we
1173 // receive the DownloadRenamedToFinalName() call. 1112 // receive the DownloadRenamedToFinalName() call.
1174 if (delegate_) { 1113 if (delegate_) {
1175 delegate_->UpdatePathForItemInPersistentStore( 1114 delegate_->UpdatePathForItemInPersistentStore(
1176 download, download->GetFullPath()); 1115 download, download->GetFullPath());
1177 } 1116 }
1178 } 1117 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698