| 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" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/path_service.h" | 12 #include "base/path_service.h" |
| 13 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
| 14 #include "base/sys_string_conversions.h" | 14 #include "base/sys_string_conversions.h" |
| 15 #include "base/task.h" | 15 #include "base/task.h" |
| 16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
| 17 #include "chrome/browser/browser.h" | 17 #include "chrome/browser/browser.h" |
| 18 #include "chrome/browser/browser_list.h" | 18 #include "chrome/browser/browser_list.h" |
| 19 #include "chrome/browser/browser_process.h" | 19 #include "chrome/browser/browser_process.h" |
| 20 #include "chrome/browser/chrome_thread.h" | 20 #include "chrome/browser/chrome_thread.h" |
| 21 #include "chrome/browser/download/download_file_manager.h" | 21 #include "chrome/browser/download/download_file_manager.h" |
| 22 #include "chrome/browser/download/download_history.h" | 22 #include "chrome/browser/download/download_history.h" |
| 23 #include "chrome/browser/download/download_item.h" | 23 #include "chrome/browser/download/download_item.h" |
| 24 #include "chrome/browser/download/download_util.h" | 24 #include "chrome/browser/download/download_util.h" |
| 25 #include "chrome/browser/extensions/crx_installer.h" | |
| 26 #include "chrome/browser/extensions/extension_install_ui.h" | |
| 27 #include "chrome/browser/extensions/extensions_service.h" | 25 #include "chrome/browser/extensions/extensions_service.h" |
| 28 #include "chrome/browser/history/download_types.h" | 26 #include "chrome/browser/history/download_types.h" |
| 29 #include "chrome/browser/net/chrome_url_request_context.h" | 27 #include "chrome/browser/net/chrome_url_request_context.h" |
| 30 #include "chrome/browser/platform_util.h" | 28 #include "chrome/browser/platform_util.h" |
| 31 #include "chrome/browser/profile.h" | 29 #include "chrome/browser/profile.h" |
| 32 #include "chrome/browser/renderer_host/render_process_host.h" | 30 #include "chrome/browser/renderer_host/render_process_host.h" |
| 33 #include "chrome/browser/renderer_host/render_view_host.h" | 31 #include "chrome/browser/renderer_host/render_view_host.h" |
| 34 #include "chrome/browser/tab_contents/infobar_delegate.h" | 32 #include "chrome/browser/tab_contents/infobar_delegate.h" |
| 35 #include "chrome/browser/tab_contents/tab_contents.h" | 33 #include "chrome/browser/tab_contents/tab_contents.h" |
| 36 #include "chrome/browser/tab_contents/tab_util.h" | 34 #include "chrome/browser/tab_contents/tab_util.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 50 #include "base/win_util.h" | 48 #include "base/win_util.h" |
| 51 #endif | 49 #endif |
| 52 | 50 |
| 53 namespace { | 51 namespace { |
| 54 | 52 |
| 55 // Used to sort download items based on descending start time. | 53 // Used to sort download items based on descending start time. |
| 56 bool CompareStartTime(DownloadItem* first, DownloadItem* second) { | 54 bool CompareStartTime(DownloadItem* first, DownloadItem* second) { |
| 57 return first->start_time() > second->start_time(); | 55 return first->start_time() > second->start_time(); |
| 58 } | 56 } |
| 59 | 57 |
| 60 void DeleteDownloadedFile(const FilePath& path) { | |
| 61 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); | |
| 62 | |
| 63 // Make sure we only delete files. | |
| 64 if (!file_util::DirectoryExists(path)) | |
| 65 file_util::Delete(path, false); | |
| 66 } | |
| 67 | |
| 68 } // namespace | 58 } // namespace |
| 69 | 59 |
| 70 // static | 60 // static |
| 71 void DownloadManager::RegisterUserPrefs(PrefService* prefs) { | 61 void DownloadManager::RegisterUserPrefs(PrefService* prefs) { |
| 72 prefs->RegisterBooleanPref(prefs::kPromptForDownload, false); | 62 prefs->RegisterBooleanPref(prefs::kPromptForDownload, false); |
| 73 prefs->RegisterStringPref(prefs::kDownloadExtensionsToOpen, ""); | 63 prefs->RegisterStringPref(prefs::kDownloadExtensionsToOpen, ""); |
| 74 prefs->RegisterBooleanPref(prefs::kDownloadDirUpgraded, false); | 64 prefs->RegisterBooleanPref(prefs::kDownloadDirUpgraded, false); |
| 75 | 65 |
| 76 // The default download path is userprofile\download. | 66 // The default download path is userprofile\download. |
| 77 const FilePath& default_download_path = | 67 const FilePath& default_download_path = |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 // Check whether this download is for an extension install or not. | 278 // Check whether this download is for an extension install or not. |
| 289 // Allow extensions to be explicitly saved. | 279 // Allow extensions to be explicitly saved. |
| 290 if (!info->prompt_user_for_save_location) { | 280 if (!info->prompt_user_for_save_location) { |
| 291 if (UserScript::HasUserScriptFileExtension(info->url) || | 281 if (UserScript::HasUserScriptFileExtension(info->url) || |
| 292 info->mime_type == Extension::kMimeType) | 282 info->mime_type == Extension::kMimeType) |
| 293 info->is_extension_install = true; | 283 info->is_extension_install = true; |
| 294 } | 284 } |
| 295 | 285 |
| 296 if (info->save_info.file_path.empty()) { | 286 if (info->save_info.file_path.empty()) { |
| 297 FilePath generated_name; | 287 FilePath generated_name; |
| 298 GenerateFileNameFromInfo(info, &generated_name); | 288 download_util::GenerateFileNameFromInfo(info, &generated_name); |
| 299 | 289 |
| 300 // Freeze the user's preference for showing a Save As dialog. We're going | 290 // Freeze the user's preference for showing a Save As dialog. We're going |
| 301 // to bounce around a bunch of threads and we don't want to worry about race | 291 // to bounce around a bunch of threads and we don't want to worry about race |
| 302 // conditions where the user changes this pref out from under us. | 292 // conditions where the user changes this pref out from under us. |
| 303 if (*prompt_for_download_) { | 293 if (*prompt_for_download_) { |
| 304 // But ignore the user's preference for the following scenarios: | 294 // But ignore the user's preference for the following scenarios: |
| 305 // 1) Extension installation. Note that we only care here about the case | 295 // 1) Extension installation. Note that we only care here about the case |
| 306 // where an extension is installed, not when one is downloaded with | 296 // where an extension is installed, not when one is downloaded with |
| 307 // "save as...". | 297 // "save as...". |
| 308 // 2) Filetypes marked "always open." If the user just wants this file | 298 // 2) Filetypes marked "always open." If the user just wants this file |
| (...skipping 14 matching lines...) Expand all Loading... |
| 323 info->suggested_path = info->suggested_path.Append(generated_name); | 313 info->suggested_path = info->suggested_path.Append(generated_name); |
| 324 } else { | 314 } else { |
| 325 info->suggested_path = info->save_info.file_path; | 315 info->suggested_path = info->save_info.file_path; |
| 326 } | 316 } |
| 327 | 317 |
| 328 if (!info->prompt_user_for_save_location && | 318 if (!info->prompt_user_for_save_location && |
| 329 info->save_info.file_path.empty()) { | 319 info->save_info.file_path.empty()) { |
| 330 // Downloads can be marked as dangerous for two reasons: | 320 // Downloads can be marked as dangerous for two reasons: |
| 331 // a) They have a dangerous-looking filename | 321 // a) They have a dangerous-looking filename |
| 332 // b) They are an extension that is not from the gallery | 322 // b) They are an extension that is not from the gallery |
| 333 if (IsDangerous(info->suggested_path.BaseName())) | 323 if (IsExecutableFile(info->suggested_path.BaseName())) |
| 334 info->is_dangerous = true; | 324 info->is_dangerous = true; |
| 335 else if (info->is_extension_install && | 325 else if (info->is_extension_install && |
| 336 !ExtensionsService::IsDownloadFromGallery(info->url, | 326 !ExtensionsService::IsDownloadFromGallery(info->url, |
| 337 info->referrer_url)) { | 327 info->referrer_url)) { |
| 338 info->is_dangerous = true; | 328 info->is_dangerous = true; |
| 339 } | 329 } |
| 340 } | 330 } |
| 341 | 331 |
| 342 // We need to move over to the download thread because we don't want to stat | 332 // We need to move over to the download thread because we don't want to stat |
| 343 // the suggested path on the UI thread. | 333 // the suggested path on the UI thread. |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 | 579 |
| 590 void DownloadManager::ContinueDownloadFinished(DownloadItem* download) { | 580 void DownloadManager::ContinueDownloadFinished(DownloadItem* download) { |
| 591 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 581 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 592 | 582 |
| 593 // If this was a dangerous download, it has now been approved and must be | 583 // If this was a dangerous download, it has now been approved and must be |
| 594 // removed from dangerous_finished_ so it does not get deleted on shutdown. | 584 // removed from dangerous_finished_ so it does not get deleted on shutdown. |
| 595 dangerous_finished_.erase(download->id()); | 585 dangerous_finished_.erase(download->id()); |
| 596 | 586 |
| 597 // Handle chrome extensions explicitly and skip the shell execute. | 587 // Handle chrome extensions explicitly and skip the shell execute. |
| 598 if (download->is_extension_install()) { | 588 if (download->is_extension_install()) { |
| 599 OpenChromeExtension(download->full_path(), | 589 download_util::OpenChromeExtension(profile_, this, *download); |
| 600 download->url(), | |
| 601 download->referrer_url(), | |
| 602 download->original_mime_type()); | |
| 603 download->set_auto_opened(true); | 590 download->set_auto_opened(true); |
| 604 } else if (download->open_when_complete() || | 591 } else if (download->open_when_complete() || |
| 605 ShouldOpenFileBasedOnExtension(download->full_path()) || | 592 ShouldOpenFileBasedOnExtension(download->full_path()) || |
| 606 download->is_temporary()) { | 593 download->is_temporary()) { |
| 607 // If the download is temporary, like in drag-and-drop, do not open it but | 594 // If the download is temporary, like in drag-and-drop, do not open it but |
| 608 // we still need to set it auto-opened so that it can be removed from the | 595 // we still need to set it auto-opened so that it can be removed from the |
| 609 // download shelf. | 596 // download shelf. |
| 610 if (!download->is_temporary()) | 597 if (!download->is_temporary()) |
| 611 OpenDownloadInShell(download, NULL); | 598 OpenDownloadInShell(download, NULL); |
| 612 download->set_auto_opened(true); | 599 download->set_auto_opened(true); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 request_id)); | 695 request_id)); |
| 709 | 696 |
| 710 // Tell the file manager to cancel the download. | 697 // Tell the file manager to cancel the download. |
| 711 file_manager_->RemoveDownload(download_id, this); // On the UI thread | 698 file_manager_->RemoveDownload(download_id, this); // On the UI thread |
| 712 ChromeThread::PostTask( | 699 ChromeThread::PostTask( |
| 713 ChromeThread::FILE, FROM_HERE, | 700 ChromeThread::FILE, FROM_HERE, |
| 714 NewRunnableMethod( | 701 NewRunnableMethod( |
| 715 file_manager_, &DownloadFileManager::CancelDownload, download_id)); | 702 file_manager_, &DownloadFileManager::CancelDownload, download_id)); |
| 716 } | 703 } |
| 717 | 704 |
| 705 // DownloadManager is owned by RDH, no need for reference counting. |
| 706 DISABLE_RUNNABLE_METHOD_REFCOUNT(ResourceDispatcherHost); |
| 707 |
| 718 void DownloadManager::PauseDownload(int32 download_id, bool pause) { | 708 void DownloadManager::PauseDownload(int32 download_id, bool pause) { |
| 719 DownloadMap::iterator it = in_progress_.find(download_id); | 709 DownloadMap::iterator it = in_progress_.find(download_id); |
| 720 if (it == in_progress_.end()) | 710 if (it == in_progress_.end()) |
| 721 return; | 711 return; |
| 722 | 712 |
| 723 DownloadItem* download = it->second; | 713 DownloadItem* download = it->second; |
| 724 if (pause == download->is_paused()) | 714 if (pause == download->is_paused()) |
| 725 return; | 715 return; |
| 726 | 716 |
| 727 // Inform the ResourceDispatcherHost of the new pause state. | 717 // Inform the ResourceDispatcherHost of the new pause state. |
| 728 ChromeThread::PostTask( | 718 ChromeThread::PostTask( |
| 729 ChromeThread::IO, FROM_HERE, | 719 ChromeThread::IO, FROM_HERE, |
| 730 NewRunnableFunction(&DownloadManager::OnPauseDownloadRequest, | 720 NewRunnableMethod(g_browser_process->resource_dispatcher_host(), |
| 731 g_browser_process->resource_dispatcher_host(), | 721 &ResourceDispatcherHost::PauseRequest, |
| 732 download->render_process_id(), | 722 download->render_process_id(), |
| 733 download->request_id(), | 723 download->request_id(), |
| 734 pause)); | 724 pause)); |
| 735 } | |
| 736 | |
| 737 // static | |
| 738 void DownloadManager::OnPauseDownloadRequest(ResourceDispatcherHost* rdh, | |
| 739 int render_process_id, | |
| 740 int request_id, | |
| 741 bool pause) { | |
| 742 rdh->PauseRequest(render_process_id, request_id, pause); | |
| 743 } | |
| 744 | |
| 745 bool DownloadManager::IsDangerous(const FilePath& file_name) { | |
| 746 // TODO(jcampan): Improve me. | |
| 747 return IsExecutableFile(file_name); | |
| 748 } | 725 } |
| 749 | 726 |
| 750 void DownloadManager::UpdateAppIcon() { | 727 void DownloadManager::UpdateAppIcon() { |
| 751 int64 total_bytes = 0; | 728 int64 total_bytes = 0; |
| 752 int64 received_bytes = 0; | 729 int64 received_bytes = 0; |
| 753 int download_count = 0; | 730 int download_count = 0; |
| 754 bool progress_known = true; | 731 bool progress_known = true; |
| 755 | 732 |
| 756 for (DownloadMap::iterator i = in_progress_.begin(); | 733 for (DownloadMap::iterator i = in_progress_.begin(); |
| 757 i != in_progress_.end(); | 734 i != in_progress_.end(); |
| 758 ++i) { | 735 ++i) { |
| 759 ++download_count; | 736 ++download_count; |
| 760 const DownloadItem* item = i->second; | 737 const DownloadItem* item = i->second; |
| 761 if (item->total_bytes() > 0) { | 738 if (item->total_bytes() > 0) { |
| 762 total_bytes += item->total_bytes(); | 739 total_bytes += item->total_bytes(); |
| 763 received_bytes += item->received_bytes(); | 740 received_bytes += item->received_bytes(); |
| 764 } else { | 741 } else { |
| 765 // This download didn't specify a Content-Length, so the combined progress | 742 // This download didn't specify a Content-Length, so the combined progress |
| 766 // bar neeeds to be indeterminate. | 743 // bar neeeds to be indeterminate. |
| 767 progress_known = false; | 744 progress_known = false; |
| 768 } | 745 } |
| 769 } | 746 } |
| 770 | 747 |
| 771 float progress = 0; | 748 float progress = 0; |
| 772 if (progress_known && download_count) | 749 if (progress_known && download_count) |
| 773 progress = (float)received_bytes / total_bytes; | 750 progress = static_cast<float>(received_bytes) / total_bytes; |
| 774 | 751 |
| 775 download_util::UpdateAppIconDownloadProgress(download_count, | 752 download_util::UpdateAppIconDownloadProgress(download_count, |
| 776 progress_known, | 753 progress_known, |
| 777 progress); | 754 progress); |
| 778 } | 755 } |
| 779 | 756 |
| 780 void DownloadManager::RenameDownload(DownloadItem* download, | 757 void DownloadManager::RenameDownload(DownloadItem* download, |
| 781 const FilePath& new_path) { | 758 const FilePath& new_path) { |
| 782 download->Rename(new_path); | 759 download->Rename(new_path); |
| 783 download_history_->UpdateDownloadPath(download, new_path); | 760 download_history_->UpdateDownloadPath(download, new_path); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 882 url, | 859 url, |
| 883 referrer, | 860 referrer, |
| 884 referrer_charset, | 861 referrer_charset, |
| 885 save_info, | 862 save_info, |
| 886 g_browser_process->resource_dispatcher_host(), | 863 g_browser_process->resource_dispatcher_host(), |
| 887 tab_contents->GetRenderProcessHost()->id(), | 864 tab_contents->GetRenderProcessHost()->id(), |
| 888 tab_contents->render_view_host()->routing_id(), | 865 tab_contents->render_view_host()->routing_id(), |
| 889 request_context_getter_)); | 866 request_context_getter_)); |
| 890 } | 867 } |
| 891 | 868 |
| 892 void DownloadManager::GenerateExtension( | |
| 893 const FilePath& file_name, | |
| 894 const std::string& mime_type, | |
| 895 FilePath::StringType* generated_extension) { | |
| 896 // We're worried about three things here: | |
| 897 // | |
| 898 // 1) Security. Many sites let users upload content, such as buddy icons, to | |
| 899 // their web sites. We want to mitigate the case where an attacker | |
| 900 // supplies a malicious executable with an executable file extension but an | |
| 901 // honest site serves the content with a benign content type, such as | |
| 902 // image/jpeg. | |
| 903 // | |
| 904 // 2) Usability. If the site fails to provide a file extension, we want to | |
| 905 // guess a reasonable file extension based on the content type. | |
| 906 // | |
| 907 // 3) Shell integration. Some file extensions automatically integrate with | |
| 908 // the shell. We block these extensions to prevent a malicious web site | |
| 909 // from integrating with the user's shell. | |
| 910 | |
| 911 static const FilePath::CharType default_extension[] = | |
| 912 FILE_PATH_LITERAL("download"); | |
| 913 | |
| 914 // See if our file name already contains an extension. | |
| 915 FilePath::StringType extension = file_name.Extension(); | |
| 916 if (!extension.empty()) | |
| 917 extension.erase(extension.begin()); // Erase preceding '.'. | |
| 918 | |
| 919 #if defined(OS_WIN) | |
| 920 // Rename shell-integrated extensions. | |
| 921 if (win_util::IsShellIntegratedExtension(extension)) | |
| 922 extension.assign(default_extension); | |
| 923 #endif | |
| 924 | |
| 925 std::string mime_type_from_extension; | |
| 926 net::GetMimeTypeFromFile(file_name, | |
| 927 &mime_type_from_extension); | |
| 928 if (mime_type == mime_type_from_extension) { | |
| 929 // The hinted extension matches the mime type. It looks like a winner. | |
| 930 generated_extension->swap(extension); | |
| 931 return; | |
| 932 } | |
| 933 | |
| 934 if (IsExecutableExtension(extension) && !IsExecutableMimeType(mime_type)) { | |
| 935 // We want to be careful about executable extensions. The worry here is | |
| 936 // that a trusted web site could be tricked into dropping an executable file | |
| 937 // on the user's filesystem. | |
| 938 if (!net::GetPreferredExtensionForMimeType(mime_type, &extension)) { | |
| 939 // We couldn't find a good extension for this content type. Use a dummy | |
| 940 // extension instead. | |
| 941 extension.assign(default_extension); | |
| 942 } | |
| 943 } | |
| 944 | |
| 945 if (extension.empty()) { | |
| 946 net::GetPreferredExtensionForMimeType(mime_type, &extension); | |
| 947 } else { | |
| 948 // Append extension generated from the mime type if: | |
| 949 // 1. New extension is not ".txt" | |
| 950 // 2. New extension is not the same as the already existing extension. | |
| 951 // 3. New extension is not executable. This action mitigates the case when | |
| 952 // an executable is hidden in a benign file extension; | |
| 953 // E.g. my-cat.jpg becomes my-cat.jpg.js if content type is | |
| 954 // application/x-javascript. | |
| 955 // 4. New extension is not ".tar" for .tar.gz files. For misconfigured web | |
| 956 // servers, i.e. bug 5772. | |
| 957 // 5. The original extension is not ".tgz" & the new extension is not "gz". | |
| 958 FilePath::StringType append_extension; | |
| 959 if (net::GetPreferredExtensionForMimeType(mime_type, &append_extension)) { | |
| 960 if (append_extension != FILE_PATH_LITERAL("txt") && | |
| 961 append_extension != extension && | |
| 962 !IsExecutableExtension(append_extension) && | |
| 963 !(append_extension == FILE_PATH_LITERAL("gz") && | |
| 964 extension == FILE_PATH_LITERAL("tgz")) && | |
| 965 (append_extension != FILE_PATH_LITERAL("tar") || | |
| 966 extension != FILE_PATH_LITERAL("tar.gz"))) { | |
| 967 extension += FILE_PATH_LITERAL("."); | |
| 968 extension += append_extension; | |
| 969 } | |
| 970 } | |
| 971 } | |
| 972 | |
| 973 generated_extension->swap(extension); | |
| 974 } | |
| 975 | |
| 976 void DownloadManager::GenerateFileNameFromInfo(DownloadCreateInfo* info, | |
| 977 FilePath* generated_name) { | |
| 978 GenerateFileName(GURL(info->url), | |
| 979 info->content_disposition, | |
| 980 info->referrer_charset, | |
| 981 info->mime_type, | |
| 982 generated_name); | |
| 983 } | |
| 984 | |
| 985 void DownloadManager::GenerateFileName(const GURL& url, | |
| 986 const std::string& content_disposition, | |
| 987 const std::string& referrer_charset, | |
| 988 const std::string& mime_type, | |
| 989 FilePath* generated_name) { | |
| 990 std::wstring default_name = | |
| 991 l10n_util::GetString(IDS_DEFAULT_DOWNLOAD_FILENAME); | |
| 992 #if defined(OS_WIN) | |
| 993 FilePath default_file_path(default_name); | |
| 994 #elif defined(OS_POSIX) | |
| 995 FilePath default_file_path(base::SysWideToNativeMB(default_name)); | |
| 996 #endif | |
| 997 | |
| 998 *generated_name = net::GetSuggestedFilename(GURL(url), | |
| 999 content_disposition, | |
| 1000 referrer_charset, | |
| 1001 default_file_path); | |
| 1002 | |
| 1003 DCHECK(!generated_name->empty()); | |
| 1004 | |
| 1005 GenerateSafeFileName(mime_type, generated_name); | |
| 1006 } | |
| 1007 | |
| 1008 void DownloadManager::AddObserver(Observer* observer) { | 869 void DownloadManager::AddObserver(Observer* observer) { |
| 1009 observers_.AddObserver(observer); | 870 observers_.AddObserver(observer); |
| 1010 observer->ModelChanged(); | 871 observer->ModelChanged(); |
| 1011 } | 872 } |
| 1012 | 873 |
| 1013 void DownloadManager::RemoveObserver(Observer* observer) { | 874 void DownloadManager::RemoveObserver(Observer* observer) { |
| 1014 observers_.RemoveObserver(observer); | 875 observers_.RemoveObserver(observer); |
| 1015 } | 876 } |
| 1016 | 877 |
| 1017 // Post Windows Shell operations to the Download thread, to avoid blocking the | 878 // Post Windows Shell operations to the Download thread, to avoid blocking the |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1029 file_manager_, &DownloadFileManager::OnShowDownloadInShell, | 890 file_manager_, &DownloadFileManager::OnShowDownloadInShell, |
| 1030 FilePath(download->full_path()))); | 891 FilePath(download->full_path()))); |
| 1031 #endif | 892 #endif |
| 1032 } | 893 } |
| 1033 | 894 |
| 1034 void DownloadManager::OpenDownload(const DownloadItem* download, | 895 void DownloadManager::OpenDownload(const DownloadItem* download, |
| 1035 gfx::NativeView parent_window) { | 896 gfx::NativeView parent_window) { |
| 1036 // Open Chrome extensions with ExtensionsService. For everything else do shell | 897 // Open Chrome extensions with ExtensionsService. For everything else do shell |
| 1037 // execute. | 898 // execute. |
| 1038 if (download->is_extension_install()) { | 899 if (download->is_extension_install()) { |
| 1039 OpenChromeExtension(download->full_path(), | 900 download_util::OpenChromeExtension(profile_, this, *download); |
| 1040 download->url(), | |
| 1041 download->referrer_url(), | |
| 1042 download->original_mime_type()); | |
| 1043 } else { | 901 } else { |
| 1044 OpenDownloadInShell(download, parent_window); | 902 OpenDownloadInShell(download, parent_window); |
| 1045 } | 903 } |
| 1046 } | 904 } |
| 1047 | 905 |
| 1048 void DownloadManager::OpenChromeExtension( | |
| 1049 const FilePath& full_path, | |
| 1050 const GURL& download_url, | |
| 1051 const GURL& referrer_url, | |
| 1052 const std::string& original_mime_type) { | |
| 1053 // We don't support extensions in OTR mode. | |
| 1054 ExtensionsService* service = profile_->GetExtensionsService(); | |
| 1055 if (service) { | |
| 1056 NotificationService* nservice = NotificationService::current(); | |
| 1057 GURL nonconst_download_url = download_url; | |
| 1058 nservice->Notify(NotificationType::EXTENSION_READY_FOR_INSTALL, | |
| 1059 Source<DownloadManager>(this), | |
| 1060 Details<GURL>(&nonconst_download_url)); | |
| 1061 | |
| 1062 scoped_refptr<CrxInstaller> installer( | |
| 1063 new CrxInstaller(service->install_directory(), | |
| 1064 service, | |
| 1065 new ExtensionInstallUI(profile_))); | |
| 1066 installer->set_delete_source(true); | |
| 1067 | |
| 1068 if (UserScript::HasUserScriptFileExtension(download_url)) { | |
| 1069 installer->InstallUserScript(full_path, download_url); | |
| 1070 } else { | |
| 1071 bool is_gallery_download = | |
| 1072 ExtensionsService::IsDownloadFromGallery(download_url, referrer_url); | |
| 1073 installer->set_original_mime_type(original_mime_type); | |
| 1074 installer->set_apps_require_extension_mime_type(true); | |
| 1075 installer->set_allow_privilege_increase(true); | |
| 1076 installer->set_original_url(download_url); | |
| 1077 installer->set_limit_web_extent_to_download_host(!is_gallery_download); | |
| 1078 installer->InstallCrx(full_path); | |
| 1079 } | |
| 1080 } else { | |
| 1081 TabContents* contents = NULL; | |
| 1082 // Get last active normal browser of profile. | |
| 1083 Browser* last_active = BrowserList::FindBrowserWithType(profile_, | |
| 1084 Browser::TYPE_NORMAL, true); | |
| 1085 if (last_active) | |
| 1086 contents = last_active->GetSelectedTabContents(); | |
| 1087 if (contents) { | |
| 1088 contents->AddInfoBar( | |
| 1089 new SimpleAlertInfoBarDelegate(contents, | |
| 1090 l10n_util::GetString( | |
| 1091 IDS_EXTENSION_INCOGNITO_INSTALL_INFOBAR_LABEL), | |
| 1092 ResourceBundle::GetSharedInstance().GetBitmapNamed( | |
| 1093 IDR_INFOBAR_PLUGIN_INSTALL), | |
| 1094 true)); | |
| 1095 } | |
| 1096 } | |
| 1097 } | |
| 1098 | |
| 1099 void DownloadManager::OpenDownloadInShell(const DownloadItem* download, | 906 void DownloadManager::OpenDownloadInShell(const DownloadItem* download, |
| 1100 gfx::NativeView parent_window) { | 907 gfx::NativeView parent_window) { |
| 1101 DCHECK(file_manager_); | 908 DCHECK(file_manager_); |
| 1102 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 909 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 1103 #if defined(OS_MACOSX) | 910 #if defined(OS_MACOSX) |
| 1104 // Mac OS X requires opening downloads on the UI thread. | 911 // Mac OS X requires opening downloads on the UI thread. |
| 1105 platform_util::OpenItem(download->full_path()); | 912 platform_util::OpenItem(download->full_path()); |
| 1106 #else | 913 #else |
| 1107 ChromeThread::PostTask( | 914 ChromeThread::PostTask( |
| 1108 ChromeThread::FILE, FROM_HERE, | 915 ChromeThread::FILE, FROM_HERE, |
| 1109 NewRunnableMethod( | 916 NewRunnableMethod( |
| 1110 file_manager_, &DownloadFileManager::OnOpenDownloadInShell, | 917 file_manager_, &DownloadFileManager::OnOpenDownloadInShell, |
| 1111 download->full_path(), download->url(), parent_window)); | 918 download->full_path(), download->url(), parent_window)); |
| 1112 #endif | 919 #endif |
| 1113 } | 920 } |
| 1114 | 921 |
| 1115 void DownloadManager::OpenFilesBasedOnExtension( | 922 void DownloadManager::OpenFilesBasedOnExtension( |
| 1116 const FilePath& path, bool open) { | 923 const FilePath& path, bool open) { |
| 1117 FilePath::StringType extension = path.Extension(); | 924 FilePath::StringType extension = path.Extension(); |
| 1118 if (extension.empty()) | 925 if (extension.empty()) |
| 1119 return; | 926 return; |
| 1120 DCHECK(extension[0] == FilePath::kExtensionSeparator); | 927 DCHECK(extension[0] == FilePath::kExtensionSeparator); |
| 1121 extension.erase(0, 1); | 928 extension.erase(0, 1); |
| 1122 if (open && !IsExecutableExtension(extension)) | 929 if (open && !download_util::IsExecutableExtension(extension)) |
| 1123 auto_open_.insert(extension); | 930 auto_open_.insert(extension); |
| 1124 else | 931 else |
| 1125 auto_open_.erase(extension); | 932 auto_open_.erase(extension); |
| 1126 SaveAutoOpens(); | 933 SaveAutoOpens(); |
| 1127 } | 934 } |
| 1128 | 935 |
| 1129 bool DownloadManager::ShouldOpenFileBasedOnExtension( | 936 bool DownloadManager::ShouldOpenFileBasedOnExtension( |
| 1130 const FilePath& path) const { | 937 const FilePath& path) const { |
| 1131 FilePath::StringType extension = path.Extension(); | 938 FilePath::StringType extension = path.Extension(); |
| 1132 if (extension.empty()) | 939 if (extension.empty()) |
| 1133 return false; | 940 return false; |
| 1134 if (IsExecutableExtension(extension)) | 941 if (download_util::IsExecutableExtension(extension)) |
| 1135 return false; | 942 return false; |
| 1136 if (Extension::IsExtension(path)) | 943 if (Extension::IsExtension(path)) |
| 1137 return false; | 944 return false; |
| 1138 DCHECK(extension[0] == FilePath::kExtensionSeparator); | 945 DCHECK(extension[0] == FilePath::kExtensionSeparator); |
| 1139 extension.erase(0, 1); | 946 extension.erase(0, 1); |
| 1140 if (auto_open_.find(extension) != auto_open_.end()) | 947 if (auto_open_.find(extension) != auto_open_.end()) |
| 1141 return true; | 948 return true; |
| 1142 return false; | 949 return false; |
| 1143 } | 950 } |
| 1144 | 951 |
| 1145 static const char* kExecutableWhiteList[] = { | |
| 1146 // JavaScript is just as powerful as EXE. | |
| 1147 "text/javascript", | |
| 1148 "text/javascript;version=*", | |
| 1149 // Registry files can cause critical changes to the MS OS behavior. | |
| 1150 // Addition of this mimetype also addresses bug 7337. | |
| 1151 "text/x-registry", | |
| 1152 // Some sites use binary/octet-stream to mean application/octet-stream. | |
| 1153 // See http://code.google.com/p/chromium/issues/detail?id=1573 | |
| 1154 "binary/octet-stream" | |
| 1155 }; | |
| 1156 | |
| 1157 static const char* kExecutableBlackList[] = { | |
| 1158 // These application types are not executable. | |
| 1159 "application/*+xml", | |
| 1160 "application/xml" | |
| 1161 }; | |
| 1162 | |
| 1163 // static | |
| 1164 bool DownloadManager::IsExecutableMimeType(const std::string& mime_type) { | |
| 1165 for (size_t i = 0; i < arraysize(kExecutableWhiteList); ++i) { | |
| 1166 if (net::MatchesMimeType(kExecutableWhiteList[i], mime_type)) | |
| 1167 return true; | |
| 1168 } | |
| 1169 for (size_t i = 0; i < arraysize(kExecutableBlackList); ++i) { | |
| 1170 if (net::MatchesMimeType(kExecutableBlackList[i], mime_type)) | |
| 1171 return false; | |
| 1172 } | |
| 1173 // We consider only other application types to be executable. | |
| 1174 return net::MatchesMimeType("application/*", mime_type); | |
| 1175 } | |
| 1176 | |
| 1177 bool DownloadManager::IsExecutableFile(const FilePath& path) const { | 952 bool DownloadManager::IsExecutableFile(const FilePath& path) const { |
| 1178 return IsExecutableExtension(path.Extension()); | 953 return download_util::IsExecutableExtension(path.Extension()); |
| 1179 } | |
| 1180 | |
| 1181 bool DownloadManager::IsExecutableExtension( | |
| 1182 const FilePath::StringType& extension) { | |
| 1183 if (extension.empty()) | |
| 1184 return false; | |
| 1185 if (!IsStringASCII(extension)) | |
| 1186 return false; | |
| 1187 #if defined(OS_WIN) | |
| 1188 std::string ascii_extension = WideToASCII(extension); | |
| 1189 #elif defined(OS_POSIX) | |
| 1190 std::string ascii_extension = extension; | |
| 1191 #endif | |
| 1192 | |
| 1193 // Strip out leading dot if it's still there | |
| 1194 if (ascii_extension[0] == FilePath::kExtensionSeparator) | |
| 1195 ascii_extension.erase(0, 1); | |
| 1196 | |
| 1197 return download_util::IsExecutableExtension(ascii_extension); | |
| 1198 } | 954 } |
| 1199 | 955 |
| 1200 void DownloadManager::ResetAutoOpenFiles() { | 956 void DownloadManager::ResetAutoOpenFiles() { |
| 1201 auto_open_.clear(); | 957 auto_open_.clear(); |
| 1202 SaveAutoOpens(); | 958 SaveAutoOpens(); |
| 1203 } | 959 } |
| 1204 | 960 |
| 1205 bool DownloadManager::HasAutoOpenFileTypesRegistered() const { | 961 bool DownloadManager::HasAutoOpenFileTypesRegistered() const { |
| 1206 return !auto_open_.empty(); | 962 return !auto_open_.empty(); |
| 1207 } | 963 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1246 | 1002 |
| 1247 void DownloadManager::FileSelectionCanceled(void* params) { | 1003 void DownloadManager::FileSelectionCanceled(void* params) { |
| 1248 // The user didn't pick a place to save the file, so need to cancel the | 1004 // The user didn't pick a place to save the file, so need to cancel the |
| 1249 // download that's already in progress to the temporary location. | 1005 // download that's already in progress to the temporary location. |
| 1250 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); | 1006 DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); |
| 1251 DownloadCancelledInternal(info->download_id, | 1007 DownloadCancelledInternal(info->download_id, |
| 1252 info->child_id, | 1008 info->child_id, |
| 1253 info->request_id); | 1009 info->request_id); |
| 1254 } | 1010 } |
| 1255 | 1011 |
| 1256 void DownloadManager::DeleteDownload(const FilePath& path) { | |
| 1257 ChromeThread::PostTask( | |
| 1258 ChromeThread::FILE, FROM_HERE, | |
| 1259 NewRunnableFunction(&DeleteDownloadedFile, path)); | |
| 1260 } | |
| 1261 | |
| 1262 void DownloadManager::DangerousDownloadValidated(DownloadItem* download) { | 1012 void DownloadManager::DangerousDownloadValidated(DownloadItem* download) { |
| 1263 DCHECK_EQ(DownloadItem::DANGEROUS, download->safety_state()); | 1013 DCHECK_EQ(DownloadItem::DANGEROUS, download->safety_state()); |
| 1264 download->set_safety_state(DownloadItem::DANGEROUS_BUT_VALIDATED); | 1014 download->set_safety_state(DownloadItem::DANGEROUS_BUT_VALIDATED); |
| 1265 download->UpdateObservers(); | 1015 download->UpdateObservers(); |
| 1266 | 1016 |
| 1267 // If the download is not complete, nothing to do. The required | 1017 // If the download is not complete, nothing to do. The required |
| 1268 // post-processing will be performed when it does complete. | 1018 // post-processing will be performed when it does complete. |
| 1269 if (download->state() != DownloadItem::COMPLETE) | 1019 if (download->state() != DownloadItem::COMPLETE) |
| 1270 return; | 1020 return; |
| 1271 | 1021 |
| 1272 ChromeThread::PostTask( | 1022 ChromeThread::PostTask( |
| 1273 ChromeThread::FILE, FROM_HERE, | 1023 ChromeThread::FILE, FROM_HERE, |
| 1274 NewRunnableMethod( | 1024 NewRunnableMethod( |
| 1275 this, &DownloadManager::ProceedWithFinishedDangerousDownload, | 1025 this, &DownloadManager::ProceedWithFinishedDangerousDownload, |
| 1276 download->db_handle(), download->full_path(), | 1026 download->db_handle(), download->full_path(), |
| 1277 download->original_name())); | 1027 download->original_name())); |
| 1278 } | 1028 } |
| 1279 | 1029 |
| 1280 void DownloadManager::GenerateSafeFileName(const std::string& mime_type, | |
| 1281 FilePath* file_name) { | |
| 1282 // Make sure we get the right file extension | |
| 1283 FilePath::StringType extension; | |
| 1284 GenerateExtension(*file_name, mime_type, &extension); | |
| 1285 *file_name = file_name->ReplaceExtension(extension); | |
| 1286 | |
| 1287 #if defined(OS_WIN) | |
| 1288 // Prepend "_" to the file name if it's a reserved name | |
| 1289 FilePath::StringType leaf_name = file_name->BaseName().value(); | |
| 1290 DCHECK(!leaf_name.empty()); | |
| 1291 if (win_util::IsReservedName(leaf_name)) { | |
| 1292 leaf_name = FilePath::StringType(FILE_PATH_LITERAL("_")) + leaf_name; | |
| 1293 *file_name = file_name->DirName(); | |
| 1294 if (file_name->value() == FilePath::kCurrentDirectory) { | |
| 1295 *file_name = FilePath(leaf_name); | |
| 1296 } else { | |
| 1297 *file_name = file_name->Append(leaf_name); | |
| 1298 } | |
| 1299 } | |
| 1300 #endif | |
| 1301 } | |
| 1302 | |
| 1303 // Operations posted to us from the history service ---------------------------- | 1030 // Operations posted to us from the history service ---------------------------- |
| 1304 | 1031 |
| 1305 // The history service has retrieved all download entries. 'entries' contains | 1032 // The history service has retrieved all download entries. 'entries' contains |
| 1306 // 'DownloadCreateInfo's in sorted order (by ascending start_time). | 1033 // 'DownloadCreateInfo's in sorted order (by ascending start_time). |
| 1307 void DownloadManager::OnQueryDownloadEntriesComplete( | 1034 void DownloadManager::OnQueryDownloadEntriesComplete( |
| 1308 std::vector<DownloadCreateInfo>* entries) { | 1035 std::vector<DownloadCreateInfo>* entries) { |
| 1309 for (size_t i = 0; i < entries->size(); ++i) { | 1036 for (size_t i = 0; i < entries->size(); ++i) { |
| 1310 DownloadItem* download = new DownloadItem(this, entries->at(i)); | 1037 DownloadItem* download = new DownloadItem(this, entries->at(i)); |
| 1311 DCHECK(!ContainsKey(downloads_, download->db_handle())); | 1038 DCHECK(!ContainsKey(downloads_, download->db_handle())); |
| 1312 downloads_[download->db_handle()] = download; | 1039 downloads_[download->db_handle()] = download; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1419 observed_download_manager_->RemoveObserver(this); | 1146 observed_download_manager_->RemoveObserver(this); |
| 1420 } | 1147 } |
| 1421 | 1148 |
| 1422 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { | 1149 void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { |
| 1423 observing_download_manager_->NotifyModelChanged(); | 1150 observing_download_manager_->NotifyModelChanged(); |
| 1424 } | 1151 } |
| 1425 | 1152 |
| 1426 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { | 1153 void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { |
| 1427 observed_download_manager_ = NULL; | 1154 observed_download_manager_ = NULL; |
| 1428 } | 1155 } |
| OLD | NEW |