Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(213)

Side by Side Diff: components/network_time/network_time_tracker.cc

Issue 1956173002: Revert of network_time_tracker: add temporary time protocol. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <utility> 8 #include <utility>
9 9
10 #include "base/feature_list.h"
11 #include "base/i18n/time_formatting.h" 10 #include "base/i18n/time_formatting.h"
12 #include "base/json/json_reader.h"
13 #include "base/logging.h" 11 #include "base/logging.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
16 #include "base/time/tick_clock.h" 13 #include "base/time/tick_clock.h"
17 #include "build/build_config.h" 14 #include "build/build_config.h"
18 #include "components/client_update_protocol/ecdsa.h"
19 #include "components/network_time/network_time_pref_names.h" 15 #include "components/network_time/network_time_pref_names.h"
20 #include "components/prefs/pref_registry_simple.h" 16 #include "components/prefs/pref_registry_simple.h"
21 #include "components/prefs/pref_service.h" 17 #include "components/prefs/pref_service.h"
22 #include "net/base/load_flags.h"
23 #include "net/base/net_errors.h"
24 #include "net/http/http_response_headers.h"
25 #include "net/url_request/url_fetcher.h"
26 #include "net/url_request/url_fetcher_response_writer.h"
27 #include "net/url_request/url_request_context_getter.h"
28 18
29 namespace network_time { 19 namespace network_time {
30 20
31 namespace { 21 namespace {
32 22
33 // Minimum number of minutes between time queries.
34 const uint32_t kMinimumQueryDelayMinutes = 60;
35
36 // Number of time measurements performed in a given network time calculation. 23 // Number of time measurements performed in a given network time calculation.
37 const uint32_t kNumTimeMeasurements = 7; 24 const uint32_t kNumTimeMeasurements = 7;
38 25
39 // Amount of divergence allowed between wall clock and tick clock. 26 // Amount of divergence allowed between wall clock and tick clock.
40 const uint32_t kClockDivergenceSeconds = 60; 27 const uint32_t kClockDivergenceSeconds = 60;
41 28
42 // Maximum time lapse before deserialized data are considered stale. 29 // Maximum time lapse before deserialized data are considered stale.
43 const uint32_t kSerializedDataMaxAgeDays = 7; 30 const uint32_t kSerializedDataMaxAgeDays = 7;
44 31
45 // Name of a pref that stores the wall clock time, via |ToJsTime|. 32 // Name of a pref that stores the wall clock time, via |ToJsTime|.
46 const char kPrefTime[] = "local"; 33 const char kPrefTime[] = "local";
47 34
48 // Name of a pref that stores the tick clock time, via |ToInternalValue|. 35 // Name of a pref that stores the tick clock time, via |ToInternalValue|.
49 const char kPrefTicks[] = "ticks"; 36 const char kPrefTicks[] = "ticks";
50 37
51 // Name of a pref that stores the time uncertainty, via |ToInternalValue|. 38 // Name of a pref that stores the time uncertainty, via |ToInternalValue|.
52 const char kPrefUncertainty[] = "uncertainty"; 39 const char kPrefUncertainty[] = "uncertainty";
53 40
54 // Name of a pref that stores the network time via |ToJsTime|. 41 // Name of a pref that stores the network time via |ToJsTime|.
55 const char kPrefNetworkTime[] = "network"; 42 const char kPrefNetworkTime[] = "network";
56 43
57 // Time server's maximum allowable clock skew, in seconds. (This is a property
58 // of the time server that we happen to know. It's unlikely that it would ever
59 // be that badly wrong, but all the same it's included here to document the very
60 // rough nature of the time service provided by this class.)
61 const uint32_t kTimeServerMaxSkewSeconds = 10;
62
63 const char kTimeServiceURL[] = "http://clients2.google.com/time/1/current";
64
65 // Finch feature that enables network time service querying.
66 const base::Feature kNetworkTimeServiceQuerying{
67 "NetworkTimeServiceQuerying", base::FEATURE_DISABLED_BY_DEFAULT};
68
69 // This is an ECDSA prime256v1 named-curve key.
70 const int kKeyVersion = 1;
71 const uint8_t kKeyPubBytes[] = {
72 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
73 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
74 0x42, 0x00, 0x04, 0xeb, 0xd8, 0xad, 0x0b, 0x8f, 0x75, 0xe8, 0x84, 0x36,
75 0x23, 0x48, 0x14, 0x24, 0xd3, 0x93, 0x42, 0x25, 0x43, 0xc1, 0xde, 0x36,
76 0x29, 0xc6, 0x95, 0xca, 0xeb, 0x28, 0x85, 0xff, 0x09, 0xdc, 0x08, 0xec,
77 0x45, 0x74, 0x6e, 0x4b, 0xc3, 0xa5, 0xfd, 0x8a, 0x2f, 0x02, 0xa0, 0x4b,
78 0xc3, 0xc6, 0xa4, 0x7b, 0xa4, 0x41, 0xfc, 0xa7, 0x02, 0x54, 0xab, 0xe3,
79 0xe4, 0xb1, 0x00, 0xf5, 0xd5, 0x09, 0x11};
80
81 std::string GetServerProof(const net::URLFetcher* source) {
82 const net::HttpResponseHeaders* response_headers =
83 source->GetResponseHeaders();
84 if (!response_headers) {
85 return std::string();
86 }
87 std::string proof;
88 return response_headers->EnumerateHeader(nullptr, "x-cup-server-proof",
89 &proof)
90 ? proof
91 : std::string();
92 }
93
94 // Limits the amount of data that will be buffered from the server's response.
95 class SizeLimitingStringWriter : public net::URLFetcherStringWriter {
96 public:
97 SizeLimitingStringWriter(size_t limit) : limit_(limit) {}
98
99 int Write(net::IOBuffer* buffer,
100 int num_bytes,
101 const net::CompletionCallback& callback) override {
102 if (data().length() + num_bytes > limit_) {
103 return net::ERR_FILE_TOO_BIG;
104 }
105 return net::URLFetcherStringWriter::Write(buffer, num_bytes, callback);
106 }
107
108 private:
109 size_t limit_;
110 };
111
112 } // namespace 44 } // namespace
113 45
114 // static 46 // static
115 void NetworkTimeTracker::RegisterPrefs(PrefRegistrySimple* registry) { 47 void NetworkTimeTracker::RegisterPrefs(PrefRegistrySimple* registry) {
116 registry->RegisterDictionaryPref(prefs::kNetworkTimeMapping, 48 registry->RegisterDictionaryPref(prefs::kNetworkTimeMapping,
117 new base::DictionaryValue()); 49 new base::DictionaryValue());
118 } 50 }
119 51
120 NetworkTimeTracker::NetworkTimeTracker( 52 NetworkTimeTracker::NetworkTimeTracker(
121 std::unique_ptr<base::Clock> clock, 53 std::unique_ptr<base::Clock> clock,
122 std::unique_ptr<base::TickClock> tick_clock, 54 std::unique_ptr<base::TickClock> tick_clock,
123 PrefService* pref_service, 55 PrefService* pref_service)
124 scoped_refptr<net::URLRequestContextGetter> getter) 56 : clock_(std::move(clock)),
125 : server_url_(kTimeServiceURL),
126 max_response_size_(1024),
127 getter_(std::move(getter)),
128 loop_(nullptr),
129 clock_(std::move(clock)),
130 tick_clock_(std::move(tick_clock)), 57 tick_clock_(std::move(tick_clock)),
131 pref_service_(pref_service) { 58 pref_service_(pref_service) {
132 const base::DictionaryValue* time_mapping = 59 const base::DictionaryValue* time_mapping =
133 pref_service_->GetDictionary(prefs::kNetworkTimeMapping); 60 pref_service_->GetDictionary(prefs::kNetworkTimeMapping);
134 double time_js = 0; 61 double time_js = 0;
135 double ticks_js = 0; 62 double ticks_js = 0;
136 double network_time_js = 0; 63 double network_time_js = 0;
137 double uncertainty_js = 0; 64 double uncertainty_js = 0;
138 if (time_mapping->GetDouble(kPrefTime, &time_js) && 65 if (time_mapping->GetDouble(kPrefTime, &time_js) &&
139 time_mapping->GetDouble(kPrefTicks, &ticks_js) && 66 time_mapping->GetDouble(kPrefTicks, &ticks_js) &&
140 time_mapping->GetDouble(kPrefUncertainty, &uncertainty_js) && 67 time_mapping->GetDouble(kPrefUncertainty, &uncertainty_js) &&
141 time_mapping->GetDouble(kPrefNetworkTime, &network_time_js)) { 68 time_mapping->GetDouble(kPrefNetworkTime, &network_time_js)) {
142 time_at_last_measurement_ = base::Time::FromJsTime(time_js); 69 time_at_last_measurement_ = base::Time::FromJsTime(time_js);
143 ticks_at_last_measurement_ = base::TimeTicks::FromInternalValue( 70 ticks_at_last_measurement_ = base::TimeTicks::FromInternalValue(
144 static_cast<int64_t>(ticks_js)); 71 static_cast<int64_t>(ticks_js));
145 network_time_uncertainty_ = base::TimeDelta::FromInternalValue( 72 network_time_uncertainty_ = base::TimeDelta::FromInternalValue(
146 static_cast<int64_t>(uncertainty_js)); 73 static_cast<int64_t>(uncertainty_js));
147 network_time_at_last_measurement_ = base::Time::FromJsTime(network_time_js); 74 network_time_at_last_measurement_ = base::Time::FromJsTime(network_time_js);
148 } 75 }
149 base::Time now = clock_->Now(); 76 base::Time now = clock_->Now();
150 if (ticks_at_last_measurement_ > tick_clock_->NowTicks() || 77 if (ticks_at_last_measurement_ > tick_clock_->NowTicks() ||
151 time_at_last_measurement_ > now || 78 time_at_last_measurement_ > now ||
152 now - time_at_last_measurement_ > 79 now - time_at_last_measurement_ >
153 base::TimeDelta::FromDays(kSerializedDataMaxAgeDays)) { 80 base::TimeDelta::FromDays(kSerializedDataMaxAgeDays)) {
154 // Drop saved mapping if either clock has run backward, or the data are too 81 // Drop saved mapping if either clock has run backward, or the data are too
155 // old. 82 // old.
156 pref_service_->ClearPref(prefs::kNetworkTimeMapping); 83 pref_service_->ClearPref(prefs::kNetworkTimeMapping);
157 network_time_at_last_measurement_ = base::Time(); // Reset. 84 network_time_at_last_measurement_ = base::Time(); // Reset.
158 } 85 }
159
160 base::StringPiece public_key = {reinterpret_cast<const char*>(kKeyPubBytes),
161 sizeof(kKeyPubBytes)};
162 query_signer_ =
163 client_update_protocol::Ecdsa::Create(kKeyVersion, public_key);
164
165 QueueTimeQuery(base::TimeDelta::FromMinutes(kMinimumQueryDelayMinutes));
166 } 86 }
167 87
168 NetworkTimeTracker::~NetworkTimeTracker() { 88 NetworkTimeTracker::~NetworkTimeTracker() {
169 DCHECK(thread_checker_.CalledOnValidThread()); 89 DCHECK(thread_checker_.CalledOnValidThread());
170 } 90 }
171 91
172 void NetworkTimeTracker::UpdateNetworkTime(base::Time network_time, 92 void NetworkTimeTracker::UpdateNetworkTime(base::Time network_time,
173 base::TimeDelta resolution, 93 base::TimeDelta resolution,
174 base::TimeDelta latency, 94 base::TimeDelta latency,
175 base::TimeTicks post_time) { 95 base::TimeTicks post_time) {
(...skipping 29 matching lines...) Expand all
205 125
206 base::DictionaryValue time_mapping; 126 base::DictionaryValue time_mapping;
207 time_mapping.SetDouble(kPrefTime, time_at_last_measurement_.ToJsTime()); 127 time_mapping.SetDouble(kPrefTime, time_at_last_measurement_.ToJsTime());
208 time_mapping.SetDouble(kPrefTicks, static_cast<double>( 128 time_mapping.SetDouble(kPrefTicks, static_cast<double>(
209 ticks_at_last_measurement_.ToInternalValue())); 129 ticks_at_last_measurement_.ToInternalValue()));
210 time_mapping.SetDouble(kPrefUncertainty, static_cast<double>( 130 time_mapping.SetDouble(kPrefUncertainty, static_cast<double>(
211 network_time_uncertainty_.ToInternalValue())); 131 network_time_uncertainty_.ToInternalValue()));
212 time_mapping.SetDouble(kPrefNetworkTime, 132 time_mapping.SetDouble(kPrefNetworkTime,
213 network_time_at_last_measurement_.ToJsTime()); 133 network_time_at_last_measurement_.ToJsTime());
214 pref_service_->Set(prefs::kNetworkTimeMapping, time_mapping); 134 pref_service_->Set(prefs::kNetworkTimeMapping, time_mapping);
215
216 // Calls to update the network time can (as of this writing) come from various
217 // sources, e.g. organically from Omaha update checks. In that even, we may
218 // as well delay the next time server query. If |UpdateNetworkTime| is ever
219 // made into a private method, this can be removed.
220 query_timer_.Reset();
221 }
222
223 void NetworkTimeTracker::SetTimeServerURLForTesting(const GURL& url) {
224 server_url_ = url;
225 }
226
227 void NetworkTimeTracker::SetMaxResponseSizeForTesting(size_t limit) {
228 max_response_size_ = limit;
229 }
230
231 void NetworkTimeTracker::SetPublicKeyForTesting(const base::StringPiece& key) {
232 query_signer_ = client_update_protocol::Ecdsa::Create(kKeyVersion, key);
233 }
234
235 bool NetworkTimeTracker::QueryTimeServiceForTesting() {
236 QueryTimeService();
237 loop_ = base::MessageLoop::current(); // Gets Quit on completion.
238 return time_fetcher_ != nullptr;
239 }
240
241 void NetworkTimeTracker::WaitForFetchForTesting(uint32_t nonce) {
242 query_signer_->OverrideNonceForTesting(kKeyVersion, nonce);
243 base::MessageLoop::current()->Run();
244 }
245
246 base::TimeDelta NetworkTimeTracker::GetTimerDelayForTesting() const {
247 DCHECK(query_timer_.IsRunning());
248 return query_timer_.GetCurrentDelay();
249 } 135 }
250 136
251 bool NetworkTimeTracker::GetNetworkTime(base::Time* network_time, 137 bool NetworkTimeTracker::GetNetworkTime(base::Time* network_time,
252 base::TimeDelta* uncertainty) const { 138 base::TimeDelta* uncertainty) const {
253 DCHECK(thread_checker_.CalledOnValidThread()); 139 DCHECK(thread_checker_.CalledOnValidThread());
254 DCHECK(network_time); 140 DCHECK(network_time);
255 if (network_time_at_last_measurement_.is_null()) { 141 if (network_time_at_last_measurement_.is_null()) {
256 return false; 142 return false;
257 } 143 }
258 DCHECK(!ticks_at_last_measurement_.is_null()); 144 DCHECK(!ticks_at_last_measurement_.is_null());
(...skipping 15 matching lines...) Expand all
274 network_time_at_last_measurement_ = base::Time(); 160 network_time_at_last_measurement_ = base::Time();
275 return false; 161 return false;
276 } 162 }
277 *network_time = network_time_at_last_measurement_ + tick_delta; 163 *network_time = network_time_at_last_measurement_ + tick_delta;
278 if (uncertainty) { 164 if (uncertainty) {
279 *uncertainty = network_time_uncertainty_ + divergence; 165 *uncertainty = network_time_uncertainty_ + divergence;
280 } 166 }
281 return true; 167 return true;
282 } 168 }
283 169
284 void NetworkTimeTracker::QueryTimeService() {
285 DCHECK(thread_checker_.CalledOnValidThread());
286
287 // Do not query the time service if not enabled via Finch.
288 if (!base::FeatureList::IsEnabled(kNetworkTimeServiceQuerying)) {
289 return;
290 }
291
292 // If GetNetworkTime() returns true, the NetworkTimeTracker thinks it is in
293 // sync, so there is no need to query.
294 base::Time network_time;
295 if (GetNetworkTime(&network_time, nullptr)) {
296 return;
297 }
298
299 std::string query_string;
300 query_signer_->SignRequest(nullptr, &query_string);
301 GURL url = server_url_;
302 GURL::Replacements replacements;
303 replacements.SetQueryStr(query_string);
304 url = url.ReplaceComponents(replacements);
305
306 // This cancels any outstanding fetch.
307 time_fetcher_ = net::URLFetcher::Create(url, net::URLFetcher::GET, this);
308 if (!time_fetcher_) {
309 DVLOG(1) << "tried to make fetch happen; failed";
310 return;
311 }
312 time_fetcher_->SaveResponseWithWriter(
313 std::unique_ptr<net::URLFetcherResponseWriter>(
314 new SizeLimitingStringWriter(max_response_size_)));
315 DCHECK(getter_);
316 time_fetcher_->SetRequestContext(getter_.get());
317 // Not expecting any cookies, but just in case.
318 time_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE |
319 net::LOAD_DO_NOT_SAVE_COOKIES |
320 net::LOAD_DO_NOT_SEND_COOKIES |
321 net::LOAD_DO_NOT_SEND_AUTH_DATA);
322 time_fetcher_->Start();
323 fetch_started_ = tick_clock_->NowTicks();
324 }
325
326 bool NetworkTimeTracker::UpdateTimeFromResponse() {
327 if (time_fetcher_->GetStatus().status() != net::URLRequestStatus::SUCCESS &&
328 time_fetcher_->GetResponseCode() != 200) {
329 DVLOG(1) << "fetch failed, status=" << time_fetcher_->GetStatus().status()
330 << ",code=" << time_fetcher_->GetResponseCode();
331 return false;
332 }
333
334 std::string response_body;
335 if (!time_fetcher_->GetResponseAsString(&response_body)) {
336 DVLOG(1) << "failed to get response";
337 return false;
338 }
339 DCHECK(query_signer_);
340 if (!query_signer_->ValidateResponse(response_body,
341 GetServerProof(time_fetcher_.get()))) {
342 DVLOG(1) << "invalid signature";
343 return false;
344 }
345 response_body = response_body.substr(5); // Skips leading )]}'\n
346 std::unique_ptr<base::Value> value = base::JSONReader::Read(response_body);
347 if (!value) {
348 DVLOG(1) << "bad JSON";
349 return false;
350 }
351 const base::DictionaryValue* dict;
352 if (!value->GetAsDictionary(&dict)) {
353 DVLOG(1) << "not a dictionary";
354 return false;
355 }
356 double current_time_millis;
357 if (!dict->GetDouble("current_time_millis", &current_time_millis)) {
358 DVLOG(1) << "no current_time_millis";
359 return false;
360 }
361 // There is a "server_nonce" key here too, but it serves no purpose other than
362 // to make the server's response unpredictable.
363 base::Time current_time = base::Time::FromJsTime(current_time_millis);
364 base::TimeDelta resolution =
365 base::TimeDelta::FromMilliseconds(1) +
366 base::TimeDelta::FromSeconds(kTimeServerMaxSkewSeconds);
367 base::TimeDelta latency = tick_clock_->NowTicks() - fetch_started_;
368 UpdateNetworkTime(current_time, resolution, latency, tick_clock_->NowTicks());
369 return true;
370 }
371
372 void NetworkTimeTracker::OnURLFetchComplete(const net::URLFetcher* source) {
373 DCHECK(thread_checker_.CalledOnValidThread());
374 DCHECK(time_fetcher_);
375 DCHECK_EQ(source, time_fetcher_.get());
376
377 if (!UpdateTimeFromResponse()) { // On error, back off.
378 DCHECK(query_timer_.IsRunning());
379 base::TimeDelta delay = query_timer_.GetCurrentDelay();
380 if (delay < base::TimeDelta::FromDays(2)) {
381 delay *= 2;
382 }
383 QueueTimeQuery(delay);
384 }
385 time_fetcher_.reset();
386 if (loop_ != nullptr) {
387 loop_->QuitWhenIdle();
388 loop_ = nullptr;
389 }
390 }
391
392 void NetworkTimeTracker::QueueTimeQuery(base::TimeDelta delay) {
393 query_timer_.Start(FROM_HERE, delay, this,
394 &NetworkTimeTracker::QueryTimeService);
395 }
396
397 } // namespace network_time 170 } // namespace network_time
OLDNEW
« no previous file with comments | « components/network_time/network_time_tracker.h ('k') | components/network_time/network_time_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698