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