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

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

Issue 7983037: Revert 102126 - Make cancel remove cancelled download from active queues at time of cancel. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 3 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 "content/browser/download/download_manager.h" 5 #include "content/browser/download/download_manager.h"
6 6
7 #include <iterator> 7 #include <iterator>
8 8
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 // The user hasn't accepted it, so we need to remove it 105 // The user hasn't accepted it, so we need to remove it
106 // from the disk. This may or may not result in it being 106 // from the disk. This may or may not result in it being
107 // removed from the DownloadManager queues and deleted 107 // removed from the DownloadManager queues and deleted
108 // (specifically, DownloadManager::RemoveDownload only 108 // (specifically, DownloadManager::RemoveDownload only
109 // removes and deletes it if it's known to the history service) 109 // removes and deletes it if it's known to the history service)
110 // so the only thing we know after calling this function is that 110 // so the only thing we know after calling this function is that
111 // the download was deleted if-and-only-if it was removed 111 // the download was deleted if-and-only-if it was removed
112 // from all queues. 112 // from all queues.
113 download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN); 113 download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN);
114 } else if (download->IsPartialDownload()) { 114 } else if (download->IsPartialDownload()) {
115 download->Cancel(); 115 download->Cancel(false);
116 delegate_->UpdateItemInPersistentStore(download);
116 } 117 }
117 } 118 }
118 119
119 // At this point, all dangerous downloads have had their files removed 120 // At this point, all dangerous downloads have had their files removed
120 // and all in progress downloads have been cancelled. We can now delete 121 // and all in progress downloads have been cancelled. We can now delete
121 // anything left. 122 // anything left.
122 123
123 // Copy downloads_ to separate container so as not to set off checks 124 // Copy downloads_ to separate container so as not to set off checks
124 // in DownloadItem destruction. 125 // in DownloadItem destruction.
125 DownloadSet downloads_to_delete; 126 DownloadSet downloads_to_delete;
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 << " download = " << download->DebugString(true); 268 << " download = " << download->DebugString(true);
268 269
269 FilePath suggested_path = download->suggested_path(); 270 FilePath suggested_path = download->suggested_path();
270 271
271 if (download->prompt_user_for_save_location()) { 272 if (download->prompt_user_for_save_location()) {
272 // We must ask the user for the place to put the download. 273 // We must ask the user for the place to put the download.
273 DownloadRequestHandle request_handle = download->request_handle(); 274 DownloadRequestHandle request_handle = download->request_handle();
274 TabContents* contents = request_handle.GetTabContents(); 275 TabContents* contents = request_handle.GetTabContents();
275 276
276 // |id_ptr| will be deleted in either FileSelected() or 277 // |id_ptr| will be deleted in either FileSelected() or
277 // FileSelectionCanceled(). 278 // FileSelectionCancelled().
278 int32* id_ptr = new int32; 279 int32* id_ptr = new int32;
279 *id_ptr = download_id; 280 *id_ptr = download_id;
280 281
281 delegate_->ChooseDownloadPath( 282 delegate_->ChooseDownloadPath(
282 contents, suggested_path, reinterpret_cast<void*>(id_ptr)); 283 contents, suggested_path, reinterpret_cast<void*>(id_ptr));
283 284
284 FOR_EACH_OBSERVER(Observer, observers_, 285 FOR_EACH_OBSERVER(Observer, observers_,
285 SelectFileDialogDisplayed(download_id)); 286 SelectFileDialogDisplayed(download_id));
286 } else { 287 } else {
287 // No prompting for download, just continue with the suggested name. 288 // No prompting for download, just continue with the suggested name.
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 NewRunnableMethod( 498 NewRunnableMethod(
498 file_manager_, &DownloadFileManager::CompleteDownload, download_id)); 499 file_manager_, &DownloadFileManager::CompleteDownload, download_id));
499 500
500 if (uniquifier) 501 if (uniquifier)
501 item->set_path_uniquifier(uniquifier); 502 item->set_path_uniquifier(uniquifier);
502 503
503 item->OnDownloadRenamedToFinalName(full_path); 504 item->OnDownloadRenamedToFinalName(full_path);
504 delegate_->UpdatePathForItemInPersistentStore(item, full_path); 505 delegate_->UpdatePathForItemInPersistentStore(item, full_path);
505 } 506 }
506 507
507 void DownloadManager::DownloadStopped(DownloadItem* download) { 508 void DownloadManager::CancelDownload(int32 download_id) {
509 DownloadItem* download = GetActiveDownload(download_id);
510 // A cancel at the right time could remove the download from the
511 // |active_downloads_| map before we get here.
512 if (!download)
513 return;
514
515 download->Cancel(true);
516 }
517
518 void DownloadManager::DownloadCancelledInternal(DownloadItem* download) {
508 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 519 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
509 CHECK(ContainsKey(active_downloads_, download->id()));
510 520
511 VLOG(20) << __FUNCTION__ << "()" 521 VLOG(20) << __FUNCTION__ << "()"
512 << " download = " << download->DebugString(true); 522 << " download = " << download->DebugString(true);
513 523
514 in_progress_.erase(download->id()); 524 RemoveFromActiveList(download);
515 active_downloads_.erase(download->id());
516 UpdateDownloadProgress(); // Reflect removal from in_progress_.
517 if (download->db_handle() != DownloadItem::kUninitializedHandle)
518 delegate_->UpdateItemInPersistentStore(download);
519
520 // This function is called from the DownloadItem, so DI state 525 // This function is called from the DownloadItem, so DI state
521 // should already have been updated. 526 // should already have been updated.
522 AssertQueueStateConsistent(download); 527 AssertQueueStateConsistent(download);
523 528
524 download->OffThreadCancel(file_manager_); 529 download->OffThreadCancel(file_manager_);
525 } 530 }
526 531
527 void DownloadManager::OnDownloadError(int32 download_id, 532 void DownloadManager::OnDownloadError(int32 download_id,
528 int64 size, 533 int64 size,
529 net::Error error) { 534 net::Error error) {
530 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 535 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
531 536
532 DownloadItem* download = GetActiveDownload(download_id); 537 DownloadItem* download = GetActiveDownload(download_id);
533 if (!download) 538 if (!download)
534 return; 539 return;
535 540
536 VLOG(20) << __FUNCTION__ << "()" << " Error " << error 541 VLOG(20) << __FUNCTION__ << "()" << " Error " << error
537 << " at offset " << download->received_bytes() 542 << " at offset " << download->received_bytes()
538 << " size = " << size 543 << " size = " << size
539 << " download = " << download->DebugString(true); 544 << " download = " << download->DebugString(true);
540 545
541 download->Interrupt(size, error); 546 RemoveFromActiveList(download);
547 download->Interrupted(size, error);
548 download->OffThreadCancel(file_manager_);
542 } 549 }
543 550
544 DownloadItem* DownloadManager::GetActiveDownload(int32 download_id) { 551 DownloadItem* DownloadManager::GetActiveDownload(int32 download_id) {
545 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 552 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
546 DownloadMap::iterator it = active_downloads_.find(download_id); 553 DownloadMap::iterator it = active_downloads_.find(download_id);
547 if (it == active_downloads_.end()) 554 if (it == active_downloads_.end())
548 return NULL; 555 return NULL;
549 556
550 DownloadItem* download = it->second; 557 DownloadItem* download = it->second;
551 558
552 DCHECK(download); 559 DCHECK(download);
553 DCHECK_EQ(download_id, download->id()); 560 DCHECK_EQ(download_id, download->id());
554 561
555 return download; 562 return download;
556 } 563 }
557 564
565 void DownloadManager::RemoveFromActiveList(DownloadItem* download) {
566 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
567 DCHECK(download);
568
569 // Clean up will happen when the history system create callback runs if we
570 // don't have a valid db_handle yet.
571 if (download->db_handle() != DownloadItem::kUninitializedHandle) {
572 in_progress_.erase(download->id());
573 active_downloads_.erase(download->id());
574 UpdateDownloadProgress(); // Reflect removal from in_progress_.
575 delegate_->UpdateItemInPersistentStore(download);
576 }
577 }
578
558 void DownloadManager::UpdateDownloadProgress() { 579 void DownloadManager::UpdateDownloadProgress() {
559 delegate_->DownloadProgressUpdated(); 580 delegate_->DownloadProgressUpdated();
560 } 581 }
561 582
562 int DownloadManager::RemoveDownloadItems( 583 int DownloadManager::RemoveDownloadItems(
563 const DownloadVector& pending_deletes) { 584 const DownloadVector& pending_deletes) {
564 if (pending_deletes.empty()) 585 if (pending_deletes.empty())
565 return 0; 586 return 0;
566 587
567 // Delete from internal maps. 588 // Delete from internal maps.
568 for (DownloadVector::const_iterator it = pending_deletes.begin(); 589 for (DownloadVector::const_iterator it = pending_deletes.begin();
569 it != pending_deletes.end(); 590 it != pending_deletes.end();
570 ++it) { 591 ++it) {
571 DownloadItem* download = *it; 592 DownloadItem* download = *it;
572 DCHECK(download); 593 DCHECK(download);
573 history_downloads_.erase(download->db_handle()); 594 history_downloads_.erase(download->db_handle());
574 save_page_downloads_.erase(download->id()); 595 save_page_downloads_.erase(download->id());
575 downloads_.erase(download); 596 downloads_.erase(download);
576 } 597 }
577 598
578 // Tell observers to refresh their views. 599 // Tell observers to refresh their views.
579 NotifyModelChanged(); 600 NotifyModelChanged();
580 601
581 // Delete the download items themselves. 602 // Delete the download items themselves.
582 const int num_deleted = static_cast<int>(pending_deletes.size()); 603 const int num_deleted = static_cast<int>(pending_deletes.size());
583 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end()); 604 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
584 return num_deleted; 605 return num_deleted;
585 } 606 }
586 607
587 void DownloadManager::RemoveDownload(DownloadItem* download) { 608 void DownloadManager::RemoveDownload(int64 download_handle) {
588 // Make history update. Ignores if db_handle isn't in history. 609 DownloadMap::iterator it = history_downloads_.find(download_handle);
589 delegate_->RemoveItemFromPersistentStore(download->db_handle()); 610 if (it == history_downloads_.end())
611 return;
612
613 // Make history update.
614 DownloadItem* download = it->second;
615 delegate_->RemoveItemFromPersistentStore(download);
590 616
591 // Remove from our tables and delete. 617 // Remove from our tables and delete.
592 int downloads_count = RemoveDownloadItems(DownloadVector(1, download)); 618 int downloads_count = RemoveDownloadItems(DownloadVector(1, download));
593 DCHECK_EQ(1, downloads_count); 619 DCHECK_EQ(1, downloads_count);
594 } 620 }
595 621
596 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin, 622 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin,
597 const base::Time remove_end) { 623 const base::Time remove_end) {
598 delegate_->RemoveItemsFromPersistentStoreBetween(remove_begin, remove_end); 624 delegate_->RemoveItemsFromPersistentStoreBetween(remove_begin, remove_end);
599 625
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 int32 download_id = *id_ptr; 755 int32 download_id = *id_ptr;
730 delete id_ptr; 756 delete id_ptr;
731 757
732 DownloadItem* download = GetActiveDownloadItem(download_id); 758 DownloadItem* download = GetActiveDownloadItem(download_id);
733 if (!download) 759 if (!download)
734 return; 760 return;
735 761
736 VLOG(20) << __FUNCTION__ << "()" 762 VLOG(20) << __FUNCTION__ << "()"
737 << " download = " << download->DebugString(true); 763 << " download = " << download->DebugString(true);
738 764
739 download->Cancel(); 765 // TODO(ahendrickson) -- This currently has no effect, as the download is
766 // not put on the active list until the file selection is complete. Need
767 // to put it on the active list earlier in the process.
768 RemoveFromActiveList(download);
769
770 download->OffThreadCancel(file_manager_);
740 } 771 }
741 772
742 // Operations posted to us from the history service ---------------------------- 773 // Operations posted to us from the history service ----------------------------
743 774
744 // The history service has retrieved all download entries. 'entries' contains 775 // The history service has retrieved all download entries. 'entries' contains
745 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time). 776 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time).
746 void DownloadManager::OnPersistentStoreQueryComplete( 777 void DownloadManager::OnPersistentStoreQueryComplete(
747 std::vector<DownloadPersistentStoreInfo>* entries) { 778 std::vector<DownloadPersistentStoreInfo>* entries) {
748 // TODO(rdsmith): Remove this and related logic when 779 // TODO(rdsmith): Remove this and related logic when
749 // http://crbug.com/84508 is fixed. 780 // http://crbug.com/84508 is fixed.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 // It's valid that we don't find a matching item, i.e. on shutdown. 831 // It's valid that we don't find a matching item, i.e. on shutdown.
801 } 832 }
802 833
803 // Once the new DownloadItem's creation info has been committed to the history 834 // Once the new DownloadItem's creation info has been committed to the history
804 // service, we associate the DownloadItem with the db handle, update our 835 // service, we associate the DownloadItem with the db handle, update our
805 // 'history_downloads_' map and inform observers. 836 // 'history_downloads_' map and inform observers.
806 void DownloadManager::OnDownloadItemAddedToPersistentStore(int32 download_id, 837 void DownloadManager::OnDownloadItemAddedToPersistentStore(int32 download_id,
807 int64 db_handle) { 838 int64 db_handle) {
808 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 839 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
809 DownloadItem* download = GetActiveDownloadItem(download_id); 840 DownloadItem* download = GetActiveDownloadItem(download_id);
810 if (!download) { 841 if (!download)
811 // The download was cancelled while the persistent store was entering it.
812 // We resolve this race by turning around and deleting it in the
813 // persistent store (implicitly treating it as a failure in download
814 // initiation, which is appropriate as the only places the cancel could
815 // have come from were in resolving issues (like the file name) which
816 // we need to have resolved for persistent store insertion).
817
818 // Make sure we haven't already been shutdown (the callback raced
819 // with shutdown), as that would mean that we no longer have access
820 // to the persistent store. In that case, the history will be cleaned up
821 // on next persistent store query.
822 if (shutdown_needed_)
823 delegate_->RemoveItemFromPersistentStore(db_handle);
824 return; 842 return;
825 }
826 843
827 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle 844 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle
828 << " download_id = " << download_id 845 << " download_id = " << download_id
829 << " download = " << download->DebugString(true); 846 << " download = " << download->DebugString(true);
830 847
831 // TODO(rdsmith): Remove after http://crbug.com/85408 resolved. 848 // TODO(rdsmith): Remove after http://crbug.com/85408 resolved.
832 int64 largest_handle = largest_db_handle_in_history_; 849 int64 largest_handle = largest_db_handle_in_history_;
833 base::debug::Alias(&largest_handle); 850 base::debug::Alias(&largest_handle);
834 int32 matching_item_download_id 851 int32 matching_item_download_id
835 = (ContainsKey(history_downloads_, db_handle) ? 852 = (ContainsKey(history_downloads_, db_handle) ?
836 history_downloads_[db_handle]->id() : 0); 853 history_downloads_[db_handle]->id() : 0);
837 base::debug::Alias(&matching_item_download_id); 854 base::debug::Alias(&matching_item_download_id);
838 855
839 CHECK(!ContainsKey(history_downloads_, db_handle)); 856 CHECK(!ContainsKey(history_downloads_, db_handle));
840 857
841 CHECK(download->IsInProgress());
842 AddDownloadItemToHistory(download, db_handle); 858 AddDownloadItemToHistory(download, db_handle);
843 859
844 MaybeCompleteDownload(download); 860 // If the download is still in progress, try to complete it.
861 //
862 // Otherwise, download has been cancelled or interrupted before we've
863 // received the DB handle. We post one final message to the history
864 // service so that it can be properly in sync with the DownloadItem's
865 // completion status, and also inform any observers so that they get
866 // more than just the start notification.
867 if (download->IsInProgress()) {
868 MaybeCompleteDownload(download);
869 } else {
870 // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/84508
871 // is fixed.
872 CHECK(download->IsCancelled())
873 << " download = " << download->DebugString(true);
874 in_progress_.erase(download_id);
875 active_downloads_.erase(download_id);
876 delegate_->UpdateItemInPersistentStore(download);
877 download->UpdateObservers();
878 }
845 } 879 }
846 880
847 void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) { 881 void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) {
848 // The 'contents' may no longer exist if the user closed the tab before we 882 // The 'contents' may no longer exist if the user closed the tab before we
849 // get this start completion event. 883 // get this start completion event.
850 DownloadRequestHandle request_handle = download->request_handle(); 884 DownloadRequestHandle request_handle = download->request_handle();
851 TabContents* content = request_handle.GetTabContents(); 885 TabContents* content = request_handle.GetTabContents();
852 886
853 // If the contents no longer exists, we ask the embedder to suggest another 887 // If the contents no longer exists, we ask the embedder to suggest another
854 // tab. 888 // tab.
(...skipping 18 matching lines...) Expand all
873 // not its id, so we have to iterate. 907 // not its id, so we have to iterate.
874 for (DownloadMap::iterator it = history_downloads_.begin(); 908 for (DownloadMap::iterator it = history_downloads_.begin();
875 it != history_downloads_.end(); ++it) { 909 it != history_downloads_.end(); ++it) {
876 DownloadItem* item = it->second; 910 DownloadItem* item = it->second;
877 if (item->id() == download_id) 911 if (item->id() == download_id)
878 return item; 912 return item;
879 } 913 }
880 return NULL; 914 return NULL;
881 } 915 }
882 916
883 void DownloadManager::GetInProgressDownloads(
884 std::vector<DownloadItem*>* result) {
885 DCHECK(result);
886
887 for (DownloadMap::iterator it = active_downloads_.begin();
888 it != active_downloads_.end(); ++it) {
889 result->push_back(it->second);
890 }
891 }
892
893 DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) { 917 DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) {
894 if (!ContainsKey(active_downloads_, download_id)) 918 DCHECK(ContainsKey(active_downloads_, download_id));
895 return NULL;
896
897 DownloadItem* download = active_downloads_[download_id]; 919 DownloadItem* download = active_downloads_[download_id];
898 DCHECK(download != NULL); 920 DCHECK(download != NULL);
899 return download; 921 return download;
900 } 922 }
901 923
902 // Confirm that everything in all maps is also in |downloads_|, and that 924 // Confirm that everything in all maps is also in |downloads_|, and that
903 // everything in |downloads_| is also in some other map. 925 // everything in |downloads_| is also in some other map.
904 void DownloadManager::AssertContainersConsistent() const { 926 void DownloadManager::AssertContainersConsistent() const {
905 #if !defined(NDEBUG) 927 #if !defined(NDEBUG)
906 // Turn everything into sets. 928 // Turn everything into sets.
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1002 DCHECK(ContainsKey(save_page_downloads_, download->id())); 1024 DCHECK(ContainsKey(save_page_downloads_, download->id()));
1003 save_page_downloads_.erase(download->id()); 1025 save_page_downloads_.erase(download->id());
1004 1026
1005 if (download->IsComplete()) 1027 if (download->IsComplete())
1006 NotificationService::current()->Notify( 1028 NotificationService::current()->Notify(
1007 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, 1029 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
1008 Source<DownloadManager>(this), 1030 Source<DownloadManager>(this),
1009 Details<DownloadItem>(download)); 1031 Details<DownloadItem>(download));
1010 } 1032 }
1011 } 1033 }
OLDNEW
« no previous file with comments | « content/browser/download/download_manager.h ('k') | content/browser/download/download_manager_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698