Index: chrome/browser/download/download_manager.cc |
diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc |
index c61912a27dab764060b2dd4e824dca69c84f7245..4d7db4a8f21263f125597bd757f44437bbbcc909 100644 |
--- a/chrome/browser/download/download_manager.cc |
+++ b/chrome/browser/download/download_manager.cc |
@@ -4,6 +4,7 @@ |
#include "chrome/browser/download/download_manager.h" |
+#include "base/bind.h" |
#include "base/callback.h" |
#include "base/file_util.h" |
#include "base/i18n/case_conversion.h" |
@@ -23,6 +24,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 +86,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 +108,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 +150,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; |
@@ -280,8 +168,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); |
} |
} |
@@ -294,27 +183,30 @@ void DownloadManager::CheckForFileRemoval(DownloadItem* download_item) { |
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(); |
} |
@@ -325,6 +217,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; |
@@ -342,6 +236,7 @@ void DownloadManager::CheckVisitedReferrerBeforeDone( |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
DownloadItem* download = GetActiveDownloadItem(download_id); |
+ DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download; |
if (!download) |
return; |
@@ -418,6 +313,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 |
@@ -508,6 +404,7 @@ void DownloadManager::OnPathExistenceAvailable( |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
DownloadItem* download = GetActiveDownloadItem(download_id); |
+ DVLOG(1) << __PRETTY_FUNCTION__ << " " << download << " " << download_id; |
if (!download) |
return; |
@@ -558,11 +455,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, |
@@ -571,12 +468,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()); |
@@ -586,8 +479,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; |
@@ -620,8 +512,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); |
@@ -653,16 +545,16 @@ void DownloadManager::OnResponseCompleted(int32 download_id, |
void DownloadManager::OnAllDataSaved(int32 download_id, |
int64 size, |
const std::string& hash) { |
- VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id |
+ DVLOG(1) << __FUNCTION__ << "()" << " download_id = " << download_id |
<< " size = " << size; |
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 |
@@ -691,48 +583,20 @@ 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__ << " p=" << download << " id=" |
+ << download->id() << " data=" << download->all_data_saved() |
+ << " safety=" << download->safety_state() << " path=" |
+ << download->full_path().value(); |
+ return download->all_data_saved() && |
+ download->safety_state() != DownloadItem::DANGEROUS && |
+ !download->full_path().value().empty(); |
// If we don't have all the data, the download is not ready for |
// completion. |
if (!download->all_data_saved()) |
@@ -743,24 +607,12 @@ 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; |
} |
void DownloadManager::MaybeCompleteDownload(DownloadItem* download) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- VLOG(20) << __FUNCTION__ << "()" << " download = " |
- << download->DebugString(false); |
+ DVLOG(1) << __FUNCTION__ << " " << download->DebugString(true); |
if (!IsDownloadReadyForCompletion(download)) |
return; |
@@ -770,24 +622,20 @@ 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())); |
+ DCHECK(!download->full_path().value().empty()); |
- VLOG(20) << __FUNCTION__ << "()" << " executing: download = " |
- << download->DebugString(false); |
+ DVLOG(1) << __FUNCTION__ << " " << download->DebugString(true); |
- // 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); |
// Finish the download. |
download->OnDownloadCompleting(file_manager_); |
+ DVLOG(1) << __FUNCTION__ << " " << download->DebugString(true); |
} |
void DownloadManager::DownloadCompleted(int32 download_id) { |
@@ -795,13 +643,12 @@ 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, |
const FilePath& full_path, |
int uniquifier) { |
- VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id |
+ DVLOG(1) << __FUNCTION__ << "()" << " download_id = " << download_id |
<< " full_path = \"" << full_path.value() << "\"" |
<< " uniquifier = " << uniquifier; |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
@@ -824,27 +671,17 @@ void DownloadManager::OnDownloadRenamedToFinalName(int download_id, |
item->OnDownloadRenamedToFinalName(full_path); |
download_history_->UpdateDownloadPath(item, full_path); |
+ UpdateAppIcon(); |
} |
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()); |
} |
@@ -863,32 +700,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( |
@@ -900,74 +718,108 @@ 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; |
- |
- // Make history update. |
- DownloadItem* download = it->second; |
- download_history_->RemoveEntry(download); |
- |
- // Remove from our tables and delete. |
- history_downloads_.erase(it); |
- int downloads_count = downloads_.erase(download); |
- DCHECK_EQ(1, downloads_count); |
- |
- // Tell observers to refresh their views. |
+ } |
+ download_history_->RemoveEntry(download.get()); |
+ downloads_.erase(it); |
NotifyModelChanged(); |
- |
- delete download; |
} |
-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()) { |
- DownloadItem* download = it->second; |
- if (download->start_time() >= remove_begin && |
- (remove_end.is_null() || download->start_time() < remove_end) && |
- (download->IsComplete() || |
- download->IsCancelled() || |
- download->IsInterrupted())) { |
- AssertQueueStateConsistent(download); |
+void DownloadManager::GetTemporaryDownloads( |
+ const FilePath& dir_path, ItemVector* result) { |
+ DCHECK(result); |
+ Search(DOWNLOAD_QUERY_FILTER(item.is_temporary()). |
+ filenameRegex("^" + dir_path.value() + "/.*"), |
+ result); |
+ DVLOG(1) << __PRETTY_FUNCTION__ << " " << result->size(); |
+} |
- // Remove from the map and move to the next in the list. |
- history_downloads_.erase(it++); |
+void DownloadManager::GetAllDownloads( |
+ const FilePath& dir_path, ItemVector* result) { |
+ DCHECK(result); |
+ Search(DOWNLOAD_QUERY_FILTER(!item.is_temporary()). |
+ filenameRegex("^" + dir_path.value() + "/.*"), |
+ result); |
+} |
- // Also remove it from any completed dangerous downloads. |
- pending_deletes.push_back(download); |
+void DownloadManager::GetCurrentDownloads( |
+ const FilePath& dir_path, ItemVector* result) { |
+ DCHECK(result); |
+ Search(DOWNLOAD_QUERY_FILTER( |
+ !item.is_temporary() && |
+ (item.IsPartialDownload() || |
+ (item.safety_state() == DownloadItem::DANGEROUS))). |
+ filenameRegex("^" + dir_path.value() + "/.*"), |
+ result); |
+} |
- continue; |
- } |
+bool DownloadManager::Search(const download_util::DownloadQuery& query, |
+ ItemVector* items, |
+ bool merge_parent_manager, |
+ std::string* error_msg, |
+ ListValue* json_results) const { |
+ ItemVector default_items; |
+ if (items == NULL) { |
+ items = &default_items; |
+ } |
+ MergeItems(merge_parent_manager, items); |
+ return query.Search(items, error_msg, json_results); |
+} |
- ++it; |
+void DownloadManager::MergeItems( |
+ bool merge_parent_manager, ItemVector* items) const { |
+ for (DownloadMap::const_iterator it = downloads_.begin(); |
+ it != downloads_.end(); ++it) items->push_back(it->second); |
+ if (!merge_parent_manager || |
+ (profile_ == NULL)) return; |
+ Profile* original_profile = profile_->GetOriginalProfile(); |
+ if ((profile_ != NULL) && |
+ (original_profile != NULL) && |
+ (original_profile != profile_) && |
+ (original_profile->GetDownloadManager() != NULL)) { |
+ original_profile->GetDownloadManager()->MergeItems( |
+ merge_parent_manager, items); |
} |
+} |
- // If we aren't deleting anything, we're done. |
- if (pending_deletes.empty()) |
- return 0; |
+void DownloadManager::SearchDownloads(const string16& query, |
+ ItemVector* result) { |
+ DCHECK(result); |
+ bool otr = false; |
+ if (profile_ != NULL) otr = profile_->IsOffTheRecord(); |
+ Search(DOWNLOAD_QUERY_FILTER1(otr, |
+ !item.is_temporary() && |
+ !item.is_extension_install() && |
+ (item.is_otr() == otr)). |
+ query(UTF16ToASCII(query)), |
+ result); |
+} |
- // 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); |
+int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin, |
+ const base::Time remove_end) { |
+ download_history_->RemoveEntriesBetween(remove_begin, remove_end); |
+ ItemVector pending_deletes; |
+ STLElementDeleter<ItemVector> delete_pending_deletes(&pending_deletes); |
+ const base::Time unix_epoch = base::Time::UnixEpoch(); |
+ Search(DOWNLOAD_QUERY_FILTER( |
+ item.IsComplete() || |
+ item.IsCancelled() || |
+ item.IsInterrupted()). |
+ startedAfter((remove_begin - unix_epoch).InMilliseconds()). |
+ startedBefore((remove_end - unix_epoch).InMilliseconds()), |
+ &pending_deletes); |
+ if (pending_deletes.empty()) return 0; |
+ for (ItemVector::const_iterator iter = pending_deletes.begin(); |
+ iter != pending_deletes.end(); ++iter) { |
+ downloads_.erase(downloads_.find((*iter)->id())); |
} |
- |
- // 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; |
} |
@@ -989,9 +841,9 @@ void DownloadManager::SavePageAsDownloadStarted(DownloadItem* download) { |
#if !defined(NDEBUG) |
save_page_as_downloads_.insert(download); |
#endif |
- downloads_.insert(download); |
+ downloads_[download->id()] = download; |
// Add to history and notify observers. |
- AddDownloadItemToHistory(download, DownloadHistory::kUninitializedHandle); |
+ AddDownloadItemToHistory(download); |
NotifyModelChanged(); |
} |
@@ -1048,36 +900,42 @@ bool DownloadManager::ShouldOpenFileBasedOnExtension( |
} |
bool DownloadManager::IsDownloadProgressKnown() { |
- for (DownloadMap::iterator i = in_progress_.begin(); |
- i != in_progress_.end(); ++i) { |
- if (i->second->total_bytes() <= 0) |
+ for (DownloadMap::iterator i = downloads_.begin(); |
+ i != downloads_.end(); ++i) { |
+ if (i->second->total_bytes() <= 0) { |
return false; |
+ } |
} |
- |
return true; |
} |
-int64 DownloadManager::GetInProgressDownloadCount() { |
- return in_progress_.size(); |
+int64 DownloadManager::GetInProgressDownloadCount() const { |
+ ItemVector in_progress; |
+ Search(download_util::DownloadQuery().state_enum(DownloadItem::IN_PROGRESS), |
+ &in_progress); |
+ DVLOG(1) << __PRETTY_FUNCTION__ << " " << in_progress.size(); |
+ return in_progress.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(); |
} |
+ DVLOG(1) << __PRETTY_FUNCTION__ << " " << received_bytes; |
return received_bytes; |
} |
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(); |
} |
+ DVLOG(1) << __PRETTY_FUNCTION__ << " " << total_bytes; |
return total_bytes; |
} |
@@ -1164,56 +1022,36 @@ 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(); |
} |
-void DownloadManager::AddDownloadItemToHistory(DownloadItem* download, |
- int64 db_handle) { |
+void DownloadManager::AddDownloadItemToHistory(DownloadItem* download) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- // 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; |
} |
// Once the new DownloadItem's creation info has been committed to the history |
// service, we associate the DownloadItem with the db handle, update our |
// 'history_downloads_' map and inform observers. |
-void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id, |
- int64 db_handle) { |
+void DownloadManager::OnCreateDownloadEntryComplete( |
+ int32 download_id) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
DownloadItem* download = GetActiveDownloadItem(download_id); |
- if (!download) |
- return; |
+ DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download; |
+ if (download == NULL) return; |
+ download->SetIsInHistory(true); |
+ VLOG(20) << __FUNCTION__ << download->DebugString(true); |
- VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle |
- << " download_id = " << download_id |
- << " download = " << download->DebugString(true); |
+ AddDownloadItemToHistory(download); |
- AddDownloadItemToHistory(download, db_handle); |
+ DVLOG(1) << __PRETTY_FUNCTION__ << " " << download_id << " " << download; |
// Show in the appropriate browser UI. |
// This includes buttons to save or cancel, for a dangerous download. |
@@ -1232,16 +1070,14 @@ 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 |
// to display its download shelf. |
@@ -1276,67 +1112,29 @@ 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. |
+// Confirm that there's only one of any download_id, and that they are all > -1 |
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); |
- } |
+ std::vector<int> ids; |
+ for (DownloadMap::const_iterator iter = downloads_.begin(); |
+ iter != downloads_.end(); ++iter) { |
+ ids.push_back(iter->second->id()); |
} |
- |
- // 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); |
+ std::sort(ids.begin(), ids.end()); |
+ int prev_id = -1; |
+ for (std::vector<int>::const_iterator iter = ids.begin(); |
+ iter != ids.end(); ++iter) { |
+ CHECK_GT(*iter, prev_id) << *iter << " " << prev_id; |
+ prev_id = *iter; |
} |
- |
- // 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 ---------------- |