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 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |