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

Side by Side Diff: chrome/browser/safe_browsing/protocol_manager.cc

Issue 1555953002: Adds backoff and Min Wait Duration compliance to Protocolmanager pver4 handlers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@osb-pm-2
Patch Set: Rebase Created 4 years, 11 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/safe_browsing/protocol_manager.h" 5 #include "chrome/browser/safe_browsing/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/environment.h" 10 #include "base/environment.h"
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 } 134 }
135 135
136 SafeBrowsingProtocolManager::SafeBrowsingProtocolManager( 136 SafeBrowsingProtocolManager::SafeBrowsingProtocolManager(
137 SafeBrowsingProtocolManagerDelegate* delegate, 137 SafeBrowsingProtocolManagerDelegate* delegate,
138 net::URLRequestContextGetter* request_context_getter, 138 net::URLRequestContextGetter* request_context_getter,
139 const SafeBrowsingProtocolConfig& config) 139 const SafeBrowsingProtocolConfig& config)
140 : delegate_(delegate), 140 : delegate_(delegate),
141 request_type_(NO_REQUEST), 141 request_type_(NO_REQUEST),
142 update_error_count_(0), 142 update_error_count_(0),
143 gethash_error_count_(0), 143 gethash_error_count_(0),
144 gethash_v4_error_count_(0),
144 update_back_off_mult_(1), 145 update_back_off_mult_(1),
145 gethash_back_off_mult_(1), 146 gethash_back_off_mult_(1),
147 gethash_v4_back_off_mult_(1),
146 next_update_interval_(base::TimeDelta::FromSeconds( 148 next_update_interval_(base::TimeDelta::FromSeconds(
147 base::RandInt(kSbTimerStartIntervalSecMin, 149 base::RandInt(kSbTimerStartIntervalSecMin,
148 kSbTimerStartIntervalSecMax))), 150 kSbTimerStartIntervalSecMax))),
149 chunk_pending_to_write_(false), 151 chunk_pending_to_write_(false),
152 next_gethash_v4_time_(Time::Now()),
150 version_(config.version), 153 version_(config.version),
151 update_size_(0), 154 update_size_(0),
152 client_name_(config.client_name), 155 client_name_(config.client_name),
153 request_context_getter_(request_context_getter), 156 request_context_getter_(request_context_getter),
154 url_prefix_(config.url_prefix), 157 url_prefix_(config.url_prefix),
155 backup_update_reason_(BACKUP_UPDATE_REASON_MAX), 158 backup_update_reason_(BACKUP_UPDATE_REASON_MAX),
156 disable_auto_update_(config.disable_auto_update), 159 disable_auto_update_(config.disable_auto_update),
157 url_fetcher_id_(0), 160 url_fetcher_id_(0),
158 app_in_foreground_(true) { 161 app_in_foreground_(true) {
159 DCHECK(!url_prefix_.empty()); 162 DCHECK(!url_prefix_.empty());
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 276
274 if (!response.ParseFromString(data)) 277 if (!response.ParseFromString(data))
275 return false; 278 return false;
276 279
277 if (response.has_negative_cache_duration()) { 280 if (response.has_negative_cache_duration()) {
278 // Seconds resolution is good enough so we ignore the nanos field. 281 // Seconds resolution is good enough so we ignore the nanos field.
279 *negative_cache_duration = base::TimeDelta::FromSeconds( 282 *negative_cache_duration = base::TimeDelta::FromSeconds(
280 response.negative_cache_duration().seconds()); 283 response.negative_cache_duration().seconds());
281 } 284 }
282 285
286 if (response.has_minimum_wait_duration()) {
287 // Seconds resolution is good enough so we ignore the nanos field.
288 next_gethash_v4_time_ = Time::Now() + base::TimeDelta::FromSeconds(
289 response.minimum_wait_duration().seconds());
290 }
291
283 // Loop over the threat matches and fill in full_hashes. 292 // Loop over the threat matches and fill in full_hashes.
284 for (const ThreatMatch& match : response.matches()) { 293 for (const ThreatMatch& match : response.matches()) {
285 // Make sure the platform and threat entry type match. 294 // Make sure the platform and threat entry type match.
286 if (!(match.has_threat_entry_type() && 295 if (!(match.has_threat_entry_type() &&
287 match.threat_entry_type() == URL_EXPRESSION && 296 match.threat_entry_type() == URL_EXPRESSION &&
288 match.has_threat())) { 297 match.has_threat())) {
289 continue; 298 continue;
290 } 299 }
291 300
292 // Fill in the full hash. 301 // Fill in the full hash.
(...skipping 24 matching lines...) Expand all
317 } 326 }
318 return true; 327 return true;
319 } 328 }
320 329
321 void SafeBrowsingProtocolManager::GetV4FullHashes( 330 void SafeBrowsingProtocolManager::GetV4FullHashes(
322 const std::vector<SBPrefix>& prefixes, 331 const std::vector<SBPrefix>& prefixes,
323 const std::vector<PlatformType>& platforms, 332 const std::vector<PlatformType>& platforms,
324 ThreatType threat_type, 333 ThreatType threat_type,
325 FullHashCallback callback) { 334 FullHashCallback callback) {
326 DCHECK(CalledOnValidThread()); 335 DCHECK(CalledOnValidThread());
327 // TODO(kcarattini): Implement backoff behavior. 336 // We need to wait the minimum waiting duration, and if we are in backoff,
337 // we need to check if we're past the next allowed time. If we are, we can
338 // proceed with the request. If not, we are required to return empty results
339 // (i.e. treat the page as safe).
340 if (Time::Now() <= next_gethash_v4_time_) {
341 // TODO(kcarattini): Add UMA recording.
342 std::vector<SBFullHashResult> full_hashes;
343 callback.Run(full_hashes, base::TimeDelta());
344 return;
345 }
328 346
329 std::string req_base64 = GetV4HashRequest(prefixes, platforms, threat_type); 347 std::string req_base64 = GetV4HashRequest(prefixes, platforms, threat_type);
330 GURL gethash_url = GetV4HashUrl(req_base64); 348 GURL gethash_url = GetV4HashUrl(req_base64);
331 349
332 net::URLFetcher* fetcher = 350 net::URLFetcher* fetcher =
333 net::URLFetcher::Create(url_fetcher_id_++, gethash_url, 351 net::URLFetcher::Create(url_fetcher_id_++, gethash_url,
334 net::URLFetcher::GET, this) 352 net::URLFetcher::GET, this)
335 .release(); 353 .release();
336 v4_hash_requests_[fetcher] = FullHashDetails(callback, 354 v4_hash_requests_[fetcher] = FullHashDetails(callback,
337 false /* is_download */); 355 false /* is_download */);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 442
425 hash_requests_.erase(it); 443 hash_requests_.erase(it);
426 } else if (v4_it != v4_hash_requests_.end()) { 444 } else if (v4_it != v4_hash_requests_.end()) {
427 // V4 FindFullHashes response. 445 // V4 FindFullHashes response.
428 fetcher.reset(v4_it->first); 446 fetcher.reset(v4_it->first);
429 const FullHashDetails& details = v4_it->second; 447 const FullHashDetails& details = v4_it->second;
430 std::vector<SBFullHashResult> full_hashes; 448 std::vector<SBFullHashResult> full_hashes;
431 base::TimeDelta negative_cache_duration; 449 base::TimeDelta negative_cache_duration;
432 if (status.is_success() && response_code == net::HTTP_OK) { 450 if (status.is_success() && response_code == net::HTTP_OK) {
433 // TODO(kcarattini): Add UMA reporting. 451 // TODO(kcarattini): Add UMA reporting.
434 // TODO(kcarattini): Implement backoff and minimum waiting duration 452 gethash_v4_error_count_ = 0;
435 // compliance. 453 gethash_v4_back_off_mult_ = 1;
436 std::string data; 454 std::string data;
437 source->GetResponseAsString(&data); 455 source->GetResponseAsString(&data);
438 if (!ParseV4HashResponse(data, &full_hashes, &negative_cache_duration)) { 456 if (!ParseV4HashResponse(data, &full_hashes, &negative_cache_duration)) {
439 full_hashes.clear(); 457 full_hashes.clear();
440 // TODO(kcarattini): Add UMA reporting. 458 // TODO(kcarattini): Add UMA reporting.
441 } 459 }
442 } else { 460 } else {
443 // TODO(kcarattini): Handle error by setting backoff interval. 461 HandleGetHashV4Error(Time::Now());
444 // TODO(kcarattini): Add UMA reporting. 462 // TODO(kcarattini): Add UMA reporting.
445 if (status.status() == net::URLRequestStatus::FAILED) { 463 if (status.status() == net::URLRequestStatus::FAILED) {
446 DVLOG(1) << "SafeBrowsing GetEncodedFullHashes request for: " << 464 DVLOG(1) << "SafeBrowsing GetEncodedFullHashes request for: " <<
447 source->GetURL() << " failed with error: " << status.error(); 465 source->GetURL() << " failed with error: " << status.error();
448 } else { 466 } else {
449 DVLOG(1) << "SafeBrowsing GetEncodedFullHashes request for: " << 467 DVLOG(1) << "SafeBrowsing GetEncodedFullHashes request for: " <<
450 source->GetURL() << " failed with error: " << response_code; 468 source->GetURL() << " failed with error: " << response_code;
451 } 469 }
452 } 470 }
453 471
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 *multiplier *= 2; 721 *multiplier *= 2;
704 if (*multiplier > kSbMaxBackOff) 722 if (*multiplier > kSbMaxBackOff)
705 *multiplier = kSbMaxBackOff; 723 *multiplier = kSbMaxBackOff;
706 return next; 724 return next;
707 } 725 }
708 if (*error_count >= 6) 726 if (*error_count >= 6)
709 return base::TimeDelta::FromHours(8); 727 return base::TimeDelta::FromHours(8);
710 return base::TimeDelta::FromMinutes(1); 728 return base::TimeDelta::FromMinutes(1);
711 } 729 }
712 730
731 // Backoff interval is MIN(((2^(n-1))*15 minutes) * (RAND + 1), 24 hours) where
732 // n is the number of consecutive errors.
733 base::TimeDelta SafeBrowsingProtocolManager::GetNextV4BackOffInterval(
Nathan Parker 2016/01/07 06:06:58 This could be static, if you remove the CalledOnVa
kcarattini 2016/01/07 06:48:53 Done.
734 size_t* error_count,
735 size_t* multiplier) const {
736 DCHECK(CalledOnValidThread());
737 DCHECK(multiplier && error_count);
738 (*error_count)++;
739 if (*error_count > 1) {
740 *multiplier *= 2;
Nathan Parker 2016/01/07 06:06:58 What happens on integer overflow? Probably want t
kcarattini 2016/01/07 06:48:53 Done.
741 }
742 base::TimeDelta next = base::TimeDelta::FromMinutes(
743 *multiplier * (1 + base::RandDouble()) * 15);
744
745 base::TimeDelta day = base::TimeDelta::FromHours(24);
746
747 if (next < day)
748 return next;
749 else
750 return day;
751 }
752
713 // This request requires getting a list of all the chunks for each list from the 753 // This request requires getting a list of all the chunks for each list from the
714 // database asynchronously. The request will be issued when we're called back in 754 // database asynchronously. The request will be issued when we're called back in
715 // OnGetChunksComplete. 755 // OnGetChunksComplete.
716 // TODO(paulg): We should get this at start up and maintain a ChunkRange cache 756 // TODO(paulg): We should get this at start up and maintain a ChunkRange cache
717 // to avoid hitting the database with each update request. On the 757 // to avoid hitting the database with each update request. On the
718 // otherhand, this request will only occur ~20-30 minutes so there 758 // otherhand, this request will only occur ~20-30 minutes so there
719 // isn't that much overhead. Measure! 759 // isn't that much overhead. Measure!
720 void SafeBrowsingProtocolManager::IssueUpdateRequest() { 760 void SafeBrowsingProtocolManager::IssueUpdateRequest() {
721 DCHECK(CalledOnValidThread()); 761 DCHECK(CalledOnValidThread());
722 request_type_ = UPDATE_REQUEST; 762 request_type_ = UPDATE_REQUEST;
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 } 897 }
858 } 898 }
859 899
860 void SafeBrowsingProtocolManager::HandleGetHashError(const Time& now) { 900 void SafeBrowsingProtocolManager::HandleGetHashError(const Time& now) {
861 DCHECK(CalledOnValidThread()); 901 DCHECK(CalledOnValidThread());
862 base::TimeDelta next = 902 base::TimeDelta next =
863 GetNextBackOffInterval(&gethash_error_count_, &gethash_back_off_mult_); 903 GetNextBackOffInterval(&gethash_error_count_, &gethash_back_off_mult_);
864 next_gethash_time_ = now + next; 904 next_gethash_time_ = now + next;
865 } 905 }
866 906
907 void SafeBrowsingProtocolManager::HandleGetHashV4Error(const Time& now) {
908 DCHECK(CalledOnValidThread());
909 base::TimeDelta next = GetNextV4BackOffInterval(
910 &gethash_v4_error_count_, &gethash_v4_back_off_mult_);
911 next_gethash_v4_time_ = now + next;
912 }
913
867 void SafeBrowsingProtocolManager::UpdateFinished(bool success) { 914 void SafeBrowsingProtocolManager::UpdateFinished(bool success) {
868 UpdateFinished(success, !success); 915 UpdateFinished(success, !success);
869 } 916 }
870 917
871 void SafeBrowsingProtocolManager::UpdateFinished(bool success, bool back_off) { 918 void SafeBrowsingProtocolManager::UpdateFinished(bool success, bool back_off) {
872 DCHECK(CalledOnValidThread()); 919 DCHECK(CalledOnValidThread());
873 UMA_HISTOGRAM_COUNTS("SB2.UpdateSize", update_size_); 920 UMA_HISTOGRAM_COUNTS("SB2.UpdateSize", update_size_);
874 update_size_ = 0; 921 update_size_ = 0;
875 bool update_success = success || request_type_ == CHUNK_REQUEST; 922 bool update_success = success || request_type_ == CHUNK_REQUEST;
876 if (backup_update_reason_ == BACKUP_UPDATE_REASON_MAX) { 923 if (backup_update_reason_ == BACKUP_UPDATE_REASON_MAX) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 SafeBrowsingProtocolManager::FullHashDetails::FullHashDetails( 1003 SafeBrowsingProtocolManager::FullHashDetails::FullHashDetails(
957 FullHashCallback callback, 1004 FullHashCallback callback,
958 bool is_download) 1005 bool is_download)
959 : callback(callback), is_download(is_download) {} 1006 : callback(callback), is_download(is_download) {}
960 1007
961 SafeBrowsingProtocolManager::FullHashDetails::~FullHashDetails() {} 1008 SafeBrowsingProtocolManager::FullHashDetails::~FullHashDetails() {}
962 1009
963 SafeBrowsingProtocolManagerDelegate::~SafeBrowsingProtocolManagerDelegate() {} 1010 SafeBrowsingProtocolManagerDelegate::~SafeBrowsingProtocolManagerDelegate() {}
964 1011
965 } // namespace safe_browsing 1012 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698