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

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

Issue 11419041: Add tests for redirect responses from SafeBrowsingProtocolManager. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Another merge Created 8 years 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 | Annotate | Revision Log
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 #ifndef NDEBUG 7 #ifndef NDEBUG
8 #include "base/base64.h" 8 #include "base/base64.h"
9 #endif 9 #endif
10 #include "base/environment.h" 10 #include "base/environment.h"
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 bool is_download, ResultType result_type) { 104 bool is_download, ResultType result_type) {
105 if (is_download) { 105 if (is_download) {
106 UMA_HISTOGRAM_ENUMERATION("SB2.GetHashResultDownload", result_type, 106 UMA_HISTOGRAM_ENUMERATION("SB2.GetHashResultDownload", result_type,
107 GET_HASH_RESULT_MAX); 107 GET_HASH_RESULT_MAX);
108 } else { 108 } else {
109 UMA_HISTOGRAM_ENUMERATION("SB2.GetHashResult", result_type, 109 UMA_HISTOGRAM_ENUMERATION("SB2.GetHashResult", result_type,
110 GET_HASH_RESULT_MAX); 110 GET_HASH_RESULT_MAX);
111 } 111 }
112 } 112 }
113 113
114 bool SafeBrowsingProtocolManager::IsUpdateScheduled() const {
115 return update_timer_.IsRunning();
116 }
117
114 SafeBrowsingProtocolManager::~SafeBrowsingProtocolManager() { 118 SafeBrowsingProtocolManager::~SafeBrowsingProtocolManager() {
115 // Delete in-progress SafeBrowsing requests. 119 // Delete in-progress SafeBrowsing requests.
116 STLDeleteContainerPairFirstPointers(hash_requests_.begin(), 120 STLDeleteContainerPairFirstPointers(hash_requests_.begin(),
117 hash_requests_.end()); 121 hash_requests_.end());
118 hash_requests_.clear(); 122 hash_requests_.clear();
119 } 123 }
120 124
121 // We can only have one update or chunk request outstanding, but there may be 125 // We can only have one update or chunk request outstanding, but there may be
122 // multiple GetHash requests pending since we don't want to serialize them and 126 // multiple GetHash requests pending since we don't want to serialize them and
123 // slow down the user. 127 // slow down the user.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 // what back off / how many times to try), and if that effects the 167 // what back off / how many times to try), and if that effects the
164 // update back off. For now, a failed parse of the chunk means we 168 // update back off. For now, a failed parse of the chunk means we
165 // drop it. This isn't so bad because the next UPDATE_REQUEST we 169 // drop it. This isn't so bad because the next UPDATE_REQUEST we
166 // do will report all the chunks we have. If that chunk is still 170 // do will report all the chunks we have. If that chunk is still
167 // required, the SafeBrowsing servers will tell us to get it again. 171 // required, the SafeBrowsing servers will tell us to get it again.
168 void SafeBrowsingProtocolManager::OnURLFetchComplete( 172 void SafeBrowsingProtocolManager::OnURLFetchComplete(
169 const net::URLFetcher* source) { 173 const net::URLFetcher* source) {
170 DCHECK(CalledOnValidThread()); 174 DCHECK(CalledOnValidThread());
171 scoped_ptr<const net::URLFetcher> fetcher; 175 scoped_ptr<const net::URLFetcher> fetcher;
172 bool parsed_ok = true; 176 bool parsed_ok = true;
173 bool must_back_off = false; // Reduce SafeBrowsing service query frequency.
174 177
175 HashRequests::iterator it = hash_requests_.find(source); 178 HashRequests::iterator it = hash_requests_.find(source);
176 if (it != hash_requests_.end()) { 179 if (it != hash_requests_.end()) {
177 // GetHash response. 180 // GetHash response.
178 fetcher.reset(it->first); 181 fetcher.reset(it->first);
179 const FullHashDetails& details = it->second; 182 const FullHashDetails& details = it->second;
180 std::vector<SBFullHashResult> full_hashes; 183 std::vector<SBFullHashResult> full_hashes;
181 bool can_cache = false; 184 bool can_cache = false;
182 if (source->GetStatus().is_success() && 185 if (source->GetStatus().is_success() &&
183 (source->GetResponseCode() == 200 || 186 (source->GetResponseCode() == 200 ||
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 fetcher.reset(request_.release()); 227 fetcher.reset(request_.release());
225 228
226 if (request_type_ == UPDATE_REQUEST) { 229 if (request_type_ == UPDATE_REQUEST) {
227 if (!fetcher.get()) { 230 if (!fetcher.get()) {
228 // We've timed out waiting for an update response, so we've cancelled 231 // We've timed out waiting for an update response, so we've cancelled
229 // the update request and scheduled a new one. Ignore this response. 232 // the update request and scheduled a new one. Ignore this response.
230 return; 233 return;
231 } 234 }
232 235
233 // Cancel the update response timeout now that we have the response. 236 // Cancel the update response timeout now that we have the response.
234 update_timer_.Stop(); 237 timeout_timer_.Stop();
235 } 238 }
236 239
237 if (source->GetStatus().is_success() && source->GetResponseCode() == 200) { 240 if (source->GetStatus().is_success() && source->GetResponseCode() == 200) {
238 // We have data from the SafeBrowsing service. 241 // We have data from the SafeBrowsing service.
239 std::string data; 242 std::string data;
240 source->GetResponseAsString(&data); 243 source->GetResponseAsString(&data);
241 parsed_ok = HandleServiceResponse( 244 parsed_ok = HandleServiceResponse(
242 source->GetURL(), data.data(), static_cast<int>(data.length())); 245 source->GetURL(), data.data(), static_cast<int>(data.length()));
243 if (!parsed_ok) { 246 if (!parsed_ok) {
244 VLOG(1) << "SafeBrowsing request for: " << source->GetURL() 247 VLOG(1) << "SafeBrowsing request for: " << source->GetURL()
245 << " failed parse."; 248 << " failed parse.";
246 must_back_off = true;
247 chunk_request_urls_.clear(); 249 chunk_request_urls_.clear();
248 UpdateFinished(false); 250 UpdateFinished(false);
249 } 251 }
250 252
251 switch (request_type_) { 253 switch (request_type_) {
252 case CHUNK_REQUEST: 254 case CHUNK_REQUEST:
253 if (parsed_ok) 255 if (parsed_ok) {
254 chunk_request_urls_.pop_front(); 256 chunk_request_urls_.pop_front();
257 if (chunk_request_urls_.empty() && !chunk_pending_to_write_)
258 UpdateFinished(true);
259 }
255 break; 260 break;
256 case UPDATE_REQUEST: 261 case UPDATE_REQUEST:
257 if (chunk_request_urls_.empty() && parsed_ok) { 262 if (chunk_request_urls_.empty() && parsed_ok) {
258 // We are up to date since the servers gave us nothing new, so we 263 // We are up to date since the servers gave us nothing new, so we
259 // are done with this update cycle. 264 // are done with this update cycle.
260 UpdateFinished(true); 265 UpdateFinished(true);
261 } 266 }
262 break; 267 break;
263 default: 268 default:
264 NOTREACHED(); 269 NOTREACHED();
265 break; 270 break;
266 } 271 }
267 } else { 272 } else {
268 // The SafeBrowsing service error, or very bad response code: back off. 273 // The SafeBrowsing service error, or very bad response code: back off.
269 must_back_off = true;
270 if (request_type_ == CHUNK_REQUEST) 274 if (request_type_ == CHUNK_REQUEST)
271 chunk_request_urls_.clear(); 275 chunk_request_urls_.clear();
272 UpdateFinished(false); 276 UpdateFinished(false);
273 if (source->GetStatus().status() == net::URLRequestStatus::FAILED) { 277 if (source->GetStatus().status() == net::URLRequestStatus::FAILED) {
274 VLOG(1) << "SafeBrowsing request for: " << source->GetURL() 278 VLOG(1) << "SafeBrowsing request for: " << source->GetURL()
275 << " failed with error: " << source->GetStatus().error(); 279 << " failed with error: " << source->GetStatus().error();
276 } else { 280 } else {
277 VLOG(1) << "SafeBrowsing request for: " << source->GetURL() 281 VLOG(1) << "SafeBrowsing request for: " << source->GetURL()
278 << " failed with error: " << source->GetResponseCode(); 282 << " failed with error: " << source->GetResponseCode();
279 } 283 }
280 } 284 }
281 } 285 }
282 286
283 // Schedule a new update request if we've finished retrieving all the chunks
284 // from the previous update. We treat the update request and the chunk URLs it
285 // contains as an atomic unit as far as back off is concerned.
286 if (chunk_request_urls_.empty() &&
287 (request_type_ == CHUNK_REQUEST || request_type_ == UPDATE_REQUEST))
288 ScheduleNextUpdate(must_back_off);
289
290 // Get the next chunk if available. 287 // Get the next chunk if available.
291 IssueChunkRequest(); 288 IssueChunkRequest();
292 } 289 }
293 290
294 bool SafeBrowsingProtocolManager::HandleServiceResponse(const GURL& url, 291 bool SafeBrowsingProtocolManager::HandleServiceResponse(const GURL& url,
295 const char* data, 292 const char* data,
296 int length) { 293 int length) {
297 DCHECK(CalledOnValidThread()); 294 DCHECK(CalledOnValidThread());
298 SafeBrowsingProtocolParser parser; 295 SafeBrowsingProtocolParser parser;
299 296
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 VLOG(1) << "ParseChunk error for chunk: " << chunk_url.url 362 VLOG(1) << "ParseChunk error for chunk: " << chunk_url.url
366 << ", Base64Encode(data): " << encoded_chunk 363 << ", Base64Encode(data): " << encoded_chunk
367 << ", length: " << length; 364 << ", length: " << length;
368 #endif 365 #endif
369 return false; 366 return false;
370 } 367 }
371 368
372 // Chunks to add to storage. Pass ownership of |chunks|. 369 // Chunks to add to storage. Pass ownership of |chunks|.
373 if (!chunks->empty()) { 370 if (!chunks->empty()) {
374 chunk_pending_to_write_ = true; 371 chunk_pending_to_write_ = true;
375 delegate_->AddChunks(chunk_url.list_name, chunks.release()); 372 delegate_->AddChunks(
373 chunk_url.list_name, chunks.release(),
374 base::Bind(&SafeBrowsingProtocolManager::OnAddChunksComplete,
375 base::Unretained(this)));
376 } 376 }
377 377
378 break; 378 break;
379 } 379 }
380 380
381 default: 381 default:
382 return false; 382 return false;
383 } 383 }
384 384
385 return true; 385 return true;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 request_->SetRequestContext(request_context_getter_); 486 request_->SetRequestContext(request_context_getter_);
487 chunk_request_start_ = base::Time::Now(); 487 chunk_request_start_ = base::Time::Now();
488 request_->Start(); 488 request_->Start();
489 } 489 }
490 490
491 void SafeBrowsingProtocolManager::OnGetChunksComplete( 491 void SafeBrowsingProtocolManager::OnGetChunksComplete(
492 const std::vector<SBListChunkRanges>& lists, bool database_error) { 492 const std::vector<SBListChunkRanges>& lists, bool database_error) {
493 DCHECK(CalledOnValidThread()); 493 DCHECK(CalledOnValidThread());
494 DCHECK_EQ(request_type_, UPDATE_REQUEST); 494 DCHECK_EQ(request_type_, UPDATE_REQUEST);
495 if (database_error) { 495 if (database_error) {
496 UpdateFinished(false); 496 // The update was not successful, but don't back off.
497 ScheduleNextUpdate(false); 497 UpdateFinished(false, false);
498 return; 498 return;
499 } 499 }
500 500
501 // Format our stored chunks: 501 // Format our stored chunks:
502 std::string list_data; 502 std::string list_data;
503 bool found_malware = false; 503 bool found_malware = false;
504 bool found_phishing = false; 504 bool found_phishing = false;
505 for (size_t i = 0; i < lists.size(); ++i) { 505 for (size_t i = 0; i < lists.size(); ++i) {
506 list_data.append(FormatList(lists[i])); 506 list_data.append(FormatList(lists[i]));
507 if (lists[i].name == safe_browsing_util::kPhishingList) 507 if (lists[i].name == safe_browsing_util::kPhishingList)
(...skipping 15 matching lines...) Expand all
523 523
524 GURL update_url = UpdateUrl(); 524 GURL update_url = UpdateUrl();
525 request_.reset(net::URLFetcher::Create( 525 request_.reset(net::URLFetcher::Create(
526 url_fetcher_id_++, update_url, net::URLFetcher::POST, this)); 526 url_fetcher_id_++, update_url, net::URLFetcher::POST, this));
527 request_->SetLoadFlags(net::LOAD_DISABLE_CACHE); 527 request_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
528 request_->SetRequestContext(request_context_getter_); 528 request_->SetRequestContext(request_context_getter_);
529 request_->SetUploadData("text/plain", list_data); 529 request_->SetUploadData("text/plain", list_data);
530 request_->Start(); 530 request_->Start();
531 531
532 // Begin the update request timeout. 532 // Begin the update request timeout.
533 update_timer_.Start(FROM_HERE, TimeDelta::FromSeconds(kSbMaxUpdateWaitSec), 533 timeout_timer_.Start(FROM_HERE, TimeDelta::FromSeconds(kSbMaxUpdateWaitSec),
534 this, 534 this,
535 &SafeBrowsingProtocolManager::UpdateResponseTimeout); 535 &SafeBrowsingProtocolManager::UpdateResponseTimeout);
536 } 536 }
537 537
538 // If we haven't heard back from the server with an update response, this method 538 // If we haven't heard back from the server with an update response, this method
539 // will run. Close the current update session and schedule another update. 539 // will run. Close the current update session and schedule another update.
540 void SafeBrowsingProtocolManager::UpdateResponseTimeout() { 540 void SafeBrowsingProtocolManager::UpdateResponseTimeout() {
541 DCHECK(CalledOnValidThread()); 541 DCHECK(CalledOnValidThread());
542 DCHECK_EQ(request_type_, UPDATE_REQUEST); 542 DCHECK_EQ(request_type_, UPDATE_REQUEST);
543 request_.reset(); 543 request_.reset();
544 UpdateFinished(false); 544 UpdateFinished(false);
545 ScheduleNextUpdate(true);
546 } 545 }
547 546
548 void SafeBrowsingProtocolManager::OnChunkInserted() { 547 void SafeBrowsingProtocolManager::OnAddChunksComplete() {
549 DCHECK(CalledOnValidThread()); 548 DCHECK(CalledOnValidThread());
550 chunk_pending_to_write_ = false; 549 chunk_pending_to_write_ = false;
551 550
552 if (chunk_request_urls_.empty()) { 551 if (chunk_request_urls_.empty()) {
553 UMA_HISTOGRAM_LONG_TIMES("SB2.Update", Time::Now() - last_update_); 552 UMA_HISTOGRAM_LONG_TIMES("SB2.Update", Time::Now() - last_update_);
554 UpdateFinished(true); 553 UpdateFinished(true);
555 } else { 554 } else {
556 IssueChunkRequest(); 555 IssueChunkRequest();
557 } 556 }
558 } 557 }
(...skipping 18 matching lines...) Expand all
577 } 576 }
578 577
579 void SafeBrowsingProtocolManager::HandleGetHashError(const Time& now) { 578 void SafeBrowsingProtocolManager::HandleGetHashError(const Time& now) {
580 DCHECK(CalledOnValidThread()); 579 DCHECK(CalledOnValidThread());
581 base::TimeDelta next = GetNextBackOffInterval( 580 base::TimeDelta next = GetNextBackOffInterval(
582 &gethash_error_count_, &gethash_back_off_mult_); 581 &gethash_error_count_, &gethash_back_off_mult_);
583 next_gethash_time_ = now + next; 582 next_gethash_time_ = now + next;
584 } 583 }
585 584
586 void SafeBrowsingProtocolManager::UpdateFinished(bool success) { 585 void SafeBrowsingProtocolManager::UpdateFinished(bool success) {
586 UpdateFinished(success, !success);
587 }
588
589 void SafeBrowsingProtocolManager::UpdateFinished(bool success, bool back_off) {
587 DCHECK(CalledOnValidThread()); 590 DCHECK(CalledOnValidThread());
588 UMA_HISTOGRAM_COUNTS("SB2.UpdateSize", update_size_); 591 UMA_HISTOGRAM_COUNTS("SB2.UpdateSize", update_size_);
589 update_size_ = 0; 592 update_size_ = 0;
590 delegate_->UpdateFinished(success); 593 delegate_->UpdateFinished(success);
594 ScheduleNextUpdate(back_off);
591 } 595 }
592 596
593 GURL SafeBrowsingProtocolManager::UpdateUrl() const { 597 GURL SafeBrowsingProtocolManager::UpdateUrl() const {
594 std::string url = SafeBrowsingProtocolManagerHelper::ComposeUrl( 598 std::string url = SafeBrowsingProtocolManagerHelper::ComposeUrl(
595 url_prefix_, "downloads", client_name_, version_, additional_query_); 599 url_prefix_, "downloads", client_name_, version_, additional_query_);
596 return GURL(url); 600 return GURL(url);
597 } 601 }
598 602
599 GURL SafeBrowsingProtocolManager::GetHashUrl() const { 603 GURL SafeBrowsingProtocolManager::GetHashUrl() const {
600 std::string url = SafeBrowsingProtocolManagerHelper::ComposeUrl( 604 std::string url = SafeBrowsingProtocolManagerHelper::ComposeUrl(
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 FullHashCallback callback, bool is_download) 640 FullHashCallback callback, bool is_download)
637 : callback(callback), 641 : callback(callback),
638 is_download(is_download) { 642 is_download(is_download) {
639 } 643 }
640 644
641 SafeBrowsingProtocolManager::FullHashDetails::~FullHashDetails() { 645 SafeBrowsingProtocolManager::FullHashDetails::~FullHashDetails() {
642 } 646 }
643 647
644 SafeBrowsingProtocolManagerDelegate::~SafeBrowsingProtocolManagerDelegate() { 648 SafeBrowsingProtocolManagerDelegate::~SafeBrowsingProtocolManagerDelegate() {
645 } 649 }
OLDNEW
« no previous file with comments | « chrome/browser/safe_browsing/protocol_manager.h ('k') | chrome/browser/safe_browsing/protocol_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698