Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(708)

Side by Side Diff: chrome/browser/safe_browsing/download_protection_service.cc

Issue 12313141: Use DownloadItem directly in DownloadProtectionService. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review fixes Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/compiler_specific.h" 8 #include "base/compiler_specific.h"
9 #include "base/format_macros.h" 9 #include "base/format_macros.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 132
133 DOWNLOAD_HASH_CHECKS_TOTAL, 133 DOWNLOAD_HASH_CHECKS_TOTAL,
134 DOWNLOAD_HASH_CHECKS_MALWARE, 134 DOWNLOAD_HASH_CHECKS_MALWARE,
135 135
136 // Memory space for histograms is determined by the max. 136 // Memory space for histograms is determined by the max.
137 // ALWAYS ADD NEW VALUES BEFORE THIS ONE. 137 // ALWAYS ADD NEW VALUES BEFORE THIS ONE.
138 DOWNLOAD_CHECKS_MAX 138 DOWNLOAD_CHECKS_MAX
139 }; 139 };
140 } // namespace 140 } // namespace
141 141
142 DownloadProtectionService::DownloadInfo::DownloadInfo()
143 : total_bytes(0), user_initiated(false), zipped_executable(false) {}
144
145 DownloadProtectionService::DownloadInfo::~DownloadInfo() {}
146
147 std::string DownloadProtectionService::DownloadInfo::DebugString() const {
148 std::string chain;
149 for (size_t i = 0; i < download_url_chain.size(); ++i) {
150 chain += download_url_chain[i].spec();
151 if (i < download_url_chain.size() - 1) {
152 chain += " -> ";
153 }
154 }
155 return base::StringPrintf(
156 "DownloadInfo {addr:0x%p, download_url_chain:[%s], local_file:%"
157 PRFilePath ", target_file:%" PRFilePath ", referrer_url:%s, "
158 "sha256_hash:%s, total_bytes:%" PRId64 ", user_initiated: %s, "
159 "zipped_executable: %s}",
160 reinterpret_cast<const void*>(this),
161 chain.c_str(),
162 local_file.value().c_str(),
163 target_file.value().c_str(),
164 referrer_url.spec().c_str(),
165 base::HexEncode(sha256_hash.data(), sha256_hash.size()).c_str(),
166 total_bytes,
167 user_initiated ? "true" : "false",
168 zipped_executable ? "true" : "false");
169 }
170
171 // static
172 DownloadProtectionService::DownloadInfo
173 DownloadProtectionService::DownloadInfo::FromDownloadItem(
174 const content::DownloadItem& item) {
175 DownloadInfo download_info;
176 download_info.target_file = item.GetTargetFilePath();
177 download_info.sha256_hash = item.GetHash();
178 download_info.local_file = item.GetFullPath();
179 download_info.download_url_chain = item.GetUrlChain();
180 download_info.referrer_url = item.GetReferrerUrl();
181 download_info.total_bytes = item.GetTotalBytes();
182 download_info.remote_address = item.GetRemoteAddress();
183 download_info.user_initiated = item.HasUserGesture();
184 return download_info;
185 }
186
187 // Parent SafeBrowsing::Client class used to lookup the bad binary 142 // Parent SafeBrowsing::Client class used to lookup the bad binary
188 // URL and digest list. There are two sub-classes (one for each list). 143 // URL and digest list. There are two sub-classes (one for each list).
189 class DownloadSBClient 144 class DownloadSBClient
190 : public SafeBrowsingDatabaseManager::Client, 145 : public SafeBrowsingDatabaseManager::Client,
191 public base::RefCountedThreadSafe<DownloadSBClient> { 146 public base::RefCountedThreadSafe<DownloadSBClient> {
192 public: 147 public:
193 DownloadSBClient( 148 DownloadSBClient(
194 const DownloadProtectionService::DownloadInfo& info, 149 const content::DownloadItem& item,
195 const DownloadProtectionService::CheckDownloadCallback& callback, 150 const DownloadProtectionService::CheckDownloadCallback& callback,
196 const scoped_refptr<SafeBrowsingUIManager>& ui_manager, 151 const scoped_refptr<SafeBrowsingUIManager>& ui_manager,
197 SBStatsType total_type, 152 SBStatsType total_type,
198 SBStatsType dangerous_type) 153 SBStatsType dangerous_type)
199 : info_(info), 154 : sha256_hash_(item.GetHash()),
155 url_chain_(item.GetUrlChain()),
156 referrer_url_(item.GetReferrerUrl()),
200 callback_(callback), 157 callback_(callback),
201 ui_manager_(ui_manager), 158 ui_manager_(ui_manager),
202 start_time_(base::TimeTicks::Now()), 159 start_time_(base::TimeTicks::Now()),
203 total_type_(total_type), 160 total_type_(total_type),
204 dangerous_type_(dangerous_type) {} 161 dangerous_type_(dangerous_type) {}
205 162
206 virtual void StartCheck() = 0; 163 virtual void StartCheck() = 0;
207 virtual bool IsDangerous(SBThreatType threat_type) const = 0; 164 virtual bool IsDangerous(SBThreatType threat_type) const = 0;
208 165
209 protected: 166 protected:
(...skipping 14 matching lines...) Expand all
224 BrowserThread::PostTask( 181 BrowserThread::PostTask(
225 BrowserThread::UI, 182 BrowserThread::UI,
226 FROM_HERE, 183 FROM_HERE,
227 base::Bind(&DownloadSBClient::ReportMalware, 184 base::Bind(&DownloadSBClient::ReportMalware,
228 this, threat_type)); 185 this, threat_type));
229 } 186 }
230 } 187 }
231 188
232 void ReportMalware(SBThreatType threat_type) { 189 void ReportMalware(SBThreatType threat_type) {
233 std::string post_data; 190 std::string post_data;
234 if (!info_.sha256_hash.empty()) 191 if (!sha256_hash_.empty())
235 post_data += base::HexEncode(info_.sha256_hash.data(), 192 post_data += base::HexEncode(sha256_hash_.data(),
236 info_.sha256_hash.size()) + "\n"; 193 sha256_hash_.size()) + "\n";
237 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { 194 for (size_t i = 0; i < url_chain_.size(); ++i) {
238 post_data += info_.download_url_chain[i].spec() + "\n"; 195 post_data += url_chain_[i].spec() + "\n";
239 } 196 }
240 ui_manager_->ReportSafeBrowsingHit( 197 ui_manager_->ReportSafeBrowsingHit(
241 info_.download_url_chain.back(), // malicious_url 198 url_chain_.back(), // malicious_url
242 info_.download_url_chain.front(), // page_url 199 url_chain_.front(), // page_url
243 info_.referrer_url, 200 referrer_url_,
244 true, // is_subresource 201 true, // is_subresource
245 threat_type, 202 threat_type,
246 post_data); 203 post_data);
247 } 204 }
248 205
249 void UpdateDownloadCheckStats(SBStatsType stat_type) { 206 void UpdateDownloadCheckStats(SBStatsType stat_type) {
250 UMA_HISTOGRAM_ENUMERATION("SB2.DownloadChecks", 207 UMA_HISTOGRAM_ENUMERATION("SB2.DownloadChecks",
251 stat_type, 208 stat_type,
252 DOWNLOAD_CHECKS_MAX); 209 DOWNLOAD_CHECKS_MAX);
253 } 210 }
254 211
255 DownloadProtectionService::DownloadInfo info_; 212 std::string sha256_hash_;
213 std::vector<GURL> url_chain_;
214 GURL referrer_url_;
256 DownloadProtectionService::CheckDownloadCallback callback_; 215 DownloadProtectionService::CheckDownloadCallback callback_;
257 scoped_refptr<SafeBrowsingUIManager> ui_manager_; 216 scoped_refptr<SafeBrowsingUIManager> ui_manager_;
258 base::TimeTicks start_time_; 217 base::TimeTicks start_time_;
259 218
260 private: 219 private:
261 const SBStatsType total_type_; 220 const SBStatsType total_type_;
262 const SBStatsType dangerous_type_; 221 const SBStatsType dangerous_type_;
263 222
264 DISALLOW_COPY_AND_ASSIGN(DownloadSBClient); 223 DISALLOW_COPY_AND_ASSIGN(DownloadSBClient);
265 }; 224 };
266 225
267 class DownloadUrlSBClient : public DownloadSBClient { 226 class DownloadUrlSBClient : public DownloadSBClient {
268 public: 227 public:
269 DownloadUrlSBClient( 228 DownloadUrlSBClient(
270 const DownloadProtectionService::DownloadInfo& info, 229 const content::DownloadItem& item,
271 const DownloadProtectionService::CheckDownloadCallback& callback, 230 const DownloadProtectionService::CheckDownloadCallback& callback,
272 const scoped_refptr<SafeBrowsingUIManager>& ui_manager, 231 const scoped_refptr<SafeBrowsingUIManager>& ui_manager,
273 const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager) 232 const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager)
274 : DownloadSBClient(info, callback, ui_manager, 233 : DownloadSBClient(item, callback, ui_manager,
275 DOWNLOAD_URL_CHECKS_TOTAL, 234 DOWNLOAD_URL_CHECKS_TOTAL,
276 DOWNLOAD_URL_CHECKS_MALWARE), 235 DOWNLOAD_URL_CHECKS_MALWARE),
277 database_manager_(database_manager) { } 236 database_manager_(database_manager) { }
278 237
279 virtual void StartCheck() OVERRIDE { 238 virtual void StartCheck() OVERRIDE {
280 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
281 if (!database_manager_ || database_manager_->CheckDownloadUrl( 240 if (!database_manager_ || database_manager_->CheckDownloadUrl(
282 info_.download_url_chain, this)) { 241 url_chain_, this)) {
283 CheckDone(SB_THREAT_TYPE_SAFE); 242 CheckDone(SB_THREAT_TYPE_SAFE);
284 } else { 243 } else {
285 AddRef(); // SafeBrowsingService takes a pointer not a scoped_refptr. 244 AddRef(); // SafeBrowsingService takes a pointer not a scoped_refptr.
286 } 245 }
287 } 246 }
288 247
289 virtual bool IsDangerous(SBThreatType threat_type) const OVERRIDE { 248 virtual bool IsDangerous(SBThreatType threat_type) const OVERRIDE {
290 return threat_type == SB_THREAT_TYPE_BINARY_MALWARE_URL; 249 return threat_type == SB_THREAT_TYPE_BINARY_MALWARE_URL;
291 } 250 }
292 251
(...skipping 11 matching lines...) Expand all
304 private: 263 private:
305 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; 264 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
306 265
307 DISALLOW_COPY_AND_ASSIGN(DownloadUrlSBClient); 266 DISALLOW_COPY_AND_ASSIGN(DownloadUrlSBClient);
308 }; 267 };
309 268
310 class DownloadProtectionService::CheckClientDownloadRequest 269 class DownloadProtectionService::CheckClientDownloadRequest
311 : public base::RefCountedThreadSafe< 270 : public base::RefCountedThreadSafe<
312 DownloadProtectionService::CheckClientDownloadRequest, 271 DownloadProtectionService::CheckClientDownloadRequest,
313 BrowserThread::DeleteOnUIThread>, 272 BrowserThread::DeleteOnUIThread>,
314 public net::URLFetcherDelegate { 273 public net::URLFetcherDelegate,
274 public content::DownloadItem::Observer {
315 public: 275 public:
316 CheckClientDownloadRequest( 276 CheckClientDownloadRequest(
317 const DownloadInfo& info, 277 content::DownloadItem* item,
318 const CheckDownloadCallback& callback, 278 const CheckDownloadCallback& callback,
319 DownloadProtectionService* service, 279 DownloadProtectionService* service,
320 const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager, 280 const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager,
321 SignatureUtil* signature_util) 281 SignatureUtil* signature_util)
322 : info_(info), 282 : item_(item),
283 url_chain_(item->GetUrlChain()),
284 referrer_url_(item->GetReferrerUrl()),
285 zipped_executable_(false),
323 callback_(callback), 286 callback_(callback),
324 service_(service), 287 service_(service),
325 signature_util_(signature_util), 288 signature_util_(signature_util),
326 database_manager_(database_manager), 289 database_manager_(database_manager),
327 pingback_enabled_(service_->enabled()), 290 pingback_enabled_(service_->enabled()),
328 finished_(false), 291 finished_(false),
329 type_(ClientDownloadRequest::WIN_EXECUTABLE), 292 type_(ClientDownloadRequest::WIN_EXECUTABLE),
330 ALLOW_THIS_IN_INITIALIZER_LIST(weakptr_factory_(this)), 293 ALLOW_THIS_IN_INITIALIZER_LIST(weakptr_factory_(this)),
331 start_time_(base::TimeTicks::Now()) { 294 start_time_(base::TimeTicks::Now()) {
332 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
296 item_->AddObserver(this);
333 } 297 }
334 298
335 void Start() { 299 void Start() {
336 VLOG(2) << "Starting SafeBrowsing download check for: " 300 VLOG(2) << "Starting SafeBrowsing download check for: "
337 << info_.DebugString(); 301 << item_->DebugString(true);
338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 302 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
339 // TODO(noelutz): implement some cache to make sure we don't issue the same 303 // TODO(noelutz): implement some cache to make sure we don't issue the same
340 // request over and over again if a user downloads the same binary multiple 304 // request over and over again if a user downloads the same binary multiple
341 // times. 305 // times.
342 DownloadCheckResultReason reason = REASON_MAX; 306 DownloadCheckResultReason reason = REASON_MAX;
343 if (!IsSupportedDownload(info_, &reason, &type_)) { 307 if (!IsSupportedDownload(
308 *item_, item_->GetTargetFilePath(), &reason, &type_)) {
344 switch (reason) { 309 switch (reason) {
345 case REASON_EMPTY_URL_CHAIN: 310 case REASON_EMPTY_URL_CHAIN:
346 case REASON_INVALID_URL: 311 case REASON_INVALID_URL:
347 RecordImprovedProtectionStats(reason); 312 PostFinishTask(SAFE, reason);
348 PostFinishTask(SAFE);
349 return; 313 return;
350 314
351 case REASON_NOT_BINARY_FILE: 315 case REASON_NOT_BINARY_FILE:
352 RecordFileExtensionType(info_.target_file); 316 RecordFileExtensionType(item_->GetTargetFilePath());
353 RecordImprovedProtectionStats(reason); 317 PostFinishTask(SAFE, reason);
354 PostFinishTask(SAFE);
355 return; 318 return;
356 319
357 default: 320 default:
358 // We only expect the reasons explicitly handled above. 321 // We only expect the reasons explicitly handled above.
359 NOTREACHED(); 322 NOTREACHED();
360 } 323 }
361 } 324 }
362 RecordFileExtensionType(info_.target_file); 325 RecordFileExtensionType(item_->GetTargetFilePath());
363 326
364 // Compute features from the file contents. Note that we record histograms 327 // Compute features from the file contents. Note that we record histograms
365 // based on the result, so this runs regardless of whether the pingbacks 328 // based on the result, so this runs regardless of whether the pingbacks
366 // are enabled. 329 // are enabled.
367 if (info_.target_file.MatchesExtension(FILE_PATH_LITERAL(".zip"))) { 330 if (item_->GetTargetFilePath().MatchesExtension(
331 FILE_PATH_LITERAL(".zip"))) {
368 StartExtractZipFeatures(); 332 StartExtractZipFeatures();
369 } else { 333 } else {
370 DCHECK(!download_protection_util::IsArchiveFile(info_.target_file)); 334 DCHECK(!download_protection_util::IsArchiveFile(
335 item_->GetTargetFilePath()));
371 StartExtractSignatureFeatures(); 336 StartExtractSignatureFeatures();
372 } 337 }
373 } 338 }
374 339
375 // Start a timeout to cancel the request if it takes too long. 340 // Start a timeout to cancel the request if it takes too long.
376 // This should only be called after we have finished accessing the file. 341 // This should only be called after we have finished accessing the file.
377 void StartTimeout() { 342 void StartTimeout() {
378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 343 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
379 if (!service_) { 344 if (!service_) {
380 // Request has already been cancelled. 345 // Request has already been cancelled.
381 return; 346 return;
382 } 347 }
383 BrowserThread::PostDelayedTask( 348 BrowserThread::PostDelayedTask(
384 BrowserThread::UI, 349 BrowserThread::UI,
385 FROM_HERE, 350 FROM_HERE,
386 base::Bind(&CheckClientDownloadRequest::Cancel, 351 base::Bind(&CheckClientDownloadRequest::Cancel,
387 weakptr_factory_.GetWeakPtr()), 352 weakptr_factory_.GetWeakPtr()),
388 base::TimeDelta::FromMilliseconds( 353 base::TimeDelta::FromMilliseconds(
389 service_->download_request_timeout_ms())); 354 service_->download_request_timeout_ms()));
390 } 355 }
391 356
392 // Canceling a request will cause us to always report the result as SAFE 357 // Canceling a request will cause us to always report the result as SAFE
393 // unless a pending request is about to call FinishRequest. 358 // unless a pending request is about to call FinishRequest.
394 void Cancel() { 359 void Cancel() {
395 // Calling FinishRequest might delete this object if we don't keep a 360 // Calling FinishRequest might delete this object if we don't keep a
396 // reference around until Cancel() is finished running. 361 // reference around until Cancel() is finished running.
397 scoped_refptr<CheckClientDownloadRequest> request(this); 362 scoped_refptr<CheckClientDownloadRequest> request(this);
398 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
399 FinishRequest(SAFE); 364 FinishRequest(SAFE, REASON_REQUEST_CANCELED);
400 if (fetcher_.get()) { 365 if (fetcher_.get()) {
401 // The DownloadProtectionService is going to release its reference, so we 366 // The DownloadProtectionService is going to release its reference, so we
402 // might be destroyed before the URLFetcher completes. Cancel the 367 // might be destroyed before the URLFetcher completes. Cancel the
403 // fetcher so it does not try to invoke OnURLFetchComplete. 368 // fetcher so it does not try to invoke OnURLFetchComplete.
404 fetcher_.reset(); 369 fetcher_.reset();
405 } 370 }
406 // Note: If there is no fetcher, then some callback is still holding a 371 // Note: If there is no fetcher, then some callback is still holding a
407 // reference to this object. We'll eventually wind up in some method on 372 // reference to this object. We'll eventually wind up in some method on
408 // the UI thread that will call FinishRequest() again. If FinishRequest() 373 // the UI thread that will call FinishRequest() again. If FinishRequest()
409 // is called a second time, it will be a no-op. 374 // is called a second time, it will be a no-op.
410 } 375 }
411 376
377 // content::DownloadItem::Observer implementation.
378 virtual void OnDownloadDestroyed(content::DownloadItem* download) OVERRIDE {
379 Cancel();
380 DCHECK(item_ == NULL);
381 }
382
412 // From the net::URLFetcherDelegate interface. 383 // From the net::URLFetcherDelegate interface.
413 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE { 384 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
414 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 385 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
415 DCHECK_EQ(source, fetcher_.get()); 386 DCHECK_EQ(source, fetcher_.get());
416 VLOG(2) << "Received a response for URL: " 387 VLOG(2) << "Received a response for URL: "
417 << info_.download_url_chain.back() << ": success=" 388 << item_->GetUrlChain().back() << ": success="
418 << source->GetStatus().is_success() << " response_code=" 389 << source->GetStatus().is_success() << " response_code="
419 << source->GetResponseCode(); 390 << source->GetResponseCode();
420 DownloadCheckResultReason reason = REASON_SERVER_PING_FAILED; 391 DownloadCheckResultReason reason = REASON_SERVER_PING_FAILED;
421 DownloadCheckResult result = SAFE; 392 DownloadCheckResult result = SAFE;
422 if (source->GetStatus().is_success() && 393 if (source->GetStatus().is_success() &&
423 net::HTTP_OK == source->GetResponseCode()) { 394 net::HTTP_OK == source->GetResponseCode()) {
424 ClientDownloadResponse response; 395 ClientDownloadResponse response;
425 std::string data; 396 std::string data;
426 bool got_data = source->GetResponseAsString(&data); 397 bool got_data = source->GetResponseAsString(&data);
427 DCHECK(got_data); 398 DCHECK(got_data);
428 if (!response.ParseFromString(data)) { 399 if (!response.ParseFromString(data)) {
429 reason = REASON_INVALID_RESPONSE_PROTO; 400 reason = REASON_INVALID_RESPONSE_PROTO;
430 } else if (response.verdict() == ClientDownloadResponse::SAFE) { 401 } else if (response.verdict() == ClientDownloadResponse::SAFE) {
431 reason = REASON_DOWNLOAD_SAFE; 402 reason = REASON_DOWNLOAD_SAFE;
432 } else if (service_ && !service_->IsSupportedDownload(info_)) { 403 } else if (service_ && !service_->IsSupportedDownload(
404 *item_, item_->GetTargetFilePath())) {
433 // The client of the download protection service assumes that we don't 405 // The client of the download protection service assumes that we don't
434 // support this download so we cannot return any other verdict than 406 // support this download so we cannot return any other verdict than
435 // SAFE even if the server says it's dangerous to download this file. 407 // SAFE even if the server says it's dangerous to download this file.
436 // Note: if service_ is NULL we already cancelled the request and 408 // Note: if service_ is NULL we already cancelled the request and
437 // returned SAFE. 409 // returned SAFE.
438 reason = REASON_DOWNLOAD_NOT_SUPPORTED; 410 reason = REASON_DOWNLOAD_NOT_SUPPORTED;
439 } else if (response.verdict() == ClientDownloadResponse::DANGEROUS) { 411 } else if (response.verdict() == ClientDownloadResponse::DANGEROUS) {
440 reason = REASON_DOWNLOAD_DANGEROUS; 412 reason = REASON_DOWNLOAD_DANGEROUS;
441 result = DANGEROUS; 413 result = DANGEROUS;
442 } else if (response.verdict() == ClientDownloadResponse::UNCOMMON) { 414 } else if (response.verdict() == ClientDownloadResponse::UNCOMMON) {
443 reason = REASON_DOWNLOAD_UNCOMMON; 415 reason = REASON_DOWNLOAD_UNCOMMON;
444 result = UNCOMMON; 416 result = UNCOMMON;
445 } else if (response.verdict() == ClientDownloadResponse::DANGEROUS_HOST) { 417 } else if (response.verdict() == ClientDownloadResponse::DANGEROUS_HOST) {
446 reason = REASON_DOWNLOAD_DANGEROUS_HOST; 418 reason = REASON_DOWNLOAD_DANGEROUS_HOST;
447 result = DANGEROUS_HOST; 419 result = DANGEROUS_HOST;
448 } else { 420 } else {
449 LOG(DFATAL) << "Unknown download response verdict: " 421 LOG(DFATAL) << "Unknown download response verdict: "
450 << response.verdict(); 422 << response.verdict();
451 reason = REASON_INVALID_RESPONSE_VERDICT; 423 reason = REASON_INVALID_RESPONSE_VERDICT;
452 } 424 }
453 } 425 }
454 // We don't need the fetcher anymore. 426 // We don't need the fetcher anymore.
455 fetcher_.reset(); 427 fetcher_.reset();
456 RecordImprovedProtectionStats(reason);
457 UMA_HISTOGRAM_TIMES("SBClientDownload.DownloadRequestDuration", 428 UMA_HISTOGRAM_TIMES("SBClientDownload.DownloadRequestDuration",
458 base::TimeTicks::Now() - start_time_); 429 base::TimeTicks::Now() - start_time_);
459 FinishRequest(result); 430 FinishRequest(result, reason);
460 } 431 }
461 432
462 static bool IsSupportedDownload(const DownloadInfo& info, 433 static bool IsSupportedDownload(const content::DownloadItem& item,
434 const base::FilePath& target_path,
463 DownloadCheckResultReason* reason, 435 DownloadCheckResultReason* reason,
464 ClientDownloadRequest::DownloadType* type) { 436 ClientDownloadRequest::DownloadType* type) {
465 if (info.download_url_chain.empty()) { 437 if (item.GetUrlChain().empty()) {
466 *reason = REASON_EMPTY_URL_CHAIN; 438 *reason = REASON_EMPTY_URL_CHAIN;
467 return false; 439 return false;
468 } 440 }
469 const GURL& final_url = info.download_url_chain.back(); 441 const GURL& final_url = item.GetUrlChain().back();
470 if (!final_url.is_valid() || final_url.is_empty() || 442 if (!final_url.is_valid() || final_url.is_empty() ||
471 !final_url.IsStandard() || final_url.SchemeIsFile()) { 443 !final_url.IsStandard() || final_url.SchemeIsFile()) {
472 *reason = REASON_INVALID_URL; 444 *reason = REASON_INVALID_URL;
473 return false; 445 return false;
474 } 446 }
475 if (!download_protection_util::IsBinaryFile(info.target_file)) { 447 if (!download_protection_util::IsBinaryFile(target_path)) {
476 *reason = REASON_NOT_BINARY_FILE; 448 *reason = REASON_NOT_BINARY_FILE;
477 return false; 449 return false;
478 } 450 }
479 *type = GetDownloadType(info.target_file); 451 *type = GetDownloadType(target_path);
480 return true; 452 return true;
481 } 453 }
482 454
483 private: 455 private:
484 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>; 456 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
485 friend class base::DeleteHelper<CheckClientDownloadRequest>; 457 friend class base::DeleteHelper<CheckClientDownloadRequest>;
486 458
487 virtual ~CheckClientDownloadRequest() { 459 virtual ~CheckClientDownloadRequest() {
488 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 460 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
461 DCHECK(item_ == NULL);
489 } 462 }
490 463
491 void OnFileFeatureExtractionDone() { 464 void OnFileFeatureExtractionDone() {
492 // This can run in any thread, since it just posts more messages. 465 // This can run in any thread, since it just posts more messages.
493 466
494 // TODO(noelutz): DownloadInfo should also contain the IP address of 467 // TODO(noelutz): DownloadInfo should also contain the IP address of
495 // every URL in the redirect chain. We also should check whether the 468 // every URL in the redirect chain. We also should check whether the
496 // download URL is hosted on the internal network. 469 // download URL is hosted on the internal network.
497 BrowserThread::PostTask( 470 BrowserThread::PostTask(
498 BrowserThread::IO, 471 BrowserThread::IO,
499 FROM_HERE, 472 FROM_HERE,
500 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this)); 473 base::Bind(&CheckClientDownloadRequest::CheckWhitelists, this));
501 474
502 // We wait until after the file checks finish to start the timeout, as 475 // We wait until after the file checks finish to start the timeout, as
503 // windows can cause permissions errors if the timeout fired while we were 476 // windows can cause permissions errors if the timeout fired while we were
504 // checking the file signature and we tried to complete the download. 477 // checking the file signature and we tried to complete the download.
505 BrowserThread::PostTask( 478 BrowserThread::PostTask(
506 BrowserThread::UI, 479 BrowserThread::UI,
507 FROM_HERE, 480 FROM_HERE,
508 base::Bind(&CheckClientDownloadRequest::StartTimeout, this)); 481 base::Bind(&CheckClientDownloadRequest::StartTimeout, this));
509 } 482 }
510 483
511 void StartExtractSignatureFeatures() { 484 void StartExtractSignatureFeatures() {
485 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
486 DCHECK(item_); // Called directly from Start(), item should still exist.
512 // Since we do blocking I/O, offload this to a worker thread. 487 // Since we do blocking I/O, offload this to a worker thread.
513 // The task does not need to block shutdown. 488 // The task does not need to block shutdown.
514 BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( 489 BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior(
515 FROM_HERE, 490 FROM_HERE,
516 base::Bind(&CheckClientDownloadRequest::ExtractSignatureFeatures, 491 base::Bind(&CheckClientDownloadRequest::ExtractSignatureFeatures,
517 this), 492 this, item_->GetFullPath()),
518 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); 493 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
519 } 494 }
520 495
521 void ExtractSignatureFeatures() { 496 void ExtractSignatureFeatures(const base::FilePath& file_path) {
522 base::TimeTicks start_time = base::TimeTicks::Now(); 497 base::TimeTicks start_time = base::TimeTicks::Now();
523 signature_util_->CheckSignature(info_.local_file, &signature_info_); 498 signature_util_->CheckSignature(file_path, &signature_info_);
524 bool is_signed = (signature_info_.certificate_chain_size() > 0); 499 bool is_signed = (signature_info_.certificate_chain_size() > 0);
525 if (is_signed) { 500 if (is_signed) {
526 VLOG(2) << "Downloaded a signed binary: " << info_.local_file.value(); 501 VLOG(2) << "Downloaded a signed binary: " << file_path.value();
527 } else { 502 } else {
528 VLOG(2) << "Downloaded an unsigned binary: " << info_.local_file.value(); 503 VLOG(2) << "Downloaded an unsigned binary: "
504 << file_path.value();
529 } 505 }
530 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed); 506 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.SignedBinaryDownload", is_signed);
531 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractSignatureFeaturesTime", 507 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractSignatureFeaturesTime",
532 base::TimeTicks::Now() - start_time); 508 base::TimeTicks::Now() - start_time);
533 509
534 OnFileFeatureExtractionDone(); 510 OnFileFeatureExtractionDone();
535 } 511 }
536 512
537 void StartExtractZipFeatures() { 513 void StartExtractZipFeatures() {
514 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
515 DCHECK(item_); // Called directly from Start(), item should still exist.
538 zip_analysis_start_time_ = base::TimeTicks::Now(); 516 zip_analysis_start_time_ = base::TimeTicks::Now();
539 // We give the zip analyzer a weak pointer to this object. Since the 517 // We give the zip analyzer a weak pointer to this object. Since the
540 // analyzer is refcounted, it might outlive the request. 518 // analyzer is refcounted, it might outlive the request.
541 analyzer_ = new SandboxedZipAnalyzer( 519 analyzer_ = new SandboxedZipAnalyzer(
542 info_.local_file, 520 item_->GetFullPath(),
543 base::Bind(&CheckClientDownloadRequest::OnZipAnalysisFinished, 521 base::Bind(&CheckClientDownloadRequest::OnZipAnalysisFinished,
544 weakptr_factory_.GetWeakPtr())); 522 weakptr_factory_.GetWeakPtr()));
545 analyzer_->Start(); 523 analyzer_->Start();
546 } 524 }
547 525
548 void OnZipAnalysisFinished(const zip_analyzer::Results& results) { 526 void OnZipAnalysisFinished(const zip_analyzer::Results& results) {
549 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 527 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
528 if (!service_)
529 return;
550 if (results.success) { 530 if (results.success) {
551 info_.zipped_executable = results.has_executable; 531 zipped_executable_ = results.has_executable;
552 VLOG(1) << "Zip analysis finished for " << info_.local_file.value() 532 VLOG(1) << "Zip analysis finished for " << item_->GetFullPath().value()
553 << ", has_executable=" << results.has_executable 533 << ", has_executable=" << results.has_executable
554 << " has_archive=" << results.has_archive; 534 << " has_archive=" << results.has_archive;
555 } else { 535 } else {
556 VLOG(1) << "Zip analysis failed for " << info_.local_file.value(); 536 VLOG(1) << "Zip analysis failed for " << item_->GetFullPath().value();
557 } 537 }
558 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasExecutable", 538 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasExecutable",
559 info_.zipped_executable); 539 zipped_executable_);
560 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasArchiveButNoExecutable", 540 UMA_HISTOGRAM_BOOLEAN("SBClientDownload.ZipFileHasArchiveButNoExecutable",
561 results.has_archive && !info_.zipped_executable); 541 results.has_archive && !zipped_executable_);
562 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractZipFeaturesTime", 542 UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractZipFeaturesTime",
563 base::TimeTicks::Now() - zip_analysis_start_time_); 543 base::TimeTicks::Now() - zip_analysis_start_time_);
564 544
565 if (!info_.zipped_executable) { 545 if (!zipped_executable_) {
566 RecordImprovedProtectionStats(REASON_ARCHIVE_WITHOUT_BINARIES); 546 PostFinishTask(SAFE, REASON_ARCHIVE_WITHOUT_BINARIES);
567 PostFinishTask(SAFE);
568 return; 547 return;
569 } 548 }
570 OnFileFeatureExtractionDone(); 549 OnFileFeatureExtractionDone();
571 } 550 }
572 551
573 void CheckWhitelists() { 552 void CheckWhitelists() {
574 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 553 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
575 DownloadCheckResultReason reason = REASON_MAX; 554 DownloadCheckResultReason reason = REASON_MAX;
576 if (!database_manager_) { 555 if (!database_manager_) {
577 reason = REASON_SB_DISABLED; 556 reason = REASON_SB_DISABLED;
578 } else { 557 } else {
579 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { 558 for (size_t i = 0; i < url_chain_.size(); ++i) {
580 const GURL& url = info_.download_url_chain[i]; 559 const GURL& url = url_chain_[i];
581 if (url.is_valid() && 560 if (url.is_valid() &&
582 database_manager_->MatchDownloadWhitelistUrl(url)) { 561 database_manager_->MatchDownloadWhitelistUrl(url)) {
583 VLOG(2) << url << " is on the download whitelist."; 562 VLOG(2) << url << " is on the download whitelist.";
584 reason = REASON_WHITELISTED_URL; 563 reason = REASON_WHITELISTED_URL;
585 break; 564 break;
586 } 565 }
587 } 566 }
588 if (info_.referrer_url.is_valid() && reason == REASON_MAX && 567 if (referrer_url_.is_valid() && reason == REASON_MAX &&
589 database_manager_->MatchDownloadWhitelistUrl( 568 database_manager_->MatchDownloadWhitelistUrl(
590 info_.referrer_url)) { 569 referrer_url_)) {
591 VLOG(2) << "Referrer url " << info_.referrer_url 570 VLOG(2) << "Referrer url " << referrer_url_
592 << " is on the download whitelist."; 571 << " is on the download whitelist.";
593 reason = REASON_WHITELISTED_REFERRER; 572 reason = REASON_WHITELISTED_REFERRER;
594 } 573 }
595 if (reason != REASON_MAX || signature_info_.trusted()) { 574 if (reason != REASON_MAX || signature_info_.trusted()) {
596 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1); 575 UMA_HISTOGRAM_COUNTS("SBClientDownload.SignedOrWhitelistedDownload", 1);
597 } 576 }
598 } 577 }
599 if (reason == REASON_MAX && signature_info_.trusted()) { 578 if (reason == REASON_MAX && signature_info_.trusted()) {
600 for (int i = 0; i < signature_info_.certificate_chain_size(); ++i) { 579 for (int i = 0; i < signature_info_.certificate_chain_size(); ++i) {
601 if (CertificateChainIsWhitelisted( 580 if (CertificateChainIsWhitelisted(
602 signature_info_.certificate_chain(i))) { 581 signature_info_.certificate_chain(i))) {
603 reason = REASON_TRUSTED_EXECUTABLE; 582 reason = REASON_TRUSTED_EXECUTABLE;
604 break; 583 break;
605 } 584 }
606 } 585 }
607 } 586 }
608 if (reason != REASON_MAX) { 587 if (reason != REASON_MAX) {
609 RecordImprovedProtectionStats(reason); 588 PostFinishTask(SAFE, reason);
610 PostFinishTask(SAFE);
611 } else if (!pingback_enabled_) { 589 } else if (!pingback_enabled_) {
612 RecordImprovedProtectionStats(REASON_PING_DISABLED); 590 PostFinishTask(SAFE, REASON_PING_DISABLED);
613 PostFinishTask(SAFE);
614 } else { 591 } else {
615 // Currently, the UI only works on Windows so we don't even bother 592 // Currently, the UI only works on Windows so we don't even bother
616 // with pinging the server if we're not on Windows. TODO(noelutz): 593 // with pinging the server if we're not on Windows. TODO(noelutz):
617 // change this code once the UI is done for Linux and Mac. 594 // change this code once the UI is done for Linux and Mac.
618 #if defined(OS_WIN) 595 #if defined(OS_WIN)
619 // The URLFetcher is owned by the UI thread, so post a message to 596 // The URLFetcher is owned by the UI thread, so post a message to
620 // start the pingback. 597 // start the pingback.
621 BrowserThread::PostTask( 598 BrowserThread::PostTask(
622 BrowserThread::UI, 599 BrowserThread::UI,
623 FROM_HERE, 600 FROM_HERE,
624 base::Bind(&CheckClientDownloadRequest::SendRequest, this)); 601 base::Bind(&CheckClientDownloadRequest::SendRequest, this));
625 #else 602 #else
626 RecordImprovedProtectionStats(REASON_OS_NOT_SUPPORTED); 603 PostFinishTask(SAFE, REASON_OS_NOT_SUPPORTED);
627 PostFinishTask(SAFE);
628 #endif 604 #endif
629 } 605 }
630 } 606 }
631 607
632 void SendRequest() { 608 void SendRequest() {
633 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 609 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
634 610
635 // This is our last chance to check whether the request has been canceled 611 // This is our last chance to check whether the request has been canceled
636 // before sending it. 612 // before sending it.
637 if (!service_) { 613 if (!service_)
638 RecordImprovedProtectionStats(REASON_REQUEST_CANCELED);
639 FinishRequest(SAFE);
640 return; 614 return;
641 }
642 615
643 ClientDownloadRequest request; 616 ClientDownloadRequest request;
644 request.set_url(info_.download_url_chain.back().spec()); 617 request.set_url(item_->GetUrlChain().back().spec());
645 request.mutable_digests()->set_sha256(info_.sha256_hash); 618 request.mutable_digests()->set_sha256(item_->GetHash());
646 request.set_length(info_.total_bytes); 619 request.set_length(item_->GetReceivedBytes());
647 for (size_t i = 0; i < info_.download_url_chain.size(); ++i) { 620 for (size_t i = 0; i < item_->GetUrlChain().size(); ++i) {
648 ClientDownloadRequest::Resource* resource = request.add_resources(); 621 ClientDownloadRequest::Resource* resource = request.add_resources();
649 resource->set_url(info_.download_url_chain[i].spec()); 622 resource->set_url(item_->GetUrlChain()[i].spec());
650 if (i == info_.download_url_chain.size() - 1) { 623 if (i == item_->GetUrlChain().size() - 1) {
651 // The last URL in the chain is the download URL. 624 // The last URL in the chain is the download URL.
652 resource->set_type(ClientDownloadRequest::DOWNLOAD_URL); 625 resource->set_type(ClientDownloadRequest::DOWNLOAD_URL);
653 resource->set_referrer(info_.referrer_url.spec()); 626 resource->set_referrer(item_->GetReferrerUrl().spec());
654 if (!info_.remote_address.empty()) { 627 if (!item_->GetRemoteAddress().empty()) {
655 resource->set_remote_ip(info_.remote_address); 628 resource->set_remote_ip(item_->GetRemoteAddress());
656 } 629 }
657 } else { 630 } else {
658 resource->set_type(ClientDownloadRequest::DOWNLOAD_REDIRECT); 631 resource->set_type(ClientDownloadRequest::DOWNLOAD_REDIRECT);
659 } 632 }
660 // TODO(noelutz): fill out the remote IP addresses. 633 // TODO(noelutz): fill out the remote IP addresses.
661 } 634 }
662 request.set_user_initiated(info_.user_initiated); 635 request.set_user_initiated(item_->HasUserGesture());
663 request.set_file_basename(info_.target_file.BaseName().AsUTF8Unsafe()); 636 request.set_file_basename(
637 item_->GetTargetFilePath().BaseName().AsUTF8Unsafe());
664 request.set_download_type(type_); 638 request.set_download_type(type_);
665 request.mutable_signature()->CopyFrom(signature_info_); 639 request.mutable_signature()->CopyFrom(signature_info_);
666 std::string request_data; 640 std::string request_data;
667 if (!request.SerializeToString(&request_data)) { 641 if (!request.SerializeToString(&request_data)) {
668 RecordImprovedProtectionStats(REASON_INVALID_REQUEST_PROTO); 642 FinishRequest(SAFE, REASON_INVALID_REQUEST_PROTO);
669 FinishRequest(SAFE);
670 return; 643 return;
671 } 644 }
672 645
673 VLOG(2) << "Sending a request for URL: " 646 VLOG(2) << "Sending a request for URL: "
674 << info_.download_url_chain.back(); 647 << item_->GetUrlChain().back();
675 fetcher_.reset(net::URLFetcher::Create(0 /* ID used for testing */, 648 fetcher_.reset(net::URLFetcher::Create(0 /* ID used for testing */,
676 GURL(GetDownloadRequestUrl()), 649 GURL(GetDownloadRequestUrl()),
677 net::URLFetcher::POST, 650 net::URLFetcher::POST,
678 this)); 651 this));
679 fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE); 652 fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
680 fetcher_->SetAutomaticallyRetryOn5xx(false); // Don't retry on error. 653 fetcher_->SetAutomaticallyRetryOn5xx(false); // Don't retry on error.
681 fetcher_->SetRequestContext(service_->request_context_getter_.get()); 654 fetcher_->SetRequestContext(service_->request_context_getter_.get());
682 fetcher_->SetUploadData("application/octet-stream", request_data); 655 fetcher_->SetUploadData("application/octet-stream", request_data);
683 fetcher_->Start(); 656 fetcher_->Start();
684 } 657 }
685 658
686 void PostFinishTask(DownloadCheckResult result) { 659 void PostFinishTask(DownloadCheckResult result,
660 DownloadCheckResultReason reason) {
687 BrowserThread::PostTask( 661 BrowserThread::PostTask(
688 BrowserThread::UI, 662 BrowserThread::UI,
689 FROM_HERE, 663 FROM_HERE,
690 base::Bind(&CheckClientDownloadRequest::FinishRequest, this, result)); 664 base::Bind(&CheckClientDownloadRequest::FinishRequest, this, result,
665 reason));
691 } 666 }
692 667
693 void FinishRequest(DownloadCheckResult result) { 668 void FinishRequest(DownloadCheckResult result,
669 DownloadCheckResultReason reason) {
694 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 670 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
695 if (finished_) { 671 if (finished_) {
696 return; 672 return;
697 } 673 }
698 finished_ = true; 674 finished_ = true;
699 if (service_) { 675 if (service_) {
676 VLOG(2) << "SafeBrowsing download verdict for: "
677 << item_->DebugString(true) << " verdict:" << reason;
678 UMA_HISTOGRAM_ENUMERATION("SBClientDownload.CheckDownloadStats",
679 reason,
680 REASON_MAX);
700 callback_.Run(result); 681 callback_.Run(result);
682 item_->RemoveObserver(this);
683 item_ = NULL;
701 DownloadProtectionService* service = service_; 684 DownloadProtectionService* service = service_;
702 service_ = NULL; 685 service_ = NULL;
703 service->RequestFinished(this); 686 service->RequestFinished(this);
704 // DownloadProtectionService::RequestFinished will decrement our refcount, 687 // DownloadProtectionService::RequestFinished will decrement our refcount,
705 // so we may be deleted now. 688 // so we may be deleted now.
706 } else { 689 } else {
707 callback_.Run(SAFE); 690 callback_.Run(SAFE);
708 } 691 }
709 } 692 }
710 693
711 void RecordImprovedProtectionStats(DownloadCheckResultReason reason) {
712 VLOG(2) << "SafeBrowsing download verdict for: "
713 << info_.DebugString() << " verdict:" << reason;
714 UMA_HISTOGRAM_ENUMERATION("SBClientDownload.CheckDownloadStats",
715 reason,
716 REASON_MAX);
717 }
718
719 bool CertificateChainIsWhitelisted( 694 bool CertificateChainIsWhitelisted(
720 const ClientDownloadRequest_CertificateChain& chain) { 695 const ClientDownloadRequest_CertificateChain& chain) {
721 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 696 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
722 if (chain.element_size() < 2) { 697 if (chain.element_size() < 2) {
723 // We need to have both a signing certificate and its issuer certificate 698 // We need to have both a signing certificate and its issuer certificate
724 // present to construct a whitelist entry. 699 // present to construct a whitelist entry.
725 return false; 700 return false;
726 } 701 }
727 scoped_refptr<net::X509Certificate> cert = 702 scoped_refptr<net::X509Certificate> cert =
728 net::X509Certificate::CreateFromBytes( 703 net::X509Certificate::CreateFromBytes(
(...skipping 21 matching lines...) Expand all
750 << cert->subject().GetDisplayName() 725 << cert->subject().GetDisplayName()
751 << " issuer=" << issuer->subject().GetDisplayName(); 726 << " issuer=" << issuer->subject().GetDisplayName();
752 return true; 727 return true;
753 } 728 }
754 } 729 }
755 cert = issuer; 730 cert = issuer;
756 } 731 }
757 return false; 732 return false;
758 } 733 }
759 734
760 DownloadInfo info_; 735 // The DownloadItem we are checking. Will be NULL if the request has been
736 // canceled. Must be accessed only on UI thread.
737 content::DownloadItem* item_;
738 // Copies of data from |item_| for access on other threads.
739 std::vector<GURL> url_chain_;
740 GURL referrer_url_;
741
742 bool zipped_executable_;
761 ClientDownloadRequest_SignatureInfo signature_info_; 743 ClientDownloadRequest_SignatureInfo signature_info_;
762 CheckDownloadCallback callback_; 744 CheckDownloadCallback callback_;
763 // Will be NULL if the request has been canceled. 745 // Will be NULL if the request has been canceled.
764 DownloadProtectionService* service_; 746 DownloadProtectionService* service_;
765 scoped_refptr<SignatureUtil> signature_util_; 747 scoped_refptr<SignatureUtil> signature_util_;
766 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; 748 scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
767 const bool pingback_enabled_; 749 const bool pingback_enabled_;
768 scoped_ptr<net::URLFetcher> fetcher_; 750 scoped_ptr<net::URLFetcher> fetcher_;
769 scoped_refptr<SandboxedZipAnalyzer> analyzer_; 751 scoped_refptr<SandboxedZipAnalyzer> analyzer_;
770 base::TimeTicks zip_analysis_start_time_; 752 base::TimeTicks zip_analysis_start_time_;
(...skipping 29 matching lines...) Expand all
800 if (enabled == enabled_) { 782 if (enabled == enabled_) {
801 return; 783 return;
802 } 784 }
803 enabled_ = enabled; 785 enabled_ = enabled;
804 if (!enabled_) { 786 if (!enabled_) {
805 CancelPendingRequests(); 787 CancelPendingRequests();
806 } 788 }
807 } 789 }
808 790
809 void DownloadProtectionService::CheckClientDownload( 791 void DownloadProtectionService::CheckClientDownload(
810 const DownloadProtectionService::DownloadInfo& info, 792 content::DownloadItem* item,
811 const CheckDownloadCallback& callback) { 793 const CheckDownloadCallback& callback) {
812 scoped_refptr<CheckClientDownloadRequest> request( 794 scoped_refptr<CheckClientDownloadRequest> request(
813 new CheckClientDownloadRequest(info, callback, this, 795 new CheckClientDownloadRequest(item, callback, this,
814 database_manager_, signature_util_.get())); 796 database_manager_, signature_util_.get()));
815 download_requests_.insert(request); 797 download_requests_.insert(request);
816 request->Start(); 798 request->Start();
817 } 799 }
818 800
819 void DownloadProtectionService::CheckDownloadUrl( 801 void DownloadProtectionService::CheckDownloadUrl(
820 const DownloadProtectionService::DownloadInfo& info, 802 const content::DownloadItem& item,
821 const CheckDownloadCallback& callback) { 803 const CheckDownloadCallback& callback) {
822 DCHECK(!info.download_url_chain.empty()); 804 DCHECK(!item.GetUrlChain().empty());
823 scoped_refptr<DownloadUrlSBClient> client( 805 scoped_refptr<DownloadUrlSBClient> client(
824 new DownloadUrlSBClient(info, callback, ui_manager_, database_manager_)); 806 new DownloadUrlSBClient(item, callback, ui_manager_, database_manager_));
825 // The client will release itself once it is done. 807 // The client will release itself once it is done.
826 BrowserThread::PostTask( 808 BrowserThread::PostTask(
827 BrowserThread::IO, 809 BrowserThread::IO,
828 FROM_HERE, 810 FROM_HERE,
829 base::Bind(&DownloadUrlSBClient::StartCheck, client)); 811 base::Bind(&DownloadUrlSBClient::StartCheck, client));
830 } 812 }
831 813
832 bool DownloadProtectionService::IsSupportedDownload( 814 bool DownloadProtectionService::IsSupportedDownload(
833 const DownloadInfo& info) const { 815 const content::DownloadItem& item,
816 const base::FilePath& target_path) const {
834 // Currently, the UI only works on Windows. On Linux and Mac we still 817 // Currently, the UI only works on Windows. On Linux and Mac we still
835 // want to show the dangerous file type warning if the file is possibly 818 // want to show the dangerous file type warning if the file is possibly
836 // dangerous which means we have to always return false here. 819 // dangerous which means we have to always return false here.
837 #if defined(OS_WIN) 820 #if defined(OS_WIN)
838 DownloadCheckResultReason reason = REASON_MAX; 821 DownloadCheckResultReason reason = REASON_MAX;
839 ClientDownloadRequest::DownloadType type = 822 ClientDownloadRequest::DownloadType type =
840 ClientDownloadRequest::WIN_EXECUTABLE; 823 ClientDownloadRequest::WIN_EXECUTABLE;
841 return (CheckClientDownloadRequest::IsSupportedDownload(info, 824 return (CheckClientDownloadRequest::IsSupportedDownload(item, target_path,
842 &reason, 825 &reason, &type) &&
843 &type) &&
844 (ClientDownloadRequest::ANDROID_APK == type || 826 (ClientDownloadRequest::ANDROID_APK == type ||
845 ClientDownloadRequest::WIN_EXECUTABLE == type || 827 ClientDownloadRequest::WIN_EXECUTABLE == type ||
846 ClientDownloadRequest::ZIPPED_EXECUTABLE == type)); 828 ClientDownloadRequest::ZIPPED_EXECUTABLE == type));
847 #else 829 #else
848 return false; 830 return false;
849 #endif 831 #endif
850 } 832 }
851 833
852 void DownloadProtectionService::CancelPendingRequests() { 834 void DownloadProtectionService::CancelPendingRequests() {
853 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 835 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
(...skipping 11 matching lines...) Expand all
865 void DownloadProtectionService::RequestFinished( 847 void DownloadProtectionService::RequestFinished(
866 CheckClientDownloadRequest* request) { 848 CheckClientDownloadRequest* request) {
867 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 849 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
868 std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = 850 std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it =
869 download_requests_.find(request); 851 download_requests_.find(request);
870 DCHECK(it != download_requests_.end()); 852 DCHECK(it != download_requests_.end());
871 download_requests_.erase(*it); 853 download_requests_.erase(*it);
872 } 854 }
873 855
874 void DownloadProtectionService::ShowDetailsForDownload( 856 void DownloadProtectionService::ShowDetailsForDownload(
875 const DownloadProtectionService::DownloadInfo& info, 857 const content::DownloadItem& item,
876 content::PageNavigator* navigator) { 858 content::PageNavigator* navigator) {
877 navigator->OpenURL( 859 navigator->OpenURL(
878 content::OpenURLParams(GURL(chrome::kDownloadScanningLearnMoreURL), 860 content::OpenURLParams(GURL(chrome::kDownloadScanningLearnMoreURL),
879 content::Referrer(), 861 content::Referrer(),
880 NEW_FOREGROUND_TAB, 862 NEW_FOREGROUND_TAB,
881 content::PAGE_TRANSITION_LINK, 863 content::PAGE_TRANSITION_LINK,
882 false)); 864 false));
883 } 865 }
884 866
885 namespace { 867 namespace {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
962 std::string url = kDownloadRequestUrl; 944 std::string url = kDownloadRequestUrl;
963 std::string api_key = google_apis::GetAPIKey(); 945 std::string api_key = google_apis::GetAPIKey();
964 if (!api_key.empty()) { 946 if (!api_key.empty()) {
965 base::StringAppendF(&url, "?key=%s", 947 base::StringAppendF(&url, "?key=%s",
966 net::EscapeQueryParamValue(api_key, true).c_str()); 948 net::EscapeQueryParamValue(api_key, true).c_str());
967 } 949 }
968 return url; 950 return url;
969 } 951 }
970 952
971 } // namespace safe_browsing 953 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698