| 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 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 // history system of a new download. Since this method can be called while the | 633 // history system of a new download. Since this method can be called while the |
| 634 // history service thread is still reading the persistent state, we do not | 634 // history service thread is still reading the persistent state, we do not |
| 635 // insert the new DownloadItem into 'downloads_' or inform our observers at this | 635 // insert the new DownloadItem into 'downloads_' or inform our observers at this |
| 636 // point. OnCreateDatabaseEntryComplete() handles that finalization of the the | 636 // point. OnCreateDatabaseEntryComplete() handles that finalization of the the |
| 637 // download creation as a callback from the history thread. | 637 // download creation as a callback from the history thread. |
| 638 void DownloadManager::StartDownload(DownloadCreateInfo* info) { | 638 void DownloadManager::StartDownload(DownloadCreateInfo* info) { |
| 639 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 639 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 640 DCHECK(info); | 640 DCHECK(info); |
| 641 | 641 |
| 642 // Check whether this download is for an extension install or not. | 642 // Check whether this download is for an extension install or not. |
| 643 if (!info->save_as) { // Allow extensions to be explicitly saved. | 643 // Allow extensions to be explicitly saved. |
| 644 if (!info->prompt_user_for_save_location) { |
| 644 if (UserScript::HasUserScriptFileExtension(info->url) || | 645 if (UserScript::HasUserScriptFileExtension(info->url) || |
| 645 info->mime_type == Extension::kMimeType) | 646 info->mime_type == Extension::kMimeType) |
| 646 info->is_extension_install = true; | 647 info->is_extension_install = true; |
| 647 } | 648 } |
| 648 | 649 |
| 649 // Freeze the user's preference for showing a Save As dialog. We're going to | 650 // Freeze the user's preference for showing a Save As dialog. We're going to |
| 650 // bounce around a bunch of threads and we don't want to worry about race | 651 // bounce around a bunch of threads and we don't want to worry about race |
| 651 // conditions where the user changes this pref out from under us. | 652 // conditions where the user changes this pref out from under us. |
| 652 if (*prompt_for_download_) { | 653 if (*prompt_for_download_) { |
| 653 // But never obey the preference for the following scenarios: | 654 // But never obey the preference for the following scenarios: |
| 654 // 1) Extension installation. Note that we only care here about the case | 655 // 1) Extension installation. Note that we only care here about the case |
| 655 // where an extension is installed, not when one is downloaded with | 656 // where an extension is installed, not when one is downloaded with |
| 656 // "save as...". | 657 // "save as...". |
| 657 // 2) Drag-out download. Since we will save to the destination folder that | 658 // 2) Drag-out download. Since we will save to the destination folder that |
| 658 // is dropped to, we should not pop up a Save As dialog. | 659 // is dropped to, we should not pop up a Save As dialog. |
| 659 if (!info->is_extension_install && info->save_info.file_path.empty()) | 660 if (!info->is_extension_install && info->save_info.file_path.empty()) |
| 660 info->save_as = true; | 661 info->prompt_user_for_save_location = true; |
| 661 } | 662 } |
| 662 | 663 |
| 663 if (info->save_info.file_path.empty()) { | 664 if (info->save_info.file_path.empty()) { |
| 664 // Determine the proper path for a download, by either one of the following: | 665 // Determine the proper path for a download, by either one of the following: |
| 665 // 1) using the default download directory. | 666 // 1) using the default download directory. |
| 666 // 2) prompting the user. | 667 // 2) prompting the user. |
| 667 FilePath generated_name; | 668 FilePath generated_name; |
| 668 GenerateFileNameFromInfo(info, &generated_name); | 669 GenerateFileNameFromInfo(info, &generated_name); |
| 669 if (info->save_as && !last_download_path_.empty()) | 670 if (info->prompt_user_for_save_location && !last_download_path_.empty()) |
| 670 info->suggested_path = last_download_path_; | 671 info->suggested_path = last_download_path_; |
| 671 else | 672 else |
| 672 info->suggested_path = download_path(); | 673 info->suggested_path = download_path(); |
| 673 info->suggested_path = info->suggested_path.Append(generated_name); | 674 info->suggested_path = info->suggested_path.Append(generated_name); |
| 674 } else { | 675 } else { |
| 675 info->suggested_path = info->save_info.file_path; | 676 info->suggested_path = info->save_info.file_path; |
| 676 } | 677 } |
| 677 | 678 |
| 678 if (!info->save_as && info->save_info.file_path.empty()) { | 679 if (!info->prompt_user_for_save_location && |
| 680 info->save_info.file_path.empty()) { |
| 679 // Downloads can be marked as dangerous for two reasons: | 681 // Downloads can be marked as dangerous for two reasons: |
| 680 // a) They have a dangerous-looking filename | 682 // a) They have a dangerous-looking filename |
| 681 // b) They are an extension that is not from the gallery | 683 // b) They are an extension that is not from the gallery |
| 682 if (IsDangerous(info->suggested_path.BaseName())) | 684 if (IsDangerous(info->suggested_path.BaseName())) |
| 683 info->is_dangerous = true; | 685 info->is_dangerous = true; |
| 684 else if (info->is_extension_install && | 686 else if (info->is_extension_install && |
| 685 !ExtensionsService::IsDownloadFromGallery(info->url, | 687 !ExtensionsService::IsDownloadFromGallery(info->url, |
| 686 info->referrer_url)) { | 688 info->referrer_url)) { |
| 687 info->is_dangerous = true; | 689 info->is_dangerous = true; |
| 688 } | 690 } |
| 689 } | 691 } |
| 690 | 692 |
| 691 // We need to move over to the download thread because we don't want to stat | 693 // We need to move over to the download thread because we don't want to stat |
| 692 // the suggested path on the UI thread. | 694 // the suggested path on the UI thread. |
| 693 ChromeThread::PostTask( | 695 ChromeThread::PostTask( |
| 694 ChromeThread::FILE, FROM_HERE, | 696 ChromeThread::FILE, FROM_HERE, |
| 695 NewRunnableMethod( | 697 NewRunnableMethod( |
| 696 this, &DownloadManager::CheckIfSuggestedPathExists, info)); | 698 this, &DownloadManager::CheckIfSuggestedPathExists, info)); |
| 697 } | 699 } |
| 698 | 700 |
| 699 void DownloadManager::CheckIfSuggestedPathExists(DownloadCreateInfo* info) { | 701 void DownloadManager::CheckIfSuggestedPathExists(DownloadCreateInfo* info) { |
| 700 DCHECK(info); | 702 DCHECK(info); |
| 701 | 703 |
| 702 // Check writability of the suggested path. If we can't write to it, default | 704 // Check writability of the suggested path. If we can't write to it, default |
| 703 // to the user's "My Documents" directory. We'll prompt them in this case. | 705 // to the user's "My Documents" directory. We'll prompt them in this case. |
| 704 FilePath dir = info->suggested_path.DirName(); | 706 FilePath dir = info->suggested_path.DirName(); |
| 705 FilePath filename = info->suggested_path.BaseName(); | 707 FilePath filename = info->suggested_path.BaseName(); |
| 706 if (!file_util::PathIsWritable(dir)) { | 708 if (!file_util::PathIsWritable(dir)) { |
| 707 info->save_as = true; | 709 info->prompt_user_for_save_location = true; |
| 708 PathService::Get(chrome::DIR_USER_DOCUMENTS, &info->suggested_path); | 710 PathService::Get(chrome::DIR_USER_DOCUMENTS, &info->suggested_path); |
| 709 info->suggested_path = info->suggested_path.Append(filename); | 711 info->suggested_path = info->suggested_path.Append(filename); |
| 710 } | 712 } |
| 711 | 713 |
| 712 // Do not add the path uniquifier if we are saving to a specific path as in | 714 // Do not add the path uniquifier if we are saving to a specific path as in |
| 713 // the drag-out case. | 715 // the drag-out case. |
| 714 if (info->save_info.file_path.empty()) { | 716 if (info->save_info.file_path.empty()) { |
| 715 info->path_uniquifier = download_util::GetUniquePathNumber( | 717 info->path_uniquifier = download_util::GetUniquePathNumber( |
| 716 info->suggested_path); | 718 info->suggested_path); |
| 717 } | 719 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 734 } else { | 736 } else { |
| 735 // We know the final path, build it if necessary. | 737 // We know the final path, build it if necessary. |
| 736 if (info->path_uniquifier > 0) { | 738 if (info->path_uniquifier > 0) { |
| 737 download_util::AppendNumberToPath(&(info->suggested_path), | 739 download_util::AppendNumberToPath(&(info->suggested_path), |
| 738 info->path_uniquifier); | 740 info->path_uniquifier); |
| 739 // Setting path_uniquifier to 0 to make sure we don't try to unique it | 741 // Setting path_uniquifier to 0 to make sure we don't try to unique it |
| 740 // later on. | 742 // later on. |
| 741 info->path_uniquifier = 0; | 743 info->path_uniquifier = 0; |
| 742 } else if (info->path_uniquifier == -1) { | 744 } else if (info->path_uniquifier == -1) { |
| 743 // We failed to find a unique path. We have to prompt the user. | 745 // We failed to find a unique path. We have to prompt the user. |
| 744 info->save_as = true; | 746 info->prompt_user_for_save_location = true; |
| 745 } | 747 } |
| 746 } | 748 } |
| 747 | 749 |
| 748 if (!info->save_as && info->save_info.file_path.empty()) { | 750 if (!info->prompt_user_for_save_location && |
| 751 info->save_info.file_path.empty()) { |
| 749 // Create an empty file at the suggested path so that we don't allocate the | 752 // Create an empty file at the suggested path so that we don't allocate the |
| 750 // same "non-existant" path to multiple downloads. | 753 // same "non-existant" path to multiple downloads. |
| 751 // See: http://code.google.com/p/chromium/issues/detail?id=3662 | 754 // See: http://code.google.com/p/chromium/issues/detail?id=3662 |
| 752 file_util::WriteFile(info->suggested_path, "", 0); | 755 file_util::WriteFile(info->suggested_path, "", 0); |
| 753 } | 756 } |
| 754 | 757 |
| 755 // Now we return to the UI thread. | 758 // Now we return to the UI thread. |
| 756 ChromeThread::PostTask( | 759 ChromeThread::PostTask( |
| 757 ChromeThread::UI, FROM_HERE, | 760 ChromeThread::UI, FROM_HERE, |
| 758 NewRunnableMethod(this, | 761 NewRunnableMethod(this, |
| 759 &DownloadManager::OnPathExistenceAvailable, | 762 &DownloadManager::OnPathExistenceAvailable, |
| 760 info)); | 763 info)); |
| 761 } | 764 } |
| 762 | 765 |
| 763 void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { | 766 void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { |
| 764 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 767 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 765 DCHECK(info); | 768 DCHECK(info); |
| 766 | 769 |
| 767 if (info->save_as) { | 770 if (info->prompt_user_for_save_location) { |
| 768 // We must ask the user for the place to put the download. | 771 // We must ask the user for the place to put the download. |
| 769 if (!select_file_dialog_.get()) | 772 if (!select_file_dialog_.get()) |
| 770 select_file_dialog_ = SelectFileDialog::Create(this); | 773 select_file_dialog_ = SelectFileDialog::Create(this); |
| 771 | 774 |
| 772 TabContents* contents = tab_util::GetTabContentsByID(info->child_id, | 775 TabContents* contents = tab_util::GetTabContentsByID(info->child_id, |
| 773 info->render_view_id); | 776 info->render_view_id); |
| 774 SelectFileDialog::FileTypeInfo file_type_info; | 777 SelectFileDialog::FileTypeInfo file_type_info; |
| 775 file_type_info.extensions.resize(1); | 778 file_type_info.extensions.resize(1); |
| 776 file_type_info.extensions[0].push_back(info->suggested_path.Extension()); | 779 file_type_info.extensions[0].push_back(info->suggested_path.Extension()); |
| 777 if (!file_type_info.extensions[0][0].empty()) | 780 if (!file_type_info.extensions[0][0].empty()) |
| (...skipping 26 matching lines...) Expand all Loading... |
| 804 info->url, | 807 info->url, |
| 805 info->referrer_url, | 808 info->referrer_url, |
| 806 info->mime_type, | 809 info->mime_type, |
| 807 info->original_mime_type, | 810 info->original_mime_type, |
| 808 info->original_name, | 811 info->original_name, |
| 809 info->start_time, | 812 info->start_time, |
| 810 info->total_bytes, | 813 info->total_bytes, |
| 811 info->child_id, | 814 info->child_id, |
| 812 info->request_id, | 815 info->request_id, |
| 813 info->is_dangerous, | 816 info->is_dangerous, |
| 814 info->save_as, | 817 info->prompt_user_for_save_location, |
| 815 profile_->IsOffTheRecord(), | 818 profile_->IsOffTheRecord(), |
| 816 info->is_extension_install, | 819 info->is_extension_install, |
| 817 !info->save_info.file_path.empty()); | 820 !info->save_info.file_path.empty()); |
| 818 download->set_manager(this); | 821 download->set_manager(this); |
| 819 in_progress_[info->download_id] = download; | 822 in_progress_[info->download_id] = download; |
| 820 } else { | 823 } else { |
| 821 NOTREACHED(); // Should not exist! | 824 NOTREACHED(); // Should not exist! |
| 822 return; | 825 return; |
| 823 } | 826 } |
| 824 | 827 |
| (...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1637 if (!extensions.empty()) | 1640 if (!extensions.empty()) |
| 1638 extensions.erase(extensions.size() - 1); | 1641 extensions.erase(extensions.size() - 1); |
| 1639 | 1642 |
| 1640 prefs->SetString(prefs::kDownloadExtensionsToOpen, extensions); | 1643 prefs->SetString(prefs::kDownloadExtensionsToOpen, extensions); |
| 1641 } | 1644 } |
| 1642 } | 1645 } |
| 1643 | 1646 |
| 1644 void DownloadManager::FileSelected(const FilePath& path, | 1647 void DownloadManager::FileSelected(const FilePath& path, |
| 1645 int index, void* params) { | 1648 int index, void* params) { |
| 1646 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); | 1649 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); |
| 1647 if (info->save_as) | 1650 if (info->prompt_user_for_save_location) |
| 1648 last_download_path_ = path.DirName(); | 1651 last_download_path_ = path.DirName(); |
| 1649 ContinueStartDownload(info, path); | 1652 ContinueStartDownload(info, path); |
| 1650 } | 1653 } |
| 1651 | 1654 |
| 1652 void DownloadManager::FileSelectionCanceled(void* params) { | 1655 void DownloadManager::FileSelectionCanceled(void* params) { |
| 1653 // The user didn't pick a place to save the file, so need to cancel the | 1656 // The user didn't pick a place to save the file, so need to cancel the |
| 1654 // download that's already in progress to the temporary location. | 1657 // download that's already in progress to the temporary location. |
| 1655 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); | 1658 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); |
| 1656 DownloadCancelledInternal(info->download_id, | 1659 DownloadCancelledInternal(info->download_id, |
| 1657 info->child_id, | 1660 info->child_id, |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1840 observing_download_manager_->NotifyModelChanged(); | 1843 observing_download_manager_->NotifyModelChanged(); |
| 1841 } | 1844 } |
| 1842 | 1845 |
| 1843 void DownloadManager::OtherDownloadManagerObserver::SetDownloads( | 1846 void DownloadManager::OtherDownloadManagerObserver::SetDownloads( |
| 1844 std::vector<DownloadItem*>& downloads) { | 1847 std::vector<DownloadItem*>& downloads) { |
| 1845 } | 1848 } |
| 1846 | 1849 |
| 1847 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { | 1850 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { |
| 1848 observed_download_manager_ = NULL; | 1851 observed_download_manager_ = NULL; |
| 1849 } | 1852 } |
| OLD | NEW |