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 12 matching lines...) Expand all Loading... | |
23 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
24 #include "crypto/sha2.h" | 24 #include "crypto/sha2.h" |
25 #include "net/base/net_util.h" | 25 #include "net/base/net_util.h" |
26 #include "url/gurl.h" | 26 #include "url/gurl.h" |
27 | 27 |
28 #if defined(OS_MACOSX) | 28 #if defined(OS_MACOSX) |
29 #include "base/mac/mac_util.h" | 29 #include "base/mac/mac_util.h" |
30 #endif | 30 #endif |
31 | 31 |
32 using content::BrowserThread; | 32 using content::BrowserThread; |
33 using safe_browsing::PrefixSet; | |
34 using safe_browsing::PrefixSetBuilder; | |
33 | 35 |
34 namespace { | 36 namespace { |
35 | 37 |
36 // Filename suffix for the bloom filter. | 38 // Filename suffix for the bloom filter. |
37 const base::FilePath::CharType kBloomFilterFile[] = | 39 const base::FilePath::CharType kBloomFilterFile[] = |
38 FILE_PATH_LITERAL(" Filter 2"); | 40 FILE_PATH_LITERAL(" Filter 2"); |
39 // Filename suffix for the prefix set. | 41 // Filename suffix for the prefix set. |
40 const base::FilePath::CharType kPrefixSetFile[] = | 42 const base::FilePath::CharType kPrefixSetFile[] = |
41 FILE_PATH_LITERAL(" Prefix Set"); | 43 FILE_PATH_LITERAL(" Prefix Set"); |
42 // Filename suffix for download store. | 44 // Filename suffix for download store. |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
455 } | 457 } |
456 return NULL; | 458 return NULL; |
457 } | 459 } |
458 | 460 |
459 // static | 461 // static |
460 void SafeBrowsingDatabase::RecordFailure(FailureType failure_type) { | 462 void SafeBrowsingDatabase::RecordFailure(FailureType failure_type) { |
461 UMA_HISTOGRAM_ENUMERATION("SB2.DatabaseFailure", failure_type, | 463 UMA_HISTOGRAM_ENUMERATION("SB2.DatabaseFailure", failure_type, |
462 FAILURE_DATABASE_MAX); | 464 FAILURE_DATABASE_MAX); |
463 } | 465 } |
464 | 466 |
467 class SafeBrowsingDatabaseNew::ThreadSafeStateManager::ReadTransaction { | |
468 public: | |
469 const SBWhitelist* GetSBWhitelist(SBWhitelistId id) { | |
470 switch (id) { | |
471 case SBWhitelistId::CSD: | |
472 return &outer_->csd_whitelist_; | |
473 case SBWhitelistId::DOWNLOAD: | |
474 return &outer_->download_whitelist_; | |
475 } | |
476 NOTREACHED(); | |
477 return nullptr; | |
478 } | |
479 | |
480 const IPBlacklist* ip_blacklist() { return &outer_->ip_blacklist_; } | |
481 | |
482 const PrefixSet* GetPrefixSet(PrefixSetId id) { | |
483 switch (id) { | |
484 case PrefixSetId::BROWSE: | |
485 return outer_->browse_prefix_set_.get(); | |
486 case PrefixSetId::SIDE_EFFECT_FREE_WHITELIST: | |
487 return outer_->side_effect_free_whitelist_prefix_set_.get(); | |
488 case PrefixSetId::UNWANTED_SOFTWARE: | |
489 return outer_->unwanted_software_prefix_set_.get(); | |
490 } | |
491 NOTREACHED(); | |
492 return nullptr; | |
493 } | |
494 | |
495 PrefixGetHashCache* prefix_gethash_cache() { | |
496 // The cache is special: it is read/write on all threads. Access to it | |
497 // therefore requires a LOCK'ed transaction (i.e. it can't benefit from | |
498 // DONT_LOCK_ON_MAIN_THREAD). | |
499 DCHECK(transaction_lock_); | |
500 return &outer_->prefix_gethash_cache_; | |
501 } | |
502 | |
503 private: | |
504 // Only ThreadSafeStateManager is allowed to build a ReadTransaction. | |
505 friend class ThreadSafeStateManager; | |
506 | |
507 enum class AutoLockRequirement { | |
508 LOCK, | |
509 // SBWhitelist's, IPBlacklist's, and PrefixSet's (not caches) are only | |
510 // ever written to on the main thread (as enforced by | |
511 // ThreadSafeStateManager) and can therefore be read on the main thread | |
512 // without first acquiring |lock_|. | |
513 DONT_LOCK_ON_MAIN_THREAD | |
514 }; | |
515 | |
516 ReadTransaction(const ThreadSafeStateManager* outer, | |
517 AutoLockRequirement auto_lock_requirement) | |
518 : outer_(outer) { | |
519 DCHECK(outer_); | |
520 if (auto_lock_requirement == AutoLockRequirement::LOCK) | |
521 transaction_lock_.reset(new base::AutoLock(outer_->lock_)); | |
522 else | |
523 DCHECK(outer_->thread_checker_.CalledOnValidThread()); | |
524 } | |
525 | |
526 const ThreadSafeStateManager* outer_; | |
527 scoped_ptr<base::AutoLock> transaction_lock_; | |
528 | |
529 DISALLOW_COPY_AND_ASSIGN(ReadTransaction); | |
530 }; | |
531 | |
532 class SafeBrowsingDatabaseNew::ThreadSafeStateManager::WriteTransaction { | |
533 public: | |
534 // Call this method if an error occured with the given whitelist. This will | |
535 // result in all lookups to the whitelist to return true. | |
536 void WhitelistEverything(SBWhitelistId id) { | |
537 SBWhitelist* whitelist = SBWhitelistForId(id); | |
538 whitelist->second = true; | |
539 whitelist->first.clear(); | |
540 } | |
541 | |
542 void SwapSBWhitelist(SBWhitelistId id, | |
543 scoped_ptr<std::vector<SBFullHash>> new_whitelist) { | |
mattm
2014/12/24 00:29:54
why not just pass "std::vector<SBFullHash>* new_wh
gab
2014/12/24 01:28:58
Because I try to always have methods that take own
| |
544 SBWhitelist* whitelist = SBWhitelistForId(id); | |
545 whitelist->second = false; | |
546 whitelist->first.swap(*new_whitelist.release()); | |
mattm
2014/12/24 00:29:53
This is a leak isn't it?
gab
2014/12/24 01:28:58
Done.
| |
547 } | |
548 | |
549 void clear_ip_blacklist() { outer_->ip_blacklist_.clear(); } | |
550 | |
551 void swap_ip_blacklist(scoped_ptr<IPBlacklist> new_blacklist) { | |
552 outer_->ip_blacklist_.swap(*new_blacklist.release()); | |
mattm
2014/12/24 00:29:54
same as above
gab
2014/12/24 01:28:58
Done.
| |
553 } | |
554 | |
555 void SwapPrefixSet(PrefixSetId id, | |
556 scoped_ptr<const PrefixSet> new_prefix_set) { | |
557 switch (id) { | |
558 case PrefixSetId::BROWSE: | |
559 outer_->browse_prefix_set_.swap(new_prefix_set); | |
560 break; | |
561 case PrefixSetId::SIDE_EFFECT_FREE_WHITELIST: | |
562 outer_->side_effect_free_whitelist_prefix_set_.swap(new_prefix_set); | |
563 break; | |
564 case PrefixSetId::UNWANTED_SOFTWARE: | |
565 outer_->unwanted_software_prefix_set_.swap(new_prefix_set); | |
566 break; | |
567 } | |
568 } | |
569 | |
570 void clear_prefix_gethash_cache() { outer_->prefix_gethash_cache_.clear(); } | |
571 | |
572 private: | |
573 // Only ThreadSafeStateManager is allowed to build a WriteTransaction. | |
574 friend class ThreadSafeStateManager; | |
575 | |
576 explicit WriteTransaction(ThreadSafeStateManager* outer) | |
577 : outer_(outer), transaction_lock_(outer_->lock_) { | |
578 DCHECK(outer_); | |
579 DCHECK(outer_->thread_checker_.CalledOnValidThread()); | |
580 } | |
581 | |
582 SBWhitelist* SBWhitelistForId(SBWhitelistId id) { | |
583 switch (id) { | |
584 case SBWhitelistId::CSD: | |
585 return &outer_->csd_whitelist_; | |
586 case SBWhitelistId::DOWNLOAD: | |
587 return &outer_->download_whitelist_; | |
588 } | |
589 NOTREACHED(); | |
590 return nullptr; | |
591 } | |
592 | |
593 ThreadSafeStateManager* outer_; | |
594 base::AutoLock transaction_lock_; | |
595 | |
596 DISALLOW_COPY_AND_ASSIGN(WriteTransaction); | |
597 }; | |
598 | |
599 SafeBrowsingDatabaseNew::ThreadSafeStateManager::ThreadSafeStateManager( | |
600 const base::ThreadChecker& thread_checker) | |
601 : thread_checker_(thread_checker) { | |
602 } | |
603 | |
604 SafeBrowsingDatabaseNew::ThreadSafeStateManager::~ThreadSafeStateManager() { | |
605 } | |
606 | |
607 scoped_ptr<SafeBrowsingDatabaseNew::ReadTransaction> | |
608 SafeBrowsingDatabaseNew::ThreadSafeStateManager::BeginReadTransaction() { | |
609 return make_scoped_ptr( | |
610 new ReadTransaction(this, ReadTransaction::AutoLockRequirement::LOCK)); | |
611 } | |
612 | |
613 scoped_ptr<SafeBrowsingDatabaseNew::ReadTransaction> SafeBrowsingDatabaseNew:: | |
614 ThreadSafeStateManager::BeginReadTransactionNoLockOnMainThread() { | |
615 return make_scoped_ptr(new ReadTransaction( | |
616 this, ReadTransaction::AutoLockRequirement::DONT_LOCK_ON_MAIN_THREAD)); | |
617 } | |
618 | |
619 scoped_ptr<SafeBrowsingDatabaseNew::WriteTransaction> | |
620 SafeBrowsingDatabaseNew::ThreadSafeStateManager::BeginWriteTransaction() { | |
621 return make_scoped_ptr(new WriteTransaction(this)); | |
622 } | |
623 | |
465 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew() | 624 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew() |
466 : SafeBrowsingDatabaseNew(new SafeBrowsingStoreFile, | 625 : SafeBrowsingDatabaseNew(new SafeBrowsingStoreFile, |
467 NULL, | 626 NULL, |
468 NULL, | 627 NULL, |
469 NULL, | 628 NULL, |
470 NULL, | 629 NULL, |
471 NULL, | 630 NULL, |
472 NULL, | 631 NULL, |
473 NULL) { | 632 NULL) { |
474 DCHECK(browse_store_.get()); | 633 DCHECK(browse_store_.get()); |
475 DCHECK(!download_store_.get()); | 634 DCHECK(!download_store_.get()); |
476 DCHECK(!csd_whitelist_store_.get()); | 635 DCHECK(!csd_whitelist_store_.get()); |
477 DCHECK(!download_whitelist_store_.get()); | 636 DCHECK(!download_whitelist_store_.get()); |
478 DCHECK(!extension_blacklist_store_.get()); | 637 DCHECK(!extension_blacklist_store_.get()); |
479 DCHECK(!side_effect_free_whitelist_store_.get()); | 638 DCHECK(!side_effect_free_whitelist_store_.get()); |
480 DCHECK(!ip_blacklist_store_.get()); | 639 DCHECK(!ip_blacklist_store_.get()); |
481 DCHECK(!unwanted_software_store_.get()); | 640 DCHECK(!unwanted_software_store_.get()); |
482 } | 641 } |
483 | 642 |
484 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew( | 643 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew( |
485 SafeBrowsingStore* browse_store, | 644 SafeBrowsingStore* browse_store, |
486 SafeBrowsingStore* download_store, | 645 SafeBrowsingStore* download_store, |
487 SafeBrowsingStore* csd_whitelist_store, | 646 SafeBrowsingStore* csd_whitelist_store, |
488 SafeBrowsingStore* download_whitelist_store, | 647 SafeBrowsingStore* download_whitelist_store, |
489 SafeBrowsingStore* extension_blacklist_store, | 648 SafeBrowsingStore* extension_blacklist_store, |
490 SafeBrowsingStore* side_effect_free_whitelist_store, | 649 SafeBrowsingStore* side_effect_free_whitelist_store, |
491 SafeBrowsingStore* ip_blacklist_store, | 650 SafeBrowsingStore* ip_blacklist_store, |
492 SafeBrowsingStore* unwanted_software_store) | 651 SafeBrowsingStore* unwanted_software_store) |
493 : browse_store_(browse_store), | 652 : state_manager_(thread_checker_), |
653 browse_store_(browse_store), | |
494 download_store_(download_store), | 654 download_store_(download_store), |
495 csd_whitelist_store_(csd_whitelist_store), | 655 csd_whitelist_store_(csd_whitelist_store), |
496 download_whitelist_store_(download_whitelist_store), | 656 download_whitelist_store_(download_whitelist_store), |
497 extension_blacklist_store_(extension_blacklist_store), | 657 extension_blacklist_store_(extension_blacklist_store), |
498 side_effect_free_whitelist_store_(side_effect_free_whitelist_store), | 658 side_effect_free_whitelist_store_(side_effect_free_whitelist_store), |
499 ip_blacklist_store_(ip_blacklist_store), | 659 ip_blacklist_store_(ip_blacklist_store), |
500 unwanted_software_store_(unwanted_software_store), | 660 unwanted_software_store_(unwanted_software_store), |
501 corruption_detected_(false), | 661 corruption_detected_(false), |
502 change_detected_(false), | 662 change_detected_(false), |
503 reset_factory_(this) { | 663 reset_factory_(this) { |
(...skipping 14 matching lines...) Expand all Loading... | |
518 filename_base_ = filename_base; | 678 filename_base_ = filename_base; |
519 | 679 |
520 // TODO(shess): The various stores are really only necessary while doing | 680 // TODO(shess): The various stores are really only necessary while doing |
521 // updates (see |UpdateFinished()|) or when querying a store directly (see | 681 // updates (see |UpdateFinished()|) or when querying a store directly (see |
522 // |ContainsDownloadUrl()|). | 682 // |ContainsDownloadUrl()|). |
523 // The store variables are also tested to see if a list is enabled. Perhaps | 683 // The store variables are also tested to see if a list is enabled. Perhaps |
524 // the stores could be refactored into an update object so that they are only | 684 // the stores could be refactored into an update object so that they are only |
525 // live in memory while being actively used. The sense of enabled probably | 685 // live in memory while being actively used. The sense of enabled probably |
526 // belongs in protocol_manager or database_manager. | 686 // belongs in protocol_manager or database_manager. |
527 | 687 |
528 browse_store_->Init( | 688 { |
529 BrowseDBFilename(filename_base_), | 689 // NOTE: A transaction here is overkill as there are no pointers to this |
530 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 690 // class on other threads until this function returns, but it's also |
531 base::Unretained(this))); | 691 // harmless as that also means there is no possibility of contention on the |
692 // lock. | |
693 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction(); | |
532 | 694 |
533 if (unwanted_software_store_.get()) { | 695 txn->clear_prefix_gethash_cache(); |
534 unwanted_software_store_->Init( | 696 |
535 UnwantedSoftwareDBFilename(filename_base_), | 697 browse_store_->Init( |
698 BrowseDBFilename(filename_base_), | |
536 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 699 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
537 base::Unretained(this))); | 700 base::Unretained(this))); |
538 } | |
539 | 701 |
540 { | |
541 // NOTE: There is no need to grab the lock in this function, since | |
542 // until it returns, there are no pointers to this class on other | |
543 // threads. Then again, that means there is no possibility of | |
544 // contention on the lock... | |
545 base::AutoLock locked(lookup_lock_); | |
546 prefix_gethash_cache_.clear(); | |
547 LoadPrefixSet(BrowseDBFilename(filename_base_), | |
548 &browse_prefix_set_, | |
549 FAILURE_BROWSE_PREFIX_SET_READ); | |
550 if (unwanted_software_store_.get()) { | 702 if (unwanted_software_store_.get()) { |
551 LoadPrefixSet(UnwantedSoftwareDBFilename(filename_base_), | 703 unwanted_software_store_->Init( |
552 &unwanted_software_prefix_set_, | 704 UnwantedSoftwareDBFilename(filename_base_), |
705 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | |
706 base::Unretained(this))); | |
707 } | |
708 LoadPrefixSet(BrowseDBFilename(filename_base_), txn.get(), | |
709 PrefixSetId::BROWSE, FAILURE_BROWSE_PREFIX_SET_READ); | |
710 if (unwanted_software_store_.get()) { | |
711 LoadPrefixSet(UnwantedSoftwareDBFilename(filename_base_), txn.get(), | |
712 PrefixSetId::UNWANTED_SOFTWARE, | |
553 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_READ); | 713 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_READ); |
554 } | 714 } |
715 | |
716 if (side_effect_free_whitelist_store_.get()) { | |
717 const base::FilePath side_effect_free_whitelist_filename = | |
718 SideEffectFreeWhitelistDBFilename(filename_base_); | |
719 side_effect_free_whitelist_store_->Init( | |
720 side_effect_free_whitelist_filename, | |
721 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | |
722 base::Unretained(this))); | |
723 | |
724 LoadPrefixSet(side_effect_free_whitelist_filename, txn.get(), | |
725 PrefixSetId::SIDE_EFFECT_FREE_WHITELIST, | |
726 FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_READ); | |
727 } else { | |
728 // Delete any files of the side-effect free sidelist that may be around | |
729 // from when it was previously enabled. | |
730 SafeBrowsingStoreFile::DeleteStore( | |
731 SideEffectFreeWhitelistDBFilename(filename_base_)); | |
732 base::DeleteFile(PrefixSetForFilename( | |
733 SideEffectFreeWhitelistDBFilename(filename_base_)), | |
734 false); | |
735 } | |
555 } | 736 } |
737 // Note: End the transaction early because LoadWhiteList() and | |
738 // WhitelistEverything() manage their own transactions. | |
556 | 739 |
557 if (download_store_.get()) { | 740 if (download_store_.get()) { |
558 download_store_->Init( | 741 download_store_->Init( |
559 DownloadDBFilename(filename_base_), | 742 DownloadDBFilename(filename_base_), |
560 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 743 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
561 base::Unretained(this))); | 744 base::Unretained(this))); |
562 } | 745 } |
563 | 746 |
564 if (csd_whitelist_store_.get()) { | 747 if (csd_whitelist_store_.get()) { |
565 csd_whitelist_store_->Init( | 748 csd_whitelist_store_->Init( |
566 CsdWhitelistDBFilename(filename_base_), | 749 CsdWhitelistDBFilename(filename_base_), |
567 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 750 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
568 base::Unretained(this))); | 751 base::Unretained(this))); |
569 | 752 |
570 std::vector<SBAddFullHash> full_hashes; | 753 std::vector<SBAddFullHash> full_hashes; |
571 if (csd_whitelist_store_->GetAddFullHashes(&full_hashes)) { | 754 if (csd_whitelist_store_->GetAddFullHashes(&full_hashes)) { |
572 LoadWhitelist(full_hashes, &csd_whitelist_); | 755 LoadWhitelist(full_hashes, SBWhitelistId::CSD); |
573 } else { | 756 } else { |
574 WhitelistEverything(&csd_whitelist_); | 757 state_manager_.BeginWriteTransaction()->WhitelistEverything( |
758 SBWhitelistId::CSD); | |
575 } | 759 } |
576 } else { | 760 } else { |
577 WhitelistEverything(&csd_whitelist_); // Just to be safe. | 761 state_manager_.BeginWriteTransaction()->WhitelistEverything( |
762 SBWhitelistId::CSD); // Just to be safe. | |
578 } | 763 } |
579 | 764 |
580 if (download_whitelist_store_.get()) { | 765 if (download_whitelist_store_.get()) { |
581 download_whitelist_store_->Init( | 766 download_whitelist_store_->Init( |
582 DownloadWhitelistDBFilename(filename_base_), | 767 DownloadWhitelistDBFilename(filename_base_), |
583 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 768 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
584 base::Unretained(this))); | 769 base::Unretained(this))); |
585 | 770 |
586 std::vector<SBAddFullHash> full_hashes; | 771 std::vector<SBAddFullHash> full_hashes; |
587 if (download_whitelist_store_->GetAddFullHashes(&full_hashes)) { | 772 if (download_whitelist_store_->GetAddFullHashes(&full_hashes)) { |
588 LoadWhitelist(full_hashes, &download_whitelist_); | 773 LoadWhitelist(full_hashes, SBWhitelistId::DOWNLOAD); |
589 } else { | 774 } else { |
590 WhitelistEverything(&download_whitelist_); | 775 state_manager_.BeginWriteTransaction()->WhitelistEverything( |
776 SBWhitelistId::DOWNLOAD); | |
591 } | 777 } |
592 } else { | 778 } else { |
593 WhitelistEverything(&download_whitelist_); // Just to be safe. | 779 state_manager_.BeginWriteTransaction()->WhitelistEverything( |
780 SBWhitelistId::DOWNLOAD); // Just to be safe. | |
594 } | 781 } |
595 | 782 |
596 if (extension_blacklist_store_.get()) { | 783 if (extension_blacklist_store_.get()) { |
597 extension_blacklist_store_->Init( | 784 extension_blacklist_store_->Init( |
598 ExtensionBlacklistDBFilename(filename_base_), | 785 ExtensionBlacklistDBFilename(filename_base_), |
599 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 786 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
600 base::Unretained(this))); | 787 base::Unretained(this))); |
601 } | 788 } |
602 | 789 |
603 if (side_effect_free_whitelist_store_.get()) { | |
604 const base::FilePath side_effect_free_whitelist_filename = | |
605 SideEffectFreeWhitelistDBFilename(filename_base_); | |
606 side_effect_free_whitelist_store_->Init( | |
607 side_effect_free_whitelist_filename, | |
608 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | |
609 base::Unretained(this))); | |
610 | |
611 LoadPrefixSet(side_effect_free_whitelist_filename, | |
612 &side_effect_free_whitelist_prefix_set_, | |
613 FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_READ); | |
614 } else { | |
615 // Delete any files of the side-effect free sidelist that may be around | |
616 // from when it was previously enabled. | |
617 SafeBrowsingStoreFile::DeleteStore( | |
618 SideEffectFreeWhitelistDBFilename(filename_base_)); | |
619 base::DeleteFile( | |
620 PrefixSetForFilename(SideEffectFreeWhitelistDBFilename(filename_base_)), | |
621 false); | |
622 } | |
623 | |
624 if (ip_blacklist_store_.get()) { | 790 if (ip_blacklist_store_.get()) { |
625 ip_blacklist_store_->Init( | 791 ip_blacklist_store_->Init( |
626 IpBlacklistDBFilename(filename_base_), | 792 IpBlacklistDBFilename(filename_base_), |
627 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 793 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
628 base::Unretained(this))); | 794 base::Unretained(this))); |
629 | 795 |
630 std::vector<SBAddFullHash> full_hashes; | 796 std::vector<SBAddFullHash> full_hashes; |
631 if (ip_blacklist_store_->GetAddFullHashes(&full_hashes)) { | 797 if (ip_blacklist_store_->GetAddFullHashes(&full_hashes)) { |
632 LoadIpBlacklist(full_hashes); | 798 LoadIpBlacklist(full_hashes); |
633 } else { | 799 } else { |
634 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. | 800 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. |
635 } | 801 } |
636 } | 802 } |
637 } | 803 } |
638 | 804 |
639 bool SafeBrowsingDatabaseNew::ResetDatabase() { | 805 bool SafeBrowsingDatabaseNew::ResetDatabase() { |
640 DCHECK(thread_checker_.CalledOnValidThread()); | 806 DCHECK(thread_checker_.CalledOnValidThread()); |
641 | 807 |
642 // Delete files on disk. | 808 // Delete files on disk. |
643 // TODO(shess): Hard to see where one might want to delete without a | 809 // TODO(shess): Hard to see where one might want to delete without a |
644 // reset. Perhaps inline |Delete()|? | 810 // reset. Perhaps inline |Delete()|? |
645 if (!Delete()) | 811 if (!Delete()) |
646 return false; | 812 return false; |
647 | 813 |
648 // Reset objects in memory. | 814 // Reset objects in memory. |
649 { | 815 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction(); |
650 base::AutoLock locked(lookup_lock_); | 816 txn->clear_prefix_gethash_cache(); |
651 prefix_gethash_cache_.clear(); | 817 txn->SwapPrefixSet(PrefixSetId::BROWSE, nullptr); |
652 browse_prefix_set_.reset(); | 818 txn->SwapPrefixSet(PrefixSetId::SIDE_EFFECT_FREE_WHITELIST, nullptr); |
653 side_effect_free_whitelist_prefix_set_.reset(); | 819 txn->SwapPrefixSet(PrefixSetId::UNWANTED_SOFTWARE, nullptr); |
654 ip_blacklist_.clear(); | 820 txn->clear_ip_blacklist(); |
655 unwanted_software_prefix_set_.reset(); | 821 txn->WhitelistEverything(SBWhitelistId::CSD); |
656 } | 822 txn->WhitelistEverything(SBWhitelistId::DOWNLOAD); |
657 // Wants to acquire the lock itself. | |
658 WhitelistEverything(&csd_whitelist_); | |
659 WhitelistEverything(&download_whitelist_); | |
660 return true; | 823 return true; |
661 } | 824 } |
662 | 825 |
663 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( | 826 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( |
664 const GURL& url, | 827 const GURL& url, |
665 std::vector<SBPrefix>* prefix_hits, | 828 std::vector<SBPrefix>* prefix_hits, |
666 std::vector<SBFullHashResult>* cache_hits) { | 829 std::vector<SBFullHashResult>* cache_hits) { |
667 return PrefixSetContainsUrl( | 830 return PrefixSetContainsUrl(url, PrefixSetId::BROWSE, prefix_hits, |
668 url, &browse_prefix_set_, prefix_hits, cache_hits); | 831 cache_hits); |
669 } | 832 } |
670 | 833 |
671 bool SafeBrowsingDatabaseNew::ContainsUnwantedSoftwareUrl( | 834 bool SafeBrowsingDatabaseNew::ContainsUnwantedSoftwareUrl( |
672 const GURL& url, | 835 const GURL& url, |
673 std::vector<SBPrefix>* prefix_hits, | 836 std::vector<SBPrefix>* prefix_hits, |
674 std::vector<SBFullHashResult>* cache_hits) { | 837 std::vector<SBFullHashResult>* cache_hits) { |
675 return PrefixSetContainsUrl( | 838 return PrefixSetContainsUrl(url, PrefixSetId::UNWANTED_SOFTWARE, prefix_hits, |
676 url, &unwanted_software_prefix_set_, prefix_hits, cache_hits); | 839 cache_hits); |
677 } | 840 } |
678 | 841 |
679 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl( | 842 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl( |
680 const GURL& url, | 843 const GURL& url, |
681 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, | 844 PrefixSetId prefix_set_id, |
682 std::vector<SBPrefix>* prefix_hits, | 845 std::vector<SBPrefix>* prefix_hits, |
683 std::vector<SBFullHashResult>* cache_hits) { | 846 std::vector<SBFullHashResult>* cache_hits) { |
684 // Clear the results first. | 847 // Clear the results first. |
685 prefix_hits->clear(); | 848 prefix_hits->clear(); |
686 cache_hits->clear(); | 849 cache_hits->clear(); |
687 | 850 |
688 std::vector<SBFullHash> full_hashes; | 851 std::vector<SBFullHash> full_hashes; |
689 UrlToFullHashes(url, false, &full_hashes); | 852 UrlToFullHashes(url, false, &full_hashes); |
690 if (full_hashes.empty()) | 853 if (full_hashes.empty()) |
691 return false; | 854 return false; |
692 | 855 |
693 return PrefixSetContainsUrlHashes( | 856 return PrefixSetContainsUrlHashes(full_hashes, prefix_set_id, prefix_hits, |
694 full_hashes, prefix_set_getter, prefix_hits, cache_hits); | 857 cache_hits); |
695 } | 858 } |
696 | 859 |
697 bool SafeBrowsingDatabaseNew::ContainsBrowseUrlHashesForTesting( | 860 bool SafeBrowsingDatabaseNew::ContainsBrowseUrlHashesForTesting( |
698 const std::vector<SBFullHash>& full_hashes, | 861 const std::vector<SBFullHash>& full_hashes, |
699 std::vector<SBPrefix>* prefix_hits, | 862 std::vector<SBPrefix>* prefix_hits, |
700 std::vector<SBFullHashResult>* cache_hits) { | 863 std::vector<SBFullHashResult>* cache_hits) { |
701 return PrefixSetContainsUrlHashes( | 864 return PrefixSetContainsUrlHashes(full_hashes, PrefixSetId::BROWSE, |
702 full_hashes, &browse_prefix_set_, prefix_hits, cache_hits); | 865 prefix_hits, cache_hits); |
703 } | 866 } |
704 | 867 |
705 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes( | 868 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes( |
706 const std::vector<SBFullHash>& full_hashes, | 869 const std::vector<SBFullHash>& full_hashes, |
707 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, | 870 PrefixSetId prefix_set_id, |
708 std::vector<SBPrefix>* prefix_hits, | 871 std::vector<SBPrefix>* prefix_hits, |
709 std::vector<SBFullHashResult>* cache_hits) { | 872 std::vector<SBFullHashResult>* cache_hits) { |
710 // Used to determine cache expiration. | 873 // Used to determine cache expiration. |
711 const base::Time now = base::Time::Now(); | 874 const base::Time now = base::Time::Now(); |
712 | 875 |
713 // This function can be called on any thread, so lock against any changes | 876 { |
714 base::AutoLock locked(lookup_lock_); | 877 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); |
715 | 878 |
716 // |prefix_set| is empty until it is either read from disk, or the first | 879 // |prefix_set| is empty until it is either read from disk, or the first |
717 // update populates it. Bail out without a hit if not yet available. | 880 // update populates it. Bail out without a hit if not yet available. |
718 // |prefix_set_getter| can only be accessed while holding |lookup_lock_| hence | 881 const PrefixSet* prefix_set = txn->GetPrefixSet(prefix_set_id); |
719 // why it is passed as a parameter rather than passing the |prefix_set| | 882 if (!prefix_set) |
720 // directly. | 883 return false; |
721 const safe_browsing::PrefixSet* prefix_set = prefix_set_getter->get(); | |
722 if (!prefix_set) | |
723 return false; | |
724 | 884 |
725 for (size_t i = 0; i < full_hashes.size(); ++i) { | 885 for (size_t i = 0; i < full_hashes.size(); ++i) { |
726 if (!GetCachedFullHash( | 886 if (!GetCachedFullHash(txn->prefix_gethash_cache(), full_hashes[i], now, |
727 &prefix_gethash_cache_, full_hashes[i], now, cache_hits)) { | 887 cache_hits)) { |
728 // No valid cached result, check the database. | 888 // No valid cached result, check the database. |
729 if (prefix_set->Exists(full_hashes[i])) | 889 if (prefix_set->Exists(full_hashes[i])) |
730 prefix_hits->push_back(full_hashes[i].prefix); | 890 prefix_hits->push_back(full_hashes[i].prefix); |
891 } | |
731 } | 892 } |
732 } | 893 } |
733 | 894 |
734 // Multiple full hashes could share prefix, remove duplicates. | 895 // Multiple full hashes could share prefix, remove duplicates. |
735 std::sort(prefix_hits->begin(), prefix_hits->end()); | 896 std::sort(prefix_hits->begin(), prefix_hits->end()); |
736 prefix_hits->erase(std::unique(prefix_hits->begin(), prefix_hits->end()), | 897 prefix_hits->erase(std::unique(prefix_hits->begin(), prefix_hits->end()), |
737 prefix_hits->end()); | 898 prefix_hits->end()); |
738 | 899 |
739 return !prefix_hits->empty() || !cache_hits->empty(); | 900 return !prefix_hits->empty() || !cache_hits->empty(); |
740 } | 901 } |
(...skipping 11 matching lines...) Expand all Loading... | |
752 GetDownloadUrlPrefixes(urls, &prefixes); | 913 GetDownloadUrlPrefixes(urls, &prefixes); |
753 return MatchAddPrefixes(download_store_.get(), | 914 return MatchAddPrefixes(download_store_.get(), |
754 safe_browsing_util::BINURL % 2, | 915 safe_browsing_util::BINURL % 2, |
755 prefixes, | 916 prefixes, |
756 prefix_hits); | 917 prefix_hits); |
757 } | 918 } |
758 | 919 |
759 bool SafeBrowsingDatabaseNew::ContainsCsdWhitelistedUrl(const GURL& url) { | 920 bool SafeBrowsingDatabaseNew::ContainsCsdWhitelistedUrl(const GURL& url) { |
760 std::vector<SBFullHash> full_hashes; | 921 std::vector<SBFullHash> full_hashes; |
761 UrlToFullHashes(url, true, &full_hashes); | 922 UrlToFullHashes(url, true, &full_hashes); |
762 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); | 923 return ContainsWhitelistedHashes(SBWhitelistId::CSD, full_hashes); |
763 } | 924 } |
764 | 925 |
765 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) { | 926 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) { |
766 std::vector<SBFullHash> full_hashes; | 927 std::vector<SBFullHash> full_hashes; |
767 UrlToFullHashes(url, true, &full_hashes); | 928 UrlToFullHashes(url, true, &full_hashes); |
768 return ContainsWhitelistedHashes(download_whitelist_, full_hashes); | 929 return ContainsWhitelistedHashes(SBWhitelistId::DOWNLOAD, full_hashes); |
769 } | 930 } |
770 | 931 |
771 bool SafeBrowsingDatabaseNew::ContainsExtensionPrefixes( | 932 bool SafeBrowsingDatabaseNew::ContainsExtensionPrefixes( |
772 const std::vector<SBPrefix>& prefixes, | 933 const std::vector<SBPrefix>& prefixes, |
773 std::vector<SBPrefix>* prefix_hits) { | 934 std::vector<SBPrefix>* prefix_hits) { |
774 DCHECK(thread_checker_.CalledOnValidThread()); | 935 DCHECK(thread_checker_.CalledOnValidThread()); |
775 | 936 |
776 if (!extension_blacklist_store_) | 937 if (!extension_blacklist_store_) |
777 return false; | 938 return false; |
778 | 939 |
779 return MatchAddPrefixes(extension_blacklist_store_.get(), | 940 return MatchAddPrefixes(extension_blacklist_store_.get(), |
780 safe_browsing_util::EXTENSIONBLACKLIST % 2, | 941 safe_browsing_util::EXTENSIONBLACKLIST % 2, |
781 prefixes, | 942 prefixes, |
782 prefix_hits); | 943 prefix_hits); |
783 } | 944 } |
784 | 945 |
785 bool SafeBrowsingDatabaseNew::ContainsSideEffectFreeWhitelistUrl( | 946 bool SafeBrowsingDatabaseNew::ContainsSideEffectFreeWhitelistUrl( |
786 const GURL& url) { | 947 const GURL& url) { |
787 std::string host; | 948 std::string host; |
788 std::string path; | 949 std::string path; |
789 std::string query; | 950 std::string query; |
790 safe_browsing_util::CanonicalizeUrl(url, &host, &path, &query); | 951 safe_browsing_util::CanonicalizeUrl(url, &host, &path, &query); |
791 std::string url_to_check = host + path; | 952 std::string url_to_check = host + path; |
792 if (!query.empty()) | 953 if (!query.empty()) |
793 url_to_check += "?" + query; | 954 url_to_check += "?" + query; |
794 SBFullHash full_hash = SBFullHashForString(url_to_check); | 955 SBFullHash full_hash = SBFullHashForString(url_to_check); |
795 | 956 |
796 // This function can be called on any thread, so lock against any changes | 957 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); |
797 base::AutoLock locked(lookup_lock_); | 958 |
959 const PrefixSet* side_effect_free_whitelist_prefix_set = | |
960 txn->GetPrefixSet(PrefixSetId::SIDE_EFFECT_FREE_WHITELIST); | |
798 | 961 |
799 // |side_effect_free_whitelist_prefix_set_| is empty until it is either read | 962 // |side_effect_free_whitelist_prefix_set_| is empty until it is either read |
800 // from disk, or the first update populates it. Bail out without a hit if | 963 // from disk, or the first update populates it. Bail out without a hit if |
801 // not yet available. | 964 // not yet available. |
802 if (!side_effect_free_whitelist_prefix_set_.get()) | 965 if (!side_effect_free_whitelist_prefix_set) |
803 return false; | 966 return false; |
804 | 967 |
805 return side_effect_free_whitelist_prefix_set_->Exists(full_hash); | 968 return side_effect_free_whitelist_prefix_set->Exists(full_hash); |
806 } | 969 } |
807 | 970 |
808 bool SafeBrowsingDatabaseNew::ContainsMalwareIP(const std::string& ip_address) { | 971 bool SafeBrowsingDatabaseNew::ContainsMalwareIP(const std::string& ip_address) { |
809 net::IPAddressNumber ip_number; | 972 net::IPAddressNumber ip_number; |
810 if (!net::ParseIPLiteralToNumber(ip_address, &ip_number)) | 973 if (!net::ParseIPLiteralToNumber(ip_address, &ip_number)) |
811 return false; | 974 return false; |
812 if (ip_number.size() == net::kIPv4AddressSize) | 975 if (ip_number.size() == net::kIPv4AddressSize) |
813 ip_number = net::ConvertIPv4NumberToIPv6Number(ip_number); | 976 ip_number = net::ConvertIPv4NumberToIPv6Number(ip_number); |
814 if (ip_number.size() != net::kIPv6AddressSize) | 977 if (ip_number.size() != net::kIPv6AddressSize) |
815 return false; // better safe than sorry. | 978 return false; // better safe than sorry. |
816 | 979 |
817 // This function can be called on any thread, so lock against any changes | 980 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); |
818 base::AutoLock locked(lookup_lock_); | 981 const IPBlacklist* ip_blacklist = txn->ip_blacklist(); |
819 for (IPBlacklist::const_iterator it = ip_blacklist_.begin(); | 982 for (IPBlacklist::const_iterator it = ip_blacklist->begin(); |
820 it != ip_blacklist_.end(); | 983 it != ip_blacklist->end(); ++it) { |
821 ++it) { | |
822 const std::string& mask = it->first; | 984 const std::string& mask = it->first; |
823 DCHECK_EQ(mask.size(), ip_number.size()); | 985 DCHECK_EQ(mask.size(), ip_number.size()); |
824 std::string subnet(net::kIPv6AddressSize, '\0'); | 986 std::string subnet(net::kIPv6AddressSize, '\0'); |
825 for (size_t i = 0; i < net::kIPv6AddressSize; ++i) { | 987 for (size_t i = 0; i < net::kIPv6AddressSize; ++i) { |
826 subnet[i] = ip_number[i] & mask[i]; | 988 subnet[i] = ip_number[i] & mask[i]; |
827 } | 989 } |
828 const std::string hash = base::SHA1HashString(subnet); | 990 const std::string hash = base::SHA1HashString(subnet); |
829 DVLOG(2) << "Lookup Malware IP: " | 991 DVLOG(2) << "Lookup Malware IP: " |
830 << " ip:" << ip_address | 992 << " ip:" << ip_address |
831 << " mask:" << base::HexEncode(mask.data(), mask.size()) | 993 << " mask:" << base::HexEncode(mask.data(), mask.size()) |
832 << " subnet:" << base::HexEncode(subnet.data(), subnet.size()) | 994 << " subnet:" << base::HexEncode(subnet.data(), subnet.size()) |
833 << " hash:" << base::HexEncode(hash.data(), hash.size()); | 995 << " hash:" << base::HexEncode(hash.data(), hash.size()); |
834 if (it->second.count(hash) > 0) { | 996 if (it->second.count(hash) > 0) { |
835 return true; | 997 return true; |
836 } | 998 } |
837 } | 999 } |
838 return false; | 1000 return false; |
839 } | 1001 } |
840 | 1002 |
841 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedString( | 1003 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedString( |
842 const std::string& str) { | 1004 const std::string& str) { |
843 std::vector<SBFullHash> hashes; | 1005 std::vector<SBFullHash> hashes; |
844 hashes.push_back(SBFullHashForString(str)); | 1006 hashes.push_back(SBFullHashForString(str)); |
845 return ContainsWhitelistedHashes(download_whitelist_, hashes); | 1007 return ContainsWhitelistedHashes(SBWhitelistId::DOWNLOAD, hashes); |
846 } | 1008 } |
847 | 1009 |
848 bool SafeBrowsingDatabaseNew::ContainsWhitelistedHashes( | 1010 bool SafeBrowsingDatabaseNew::ContainsWhitelistedHashes( |
849 const SBWhitelist& whitelist, | 1011 SBWhitelistId whitelist_id, |
850 const std::vector<SBFullHash>& hashes) { | 1012 const std::vector<SBFullHash>& hashes) { |
851 base::AutoLock l(lookup_lock_); | 1013 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); |
852 if (whitelist.second) | 1014 const SBWhitelist* whitelist = txn->GetSBWhitelist(whitelist_id); |
1015 if (whitelist->second) | |
853 return true; | 1016 return true; |
854 for (std::vector<SBFullHash>::const_iterator it = hashes.begin(); | 1017 for (std::vector<SBFullHash>::const_iterator it = hashes.begin(); |
855 it != hashes.end(); ++it) { | 1018 it != hashes.end(); ++it) { |
856 if (std::binary_search(whitelist.first.begin(), whitelist.first.end(), | 1019 if (std::binary_search(whitelist->first.begin(), whitelist->first.end(), |
857 *it, SBFullHashLess)) { | 1020 *it, SBFullHashLess)) { |
858 return true; | 1021 return true; |
859 } | 1022 } |
860 } | 1023 } |
861 return false; | 1024 return false; |
862 } | 1025 } |
863 | 1026 |
864 // Helper to insert add-chunk entries. | 1027 // Helper to insert add-chunk entries. |
865 void SafeBrowsingDatabaseNew::InsertAddChunk( | 1028 void SafeBrowsingDatabaseNew::InsertAddChunk( |
866 SafeBrowsingStore* store, | 1029 SafeBrowsingStore* store, |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
993 } | 1156 } |
994 } | 1157 } |
995 } | 1158 } |
996 | 1159 |
997 void SafeBrowsingDatabaseNew::CacheHashResults( | 1160 void SafeBrowsingDatabaseNew::CacheHashResults( |
998 const std::vector<SBPrefix>& prefixes, | 1161 const std::vector<SBPrefix>& prefixes, |
999 const std::vector<SBFullHashResult>& full_hits, | 1162 const std::vector<SBFullHashResult>& full_hits, |
1000 const base::TimeDelta& cache_lifetime) { | 1163 const base::TimeDelta& cache_lifetime) { |
1001 const base::Time expire_after = base::Time::Now() + cache_lifetime; | 1164 const base::Time expire_after = base::Time::Now() + cache_lifetime; |
1002 | 1165 |
1003 // This function can be called on any thread, so lock against any changes | 1166 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); |
1004 base::AutoLock locked(lookup_lock_); | 1167 PrefixGetHashCache* prefix_gethash_cache = txn->prefix_gethash_cache(); |
1005 | 1168 |
1006 // Create or reset all cached results for these prefixes. | 1169 // Create or reset all cached results for these prefixes. |
1007 for (size_t i = 0; i < prefixes.size(); ++i) { | 1170 for (size_t i = 0; i < prefixes.size(); ++i) { |
1008 prefix_gethash_cache_[prefixes[i]] = SBCachedFullHashResult(expire_after); | 1171 (*prefix_gethash_cache)[prefixes[i]] = SBCachedFullHashResult(expire_after); |
1009 } | 1172 } |
1010 | 1173 |
1011 // Insert any fullhash hits. Note that there may be one, multiple, or no | 1174 // Insert any fullhash hits. Note that there may be one, multiple, or no |
1012 // fullhashes for any given entry in |prefixes|. | 1175 // fullhashes for any given entry in |prefixes|. |
1013 for (size_t i = 0; i < full_hits.size(); ++i) { | 1176 for (size_t i = 0; i < full_hits.size(); ++i) { |
1014 const SBPrefix prefix = full_hits[i].hash.prefix; | 1177 const SBPrefix prefix = full_hits[i].hash.prefix; |
1015 prefix_gethash_cache_[prefix].full_hashes.push_back(full_hits[i]); | 1178 (*prefix_gethash_cache)[prefix].full_hashes.push_back(full_hits[i]); |
1016 } | 1179 } |
1017 } | 1180 } |
1018 | 1181 |
1019 bool SafeBrowsingDatabaseNew::UpdateStarted( | 1182 bool SafeBrowsingDatabaseNew::UpdateStarted( |
1020 std::vector<SBListChunkRanges>* lists) { | 1183 std::vector<SBListChunkRanges>* lists) { |
1021 DCHECK(thread_checker_.CalledOnValidThread()); | 1184 DCHECK(thread_checker_.CalledOnValidThread()); |
1022 DCHECK(lists); | 1185 DCHECK(lists); |
1023 | 1186 |
1024 // If |BeginUpdate()| fails, reset the database. | 1187 // If |BeginUpdate()| fails, reset the database. |
1025 if (!browse_store_->BeginUpdate()) { | 1188 if (!browse_store_->BeginUpdate()) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1066 HandleCorruptDatabase(); | 1229 HandleCorruptDatabase(); |
1067 return false; | 1230 return false; |
1068 } | 1231 } |
1069 | 1232 |
1070 if (unwanted_software_store_ && !unwanted_software_store_->BeginUpdate()) { | 1233 if (unwanted_software_store_ && !unwanted_software_store_->BeginUpdate()) { |
1071 RecordFailure(FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_BEGIN); | 1234 RecordFailure(FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_BEGIN); |
1072 HandleCorruptDatabase(); | 1235 HandleCorruptDatabase(); |
1073 return false; | 1236 return false; |
1074 } | 1237 } |
1075 | 1238 |
1076 { | 1239 // Cached fullhash results must be cleared on every database update (whether |
1077 base::AutoLock locked(lookup_lock_); | 1240 // successful or not). |
1078 // Cached fullhash results must be cleared on every database update (whether | 1241 state_manager_.BeginWriteTransaction()->clear_prefix_gethash_cache(); |
1079 // successful or not.) | |
1080 prefix_gethash_cache_.clear(); | |
1081 } | |
1082 | 1242 |
1083 UpdateChunkRangesForLists(browse_store_.get(), | 1243 UpdateChunkRangesForLists(browse_store_.get(), |
1084 safe_browsing_util::kMalwareList, | 1244 safe_browsing_util::kMalwareList, |
1085 safe_browsing_util::kPhishingList, | 1245 safe_browsing_util::kPhishingList, |
1086 lists); | 1246 lists); |
1087 | 1247 |
1088 // NOTE(shess): |download_store_| used to contain kBinHashList, which has been | 1248 // NOTE(shess): |download_store_| used to contain kBinHashList, which has been |
1089 // deprecated. Code to delete the list from the store shows ~15k hits/day as | 1249 // deprecated. Code to delete the list from the store shows ~15k hits/day as |
1090 // of Feb 2014, so it has been removed. Everything _should_ be resilient to | 1250 // of Feb 2014, so it has been removed. Everything _should_ be resilient to |
1091 // extra data of that sort. | 1251 // extra data of that sort. |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1193 int64 size_bytes = UpdateHashPrefixStore( | 1353 int64 size_bytes = UpdateHashPrefixStore( |
1194 DownloadDBFilename(filename_base_), | 1354 DownloadDBFilename(filename_base_), |
1195 download_store_.get(), | 1355 download_store_.get(), |
1196 FAILURE_DOWNLOAD_DATABASE_UPDATE_FINISH); | 1356 FAILURE_DOWNLOAD_DATABASE_UPDATE_FINISH); |
1197 UMA_HISTOGRAM_COUNTS("SB2.DownloadDatabaseKilobytes", | 1357 UMA_HISTOGRAM_COUNTS("SB2.DownloadDatabaseKilobytes", |
1198 static_cast<int>(size_bytes / 1024)); | 1358 static_cast<int>(size_bytes / 1024)); |
1199 } | 1359 } |
1200 | 1360 |
1201 UpdatePrefixSetUrlStore(BrowseDBFilename(filename_base_), | 1361 UpdatePrefixSetUrlStore(BrowseDBFilename(filename_base_), |
1202 browse_store_.get(), | 1362 browse_store_.get(), |
1203 &browse_prefix_set_, | 1363 PrefixSetId::BROWSE, |
1204 FAILURE_BROWSE_DATABASE_UPDATE_FINISH, | 1364 FAILURE_BROWSE_DATABASE_UPDATE_FINISH, |
1205 FAILURE_BROWSE_PREFIX_SET_WRITE, | 1365 FAILURE_BROWSE_PREFIX_SET_WRITE, |
1206 true); | 1366 true); |
1207 | 1367 |
1208 UpdateWhitelistStore(CsdWhitelistDBFilename(filename_base_), | 1368 UpdateWhitelistStore(CsdWhitelistDBFilename(filename_base_), |
1209 csd_whitelist_store_.get(), | 1369 csd_whitelist_store_.get(), |
1210 &csd_whitelist_); | 1370 SBWhitelistId::CSD); |
1211 UpdateWhitelistStore(DownloadWhitelistDBFilename(filename_base_), | 1371 UpdateWhitelistStore(DownloadWhitelistDBFilename(filename_base_), |
1212 download_whitelist_store_.get(), | 1372 download_whitelist_store_.get(), |
1213 &download_whitelist_); | 1373 SBWhitelistId::DOWNLOAD); |
1214 | 1374 |
1215 if (extension_blacklist_store_) { | 1375 if (extension_blacklist_store_) { |
1216 int64 size_bytes = UpdateHashPrefixStore( | 1376 int64 size_bytes = UpdateHashPrefixStore( |
1217 ExtensionBlacklistDBFilename(filename_base_), | 1377 ExtensionBlacklistDBFilename(filename_base_), |
1218 extension_blacklist_store_.get(), | 1378 extension_blacklist_store_.get(), |
1219 FAILURE_EXTENSION_BLACKLIST_UPDATE_FINISH); | 1379 FAILURE_EXTENSION_BLACKLIST_UPDATE_FINISH); |
1220 UMA_HISTOGRAM_COUNTS("SB2.ExtensionBlacklistKilobytes", | 1380 UMA_HISTOGRAM_COUNTS("SB2.ExtensionBlacklistKilobytes", |
1221 static_cast<int>(size_bytes / 1024)); | 1381 static_cast<int>(size_bytes / 1024)); |
1222 } | 1382 } |
1223 | 1383 |
1224 if (side_effect_free_whitelist_store_) { | 1384 if (side_effect_free_whitelist_store_) { |
1225 UpdatePrefixSetUrlStore(SideEffectFreeWhitelistDBFilename(filename_base_), | 1385 UpdatePrefixSetUrlStore(SideEffectFreeWhitelistDBFilename(filename_base_), |
1226 side_effect_free_whitelist_store_.get(), | 1386 side_effect_free_whitelist_store_.get(), |
1227 &side_effect_free_whitelist_prefix_set_, | 1387 PrefixSetId::SIDE_EFFECT_FREE_WHITELIST, |
1228 FAILURE_SIDE_EFFECT_FREE_WHITELIST_UPDATE_FINISH, | 1388 FAILURE_SIDE_EFFECT_FREE_WHITELIST_UPDATE_FINISH, |
1229 FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_WRITE, | 1389 FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_WRITE, |
1230 false); | 1390 false); |
1231 } | 1391 } |
1232 | 1392 |
1233 if (ip_blacklist_store_) | 1393 if (ip_blacklist_store_) |
1234 UpdateIpBlacklistStore(); | 1394 UpdateIpBlacklistStore(); |
1235 | 1395 |
1236 if (unwanted_software_store_) { | 1396 if (unwanted_software_store_) { |
1237 UpdatePrefixSetUrlStore(UnwantedSoftwareDBFilename(filename_base_), | 1397 UpdatePrefixSetUrlStore(UnwantedSoftwareDBFilename(filename_base_), |
1238 unwanted_software_store_.get(), | 1398 unwanted_software_store_.get(), |
1239 &unwanted_software_prefix_set_, | 1399 PrefixSetId::UNWANTED_SOFTWARE, |
1240 FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_FINISH, | 1400 FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_FINISH, |
1241 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_WRITE, | 1401 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_WRITE, |
1242 true); | 1402 true); |
1243 } | 1403 } |
1244 } | 1404 } |
1245 | 1405 |
1246 void SafeBrowsingDatabaseNew::UpdateWhitelistStore( | 1406 void SafeBrowsingDatabaseNew::UpdateWhitelistStore( |
1247 const base::FilePath& store_filename, | 1407 const base::FilePath& store_filename, |
1248 SafeBrowsingStore* store, | 1408 SafeBrowsingStore* store, |
1249 SBWhitelist* whitelist) { | 1409 SBWhitelistId whitelist_id) { |
1250 DCHECK(thread_checker_.CalledOnValidThread()); | 1410 DCHECK(thread_checker_.CalledOnValidThread()); |
1251 | 1411 |
1252 if (!store) | 1412 if (!store) |
1253 return; | 1413 return; |
1254 | 1414 |
1255 // Note: |builder| will not be empty. The current data store implementation | 1415 // Note: |builder| will not be empty. The current data store implementation |
1256 // stores all full-length hashes as both full and prefix hashes. | 1416 // stores all full-length hashes as both full and prefix hashes. |
1257 safe_browsing::PrefixSetBuilder builder; | 1417 PrefixSetBuilder builder; |
1258 std::vector<SBAddFullHash> full_hashes; | 1418 std::vector<SBAddFullHash> full_hashes; |
1259 if (!store->FinishUpdate(&builder, &full_hashes)) { | 1419 if (!store->FinishUpdate(&builder, &full_hashes)) { |
1260 RecordFailure(FAILURE_WHITELIST_DATABASE_UPDATE_FINISH); | 1420 RecordFailure(FAILURE_WHITELIST_DATABASE_UPDATE_FINISH); |
1261 WhitelistEverything(whitelist); | 1421 state_manager_.BeginWriteTransaction()->WhitelistEverything(whitelist_id); |
1262 return; | 1422 return; |
1263 } | 1423 } |
1264 | 1424 |
1265 #if defined(OS_MACOSX) | 1425 #if defined(OS_MACOSX) |
1266 base::mac::SetFileBackupExclusion(store_filename); | 1426 base::mac::SetFileBackupExclusion(store_filename); |
1267 #endif | 1427 #endif |
1268 | 1428 |
1269 LoadWhitelist(full_hashes, whitelist); | 1429 LoadWhitelist(full_hashes, whitelist_id); |
1270 } | 1430 } |
1271 | 1431 |
1272 int64 SafeBrowsingDatabaseNew::UpdateHashPrefixStore( | 1432 int64 SafeBrowsingDatabaseNew::UpdateHashPrefixStore( |
1273 const base::FilePath& store_filename, | 1433 const base::FilePath& store_filename, |
1274 SafeBrowsingStore* store, | 1434 SafeBrowsingStore* store, |
1275 FailureType failure_type) { | 1435 FailureType failure_type) { |
1276 DCHECK(thread_checker_.CalledOnValidThread()); | 1436 DCHECK(thread_checker_.CalledOnValidThread()); |
1277 | 1437 |
1278 // These results are not used after this call. Simply ignore the | 1438 // These results are not used after this call. Simply ignore the |
1279 // returned value after FinishUpdate(...). | 1439 // returned value after FinishUpdate(...). |
1280 safe_browsing::PrefixSetBuilder builder; | 1440 PrefixSetBuilder builder; |
1281 std::vector<SBAddFullHash> add_full_hashes_result; | 1441 std::vector<SBAddFullHash> add_full_hashes_result; |
1282 | 1442 |
1283 if (!store->FinishUpdate(&builder, &add_full_hashes_result)) | 1443 if (!store->FinishUpdate(&builder, &add_full_hashes_result)) |
1284 RecordFailure(failure_type); | 1444 RecordFailure(failure_type); |
1285 | 1445 |
1286 #if defined(OS_MACOSX) | 1446 #if defined(OS_MACOSX) |
1287 base::mac::SetFileBackupExclusion(store_filename); | 1447 base::mac::SetFileBackupExclusion(store_filename); |
1288 #endif | 1448 #endif |
1289 | 1449 |
1290 return GetFileSizeOrZero(store_filename); | 1450 return GetFileSizeOrZero(store_filename); |
1291 } | 1451 } |
1292 | 1452 |
1293 void SafeBrowsingDatabaseNew::UpdatePrefixSetUrlStore( | 1453 void SafeBrowsingDatabaseNew::UpdatePrefixSetUrlStore( |
1294 const base::FilePath& db_filename, | 1454 const base::FilePath& db_filename, |
1295 SafeBrowsingStore* url_store, | 1455 SafeBrowsingStore* url_store, |
1296 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, | 1456 PrefixSetId prefix_set_id, |
1297 FailureType finish_failure_type, | 1457 FailureType finish_failure_type, |
1298 FailureType write_failure_type, | 1458 FailureType write_failure_type, |
1299 bool store_full_hashes_in_prefix_set) { | 1459 bool store_full_hashes_in_prefix_set) { |
1300 DCHECK(thread_checker_.CalledOnValidThread()); | 1460 DCHECK(thread_checker_.CalledOnValidThread()); |
1301 DCHECK(url_store); | 1461 DCHECK(url_store); |
1302 DCHECK(prefix_set); | |
1303 | 1462 |
1304 // Measure the amount of IO during the filter build. | 1463 // Measure the amount of IO during the filter build. |
1305 base::IoCounters io_before, io_after; | 1464 base::IoCounters io_before, io_after; |
1306 base::ProcessHandle handle = base::GetCurrentProcessHandle(); | 1465 base::ProcessHandle handle = base::GetCurrentProcessHandle(); |
1307 scoped_ptr<base::ProcessMetrics> metric( | 1466 scoped_ptr<base::ProcessMetrics> metric( |
1308 #if !defined(OS_MACOSX) | 1467 #if !defined(OS_MACOSX) |
1309 base::ProcessMetrics::CreateProcessMetrics(handle) | 1468 base::ProcessMetrics::CreateProcessMetrics(handle) |
1310 #else | 1469 #else |
1311 // Getting stats only for the current process is enough, so NULL is fine. | 1470 // Getting stats only for the current process is enough, so NULL is fine. |
1312 base::ProcessMetrics::CreateProcessMetrics(handle, NULL) | 1471 base::ProcessMetrics::CreateProcessMetrics(handle, NULL) |
1313 #endif | 1472 #endif |
1314 ); | 1473 ); |
1315 | 1474 |
1316 // IoCounters are currently not supported on Mac, and may not be | 1475 // IoCounters are currently not supported on Mac, and may not be |
1317 // available for Linux, so we check the result and only show IO | 1476 // available for Linux, so we check the result and only show IO |
1318 // stats if they are available. | 1477 // stats if they are available. |
1319 const bool got_counters = metric->GetIOCounters(&io_before); | 1478 const bool got_counters = metric->GetIOCounters(&io_before); |
1320 | 1479 |
1321 const base::TimeTicks before = base::TimeTicks::Now(); | 1480 const base::TimeTicks before = base::TimeTicks::Now(); |
1322 | 1481 |
1323 // TODO(shess): Perhaps refactor to let builder accumulate full hashes on the | 1482 // TODO(shess): Perhaps refactor to let builder accumulate full hashes on the |
1324 // fly? Other clients use the SBAddFullHash vector, but AFAICT they only use | 1483 // fly? Other clients use the SBAddFullHash vector, but AFAICT they only use |
1325 // the SBFullHash portion. It would need an accessor on PrefixSet. | 1484 // the SBFullHash portion. It would need an accessor on PrefixSet. |
1326 safe_browsing::PrefixSetBuilder builder; | 1485 PrefixSetBuilder builder; |
1327 std::vector<SBAddFullHash> add_full_hashes; | 1486 std::vector<SBAddFullHash> add_full_hashes; |
1328 if (!url_store->FinishUpdate(&builder, &add_full_hashes)) { | 1487 if (!url_store->FinishUpdate(&builder, &add_full_hashes)) { |
1329 RecordFailure(finish_failure_type); | 1488 RecordFailure(finish_failure_type); |
1330 return; | 1489 return; |
1331 } | 1490 } |
1332 | 1491 |
1333 scoped_ptr<const safe_browsing::PrefixSet> new_prefix_set; | 1492 scoped_ptr<const PrefixSet> new_prefix_set; |
1334 if (store_full_hashes_in_prefix_set) { | 1493 if (store_full_hashes_in_prefix_set) { |
1335 std::vector<SBFullHash> full_hash_results; | 1494 std::vector<SBFullHash> full_hash_results; |
1336 for (size_t i = 0; i < add_full_hashes.size(); ++i) { | 1495 for (size_t i = 0; i < add_full_hashes.size(); ++i) { |
1337 full_hash_results.push_back(add_full_hashes[i].full_hash); | 1496 full_hash_results.push_back(add_full_hashes[i].full_hash); |
1338 } | 1497 } |
1339 | 1498 |
1340 new_prefix_set = builder.GetPrefixSet(full_hash_results); | 1499 new_prefix_set = builder.GetPrefixSet(full_hash_results); |
1341 } else { | 1500 } else { |
1342 // TODO(gab): Ensure that stores which do not want full hashes just don't | 1501 // TODO(gab): Ensure that stores which do not want full hashes just don't |
1343 // have full hashes in the first place and remove | 1502 // have full hashes in the first place and remove |
1344 // |store_full_hashes_in_prefix_set| and the code specialization incurred | 1503 // |store_full_hashes_in_prefix_set| and the code specialization incurred |
1345 // here. | 1504 // here. |
1346 new_prefix_set = builder.GetPrefixSetNoHashes(); | 1505 new_prefix_set = builder.GetPrefixSetNoHashes(); |
1347 } | 1506 } |
1348 | 1507 |
1349 // Swap in the newly built filter. | 1508 // Swap in the newly built filter. |
1350 { | 1509 state_manager_.BeginWriteTransaction()->SwapPrefixSet(prefix_set_id, |
1351 base::AutoLock locked(lookup_lock_); | 1510 new_prefix_set.Pass()); |
1352 prefix_set->swap(new_prefix_set); | |
1353 } | |
1354 | 1511 |
1355 UMA_HISTOGRAM_LONG_TIMES("SB2.BuildFilter", base::TimeTicks::Now() - before); | 1512 UMA_HISTOGRAM_LONG_TIMES("SB2.BuildFilter", base::TimeTicks::Now() - before); |
1356 | 1513 |
1357 // Persist the prefix set to disk. Note: there is no need to lock since the | 1514 { |
1358 // only write to |*prefix_set| is on this thread (in the swap() above). | 1515 // Persist the prefix set to disk. Do not grab the lock to avoid contention |
1359 WritePrefixSet(db_filename, prefix_set->get(), write_failure_type); | 1516 // while writing to disk. This is safe as only this thread can ever modify |
1517 // |state_manager_|'s prefix sets anyways. | |
1518 scoped_ptr<ReadTransaction> txn = | |
1519 state_manager_.BeginReadTransactionNoLockOnMainThread(); | |
1520 WritePrefixSet(db_filename, txn->GetPrefixSet(prefix_set_id), | |
1521 write_failure_type); | |
1522 } | |
1360 | 1523 |
1361 // Gather statistics. | 1524 // Gather statistics. |
1362 if (got_counters && metric->GetIOCounters(&io_after)) { | 1525 if (got_counters && metric->GetIOCounters(&io_after)) { |
1363 UMA_HISTOGRAM_COUNTS("SB2.BuildReadKilobytes", | 1526 UMA_HISTOGRAM_COUNTS("SB2.BuildReadKilobytes", |
1364 static_cast<int>(io_after.ReadTransferCount - | 1527 static_cast<int>(io_after.ReadTransferCount - |
1365 io_before.ReadTransferCount) / 1024); | 1528 io_before.ReadTransferCount) / 1024); |
1366 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteKilobytes", | 1529 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteKilobytes", |
1367 static_cast<int>(io_after.WriteTransferCount - | 1530 static_cast<int>(io_after.WriteTransferCount - |
1368 io_before.WriteTransferCount) / 1024); | 1531 io_before.WriteTransferCount) / 1024); |
1369 UMA_HISTOGRAM_COUNTS("SB2.BuildReadOperations", | 1532 UMA_HISTOGRAM_COUNTS("SB2.BuildReadOperations", |
(...skipping 11 matching lines...) Expand all Loading... | |
1381 #if defined(OS_MACOSX) | 1544 #if defined(OS_MACOSX) |
1382 base::mac::SetFileBackupExclusion(db_filename); | 1545 base::mac::SetFileBackupExclusion(db_filename); |
1383 #endif | 1546 #endif |
1384 } | 1547 } |
1385 | 1548 |
1386 void SafeBrowsingDatabaseNew::UpdateIpBlacklistStore() { | 1549 void SafeBrowsingDatabaseNew::UpdateIpBlacklistStore() { |
1387 DCHECK(thread_checker_.CalledOnValidThread()); | 1550 DCHECK(thread_checker_.CalledOnValidThread()); |
1388 | 1551 |
1389 // Note: prefixes will not be empty. The current data store implementation | 1552 // Note: prefixes will not be empty. The current data store implementation |
1390 // stores all full-length hashes as both full and prefix hashes. | 1553 // stores all full-length hashes as both full and prefix hashes. |
1391 safe_browsing::PrefixSetBuilder builder; | 1554 PrefixSetBuilder builder; |
1392 std::vector<SBAddFullHash> full_hashes; | 1555 std::vector<SBAddFullHash> full_hashes; |
1393 if (!ip_blacklist_store_->FinishUpdate(&builder, &full_hashes)) { | 1556 if (!ip_blacklist_store_->FinishUpdate(&builder, &full_hashes)) { |
1394 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_FINISH); | 1557 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_FINISH); |
1395 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. | 1558 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. |
1396 return; | 1559 return; |
1397 } | 1560 } |
1398 | 1561 |
1399 #if defined(OS_MACOSX) | 1562 #if defined(OS_MACOSX) |
1400 base::mac::SetFileBackupExclusion(IpBlacklistDBFilename(filename_base_)); | 1563 base::mac::SetFileBackupExclusion(IpBlacklistDBFilename(filename_base_)); |
1401 #endif | 1564 #endif |
(...skipping 23 matching lines...) Expand all Loading... | |
1425 | 1588 |
1426 // NOTE(shess): ResetDatabase() should remove the corruption, so this should | 1589 // NOTE(shess): ResetDatabase() should remove the corruption, so this should |
1427 // only happen once. If you are here because you are hitting this after a | 1590 // only happen once. If you are here because you are hitting this after a |
1428 // restart, then I would be very interested in working with you to figure out | 1591 // restart, then I would be very interested in working with you to figure out |
1429 // what is happening, since it may affect real users. | 1592 // what is happening, since it may affect real users. |
1430 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; | 1593 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; |
1431 } | 1594 } |
1432 | 1595 |
1433 // TODO(shess): I'm not clear why this code doesn't have any | 1596 // TODO(shess): I'm not clear why this code doesn't have any |
1434 // real error-handling. | 1597 // real error-handling. |
1435 void SafeBrowsingDatabaseNew::LoadPrefixSet( | 1598 void SafeBrowsingDatabaseNew::LoadPrefixSet(const base::FilePath& db_filename, |
1436 const base::FilePath& db_filename, | 1599 WriteTransaction* txn, |
1437 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, | 1600 PrefixSetId prefix_set_id, |
1438 FailureType read_failure_type) { | 1601 FailureType read_failure_type) { |
1439 DCHECK(thread_checker_.CalledOnValidThread()); | 1602 DCHECK(thread_checker_.CalledOnValidThread()); |
1440 | 1603 DCHECK(txn); |
1441 if (!prefix_set) | |
1442 return; | |
1443 | |
1444 DCHECK(!filename_base_.empty()); | 1604 DCHECK(!filename_base_.empty()); |
1445 | 1605 |
1446 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); | |
1447 | |
1448 // Only use the prefix set if database is present and non-empty. | 1606 // Only use the prefix set if database is present and non-empty. |
1449 if (!GetFileSizeOrZero(db_filename)) | 1607 if (!GetFileSizeOrZero(db_filename)) |
1450 return; | 1608 return; |
1451 | 1609 |
1452 // Cleanup any stale bloom filter (no longer used). | 1610 // Cleanup any stale bloom filter (no longer used). |
1453 // TODO(shess): Track existence to drive removal of this code? | 1611 // TODO(shess): Track existence to drive removal of this code? |
1454 const base::FilePath bloom_filter_filename = | 1612 const base::FilePath bloom_filter_filename = |
1455 BloomFilterForFilename(db_filename); | 1613 BloomFilterForFilename(db_filename); |
1456 base::DeleteFile(bloom_filter_filename, false); | 1614 base::DeleteFile(bloom_filter_filename, false); |
1457 | 1615 |
1458 const base::TimeTicks before = base::TimeTicks::Now(); | 1616 const base::TimeTicks before = base::TimeTicks::Now(); |
1459 *prefix_set = safe_browsing::PrefixSet::LoadFile(prefix_set_filename); | 1617 scoped_ptr<const PrefixSet> new_prefix_set = |
1618 PrefixSet::LoadFile(PrefixSetForFilename(db_filename)); | |
1619 if (!new_prefix_set.get()) | |
1620 RecordFailure(read_failure_type); | |
1621 txn->SwapPrefixSet(prefix_set_id, new_prefix_set.Pass()); | |
1460 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before); | 1622 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before); |
1461 | |
1462 if (!prefix_set->get()) | |
1463 RecordFailure(read_failure_type); | |
1464 } | 1623 } |
1465 | 1624 |
1466 bool SafeBrowsingDatabaseNew::Delete() { | 1625 bool SafeBrowsingDatabaseNew::Delete() { |
1467 DCHECK(thread_checker_.CalledOnValidThread()); | 1626 DCHECK(thread_checker_.CalledOnValidThread()); |
1468 DCHECK(!filename_base_.empty()); | 1627 DCHECK(!filename_base_.empty()); |
1469 | 1628 |
1470 // TODO(shess): This is a mess. SafeBrowsingFileStore::Delete() closes the | 1629 // TODO(shess): This is a mess. SafeBrowsingFileStore::Delete() closes the |
1471 // store before calling DeleteStore(). DeleteStore() deletes transient files | 1630 // store before calling DeleteStore(). DeleteStore() deletes transient files |
1472 // in addition to the main file. Probably all of these should be converted to | 1631 // in addition to the main file. Probably all of these should be converted to |
1473 // a helper which calls Delete() if the store exists, else DeleteStore() on | 1632 // a helper which calls Delete() if the store exists, else DeleteStore() on |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1536 RecordFailure(FAILURE_IP_BLACKLIST_DELETE); | 1695 RecordFailure(FAILURE_IP_BLACKLIST_DELETE); |
1537 | 1696 |
1538 const bool r11 = | 1697 const bool r11 = |
1539 base::DeleteFile(UnwantedSoftwareDBFilename(filename_base_), false); | 1698 base::DeleteFile(UnwantedSoftwareDBFilename(filename_base_), false); |
1540 if (!r11) | 1699 if (!r11) |
1541 RecordFailure(FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_DELETE); | 1700 RecordFailure(FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_DELETE); |
1542 | 1701 |
1543 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9 && r10 && r11; | 1702 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9 && r10 && r11; |
1544 } | 1703 } |
1545 | 1704 |
1546 void SafeBrowsingDatabaseNew::WritePrefixSet( | 1705 void SafeBrowsingDatabaseNew::WritePrefixSet(const base::FilePath& db_filename, |
1547 const base::FilePath& db_filename, | 1706 const PrefixSet* prefix_set, |
1548 const safe_browsing::PrefixSet* prefix_set, | 1707 FailureType write_failure_type) { |
1549 FailureType write_failure_type) { | |
1550 DCHECK(thread_checker_.CalledOnValidThread()); | 1708 DCHECK(thread_checker_.CalledOnValidThread()); |
1551 | 1709 |
1552 if (!prefix_set) | 1710 if (!prefix_set) |
1553 return; | 1711 return; |
1554 | 1712 |
1555 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); | 1713 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); |
1556 | 1714 |
1557 const base::TimeTicks before = base::TimeTicks::Now(); | 1715 const base::TimeTicks before = base::TimeTicks::Now(); |
1558 const bool write_ok = prefix_set->WriteFile(prefix_set_filename); | 1716 const bool write_ok = prefix_set->WriteFile(prefix_set_filename); |
1559 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before); | 1717 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before); |
1560 | 1718 |
1561 const int64 file_size = GetFileSizeOrZero(prefix_set_filename); | 1719 const int64 file_size = GetFileSizeOrZero(prefix_set_filename); |
1562 UMA_HISTOGRAM_COUNTS("SB2.PrefixSetKilobytes", | 1720 UMA_HISTOGRAM_COUNTS("SB2.PrefixSetKilobytes", |
1563 static_cast<int>(file_size / 1024)); | 1721 static_cast<int>(file_size / 1024)); |
1564 | 1722 |
1565 if (!write_ok) | 1723 if (!write_ok) |
1566 RecordFailure(write_failure_type); | 1724 RecordFailure(write_failure_type); |
1567 | 1725 |
1568 #if defined(OS_MACOSX) | 1726 #if defined(OS_MACOSX) |
1569 base::mac::SetFileBackupExclusion(prefix_set_filename); | 1727 base::mac::SetFileBackupExclusion(prefix_set_filename); |
1570 #endif | 1728 #endif |
1571 } | 1729 } |
1572 | 1730 |
1573 void SafeBrowsingDatabaseNew::WhitelistEverything(SBWhitelist* whitelist) { | |
1574 DCHECK(thread_checker_.CalledOnValidThread()); | |
1575 base::AutoLock locked(lookup_lock_); | |
1576 whitelist->second = true; | |
1577 whitelist->first.clear(); | |
1578 } | |
1579 | |
1580 void SafeBrowsingDatabaseNew::LoadWhitelist( | 1731 void SafeBrowsingDatabaseNew::LoadWhitelist( |
1581 const std::vector<SBAddFullHash>& full_hashes, | 1732 const std::vector<SBAddFullHash>& full_hashes, |
1582 SBWhitelist* whitelist) { | 1733 SBWhitelistId whitelist_id) { |
1583 DCHECK(thread_checker_.CalledOnValidThread()); | 1734 DCHECK(thread_checker_.CalledOnValidThread()); |
1584 | 1735 |
1585 if (full_hashes.size() > kMaxWhitelistSize) { | 1736 if (full_hashes.size() > kMaxWhitelistSize) { |
1586 WhitelistEverything(whitelist); | 1737 state_manager_.BeginWriteTransaction()->WhitelistEverything(whitelist_id); |
1587 return; | 1738 return; |
1588 } | 1739 } |
1589 | 1740 |
1590 std::vector<SBFullHash> new_whitelist; | 1741 scoped_ptr<std::vector<SBFullHash>> new_whitelist( |
1591 new_whitelist.reserve(full_hashes.size()); | 1742 new std::vector<SBFullHash>); |
1743 new_whitelist->reserve(full_hashes.size()); | |
1592 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); | 1744 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); |
1593 it != full_hashes.end(); ++it) { | 1745 it != full_hashes.end(); ++it) { |
1594 new_whitelist.push_back(it->full_hash); | 1746 new_whitelist->push_back(it->full_hash); |
1595 } | 1747 } |
1596 std::sort(new_whitelist.begin(), new_whitelist.end(), SBFullHashLess); | 1748 std::sort(new_whitelist->begin(), new_whitelist->end(), SBFullHashLess); |
1597 | 1749 |
1598 SBFullHash kill_switch = SBFullHashForString(kWhitelistKillSwitchUrl); | 1750 SBFullHash kill_switch = SBFullHashForString(kWhitelistKillSwitchUrl); |
1599 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), | 1751 if (std::binary_search(new_whitelist->begin(), new_whitelist->end(), |
1600 kill_switch, SBFullHashLess)) { | 1752 kill_switch, SBFullHashLess)) { |
1601 // The kill switch is whitelisted hence we whitelist all URLs. | 1753 // The kill switch is whitelisted hence we whitelist all URLs. |
1602 WhitelistEverything(whitelist); | 1754 state_manager_.BeginWriteTransaction()->WhitelistEverything(whitelist_id); |
1603 } else { | 1755 } else { |
1604 base::AutoLock locked(lookup_lock_); | 1756 state_manager_.BeginWriteTransaction()->SwapSBWhitelist( |
1605 whitelist->second = false; | 1757 whitelist_id, new_whitelist.Pass()); |
1606 whitelist->first.swap(new_whitelist); | |
1607 } | 1758 } |
1608 } | 1759 } |
1609 | 1760 |
1610 void SafeBrowsingDatabaseNew::LoadIpBlacklist( | 1761 void SafeBrowsingDatabaseNew::LoadIpBlacklist( |
1611 const std::vector<SBAddFullHash>& full_hashes) { | 1762 const std::vector<SBAddFullHash>& full_hashes) { |
1612 DCHECK(thread_checker_.CalledOnValidThread()); | 1763 DCHECK(thread_checker_.CalledOnValidThread()); |
1613 | 1764 |
1614 IPBlacklist new_blacklist; | 1765 scoped_ptr<IPBlacklist> new_blacklist(new IPBlacklist); |
1615 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); | 1766 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); |
1616 it != full_hashes.end(); | 1767 it != full_hashes.end(); |
1617 ++it) { | 1768 ++it) { |
1618 const char* full_hash = it->full_hash.full_hash; | 1769 const char* full_hash = it->full_hash.full_hash; |
1619 DCHECK_EQ(crypto::kSHA256Length, arraysize(it->full_hash.full_hash)); | 1770 DCHECK_EQ(crypto::kSHA256Length, arraysize(it->full_hash.full_hash)); |
1620 // The format of the IP blacklist is: | 1771 // The format of the IP blacklist is: |
1621 // SHA-1(IPv6 prefix) + uint8(prefix size) + 11 unused bytes. | 1772 // SHA-1(IPv6 prefix) + uint8(prefix size) + 11 unused bytes. |
1622 std::string hashed_ip_prefix(full_hash, base::kSHA1Length); | 1773 std::string hashed_ip_prefix(full_hash, base::kSHA1Length); |
1623 size_t prefix_size = static_cast<uint8>(full_hash[base::kSHA1Length]); | 1774 size_t prefix_size = static_cast<uint8>(full_hash[base::kSHA1Length]); |
1624 if (prefix_size > kMaxIpPrefixSize || prefix_size < kMinIpPrefixSize) { | 1775 if (prefix_size > kMaxIpPrefixSize || prefix_size < kMinIpPrefixSize) { |
1625 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_INVALID); | 1776 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_INVALID); |
1626 new_blacklist.clear(); // Load empty blacklist. | 1777 new_blacklist->clear(); // Load empty blacklist. |
1627 break; | 1778 break; |
1628 } | 1779 } |
1629 | 1780 |
1630 // We precompute the mask for the given subnet size to speed up lookups. | 1781 // We precompute the mask for the given subnet size to speed up lookups. |
1631 // Basically we need to create a 16B long string which has the highest | 1782 // Basically we need to create a 16B long string which has the highest |
1632 // |size| bits sets to one. | 1783 // |size| bits sets to one. |
1633 std::string mask(net::kIPv6AddressSize, '\0'); | 1784 std::string mask(net::kIPv6AddressSize, '\0'); |
1634 mask.replace(0, prefix_size / 8, prefix_size / 8, '\xFF'); | 1785 mask.replace(0, prefix_size / 8, prefix_size / 8, '\xFF'); |
1635 if ((prefix_size % 8) != 0) { | 1786 if ((prefix_size % 8) != 0) { |
1636 mask[prefix_size / 8] = 0xFF << (8 - (prefix_size % 8)); | 1787 mask[prefix_size / 8] = 0xFF << (8 - (prefix_size % 8)); |
1637 } | 1788 } |
1638 DVLOG(2) << "Inserting malicious IP: " | 1789 DVLOG(2) << "Inserting malicious IP: " |
1639 << " raw:" << base::HexEncode(full_hash, crypto::kSHA256Length) | 1790 << " raw:" << base::HexEncode(full_hash, crypto::kSHA256Length) |
1640 << " mask:" << base::HexEncode(mask.data(), mask.size()) | 1791 << " mask:" << base::HexEncode(mask.data(), mask.size()) |
1641 << " prefix_size:" << prefix_size | 1792 << " prefix_size:" << prefix_size |
1642 << " hashed_ip:" << base::HexEncode(hashed_ip_prefix.data(), | 1793 << " hashed_ip:" << base::HexEncode(hashed_ip_prefix.data(), |
1643 hashed_ip_prefix.size()); | 1794 hashed_ip_prefix.size()); |
1644 new_blacklist[mask].insert(hashed_ip_prefix); | 1795 (*new_blacklist)[mask].insert(hashed_ip_prefix); |
1645 } | 1796 } |
1646 | 1797 |
1647 base::AutoLock locked(lookup_lock_); | 1798 state_manager_.BeginWriteTransaction()->swap_ip_blacklist( |
1648 ip_blacklist_.swap(new_blacklist); | 1799 new_blacklist.Pass()); |
1649 } | 1800 } |
1650 | 1801 |
1651 bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() { | 1802 bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() { |
1652 SBFullHash malware_kill_switch = SBFullHashForString(kMalwareIPKillSwitchUrl); | 1803 SBFullHash malware_kill_switch = SBFullHashForString(kMalwareIPKillSwitchUrl); |
1653 std::vector<SBFullHash> full_hashes; | 1804 std::vector<SBFullHash> full_hashes; |
1654 full_hashes.push_back(malware_kill_switch); | 1805 full_hashes.push_back(malware_kill_switch); |
1655 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); | 1806 return ContainsWhitelistedHashes(SBWhitelistId::CSD, full_hashes); |
1656 } | 1807 } |
1657 | 1808 |
1658 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() { | 1809 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() { |
1659 base::AutoLock locked(lookup_lock_); | 1810 return state_manager_.BeginReadTransaction() |
1660 return csd_whitelist_.second; | 1811 ->GetSBWhitelist(SBWhitelistId::CSD) |
1812 ->second; | |
1661 } | 1813 } |
1814 | |
1815 SafeBrowsingDatabaseNew::PrefixGetHashCache* | |
1816 SafeBrowsingDatabaseNew::GetUnsynchronizedPrefixGetHashCacheForTesting() { | |
1817 return state_manager_.BeginReadTransaction()->prefix_gethash_cache(); | |
1818 } | |
OLD | NEW |