Chromium Code Reviews| Index: chrome/browser/download/download_file_manager.cc |
| diff --git a/chrome/browser/download/download_file_manager.cc b/chrome/browser/download/download_file_manager.cc |
| index 4d19e6139e8b614a1118aed43d62fd6a4e8cc2ae..71852202dd3811812ab2ea775fdc907df0cebdbb 100644 |
| --- a/chrome/browser/download/download_file_manager.cc |
| +++ b/chrome/browser/download/download_file_manager.cc |
| @@ -169,11 +169,36 @@ void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) { |
| } |
| DownloadFile* download_file = GetDownloadFile(id); |
| + bool had_error = false; |
| for (size_t i = 0; i < contents.size(); ++i) { |
| net::IOBuffer* data = contents[i].first; |
| const int data_len = contents[i].second; |
| - if (download_file) |
| - download_file->AppendDataToFile(data->data(), data_len); |
| + if (!had_error && download_file) { |
| + bool write_succeeded = |
|
cbentzel
2011/08/16 15:50:36
If this is going to end up with a net_error code r
ahendrickson
2011/08/18 21:52:01
AppendDataToFile() returns a bool currently. Anot
|
| + download_file->AppendDataToFile(data->data(), data_len); |
| + if (!write_succeeded) { |
| + // Write failed: interrupt the download. |
| + std::string hash; |
| + DownloadManager* download_manager = download_file->GetDownloadManager(); |
| + had_error = true; |
| + |
| + // Calling this here in case we get more data, to avoid calling |
| + // |OnDownloadError()| more than once. |
| + CancelDownload(id); |
|
cbentzel
2011/08/16 15:50:36
BUG: I'm not sure the CancelDownload is right.
a]
ahendrickson
2011/08/18 21:52:01
Fixed. Now get the number of bytes before canceli
cbentzel
2011/08/19 13:02:41
What race condition?
I agree that calling CancelD
ahendrickson
2011/08/19 18:11:59
Hmm, I misspoke a bit, I think. We might not make
|
| + |
| + if (download_manager) { |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, |
| + FROM_HERE, |
| + NewRunnableMethod( |
| + download_manager, |
| + &DownloadManager::OnDownloadError, |
| + id, |
| + download_file->bytes_so_far(), |
| + net::ERR_FAILED)); |
| + } |
| + } |
| + } |
| data->Release(); |
| } |
| } |
| @@ -181,10 +206,10 @@ void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) { |
| void DownloadFileManager::OnResponseCompleted( |
| int id, |
| DownloadBuffer* buffer, |
| - int os_error, |
| + int net_error, |
| const std::string& security_info) { |
| VLOG(20) << __FUNCTION__ << "()" << " id = " << id |
| - << " os_error = " << os_error |
| + << " net_error = " << net_error |
| << " security_info = \"" << security_info << "\""; |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| delete buffer; |
| @@ -204,11 +229,32 @@ void DownloadFileManager::OnResponseCompleted( |
| if (!download_file->GetSha256Hash(&hash)) |
| hash.clear(); |
| - BrowserThread::PostTask( |
| - BrowserThread::UI, FROM_HERE, |
| - NewRunnableMethod( |
| - download_manager, &DownloadManager::OnResponseCompleted, |
| - id, download_file->bytes_so_far(), os_error, hash)); |
| + // ERR_CONNECTION_CLOSED is allowed since a number of servers in the wild |
| + // advertise a larger Content-Length than the amount of bytes in the message |
| + // body, and then close the connection. Other browsers - IE8, Firefox 4.0.1, |
| + // and Safari 5.0.4 - treat the download as complete in this case, so we |
| + // follow their lead. |
| + if (net_error == net::OK || net_error == net::ERR_CONNECTION_CLOSED) { |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, |
| + FROM_HERE, |
| + NewRunnableMethod( |
| + download_manager, |
| + &DownloadManager::OnResponseCompleted, |
| + id, |
| + download_file->bytes_so_far(), |
| + hash)); |
| + } else { |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, |
| + FROM_HERE, |
| + NewRunnableMethod( |
| + download_manager, |
| + &DownloadManager::OnDownloadError, |
| + id, |
| + download_file->bytes_so_far(), |
| + net_error)); |
| + } |
| // We need to keep the download around until the UI thread has finalized |
| // the name. |
| } |
| @@ -294,7 +340,7 @@ void DownloadFileManager::RenameInProgressDownloadFile( |
| if (!download_file->Rename(full_path)) { |
| // Error. Between the time the UI thread generated 'full_path' to the time |
| // this code runs, something happened that prevents us from renaming. |
| - CancelDownloadOnRename(id); |
| + CancelDownloadOnRename(id, net::ERR_FAILED); |
| } |
| } |
| @@ -342,7 +388,7 @@ void DownloadFileManager::RenameCompletingDownloadFile( |
| if (!download_file->Rename(new_path)) { |
| // Error. Between the time the UI thread generated 'full_path' to the time |
| // this code runs, something happened that prevents us from renaming. |
| - CancelDownloadOnRename(id); |
| + CancelDownloadOnRename(id, net::ERR_FAILED); |
| return; |
| } |
| @@ -361,7 +407,7 @@ void DownloadFileManager::RenameCompletingDownloadFile( |
| // Called only from RenameInProgressDownloadFile and |
| // RenameCompletingDownloadFile on the FILE thread. |
| -void DownloadFileManager::CancelDownloadOnRename(int id) { |
| +void DownloadFileManager::CancelDownloadOnRename(int id, int rename_error) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| DownloadFile* download_file = GetDownloadFile(id); |
| @@ -372,7 +418,7 @@ void DownloadFileManager::CancelDownloadOnRename(int id) { |
| if (!download_manager) { |
| // Without a download manager, we can't cancel the request normally, so we |
| // need to do it here. The normal path will also update the download |
| - // history before cancelling the request. |
| + // history before canceling the request. |
| download_file->CancelDownloadRequest(); |
| return; |
| } |
| @@ -380,7 +426,10 @@ void DownloadFileManager::CancelDownloadOnRename(int id) { |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| NewRunnableMethod(download_manager, |
| - &DownloadManager::DownloadCancelled, id)); |
| + &DownloadManager::OnDownloadError, |
| + id, |
| + download_file->bytes_so_far(), |
| + rename_error)); |
| } |
| void DownloadFileManager::EraseDownload(int id) { |