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

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: Final Cancel arg fix. 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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 // The user hasn't accepted it, so we need to remove it 97 // The user hasn't accepted it, so we need to remove it
98 // from the disk. This may or may not result in it being 98 // from the disk. This may or may not result in it being
99 // removed from the DownloadManager queues and deleted 99 // removed from the DownloadManager queues and deleted
100 // (specifically, DownloadManager::RemoveDownload only 100 // (specifically, DownloadManager::RemoveDownload only
101 // removes and deletes it if it's known to the history service) 101 // removes and deletes it if it's known to the history service)
102 // so the only thing we know after calling this function is that 102 // so the only thing we know after calling this function is that
103 // the download was deleted if-and-only-if it was removed 103 // the download was deleted if-and-only-if it was removed
104 // from all queues. 104 // from all queues.
105 download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN); 105 download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN);
106 } else if (download->IsPartialDownload()) { 106 } else if (download->IsPartialDownload()) {
107 download->Cancel(false); 107 download->Cancel();
108 delegate_->UpdateItemInPersistentStore(download);
109 } 108 }
110 } 109 }
111 110
112 // At this point, all dangerous downloads have had their files removed 111 // At this point, all dangerous downloads have had their files removed
113 // and all in progress downloads have been cancelled. We can now delete 112 // and all in progress downloads have been cancelled. We can now delete
114 // anything left. 113 // anything left.
115 114
116 // Copy downloads_ to separate container so as not to set off checks 115 // Copy downloads_ to separate container so as not to set off checks
117 // in DownloadItem destruction. 116 // in DownloadItem destruction.
118 DownloadSet downloads_to_delete; 117 DownloadSet downloads_to_delete;
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 delegate_->UpdatePathForItemInPersistentStore(item, full_path); 494 delegate_->UpdatePathForItemInPersistentStore(item, full_path);
496 } 495 }
497 496
498 void DownloadManager::CancelDownload(int32 download_id) { 497 void DownloadManager::CancelDownload(int32 download_id) {
499 DownloadItem* download = GetActiveDownload(download_id); 498 DownloadItem* download = GetActiveDownload(download_id);
500 // A cancel at the right time could remove the download from the 499 // A cancel at the right time could remove the download from the
501 // |active_downloads_| map before we get here. 500 // |active_downloads_| map before we get here.
502 if (!download) 501 if (!download)
503 return; 502 return;
504 503
505 download->Cancel(true); 504 download->Cancel();
506 } 505 }
507 506
508 void DownloadManager::DownloadCancelledInternal(DownloadItem* download) { 507 void DownloadManager::DownloadStopped(DownloadItem* download) {
509 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 508 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
509 DCHECK(ContainsKey(active_downloads_, download->id()));
benjhayden 2011/09/12 18:13:38 CHECK?
Randy Smith (Not in Mondays) 2011/09/12 19:43:23 Done.
510 510
511 VLOG(20) << __FUNCTION__ << "()" 511 VLOG(20) << __FUNCTION__ << "()"
512 << " download = " << download->DebugString(true); 512 << " download = " << download->DebugString(true);
513 513
514 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
515 // This function is called from the DownloadItem, so DI state 520 // This function is called from the DownloadItem, so DI state
516 // should already have been updated. 521 // should already have been updated.
517 AssertQueueStateConsistent(download); 522 AssertQueueStateConsistent(download);
518 523
519 download->OffThreadCancel(file_manager_); 524 download->OffThreadCancel(file_manager_);
520 } 525 }
521 526
522 void DownloadManager::OnDownloadError(int32 download_id, 527 void DownloadManager::OnDownloadError(int32 download_id,
523 int64 size, 528 int64 size,
524 net::Error error) { 529 net::Error error) {
525 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 530 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
526 531
527 DownloadItem* download = GetActiveDownload(download_id); 532 DownloadItem* download = GetActiveDownload(download_id);
528 if (!download) 533 if (!download)
529 return; 534 return;
530 535
531 VLOG(20) << __FUNCTION__ << "()" << " Error " << error 536 VLOG(20) << __FUNCTION__ << "()" << " Error " << error
532 << " at offset " << download->received_bytes() 537 << " at offset " << download->received_bytes()
533 << " size = " << size 538 << " size = " << size
534 << " download = " << download->DebugString(true); 539 << " download = " << download->DebugString(true);
535 540
536 RemoveFromActiveList(download); 541 download->Interrupt(size, error);
537 download->Interrupted(size, error);
538 download->OffThreadCancel(file_manager_);
539 } 542 }
540 543
541 DownloadItem* DownloadManager::GetActiveDownload(int32 download_id) { 544 DownloadItem* DownloadManager::GetActiveDownload(int32 download_id) {
542 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 545 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
543 DownloadMap::iterator it = active_downloads_.find(download_id); 546 DownloadMap::iterator it = active_downloads_.find(download_id);
544 if (it == active_downloads_.end()) 547 if (it == active_downloads_.end())
545 return NULL; 548 return NULL;
546 549
547 DownloadItem* download = it->second; 550 DownloadItem* download = it->second;
548 551
549 DCHECK(download); 552 DCHECK(download);
550 DCHECK_EQ(download_id, download->id()); 553 DCHECK_EQ(download_id, download->id());
551 554
552 return download; 555 return download;
553 } 556 }
554 557
555 void DownloadManager::RemoveFromActiveList(DownloadItem* download) {
556 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
557 DCHECK(download);
558
559 // Clean up will happen when the history system create callback runs if we
560 // don't have a valid db_handle yet.
561 if (download->db_handle() != DownloadItem::kUninitializedHandle) {
562 in_progress_.erase(download->id());
563 active_downloads_.erase(download->id());
564 UpdateDownloadProgress(); // Reflect removal from in_progress_.
565 delegate_->UpdateItemInPersistentStore(download);
566 }
567 }
568
569 void DownloadManager::UpdateDownloadProgress() { 558 void DownloadManager::UpdateDownloadProgress() {
570 delegate_->DownloadProgressUpdated(); 559 delegate_->DownloadProgressUpdated();
571 } 560 }
572 561
573 int DownloadManager::RemoveDownloadItems( 562 int DownloadManager::RemoveDownloadItems(
574 const DownloadVector& pending_deletes) { 563 const DownloadVector& pending_deletes) {
575 if (pending_deletes.empty()) 564 if (pending_deletes.empty())
576 return 0; 565 return 0;
577 566
578 // Delete from internal maps. 567 // Delete from internal maps.
579 for (DownloadVector::const_iterator it = pending_deletes.begin(); 568 for (DownloadVector::const_iterator it = pending_deletes.begin();
580 it != pending_deletes.end(); 569 it != pending_deletes.end();
581 ++it) { 570 ++it) {
582 DownloadItem* download = *it; 571 DownloadItem* download = *it;
583 DCHECK(download); 572 DCHECK(download);
584 history_downloads_.erase(download->db_handle()); 573 history_downloads_.erase(download->db_handle());
585 save_page_downloads_.erase(download->id()); 574 save_page_downloads_.erase(download->id());
586 downloads_.erase(download); 575 downloads_.erase(download);
587 } 576 }
588 577
589 // Tell observers to refresh their views. 578 // Tell observers to refresh their views.
590 NotifyModelChanged(); 579 NotifyModelChanged();
591 580
592 // Delete the download items themselves. 581 // Delete the download items themselves.
593 const int num_deleted = static_cast<int>(pending_deletes.size()); 582 const int num_deleted = static_cast<int>(pending_deletes.size());
594 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end()); 583 STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
595 return num_deleted; 584 return num_deleted;
596 } 585 }
597 586
598 void DownloadManager::RemoveDownload(int64 download_handle) { 587 void DownloadManager::RemoveDownload(DownloadItem* download) {
599 DownloadMap::iterator it = history_downloads_.find(download_handle); 588 DownloadMap::iterator it = history_downloads_.find(download->db_handle());
ahendrickson 2011/09/11 15:57:02 I don't think we need this iterator here any more
Randy Smith (Not in Mondays) 2011/09/12 18:00:27 Whooops. Done.
600 if (it == history_downloads_.end())
601 return;
602 589
603 // Make history update. 590 // Make history update. Ignores if db_handle isn't in history.
604 DownloadItem* download = it->second; 591 delegate_->RemoveItemFromPersistentStore(download->db_handle());
605 delegate_->RemoveItemFromPersistentStore(download);
606 592
607 // Remove from our tables and delete. 593 // Remove from our tables and delete.
608 int downloads_count = RemoveDownloadItems(DownloadVector(1, download)); 594 int downloads_count = RemoveDownloadItems(DownloadVector(1, download));
609 DCHECK_EQ(1, downloads_count); 595 DCHECK_EQ(1, downloads_count);
610 } 596 }
611 597
612 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin, 598 int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin,
613 const base::Time remove_end) { 599 const base::Time remove_end) {
614 delegate_->RemoveItemsFromPersistentStoreBetween(remove_begin, remove_end); 600 delegate_->RemoveItemsFromPersistentStoreBetween(remove_begin, remove_end);
615 601
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 int32 download_id = *id_ptr; 731 int32 download_id = *id_ptr;
746 delete id_ptr; 732 delete id_ptr;
747 733
748 DownloadItem* download = GetActiveDownloadItem(download_id); 734 DownloadItem* download = GetActiveDownloadItem(download_id);
749 if (!download) 735 if (!download)
750 return; 736 return;
751 737
752 VLOG(20) << __FUNCTION__ << "()" 738 VLOG(20) << __FUNCTION__ << "()"
753 << " download = " << download->DebugString(true); 739 << " download = " << download->DebugString(true);
754 740
755 // TODO(ahendrickson) -- This currently has no effect, as the download is 741 download->Cancel();
756 // not put on the active list until the file selection is complete. Need
757 // to put it on the active list earlier in the process.
758 RemoveFromActiveList(download);
759
760 download->OffThreadCancel(file_manager_);
761 } 742 }
762 743
763 // Operations posted to us from the history service ---------------------------- 744 // Operations posted to us from the history service ----------------------------
764 745
765 // The history service has retrieved all download entries. 'entries' contains 746 // The history service has retrieved all download entries. 'entries' contains
766 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time). 747 // 'DownloadPersistentStoreInfo's in sorted order (by ascending start_time).
767 void DownloadManager::OnPersistentStoreQueryComplete( 748 void DownloadManager::OnPersistentStoreQueryComplete(
768 std::vector<DownloadPersistentStoreInfo>* entries) { 749 std::vector<DownloadPersistentStoreInfo>* entries) {
769 // TODO(rdsmith): Remove this and related logic when 750 // TODO(rdsmith): Remove this and related logic when
770 // http://crbug.com/84508 is fixed. 751 // http://crbug.com/84508 is fixed.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 // It's valid that we don't find a matching item, i.e. on shutdown. 802 // It's valid that we don't find a matching item, i.e. on shutdown.
822 } 803 }
823 804
824 // Once the new DownloadItem's creation info has been committed to the history 805 // Once the new DownloadItem's creation info has been committed to the history
825 // service, we associate the DownloadItem with the db handle, update our 806 // service, we associate the DownloadItem with the db handle, update our
826 // 'history_downloads_' map and inform observers. 807 // 'history_downloads_' map and inform observers.
827 void DownloadManager::OnDownloadItemAddedToPersistentStore(int32 download_id, 808 void DownloadManager::OnDownloadItemAddedToPersistentStore(int32 download_id,
828 int64 db_handle) { 809 int64 db_handle) {
829 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 810 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
830 DownloadItem* download = GetActiveDownloadItem(download_id); 811 DownloadItem* download = GetActiveDownloadItem(download_id);
831 if (!download) 812 if (!download) {
813 // The download was cancelled while the persistent store was entering it.
814 // We resolve this race by turning around and deleting it in the
815 // persistent store (implicitly treating it as a failure in download
816 // initiation, which is appropriate as the only places the cancel could
817 // have come from were in resolving issues (like the file name) which
818 // we need to have resolved for persistent store insertion).
819
820 // Make sure we haven't already been shutdown (the callback raced
821 // with shutdown), as that would mean that we no longer have access
822 // to the persistent store. In that case, the history will be cleaned up
823 // on next persistent store query.
824 if (shutdown_needed_)
825 delegate_->RemoveItemFromPersistentStore(db_handle);
832 return; 826 return;
827 }
833 828
834 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle 829 VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle
835 << " download_id = " << download_id 830 << " download_id = " << download_id
836 << " download = " << download->DebugString(true); 831 << " download = " << download->DebugString(true);
837 832
838 // TODO(rdsmith): Remove after http://crbug.com/85408 resolved. 833 // TODO(rdsmith): Remove after http://crbug.com/85408 resolved.
839 int64 largest_handle = largest_db_handle_in_history_; 834 int64 largest_handle = largest_db_handle_in_history_;
840 base::debug::Alias(&largest_handle); 835 base::debug::Alias(&largest_handle);
841 CHECK(!ContainsKey(history_downloads_, db_handle)); 836 CHECK(!ContainsKey(history_downloads_, db_handle));
842 837
838 CHECK(download->IsInProgress());
843 AddDownloadItemToHistory(download, db_handle); 839 AddDownloadItemToHistory(download, db_handle);
844 840
845 // If the download is still in progress, try to complete it. 841 MaybeCompleteDownload(download);
846 //
847 // Otherwise, download has been cancelled or interrupted before we've
848 // received the DB handle. We post one final message to the history
849 // service so that it can be properly in sync with the DownloadItem's
850 // completion status, and also inform any observers so that they get
851 // more than just the start notification.
852 if (download->IsInProgress()) {
853 MaybeCompleteDownload(download);
854 } else {
855 // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/84508
856 // is fixed.
857 CHECK(download->IsCancelled())
858 << " download = " << download->DebugString(true);
859 in_progress_.erase(download_id);
860 active_downloads_.erase(download_id);
861 delegate_->UpdateItemInPersistentStore(download);
862 download->UpdateObservers();
863 }
864 } 842 }
865 843
866 void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) { 844 void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) {
867 // The 'contents' may no longer exist if the user closed the tab before we 845 // The 'contents' may no longer exist if the user closed the tab before we
868 // get this start completion event. 846 // get this start completion event.
869 DownloadRequestHandle request_handle = download->request_handle(); 847 DownloadRequestHandle request_handle = download->request_handle();
870 TabContents* content = request_handle.GetTabContents(); 848 TabContents* content = request_handle.GetTabContents();
871 849
872 // If the contents no longer exists, we ask the embedder to suggest another 850 // If the contents no longer exists, we ask the embedder to suggest another
873 // tab. 851 // tab.
(...skipping 18 matching lines...) Expand all
892 // not its id, so we have to iterate. 870 // not its id, so we have to iterate.
893 for (DownloadMap::iterator it = history_downloads_.begin(); 871 for (DownloadMap::iterator it = history_downloads_.begin();
894 it != history_downloads_.end(); ++it) { 872 it != history_downloads_.end(); ++it) {
895 DownloadItem* item = it->second; 873 DownloadItem* item = it->second;
896 if (item->id() == download_id) 874 if (item->id() == download_id)
897 return item; 875 return item;
898 } 876 }
899 return NULL; 877 return NULL;
900 } 878 }
901 879
880 void DownloadManager::GetInProgressDownloads(
881 std::vector<DownloadItem*>* result) {
882 DCHECK(result);
883
884 for (DownloadMap::iterator it = active_downloads_.begin();
885 it != active_downloads_.end(); ++it) {
886 result->push_back(it->second);
887 }
888 }
889
902 DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) { 890 DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) {
903 DCHECK(ContainsKey(active_downloads_, download_id)); 891 DCHECK(ContainsKey(active_downloads_, download_id));
904 DownloadItem* download = active_downloads_[download_id]; 892 DownloadItem* download = active_downloads_[download_id];
905 DCHECK(download != NULL); 893 DCHECK(download != NULL);
906 return download; 894 return download;
907 } 895 }
908 896
909 // Confirm that everything in all maps is also in |downloads_|, and that 897 // Confirm that everything in all maps is also in |downloads_|, and that
910 // everything in |downloads_| is also in some other map. 898 // everything in |downloads_| is also in some other map.
911 void DownloadManager::AssertContainersConsistent() const { 899 void DownloadManager::AssertContainersConsistent() const {
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1009 DCHECK(ContainsKey(save_page_downloads_, download->id())); 997 DCHECK(ContainsKey(save_page_downloads_, download->id()));
1010 save_page_downloads_.erase(download->id()); 998 save_page_downloads_.erase(download->id());
1011 999
1012 if (download->IsComplete()) 1000 if (download->IsComplete())
1013 NotificationService::current()->Notify( 1001 NotificationService::current()->Notify(
1014 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED, 1002 content::NOTIFICATION_SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
1015 Source<DownloadManager>(this), 1003 Source<DownloadManager>(this),
1016 Details<DownloadItem>(download)); 1004 Details<DownloadItem>(download));
1017 } 1005 }
1018 } 1006 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698