diff options
27 files changed, 376 insertions, 291 deletions
diff --git a/chrome/browser/download/download_exe.cc b/chrome/browser/download/download_exe.cc deleted file mode 100644 index 8111f5d..0000000 --- a/chrome/browser/download/download_exe.cc +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <set> -#include <string> - -#include "chrome/browser/download/download_util.h" - -#include "base/string_util.h" -#include "net/base/mime_util.h" -#include "net/base/net_util.h" - -namespace download_util { - -// For file extensions taken from mozilla: - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Doug Turner <dougt@netscape.com> - * Dean Tessman <dean_tessman@hotmail.com> - * Brodie Thiesfield <brofield@jellycan.com> - * Jungshik Shin <jshin@i18nl10n.com> - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -static const char* const g_executables[] = { - "class", - "htm", - "html", - "jar", - "pdf", - "pdfxml", - "mars", - "fdf", - "xfdf", - "xdp", - "xfd", - "pl", - "py", - "rb", - "shtm", - "shtml", - "svg", - "swf", - "xht", - "xhtm", - "xhtml", - "xml", - "xsl", - "xslt", -#if defined(OS_WIN) - "ad", - "ade", - "adp", - "app", - "application", - "asp", - "asx", - "bas", - "bat", - "chm", - "cmd", - "com", - "cpl", - "crt", - "dll", - "exe", - "fxp", - "hlp", - "hta", - "htt", - "inf", - "ins", - "isp", - "js", - "jse", - "lnk", - "mad", - "maf", - "mag", - "mam", - "maq", - "mar", - "mas", - "mat", - "mau", - "mav", - "maw", - "mda", - "mdb", - "mde", - "mdt", - "mdw", - "mdz", - "mht", - "mhtml", - "msc", - "msh", - "mshxml", - "msi", - "msp", - "mst", - "ocx", - "ops", - "pcd", - "pif", - "plg", - "prf", - "prg", - "pst", - "reg", - "scf", - "scr", - "sct", - "shb", - "shs", - "url", - "vb", - "vbe", - "vbs", - "vsd", - "vsmacros", - "vss", - "vst", - "vsw", - "ws", - "wsc", - "wsf", - "wsh", - "xbap", -#elif defined(OS_MACOSX) - // TODO(thakis): Figure out what makes sense here -- crbug.com/19096 - "app", - "dmg", -#elif defined(OS_POSIX) - // TODO(estade): lengthen this list. - "bash", - "csh", - "deb", - "exe", - "ksh", - "rpm", - "sh", - "tcsh", -#endif -}; - -bool IsExecutableFile(const FilePath& path) { - return IsExecutableExtension(path.Extension()); -} - -bool 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); - - for (size_t i = 0; i < arraysize(g_executables); ++i) { - if (LowerCaseEqualsASCII(ascii_extension, g_executables[i])) - return true; - } - return false; -} - -static const char* kExecutableWhiteList[] = { - // JavaScript is just as powerful as EXE. - "text/javascript", - "text/javascript;version=*", - "text/html", - // Registry files can cause critical changes to the MS OS behavior. - // Addition of this mimetype also addresses bug 7337. - "text/x-registry", - "text/x-sh", - // 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" -}; - -bool 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); -} - - -} // namespace download_util diff --git a/chrome/browser/download/download_extensions.cc b/chrome/browser/download/download_extensions.cc new file mode 100644 index 0000000..f246b1d7 --- /dev/null +++ b/chrome/browser/download/download_extensions.cc @@ -0,0 +1,258 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <set> +#include <string> + +#include "chrome/browser/download/download_extensions.h" + +#include "base/string_util.h" +#include "net/base/mime_util.h" +#include "net/base/net_util.h" + +namespace download_util { + +// For file extensions taken from mozilla: + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner <dougt@netscape.com> + * Dean Tessman <dean_tessman@hotmail.com> + * Brodie Thiesfield <brofield@jellycan.com> + * Jungshik Shin <jshin@i18nl10n.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +static const struct Executables { + const char* extension; + DownloadDangerLevel level; +} g_executables[] = { + { "class", AllowOnUserGesture }, + { "htm", AllowOnUserGesture }, + { "html", AllowOnUserGesture }, + { "jar", AllowOnUserGesture }, + { "jnlp", AllowOnUserGesture }, + { "pdf", AllowOnUserGesture }, + { "pdfxml", AllowOnUserGesture }, + { "mars", AllowOnUserGesture }, + { "fdf", AllowOnUserGesture }, + { "xfdf", AllowOnUserGesture }, + { "xdp", AllowOnUserGesture }, + { "xfd", AllowOnUserGesture }, + { "pl", AllowOnUserGesture }, + { "py", AllowOnUserGesture }, + { "rb", AllowOnUserGesture }, + { "shtm", AllowOnUserGesture }, + { "shtml", AllowOnUserGesture }, + { "svg", AllowOnUserGesture }, + { "swf", AllowOnUserGesture }, + { "xht", AllowOnUserGesture }, + { "xhtm", AllowOnUserGesture }, + { "xhtml", AllowOnUserGesture }, + { "xml", AllowOnUserGesture }, + { "xsl", AllowOnUserGesture }, + { "xslt", AllowOnUserGesture }, +#if defined(OS_WIN) + { "ad", AllowOnUserGesture }, + { "ade", AllowOnUserGesture }, + { "adp", AllowOnUserGesture }, + { "app", AllowOnUserGesture }, + { "application", AllowOnUserGesture }, + { "asp", AllowOnUserGesture }, + { "asx", AllowOnUserGesture }, + { "bas", AllowOnUserGesture }, + { "bat", AllowOnUserGesture }, + { "chi", AllowOnUserGesture }, + { "chm", AllowOnUserGesture }, + { "cmd", AllowOnUserGesture }, + { "com", AllowOnUserGesture }, + { "cpl", AllowOnUserGesture }, + { "crt", AllowOnUserGesture }, + { "dll", Dangerous }, + { "drv", Dangerous }, + { "exe", AllowOnUserGesture }, + { "fxp", AllowOnUserGesture }, + { "hlp", AllowOnUserGesture }, + { "hta", AllowOnUserGesture }, + { "htt", AllowOnUserGesture }, + { "inf", AllowOnUserGesture }, + { "ins", AllowOnUserGesture }, + { "isp", AllowOnUserGesture }, + { "js", AllowOnUserGesture }, + { "jse", AllowOnUserGesture }, + { "lnk", AllowOnUserGesture }, + { "mad", AllowOnUserGesture }, + { "maf", AllowOnUserGesture }, + { "mag", AllowOnUserGesture }, + { "mam", AllowOnUserGesture }, + { "maq", AllowOnUserGesture }, + { "mar", AllowOnUserGesture }, + { "mas", AllowOnUserGesture }, + { "mat", AllowOnUserGesture }, + { "mau", AllowOnUserGesture }, + { "mav", AllowOnUserGesture }, + { "maw", AllowOnUserGesture }, + { "mda", AllowOnUserGesture }, + { "mdb", AllowOnUserGesture }, + { "mde", AllowOnUserGesture }, + { "mdt", AllowOnUserGesture }, + { "mdw", AllowOnUserGesture }, + { "mdz", AllowOnUserGesture }, + { "mht", AllowOnUserGesture }, + { "mhtml", AllowOnUserGesture }, + { "mmc", AllowOnUserGesture }, + { "msc", AllowOnUserGesture }, + { "msh", AllowOnUserGesture }, + { "mshxml", AllowOnUserGesture }, + { "msi", AllowOnUserGesture }, + { "msp", AllowOnUserGesture }, + { "mst", AllowOnUserGesture }, + { "ocx", AllowOnUserGesture }, + { "ops", AllowOnUserGesture }, + { "pcd", AllowOnUserGesture }, + { "pif", AllowOnUserGesture }, + { "plg", AllowOnUserGesture }, + { "prf", AllowOnUserGesture }, + { "prg", AllowOnUserGesture }, + { "pst", AllowOnUserGesture }, + { "reg", AllowOnUserGesture }, + { "scf", AllowOnUserGesture }, + { "scr", AllowOnUserGesture }, + { "sct", AllowOnUserGesture }, + { "shb", AllowOnUserGesture }, + { "shs", AllowOnUserGesture }, + { "sys", Dangerous }, + { "url", AllowOnUserGesture }, + { "vb", AllowOnUserGesture }, + { "vbe", AllowOnUserGesture }, + { "vbs", AllowOnUserGesture }, + { "vsd", AllowOnUserGesture }, + { "vsmacros", AllowOnUserGesture }, + { "vss", AllowOnUserGesture }, + { "vst", AllowOnUserGesture }, + { "vsw", AllowOnUserGesture }, + { "ws", AllowOnUserGesture }, + { "wsc", AllowOnUserGesture }, + { "wsf", AllowOnUserGesture }, + { "wsh", AllowOnUserGesture }, + { "xbap", Dangerous }, +#elif defined(OS_MACOSX) + // TODO(thakis): Figure out what makes sense here -- crbug.com/19096 + { "app", AllowOnUserGesture }, + { "dmg", AllowOnUserGesture }, +#elif defined(OS_POSIX) + // TODO(estade): lengthen this list. + { "bash", AllowOnUserGesture }, + { "csh", AllowOnUserGesture }, + { "deb", AllowOnUserGesture }, + { "exe", AllowOnUserGesture }, + { "ksh", AllowOnUserGesture }, + { "rpm", AllowOnUserGesture }, + { "sh", AllowOnUserGesture }, + { "tcsh", AllowOnUserGesture }, +#endif +}; + +DownloadDangerLevel GetFileDangerLevel(const FilePath& path) { + return GetFileExtensionDangerLevel(path.Extension()); +} + +DownloadDangerLevel GetFileExtensionDangerLevel( + const FilePath::StringType& extension) { + if (extension.empty()) + return NotDangerous; + if (!IsStringASCII(extension)) + return NotDangerous; +#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); + + for (size_t i = 0; i < arraysize(g_executables); ++i) { + if (LowerCaseEqualsASCII(ascii_extension, g_executables[i].extension)) + return g_executables[i].level; + } + return NotDangerous; +} + +bool IsFileExtensionSafe(const FilePath::StringType& extension) { + return GetFileExtensionDangerLevel(extension) == NotDangerous; +} + +bool IsFileSafe(const FilePath& path) { + return GetFileDangerLevel(path) == NotDangerous; +} + +static const char* kExecutableWhiteList[] = { + // JavaScript is just as powerful as EXE. + "text/javascript", + "text/javascript;version=*", + "text/html", + // Registry files can cause critical changes to the MS OS behavior. + // Addition of this mimetype also addresses bug 7337. + "text/x-registry", + "text/x-sh", + // 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" +}; + +bool 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); +} + + +} // namespace download_util diff --git a/chrome/browser/download/download_extensions.h b/chrome/browser/download/download_extensions.h new file mode 100644 index 0000000..3a7c557 --- /dev/null +++ b/chrome/browser/download/download_extensions.h @@ -0,0 +1,39 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_EXTENSIONS_H_ +#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_EXTENSIONS_H_ +#pragma once + +#include <string> + +#include "base/file_path.h" + +namespace download_util { + +enum DownloadDangerLevel { + NotDangerous, + AllowOnUserGesture, + Dangerous +}; + +// Determine the download danger level of a file. +DownloadDangerLevel GetFileDangerLevel(const FilePath& path); + +// Determine the download danger level using a file extension. +DownloadDangerLevel GetFileExtensionDangerLevel( + const FilePath::StringType& extension); + +// True if the download danger level of the file is NotDangerous. +bool IsFileSafe(const FilePath& path); + +// True if the download danger level of the extension is NotDangerous. +bool IsFileExtensionSafe(const FilePath::StringType& extension); + +// Tests if we think the server means for this mime_type to be executable. +bool IsExecutableMimeType(const std::string& mime_type); + +} // namespace download_util + +#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_EXTENSIONS_H_ diff --git a/chrome/browser/download/download_item.cc b/chrome/browser/download/download_item.cc index 7d3afb0..2feba50 100644 --- a/chrome/browser/download/download_item.cc +++ b/chrome/browser/download/download_item.cc @@ -13,6 +13,7 @@ #include "base/utf_string_conversions.h" #include "net/base/net_util.h" #include "chrome/browser/browser_thread.h" +#include "chrome/browser/download/download_extensions.h" #include "chrome/browser/download/download_file_manager.h" #include "chrome/browser/download/download_history.h" #include "chrome/browser/download/download_manager.h" @@ -196,7 +197,7 @@ void DownloadItem::NotifyObserversDownloadFileCompleted() { bool DownloadItem::CanOpenDownload() { return !Extension::IsExtension(target_name_) && - !download_util::IsExecutableFile(target_name_); + download_util::IsFileSafe(target_name_); } bool DownloadItem::ShouldOpenFileBasedOnExtension() { diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc index c2b63f3..133ca29 100644 --- a/chrome/browser/download/download_manager.cc +++ b/chrome/browser/download/download_manager.cc @@ -20,6 +20,7 @@ #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" +#include "chrome/browser/download/download_extensions.h" #include "chrome/browser/download/download_file_manager.h" #include "chrome/browser/download/download_history.h" #include "chrome/browser/download/download_item.h" @@ -836,7 +837,7 @@ bool DownloadManager::ShouldOpenFileBasedOnExtension( FilePath::StringType extension = path.Extension(); if (extension.empty()) return false; - if (download_util::IsExecutableExtension(extension)) + if (!download_util::IsFileExtensionSafe(extension)) return false; if (Extension::IsExtension(path)) return false; diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc index 7da48de..b4f9ddc 100644 --- a/chrome/browser/download/download_prefs.cc +++ b/chrome/browser/download/download_prefs.cc @@ -10,6 +10,7 @@ #include "base/sys_string_conversions.h" #include "base/utf_string_conversions.h" #include "chrome/browser/browser_thread.h" +#include "chrome/browser/download/download_extensions.h" #include "chrome/browser/download/download_util.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/common/pref_names.h" @@ -31,7 +32,7 @@ DownloadPrefs::DownloadPrefs(PrefService* prefs) : prefs_(prefs) { #elif defined(OS_WIN) FilePath path(UTF8ToWide(extensions[i])); #endif - if (!extensions[i].empty() && !download_util::IsExecutableFile(path)) + if (!extensions[i].empty() && download_util::IsFileSafe(path)) auto_open_.insert(path.value()); } } @@ -88,7 +89,7 @@ bool DownloadPrefs::EnableAutoOpenBasedOnExtension(const FilePath& file_name) { return false; DCHECK(extension[0] == FilePath::kExtensionSeparator); extension.erase(0, 1); - if (download_util::IsExecutableExtension(extension)) + if (!download_util::IsFileExtensionSafe(extension)) return false; auto_open_.insert(extension); diff --git a/chrome/browser/download/download_util.cc b/chrome/browser/download/download_util.cc index 3dd6012..dbed4db 100644 --- a/chrome/browser/download/download_util.cc +++ b/chrome/browser/download/download_util.cc @@ -27,6 +27,7 @@ #include "base/values.h" #include "base/win/windows_version.h" #include "chrome/browser/browser_thread.h" +#include "chrome/browser/download/download_extensions.h" #include "chrome/browser/download/download_item.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_manager.h" @@ -719,18 +720,22 @@ FilePath GetCrDownloadPath(const FilePath& suggested_path) { // TODO(erikkay,phajdan.jr): This is apparently not being exercised in tests. bool IsDangerous(DownloadCreateInfo* info, Profile* profile) { - // 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 (IsExecutableFile(info->suggested_path.BaseName())) { + DownloadDangerLevel danger_level = GetFileDangerLevel( + info->suggested_path.BaseName()); + + if (danger_level == Dangerous) { + return true; + } else if (danger_level == AllowOnUserGesture && !info->has_user_gesture) { return true; } else if (info->is_extension_install) { ExtensionsService* service = profile->GetExtensionsService(); if (!service || !service->IsDownloadFromGallery(info->url, info->referrer_url)) { + // Extensions that are not from the gallery are considered dangerous. return true; } } + return false; } diff --git a/chrome/browser/download/download_util.h b/chrome/browser/download/download_util.h index 0224a26..0a0bd90 100644 --- a/chrome/browser/download/download_util.h +++ b/chrome/browser/download/download_util.h @@ -150,17 +150,6 @@ void DragDownload(const DownloadItem* download, SkBitmap* icon, gfx::NativeView view); -// Executable file support ----------------------------------------------------- - -// Tests if a file is considered executable, based on its type. -bool IsExecutableFile(const FilePath& path); - -// Determine if the specified extension is an executable extension. -bool IsExecutableExtension(const FilePath::StringType& extension); - -// Tests if we think the server means for this mime_type to be executable. -bool IsExecutableMimeType(const std::string& mime_type); - // Helpers --------------------------------------------------------------------- // Creates a representation of a download in a format that the downloads diff --git a/chrome/browser/extensions/user_script_listener_unittest.cc b/chrome/browser/extensions/user_script_listener_unittest.cc index 9658f41..57153b7 100644 --- a/chrome/browser/extensions/user_script_listener_unittest.cc +++ b/chrome/browser/extensions/user_script_listener_unittest.cc @@ -90,7 +90,7 @@ ResourceDispatcherHostRequestInfo* CreateRequestInfo(int request_id) { return new ResourceDispatcherHostRequestInfo( new DummyResourceHandler(), ChildProcessInfo::RENDER_PROCESS, 0, 0, request_id, "null", "null", ResourceType::MAIN_FRAME, - 0, false, false, -1, -1); + 0, false, false, false, -1, -1); } // A simple test URLRequestJob. We don't care what it does, only that whether it diff --git a/chrome/browser/history/download_create_info.cc b/chrome/browser/history/download_create_info.cc index 67ffdc7..a04d3e9 100644 --- a/chrome/browser/history/download_create_info.cc +++ b/chrome/browser/history/download_create_info.cc @@ -15,7 +15,8 @@ DownloadCreateInfo::DownloadCreateInfo(const FilePath& path, int64 received_bytes, int64 total_bytes, int32 state, - int32 download_id) + int32 download_id, + bool has_user_gesture) : path(path), url(url), path_uniquifier(0), @@ -24,6 +25,7 @@ DownloadCreateInfo::DownloadCreateInfo(const FilePath& path, total_bytes(total_bytes), state(state), download_id(download_id), + has_user_gesture(has_user_gesture), child_id(-1), render_view_id(-1), request_id(-1), @@ -39,6 +41,7 @@ DownloadCreateInfo::DownloadCreateInfo() total_bytes(0), state(-1), download_id(-1), + has_user_gesture(has_user_gesture), child_id(-1), render_view_id(-1), request_id(-1), diff --git a/chrome/browser/history/download_create_info.h b/chrome/browser/history/download_create_info.h index b995b0b..49ac635 100644 --- a/chrome/browser/history/download_create_info.h +++ b/chrome/browser/history/download_create_info.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -27,7 +27,8 @@ struct DownloadCreateInfo { int64 received_bytes, int64 total_bytes, int32 state, - int32 download_id); + int32 download_id, + bool has_user_gesture); DownloadCreateInfo(); ~DownloadCreateInfo(); @@ -46,6 +47,7 @@ struct DownloadCreateInfo { int64 total_bytes; int32 state; int32 download_id; + bool has_user_gesture; int child_id; int render_view_id; int request_id; diff --git a/chrome/browser/history/history_unittest.cc b/chrome/browser/history/history_unittest.cc index 9abad7e..b570892 100644 --- a/chrome/browser/history/history_unittest.cc +++ b/chrome/browser/history/history_unittest.cc @@ -199,7 +199,7 @@ class HistoryTest : public testing::Test { int64 AddDownload(int32 state, const Time& time) { DownloadCreateInfo download(FilePath(FILE_PATH_LITERAL("foo-path")), - GURL("foo-url"), time, 0, 512, state, 0); + GURL("foo-url"), time, 0, 512, state, 0, false); return db_->CreateDownload(download); } diff --git a/chrome/browser/renderer_host/download_resource_handler.cc b/chrome/browser/renderer_host/download_resource_handler.cc index 5de9750..6e34a30 100644 --- a/chrome/browser/renderer_host/download_resource_handler.cc +++ b/chrome/browser/renderer_host/download_resource_handler.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -14,6 +14,7 @@ #include "chrome/browser/history/download_create_info.h" #include "chrome/browser/renderer_host/global_request_id.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" +#include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h" #include "chrome/common/resource_response.h" #include "net/base/io_buffer.h" #include "net/http/http_response_headers.h" @@ -69,6 +70,9 @@ bool DownloadResourceHandler::OnResponseStarted(int request_id, set_content_disposition(content_disposition); set_content_length(response->response_head.content_length); + const ResourceDispatcherHostRequestInfo* request_info = + ResourceDispatcherHost::InfoForRequest(request_); + download_id_ = download_file_manager_->GetNextId(); // |download_file_manager_| consumes (deletes): DownloadCreateInfo* info = new DownloadCreateInfo; @@ -79,6 +83,7 @@ bool DownloadResourceHandler::OnResponseStarted(int request_id, info->total_bytes = content_length_; info->state = DownloadItem::IN_PROGRESS; info->download_id = download_id_; + info->has_user_gesture = request_info->has_user_gesture(); info->child_id = global_id_.child_id; info->render_view_id = render_view_id_; info->request_id = global_id_.request_id; diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc index 4c6ec1e..14493fa 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host.cc +++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc @@ -519,6 +519,7 @@ void ResourceDispatcherHost::BeginRequest( upload_size, false, // is download ResourceType::IsFrame(request_data.resource_type), // allow_download + request_data.has_user_gesture, request_data.host_renderer_id, request_data.host_render_view_id); ApplyExtensionLocalizationFilter(request_data.url, request_data.resource_type, @@ -650,14 +651,15 @@ ResourceDispatcherHost::CreateRequestInfoForBrowserRequest( child_id, route_id, request_id_, - "null", // frame_origin - "null", // main_frame_origin + "null", // frame_origin + "null", // main_frame_origin ResourceType::SUB_RESOURCE, - 0, // upload_size + 0, // upload_size download, // is_download download, // allow_download - -1, // Host renderer id - -1); // Host render view id + false, // has_user_gesture + -1, // host renderer id + -1); // host render view id } void ResourceDispatcherHost::OnClosePageACK( diff --git a/chrome/browser/renderer_host/resource_dispatcher_host_request_info.cc b/chrome/browser/renderer_host/resource_dispatcher_host_request_info.cc index bf936c3..65f89cb 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host_request_info.cc +++ b/chrome/browser/renderer_host/resource_dispatcher_host_request_info.cc @@ -21,6 +21,7 @@ ResourceDispatcherHostRequestInfo::ResourceDispatcherHostRequestInfo( uint64 upload_size, bool is_download, bool allow_download, + bool has_user_gesture, int host_renderer_id, int host_render_view_id) : resource_handler_(handler), @@ -32,6 +33,7 @@ ResourceDispatcherHostRequestInfo::ResourceDispatcherHostRequestInfo( pending_data_count_(0), is_download_(is_download), allow_download_(allow_download), + has_user_gesture_(has_user_gesture), pause_count_(0), frame_origin_(frame_origin), main_frame_origin_(main_frame_origin), diff --git a/chrome/browser/renderer_host/resource_dispatcher_host_request_info.h b/chrome/browser/renderer_host/resource_dispatcher_host_request_info.h index 032c4bd..ead2239 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host_request_info.h +++ b/chrome/browser/renderer_host/resource_dispatcher_host_request_info.h @@ -42,6 +42,7 @@ class ResourceDispatcherHostRequestInfo : public net::URLRequest::UserData { uint64 upload_size, bool is_download, bool allow_download, + bool has_user_gesture, int host_renderer_id, int host_render_view_id); virtual ~ResourceDispatcherHostRequestInfo(); @@ -95,6 +96,8 @@ class ResourceDispatcherHostRequestInfo : public net::URLRequest::UserData { // Downloads are allowed only as a top level request. bool allow_download() const { return allow_download_; } + bool has_user_gesture() const { return has_user_gesture_; } + // Whether this is a download. bool is_download() const { return is_download_; } void set_is_download(bool download) { is_download_ = download; } @@ -214,6 +217,7 @@ class ResourceDispatcherHostRequestInfo : public net::URLRequest::UserData { int pending_data_count_; bool is_download_; bool allow_download_; + bool has_user_gesture_; int pause_count_; std::string frame_origin_; std::string main_frame_origin_; diff --git a/chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc b/chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc index 4ca79ac..228c83e 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc +++ b/chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc @@ -1003,7 +1003,7 @@ class ApplyExtensionLocalizationFilterTest : public testing::Test { return new ResourceDispatcherHostRequestInfo( resource_handler_.get(), ChildProcessInfo::RENDER_PROCESS, 0, 0, 0, "not important", "not important", - ResourceType::STYLESHEET, 0U, false, false, -1, -1); + ResourceType::STYLESHEET, 0U, false, false, false, -1, -1); } scoped_ptr<GURL> url_; diff --git a/chrome/browser/renderer_host/resource_queue_unittest.cc b/chrome/browser/renderer_host/resource_queue_unittest.cc index 983ea0c..fa466f1 100644 --- a/chrome/browser/renderer_host/resource_queue_unittest.cc +++ b/chrome/browser/renderer_host/resource_queue_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -76,7 +76,7 @@ ResourceDispatcherHostRequestInfo* GetRequestInfo(int request_id) { return new ResourceDispatcherHostRequestInfo( new DummyResourceHandler(), ChildProcessInfo::RENDER_PROCESS, 0, 0, request_id, "null", "null", ResourceType::MAIN_FRAME, - 0, false, false, -1, -1); + 0, false, false, false, -1, -1); } void InitializeQueue(ResourceQueue* queue, ResourceQueueDelegate* delegate) { diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 3f3a54c..8452b44 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -947,7 +947,8 @@ 'browser/dom_ui/value_helper.h', 'browser/download/base_file.cc', 'browser/download/base_file.h', - 'browser/download/download_exe.cc', + 'browser/download/download_extensions.cc', + 'browser/download/download_extensions.h', 'browser/download/download_file.cc', 'browser/download/download_file.h', 'browser/download/download_file_manager.cc', diff --git a/chrome/common/navigation_gesture.h b/chrome/common/navigation_gesture.h index e27ea4c..729f4d2 100644 --- a/chrome/common/navigation_gesture.h +++ b/chrome/common/navigation_gesture.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,17 +7,14 @@ #pragma once enum NavigationGesture { - NavigationGestureUser, // User initiated navigation/load. This is not - // currently used due to the untrustworthy nature - // of userGestureHint (wasRunByUserGesture). See - // bug 1051891. - NavigationGestureAuto, // Non-user initiated navigation / load. For example - // onload or setTimeout triggered document.location - // changes, and form.submits. See bug 1046841 for - // some cases that should be treated this way but - // aren't yet. - NavigationGestureUnknown, // What we assign when userGestureHint returns true - // because we can't trust it. + // User initiated navigation/load. + NavigationGestureUser, + // Non-user initiated navigation/load. For example, onload- or + // setTimeout-triggered document.location changes and form.submits. See + // http://b/1046841 for some cases that should be treated this way but aren't. + NavigationGestureAuto, + // Initial state. + NavigationGestureUnknown, }; #endif // CHROME_COMMON_NAVIGATION_GESTURE_H_ diff --git a/chrome/common/render_messages_params.cc b/chrome/common/render_messages_params.cc index 2d7a006..8e8c6ff 100644 --- a/chrome/common/render_messages_params.cc +++ b/chrome/common/render_messages_params.cc @@ -66,6 +66,7 @@ ViewHostMsg_Resource_Request::ViewHostMsg_Resource_Request() request_context(0), appcache_host_id(0), download_to_file(false), + has_user_gesture(false), host_renderer_id(0), host_render_view_id(0) { } @@ -938,6 +939,7 @@ void ParamTraits<ViewHostMsg_Resource_Request>::Write(Message* m, WriteParam(m, p.appcache_host_id); WriteParam(m, p.upload_data); WriteParam(m, p.download_to_file); + WriteParam(m, p.has_user_gesture); WriteParam(m, p.host_renderer_id); WriteParam(m, p.host_render_view_id); } @@ -960,6 +962,7 @@ bool ParamTraits<ViewHostMsg_Resource_Request>::Read(const Message* m, ReadParam(m, iter, &r->appcache_host_id) && ReadParam(m, iter, &r->upload_data) && ReadParam(m, iter, &r->download_to_file) && + ReadParam(m, iter, &r->has_user_gesture) && ReadParam(m, iter, &r->host_renderer_id) && ReadParam(m, iter, &r->host_render_view_id); } @@ -989,6 +992,8 @@ void ParamTraits<ViewHostMsg_Resource_Request>::Log(const param_type& p, l->append(", "); LogParam(p.download_to_file, l); l->append(", "); + LogParam(p.has_user_gesture, l); + l->append(", "); LogParam(p.host_renderer_id, l); l->append(", "); LogParam(p.host_render_view_id, l); diff --git a/chrome/common/render_messages_params.h b/chrome/common/render_messages_params.h index 3574b7c..1996941 100644 --- a/chrome/common/render_messages_params.h +++ b/chrome/common/render_messages_params.h @@ -469,6 +469,9 @@ struct ViewHostMsg_Resource_Request { bool download_to_file; + // True if the request was user initiated. + bool has_user_gesture; + // The following two members are specified if the request is initiated by // a plugin like Gears. diff --git a/chrome/common/resource_dispatcher.cc b/chrome/common/resource_dispatcher.cc index 1b2e175c..e4747b9 100644 --- a/chrome/common/resource_dispatcher.cc +++ b/chrome/common/resource_dispatcher.cc @@ -111,6 +111,7 @@ IPCResourceLoaderBridge::IPCResourceLoaderBridge( request_.request_context = request_info.request_context; request_.appcache_host_id = request_info.appcache_host_id; request_.download_to_file = request_info.download_to_file; + request_.has_user_gesture = request_info.has_user_gesture; request_.host_renderer_id = host_renderer_id_; request_.host_render_view_id = host_render_view_id_; } diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 4282a04..92cf78a 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -3211,7 +3211,7 @@ void RenderView::didStartProvisionalLoad(WebFrame* frame) { bool is_top_most = !frame->parent(); if (is_top_most) { navigation_gesture_ = frame->isProcessingUserGesture() ? - NavigationGestureUnknown : NavigationGestureAuto; + NavigationGestureUser : NavigationGestureAuto; // Make sure redirect tracking state is clear for the new load. completed_client_redirect_src_ = GURL(); @@ -3579,6 +3579,8 @@ void RenderView::willSendRequest( } request.setRequestorID(routing_id_); + request.setHasUserGesture(frame->isProcessingUserGesture()); + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoReferrers)) request.clearHTTPHeaderField("Referer"); diff --git a/webkit/glue/resource_loader_bridge.cc b/webkit/glue/resource_loader_bridge.cc index 86029e2..3e9c9e8 100644 --- a/webkit/glue/resource_loader_bridge.cc +++ b/webkit/glue/resource_loader_bridge.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -54,7 +54,8 @@ ResourceLoaderBridge::RequestInfo::RequestInfo() request_context(0), appcache_host_id(0), routing_id(0), - download_to_file(false) { + download_to_file(false), + has_user_gesture(false) { } ResourceLoaderBridge::RequestInfo::~RequestInfo() { diff --git a/webkit/glue/resource_loader_bridge.h b/webkit/glue/resource_loader_bridge.h index 951eb87..7257b0c 100644 --- a/webkit/glue/resource_loader_bridge.h +++ b/webkit/glue/resource_loader_bridge.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -236,6 +236,9 @@ class ResourceLoaderBridge { // If true, then the response body will be downloaded to a file and the // path to that file will be provided in ResponseInfo::download_file_path. bool download_to_file; + + // True if the request was user initiated. + bool has_user_gesture; }; // See the SyncLoad method declared below. (The name of this struct is not diff --git a/webkit/glue/weburlloader_impl.cc b/webkit/glue/weburlloader_impl.cc index d134382..0372567 100644 --- a/webkit/glue/weburlloader_impl.cc +++ b/webkit/glue/weburlloader_impl.cc @@ -435,6 +435,7 @@ void WebURLLoaderImpl::Context::Start( request_info.appcache_host_id = request.appCacheHostID(); request_info.routing_id = request.requestorID(); request_info.download_to_file = request.downloadToFile(); + request_info.has_user_gesture = request.hasUserGesture(); bridge_.reset(ResourceLoaderBridge::Create(request_info)); if (!request.httpBody().isNull()) { |