chrome/browser/safe_browsing/protocol_manager.cc
// All SafeBrowsing request responses are handled here.
// TODO(paulg): Clarify with the SafeBrowsing team whether a failed parse of a
//              chunk should retry the download and parse of that chunk (and
//              what back off / how many times to try), and if that effects the
//              update back off. For now, a failed parse of the chunk means we
//              drop it. This isn't so bad because the next UPDATE_REQUEST we
//              do will report all the chunks we have. If that chunk is still
//              required, the SafeBrowsing servers will tell us to get it again.
All SafeBrowsing request responses are handled here.
TODO(paulg): Clarify with the SafeBrowsing team whether a failed parse of a
chunk should retry the download and parse of that chunk (and
what back off / how many times to try), and if that effects the
update back off. For now, a failed parse of the chunk means we
drop it. This isn't so bad because the next UPDATE_REQUEST we
do will report all the chunks we have. If that chunk is still
required, the SafeBrowsing servers will tell us to get it again.
All SafeBrowsing request responses are handled here . TODO ( paulg ) : Clarify with the SafeBrowsing team whether a failed parse of a chunk should retry the download and parse of that chunk ( and what back off / how many times to try ) and if that effects the update back off . For now a failed parse of the chunk means we drop it . This isn ' t so bad because the next UPDATE_REQUEST we do will report all the chunks we have . If that chunk is still required the SafeBrowsing servers will tell us to get it again .
void SafeBrowsingProtocolManager::OnURLFetchComplete(
    const net::URLFetcher* source) {
  DCHECK(CalledOnValidThread());
  scoped_ptr<const net::URLFetcher> fetcher;
  bool parsed_ok = true;
  bool must_back_off = false;  
  HashRequests::iterator it = hash_requests_.find(source);
  if (it != hash_requests_.end()) {
    fetcher.reset(it->first);
    const FullHashDetails& details = it->second;
    std::vector<SBFullHashResult> full_hashes;
    bool can_cache = false;
    if (source->GetStatus().is_success() &&
        (source->GetResponseCode() == 200 ||
         source->GetResponseCode() == 204)) {
      if (source->GetResponseCode() == 200)
        RecordGetHashResult(details.is_download, GET_HASH_STATUS_200);
      else
        RecordGetHashResult(details.is_download, GET_HASH_STATUS_204);
      can_cache = true;
      gethash_error_count_ = 0;
      gethash_back_off_mult_ = 1;
      SafeBrowsingProtocolParser parser;
      std::string data;
      source->GetResponseAsString(&data);
      parsed_ok = parser.ParseGetHash(
          data.data(),
          static_cast<int>(data.length()),
          &full_hashes);
      if (!parsed_ok) {
        full_hashes.clear();
      }
    } else {
      HandleGetHashError(Time::Now());
      if (source->GetStatus().status() == net::URLRequestStatus::FAILED) {
        VLOG(1) << "SafeBrowsing GetHash request for: " << source->GetURL()
                << " failed with error: " << source->GetStatus().error();
      } else {
        VLOG(1) << "SafeBrowsing GetHash request for: " << source->GetURL()
                << " failed with error: " << source->GetResponseCode();
      }
    }
    details.callback.Run(full_hashes, can_cache);
    hash_requests_.erase(it);
  } else {
    fetcher.reset(request_.release());
    if (request_type_ == UPDATE_REQUEST) {
      if (!fetcher.get()) {
        return;
      }
      update_timer_.Stop();
    }
    if (source->GetStatus().is_success() && source->GetResponseCode() == 200) {
      std::string data;
      source->GetResponseAsString(&data);
      parsed_ok = HandleServiceResponse(
          source->GetURL(), data.data(), static_cast<int>(data.length()));
      if (!parsed_ok) {
        VLOG(1) << "SafeBrowsing request for: " << source->GetURL()
                << " failed parse.";
        must_back_off = true;
        chunk_request_urls_.clear();
        UpdateFinished(false);
      }
      switch (request_type_) {
        case CHUNK_REQUEST:
          if (parsed_ok)
            chunk_request_urls_.pop_front();
          break;
        case UPDATE_REQUEST:
          if (chunk_request_urls_.empty() && parsed_ok) {
            UpdateFinished(true);
          }
          break;
        default:
          NOTREACHED();
          break;
      }
    } else {
      must_back_off = true;
      if (request_type_ == CHUNK_REQUEST)
        chunk_request_urls_.clear();
      UpdateFinished(false);
      if (source->GetStatus().status() == net::URLRequestStatus::FAILED) {
        VLOG(1) << "SafeBrowsing request for: " << source->GetURL()
                << " failed with error: " << source->GetStatus().error();
      } else {
        VLOG(1) << "SafeBrowsing request for: " << source->GetURL()
                << " failed with error: " << source->GetResponseCode();
      }
    }
  }
  if (chunk_request_urls_.empty() &&
      (request_type_ == CHUNK_REQUEST || request_type_ == UPDATE_REQUEST))
    ScheduleNextUpdate(must_back_off);
  IssueChunkRequest();
}
void SafeBrowsingProtocolManager :: OnURLFetchComplete ( const net :: URLFetcher * source ) { DCHECK ( CalledOnValidThread ( ) ) ; scoped_ptr < const net :: URLFetcher > fetcher ; bool parsed_ok = true ; bool must_back_off = false ; HashRequests :: iterator it = hash_requests_ . find ( source ) ; if ( it != hash_requests_ . end ( ) ) { fetcher . reset ( it -> first ) ; const FullHashDetails & details = it -> second ; std :: vector < SBFullHashResult > full_hashes ; bool can_cache = false ; if ( source -> GetStatus ( ) . is_success ( ) && ( source -> GetResponseCode ( ) == 200 || source -> GetResponseCode ( ) == 204 ) ) { if ( source -> GetResponseCode ( ) == 200 ) RecordGetHashResult ( details . is_download , GET_HASH_STATUS_200 ) ; else RecordGetHashResult ( details . is_download , GET_HASH_STATUS_204 ) ; can_cache = true ; gethash_error_count_ = 0 ; gethash_back_off_mult_ = 1 ; SafeBrowsingProtocolParser parser ; std :: string data ; source -> GetResponseAsString ( & data ) ; parsed_ok = parser . ParseGetHash ( data . data ( ) , static_cast < int > ( data . length ( ) ) , & full_hashes ) ; if ( ! parsed_ok ) { full_hashes . clear ( ) ; } } else { HandleGetHashError ( Time :: Now ( ) ) ; if ( source -> GetStatus ( ) . status ( ) == net :: URLRequestStatus :: FAILED ) { VLOG ( 1 ) << " " << source -> GetURL ( ) << " " << source -> GetStatus ( ) . error ( ) ; } else { VLOG ( 1 ) << " " << source -> GetURL ( ) << " " << source -> GetResponseCode ( ) ; } } details . callback . Run ( full_hashes , can_cache ) ; hash_requests_ . erase ( it ) ; } else { fetcher . reset ( request_ . release ( ) ) ; if ( request_type_ == UPDATE_REQUEST ) { if ( ! fetcher . get ( ) ) { return ; } update_timer_ . Stop ( ) ; } if ( source -> GetStatus ( ) . is_success ( ) && source -> GetResponseCode ( ) == 200 ) { std :: string data ; source -> GetResponseAsString ( & data ) ; parsed_ok = HandleServiceResponse ( source -> GetURL ( ) , data . data ( ) , static_cast < int > ( data . length ( ) ) ) ; if ( ! parsed_ok ) { VLOG ( 1 ) << " " << source -> GetURL ( ) << " " ; must_back_off = true ; chunk_request_urls_ . clear ( ) ; UpdateFinished ( false ) ; } switch ( request_type_ ) { case CHUNK_REQUEST : if ( parsed_ok ) chunk_request_urls_ . pop_front ( ) ; break ; case UPDATE_REQUEST : if ( chunk_request_urls_ . empty ( ) && parsed_ok ) { UpdateFinished ( true ) ; } break ; default : NOTREACHED ( ) ; break ; } } else { must_back_off = true ; if ( request_type_ == CHUNK_REQUEST ) chunk_request_urls_ . clear ( ) ; UpdateFinished ( false ) ; if ( source -> GetStatus ( ) . status ( ) == net :: URLRequestStatus :: FAILED ) { VLOG ( 1 ) << " " << source -> GetURL ( ) << " " << source -> GetStatus ( ) . error ( ) ; } else { VLOG ( 1 ) << " " << source -> GetURL ( ) << " " << source -> GetResponseCode ( ) ; } } } if ( chunk_request_urls_ . empty ( ) && ( request_type_ == CHUNK_REQUEST || request_type_ == UPDATE_REQUEST ) ) ScheduleNextUpdate ( must_back_off ) ; IssueChunkRequest ( ) ; }
All SafeBrowsing request responses are handled here.
All SafeBrowsing request responses are handled here .
// Reduce SafeBrowsing service query frequency. // GetHash response. // For tracking our GetHash false positive (204) rate, compared to real // (200) responses. // TODO(cbentzel): Should can_cache be set to false here? // Invoke the callback with full_hashes, even if there was a parse error or // an error response code (in which case full_hashes will be empty). The // caller can't be blocked indefinitely. // Update or chunk response. // We've timed out waiting for an update response, so we've cancelled // the update request and scheduled a new one. Ignore this response. // Cancel the update response timeout now that we have the response. // We have data from the SafeBrowsing service. // We are up to date since the servers gave us nothing new, so we // are done with this update cycle. // The SafeBrowsing service error, or very bad response code: back off. // Schedule a new update request if we've finished retrieving all the chunks // from the previous update. We treat the update request and the chunk URLs it // contains as an atomic unit as far as back off is concerned. // Get the next chunk if available.