Chromium Code Reviews| Index: chrome/browser/safe_browsing/protocol_manager.cc |
| diff --git a/chrome/browser/safe_browsing/protocol_manager.cc b/chrome/browser/safe_browsing/protocol_manager.cc |
| index 2ac7c7b4afefce06e058fef382a0d684f85ffd12..6c5a6a7818e590fd62473872ce93d1b845566e05 100644 |
| --- a/chrome/browser/safe_browsing/protocol_manager.cc |
| +++ b/chrome/browser/safe_browsing/protocol_manager.cc |
| @@ -260,6 +260,61 @@ std::string SafeBrowsingProtocolManager::GetV4HashRequest( |
| return req_base64; |
| } |
| +bool SafeBrowsingProtocolManager::ParseV4HashResponse( |
| + const std::string& data_base64, |
| + std::vector<SBFullHashResult>* full_hashes, |
| + base::TimeDelta* cache_lifetime) { |
| + std::string data; |
| + base::Base64Decode(data_base64, &data); |
| + FindFullHashesResponse response; |
| + |
| + if (!response.ParseFromString(data)) |
| + return false; |
| + |
| + if (response.has_negative_cache_duration()) { |
| + // Seconds resolution is good enough so we ignore the nanos field. |
| + *cache_lifetime = base::TimeDelta::FromSeconds( |
| + response.negative_cache_duration().seconds()); |
| + } |
| + |
| + // Loop over the threat matches and fill in full_hashes. |
| + for (const ThreatMatch& match : response.matches()) { |
| + // Make sure the platform and threat entry type match. |
| + if (!(match.has_threat_entry_type() && |
| + match.threat_entry_type() == URL_EXPRESSION && |
| + match.has_platform_type() && |
| + match.platform_type() == CHROME_PLATFORM && |
|
awoz
2015/12/30 18:23:13
If you're making this generic, you won't want to f
kcarattini
2016/01/04 00:52:01
Done.
|
| + match.has_threat())) { |
| + continue; |
| + } |
| + |
| + // Fill in the full hash. |
| + SBFullHashResult result; |
| + result.hash = StringToSBFullHash(match.threat().hash()); |
| + |
| + if (match.has_cache_duration()) { |
| + // Seconds resolution is good enough so we ignore the nanos field. |
| + result.cache_duration = base::TimeDelta::FromSeconds( |
| + match.cache_duration().seconds()); |
| + } |
| + |
| + // Different threat types will handle the metadata differently. |
| + if (match.has_threat_type() && match.threat_type() == API_ABUSE && |
| + match.has_threat_entry_metadata()) { |
| + // For API Abuse, store a csv of the returned permissions. |
| + for (const ThreatEntryMetadata::MetadataEntry& m : |
| + match.threat_entry_metadata().entries()) { |
| + if (m.key() == "permission") { |
| + result.metadata += m.value() + ","; |
|
awoz
2015/12/30 18:23:13
Do you care about having a trailing comma?
kcarattini
2016/01/04 00:52:01
No, I imagine I'll parse this to a set and check f
|
| + } |
| + } |
| + } |
| + |
| + full_hashes->push_back(result); |
| + } |
| + return true; |
| +} |
| + |
| void SafeBrowsingProtocolManager::GetV4FullHashes( |
| const std::vector<SBPrefix>& prefixes, |
| ThreatType threat_type, |
| @@ -274,7 +329,6 @@ void SafeBrowsingProtocolManager::GetV4FullHashes( |
| net::URLFetcher::Create(url_fetcher_id_++, gethash_url, |
| net::URLFetcher::GET, this) |
| .release(); |
| - // TODO(kcarattini): Implement a new response processor. |
| v4_hash_requests_[fetcher] = FullHashDetails(callback, |
| false /* is_download */); |
| @@ -313,6 +367,7 @@ void SafeBrowsingProtocolManager::OnURLFetchComplete( |
| scoped_ptr<const net::URLFetcher> fetcher; |
| HashRequests::iterator it = hash_requests_.find(source); |
| + HashRequests::iterator v4_it = v4_hash_requests_.find(source); |
| int response_code = source->GetResponseCode(); |
| net::URLRequestStatus status = source->GetStatus(); |
| RecordHttpResponseOrErrorCode(kUmaHashResponseMetricName, status, |
| @@ -362,6 +417,40 @@ void SafeBrowsingProtocolManager::OnURLFetchComplete( |
| details.callback.Run(full_hashes, cache_lifetime); |
| hash_requests_.erase(it); |
| + } else if (v4_it != v4_hash_requests_.end()) { |
| + // V4 FindFullHashes response. |
| + fetcher.reset(v4_it->first); |
| + const FullHashDetails& details = v4_it->second; |
| + std::vector<SBFullHashResult> full_hashes; |
| + base::TimeDelta cache_lifetime; |
| + if (status.is_success() && response_code == net::HTTP_OK) { |
| + // TODO(kcarattini): Add UMA reporting. |
| + // TODO(kcarattini): Implement backoff and minimum waiting duration |
| + // compliance. |
| + std::string data_base64; |
|
awoz
2015/12/30 18:23:13
The protocol returns a serialized protobuf in bina
kcarattini
2016/01/04 00:52:01
Done.
|
| + source->GetResponseAsString(&data_base64); |
| + if (!ParseV4HashResponse(data_base64, &full_hashes, &cache_lifetime)) { |
| + full_hashes.clear(); |
| + // TODO(kcarattini): Add UMA reporting. |
| + } |
| + } else { |
| + // TODO(kcarattini): Handle error by setting backoff interval. |
| + // TODO(kcarattini): Add UMA reporting. |
| + if (status.status() == net::URLRequestStatus::FAILED) { |
| + DVLOG(1) << "SafeBrowsing GetEncodedFullHashes request for: " << |
| + source->GetURL() << " failed with error: " << status.error(); |
| + } else { |
| + DVLOG(1) << "SafeBrowsing GetEncodedFullHashes request for: " << |
| + source->GetURL() << " failed with error: " << response_code; |
| + } |
| + } |
| + |
| + // 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. |
| + details.callback.Run(full_hashes, cache_lifetime); |
| + |
| + v4_hash_requests_.erase(it); |
| } else { |
| // Update or chunk response. |
| fetcher.reset(request_.release()); |