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

Unified Diff: chrome/browser/download/download_manager.cc

Issue 7294013: Modified cancel and interrupt processing to avoid race with history. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/download/download_manager.cc
diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc
index 26a58bede0001edf11ab5441d78ef1998ead02e4..3b03e4524901960091663439599d3991d0cc862c 100644
--- a/chrome/browser/download/download_manager.cc
+++ b/chrome/browser/download/download_manager.cc
@@ -106,8 +106,7 @@ void DownloadManager::Shutdown() {
// from all queues.
download->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN);
} else if (download->IsPartialDownload()) {
- download->Cancel(false);
- download_history_->UpdateEntry(download);
+ download->Cancel();
}
}
@@ -644,6 +643,15 @@ void DownloadManager::OnResponseCompleted(int32 download_id,
}
}
+void DownloadManager::CancelDownload(int32 download_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DownloadMap::iterator it = active_downloads_.find(download_id);
+ if (it == active_downloads_.end())
+ return;
+
+ it->second->Cancel();
+}
+
void DownloadManager::OnAllDataSaved(int32 download_id,
int64 size,
const std::string& hash) {
@@ -718,8 +726,8 @@ void DownloadManager::AssertQueueStateConsistent(DownloadItem* download) {
CHECK(ContainsKey(active_downloads_, download->id()) ==
(download->state() == DownloadItem::IN_PROGRESS));
- CHECK(ContainsKey(in_progress_, download->id()) ==
- (download->state() == DownloadItem::IN_PROGRESS));
+ // Would check in_progress_, but removal from that queue happens
+ // before transition from IN_PROGRESS for legacy reasons, so skipping.
}
bool DownloadManager::IsDownloadReadyForCompletion(DownloadItem* download) {
@@ -816,33 +824,27 @@ void DownloadManager::OnDownloadRenamedToFinalName(int download_id,
download_history_->UpdateDownloadPath(item, full_path);
}
-void DownloadManager::DownloadCancelled(int32 download_id) {
+void DownloadManager::DownloadStopped(int32 download_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DownloadMap::iterator it = in_progress_.find(download_id);
- if (it == in_progress_.end())
+ DownloadMap::iterator it = active_downloads_.find(download_id);
+ if (it == active_downloads_.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);
- }
+ in_progress_.erase(download_id);
+ active_downloads_.erase(download_id);
+ UpdateAppIcon(); // Reflect removal from in_progress_.
- DownloadCancelledInternal(download_id, download->request_handle());
-}
+ // The history service should always outlive the DownloadManager.
+ download_history_->UpdateEntry(download);
-void DownloadManager::DownloadCancelledInternal(
- int download_id, DownloadRequestHandle request_handle) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- request_handle.CancelRequest();
+ download->request_handle().CancelRequest();
+ // TODO(ahendrickson) - Remove this when we add resuming of interrupted
+ // downloads, as we will keep the download item around in that case.
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
NewRunnableMethod(
@@ -865,24 +867,7 @@ void DownloadManager::OnDownloadError(int32 download_id,
<< " at offset " << download->received_bytes()
<< " for download = " << download->DebugString(true);
- 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);
- }
-
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(
- file_manager_, &DownloadFileManager::CancelDownload, download_id));
+ download->Interrupt(size, os_error);
}
void DownloadManager::UpdateAppIcon() {
@@ -890,17 +875,14 @@ 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())
- return;
-
- // Make history update.
- DownloadItem* download = it->second;
- download_history_->RemoveEntry(download);
+void DownloadManager::RemoveDownload(DownloadItem* download) {
+ // Silently ignores request if db handled indicates that the download
Randy Smith (Not in Mondays) 2011/06/30 23:05:13 "handled" -> "handle"
Randy Smith (Not in Mondays) 2011/07/05 20:28:44 Done.
+ // isn't in the history.
+ download_history_->RemoveEntry(download->db_handle());
// Remove from our tables and delete.
- history_downloads_.erase(it);
+ if (download->db_handle() != DownloadHistory::kUninitializedHandle)
+ history_downloads_.erase(download->db_handle());
int downloads_count = downloads_.erase(download);
DCHECK_EQ(1, downloads_count);
@@ -1106,7 +1088,7 @@ void DownloadManager::FileSelectionCanceled(void* params) {
VLOG(20) << __FUNCTION__ << "()"
<< " download = " << download->DebugString(true);
- DownloadCancelledInternal(download_id, download->request_handle());
+ download->Cancel();
}
// TODO(phajdan.jr): This is apparently not being exercised in tests.
@@ -1169,13 +1151,9 @@ void DownloadManager::OnQueryDownloadEntriesComplete(
void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id,
int64 db_handle) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DownloadItem* download = GetActiveDownloadItem(download_id);
- if (!download)
- return;
VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle
- << " download_id = " << download_id
- << " download = " << download->DebugString(true);
+ << " download_id = " << download_id;
// It's not immediately obvious, but HistoryBackend::CreateDownload() can
// call this function with an invalid |db_handle|. For instance, this can
@@ -1185,6 +1163,32 @@ void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id,
if (db_handle == DownloadHistory::kUninitializedHandle)
db_handle = download_history_->GetNextFakeDbHandle();
+ DownloadItem* download = GetActiveDownloadItem(download_id);
+ if (!download) {
+ // The download was cancelled while the history system was entering it.
+ // We resolve this race by turning around and deleting it in the
+ // history system (implicitly treating is as a failure in download
Randy Smith (Not in Mondays) 2011/06/30 23:05:13 "is" -> "it"
Randy Smith (Not in Mondays) 2011/07/05 20:28:44 Done.
+ // initiation, which is appropriate as the only places the cancel could
+ // have come from were in resolving issues (like the file name) which
+ // we need to have resolved for history system insertion.
Randy Smith (Not in Mondays) 2011/06/30 23:05:13 Not quite true--could have come from FileSelection
Randy Smith (Not in Mondays) 2011/07/05 20:28:44 FileSelectionCancelled is part of resolving the fi
+
+ // Make sure we haven't already been shutdown (the callback raced
+ // with shutdown), as that would mean that the history service has
+ // also been shutdown. In that case, the history will be fixed up
+ // when it's next read in.
Randy Smith (Not in Mondays) 2011/06/30 23:05:13 "on next browser startup".
Randy Smith (Not in Mondays) 2011/07/05 20:28:44 Done.
+ if (download_history_.get())
+ download_history_->RemoveEntry(db_handle);
+ return;
+ }
+
+ VLOG(20) << __FUNCTION__ << "()" << " db_handle = " << db_handle
+ << " download_id = " << download_id
+ << " download = " << download->DebugString(true);
+
+ // The download shouldn't have been returned from GetActiveDownloadItem()
+ // if it's not in progress.
+ DCHECK(download->IsInProgress());
+
DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle);
download->set_db_handle(db_handle);
@@ -1198,23 +1202,7 @@ void DownloadManager::OnCreateDownloadEntryComplete(int32 download_id,
// Inform interested objects about the new download.
NotifyModelChanged();
- // If the download is still in progress, try to complete it.
- //
- // Otherwise, download has been cancelled or interrupted before we've
- // received the DB handle. We post one final message to the history
- // service so that it can be properly in sync with the DownloadItem's
- // completion status, and also inform any observers so that they get
- // more than just the start notification.
- 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();
- }
+ MaybeCompleteDownload(download);
}
void DownloadManager::ShowDownloadInBrowser(DownloadItem* download) {
@@ -1264,6 +1252,16 @@ DownloadItem* DownloadManager::GetDownloadItem(int download_id) {
return NULL;
}
+void DownloadManager::GetInProgressDownloads(
+ std::vector<DownloadItem*>* result) {
+ DCHECK(result);
+
+ for (DownloadMap::iterator it = active_downloads_.begin();
+ it != active_downloads_.end(); ++it) {
+ result->push_back(it->second);
+ }
+}
+
DownloadItem* DownloadManager::GetActiveDownloadItem(int download_id) {
DCHECK(ContainsKey(active_downloads_, download_id));
DownloadItem* download = active_downloads_[download_id];

Powered by Google App Engine
This is Rietveld 408576698