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

Unified Diff: chrome/browser/safe_browsing/safe_browsing_database.h

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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/safe_browsing/safe_browsing_database.h
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.h b/chrome/browser/safe_browsing/safe_browsing_database.h
index 37dcf8f06f9ce0f8ce197e6512c2e64dad285981..9d381778077a8b51bd3557acaf2225438e58c541 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.h
+++ b/chrome/browser/safe_browsing/safe_browsing_database.h
@@ -367,11 +367,95 @@ class SafeBrowsingDatabaseNew : public SafeBrowsingDatabase {
// IPv6 IP prefix using SHA-1.
typedef std::map<std::string, base::hash_set<std::string> > IPBlacklist;
- bool PrefixSetContainsUrl(
- const GURL& url,
- scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter,
- std::vector<SBPrefix>* prefix_hits,
- std::vector<SBFullHashResult>* cache_hits);
+ typedef std::map<SBPrefix, SBCachedFullHashResult> PrefixGetHashCache;
+
+ // The ThreadSafeStateManager holds the SafeBrowsingDatabase's state which
+ // must be accessed in a thread-safe fashion. It must be constructed on the
+ // SafeBrowsingDatabaseManager's main thread. The main thread will then be the
+ // only thread on which this state can be modified; allowing for unlocked
+ // reads on the main thread and thus avoiding contention while performing
+ // intensive operations such as writing that state to disk. The state can only
+ // be accessed via (Read|Write)Transactions obtained through this class which
+ // will automatically handle thread-safety.
+ class ThreadSafeStateManager {
+ public:
+ // Identifiers for stores held by the ThreadSafeStateManager. Allows helper
+ // methods to start a transaction themselves and keep it as short as
+ // possible rather than force callers to start the transaction early to pass
+ // a store pointer to the said helper methods.
+ enum class SBWhitelistId {
+ CSD,
+ DOWNLOAD,
+ };
+ enum class PrefixSetId {
+ BROWSE,
+ SIDE_EFFECT_FREE_WHITELIST,
+ UNWANTED_SOFTWARE,
+ };
+
+ // A ReadTransaction allows read-only observations of the
+ // ThreadSafeStateManager's state. The |prefix_gethash_cache_| has a special
+ // allowance to be writable from a ReadTransaction but can't benefit from
+ // unlocked ReadTransactions. ReadTransaction should be held for the
+ // shortest amount of time possible (e.g., release it before computing final
+ // results if possible).
+ class ReadTransaction;
+
+ // A WriteTransaction allows modification of the ThreadSafeStateManager's
+ // state. It should be used for the shortest amount of time possible (e.g.,
+ // pre-compute the new state before grabbing a WriteTransaction to swap it
+ // in atomically).
+ class WriteTransaction;
+
+ ThreadSafeStateManager();
+ ~ThreadSafeStateManager();
+
+ scoped_ptr<ReadTransaction> BeginReadTransaction();
+ scoped_ptr<ReadTransaction> BeginReadTransactionNoLockOnMainThread();
+ scoped_ptr<WriteTransaction> BeginWriteTransaction();
+
+ private:
+ // Used to verify that writes are only made on this object's main thread.
+ // This is important as this class allows reading from the main thread
+ // without holding the lock.
+ base::ThreadChecker thread_checker_;
+
+ // Lock for protecting access to this class' state.
+ base::Lock lock_;
+
+ SBWhitelist csd_whitelist_;
+ SBWhitelist download_whitelist_;
+
+ // The IP blacklist should be small. At most a couple hundred IPs.
+ IPBlacklist ip_blacklist_;
+
+ // PrefixSets to speed up lookups for particularly large lists. The
+ // PrefixSet themselves are never modified, instead a new one is swapped in
+ // on update.
+ scoped_ptr<const safe_browsing::PrefixSet> browse_prefix_set_;
+ scoped_ptr<const safe_browsing::PrefixSet>
+ side_effect_free_whitelist_prefix_set_;
+ scoped_ptr<const safe_browsing::PrefixSet> unwanted_software_prefix_set_;
+
+ // Cache of gethash results for prefix stores. Entries should not be used if
+ // they are older than their expire_after field. Cached misses will have
+ // empty full_hashes field. Cleared on each update.
+ PrefixGetHashCache prefix_gethash_cache_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThreadSafeStateManager);
+ };
+
+ // Forward the above inner-definitions to alleviate some verbosity in the
+ // impl.
+ using SBWhitelistId = ThreadSafeStateManager::SBWhitelistId;
+ using PrefixSetId = ThreadSafeStateManager::PrefixSetId;
+ using ReadTransaction = ThreadSafeStateManager::ReadTransaction;
+ using WriteTransaction = ThreadSafeStateManager::WriteTransaction;
+
+ bool PrefixSetContainsUrl(const GURL& url,
+ PrefixSetId prefix_set_id,
+ std::vector<SBPrefix>* prefix_hits,
+ std::vector<SBFullHashResult>* cache_hits);
// Exposed for testing of PrefixSetContainsUrlHashes() on the
// PrefixSet backing kMalwareList.
@@ -380,15 +464,14 @@ class SafeBrowsingDatabaseNew : public SafeBrowsingDatabase {
std::vector<SBPrefix>* prefix_hits,
std::vector<SBFullHashResult>* cache_hits);
- bool PrefixSetContainsUrlHashes(
- const std::vector<SBFullHash>& full_hashes,
- scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter,
- std::vector<SBPrefix>* prefix_hits,
- std::vector<SBFullHashResult>* cache_hits);
+ bool PrefixSetContainsUrlHashes(const std::vector<SBFullHash>& full_hashes,
+ PrefixSetId prefix_set_id,
+ std::vector<SBPrefix>* prefix_hits,
+ std::vector<SBFullHashResult>* cache_hits);
// Returns true if the whitelist is disabled or if any of the given hashes
// matches the whitelist.
- bool ContainsWhitelistedHashes(const SBWhitelist& whitelist,
+ bool ContainsWhitelistedHashes(SBWhitelistId whitelist_id,
const std::vector<SBFullHash>& hashes);
// Return the browse_store_, download_store_, download_whitelist_store or
@@ -399,10 +482,15 @@ class SafeBrowsingDatabaseNew : public SafeBrowsingDatabase {
bool Delete();
// Load the prefix set in "|db_filename| Prefix Set" off disk, if available,
- // and stores it in |prefix_set|. |read_failure_type| provides a
- // caller-specific error code to be used on failure.
+ // and stores it in the PrefixSet identified by |prefix_set_id|.
+ // |read_failure_type| provides a caller-specific error code to be used on
+ // failure. This method should only ever be called during initialization as
+ // it performs some disk IO while holding a transaction (for the sake of
+ // avoiding uncessary back-and-forth interactions with the lock during
+ // Init()).
void LoadPrefixSet(const base::FilePath& db_filename,
- scoped_ptr<const safe_browsing::PrefixSet>* prefix_set,
+ ThreadSafeStateManager::WriteTransaction* txn,
+ PrefixSetId prefix_set_id,
FailureType read_failure_type);
// Writes the current prefix set "|db_filename| Prefix Set" on disk.
@@ -416,11 +504,11 @@ class SafeBrowsingDatabaseNew : public SafeBrowsingDatabase {
// of hashes is too large or if the kill switch URL is on the whitelist
// we will whitelist everything.
void LoadWhitelist(const std::vector<SBAddFullHash>& full_hashes,
- SBWhitelist* whitelist);
+ SBWhitelistId whitelist_id);
// Call this method if an error occured with the given whitelist. This will
// result in all lookups to the whitelist to return true.
- void WhitelistEverything(SBWhitelist* whitelist);
+ void WhitelistEverything(SBWhitelistId whitelist_id);
// Parses the IP blacklist from the given full-length hashes.
void LoadIpBlacklist(const std::vector<SBAddFullHash>& full_hashes);
@@ -453,26 +541,28 @@ class SafeBrowsingDatabaseNew : public SafeBrowsingDatabase {
// to highlight the specific store who made the initial request on failure.
// |store_full_hashes_in_prefix_set| dictates whether full_hashes from the
// |url_store| should be cached in the |prefix_set| as well.
- void UpdatePrefixSetUrlStore(
- const base::FilePath& db_filename,
- SafeBrowsingStore* url_store,
- scoped_ptr<const safe_browsing::PrefixSet>* prefix_set,
- FailureType finish_failure_type,
- FailureType write_failure_type,
- bool store_full_hashes_in_prefix_set);
+ void UpdatePrefixSetUrlStore(const base::FilePath& db_filename,
+ SafeBrowsingStore* url_store,
+ PrefixSetId prefix_set_id,
+ FailureType finish_failure_type,
+ FailureType write_failure_type,
+ bool store_full_hashes_in_prefix_set);
void UpdateUrlStore(SafeBrowsingStore* url_store,
- scoped_ptr<const safe_browsing::PrefixSet>* prefix_set,
+ PrefixSetId prefix_set_id,
FailureType failure_type);
void UpdateWhitelistStore(const base::FilePath& store_filename,
SafeBrowsingStore* store,
- SBWhitelist* whitelist);
+ SBWhitelistId whitelist_id);
void UpdateIpBlacklistStore();
- // Used to verify that various calls are made from the thread the
- // object was created on (i.e., the safe_browsing_thread).
- base::ThreadChecker thread_checker_;
+ // Returns a raw pointer to ThreadSafeStateManager's PrefixGetHashCache for
+ // testing. This should only be used in unit tests (where multi-threading and
+ // synchronization are not problematic).
+ PrefixGetHashCache* GetUnsynchronizedPrefixGetHashCacheForTesting();
+
+ ThreadSafeStateManager state_manager_;
// The base filename passed to Init(), used to generate the store and prefix
// set filenames used to store data on disk.
@@ -505,21 +595,6 @@ class SafeBrowsingDatabaseNew : public SafeBrowsingDatabase {
// For unwanted software list.
scoped_ptr<SafeBrowsingStore> unwanted_software_store_;
- // Lock for protecting access to variables that may be used on any threads.
- // This includes all SBWhitelist's, PrefixSet's, and caches.
- base::Lock lookup_lock_;
-
- SBWhitelist csd_whitelist_;
- SBWhitelist download_whitelist_;
-
- // The IP blacklist should be small. At most a couple hundred IPs.
- IPBlacklist ip_blacklist_;
-
- // Cache of gethash results for prefix stores. Entries should not be used if
- // they are older than their expire_after field. Cached misses will have
- // empty full_hashes field. Cleared on each update.
- std::map<SBPrefix, SBCachedFullHashResult> prefix_gethash_cache_;
-
// Set if corruption is detected during the course of an update.
// Causes the update functions to fail with no side effects, until
// the next call to |UpdateStarted()|.
@@ -529,17 +604,6 @@ class SafeBrowsingDatabaseNew : public SafeBrowsingDatabase {
// Used to optimize away database update.
bool change_detected_;
mattm 2014/12/12 23:20:31 Should all the non-thread-safe members be moved to
gab 2014/12/15 23:02:30 Good point, do you think the SafeBrowsingStores sh
mattm 2014/12/23 02:09:45 I guess to make it more consistent putting them in
gab 2014/12/23 21:39:54 SG, how about we do this in a follow-up CL since t
mattm 2014/12/24 00:29:53 separate CL sounds good
- // PrefixSets to speed up lookups for particularly large lists. The PrefixSet
- // themselves are never modified, instead a new one is swapped in on update
- // while holding |lookup_lock_|. Any thread other than this class' main thread
- // (which handles updates) must hold |lookup_lock_| before reading from these
- // sets.
- // TODO(gab): Enforce this by design.
- scoped_ptr<const safe_browsing::PrefixSet> browse_prefix_set_;
- scoped_ptr<const safe_browsing::PrefixSet>
- side_effect_free_whitelist_prefix_set_;
- scoped_ptr<const safe_browsing::PrefixSet> unwanted_software_prefix_set_;
-
// Used to schedule resetting the database because of corruption.
base::WeakPtrFactory<SafeBrowsingDatabaseNew> reset_factory_;
};

Powered by Google App Engine
This is Rietveld 408576698