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

Unified Diff: chrome/browser/download/download_util.cc

Issue 3043048: Clean up download code: (Closed)
Patch Set: Created 10 years, 5 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/download/download_util.cc
diff --git a/chrome/browser/download/download_util.cc b/chrome/browser/download/download_util.cc
index 4aeb9827825cf33344ba7999ddf69917639a2eb8..2a4e00288132fc0fb003bc167246caa145e491b1 100644
--- a/chrome/browser/download/download_util.cc
+++ b/chrome/browser/download/download_util.cc
@@ -19,16 +19,27 @@
#include "base/path_service.h"
#include "base/singleton.h"
#include "base/string_number_conversions.h"
+#include "base/sys_string_conversions.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/download/download_item.h"
#include "chrome/browser/download/download_item_model.h"
#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/extensions/crx_installer.h"
+#include "chrome/browser/extensions/extension_install_ui.h"
+#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/browser/history/download_types.h"
#include "chrome/browser/net/chrome_url_request_context.h"
+#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
+#include "chrome/browser/tab_contents/infobar_delegate.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_paths.h"
+#include "chrome/common/notification_service.h"
#include "chrome/common/time_format.h"
#include "gfx/canvas_skia.h"
#include "gfx/rect.h"
@@ -36,6 +47,7 @@
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"
#include "net/base/mime_util.h"
+#include "net/base/net_util.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkShader.h"
@@ -56,7 +68,9 @@
#if defined(OS_WIN)
#include "app/os_exchange_data_provider_win.h"
+#include "app/win_util.h"
#include "base/base_drag_source.h"
+#include "base/registry.h"
#include "base/scoped_comptr_win.h"
#include "base/win_util.h"
#include "chrome/browser/browser_list.h"
@@ -109,6 +123,196 @@ bool DownloadPathIsDangerous(const FilePath& download_path) {
return (download_path == desktop_dir);
}
+void GenerateExtension(const FilePath& file_name,
+ const std::string& mime_type,
+ FilePath::StringType* generated_extension) {
+ // We're worried about three things here:
+ //
+ // 1) Security. Many sites let users upload content, such as buddy icons, to
+ // their web sites. We want to mitigate the case where an attacker
+ // supplies a malicious executable with an executable file extension but an
+ // honest site serves the content with a benign content type, such as
+ // image/jpeg.
+ //
+ // 2) Usability. If the site fails to provide a file extension, we want to
+ // guess a reasonable file extension based on the content type.
+ //
+ // 3) Shell integration. Some file extensions automatically integrate with
+ // the shell. We block these extensions to prevent a malicious web site
+ // from integrating with the user's shell.
+
+ static const FilePath::CharType default_extension[] =
+ FILE_PATH_LITERAL("download");
+
+ // See if our file name already contains an extension.
+ FilePath::StringType extension = file_name.Extension();
+ if (!extension.empty())
+ extension.erase(extension.begin()); // Erase preceding '.'.
+
+#if defined(OS_WIN)
+ // Rename shell-integrated extensions.
+ if (win_util::IsShellIntegratedExtension(extension))
+ extension.assign(default_extension);
+#endif
+
+ std::string mime_type_from_extension;
+ net::GetMimeTypeFromFile(file_name,
+ &mime_type_from_extension);
+ if (mime_type == mime_type_from_extension) {
+ // The hinted extension matches the mime type. It looks like a winner.
+ generated_extension->swap(extension);
+ return;
+ }
+
+ if (IsExecutableExtension(extension) && !IsExecutableMimeType(mime_type)) {
+ // We want to be careful about executable extensions. The worry here is
+ // that a trusted web site could be tricked into dropping an executable file
+ // on the user's filesystem.
+ if (!net::GetPreferredExtensionForMimeType(mime_type, &extension)) {
+ // We couldn't find a good extension for this content type. Use a dummy
+ // extension instead.
+ extension.assign(default_extension);
+ }
+ }
+
+ if (extension.empty()) {
+ net::GetPreferredExtensionForMimeType(mime_type, &extension);
+ } else {
+ // Append extension generated from the mime type if:
+ // 1. New extension is not ".txt"
+ // 2. New extension is not the same as the already existing extension.
+ // 3. New extension is not executable. This action mitigates the case when
+ // an executable is hidden in a benign file extension;
+ // E.g. my-cat.jpg becomes my-cat.jpg.js if content type is
+ // application/x-javascript.
+ // 4. New extension is not ".tar" for .tar.gz files. For misconfigured web
+ // servers, i.e. bug 5772.
+ // 5. The original extension is not ".tgz" & the new extension is not "gz".
+ FilePath::StringType append_extension;
+ if (net::GetPreferredExtensionForMimeType(mime_type, &append_extension)) {
+ if (append_extension != FILE_PATH_LITERAL("txt") &&
+ append_extension != extension &&
+ !IsExecutableExtension(append_extension) &&
+ !(append_extension == FILE_PATH_LITERAL("gz") &&
+ extension == FILE_PATH_LITERAL("tgz")) &&
+ (append_extension != FILE_PATH_LITERAL("tar") ||
+ extension != FILE_PATH_LITERAL("tar.gz"))) {
+ extension += FILE_PATH_LITERAL(".");
+ extension += append_extension;
+ }
+ }
+ }
+
+ generated_extension->swap(extension);
+}
+
+void GenerateFileNameFromInfo(DownloadCreateInfo* info,
+ FilePath* generated_name) {
+ GenerateFileName(GURL(info->url),
+ info->content_disposition,
+ info->referrer_charset,
+ info->mime_type,
+ generated_name);
+}
+
+void GenerateFileName(const GURL& url,
+ const std::string& content_disposition,
+ const std::string& referrer_charset,
+ const std::string& mime_type,
+ FilePath* generated_name) {
+ std::wstring default_name =
+ l10n_util::GetString(IDS_DEFAULT_DOWNLOAD_FILENAME);
+#if defined(OS_WIN)
+ FilePath default_file_path(default_name);
+#elif defined(OS_POSIX)
+ FilePath default_file_path(base::SysWideToNativeMB(default_name));
+#endif
+
+ *generated_name = net::GetSuggestedFilename(GURL(url),
+ content_disposition,
+ referrer_charset,
+ default_file_path);
+
+ DCHECK(!generated_name->empty());
+
+ GenerateSafeFileName(mime_type, generated_name);
+}
+
+void GenerateSafeFileName(const std::string& mime_type, FilePath* file_name) {
+ // Make sure we get the right file extension
+ FilePath::StringType extension;
+ GenerateExtension(*file_name, mime_type, &extension);
+ *file_name = file_name->ReplaceExtension(extension);
+
+#if defined(OS_WIN)
+ // Prepend "_" to the file name if it's a reserved name
+ FilePath::StringType leaf_name = file_name->BaseName().value();
+ DCHECK(!leaf_name.empty());
+ if (win_util::IsReservedName(leaf_name)) {
+ leaf_name = FilePath::StringType(FILE_PATH_LITERAL("_")) + leaf_name;
+ *file_name = file_name->DirName();
+ if (file_name->value() == FilePath::kCurrentDirectory) {
+ *file_name = FilePath(leaf_name);
+ } else {
+ *file_name = file_name->Append(leaf_name);
+ }
+ }
+#endif
+}
+
+void OpenChromeExtension(Profile* profile,
+ DownloadManager* download_manager,
+ const DownloadItem& download_item) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ DCHECK(download_item.is_extension_install());
+
+ // We don't support extensions in OTR mode.
+ ExtensionsService* service = profile->GetExtensionsService();
+ if (service) {
+ NotificationService* nservice = NotificationService::current();
+ GURL nonconst_download_url = download_item.url();
+ nservice->Notify(NotificationType::EXTENSION_READY_FOR_INSTALL,
+ Source<DownloadManager>(download_manager),
+ Details<GURL>(&nonconst_download_url));
+
+ scoped_refptr<CrxInstaller> installer(
+ new CrxInstaller(service->install_directory(),
+ service,
+ new ExtensionInstallUI(profile)));
+ installer->set_delete_source(true);
+
+ if (UserScript::HasUserScriptFileExtension(download_item.url())) {
+ installer->InstallUserScript(download_item.full_path(),
+ download_item.url());
+ } else {
+ bool is_gallery_download = ExtensionsService::IsDownloadFromGallery(
+ download_item.url(), download_item.referrer_url());
+ installer->set_original_mime_type(download_item.original_mime_type());
+ installer->set_apps_require_extension_mime_type(true);
+ installer->set_allow_privilege_increase(true);
+ installer->set_original_url(download_item.url());
+ installer->set_limit_web_extent_to_download_host(!is_gallery_download);
+ installer->InstallCrx(download_item.full_path());
+ }
+ } else {
+ TabContents* contents = NULL;
+ // Get last active normal browser of profile.
+ Browser* last_active =
+ BrowserList::FindBrowserWithType(profile, Browser::TYPE_NORMAL, true);
+ if (last_active)
+ contents = last_active->GetSelectedTabContents();
+ if (contents) {
+ contents->AddInfoBar(
+ new SimpleAlertInfoBarDelegate(contents,
+ l10n_util::GetString(
+ IDS_EXTENSION_INCOGNITO_INSTALL_INFOBAR_LABEL),
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_INFOBAR_PLUGIN_INSTALL),
+ true));
+ }
+ }
+}
+
// Download progress painting --------------------------------------------------
// Common bitmaps used for download progress animations. We load them once the
« 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