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