| 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_;
|
| };
|
|
|