summaryrefslogtreecommitdiff
path: root/chromium/components/network_time
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-08-01 12:59:39 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2016-08-04 12:40:43 +0000
commit28b1110370900897ab652cb420c371fab8857ad4 (patch)
tree41b32127d23b0df4f2add2a27e12dc87bddb260e /chromium/components/network_time
parent399c965b6064c440ddcf4015f5f8e9d131c7a0a6 (diff)
downloadqtwebengine-chromium-28b1110370900897ab652cb420c371fab8857ad4.tar.gz
BASELINE: Update Chromium to 53.0.2785.41
Also adds a few extra files for extensions. Change-Id: Iccdd55d98660903331cf8b7b29188da781830af4 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/network_time')
-rw-r--r--chromium/components/network_time/BUILD.gn2
-rw-r--r--chromium/components/network_time/DEPS1
-rw-r--r--chromium/components/network_time/network_time_tracker.cc127
-rw-r--r--chromium/components/network_time/network_time_tracker.h19
-rw-r--r--chromium/components/network_time/network_time_tracker_unittest.cc81
5 files changed, 184 insertions, 46 deletions
diff --git a/chromium/components/network_time/BUILD.gn b/chromium/components/network_time/BUILD.gn
index 5bb5fb7b497..c7170edd004 100644
--- a/chromium/components/network_time/BUILD.gn
+++ b/chromium/components/network_time/BUILD.gn
@@ -15,6 +15,7 @@ static_library("network_time") {
"//base:i18n",
"//components/client_update_protocol",
"//components/prefs",
+ "//components/variations",
"//net",
]
}
@@ -31,6 +32,7 @@ source_set("unit_tests") {
"//base/test:test_support",
"//components/client_update_protocol",
"//components/prefs:test_support",
+ "//components/variations",
"//net",
"//net:test_support",
"//testing/gtest",
diff --git a/chromium/components/network_time/DEPS b/chromium/components/network_time/DEPS
index f216f9cc4f3..333f4bccda3 100644
--- a/chromium/components/network_time/DEPS
+++ b/chromium/components/network_time/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+components/client_update_protocol",
+ "+components/variations",
"+components/prefs",
"+net",
]
diff --git a/chromium/components/network_time/network_time_tracker.cc b/chromium/components/network_time/network_time_tracker.cc
index 1dbfd820fa2..dc4ccbb56d3 100644
--- a/chromium/components/network_time/network_time_tracker.cc
+++ b/chromium/components/network_time/network_time_tracker.cc
@@ -13,6 +13,9 @@
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
+#include "base/rand_util.h"
+#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/tick_clock.h"
#include "build/build_config.h"
@@ -20,6 +23,7 @@
#include "components/network_time/network_time_pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
+#include "components/variations/variations_associated_data.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
@@ -31,8 +35,34 @@ namespace network_time {
namespace {
+// Time updates happen in two ways. First, other components may call
+// UpdateNetworkTime() if they happen to obtain the time securely. This will
+// likely be deprecated in favor of the second way, which is scheduled time
+// queries issued by NetworkTimeTracker itself.
+//
+// On startup, the clock state may be read from a pref. (This, too, may be
+// deprecated.) After that, the time is checked every
+// |kCheckTimeIntervalSeconds|. A "check" means the possibility, but not the
+// certainty, of a time query. A time query may be issued at random, or if the
+// network time is believed to have become inaccurate.
+//
+// After issuing a query, the next check will not happen until
+// |kBackoffMinutes|. This delay is doubled in the event of an error.
+
// Minimum number of minutes between time queries.
-const uint32_t kMinimumQueryDelayMinutes = 60;
+const uint32_t kBackoffMinutes = 60;
+
+// Number of seconds between time checks. This may be overridden via Variations
+// Service.
+// Note that a "check" is not necessarily a network time query!
+const uint32_t kCheckTimeIntervalSeconds = 360;
+
+// Probability that a check will randomly result in a query. This may
+// be overridden via Variations Service. Checks are made every
+// |kCheckTimeIntervalSeconds|. The default values are chosen with
+// the goal of a high probability that a query will be issued every 24
+// hours.
+const float kRandomQueryProbability = .012f;
// Number of time measurements performed in a given network time calculation.
const uint32_t kNumTimeMeasurements = 7;
@@ -63,10 +93,15 @@ const uint32_t kTimeServerMaxSkewSeconds = 10;
const char kTimeServiceURL[] = "http://clients2.google.com/time/1/current";
-// Finch feature that enables network time service querying.
+// Variations Service feature that enables network time service querying.
const base::Feature kNetworkTimeServiceQuerying{
"NetworkTimeServiceQuerying", base::FEATURE_DISABLED_BY_DEFAULT};
+const char kVariationsServiceCheckTimeIntervalSeconds[] =
+ "CheckTimeIntervalSeconds";
+const char kVariationsServiceRandomQueryProbability[] =
+ "RandomQueryProbability";
+
// This is an ECDSA prime256v1 named-curve key.
const int kKeyVersion = 1;
const uint8_t kKeyPubBytes[] = {
@@ -110,6 +145,27 @@ class SizeLimitingStringWriter : public net::URLFetcherStringWriter {
size_t limit_;
};
+base::TimeDelta CheckTimeInterval() {
+ int64_t seconds;
+ const std::string param = variations::GetVariationParamValueByFeature(
+ kNetworkTimeServiceQuerying, kVariationsServiceCheckTimeIntervalSeconds);
+ if (!param.empty() && base::StringToInt64(param, &seconds) && seconds > 0) {
+ return base::TimeDelta::FromSeconds(seconds);
+ }
+ return base::TimeDelta::FromSeconds(kCheckTimeIntervalSeconds);
+}
+
+double RandomQueryProbability() {
+ double probability;
+ const std::string param = variations::GetVariationParamValueByFeature(
+ kNetworkTimeServiceQuerying, kVariationsServiceRandomQueryProbability);
+ if (!param.empty() && base::StringToDouble(param, &probability) &&
+ probability >= 0.0 && probability <= 1.0) {
+ return probability;
+ }
+ return kRandomQueryProbability;
+}
+
} // namespace
// static
@@ -125,6 +181,7 @@ NetworkTimeTracker::NetworkTimeTracker(
scoped_refptr<net::URLRequestContextGetter> getter)
: server_url_(kTimeServiceURL),
max_response_size_(1024),
+ backoff_(base::TimeDelta::FromMinutes(kBackoffMinutes)),
getter_(std::move(getter)),
loop_(nullptr),
clock_(std::move(clock)),
@@ -163,7 +220,7 @@ NetworkTimeTracker::NetworkTimeTracker(
query_signer_ =
client_update_protocol::Ecdsa::Create(kKeyVersion, public_key);
- QueueTimeQuery(base::TimeDelta::FromMinutes(kMinimumQueryDelayMinutes));
+ QueueCheckTime(base::TimeDelta::FromSeconds(0));
}
NetworkTimeTracker::~NetworkTimeTracker() {
@@ -213,12 +270,6 @@ void NetworkTimeTracker::UpdateNetworkTime(base::Time network_time,
time_mapping.SetDouble(kPrefNetworkTime,
network_time_at_last_measurement_.ToJsTime());
pref_service_->Set(prefs::kNetworkTimeMapping, time_mapping);
-
- // Calls to update the network time can (as of this writing) come from various
- // sources, e.g. organically from Omaha update checks. In that even, we may
- // as well delay the next time server query. If |UpdateNetworkTime| is ever
- // made into a private method, this can be removed.
- query_timer_.Reset();
}
void NetworkTimeTracker::SetTimeServerURLForTesting(const GURL& url) {
@@ -234,19 +285,19 @@ void NetworkTimeTracker::SetPublicKeyForTesting(const base::StringPiece& key) {
}
bool NetworkTimeTracker::QueryTimeServiceForTesting() {
- QueryTimeService();
+ CheckTime();
loop_ = base::MessageLoop::current(); // Gets Quit on completion.
return time_fetcher_ != nullptr;
}
void NetworkTimeTracker::WaitForFetchForTesting(uint32_t nonce) {
query_signer_->OverrideNonceForTesting(kKeyVersion, nonce);
- base::MessageLoop::current()->Run();
+ base::RunLoop().Run();
}
base::TimeDelta NetworkTimeTracker::GetTimerDelayForTesting() const {
- DCHECK(query_timer_.IsRunning());
- return query_timer_.GetCurrentDelay();
+ DCHECK(timer_.IsRunning());
+ return timer_.GetCurrentDelay();
}
bool NetworkTimeTracker::GetNetworkTime(base::Time* network_time,
@@ -282,18 +333,14 @@ bool NetworkTimeTracker::GetNetworkTime(base::Time* network_time,
return true;
}
-void NetworkTimeTracker::QueryTimeService() {
+void NetworkTimeTracker::CheckTime() {
DCHECK(thread_checker_.CalledOnValidThread());
- // Do not query the time service if not enabled via Finch.
- if (!base::FeatureList::IsEnabled(kNetworkTimeServiceQuerying)) {
- return;
- }
+ // If NetworkTimeTracker is waking up after a backoff, this will reset the
+ // timer to its default faster frequency.
+ QueueCheckTime(CheckTimeInterval());
- // If GetNetworkTime() returns true, the NetworkTimeTracker thinks it is in
- // sync, so there is no need to query.
- base::Time network_time;
- if (GetNetworkTime(&network_time, nullptr)) {
+ if (!ShouldIssueTimeQuery()) {
return;
}
@@ -322,6 +369,8 @@ void NetworkTimeTracker::QueryTimeService() {
net::LOAD_DO_NOT_SEND_AUTH_DATA);
time_fetcher_->Start();
fetch_started_ = tick_clock_->NowTicks();
+
+ timer_.Stop(); // Restarted in OnURLFetchComplete().
}
bool NetworkTimeTracker::UpdateTimeFromResponse() {
@@ -375,14 +424,16 @@ void NetworkTimeTracker::OnURLFetchComplete(const net::URLFetcher* source) {
DCHECK(time_fetcher_);
DCHECK_EQ(source, time_fetcher_.get());
+ // After completion of a query, whether succeeded or failed, go to sleep for a
+ // long time.
if (!UpdateTimeFromResponse()) { // On error, back off.
- DCHECK(query_timer_.IsRunning());
- base::TimeDelta delay = query_timer_.GetCurrentDelay();
- if (delay < base::TimeDelta::FromDays(2)) {
- delay *= 2;
+ if (backoff_ < base::TimeDelta::FromDays(2)) {
+ backoff_ *= 2;
}
- QueueTimeQuery(delay);
+ } else {
+ backoff_ = base::TimeDelta::FromMinutes(kBackoffMinutes);
}
+ QueueCheckTime(backoff_);
time_fetcher_.reset();
if (loop_ != nullptr) {
loop_->QuitWhenIdle();
@@ -390,9 +441,25 @@ void NetworkTimeTracker::OnURLFetchComplete(const net::URLFetcher* source) {
}
}
-void NetworkTimeTracker::QueueTimeQuery(base::TimeDelta delay) {
- query_timer_.Start(FROM_HERE, delay, this,
- &NetworkTimeTracker::QueryTimeService);
+void NetworkTimeTracker::QueueCheckTime(base::TimeDelta delay) {
+ timer_.Start(FROM_HERE, delay, this, &NetworkTimeTracker::CheckTime);
+}
+
+bool NetworkTimeTracker::ShouldIssueTimeQuery() {
+ // Do not query the time service if not enabled via Variations Service.
+ if (!base::FeatureList::IsEnabled(kNetworkTimeServiceQuerying)) {
+ return false;
+ }
+
+ // If GetNetworkTime() returns false, synchronization has been lost
+ // and a query is needed.
+ base::Time network_time;
+ if (!GetNetworkTime(&network_time, nullptr)) {
+ return true;
+ }
+
+ // Otherwise, make the decision at random.
+ return base::RandDouble() < RandomQueryProbability();
}
} // namespace network_time
diff --git a/chromium/components/network_time/network_time_tracker.h b/chromium/components/network_time/network_time_tracker.h
index 69268ffcb9d..07869e3f271 100644
--- a/chromium/components/network_time/network_time_tracker.h
+++ b/chromium/components/network_time/network_time_tracker.h
@@ -94,9 +94,9 @@ class NetworkTimeTracker : public net::URLFetcherDelegate {
base::TimeDelta GetTimerDelayForTesting() const;
private:
- // If synchronization has been lost, sends a query to the secure time service.
+ // Checks whether a network time query should be issued, and issues one if so.
// Upon response, execution resumes in |OnURLFetchComplete|.
- void QueryTimeService();
+ void CheckTime();
// Updates network time from a time server response, returning true
// if successful.
@@ -107,12 +107,21 @@ class NetworkTimeTracker : public net::URLFetcherDelegate {
void OnURLFetchComplete(const net::URLFetcher* source) override;
// Sets the next time query to be run at the specified time.
- void QueueTimeQuery(base::TimeDelta delay);
+ void QueueCheckTime(base::TimeDelta delay);
+
+ // Returns true if there's sufficient reason to suspect that
+ // NetworkTimeTracker does not know what time it is. This returns true
+ // unconditionally every once in a long while, just to be on the safe side.
+ bool ShouldIssueTimeQuery();
// State variables for internally-managed secure time service queries.
GURL server_url_;
size_t max_response_size_;
- base::RepeatingTimer query_timer_;
+ base::TimeDelta backoff_;
+ // Timer that runs CheckTime(). All backoff and delay is implemented by
+ // changing the delay of this timer, with the result that CheckTime() may
+ // assume that if it runs, it is eligible to issue a time query.
+ base::RepeatingTimer timer_;
scoped_refptr<net::URLRequestContextGetter> getter_;
std::unique_ptr<net::URLFetcher> time_fetcher_;
base::TimeTicks fetch_started_;
@@ -144,8 +153,6 @@ class NetworkTimeTracker : public net::URLFetcherDelegate {
base::ThreadChecker thread_checker_;
- bool received_network_time_;
-
DISALLOW_COPY_AND_ASSIGN(NetworkTimeTracker);
};
diff --git a/chromium/components/network_time/network_time_tracker_unittest.cc b/chromium/components/network_time/network_time_tracker_unittest.cc
index 6b7d75da86e..d4d5c939177 100644
--- a/chromium/components/network_time/network_time_tracker_unittest.cc
+++ b/chromium/components/network_time/network_time_tracker_unittest.cc
@@ -4,17 +4,23 @@
#include "components/network_time/network_time_tracker.h"
+#include <map>
#include <memory>
+#include <string>
#include <utility>
#include "base/compiler_specific.h"
#include "base/feature_list.h"
+#include "base/metrics/field_trial.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
+#include "base/test/mock_entropy_provider.h"
#include "base/test/simple_test_clock.h"
#include "base/test/simple_test_tick_clock.h"
#include "components/client_update_protocol/ecdsa.h"
#include "components/network_time/network_time_pref_names.h"
#include "components/prefs/testing_pref_service.h"
+#include "components/variations/variations_associated_data.h"
#include "net/http/http_response_headers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_response.h"
@@ -38,6 +44,8 @@ class NetworkTimeTrackerTest : public testing::Test {
EXPECT_TRUE(io_thread_.StartWithOptions(thread_options));
NetworkTimeTracker::RegisterPrefs(pref_service_.registry());
+ SetNetworkQueriesWithVariationsService(true, 0.0 /* query probability */);
+
tracker_.reset(new NetworkTimeTracker(
std::unique_ptr<base::Clock>(clock_),
std::unique_ptr<base::TickClock>(tick_clock_), &pref_service_,
@@ -51,8 +59,6 @@ class NetworkTimeTrackerTest : public testing::Test {
resolution_ = base::TimeDelta::FromMilliseconds(17);
latency_ = base::TimeDelta::FromMilliseconds(50);
adjustment_ = 7 * base::TimeDelta::FromMilliseconds(kTicksResolutionMs);
-
- SetNetworkQueriesWithFinch(true);
}
void TearDown() override { io_thread_.Stop(); }
@@ -159,12 +165,45 @@ class NetworkTimeTrackerTest : public testing::Test {
}
protected:
- void SetNetworkQueriesWithFinch(bool enable) {
+ void SetNetworkQueriesWithVariationsService(bool enable,
+ float query_probability) {
+ const std::string kTrialName = "Trial";
+ const std::string kGroupName = "group";
+ const base::Feature kFeature{"NetworkTimeServiceQuerying",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+ // Clear all the things.
base::FeatureList::ClearInstanceForTesting();
+ variations::testing::ClearAllVariationParams();
+
+ std::map<std::string, std::string> params;
+ params["RandomQueryProbability"] = base::DoubleToString(query_probability);
+ params["CheckTimeIntervalSeconds"] = base::Int64ToString(360);
+
+ // There are 3 things here: a FieldTrial, a FieldTrialList, and a
+ // FeatureList. Don't get confused! The FieldTrial is reference-counted,
+ // and a reference is held by the FieldTrialList. The FieldTrialList and
+ // FeatureList are both singletons. The authorized way to reset the former
+ // for testing is to destruct it (above). The latter, by contrast, is reset
+ // with |ClearInstanceForTesting|, above. If this comment was useful to you
+ // please send me a postcard.
+
+ field_trial_list_.reset(); // Averts a CHECK fail in constructor below.
+ field_trial_list_.reset(
+ new base::FieldTrialList(new base::MockEntropyProvider()));
+ // refcounted, and reference held by field_trial_list_.
+ base::FieldTrial* trial = base::FieldTrialList::FactoryGetFieldTrial(
+ kTrialName, 100, kGroupName, 1971, 1, 1,
+ base::FieldTrial::SESSION_RANDOMIZED,
+ nullptr /* default_group_number */);
+ ASSERT_TRUE(
+ variations::AssociateVariationParams(kTrialName, kGroupName, params));
+
std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- if (enable) {
- feature_list->InitializeFromCommandLine("NetworkTimeServiceQuerying", "");
- }
+ feature_list->RegisterFieldTrialOverride(
+ kFeature.name, enable ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
+ : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
+ trial);
base::FeatureList::SetInstance(std::move(feature_list));
}
@@ -176,6 +215,7 @@ class NetworkTimeTrackerTest : public testing::Test {
base::SimpleTestClock* clock_;
base::SimpleTestTickClock* tick_clock_;
TestingPrefServiceSimple pref_service_;
+ std::unique_ptr<base::FieldTrialList> field_trial_list_;
std::unique_ptr<NetworkTimeTracker> tracker_;
std::unique_ptr<net::EmbeddedTestServer> test_server_;
};
@@ -396,6 +436,9 @@ TEST_F(NetworkTimeTrackerTest, SerializeWithWallClockAdvance) {
TEST_F(NetworkTimeTrackerTest, UpdateFromNetwork) {
base::Time out_network_time;
EXPECT_FALSE(tracker_->GetNetworkTime(&out_network_time, nullptr));
+ // First query should happen soon.
+ EXPECT_EQ(base::TimeDelta::FromMinutes(0),
+ tracker_->GetTimerDelayForTesting());
test_server_->RegisterRequestHandler(
base::Bind(&NetworkTimeTrackerTest::GoodTimeResponseHandler));
@@ -414,20 +457,38 @@ TEST_F(NetworkTimeTrackerTest, UpdateFromNetwork) {
}
TEST_F(NetworkTimeTrackerTest, NoNetworkQueryWhileSynced) {
+ test_server_->RegisterRequestHandler(
+ base::Bind(&NetworkTimeTrackerTest::GoodTimeResponseHandler));
+ EXPECT_TRUE(test_server_->Start());
+ tracker_->SetTimeServerURLForTesting(test_server_->GetURL("/"));
+
+ SetNetworkQueriesWithVariationsService(true, 0.0);
base::Time in_network_time = clock_->Now();
UpdateNetworkTime(in_network_time, resolution_, latency_,
tick_clock_->NowTicks());
- EXPECT_FALSE(
- tracker_->QueryTimeServiceForTesting()); // No query should be started.
+
+ // No query should be started so long as NetworkTimeTracker is synced, but the
+ // next check should happen soon.
+ EXPECT_FALSE(tracker_->QueryTimeServiceForTesting());
+ EXPECT_EQ(base::TimeDelta::FromMinutes(6),
+ tracker_->GetTimerDelayForTesting());
+
+ SetNetworkQueriesWithVariationsService(true, 1.0);
+ EXPECT_TRUE(tracker_->QueryTimeServiceForTesting());
+ tracker_->WaitForFetchForTesting(123123123);
+ EXPECT_EQ(base::TimeDelta::FromMinutes(60),
+ tracker_->GetTimerDelayForTesting());
}
TEST_F(NetworkTimeTrackerTest, NoNetworkQueryWhileFeatureDisabled) {
// Disable network time queries and check that a query is not sent.
- SetNetworkQueriesWithFinch(false);
+ SetNetworkQueriesWithVariationsService(false, 0.0);
EXPECT_FALSE(tracker_->QueryTimeServiceForTesting());
+ EXPECT_EQ(base::TimeDelta::FromMinutes(6),
+ tracker_->GetTimerDelayForTesting());
// Enable time queries and check that a query is sent.
- SetNetworkQueriesWithFinch(true);
+ SetNetworkQueriesWithVariationsService(true, 0.0);
EXPECT_TRUE(tracker_->QueryTimeServiceForTesting());
tracker_->WaitForFetchForTesting(123123123);
}