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

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

Issue 7796014: Make cancel remove cancelled download from active queues at time of cancel. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix to try to get past main waterfall failure. 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(false); 115 download->Cancel();
116 delegate_->UpdateItemInPersistentStore(download);
117 } 116 }
118 } 117 }
119 118
120 // At this point, all dangerous downloads have had their files removed 119 // At this point, all dangerous downloads have had their files removed
121 // and all in progress downloads have been cancelled. We can now delete 120 // and all in progress downloads have been cancelled. We can now delete
122 // anything left. 121 // anything left.
123 122
124 // Copy downloads_ to separate container so as not to set off checks 123 // Copy downloads_ to separate container so as not to set off checks
125 // in DownloadItem destruction. 124 // in DownloadItem destruction.
126 DownloadSet downloads_to_delete; 125 DownloadSet downloads_to_delete;
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 << " download = " << download->DebugString(true); 267 << " download = " << download->DebugString(true);
269 268
270 FilePath suggested_path = download->suggested_path(); 269 FilePath suggested_path = download->suggested_path();
271 270
272 if (download->prompt_user_for_save_location()) { 271 if (download->prompt_user_for_save_location()) {
273 // We must ask the user for the place to put the download. 272 // We must ask the user for the place to put the download.
274 DownloadRequestHandle request_handle = download->request_handle(); 273 DownloadRequestHandle request_handle = download->request_handle();
275 TabContents* contents = request_handle.GetTabContents(); 274 TabContents* contents = request_handle.GetTabContents();
276 275
277 // |id_ptr| will be deleted in either FileSelected() or 276 // |id_ptr| will be deleted in either FileSelected() or
278 // FileSelectionCancelled(). 277 // FileSelectionCanceled().
279 int32* id_ptr = new int32; 278 int32* id_ptr = new int32;
280 *id_ptr = download_id; 279 *id_ptr = download_id;
281 280
282 delegate_->ChooseDownloadPath( 281 delegate_->ChooseDownloadPath(
283 contents, suggested_path, reinterpret_cast<void*>(id_ptr)); 282 contents, suggested_path, reinterpret_cast<void*>(id_ptr));
284 283
285 FOR_EACH_OBSERVER(Observer, observers_, 284 FOR_EACH_OBSERVER(Observer, observers_,
286 SelectFileDialogDisplayed(download_id)); 285 SelectFileDialogDisplayed(download_id));
287 } else { 286 } else {
288 // No prompting for download, just continue with the suggested name. 287 // No prompting for download, just continue with the suggested name.
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 NewRunnableMethod( 497 NewRunnableMethod(
499 file_manager_, &DownloadFileManager::CompleteDownload, download_id)); 498 file_manager_, &DownloadFileManager::CompleteDownload, download_id));
500 499
501 if (uniquifier) 500 if (uniquifier)
502 item->set_path_uniquifier(uniquifier); 501 item->set_path_uniquifier(uniquifier);
503 502
504 item->OnDownloadRenamedToFinalName(full_path); 503 item->OnDownloadRenamedToFinalName(full_path);
505 delegate_->UpdatePathForItemInPersistentStore(item, full_path); 504 delegate_->UpdatePathForItemInPersistentStore(item, full_path);
506 } 505 }
507 506
508 void DownloadManager::CancelDownload(int32 download_id) { 507 void DownloadManager::DownloadStopped(DownloadItem* download) {
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) {
519 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 508 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
509 CHECK(ContainsKey(active_downloads_, download->id()));
520 510
521 VLOG(20) << __FUNCTION__ << "()" 511 VLOG(20) << __FUNCTION__ << "()"
522 << " download = " << download->DebugString(true); 512 << " download = " << download->DebugString(true);
523 513
524 RemoveFromActiveList(download); 514 in_progress_.erase(download->id());
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
525 // This function is called from the DownloadItem, so DI state 520 // This function is called from the DownloadItem, so DI state
526 // should already have been updated. 521 // should already have been updated.
527 AssertQueueStateConsistent(download); 522 AssertQueueStateConsistent(download);
528 523
529 download->OffThreadCancel(file_manager_); 524 download->OffThreadCancel(file_manager_);
530 } 525 }
531 526
532 void DownloadManager::OnDownloadError(int32 download_id, 527 void DownloadManager::OnDownloadError(int32 download_id,
533 int64 size, 528 int64 size,
534 net::Error error) { 529 net::Error error) {
535 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 530 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
536 531
537 DownloadItem* download = GetActiveDownload(download_id); 532 DownloadItem* download = GetActiveDownload(download_id);
538 if (!download) 533 if (!download)
539 return; 534 return;
540 535
541 VLOG(20) << __FUNCTION__ << "()" << " Error " << error 536 VLOG(20) << __FUNCTION__ << "()" << " Error " << error
542 << " at offset " << download->received_bytes() 537 << " at offset " << download->received_bytes()
543 << " size = " << size 538 << " size = " << size
544 << " download = " << download->DebugString(true); 539 << " download = " << download->DebugString(true);
545 540
546 RemoveFromActiveList(download); 541 download->Interrupt(size, error);
547 download->Interrupted(size, error);
548 download->OffThreadCancel(file_manager_);
549 } 542 }
550 543
551 DownloadItem* DownloadManager::GetActiveDownload(int32 download_id) { 544 DownloadItem* DownloadManager::GetActiveDownload(int32 download_id) {
552 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 545 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
553 DownloadMap::iterator it = active_downloads_.find(download_id); 546 DownloadMap::iterator it = active_downloads_.find(download_id);
554 if (it == active_downloads_.end()) 547 if (it == active_downloads_.end())
555 return NULL; 548 return NULL;
556 549
557 DownloadItem* download = it->second; 550 DownloadItem* download = it->second;
558 551
559 DCHECK(download); 552 DCHECK(download);
560 DCHECK_EQ(download_id, download->id()); 553 DCHECK_EQ(download_id, download->id());
561 554
562 return download; 555 return download;
563 } 556 }
564 557
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
579 void DownloadManager::UpdateDownloadProgress() { 558 void DownloadManager::UpdateDownloadProgress() {
580 delegate_->DownloadProgressUpdated(); 559 delegate_->DownloadProgressUpdated();
581 } 560 }
582 561
583 int DownloadManager::RemoveDownloadItems( 562 int DownloadManager::RemoveDownloadItems(
584 const DownloadVector& pending_deletes) { 563 const DownloadVector& pending_deletes) {
585 if (pending_deletes.empty()) 564 if (pending_deletes.empty())
586 return 0; 565 return 0;
587 566
588 // Delete from internal maps. 567 // Delete from internal maps.
589 for (DownloadVector::const_iterator it = pending_deletes.begin(); 568 for (DownloadVector::const_iterator it = pending_deletes.begin();
590 it != pending_deletes.end(); 569 it != pending_deletes.end();
591 ++it) { 570 ++it) {
592 DownloadItem* download = *it; 571 DownloadItem* download = *it;
593 DCHECK(download); 572 DCHECK(download);
594 history_downloads_.erase(download->db_handle()); 573 history_downloads_.erase(download->db_handle());
595 save_page_downloads_.erase(download->id()); 574 save_page_downloads_.erase(download->id());
596 downloads_.erase(download); 575 downloads_.erase(download);
597 } 576 }
598 577
599 // Tell observers to refresh their views. 578 // Tell observers to refresh their views.
600 NotifyModelChanged(); 579 NotifyModelChanged();
601 580
602 // Delete the download items themselves. 581 // Delete the download items themselves.
603 const int num_deleted = static_cast<int>(pending_deletes.size()); 582 const int num_deleted = static_cast<int>(pending_deletes.size());
604 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end()); 583 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
605 return num_deleted; 584 return num_deleted;
606 } 585 }
607 586
608 void DownloadManager::RemoveDownload(int64 download_handle) { 587 void DownloadManager::RemoveDownload(DownloadItem* download) {
609 DownloadMap::iterator it = history_downloads_.find(download_handle); 588 // Make history update. Ignores if db_handle isn't in history.
610 if (it == history_downloads_.end()) 589 delegate_->RemoveItemFromPersistentStore(download->db_handle());
611 return;
612
613 // Make history update.
614 DownloadItem* download = it->second;
615 delegate_->RemoveItemFromPersistentStore(download);
616 590
617 // Remove from our tables and delete. 591 // Remove from our tables and delete.
618 int downloads_count = RemoveDownloadItems(DownloadVector(1, download)); 592 int downloads_count = RemoveDownloadItems(DownloadVector(1, download));
619 DCHECK_EQ(1, downloads_count); 593 DCHECK_EQ(1, downloads_count);
620 } 594 }
621 595
622 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin, 596 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin,
623 const base::Time remove_end) { 597 const base::Time remove_end) {
624 delegate_->RemoveItemsFromPersistentStoreBetween(remove_begin, remove_end); 598 delegate_->RemoveItemsFromPersistentStoreBetween(remove_begin, remove_end);
625 599
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 int32 download_id = *id_ptr; 729 int32 download_id = *id_ptr;
756 delete id_ptr; 730 delete id_ptr;
757 731
758 DownloadItem* download = GetActiveDownloadItem(download_id); 732 DownloadItem* download = GetActiveDownloadItem(download_id);
759 if (!download) 733 if (!download)
760 return; 734 return;
761 735
762 VLOG(20) << __FUNCTION__ << "()" 736 VLOG(20) << __FUNCTION__ << "()"
763 << " download = " << download->DebugString(true); 737 << " download = " << download->DebugString(true);
764 738
765 // TODO(ahendrickson) -- This currently has no effect, as the download is 739 download->Cancel();
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_);
771 } 740 }
772 741
773 // Operations posted to us from the history service ---------------------------- 742 // Operations posted to us from the history service ----------------------------
774 743
775 // The history service has retrieved all download entries. 'entries' contains 744 // The history service has retrieved all download entries. 'entries' contains
776 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time). 745 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time).
777 void DownloadManager::OnPersistentStoreQueryComplete( 746 void DownloadManager::OnPersistentStoreQueryComplete(
778 std::vector<DownloadPersistentStoreInfo>* entries) { 747 std::vector<DownloadPersistentStoreInfo>* entries) {
779 // TODO(rdsmith): Remove this and related logic when 748 // TODO(rdsmith): Remove this and related logic when
780 // http://crbug.com/84508 is fixed. 749 // http://crbug.com/84508 is fixed.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
831 // It's valid that we don't find a matching item, i.e. on shutdown. 800 // It's valid that we don't find a matching item, i.e. on shutdown.
832 } 801 }
833 802
834 // Once the new DownloadItem's creation info has been committed to the history 803 // Once the new DownloadItem's creation info has been committed to the history
835 // service, we associate the DownloadItem with the db handle, update our 804 // service, we associate the DownloadItem with the db handle, update our
836 // 'history_downloads_' map and inform observers. 805 // 'history_downloads_' map and inform observers.
837 void DownloadManager::OnDownloadItemAddedToPersistentStore(int32 download_id, 806 void DownloadManager::OnDownloadItemAddedToPersistentStore(int32 download_id,
838 int64 db_handle) { 807 int64 db_handle) {
839 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 808 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
840 DownloadItem* download = GetActiveDownloadItem(download_id); 809 DownloadItem* download = GetActiveDownloadItem(download_id);
841 if (!download) 810 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);
842 return; 824 return;
825 }
843 826
844 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle 827 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle
845 << " download_id = " << download_id 828 << " download_id = " << download_id
846 << " download = " << download->DebugString(true); 829 << " download = " << download->DebugString(true);
847 830
848 // TODO(rdsmith): Remove after http://crbug.com/85408 resolved. 831 // TODO(rdsmith): Remove after http://crbug.com/85408 resolved.
849 int64 largest_handle = largest_db_handle_in_history_; 832 int64 largest_handle = largest_db_handle_in_history_;
850 base::debug::Alias(&largest_handle); 833 base::debug::Alias(&largest_handle);
851 int32 matching_item_download_id 834 int32 matching_item_download_id
852 = (ContainsKey(history_downloads_, db_handle) ? 835 = (ContainsKey(history_downloads_, db_handle) ?
853 history_downloads_[db_handle]->id() : 0); 836 history_downloads_[db_handle]->id() : 0);
854 base::debug::Alias(&matching_item_download_id); 837 base::debug::Alias(&matching_item_download_id);
855 838
856 CHECK(!ContainsKey(history_downloads_, db_handle)); 839 CHECK(!ContainsKey(history_downloads_, db_handle));
857 840
841 CHECK(download->IsInProgress());
858 AddDownloadItemToHistory(download, db_handle); 842 AddDownloadItemToHistory(download, db_handle);
859 843
860 // If the download is still in progress, try to complete it. 844 MaybeCompleteDownload(download);
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 }
879 } 845 }
880 846
881 void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) { 847 void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) {
882 // The 'contents' may no longer exist if the user closed the tab before we 848 // The 'contents' may no longer exist if the user closed the tab before we
883 // get this start completion event. 849 // get this start completion event.
884 DownloadRequestHandle request_handle = download->request_handle(); 850 DownloadRequestHandle request_handle = download->request_handle();
885 TabContents* content = request_handle.GetTabContents(); 851 TabContents* content = request_handle.GetTabContents();
886 852
887 // If the contents no longer exists, we ask the embedder to suggest another 853 // If the contents no longer exists, we ask the embedder to suggest another
888 // tab. 854 // tab.
(...skipping 18 matching lines...) Expand all
907 // not its id, so we have to iterate. 873 // not its id, so we have to iterate.
908 for (DownloadMap::iterator it = history_downloads_.begin(); 874 for (DownloadMap::iterator it = history_downloads_.begin();
909 it != history_downloads_.end(); ++it) { 875 it != history_downloads_.end(); ++it) {
910 DownloadItem* item = it->second; 876 DownloadItem* item = it->second;
911 if (item->id() == download_id) 877 if (item->id() == download_id)
912 return item; 878 return item;
913 } 879 }
914 return NULL; 880 return NULL;
915 } 881 }
916 882
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
917 DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) { 893 DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) {
918 DCHECK(ContainsKey(active_downloads_, download_id)); 894 if (!ContainsKey(active_downloads_, download_id))
895 return NULL;
896
919 DownloadItem* download = active_downloads_[download_id]; 897 DownloadItem* download = active_downloads_[download_id];
920 DCHECK(download != NULL); 898 DCHECK(download != NULL);
921 return download; 899 return download;
922 } 900 }
923 901
924 // Confirm that everything in all maps is also in |downloads_|, and that 902 // Confirm that everything in all maps is also in |downloads_|, and that
925 // everything in |downloads_| is also in some other map. 903 // everything in |downloads_| is also in some other map.
926 void DownloadManager::AssertContainersConsistent() const { 904 void DownloadManager::AssertContainersConsistent() const {
927 #if !defined(NDEBUG) 905 #if !defined(NDEBUG)
928 // Turn everything into sets. 906 // Turn everything into sets.
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 DCHECK(ContainsKey(save_page_downloads_, download->id())); 1002 DCHECK(ContainsKey(save_page_downloads_, download->id()));
1025 save_page_downloads_.erase(download->id()); 1003 save_page_downloads_.erase(download->id());
1026 1004
1027 if (download->IsComplete()) 1005 if (download->IsComplete())
1028 NotificationService::current()->Notify( 1006 NotificationService::current()->Notify(
1029 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, 1007 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
1030 Source<DownloadManager>(this), 1008 Source<DownloadManager>(this),
1031 Details<DownloadItem>(download)); 1009 Details<DownloadItem>(download));
1032 } 1010 }
1033 } 1011 }
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