diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-08-01 12:59:39 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2016-08-04 12:40:43 +0000 |
commit | 28b1110370900897ab652cb420c371fab8857ad4 (patch) | |
tree | 41b32127d23b0df4f2add2a27e12dc87bddb260e /chromium/components/network_time | |
parent | 399c965b6064c440ddcf4015f5f8e9d131c7a0a6 (diff) | |
download | qtwebengine-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')
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); } |