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

Side by Side Diff: components/safe_browsing_db/v4_get_hash_protocol_manager.cc

Issue 1703413002: Move common PVer4 code into a V4ProtocolManagerUtil class. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: sync and fix compile Created 4 years, 10 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/safe_browsing_db/v4_get_hash_protocol_manager.h" 5 #include "components/safe_browsing_db/v4_get_hash_protocol_manager.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/base64.h" 9 #include "base/base64.h"
10 #include "base/logging.h"
11 #include "base/macros.h" 10 #include "base/macros.h"
12 #include "base/metrics/histogram_macros.h" 11 #include "base/metrics/histogram_macros.h"
13 #include "base/metrics/sparse_histogram.h"
14 #include "base/rand_util.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/timer/timer.h" 12 #include "base/timer/timer.h"
19 #include "net/base/escape.h"
20 #include "net/base/load_flags.h" 13 #include "net/base/load_flags.h"
21 #include "net/base/net_errors.h"
22 #include "net/http/http_response_headers.h" 14 #include "net/http/http_response_headers.h"
23 #include "net/http/http_status_code.h" 15 #include "net/http/http_status_code.h"
24 #include "net/url_request/url_fetcher.h" 16 #include "net/url_request/url_fetcher.h"
25 #include "net/url_request/url_request_context_getter.h" 17 #include "net/url_request/url_request_context_getter.h"
26 #include "net/url_request/url_request_status.h"
27 18
28 using base::Time; 19 using base::Time;
29 using base::TimeDelta; 20 using base::TimeDelta;
30 21
31 namespace { 22 namespace {
32 23
33 // Enumerate parsing failures for histogramming purposes. DO NOT CHANGE
34 // THE ORDERING OF THESE VALUES.
35 enum ParseResultType {
36 // Error parsing the protocol buffer from a string.
37 PARSE_FROM_STRING_ERROR = 0,
38
39 // A match in the response had an unexpected THREAT_ENTRY_TYPE.
40 UNEXPECTED_THREAT_ENTRY_TYPE_ERROR = 1,
41
42 // A match in the response had an unexpected THREAT_TYPE.
43 UNEXPECTED_THREAT_TYPE_ERROR = 2,
44
45 // A match in the response had an unexpected PLATFORM_TYPE.
46 UNEXPECTED_PLATFORM_TYPE_ERROR = 3,
47
48 // A match in the response contained no metadata where metadata was
49 // expected.
50 NO_METADATA_ERROR = 4,
51
52 // A match in the response contained a ThreatType that was inconsistent
53 // with the other matches.
54 INCONSISTENT_THREAT_TYPE_ERROR = 5,
55
56 // Memory space for histograms is determined by the max. ALWAYS
57 // ADD NEW VALUES BEFORE THIS ONE.
58 PARSE_GET_HASH_RESULT_MAX = 6
59 };
60
61 // Record parsing errors of a GetHash result. 24 // Record parsing errors of a GetHash result.
62 void RecordParseGetHashResult(ParseResultType result_type) { 25 void RecordParseGetHashResult(ParseResultType result_type) {
63 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.ParseV4HashResult", result_type, 26 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.ParseV4HashResult", result_type,
64 PARSE_GET_HASH_RESULT_MAX); 27 PARSE_RESULT_TYPE_MAX);
65 } 28 }
66 29
67 } // namespace 30 } // namespace
68 31
69 namespace safe_browsing { 32 namespace safe_browsing {
70 33
71 const char kUmaV4HashResponseMetricName[] = 34 const char kUmaV4HashResponseMetricName[] =
72 "SafeBrowsing.GetV4HashHttpResponseOrErrorCode"; 35 "SafeBrowsing.GetV4HashHttpResponseOrErrorCode";
73 36
74 // The default V4GetHashProtocolManagerFactory. 37 // The default V4GetHashProtocolManagerFactory.
75 class V4GetHashProtocolManagerFactoryImpl 38 class V4GetHashProtocolManagerFactoryImpl
76 : public V4GetHashProtocolManagerFactory { 39 : public V4GetHashProtocolManagerFactory {
77 public: 40 public:
78 V4GetHashProtocolManagerFactoryImpl() {} 41 V4GetHashProtocolManagerFactoryImpl() {}
79 ~V4GetHashProtocolManagerFactoryImpl() override {} 42 ~V4GetHashProtocolManagerFactoryImpl() override {}
80 V4GetHashProtocolManager* CreateProtocolManager( 43 V4GetHashProtocolManager* CreateProtocolManager(
81 net::URLRequestContextGetter* request_context_getter, 44 net::URLRequestContextGetter* request_context_getter,
82 const V4GetHashProtocolConfig& config) override { 45 const V4ProtocolConfig& config) override {
83 return new V4GetHashProtocolManager(request_context_getter, config); 46 return new V4GetHashProtocolManager(request_context_getter, config);
84 } 47 }
85 48
86 private: 49 private:
87 DISALLOW_COPY_AND_ASSIGN(V4GetHashProtocolManagerFactoryImpl); 50 DISALLOW_COPY_AND_ASSIGN(V4GetHashProtocolManagerFactoryImpl);
88 }; 51 };
89 52
90 // V4GetHashProtocolManager implementation -------------------------------- 53 // V4GetHashProtocolManager implementation --------------------------------
91 54
92 // static 55 // static
93 V4GetHashProtocolManagerFactory* V4GetHashProtocolManager::factory_ = NULL; 56 V4GetHashProtocolManagerFactory* V4GetHashProtocolManager::factory_ = NULL;
94 57
95 // static 58 // static
96 V4GetHashProtocolManager* V4GetHashProtocolManager::Create( 59 V4GetHashProtocolManager* V4GetHashProtocolManager::Create(
97 net::URLRequestContextGetter* request_context_getter, 60 net::URLRequestContextGetter* request_context_getter,
98 const V4GetHashProtocolConfig& config) { 61 const V4ProtocolConfig& config) {
99 if (!factory_) 62 if (!factory_)
100 factory_ = new V4GetHashProtocolManagerFactoryImpl(); 63 factory_ = new V4GetHashProtocolManagerFactoryImpl();
101 return factory_->CreateProtocolManager(request_context_getter, config); 64 return factory_->CreateProtocolManager(request_context_getter, config);
102 } 65 }
103 66
104 // static
105 // Backoff interval is MIN(((2^(n-1))*15 minutes) * (RAND + 1), 24 hours) where
106 // n is the number of consecutive errors.
107 base::TimeDelta V4GetHashProtocolManager::GetNextBackOffInterval(
108 size_t* error_count,
109 size_t* multiplier) {
110 DCHECK(multiplier && error_count);
111 (*error_count)++;
112 if (*error_count > 1 && *error_count < 9) {
113 // With error count 9 and above we will hit the 24 hour max interval.
114 // Cap the multiplier here to prevent integer overflow errors.
115 *multiplier *= 2;
116 }
117 base::TimeDelta next =
118 base::TimeDelta::FromMinutes(*multiplier * (1 + base::RandDouble()) * 15);
119
120 base::TimeDelta day = base::TimeDelta::FromHours(24);
121
122 if (next < day)
123 return next;
124 else
125 return day;
126 }
127
128 void V4GetHashProtocolManager::ResetGetHashErrors() { 67 void V4GetHashProtocolManager::ResetGetHashErrors() {
129 gethash_error_count_ = 0; 68 gethash_error_count_ = 0;
130 gethash_back_off_mult_ = 1; 69 gethash_back_off_mult_ = 1;
131 } 70 }
132 71
133 V4GetHashProtocolManager::V4GetHashProtocolManager( 72 V4GetHashProtocolManager::V4GetHashProtocolManager(
134 net::URLRequestContextGetter* request_context_getter, 73 net::URLRequestContextGetter* request_context_getter,
135 const V4GetHashProtocolConfig& config) 74 const V4ProtocolConfig& config)
136 : gethash_error_count_(0), 75 : gethash_error_count_(0),
137 gethash_back_off_mult_(1), 76 gethash_back_off_mult_(1),
138 next_gethash_time_(Time::FromDoubleT(0)), 77 next_gethash_time_(Time::FromDoubleT(0)),
139 version_(config.version), 78 config_(config),
140 client_name_(config.client_name),
141 key_param_(config.key_param),
142 request_context_getter_(request_context_getter), 79 request_context_getter_(request_context_getter),
143 url_fetcher_id_(0) { 80 url_fetcher_id_(0) {
144 DCHECK(!version_.empty());
145 } 81 }
146 82
147 // static 83 // static
148 void V4GetHashProtocolManager::RecordGetHashResult(ResultType result_type) { 84 void V4GetHashProtocolManager::RecordGetHashResult(ResultType result_type) {
149 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.GetV4HashResult", result_type, 85 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.GetV4HashResult", result_type,
150 GET_HASH_RESULT_MAX); 86 GET_HASH_RESULT_MAX);
151 } 87 }
152 88
153 void V4GetHashProtocolManager::RecordHttpResponseOrErrorCode(
154 const char* metric_name,
155 const net::URLRequestStatus& status,
156 int response_code) {
157 UMA_HISTOGRAM_SPARSE_SLOWLY(
158 metric_name, status.is_success() ? response_code : status.error());
159 }
160
161 V4GetHashProtocolManager::~V4GetHashProtocolManager() { 89 V4GetHashProtocolManager::~V4GetHashProtocolManager() {
162 // Delete in-progress SafeBrowsing requests. 90 // Delete in-progress SafeBrowsing requests.
163 STLDeleteContainerPairFirstPointers(hash_requests_.begin(), 91 STLDeleteContainerPairFirstPointers(hash_requests_.begin(),
164 hash_requests_.end()); 92 hash_requests_.end());
165 hash_requests_.clear(); 93 hash_requests_.clear();
166 } 94 }
167 95
168 std::string V4GetHashProtocolManager::GetHashRequest( 96 std::string V4GetHashProtocolManager::GetHashRequest(
169 const std::vector<SBPrefix>& prefixes, 97 const std::vector<SBPrefix>& prefixes,
170 const std::vector<PlatformType>& platforms, 98 const std::vector<PlatformType>& platforms,
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 259
332 HashRequests::iterator it = hash_requests_.find(source); 260 HashRequests::iterator it = hash_requests_.find(source);
333 DCHECK(it != hash_requests_.end()) << "Request not found"; 261 DCHECK(it != hash_requests_.end()) << "Request not found";
334 262
335 // FindFullHashes response. 263 // FindFullHashes response.
336 // Reset the scoped pointer so the fetcher gets destroyed properly. 264 // Reset the scoped pointer so the fetcher gets destroyed properly.
337 scoped_ptr<const net::URLFetcher> fetcher(it->first); 265 scoped_ptr<const net::URLFetcher> fetcher(it->first);
338 266
339 int response_code = source->GetResponseCode(); 267 int response_code = source->GetResponseCode();
340 net::URLRequestStatus status = source->GetStatus(); 268 net::URLRequestStatus status = source->GetStatus();
341 RecordHttpResponseOrErrorCode(kUmaV4HashResponseMetricName, status, 269 V4ProtocolManagerUtil::RecordHttpResponseOrErrorCode(
342 response_code); 270 kUmaV4HashResponseMetricName, status, response_code);
343 271
344 const FullHashCallback& callback = it->second; 272 const FullHashCallback& callback = it->second;
345 std::vector<SBFullHashResult> full_hashes; 273 std::vector<SBFullHashResult> full_hashes;
346 base::TimeDelta negative_cache_duration; 274 base::TimeDelta negative_cache_duration;
347 if (status.is_success() && response_code == net::HTTP_OK) { 275 if (status.is_success() && response_code == net::HTTP_OK) {
348 RecordGetHashResult(GET_HASH_STATUS_200); 276 RecordGetHashResult(GET_HASH_STATUS_200);
349 ResetGetHashErrors(); 277 ResetGetHashErrors();
350 std::string data; 278 std::string data;
351 source->GetResponseAsString(&data); 279 source->GetResponseAsString(&data);
352 if (!ParseHashResponse(data, &full_hashes, &negative_cache_duration)) { 280 if (!ParseHashResponse(data, &full_hashes, &negative_cache_duration)) {
(...skipping 17 matching lines...) Expand all
370 // Invoke the callback with full_hashes, even if there was a parse error or 298 // Invoke the callback with full_hashes, even if there was a parse error or
371 // an error response code (in which case full_hashes will be empty). The 299 // an error response code (in which case full_hashes will be empty). The
372 // caller can't be blocked indefinitely. 300 // caller can't be blocked indefinitely.
373 callback.Run(full_hashes, negative_cache_duration); 301 callback.Run(full_hashes, negative_cache_duration);
374 302
375 hash_requests_.erase(it); 303 hash_requests_.erase(it);
376 } 304 }
377 305
378 void V4GetHashProtocolManager::HandleGetHashError(const Time& now) { 306 void V4GetHashProtocolManager::HandleGetHashError(const Time& now) {
379 DCHECK(CalledOnValidThread()); 307 DCHECK(CalledOnValidThread());
380 base::TimeDelta next = 308 base::TimeDelta next = V4ProtocolManagerUtil::GetNextBackOffInterval(
381 GetNextBackOffInterval(&gethash_error_count_, &gethash_back_off_mult_); 309 &gethash_error_count_, &gethash_back_off_mult_);
382 next_gethash_time_ = now + next; 310 next_gethash_time_ = now + next;
383 } 311 }
384 312
385 // The API hash call uses the pver4 Safe Browsing server. 313 GURL V4GetHashProtocolManager::GetHashUrl(const std::string& req_base64) const {
386 GURL V4GetHashProtocolManager::GetHashUrl( 314 return V4ProtocolManagerUtil::GetRequestUrl(req_base64, "encodedFullHashes",
387 const std::string& request_base64) const { 315 config_);
388 std::string url =
389 ComposePver4Url(kSbV4UrlPrefix, "encodedFullHashes", request_base64,
390 client_name_, version_, key_param_);
391 return GURL(url);
392 } 316 }
393 317
394 // static
395 std::string V4GetHashProtocolManager::ComposePver4Url(
396 const std::string& prefix,
397 const std::string& method,
398 const std::string& request_base64,
399 const std::string& client_id,
400 const std::string& version,
401 const std::string& key_param) {
402 DCHECK(!prefix.empty() && !method.empty() && !client_id.empty() &&
403 !version.empty());
404 std::string url =
405 base::StringPrintf("%s/%s/%s?alt=proto&client_id=%s&client_version=%s",
406 prefix.c_str(), method.c_str(), request_base64.c_str(),
407 client_id.c_str(), version.c_str());
408 if (!key_param.empty()) {
409 base::StringAppendF(&url, "&key=%s",
410 net::EscapeQueryParamValue(key_param, true).c_str());
411 }
412 return url;
413 }
414 318
415 } // namespace safe_browsing 319 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698