OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |