blob: f0bfc7410c0ad5d91c6d89882e944b40cee06441 [file] [log] [blame]
// 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 <string>
#include <vector>
#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<void(const std::vector<SBFullHashResult>&,
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<SBPrefix>& prefixes,
const std::vector<PlatformType>& 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<SBPrefix>& prefixes,
FullHashCallback callback);
// Enumerate failures for histogramming purposes. DO NOT CHANGE THE
// ORDERING OF THESE VALUES.
enum ResultType {
// 200 response code means that the server recognized the hash
// prefix.
GET_HASH_STATUS_200 = 0,
// Subset of successful responses where the response body wasn't parsable.
GET_HASH_PARSE_ERROR = 1,
// Gethash request failed (network error).
GET_HASH_NETWORK_ERROR = 2,
// Gethash request returned HTTP result code other than 200.
GET_HASH_HTTP_ERROR = 3,
// Gethash attempted during error backoff, no request sent.
GET_HASH_BACKOFF_ERROR = 4,
// Gethash attempted before min wait duration elapsed, no request sent.
GET_HASH_MIN_WAIT_DURATION_ERROR = 5,
// Memory space for histograms is determined by the max. ALWAYS
// ADD NEW VALUES BEFORE THIS ONE.
GET_HASH_RESULT_MAX = 6
};
// Record a GetHash result.
static void RecordGetHashResult(ResultType result_type);
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<SBPrefix>& prefixes,
const std::vector<PlatformType>& 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<SBFullHashResult>* 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<const net::URLFetcher*, FullHashCallback> 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<net::URLFetcher> 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<net::URLRequestContextGetter> 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_