OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_manager.h" | 5 #include "chrome/browser/download/download_manager.h" |
6 | 6 |
7 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
8 #include "app/resource_bundle.h" | 8 #include "app/resource_bundle.h" |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 | 68 |
69 if (file_manager_) { | 69 if (file_manager_) { |
70 ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE, | 70 ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE, |
71 NewRunnableMethod(file_manager_, | 71 NewRunnableMethod(file_manager_, |
72 &DownloadFileManager::OnDownloadManagerShutdown, | 72 &DownloadFileManager::OnDownloadManagerShutdown, |
73 this)); | 73 this)); |
74 } | 74 } |
75 | 75 |
76 // 'in_progress_' may contain DownloadItems that have not finished the start | 76 // 'in_progress_' may contain DownloadItems that have not finished the start |
77 // complete (from the history service) and thus aren't in downloads_. | 77 // complete (from the history service) and thus aren't in downloads_. |
| 78 // It may also contain DownloadItems that have been interrupted. |
78 DownloadMap::iterator it = in_progress_.begin(); | 79 DownloadMap::iterator it = in_progress_.begin(); |
79 std::set<DownloadItem*> to_remove; | 80 std::set<DownloadItem*> to_remove; |
80 for (; it != in_progress_.end(); ++it) { | 81 for (; it != in_progress_.end(); ++it) { |
81 DownloadItem* download = it->second; | 82 DownloadItem* download = it->second; |
82 if (download->safety_state() == DownloadItem::DANGEROUS) { | 83 if (download->safety_state() == DownloadItem::DANGEROUS) { |
83 // Forget about any download that the user did not approve. | 84 // Forget about any download that the user did not approve. |
84 // Note that we cannot call download->Remove() this would invalidate our | 85 // Note that we cannot call download->Remove() this would invalidate our |
85 // iterator. | 86 // iterator. |
86 to_remove.insert(download); | 87 to_remove.insert(download); |
87 continue; | 88 continue; |
88 } | 89 } |
89 DCHECK_EQ(DownloadItem::IN_PROGRESS, download->state()); | 90 DCHECK(download->IsPartialDownload()); |
90 download->Cancel(false); | 91 download->Cancel(false); |
91 download_history_->UpdateEntry(download); | 92 download_history_->UpdateEntry(download); |
92 if (download->db_handle() == DownloadHistory::kUninitializedHandle) { | 93 if (download->db_handle() == DownloadHistory::kUninitializedHandle) { |
93 // An invalid handle means that 'download' does not yet exist in | 94 // An invalid handle means that 'download' does not yet exist in |
94 // 'downloads_', so we have to delete it here. | 95 // 'downloads_', so we have to delete it here. |
95 delete download; | 96 delete download; |
96 } | 97 } |
97 } | 98 } |
98 | 99 |
99 // 'dangerous_finished_' contains all complete downloads that have not been | 100 // 'dangerous_finished_' contains all complete downloads that have not been |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 } | 162 } |
162 } | 163 } |
163 | 164 |
164 void DownloadManager::GetCurrentDownloads( | 165 void DownloadManager::GetCurrentDownloads( |
165 const FilePath& dir_path, std::vector<DownloadItem*>* result) { | 166 const FilePath& dir_path, std::vector<DownloadItem*>* result) { |
166 DCHECK(result); | 167 DCHECK(result); |
167 | 168 |
168 for (DownloadMap::iterator it = downloads_.begin(); | 169 for (DownloadMap::iterator it = downloads_.begin(); |
169 it != downloads_.end(); ++it) { | 170 it != downloads_.end(); ++it) { |
170 if (!it->second->is_temporary() && | 171 if (!it->second->is_temporary() && |
171 (it->second->state() == DownloadItem::IN_PROGRESS || | 172 (it->second->IsPartialDownload() || |
172 it->second->safety_state() == DownloadItem::DANGEROUS) && | 173 (it->second->safety_state() == DownloadItem::DANGEROUS)) && |
173 (dir_path.empty() || it->second->full_path().DirName() == dir_path)) | 174 (dir_path.empty() || |
| 175 (it->second->full_path().DirName() == dir_path))) { |
174 result->push_back(it->second); | 176 result->push_back(it->second); |
| 177 } |
175 } | 178 } |
176 } | 179 } |
177 | 180 |
178 void DownloadManager::SearchDownloads(const string16& query, | 181 void DownloadManager::SearchDownloads(const string16& query, |
179 std::vector<DownloadItem*>* result) { | 182 std::vector<DownloadItem*>* result) { |
180 DCHECK(result); | 183 DCHECK(result); |
181 | 184 |
182 string16 query_lower(l10n_util::ToLower(query)); | 185 string16 query_lower(l10n_util::ToLower(query)); |
183 | 186 |
184 for (DownloadMap::iterator it = downloads_.begin(); | 187 for (DownloadMap::iterator it = downloads_.begin(); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 else if (info->is_extension_install && | 297 else if (info->is_extension_install && |
295 !ExtensionsService::IsDownloadFromGallery(info->url, | 298 !ExtensionsService::IsDownloadFromGallery(info->url, |
296 info->referrer_url)) { | 299 info->referrer_url)) { |
297 info->is_dangerous = true; | 300 info->is_dangerous = true; |
298 } | 301 } |
299 } | 302 } |
300 | 303 |
301 // We need to move over to the download thread because we don't want to stat | 304 // We need to move over to the download thread because we don't want to stat |
302 // the suggested path on the UI thread. | 305 // the suggested path on the UI thread. |
303 ChromeThread::PostTask( | 306 ChromeThread::PostTask( |
304 ChromeThread::FILE, FROM_HERE, | 307 ChromeThread::FILE, |
| 308 FROM_HERE, |
305 NewRunnableMethod( | 309 NewRunnableMethod( |
306 this, &DownloadManager::CheckIfSuggestedPathExists, info)); | 310 this, &DownloadManager::CheckIfSuggestedPathExists, info)); |
307 } | 311 } |
308 | 312 |
309 void DownloadManager::CheckIfSuggestedPathExists(DownloadCreateInfo* info) { | 313 void DownloadManager::CheckIfSuggestedPathExists(DownloadCreateInfo* info) { |
310 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); | 314 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
311 DCHECK(info); | 315 DCHECK(info); |
312 | 316 |
313 // Check writability of the suggested path. If we can't write to it, default | 317 // Check writability of the suggested path. If we can't write to it, default |
314 // to the user's "My Documents" directory. We'll prompt them in this case. | 318 // to the user's "My Documents" directory. We'll prompt them in this case. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 if (!info->prompt_user_for_save_location && | 365 if (!info->prompt_user_for_save_location && |
362 info->save_info.file_path.empty()) { | 366 info->save_info.file_path.empty()) { |
363 if (info->is_dangerous) | 367 if (info->is_dangerous) |
364 file_util::WriteFile(info->suggested_path, "", 0); | 368 file_util::WriteFile(info->suggested_path, "", 0); |
365 else | 369 else |
366 file_util::WriteFile(download_util::GetCrDownloadPath( | 370 file_util::WriteFile(download_util::GetCrDownloadPath( |
367 info->suggested_path), "", 0); | 371 info->suggested_path), "", 0); |
368 } | 372 } |
369 | 373 |
370 ChromeThread::PostTask( | 374 ChromeThread::PostTask( |
371 ChromeThread::UI, FROM_HERE, | 375 ChromeThread::UI, |
| 376 FROM_HERE, |
372 NewRunnableMethod(this, | 377 NewRunnableMethod(this, |
373 &DownloadManager::OnPathExistenceAvailable, | 378 &DownloadManager::OnPathExistenceAvailable, |
374 info)); | 379 info)); |
375 } | 380 } |
376 | 381 |
377 void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { | 382 void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { |
378 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 383 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
379 DCHECK(info); | 384 DCHECK(info); |
380 | 385 |
381 if (info->prompt_user_for_save_location) { | 386 if (info->prompt_user_for_save_location) { |
(...skipping 22 matching lines...) Expand all Loading... |
404 } | 409 } |
405 } | 410 } |
406 | 411 |
407 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info, | 412 void DownloadManager::CreateDownloadItem(DownloadCreateInfo* info, |
408 const FilePath& target_path) { | 413 const FilePath& target_path) { |
409 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 414 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
410 | 415 |
411 scoped_ptr<DownloadCreateInfo> infop(info); | 416 scoped_ptr<DownloadCreateInfo> infop(info); |
412 info->path = target_path; | 417 info->path = target_path; |
413 | 418 |
414 DownloadItem* download = new DownloadItem(this, *info, | 419 DownloadItem* download = NULL; |
415 profile_->IsOffTheRecord()); | 420 // For partial downloads, reuse the existing DownloadItem. |
416 DCHECK(!ContainsKey(in_progress_, info->download_id)); | 421 if (info->is_partial_download && (info->download_id != -1)) { |
417 in_progress_[info->download_id] = download; | 422 DownloadMap::iterator it = in_progress_.find(info->download_id); |
| 423 if (it != in_progress_.end()) { |
| 424 download = it->second; |
| 425 download->Resumed(info->request_id); |
| 426 } |
| 427 } |
| 428 if (!download) { |
| 429 download = new DownloadItem(this, *info, profile_->IsOffTheRecord()); |
| 430 DCHECK(!ContainsKey(in_progress_, info->download_id)); |
| 431 in_progress_[info->download_id] = download; |
| 432 } |
418 | 433 |
419 bool download_finished = ContainsKey(pending_finished_downloads_, | 434 bool download_finished = ContainsKey(pending_finished_downloads_, |
420 info->download_id); | 435 info->download_id); |
421 | 436 |
422 if (download_finished || info->is_dangerous) { | 437 if (download_finished || info->is_dangerous) { |
423 // The download has already finished or the download is not safe. | 438 // The download has already finished or the download is not safe. |
424 // We can now rename the file to its final name (or its tentative name | 439 // We can now rename the file to its final name (or its tentative name |
425 // in dangerous download cases). | 440 // in dangerous download cases). |
426 ChromeThread::PostTask( | 441 ChromeThread::PostTask( |
427 ChromeThread::FILE, FROM_HERE, | 442 ChromeThread::FILE, |
| 443 FROM_HERE, |
428 NewRunnableMethod( | 444 NewRunnableMethod( |
429 file_manager_, &DownloadFileManager::OnFinalDownloadName, | 445 file_manager_, &DownloadFileManager::OnFinalDownloadName, |
430 download->id(), target_path, !info->is_dangerous, this)); | 446 download->id(), target_path, !info->is_dangerous, this)); |
431 } else { | 447 } else { |
432 // The download hasn't finished and it is a safe download. We need to | 448 // The download hasn't finished and it is a safe download. We need to |
433 // rename it to its intermediate '.crdownload' path. | 449 // rename it to its intermediate '.crdownload' path. |
434 FilePath download_path = download_util::GetCrDownloadPath(target_path); | 450 FilePath download_path = download_util::GetCrDownloadPath(target_path); |
435 ChromeThread::PostTask( | 451 ChromeThread::PostTask( |
436 ChromeThread::FILE, FROM_HERE, | 452 ChromeThread::FILE, |
| 453 FROM_HERE, |
437 NewRunnableMethod( | 454 NewRunnableMethod( |
438 file_manager_, &DownloadFileManager::OnIntermediateDownloadName, | 455 file_manager_, &DownloadFileManager::OnIntermediateDownloadName, |
439 download->id(), download_path, this)); | 456 download->id(), download_path, this)); |
440 download->set_need_final_rename(true); | 457 download->set_need_final_rename(true); |
441 } | 458 } |
442 | 459 |
443 if (download_finished) { | 460 if (download_finished) { |
444 // If the download already completed by the time we reached this point, then | 461 // If the download already completed by the time we reached this point, then |
445 // notify observers that it did. | 462 // notify observers that it did. |
446 OnAllDataSaved(info->download_id, | 463 OnAllDataSaved(info->download_id, |
(...skipping 11 matching lines...) Expand all Loading... |
458 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { | 475 void DownloadManager::UpdateDownload(int32 download_id, int64 size) { |
459 DownloadMap::iterator it = in_progress_.find(download_id); | 476 DownloadMap::iterator it = in_progress_.find(download_id); |
460 if (it != in_progress_.end()) { | 477 if (it != in_progress_.end()) { |
461 DownloadItem* download = it->second; | 478 DownloadItem* download = it->second; |
462 download->Update(size); | 479 download->Update(size); |
463 download_history_->UpdateEntry(download); | 480 download_history_->UpdateEntry(download); |
464 } | 481 } |
465 UpdateAppIcon(); | 482 UpdateAppIcon(); |
466 } | 483 } |
467 | 484 |
| 485 void DownloadManager::OnResponseCompleted(int32 download_id, |
| 486 int64 size, |
| 487 int os_error) { |
| 488 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 489 if (os_error == 0) { |
| 490 OnAllDataSaved(download_id, size); |
| 491 } else { |
| 492 DownloadError(download_id, size, os_error); |
| 493 } |
| 494 } |
| 495 |
468 void DownloadManager::OnAllDataSaved(int32 download_id, int64 size) { | 496 void DownloadManager::OnAllDataSaved(int32 download_id, int64 size) { |
469 DownloadMap::iterator it = in_progress_.find(download_id); | 497 DownloadMap::iterator it = in_progress_.find(download_id); |
470 if (it == in_progress_.end()) { | 498 if (it == in_progress_.end()) { |
471 // The download is done, but the user hasn't selected a final location for | 499 // The download is done, but the user hasn't selected a final location for |
472 // it yet (the Save As dialog box is probably still showing), so just keep | 500 // it yet (the Save As dialog box is probably still showing), so just keep |
473 // track of the fact that this download id is complete, when the | 501 // track of the fact that this download id is complete, when the |
474 // DownloadItem is constructed later we'll notify its completion then. | 502 // DownloadItem is constructed later we'll notify its completion then. |
475 PendingFinishedMap::iterator erase_it = | 503 PendingFinishedMap::iterator erase_it = |
476 pending_finished_downloads_.find(download_id); | 504 pending_finished_downloads_.find(download_id); |
477 DCHECK(erase_it == pending_finished_downloads_.end()); | 505 DCHECK(erase_it == pending_finished_downloads_.end()); |
(...skipping 24 matching lines...) Expand all Loading... |
502 // ProceedWithFinishedDangerousDownload. | 530 // ProceedWithFinishedDangerousDownload. |
503 if (download->safety_state() == DownloadItem::DANGEROUS) { | 531 if (download->safety_state() == DownloadItem::DANGEROUS) { |
504 dangerous_finished_[download_id] = download; | 532 dangerous_finished_[download_id] = download; |
505 return; | 533 return; |
506 } | 534 } |
507 | 535 |
508 if (download->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED) { | 536 if (download->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED) { |
509 // We first need to rename the downloaded file from its temporary name to | 537 // We first need to rename the downloaded file from its temporary name to |
510 // its final name before we can continue. | 538 // its final name before we can continue. |
511 ChromeThread::PostTask( | 539 ChromeThread::PostTask( |
512 ChromeThread::FILE, FROM_HERE, | 540 ChromeThread::FILE, |
| 541 FROM_HERE, |
513 NewRunnableMethod( | 542 NewRunnableMethod( |
514 this, &DownloadManager::ProceedWithFinishedDangerousDownload, | 543 this, &DownloadManager::ProceedWithFinishedDangerousDownload, |
515 download->db_handle(), | 544 download->db_handle(), |
516 download->full_path(), download->original_name())); | 545 download->full_path(), download->original_name())); |
517 return; | 546 return; |
518 } | 547 } |
519 | 548 |
520 if (download->need_final_rename()) { | 549 if (download->need_final_rename()) { |
521 ChromeThread::PostTask( | 550 ChromeThread::PostTask( |
522 ChromeThread::FILE, FROM_HERE, | 551 ChromeThread::FILE, |
| 552 FROM_HERE, |
523 NewRunnableMethod( | 553 NewRunnableMethod( |
524 file_manager_, &DownloadFileManager::OnFinalDownloadName, | 554 file_manager_, &DownloadFileManager::OnFinalDownloadName, |
525 download->id(), download->full_path(), false, this)); | 555 download->id(), download->full_path(), false, this)); |
526 return; | 556 return; |
527 } | 557 } |
528 | 558 |
529 ContinueDownloadFinished(download); | 559 ContinueDownloadFinished(download); |
530 } | 560 } |
531 | 561 |
| 562 void DownloadManager::DownloadError(int32 download_id, |
| 563 int64 size, |
| 564 int os_error) { |
| 565 DownloadMap::iterator it = in_progress_.find(download_id); |
| 566 // If enough time passes, the download item could be |
| 567 // removed from the |in_progress_| map before we get here. |
| 568 if (it == in_progress_.end()) |
| 569 return; |
| 570 |
| 571 DownloadItem* download = it->second; |
| 572 download->Interrupted(size, os_error); |
| 573 |
| 574 LOG(INFO) << "Error " << download->last_os_error() << " at offset " |
| 575 << download->received_bytes() << " for file at \"" |
| 576 << download->url().spec() << "\""; |
| 577 |
| 578 // Clean up will happen when the history system create callback runs if we |
| 579 // don't have a valid db_handle yet, and otherwise when we restart. |
| 580 if (download->db_handle() != DownloadHistory::kUninitializedHandle) |
| 581 download_history_->UpdateEntry(download); |
| 582 |
| 583 UpdateAppIcon(); |
| 584 |
| 585 // Notify our observers that we are interrupted. |
| 586 download->UpdateObservers(); |
| 587 } |
| 588 |
532 void DownloadManager::DownloadRenamedToFinalName(int download_id, | 589 void DownloadManager::DownloadRenamedToFinalName(int download_id, |
533 const FilePath& full_path) { | 590 const FilePath& full_path) { |
534 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 591 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
535 | 592 |
536 DownloadItem* item = GetDownloadItem(download_id); | 593 DownloadItem* item = GetDownloadItem(download_id); |
537 if (!item) | 594 if (!item) |
538 return; | 595 return; |
539 item->OnNameFinalized(); | 596 item->OnNameFinalized(); |
540 | 597 |
541 // This was called from DownloadFinished; continue to call | 598 // This was called from DownloadFinished; continue to call |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 // file gets the same name. | 630 // file gets the same name. |
574 uniquifier = download_util::GetUniquePathNumber(new_path); | 631 uniquifier = download_util::GetUniquePathNumber(new_path); |
575 if (uniquifier > 0) | 632 if (uniquifier > 0) |
576 download_util::AppendNumberToPath(&new_path, uniquifier); | 633 download_util::AppendNumberToPath(&new_path, uniquifier); |
577 success = file_util::Move(path, new_path); | 634 success = file_util::Move(path, new_path); |
578 } else { | 635 } else { |
579 NOTREACHED(); | 636 NOTREACHED(); |
580 } | 637 } |
581 | 638 |
582 ChromeThread::PostTask( | 639 ChromeThread::PostTask( |
583 ChromeThread::UI, FROM_HERE, | 640 ChromeThread::UI, |
| 641 FROM_HERE, |
584 NewRunnableMethod(this, &DownloadManager::DangerousDownloadRenamed, | 642 NewRunnableMethod(this, &DownloadManager::DangerousDownloadRenamed, |
585 download_handle, success, new_path, uniquifier)); | 643 download_handle, success, new_path, uniquifier)); |
586 } | 644 } |
587 | 645 |
588 // Call from the file thread when the finished dangerous download was renamed. | 646 // Call from the file thread when the finished dangerous download was renamed. |
589 void DownloadManager::DangerousDownloadRenamed(int64 download_handle, | 647 void DownloadManager::DangerousDownloadRenamed(int64 download_handle, |
590 bool success, | 648 bool success, |
591 const FilePath& new_path, | 649 const FilePath& new_path, |
592 int new_path_uniquifier) { | 650 int new_path_uniquifier) { |
593 DownloadMap::iterator it = downloads_.find(download_handle); | 651 DownloadMap::iterator it = downloads_.find(download_handle); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 download->render_process_id(), | 684 download->render_process_id(), |
627 download->request_id()); | 685 download->request_id()); |
628 UpdateAppIcon(); | 686 UpdateAppIcon(); |
629 } | 687 } |
630 | 688 |
631 void DownloadManager::DownloadCancelledInternal(int download_id, | 689 void DownloadManager::DownloadCancelledInternal(int download_id, |
632 int render_process_id, | 690 int render_process_id, |
633 int request_id) { | 691 int request_id) { |
634 // Cancel the network request. RDH is guaranteed to outlive the IO thread. | 692 // Cancel the network request. RDH is guaranteed to outlive the IO thread. |
635 ChromeThread::PostTask( | 693 ChromeThread::PostTask( |
636 ChromeThread::IO, FROM_HERE, | 694 ChromeThread::IO, |
| 695 FROM_HERE, |
637 NewRunnableFunction(&download_util::CancelDownloadRequest, | 696 NewRunnableFunction(&download_util::CancelDownloadRequest, |
638 g_browser_process->resource_dispatcher_host(), | 697 g_browser_process->resource_dispatcher_host(), |
639 render_process_id, | 698 render_process_id, |
640 request_id)); | 699 request_id)); |
641 | 700 |
642 ChromeThread::PostTask( | 701 ChromeThread::PostTask( |
643 ChromeThread::FILE, FROM_HERE, | 702 ChromeThread::FILE, |
| 703 FROM_HERE, |
644 NewRunnableMethod( | 704 NewRunnableMethod( |
645 file_manager_, &DownloadFileManager::CancelDownload, download_id)); | 705 file_manager_, &DownloadFileManager::CancelDownload, download_id)); |
646 } | 706 } |
647 | 707 |
648 void DownloadManager::PauseDownload(int32 download_id, bool pause) { | 708 void DownloadManager::PauseDownload(int32 download_id, bool pause) { |
649 DownloadMap::iterator it = in_progress_.find(download_id); | 709 DownloadMap::iterator it = in_progress_.find(download_id); |
650 if (it == in_progress_.end()) | 710 if (it == in_progress_.end()) |
651 return; | 711 return; |
652 | 712 |
653 DownloadItem* download = it->second; | 713 DownloadItem* download = it->second; |
654 if (pause == download->is_paused()) | 714 if (pause == download->is_paused()) |
655 return; | 715 return; |
656 | 716 |
657 ChromeThread::PostTask( | 717 ChromeThread::PostTask( |
658 ChromeThread::IO, FROM_HERE, | 718 ChromeThread::IO, |
| 719 FROM_HERE, |
659 NewRunnableMethod(this, | 720 NewRunnableMethod(this, |
660 &DownloadManager::PauseDownloadRequest, | 721 &DownloadManager::PauseDownloadRequest, |
661 g_browser_process->resource_dispatcher_host(), | 722 g_browser_process->resource_dispatcher_host(), |
662 download->render_process_id(), | 723 download->render_process_id(), |
663 download->request_id(), | 724 download->request_id(), |
664 pause)); | 725 pause)); |
665 } | 726 } |
666 | 727 |
| 728 void DownloadManager::RestartDownload(int32 download_id) { |
| 729 // Handle the case of clicking 'Resume' in the download shelf. |
| 730 DownloadMap::iterator it = in_progress_.find(download_id); |
| 731 if (it == in_progress_.end()) |
| 732 return; |
| 733 |
| 734 DownloadItem* download = it->second; |
| 735 if (!download->IsInterruptedDownload()) |
| 736 return; |
| 737 |
| 738 // Restart the download. |
| 739 // |info| is cleaned up in ResourceDispatcherHost::RestartRequestAsync(). |
| 740 DownloadCreateInfo* info = new DownloadCreateInfo( |
| 741 download->full_path(), |
| 742 download->url(), |
| 743 download->start_time(), |
| 744 download->received_bytes(), |
| 745 download->total_bytes(), |
| 746 DownloadItem::IN_PROGRESS, // Don't want this to show INTERRUPTED. |
| 747 -1); |
| 748 info->referrer_url = download->referrer_url(); |
| 749 |
| 750 // Inform the ResourceDispatcherHost that we're restarting the download. |
| 751 ChromeThread::PostTask( |
| 752 ChromeThread::IO, |
| 753 FROM_HERE, |
| 754 NewRunnableMethod(this, |
| 755 &DownloadManager::RestartDownloadRequest, |
| 756 g_browser_process->resource_dispatcher_host(), |
| 757 download->render_process_id(), |
| 758 download->request_id(), |
| 759 info)); |
| 760 } |
| 761 |
667 void DownloadManager::UpdateAppIcon() { | 762 void DownloadManager::UpdateAppIcon() { |
668 int64 total_bytes = 0; | 763 int64 total_bytes = 0; |
669 int64 received_bytes = 0; | 764 int64 received_bytes = 0; |
670 int download_count = 0; | 765 int download_count = 0; |
671 bool progress_known = true; | 766 bool progress_known = true; |
672 | 767 |
673 for (DownloadMap::iterator i = in_progress_.begin(); | 768 for (DownloadMap::iterator i = in_progress_.begin(); |
674 i != in_progress_.end(); | 769 i != in_progress_.end(); |
675 ++i) { | 770 ++i) { |
676 ++download_count; | 771 ++download_count; |
(...skipping 24 matching lines...) Expand all Loading... |
701 } | 796 } |
702 | 797 |
703 void DownloadManager::PauseDownloadRequest(ResourceDispatcherHost* rdh, | 798 void DownloadManager::PauseDownloadRequest(ResourceDispatcherHost* rdh, |
704 int render_process_id, | 799 int render_process_id, |
705 int request_id, | 800 int request_id, |
706 bool pause) { | 801 bool pause) { |
707 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); | 802 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
708 rdh->PauseRequest(render_process_id, request_id, pause); | 803 rdh->PauseRequest(render_process_id, request_id, pause); |
709 } | 804 } |
710 | 805 |
| 806 void DownloadManager::RestartDownloadRequest(ResourceDispatcherHost* rdh, |
| 807 int render_process_id, |
| 808 int request_id, |
| 809 DownloadCreateInfo* info) { |
| 810 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
| 811 rdh->RestartRequest(render_process_id, request_id, info); |
| 812 } |
| 813 |
711 void DownloadManager::RemoveDownload(int64 download_handle) { | 814 void DownloadManager::RemoveDownload(int64 download_handle) { |
712 DownloadMap::iterator it = downloads_.find(download_handle); | 815 DownloadMap::iterator it = downloads_.find(download_handle); |
713 if (it == downloads_.end()) | 816 if (it == downloads_.end()) |
714 return; | 817 return; |
715 | 818 |
716 // Make history update. | 819 // Make history update. |
717 DownloadItem* download = it->second; | 820 DownloadItem* download = it->second; |
718 download_history_->RemoveEntry(download); | 821 download_history_->RemoveEntry(download); |
719 | 822 |
720 // Remove from our tables and delete. | 823 // Remove from our tables and delete. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(), | 901 DownloadUrlToFile(url, referrer, referrer_charset, DownloadSaveInfo(), |
799 tab_contents); | 902 tab_contents); |
800 } | 903 } |
801 | 904 |
802 void DownloadManager::DownloadUrlToFile(const GURL& url, | 905 void DownloadManager::DownloadUrlToFile(const GURL& url, |
803 const GURL& referrer, | 906 const GURL& referrer, |
804 const std::string& referrer_charset, | 907 const std::string& referrer_charset, |
805 const DownloadSaveInfo& save_info, | 908 const DownloadSaveInfo& save_info, |
806 TabContents* tab_contents) { | 909 TabContents* tab_contents) { |
807 DCHECK(tab_contents); | 910 DCHECK(tab_contents); |
808 ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, | 911 ChromeThread::PostTask( |
| 912 ChromeThread::IO, |
| 913 FROM_HERE, |
809 NewRunnableFunction(&download_util::DownloadUrl, | 914 NewRunnableFunction(&download_util::DownloadUrl, |
810 url, | 915 url, |
811 referrer, | 916 referrer, |
812 referrer_charset, | 917 referrer_charset, |
813 save_info, | 918 save_info, |
814 g_browser_process->resource_dispatcher_host(), | 919 g_browser_process->resource_dispatcher_host(), |
815 tab_contents->GetRenderProcessHost()->id(), | 920 tab_contents->GetRenderProcessHost()->id(), |
816 tab_contents->render_view_host()->routing_id(), | 921 tab_contents->render_view_host()->routing_id(), |
817 request_context_getter_)); | 922 request_context_getter_)); |
818 } | 923 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
861 DCHECK_EQ(DownloadItem::DANGEROUS, download->safety_state()); | 966 DCHECK_EQ(DownloadItem::DANGEROUS, download->safety_state()); |
862 download->set_safety_state(DownloadItem::DANGEROUS_BUT_VALIDATED); | 967 download->set_safety_state(DownloadItem::DANGEROUS_BUT_VALIDATED); |
863 download->UpdateObservers(); | 968 download->UpdateObservers(); |
864 | 969 |
865 // If the download is not complete, nothing to do. The required | 970 // If the download is not complete, nothing to do. The required |
866 // post-processing will be performed when it does complete. | 971 // post-processing will be performed when it does complete. |
867 if (download->state() != DownloadItem::COMPLETE) | 972 if (download->state() != DownloadItem::COMPLETE) |
868 return; | 973 return; |
869 | 974 |
870 ChromeThread::PostTask( | 975 ChromeThread::PostTask( |
871 ChromeThread::FILE, FROM_HERE, | 976 ChromeThread::FILE, |
| 977 FROM_HERE, |
872 NewRunnableMethod( | 978 NewRunnableMethod( |
873 this, &DownloadManager::ProceedWithFinishedDangerousDownload, | 979 this, &DownloadManager::ProceedWithFinishedDangerousDownload, |
874 download->db_handle(), download->full_path(), | 980 download->db_handle(), download->full_path(), |
875 download->original_name())); | 981 download->original_name())); |
876 } | 982 } |
877 | 983 |
878 // Operations posted to us from the history service ---------------------------- | 984 // Operations posted to us from the history service ---------------------------- |
879 | 985 |
880 // The history service has retrieved all download entries. 'entries' contains | 986 // The history service has retrieved all download entries. 'entries' contains |
881 // 'DownloadCreateInfo's in sorted order (by ascending start_time). | 987 // 'DownloadCreateInfo's in sorted order (by ascending start_time). |
(...skipping 10 matching lines...) Expand all Loading... |
892 // Once the new DownloadItem's creation info has been committed to the history | 998 // Once the new DownloadItem's creation info has been committed to the history |
893 // service, we associate the DownloadItem with the db handle, update our | 999 // service, we associate the DownloadItem with the db handle, update our |
894 // 'downloads_' map and inform observers. | 1000 // 'downloads_' map and inform observers. |
895 void DownloadManager::OnCreateDownloadEntryComplete(DownloadCreateInfo info, | 1001 void DownloadManager::OnCreateDownloadEntryComplete(DownloadCreateInfo info, |
896 int64 db_handle) { | 1002 int64 db_handle) { |
897 DownloadMap::iterator it = in_progress_.find(info.download_id); | 1003 DownloadMap::iterator it = in_progress_.find(info.download_id); |
898 DCHECK(it != in_progress_.end()); | 1004 DCHECK(it != in_progress_.end()); |
899 | 1005 |
900 DownloadItem* download = it->second; | 1006 DownloadItem* download = it->second; |
901 | 1007 |
902 // It's not immediately obvious, but HistoryBackend::CreateDownload() can | 1008 if (download->db_handle() != DownloadHistory::kUninitializedHandle) { |
903 // call this function with an invalid |db_handle|. For instance, this can | 1009 // We're reusing the download. |
904 // happen when the history database is offline. We cannot have multiple | 1010 } else { |
905 // DownloadItems with the same invalid db_handle, so we need to assign a | 1011 // It's not immediately obvious, but HistoryBackend::CreateDownload() can |
906 // unique |db_handle| here. | 1012 // call this function with an invalid |db_handle|. For instance, this can |
907 if (db_handle == DownloadHistory::kUninitializedHandle) | 1013 // happen when the history database is offline. We cannot have multiple |
908 db_handle = download_history_->GetNextFakeDbHandle(); | 1014 // DownloadItems with the same invalid db_handle, so we need to assign a |
| 1015 // unique |db_handle| here. |
| 1016 if (db_handle == DownloadHistory::kUninitializedHandle) |
| 1017 db_handle = download_history_->GetNextFakeDbHandle(); |
909 | 1018 |
910 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); | 1019 DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); |
911 download->set_db_handle(db_handle); | 1020 download->set_db_handle(db_handle); |
912 | 1021 |
913 // Insert into our full map. | 1022 // Insert into our full map. |
914 DCHECK(downloads_.find(download->db_handle()) == downloads_.end()); | 1023 DCHECK(downloads_.find(download->db_handle()) == downloads_.end()); |
915 downloads_[download->db_handle()] = download; | 1024 downloads_[download->db_handle()] = download; |
| 1025 } |
916 | 1026 |
917 // Show in the appropropriate browser UI. | 1027 // Show in the appropropriate browser UI. |
918 ShowDownloadInBrowser(info, download); | 1028 ShowDownloadInBrowser(info, download); |
919 | 1029 |
920 // Inform interested objects about the new download. | 1030 // Inform interested objects about the new download. |
921 NotifyModelChanged(); | 1031 NotifyModelChanged(); |
922 | 1032 |
923 // If this download has been completed before we've received the db handle, | 1033 // If this download has been completed before we've received the db handle, |
924 // post one final message to the history service so that it can be properly | 1034 // post one final message to the history service so that it can be properly |
925 // in sync with the DownloadItem's completion status, and also inform any | 1035 // in sync with the DownloadItem's completion status, and also inform any |
926 // observers so that they get more than just the start notification. | 1036 // observers so that they get more than just the start notification. |
927 if (download->state() != DownloadItem::IN_PROGRESS) { | 1037 if (download->state() != DownloadItem::IN_PROGRESS) { |
928 in_progress_.erase(it); | 1038 if (!download->IsInterruptedDownload()) |
| 1039 in_progress_.erase(it); |
929 download_history_->UpdateEntry(download); | 1040 download_history_->UpdateEntry(download); |
930 download->UpdateObservers(); | 1041 download->UpdateObservers(); |
931 } | 1042 } |
932 | 1043 |
933 UpdateAppIcon(); | 1044 UpdateAppIcon(); |
934 } | 1045 } |
935 | 1046 |
936 void DownloadManager::ShowDownloadInBrowser(const DownloadCreateInfo& info, | 1047 void DownloadManager::ShowDownloadInBrowser(const DownloadCreateInfo& info, |
937 DownloadItem* download) { | 1048 DownloadItem* download) { |
938 // The 'contents' may no longer exist if the user closed the tab before we | 1049 // The 'contents' may no longer exist if the user closed the tab before we |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
994 observed_download_manager_->RemoveObserver(this); | 1105 observed_download_manager_->RemoveObserver(this); |
995 } | 1106 } |
996 | 1107 |
997 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { | 1108 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { |
998 observing_download_manager_->NotifyModelChanged(); | 1109 observing_download_manager_->NotifyModelChanged(); |
999 } | 1110 } |
1000 | 1111 |
1001 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { | 1112 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { |
1002 observed_download_manager_ = NULL; | 1113 observed_download_manager_ = NULL; |
1003 } | 1114 } |
OLD | NEW |