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 // Download utility implementation | 5 // Download utility implementation |
6 | 6 |
7 #include "chrome/browser/download/download_util.h" | 7 #include "chrome/browser/download/download_util.h" |
8 | 8 |
9 #if defined(OS_WIN) | 9 #if defined(OS_WIN) |
10 #include <shobjidl.h> | 10 #include <shobjidl.h> |
11 #endif | 11 #endif |
12 #include <string> | 12 #include <string> |
13 | 13 |
14 #include "app/l10n_util.h" | 14 #include "app/l10n_util.h" |
15 #include "app/resource_bundle.h" | 15 #include "app/resource_bundle.h" |
16 #include "base/file_util.h" | 16 #include "base/file_util.h" |
17 #include "base/i18n/rtl.h" | 17 #include "base/i18n/rtl.h" |
18 #include "base/i18n/time_formatting.h" | 18 #include "base/i18n/time_formatting.h" |
19 #include "base/path_service.h" | 19 #include "base/path_service.h" |
20 #include "base/singleton.h" | 20 #include "base/singleton.h" |
21 #include "base/string_number_conversions.h" | 21 #include "base/string_number_conversions.h" |
| 22 #include "base/sys_string_conversions.h" |
22 #include "base/utf_string_conversions.h" | 23 #include "base/utf_string_conversions.h" |
23 #include "base/values.h" | 24 #include "base/values.h" |
| 25 #include "chrome/browser/browser.h" |
| 26 #include "chrome/browser/browser_list.h" |
24 #include "chrome/browser/browser_process.h" | 27 #include "chrome/browser/browser_process.h" |
25 #include "chrome/browser/chrome_thread.h" | 28 #include "chrome/browser/chrome_thread.h" |
26 #include "chrome/browser/download/download_item.h" | 29 #include "chrome/browser/download/download_item.h" |
27 #include "chrome/browser/download/download_item_model.h" | 30 #include "chrome/browser/download/download_item_model.h" |
28 #include "chrome/browser/download/download_manager.h" | 31 #include "chrome/browser/download/download_manager.h" |
| 32 #include "chrome/browser/extensions/crx_installer.h" |
| 33 #include "chrome/browser/extensions/extension_install_ui.h" |
| 34 #include "chrome/browser/extensions/extensions_service.h" |
| 35 #include "chrome/browser/history/download_types.h" |
29 #include "chrome/browser/net/chrome_url_request_context.h" | 36 #include "chrome/browser/net/chrome_url_request_context.h" |
| 37 #include "chrome/browser/profile.h" |
30 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" | 38 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" |
| 39 #include "chrome/browser/tab_contents/infobar_delegate.h" |
| 40 #include "chrome/browser/tab_contents/tab_contents.h" |
31 #include "chrome/common/chrome_paths.h" | 41 #include "chrome/common/chrome_paths.h" |
| 42 #include "chrome/common/notification_service.h" |
32 #include "chrome/common/time_format.h" | 43 #include "chrome/common/time_format.h" |
33 #include "gfx/canvas_skia.h" | 44 #include "gfx/canvas_skia.h" |
34 #include "gfx/rect.h" | 45 #include "gfx/rect.h" |
35 #include "grit/generated_resources.h" | 46 #include "grit/generated_resources.h" |
36 #include "grit/locale_settings.h" | 47 #include "grit/locale_settings.h" |
37 #include "grit/theme_resources.h" | 48 #include "grit/theme_resources.h" |
38 #include "net/base/mime_util.h" | 49 #include "net/base/mime_util.h" |
| 50 #include "net/base/net_util.h" |
39 #include "skia/ext/image_operations.h" | 51 #include "skia/ext/image_operations.h" |
40 #include "third_party/skia/include/core/SkPath.h" | 52 #include "third_party/skia/include/core/SkPath.h" |
41 #include "third_party/skia/include/core/SkShader.h" | 53 #include "third_party/skia/include/core/SkShader.h" |
42 | 54 |
43 #if defined(TOOLKIT_VIEWS) | 55 #if defined(TOOLKIT_VIEWS) |
44 #include "app/os_exchange_data.h" | 56 #include "app/os_exchange_data.h" |
45 #include "views/drag_utils.h" | 57 #include "views/drag_utils.h" |
46 #endif | 58 #endif |
47 | 59 |
48 #if defined(OS_LINUX) | 60 #if defined(OS_LINUX) |
49 #if defined(TOOLKIT_VIEWS) | 61 #if defined(TOOLKIT_VIEWS) |
50 #include "app/drag_drop_types.h" | 62 #include "app/drag_drop_types.h" |
51 #include "views/widget/widget_gtk.h" | 63 #include "views/widget/widget_gtk.h" |
52 #elif defined(TOOLKIT_GTK) | 64 #elif defined(TOOLKIT_GTK) |
53 #include "chrome/browser/gtk/custom_drag.h" | 65 #include "chrome/browser/gtk/custom_drag.h" |
54 #endif // defined(TOOLKIT_GTK) | 66 #endif // defined(TOOLKIT_GTK) |
55 #endif // defined(OS_LINUX) | 67 #endif // defined(OS_LINUX) |
56 | 68 |
57 #if defined(OS_WIN) | 69 #if defined(OS_WIN) |
58 #include "app/os_exchange_data_provider_win.h" | 70 #include "app/os_exchange_data_provider_win.h" |
| 71 #include "app/win_util.h" |
59 #include "base/base_drag_source.h" | 72 #include "base/base_drag_source.h" |
| 73 #include "base/registry.h" |
60 #include "base/scoped_comptr_win.h" | 74 #include "base/scoped_comptr_win.h" |
61 #include "base/win_util.h" | 75 #include "base/win_util.h" |
62 #include "chrome/browser/browser_list.h" | 76 #include "chrome/browser/browser_list.h" |
63 #include "chrome/browser/views/frame/browser_view.h" | 77 #include "chrome/browser/views/frame/browser_view.h" |
64 #endif | 78 #endif |
65 | 79 |
66 namespace download_util { | 80 namespace download_util { |
67 | 81 |
68 // How many times to cycle the complete animation. This should be an odd number | 82 // How many times to cycle the complete animation. This should be an odd number |
69 // so that the animation ends faded out. | 83 // so that the animation ends faded out. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 | 116 |
103 bool DownloadPathIsDangerous(const FilePath& download_path) { | 117 bool DownloadPathIsDangerous(const FilePath& download_path) { |
104 FilePath desktop_dir; | 118 FilePath desktop_dir; |
105 if (!PathService::Get(chrome::DIR_USER_DESKTOP, &desktop_dir)) { | 119 if (!PathService::Get(chrome::DIR_USER_DESKTOP, &desktop_dir)) { |
106 NOTREACHED(); | 120 NOTREACHED(); |
107 return false; | 121 return false; |
108 } | 122 } |
109 return (download_path == desktop_dir); | 123 return (download_path == desktop_dir); |
110 } | 124 } |
111 | 125 |
| 126 void GenerateExtension(const FilePath& file_name, |
| 127 const std::string& mime_type, |
| 128 FilePath::StringType* generated_extension) { |
| 129 // We're worried about three things here: |
| 130 // |
| 131 // 1) Security. Many sites let users upload content, such as buddy icons, to |
| 132 // their web sites. We want to mitigate the case where an attacker |
| 133 // supplies a malicious executable with an executable file extension but an |
| 134 // honest site serves the content with a benign content type, such as |
| 135 // image/jpeg. |
| 136 // |
| 137 // 2) Usability. If the site fails to provide a file extension, we want to |
| 138 // guess a reasonable file extension based on the content type. |
| 139 // |
| 140 // 3) Shell integration. Some file extensions automatically integrate with |
| 141 // the shell. We block these extensions to prevent a malicious web site |
| 142 // from integrating with the user's shell. |
| 143 |
| 144 static const FilePath::CharType default_extension[] = |
| 145 FILE_PATH_LITERAL("download"); |
| 146 |
| 147 // See if our file name already contains an extension. |
| 148 FilePath::StringType extension = file_name.Extension(); |
| 149 if (!extension.empty()) |
| 150 extension.erase(extension.begin()); // Erase preceding '.'. |
| 151 |
| 152 #if defined(OS_WIN) |
| 153 // Rename shell-integrated extensions. |
| 154 if (win_util::IsShellIntegratedExtension(extension)) |
| 155 extension.assign(default_extension); |
| 156 #endif |
| 157 |
| 158 std::string mime_type_from_extension; |
| 159 net::GetMimeTypeFromFile(file_name, |
| 160 &mime_type_from_extension); |
| 161 if (mime_type == mime_type_from_extension) { |
| 162 // The hinted extension matches the mime type. It looks like a winner. |
| 163 generated_extension->swap(extension); |
| 164 return; |
| 165 } |
| 166 |
| 167 if (IsExecutableExtension(extension) && !IsExecutableMimeType(mime_type)) { |
| 168 // We want to be careful about executable extensions. The worry here is |
| 169 // that a trusted web site could be tricked into dropping an executable file |
| 170 // on the user's filesystem. |
| 171 if (!net::GetPreferredExtensionForMimeType(mime_type, &extension)) { |
| 172 // We couldn't find a good extension for this content type. Use a dummy |
| 173 // extension instead. |
| 174 extension.assign(default_extension); |
| 175 } |
| 176 } |
| 177 |
| 178 if (extension.empty()) { |
| 179 net::GetPreferredExtensionForMimeType(mime_type, &extension); |
| 180 } else { |
| 181 // Append extension generated from the mime type if: |
| 182 // 1. New extension is not ".txt" |
| 183 // 2. New extension is not the same as the already existing extension. |
| 184 // 3. New extension is not executable. This action mitigates the case when |
| 185 // an executable is hidden in a benign file extension; |
| 186 // E.g. my-cat.jpg becomes my-cat.jpg.js if content type is |
| 187 // application/x-javascript. |
| 188 // 4. New extension is not ".tar" for .tar.gz files. For misconfigured web |
| 189 // servers, i.e. bug 5772. |
| 190 // 5. The original extension is not ".tgz" & the new extension is not "gz". |
| 191 FilePath::StringType append_extension; |
| 192 if (net::GetPreferredExtensionForMimeType(mime_type, &append_extension)) { |
| 193 if (append_extension != FILE_PATH_LITERAL("txt") && |
| 194 append_extension != extension && |
| 195 !IsExecutableExtension(append_extension) && |
| 196 !(append_extension == FILE_PATH_LITERAL("gz") && |
| 197 extension == FILE_PATH_LITERAL("tgz")) && |
| 198 (append_extension != FILE_PATH_LITERAL("tar") || |
| 199 extension != FILE_PATH_LITERAL("tar.gz"))) { |
| 200 extension += FILE_PATH_LITERAL("."); |
| 201 extension += append_extension; |
| 202 } |
| 203 } |
| 204 } |
| 205 |
| 206 generated_extension->swap(extension); |
| 207 } |
| 208 |
| 209 void GenerateFileNameFromInfo(DownloadCreateInfo* info, |
| 210 FilePath* generated_name) { |
| 211 GenerateFileName(GURL(info->url), |
| 212 info->content_disposition, |
| 213 info->referrer_charset, |
| 214 info->mime_type, |
| 215 generated_name); |
| 216 } |
| 217 |
| 218 void GenerateFileName(const GURL& url, |
| 219 const std::string& content_disposition, |
| 220 const std::string& referrer_charset, |
| 221 const std::string& mime_type, |
| 222 FilePath* generated_name) { |
| 223 std::wstring default_name = |
| 224 l10n_util::GetString(IDS_DEFAULT_DOWNLOAD_FILENAME); |
| 225 #if defined(OS_WIN) |
| 226 FilePath default_file_path(default_name); |
| 227 #elif defined(OS_POSIX) |
| 228 FilePath default_file_path(base::SysWideToNativeMB(default_name)); |
| 229 #endif |
| 230 |
| 231 *generated_name = net::GetSuggestedFilename(GURL(url), |
| 232 content_disposition, |
| 233 referrer_charset, |
| 234 default_file_path); |
| 235 |
| 236 DCHECK(!generated_name->empty()); |
| 237 |
| 238 GenerateSafeFileName(mime_type, generated_name); |
| 239 } |
| 240 |
| 241 void GenerateSafeFileName(const std::string& mime_type, FilePath* file_name) { |
| 242 // Make sure we get the right file extension |
| 243 FilePath::StringType extension; |
| 244 GenerateExtension(*file_name, mime_type, &extension); |
| 245 *file_name = file_name->ReplaceExtension(extension); |
| 246 |
| 247 #if defined(OS_WIN) |
| 248 // Prepend "_" to the file name if it's a reserved name |
| 249 FilePath::StringType leaf_name = file_name->BaseName().value(); |
| 250 DCHECK(!leaf_name.empty()); |
| 251 if (win_util::IsReservedName(leaf_name)) { |
| 252 leaf_name = FilePath::StringType(FILE_PATH_LITERAL("_")) + leaf_name; |
| 253 *file_name = file_name->DirName(); |
| 254 if (file_name->value() == FilePath::kCurrentDirectory) { |
| 255 *file_name = FilePath(leaf_name); |
| 256 } else { |
| 257 *file_name = file_name->Append(leaf_name); |
| 258 } |
| 259 } |
| 260 #endif |
| 261 } |
| 262 |
| 263 void OpenChromeExtension(Profile* profile, |
| 264 DownloadManager* download_manager, |
| 265 const DownloadItem& download_item) { |
| 266 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
| 267 DCHECK(download_item.is_extension_install()); |
| 268 |
| 269 // We don't support extensions in OTR mode. |
| 270 ExtensionsService* service = profile->GetExtensionsService(); |
| 271 if (service) { |
| 272 NotificationService* nservice = NotificationService::current(); |
| 273 GURL nonconst_download_url = download_item.url(); |
| 274 nservice->Notify(NotificationType::EXTENSION_READY_FOR_INSTALL, |
| 275 Source<DownloadManager>(download_manager), |
| 276 Details<GURL>(&nonconst_download_url)); |
| 277 |
| 278 scoped_refptr<CrxInstaller> installer( |
| 279 new CrxInstaller(service->install_directory(), |
| 280 service, |
| 281 new ExtensionInstallUI(profile))); |
| 282 installer->set_delete_source(true); |
| 283 |
| 284 if (UserScript::HasUserScriptFileExtension(download_item.url())) { |
| 285 installer->InstallUserScript(download_item.full_path(), |
| 286 download_item.url()); |
| 287 } else { |
| 288 bool is_gallery_download = ExtensionsService::IsDownloadFromGallery( |
| 289 download_item.url(), download_item.referrer_url()); |
| 290 installer->set_original_mime_type(download_item.original_mime_type()); |
| 291 installer->set_apps_require_extension_mime_type(true); |
| 292 installer->set_allow_privilege_increase(true); |
| 293 installer->set_original_url(download_item.url()); |
| 294 installer->set_limit_web_extent_to_download_host(!is_gallery_download); |
| 295 installer->InstallCrx(download_item.full_path()); |
| 296 } |
| 297 } else { |
| 298 TabContents* contents = NULL; |
| 299 // Get last active normal browser of profile. |
| 300 Browser* last_active = |
| 301 BrowserList::FindBrowserWithType(profile, Browser::TYPE_NORMAL, true); |
| 302 if (last_active) |
| 303 contents = last_active->GetSelectedTabContents(); |
| 304 if (contents) { |
| 305 contents->AddInfoBar( |
| 306 new SimpleAlertInfoBarDelegate(contents, |
| 307 l10n_util::GetString( |
| 308 IDS_EXTENSION_INCOGNITO_INSTALL_INFOBAR_LABEL), |
| 309 ResourceBundle::GetSharedInstance().GetBitmapNamed( |
| 310 IDR_INFOBAR_PLUGIN_INSTALL), |
| 311 true)); |
| 312 } |
| 313 } |
| 314 } |
| 315 |
112 // Download progress painting -------------------------------------------------- | 316 // Download progress painting -------------------------------------------------- |
113 | 317 |
114 // Common bitmaps used for download progress animations. We load them once the | 318 // Common bitmaps used for download progress animations. We load them once the |
115 // first time we do a progress paint, then reuse them as they are always the | 319 // first time we do a progress paint, then reuse them as they are always the |
116 // same. | 320 // same. |
117 SkBitmap* g_foreground_16 = NULL; | 321 SkBitmap* g_foreground_16 = NULL; |
118 SkBitmap* g_background_16 = NULL; | 322 SkBitmap* g_background_16 = NULL; |
119 SkBitmap* g_foreground_32 = NULL; | 323 SkBitmap* g_foreground_32 = NULL; |
120 SkBitmap* g_background_32 = NULL; | 324 SkBitmap* g_background_32 = NULL; |
121 | 325 |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 } | 752 } |
549 | 753 |
550 FilePath GetCrDownloadPath(const FilePath& suggested_path) { | 754 FilePath GetCrDownloadPath(const FilePath& suggested_path) { |
551 FilePath::StringType file_name; | 755 FilePath::StringType file_name; |
552 SStringPrintf(&file_name, PRFilePathLiteral FILE_PATH_LITERAL(".crdownload"), | 756 SStringPrintf(&file_name, PRFilePathLiteral FILE_PATH_LITERAL(".crdownload"), |
553 suggested_path.value().c_str()); | 757 suggested_path.value().c_str()); |
554 return FilePath(file_name); | 758 return FilePath(file_name); |
555 } | 759 } |
556 | 760 |
557 } // namespace download_util | 761 } // namespace download_util |
OLD | NEW |