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

Unified Diff: components/safe_browsing_db/v4_get_hash_protocol_manager.h

Issue 2233103002: Move full hash caching logic to v4_get_hash_protocol_manager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Bring back the histogram to check if there were any hits in the response from the server Created 4 years, 3 months 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: components/safe_browsing_db/v4_get_hash_protocol_manager.h
diff --git a/components/safe_browsing_db/v4_get_hash_protocol_manager.h b/components/safe_browsing_db/v4_get_hash_protocol_manager.h
index d65e1a656db1f2c568983403c96b116198aa3f31..fb74446efcb403cb7bd28ef11f5d40171e2b1a64 100644
--- a/components/safe_browsing_db/v4_get_hash_protocol_manager.h
+++ b/components/safe_browsing_db/v4_get_hash_protocol_manager.h
@@ -37,111 +37,259 @@ class URLRequestContextGetter;
namespace safe_browsing {
+// The matching hash prefixes and corresponding stores, for each full hash
+// generated for a given URL.
+typedef base::hash_map<FullHash, StoreAndHashPrefixes>
+ FullHashToStoreAndHashPrefixesMap;
+
+// ----------------------------------------------------------------
+
+// All information about a particular full hash i.e. negative TTL, store for
+// which it is valid, and metadata associated with that store.
+struct FullHashInfo {
+ public:
+ FullHash full_hash;
+
+ // The list for which this full hash is applicable.
+ UpdateListIdentifier list_id;
+
+ // The expiration time of the full hash for a particular store.
+ base::Time positive_ttl;
Scott Hess - ex-Googler 2016/09/12 23:31:35 I'm slightly unnerved by this use of "ttl" with an
vakh (use Gerrit instead) 2016/09/13 00:12:07 I understand your concern but I feel like there ar
Scott Hess - ex-Googler 2016/09/13 00:31:34 Sometimes the code uses "expire" for this concept,
vakh (use Gerrit instead) 2016/09/13 01:18:56 Done.
+
+ // Any metadata for this full hash for a particular store.
+ ThreatMetadata metadata;
+
+ FullHashInfo(const FullHash& full_hash,
+ const UpdateListIdentifier& list_id,
+ const base::Time& positive_ttl);
+ FullHashInfo(const FullHashInfo& other);
+ ~FullHashInfo();
+
+ bool operator==(const FullHashInfo& other) const;
+ bool operator!=(const FullHashInfo& other) const;
+
+ private:
+ FullHashInfo();
+};
+
+// Caches individual response from GETHASH response.
+struct CachedHashPrefixInfo {
+ // The negative TTL for the hash prefix that leads to this
+ // CachedHashPrefixInfo. The client should not send any more requests for that
+ // hash prefix until this time.
+ base::Time negative_ttl;
+
+ // The list of all full hashes (and related info) that start with a
+ // particular hash prefix and are known to be unsafe.
+ std::vector<FullHashInfo> full_hash_infos;
+
+ CachedHashPrefixInfo();
+ CachedHashPrefixInfo(const CachedHashPrefixInfo& other);
+ ~CachedHashPrefixInfo();
+};
+
+// Cached full hashes received from the server for the corresponding hash
+// prefixes.
+typedef base::hash_map<HashPrefix, CachedHashPrefixInfo> FullHashCache;
+
+// FullHashCallback is invoked when GetFullHashes completes.
+// Parameters:
+// - The vector of full hash results. If empty, indicates that there
+// were no matches, and that the resource is safe.
Scott Hess - ex-Googler 2016/09/12 23:31:35 Is this going to acquire additional parameters? O
vakh (use Gerrit instead) 2016/09/13 00:12:07 Are you asking this because of "Parameters:"? I th
Scott Hess - ex-Googler 2016/09/13 00:31:34 Mostly because the comment is setup like "Here's t
vakh (use Gerrit instead) 2016/09/13 01:18:56 Done.
vakh (use Gerrit instead) 2016/09/13 01:18:56 Done.
+typedef base::Callback<void(const std::vector<FullHashInfo>&)> FullHashCallback;
+
+// Information needed to update the cache and call the callback to post the
+// results.
+struct FullHashCallbackInfo {
+ FullHashCallbackInfo();
+ FullHashCallbackInfo(const std::vector<FullHashInfo>& cached_full_hash_infos,
+ const std::vector<HashPrefix>& prefixes_requested,
+ std::unique_ptr<net::URLFetcher> fetcher,
+ const FullHashToStoreAndHashPrefixesMap&
+ full_hash_to_store_and_hash_prefixes,
+ const FullHashCallback& callback);
+ ~FullHashCallbackInfo();
+
+ // The FullHashInfo objects retrieved from cache. These are merged with the
+ // results received from the server before invoking the callback.
+ std::vector<FullHashInfo> cached_full_hash_infos;
+
+ // The callback method to call after collecting the full hashes for given
+ // hash prefixes.
+ FullHashCallback callback;
+
+ // The fetcher that will return the response from the server. This is stored
+ // here as a unique pointer to be able to reason about its lifetime easily.
+ std::unique_ptr<net::URLFetcher> fetcher;
+
+ // The generated full hashes and the corresponding prefixes and the stores in
+ // which to look for a full hash match.
+ FullHashToStoreAndHashPrefixesMap full_hash_to_store_and_hash_prefixes;
+
+ // The prefixes that were requested from the server.
+ std::vector<HashPrefix> prefixes_requested;
+};
+
+// ----------------------------------------------------------------
+
class V4GetHashProtocolManagerFactory;
class V4GetHashProtocolManager : public net::URLFetcherDelegate,
public base::NonThreadSafe {
public:
- // FullHashCallback is invoked when GetFullHashes completes.
+ // Invoked when GetFullHashesWithApis completes.
// Parameters:
- // - The vector of full hash results. If empty, indicates that there
- // were no matches, and that the resource is safe.
- // - The negative cache expire time of the result. This value may be
- // uninitialized, and the results should not be cached in this case.
- typedef base::Callback<void(const std::vector<SBFullHashResult>&,
- const base::Time&)>
- FullHashCallback;
+ // - The API threat metadata for the given URL.
+ typedef base::Callback<void(const ThreatMetadata& md)>
+ ThreatMetadataForApiCallback;
~V4GetHashProtocolManager() override;
+ // Create an instance of the safe browsing v4 protocol manager.
+ static std::unique_ptr<V4GetHashProtocolManager> Create(
+ net::URLRequestContextGetter* request_context_getter,
+ const base::hash_set<UpdateListIdentifier>& stores_to_request,
+ const V4ProtocolConfig& config);
+
// Makes the passed |factory| the factory used to instantiate
// a V4GetHashProtocolManager. Useful for tests.
static void RegisterFactory(
std::unique_ptr<V4GetHashProtocolManagerFactory> factory);
- // Create an instance of the safe browsing v4 protocol manager.
- static V4GetHashProtocolManager* Create(
- net::URLRequestContextGetter* request_context_getter,
- const V4ProtocolConfig& config);
-
- // net::URLFetcherDelegate interface.
- void OnURLFetchComplete(const net::URLFetcher* source) override;
+ // Empties the cache.
+ void ClearCache();
// Retrieve the full hash for a set of prefixes, and invoke the callback
// argument when the results are retrieved. The callback may be invoked
// synchronously.
- virtual void GetFullHashes(const std::vector<SBPrefix>& prefixes,
- const std::vector<PlatformType>& platforms,
- ThreatType threat_type,
+ virtual void GetFullHashes(const FullHashToStoreAndHashPrefixesMap&
+ full_hash_to_matching_hash_prefixes,
FullHashCallback callback);
- // Retrieve the full hash and API metadata for a set of prefixes, and invoke
- // the callback argument when the results are retrieved. The callback may be
- // invoked synchronously.
- virtual void GetFullHashesWithApis(const std::vector<SBPrefix>& prefixes,
- FullHashCallback callback);
+ // Retrieve the full hash and API metadata for a URL, and invoke the callback
+ // argument when the results are retrieved. The callback may be invoked
+ // synchronously.
+ // GetFullHashesWithApis is a special case of GetFullHashes. It is here
+ // primarily for legacy reasons: so that DatabaseManager, which speaks PVer3,
+ // and V4LocalDatabaseManager, which speaks PVer4, can both use this class to
+ // perform API lookups. Once PVer4 migration is complete, DatabaseManager
+ // should be deleted and then this method can be moved to the
+ // V4LocalDatabaseManager class.
+ // TODO(vakh): Move this method to V4LocalDatabaseManager after launching
+ // PVer4 in Chromium.
+ virtual void GetFullHashesWithApis(const GURL& url,
+ ThreatMetadataForApiCallback api_callback);
- // Overrides the clock used to check the time.
- void SetClockForTests(std::unique_ptr<base::Clock> clock);
+ // net::URLFetcherDelegate interface.
+ void OnURLFetchComplete(const net::URLFetcher* source) override;
protected:
// Constructs a V4GetHashProtocolManager that issues
// network requests using |request_context_getter|.
- V4GetHashProtocolManager(net::URLRequestContextGetter* request_context_getter,
- const V4ProtocolConfig& config);
+ V4GetHashProtocolManager(
+ net::URLRequestContextGetter* request_context_getter,
+ const base::hash_set<UpdateListIdentifier>& stores_to_request,
+ const V4ProtocolConfig& config);
private:
- FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest,
- TestGetHashRequest);
- FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest,
- TestParseHashResponse);
- FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest,
+ FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest, TestGetHashRequest);
+ FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest, TestParseHashResponse);
+ FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest,
TestParseHashResponseWrongThreatEntryType);
- FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest,
+ FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest,
TestParseHashThreatPatternType);
- FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest,
+ FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest,
TestParseHashResponseNonPermissionMetadata);
- FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest,
+ FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest,
TestParseHashResponseInconsistentThreatTypes);
- FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest,
+ FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest,
TestGetHashErrorHandlingOK);
- FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest,
+ FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest,
+ TestResultsNotCachedForNegativeCacheDuration);
+ FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest,
TestGetHashErrorHandlingNetwork);
- FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest,
+ FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest,
TestGetHashErrorHandlingResponseCode);
+ FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest, GetCachedResults);
+ FRIEND_TEST_ALL_PREFIXES(V4GetHashProtocolManagerTest, TestUpdatesAreMerged);
+ friend class V4GetHashProtocolManagerTest;
friend class V4GetHashProtocolManagerFactoryImpl;
+ FullHashCache* full_hash_cache_for_tests() { return &full_hash_cache_; }
+
+ // Looks up the cached results for full hashes in
+ // |full_hash_to_store_and_hash_prefixes|. Fills |prefixes_to_request| with
+ // the prefixes that need to be requested. Fills |cached_full_hash_infos|
+ // with the cached results.
+ // Note: It is valid for both |prefixes_to_request| and
+ // |cached_full_hash_infos| to be empty after this function finishes.
+ void GetFullHashCachedResults(
+ const FullHashToStoreAndHashPrefixesMap&
+ full_hash_to_store_and_hash_prefixes,
+ const base::Time& now,
+ std::vector<HashPrefix>* prefixes_to_request,
+ std::vector<FullHashInfo>* cached_full_hash_infos) const;
+
+ // Fills a FindFullHashesRequest protocol buffer for a request.
+ // Returns the serialized and base 64 encoded request as a string.
+ std::string GetHashRequest(
+ const std::vector<HashPrefix>& prefixes_to_request);
+
void GetHashUrlAndHeaders(const std::string& request_base64,
GURL* gurl,
net::HttpRequestHeaders* headers) const;
- // Fills a FindFullHashesRequest protocol buffer for a request.
- // Returns the serialized and base 64 encoded request as a string.
- std::string GetHashRequest(const std::vector<SBPrefix>& prefixes,
- const std::vector<PlatformType>& platforms,
- ThreatType threat_type);
+ // Updates internal state for each GetHash response error, assuming that
+ // the current time is |now|.
+ void HandleGetHashError(const base::Time& now);
+
+ // Merges the results from the cache and the results from the server. The
+ // response from the server may include information for full hashes from
+ // stores other than those required by this client so it filters out those
+ // results that the client did not ask for.
+ void MergeResults(const FullHashToStoreAndHashPrefixesMap&
+ full_hash_to_store_and_hash_prefixes,
+ const std::vector<FullHashInfo>& full_hash_infos,
+ std::vector<FullHashInfo>* merged_full_hash_infos);
+
+ // Calls |api_callback| with an object of ThreatMetadata that contains
+ // permission API metadata for full hashes in those |full_hash_infos| that
+ // have a full hash in |full_hashes|.
+ void OnFullHashForApi(const ThreatMetadataForApiCallback& api_callback,
+ const base::hash_set<FullHash>& full_hashes,
+ const std::vector<FullHashInfo>& full_hash_infos);
// Parses a FindFullHashesResponse protocol buffer and fills the results in
- // |full_hashes| and |negative_cache_expire|. |data| is a serialized
- // FindFullHashes protocol buffer. |negative_cache_expire| is the cache expiry
- // time of the response for entities that did not match the threat list.
- // Returns true if parsing is successful, false otherwise.
- bool ParseHashResponse(const std::string& data_base64,
- std::vector<SBFullHashResult>* full_hashes,
+ // |full_hash_infos| and |negative_cache_expire|. |response_data| is a
+ // serialized FindFullHashes protocol buffer. |negative_cache_expire| is the
+ // cache expiry time of the hash prefixes that were requested. Returns true if
+ // parsing is successful; false otherwise.
+ bool ParseHashResponse(const std::string& response_data,
+ std::vector<FullHashInfo>* full_hash_infos,
base::Time* negative_cache_expire);
+ // Parses the store specific |metadata| information from |match|. Returns
+ // true if the metadata information was parsed correctly and was consistent
+ // with what's expected from that corresponding store; false otherwise.
+ bool ParseMetadata(const ThreatMatch& match, ThreatMetadata* metadata);
+
// Resets the gethash error counter and multiplier.
void ResetGetHashErrors();
- // Updates internal state for each GetHash response error, assuming that
- // the current time is |now|.
- void HandleGetHashError(const base::Time& now);
+ // Overrides the clock used to check the time.
+ void SetClockForTests(std::unique_ptr<base::Clock> clock);
+
+ // Updates the state of the full hash cache upon receiving a valid response
+ // from the server.
+ void UpdateCache(const std::vector<HashPrefix>& prefixes_requested,
+ const std::vector<FullHashInfo>& full_hash_infos,
+ const base::Time& negative_cache_expire);
private:
// Map of GetHash requests to parameters which created it.
- using HashRequests = base::hash_map<
- const net::URLFetcher*,
- std::pair<std::unique_ptr<net::URLFetcher>, FullHashCallback>>;
+ using PendingHashRequests =
+ base::hash_map<const net::URLFetcher*,
+ std::unique_ptr<FullHashCallbackInfo>>;
// The factory that controls the creation of V4GetHashProtocolManager.
// This is used by tests.
@@ -159,7 +307,7 @@ class V4GetHashProtocolManager : public net::URLFetcherDelegate,
// Multiplier for the backoff error after the second.
size_t gethash_back_off_mult_;
- HashRequests hash_requests_;
+ PendingHashRequests pending_hash_requests_;
// For v4, the next gethash time is set to the backoff time is the last
// response was an error, or the minimum wait time if the last response was
@@ -178,6 +326,16 @@ class V4GetHashProtocolManager : public net::URLFetcherDelegate,
// The clock used to vend times.
std::unique_ptr<base::Clock> clock_;
+ // A cache of full hash results.
+ FullHashCache full_hash_cache_;
+
+ // The following sets represent the combination of lists that we would always
+ // request from the server, irrespective of which list we found the hash
+ // prefix match in.
+ base::hash_set<PlatformType> platform_types_;
+ base::hash_set<ThreatEntryType> threat_entry_types_;
+ base::hash_set<ThreatType> threat_types_;
+
DISALLOW_COPY_AND_ASSIGN(V4GetHashProtocolManager);
};
@@ -186,14 +344,19 @@ class V4GetHashProtocolManagerFactory {
public:
V4GetHashProtocolManagerFactory() {}
virtual ~V4GetHashProtocolManagerFactory() {}
- virtual V4GetHashProtocolManager* CreateProtocolManager(
+ virtual std::unique_ptr<V4GetHashProtocolManager> CreateProtocolManager(
net::URLRequestContextGetter* request_context_getter,
+ const base::hash_set<UpdateListIdentifier>& stores_to_request,
const V4ProtocolConfig& config) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(V4GetHashProtocolManagerFactory);
};
+#ifndef NDEBUG
+std::ostream& operator<<(std::ostream& os, const FullHashInfo& id);
+#endif
+
} // namespace safe_browsing
#endif // COMPONENTS_SAFE_BROWSING_DB_V4_GET_HASH_PROTOCOL_MANAGER_H_

Powered by Google App Engine
This is Rietveld 408576698