Chromium Code Reviews| 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 |