| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "components/safe_browsing_db/v4_update_protocol_manager.h" | 5 #include "components/safe_browsing_db/v4_update_protocol_manager.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/base64url.h" | 9 #include "base/base64url.h" |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| 11 #include "base/memory/ptr_util.h" |
| 11 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
| 12 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
| 13 #include "base/timer/timer.h" | 14 #include "base/timer/timer.h" |
| 14 #include "components/safe_browsing_db/safebrowsing.pb.h" | 15 #include "components/safe_browsing_db/safebrowsing.pb.h" |
| 15 #include "net/base/load_flags.h" | 16 #include "net/base/load_flags.h" |
| 16 #include "net/http/http_response_headers.h" | 17 #include "net/http/http_response_headers.h" |
| 17 #include "net/http/http_status_code.h" | 18 #include "net/http/http_status_code.h" |
| 18 #include "net/url_request/url_fetcher.h" | 19 #include "net/url_request/url_fetcher.h" |
| 19 #include "net/url_request/url_request_context_getter.h" | 20 #include "net/url_request/url_request_context_getter.h" |
| 20 | 21 |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 // Serialize and Base64 encode. | 216 // Serialize and Base64 encode. |
| 216 std::string req_data, req_base64; | 217 std::string req_data, req_base64; |
| 217 request.SerializeToString(&req_data); | 218 request.SerializeToString(&req_data); |
| 218 base::Base64UrlEncode(req_data, base::Base64UrlEncodePolicy::INCLUDE_PADDING, | 219 base::Base64UrlEncode(req_data, base::Base64UrlEncodePolicy::INCLUDE_PADDING, |
| 219 &req_base64); | 220 &req_base64); |
| 220 return req_base64; | 221 return req_base64; |
| 221 } | 222 } |
| 222 | 223 |
| 223 bool V4UpdateProtocolManager::ParseUpdateResponse( | 224 bool V4UpdateProtocolManager::ParseUpdateResponse( |
| 224 const std::string& data, | 225 const std::string& data, |
| 225 std::vector<ListUpdateResponse>* list_update_responses) { | 226 ParsedServerResponse* parsed_server_response) { |
| 226 FetchThreatListUpdatesResponse response; | 227 FetchThreatListUpdatesResponse response; |
| 227 | 228 |
| 228 if (!response.ParseFromString(data)) { | 229 if (!response.ParseFromString(data)) { |
| 229 RecordParseUpdateResult(PARSE_FROM_STRING_ERROR); | 230 RecordParseUpdateResult(PARSE_FROM_STRING_ERROR); |
| 230 return false; | 231 return false; |
| 231 } | 232 } |
| 232 | 233 |
| 233 if (response.has_minimum_wait_duration()) { | 234 if (response.has_minimum_wait_duration()) { |
| 234 // Seconds resolution is good enough so we ignore the nanos field. | 235 // Seconds resolution is good enough so we ignore the nanos field. |
| 235 int64_t minimum_wait_duration_seconds = | 236 int64_t minimum_wait_duration_seconds = |
| 236 response.minimum_wait_duration().seconds(); | 237 response.minimum_wait_duration().seconds(); |
| 237 | 238 |
| 238 // Do not let the next_update_interval_ to be too low. | 239 // Do not let the next_update_interval_ to be too low. |
| 239 if (minimum_wait_duration_seconds < kV4TimerStartIntervalSecMin) { | 240 if (minimum_wait_duration_seconds < kV4TimerStartIntervalSecMin) { |
| 240 minimum_wait_duration_seconds = kV4TimerStartIntervalSecMin; | 241 minimum_wait_duration_seconds = kV4TimerStartIntervalSecMin; |
| 241 } | 242 } |
| 242 next_update_interval_ = | 243 next_update_interval_ = |
| 243 base::TimeDelta::FromSeconds(minimum_wait_duration_seconds); | 244 base::TimeDelta::FromSeconds(minimum_wait_duration_seconds); |
| 244 } | 245 } |
| 245 | 246 |
| 246 // TODO(vakh): Do something useful with this response. | 247 // TODO(vakh): Do something useful with this response. |
| 247 for (const ListUpdateResponse& list_update_response : | 248 for (ListUpdateResponse& list_update_response : |
| 248 response.list_update_responses()) { | 249 *response.mutable_list_update_responses()) { |
| 249 if (!list_update_response.has_platform_type()) { | 250 if (!list_update_response.has_platform_type()) { |
| 250 RecordParseUpdateResult(NO_PLATFORM_TYPE_ERROR); | 251 RecordParseUpdateResult(NO_PLATFORM_TYPE_ERROR); |
| 251 } else if (!list_update_response.has_threat_entry_type()) { | 252 } else if (!list_update_response.has_threat_entry_type()) { |
| 252 RecordParseUpdateResult(NO_THREAT_ENTRY_TYPE_ERROR); | 253 RecordParseUpdateResult(NO_THREAT_ENTRY_TYPE_ERROR); |
| 253 } else if (!list_update_response.has_threat_type()) { | 254 } else if (!list_update_response.has_threat_type()) { |
| 254 RecordParseUpdateResult(NO_THREAT_TYPE_ERROR); | 255 RecordParseUpdateResult(NO_THREAT_TYPE_ERROR); |
| 255 } else if (!list_update_response.has_new_client_state()) { | 256 } else if (!list_update_response.has_new_client_state()) { |
| 256 RecordParseUpdateResult(NO_STATE_ERROR); | 257 RecordParseUpdateResult(NO_STATE_ERROR); |
| 257 } else { | 258 } else { |
| 258 list_update_responses->push_back(list_update_response); | 259 std::unique_ptr<ListUpdateResponse> add(new ListUpdateResponse); |
| 260 add->Swap(&list_update_response); |
| 261 parsed_server_response->push_back(std::move(add)); |
| 259 } | 262 } |
| 260 } | 263 } |
| 261 return true; | 264 return true; |
| 262 } | 265 } |
| 263 | 266 |
| 264 void V4UpdateProtocolManager::IssueUpdateRequest() { | 267 void V4UpdateProtocolManager::IssueUpdateRequest() { |
| 265 DCHECK(CalledOnValidThread()); | 268 DCHECK(CalledOnValidThread()); |
| 266 | 269 |
| 267 // If an update request is already pending, record and return silently. | 270 // If an update request is already pending, record and return silently. |
| 268 if (request_.get()) { | 271 if (request_.get()) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 295 const net::URLFetcher* source) { | 298 const net::URLFetcher* source) { |
| 296 DCHECK(CalledOnValidThread()); | 299 DCHECK(CalledOnValidThread()); |
| 297 | 300 |
| 298 int response_code = source->GetResponseCode(); | 301 int response_code = source->GetResponseCode(); |
| 299 net::URLRequestStatus status = source->GetStatus(); | 302 net::URLRequestStatus status = source->GetStatus(); |
| 300 V4ProtocolManagerUtil::RecordHttpResponseOrErrorCode( | 303 V4ProtocolManagerUtil::RecordHttpResponseOrErrorCode( |
| 301 "SafeBrowsing.V4UpdateHttpResponseOrErrorCode", status, response_code); | 304 "SafeBrowsing.V4UpdateHttpResponseOrErrorCode", status, response_code); |
| 302 | 305 |
| 303 last_response_time_ = Time::Now(); | 306 last_response_time_ = Time::Now(); |
| 304 | 307 |
| 305 std::vector<ListUpdateResponse> list_update_responses; | 308 std::unique_ptr<ParsedServerResponse> parsed_server_response( |
| 309 new ParsedServerResponse); |
| 306 if (status.is_success() && response_code == net::HTTP_OK) { | 310 if (status.is_success() && response_code == net::HTTP_OK) { |
| 307 RecordUpdateResult(V4OperationResult::STATUS_200); | 311 RecordUpdateResult(V4OperationResult::STATUS_200); |
| 308 ResetUpdateErrors(); | 312 ResetUpdateErrors(); |
| 309 std::string data; | 313 std::string data; |
| 310 source->GetResponseAsString(&data); | 314 source->GetResponseAsString(&data); |
| 311 if (!ParseUpdateResponse(data, &list_update_responses)) { | 315 if (!ParseUpdateResponse(data, parsed_server_response.get())) { |
| 312 list_update_responses.clear(); | 316 parsed_server_response->clear(); |
| 313 RecordUpdateResult(V4OperationResult::PARSE_ERROR); | 317 RecordUpdateResult(V4OperationResult::PARSE_ERROR); |
| 314 } | 318 } |
| 315 request_.reset(); | 319 request_.reset(); |
| 316 | 320 |
| 317 UMA_HISTOGRAM_COUNTS("SafeBrowsing.V4UpdateResponseSizeKB", | 321 UMA_HISTOGRAM_COUNTS("SafeBrowsing.V4UpdateResponseSizeKB", |
| 318 data.size() / 1024); | 322 data.size() / 1024); |
| 319 | 323 |
| 320 // Invoke the callback with list_update_responses. | 324 // The caller should update its state now, based on parsed_server_response. |
| 321 // The caller should update its state now, based on list_update_responses. | |
| 322 // The callback must call ScheduleNextUpdate() at the end to resume | 325 // The callback must call ScheduleNextUpdate() at the end to resume |
| 323 // downloading updates. | 326 // downloading updates. |
| 324 update_callback_.Run(list_update_responses); | 327 update_callback_.Run(std::move(parsed_server_response)); |
| 325 } else { | 328 } else { |
| 326 DVLOG(1) << "SafeBrowsing GetEncodedUpdates request for: " | 329 DVLOG(1) << "SafeBrowsing GetEncodedUpdates request for: " |
| 327 << source->GetURL() << " failed with error: " << status.error() | 330 << source->GetURL() << " failed with error: " << status.error() |
| 328 << " and response code: " << response_code; | 331 << " and response code: " << response_code; |
| 329 | 332 |
| 330 if (status.status() == net::URLRequestStatus::FAILED) { | 333 if (status.status() == net::URLRequestStatus::FAILED) { |
| 331 RecordUpdateResult(V4OperationResult::NETWORK_ERROR); | 334 RecordUpdateResult(V4OperationResult::NETWORK_ERROR); |
| 332 } else { | 335 } else { |
| 333 RecordUpdateResult(V4OperationResult::HTTP_ERROR); | 336 RecordUpdateResult(V4OperationResult::HTTP_ERROR); |
| 334 } | 337 } |
| 335 // TODO(vakh): Figure out whether it is just a network error vs backoff vs | 338 // TODO(vakh): Figure out whether it is just a network error vs backoff vs |
| 336 // another condition and RecordUpdateResult more accurately. | 339 // another condition and RecordUpdateResult more accurately. |
| 337 | 340 |
| 338 request_.reset(); | 341 request_.reset(); |
| 339 ScheduleNextUpdateWithBackoff(true); | 342 ScheduleNextUpdateWithBackoff(true); |
| 340 } | 343 } |
| 341 } | 344 } |
| 342 | 345 |
| 343 void V4UpdateProtocolManager::GetUpdateUrlAndHeaders( | 346 void V4UpdateProtocolManager::GetUpdateUrlAndHeaders( |
| 344 const std::string& req_base64, | 347 const std::string& req_base64, |
| 345 GURL* gurl, | 348 GURL* gurl, |
| 346 net::HttpRequestHeaders* headers) const { | 349 net::HttpRequestHeaders* headers) const { |
| 347 V4ProtocolManagerUtil::GetRequestUrlAndHeaders( | 350 V4ProtocolManagerUtil::GetRequestUrlAndHeaders( |
| 348 req_base64, "threatListUpdates:fetch", config_, gurl, headers); | 351 req_base64, "threatListUpdates:fetch", config_, gurl, headers); |
| 349 } | 352 } |
| 350 | 353 |
| 351 } // namespace safe_browsing | 354 } // namespace safe_browsing |
| OLD | NEW |