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()); |