| 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 "chrome/browser/download/download_file_manager.h" | 5 #include "chrome/browser/download/download_file_manager.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/stl_util-inl.h" | 9 #include "base/stl_util-inl.h" |
| 10 #include "base/task.h" | 10 #include "base/task.h" |
| 11 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
| 12 #include "build/build_config.h" | 12 #include "build/build_config.h" |
| 13 #include "chrome/browser/download/download_create_info.h" |
| 13 #include "chrome/browser/download/download_manager.h" | 14 #include "chrome/browser/download/download_manager.h" |
| 14 #include "chrome/browser/download/download_process_handle.h" | 15 #include "chrome/browser/download/download_process_handle.h" |
| 15 #include "chrome/browser/download/download_util.h" | 16 #include "chrome/browser/download/download_util.h" |
| 16 #include "chrome/browser/history/download_create_info.h" | |
| 17 #include "chrome/browser/net/chrome_url_request_context.h" | 17 #include "chrome/browser/net/chrome_url_request_context.h" |
| 18 #include "chrome/browser/platform_util.h" | 18 #include "chrome/browser/platform_util.h" |
| 19 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
| 20 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | 20 #include "chrome/browser/safe_browsing/safe_browsing_service.h" |
| 21 #include "chrome/browser/tab_contents/tab_util.h" | 21 #include "chrome/browser/tab_contents/tab_util.h" |
| 22 #include "content/browser/browser_thread.h" | 22 #include "content/browser/browser_thread.h" |
| 23 #include "content/browser/renderer_host/resource_dispatcher_host.h" | 23 #include "content/browser/renderer_host/resource_dispatcher_host.h" |
| 24 #include "content/browser/tab_contents/tab_contents.h" | 24 #include "content/browser/tab_contents/tab_contents.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" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 51 | 51 |
| 52 void DownloadFileManager::OnShutdown() { | 52 void DownloadFileManager::OnShutdown() { |
| 53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 54 StopUpdateTimer(); | 54 StopUpdateTimer(); |
| 55 STLDeleteValues(&downloads_); | 55 STLDeleteValues(&downloads_); |
| 56 } | 56 } |
| 57 | 57 |
| 58 void DownloadFileManager::CreateDownloadFile(DownloadCreateInfo* info, | 58 void DownloadFileManager::CreateDownloadFile(DownloadCreateInfo* info, |
| 59 DownloadManager* download_manager, | 59 DownloadManager* download_manager, |
| 60 bool get_hash) { | 60 bool get_hash) { |
| 61 DCHECK(info); |
| 61 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); | 62 VLOG(20) << __FUNCTION__ << "()" << " info = " << info->DebugString(); |
| 62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 63 | 64 |
| 65 // Life of |info| ends here. No more references to it after this method. |
| 66 scoped_ptr<DownloadCreateInfo> infop(info); |
| 67 |
| 64 scoped_ptr<DownloadFile> | 68 scoped_ptr<DownloadFile> |
| 65 download_file(new DownloadFile(info, download_manager)); | 69 download_file(new DownloadFile(info, download_manager)); |
| 66 if (!download_file->Initialize(get_hash)) { | 70 if (!download_file->Initialize(get_hash)) { |
| 67 download_util::CancelDownloadRequest(resource_dispatcher_host_, | 71 download_util::CancelDownloadRequest(resource_dispatcher_host_, |
| 68 info->process_handle); | 72 info->process_handle); |
| 69 delete info; | |
| 70 return; | 73 return; |
| 71 } | 74 } |
| 72 | 75 |
| 73 DCHECK(GetDownloadFile(info->download_id) == NULL); | 76 int32 id = info->download_id; |
| 74 downloads_[info->download_id] = download_file.release(); | 77 DCHECK(GetDownloadFile(id) == NULL); |
| 75 // TODO(phajdan.jr): fix the duplication of path info below. | 78 downloads_[id] = download_file.release(); |
| 76 info->path = info->save_info.file_path; | |
| 77 | 79 |
| 78 // The file is now ready, we can un-pause the request and start saving data. | 80 // The file is now ready, we can un-pause the request and start saving data. |
| 79 BrowserThread::PostTask( | 81 BrowserThread::PostTask( |
| 80 BrowserThread::IO, FROM_HERE, | 82 BrowserThread::IO, FROM_HERE, |
| 81 NewRunnableMethod(this, &DownloadFileManager::ResumeDownloadRequest, | 83 NewRunnableMethod(this, &DownloadFileManager::ResumeDownloadRequest, |
| 82 info->process_handle)); | 84 info->process_handle)); |
| 83 | 85 |
| 84 StartUpdateTimer(); | 86 StartUpdateTimer(); |
| 85 | 87 |
| 86 BrowserThread::PostTask( | 88 BrowserThread::PostTask( |
| 87 BrowserThread::UI, FROM_HERE, | 89 BrowserThread::UI, FROM_HERE, |
| 88 NewRunnableMethod(download_manager, | 90 NewRunnableMethod(download_manager, |
| 89 &DownloadManager::StartDownload, info)); | 91 &DownloadManager::StartDownload, id)); |
| 90 } | 92 } |
| 91 | 93 |
| 92 void DownloadFileManager::ResumeDownloadRequest( | 94 void DownloadFileManager::ResumeDownloadRequest( |
| 93 DownloadProcessHandle process) { | 95 DownloadProcessHandle process) { |
| 94 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 96 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 95 | 97 |
| 96 // This balances the pause in DownloadResourceHandler::OnResponseStarted. | 98 // This balances the pause in DownloadResourceHandler::OnResponseStarted. |
| 97 resource_dispatcher_host_->PauseRequest(process.child_id(), | 99 resource_dispatcher_host_->PauseRequest(process.child_id(), |
| 98 process.request_id(), | 100 process.request_id(), |
| 99 false); | 101 false); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 DCHECK(info); | 146 DCHECK(info); |
| 145 | 147 |
| 146 DownloadManager* manager = info->process_handle.GetDownloadManager(); | 148 DownloadManager* manager = info->process_handle.GetDownloadManager(); |
| 147 if (!manager) { | 149 if (!manager) { |
| 148 download_util::CancelDownloadRequest(resource_dispatcher_host_, | 150 download_util::CancelDownloadRequest(resource_dispatcher_host_, |
| 149 info->process_handle); | 151 info->process_handle); |
| 150 delete info; | 152 delete info; |
| 151 return; | 153 return; |
| 152 } | 154 } |
| 153 | 155 |
| 156 // TODO(phajdan.jr): fix the duplication of path info below. |
| 157 info->path = info->save_info.file_path; |
| 158 |
| 154 manager->CreateDownloadItem(info); | 159 manager->CreateDownloadItem(info); |
| 155 | 160 |
| 156 bool hash_needed = resource_dispatcher_host_->safe_browsing_service()-> | 161 bool hash_needed = resource_dispatcher_host_->safe_browsing_service()-> |
| 157 DownloadBinHashNeeded(); | 162 DownloadBinHashNeeded(); |
| 158 | 163 |
| 159 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 164 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 160 NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile, | 165 NewRunnableMethod(this, &DownloadFileManager::CreateDownloadFile, |
| 161 info, | 166 info, make_scoped_refptr(manager), hash_needed)); |
| 162 make_scoped_refptr(manager), hash_needed)); | |
| 163 } | 167 } |
| 164 | 168 |
| 165 // We don't forward an update to the UI thread here, since we want to throttle | 169 // We don't forward an update to the UI thread here, since we want to throttle |
| 166 // the UI update rate via a periodic timer. If the user has cancelled the | 170 // the UI update rate via a periodic timer. If the user has cancelled the |
| 167 // download (in the UI thread), we may receive a few more updates before the IO | 171 // download (in the UI thread), we may receive a few more updates before the IO |
| 168 // thread gets the cancel message: we just delete the data since the | 172 // thread gets the cancel message: we just delete the data since the |
| 169 // DownloadFile has been deleted. | 173 // DownloadFile has been deleted. |
| 170 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) { | 174 void DownloadFileManager::UpdateDownload(int id, DownloadBuffer* buffer) { |
| 171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 172 std::vector<DownloadBuffer::Contents> contents; | 176 std::vector<DownloadBuffer::Contents> contents; |
| 173 { | 177 { |
| 174 base::AutoLock auto_lock(buffer->lock); | 178 base::AutoLock auto_lock(buffer->lock); |
| 175 contents.swap(buffer->contents); | 179 contents.swap(buffer->contents); |
| 176 } | 180 } |
| 177 | 181 |
| 178 DownloadFile* download = GetDownloadFile(id); | 182 DownloadFile* download_file = GetDownloadFile(id); |
| 179 for (size_t i = 0; i < contents.size(); ++i) { | 183 for (size_t i = 0; i < contents.size(); ++i) { |
| 180 net::IOBuffer* data = contents[i].first; | 184 net::IOBuffer* data = contents[i].first; |
| 181 const int data_len = contents[i].second; | 185 const int data_len = contents[i].second; |
| 182 if (download) | 186 if (download_file) |
| 183 download->AppendDataToFile(data->data(), data_len); | 187 download_file->AppendDataToFile(data->data(), data_len); |
| 184 data->Release(); | 188 data->Release(); |
| 185 } | 189 } |
| 186 } | 190 } |
| 187 | 191 |
| 188 void DownloadFileManager::OnResponseCompleted( | 192 void DownloadFileManager::OnResponseCompleted( |
| 189 int id, | 193 int id, |
| 190 DownloadBuffer* buffer, | 194 DownloadBuffer* buffer, |
| 191 int os_error, | 195 int os_error, |
| 192 const std::string& security_info) { | 196 const std::string& security_info) { |
| 193 VLOG(20) << __FUNCTION__ << "()" << " id = " << id | 197 VLOG(20) << __FUNCTION__ << "()" << " id = " << id |
| 194 << " os_error = " << os_error | 198 << " os_error = " << os_error |
| 195 << " security_info = \"" << security_info << "\""; | 199 << " security_info = \"" << security_info << "\""; |
| 196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 197 delete buffer; | 201 delete buffer; |
| 198 DownloadFile* download = GetDownloadFile(id); | 202 DownloadFile* download_file = GetDownloadFile(id); |
| 199 if (!download) | 203 if (!download_file) |
| 200 return; | 204 return; |
| 201 | 205 |
| 202 download->Finish(); | 206 download_file->Finish(); |
| 203 | 207 |
| 204 DownloadManager* download_manager = download->GetDownloadManager(); | 208 DownloadManager* download_manager = download_file->GetDownloadManager(); |
| 205 if (!download_manager) { | 209 if (!download_manager) { |
| 206 CancelDownload(id); | 210 CancelDownload(id); |
| 207 return; | 211 return; |
| 208 } | 212 } |
| 209 | 213 |
| 210 std::string hash; | 214 std::string hash; |
| 211 if (!download->GetSha256Hash(&hash)) | 215 if (!download_file->GetSha256Hash(&hash)) |
| 212 hash.clear(); | 216 hash.clear(); |
| 213 | 217 |
| 214 BrowserThread::PostTask( | 218 BrowserThread::PostTask( |
| 215 BrowserThread::UI, FROM_HERE, | 219 BrowserThread::UI, FROM_HERE, |
| 216 NewRunnableMethod( | 220 NewRunnableMethod( |
| 217 download_manager, &DownloadManager::OnResponseCompleted, | 221 download_manager, &DownloadManager::OnResponseCompleted, |
| 218 id, download->bytes_so_far(), os_error, hash)); | 222 id, download_file->bytes_so_far(), os_error, hash)); |
| 219 // We need to keep the download around until the UI thread has finalized | 223 // We need to keep the download around until the UI thread has finalized |
| 220 // the name. | 224 // the name. |
| 221 } | 225 } |
| 222 | 226 |
| 223 // This method will be sent via a user action, or shutdown on the UI thread, and | 227 // This method will be sent via a user action, or shutdown on the UI thread, and |
| 224 // run on the download thread. Since this message has been sent from the UI | 228 // run on the download thread. Since this message has been sent from the UI |
| 225 // thread, the download may have already completed and won't exist in our map. | 229 // thread, the download may have already completed and won't exist in our map. |
| 226 void DownloadFileManager::CancelDownload(int id) { | 230 void DownloadFileManager::CancelDownload(int id) { |
| 227 VLOG(20) << __FUNCTION__ << "()" << " id = " << id; | 231 VLOG(20) << __FUNCTION__ << "()" << " id = " << id; |
| 228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 229 DownloadFileMap::iterator it = downloads_.find(id); | 233 DownloadFileMap::iterator it = downloads_.find(id); |
| 230 if (it == downloads_.end()) | 234 if (it == downloads_.end()) |
| 231 return; | 235 return; |
| 232 | 236 |
| 233 DownloadFile* download = it->second; | 237 DownloadFile* download_file = it->second; |
| 234 VLOG(20) << __FUNCTION__ << "()" | 238 VLOG(20) << __FUNCTION__ << "()" |
| 235 << " download = " << download->DebugString(); | 239 << " download_file = " << download_file->DebugString(); |
| 236 download->Cancel(); | 240 download_file->Cancel(); |
| 237 | 241 |
| 238 EraseDownload(id); | 242 EraseDownload(id); |
| 239 } | 243 } |
| 240 | 244 |
| 241 void DownloadFileManager::CompleteDownload(int id) { | 245 void DownloadFileManager::CompleteDownload(int id) { |
| 242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 243 | 247 |
| 244 if (!ContainsKey(downloads_, id)) | 248 if (!ContainsKey(downloads_, id)) |
| 245 return; | 249 return; |
| 246 | 250 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 // | 288 // |
| 285 // There are 2 possible rename cases where this method can be called: | 289 // There are 2 possible rename cases where this method can be called: |
| 286 // 1. tmp -> foo.crdownload (not final, safe) | 290 // 1. tmp -> foo.crdownload (not final, safe) |
| 287 // 2. tmp-> Unconfirmed.xxx.crdownload (not final, dangerous) | 291 // 2. tmp-> Unconfirmed.xxx.crdownload (not final, dangerous) |
| 288 void DownloadFileManager::RenameInProgressDownloadFile( | 292 void DownloadFileManager::RenameInProgressDownloadFile( |
| 289 int id, const FilePath& full_path) { | 293 int id, const FilePath& full_path) { |
| 290 VLOG(20) << __FUNCTION__ << "()" << " id = " << id | 294 VLOG(20) << __FUNCTION__ << "()" << " id = " << id |
| 291 << " full_path = \"" << full_path.value() << "\""; | 295 << " full_path = \"" << full_path.value() << "\""; |
| 292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 296 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 293 | 297 |
| 294 DownloadFile* download = GetDownloadFile(id); | 298 DownloadFile* download_file = GetDownloadFile(id); |
| 295 if (!download) | 299 if (!download_file) |
| 296 return; | 300 return; |
| 297 | 301 |
| 298 VLOG(20) << __FUNCTION__ << "()" << " download = " << download->DebugString(); | 302 VLOG(20) << __FUNCTION__ << "()" |
| 303 << " download_file = " << download_file->DebugString(); |
| 299 | 304 |
| 300 if (!download->Rename(full_path)) { | 305 if (!download_file->Rename(full_path)) { |
| 301 // Error. Between the time the UI thread generated 'full_path' to the time | 306 // Error. Between the time the UI thread generated 'full_path' to the time |
| 302 // this code runs, something happened that prevents us from renaming. | 307 // this code runs, something happened that prevents us from renaming. |
| 303 CancelDownloadOnRename(id); | 308 CancelDownloadOnRename(id); |
| 304 } | 309 } |
| 305 } | 310 } |
| 306 | 311 |
| 307 // The DownloadManager in the UI thread has provided a final name for the | 312 // The DownloadManager in the UI thread has provided a final name for the |
| 308 // download specified by 'id'. Rename the download that's in the process | 313 // download specified by 'id'. Rename the download that's in the process |
| 309 // of completing. | 314 // of completing. |
| 310 // | 315 // |
| 311 // There are 2 possible rename cases where this method can be called: | 316 // There are 2 possible rename cases where this method can be called: |
| 312 // 1. foo.crdownload -> foo (final, safe) | 317 // 1. foo.crdownload -> foo (final, safe) |
| 313 // 2. Unconfirmed.xxx.crdownload -> xxx (final, validated) | 318 // 2. Unconfirmed.xxx.crdownload -> xxx (final, validated) |
| 314 void DownloadFileManager::RenameCompletingDownloadFile( | 319 void DownloadFileManager::RenameCompletingDownloadFile( |
| 315 int id, const FilePath& full_path, bool overwrite_existing_file) { | 320 int id, const FilePath& full_path, bool overwrite_existing_file) { |
| 316 VLOG(20) << __FUNCTION__ << "()" << " id = " << id | 321 VLOG(20) << __FUNCTION__ << "()" << " id = " << id |
| 317 << " overwrite_existing_file = " << overwrite_existing_file | 322 << " overwrite_existing_file = " << overwrite_existing_file |
| 318 << " full_path = \"" << full_path.value() << "\""; | 323 << " full_path = \"" << full_path.value() << "\""; |
| 319 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 320 | 325 |
| 321 DownloadFile* download = GetDownloadFile(id); | 326 DownloadFile* download_file = GetDownloadFile(id); |
| 322 if (!download) | 327 if (!download_file) |
| 323 return; | 328 return; |
| 324 | 329 |
| 325 DCHECK(download->GetDownloadManager()); | 330 DCHECK(download_file->GetDownloadManager()); |
| 326 DownloadManager* download_manager = download->GetDownloadManager(); | 331 DownloadManager* download_manager = download_file->GetDownloadManager(); |
| 327 | 332 |
| 328 VLOG(20) << __FUNCTION__ << "()" << " download = " << download->DebugString(); | 333 VLOG(20) << __FUNCTION__ << "()" |
| 334 << " download_file = " << download_file->DebugString(); |
| 329 | 335 |
| 330 int uniquifier = 0; | 336 int uniquifier = 0; |
| 331 FilePath new_path = full_path; | 337 FilePath new_path = full_path; |
| 332 if (!overwrite_existing_file) { | 338 if (!overwrite_existing_file) { |
| 333 // Make our name unique at this point, as if a dangerous file is | 339 // Make our name unique at this point, as if a dangerous file is |
| 334 // downloading and a 2nd download is started for a file with the same | 340 // downloading and a 2nd download is started for a file with the same |
| 335 // name, they would have the same path. This is because we uniquify | 341 // name, they would have the same path. This is because we uniquify |
| 336 // the name on download start, and at that time the first file does | 342 // the name on download start, and at that time the first file does |
| 337 // not exists yet, so the second file gets the same name. | 343 // not exists yet, so the second file gets the same name. |
| 338 // This should not happen in the SAFE case, and we check for that in the UI | 344 // This should not happen in the SAFE case, and we check for that in the UI |
| 339 // thread. | 345 // thread. |
| 340 uniquifier = download_util::GetUniquePathNumber(new_path); | 346 uniquifier = download_util::GetUniquePathNumber(new_path); |
| 341 if (uniquifier > 0) { | 347 if (uniquifier > 0) { |
| 342 download_util::AppendNumberToPath(&new_path, uniquifier); | 348 download_util::AppendNumberToPath(&new_path, uniquifier); |
| 343 } | 349 } |
| 344 } | 350 } |
| 345 | 351 |
| 346 // Rename the file, overwriting if necessary. | 352 // Rename the file, overwriting if necessary. |
| 347 if (!download->Rename(new_path)) { | 353 if (!download_file->Rename(new_path)) { |
| 348 // Error. Between the time the UI thread generated 'full_path' to the time | 354 // Error. Between the time the UI thread generated 'full_path' to the time |
| 349 // this code runs, something happened that prevents us from renaming. | 355 // this code runs, something happened that prevents us from renaming. |
| 350 CancelDownloadOnRename(id); | 356 CancelDownloadOnRename(id); |
| 351 return; | 357 return; |
| 352 } | 358 } |
| 353 | 359 |
| 354 #if defined(OS_MACOSX) | 360 #if defined(OS_MACOSX) |
| 355 // Done here because we only want to do this once; see | 361 // Done here because we only want to do this once; see |
| 356 // http://crbug.com/13120 for details. | 362 // http://crbug.com/13120 for details. |
| 357 download->AnnotateWithSourceInformation(); | 363 download_file->AnnotateWithSourceInformation(); |
| 358 #endif | 364 #endif |
| 359 | 365 |
| 360 BrowserThread::PostTask( | 366 BrowserThread::PostTask( |
| 361 BrowserThread::UI, FROM_HERE, | 367 BrowserThread::UI, FROM_HERE, |
| 362 NewRunnableMethod( | 368 NewRunnableMethod( |
| 363 download_manager, &DownloadManager::OnDownloadRenamedToFinalName, id, | 369 download_manager, &DownloadManager::OnDownloadRenamedToFinalName, id, |
| 364 new_path, uniquifier)); | 370 new_path, uniquifier)); |
| 365 } | 371 } |
| 366 | 372 |
| 367 // Called only from RenameInProgressDownloadFile and | 373 // Called only from RenameInProgressDownloadFile and |
| 368 // RenameCompletingDownloadFile on the FILE thread. | 374 // RenameCompletingDownloadFile on the FILE thread. |
| 369 void DownloadFileManager::CancelDownloadOnRename(int id) { | 375 void DownloadFileManager::CancelDownloadOnRename(int id) { |
| 370 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 371 | 377 |
| 372 DownloadFile* download = GetDownloadFile(id); | 378 DownloadFile* download_file = GetDownloadFile(id); |
| 373 if (!download) | 379 if (!download_file) |
| 374 return; | 380 return; |
| 375 | 381 |
| 376 DownloadManager* download_manager = download->GetDownloadManager(); | 382 DownloadManager* download_manager = download_file->GetDownloadManager(); |
| 377 if (!download_manager) { | 383 if (!download_manager) { |
| 378 // Without a download manager, we can't cancel the request normally, so we | 384 // Without a download manager, we can't cancel the request normally, so we |
| 379 // need to do it here. The normal path will also update the download | 385 // need to do it here. The normal path will also update the download |
| 380 // history before cancelling the request. | 386 // history before cancelling the request. |
| 381 download->CancelDownloadRequest(resource_dispatcher_host_); | 387 download_file->CancelDownloadRequest(resource_dispatcher_host_); |
| 382 return; | 388 return; |
| 383 } | 389 } |
| 384 | 390 |
| 385 BrowserThread::PostTask( | 391 BrowserThread::PostTask( |
| 386 BrowserThread::UI, FROM_HERE, | 392 BrowserThread::UI, FROM_HERE, |
| 387 NewRunnableMethod(download_manager, | 393 NewRunnableMethod(download_manager, |
| 388 &DownloadManager::DownloadCancelled, id)); | 394 &DownloadManager::DownloadCancelled, id)); |
| 389 } | 395 } |
| 390 | 396 |
| 391 void DownloadFileManager::EraseDownload(int id) { | 397 void DownloadFileManager::EraseDownload(int id) { |
| 392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 398 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 393 | 399 |
| 394 if (!ContainsKey(downloads_, id)) | 400 if (!ContainsKey(downloads_, id)) |
| 395 return; | 401 return; |
| 396 | 402 |
| 397 DownloadFile* download_file = downloads_[id]; | 403 DownloadFile* download_file = downloads_[id]; |
| 398 | 404 |
| 399 VLOG(20) << " " << __FUNCTION__ << "()" | 405 VLOG(20) << " " << __FUNCTION__ << "()" |
| 400 << " id = " << id | 406 << " id = " << id |
| 401 << " download_file = " << download_file->DebugString(); | 407 << " download_file = " << download_file->DebugString(); |
| 402 | 408 |
| 403 downloads_.erase(id); | 409 downloads_.erase(id); |
| 404 | 410 |
| 405 delete download_file; | 411 delete download_file; |
| 406 | 412 |
| 407 if (downloads_.empty()) | 413 if (downloads_.empty()) |
| 408 StopUpdateTimer(); | 414 StopUpdateTimer(); |
| 409 } | 415 } |
| OLD | NEW |