Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/network_time/network_time_tracker.h" | 5 #include "components/network_time/network_time_tracker.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/feature_list.h" | 11 #include "base/feature_list.h" |
| 12 #include "base/i18n/time_formatting.h" | 12 #include "base/i18n/time_formatting.h" |
| 13 #include "base/json/json_reader.h" | 13 #include "base/json/json_reader.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
| 16 #include "base/metrics/histogram_macros.h" | |
| 17 #include "base/metrics/sparse_histogram.h" | |
| 16 #include "base/rand_util.h" | 18 #include "base/rand_util.h" |
| 17 #include "base/run_loop.h" | 19 #include "base/run_loop.h" |
| 18 #include "base/strings/string_number_conversions.h" | 20 #include "base/strings/string_number_conversions.h" |
| 19 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
| 20 #include "base/time/tick_clock.h" | 22 #include "base/time/tick_clock.h" |
| 21 #include "build/build_config.h" | 23 #include "build/build_config.h" |
| 22 #include "components/client_update_protocol/ecdsa.h" | 24 #include "components/client_update_protocol/ecdsa.h" |
| 23 #include "components/network_time/network_time_pref_names.h" | 25 #include "components/network_time/network_time_pref_names.h" |
| 24 #include "components/prefs/pref_registry_simple.h" | 26 #include "components/prefs/pref_registry_simple.h" |
| 25 #include "components/prefs/pref_service.h" | 27 #include "components/prefs/pref_service.h" |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 360 time_fetcher_->SaveResponseWithWriter( | 362 time_fetcher_->SaveResponseWithWriter( |
| 361 std::unique_ptr<net::URLFetcherResponseWriter>( | 363 std::unique_ptr<net::URLFetcherResponseWriter>( |
| 362 new SizeLimitingStringWriter(max_response_size_))); | 364 new SizeLimitingStringWriter(max_response_size_))); |
| 363 DCHECK(getter_); | 365 DCHECK(getter_); |
| 364 time_fetcher_->SetRequestContext(getter_.get()); | 366 time_fetcher_->SetRequestContext(getter_.get()); |
| 365 // Not expecting any cookies, but just in case. | 367 // Not expecting any cookies, but just in case. |
| 366 time_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE | | 368 time_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE | |
| 367 net::LOAD_DO_NOT_SAVE_COOKIES | | 369 net::LOAD_DO_NOT_SAVE_COOKIES | |
| 368 net::LOAD_DO_NOT_SEND_COOKIES | | 370 net::LOAD_DO_NOT_SEND_COOKIES | |
| 369 net::LOAD_DO_NOT_SEND_AUTH_DATA); | 371 net::LOAD_DO_NOT_SEND_AUTH_DATA); |
| 372 | |
| 373 UMA_HISTOGRAM_BOOLEAN("NetworkTimeTracker.UpdateTimeFetchAttempted", true); | |
|
mab
2016/07/26 21:05:48
Is a Boolean the idiomatic way to count things?
estark
2016/07/26 21:21:27
I have been told that it is, though admittedly I c
mab
2016/07/27 02:47:56
Ack.
| |
| 374 | |
| 370 time_fetcher_->Start(); | 375 time_fetcher_->Start(); |
| 371 fetch_started_ = tick_clock_->NowTicks(); | 376 fetch_started_ = tick_clock_->NowTicks(); |
| 372 | 377 |
| 373 timer_.Stop(); // Restarted in OnURLFetchComplete(). | 378 timer_.Stop(); // Restarted in OnURLFetchComplete(). |
| 374 } | 379 } |
| 375 | 380 |
| 376 bool NetworkTimeTracker::UpdateTimeFromResponse() { | 381 bool NetworkTimeTracker::UpdateTimeFromResponse() { |
| 377 if (time_fetcher_->GetStatus().status() != net::URLRequestStatus::SUCCESS && | 382 if (time_fetcher_->GetStatus().status() != net::URLRequestStatus::SUCCESS || |
|
mab
2016/07/26 21:05:48
Yikes, good catch.
mab
2016/07/28 06:58:54
(I take it your metrics would have caught this bug
estark
2016/07/28 18:27:58
Presumably, yeah -- one of the tests I added faile
| |
| 378 time_fetcher_->GetResponseCode() != 200) { | 383 time_fetcher_->GetResponseCode() != 200) { |
| 379 DVLOG(1) << "fetch failed, status=" << time_fetcher_->GetStatus().status() | 384 DVLOG(1) << "fetch failed, status=" << time_fetcher_->GetStatus().status() |
| 380 << ",code=" << time_fetcher_->GetResponseCode(); | 385 << ",code=" << time_fetcher_->GetResponseCode(); |
| 386 UMA_HISTOGRAM_SPARSE_SLOWLY("NetworkTimeTracker.UpdateTimeFetchFailed", | |
| 387 -time_fetcher_->GetStatus().error()); | |
|
mab
2016/07/26 21:05:48
Why negative? Is that the convention for errors?
estark
2016/07/26 21:21:26
Net error codes are negative (see net/base/net_err
mab
2016/07/27 02:47:56
OK, SG.
| |
| 381 return false; | 388 return false; |
| 382 } | 389 } |
| 383 | 390 |
| 391 UMA_HISTOGRAM_BOOLEAN("NetworkTimeTracker.UpdateTimeFetchSucceeded", true); | |
|
mab
2016/07/26 21:05:48
I think you could get away with having just one hi
estark
2016/07/26 21:21:26
By "just one histogram", do you mean collapsing Up
mab
2016/07/27 02:47:56
I meant collapse all 4 into one. Is the problem t
estark
2016/07/27 17:50:56
Yeah, I don't know of any way to do that... but a
mab
2016/07/28 06:58:55
Sure. Can you document that intent somewhere outs
estark
2016/07/28 18:27:58
Filed https://crbug.com/632419
| |
| 392 | |
| 384 std::string response_body; | 393 std::string response_body; |
| 385 if (!time_fetcher_->GetResponseAsString(&response_body)) { | 394 if (!time_fetcher_->GetResponseAsString(&response_body)) { |
| 386 DVLOG(1) << "failed to get response"; | 395 DVLOG(1) << "failed to get response"; |
| 387 return false; | 396 return false; |
| 388 } | 397 } |
| 389 DCHECK(query_signer_); | 398 DCHECK(query_signer_); |
| 390 if (!query_signer_->ValidateResponse(response_body, | 399 if (!query_signer_->ValidateResponse(response_body, |
| 391 GetServerProof(time_fetcher_.get()))) { | 400 GetServerProof(time_fetcher_.get()))) { |
| 392 DVLOG(1) << "invalid signature"; | 401 DVLOG(1) << "invalid signature"; |
| 393 return false; | 402 return false; |
| 394 } | 403 } |
| 395 response_body = response_body.substr(5); // Skips leading )]}'\n | 404 response_body = response_body.substr(5); // Skips leading )]}'\n |
| 396 std::unique_ptr<base::Value> value = base::JSONReader::Read(response_body); | 405 std::unique_ptr<base::Value> value = base::JSONReader::Read(response_body); |
| 397 if (!value) { | 406 if (!value) { |
| 398 DVLOG(1) << "bad JSON"; | 407 DVLOG(1) << "bad JSON"; |
| 399 return false; | 408 return false; |
| 400 } | 409 } |
| 401 const base::DictionaryValue* dict; | 410 const base::DictionaryValue* dict; |
| 402 if (!value->GetAsDictionary(&dict)) { | 411 if (!value->GetAsDictionary(&dict)) { |
| 403 DVLOG(1) << "not a dictionary"; | 412 DVLOG(1) << "not a dictionary"; |
| 404 return false; | 413 return false; |
| 405 } | 414 } |
| 406 double current_time_millis; | 415 double current_time_millis; |
| 407 if (!dict->GetDouble("current_time_millis", ¤t_time_millis)) { | 416 if (!dict->GetDouble("current_time_millis", ¤t_time_millis)) { |
| 408 DVLOG(1) << "no current_time_millis"; | 417 DVLOG(1) << "no current_time_millis"; |
| 409 return false; | 418 return false; |
| 410 } | 419 } |
| 420 | |
| 421 UMA_HISTOGRAM_BOOLEAN("NetworkTimeTracker.UpdateTimeFetchValid", true); | |
| 422 | |
| 411 // There is a "server_nonce" key here too, but it serves no purpose other than | 423 // There is a "server_nonce" key here too, but it serves no purpose other than |
| 412 // to make the server's response unpredictable. | 424 // to make the server's response unpredictable. |
| 413 base::Time current_time = base::Time::FromJsTime(current_time_millis); | 425 base::Time current_time = base::Time::FromJsTime(current_time_millis); |
| 414 base::TimeDelta resolution = | 426 base::TimeDelta resolution = |
| 415 base::TimeDelta::FromMilliseconds(1) + | 427 base::TimeDelta::FromMilliseconds(1) + |
| 416 base::TimeDelta::FromSeconds(kTimeServerMaxSkewSeconds); | 428 base::TimeDelta::FromSeconds(kTimeServerMaxSkewSeconds); |
| 417 base::TimeDelta latency = tick_clock_->NowTicks() - fetch_started_; | 429 base::TimeDelta latency = tick_clock_->NowTicks() - fetch_started_; |
| 418 UpdateNetworkTime(current_time, resolution, latency, tick_clock_->NowTicks()); | 430 UpdateNetworkTime(current_time, resolution, latency, tick_clock_->NowTicks()); |
| 419 return true; | 431 return true; |
| 420 } | 432 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 456 base::Time network_time; | 468 base::Time network_time; |
| 457 if (!GetNetworkTime(&network_time, nullptr)) { | 469 if (!GetNetworkTime(&network_time, nullptr)) { |
| 458 return true; | 470 return true; |
| 459 } | 471 } |
| 460 | 472 |
| 461 // Otherwise, make the decision at random. | 473 // Otherwise, make the decision at random. |
| 462 return base::RandDouble() < RandomQueryProbability(); | 474 return base::RandDouble() < RandomQueryProbability(); |
| 463 } | 475 } |
| 464 | 476 |
| 465 } // namespace network_time | 477 } // namespace network_time |
| OLD | NEW |