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

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: fix memory management 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
« no previous file with comments | « no previous file | chrome/browser/safe_browsing/safe_browsing_database.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 64148ce8aa3a92a30db9aa0135d77a4c6e52b85b..68dea690946034b3bed9172b659946cc9643bd95 100644
--- a/chrome/browser/safe_browsing/safe_browsing_database.h
+++ b/chrome/browser/safe_browsing/safe_browsing_database.h
@@ -117,7 +117,7 @@ class SafeBrowsingDatabase {
// Returns false if none of |urls| are in Download database. If it returns
// true, |prefix_hits| should contain the prefixes for the URLs that were in
- // the database. This function can ONLY be called from the creation thread.
+ // the database. This function can ONLY be accessed from creation thread.
virtual bool ContainsDownloadUrl(const std::vector<GURL>& urls,
std::vector<SBPrefix>* prefix_hits) = 0;
@@ -140,7 +140,7 @@ class SafeBrowsingDatabase {
// Populates |prefix_hits| with any prefixes in |prefixes| that have matches
// in the database.
//
- // This function can ONLY be called from the creation thread.
+ // This function can ONLY be accessed from the creation thread.
virtual bool ContainsExtensionPrefixes(
const std::vector<SBPrefix>& prefixes,
std::vector<SBPrefix>* prefix_hits) = 0;
@@ -367,11 +367,98 @@ 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,
+ };
+
+ // Obtained through BeginReadTransaction(NoLockOnMainThread)?(): 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;
+
+ // Obtained through BeginWriteTransaction(): 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;
+
+ explicit ThreadSafeStateManager(const base::ThreadChecker& thread_checker);
+ ~ThreadSafeStateManager();
+
+ scoped_ptr<ReadTransaction> BeginReadTransaction();
+ scoped_ptr<ReadTransaction> BeginReadTransactionNoLockOnMainThread();
+ scoped_ptr<WriteTransaction> BeginWriteTransaction();
+
+ private:
+ // The SafeBrowsingDatabase's ThreadChecker, used to verify that writes are
+ // only made on its main thread. This is important as it allows reading from
+ // the main thread without holding the lock.
+ const base::ThreadChecker& thread_checker_;
+
+ // Lock for protecting access to this class' state.
+ mutable 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. The cache is "mutable"
+ // as it can be written to from any transaction holding the lock, including
+ // ReadTransactions.
+ mutable 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 +467,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 +485,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 +507,7 @@ 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);
-
- // 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);
+ SBWhitelistId whitelist_id);
// Parses the IP blacklist from the given full-length hashes.
void LoadIpBlacklist(const std::vector<SBAddFullHash>& full_hashes);
@@ -453,27 +540,31 @@ 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).
+ // 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();
+
base::ThreadChecker thread_checker_;
+ ThreadSafeStateManager state_manager_;
+
// The base filename passed to Init(), used to generate the store and prefix
// set filenames used to store data on disk.
base::FilePath filename_base_;
@@ -505,21 +596,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 +605,6 @@ class SafeBrowsingDatabaseNew : public SafeBrowsingDatabase {
// Used to optimize away database update.
bool change_detected_;
- // 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_;
};
« no previous file with comments | « no previous file | chrome/browser/safe_browsing/safe_browsing_database.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698