Index: content/browser/download/download_file_impl.cc |
diff --git a/content/browser/download/download_file_impl.cc b/content/browser/download/download_file_impl.cc |
index 9d4a6880eaa52157f0fe88b8fd58c989d399d028..8c425159db751d7c5692dae11bd5d2ac46ad7ea3 100644 |
--- a/content/browser/download/download_file_impl.cc |
+++ b/content/browser/download/download_file_impl.cc |
@@ -88,11 +88,39 @@ content::DownloadInterruptReason DownloadFileImpl::AppendDataToFile( |
content::DOWNLOAD_INTERRUPT_FROM_DISK); |
} |
-content::DownloadInterruptReason DownloadFileImpl::Rename( |
- const FilePath& full_path) { |
- return content::ConvertNetErrorToInterruptReason( |
- file_.Rename(full_path), |
- content::DOWNLOAD_INTERRUPT_FROM_DISK); |
+void DownloadFileImpl::Rename(const FilePath& full_path, |
+ bool overwrite_existing_file, |
+ const RenameCompletionCallback& callback) { |
+ FilePath new_path(full_path); |
+ if (!overwrite_existing_file) { |
+ // Make the file unique if requested. |
+ int uniquifier = |
+ file_util::GetUniquePathNumber(new_path, FILE_PATH_LITERAL("")); |
+ if (uniquifier > 0) { |
+ new_path = new_path.InsertBeforeExtensionASCII( |
+ StringPrintf(" (%d)", uniquifier)); |
+ } |
+ } |
+ |
+ net::Error rename_error = file_.Rename(new_path); |
+ content::DownloadInterruptReason reason( |
+ content::DOWNLOAD_INTERRUPT_REASON_NONE); |
+ if (net::OK != rename_error) { |
+ // Make sure our information is updated, since we're about to |
+ // error out. |
+ SendUpdate(); |
+ |
+ reason = |
+ content::ConvertNetErrorToInterruptReason( |
+ rename_error, |
+ content::DOWNLOAD_INTERRUPT_FROM_DISK); |
+ |
+ new_path.clear(); |
+ } |
+ |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(callback, reason, new_path)); |
} |
void DownloadFileImpl::Detach() { |
@@ -190,6 +218,10 @@ void DownloadFileImpl::StreamActive() { |
base::TimeTicks write_start(base::TimeTicks::Now()); |
reason = AppendDataToFile( |
incoming_data.get()->data(), incoming_data_size); |
+ // Note that if we're after a rename failure but before any |
+ // cancel that our owner generates based on that rename failure, |
+ // we'll get an ERR_UNEXPECTED from the above. Our consumers |
+ // need to handle this situation. |
disk_writes_time_ += (base::TimeTicks::Now() - write_start); |
bytes_seen_ += incoming_data_size; |
total_incoming_data_size += incoming_data_size; |
@@ -238,11 +270,11 @@ void DownloadFileImpl::StreamActive() { |
// Our controller will clean us up. |
stream_reader_->RegisterCallback(base::Closure()); |
weak_factory_.InvalidateWeakPtrs(); |
+ SendUpdate(); // Make info up to date before error. |
BrowserThread::PostTask( |
BrowserThread::UI, FROM_HERE, |
base::Bind(&DownloadManager::OnDownloadInterrupted, |
- download_manager_, id_.local(), |
- BytesSoFar(), GetHashState(), reason)); |
+ download_manager_, id_.local(), reason)); |
} else if (state == content::ByteStreamReader::STREAM_COMPLETE) { |
// Signal successful completion and shut down processing. |
stream_reader_->RegisterCallback(base::Closure()); |