| 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" |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 const int kUpdatePeriodMs = 500; | 37 const int kUpdatePeriodMs = 500; |
| 38 | 38 |
| 39 class DownloadFileFactoryImpl | 39 class DownloadFileFactoryImpl |
| 40 : public DownloadFileManager::DownloadFileFactory { | 40 : public DownloadFileManager::DownloadFileFactory { |
| 41 public: | 41 public: |
| 42 DownloadFileFactoryImpl() {} | 42 DownloadFileFactoryImpl() {} |
| 43 | 43 |
| 44 virtual content::DownloadFile* CreateFile( | 44 virtual content::DownloadFile* CreateFile( |
| 45 DownloadCreateInfo* info, | 45 DownloadCreateInfo* info, |
| 46 const DownloadRequestHandle& request_handle, | 46 const DownloadRequestHandle& request_handle, |
| 47 content::DownloadManager* download_manager) OVERRIDE; | 47 content::DownloadManager* download_manager, |
| 48 bool calculate_hash) OVERRIDE; |
| 48 }; | 49 }; |
| 49 | 50 |
| 50 DownloadFile* DownloadFileFactoryImpl::CreateFile( | 51 DownloadFile* DownloadFileFactoryImpl::CreateFile( |
| 51 DownloadCreateInfo* info, | 52 DownloadCreateInfo* info, |
| 52 const DownloadRequestHandle& request_handle, | 53 const DownloadRequestHandle& request_handle, |
| 53 content::DownloadManager* download_manager) { | 54 content::DownloadManager* download_manager, |
| 55 bool calculate_hash) { |
| 54 return new DownloadFileImpl(info, | 56 return new DownloadFileImpl(info, |
| 55 new DownloadRequestHandle(request_handle), | 57 new DownloadRequestHandle(request_handle), |
| 56 download_manager); | 58 download_manager, calculate_hash); |
| 57 } | 59 } |
| 58 | 60 |
| 59 } // namespace | 61 } // namespace |
| 60 | 62 |
| 61 DownloadFileManager::DownloadFileManager(ResourceDispatcherHost* rdh, | 63 DownloadFileManager::DownloadFileManager(ResourceDispatcherHost* rdh, |
| 62 DownloadFileFactory* factory) | 64 DownloadFileFactory* factory) |
| 63 : resource_dispatcher_host_(rdh), download_file_factory_(factory) { | 65 : resource_dispatcher_host_(rdh), download_file_factory_(factory) { |
| 64 if (download_file_factory_ == NULL) | 66 if (download_file_factory_ == NULL) |
| 65 download_file_factory_.reset(new DownloadFileFactoryImpl); | 67 download_file_factory_.reset(new DownloadFileFactoryImpl); |
| 66 } | 68 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 86 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle, | 88 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle, |
| 87 content::DownloadManager* download_manager, bool get_hash) { | 89 content::DownloadManager* download_manager, bool get_hash) { |
| 88 DCHECK(info); | 90 DCHECK(info); |
| 89 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); | 91 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); |
| 90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 91 | 93 |
| 92 // Life of |info| ends here. No more references to it after this method. | 94 // Life of |info| ends here. No more references to it after this method. |
| 93 scoped_ptr<DownloadCreateInfo> infop(info); | 95 scoped_ptr<DownloadCreateInfo> infop(info); |
| 94 | 96 |
| 95 scoped_ptr<DownloadFile> download_file(download_file_factory_->CreateFile( | 97 scoped_ptr<DownloadFile> download_file(download_file_factory_->CreateFile( |
| 96 info, request_handle, download_manager)); | 98 info, request_handle, download_manager, get_hash)); |
| 97 if (net::OK != download_file->Initialize(get_hash)) { | 99 if (net::OK != download_file->Initialize()) { |
| 98 request_handle.CancelRequest(); | 100 request_handle.CancelRequest(); |
| 99 return; | 101 return; |
| 100 } | 102 } |
| 101 | 103 |
| 102 DCHECK(GetDownloadFile(info->download_id) == NULL); | 104 DCHECK(GetDownloadFile(info->download_id) == NULL); |
| 103 downloads_[info->download_id] = download_file.release(); | 105 downloads_[info->download_id] = download_file.release(); |
| 104 | 106 |
| 105 // The file is now ready, we can un-pause the request and start saving data. | 107 // The file is now ready, we can un-pause the request and start saving data. |
| 106 request_handle.ResumeRequest(); | 108 request_handle.ResumeRequest(); |
| 107 | 109 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 135 | 137 |
| 136 void DownloadFileManager::UpdateInProgressDownloads() { | 138 void DownloadFileManager::UpdateInProgressDownloads() { |
| 137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 138 for (DownloadFileMap::iterator i = downloads_.begin(); | 140 for (DownloadFileMap::iterator i = downloads_.begin(); |
| 139 i != downloads_.end(); ++i) { | 141 i != downloads_.end(); ++i) { |
| 140 DownloadId global_id = i->first; | 142 DownloadId global_id = i->first; |
| 141 DownloadFile* download_file = i->second; | 143 DownloadFile* download_file = i->second; |
| 142 content::DownloadManager* manager = download_file->GetDownloadManager(); | 144 content::DownloadManager* manager = download_file->GetDownloadManager(); |
| 143 if (manager) { | 145 if (manager) { |
| 144 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 146 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 145 base::Bind(&content::DownloadManager::UpdateDownload, manager, | 147 base::Bind(&content::DownloadManager::UpdateDownload, |
| 146 global_id.local(), download_file->BytesSoFar(), | 148 manager, |
| 147 download_file->CurrentSpeed())); | 149 global_id.local(), |
| 150 download_file->BytesSoFar(), |
| 151 download_file->CurrentSpeed(), |
| 152 download_file->GetHashState())); |
| 148 } | 153 } |
| 149 } | 154 } |
| 150 } | 155 } |
| 151 | 156 |
| 152 void DownloadFileManager::StartDownload( | 157 void DownloadFileManager::StartDownload( |
| 153 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle) { | 158 DownloadCreateInfo* info, const DownloadRequestHandle& request_handle) { |
| 154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 155 DCHECK(info); | 160 DCHECK(info); |
| 156 | 161 |
| 157 content::DownloadManager* manager = request_handle.GetDownloadManager(); | 162 content::DownloadManager* manager = request_handle.GetDownloadManager(); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 if (!had_error && download_file) { | 195 if (!had_error && download_file) { |
| 191 net::Error write_result = | 196 net::Error write_result = |
| 192 download_file->AppendDataToFile(data->data(), data_len); | 197 download_file->AppendDataToFile(data->data(), data_len); |
| 193 if (write_result != net::OK) { | 198 if (write_result != net::OK) { |
| 194 // Write failed: interrupt the download. | 199 // Write failed: interrupt the download. |
| 195 content::DownloadManager* download_manager = | 200 content::DownloadManager* download_manager = |
| 196 download_file->GetDownloadManager(); | 201 download_file->GetDownloadManager(); |
| 197 had_error = true; | 202 had_error = true; |
| 198 | 203 |
| 199 int64 bytes_downloaded = download_file->BytesSoFar(); | 204 int64 bytes_downloaded = download_file->BytesSoFar(); |
| 205 std::string hash_state(download_file->GetHashState()); |
| 206 |
| 200 // Calling this here in case we get more data, to avoid | 207 // Calling this here in case we get more data, to avoid |
| 201 // processing data after an error. That could lead to | 208 // processing data after an error. That could lead to |
| 202 // files that are corrupted if the later processing succeeded. | 209 // files that are corrupted if the later processing succeeded. |
| 203 CancelDownload(global_id); | 210 CancelDownload(global_id); |
| 204 download_file = NULL; // Was deleted in |CancelDownload|. | 211 download_file = NULL; // Was deleted in |CancelDownload|. |
| 205 | 212 |
| 206 if (download_manager) { | 213 if (download_manager) { |
| 207 BrowserThread::PostTask( | 214 BrowserThread::PostTask( |
| 208 BrowserThread::UI, FROM_HERE, | 215 BrowserThread::UI, FROM_HERE, |
| 209 base::Bind(&content::DownloadManager::OnDownloadInterrupted, | 216 base::Bind(&content::DownloadManager::OnDownloadInterrupted, |
| 210 download_manager, global_id.local(), bytes_downloaded, | 217 download_manager, |
| 218 global_id.local(), |
| 219 bytes_downloaded, |
| 220 hash_state, |
| 211 ConvertNetErrorToInterruptReason( | 221 ConvertNetErrorToInterruptReason( |
| 212 write_result, DOWNLOAD_INTERRUPT_FROM_DISK))); | 222 write_result, |
| 223 DOWNLOAD_INTERRUPT_FROM_DISK))); |
| 213 } | 224 } |
| 214 } | 225 } |
| 215 } | 226 } |
| 216 data->Release(); | 227 data->Release(); |
| 217 } | 228 } |
| 218 } | 229 } |
| 219 | 230 |
| 220 void DownloadFileManager::OnResponseCompleted( | 231 void DownloadFileManager::OnResponseCompleted( |
| 221 DownloadId global_id, | 232 DownloadId global_id, |
| 222 InterruptReason reason, | 233 InterruptReason reason, |
| 223 const std::string& security_info) { | 234 const std::string& security_info) { |
| 224 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id | 235 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id |
| 225 << " reason = " << InterruptReasonDebugString(reason) | 236 << " reason = " << InterruptReasonDebugString(reason) |
| 226 << " security_info = \"" << security_info << "\""; | 237 << " security_info = \"" << security_info << "\""; |
| 227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 228 DownloadFile* download_file = GetDownloadFile(global_id); | 239 DownloadFile* download_file = GetDownloadFile(global_id); |
| 229 if (!download_file) | 240 if (!download_file) |
| 230 return; | 241 return; |
| 231 | 242 |
| 232 download_file->Finish(); | 243 download_file->Finish(); |
| 233 | 244 |
| 234 content::DownloadManager* download_manager = | 245 content::DownloadManager* download_manager = |
| 235 download_file->GetDownloadManager(); | 246 download_file->GetDownloadManager(); |
| 236 if (!download_manager) { | 247 if (!download_manager) { |
| 237 CancelDownload(global_id); | 248 CancelDownload(global_id); |
| 238 return; | 249 return; |
| 239 } | 250 } |
| 240 | 251 |
| 241 std::string hash; | 252 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) { |
| 242 if (!download_file->GetSha256Hash(&hash) || BaseFile::IsEmptySha256Hash(hash)) | 253 std::string hash; |
| 243 hash.clear(); | 254 if (!download_file->GetHash(&hash) || |
| 255 BaseFile::IsEmptyHash(hash)) { |
| 256 hash.clear(); |
| 257 } |
| 244 | 258 |
| 245 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) { | |
| 246 BrowserThread::PostTask( | 259 BrowserThread::PostTask( |
| 247 BrowserThread::UI, FROM_HERE, | 260 BrowserThread::UI, FROM_HERE, |
| 248 base::Bind(&content::DownloadManager::OnResponseCompleted, | 261 base::Bind(&content::DownloadManager::OnResponseCompleted, |
| 249 download_manager, global_id.local(), | 262 download_manager, global_id.local(), |
| 250 download_file->BytesSoFar(), hash)); | 263 download_file->BytesSoFar(), hash)); |
| 251 } else { | 264 } else { |
| 252 BrowserThread::PostTask( | 265 BrowserThread::PostTask( |
| 253 BrowserThread::UI, FROM_HERE, | 266 BrowserThread::UI, FROM_HERE, |
| 254 base::Bind(&content::DownloadManager::OnDownloadInterrupted, | 267 base::Bind(&content::DownloadManager::OnDownloadInterrupted, |
| 255 download_manager, global_id.local(), | 268 download_manager, |
| 256 download_file->BytesSoFar(), reason)); | 269 global_id.local(), |
| 270 download_file->BytesSoFar(), |
| 271 download_file->GetHashState(), |
| 272 reason)); |
| 257 } | 273 } |
| 258 // We need to keep the download around until the UI thread has finalized | 274 // We need to keep the download around until the UI thread has finalized |
| 259 // the name. | 275 // the name. |
| 260 } | 276 } |
| 261 | 277 |
| 262 // This method will be sent via a user action, or shutdown on the UI thread, and | 278 // This method will be sent via a user action, or shutdown on the UI thread, and |
| 263 // run on the download thread. Since this message has been sent from the UI | 279 // run on the download thread. Since this message has been sent from the UI |
| 264 // thread, the download may have already completed and won't exist in our map. | 280 // thread, the download may have already completed and won't exist in our map. |
| 265 void DownloadFileManager::CancelDownload(DownloadId global_id) { | 281 void DownloadFileManager::CancelDownload(DownloadId global_id) { |
| 266 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id; | 282 VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id; |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 // Without a download manager, we can't cancel the request normally, so we | 442 // Without a download manager, we can't cancel the request normally, so we |
| 427 // need to do it here. The normal path will also update the download | 443 // need to do it here. The normal path will also update the download |
| 428 // history before canceling the request. | 444 // history before canceling the request. |
| 429 download_file->CancelDownloadRequest(); | 445 download_file->CancelDownloadRequest(); |
| 430 return; | 446 return; |
| 431 } | 447 } |
| 432 | 448 |
| 433 BrowserThread::PostTask( | 449 BrowserThread::PostTask( |
| 434 BrowserThread::UI, FROM_HERE, | 450 BrowserThread::UI, FROM_HERE, |
| 435 base::Bind(&content::DownloadManager::OnDownloadInterrupted, | 451 base::Bind(&content::DownloadManager::OnDownloadInterrupted, |
| 436 download_manager, global_id.local(), | 452 download_manager, |
| 453 global_id.local(), |
| 437 download_file->BytesSoFar(), | 454 download_file->BytesSoFar(), |
| 455 download_file->GetHashState(), |
| 438 ConvertNetErrorToInterruptReason( | 456 ConvertNetErrorToInterruptReason( |
| 439 rename_error, DOWNLOAD_INTERRUPT_FROM_DISK))); | 457 rename_error, |
| 458 DOWNLOAD_INTERRUPT_FROM_DISK))); |
| 440 } | 459 } |
| 441 | 460 |
| 442 void DownloadFileManager::EraseDownload(DownloadId global_id) { | 461 void DownloadFileManager::EraseDownload(DownloadId global_id) { |
| 443 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 444 | 463 |
| 445 if (!ContainsKey(downloads_, global_id)) | 464 if (!ContainsKey(downloads_, global_id)) |
| 446 return; | 465 return; |
| 447 | 466 |
| 448 DownloadFile* download_file = downloads_[global_id]; | 467 DownloadFile* download_file = downloads_[global_id]; |
| 449 | 468 |
| 450 VLOG(20) << " " << __FUNCTION__ << "()" | 469 VLOG(20) << " " << __FUNCTION__ << "()" |
| 451 << " id = " << global_id | 470 << " id = " << global_id |
| 452 << " download_file = " << download_file->DebugString(); | 471 << " download_file = " << download_file->DebugString(); |
| 453 | 472 |
| 454 downloads_.erase(global_id); | 473 downloads_.erase(global_id); |
| 455 | 474 |
| 456 delete download_file; | 475 delete download_file; |
| 457 | 476 |
| 458 if (downloads_.empty()) | 477 if (downloads_.empty()) |
| 459 StopUpdateTimer(); | 478 StopUpdateTimer(); |
| 460 } | 479 } |
| OLD | NEW |