| 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/safe_browsing_database.h" | 5 #include "chrome/browser/safe_browsing/safe_browsing_database.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 // This method is theoretically thread-safe but document that it is currently | 689 // This method is theoretically thread-safe but document that it is currently |
| 690 // only expected to be called on the IO thread. | 690 // only expected to be called on the IO thread. |
| 691 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 691 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 692 | 692 |
| 693 return PrefixSetContainsUrl( | 693 return PrefixSetContainsUrl( |
| 694 url, &unwanted_software_prefix_set_, prefix_hits, cache_hits); | 694 url, &unwanted_software_prefix_set_, prefix_hits, cache_hits); |
| 695 } | 695 } |
| 696 | 696 |
| 697 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl( | 697 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl( |
| 698 const GURL& url, | 698 const GURL& url, |
| 699 scoped_ptr<safe_browsing::PrefixSet>* prefix_set_getter, | 699 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, |
| 700 std::vector<SBPrefix>* prefix_hits, | 700 std::vector<SBPrefix>* prefix_hits, |
| 701 std::vector<SBFullHashResult>* cache_hits) { | 701 std::vector<SBFullHashResult>* cache_hits) { |
| 702 // This method is theoretically thread-safe but document that it is currently | 702 // This method is theoretically thread-safe but document that it is currently |
| 703 // only expected to be called on the IO thread. | 703 // only expected to be called on the IO thread. |
| 704 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 704 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 705 | 705 |
| 706 // Clear the results first. | 706 // Clear the results first. |
| 707 prefix_hits->clear(); | 707 prefix_hits->clear(); |
| 708 cache_hits->clear(); | 708 cache_hits->clear(); |
| 709 | 709 |
| 710 std::vector<SBFullHash> full_hashes; | 710 std::vector<SBFullHash> full_hashes; |
| 711 UrlToFullHashes(url, false, &full_hashes); | 711 UrlToFullHashes(url, false, &full_hashes); |
| 712 if (full_hashes.empty()) | 712 if (full_hashes.empty()) |
| 713 return false; | 713 return false; |
| 714 | 714 |
| 715 return PrefixSetContainsUrlHashes( | 715 return PrefixSetContainsUrlHashes( |
| 716 full_hashes, prefix_set_getter, prefix_hits, cache_hits); | 716 full_hashes, prefix_set_getter, prefix_hits, cache_hits); |
| 717 } | 717 } |
| 718 | 718 |
| 719 bool SafeBrowsingDatabaseNew::ContainsBrowseUrlHashesForTesting( | 719 bool SafeBrowsingDatabaseNew::ContainsBrowseUrlHashesForTesting( |
| 720 const std::vector<SBFullHash>& full_hashes, | 720 const std::vector<SBFullHash>& full_hashes, |
| 721 std::vector<SBPrefix>* prefix_hits, | 721 std::vector<SBPrefix>* prefix_hits, |
| 722 std::vector<SBFullHashResult>* cache_hits) { | 722 std::vector<SBFullHashResult>* cache_hits) { |
| 723 return PrefixSetContainsUrlHashes( | 723 return PrefixSetContainsUrlHashes( |
| 724 full_hashes, &browse_prefix_set_, prefix_hits, cache_hits); | 724 full_hashes, &browse_prefix_set_, prefix_hits, cache_hits); |
| 725 } | 725 } |
| 726 | 726 |
| 727 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes( | 727 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes( |
| 728 const std::vector<SBFullHash>& full_hashes, | 728 const std::vector<SBFullHash>& full_hashes, |
| 729 scoped_ptr<safe_browsing::PrefixSet>* prefix_set_getter, | 729 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, |
| 730 std::vector<SBPrefix>* prefix_hits, | 730 std::vector<SBPrefix>* prefix_hits, |
| 731 std::vector<SBFullHashResult>* cache_hits) { | 731 std::vector<SBFullHashResult>* cache_hits) { |
| 732 // This method is theoretically thread-safe but document that it is currently | 732 // This method is theoretically thread-safe but document that it is currently |
| 733 // only expected to be called on the IO thread. | 733 // only expected to be called on the IO thread. |
| 734 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 734 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 735 | 735 |
| 736 // Used to determine cache expiration. | 736 // Used to determine cache expiration. |
| 737 const base::Time now = base::Time::Now(); | 737 const base::Time now = base::Time::Now(); |
| 738 | 738 |
| 739 base::AutoLock locked(lookup_lock_); | 739 base::AutoLock locked(lookup_lock_); |
| 740 | 740 |
| 741 // |prefix_set| is empty until it is either read from disk, or the first | 741 // |prefix_set| is empty until it is either read from disk, or the first |
| 742 // update populates it. Bail out without a hit if not yet available. | 742 // update populates it. Bail out without a hit if not yet available. |
| 743 // |prefix_set_getter| can only be accessed while holding |lookup_lock_| hence | 743 // |prefix_set_getter| can only be accessed while holding |lookup_lock_| hence |
| 744 // why it is passed as a parameter rather than passing the |prefix_set| | 744 // why it is passed as a parameter rather than passing the |prefix_set| |
| 745 // directly. | 745 // directly. |
| 746 safe_browsing::PrefixSet* prefix_set = prefix_set_getter->get(); | 746 const safe_browsing::PrefixSet* prefix_set = prefix_set_getter->get(); |
| 747 if (!prefix_set) | 747 if (!prefix_set) |
| 748 return false; | 748 return false; |
| 749 | 749 |
| 750 for (size_t i = 0; i < full_hashes.size(); ++i) { | 750 for (size_t i = 0; i < full_hashes.size(); ++i) { |
| 751 if (!GetCachedFullHash( | 751 if (!GetCachedFullHash( |
| 752 &prefix_gethash_cache_, full_hashes[i], now, cache_hits)) { | 752 &prefix_gethash_cache_, full_hashes[i], now, cache_hits)) { |
| 753 // No valid cached result, check the database. | 753 // No valid cached result, check the database. |
| 754 if (prefix_set->Exists(full_hashes[i])) | 754 if (prefix_set->Exists(full_hashes[i])) |
| 755 prefix_hits->push_back(full_hashes[i].prefix); | 755 prefix_hits->push_back(full_hashes[i].prefix); |
| 756 } | 756 } |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1323 #if defined(OS_MACOSX) | 1323 #if defined(OS_MACOSX) |
| 1324 base::mac::SetFileBackupExclusion(store_filename); | 1324 base::mac::SetFileBackupExclusion(store_filename); |
| 1325 #endif | 1325 #endif |
| 1326 | 1326 |
| 1327 return GetFileSizeOrZero(store_filename); | 1327 return GetFileSizeOrZero(store_filename); |
| 1328 } | 1328 } |
| 1329 | 1329 |
| 1330 void SafeBrowsingDatabaseNew::UpdatePrefixSetUrlStore( | 1330 void SafeBrowsingDatabaseNew::UpdatePrefixSetUrlStore( |
| 1331 const base::FilePath& db_filename, | 1331 const base::FilePath& db_filename, |
| 1332 SafeBrowsingStore* url_store, | 1332 SafeBrowsingStore* url_store, |
| 1333 scoped_ptr<safe_browsing::PrefixSet>* prefix_set, | 1333 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, |
| 1334 FailureType finish_failure_type, | 1334 FailureType finish_failure_type, |
| 1335 FailureType write_failure_type) { | 1335 FailureType write_failure_type) { |
| 1336 DCHECK(thread_checker_.CalledOnValidThread()); | 1336 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1337 | 1337 |
| 1338 // Measure the amount of IO during the filter build. | 1338 // Measure the amount of IO during the filter build. |
| 1339 base::IoCounters io_before, io_after; | 1339 base::IoCounters io_before, io_after; |
| 1340 base::ProcessHandle handle = base::GetCurrentProcessHandle(); | 1340 base::ProcessHandle handle = base::GetCurrentProcessHandle(); |
| 1341 scoped_ptr<base::ProcessMetrics> metric( | 1341 scoped_ptr<base::ProcessMetrics> metric( |
| 1342 #if !defined(OS_MACOSX) | 1342 #if !defined(OS_MACOSX) |
| 1343 base::ProcessMetrics::CreateProcessMetrics(handle) | 1343 base::ProcessMetrics::CreateProcessMetrics(handle) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1362 if (!url_store->FinishUpdate(&builder, &add_full_hashes)) { | 1362 if (!url_store->FinishUpdate(&builder, &add_full_hashes)) { |
| 1363 RecordFailure(finish_failure_type); | 1363 RecordFailure(finish_failure_type); |
| 1364 return; | 1364 return; |
| 1365 } | 1365 } |
| 1366 | 1366 |
| 1367 std::vector<SBFullHash> full_hash_results; | 1367 std::vector<SBFullHash> full_hash_results; |
| 1368 for (size_t i = 0; i < add_full_hashes.size(); ++i) { | 1368 for (size_t i = 0; i < add_full_hashes.size(); ++i) { |
| 1369 full_hash_results.push_back(add_full_hashes[i].full_hash); | 1369 full_hash_results.push_back(add_full_hashes[i].full_hash); |
| 1370 } | 1370 } |
| 1371 | 1371 |
| 1372 scoped_ptr<safe_browsing::PrefixSet> new_prefix_set( | 1372 scoped_ptr<const safe_browsing::PrefixSet> new_prefix_set( |
| 1373 builder.GetPrefixSet(full_hash_results)); | 1373 builder.GetPrefixSet(full_hash_results)); |
| 1374 | 1374 |
| 1375 // Swap in the newly built filter. | 1375 // Swap in the newly built filter. |
| 1376 { | 1376 { |
| 1377 base::AutoLock locked(lookup_lock_); | 1377 base::AutoLock locked(lookup_lock_); |
| 1378 prefix_set->swap(new_prefix_set); | 1378 prefix_set->swap(new_prefix_set); |
| 1379 } | 1379 } |
| 1380 | 1380 |
| 1381 UMA_HISTOGRAM_LONG_TIMES("SB2.BuildFilter", base::TimeTicks::Now() - before); | 1381 UMA_HISTOGRAM_LONG_TIMES("SB2.BuildFilter", base::TimeTicks::Now() - before); |
| 1382 | 1382 |
| 1383 // Persist the prefix set to disk. Note: there is no need to lock since the | 1383 // Persist the prefix set to disk. Note: there is no need to lock since the |
| 1384 // only write to |*prefix_set| is on this thread (in the swap() above). | 1384 // only write to |*prefix_set| is on this thread (in the swap() above). |
| 1385 // TODO(gab): Strengthen this requirement by design (const pointers) rather | |
| 1386 // than assumptions. | |
| 1387 WritePrefixSet(db_filename, prefix_set->get(), write_failure_type); | 1385 WritePrefixSet(db_filename, prefix_set->get(), write_failure_type); |
| 1388 | 1386 |
| 1389 // Gather statistics. | 1387 // Gather statistics. |
| 1390 if (got_counters && metric->GetIOCounters(&io_after)) { | 1388 if (got_counters && metric->GetIOCounters(&io_after)) { |
| 1391 UMA_HISTOGRAM_COUNTS("SB2.BuildReadKilobytes", | 1389 UMA_HISTOGRAM_COUNTS("SB2.BuildReadKilobytes", |
| 1392 static_cast<int>(io_after.ReadTransferCount - | 1390 static_cast<int>(io_after.ReadTransferCount - |
| 1393 io_before.ReadTransferCount) / 1024); | 1391 io_before.ReadTransferCount) / 1024); |
| 1394 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteKilobytes", | 1392 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteKilobytes", |
| 1395 static_cast<int>(io_after.WriteTransferCount - | 1393 static_cast<int>(io_after.WriteTransferCount - |
| 1396 io_before.WriteTransferCount) / 1024); | 1394 io_before.WriteTransferCount) / 1024); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1415 DCHECK(thread_checker_.CalledOnValidThread()); | 1413 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1416 | 1414 |
| 1417 safe_browsing::PrefixSetBuilder builder; | 1415 safe_browsing::PrefixSetBuilder builder; |
| 1418 std::vector<SBAddFullHash> add_full_hashes_result; | 1416 std::vector<SBAddFullHash> add_full_hashes_result; |
| 1419 | 1417 |
| 1420 if (!side_effect_free_whitelist_store_->FinishUpdate( | 1418 if (!side_effect_free_whitelist_store_->FinishUpdate( |
| 1421 &builder, &add_full_hashes_result)) { | 1419 &builder, &add_full_hashes_result)) { |
| 1422 RecordFailure(FAILURE_SIDE_EFFECT_FREE_WHITELIST_UPDATE_FINISH); | 1420 RecordFailure(FAILURE_SIDE_EFFECT_FREE_WHITELIST_UPDATE_FINISH); |
| 1423 return; | 1421 return; |
| 1424 } | 1422 } |
| 1425 scoped_ptr<safe_browsing::PrefixSet> | 1423 scoped_ptr<const safe_browsing::PrefixSet> new_prefix_set( |
| 1426 prefix_set(builder.GetPrefixSetNoHashes()); | 1424 builder.GetPrefixSetNoHashes()); |
| 1427 | 1425 |
| 1428 // Swap in the newly built prefix set. | 1426 // Swap in the newly built prefix set. |
| 1429 { | 1427 { |
| 1430 base::AutoLock locked(lookup_lock_); | 1428 base::AutoLock locked(lookup_lock_); |
| 1431 side_effect_free_whitelist_prefix_set_.swap(prefix_set); | 1429 side_effect_free_whitelist_prefix_set_.swap(new_prefix_set); |
| 1432 } | 1430 } |
| 1433 | 1431 |
| 1434 const base::FilePath side_effect_free_whitelist_filename = | 1432 const base::FilePath side_effect_free_whitelist_filename = |
| 1435 SideEffectFreeWhitelistDBFilename(filename_base_); | 1433 SideEffectFreeWhitelistDBFilename(filename_base_); |
| 1436 const base::FilePath side_effect_free_whitelist_prefix_set_filename = | 1434 const base::FilePath side_effect_free_whitelist_prefix_set_filename = |
| 1437 PrefixSetForFilename(side_effect_free_whitelist_filename); | 1435 PrefixSetForFilename(side_effect_free_whitelist_filename); |
| 1438 const base::TimeTicks before = base::TimeTicks::Now(); | 1436 const base::TimeTicks before = base::TimeTicks::Now(); |
| 1439 const bool write_ok = side_effect_free_whitelist_prefix_set_->WriteFile( | 1437 const bool write_ok = side_effect_free_whitelist_prefix_set_->WriteFile( |
| 1440 side_effect_free_whitelist_prefix_set_filename); | 1438 side_effect_free_whitelist_prefix_set_filename); |
| 1441 UMA_HISTOGRAM_TIMES("SB2.SideEffectFreePrefixSetWrite", | 1439 UMA_HISTOGRAM_TIMES("SB2.SideEffectFreePrefixSetWrite", |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1504 // only happen once. If you are here because you are hitting this after a | 1502 // only happen once. If you are here because you are hitting this after a |
| 1505 // restart, then I would be very interested in working with you to figure out | 1503 // restart, then I would be very interested in working with you to figure out |
| 1506 // what is happening, since it may affect real users. | 1504 // what is happening, since it may affect real users. |
| 1507 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; | 1505 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; |
| 1508 } | 1506 } |
| 1509 | 1507 |
| 1510 // TODO(shess): I'm not clear why this code doesn't have any | 1508 // TODO(shess): I'm not clear why this code doesn't have any |
| 1511 // real error-handling. | 1509 // real error-handling. |
| 1512 void SafeBrowsingDatabaseNew::LoadPrefixSet( | 1510 void SafeBrowsingDatabaseNew::LoadPrefixSet( |
| 1513 const base::FilePath& db_filename, | 1511 const base::FilePath& db_filename, |
| 1514 scoped_ptr<safe_browsing::PrefixSet>* prefix_set, | 1512 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, |
| 1515 FailureType read_failure_type) { | 1513 FailureType read_failure_type) { |
| 1516 DCHECK(thread_checker_.CalledOnValidThread()); | 1514 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1517 | 1515 |
| 1518 if (!prefix_set) | 1516 if (!prefix_set) |
| 1519 return; | 1517 return; |
| 1520 | 1518 |
| 1521 DCHECK(!filename_base_.empty()); | 1519 DCHECK(!filename_base_.empty()); |
| 1522 | 1520 |
| 1523 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); | 1521 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); |
| 1524 | 1522 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1615 const bool r11 = | 1613 const bool r11 = |
| 1616 base::DeleteFile(UnwantedSoftwareDBFilename(filename_base_), false); | 1614 base::DeleteFile(UnwantedSoftwareDBFilename(filename_base_), false); |
| 1617 if (!r11) | 1615 if (!r11) |
| 1618 RecordFailure(FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_DELETE); | 1616 RecordFailure(FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_DELETE); |
| 1619 | 1617 |
| 1620 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9 && r10 && r11; | 1618 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9 && r10 && r11; |
| 1621 } | 1619 } |
| 1622 | 1620 |
| 1623 void SafeBrowsingDatabaseNew::WritePrefixSet( | 1621 void SafeBrowsingDatabaseNew::WritePrefixSet( |
| 1624 const base::FilePath& db_filename, | 1622 const base::FilePath& db_filename, |
| 1625 safe_browsing::PrefixSet* prefix_set, | 1623 const safe_browsing::PrefixSet* prefix_set, |
| 1626 FailureType write_failure_type) { | 1624 FailureType write_failure_type) { |
| 1627 DCHECK(thread_checker_.CalledOnValidThread()); | 1625 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1628 | 1626 |
| 1629 if (!prefix_set) | 1627 if (!prefix_set) |
| 1630 return; | 1628 return; |
| 1631 | 1629 |
| 1632 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); | 1630 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); |
| 1633 | 1631 |
| 1634 const base::TimeTicks before = base::TimeTicks::Now(); | 1632 const base::TimeTicks before = base::TimeTicks::Now(); |
| 1635 const bool write_ok = prefix_set->WriteFile(prefix_set_filename); | 1633 const bool write_ok = prefix_set->WriteFile(prefix_set_filename); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1736 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); | 1734 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); |
| 1737 } | 1735 } |
| 1738 | 1736 |
| 1739 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() { | 1737 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() { |
| 1740 // This method is theoretically thread-safe but document that it is currently | 1738 // This method is theoretically thread-safe but document that it is currently |
| 1741 // only expected to be called on the IO thread. | 1739 // only expected to be called on the IO thread. |
| 1742 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1740 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 1743 | 1741 |
| 1744 return csd_whitelist_.second; | 1742 return csd_whitelist_.second; |
| 1745 } | 1743 } |
| OLD | NEW |