// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_SAFE_BROWSING_DB_V4_GET_HASH_PROTOCOL_MANAGER_H_ #define COMPONENTS_SAFE_BROWSING_DB_V4_GET_HASH_PROTOCOL_MANAGER_H_ // A class that implements Chrome's interface with the SafeBrowsing V4 protocol. // // The V4GetHashProtocolManager handles formatting and making requests of, and // handling responses from, Google's SafeBrowsing servers. The purpose of this // class is to get full hash matches from the SB server for the given set of // hash prefixes. #include #include #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/threading/non_thread_safe.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "components/safe_browsing_db/safebrowsing.pb.h" #include "components/safe_browsing_db/util.h" #include "components/safe_browsing_db/v4_protocol_manager_util.h" #include "net/url_request/url_fetcher_delegate.h" #include "url/gurl.h" namespace net { class URLFetcher; class URLRequestContextGetter; } // namespace net namespace safe_browsing { class V4GetHashProtocolManagerFactory; class V4GetHashProtocolManager : public net::URLFetcherDelegate, public base::NonThreadSafe { public: // 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. // - The negative cache duration of the result. typedef base::Callback&, const base::TimeDelta&)> FullHashCallback; ~V4GetHashProtocolManager() override; // Makes the passed |factory| the factory used to instantiate // a V4GetHashProtocolManager. Useful for tests. static void RegisterFactory(V4GetHashProtocolManagerFactory* factory) { factory_ = 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; // 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& prefixes, const std::vector& platforms, ThreatType threat_type, 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& prefixes, FullHashCallback callback); protected: // Constructs a V4GetHashProtocolManager that issues // network requests using |request_context_getter|. V4GetHashProtocolManager( net::URLRequestContextGetter* request_context_getter, const V4ProtocolConfig& config); private: FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest, TestGetHashRequest); FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest, TestParseHashResponse); FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest, TestParseHashResponseWrongThreatEntryType); FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest, TestParseHashResponseSocialEngineeringThreatType); FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest, TestParseHashResponseNonPermissionMetadata); FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest, TestParseHashResponseInconsistentThreatTypes); FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest, TestGetHashErrorHandlingOK); FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest, TestGetHashErrorHandlingNetwork); FRIEND_TEST_ALL_PREFIXES(SafeBrowsingV4GetHashProtocolManagerTest, TestGetHashErrorHandlingResponseCode); friend class V4GetHashProtocolManagerFactoryImpl; GURL GetHashUrl(const std::string& request_base64) 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& prefixes, const std::vector& platforms, ThreatType threat_type); // Parses a FindFullHashesResponse protocol buffer and fills the results in // |full_hashes| and |negative_cache_duration|. |data| is a serialized // FindFullHashes protocol buffer. |negative_cache_duration| is the duration // to cache 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* full_hashes, base::TimeDelta* negative_cache_duration); // 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); private: // Map of GetHash requests to parameters which created it. typedef base::hash_map HashRequests; // The factory that controls the creation of V4GetHashProtocolManager. // This is used by tests. static V4GetHashProtocolManagerFactory* factory_; // Current active request (in case we need to cancel) for updates or chunks // from the SafeBrowsing service. We can only have one of these outstanding // at any given time unlike GetHash requests, which are tracked separately. scoped_ptr request_; // The number of HTTP response errors since the the last successful HTTP // response, used for request backoff timing. size_t gethash_error_count_; // Multiplier for the backoff error after the second. size_t gethash_back_off_mult_; HashRequests 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 // successful. base::Time next_gethash_time_; // The config of the client making Pver4 requests. const V4ProtocolConfig config_; // The context we use to issue network requests. scoped_refptr request_context_getter_; // ID for URLFetchers for testing. int url_fetcher_id_; DISALLOW_COPY_AND_ASSIGN(V4GetHashProtocolManager); }; // Interface of a factory to create V4GetHashProtocolManager. Useful for tests. class V4GetHashProtocolManagerFactory { public: V4GetHashProtocolManagerFactory() {} virtual ~V4GetHashProtocolManagerFactory() {} virtual V4GetHashProtocolManager* CreateProtocolManager( net::URLRequestContextGetter* request_context_getter, const V4ProtocolConfig& config) = 0; private: DISALLOW_COPY_AND_ASSIGN(V4GetHashProtocolManagerFactory); }; } // namespace safe_browsing #endif // COMPONENTS_SAFE_BROWSING_DB_V4_GET_HASH_PROTOCOL_MANAGER_H_