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

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

Issue 794273002: Introduce SafeBrowsingDatabase::ThreadSafeStateManager. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@a6_dedup_sideeffectfreeWLcode
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/safe_browsing/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
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 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 return base::FilePath(db_filename.value() + kIPBlacklistDBFile); 427 return base::FilePath(db_filename.value() + kIPBlacklistDBFile);
426 } 428 }
427 429
428 // static 430 // static
429 base::FilePath SafeBrowsingDatabase::UnwantedSoftwareDBFilename( 431 base::FilePath SafeBrowsingDatabase::UnwantedSoftwareDBFilename(
430 const base::FilePath& db_filename) { 432 const base::FilePath& db_filename) {
431 return base::FilePath(db_filename.value() + kUnwantedSoftwareDBFile); 433 return base::FilePath(db_filename.value() + kUnwantedSoftwareDBFile);
432 } 434 }
433 435
434 SafeBrowsingStore* SafeBrowsingDatabaseNew::GetStore(const int list_id) { 436 SafeBrowsingStore* SafeBrowsingDatabaseNew::GetStore(const int list_id) {
435 // Stores are not thread safe.
436 DCHECK(thread_checker_.CalledOnValidThread());
437
438 if (list_id == safe_browsing_util::PHISH || 437 if (list_id == safe_browsing_util::PHISH ||
439 list_id == safe_browsing_util::MALWARE) { 438 list_id == safe_browsing_util::MALWARE) {
440 return browse_store_.get(); 439 return browse_store_.get();
441 } else if (list_id == safe_browsing_util::BINURL) { 440 } else if (list_id == safe_browsing_util::BINURL) {
442 return download_store_.get(); 441 return download_store_.get();
443 } else if (list_id == safe_browsing_util::CSDWHITELIST) { 442 } else if (list_id == safe_browsing_util::CSDWHITELIST) {
444 return csd_whitelist_store_.get(); 443 return csd_whitelist_store_.get();
445 } else if (list_id == safe_browsing_util::DOWNLOADWHITELIST) { 444 } else if (list_id == safe_browsing_util::DOWNLOADWHITELIST) {
446 return download_whitelist_store_.get(); 445 return download_whitelist_store_.get();
447 } else if (list_id == safe_browsing_util::EXTENSIONBLACKLIST) { 446 } else if (list_id == safe_browsing_util::EXTENSIONBLACKLIST) {
448 return extension_blacklist_store_.get(); 447 return extension_blacklist_store_.get();
449 } else if (list_id == safe_browsing_util::SIDEEFFECTFREEWHITELIST) { 448 } else if (list_id == safe_browsing_util::SIDEEFFECTFREEWHITELIST) {
450 return side_effect_free_whitelist_store_.get(); 449 return side_effect_free_whitelist_store_.get();
451 } else if (list_id == safe_browsing_util::IPBLACKLIST) { 450 } else if (list_id == safe_browsing_util::IPBLACKLIST) {
452 return ip_blacklist_store_.get(); 451 return ip_blacklist_store_.get();
453 } else if (list_id == safe_browsing_util::UNWANTEDURL) { 452 } else if (list_id == safe_browsing_util::UNWANTEDURL) {
454 return unwanted_software_store_.get(); 453 return unwanted_software_store_.get();
455 } 454 }
456 return NULL; 455 return NULL;
457 } 456 }
458 457
459 // static 458 // static
460 void SafeBrowsingDatabase::RecordFailure(FailureType failure_type) { 459 void SafeBrowsingDatabase::RecordFailure(FailureType failure_type) {
461 UMA_HISTOGRAM_ENUMERATION("SB2.DatabaseFailure", failure_type, 460 UMA_HISTOGRAM_ENUMERATION("SB2.DatabaseFailure", failure_type,
462 FAILURE_DATABASE_MAX); 461 FAILURE_DATABASE_MAX);
463 } 462 }
464 463
464 class SafeBrowsingDatabaseNew::ThreadSafeStateManager::ReadTransaction {
465 public:
466 enum class AutoLockRequirement {
467 LOCK,
468 // SBWhitelist's, IPBlacklist's, and PrefixSet's (not caches) are only
469 // ever written to on the main thread (as enforced by
470 // ThreadSafeStateManager) and can therefore be read on the main thread
471 // without first acquiring |lock_|.
472 DONT_LOCK_ON_MAIN_THREAD
473 };
474
475 ReadTransaction(ThreadSafeStateManager* outer,
mattm 2014/12/12 23:20:30 Maybe ReadTransaction can take a const pointer to
gab 2014/12/15 23:02:30 It could but |prefix_gethash_cache_| would also ha
mattm 2014/12/23 02:09:45 Hm, good point. It kinda seems like prefix_gethash
gab 2014/12/23 21:39:54 Agree that it's kind-of weird to write to the cach
mattm 2014/12/24 00:29:53 Not coming up with anything.. I guess this is okay
476 AutoLockRequirement auto_lock_requirement)
477 : outer_(outer) {
478 if (auto_lock_requirement == AutoLockRequirement::LOCK)
479 transaction_lock_.reset(new base::AutoLock(outer_->lock_));
480 else
481 DCHECK(outer_->thread_checker_.CalledOnValidThread());
482 }
483
484 const SBWhitelist* GetSBWhitelist(SBWhitelistId id) {
485 switch (id) {
486 case SBWhitelistId::CSD:
487 return &outer_->csd_whitelist_;
488 case SBWhitelistId::DOWNLOAD:
489 return &outer_->download_whitelist_;
490 }
491 NOTREACHED();
492 return nullptr;
493 }
494
495 const IPBlacklist* ip_blacklist() { return &outer_->ip_blacklist_; }
496
497 const PrefixSet* GetPrefixSet(PrefixSetId id) {
498 switch (id) {
499 case PrefixSetId::BROWSE:
500 return outer_->browse_prefix_set_.get();
501 case PrefixSetId::SIDE_EFFECT_FREE_WHITELIST:
502 return outer_->side_effect_free_whitelist_prefix_set_.get();
503 case PrefixSetId::UNWANTED_SOFTWARE:
504 return outer_->unwanted_software_prefix_set_.get();
505 }
506 NOTREACHED();
507 return nullptr;
508 }
509
510 PrefixGetHashCache* prefix_gethash_cache() {
511 // The cache is special: it is read/write on all threads. Access to it
512 // therefore requires a LOCK'ed transaction (i.e. it can't benefit from
513 // DONT_LOCK_ON_MAIN_THREAD).
514 DCHECK(transaction_lock_);
515 return &outer_->prefix_gethash_cache_;
516 }
517
518 private:
519 ThreadSafeStateManager* outer_;
520 scoped_ptr<base::AutoLock> transaction_lock_;
521
522 DISALLOW_COPY_AND_ASSIGN(ReadTransaction);
523 };
524
525 class SafeBrowsingDatabaseNew::ThreadSafeStateManager::WriteTransaction {
526 public:
527 explicit WriteTransaction(ThreadSafeStateManager* outer)
528 : outer_(outer), transaction_lock_(outer_->lock_) {
529 DCHECK(outer_->thread_checker_.CalledOnValidThread());
530 }
531
532 SBWhitelist* GetWritableSBWhitelist(SBWhitelistId id) {
533 switch (id) {
534 case SBWhitelistId::CSD:
535 return &outer_->csd_whitelist_;
536 case SBWhitelistId::DOWNLOAD:
537 return &outer_->download_whitelist_;
538 }
539 NOTREACHED();
540 return nullptr;
541 }
542
543 IPBlacklist* writable_ip_blacklist() { return &outer_->ip_blacklist_; }
544
545 void SwapPrefixSet(PrefixSetId id,
546 scoped_ptr<const PrefixSet> new_prefix_set) {
547 switch (id) {
548 case PrefixSetId::BROWSE:
549 outer_->browse_prefix_set_.swap(new_prefix_set);
550 break;
551 case PrefixSetId::SIDE_EFFECT_FREE_WHITELIST:
552 outer_->side_effect_free_whitelist_prefix_set_.swap(new_prefix_set);
553 break;
554 case PrefixSetId::UNWANTED_SOFTWARE:
555 outer_->unwanted_software_prefix_set_.swap(new_prefix_set);
556 break;
557 }
558 }
559
560 void clear_prefix_gethash_cache() { outer_->prefix_gethash_cache_.clear(); }
561
562 private:
563 ThreadSafeStateManager* outer_;
564 base::AutoLock transaction_lock_;
565
566 DISALLOW_COPY_AND_ASSIGN(WriteTransaction);
567 };
568
569 SafeBrowsingDatabaseNew::ThreadSafeStateManager::ThreadSafeStateManager() {
570 }
571 SafeBrowsingDatabaseNew::ThreadSafeStateManager::~ThreadSafeStateManager() {
572 }
573
574 scoped_ptr<SafeBrowsingDatabaseNew::ReadTransaction>
575 SafeBrowsingDatabaseNew::ThreadSafeStateManager::BeginReadTransaction() {
576 return make_scoped_ptr(
577 new ReadTransaction(this, ReadTransaction::AutoLockRequirement::LOCK));
578 }
579
580 scoped_ptr<SafeBrowsingDatabaseNew::ReadTransaction> SafeBrowsingDatabaseNew::
581 ThreadSafeStateManager::BeginReadTransactionNoLockOnMainThread() {
582 return make_scoped_ptr(new ReadTransaction(
583 this, ReadTransaction::AutoLockRequirement::DONT_LOCK_ON_MAIN_THREAD));
584 }
585
586 scoped_ptr<SafeBrowsingDatabaseNew::WriteTransaction>
587 SafeBrowsingDatabaseNew::ThreadSafeStateManager::BeginWriteTransaction() {
588 return make_scoped_ptr(new WriteTransaction(this));
589 }
590
465 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew() 591 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew()
466 : SafeBrowsingDatabaseNew(new SafeBrowsingStoreFile, 592 : SafeBrowsingDatabaseNew(new SafeBrowsingStoreFile,
467 NULL, 593 NULL,
468 NULL, 594 NULL,
469 NULL, 595 NULL,
470 NULL, 596 NULL,
471 NULL, 597 NULL,
472 NULL, 598 NULL,
473 NULL) { 599 NULL) {
474 DCHECK(browse_store_.get()); 600 DCHECK(browse_store_.get());
(...skipping 23 matching lines...) Expand all
498 side_effect_free_whitelist_store_(side_effect_free_whitelist_store), 624 side_effect_free_whitelist_store_(side_effect_free_whitelist_store),
499 ip_blacklist_store_(ip_blacklist_store), 625 ip_blacklist_store_(ip_blacklist_store),
500 unwanted_software_store_(unwanted_software_store), 626 unwanted_software_store_(unwanted_software_store),
501 corruption_detected_(false), 627 corruption_detected_(false),
502 change_detected_(false), 628 change_detected_(false),
503 reset_factory_(this) { 629 reset_factory_(this) {
504 DCHECK(browse_store_.get()); 630 DCHECK(browse_store_.get());
505 } 631 }
506 632
507 SafeBrowsingDatabaseNew::~SafeBrowsingDatabaseNew() { 633 SafeBrowsingDatabaseNew::~SafeBrowsingDatabaseNew() {
508 // The DCHECK is disabled due to crbug.com/338486 .
509 // DCHECK(thread_checker_.CalledOnValidThread());
gab 2014/12/11 19:39:20 This DCHECK is still covered by making SafeBrowsin
510 } 634 }
511 635
512 void SafeBrowsingDatabaseNew::Init(const base::FilePath& filename_base) { 636 void SafeBrowsingDatabaseNew::Init(const base::FilePath& filename_base) {
513 DCHECK(thread_checker_.CalledOnValidThread());
514
515 // This should not be run multiple times. 637 // This should not be run multiple times.
516 DCHECK(filename_base_.empty()); 638 DCHECK(filename_base_.empty());
517 639
518 filename_base_ = filename_base; 640 filename_base_ = filename_base;
519 641
520 // TODO(shess): The various stores are really only necessary while doing 642 // TODO(shess): The various stores are really only necessary while doing
521 // updates (see |UpdateFinished()|) or when querying a store directly (see 643 // updates (see |UpdateFinished()|) or when querying a store directly (see
522 // |ContainsDownloadUrl()|). 644 // |ContainsDownloadUrl()|).
523 // The store variables are also tested to see if a list is enabled. Perhaps 645 // 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 646 // 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 647 // live in memory while being actively used. The sense of enabled probably
526 // belongs in protocol_manager or database_manager. 648 // belongs in protocol_manager or database_manager.
527 649
528 browse_store_->Init( 650 {
529 BrowseDBFilename(filename_base_), 651 // NOTE: A transaction here is overkill as there are no pointers to this
530 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, 652 // class on other threads until this function returns, but it's also
531 base::Unretained(this))); 653 // harmless as that also means there is no possibility of contention on the
654 // lock.
655 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction();
532 656
533 if (unwanted_software_store_.get()) { 657 txn->clear_prefix_gethash_cache();
534 unwanted_software_store_->Init( 658
535 UnwantedSoftwareDBFilename(filename_base_), 659 browse_store_->Init(
660 BrowseDBFilename(filename_base_),
536 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, 661 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase,
537 base::Unretained(this))); 662 base::Unretained(this)));
538 }
539 663
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()) { 664 if (unwanted_software_store_.get()) {
551 LoadPrefixSet(UnwantedSoftwareDBFilename(filename_base_), 665 unwanted_software_store_->Init(
552 &unwanted_software_prefix_set_, 666 UnwantedSoftwareDBFilename(filename_base_),
667 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase,
668 base::Unretained(this)));
669 }
670 LoadPrefixSet(BrowseDBFilename(filename_base_), txn.get(),
671 PrefixSetId::BROWSE, FAILURE_BROWSE_PREFIX_SET_READ);
672 if (unwanted_software_store_.get()) {
673 LoadPrefixSet(UnwantedSoftwareDBFilename(filename_base_), txn.get(),
674 PrefixSetId::UNWANTED_SOFTWARE,
553 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_READ); 675 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_READ);
554 } 676 }
677
678 if (side_effect_free_whitelist_store_.get()) {
679 const base::FilePath side_effect_free_whitelist_filename =
680 SideEffectFreeWhitelistDBFilename(filename_base_);
681 side_effect_free_whitelist_store_->Init(
682 side_effect_free_whitelist_filename,
683 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase,
684 base::Unretained(this)));
685
686 LoadPrefixSet(side_effect_free_whitelist_filename, txn.get(),
687 PrefixSetId::SIDE_EFFECT_FREE_WHITELIST,
688 FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_READ);
689 } else {
690 // Delete any files of the side-effect free sidelist that may be around
691 // from when it was previously enabled.
692 SafeBrowsingStoreFile::DeleteStore(
693 SideEffectFreeWhitelistDBFilename(filename_base_));
694 base::DeleteFile(PrefixSetForFilename(
695 SideEffectFreeWhitelistDBFilename(filename_base_)),
696 false);
697 }
555 } 698 }
699 // Note: End the transaction early because LoadWhiteList() and
700 // WhitelistEverything() manage their own transactions.
556 701
557 if (download_store_.get()) { 702 if (download_store_.get()) {
558 download_store_->Init( 703 download_store_->Init(
559 DownloadDBFilename(filename_base_), 704 DownloadDBFilename(filename_base_),
560 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, 705 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase,
561 base::Unretained(this))); 706 base::Unretained(this)));
562 } 707 }
563 708
564 if (csd_whitelist_store_.get()) { 709 if (csd_whitelist_store_.get()) {
565 csd_whitelist_store_->Init( 710 csd_whitelist_store_->Init(
566 CsdWhitelistDBFilename(filename_base_), 711 CsdWhitelistDBFilename(filename_base_),
567 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, 712 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase,
568 base::Unretained(this))); 713 base::Unretained(this)));
569 714
570 std::vector<SBAddFullHash> full_hashes; 715 std::vector<SBAddFullHash> full_hashes;
571 if (csd_whitelist_store_->GetAddFullHashes(&full_hashes)) { 716 if (csd_whitelist_store_->GetAddFullHashes(&full_hashes)) {
572 LoadWhitelist(full_hashes, &csd_whitelist_); 717 LoadWhitelist(full_hashes, SBWhitelistId::CSD);
573 } else { 718 } else {
574 WhitelistEverything(&csd_whitelist_); 719 WhitelistEverything(SBWhitelistId::CSD);
575 } 720 }
576 } else { 721 } else {
577 WhitelistEverything(&csd_whitelist_); // Just to be safe. 722 WhitelistEverything(SBWhitelistId::CSD); // Just to be safe.
578 } 723 }
579 724
580 if (download_whitelist_store_.get()) { 725 if (download_whitelist_store_.get()) {
581 download_whitelist_store_->Init( 726 download_whitelist_store_->Init(
582 DownloadWhitelistDBFilename(filename_base_), 727 DownloadWhitelistDBFilename(filename_base_),
583 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, 728 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase,
584 base::Unretained(this))); 729 base::Unretained(this)));
585 730
586 std::vector<SBAddFullHash> full_hashes; 731 std::vector<SBAddFullHash> full_hashes;
587 if (download_whitelist_store_->GetAddFullHashes(&full_hashes)) { 732 if (download_whitelist_store_->GetAddFullHashes(&full_hashes)) {
588 LoadWhitelist(full_hashes, &download_whitelist_); 733 LoadWhitelist(full_hashes, SBWhitelistId::DOWNLOAD);
589 } else { 734 } else {
590 WhitelistEverything(&download_whitelist_); 735 WhitelistEverything(SBWhitelistId::DOWNLOAD);
591 } 736 }
592 } else { 737 } else {
593 WhitelistEverything(&download_whitelist_); // Just to be safe. 738 WhitelistEverything(SBWhitelistId::DOWNLOAD); // Just to be safe.
594 } 739 }
595 740
596 if (extension_blacklist_store_.get()) { 741 if (extension_blacklist_store_.get()) {
597 extension_blacklist_store_->Init( 742 extension_blacklist_store_->Init(
598 ExtensionBlacklistDBFilename(filename_base_), 743 ExtensionBlacklistDBFilename(filename_base_),
599 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, 744 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase,
600 base::Unretained(this))); 745 base::Unretained(this)));
601 } 746 }
602 747
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()) { 748 if (ip_blacklist_store_.get()) {
625 ip_blacklist_store_->Init( 749 ip_blacklist_store_->Init(
626 IpBlacklistDBFilename(filename_base_), 750 IpBlacklistDBFilename(filename_base_),
627 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, 751 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase,
628 base::Unretained(this))); 752 base::Unretained(this)));
629 753
630 std::vector<SBAddFullHash> full_hashes; 754 std::vector<SBAddFullHash> full_hashes;
631 if (ip_blacklist_store_->GetAddFullHashes(&full_hashes)) { 755 if (ip_blacklist_store_->GetAddFullHashes(&full_hashes)) {
632 LoadIpBlacklist(full_hashes); 756 LoadIpBlacklist(full_hashes);
633 } else { 757 } else {
634 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. 758 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list.
635 } 759 }
636 } 760 }
637 } 761 }
638 762
639 bool SafeBrowsingDatabaseNew::ResetDatabase() { 763 bool SafeBrowsingDatabaseNew::ResetDatabase() {
640 DCHECK(thread_checker_.CalledOnValidThread());
641
642 // Delete files on disk. 764 // Delete files on disk.
643 // TODO(shess): Hard to see where one might want to delete without a 765 // TODO(shess): Hard to see where one might want to delete without a
644 // reset. Perhaps inline |Delete()|? 766 // reset. Perhaps inline |Delete()|?
645 if (!Delete()) 767 if (!Delete())
646 return false; 768 return false;
647 769
648 // Reset objects in memory. 770 // Reset objects in memory.
649 { 771 {
650 base::AutoLock locked(lookup_lock_); 772 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction();
651 prefix_gethash_cache_.clear(); 773 txn->clear_prefix_gethash_cache();
652 browse_prefix_set_.reset(); 774 txn->SwapPrefixSet(PrefixSetId::BROWSE, nullptr);
653 side_effect_free_whitelist_prefix_set_.reset(); 775 txn->SwapPrefixSet(PrefixSetId::SIDE_EFFECT_FREE_WHITELIST, nullptr);
654 ip_blacklist_.clear(); 776 txn->SwapPrefixSet(PrefixSetId::UNWANTED_SOFTWARE, nullptr);
655 unwanted_software_prefix_set_.reset(); 777 txn->writable_ip_blacklist()->clear();
656 } 778 }
657 // Wants to acquire the lock itself. 779 // Wants to acquire the lock itself.
mattm 2014/12/12 23:20:31 Why not make WhitelistEverything a method on Write
gab 2014/12/15 23:02:30 I debated that in lengths while writing this and h
mattm 2014/12/23 02:09:45 Well, you could one-line it like state_manager_.Be
gab 2014/12/23 21:39:54 Actually, I kind of like that and used it for a fe
658 WhitelistEverything(&csd_whitelist_); 780 WhitelistEverything(SBWhitelistId::CSD);
659 WhitelistEverything(&download_whitelist_); 781 WhitelistEverything(SBWhitelistId::DOWNLOAD);
660 return true; 782 return true;
661 } 783 }
662 784
663 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( 785 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl(
664 const GURL& url, 786 const GURL& url,
665 std::vector<SBPrefix>* prefix_hits, 787 std::vector<SBPrefix>* prefix_hits,
666 std::vector<SBFullHashResult>* cache_hits) { 788 std::vector<SBFullHashResult>* cache_hits) {
667 // This method is theoretically thread-safe but document that it is currently 789 return PrefixSetContainsUrl(url, PrefixSetId::BROWSE, prefix_hits,
668 // only expected to be called on the IO thread. 790 cache_hits);
669 DCHECK_CURRENTLY_ON(BrowserThread::IO);
670
671 return PrefixSetContainsUrl(
672 url, &browse_prefix_set_, prefix_hits, cache_hits);
673 } 791 }
674 792
675 bool SafeBrowsingDatabaseNew::ContainsUnwantedSoftwareUrl( 793 bool SafeBrowsingDatabaseNew::ContainsUnwantedSoftwareUrl(
676 const GURL& url, 794 const GURL& url,
677 std::vector<SBPrefix>* prefix_hits, 795 std::vector<SBPrefix>* prefix_hits,
678 std::vector<SBFullHashResult>* cache_hits) { 796 std::vector<SBFullHashResult>* cache_hits) {
679 // This method is theoretically thread-safe but document that it is currently 797 return PrefixSetContainsUrl(url, PrefixSetId::UNWANTED_SOFTWARE, prefix_hits,
680 // only expected to be called on the IO thread. 798 cache_hits);
681 DCHECK_CURRENTLY_ON(BrowserThread::IO);
682
683 return PrefixSetContainsUrl(
684 url, &unwanted_software_prefix_set_, prefix_hits, cache_hits);
685 } 799 }
686 800
687 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl( 801 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl(
688 const GURL& url, 802 const GURL& url,
689 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, 803 PrefixSetId prefix_set_id,
690 std::vector<SBPrefix>* prefix_hits, 804 std::vector<SBPrefix>* prefix_hits,
691 std::vector<SBFullHashResult>* cache_hits) { 805 std::vector<SBFullHashResult>* cache_hits) {
692 // This method is theoretically thread-safe but document that it is currently
693 // only expected to be called on the IO thread.
694 DCHECK_CURRENTLY_ON(BrowserThread::IO);
695
696 // Clear the results first. 806 // Clear the results first.
697 prefix_hits->clear(); 807 prefix_hits->clear();
698 cache_hits->clear(); 808 cache_hits->clear();
699 809
700 std::vector<SBFullHash> full_hashes; 810 std::vector<SBFullHash> full_hashes;
701 UrlToFullHashes(url, false, &full_hashes); 811 UrlToFullHashes(url, false, &full_hashes);
702 if (full_hashes.empty()) 812 if (full_hashes.empty())
703 return false; 813 return false;
704 814
705 return PrefixSetContainsUrlHashes( 815 return PrefixSetContainsUrlHashes(full_hashes, prefix_set_id, prefix_hits,
706 full_hashes, prefix_set_getter, prefix_hits, cache_hits); 816 cache_hits);
707 } 817 }
708 818
709 bool SafeBrowsingDatabaseNew::ContainsBrowseUrlHashesForTesting( 819 bool SafeBrowsingDatabaseNew::ContainsBrowseUrlHashesForTesting(
710 const std::vector<SBFullHash>& full_hashes, 820 const std::vector<SBFullHash>& full_hashes,
711 std::vector<SBPrefix>* prefix_hits, 821 std::vector<SBPrefix>* prefix_hits,
712 std::vector<SBFullHashResult>* cache_hits) { 822 std::vector<SBFullHashResult>* cache_hits) {
713 return PrefixSetContainsUrlHashes( 823 return PrefixSetContainsUrlHashes(full_hashes, PrefixSetId::BROWSE,
714 full_hashes, &browse_prefix_set_, prefix_hits, cache_hits); 824 prefix_hits, cache_hits);
715 } 825 }
716 826
717 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes( 827 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes(
718 const std::vector<SBFullHash>& full_hashes, 828 const std::vector<SBFullHash>& full_hashes,
719 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, 829 PrefixSetId prefix_set_id,
720 std::vector<SBPrefix>* prefix_hits, 830 std::vector<SBPrefix>* prefix_hits,
721 std::vector<SBFullHashResult>* cache_hits) { 831 std::vector<SBFullHashResult>* cache_hits) {
722 // This method is theoretically thread-safe but document that it is currently
723 // only expected to be called on the IO thread.
724 DCHECK_CURRENTLY_ON(BrowserThread::IO);
725
726 // Used to determine cache expiration. 832 // Used to determine cache expiration.
727 const base::Time now = base::Time::Now(); 833 const base::Time now = base::Time::Now();
728 834
729 base::AutoLock locked(lookup_lock_); 835 {
836 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction();
730 837
731 // |prefix_set| is empty until it is either read from disk, or the first 838 // |prefix_set| is empty until it is either read from disk, or the first
732 // update populates it. Bail out without a hit if not yet available. 839 // update populates it. Bail out without a hit if not yet available.
733 // |prefix_set_getter| can only be accessed while holding |lookup_lock_| hence 840 const PrefixSet* prefix_set = txn->GetPrefixSet(prefix_set_id);
734 // why it is passed as a parameter rather than passing the |prefix_set| 841 if (!prefix_set)
735 // directly. 842 return false;
736 const safe_browsing::PrefixSet* prefix_set = prefix_set_getter->get();
737 if (!prefix_set)
738 return false;
739 843
740 for (size_t i = 0; i < full_hashes.size(); ++i) { 844 for (size_t i = 0; i < full_hashes.size(); ++i) {
741 if (!GetCachedFullHash( 845 if (!GetCachedFullHash(txn->prefix_gethash_cache(), full_hashes[i], now,
742 &prefix_gethash_cache_, full_hashes[i], now, cache_hits)) { 846 cache_hits)) {
743 // No valid cached result, check the database. 847 // No valid cached result, check the database.
744 if (prefix_set->Exists(full_hashes[i])) 848 if (prefix_set->Exists(full_hashes[i]))
745 prefix_hits->push_back(full_hashes[i].prefix); 849 prefix_hits->push_back(full_hashes[i].prefix);
850 }
746 } 851 }
747 } 852 }
748 853
749 // Multiple full hashes could share prefix, remove duplicates. 854 // Multiple full hashes could share prefix, remove duplicates.
750 std::sort(prefix_hits->begin(), prefix_hits->end()); 855 std::sort(prefix_hits->begin(), prefix_hits->end());
751 prefix_hits->erase(std::unique(prefix_hits->begin(), prefix_hits->end()), 856 prefix_hits->erase(std::unique(prefix_hits->begin(), prefix_hits->end()),
752 prefix_hits->end()); 857 prefix_hits->end());
753 858
754 return !prefix_hits->empty() || !cache_hits->empty(); 859 return !prefix_hits->empty() || !cache_hits->empty();
755 } 860 }
756 861
757 bool SafeBrowsingDatabaseNew::ContainsDownloadUrl( 862 bool SafeBrowsingDatabaseNew::ContainsDownloadUrl(
758 const std::vector<GURL>& urls, 863 const std::vector<GURL>& urls,
759 std::vector<SBPrefix>* prefix_hits) { 864 std::vector<SBPrefix>* prefix_hits) {
760 DCHECK(thread_checker_.CalledOnValidThread());
mattm 2014/12/12 23:20:31 Why are all these removed?
gab 2014/12/15 23:02:30 Because |thread_checker_| moved to ThreadSafeState
761
762 // Ignore this check when download checking is not enabled. 865 // Ignore this check when download checking is not enabled.
763 if (!download_store_.get()) 866 if (!download_store_.get())
764 return false; 867 return false;
765 868
766 std::vector<SBPrefix> prefixes; 869 std::vector<SBPrefix> prefixes;
767 GetDownloadUrlPrefixes(urls, &prefixes); 870 GetDownloadUrlPrefixes(urls, &prefixes);
768 return MatchAddPrefixes(download_store_.get(), 871 return MatchAddPrefixes(download_store_.get(),
769 safe_browsing_util::BINURL % 2, 872 safe_browsing_util::BINURL % 2,
770 prefixes, 873 prefixes,
771 prefix_hits); 874 prefix_hits);
772 } 875 }
773 876
774 bool SafeBrowsingDatabaseNew::ContainsCsdWhitelistedUrl(const GURL& url) { 877 bool SafeBrowsingDatabaseNew::ContainsCsdWhitelistedUrl(const GURL& url) {
775 // This method is theoretically thread-safe but document that it is currently
776 // only expected to be called on the IO thread.
777 DCHECK_CURRENTLY_ON(BrowserThread::IO);
778
779 std::vector<SBFullHash> full_hashes; 878 std::vector<SBFullHash> full_hashes;
780 UrlToFullHashes(url, true, &full_hashes); 879 UrlToFullHashes(url, true, &full_hashes);
781 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); 880 return ContainsWhitelistedHashes(SBWhitelistId::CSD, full_hashes);
782 } 881 }
783 882
784 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) { 883 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) {
785 std::vector<SBFullHash> full_hashes; 884 std::vector<SBFullHash> full_hashes;
786 UrlToFullHashes(url, true, &full_hashes); 885 UrlToFullHashes(url, true, &full_hashes);
787 return ContainsWhitelistedHashes(download_whitelist_, full_hashes); 886 return ContainsWhitelistedHashes(SBWhitelistId::DOWNLOAD, full_hashes);
788 } 887 }
789 888
790 bool SafeBrowsingDatabaseNew::ContainsExtensionPrefixes( 889 bool SafeBrowsingDatabaseNew::ContainsExtensionPrefixes(
791 const std::vector<SBPrefix>& prefixes, 890 const std::vector<SBPrefix>& prefixes,
792 std::vector<SBPrefix>* prefix_hits) { 891 std::vector<SBPrefix>* prefix_hits) {
793 DCHECK(thread_checker_.CalledOnValidThread());
794
795 if (!extension_blacklist_store_) 892 if (!extension_blacklist_store_)
796 return false; 893 return false;
797 894
798 return MatchAddPrefixes(extension_blacklist_store_.get(), 895 return MatchAddPrefixes(extension_blacklist_store_.get(),
799 safe_browsing_util::EXTENSIONBLACKLIST % 2, 896 safe_browsing_util::EXTENSIONBLACKLIST % 2,
800 prefixes, 897 prefixes,
801 prefix_hits); 898 prefix_hits);
802 } 899 }
803 900
804 bool SafeBrowsingDatabaseNew::ContainsSideEffectFreeWhitelistUrl( 901 bool SafeBrowsingDatabaseNew::ContainsSideEffectFreeWhitelistUrl(
805 const GURL& url) { 902 const GURL& url) {
806 // This method is theoretically thread-safe but document that it is currently
807 // only expected to be called on the UI thread.
808 DCHECK_CURRENTLY_ON(BrowserThread::UI);
809
810 std::string host; 903 std::string host;
811 std::string path; 904 std::string path;
812 std::string query; 905 std::string query;
813 safe_browsing_util::CanonicalizeUrl(url, &host, &path, &query); 906 safe_browsing_util::CanonicalizeUrl(url, &host, &path, &query);
814 std::string url_to_check = host + path; 907 std::string url_to_check = host + path;
815 if (!query.empty()) 908 if (!query.empty())
816 url_to_check += "?" + query; 909 url_to_check += "?" + query;
817 SBFullHash full_hash = SBFullHashForString(url_to_check); 910 SBFullHash full_hash = SBFullHashForString(url_to_check);
818 911
819 base::AutoLock locked(lookup_lock_); 912 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction();
913
914 const PrefixSet* side_effect_free_whitelist_prefix_set =
915 txn->GetPrefixSet(PrefixSetId::SIDE_EFFECT_FREE_WHITELIST);
820 916
821 // |side_effect_free_whitelist_prefix_set_| is empty until it is either read 917 // |side_effect_free_whitelist_prefix_set_| is empty until it is either read
822 // from disk, or the first update populates it. Bail out without a hit if 918 // from disk, or the first update populates it. Bail out without a hit if
823 // not yet available. 919 // not yet available.
824 if (!side_effect_free_whitelist_prefix_set_.get()) 920 if (!side_effect_free_whitelist_prefix_set)
825 return false; 921 return false;
826 922
827 return side_effect_free_whitelist_prefix_set_->Exists(full_hash); 923 return side_effect_free_whitelist_prefix_set->Exists(full_hash);
828 } 924 }
829 925
830 bool SafeBrowsingDatabaseNew::ContainsMalwareIP(const std::string& ip_address) { 926 bool SafeBrowsingDatabaseNew::ContainsMalwareIP(const std::string& ip_address) {
831 // This method is theoretically thread-safe but document that it is currently
832 // only expected to be called on the IO thread.
833 DCHECK_CURRENTLY_ON(BrowserThread::IO);
834
835 net::IPAddressNumber ip_number; 927 net::IPAddressNumber ip_number;
836 if (!net::ParseIPLiteralToNumber(ip_address, &ip_number)) 928 if (!net::ParseIPLiteralToNumber(ip_address, &ip_number))
837 return false; 929 return false;
838 if (ip_number.size() == net::kIPv4AddressSize) 930 if (ip_number.size() == net::kIPv4AddressSize)
839 ip_number = net::ConvertIPv4NumberToIPv6Number(ip_number); 931 ip_number = net::ConvertIPv4NumberToIPv6Number(ip_number);
840 if (ip_number.size() != net::kIPv6AddressSize) 932 if (ip_number.size() != net::kIPv6AddressSize)
841 return false; // better safe than sorry. 933 return false; // better safe than sorry.
842 934
843 base::AutoLock locked(lookup_lock_); 935 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction();
844 for (IPBlacklist::const_iterator it = ip_blacklist_.begin(); 936 const IPBlacklist* ip_blacklist = txn->ip_blacklist();
845 it != ip_blacklist_.end(); 937 for (IPBlacklist::const_iterator it = ip_blacklist->begin();
846 ++it) { 938 it != ip_blacklist->end(); ++it) {
847 const std::string& mask = it->first; 939 const std::string& mask = it->first;
848 DCHECK_EQ(mask.size(), ip_number.size()); 940 DCHECK_EQ(mask.size(), ip_number.size());
849 std::string subnet(net::kIPv6AddressSize, '\0'); 941 std::string subnet(net::kIPv6AddressSize, '\0');
850 for (size_t i = 0; i < net::kIPv6AddressSize; ++i) { 942 for (size_t i = 0; i < net::kIPv6AddressSize; ++i) {
851 subnet[i] = ip_number[i] & mask[i]; 943 subnet[i] = ip_number[i] & mask[i];
852 } 944 }
853 const std::string hash = base::SHA1HashString(subnet); 945 const std::string hash = base::SHA1HashString(subnet);
854 DVLOG(2) << "Lookup Malware IP: " 946 DVLOG(2) << "Lookup Malware IP: "
855 << " ip:" << ip_address 947 << " ip:" << ip_address
856 << " mask:" << base::HexEncode(mask.data(), mask.size()) 948 << " mask:" << base::HexEncode(mask.data(), mask.size())
857 << " subnet:" << base::HexEncode(subnet.data(), subnet.size()) 949 << " subnet:" << base::HexEncode(subnet.data(), subnet.size())
858 << " hash:" << base::HexEncode(hash.data(), hash.size()); 950 << " hash:" << base::HexEncode(hash.data(), hash.size());
859 if (it->second.count(hash) > 0) { 951 if (it->second.count(hash) > 0) {
860 return true; 952 return true;
861 } 953 }
862 } 954 }
863 return false; 955 return false;
864 } 956 }
865 957
866 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedString( 958 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedString(
867 const std::string& str) { 959 const std::string& str) {
868 // This method is theoretically thread-safe but document that it is currently
869 // only expected to be called on the IO thread.
870 DCHECK_CURRENTLY_ON(BrowserThread::IO);
871
872 std::vector<SBFullHash> hashes; 960 std::vector<SBFullHash> hashes;
873 hashes.push_back(SBFullHashForString(str)); 961 hashes.push_back(SBFullHashForString(str));
874 return ContainsWhitelistedHashes(download_whitelist_, hashes); 962 return ContainsWhitelistedHashes(SBWhitelistId::DOWNLOAD, hashes);
875 } 963 }
876 964
877 bool SafeBrowsingDatabaseNew::ContainsWhitelistedHashes( 965 bool SafeBrowsingDatabaseNew::ContainsWhitelistedHashes(
878 const SBWhitelist& whitelist, 966 SBWhitelistId whitelist_id,
879 const std::vector<SBFullHash>& hashes) { 967 const std::vector<SBFullHash>& hashes) {
880 // This method is theoretically thread-safe but document that it is currently 968 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction();
881 // only expected to be called on the IO thread. 969 const SBWhitelist* whitelist = txn->GetSBWhitelist(whitelist_id);
882 DCHECK_CURRENTLY_ON(BrowserThread::IO); 970 if (whitelist->second)
883
884 base::AutoLock l(lookup_lock_);
885 if (whitelist.second)
886 return true; 971 return true;
887 for (std::vector<SBFullHash>::const_iterator it = hashes.begin(); 972 for (std::vector<SBFullHash>::const_iterator it = hashes.begin();
888 it != hashes.end(); ++it) { 973 it != hashes.end(); ++it) {
889 if (std::binary_search(whitelist.first.begin(), whitelist.first.end(), 974 if (std::binary_search(whitelist->first.begin(), whitelist->first.end(),
890 *it, SBFullHashLess)) { 975 *it, SBFullHashLess)) {
891 return true; 976 return true;
892 } 977 }
893 } 978 }
894 return false; 979 return false;
895 } 980 }
896 981
897 // Helper to insert add-chunk entries. 982 // Helper to insert add-chunk entries.
898 void SafeBrowsingDatabaseNew::InsertAddChunk( 983 void SafeBrowsingDatabaseNew::InsertAddChunk(
899 SafeBrowsingStore* store, 984 SafeBrowsingStore* store,
900 const safe_browsing_util::ListType list_id, 985 const safe_browsing_util::ListType list_id,
901 const SBChunkData& chunk_data) { 986 const SBChunkData& chunk_data) {
902 DCHECK(thread_checker_.CalledOnValidThread());
903 DCHECK(store); 987 DCHECK(store);
904 988
905 // The server can give us a chunk that we already have because 989 // The server can give us a chunk that we already have because
906 // it's part of a range. Don't add it again. 990 // it's part of a range. Don't add it again.
907 const int chunk_id = chunk_data.ChunkNumber(); 991 const int chunk_id = chunk_data.ChunkNumber();
908 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); 992 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id);
909 if (store->CheckAddChunk(encoded_chunk_id)) 993 if (store->CheckAddChunk(encoded_chunk_id))
910 return; 994 return;
911 995
912 store->SetAddChunk(encoded_chunk_id); 996 store->SetAddChunk(encoded_chunk_id);
(...skipping 10 matching lines...) Expand all
923 store->WriteAddHash(encoded_chunk_id, chunk_data.FullHashAt(i)); 1007 store->WriteAddHash(encoded_chunk_id, chunk_data.FullHashAt(i));
924 } 1008 }
925 } 1009 }
926 } 1010 }
927 1011
928 // Helper to insert sub-chunk entries. 1012 // Helper to insert sub-chunk entries.
929 void SafeBrowsingDatabaseNew::InsertSubChunk( 1013 void SafeBrowsingDatabaseNew::InsertSubChunk(
930 SafeBrowsingStore* store, 1014 SafeBrowsingStore* store,
931 const safe_browsing_util::ListType list_id, 1015 const safe_browsing_util::ListType list_id,
932 const SBChunkData& chunk_data) { 1016 const SBChunkData& chunk_data) {
933 DCHECK(thread_checker_.CalledOnValidThread());
934 DCHECK(store); 1017 DCHECK(store);
935 1018
936 // The server can give us a chunk that we already have because 1019 // The server can give us a chunk that we already have because
937 // it's part of a range. Don't add it again. 1020 // it's part of a range. Don't add it again.
938 const int chunk_id = chunk_data.ChunkNumber(); 1021 const int chunk_id = chunk_data.ChunkNumber();
939 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); 1022 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id);
940 if (store->CheckSubChunk(encoded_chunk_id)) 1023 if (store->CheckSubChunk(encoded_chunk_id))
941 return; 1024 return;
942 1025
943 store->SetSubChunk(encoded_chunk_id); 1026 store->SetSubChunk(encoded_chunk_id);
(...skipping 14 matching lines...) Expand all
958 const int encoded_add_chunk_id = EncodeChunkId(add_chunk_id, list_id); 1041 const int encoded_add_chunk_id = EncodeChunkId(add_chunk_id, list_id);
959 store->WriteSubHash(encoded_chunk_id, encoded_add_chunk_id, 1042 store->WriteSubHash(encoded_chunk_id, encoded_add_chunk_id,
960 chunk_data.FullHashAt(i)); 1043 chunk_data.FullHashAt(i));
961 } 1044 }
962 } 1045 }
963 } 1046 }
964 1047
965 void SafeBrowsingDatabaseNew::InsertChunks( 1048 void SafeBrowsingDatabaseNew::InsertChunks(
966 const std::string& list_name, 1049 const std::string& list_name,
967 const std::vector<SBChunkData*>& chunks) { 1050 const std::vector<SBChunkData*>& chunks) {
968 DCHECK(thread_checker_.CalledOnValidThread());
969
970 if (corruption_detected_ || chunks.empty()) 1051 if (corruption_detected_ || chunks.empty())
971 return; 1052 return;
972 1053
973 const base::TimeTicks before = base::TimeTicks::Now(); 1054 const base::TimeTicks before = base::TimeTicks::Now();
974 1055
975 // TODO(shess): The caller should just pass list_id. 1056 // TODO(shess): The caller should just pass list_id.
976 const safe_browsing_util::ListType list_id = 1057 const safe_browsing_util::ListType list_id =
977 safe_browsing_util::GetListId(list_name); 1058 safe_browsing_util::GetListId(list_name);
978 1059
979 SafeBrowsingStore* store = GetStore(list_id); 1060 SafeBrowsingStore* store = GetStore(list_id);
(...skipping 13 matching lines...) Expand all
993 NOTREACHED(); 1074 NOTREACHED();
994 } 1075 }
995 } 1076 }
996 store->FinishChunk(); 1077 store->FinishChunk();
997 1078
998 UMA_HISTOGRAM_TIMES("SB2.ChunkInsert", base::TimeTicks::Now() - before); 1079 UMA_HISTOGRAM_TIMES("SB2.ChunkInsert", base::TimeTicks::Now() - before);
999 } 1080 }
1000 1081
1001 void SafeBrowsingDatabaseNew::DeleteChunks( 1082 void SafeBrowsingDatabaseNew::DeleteChunks(
1002 const std::vector<SBChunkDelete>& chunk_deletes) { 1083 const std::vector<SBChunkDelete>& chunk_deletes) {
1003 DCHECK(thread_checker_.CalledOnValidThread());
1004
1005 if (corruption_detected_ || chunk_deletes.empty()) 1084 if (corruption_detected_ || chunk_deletes.empty())
1006 return; 1085 return;
1007 1086
1008 const std::string& list_name = chunk_deletes.front().list_name; 1087 const std::string& list_name = chunk_deletes.front().list_name;
1009 const safe_browsing_util::ListType list_id = 1088 const safe_browsing_util::ListType list_id =
1010 safe_browsing_util::GetListId(list_name); 1089 safe_browsing_util::GetListId(list_name);
1011 1090
1012 SafeBrowsingStore* store = GetStore(list_id); 1091 SafeBrowsingStore* store = GetStore(list_id);
1013 if (!store) return; 1092 if (!store) return;
1014 1093
1015 change_detected_ = true; 1094 change_detected_ = true;
1016 1095
1017 for (size_t i = 0; i < chunk_deletes.size(); ++i) { 1096 for (size_t i = 0; i < chunk_deletes.size(); ++i) {
1018 std::vector<int> chunk_numbers; 1097 std::vector<int> chunk_numbers;
1019 RangesToChunks(chunk_deletes[i].chunk_del, &chunk_numbers); 1098 RangesToChunks(chunk_deletes[i].chunk_del, &chunk_numbers);
1020 for (size_t j = 0; j < chunk_numbers.size(); ++j) { 1099 for (size_t j = 0; j < chunk_numbers.size(); ++j) {
1021 const int encoded_chunk_id = EncodeChunkId(chunk_numbers[j], list_id); 1100 const int encoded_chunk_id = EncodeChunkId(chunk_numbers[j], list_id);
1022 if (chunk_deletes[i].is_sub_del) 1101 if (chunk_deletes[i].is_sub_del)
1023 store->DeleteSubChunk(encoded_chunk_id); 1102 store->DeleteSubChunk(encoded_chunk_id);
1024 else 1103 else
1025 store->DeleteAddChunk(encoded_chunk_id); 1104 store->DeleteAddChunk(encoded_chunk_id);
1026 } 1105 }
1027 } 1106 }
1028 } 1107 }
1029 1108
1030 void SafeBrowsingDatabaseNew::CacheHashResults( 1109 void SafeBrowsingDatabaseNew::CacheHashResults(
1031 const std::vector<SBPrefix>& prefixes, 1110 const std::vector<SBPrefix>& prefixes,
1032 const std::vector<SBFullHashResult>& full_hits, 1111 const std::vector<SBFullHashResult>& full_hits,
1033 const base::TimeDelta& cache_lifetime) { 1112 const base::TimeDelta& cache_lifetime) {
1034 // This method is theoretically thread-safe but document that it is currently
1035 // only expected to be called on the IO thread.
1036 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1037
1038 const base::Time expire_after = base::Time::Now() + cache_lifetime; 1113 const base::Time expire_after = base::Time::Now() + cache_lifetime;
1039 1114
1040 base::AutoLock locked(lookup_lock_); 1115 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction();
1116 PrefixGetHashCache* prefix_gethash_cache = txn->prefix_gethash_cache();
1041 1117
1042 // Create or reset all cached results for these prefixes. 1118 // Create or reset all cached results for these prefixes.
1043 for (size_t i = 0; i < prefixes.size(); ++i) { 1119 for (size_t i = 0; i < prefixes.size(); ++i) {
1044 prefix_gethash_cache_[prefixes[i]] = SBCachedFullHashResult(expire_after); 1120 (*prefix_gethash_cache)[prefixes[i]] = SBCachedFullHashResult(expire_after);
1045 } 1121 }
1046 1122
1047 // Insert any fullhash hits. Note that there may be one, multiple, or no 1123 // Insert any fullhash hits. Note that there may be one, multiple, or no
1048 // fullhashes for any given entry in |prefixes|. 1124 // fullhashes for any given entry in |prefixes|.
1049 for (size_t i = 0; i < full_hits.size(); ++i) { 1125 for (size_t i = 0; i < full_hits.size(); ++i) {
1050 const SBPrefix prefix = full_hits[i].hash.prefix; 1126 const SBPrefix prefix = full_hits[i].hash.prefix;
1051 prefix_gethash_cache_[prefix].full_hashes.push_back(full_hits[i]); 1127 (*prefix_gethash_cache)[prefix].full_hashes.push_back(full_hits[i]);
1052 } 1128 }
1053 } 1129 }
1054 1130
1055 bool SafeBrowsingDatabaseNew::UpdateStarted( 1131 bool SafeBrowsingDatabaseNew::UpdateStarted(
1056 std::vector<SBListChunkRanges>* lists) { 1132 std::vector<SBListChunkRanges>* lists) {
1057 DCHECK(thread_checker_.CalledOnValidThread());
1058 DCHECK(lists); 1133 DCHECK(lists);
1059 1134
1060 // If |BeginUpdate()| fails, reset the database. 1135 // If |BeginUpdate()| fails, reset the database.
1061 if (!browse_store_->BeginUpdate()) { 1136 if (!browse_store_->BeginUpdate()) {
1062 RecordFailure(FAILURE_BROWSE_DATABASE_UPDATE_BEGIN); 1137 RecordFailure(FAILURE_BROWSE_DATABASE_UPDATE_BEGIN);
1063 HandleCorruptDatabase(); 1138 HandleCorruptDatabase();
1064 return false; 1139 return false;
1065 } 1140 }
1066 1141
1067 if (download_store_.get() && !download_store_->BeginUpdate()) { 1142 if (download_store_.get() && !download_store_->BeginUpdate()) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1103 return false; 1178 return false;
1104 } 1179 }
1105 1180
1106 if (unwanted_software_store_ && !unwanted_software_store_->BeginUpdate()) { 1181 if (unwanted_software_store_ && !unwanted_software_store_->BeginUpdate()) {
1107 RecordFailure(FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_BEGIN); 1182 RecordFailure(FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_BEGIN);
1108 HandleCorruptDatabase(); 1183 HandleCorruptDatabase();
1109 return false; 1184 return false;
1110 } 1185 }
1111 1186
1112 { 1187 {
1113 base::AutoLock locked(lookup_lock_); 1188 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction();
1114 // Cached fullhash results must be cleared on every database update (whether 1189 // Cached fullhash results must be cleared on every database update (whether
1115 // successful or not.) 1190 // successful or not).
1116 prefix_gethash_cache_.clear(); 1191 txn->clear_prefix_gethash_cache();
1117 } 1192 }
1118 1193
1119 UpdateChunkRangesForLists(browse_store_.get(), 1194 UpdateChunkRangesForLists(browse_store_.get(),
1120 safe_browsing_util::kMalwareList, 1195 safe_browsing_util::kMalwareList,
1121 safe_browsing_util::kPhishingList, 1196 safe_browsing_util::kPhishingList,
1122 lists); 1197 lists);
1123 1198
1124 // NOTE(shess): |download_store_| used to contain kBinHashList, which has been 1199 // NOTE(shess): |download_store_| used to contain kBinHashList, which has been
1125 // deprecated. Code to delete the list from the store shows ~15k hits/day as 1200 // deprecated. Code to delete the list from the store shows ~15k hits/day as
1126 // of Feb 2014, so it has been removed. Everything _should_ be resilient to 1201 // of Feb 2014, so it has been removed. Everything _should_ be resilient to
(...skipping 19 matching lines...) Expand all
1146 UpdateChunkRangesForList(unwanted_software_store_.get(), 1221 UpdateChunkRangesForList(unwanted_software_store_.get(),
1147 safe_browsing_util::kUnwantedUrlList, 1222 safe_browsing_util::kUnwantedUrlList,
1148 lists); 1223 lists);
1149 1224
1150 corruption_detected_ = false; 1225 corruption_detected_ = false;
1151 change_detected_ = false; 1226 change_detected_ = false;
1152 return true; 1227 return true;
1153 } 1228 }
1154 1229
1155 void SafeBrowsingDatabaseNew::UpdateFinished(bool update_succeeded) { 1230 void SafeBrowsingDatabaseNew::UpdateFinished(bool update_succeeded) {
1156 DCHECK(thread_checker_.CalledOnValidThread());
1157
1158 // The update may have failed due to corrupt storage (for instance, 1231 // The update may have failed due to corrupt storage (for instance,
1159 // an excessive number of invalid add_chunks and sub_chunks). 1232 // an excessive number of invalid add_chunks and sub_chunks).
1160 // Double-check that the databases are valid. 1233 // Double-check that the databases are valid.
1161 // TODO(shess): Providing a checksum for the add_chunk and sub_chunk 1234 // TODO(shess): Providing a checksum for the add_chunk and sub_chunk
1162 // sections would allow throwing a corruption error in 1235 // sections would allow throwing a corruption error in
1163 // UpdateStarted(). 1236 // UpdateStarted().
1164 if (!update_succeeded) { 1237 if (!update_succeeded) {
1165 if (!browse_store_->CheckValidity()) 1238 if (!browse_store_->CheckValidity())
1166 DLOG(ERROR) << "Safe-browsing browse database corrupt."; 1239 DLOG(ERROR) << "Safe-browsing browse database corrupt.";
1167 1240
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1229 int64 size_bytes = UpdateHashPrefixStore( 1302 int64 size_bytes = UpdateHashPrefixStore(
1230 DownloadDBFilename(filename_base_), 1303 DownloadDBFilename(filename_base_),
1231 download_store_.get(), 1304 download_store_.get(),
1232 FAILURE_DOWNLOAD_DATABASE_UPDATE_FINISH); 1305 FAILURE_DOWNLOAD_DATABASE_UPDATE_FINISH);
1233 UMA_HISTOGRAM_COUNTS("SB2.DownloadDatabaseKilobytes", 1306 UMA_HISTOGRAM_COUNTS("SB2.DownloadDatabaseKilobytes",
1234 static_cast<int>(size_bytes / 1024)); 1307 static_cast<int>(size_bytes / 1024));
1235 } 1308 }
1236 1309
1237 UpdatePrefixSetUrlStore(BrowseDBFilename(filename_base_), 1310 UpdatePrefixSetUrlStore(BrowseDBFilename(filename_base_),
1238 browse_store_.get(), 1311 browse_store_.get(),
1239 &browse_prefix_set_, 1312 PrefixSetId::BROWSE,
1240 FAILURE_BROWSE_DATABASE_UPDATE_FINISH, 1313 FAILURE_BROWSE_DATABASE_UPDATE_FINISH,
1241 FAILURE_BROWSE_PREFIX_SET_WRITE, 1314 FAILURE_BROWSE_PREFIX_SET_WRITE,
1242 true); 1315 true);
1243 1316
1244 UpdateWhitelistStore(CsdWhitelistDBFilename(filename_base_), 1317 UpdateWhitelistStore(CsdWhitelistDBFilename(filename_base_),
1245 csd_whitelist_store_.get(), 1318 csd_whitelist_store_.get(),
1246 &csd_whitelist_); 1319 SBWhitelistId::CSD);
1247 UpdateWhitelistStore(DownloadWhitelistDBFilename(filename_base_), 1320 UpdateWhitelistStore(DownloadWhitelistDBFilename(filename_base_),
1248 download_whitelist_store_.get(), 1321 download_whitelist_store_.get(),
1249 &download_whitelist_); 1322 SBWhitelistId::DOWNLOAD);
1250 1323
1251 if (extension_blacklist_store_) { 1324 if (extension_blacklist_store_) {
1252 int64 size_bytes = UpdateHashPrefixStore( 1325 int64 size_bytes = UpdateHashPrefixStore(
1253 ExtensionBlacklistDBFilename(filename_base_), 1326 ExtensionBlacklistDBFilename(filename_base_),
1254 extension_blacklist_store_.get(), 1327 extension_blacklist_store_.get(),
1255 FAILURE_EXTENSION_BLACKLIST_UPDATE_FINISH); 1328 FAILURE_EXTENSION_BLACKLIST_UPDATE_FINISH);
1256 UMA_HISTOGRAM_COUNTS("SB2.ExtensionBlacklistKilobytes", 1329 UMA_HISTOGRAM_COUNTS("SB2.ExtensionBlacklistKilobytes",
1257 static_cast<int>(size_bytes / 1024)); 1330 static_cast<int>(size_bytes / 1024));
1258 } 1331 }
1259 1332
1260 if (side_effect_free_whitelist_store_) { 1333 if (side_effect_free_whitelist_store_) {
1261 UpdatePrefixSetUrlStore(SideEffectFreeWhitelistDBFilename(filename_base_), 1334 UpdatePrefixSetUrlStore(SideEffectFreeWhitelistDBFilename(filename_base_),
1262 side_effect_free_whitelist_store_.get(), 1335 side_effect_free_whitelist_store_.get(),
1263 &side_effect_free_whitelist_prefix_set_, 1336 PrefixSetId::SIDE_EFFECT_FREE_WHITELIST,
1264 FAILURE_SIDE_EFFECT_FREE_WHITELIST_UPDATE_FINISH, 1337 FAILURE_SIDE_EFFECT_FREE_WHITELIST_UPDATE_FINISH,
1265 FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_WRITE, 1338 FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_WRITE,
1266 false); 1339 false);
1267 } 1340 }
1268 1341
1269 if (ip_blacklist_store_) 1342 if (ip_blacklist_store_)
1270 UpdateIpBlacklistStore(); 1343 UpdateIpBlacklistStore();
1271 1344
1272 if (unwanted_software_store_) { 1345 if (unwanted_software_store_) {
1273 UpdatePrefixSetUrlStore(UnwantedSoftwareDBFilename(filename_base_), 1346 UpdatePrefixSetUrlStore(UnwantedSoftwareDBFilename(filename_base_),
1274 unwanted_software_store_.get(), 1347 unwanted_software_store_.get(),
1275 &unwanted_software_prefix_set_, 1348 PrefixSetId::UNWANTED_SOFTWARE,
1276 FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_FINISH, 1349 FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_FINISH,
1277 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_WRITE, 1350 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_WRITE,
1278 true); 1351 true);
1279 } 1352 }
1280 } 1353 }
1281 1354
1282 void SafeBrowsingDatabaseNew::UpdateWhitelistStore( 1355 void SafeBrowsingDatabaseNew::UpdateWhitelistStore(
1283 const base::FilePath& store_filename, 1356 const base::FilePath& store_filename,
1284 SafeBrowsingStore* store, 1357 SafeBrowsingStore* store,
1285 SBWhitelist* whitelist) { 1358 SBWhitelistId whitelist_id) {
1286 DCHECK(thread_checker_.CalledOnValidThread());
1287
1288 if (!store) 1359 if (!store)
1289 return; 1360 return;
1290 1361
1291 // Note: |builder| will not be empty. The current data store implementation 1362 // Note: |builder| will not be empty. The current data store implementation
1292 // stores all full-length hashes as both full and prefix hashes. 1363 // stores all full-length hashes as both full and prefix hashes.
1293 safe_browsing::PrefixSetBuilder builder; 1364 PrefixSetBuilder builder;
1294 std::vector<SBAddFullHash> full_hashes; 1365 std::vector<SBAddFullHash> full_hashes;
1295 if (!store->FinishUpdate(&builder, &full_hashes)) { 1366 if (!store->FinishUpdate(&builder, &full_hashes)) {
1296 RecordFailure(FAILURE_WHITELIST_DATABASE_UPDATE_FINISH); 1367 RecordFailure(FAILURE_WHITELIST_DATABASE_UPDATE_FINISH);
1297 WhitelistEverything(whitelist); 1368 WhitelistEverything(whitelist_id);
1298 return; 1369 return;
1299 } 1370 }
1300 1371
1301 #if defined(OS_MACOSX) 1372 #if defined(OS_MACOSX)
1302 base::mac::SetFileBackupExclusion(store_filename); 1373 base::mac::SetFileBackupExclusion(store_filename);
1303 #endif 1374 #endif
1304 1375
1305 LoadWhitelist(full_hashes, whitelist); 1376 LoadWhitelist(full_hashes, whitelist_id);
1306 } 1377 }
1307 1378
1308 int64 SafeBrowsingDatabaseNew::UpdateHashPrefixStore( 1379 int64 SafeBrowsingDatabaseNew::UpdateHashPrefixStore(
1309 const base::FilePath& store_filename, 1380 const base::FilePath& store_filename,
1310 SafeBrowsingStore* store, 1381 SafeBrowsingStore* store,
1311 FailureType failure_type) { 1382 FailureType failure_type) {
1312 DCHECK(thread_checker_.CalledOnValidThread());
1313
1314 // These results are not used after this call. Simply ignore the 1383 // These results are not used after this call. Simply ignore the
1315 // returned value after FinishUpdate(...). 1384 // returned value after FinishUpdate(...).
1316 safe_browsing::PrefixSetBuilder builder; 1385 PrefixSetBuilder builder;
1317 std::vector<SBAddFullHash> add_full_hashes_result; 1386 std::vector<SBAddFullHash> add_full_hashes_result;
1318 1387
1319 if (!store->FinishUpdate(&builder, &add_full_hashes_result)) 1388 if (!store->FinishUpdate(&builder, &add_full_hashes_result))
1320 RecordFailure(failure_type); 1389 RecordFailure(failure_type);
1321 1390
1322 #if defined(OS_MACOSX) 1391 #if defined(OS_MACOSX)
1323 base::mac::SetFileBackupExclusion(store_filename); 1392 base::mac::SetFileBackupExclusion(store_filename);
1324 #endif 1393 #endif
1325 1394
1326 return GetFileSizeOrZero(store_filename); 1395 return GetFileSizeOrZero(store_filename);
1327 } 1396 }
1328 1397
1329 void SafeBrowsingDatabaseNew::UpdatePrefixSetUrlStore( 1398 void SafeBrowsingDatabaseNew::UpdatePrefixSetUrlStore(
1330 const base::FilePath& db_filename, 1399 const base::FilePath& db_filename,
1331 SafeBrowsingStore* url_store, 1400 SafeBrowsingStore* url_store,
1332 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, 1401 PrefixSetId prefix_set_id,
1333 FailureType finish_failure_type, 1402 FailureType finish_failure_type,
1334 FailureType write_failure_type, 1403 FailureType write_failure_type,
1335 bool store_full_hashes_in_prefix_set) { 1404 bool store_full_hashes_in_prefix_set) {
1336 DCHECK(thread_checker_.CalledOnValidThread());
1337 DCHECK(url_store); 1405 DCHECK(url_store);
1338 DCHECK(prefix_set);
1339 1406
1340 // Measure the amount of IO during the filter build. 1407 // Measure the amount of IO during the filter build.
1341 base::IoCounters io_before, io_after; 1408 base::IoCounters io_before, io_after;
1342 base::ProcessHandle handle = base::GetCurrentProcessHandle(); 1409 base::ProcessHandle handle = base::GetCurrentProcessHandle();
1343 scoped_ptr<base::ProcessMetrics> metric( 1410 scoped_ptr<base::ProcessMetrics> metric(
1344 #if !defined(OS_MACOSX) 1411 #if !defined(OS_MACOSX)
1345 base::ProcessMetrics::CreateProcessMetrics(handle) 1412 base::ProcessMetrics::CreateProcessMetrics(handle)
1346 #else 1413 #else
1347 // Getting stats only for the current process is enough, so NULL is fine. 1414 // Getting stats only for the current process is enough, so NULL is fine.
1348 base::ProcessMetrics::CreateProcessMetrics(handle, NULL) 1415 base::ProcessMetrics::CreateProcessMetrics(handle, NULL)
1349 #endif 1416 #endif
1350 ); 1417 );
1351 1418
1352 // IoCounters are currently not supported on Mac, and may not be 1419 // IoCounters are currently not supported on Mac, and may not be
1353 // available for Linux, so we check the result and only show IO 1420 // available for Linux, so we check the result and only show IO
1354 // stats if they are available. 1421 // stats if they are available.
1355 const bool got_counters = metric->GetIOCounters(&io_before); 1422 const bool got_counters = metric->GetIOCounters(&io_before);
1356 1423
1357 const base::TimeTicks before = base::TimeTicks::Now(); 1424 const base::TimeTicks before = base::TimeTicks::Now();
1358 1425
1359 // TODO(shess): Perhaps refactor to let builder accumulate full hashes on the 1426 // TODO(shess): Perhaps refactor to let builder accumulate full hashes on the
1360 // fly? Other clients use the SBAddFullHash vector, but AFAICT they only use 1427 // fly? Other clients use the SBAddFullHash vector, but AFAICT they only use
1361 // the SBFullHash portion. It would need an accessor on PrefixSet. 1428 // the SBFullHash portion. It would need an accessor on PrefixSet.
1362 safe_browsing::PrefixSetBuilder builder; 1429 PrefixSetBuilder builder;
1363 std::vector<SBAddFullHash> add_full_hashes; 1430 std::vector<SBAddFullHash> add_full_hashes;
1364 if (!url_store->FinishUpdate(&builder, &add_full_hashes)) { 1431 if (!url_store->FinishUpdate(&builder, &add_full_hashes)) {
1365 RecordFailure(finish_failure_type); 1432 RecordFailure(finish_failure_type);
1366 return; 1433 return;
1367 } 1434 }
1368 1435
1369 scoped_ptr<const safe_browsing::PrefixSet> new_prefix_set; 1436 scoped_ptr<const PrefixSet> new_prefix_set;
1370 if (store_full_hashes_in_prefix_set) { 1437 if (store_full_hashes_in_prefix_set) {
1371 std::vector<SBFullHash> full_hash_results; 1438 std::vector<SBFullHash> full_hash_results;
1372 for (size_t i = 0; i < add_full_hashes.size(); ++i) { 1439 for (size_t i = 0; i < add_full_hashes.size(); ++i) {
1373 full_hash_results.push_back(add_full_hashes[i].full_hash); 1440 full_hash_results.push_back(add_full_hashes[i].full_hash);
1374 } 1441 }
1375 1442
1376 new_prefix_set = builder.GetPrefixSet(full_hash_results); 1443 new_prefix_set = builder.GetPrefixSet(full_hash_results);
1377 } else { 1444 } else {
1378 new_prefix_set = builder.GetPrefixSetNoHashes(); 1445 new_prefix_set = builder.GetPrefixSetNoHashes();
1379 } 1446 }
1380 1447
1381 // Swap in the newly built filter. 1448 // Swap in the newly built filter.
1382 { 1449 {
1383 base::AutoLock locked(lookup_lock_); 1450 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction();
1384 prefix_set->swap(new_prefix_set); 1451 txn->SwapPrefixSet(prefix_set_id, new_prefix_set.Pass());
1385 } 1452 }
1386 1453
1387 UMA_HISTOGRAM_LONG_TIMES("SB2.BuildFilter", base::TimeTicks::Now() - before); 1454 UMA_HISTOGRAM_LONG_TIMES("SB2.BuildFilter", base::TimeTicks::Now() - before);
1388 1455
1389 // Persist the prefix set to disk. Note: there is no need to lock since the 1456 {
1390 // only write to |*prefix_set| is on this thread (in the swap() above). 1457 // Persist the prefix set to disk. Do not grab the lock to avoid contention
1391 WritePrefixSet(db_filename, prefix_set->get(), write_failure_type); 1458 // while writing to disk. This is safe as only this thread can ever modify
1459 // |state_manager_|'s prefix sets anyways.
1460 scoped_ptr<ReadTransaction> txn =
1461 state_manager_.BeginReadTransactionNoLockOnMainThread();
1462 WritePrefixSet(db_filename, txn->GetPrefixSet(prefix_set_id),
1463 write_failure_type);
1464 }
1392 1465
1393 // Gather statistics. 1466 // Gather statistics.
1394 if (got_counters && metric->GetIOCounters(&io_after)) { 1467 if (got_counters && metric->GetIOCounters(&io_after)) {
1395 UMA_HISTOGRAM_COUNTS("SB2.BuildReadKilobytes", 1468 UMA_HISTOGRAM_COUNTS("SB2.BuildReadKilobytes",
1396 static_cast<int>(io_after.ReadTransferCount - 1469 static_cast<int>(io_after.ReadTransferCount -
1397 io_before.ReadTransferCount) / 1024); 1470 io_before.ReadTransferCount) / 1024);
1398 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteKilobytes", 1471 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteKilobytes",
1399 static_cast<int>(io_after.WriteTransferCount - 1472 static_cast<int>(io_after.WriteTransferCount -
1400 io_before.WriteTransferCount) / 1024); 1473 io_before.WriteTransferCount) / 1024);
1401 UMA_HISTOGRAM_COUNTS("SB2.BuildReadOperations", 1474 UMA_HISTOGRAM_COUNTS("SB2.BuildReadOperations",
1402 static_cast<int>(io_after.ReadOperationCount - 1475 static_cast<int>(io_after.ReadOperationCount -
1403 io_before.ReadOperationCount)); 1476 io_before.ReadOperationCount));
1404 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteOperations", 1477 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteOperations",
1405 static_cast<int>(io_after.WriteOperationCount - 1478 static_cast<int>(io_after.WriteOperationCount -
1406 io_before.WriteOperationCount)); 1479 io_before.WriteOperationCount));
1407 } 1480 }
1408 1481
1409 const int64 file_size = GetFileSizeOrZero(db_filename); 1482 const int64 file_size = GetFileSizeOrZero(db_filename);
1410 UMA_HISTOGRAM_COUNTS("SB2.DatabaseKilobytes", 1483 UMA_HISTOGRAM_COUNTS("SB2.DatabaseKilobytes",
1411 static_cast<int>(file_size / 1024)); 1484 static_cast<int>(file_size / 1024));
1412 1485
1413 #if defined(OS_MACOSX) 1486 #if defined(OS_MACOSX)
1414 base::mac::SetFileBackupExclusion(db_filename); 1487 base::mac::SetFileBackupExclusion(db_filename);
1415 #endif 1488 #endif
1416 } 1489 }
1417 1490
1418 void SafeBrowsingDatabaseNew::UpdateIpBlacklistStore() { 1491 void SafeBrowsingDatabaseNew::UpdateIpBlacklistStore() {
1419 DCHECK(thread_checker_.CalledOnValidThread());
1420
1421 // Note: prefixes will not be empty. The current data store implementation 1492 // Note: prefixes will not be empty. The current data store implementation
1422 // stores all full-length hashes as both full and prefix hashes. 1493 // stores all full-length hashes as both full and prefix hashes.
1423 safe_browsing::PrefixSetBuilder builder; 1494 PrefixSetBuilder builder;
1424 std::vector<SBAddFullHash> full_hashes; 1495 std::vector<SBAddFullHash> full_hashes;
1425 if (!ip_blacklist_store_->FinishUpdate(&builder, &full_hashes)) { 1496 if (!ip_blacklist_store_->FinishUpdate(&builder, &full_hashes)) {
1426 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_FINISH); 1497 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_FINISH);
1427 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. 1498 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list.
1428 return; 1499 return;
1429 } 1500 }
1430 1501
1431 #if defined(OS_MACOSX) 1502 #if defined(OS_MACOSX)
1432 base::mac::SetFileBackupExclusion(IpBlacklistDBFilename(filename_base_)); 1503 base::mac::SetFileBackupExclusion(IpBlacklistDBFilename(filename_base_));
1433 #endif 1504 #endif
1434 1505
1435 LoadIpBlacklist(full_hashes); 1506 LoadIpBlacklist(full_hashes);
1436 } 1507 }
1437 1508
1438 void SafeBrowsingDatabaseNew::HandleCorruptDatabase() { 1509 void SafeBrowsingDatabaseNew::HandleCorruptDatabase() {
1439 DCHECK(thread_checker_.CalledOnValidThread());
1440
1441 // Reset the database after the current task has unwound (but only 1510 // Reset the database after the current task has unwound (but only
1442 // reset once within the scope of a given task). 1511 // reset once within the scope of a given task).
1443 if (!reset_factory_.HasWeakPtrs()) { 1512 if (!reset_factory_.HasWeakPtrs()) {
1444 RecordFailure(FAILURE_DATABASE_CORRUPT); 1513 RecordFailure(FAILURE_DATABASE_CORRUPT);
1445 base::MessageLoop::current()->PostTask(FROM_HERE, 1514 base::MessageLoop::current()->PostTask(FROM_HERE,
1446 base::Bind(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase, 1515 base::Bind(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase,
1447 reset_factory_.GetWeakPtr())); 1516 reset_factory_.GetWeakPtr()));
1448 } 1517 }
1449 } 1518 }
1450 1519
1451 void SafeBrowsingDatabaseNew::OnHandleCorruptDatabase() { 1520 void SafeBrowsingDatabaseNew::OnHandleCorruptDatabase() {
1452 DCHECK(thread_checker_.CalledOnValidThread());
1453
1454 RecordFailure(FAILURE_DATABASE_CORRUPT_HANDLER); 1521 RecordFailure(FAILURE_DATABASE_CORRUPT_HANDLER);
1455 corruption_detected_ = true; // Stop updating the database. 1522 corruption_detected_ = true; // Stop updating the database.
1456 ResetDatabase(); 1523 ResetDatabase();
1457 1524
1458 // NOTE(shess): ResetDatabase() should remove the corruption, so this should 1525 // NOTE(shess): ResetDatabase() should remove the corruption, so this should
1459 // only happen once. If you are here because you are hitting this after a 1526 // only happen once. If you are here because you are hitting this after a
1460 // restart, then I would be very interested in working with you to figure out 1527 // restart, then I would be very interested in working with you to figure out
1461 // what is happening, since it may affect real users. 1528 // what is happening, since it may affect real users.
1462 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; 1529 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset";
1463 } 1530 }
1464 1531
1465 // TODO(shess): I'm not clear why this code doesn't have any 1532 // TODO(shess): I'm not clear why this code doesn't have any
1466 // real error-handling. 1533 // real error-handling.
1467 void SafeBrowsingDatabaseNew::LoadPrefixSet( 1534 void SafeBrowsingDatabaseNew::LoadPrefixSet(const base::FilePath& db_filename,
1468 const base::FilePath& db_filename, 1535 WriteTransaction* txn,
1469 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, 1536 PrefixSetId prefix_set_id,
1470 FailureType read_failure_type) { 1537 FailureType read_failure_type) {
1471 DCHECK(thread_checker_.CalledOnValidThread()); 1538 DCHECK(txn);
1472
1473 if (!prefix_set)
1474 return;
1475
1476 DCHECK(!filename_base_.empty()); 1539 DCHECK(!filename_base_.empty());
1477 1540
1478 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename);
1479
1480 // Only use the prefix set if database is present and non-empty. 1541 // Only use the prefix set if database is present and non-empty.
1481 if (!GetFileSizeOrZero(db_filename)) 1542 if (!GetFileSizeOrZero(db_filename))
1482 return; 1543 return;
1483 1544
1484 // Cleanup any stale bloom filter (no longer used). 1545 // Cleanup any stale bloom filter (no longer used).
1485 // TODO(shess): Track existence to drive removal of this code? 1546 // TODO(shess): Track existence to drive removal of this code?
1486 const base::FilePath bloom_filter_filename = 1547 const base::FilePath bloom_filter_filename =
1487 BloomFilterForFilename(db_filename); 1548 BloomFilterForFilename(db_filename);
1488 base::DeleteFile(bloom_filter_filename, false); 1549 base::DeleteFile(bloom_filter_filename, false);
1489 1550
1490 const base::TimeTicks before = base::TimeTicks::Now(); 1551 const base::TimeTicks before = base::TimeTicks::Now();
1491 *prefix_set = safe_browsing::PrefixSet::LoadFile(prefix_set_filename); 1552 scoped_ptr<const PrefixSet> new_prefix_set =
1553 PrefixSet::LoadFile(PrefixSetForFilename(db_filename));
1554 if (!new_prefix_set.get())
1555 RecordFailure(read_failure_type);
1556 txn->SwapPrefixSet(prefix_set_id, new_prefix_set.Pass());
1492 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before); 1557 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before);
1493
1494 if (!prefix_set->get())
1495 RecordFailure(read_failure_type);
1496 } 1558 }
1497 1559
1498 bool SafeBrowsingDatabaseNew::Delete() { 1560 bool SafeBrowsingDatabaseNew::Delete() {
1499 DCHECK(thread_checker_.CalledOnValidThread());
1500 DCHECK(!filename_base_.empty()); 1561 DCHECK(!filename_base_.empty());
1501 1562
1502 // TODO(shess): This is a mess. SafeBrowsingFileStore::Delete() closes the 1563 // TODO(shess): This is a mess. SafeBrowsingFileStore::Delete() closes the
1503 // store before calling DeleteStore(). DeleteStore() deletes transient files 1564 // store before calling DeleteStore(). DeleteStore() deletes transient files
1504 // in addition to the main file. Probably all of these should be converted to 1565 // in addition to the main file. Probably all of these should be converted to
1505 // a helper which calls Delete() if the store exists, else DeleteStore() on 1566 // a helper which calls Delete() if the store exists, else DeleteStore() on
1506 // the generated filename. 1567 // the generated filename.
1507 1568
1508 // TODO(shess): Determine if the histograms are useful in any way. I cannot 1569 // TODO(shess): Determine if the histograms are useful in any way. I cannot
1509 // recall any action taken as a result of their values, in which case it might 1570 // recall any action taken as a result of their values, in which case it might
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1568 RecordFailure(FAILURE_IP_BLACKLIST_DELETE); 1629 RecordFailure(FAILURE_IP_BLACKLIST_DELETE);
1569 1630
1570 const bool r11 = 1631 const bool r11 =
1571 base::DeleteFile(UnwantedSoftwareDBFilename(filename_base_), false); 1632 base::DeleteFile(UnwantedSoftwareDBFilename(filename_base_), false);
1572 if (!r11) 1633 if (!r11)
1573 RecordFailure(FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_DELETE); 1634 RecordFailure(FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_DELETE);
1574 1635
1575 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9 && r10 && r11; 1636 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9 && r10 && r11;
1576 } 1637 }
1577 1638
1578 void SafeBrowsingDatabaseNew::WritePrefixSet( 1639 void SafeBrowsingDatabaseNew::WritePrefixSet(const base::FilePath& db_filename,
1579 const base::FilePath& db_filename, 1640 const PrefixSet* prefix_set,
1580 const safe_browsing::PrefixSet* prefix_set, 1641 FailureType write_failure_type) {
1581 FailureType write_failure_type) {
1582 DCHECK(thread_checker_.CalledOnValidThread());
1583
1584 if (!prefix_set) 1642 if (!prefix_set)
1585 return; 1643 return;
1586 1644
1587 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); 1645 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename);
1588 1646
1589 const base::TimeTicks before = base::TimeTicks::Now(); 1647 const base::TimeTicks before = base::TimeTicks::Now();
1590 const bool write_ok = prefix_set->WriteFile(prefix_set_filename); 1648 const bool write_ok = prefix_set->WriteFile(prefix_set_filename);
1591 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before); 1649 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before);
1592 1650
1593 const int64 file_size = GetFileSizeOrZero(prefix_set_filename); 1651 const int64 file_size = GetFileSizeOrZero(prefix_set_filename);
1594 UMA_HISTOGRAM_COUNTS("SB2.PrefixSetKilobytes", 1652 UMA_HISTOGRAM_COUNTS("SB2.PrefixSetKilobytes",
1595 static_cast<int>(file_size / 1024)); 1653 static_cast<int>(file_size / 1024));
1596 1654
1597 if (!write_ok) 1655 if (!write_ok)
1598 RecordFailure(write_failure_type); 1656 RecordFailure(write_failure_type);
1599 1657
1600 #if defined(OS_MACOSX) 1658 #if defined(OS_MACOSX)
1601 base::mac::SetFileBackupExclusion(prefix_set_filename); 1659 base::mac::SetFileBackupExclusion(prefix_set_filename);
1602 #endif 1660 #endif
1603 } 1661 }
1604 1662
1605 void SafeBrowsingDatabaseNew::WhitelistEverything(SBWhitelist* whitelist) { 1663 void SafeBrowsingDatabaseNew::WhitelistEverything(SBWhitelistId whitelist_id) {
1606 DCHECK(thread_checker_.CalledOnValidThread()); 1664 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction();
1607 base::AutoLock locked(lookup_lock_); 1665 SBWhitelist* whitelist = txn->GetWritableSBWhitelist(whitelist_id);
1608 whitelist->second = true; 1666 whitelist->second = true;
1609 whitelist->first.clear(); 1667 whitelist->first.clear();
1610 } 1668 }
1611 1669
1612 void SafeBrowsingDatabaseNew::LoadWhitelist( 1670 void SafeBrowsingDatabaseNew::LoadWhitelist(
1613 const std::vector<SBAddFullHash>& full_hashes, 1671 const std::vector<SBAddFullHash>& full_hashes,
1614 SBWhitelist* whitelist) { 1672 SBWhitelistId whitelist_id) {
1615 DCHECK(thread_checker_.CalledOnValidThread());
1616
1617 if (full_hashes.size() > kMaxWhitelistSize) { 1673 if (full_hashes.size() > kMaxWhitelistSize) {
1618 WhitelistEverything(whitelist); 1674 WhitelistEverything(whitelist_id);
1619 return; 1675 return;
1620 } 1676 }
1621 1677
1622 std::vector<SBFullHash> new_whitelist; 1678 std::vector<SBFullHash> new_whitelist;
1623 new_whitelist.reserve(full_hashes.size()); 1679 new_whitelist.reserve(full_hashes.size());
1624 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); 1680 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin();
1625 it != full_hashes.end(); ++it) { 1681 it != full_hashes.end(); ++it) {
1626 new_whitelist.push_back(it->full_hash); 1682 new_whitelist.push_back(it->full_hash);
1627 } 1683 }
1628 std::sort(new_whitelist.begin(), new_whitelist.end(), SBFullHashLess); 1684 std::sort(new_whitelist.begin(), new_whitelist.end(), SBFullHashLess);
1629 1685
1630 SBFullHash kill_switch = SBFullHashForString(kWhitelistKillSwitchUrl); 1686 SBFullHash kill_switch = SBFullHashForString(kWhitelistKillSwitchUrl);
1631 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), 1687 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(),
1632 kill_switch, SBFullHashLess)) { 1688 kill_switch, SBFullHashLess)) {
1633 // The kill switch is whitelisted hence we whitelist all URLs. 1689 // The kill switch is whitelisted hence we whitelist all URLs.
1634 WhitelistEverything(whitelist); 1690 WhitelistEverything(whitelist_id);
1635 } else { 1691 } else {
1636 base::AutoLock locked(lookup_lock_); 1692 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction();
1693 SBWhitelist* whitelist = txn->GetWritableSBWhitelist(whitelist_id);
1637 whitelist->second = false; 1694 whitelist->second = false;
1638 whitelist->first.swap(new_whitelist); 1695 whitelist->first.swap(new_whitelist);
1639 } 1696 }
1640 } 1697 }
1641 1698
1642 void SafeBrowsingDatabaseNew::LoadIpBlacklist( 1699 void SafeBrowsingDatabaseNew::LoadIpBlacklist(
1643 const std::vector<SBAddFullHash>& full_hashes) { 1700 const std::vector<SBAddFullHash>& full_hashes) {
1644 DCHECK(thread_checker_.CalledOnValidThread());
1645
1646 IPBlacklist new_blacklist; 1701 IPBlacklist new_blacklist;
1647 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); 1702 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin();
1648 it != full_hashes.end(); 1703 it != full_hashes.end();
1649 ++it) { 1704 ++it) {
1650 const char* full_hash = it->full_hash.full_hash; 1705 const char* full_hash = it->full_hash.full_hash;
1651 DCHECK_EQ(crypto::kSHA256Length, arraysize(it->full_hash.full_hash)); 1706 DCHECK_EQ(crypto::kSHA256Length, arraysize(it->full_hash.full_hash));
1652 // The format of the IP blacklist is: 1707 // The format of the IP blacklist is:
1653 // SHA-1(IPv6 prefix) + uint8(prefix size) + 11 unused bytes. 1708 // SHA-1(IPv6 prefix) + uint8(prefix size) + 11 unused bytes.
1654 std::string hashed_ip_prefix(full_hash, base::kSHA1Length); 1709 std::string hashed_ip_prefix(full_hash, base::kSHA1Length);
1655 size_t prefix_size = static_cast<uint8>(full_hash[base::kSHA1Length]); 1710 size_t prefix_size = static_cast<uint8>(full_hash[base::kSHA1Length]);
(...skipping 13 matching lines...) Expand all
1669 } 1724 }
1670 DVLOG(2) << "Inserting malicious IP: " 1725 DVLOG(2) << "Inserting malicious IP: "
1671 << " raw:" << base::HexEncode(full_hash, crypto::kSHA256Length) 1726 << " raw:" << base::HexEncode(full_hash, crypto::kSHA256Length)
1672 << " mask:" << base::HexEncode(mask.data(), mask.size()) 1727 << " mask:" << base::HexEncode(mask.data(), mask.size())
1673 << " prefix_size:" << prefix_size 1728 << " prefix_size:" << prefix_size
1674 << " hashed_ip:" << base::HexEncode(hashed_ip_prefix.data(), 1729 << " hashed_ip:" << base::HexEncode(hashed_ip_prefix.data(),
1675 hashed_ip_prefix.size()); 1730 hashed_ip_prefix.size());
1676 new_blacklist[mask].insert(hashed_ip_prefix); 1731 new_blacklist[mask].insert(hashed_ip_prefix);
1677 } 1732 }
1678 1733
1679 base::AutoLock locked(lookup_lock_); 1734 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction();
1680 ip_blacklist_.swap(new_blacklist); 1735 txn->writable_ip_blacklist()->swap(new_blacklist);
1681 } 1736 }
1682 1737
1683 bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() { 1738 bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() {
1684 // This method is theoretically thread-safe but document that it is currently
1685 // only expected to be called on the IO thread.
1686 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1687
1688 SBFullHash malware_kill_switch = SBFullHashForString(kMalwareIPKillSwitchUrl); 1739 SBFullHash malware_kill_switch = SBFullHashForString(kMalwareIPKillSwitchUrl);
1689 std::vector<SBFullHash> full_hashes; 1740 std::vector<SBFullHash> full_hashes;
1690 full_hashes.push_back(malware_kill_switch); 1741 full_hashes.push_back(malware_kill_switch);
1691 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); 1742 return ContainsWhitelistedHashes(SBWhitelistId::CSD, full_hashes);
1692 } 1743 }
1693 1744
1694 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() { 1745 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() {
1695 // This method is theoretically thread-safe but document that it is currently 1746 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction();
1696 // only expected to be called on the IO thread. 1747 return txn->GetSBWhitelist(SBWhitelistId::CSD)->second;
1697 DCHECK_CURRENTLY_ON(BrowserThread::IO); 1748 }
1698 1749
1699 base::AutoLock locked(lookup_lock_); 1750 SafeBrowsingDatabaseNew::PrefixGetHashCache*
1700 return csd_whitelist_.second; 1751 SafeBrowsingDatabaseNew::GetUnsynchronizedPrefixGetHashCacheForTesting() {
1752 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction();
1753 return txn->prefix_gethash_cache();
1701 } 1754 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698