| Index: chrome/browser/download/download_manager.cc
|
| diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc
|
| index f2e3a65b494b28653ced3c3dbdf02c6364c84105..652b9d7fcef9273cc7dacd2e5b2cd6fd020eacc0 100644
|
| --- a/chrome/browser/download/download_manager.cc
|
| +++ b/chrome/browser/download/download_manager.cc
|
| @@ -22,8 +22,6 @@
|
| #include "chrome/browser/download/download_history.h"
|
| #include "chrome/browser/download/download_item.h"
|
| #include "chrome/browser/download/download_util.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"
|
| @@ -57,14 +55,6 @@ bool CompareStartTime(DownloadItem* first, DownloadItem* second) {
|
| return first->start_time() > second->start_time();
|
| }
|
|
|
| -void DeleteDownloadedFile(const FilePath& path) {
|
| - DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
|
| -
|
| - // Make sure we only delete files.
|
| - if (!file_util::DirectoryExists(path))
|
| - file_util::Delete(path, false);
|
| -}
|
| -
|
| } // namespace
|
|
|
| // static
|
| @@ -295,7 +285,7 @@ void DownloadManager::StartDownload(DownloadCreateInfo* info) {
|
|
|
| if (info->save_info.file_path.empty()) {
|
| FilePath generated_name;
|
| - GenerateFileNameFromInfo(info, &generated_name);
|
| + download_util::GenerateFileNameFromInfo(info, &generated_name);
|
|
|
| // Freeze the user's preference for showing a Save As dialog. We're going
|
| // to bounce around a bunch of threads and we don't want to worry about race
|
| @@ -330,7 +320,7 @@ void DownloadManager::StartDownload(DownloadCreateInfo* info) {
|
| // Downloads can be marked as dangerous for two reasons:
|
| // a) They have a dangerous-looking filename
|
| // b) They are an extension that is not from the gallery
|
| - if (IsDangerous(info->suggested_path.BaseName()))
|
| + if (IsExecutableFile(info->suggested_path.BaseName()))
|
| info->is_dangerous = true;
|
| else if (info->is_extension_install &&
|
| !ExtensionsService::IsDownloadFromGallery(info->url,
|
| @@ -596,10 +586,7 @@ void DownloadManager::ContinueDownloadFinished(DownloadItem* download) {
|
|
|
| // Handle chrome extensions explicitly and skip the shell execute.
|
| if (download->is_extension_install()) {
|
| - OpenChromeExtension(download->full_path(),
|
| - download->url(),
|
| - download->referrer_url(),
|
| - download->original_mime_type());
|
| + download_util::OpenChromeExtension(profile_, this, *download);
|
| download->set_auto_opened(true);
|
| } else if (download->open_when_complete() ||
|
| ShouldOpenFileBasedOnExtension(download->full_path()) ||
|
| @@ -715,6 +702,9 @@ void DownloadManager::DownloadCancelledInternal(int download_id,
|
| file_manager_, &DownloadFileManager::CancelDownload, download_id));
|
| }
|
|
|
| +// DownloadManager is owned by RDH, no need for reference counting.
|
| +DISABLE_RUNNABLE_METHOD_REFCOUNT(ResourceDispatcherHost);
|
| +
|
| void DownloadManager::PauseDownload(int32 download_id, bool pause) {
|
| DownloadMap::iterator it = in_progress_.find(download_id);
|
| if (it == in_progress_.end())
|
| @@ -727,24 +717,11 @@ void DownloadManager::PauseDownload(int32 download_id, bool pause) {
|
| // Inform the ResourceDispatcherHost of the new pause state.
|
| ChromeThread::PostTask(
|
| ChromeThread::IO, FROM_HERE,
|
| - NewRunnableFunction(&DownloadManager::OnPauseDownloadRequest,
|
| - g_browser_process->resource_dispatcher_host(),
|
| - download->render_process_id(),
|
| - download->request_id(),
|
| - pause));
|
| -}
|
| -
|
| -// static
|
| -void DownloadManager::OnPauseDownloadRequest(ResourceDispatcherHost* rdh,
|
| - int render_process_id,
|
| - int request_id,
|
| - bool pause) {
|
| - rdh->PauseRequest(render_process_id, request_id, pause);
|
| -}
|
| -
|
| -bool DownloadManager::IsDangerous(const FilePath& file_name) {
|
| - // TODO(jcampan): Improve me.
|
| - return IsExecutableFile(file_name);
|
| + NewRunnableMethod(g_browser_process->resource_dispatcher_host(),
|
| + &ResourceDispatcherHost::PauseRequest,
|
| + download->render_process_id(),
|
| + download->request_id(),
|
| + pause));
|
| }
|
|
|
| void DownloadManager::UpdateAppIcon() {
|
| @@ -770,7 +747,7 @@ void DownloadManager::UpdateAppIcon() {
|
|
|
| float progress = 0;
|
| if (progress_known && download_count)
|
| - progress = (float)received_bytes / total_bytes;
|
| + progress = static_cast<float>(received_bytes) / total_bytes;
|
|
|
| download_util::UpdateAppIconDownloadProgress(download_count,
|
| progress_known,
|
| @@ -889,122 +866,6 @@ void DownloadManager::DownloadUrlToFile(const GURL& url,
|
| request_context_getter_));
|
| }
|
|
|
| -void DownloadManager::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 DownloadManager::GenerateFileNameFromInfo(DownloadCreateInfo* info,
|
| - FilePath* generated_name) {
|
| - GenerateFileName(GURL(info->url),
|
| - info->content_disposition,
|
| - info->referrer_charset,
|
| - info->mime_type,
|
| - generated_name);
|
| -}
|
| -
|
| -void DownloadManager::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 DownloadManager::AddObserver(Observer* observer) {
|
| observers_.AddObserver(observer);
|
| observer->ModelChanged();
|
| @@ -1036,66 +897,12 @@ void DownloadManager::OpenDownload(const DownloadItem* download,
|
| // Open Chrome extensions with ExtensionsService. For everything else do shell
|
| // execute.
|
| if (download->is_extension_install()) {
|
| - OpenChromeExtension(download->full_path(),
|
| - download->url(),
|
| - download->referrer_url(),
|
| - download->original_mime_type());
|
| + download_util::OpenChromeExtension(profile_, this, *download);
|
| } else {
|
| OpenDownloadInShell(download, parent_window);
|
| }
|
| }
|
|
|
| -void DownloadManager::OpenChromeExtension(
|
| - const FilePath& full_path,
|
| - const GURL& download_url,
|
| - const GURL& referrer_url,
|
| - const std::string& original_mime_type) {
|
| - // We don't support extensions in OTR mode.
|
| - ExtensionsService* service = profile_->GetExtensionsService();
|
| - if (service) {
|
| - NotificationService* nservice = NotificationService::current();
|
| - GURL nonconst_download_url = download_url;
|
| - nservice->Notify(NotificationType::EXTENSION_READY_FOR_INSTALL,
|
| - Source<DownloadManager>(this),
|
| - 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_url)) {
|
| - installer->InstallUserScript(full_path, download_url);
|
| - } else {
|
| - bool is_gallery_download =
|
| - ExtensionsService::IsDownloadFromGallery(download_url, referrer_url);
|
| - installer->set_original_mime_type(original_mime_type);
|
| - installer->set_apps_require_extension_mime_type(true);
|
| - installer->set_allow_privilege_increase(true);
|
| - installer->set_original_url(download_url);
|
| - installer->set_limit_web_extent_to_download_host(!is_gallery_download);
|
| - installer->InstallCrx(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));
|
| - }
|
| - }
|
| -}
|
| -
|
| void DownloadManager::OpenDownloadInShell(const DownloadItem* download,
|
| gfx::NativeView parent_window) {
|
| DCHECK(file_manager_);
|
| @@ -1119,7 +926,7 @@ void DownloadManager::OpenFilesBasedOnExtension(
|
| return;
|
| DCHECK(extension[0] == FilePath::kExtensionSeparator);
|
| extension.erase(0, 1);
|
| - if (open && !IsExecutableExtension(extension))
|
| + if (open && !download_util::IsExecutableExtension(extension))
|
| auto_open_.insert(extension);
|
| else
|
| auto_open_.erase(extension);
|
| @@ -1131,7 +938,7 @@ bool DownloadManager::ShouldOpenFileBasedOnExtension(
|
| FilePath::StringType extension = path.Extension();
|
| if (extension.empty())
|
| return false;
|
| - if (IsExecutableExtension(extension))
|
| + if (download_util::IsExecutableExtension(extension))
|
| return false;
|
| if (Extension::IsExtension(path))
|
| return false;
|
| @@ -1142,59 +949,8 @@ bool DownloadManager::ShouldOpenFileBasedOnExtension(
|
| return false;
|
| }
|
|
|
| -static const char* kExecutableWhiteList[] = {
|
| - // JavaScript is just as powerful as EXE.
|
| - "text/javascript",
|
| - "text/javascript;version=*",
|
| - // Registry files can cause critical changes to the MS OS behavior.
|
| - // Addition of this mimetype also addresses bug 7337.
|
| - "text/x-registry",
|
| - // Some sites use binary/octet-stream to mean application/octet-stream.
|
| - // See http://code.google.com/p/chromium/issues/detail?id=1573
|
| - "binary/octet-stream"
|
| -};
|
| -
|
| -static const char* kExecutableBlackList[] = {
|
| - // These application types are not executable.
|
| - "application/*+xml",
|
| - "application/xml"
|
| -};
|
| -
|
| -// static
|
| -bool DownloadManager::IsExecutableMimeType(const std::string& mime_type) {
|
| - for (size_t i = 0; i < arraysize(kExecutableWhiteList); ++i) {
|
| - if (net::MatchesMimeType(kExecutableWhiteList[i], mime_type))
|
| - return true;
|
| - }
|
| - for (size_t i = 0; i < arraysize(kExecutableBlackList); ++i) {
|
| - if (net::MatchesMimeType(kExecutableBlackList[i], mime_type))
|
| - return false;
|
| - }
|
| - // We consider only other application types to be executable.
|
| - return net::MatchesMimeType("application/*", mime_type);
|
| -}
|
| -
|
| bool DownloadManager::IsExecutableFile(const FilePath& path) const {
|
| - return IsExecutableExtension(path.Extension());
|
| -}
|
| -
|
| -bool DownloadManager::IsExecutableExtension(
|
| - const FilePath::StringType& extension) {
|
| - if (extension.empty())
|
| - return false;
|
| - if (!IsStringASCII(extension))
|
| - return false;
|
| -#if defined(OS_WIN)
|
| - std::string ascii_extension = WideToASCII(extension);
|
| -#elif defined(OS_POSIX)
|
| - std::string ascii_extension = extension;
|
| -#endif
|
| -
|
| - // Strip out leading dot if it's still there
|
| - if (ascii_extension[0] == FilePath::kExtensionSeparator)
|
| - ascii_extension.erase(0, 1);
|
| -
|
| - return download_util::IsExecutableExtension(ascii_extension);
|
| + return download_util::IsExecutableExtension(path.Extension());
|
| }
|
|
|
| void DownloadManager::ResetAutoOpenFiles() {
|
| @@ -1253,12 +1009,6 @@ void DownloadManager::FileSelectionCanceled(void* params) {
|
| info->request_id);
|
| }
|
|
|
| -void DownloadManager::DeleteDownload(const FilePath& path) {
|
| - ChromeThread::PostTask(
|
| - ChromeThread::FILE, FROM_HERE,
|
| - NewRunnableFunction(&DeleteDownloadedFile, path));
|
| -}
|
| -
|
| void DownloadManager::DangerousDownloadValidated(DownloadItem* download) {
|
| DCHECK_EQ(DownloadItem::DANGEROUS, download->safety_state());
|
| download->set_safety_state(DownloadItem::DANGEROUS_BUT_VALIDATED);
|
| @@ -1277,29 +1027,6 @@ void DownloadManager::DangerousDownloadValidated(DownloadItem* download) {
|
| download->original_name()));
|
| }
|
|
|
| -void DownloadManager::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
|
| -}
|
| -
|
| // Operations posted to us from the history service ----------------------------
|
|
|
| // The history service has retrieved all download entries. 'entries' contains
|
|
|