| 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
|
|
|