1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5
6 #include "chrome/browser/download/download_safe_browsing_client.h"
7
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/metrics/stats_counters.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/download/download_manager.h"
14 #include "chrome/browser/history/download_create_info.h"
15 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
16 #include "chrome/common/chrome_switches.h"
17 #include "content/browser/browser_thread.h"
18 #include "content/browser/renderer_host/resource_dispatcher_host.h"
19
20 // TODO(lzheng): Get rid of the AddRef and Release after
21 // SafeBrowsingService::Client is changed to RefCountedThreadSafe<>.
22
DownloadSBClient(int32 download_id,const std::vector<GURL> & url_chain,const GURL & referrer_url)23 DownloadSBClient::DownloadSBClient(int32 download_id,
24 const std::vector<GURL>& url_chain,
25 const GURL& referrer_url)
26 : info_(NULL),
27 download_id_(download_id),
28 url_chain_(url_chain),
29 referrer_url_(referrer_url) {
30 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
31 DCHECK(!url_chain.empty());
32 ResourceDispatcherHost* rdh = g_browser_process->resource_dispatcher_host();
33 if (rdh)
34 sb_service_ = rdh->safe_browsing_service();
35 }
36
~DownloadSBClient()37 DownloadSBClient::~DownloadSBClient() {}
38
CheckDownloadUrl(DownloadCreateInfo * info,UrlDoneCallback * callback)39 void DownloadSBClient::CheckDownloadUrl(DownloadCreateInfo* info,
40 UrlDoneCallback* callback) {
41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
42 // It is not allowed to call this method twice.
43 CHECK(!url_done_callback_.get() && !hash_done_callback_.get());
44 CHECK(callback);
45 CHECK(info);
46
47 info_ = info;
48 start_time_ = base::TimeTicks::Now();
49 url_done_callback_.reset(callback);
50 BrowserThread::PostTask(
51 BrowserThread::IO, FROM_HERE,
52 NewRunnableMethod(this,
53 &DownloadSBClient::CheckDownloadUrlOnIOThread,
54 info->url_chain));
55 }
56
CheckDownloadHash(const std::string & hash,HashDoneCallback * callback)57 void DownloadSBClient::CheckDownloadHash(const std::string& hash,
58 HashDoneCallback* callback) {
59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
60 // It is not allowed to call this method twice.
61 CHECK(!url_done_callback_.get() && !hash_done_callback_.get());
62 CHECK(callback);
63
64 start_time_ = base::TimeTicks::Now();
65 hash_done_callback_.reset(callback);
66 BrowserThread::PostTask(
67 BrowserThread::IO, FROM_HERE,
68 NewRunnableMethod(this,
69 &DownloadSBClient::CheckDownloadHashOnIOThread,
70 hash));
71 }
72
CheckDownloadUrlOnIOThread(const std::vector<GURL> & url_chain)73 void DownloadSBClient::CheckDownloadUrlOnIOThread(
74 const std::vector<GURL>& url_chain) {
75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
76
77 // Will be released in OnDownloadUrlCheckResult.
78 AddRef();
79 if (sb_service_.get() && !sb_service_->CheckDownloadUrl(url_chain, this)) {
80 // Wait for SafeBrowsingService to call back OnDownloadUrlCheckResult.
81 return;
82 }
83 OnDownloadUrlCheckResult(url_chain, SafeBrowsingService::SAFE);
84 }
85
86 // The callback interface for SafeBrowsingService::Client.
87 // Called when the result of checking a download URL is known.
OnDownloadUrlCheckResult(const std::vector<GURL> & url_chain,SafeBrowsingService::UrlCheckResult result)88 void DownloadSBClient::OnDownloadUrlCheckResult(
89 const std::vector<GURL>& url_chain,
90 SafeBrowsingService::UrlCheckResult result) {
91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
92 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
93 NewRunnableMethod(this,
94 &DownloadSBClient::SafeBrowsingCheckUrlDone,
95 result));
96 Release();
97 }
98
CheckDownloadHashOnIOThread(const std::string & hash)99 void DownloadSBClient::CheckDownloadHashOnIOThread(const std::string& hash) {
100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
101 // Will be released in OnDownloadUrlCheckResult.
102 AddRef();
103 if (sb_service_.get() && !sb_service_->CheckDownloadHash(hash, this)) {
104 // Wait for SafeBrowsingService to call back OnDownloadUrlCheckResult.
105 return;
106 }
107 OnDownloadHashCheckResult(hash, SafeBrowsingService::SAFE);
108 }
109
110 // The callback interface for SafeBrowsingService::Client.
111 // Called when the result of checking a download URL is known.
OnDownloadHashCheckResult(const std::string & hash,SafeBrowsingService::UrlCheckResult result)112 void DownloadSBClient::OnDownloadHashCheckResult(
113 const std::string& hash, SafeBrowsingService::UrlCheckResult result) {
114 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
115 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
116 NewRunnableMethod(this,
117 &DownloadSBClient::SafeBrowsingCheckHashDone,
118 result));
119 Release();
120 }
121
SafeBrowsingCheckUrlDone(SafeBrowsingService::UrlCheckResult result)122 void DownloadSBClient::SafeBrowsingCheckUrlDone(
123 SafeBrowsingService::UrlCheckResult result) {
124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
125 DVLOG(1) << "SafeBrowsingCheckUrlDone with result: " << result;
126
127 bool is_dangerous = result != SafeBrowsingService::SAFE;
128 url_done_callback_->Run(info_, is_dangerous);
129
130 if (sb_service_.get() && sb_service_->download_protection_enabled()) {
131 UMA_HISTOGRAM_TIMES("SB2.DownloadUrlCheckDuration",
132 base::TimeTicks::Now() - start_time_);
133 UpdateDownloadCheckStats(DOWNLOAD_URL_CHECKS_TOTAL);
134 if (is_dangerous) {
135 UpdateDownloadCheckStats(DOWNLOAD_URL_CHECKS_MALWARE);
136 ReportMalware(result);
137 }
138 }
139 }
140
SafeBrowsingCheckHashDone(SafeBrowsingService::UrlCheckResult result)141 void DownloadSBClient::SafeBrowsingCheckHashDone(
142 SafeBrowsingService::UrlCheckResult result) {
143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
144 DVLOG(1) << "SafeBrowsingCheckHashDone with result: " << result;
145
146 bool is_dangerous = result != SafeBrowsingService::SAFE;
147 hash_done_callback_->Run(download_id_, is_dangerous);
148
149 if (sb_service_.get() && sb_service_->download_protection_enabled()) {
150 UMA_HISTOGRAM_TIMES("SB2.DownloadHashCheckDuration",
151 base::TimeTicks::Now() - start_time_);
152 UpdateDownloadCheckStats(DOWNLOAD_HASH_CHECKS_TOTAL);
153 if (is_dangerous) {
154 UpdateDownloadCheckStats(DOWNLOAD_HASH_CHECKS_MALWARE);
155 ReportMalware(result);
156 }
157 }
158 }
159
ReportMalware(SafeBrowsingService::UrlCheckResult result)160 void DownloadSBClient::ReportMalware(
161 SafeBrowsingService::UrlCheckResult result) {
162 std::string post_data;
163 for (size_t i = 0; i < url_chain_.size(); ++i)
164 post_data += url_chain_[i].spec() + "\n";
165
166 sb_service_->ReportSafeBrowsingHit(url_chain_.back(), // malicious_url
167 url_chain_.front(), // page_url
168 referrer_url_,
169 true,
170 result,
171 post_data);
172 }
173
UpdateDownloadCheckStats(SBStatsType stat_type)174 void DownloadSBClient::UpdateDownloadCheckStats(SBStatsType stat_type) {
175 UMA_HISTOGRAM_ENUMERATION("SB2.DownloadChecks",
176 stat_type,
177 DOWNLOAD_CHECKS_MAX);
178 }
179