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 |