Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: chrome/browser/download/download_util.cc

Issue 3043048: Clean up download code: (Closed)
Patch Set: Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « chrome/browser/download/download_util.h ('k') | chrome/browser/download/download_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698