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..09f74597c7c605b99b39c334fd4c30bdf856f02b 100644 |
| --- a/chrome/browser/safe_browsing/protocol_manager.cc |
| +++ b/chrome/browser/safe_browsing/protocol_manager.cc |
| @@ -238,14 +238,17 @@ void SafeBrowsingProtocolManager::GetFullHash( |
| std::string SafeBrowsingProtocolManager::GetV4HashRequest( |
| const std::vector<SBPrefix>& prefixes, |
| + const std::vector<PlatformType>& platforms, |
| ThreatType threat_type) { |
| // Build the request. Client info and client states are not added to the |
| // request protocol buffer. Client info is passed as params in the url. |
| FindFullHashesRequest req; |
| ThreatInfo* info = req.mutable_threat_info(); |
| info->add_threat_types(threat_type); |
| - info->add_platform_types(CHROME_PLATFORM); |
| info->add_threat_entry_types(URL_EXPRESSION); |
| + for (const PlatformType p : platforms) { |
| + info->add_platform_types(p); |
| + } |
| for (const SBPrefix& prefix : prefixes) { |
| std::string hash; |
| hash.append(reinterpret_cast<const char*>(&prefix), sizeof(SBPrefix)); |
| @@ -260,21 +263,74 @@ std::string SafeBrowsingProtocolManager::GetV4HashRequest( |
| return req_base64; |
| } |
| +bool SafeBrowsingProtocolManager::ParseV4HashResponse( |
| + const std::string& data, |
| + std::vector<SBFullHashResult>* full_hashes, |
| + base::TimeDelta* negative_cache_duration) { |
| + 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. |
| + *negative_cache_duration = 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_threat())) { |
| + continue; |
| + } |
| + |
| + // Fill in the full hash. |
| + SBFullHashResult result; |
| + result.hash = StringToSBFullHash(match.threat().hash()); |
|
awoz
2016/01/05 17:20:10
Should the threat type also be passed back?
awoz
2016/01/12 22:55:04
This is irrelevant since only one threat type is b
|
| + |
| + 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_platform_type() && |
| + match.platform_type() == CHROME_PLATFORM && |
| + 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() + ","; |
| + } |
| + } |
| + } |
| + |
| + full_hashes->push_back(result); |
| + } |
| + return true; |
| +} |
| + |
| void SafeBrowsingProtocolManager::GetV4FullHashes( |
| const std::vector<SBPrefix>& prefixes, |
| + const std::vector<PlatformType>& platforms, |
| ThreatType threat_type, |
| FullHashCallback callback) { |
| DCHECK(CalledOnValidThread()); |
| // TODO(kcarattini): Implement backoff behavior. |
| - std::string req_base64 = GetV4HashRequest(prefixes, threat_type); |
| + std::string req_base64 = GetV4HashRequest(prefixes, platforms, threat_type); |
| GURL gethash_url = GetV4HashUrl(req_base64); |
| net::URLFetcher* fetcher = |
| 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 */); |
| @@ -286,7 +342,9 @@ void SafeBrowsingProtocolManager::GetV4FullHashes( |
| void SafeBrowsingProtocolManager::GetFullHashesWithApis( |
| const std::vector<SBPrefix>& prefixes, |
| FullHashCallback callback) { |
| - GetV4FullHashes(prefixes, API_ABUSE, callback); |
| + std::vector<PlatformType> platform; |
| + platform.push_back(CHROME_PLATFORM); |
| + GetV4FullHashes(prefixes, platform, API_ABUSE, callback); |
| } |
| void SafeBrowsingProtocolManager::GetNextUpdate() { |
| @@ -313,6 +371,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 +421,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 negative_cache_duration; |
| + 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; |
| + source->GetResponseAsString(&data); |
| + if (!ParseV4HashResponse(data, &full_hashes, &negative_cache_duration)) { |
| + 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, negative_cache_duration); |
| + |
| + v4_hash_requests_.erase(it); |
| } else { |
| // Update or chunk response. |
| fetcher.reset(request_.release()); |