Chromium Code Reviews| 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 |