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 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 | 458 |
459 // We need to move over to the download thread because we don't want to stat | 459 // We need to move over to the download thread because we don't want to stat |
460 // the suggested path on the UI thread. | 460 // the suggested path on the UI thread. |
461 ChromeThread::PostTask( | 461 ChromeThread::PostTask( |
462 ChromeThread::FILE, FROM_HERE, | 462 ChromeThread::FILE, FROM_HERE, |
463 NewRunnableMethod( | 463 NewRunnableMethod( |
464 this, &DownloadManager::CheckIfSuggestedPathExists, info)); | 464 this, &DownloadManager::CheckIfSuggestedPathExists, info)); |
465 } | 465 } |
466 | 466 |
467 void DownloadManager::CheckIfSuggestedPathExists(DownloadCreateInfo* info) { | 467 void DownloadManager::CheckIfSuggestedPathExists(DownloadCreateInfo* info) { |
| 468 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
468 DCHECK(info); | 469 DCHECK(info); |
469 | 470 |
470 // Check writability of the suggested path. If we can't write to it, default | 471 // Check writability of the suggested path. If we can't write to it, default |
471 // to the user's "My Documents" directory. We'll prompt them in this case. | 472 // to the user's "My Documents" directory. We'll prompt them in this case. |
472 FilePath dir = info->suggested_path.DirName(); | 473 FilePath dir = info->suggested_path.DirName(); |
473 FilePath filename = info->suggested_path.BaseName(); | 474 FilePath filename = info->suggested_path.BaseName(); |
474 if (!file_util::PathIsWritable(dir)) { | 475 if (!file_util::PathIsWritable(dir)) { |
475 info->prompt_user_for_save_location = true; | 476 info->prompt_user_for_save_location = true; |
476 PathService::Get(chrome::DIR_USER_DOCUMENTS, &info->suggested_path); | 477 PathService::Get(chrome::DIR_USER_DOCUMENTS, &info->suggested_path); |
477 info->suggested_path = info->suggested_path.Append(filename); | 478 info->suggested_path = info->suggested_path.Append(filename); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 // See: http://code.google.com/p/chromium/issues/detail?id=3662 | 518 // See: http://code.google.com/p/chromium/issues/detail?id=3662 |
518 if (!info->prompt_user_for_save_location && | 519 if (!info->prompt_user_for_save_location && |
519 info->save_info.file_path.empty()) { | 520 info->save_info.file_path.empty()) { |
520 if (info->is_dangerous) | 521 if (info->is_dangerous) |
521 file_util::WriteFile(info->suggested_path, "", 0); | 522 file_util::WriteFile(info->suggested_path, "", 0); |
522 else | 523 else |
523 file_util::WriteFile(download_util::GetCrDownloadPath( | 524 file_util::WriteFile(download_util::GetCrDownloadPath( |
524 info->suggested_path), "", 0); | 525 info->suggested_path), "", 0); |
525 } | 526 } |
526 | 527 |
527 // Now we return to the UI thread. | |
528 ChromeThread::PostTask( | 528 ChromeThread::PostTask( |
529 ChromeThread::UI, FROM_HERE, | 529 ChromeThread::UI, FROM_HERE, |
530 NewRunnableMethod(this, | 530 NewRunnableMethod(this, |
531 &DownloadManager::OnPathExistenceAvailable, | 531 &DownloadManager::OnPathExistenceAvailable, |
532 info)); | 532 info)); |
533 } | 533 } |
534 | 534 |
535 void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { | 535 void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { |
536 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 536 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
537 DCHECK(info); | 537 DCHECK(info); |
(...skipping 19 matching lines...) Expand all Loading... |
557 &file_type_info, 0, FILE_PATH_LITERAL(""), | 557 &file_type_info, 0, FILE_PATH_LITERAL(""), |
558 owning_window, info); | 558 owning_window, info); |
559 } else { | 559 } else { |
560 // No prompting for download, just continue with the suggested name. | 560 // No prompting for download, just continue with the suggested name. |
561 ContinueStartDownload(info, info->suggested_path); | 561 ContinueStartDownload(info, info->suggested_path); |
562 } | 562 } |
563 } | 563 } |
564 | 564 |
565 void DownloadManager::ContinueStartDownload(DownloadCreateInfo* info, | 565 void DownloadManager::ContinueStartDownload(DownloadCreateInfo* info, |
566 const FilePath& target_path) { | 566 const FilePath& target_path) { |
| 567 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 568 |
567 scoped_ptr<DownloadCreateInfo> infop(info); | 569 scoped_ptr<DownloadCreateInfo> infop(info); |
568 info->path = target_path; | 570 info->path = target_path; |
569 | 571 |
570 DownloadItem* download = NULL; | 572 DownloadItem* download = new DownloadItem(this, *info, |
571 DownloadMap::iterator it = in_progress_.find(info->download_id); | 573 profile_->IsOffTheRecord()); |
572 if (it == in_progress_.end()) { | 574 DCHECK(!ContainsKey(in_progress_, info->download_id)); |
573 download = new DownloadItem(info->download_id, | 575 in_progress_[info->download_id] = download; |
574 info->path, | |
575 info->path_uniquifier, | |
576 info->url, | |
577 info->referrer_url, | |
578 info->mime_type, | |
579 info->original_mime_type, | |
580 info->original_name, | |
581 info->start_time, | |
582 info->total_bytes, | |
583 info->child_id, | |
584 info->request_id, | |
585 info->is_dangerous, | |
586 info->prompt_user_for_save_location, | |
587 profile_->IsOffTheRecord(), | |
588 info->is_extension_install, | |
589 !info->save_info.file_path.empty()); | |
590 download->set_manager(this); | |
591 in_progress_[info->download_id] = download; | |
592 } else { | |
593 NOTREACHED(); // Should not exist! | |
594 return; | |
595 } | |
596 | 576 |
597 PendingFinishedMap::iterator pending_it = | 577 bool download_finished = ContainsKey(pending_finished_downloads_, |
598 pending_finished_downloads_.find(info->download_id); | 578 info->download_id); |
599 bool download_finished = (pending_it != pending_finished_downloads_.end()); | |
600 | 579 |
601 if (download_finished || info->is_dangerous) { | 580 if (download_finished || info->is_dangerous) { |
602 // The download has already finished or the download is not safe. | 581 // The download has already finished or the download is not safe. |
603 // We can now rename the file to its final name (or its tentative name | 582 // We can now rename the file to its final name (or its tentative name |
604 // in dangerous download cases). | 583 // in dangerous download cases). |
605 ChromeThread::PostTask( | 584 ChromeThread::PostTask( |
606 ChromeThread::FILE, FROM_HERE, | 585 ChromeThread::FILE, FROM_HERE, |
607 NewRunnableMethod( | 586 NewRunnableMethod( |
608 file_manager_, &DownloadFileManager::OnFinalDownloadName, | 587 file_manager_, &DownloadFileManager::OnFinalDownloadName, |
609 download->id(), target_path, !info->is_dangerous, this)); | 588 download->id(), target_path, !info->is_dangerous, this)); |
610 } else { | 589 } else { |
611 // The download hasn't finished and it is a safe download. We need to | 590 // The download hasn't finished and it is a safe download. We need to |
612 // rename it to its intermediate '.crdownload' path. | 591 // rename it to its intermediate '.crdownload' path. |
613 FilePath download_path = download_util::GetCrDownloadPath(target_path); | 592 FilePath download_path = download_util::GetCrDownloadPath(target_path); |
614 ChromeThread::PostTask( | 593 ChromeThread::PostTask( |
615 ChromeThread::FILE, FROM_HERE, | 594 ChromeThread::FILE, FROM_HERE, |
616 NewRunnableMethod( | 595 NewRunnableMethod( |
617 file_manager_, &DownloadFileManager::OnIntermediateDownloadName, | 596 file_manager_, &DownloadFileManager::OnIntermediateDownloadName, |
618 download->id(), download_path, this)); | 597 download->id(), download_path, this)); |
619 download->set_need_final_rename(true); | 598 download->set_need_final_rename(true); |
620 } | 599 } |
621 | 600 |
622 if (download_finished) { | 601 if (download_finished) { |
623 // If the download already completed by the time we reached this point, then | 602 // If the download already completed by the time we reached this point, then |
624 // notify observers that it did. | 603 // notify observers that it did. |
625 DownloadFinished(pending_it->first, pending_it->second); | 604 DownloadFinished(info->download_id, |
| 605 pending_finished_downloads_[info->download_id]); |
626 } | 606 } |
627 | 607 |
628 download->Rename(target_path); | 608 download->Rename(target_path); |
629 | 609 |
630 // Do not store the download in the history database for a few special cases: | 610 // Do not store the download in the history database for a few special cases: |
631 // - incognito mode (that is the point of this mode) | 611 // - incognito mode (that is the point of this mode) |
632 // - extensions (users don't think of extension installation as 'downloading') | 612 // - extensions (users don't think of extension installation as 'downloading') |
633 // - temporary download, like in drag-and-drop | 613 // - temporary download, like in drag-and-drop |
634 // - history service is not available (e.g. in tests) | 614 // - history service is not available (e.g. in tests) |
635 // We have to make sure that these handles don't collide with normal db | 615 // We have to make sure that these handles don't collide with normal db |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 file_manager_, &DownloadFileManager::OnFinalDownloadName, | 735 file_manager_, &DownloadFileManager::OnFinalDownloadName, |
756 download->id(), download->full_path(), false, this)); | 736 download->id(), download->full_path(), false, this)); |
757 return; | 737 return; |
758 } | 738 } |
759 | 739 |
760 ContinueDownloadFinished(download); | 740 ContinueDownloadFinished(download); |
761 } | 741 } |
762 | 742 |
763 void DownloadManager::DownloadRenamedToFinalName(int download_id, | 743 void DownloadManager::DownloadRenamedToFinalName(int download_id, |
764 const FilePath& full_path) { | 744 const FilePath& full_path) { |
| 745 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 746 |
765 DownloadItem* item = GetDownloadItem(download_id); | 747 DownloadItem* item = GetDownloadItem(download_id); |
766 if (!item) | 748 if (!item) |
767 return; | 749 return; |
768 item->OnNameFinalized(); | 750 item->OnNameFinalized(); |
769 | 751 |
770 // This was called from DownloadFinished; continue to call | 752 // This was called from DownloadFinished; continue to call |
771 // ContinueDownloadFinished. | 753 // ContinueDownloadFinished. |
772 if (item->need_final_rename()) { | 754 if (item->need_final_rename()) { |
773 item->set_need_final_rename(false); | 755 item->set_need_final_rename(false); |
774 ContinueDownloadFinished(item); | 756 ContinueDownloadFinished(item); |
775 } | 757 } |
776 } | 758 } |
777 | 759 |
778 void DownloadManager::ContinueDownloadFinished(DownloadItem* download) { | 760 void DownloadManager::ContinueDownloadFinished(DownloadItem* download) { |
| 761 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 762 |
779 // If this was a dangerous download, it has now been approved and must be | 763 // If this was a dangerous download, it has now been approved and must be |
780 // removed from dangerous_finished_ so it does not get deleted on shutdown. | 764 // removed from dangerous_finished_ so it does not get deleted on shutdown. |
781 DownloadMap::iterator it = dangerous_finished_.find(download->id()); | 765 dangerous_finished_.erase(download->id()); |
782 if (it != dangerous_finished_.end()) | |
783 dangerous_finished_.erase(it); | |
784 | 766 |
785 // Handle chrome extensions explicitly and skip the shell execute. | 767 // Handle chrome extensions explicitly and skip the shell execute. |
786 if (download->is_extension_install()) { | 768 if (download->is_extension_install()) { |
787 OpenChromeExtension(download->full_path(), | 769 OpenChromeExtension(download->full_path(), |
788 download->url(), | 770 download->url(), |
789 download->referrer_url(), | 771 download->referrer_url(), |
790 download->original_mime_type()); | 772 download->original_mime_type()); |
791 download->set_auto_opened(true); | 773 download->set_auto_opened(true); |
792 } else if (download->open_when_complete() || | 774 } else if (download->open_when_complete() || |
793 ShouldOpenFileBasedOnExtension(download->full_path()) || | 775 ShouldOpenFileBasedOnExtension(download->full_path()) || |
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1488 #endif | 1470 #endif |
1489 } | 1471 } |
1490 | 1472 |
1491 // Operations posted to us from the history service ---------------------------- | 1473 // Operations posted to us from the history service ---------------------------- |
1492 | 1474 |
1493 // The history service has retrieved all download entries. 'entries' contains | 1475 // The history service has retrieved all download entries. 'entries' contains |
1494 // 'DownloadCreateInfo's in sorted order (by ascending start_time). | 1476 // 'DownloadCreateInfo's in sorted order (by ascending start_time). |
1495 void DownloadManager::OnQueryDownloadEntriesComplete( | 1477 void DownloadManager::OnQueryDownloadEntriesComplete( |
1496 std::vector<DownloadCreateInfo>* entries) { | 1478 std::vector<DownloadCreateInfo>* entries) { |
1497 for (size_t i = 0; i < entries->size(); ++i) { | 1479 for (size_t i = 0; i < entries->size(); ++i) { |
1498 DownloadItem* download = new DownloadItem(entries->at(i)); | 1480 DownloadItem* download = new DownloadItem(this, entries->at(i)); |
1499 DCHECK(downloads_.find(download->db_handle()) == downloads_.end()); | 1481 DCHECK(!ContainsKey(downloads_, download->db_handle())); |
1500 downloads_[download->db_handle()] = download; | 1482 downloads_[download->db_handle()] = download; |
1501 download->set_manager(this); | |
1502 } | 1483 } |
1503 NotifyModelChanged(); | 1484 NotifyModelChanged(); |
1504 } | 1485 } |
1505 | 1486 |
1506 // Once the new DownloadItem's creation info has been committed to the history | 1487 // Once the new DownloadItem's creation info has been committed to the history |
1507 // service, we associate the DownloadItem with the db handle, update our | 1488 // service, we associate the DownloadItem with the db handle, update our |
1508 // 'downloads_' map and inform observers. | 1489 // 'downloads_' map and inform observers. |
1509 void DownloadManager::OnCreateDownloadEntryComplete(DownloadCreateInfo info, | 1490 void DownloadManager::OnCreateDownloadEntryComplete(DownloadCreateInfo info, |
1510 int64 db_handle) { | 1491 int64 db_handle) { |
1511 DownloadMap::iterator it = in_progress_.find(info.download_id); | 1492 DownloadMap::iterator it = in_progress_.find(info.download_id); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1632 observing_download_manager_->NotifyModelChanged(); | 1613 observing_download_manager_->NotifyModelChanged(); |
1633 } | 1614 } |
1634 | 1615 |
1635 void DownloadManager::OtherDownloadManagerObserver::SetDownloads( | 1616 void DownloadManager::OtherDownloadManagerObserver::SetDownloads( |
1636 std::vector<DownloadItem*>& downloads) { | 1617 std::vector<DownloadItem*>& downloads) { |
1637 } | 1618 } |
1638 | 1619 |
1639 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { | 1620 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { |
1640 observed_download_manager_ = NULL; | 1621 observed_download_manager_ = NULL; |
1641 } | 1622 } |
OLD | NEW |