blob: c80f2da773f2d1489438d41e85060667c1b4f8f6 [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 <memory>
#include <string>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/threading/non_thread_safe.h"
#include "base/time/default_clock.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"
class GURL;
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 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;
~V4GetHashProtocolManager() override;
// 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;
// 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);
// Overrides the clock used to check the time.
void SetClockForTests(std::unique_ptr<base::Clock> clock);
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,
TestParseHashThreatPatternType);
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;
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);
// 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,
base::Time* negative_cache_expire);
// 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.
std::unique_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_;
// The clock used to vend times.
std::unique_ptr<base::Clock> clock_;
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_