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 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 37 DownloadSBClient::~DownloadSBClient() {} 38 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 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 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. 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 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. 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 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 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 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 174 void DownloadSBClient::UpdateDownloadCheckStats(SBStatsType stat_type) { 175 UMA_HISTOGRAM_ENUMERATION("SB2.DownloadChecks", 176 stat_type, 177 DOWNLOAD_CHECKS_MAX); 178 } 179