| OLD | NEW |
| 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/local_database_manager.h" | 5 #include "chrome/browser/safe_browsing/local_database_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 12 #include "base/callback.h" | 12 #include "base/callback.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/debug/leak_tracker.h" | 14 #include "base/debug/leak_tracker.h" |
| 15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/memory/ptr_util.h" |
| 16 #include "base/metrics/histogram_macros.h" | 17 #include "base/metrics/histogram_macros.h" |
| 17 #include "base/single_thread_task_runner.h" | 18 #include "base/single_thread_task_runner.h" |
| 18 #include "base/stl_util.h" | |
| 19 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
| 20 #include "base/threading/thread_task_runner_handle.h" | 20 #include "base/threading/thread_task_runner_handle.h" |
| 21 #include "chrome/browser/browser_process.h" | 21 #include "chrome/browser/browser_process.h" |
| 22 #include "chrome/browser/chrome_notification_types.h" | 22 #include "chrome/browser/chrome_notification_types.h" |
| 23 #include "chrome/browser/prerender/prerender_field_trial.h" | 23 #include "chrome/browser/prerender/prerender_field_trial.h" |
| 24 #include "chrome/browser/profiles/profile_manager.h" | 24 #include "chrome/browser/profiles/profile_manager.h" |
| 25 #include "chrome/browser/safe_browsing/client_side_detection_service.h" | 25 #include "chrome/browser/safe_browsing/client_side_detection_service.h" |
| 26 #include "chrome/browser/safe_browsing/download_protection_service.h" | 26 #include "chrome/browser/safe_browsing/download_protection_service.h" |
| 27 #include "chrome/browser/safe_browsing/protocol_manager.h" | 27 #include "chrome/browser/safe_browsing/protocol_manager.h" |
| 28 #include "chrome/browser/safe_browsing/safe_browsing_database.h" | 28 #include "chrome/browser/safe_browsing/safe_browsing_database.h" |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 | 342 |
| 343 bool LocalSafeBrowsingDatabaseManager::CheckDownloadUrl( | 343 bool LocalSafeBrowsingDatabaseManager::CheckDownloadUrl( |
| 344 const std::vector<GURL>& url_chain, | 344 const std::vector<GURL>& url_chain, |
| 345 Client* client) { | 345 Client* client) { |
| 346 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 346 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 347 if (!enabled_ || !enable_download_protection_) | 347 if (!enabled_ || !enable_download_protection_) |
| 348 return true; | 348 return true; |
| 349 | 349 |
| 350 // We need to check the database for url prefix, and later may fetch the url | 350 // We need to check the database for url prefix, and later may fetch the url |
| 351 // from the safebrowsing backends. These need to be asynchronous. | 351 // from the safebrowsing backends. These need to be asynchronous. |
| 352 SafeBrowsingCheck* check = new SafeBrowsingCheck( | 352 std::unique_ptr<SafeBrowsingCheck> check = |
| 353 url_chain, std::vector<SBFullHash>(), client, BINURL, | 353 base::MakeUnique<SafeBrowsingCheck>( |
| 354 std::vector<SBThreatType>(1, SB_THREAT_TYPE_BINARY_MALWARE_URL)); | 354 url_chain, std::vector<SBFullHash>(), client, BINURL, |
| 355 std::vector<SBThreatType>(1, SB_THREAT_TYPE_BINARY_MALWARE_URL)); |
| 355 std::vector<SBPrefix> prefixes; | 356 std::vector<SBPrefix> prefixes; |
| 356 SafeBrowsingDatabase::GetDownloadUrlPrefixes(url_chain, &prefixes); | 357 SafeBrowsingDatabase::GetDownloadUrlPrefixes(url_chain, &prefixes); |
| 357 StartSafeBrowsingCheck( | 358 StartSafeBrowsingCheck( |
| 358 check, | 359 std::move(check), |
| 359 base::Bind(&LocalSafeBrowsingDatabaseManager::CheckDownloadUrlOnSBThread, | 360 base::Bind(&LocalSafeBrowsingDatabaseManager::CheckDownloadUrlOnSBThread, |
| 360 this, prefixes)); | 361 this, prefixes)); |
| 361 return false; | 362 return false; |
| 362 } | 363 } |
| 363 | 364 |
| 364 bool LocalSafeBrowsingDatabaseManager::CheckExtensionIDs( | 365 bool LocalSafeBrowsingDatabaseManager::CheckExtensionIDs( |
| 365 const std::set<std::string>& extension_ids, | 366 const std::set<std::string>& extension_ids, |
| 366 Client* client) { | 367 Client* client) { |
| 367 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 368 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 368 | 369 |
| 369 if (!enabled_ || !enable_extension_blacklist_) | 370 if (!enabled_ || !enable_extension_blacklist_) |
| 370 return true; | 371 return true; |
| 371 | 372 |
| 372 std::vector<SBFullHash> extension_id_hashes; | 373 std::vector<SBFullHash> extension_id_hashes; |
| 373 std::transform(extension_ids.begin(), extension_ids.end(), | 374 std::transform(extension_ids.begin(), extension_ids.end(), |
| 374 std::back_inserter(extension_id_hashes), StringToSBFullHash); | 375 std::back_inserter(extension_id_hashes), StringToSBFullHash); |
| 375 std::vector<SBPrefix> prefixes; | 376 std::vector<SBPrefix> prefixes; |
| 376 for (const SBFullHash& hash : extension_id_hashes) | 377 for (const SBFullHash& hash : extension_id_hashes) |
| 377 prefixes.push_back(hash.prefix); | 378 prefixes.push_back(hash.prefix); |
| 378 | 379 |
| 379 SafeBrowsingCheck* check = new SafeBrowsingCheck( | 380 std::unique_ptr<SafeBrowsingCheck> check = |
| 380 std::vector<GURL>(), extension_id_hashes, client, EXTENSIONBLACKLIST, | 381 base::MakeUnique<SafeBrowsingCheck>( |
| 381 std::vector<SBThreatType>(1, SB_THREAT_TYPE_EXTENSION)); | 382 std::vector<GURL>(), extension_id_hashes, client, EXTENSIONBLACKLIST, |
| 383 std::vector<SBThreatType>(1, SB_THREAT_TYPE_EXTENSION)); |
| 382 StartSafeBrowsingCheck( | 384 StartSafeBrowsingCheck( |
| 383 check, | 385 std::move(check), |
| 384 base::Bind(&LocalSafeBrowsingDatabaseManager::CheckExtensionIDsOnSBThread, | 386 base::Bind(&LocalSafeBrowsingDatabaseManager::CheckExtensionIDsOnSBThread, |
| 385 this, prefixes)); | 387 this, prefixes)); |
| 386 return false; | 388 return false; |
| 387 } | 389 } |
| 388 | 390 |
| 389 bool LocalSafeBrowsingDatabaseManager::CheckResourceUrl(const GURL& url, | 391 bool LocalSafeBrowsingDatabaseManager::CheckResourceUrl(const GURL& url, |
| 390 Client* client) { | 392 Client* client) { |
| 391 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 393 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 392 | 394 |
| 393 if (!enabled_ || !CanCheckUrl(url)) | 395 if (!enabled_ || !CanCheckUrl(url)) |
| 394 return true; | 396 return true; |
| 395 | 397 |
| 396 std::vector<SBThreatType> expected_threats = { | 398 std::vector<SBThreatType> expected_threats = { |
| 397 SB_THREAT_TYPE_BLACKLISTED_RESOURCE}; | 399 SB_THREAT_TYPE_BLACKLISTED_RESOURCE}; |
| 398 | 400 |
| 399 if (!MakeDatabaseAvailable()) { | 401 if (!MakeDatabaseAvailable()) { |
| 400 QueuedCheck queued_check(RESOURCEBLACKLIST, client, url, expected_threats, | 402 QueuedCheck queued_check(RESOURCEBLACKLIST, client, url, expected_threats, |
| 401 base::TimeTicks::Now()); | 403 base::TimeTicks::Now()); |
| 402 queued_checks_.push_back(queued_check); | 404 queued_checks_.push_back(queued_check); |
| 403 return false; | 405 return false; |
| 404 } | 406 } |
| 405 | 407 |
| 406 SafeBrowsingCheck* check = | 408 std::unique_ptr<SafeBrowsingCheck> check = base::WrapUnique( |
| 407 new SafeBrowsingCheck({url}, std::vector<SBFullHash>(), client, | 409 new SafeBrowsingCheck({url}, std::vector<SBFullHash>(), client, |
| 408 RESOURCEBLACKLIST, expected_threats); | 410 RESOURCEBLACKLIST, expected_threats)); |
| 409 | 411 |
| 410 std::vector<SBPrefix> prefixes; | 412 std::vector<SBPrefix> prefixes; |
| 411 SafeBrowsingDatabase::GetDownloadUrlPrefixes(check->urls, &prefixes); | 413 SafeBrowsingDatabase::GetDownloadUrlPrefixes(check->urls, &prefixes); |
| 412 StartSafeBrowsingCheck( | 414 StartSafeBrowsingCheck( |
| 413 check, | 415 std::move(check), |
| 414 base::Bind(&LocalSafeBrowsingDatabaseManager::CheckResourceUrlOnSBThread, | 416 base::Bind(&LocalSafeBrowsingDatabaseManager::CheckResourceUrlOnSBThread, |
| 415 this, prefixes)); | 417 this, prefixes)); |
| 416 return false; | 418 return false; |
| 417 } | 419 } |
| 418 | 420 |
| 419 bool LocalSafeBrowsingDatabaseManager::MatchMalwareIP( | 421 bool LocalSafeBrowsingDatabaseManager::MatchMalwareIP( |
| 420 const std::string& ip_address) { | 422 const std::string& ip_address) { |
| 421 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 423 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 422 if (!enabled_ || !enable_ip_blacklist_ || !MakeDatabaseAvailable()) { | 424 if (!enabled_ || !enable_ip_blacklist_ || !MakeDatabaseAvailable()) { |
| 423 return false; // Fail open. | 425 return false; // Fail open. |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 540 // This check will ping the Safe Browsing servers and get all lists which it | 542 // This check will ping the Safe Browsing servers and get all lists which it |
| 541 // matches. These lists will then be filtered against the |expected_threats| | 543 // matches. These lists will then be filtered against the |expected_threats| |
| 542 // and the result callback for MALWARE (which is the same as for PHISH and | 544 // and the result callback for MALWARE (which is the same as for PHISH and |
| 543 // UNWANTEDURL) will eventually be invoked with the final decision. | 545 // UNWANTEDURL) will eventually be invoked with the final decision. |
| 544 SafeBrowsingCheck* check = new SafeBrowsingCheck( | 546 SafeBrowsingCheck* check = new SafeBrowsingCheck( |
| 545 std::vector<GURL>(1, url), std::vector<SBFullHash>(), client, MALWARE, | 547 std::vector<GURL>(1, url), std::vector<SBFullHash>(), client, MALWARE, |
| 546 expected_threats); | 548 expected_threats); |
| 547 check->need_get_hash = cache_hits.empty(); | 549 check->need_get_hash = cache_hits.empty(); |
| 548 check->prefix_hits.swap(prefix_hits); | 550 check->prefix_hits.swap(prefix_hits); |
| 549 check->cache_hits.swap(cache_hits); | 551 check->cache_hits.swap(cache_hits); |
| 550 checks_.insert(check); | 552 checks_[check] = base::WrapUnique(check); |
| 551 | 553 |
| 552 BrowserThread::PostTask( | 554 BrowserThread::PostTask( |
| 553 BrowserThread::IO, FROM_HERE, | 555 BrowserThread::IO, FROM_HERE, |
| 554 base::Bind(&LocalSafeBrowsingDatabaseManager::OnCheckDone, this, check)); | 556 base::Bind(&LocalSafeBrowsingDatabaseManager::OnCheckDone, this, check)); |
| 555 | 557 |
| 556 return false; | 558 return false; |
| 557 } | 559 } |
| 558 | 560 |
| 559 void LocalSafeBrowsingDatabaseManager::CancelCheck(Client* client) { | 561 void LocalSafeBrowsingDatabaseManager::CancelCheck(Client* client) { |
| 560 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 562 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 561 for (CurrentChecks::iterator i = checks_.begin(); i != checks_.end(); ++i) { | 563 for (const auto& check : checks_) { |
| 562 // We can't delete matching checks here because the db thread has a copy of | 564 // We can't delete matching checks here because the db thread has a copy of |
| 563 // the pointer. Instead, we simply NULL out the client, and when the db | 565 // the pointer. Instead, we simply NULL out the client, and when the db |
| 564 // thread calls us back, we'll clean up the check. | 566 // thread calls us back, we'll clean up the check. |
| 565 if ((*i)->client == client) | 567 if (check.first->client == client) |
| 566 (*i)->client = NULL; | 568 check.first->client = NULL; |
| 567 } | 569 } |
| 568 | 570 |
| 569 // Scan the queued clients store. Clients may be here if they requested a URL | 571 // Scan the queued clients store. Clients may be here if they requested a URL |
| 570 // check before the database has finished loading. | 572 // check before the database has finished loading. |
| 571 for (std::deque<QueuedCheck>::iterator it(queued_checks_.begin()); | 573 for (auto it = queued_checks_.begin(); it != queued_checks_.end();) { |
| 572 it != queued_checks_.end();) { | |
| 573 // In this case it's safe to delete matches entirely since nothing has a | 574 // In this case it's safe to delete matches entirely since nothing has a |
| 574 // pointer to them. | 575 // pointer to them. |
| 575 if (it->client == client) | 576 if (it->client == client) |
| 576 it = queued_checks_.erase(it); | 577 it = queued_checks_.erase(it); |
| 577 else | 578 else |
| 578 ++it; | 579 ++it; |
| 579 } | 580 } |
| 580 } | 581 } |
| 581 | 582 |
| 582 void LocalSafeBrowsingDatabaseManager::HandleGetHashResults( | 583 void LocalSafeBrowsingDatabaseManager::HandleGetHashResults( |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 closing_database_ = true; | 762 closing_database_ = true; |
| 762 safe_browsing_task_runner_->PostTask( | 763 safe_browsing_task_runner_->PostTask( |
| 763 FROM_HERE, | 764 FROM_HERE, |
| 764 base::Bind(&LocalSafeBrowsingDatabaseManager::OnCloseDatabase, this)); | 765 base::Bind(&LocalSafeBrowsingDatabaseManager::OnCloseDatabase, this)); |
| 765 } | 766 } |
| 766 | 767 |
| 767 // Delete pending checks, calling back any clients with 'SB_THREAT_TYPE_SAFE'. | 768 // Delete pending checks, calling back any clients with 'SB_THREAT_TYPE_SAFE'. |
| 768 // We have to do this after the db thread returns because methods on it can | 769 // We have to do this after the db thread returns because methods on it can |
| 769 // have copies of these pointers, so deleting them might lead to accessing | 770 // have copies of these pointers, so deleting them might lead to accessing |
| 770 // garbage. | 771 // garbage. |
| 771 for (CurrentChecks::iterator it = checks_.begin(); it != checks_.end(); | 772 for (const auto& check : checks_) { |
| 772 ++it) { | 773 if (check.first->client) |
| 773 SafeBrowsingCheck* check = *it; | 774 check.first->OnSafeBrowsingResult(); |
| 774 if (check->client) | |
| 775 check->OnSafeBrowsingResult(); | |
| 776 } | 775 } |
| 777 base::STLDeleteElements(&checks_); | |
| 778 | 776 |
| 777 checks_.clear(); |
| 779 gethash_requests_.clear(); | 778 gethash_requests_.clear(); |
| 780 } | 779 } |
| 781 | 780 |
| 782 bool LocalSafeBrowsingDatabaseManager::DatabaseAvailable() const { | 781 bool LocalSafeBrowsingDatabaseManager::DatabaseAvailable() const { |
| 783 base::AutoLock lock(database_lock_); | 782 base::AutoLock lock(database_lock_); |
| 784 return !closing_database_ && (database_ != NULL); | 783 return !closing_database_ && (database_ != NULL); |
| 785 } | 784 } |
| 786 | 785 |
| 787 bool LocalSafeBrowsingDatabaseManager::MakeDatabaseAvailable() { | 786 bool LocalSafeBrowsingDatabaseManager::MakeDatabaseAvailable() { |
| 788 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 787 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1213 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1212 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1214 DCHECK(check); | 1213 DCHECK(check); |
| 1215 | 1214 |
| 1216 if (!enabled_) | 1215 if (!enabled_) |
| 1217 return; | 1216 return; |
| 1218 | 1217 |
| 1219 DCHECK(checks_.find(check) != checks_.end()); | 1218 DCHECK(checks_.find(check) != checks_.end()); |
| 1220 if (check->client) | 1219 if (check->client) |
| 1221 check->OnSafeBrowsingResult(); | 1220 check->OnSafeBrowsingResult(); |
| 1222 checks_.erase(check); | 1221 checks_.erase(check); |
| 1223 delete check; | |
| 1224 } | 1222 } |
| 1225 | 1223 |
| 1226 void LocalSafeBrowsingDatabaseManager::StartSafeBrowsingCheck( | 1224 void LocalSafeBrowsingDatabaseManager::StartSafeBrowsingCheck( |
| 1227 SafeBrowsingCheck* check, | 1225 std::unique_ptr<SafeBrowsingCheck> check, |
| 1228 const base::Callback<std::vector<SBPrefix>(void)>& task) { | 1226 const base::Callback<std::vector<SBPrefix>(void)>& task) { |
| 1229 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1227 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1230 check->weak_ptr_factory_.reset( | 1228 check->weak_ptr_factory_.reset( |
| 1231 new base::WeakPtrFactory<LocalSafeBrowsingDatabaseManager>(this)); | 1229 new base::WeakPtrFactory<LocalSafeBrowsingDatabaseManager>(this)); |
| 1232 checks_.insert(check); | 1230 SafeBrowsingCheck* check_ptr = check.get(); |
| 1231 checks_[check_ptr] = std::move(check); |
| 1233 | 1232 |
| 1234 base::PostTaskAndReplyWithResult( | 1233 base::PostTaskAndReplyWithResult( |
| 1235 safe_browsing_task_runner_.get(), FROM_HERE, task, | 1234 safe_browsing_task_runner_.get(), FROM_HERE, task, |
| 1236 base::Bind(&LocalSafeBrowsingDatabaseManager::OnAsyncCheckDone, | 1235 base::Bind(&LocalSafeBrowsingDatabaseManager::OnAsyncCheckDone, |
| 1237 check->weak_ptr_factory_->GetWeakPtr(), check)); | 1236 check_ptr->weak_ptr_factory_->GetWeakPtr(), check_ptr)); |
| 1238 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 1237 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 1239 FROM_HERE, base::Bind(&LocalSafeBrowsingDatabaseManager::TimeoutCallback, | 1238 FROM_HERE, |
| 1240 check->weak_ptr_factory_->GetWeakPtr(), check), | 1239 base::Bind(&LocalSafeBrowsingDatabaseManager::TimeoutCallback, |
| 1240 check_ptr->weak_ptr_factory_->GetWeakPtr(), check_ptr), |
| 1241 check_timeout_); | 1241 check_timeout_); |
| 1242 } | 1242 } |
| 1243 | 1243 |
| 1244 bool LocalSafeBrowsingDatabaseManager::IsDownloadProtectionEnabled() const { | 1244 bool LocalSafeBrowsingDatabaseManager::IsDownloadProtectionEnabled() const { |
| 1245 return enable_download_protection_; | 1245 return enable_download_protection_; |
| 1246 } | 1246 } |
| 1247 | 1247 |
| 1248 } // namespace safe_browsing | 1248 } // namespace safe_browsing |
| OLD | NEW |