summaryrefslogtreecommitdiffstats
path: root/components/safe_browsing_db/v4_update_protocol_manager.h
blob: 19e323436c67faf1037f7a482bcc96b5e64159d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// 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_UPDATE_PROTOCOL_MANAGER_H_
#define COMPONENTS_SAFE_BROWSING_DB_V4_UPDATE_PROTOCOL_MANAGER_H_

// A class that implements Chrome's interface with the SafeBrowsing V4 update
// protocol.
//
// The V4UpdateProtocolManager handles formatting and making requests of, and
// handling responses from, Google's SafeBrowsing servers. The purpose of this
// class is to get hash prefixes from the SB server for the given set of lists.

#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 V4UpdateProtocolManagerFactory;

class V4UpdateProtocolManager : public net::URLFetcherDelegate,
                                public base::NonThreadSafe {
 public:
  typedef FetchThreatListUpdatesRequest::ListUpdateRequest ListUpdateRequest;
  typedef FetchThreatListUpdatesResponse::ListUpdateResponse ListUpdateResponse;

  // UpdateCallback is invoked when GetUpdates completes.
  // Parameters:
  //   - The vector of update response protobufs received from the server for
  //     each list type.
  //  The caller can then use this vector to re-build the current_list_states.
  typedef base::Callback<void(const std::vector<ListUpdateResponse>&)>
      UpdateCallback;

  ~V4UpdateProtocolManager() override;

  // Makes the passed |factory| the factory used to instantiate
  // a V4UpdateProtocolManager. Useful for tests.
  static void RegisterFactory(V4UpdateProtocolManagerFactory* factory) {
    factory_ = factory;
  }

  // Create an instance of the safe browsing v4 protocol manager.
  static V4UpdateProtocolManager* Create(
      net::URLRequestContextGetter* request_context_getter,
      const V4ProtocolConfig& config);

  // net::URLFetcherDelegate interface.
  void OnURLFetchComplete(const net::URLFetcher* source) override;

  // Retrieve the hash prefix update, and invoke the callback argument when the
  // results are retrieved. The callback may be invoked synchronously.
  // Parameters:
  //   - The set of lists to fetch the updates for.
  //   - The last known state for each of the known lists.
  // It is valid to have one or more lists in lists_to_update set that have no
  // corresponding value in the current_list_states map. This corresponds to the
  // initial state for those lists.
  virtual void GetUpdates(
      const base::hash_set<UpdateListIdentifier>& lists_to_update,
      const base::hash_map<UpdateListIdentifier, std::string>&
          current_list_states,
      UpdateCallback callback);

 protected:
  // Constructs a V4UpdateProtocolManager that issues network requests using
  // |request_context_getter|.
  V4UpdateProtocolManager(net::URLRequestContextGetter* request_context_getter,
                          const V4ProtocolConfig& config);

 private:
  FRIEND_TEST_ALL_PREFIXES(V4UpdateProtocolManagerTest,
                           TestGetUpdatesErrorHandlingNetwork);
  FRIEND_TEST_ALL_PREFIXES(V4UpdateProtocolManagerTest,
                           TestGetUpdatesErrorHandlingResponseCode);
  FRIEND_TEST_ALL_PREFIXES(V4UpdateProtocolManagerTest, TestGetUpdatesNoError);
  friend class V4UpdateProtocolManagerFactoryImpl;

  // The method to generate the URL for the request to be sent to the server.
  // |request_base64| is the base64 encoded form of an instance of the protobuf
  // FetchThreatListUpdatesRequest.
  GURL GetUpdateUrl(const std::string& request_base64) const;

  // Fills a FetchThreatListUpdatesRequest protocol buffer for a request.
  // Returns the serialized and base 64 encoded request as a string.
  std::string GetUpdateRequest(
      const base::hash_set<UpdateListIdentifier>& lists_to_update,
      const base::hash_map<UpdateListIdentifier, std::string>&
          current_list_states);

  // Parses the base64 encoded response received from the server as a
  // FetchThreatListUpdatesResponse protobuf and returns each of the
  // ListUpdateResponse protobufs contained in it as a vector.
  // Returns true if parsing is successful, false otherwise.
  bool ParseUpdateResponse(
      const std::string& data_base64,
      std::vector<ListUpdateResponse>* list_update_responses);

  // Resets the update error counter and multiplier.
  void ResetUpdateErrors();

  // Updates internal update and backoff state for each update response error,
  // assuming that the current time is |now|.
  void HandleUpdateError(const base::Time& now);

  // The factory that controls the creation of V4UpdateProtocolManager.
  // This is used by tests.
  static V4UpdateProtocolManagerFactory* factory_;

  // The number of HTTP response errors since the the last successful HTTP
  // response, used for request backoff timing.
  size_t update_error_count_;

  // Multiplier for the backoff error after the second.
  size_t update_back_off_mult_;

  // The time before which the next update request may not be sent.
  // It is set to:
  // the backoff time, if the last response was an error, or
  // the minimum wait time, if the last response was successful.
  base::Time next_update_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_;

  // True if there's a request pending.
  bool update_request_pending_;

  // The callback that's called when GetUpdates completes.
  UpdateCallback callback_;

  // The pending update request. The request must be canceled when the object is
  // destroyed.
  scoped_ptr<net::URLFetcher> request_;

  DISALLOW_COPY_AND_ASSIGN(V4UpdateProtocolManager);
};

// Interface of a factory to create V4UpdateProtocolManager.  Useful for tests.
class V4UpdateProtocolManagerFactory {
 public:
  V4UpdateProtocolManagerFactory() {}
  virtual ~V4UpdateProtocolManagerFactory() {}
  virtual V4UpdateProtocolManager* CreateProtocolManager(
      net::URLRequestContextGetter* request_context_getter,
      const V4ProtocolConfig& config) = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(V4UpdateProtocolManagerFactory);
};

}  // namespace safe_browsing

#endif  // COMPONENTS_SAFE_BROWSING_DB_V4_UPDATE_PROTOCOL_MANAGER_H_