Add support for safebrowsing download protection. It is currently under flag --safebrowsing-download-protection.
TEST=safe_browsing_service_browsertest.cc
BUG=60822
Review URL: http://codereview.chromium.org/5141006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69979 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/renderer_host/download_resource_handler.cc b/chrome/browser/renderer_host/download_resource_handler.cc
index 6e34a30..f8064060 100644
--- a/chrome/browser/renderer_host/download_resource_handler.cc
+++ b/chrome/browser/renderer_host/download_resource_handler.cc
@@ -7,6 +7,8 @@
#include <string>
#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/stats_counters.h"
#include "base/stringprintf.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/download/download_item.h"
@@ -41,7 +43,8 @@
save_info_(save_info),
buffer_(new DownloadBuffer),
rdh_(rdh),
- is_paused_(false) {
+ is_paused_(false),
+ url_check_pending_(false) {
}
bool DownloadResourceHandler::OnUploadProgress(int request_id,
@@ -59,11 +62,55 @@
return true;
}
+// Callback when the result of checking a download URL is known.
+// TODO(lzheng): We should create a information bar with buttons to ask
+// if users want to proceed when the download is malicious.
+void DownloadResourceHandler::OnDownloadUrlCheckResult(
+ const GURL& url, SafeBrowsingService::UrlCheckResult result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(url_check_pending_);
+
+ UMA_HISTOGRAM_TIMES("SB2.DownloadUrlCheckDuration",
+ base::TimeTicks::Now() - download_start_time_);
+
+ if (result == SafeBrowsingService::BINARY_MALWARE) {
+ // TODO(lzheng): More UI work to show warnings properly on download shelf.
+ DLOG(WARNING) << "This url leads to a malware downloading: "
+ << url.spec();
+ UpdateDownloadUrlCheckStats(DOWNLOAD_URL_CHECKS_MALWARE);
+ }
+
+ url_check_pending_ = false;
+ // Note: Release() should be the last line in this call. It is for
+ // the AddRef in CheckSafeBrowsing.
+ Release();
+}
+
+// Send the download creation information to the download thread.
+void DownloadResourceHandler::StartDownloadUrlCheck() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ AddRef();
+ if (!rdh_->safe_browsing_service()->CheckDownloadUrl(url_, this)) {
+ url_check_pending_ = true;
+ UpdateDownloadUrlCheckStats(DOWNLOAD_URL_CHECKS_TOTAL);
+ // Note: in this case, the AddRef will be balanced in
+ // "OnDownloadUrlCheckResult" or "OnRequestClosed".
+ } else {
+ // Immediately release the AddRef() at the beginning of this function
+ // since no more callbacks will happen.
+ Release();
+ DVLOG(1) << "url: " << url_.spec() << " is safe to download.";
+ }
+}
+
// Send the download creation information to the download thread.
bool DownloadResourceHandler::OnResponseStarted(int request_id,
ResourceResponse* response) {
VLOG(20) << __FUNCTION__ << "()" << DebugString()
<< " request_id = " << request_id;
+ DCHECK(!url_check_pending_);
+ download_start_time_ = base::TimeTicks::Now();
+ StartDownloadUrlCheck();
std::string content_disposition;
request_->GetResponseHeaderByName("content-disposition",
&content_disposition);
@@ -183,6 +230,17 @@
}
void DownloadResourceHandler::OnRequestClosed() {
+ UMA_HISTOGRAM_TIMES("SB2.DownloadDuration",
+ base::TimeTicks::Now() - download_start_time_);
+ if (url_check_pending_) {
+ DVLOG(1) << "Cancel pending download url checking request: " << this;
+ rdh_->safe_browsing_service()->CancelCheck(this);
+ UpdateDownloadUrlCheckStats(DOWNLOAD_URL_CHECKS_CANCELED);
+ url_check_pending_ = false;
+ // Balance the AddRef() from StartDownloadUrlCheck() which would usually be
+ // balanced by OnDownloadUrlCheckResult().
+ Release();
+ }
}
// If the content-length header is not present (or contains something other
@@ -249,3 +307,10 @@
render_view_id_,
save_info_.file_path.value().c_str());
}
+
+void DownloadResourceHandler::UpdateDownloadUrlCheckStats(
+ SBStatsType stat_type) {
+ UMA_HISTOGRAM_ENUMERATION("SB2.DownloadUrlChecks",
+ stat_type,
+ DOWNLOAD_URL_CHECKS_MAX);
+}
diff --git a/chrome/browser/renderer_host/download_resource_handler.h b/chrome/browser/renderer_host/download_resource_handler.h
index 3fb6961..5a66f662 100644
--- a/chrome/browser/renderer_host/download_resource_handler.h
+++ b/chrome/browser/renderer_host/download_resource_handler.h
@@ -12,6 +12,7 @@
#include "chrome/browser/download/download_file.h"
#include "chrome/browser/renderer_host/global_request_id.h"
#include "chrome/browser/renderer_host/resource_handler.h"
+#include "chrome/browser/safe_browsing/safe_browsing_service.h"
class DownloadFileManager;
class ResourceDispatcherHost;
@@ -22,7 +23,8 @@
} // namespace net
// Forwards data to the download thread.
-class DownloadResourceHandler : public ResourceHandler {
+class DownloadResourceHandler : public ResourceHandler,
+ public SafeBrowsingService::Client {
public:
DownloadResourceHandler(ResourceDispatcherHost* rdh,
int render_process_host_id,
@@ -70,10 +72,31 @@
std::string DebugString() const;
private:
+ // Enumerate for histogramming purposes. DO NOT CHANGE THE
+ // ORDERING OF THESE VALUES.
+ enum SBStatsType {
+ DOWNLOAD_URL_CHECKS_TOTAL,
+ DOWNLOAD_URL_CHECKS_CANCELED,
+ DOWNLOAD_URL_CHECKS_MALWARE,
+
+ // Memory space for histograms is determined by the max. ALWAYS
+ // ADD NEW VALUES BEFORE THIS ONE.
+ DOWNLOAD_URL_CHECKS_MAX
+ };
+
~DownloadResourceHandler();
void StartPauseTimer();
+ void StartDownloadUrlCheck();
+
+ // Called when the result of checking a download URL is known.
+ void OnDownloadUrlCheckResult(const GURL& url,
+ SafeBrowsingService::UrlCheckResult result);
+
+ // A helper function that updates UMA for download url checks.
+ static void UpdateDownloadUrlCheckStats(SBStatsType stat_type);
+
int download_id_;
GlobalRequestID global_id_;
int render_view_id_;
@@ -89,6 +112,8 @@
ResourceDispatcherHost* rdh_;
bool is_paused_;
base::OneShotTimer<DownloadResourceHandler> pause_timer_;
+ bool url_check_pending_;
+ base::TimeTicks download_start_time_; // used to collect stats.
static const int kReadBufSize = 32768; // bytes
static const size_t kLoadsToWrite = 100; // number of data buffers queued