| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/download/download_file_manager.h" | 5 #include "content/browser/download/download_file_manager.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
| 15 #include "content/browser/download/download_buffer.h" | 15 #include "content/browser/download/download_buffer.h" |
| 16 #include "content/browser/download/download_create_info.h" | 16 #include "content/browser/download/download_create_info.h" |
| 17 #include "content/browser/download/download_file.h" | 17 #include "content/browser/download/download_file_impl.h" |
| 18 #include "content/browser/download/download_manager.h" | 18 #include "content/browser/download/download_manager.h" |
| 19 #include "content/browser/download/download_request_handle.h" | 19 #include "content/browser/download/download_request_handle.h" |
| 20 #include "content/browser/download/download_stats.h" | 20 #include "content/browser/download/download_stats.h" |
| 21 #include "content/browser/renderer_host/resource_dispatcher_host.h" | 21 #include "content/browser/renderer_host/resource_dispatcher_host.h" |
| 22 #include "content/browser/tab_contents/tab_contents.h" | 22 #include "content/browser/tab_contents/tab_contents.h" |
| 23 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
| 24 #include "content/public/browser/download_manager_delegate.h" | 24 #include "content/public/browser/download_manager_delegate.h" |
| 25 #include "googleurl/src/gurl.h" | 25 #include "googleurl/src/gurl.h" |
| 26 #include "net/base/io_buffer.h" | 26 #include "net/base/io_buffer.h" |
| 27 | 27 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 49 BrowserThread::FILE, FROM_HERE, | 49 BrowserThread::FILE, FROM_HERE, |
| 50 base::Bind(&DownloadFileManager::OnShutdown, this)); | 50 base::Bind(&DownloadFileManager::OnShutdown, this)); |
| 51 } | 51 } |
| 52 | 52 |
| 53 void DownloadFileManager::OnShutdown() { | 53 void DownloadFileManager::OnShutdown() { |
| 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 55 StopUpdateTimer(); | 55 StopUpdateTimer(); |
| 56 STLDeleteValues(&downloads_); | 56 STLDeleteValues(&downloads_); |
| 57 } | 57 } |
| 58 | 58 |
| 59 DownloadFile* DownloadFileManager::NewDownloadFile( |
| 60 DownloadCreateInfo* info, |
| 61 const DownloadRequestHandle& request_handle, |
| 62 DownloadManager* download_manager) { |
| 63 return new DownloadFileImpl(info, |
| 64 new DownloadRequestHandle(request_handle), |
| 65 download_manager); |
| 66 } |
| 67 |
| 59 void DownloadFileManager::CreateDownloadFile( | 68 void DownloadFileManager::CreateDownloadFile( |
| 60 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle, | 69 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle, |
| 61 DownloadManager* download_manager, bool get_hash) { | 70 DownloadManager* download_manager, bool get_hash) { |
| 62 DCHECK(info); | 71 DCHECK(info); |
| 63 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); | 72 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); |
| 64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 65 | 74 |
| 66 // Life of |info| ends here. No more references to it after this method. | 75 // Life of |info| ends here. No more references to it after this method. |
| 67 scoped_ptr<DownloadCreateInfo> infop(info); | 76 scoped_ptr<DownloadCreateInfo> infop(info); |
| 68 | 77 |
| 69 scoped_ptr<DownloadFile> | 78 scoped_ptr<DownloadFile> download_file( |
| 70 download_file(new DownloadFile(info, | 79 NewDownloadFile(info, request_handle, download_manager)); |
| 71 new DownloadRequestHandle(request_handle), | |
| 72 download_manager)); | |
| 73 if (net::OK != download_file->Initialize(get_hash)) { | 80 if (net::OK != download_file->Initialize(get_hash)) { |
| 74 request_handle.CancelRequest(); | 81 request_handle.CancelRequest(); |
| 75 return; | 82 return; |
| 76 } | 83 } |
| 77 | 84 |
| 78 DCHECK(GetDownloadFile(info->download_id) == NULL); | 85 DCHECK(GetDownloadFile(info->download_id) == NULL); |
| 79 downloads_[info->download_id] = download_file.release(); | 86 downloads_[info->download_id] = download_file.release(); |
| 80 | 87 |
| 81 // The file is now ready, we can un-pause the request and start saving data. | 88 // The file is now ready, we can un-pause the request and start saving data. |
| 82 request_handle.ResumeRequest(); | 89 request_handle.ResumeRequest(); |
| 83 | 90 |
| 84 StartUpdateTimer(); | 91 StartUpdateTimer(); |
| 85 | 92 |
| 86 BrowserThread::PostTask( | 93 BrowserThread::PostTask( |
| 87 BrowserThread::UI, FROM_HERE, | 94 BrowserThread::UI, FROM_HERE, |
| 88 base::Bind(&DownloadManager::StartDownload, download_manager, | 95 base::Bind(&DownloadManager::StartDownload, download_manager, |
| 89 info->download_id.local())); | 96 info->download_id.local())); |
| 90 } | 97 } |
| 91 | 98 |
| 92 DownloadFile* DownloadFileManager::GetDownloadFile(DownloadId global_id) { | 99 DownloadFile* DownloadFileManager::GetDownloadFile( |
| 100 DownloadId global_id) { |
| 93 DownloadFileMap::iterator it = downloads_.find(global_id); | 101 DownloadFileMap::iterator it = downloads_.find(global_id); |
| 94 return it == downloads_.end() ? NULL : it->second; | 102 return it == downloads_.end() ? NULL : it->second; |
| 95 } | 103 } |
| 96 | 104 |
| 97 void DownloadFileManager::StartUpdateTimer() { | 105 void DownloadFileManager::StartUpdateTimer() { |
| 98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 99 if (!update_timer_.IsRunning()) { | 107 if (!update_timer_.IsRunning()) { |
| 100 update_timer_.Start(FROM_HERE, | 108 update_timer_.Start(FROM_HERE, |
| 101 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), | 109 base::TimeDelta::FromMilliseconds(kUpdatePeriodMs), |
| 102 this, &DownloadFileManager::UpdateInProgressDownloads); | 110 this, &DownloadFileManager::UpdateInProgressDownloads); |
| 103 } | 111 } |
| 104 } | 112 } |
| 105 | 113 |
| 106 void DownloadFileManager::StopUpdateTimer() { | 114 void DownloadFileManager::StopUpdateTimer() { |
| 107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 108 update_timer_.Stop(); | 116 update_timer_.Stop(); |
| 109 } | 117 } |
| 110 | 118 |
| 111 void DownloadFileManager::UpdateInProgressDownloads() { | 119 void DownloadFileManager::UpdateInProgressDownloads() { |
| 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 120 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 113 for (DownloadFileMap::iterator i = downloads_.begin(); | 121 for (DownloadFileMap::iterator i = downloads_.begin(); |
| 114 i != downloads_.end(); ++i) { | 122 i != downloads_.end(); ++i) { |
| 115 DownloadId global_id = i->first; | 123 DownloadId global_id = i->first; |
| 116 DownloadFile* download_file = i->second; | 124 DownloadFile* download_file = i->second; |
| 117 DownloadManager* manager = download_file->GetDownloadManager(); | 125 DownloadManager* manager = download_file->GetDownloadManager(); |
| 118 if (manager) { | 126 if (manager) { |
| 119 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 127 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 120 base::Bind(&DownloadManager::UpdateDownload, manager, | 128 base::Bind(&DownloadManager::UpdateDownload, manager, |
| 121 global_id.local(), download_file->bytes_so_far())); | 129 global_id.local(), download_file->BytesSoFar())); |
| 122 } | 130 } |
| 123 } | 131 } |
| 124 } | 132 } |
| 125 | 133 |
| 126 void DownloadFileManager::StartDownload( | 134 void DownloadFileManager::StartDownload( |
| 127 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle) { | 135 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle) { |
| 128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 129 DCHECK(info); | 137 DCHECK(info); |
| 130 | 138 |
| 131 DownloadManager* manager = request_handle.GetDownloadManager(); | 139 DownloadManager* manager = request_handle.GetDownloadManager(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 net::IOBuffer* data = (*contents)[i].first; | 173 net::IOBuffer* data = (*contents)[i].first; |
| 166 const int data_len = (*contents)[i].second; | 174 const int data_len = (*contents)[i].second; |
| 167 if (!had_error && download_file) { | 175 if (!had_error && download_file) { |
| 168 net::Error write_result = | 176 net::Error write_result = |
| 169 download_file->AppendDataToFile(data->data(), data_len); | 177 download_file->AppendDataToFile(data->data(), data_len); |
| 170 if (write_result != net::OK) { | 178 if (write_result != net::OK) { |
| 171 // Write failed: interrupt the download. | 179 // Write failed: interrupt the download. |
| 172 DownloadManager* download_manager = download_file->GetDownloadManager(); | 180 DownloadManager* download_manager = download_file->GetDownloadManager(); |
| 173 had_error = true; | 181 had_error = true; |
| 174 | 182 |
| 175 int64 bytes_downloaded = download_file->bytes_so_far(); | 183 int64 bytes_downloaded = download_file->BytesSoFar(); |
| 176 // Calling this here in case we get more data, to avoid | 184 // Calling this here in case we get more data, to avoid |
| 177 // processing data after an error. That could lead to | 185 // processing data after an error. That could lead to |
| 178 // files that are corrupted if the later processing succeeded. | 186 // files that are corrupted if the later processing succeeded. |
| 179 CancelDownload(global_id); | 187 CancelDownload(global_id); |
| 180 download_file = NULL; // Was deleted in |CancelDownload|. | 188 download_file = NULL; // Was deleted in |CancelDownload|. |
| 181 | 189 |
| 182 if (download_manager) { | 190 if (download_manager) { |
| 183 BrowserThread::PostTask( | 191 BrowserThread::PostTask( |
| 184 BrowserThread::UI, FROM_HERE, | 192 BrowserThread::UI, FROM_HERE, |
| 185 base::Bind(&DownloadManager::OnDownloadInterrupted, | 193 base::Bind(&DownloadManager::OnDownloadInterrupted, |
| (...skipping 29 matching lines...) Expand all Loading... |
| 215 | 223 |
| 216 std::string hash; | 224 std::string hash; |
| 217 if (!download_file->GetSha256Hash(&hash)) | 225 if (!download_file->GetSha256Hash(&hash)) |
| 218 hash.clear(); | 226 hash.clear(); |
| 219 | 227 |
| 220 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) { | 228 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) { |
| 221 BrowserThread::PostTask( | 229 BrowserThread::PostTask( |
| 222 BrowserThread::UI, FROM_HERE, | 230 BrowserThread::UI, FROM_HERE, |
| 223 base::Bind(&DownloadManager::OnResponseCompleted, | 231 base::Bind(&DownloadManager::OnResponseCompleted, |
| 224 download_manager, global_id.local(), | 232 download_manager, global_id.local(), |
| 225 download_file->bytes_so_far(), hash)); | 233 download_file->BytesSoFar(), hash)); |
| 226 } else { | 234 } else { |
| 227 BrowserThread::PostTask( | 235 BrowserThread::PostTask( |
| 228 BrowserThread::UI, FROM_HERE, | 236 BrowserThread::UI, FROM_HERE, |
| 229 base::Bind(&DownloadManager::OnDownloadInterrupted, | 237 base::Bind(&DownloadManager::OnDownloadInterrupted, |
| 230 download_manager, global_id.local(), | 238 download_manager, global_id.local(), |
| 231 download_file->bytes_so_far(), reason)); | 239 download_file->BytesSoFar(), reason)); |
| 232 } | 240 } |
| 233 // We need to keep the download around until the UI thread has finalized | 241 // We need to keep the download around until the UI thread has finalized |
| 234 // the name. | 242 // the name. |
| 235 } | 243 } |
| 236 | 244 |
| 237 // This method will be sent via a user action, or shutdown on the UI thread, and | 245 // This method will be sent via a user action, or shutdown on the UI thread, and |
| 238 // run on the download thread. Since this message has been sent from the UI | 246 // run on the download thread. Since this message has been sent from the UI |
| 239 // thread, the download may have already completed and won't exist in our map. | 247 // thread, the download may have already completed and won't exist in our map. |
| 240 void DownloadFileManager::CancelDownload(DownloadId global_id) { | 248 void DownloadFileManager::CancelDownload(DownloadId global_id) { |
| 241 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id; | 249 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 i != downloads_.end(); ++i) { | 287 i != downloads_.end(); ++i) { |
| 280 DownloadFile* download_file = i->second; | 288 DownloadFile* download_file = i->second; |
| 281 if (download_file->GetDownloadManager() == manager) { | 289 if (download_file->GetDownloadManager() == manager) { |
| 282 download_file->CancelDownloadRequest(); | 290 download_file->CancelDownloadRequest(); |
| 283 to_remove.insert(download_file); | 291 to_remove.insert(download_file); |
| 284 } | 292 } |
| 285 } | 293 } |
| 286 | 294 |
| 287 for (std::set<DownloadFile*>::iterator i = to_remove.begin(); | 295 for (std::set<DownloadFile*>::iterator i = to_remove.begin(); |
| 288 i != to_remove.end(); ++i) { | 296 i != to_remove.end(); ++i) { |
| 289 downloads_.erase((*i)->global_id()); | 297 downloads_.erase((*i)->GlobalId()); |
| 290 delete *i; | 298 delete *i; |
| 291 } | 299 } |
| 292 } | 300 } |
| 293 | 301 |
| 294 // Actions from the UI thread and run on the download thread | 302 // Actions from the UI thread and run on the download thread |
| 295 | 303 |
| 296 // The DownloadManager in the UI thread has provided an intermediate .crdownload | 304 // The DownloadManager in the UI thread has provided an intermediate .crdownload |
| 297 // name for the download specified by 'id'. Rename the in progress download. | 305 // name for the download specified by 'id'. Rename the in progress download. |
| 298 // | 306 // |
| 299 // There are 2 possible rename cases where this method can be called: | 307 // There are 2 possible rename cases where this method can be called: |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 // need to do it here. The normal path will also update the download | 407 // need to do it here. The normal path will also update the download |
| 400 // history before canceling the request. | 408 // history before canceling the request. |
| 401 download_file->CancelDownloadRequest(); | 409 download_file->CancelDownloadRequest(); |
| 402 return; | 410 return; |
| 403 } | 411 } |
| 404 | 412 |
| 405 BrowserThread::PostTask( | 413 BrowserThread::PostTask( |
| 406 BrowserThread::UI, FROM_HERE, | 414 BrowserThread::UI, FROM_HERE, |
| 407 base::Bind(&DownloadManager::OnDownloadInterrupted, | 415 base::Bind(&DownloadManager::OnDownloadInterrupted, |
| 408 download_manager, global_id.local(), | 416 download_manager, global_id.local(), |
| 409 download_file->bytes_so_far(), | 417 download_file->BytesSoFar(), |
| 410 ConvertNetErrorToInterruptReason( | 418 ConvertNetErrorToInterruptReason( |
| 411 rename_error, DOWNLOAD_INTERRUPT_FROM_DISK))); | 419 rename_error, DOWNLOAD_INTERRUPT_FROM_DISK))); |
| 412 } | 420 } |
| 413 | 421 |
| 414 void DownloadFileManager::EraseDownload(DownloadId global_id) { | 422 void DownloadFileManager::EraseDownload(DownloadId global_id) { |
| 415 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 416 | 424 |
| 417 if (!ContainsKey(downloads_, global_id)) | 425 if (!ContainsKey(downloads_, global_id)) |
| 418 return; | 426 return; |
| 419 | 427 |
| 420 DownloadFile* download_file = downloads_[global_id]; | 428 DownloadFile* download_file = downloads_[global_id]; |
| 421 | 429 |
| 422 VLOG(20) << " " << __FUNCTION__ << "()" | 430 VLOG(20) << " " << __FUNCTION__ << "()" |
| 423 << " id = " << global_id | 431 << " id = " << global_id |
| 424 << " download_file = " << download_file->DebugString(); | 432 << " download_file = " << download_file->DebugString(); |
| 425 | 433 |
| 426 downloads_.erase(global_id); | 434 downloads_.erase(global_id); |
| 427 | 435 |
| 428 delete download_file; | 436 delete download_file; |
| 429 | 437 |
| 430 if (downloads_.empty()) | 438 if (downloads_.empty()) |
| 431 StopUpdateTimer(); | 439 StopUpdateTimer(); |
| 432 } | 440 } |
| OLD | NEW |