OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/safe_browsing/download_protection_service.h" | 5 #include "chrome/browser/safe_browsing/download_protection_service.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/format_macros.h" |
8 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
9 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
10 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
11 #include "base/string_number_conversions.h" | 12 #include "base/string_number_conversions.h" |
12 #include "base/string_util.h" | 13 #include "base/string_util.h" |
13 #include "base/stringprintf.h" | 14 #include "base/stringprintf.h" |
14 #include "base/time.h" | 15 #include "base/time.h" |
15 #include "chrome/browser/safe_browsing/safe_browsing_service.h" | 16 #include "chrome/browser/safe_browsing/safe_browsing_service.h" |
16 #include "chrome/browser/safe_browsing/signature_util.h" | 17 #include "chrome/browser/safe_browsing/signature_util.h" |
17 #include "chrome/common/net/http_return.h" | 18 #include "chrome/common/net/http_return.h" |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 // ALWAYS ADD NEW VALUES BEFORE THIS ONE. | 106 // ALWAYS ADD NEW VALUES BEFORE THIS ONE. |
106 DOWNLOAD_CHECKS_MAX | 107 DOWNLOAD_CHECKS_MAX |
107 }; | 108 }; |
108 } // namespace | 109 } // namespace |
109 | 110 |
110 DownloadProtectionService::DownloadInfo::DownloadInfo() | 111 DownloadProtectionService::DownloadInfo::DownloadInfo() |
111 : total_bytes(0), user_initiated(false) {} | 112 : total_bytes(0), user_initiated(false) {} |
112 | 113 |
113 DownloadProtectionService::DownloadInfo::~DownloadInfo() {} | 114 DownloadProtectionService::DownloadInfo::~DownloadInfo() {} |
114 | 115 |
| 116 std::string DownloadProtectionService::DownloadInfo::DebugString() const { |
| 117 std::string chain; |
| 118 for (size_t i = 0; i < download_url_chain.size(); ++i) { |
| 119 chain += download_url_chain[i].spec(); |
| 120 if (i < download_url_chain.size() - 1) { |
| 121 chain += " -> "; |
| 122 } |
| 123 } |
| 124 return base::StringPrintf( |
| 125 "DownloadInfo {addr:0x%p, download_url_chain:[%s], local_file:%s, " |
| 126 "target_file:%s, referrer_url:%s, sha256_hash:%s, total_bytes:%" PRId64 |
| 127 ", user_initiated: %s}", |
| 128 reinterpret_cast<const void*>(this), |
| 129 chain.c_str(), |
| 130 local_file.value().c_str(), |
| 131 target_file.value().c_str(), |
| 132 referrer_url.spec().c_str(), |
| 133 "TODO", |
| 134 total_bytes, |
| 135 user_initiated ? "true" : "false"); |
| 136 } |
| 137 |
115 // static | 138 // static |
116 DownloadProtectionService::DownloadInfo | 139 DownloadProtectionService::DownloadInfo |
117 DownloadProtectionService::DownloadInfo::FromDownloadItem( | 140 DownloadProtectionService::DownloadInfo::FromDownloadItem( |
118 const DownloadItem& item) { | 141 const DownloadItem& item) { |
119 DownloadInfo download_info; | 142 DownloadInfo download_info; |
120 download_info.local_file = item.full_path(); | 143 download_info.local_file = item.full_path(); |
| 144 download_info.target_file = item.GetTargetFilePath(); |
121 download_info.download_url_chain = item.url_chain(); | 145 download_info.download_url_chain = item.url_chain(); |
122 download_info.referrer_url = item.referrer_url(); | 146 download_info.referrer_url = item.referrer_url(); |
123 // TODO(bryner): Fill in the hash (we shouldn't compute it again) | 147 // TODO(bryner): Fill in the hash (we shouldn't compute it again) |
124 download_info.total_bytes = item.total_bytes(); | 148 download_info.total_bytes = item.total_bytes(); |
125 // TODO(bryner): Populate user_initiated | 149 // TODO(bryner): Populate user_initiated |
126 return download_info; | 150 return download_info; |
127 } | 151 } |
128 | 152 |
129 // Parent SafeBrowsing::Client class used to lookup the bad binary | 153 // Parent SafeBrowsing::Client class used to lookup the bad binary |
130 // URL and digest list. There are two sub-classes (one for each list). | 154 // URL and digest list. There are two sub-classes (one for each list). |
(...skipping 23 matching lines...) Expand all Loading... |
154 | 178 |
155 void CheckDone(SafeBrowsingService::UrlCheckResult sb_result) { | 179 void CheckDone(SafeBrowsingService::UrlCheckResult sb_result) { |
156 DownloadProtectionService::DownloadCheckResult result = | 180 DownloadProtectionService::DownloadCheckResult result = |
157 IsDangerous(sb_result) ? | 181 IsDangerous(sb_result) ? |
158 DownloadProtectionService::DANGEROUS : | 182 DownloadProtectionService::DANGEROUS : |
159 DownloadProtectionService::SAFE; | 183 DownloadProtectionService::SAFE; |
160 BrowserThread::PostTask(BrowserThread::UI, | 184 BrowserThread::PostTask(BrowserThread::UI, |
161 FROM_HERE, | 185 FROM_HERE, |
162 base::Bind(callback_, result)); | 186 base::Bind(callback_, result)); |
163 UpdateDownloadCheckStats(total_type_); | 187 UpdateDownloadCheckStats(total_type_); |
164 if (IsDangerous(sb_result)) { | 188 if (sb_result != SafeBrowsingService::SAFE) { |
165 UpdateDownloadCheckStats(dangerous_type_); | 189 UpdateDownloadCheckStats(dangerous_type_); |
166 BrowserThread::PostTask( | 190 BrowserThread::PostTask( |
167 BrowserThread::UI, | 191 BrowserThread::UI, |
168 FROM_HERE, | 192 FROM_HERE, |
169 base::Bind(&DownloadSBClient::ReportMalware, | 193 base::Bind(&DownloadSBClient::ReportMalware, |
170 this, sb_result)); | 194 this, sb_result)); |
171 } | 195 } |
172 } | 196 } |
173 | 197 |
174 void ReportMalware(SafeBrowsingService::UrlCheckResult result) { | 198 void ReportMalware(SafeBrowsingService::UrlCheckResult result) { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 if (!sb_service_ || | 286 if (!sb_service_ || |
263 sb_service_->CheckDownloadHash(info_.sha256_hash, this)) { | 287 sb_service_->CheckDownloadHash(info_.sha256_hash, this)) { |
264 CheckDone(SafeBrowsingService::SAFE); | 288 CheckDone(SafeBrowsingService::SAFE); |
265 } else { | 289 } else { |
266 AddRef(); // SafeBrowsingService takes a pointer not a scoped_refptr. | 290 AddRef(); // SafeBrowsingService takes a pointer not a scoped_refptr. |
267 } | 291 } |
268 } | 292 } |
269 | 293 |
270 virtual bool IsDangerous( | 294 virtual bool IsDangerous( |
271 SafeBrowsingService::UrlCheckResult result) const OVERRIDE { | 295 SafeBrowsingService::UrlCheckResult result) const OVERRIDE { |
272 return result == SafeBrowsingService::BINARY_MALWARE_HASH; | 296 // We always return false here because we don't want to warn based on |
| 297 // a match with the digest list. However, for UMA users, we want to |
| 298 // report the malware URL: DownloadSBClient::CheckDone() will still report |
| 299 // the URL even if the download is not considered dangerous. |
| 300 return false; |
273 } | 301 } |
274 | 302 |
275 virtual void OnDownloadHashCheckResult( | 303 virtual void OnDownloadHashCheckResult( |
276 const std::string& hash, | 304 const std::string& hash, |
277 SafeBrowsingService::UrlCheckResult sb_result) OVERRIDE { | 305 SafeBrowsingService::UrlCheckResult sb_result) OVERRIDE { |
278 CheckDone(sb_result); | 306 CheckDone(sb_result); |
279 UMA_HISTOGRAM_TIMES("SB2.DownloadHashCheckDuration", | 307 UMA_HISTOGRAM_TIMES("SB2.DownloadHashCheckDuration", |
280 base::TimeTicks::Now() - start_time_); | 308 base::TimeTicks::Now() - start_time_); |
281 Release(); | 309 Release(); |
282 } | 310 } |
(...skipping 19 matching lines...) Expand all Loading... |
302 : info_(info), | 330 : info_(info), |
303 callback_(callback), | 331 callback_(callback), |
304 service_(service), | 332 service_(service), |
305 signature_util_(signature_util), | 333 signature_util_(signature_util), |
306 sb_service_(sb_service), | 334 sb_service_(sb_service), |
307 pingback_enabled_(service_->enabled()) { | 335 pingback_enabled_(service_->enabled()) { |
308 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
309 } | 337 } |
310 | 338 |
311 void Start() { | 339 void Start() { |
| 340 VLOG(2) << "Starting SafeBrowsing download check for: " |
| 341 << info_.DebugString(); |
312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
313 // TODO(noelutz): implement some cache to make sure we don't issue the same | 343 // TODO(noelutz): implement some cache to make sure we don't issue the same |
314 // request over and over again if a user downloads the same binary multiple | 344 // request over and over again if a user downloads the same binary multiple |
315 // times. | 345 // times. |
316 if (info_.download_url_chain.empty()) { | 346 if (info_.download_url_chain.empty()) { |
317 RecordImprovedProtectionStats(REASON_EMPTY_URL_CHAIN); | 347 RecordImprovedProtectionStats(REASON_EMPTY_URL_CHAIN); |
318 PostFinishTask(SAFE); | 348 PostFinishTask(SAFE); |
319 return; | 349 return; |
320 } | 350 } |
321 const GURL& final_url = info_.download_url_chain.back(); | 351 const GURL& final_url = info_.download_url_chain.back(); |
322 if (!final_url.is_valid() || final_url.is_empty()) { | 352 if (!final_url.is_valid() || final_url.is_empty()) { |
323 RecordImprovedProtectionStats(REASON_INVALID_URL); | 353 RecordImprovedProtectionStats(REASON_INVALID_URL); |
324 PostFinishTask(SAFE); | 354 PostFinishTask(SAFE); |
325 return; | 355 return; |
326 } | 356 } |
327 RecordFileExtensionType(info_.local_file); | 357 RecordFileExtensionType(info_.target_file); |
328 | 358 |
329 if (!final_url.SchemeIs("http") || !IsBinaryFile(info_.local_file)) { | 359 if (final_url.SchemeIs("https") || !IsBinaryFile(info_.target_file)) { |
330 RecordImprovedProtectionStats(!final_url.SchemeIs("http") ? | 360 RecordImprovedProtectionStats(final_url.SchemeIs("https") ? |
331 REASON_HTTPS_URL : REASON_NOT_BINARY_FILE); | 361 REASON_HTTPS_URL : REASON_NOT_BINARY_FILE); |
332 BrowserThread::PostTask( | 362 BrowserThread::PostTask( |
333 BrowserThread::IO, | 363 BrowserThread::IO, |
334 FROM_HERE, | 364 FROM_HERE, |
335 base::Bind(&CheckClientDownloadRequest::CheckDigestList, this)); | 365 base::Bind(&CheckClientDownloadRequest::CheckDigestList, this)); |
336 return; | 366 return; |
337 } | 367 } |
338 | 368 |
339 // Compute features from the file contents. Note that we record histograms | 369 // Compute features from the file contents. Note that we record histograms |
340 // based on the result, so this runs regardless of whether the pingbacks | 370 // based on the result, so this runs regardless of whether the pingbacks |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 | 649 |
620 void DownloadProtectionService::RequestFinished( | 650 void DownloadProtectionService::RequestFinished( |
621 CheckClientDownloadRequest* request) { | 651 CheckClientDownloadRequest* request) { |
622 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 652 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
623 std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = | 653 std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = |
624 download_requests_.find(request); | 654 download_requests_.find(request); |
625 DCHECK(it != download_requests_.end()); | 655 DCHECK(it != download_requests_.end()); |
626 download_requests_.erase(*it); | 656 download_requests_.erase(*it); |
627 } | 657 } |
628 } // namespace safe_browsing | 658 } // namespace safe_browsing |
OLD | NEW |