Commit ec22cb6b authored by tbansal's avatar tbansal Committed by Commit bot

Add Network Quality Estimator (NQE) pref manager

The PrefManager class owns an IO Object (CacheObserver) and
a Pref object (PrefDelegate).

The embedder would need to implement PrefDelegate and create
an instance of PrefManager for prefs to work. Right now, only
writes to the prefs is implemented. Reads would come in the
next CL, along with the Chromium implementation.

BUG=490870

Review-Url: https://codereview.chromium.org/2322183002
Cr-Commit-Position: refs/heads/master@{#420786}
parent 971faed8
...@@ -769,6 +769,8 @@ ...@@ -769,6 +769,8 @@
'nqe/effective_connection_type.h', 'nqe/effective_connection_type.h',
'nqe/external_estimate_provider.h', 'nqe/external_estimate_provider.h',
'nqe/network_id.h', 'nqe/network_id.h',
'nqe/network_qualities_prefs_manager.cc',
'nqe/network_qualities_prefs_manager.h',
'nqe/network_quality.cc', 'nqe/network_quality.cc',
'nqe/network_quality.h', 'nqe/network_quality.h',
'nqe/network_quality_estimator.cc', 'nqe/network_quality_estimator.cc',
...@@ -1589,6 +1591,7 @@ ...@@ -1589,6 +1591,7 @@
'log/write_to_file_net_log_observer_unittest.cc', 'log/write_to_file_net_log_observer_unittest.cc',
'log/bounded_file_net_log_observer_unittest.cc', 'log/bounded_file_net_log_observer_unittest.cc',
'nqe/effective_connection_type_unittest.cc', 'nqe/effective_connection_type_unittest.cc',
'nqe/network_qualities_prefs_manager_unittest.cc',
'nqe/network_quality_estimator_test_util.cc', 'nqe/network_quality_estimator_test_util.cc',
'nqe/network_quality_estimator_test_util.h', 'nqe/network_quality_estimator_test_util.h',
'nqe/network_quality_estimator_unittest.cc', 'nqe/network_quality_estimator_unittest.cc',
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
#include "net/base/net_export.h" #include "net/base/net_export.h"
#include "net/base/network_change_notifier.h" #include "net/base/network_change_notifier.h"
namespace {
const char kValueSeparator[] = ",";
}
namespace net { namespace net {
namespace nqe { namespace nqe {
namespace internal { namespace internal {
...@@ -38,6 +42,11 @@ struct NET_EXPORT_PRIVATE NetworkID { ...@@ -38,6 +42,11 @@ struct NET_EXPORT_PRIVATE NetworkID {
return std::tie(type, id) < std::tie(other.type, other.id); return std::tie(type, id) < std::tie(other.type, other.id);
} }
std::string ToString() const {
return id + kValueSeparator +
NetworkChangeNotifier::ConnectionTypeToString(type);
}
// Connection type of the network. // Connection type of the network.
NetworkChangeNotifier::ConnectionType type; NetworkChangeNotifier::ConnectionType type;
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/nqe/network_qualities_prefs_manager.h"
#include <utility>
#include "base/bind.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "net/nqe/cached_network_quality.h"
#include "net/nqe/network_quality_estimator.h"
namespace net {
NetworkQualitiesPrefsManager::NetworkQualitiesPrefsManager(
std::unique_ptr<PrefDelegate> pref_delegate)
: pref_delegate_(std::move(pref_delegate)),
pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
network_quality_estimator_(nullptr),
pref_weak_ptr_factory_(this) {
DCHECK(pref_delegate_);
pref_weak_ptr_ = pref_weak_ptr_factory_.GetWeakPtr();
}
NetworkQualitiesPrefsManager::~NetworkQualitiesPrefsManager() {
DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
if (network_quality_estimator_)
network_quality_estimator_->RemoveNetworkQualitiesCacheObserver(this);
}
void NetworkQualitiesPrefsManager::InitializeOnNetworkThread(
NetworkQualityEstimator* network_quality_estimator) {
DCHECK(!network_task_runner_);
DCHECK(network_quality_estimator);
network_task_runner_ = base::ThreadTaskRunnerHandle::Get();
network_quality_estimator_ = network_quality_estimator;
network_quality_estimator_->AddNetworkQualitiesCacheObserver(this);
}
void NetworkQualitiesPrefsManager::OnChangeInCachedNetworkQuality(
const nqe::internal::NetworkID& network_id,
const nqe::internal::CachedNetworkQuality& cached_network_quality) {
DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
// Notify |this| on the pref thread.
pref_task_runner_->PostTask(
FROM_HERE,
base::Bind(&NetworkQualitiesPrefsManager::
OnChangeInCachedNetworkQualityOnPrefThread,
pref_weak_ptr_, network_id, cached_network_quality));
}
void NetworkQualitiesPrefsManager::ShutdownOnPrefThread() {
DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
pref_delegate_.reset();
}
void NetworkQualitiesPrefsManager::OnChangeInCachedNetworkQualityOnPrefThread(
const nqe::internal::NetworkID& network_id,
const nqe::internal::CachedNetworkQuality& cached_network_quality) {
// The prefs can only be written on the pref thread.
DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
base::DictionaryValue dictionary_value;
dictionary_value.SetString(
network_id.ToString(),
GetNameForEffectiveConnectionType(
cached_network_quality.effective_connection_type()));
// Notify the pref delegate so that it updates the prefs on the disk.
pref_delegate_->SetDictionaryValue(dictionary_value);
}
} // namespace net
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_NQE_NETWORK_QUALITIES_PREFS_MANAGER_H_
#define NET_NQE_NETWORK_QUALITIES_PREFS_MANAGER_H_
#include <memory>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "net/base/net_export.h"
#include "net/nqe/effective_connection_type.h"
#include "net/nqe/network_id.h"
#include "net/nqe/network_quality_store.h"
namespace base {
class DictionaryValue;
class SequencedTaskRunner;
}
namespace net {
namespace nqe {
namespace internal {
class CachedNetworkQuality;
}
}
class NetworkQualityEstimator;
typedef base::Callback<void(
const nqe::internal::NetworkID& network_id,
const nqe::internal::CachedNetworkQuality& cached_network_quality)>
OnChangeInCachedNetworkQualityCallback;
// Using the provided PrefDelegate, NetworkQualitiesPrefsManager creates and
// updates network quality information that is stored in prefs. Instances of
// this class must be constructed on the pref thread, and should later be moved
// to the network thread by calling InitializeOnNetworkThread.
//
// This class interacts with both the pref thread and the network thread, and
// propagates network quality pref changes from the network thread to the
// provided pref delegate on the pref thread.
//
// ShutdownOnPrefThread must be called from the pref thread before destruction.
class NET_EXPORT NetworkQualitiesPrefsManager
: public nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver {
public:
// Provides an interface that must be implemented by the embedder.
class NET_EXPORT PrefDelegate {
public:
// Sets the persistent pref to the given value.
virtual void SetDictionaryValue(const base::DictionaryValue& value) = 0;
};
// Creates an instance of the NetworkQualitiesPrefsManager. Ownership of
// |pref_delegate| is taken by this class. Must be constructed on the pref
// thread, and then moved to network thread.
explicit NetworkQualitiesPrefsManager(
std::unique_ptr<PrefDelegate> pref_delegate);
~NetworkQualitiesPrefsManager() override;
// Initialize on the Network thread.
void InitializeOnNetworkThread(
NetworkQualityEstimator* network_quality_estimator);
// Prepare for shutdown. Must be called on the pref thread before destruction.
void ShutdownOnPrefThread();
private:
// Pref thread members:
// Called on pref thread when there is a change in the cached network quality.
void OnChangeInCachedNetworkQualityOnPrefThread(
const nqe::internal::NetworkID& network_id,
const nqe::internal::CachedNetworkQuality& cached_network_quality);
// Responsible for writing the persistent prefs to the disk.
std::unique_ptr<PrefDelegate> pref_delegate_;
scoped_refptr<base::SequencedTaskRunner> pref_task_runner_;
// Should be accessed only on the pref thread.
base::WeakPtr<NetworkQualitiesPrefsManager> pref_weak_ptr_;
// Network thread members:
// nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver
// implementation:
void OnChangeInCachedNetworkQuality(
const nqe::internal::NetworkID& network_id,
const nqe::internal::CachedNetworkQuality& cached_network_quality)
override;
NetworkQualityEstimator* network_quality_estimator_;
scoped_refptr<base::SequencedTaskRunner> network_task_runner_;
// Used to get |weak_ptr_| to self on the pref thread.
base::WeakPtrFactory<NetworkQualitiesPrefsManager> pref_weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(NetworkQualitiesPrefsManager);
};
} // namespace net
#endif // NET_NQE_NETWORK_QUALITIES_PREFS_MANAGER_H_
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/nqe/network_qualities_prefs_manager.h"
#include <map>
#include <memory>
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/values.h"
#include "net/base/network_change_notifier.h"
#include "net/nqe/effective_connection_type.h"
#include "net/nqe/network_quality_estimator_test_util.h"
#include "net/nqe/network_quality_store.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace {
class MockPrefDelegate : public NetworkQualitiesPrefsManager::PrefDelegate {
public:
MockPrefDelegate() : write_count_(0) {}
~MockPrefDelegate() {}
void SetDictionaryValue(const base::DictionaryValue& value) override {
write_count_++;
}
size_t write_count() const { return write_count_; }
private:
// Number of times prefs were written.
mutable size_t write_count_;
DISALLOW_COPY_AND_ASSIGN(MockPrefDelegate);
};
TEST(NetworkQualitiesPrefManager, Write) {
std::map<std::string, std::string> variation_params;
TestNetworkQualityEstimator estimator(variation_params, nullptr);
std::unique_ptr<MockPrefDelegate> prefs_delegate(new MockPrefDelegate());
MockPrefDelegate* prefs_delegate_ptr = prefs_delegate.get();
NetworkQualitiesPrefsManager manager(std::move(prefs_delegate));
manager.InitializeOnNetworkThread(&estimator);
base::RunLoop().RunUntilIdle();
estimator.SimulateNetworkChange(
NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "test");
EXPECT_EQ(0u, prefs_delegate_ptr->write_count());
estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_2G);
// Run a request so that effective connection type is recomputed, and
// observers are notified of change in the network quality.
estimator.RunOneRequest();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, prefs_delegate_ptr->write_count());
estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_3G);
// Run a request so that effective connection type is recomputed, and
// observers are notified of change in the network quality..
estimator.RunOneRequest();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2u, prefs_delegate_ptr->write_count());
manager.ShutdownOnPrefThread();
}
} // namespace
} // namespace net
\ No newline at end of file
...@@ -1363,12 +1363,6 @@ NetworkQualityEstimator::GetRecentEffectiveConnectionTypeUsingMetrics( ...@@ -1363,12 +1363,6 @@ NetworkQualityEstimator::GetRecentEffectiveConnectionTypeUsingMetrics(
1); 1);
} }
nqe::internal::NetworkQualityStore*
NetworkQualityEstimator::NetworkQualityStoreForTesting() const {
DCHECK(thread_checker_.CalledOnValidThread());
return network_quality_store_.get();
}
void NetworkQualityEstimator::AddEffectiveConnectionTypeObserver( void NetworkQualityEstimator::AddEffectiveConnectionTypeObserver(
EffectiveConnectionTypeObserver* observer) { EffectiveConnectionTypeObserver* observer) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
...@@ -1717,4 +1711,18 @@ void NetworkQualityEstimator:: ...@@ -1717,4 +1711,18 @@ void NetworkQualityEstimator::
} }
} }
void NetworkQualityEstimator::AddNetworkQualitiesCacheObserver(
nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver*
observer) {
DCHECK(thread_checker_.CalledOnValidThread());
network_quality_store_->AddNetworkQualitiesCacheObserver(observer);
}
void NetworkQualityEstimator::RemoveNetworkQualitiesCacheObserver(
nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver*
observer) {
DCHECK(thread_checker_.CalledOnValidThread());
network_quality_store_->RemoveNetworkQualitiesCacheObserver(observer);
}
} // namespace net } // namespace net
...@@ -233,6 +233,14 @@ class NET_EXPORT NetworkQualityEstimator ...@@ -233,6 +233,14 @@ class NET_EXPORT NetworkQualityEstimator
void ReportEffectiveConnectionTypeForTesting( void ReportEffectiveConnectionTypeForTesting(
EffectiveConnectionType effective_connection_type); EffectiveConnectionType effective_connection_type);
// Adds and removes |observer| from the list of cache observers.
void AddNetworkQualitiesCacheObserver(
nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver*
observer);
void RemoveNetworkQualitiesCacheObserver(
nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver*
observer);
protected: protected:
// NetworkChangeNotifier::ConnectionTypeObserver implementation: // NetworkChangeNotifier::ConnectionTypeObserver implementation:
void OnConnectionTypeChanged( void OnConnectionTypeChanged(
...@@ -300,9 +308,6 @@ class NET_EXPORT NetworkQualityEstimator ...@@ -300,9 +308,6 @@ class NET_EXPORT NetworkQualityEstimator
// Returns a random double in the range [0.0, 1.0). Virtualized for testing. // Returns a random double in the range [0.0, 1.0). Virtualized for testing.
virtual double RandDouble() const; virtual double RandDouble() const;
// Returns a pointer to |network_quality_store_|. Used only for testing.
nqe::internal::NetworkQualityStore* NetworkQualityStoreForTesting() const;
private: private:
FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
AdaptiveRecomputationEffectiveConnectionType); AdaptiveRecomputationEffectiveConnectionType);
......
...@@ -150,7 +150,6 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator { ...@@ -150,7 +150,6 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator {
using NetworkQualityEstimator::SetTickClockForTesting; using NetworkQualityEstimator::SetTickClockForTesting;
using NetworkQualityEstimator::OnConnectionTypeChanged; using NetworkQualityEstimator::OnConnectionTypeChanged;
using NetworkQualityEstimator::NetworkQualityStoreForTesting;
private: private:
// NetworkQualityEstimator implementation that returns the overridden // NetworkQualityEstimator implementation that returns the overridden
......
...@@ -2003,8 +2003,7 @@ TEST(NetworkQualityEstimatorTest, CacheObserver) { ...@@ -2003,8 +2003,7 @@ TEST(NetworkQualityEstimatorTest, CacheObserver) {
TestNetworkQualityEstimator estimator(variation_params); TestNetworkQualityEstimator estimator(variation_params);
// Add |observer| as a persistent caching observer. // Add |observer| as a persistent caching observer.
estimator.NetworkQualityStoreForTesting()->AddNetworkQualitiesCacheObserver( estimator.AddNetworkQualitiesCacheObserver(&observer);
&observer);
estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_3G); estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_3G);
estimator.SimulateNetworkChange( estimator.SimulateNetworkChange(
...@@ -2037,8 +2036,7 @@ TEST(NetworkQualityEstimatorTest, CacheObserver) { ...@@ -2037,8 +2036,7 @@ TEST(NetworkQualityEstimatorTest, CacheObserver) {
EXPECT_EQ(1u, observer.get_notification_received_and_reset()); EXPECT_EQ(1u, observer.get_notification_received_and_reset());
// Remove |observer|, and it should not receive any notifications. // Remove |observer|, and it should not receive any notifications.
estimator.NetworkQualityStoreForTesting() estimator.RemoveNetworkQualitiesCacheObserver(&observer);
->RemoveNetworkQualitiesCacheObserver(&observer);
estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_3G); estimator.set_recent_effective_connection_type(EFFECTIVE_CONNECTION_TYPE_3G);
estimator.SimulateNetworkChange( estimator.SimulateNetworkChange(
NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test2g"); NetworkChangeNotifier::ConnectionType::CONNECTION_2G, "test2g");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment