Chromium Code Reviews| 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/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 60 public content::URLFetcherDelegate { | 60 public content::URLFetcherDelegate { |
| 61 public: | 61 public: |
| 62 CheckClientDownloadRequest(const DownloadInfo& info, | 62 CheckClientDownloadRequest(const DownloadInfo& info, |
| 63 const CheckDownloadCallback& callback, | 63 const CheckDownloadCallback& callback, |
| 64 DownloadProtectionService* service, | 64 DownloadProtectionService* service, |
| 65 SafeBrowsingService* sb_service) | 65 SafeBrowsingService* sb_service) |
| 66 : info_(info), | 66 : info_(info), |
| 67 callback_(callback), | 67 callback_(callback), |
| 68 service_(service), | 68 service_(service), |
| 69 sb_service_(sb_service), | 69 sb_service_(sb_service), |
| 70 pingback_enabled_(service_->enabled()) { | 70 pingback_enabled_(service_->enabled()), |
| 71 is_signed_(false) { | |
| 71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 72 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 72 } | 73 } |
| 73 | 74 |
| 74 void Start() { | 75 void Start() { |
| 75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 76 // TODO(noelutz): implement some cache to make sure we don't issue the same | 77 // TODO(noelutz): implement some cache to make sure we don't issue the same |
| 77 // request over and over again if a user downloads the same binary multiple | 78 // request over and over again if a user downloads the same binary multiple |
| 78 // times. | 79 // times. |
| 79 if (info_.download_url_chain.empty()) { | 80 if (info_.download_url_chain.empty()) { |
| 80 RecordStats(REASON_INVALID_URL); | 81 RecordStats(REASON_INVALID_URL); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 private: | 156 private: |
| 156 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; | 157 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; |
| 157 friend class DeleteTask<CheckClientDownloadRequest>; | 158 friend class DeleteTask<CheckClientDownloadRequest>; |
| 158 | 159 |
| 159 virtual ~CheckClientDownloadRequest() { | 160 virtual ~CheckClientDownloadRequest() { |
| 160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 161 } | 162 } |
| 162 | 163 |
| 163 void ExtractFileFeatures() { | 164 void ExtractFileFeatures() { |
| 164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 165 bool is_signed; | |
| 166 if (safe_browsing::signature_util::IsSigned(info_.local_file)) { | 166 if (safe_browsing::signature_util::IsSigned(info_.local_file)) { |
| 167 VLOG(2) << "Downloaded a signed binary: " << info_.local_file.value(); | 167 VLOG(2) << "Downloaded a signed binary: " << info_.local_file.value(); |
| 168 is_signed = true; | 168 is_signed_ = true; |
| 169 } else { | 169 } else { |
| 170 VLOG(2) << "Downloaded an unsigned binary: " << info_.local_file.value(); | 170 VLOG(2) << "Downloaded an unsigned binary: " << info_.local_file.value(); |
| 171 is_signed = false; | 171 is_signed_ = false; |
| 172 } | 172 } |
| 173 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed); | 173 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed_); |
| 174 | 174 |
| 175 // TODO(noelutz): DownloadInfo should also contain the IP address of every | 175 // TODO(noelutz): DownloadInfo should also contain the IP address of every |
| 176 // URL in the redirect chain. We also should check whether the download | 176 // URL in the redirect chain. We also should check whether the download |
| 177 // URL is hosted on the internal network. | 177 // URL is hosted on the internal network. |
| 178 BrowserThread::PostTask( | 178 BrowserThread::PostTask( |
| 179 BrowserThread::IO, | 179 BrowserThread::IO, |
| 180 FROM_HERE, | 180 FROM_HERE, |
| 181 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this)); | 181 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this)); |
| 182 } | 182 } |
| 183 | 183 |
| 184 void CheckWhitelists() { | 184 void CheckWhitelists() { |
| 185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 186 DownloadCheckResultReason reason = REASON_MAX; | 186 DownloadCheckResultReason reason = REASON_MAX; |
| 187 if (!pingback_enabled_ || !sb_service_.get()) { | 187 if (!sb_service_.get()) { |
| 188 reason = REASON_SB_DISABLED; | 188 reason = REASON_SB_DISABLED; |
| 189 } else { | 189 } else { |
| 190 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { | 190 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { |
| 191 const GURL& url = info_.download_url_chain[i]; | 191 const GURL& url = info_.download_url_chain[i]; |
| 192 if (url.is_valid() && sb_service_->MatchDownloadWhitelistUrl(url)) { | 192 if (url.is_valid() && sb_service_->MatchDownloadWhitelistUrl(url)) { |
| 193 reason = REASON_WHITELISTED_URL; | 193 reason = REASON_WHITELISTED_URL; |
| 194 break; | 194 break; |
| 195 } | 195 } |
| 196 } | 196 } |
| 197 if (info_.referrer_url.is_valid() && | 197 if (info_.referrer_url.is_valid() && reason == REASON_MAX && |
| 198 sb_service_->MatchDownloadWhitelistUrl(info_.referrer_url)) { | 198 sb_service_->MatchDownloadWhitelistUrl(info_.referrer_url)) { |
| 199 reason = REASON_WHITELISTED_REFERRER; | 199 reason = REASON_WHITELISTED_REFERRER; |
| 200 } | 200 } |
| 201 if (reason != REASON_MAX || is_signed_) { | |
| 202 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedOrWhitelistedDownload", | |
|
Brian Ryner
2011/10/28 23:00:59
Should this be UMA_HISTOGRAM_COUNTS given how you'
noelutz
2011/10/28 23:11:24
Done.
| |
| 203 1); | |
| 204 } | |
| 201 } | 205 } |
| 202 if (reason != REASON_MAX) { | 206 if (reason != REASON_MAX) { |
| 203 RecordStats(reason); | 207 RecordStats(reason); |
| 204 PostFinishTask(SAFE); | 208 PostFinishTask(SAFE); |
| 205 return; | 209 } else if (!pingback_enabled_) { |
| 210 RecordStats(REASON_SB_DISABLED); | |
| 211 PostFinishTask(SAFE); | |
| 212 } else { | |
| 213 // TODO(noelutz): check signature and CA against whitelist. | |
| 214 | |
| 215 // The URLFetcher is owned by the UI thread, so post a message to | |
| 216 // start the pingback. | |
| 217 BrowserThread::PostTask( | |
| 218 BrowserThread::UI, | |
| 219 FROM_HERE, | |
| 220 base::Bind(&CheckClientDownloadRequest::SendRequest, this)); | |
| 206 } | 221 } |
| 207 | |
| 208 // TODO(noelutz): check signature and CA against whitelist. | |
| 209 | |
| 210 // The URLFetcher is owned by the UI thread, so post a message to | |
| 211 // start the pingback. | |
| 212 BrowserThread::PostTask( | |
| 213 BrowserThread::UI, | |
| 214 FROM_HERE, | |
| 215 base::Bind(&CheckClientDownloadRequest::SendRequest, this)); | |
| 216 } | 222 } |
| 217 | 223 |
| 218 void SendRequest() { | 224 void SendRequest() { |
| 219 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 220 | 226 |
| 221 // This is our last chance to check whether the request has been canceled | 227 // This is our last chance to check whether the request has been canceled |
| 222 // before sending it. | 228 // before sending it. |
| 223 if (!service_) { | 229 if (!service_) { |
| 230 RecordStats(REASON_REQUEST_CANCELED); | |
| 224 FinishRequest(SAFE); | 231 FinishRequest(SAFE); |
| 225 return; | 232 return; |
| 226 } | 233 } |
| 227 | 234 |
| 228 ClientDownloadRequest request; | 235 ClientDownloadRequest request; |
| 229 request.set_url(info_.download_url_chain.back().spec()); | 236 request.set_url(info_.download_url_chain.back().spec()); |
| 230 request.mutable_digests()->set_sha256(info_.sha256_hash); | 237 request.mutable_digests()->set_sha256(info_.sha256_hash); |
| 231 request.set_length(info_.total_bytes); | 238 request.set_length(info_.total_bytes); |
| 232 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { | 239 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { |
| 233 ClientDownloadRequest::Resource* resource = request.add_resources(); | 240 ClientDownloadRequest::Resource* resource = request.add_resources(); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 UMA_HISTOGRAM_ENUMERATION("SBClientDownload.CheckDownloadStats", | 289 UMA_HISTOGRAM_ENUMERATION("SBClientDownload.CheckDownloadStats", |
| 283 reason, | 290 reason, |
| 284 REASON_MAX); | 291 REASON_MAX); |
| 285 } | 292 } |
| 286 | 293 |
| 287 DownloadInfo info_; | 294 DownloadInfo info_; |
| 288 CheckDownloadCallback callback_; | 295 CheckDownloadCallback callback_; |
| 289 // Will be NULL if the request has been canceled. | 296 // Will be NULL if the request has been canceled. |
| 290 DownloadProtectionService* service_; | 297 DownloadProtectionService* service_; |
| 291 scoped_refptr<SafeBrowsingService> sb_service_; | 298 scoped_refptr<SafeBrowsingService> sb_service_; |
| 292 bool pingback_enabled_; | 299 const bool pingback_enabled_; |
| 300 bool is_signed_; | |
| 293 scoped_ptr<content::URLFetcher> fetcher_; | 301 scoped_ptr<content::URLFetcher> fetcher_; |
| 294 | 302 |
| 295 DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest); | 303 DISALLOW_COPY_AND_ASSIGN(CheckClientDownloadRequest); |
| 296 }; | 304 }; |
| 297 | 305 |
| 298 DownloadProtectionService::DownloadProtectionService( | 306 DownloadProtectionService::DownloadProtectionService( |
| 299 SafeBrowsingService* sb_service, | 307 SafeBrowsingService* sb_service, |
| 300 net::URLRequestContextGetter* request_context_getter) | 308 net::URLRequestContextGetter* request_context_getter) |
| 301 : sb_service_(sb_service), | 309 : sb_service_(sb_service), |
| 302 request_context_getter_(request_context_getter), | 310 request_context_getter_(request_context_getter), |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 340 void DownloadProtectionService::RequestFinished( | 348 void DownloadProtectionService::RequestFinished( |
| 341 CheckClientDownloadRequest* request) { | 349 CheckClientDownloadRequest* request) { |
| 342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 343 std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = | 351 std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = |
| 344 download_requests_.find(request); | 352 download_requests_.find(request); |
| 345 DCHECK(it != download_requests_.end()); | 353 DCHECK(it != download_requests_.end()); |
| 346 download_requests_.erase(*it); | 354 download_requests_.erase(*it); |
| 347 } | 355 } |
| 348 | 356 |
| 349 } // namespace safe_browsing | 357 } // namespace safe_browsing |
| OLD | NEW |