| Index: chrome/browser/download/download_manager.cc
|
| diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc
|
| index 10ac74e7b06aeef486bf84de64defb6bde68d892..52af7502fafdb556bd23e26ba655e27a1b810cbb 100644
|
| --- a/chrome/browser/download/download_manager.cc
|
| +++ b/chrome/browser/download/download_manager.cc
|
| @@ -23,6 +23,7 @@
|
| #include "chrome/browser/download/download_history.h"
|
| #include "chrome/browser/download/download_item.h"
|
| #include "chrome/browser/download/download_prefs.h"
|
| +#include "chrome/browser/download/download_query.h"
|
| #include "chrome/browser/download/download_request_handle.h"
|
| #include "chrome/browser/download/download_safe_browsing_client.h"
|
| #include "chrome/browser/download/download_status_updater.h"
|
| @@ -84,49 +85,18 @@ void DownloadManager::Shutdown() {
|
|
|
| AssertContainersConsistent();
|
|
|
| - // Go through all downloads in downloads_. Dangerous ones we need to
|
| - // remove on disk, and in progress ones we need to cancel.
|
| - for (DownloadSet::iterator it = downloads_.begin(); it != downloads_.end();) {
|
| - DownloadItem* download = *it;
|
| -
|
| - // Save iterator from potential erases in this set done by called code.
|
| - // Iterators after an erasure point are still valid for lists and
|
| - // associative containers such as sets.
|
| - it++;
|
| -
|
| + for (DownloadMap::iterator it = downloads_.begin(); it != downloads_.end();) {
|
| + DownloadItem* download = it->second;
|
| + ++it;
|
| if (download->safety_state() == DownloadItem::DANGEROUS &&
|
| download->IsPartialDownload()) {
|
| - // The user hasn't accepted it, so we need to remove it
|
| - // from the disk. This may or may not result in it being
|
| - // removed from the DownloadManager queues and deleted
|
| - // (specifically, DownloadManager::RemoveDownload only
|
| - // removes and deletes it if it's known to the history service)
|
| - // so the only thing we know after calling this function is that
|
| - // the download was deleted if-and-only-if it was removed
|
| - // from all queues.
|
| download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN);
|
| } else if (download->IsPartialDownload()) {
|
| download->Cancel(false);
|
| download_history_->UpdateEntry(download);
|
| }
|
| }
|
| -
|
| - // At this point, all dangerous downloads have had their files removed
|
| - // and all in progress downloads have been cancelled. We can now delete
|
| - // anything left.
|
| -
|
| - // Copy downloads_ to separate container so as not to set off checks
|
| - // in DownloadItem destruction.
|
| - DownloadSet downloads_to_delete;
|
| - downloads_to_delete.swap(downloads_);
|
| -
|
| - in_progress_.clear();
|
| - active_downloads_.clear();
|
| - history_downloads_.clear();
|
| -#if !defined(NDEBUG)
|
| - save_page_as_downloads_.clear();
|
| -#endif
|
| - STLDeleteElements(&downloads_to_delete);
|
| + STLValueDeleter<DownloadMap> delete_items(&downloads_);
|
|
|
| file_manager_ = NULL;
|
|
|
| @@ -137,90 +107,6 @@ void DownloadManager::Shutdown() {
|
|
|
| download_history_.reset();
|
| download_prefs_.reset();
|
| -
|
| - shutdown_needed_ = false;
|
| -}
|
| -
|
| -void DownloadManager::GetTemporaryDownloads(
|
| - const FilePath& dir_path, std::vector<DownloadItem*>* result) {
|
| - DCHECK(result);
|
| -
|
| - for (DownloadMap::iterator it = history_downloads_.begin();
|
| - it != history_downloads_.end(); ++it) {
|
| - if (it->second->is_temporary() &&
|
| - it->second->full_path().DirName() == dir_path)
|
| - result->push_back(it->second);
|
| - }
|
| -}
|
| -
|
| -void DownloadManager::GetAllDownloads(
|
| - const FilePath& dir_path, std::vector<DownloadItem*>* result) {
|
| - DCHECK(result);
|
| -
|
| - for (DownloadMap::iterator it = history_downloads_.begin();
|
| - it != history_downloads_.end(); ++it) {
|
| - if (!it->second->is_temporary() &&
|
| - (dir_path.empty() || it->second->full_path().DirName() == dir_path))
|
| - result->push_back(it->second);
|
| - }
|
| -}
|
| -
|
| -void DownloadManager::GetCurrentDownloads(
|
| - const FilePath& dir_path, std::vector<DownloadItem*>* result) {
|
| - DCHECK(result);
|
| -
|
| - for (DownloadMap::iterator it = history_downloads_.begin();
|
| - it != history_downloads_.end(); ++it) {
|
| - DownloadItem* item =it->second;
|
| - // Skip temporary items.
|
| - if (item->is_temporary())
|
| - continue;
|
| - // Skip items that have all their data, and are OK to save.
|
| - if (!item->IsPartialDownload() &&
|
| - (item->safety_state() != DownloadItem::DANGEROUS))
|
| - continue;
|
| - // Skip items that don't match |dir_path|.
|
| - // If |dir_path| is empty, all remaining items match.
|
| - if (!dir_path.empty() && (it->second->full_path().DirName() != dir_path))
|
| - continue;
|
| -
|
| - result->push_back(item);
|
| - }
|
| -
|
| - // If we have a parent profile, let it add its downloads to the results.
|
| - Profile* original_profile = profile_->GetOriginalProfile();
|
| - if (original_profile != profile_)
|
| - original_profile->GetDownloadManager()->GetCurrentDownloads(dir_path,
|
| - result);
|
| -}
|
| -
|
| -void DownloadManager::SearchDownloads(const string16& query,
|
| - std::vector<DownloadItem*>* result) {
|
| - DCHECK(result);
|
| -
|
| - string16 query_lower(base::i18n::ToLower(query));
|
| -
|
| - for (DownloadMap::iterator it = history_downloads_.begin();
|
| - it != history_downloads_.end(); ++it) {
|
| - DownloadItem* download_item = it->second;
|
| -
|
| - if (download_item->is_temporary() || download_item->is_extension_install())
|
| - continue;
|
| -
|
| - // Display Incognito downloads only in Incognito window, and vice versa.
|
| - // The Incognito Downloads page will get the list of non-Incognito downloads
|
| - // from its parent profile.
|
| - if (profile_->IsOffTheRecord() != download_item->is_otr())
|
| - continue;
|
| -
|
| - if (download_item->MatchesQuery(query_lower))
|
| - result->push_back(download_item);
|
| - }
|
| -
|
| - // If we have a parent profile, let it add its downloads to the results.
|
| - Profile* original_profile = profile_->GetOriginalProfile();
|
| - if (original_profile != profile_)
|
| - original_profile->GetDownloadManager()->SearchDownloads(query, result);
|
| }
|
|
|
| // Query the history service for information about all persisted downloads.
|
| @@ -263,6 +149,7 @@ void DownloadManager::StartDownload(int32 download_id) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
|
|
| DownloadItem* download = GetActiveDownloadItem(download_id);
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download;
|
| if (!download)
|
| return;
|
|
|
| @@ -276,8 +163,9 @@ void DownloadManager::StartDownload(int32 download_id) {
|
|
|
| void DownloadManager::CheckForHistoryFilesRemoval() {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - for (DownloadMap::iterator it = history_downloads_.begin();
|
| - it != history_downloads_.end(); ++it) {
|
| + DVLOG(1) << __PRETTY_FUNCTION__;
|
| + for (DownloadMap::iterator it = downloads_.begin();
|
| + it != downloads_.end(); ++it) {
|
| CheckForFileRemoval(it->second);
|
| }
|
| }
|
| @@ -286,31 +174,35 @@ void DownloadManager::CheckForFileRemoval(DownloadItem* download_item) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| if (download_item->IsComplete() &&
|
| !download_item->file_externally_removed()) {
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << download_item->id();
|
| BrowserThread::PostTask(
|
| BrowserThread::FILE, FROM_HERE,
|
| NewRunnableMethod(this,
|
| &DownloadManager::CheckForFileRemovalOnFileThread,
|
| - download_item->db_handle(),
|
| + download_item->id(),
|
| download_item->GetTargetFilePath()));
|
| }
|
| }
|
|
|
| void DownloadManager::CheckForFileRemovalOnFileThread(
|
| - int64 db_handle, const FilePath& path) {
|
| + int64 id, const FilePath& path) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| if (!file_util::PathExists(path)) {
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << id;
|
| BrowserThread::PostTask(
|
| BrowserThread::UI, FROM_HERE,
|
| NewRunnableMethod(this,
|
| &DownloadManager::OnFileRemovalDetected,
|
| - db_handle));
|
| + id));
|
| }
|
| }
|
|
|
| -void DownloadManager::OnFileRemovalDetected(int64 db_handle) {
|
| +void DownloadManager::OnFileRemovalDetected(int64 id) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DownloadMap::iterator it = history_downloads_.find(db_handle);
|
| - if (it != history_downloads_.end()) {
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << id;
|
| + DownloadMap::iterator it = downloads_.find(id);
|
| + if (it != downloads_.end()) {
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << id;
|
| DownloadItem* download_item = it->second;
|
| download_item->OnDownloadedFileRemoved();
|
| }
|
| @@ -321,6 +213,8 @@ void DownloadManager::CheckDownloadUrlDone(int32 download_id,
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
|
|
| DownloadItem* download = GetActiveDownloadItem(download_id);
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " "
|
| + << is_dangerous_url << " " << download;
|
| if (!download)
|
| return;
|
|
|
| @@ -338,6 +232,7 @@ void DownloadManager::CheckVisitedReferrerBeforeDone(
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
|
|
| DownloadItem* download = GetActiveDownloadItem(download_id);
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download;
|
| if (!download)
|
| return;
|
|
|
| @@ -414,6 +309,7 @@ void DownloadManager::CheckIfSuggestedPathExists(int32 download_id,
|
| DownloadStateInfo state,
|
| const FilePath& default_path) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id;
|
|
|
| // Make sure the default download directory exists.
|
| // TODO(phajdan.jr): only create the directory when we're sure the user
|
| @@ -504,6 +400,7 @@ void DownloadManager::OnPathExistenceAvailable(
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
|
|
| DownloadItem* download = GetActiveDownloadItem(download_id);
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download << " " << download_id;
|
| if (!download)
|
| return;
|
|
|
| @@ -554,11 +451,11 @@ void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info) {
|
|
|
| DownloadItem* download = new DownloadItem(this, *info,
|
| profile_->IsOffTheRecord());
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << info->download_id << " "
|
| + << download;
|
| int32 download_id = info->download_id;
|
| - DCHECK(!ContainsKey(in_progress_, download_id));
|
| - DCHECK(!ContainsKey(active_downloads_, download_id));
|
| - downloads_.insert(download);
|
| - active_downloads_[download_id] = download;
|
| + DCHECK(!ContainsKey(downloads_, download_id));
|
| + downloads_[download_id] = download;
|
| }
|
|
|
| void DownloadManager::ContinueDownloadWithPath(DownloadItem* download,
|
| @@ -567,12 +464,8 @@ void DownloadManager::ContinueDownloadWithPath(DownloadItem* download,
|
| DCHECK(download);
|
|
|
| int32 download_id = download->id();
|
| -
|
| - // NOTE(ahendrickson) Eventually |active_downloads_| will replace
|
| - // |in_progress_|, but we don't want to change the semantics yet.
|
| - DCHECK(!ContainsKey(in_progress_, download_id));
|
| - DCHECK(ContainsKey(downloads_, download));
|
| - DCHECK(ContainsKey(active_downloads_, download_id));
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download
|
| + << " " << chosen_file.value();
|
|
|
| // Make sure the initial file name is set only once.
|
| DCHECK(download->full_path().empty());
|
| @@ -582,8 +475,7 @@ void DownloadManager::ContinueDownloadWithPath(DownloadItem* download,
|
| VLOG(20) << __FUNCTION__ << "()"
|
| << " download = " << download->DebugString(true);
|
|
|
| - in_progress_[download_id] = download;
|
| - UpdateAppIcon(); // Reflect entry into in_progress_.
|
| + UpdateAppIcon(); // Reflect entry into .
|
|
|
| // Rename to intermediate name.
|
| FilePath download_path;
|
| @@ -616,8 +508,8 @@ void DownloadManager::ContinueDownloadWithPath(DownloadItem* download,
|
|
|
| void DownloadManager::UpdateDownload(int32 download_id, int64 size) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DownloadMap::iterator it = active_downloads_.find(download_id);
|
| - if (it != active_downloads_.end()) {
|
| + DownloadMap::iterator it = downloads_.find(download_id);
|
| + if (it != downloads_.end()) {
|
| DownloadItem* download = it->second;
|
| if (download->IsInProgress()) {
|
| download->Update(size);
|
| @@ -648,15 +540,15 @@ void DownloadManager::OnAllDataSaved(int32 download_id,
|
| int64 size,
|
| const std::string& hash) {
|
| VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
|
| - << " size = " << size;
|
| + << " size = " << size << " occam " << downloads_.count(download_id);
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
|
|
| - // If it's not in active_downloads_, that means it was cancelled; just
|
| - // ignore the notification.
|
| - if (active_downloads_.count(download_id) == 0)
|
| + DownloadItem* download = downloads_[download_id];
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << size << " "
|
| + << hash << " " << download;
|
| + if (!download) {
|
| return;
|
| -
|
| - DownloadItem* download = active_downloads_[download_id];
|
| + }
|
| download->OnAllDataSaved(size);
|
|
|
| // When hash is not available, it means either it is not calculated
|
| @@ -681,48 +573,14 @@ void DownloadManager::CheckDownloadHashDone(int32 download_id,
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| DVLOG(1) << "CheckDownloadHashDone, download_id: " << download_id
|
| << " is dangerous_hash: " << is_dangerous_hash;
|
| -
|
| - // If it's not in active_downloads_, that means it was cancelled or
|
| - // the download already finished.
|
| - if (active_downloads_.count(download_id) == 0)
|
| - return;
|
| -
|
| - DVLOG(1) << "CheckDownloadHashDone, url: "
|
| - << active_downloads_[download_id]->GetURL().spec();
|
| }
|
|
|
| void DownloadManager::AssertQueueStateConsistent(DownloadItem* download) {
|
| - // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
|
| - if (download->state() == DownloadItem::REMOVING) {
|
| - CHECK(!ContainsKey(downloads_, download));
|
| - CHECK(!ContainsKey(active_downloads_, download->id()));
|
| - CHECK(!ContainsKey(in_progress_, download->id()));
|
| - CHECK(!ContainsKey(history_downloads_, download->db_handle()));
|
| - return;
|
| - }
|
| -
|
| - // Should be in downloads_ if we're not REMOVING.
|
| - CHECK(ContainsKey(downloads_, download));
|
| -
|
| - // Check history_downloads_ consistency.
|
| - if (download->db_handle() != DownloadHistory::kUninitializedHandle) {
|
| - CHECK(ContainsKey(history_downloads_, download->db_handle()));
|
| - } else {
|
| - // TODO(rdsmith): Somewhat painful; make sure to disable in
|
| - // release builds after resolution of http://crbug.com/85408.
|
| - for (DownloadMap::iterator it = history_downloads_.begin();
|
| - it != history_downloads_.end(); ++it) {
|
| - CHECK(it->second != download);
|
| - }
|
| - }
|
| -
|
| - CHECK(ContainsKey(active_downloads_, download->id()) ==
|
| - (download->state() == DownloadItem::IN_PROGRESS));
|
| - CHECK(ContainsKey(in_progress_, download->id()) ==
|
| - (download->state() == DownloadItem::IN_PROGRESS));
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download;
|
| }
|
|
|
| bool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) {
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download << " " << download->id();
|
| // If we don't have all the data, the download is not ready for
|
| // completion.
|
| if (!download->all_data_saved())
|
| @@ -733,17 +591,6 @@ bool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) {
|
| if (download->safety_state() == DownloadItem::DANGEROUS)
|
| return false;
|
|
|
| - // If the download isn't active (e.g. has been cancelled) it's not
|
| - // ready for completion.
|
| - if (active_downloads_.count(download->id()) == 0)
|
| - return false;
|
| -
|
| - // If the download hasn't been inserted into the history system
|
| - // (which occurs strictly after file name determination, intermediate
|
| - // file rename, and UI display) then it's not ready for completion.
|
| - if (download->db_handle() == DownloadHistory::kUninitializedHandle)
|
| - return false;
|
| -
|
| return true;
|
| }
|
|
|
| @@ -760,19 +607,14 @@ void DownloadManager::MaybeCompleteDownload(DownloadItem* download) {
|
| // transition on the DownloadItem.
|
|
|
| // Confirm we're in the proper set of states to be here;
|
| - // in in_progress_, have all data, have a history handle, (validated or safe).
|
| + // in , have all data, have a history handle, (validated or safe).
|
| DCHECK_NE(DownloadItem::DANGEROUS, download->safety_state());
|
| - DCHECK_EQ(1u, in_progress_.count(download->id()));
|
| DCHECK(download->all_data_saved());
|
| - DCHECK(download->db_handle() != DownloadHistory::kUninitializedHandle);
|
| - DCHECK_EQ(1u, history_downloads_.count(download->db_handle()));
|
|
|
| VLOG(20) << __FUNCTION__ << "()" << " executing: download = "
|
| << download->DebugString(false);
|
|
|
| - // Remove the id from in_progress
|
| - in_progress_.erase(download->id());
|
| - UpdateAppIcon(); // Reflect removal from in_progress_.
|
| + UpdateAppIcon(); // Reflect removal from .
|
|
|
| download_history_->UpdateEntry(download);
|
|
|
| @@ -785,7 +627,6 @@ void DownloadManager::DownloadCompleted(int32 download_id) {
|
| DownloadItem* download = GetDownloadItem(download_id);
|
| DCHECK(download);
|
| download_history_->UpdateEntry(download);
|
| - active_downloads_.erase(download_id);
|
| }
|
|
|
| void DownloadManager::OnDownloadRenamedToFinalName(int download_id,
|
| @@ -818,23 +659,12 @@ void DownloadManager::OnDownloadRenamedToFinalName(int download_id,
|
|
|
| void DownloadManager::DownloadCancelled(int32 download_id) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DownloadMap::iterator it = in_progress_.find(download_id);
|
| - if (it == in_progress_.end())
|
| - return;
|
| - DownloadItem* download = it->second;
|
| -
|
| - VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
|
| - << " download = " << download->DebugString(true);
|
| -
|
| - // Clean up will happen when the history system create callback runs if we
|
| - // don't have a valid db_handle yet.
|
| - if (download->db_handle() != DownloadHistory::kUninitializedHandle) {
|
| - in_progress_.erase(it);
|
| - active_downloads_.erase(download_id);
|
| - UpdateAppIcon(); // Reflect removal from in_progress_.
|
| - download_history_->UpdateEntry(download);
|
| - }
|
| -
|
| + DownloadItem* download = downloads_[download_id];
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download
|
| + << " " << (download ? download->DebugString(true) : "");
|
| + DCHECK(download);
|
| + UpdateAppIcon(); // Reflect removal from .
|
| + download_history_->UpdateEntry(download);
|
| DownloadCancelledInternal(download_id, download->request_handle());
|
| }
|
|
|
| @@ -853,32 +683,13 @@ void DownloadManager::OnDownloadError(int32 download_id,
|
| int64 size,
|
| int os_error) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| - DownloadMap::iterator it = active_downloads_.find(download_id);
|
| - // A cancel at the right time could remove the download from the
|
| - // |active_downloads_| map before we get here.
|
| - if (it == active_downloads_.end())
|
| - return;
|
| -
|
| - DownloadItem* download = it->second;
|
| -
|
| - VLOG(20) << __FUNCTION__ << "()" << " Error " << os_error
|
| - << " at offset " << download->received_bytes()
|
| - << " for download = " << download->DebugString(true);
|
| -
|
| + DownloadItem* download = downloads_[download_id];
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download
|
| + << " " << (download ? download->DebugString(true) : "");
|
| + DCHECK(download);
|
| download->Interrupted(size, os_error);
|
| -
|
| - // TODO(ahendrickson) - Remove this when we add resuming of interrupted
|
| - // downloads, as we will keep the download item around in that case.
|
| - //
|
| - // Clean up will happen when the history system create callback runs if we
|
| - // don't have a valid db_handle yet.
|
| - if (download->db_handle() != DownloadHistory::kUninitializedHandle) {
|
| - in_progress_.erase(download_id);
|
| - active_downloads_.erase(download_id);
|
| - UpdateAppIcon(); // Reflect removal from in_progress_.
|
| - download_history_->UpdateEntry(download);
|
| - }
|
| -
|
| + UpdateAppIcon(); // Reflect removal from .
|
| + download_history_->UpdateEntry(download);
|
| BrowserThread::PostTask(
|
| BrowserThread::FILE, FROM_HERE,
|
| NewRunnableMethod(
|
| @@ -890,35 +701,123 @@ void DownloadManager::UpdateAppIcon() {
|
| status_updater_->Update();
|
| }
|
|
|
| -void DownloadManager::RemoveDownload(int64 download_handle) {
|
| - DownloadMap::iterator it = history_downloads_.find(download_handle);
|
| - if (it == history_downloads_.end())
|
| +void DownloadManager::RemoveDownload(int64 id) {
|
| + DownloadMap::iterator it = downloads_.find(id);
|
| + scoped_ptr<DownloadItem> download(it->second);
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << id << " " << download.get();
|
| + if (download.get() == NULL) {
|
| return;
|
| + }
|
| + download_history_->RemoveEntry(download.get());
|
| + downloads_.erase(it);
|
| + NotifyModelChanged();
|
| +}
|
|
|
| - // Make history update.
|
| - DownloadItem* download = it->second;
|
| - download_history_->RemoveEntry(download);
|
| +void DownloadManager::GetTemporaryDownloads(
|
| + const FilePath& dir_path, std::vector<DownloadItem*>* result) {
|
| + DCHECK(result);
|
|
|
| - // Remove from our tables and delete.
|
| - history_downloads_.erase(it);
|
| - int downloads_count = downloads_.erase(download);
|
| - DCHECK_EQ(1, downloads_count);
|
| + for (DownloadMap::iterator it = downloads_.begin();
|
| + it != downloads_.end(); ++it) {
|
| + if (it->second->is_temporary() &&
|
| + it->second->full_path().DirName() == dir_path)
|
| + result->push_back(it->second);
|
| + }
|
| +}
|
|
|
| - // Tell observers to refresh their views.
|
| - NotifyModelChanged();
|
| +void DownloadManager::GetAllDownloads(
|
| + const FilePath& dir_path, std::vector<DownloadItem*>* result) {
|
| + DCHECK(result);
|
| +
|
| + for (DownloadMap::iterator it = downloads_.begin();
|
| + it != downloads_.end(); ++it) {
|
| + if (!it->second->is_temporary() &&
|
| + (dir_path.empty() || it->second->full_path().DirName() == dir_path))
|
| + result->push_back(it->second);
|
| + }
|
| +}
|
| +
|
| +void DownloadManager::GetCurrentDownloads(
|
| + const FilePath& dir_path, std::vector<DownloadItem*>* result) {
|
| + DCHECK(result);
|
| +
|
| + for (DownloadMap::iterator it = downloads_.begin();
|
| + it != downloads_.end(); ++it) {
|
| + DownloadItem* item =it->second;
|
| + // Skip temporary items.
|
| + if (item->is_temporary())
|
| + continue;
|
| + // Skip items that have all their data, and are OK to save.
|
| + if (!item->IsPartialDownload() &&
|
| + (item->safety_state() != DownloadItem::DANGEROUS))
|
| + continue;
|
| + // Skip items that don't match |dir_path|.
|
| + // If |dir_path| is empty, all remaining items match.
|
| + if (!dir_path.empty() && (it->second->full_path().DirName() != dir_path))
|
| + continue;
|
| +
|
| + result->push_back(item);
|
| + }
|
| +
|
| + // If we have a parent profile, let it add its downloads to the results.
|
| + Profile* original_profile = profile_->GetOriginalProfile();
|
| + if (original_profile != profile_)
|
| + original_profile->GetDownloadManager()->GetCurrentDownloads(dir_path,
|
| + result);
|
| +}
|
|
|
| - delete download;
|
| +bool DownloadManager::Search(const download_util::DownloadQuery& query,
|
| + std::vector<DownloadItem*>* items,
|
| + std::string* error_msg,
|
| + ListValue* json_results) const {
|
| + std::vector<DownloadItem*> default_items;
|
| + if (items == NULL) {
|
| + items = &default_items;
|
| + }
|
| + for (DownloadMap::const_iterator it = downloads_.begin();
|
| + it != downloads_.end(); ++it) {
|
| + items->push_back(it->second);
|
| + }
|
| + return query.Search(items, error_msg, json_results);
|
| +}
|
| +
|
| +void DownloadManager::SearchDownloads(const string16& query,
|
| + std::vector<DownloadItem*>* result) {
|
| + DCHECK(result);
|
| +
|
| + string16 query_lower(base::i18n::ToLower(query));
|
| +
|
| + for (DownloadMap::iterator it = downloads_.begin();
|
| + it != downloads_.end(); ++it) {
|
| + DownloadItem* download_item = it->second;
|
| +
|
| + if (download_item->is_temporary() || download_item->is_extension_install())
|
| + continue;
|
| +
|
| + // Display Incognito downloads only in Incognito window, and vice versa.
|
| + // The Incognito Downloads page will get the list of non-Incognito downloads
|
| + // from its parent profile.
|
| + if (profile_->IsOffTheRecord() != download_item->is_otr())
|
| + continue;
|
| +
|
| + if (download_item->MatchesQuery(query_lower))
|
| + result->push_back(download_item);
|
| + }
|
| +
|
| + // If we have a parent profile, let it add its downloads to the results.
|
| + Profile* original_profile = profile_->GetOriginalProfile();
|
| + if (original_profile != profile_)
|
| + original_profile->GetDownloadManager()->SearchDownloads(query, result);
|
| }
|
|
|
| int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin,
|
| const base::Time remove_end) {
|
| download_history_->RemoveEntriesBetween(remove_begin, remove_end);
|
| -
|
| - // All downloads visible to the user will be in the history,
|
| - // so scan that map.
|
| - DownloadMap::iterator it = history_downloads_.begin();
|
| std::vector<DownloadItem*> pending_deletes;
|
| - while (it != history_downloads_.end()) {
|
| + STLElementDeleter<std::vector<DownloadItem*> >
|
| + delete_pending_deletes(&pending_deletes);
|
| + for (DownloadMap::iterator it = downloads_.begin();
|
| + it != downloads_.end();) {
|
| DownloadItem* download = it->second;
|
| if (download->start_time() >= remove_begin &&
|
| (remove_end.is_null() || download->start_time() < remove_end) &&
|
| @@ -926,38 +825,17 @@ int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin,
|
| download->IsCancelled() ||
|
| download->IsInterrupted())) {
|
| AssertQueueStateConsistent(download);
|
| -
|
| - // Remove from the map and move to the next in the list.
|
| - history_downloads_.erase(it++);
|
| -
|
| - // Also remove it from any completed dangerous downloads.
|
| + downloads_.erase(it++);
|
| pending_deletes.push_back(download);
|
| -
|
| - continue;
|
| + } else {
|
| + ++it;
|
| }
|
| -
|
| - ++it;
|
| }
|
| -
|
| - // If we aren't deleting anything, we're done.
|
| - if (pending_deletes.empty())
|
| + if (pending_deletes.empty()) {
|
| return 0;
|
| -
|
| - // Remove the chosen downloads from the main owning container.
|
| - for (std::vector<DownloadItem*>::iterator it = pending_deletes.begin();
|
| - it != pending_deletes.end(); it++) {
|
| - downloads_.erase(*it);
|
| }
|
| -
|
| - // Tell observers to refresh their views.
|
| NotifyModelChanged();
|
| -
|
| - // Delete the download items themselves.
|
| int num_deleted = static_cast<int>(pending_deletes.size());
|
| -
|
| - STLDeleteContainerPointers(pending_deletes.begin(), pending_deletes.end());
|
| - pending_deletes.clear();
|
| -
|
| return num_deleted;
|
| }
|
|
|
| @@ -979,7 +857,7 @@ void DownloadManager::SavePageAsDownloadStarted(DownloadItem* download_item) {
|
| #if !defined(NDEBUG)
|
| save_page_as_downloads_.insert(download_item);
|
| #endif
|
| - downloads_.insert(download_item);
|
| + downloads_[download_item->id()] = download_item;
|
| }
|
|
|
| // Initiate a download of a specific URL. We send the request to the
|
| @@ -1035,8 +913,8 @@ bool DownloadManager::ShouldOpenFileBasedOnExtension(
|
| }
|
|
|
| bool DownloadManager::IsDownloadProgressKnown() {
|
| - for (DownloadMap::iterator i = in_progress_.begin();
|
| - i != in_progress_.end(); ++i) {
|
| + for (DownloadMap::iterator i = downloads_.begin();
|
| + i != downloads_.end(); ++i) {
|
| if (i->second->total_bytes() <= 0)
|
| return false;
|
| }
|
| @@ -1045,14 +923,14 @@ bool DownloadManager::IsDownloadProgressKnown() {
|
| }
|
|
|
| int64 DownloadManager::GetInProgressDownloadCount() {
|
| - return in_progress_.size();
|
| + return downloads_.size();
|
| }
|
|
|
| int64 DownloadManager::GetReceivedDownloadBytes() {
|
| DCHECK(IsDownloadProgressKnown());
|
| int64 received_bytes = 0;
|
| - for (DownloadMap::iterator i = in_progress_.begin();
|
| - i != in_progress_.end(); ++i) {
|
| + for (DownloadMap::iterator i = downloads_.begin();
|
| + i != downloads_.end(); ++i) {
|
| received_bytes += i->second->received_bytes();
|
| }
|
| return received_bytes;
|
| @@ -1061,8 +939,8 @@ int64 DownloadManager::GetReceivedDownloadBytes() {
|
| int64 DownloadManager::GetTotalDownloadBytes() {
|
| DCHECK(IsDownloadProgressKnown());
|
| int64 total_bytes = 0;
|
| - for (DownloadMap::iterator i = in_progress_.begin();
|
| - i != in_progress_.end(); ++i) {
|
| + for (DownloadMap::iterator i = downloads_.begin();
|
| + i != downloads_.end(); ++i) {
|
| total_bytes += i->second->total_bytes();
|
| }
|
| return total_bytes;
|
| @@ -1151,13 +1029,12 @@ void DownloadManager::DangerousDownloadValidated(DownloadItem* download) {
|
| // 'DownloadHistoryInfo's in sorted order (by ascending start_time).
|
| void DownloadManager::OnQueryDownloadEntriesComplete(
|
| std::vector<DownloadHistoryInfo>* entries) {
|
| - for (size_t i = 0; i < entries->size(); ++i) {
|
| - DownloadItem* download = new DownloadItem(this, entries->at(i));
|
| - DCHECK(!ContainsKey(history_downloads_, download->db_handle()));
|
| - downloads_.insert(download);
|
| - history_downloads_[download->db_handle()] = download;
|
| - VLOG(20) << __FUNCTION__ << "()" << i << ">"
|
| - << " download = " << download->DebugString(true);
|
| + for (std::vector<DownloadHistoryInfo>::iterator it = entries->begin();
|
| + it != entries->end(); ++it) {
|
| + DownloadItem* download = new DownloadItem(this, *it);
|
| + DVLOG(2) << __PRETTY_FUNCTION__ << " " << download->id() << " " << download;
|
| + DCHECK(!ContainsKey(downloads_, download->id()));
|
| + downloads_[download->id()] = download;
|
| }
|
| NotifyModelChanged();
|
| CheckForHistoryFilesRemoval();
|
| @@ -1170,6 +1047,8 @@ void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id,
|
| int64 db_handle) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| DownloadItem* download = GetActiveDownloadItem(download_id);
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << db_handle
|
| + << " " << download;
|
| if (!download)
|
| return;
|
|
|
| @@ -1177,24 +1056,6 @@ void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id,
|
| << " download_id = " << download_id
|
| << " download = " << download->DebugString(true);
|
|
|
| - // It's not immediately obvious, but HistoryBackend::CreateDownload() can
|
| - // call this function with an invalid |db_handle|. For instance, this can
|
| - // happen when the history database is offline. We cannot have multiple
|
| - // DownloadItems with the same invalid db_handle, so we need to assign a
|
| - // unique |db_handle| here.
|
| - if (db_handle == DownloadHistory::kUninitializedHandle)
|
| - db_handle = download_history_->GetNextFakeDbHandle();
|
| -
|
| - // TODO(rdsmith): Convert to DCHECK() when http://crbug.com/84508
|
| - // is fixed.
|
| - CHECK_NE(DownloadHistory::kUninitializedHandle, db_handle);
|
| -
|
| - DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle);
|
| - download->set_db_handle(db_handle);
|
| -
|
| - DCHECK(!ContainsKey(history_downloads_, download->db_handle()));
|
| - history_downloads_[download->db_handle()] = download;
|
| -
|
| // Show in the appropriate browser UI.
|
| // This includes buttons to save or cancel, for a dangerous download.
|
| ShowDownloadInBrowser(download);
|
| @@ -1212,16 +1073,13 @@ void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id,
|
| if (download->IsInProgress()) {
|
| MaybeCompleteDownload(download);
|
| } else {
|
| - DCHECK(download->IsCancelled())
|
| - << " download = " << download->DebugString(true);
|
| - in_progress_.erase(download_id);
|
| - active_downloads_.erase(download_id);
|
| download_history_->UpdateEntry(download);
|
| download->UpdateObservers();
|
| }
|
| }
|
|
|
| void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) {
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download << " " << download->id();
|
|
|
| // The 'contents' may no longer exist if the user closed the tab before we
|
| // get this start completion event. If it does, tell the origin TabContents
|
| @@ -1257,67 +1115,18 @@ void DownloadManager::NotifyModelChanged() {
|
| }
|
|
|
| DownloadItem* DownloadManager::GetDownloadItem(int download_id) {
|
| - // The |history_downloads_| map is indexed by the download's db_handle,
|
| - // not its id, so we have to iterate.
|
| - for (DownloadMap::iterator it = history_downloads_.begin();
|
| - it != history_downloads_.end(); ++it) {
|
| - DownloadItem* item = it->second;
|
| - if (item->id() == download_id)
|
| - return item;
|
| - }
|
| - return NULL;
|
| + DownloadItem* download = downloads_[download_id];
|
| + DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download;
|
| + return download;
|
| }
|
|
|
| DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) {
|
| - DCHECK(ContainsKey(active_downloads_, download_id));
|
| - DownloadItem* download = active_downloads_[download_id];
|
| - DCHECK(download != NULL);
|
| - return download;
|
| + return GetDownloadItem(download_id);
|
| }
|
|
|
| // Confirm that everything in all maps is also in |downloads_|, and that
|
| // everything in |downloads_| is also in some other map.
|
| void DownloadManager::AssertContainersConsistent() const {
|
| -#if !defined(NDEBUG)
|
| - // Turn everything into sets.
|
| - DownloadSet active_set, history_set;
|
| - const DownloadMap* input_maps[] = {&active_downloads_, &history_downloads_};
|
| - DownloadSet* local_sets[] = {&active_set, &history_set};
|
| - DCHECK_EQ(ARRAYSIZE_UNSAFE(input_maps), ARRAYSIZE_UNSAFE(local_sets));
|
| - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input_maps); i++) {
|
| - for (DownloadMap::const_iterator it = input_maps[i]->begin();
|
| - it != input_maps[i]->end(); it++) {
|
| - local_sets[i]->insert(&*it->second);
|
| - }
|
| - }
|
| -
|
| - // Check if each set is fully present in downloads, and create a union.
|
| - const DownloadSet* all_sets[] = {&active_set, &history_set,
|
| - &save_page_as_downloads_};
|
| - DownloadSet downloads_union;
|
| - for (int i = 0; i < static_cast<int>(ARRAYSIZE_UNSAFE(all_sets)); i++) {
|
| - DownloadSet remainder;
|
| - std::insert_iterator<DownloadSet> insert_it(remainder, remainder.begin());
|
| - std::set_difference(all_sets[i]->begin(), all_sets[i]->end(),
|
| - downloads_.begin(), downloads_.end(),
|
| - insert_it);
|
| - DCHECK(remainder.empty());
|
| - std::insert_iterator<DownloadSet>
|
| - insert_union(downloads_union, downloads_union.end());
|
| - std::set_union(downloads_union.begin(), downloads_union.end(),
|
| - all_sets[i]->begin(), all_sets[i]->end(),
|
| - insert_union);
|
| - }
|
| -
|
| - // Is everything in downloads_ present in one of the other sets?
|
| - DownloadSet remainder;
|
| - std::insert_iterator<DownloadSet>
|
| - insert_remainder(remainder, remainder.begin());
|
| - std::set_difference(downloads_.begin(), downloads_.end(),
|
| - downloads_union.begin(), downloads_union.end(),
|
| - insert_remainder);
|
| - DCHECK(remainder.empty());
|
| -#endif
|
| }
|
|
|
| // DownloadManager::OtherDownloadManagerObserver implementation ----------------
|
|
|