mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-24 06:16:30 +03:00
176 lines
6.4 KiB
C++
176 lines
6.4 KiB
C++
// 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 <string>
|
|
#include <utility>
|
|
|
|
#include "base/bind.h"
|
|
#include "base/optional.h"
|
|
#include "base/rand_util.h"
|
|
#include "base/sequenced_task_runner.h"
|
|
#include "base/threading/thread_checker.h"
|
|
#include "base/threading/thread_task_runner_handle.h"
|
|
#include "net/nqe/network_quality_estimator.h"
|
|
|
|
namespace net {
|
|
|
|
namespace {
|
|
|
|
// Maximum size of the prefs that hold the qualities of different networks.
|
|
// A single entry in the cache consists of three tuples:
|
|
// (i) SSID or MCCMNC of the network. SSID is at most 32 characters in length
|
|
// (but is typically shorter than that). MCCMNC is at most 6 characters
|
|
// long.
|
|
// (ii) Connection type of the network as reported by network
|
|
// change notifier (an enum).
|
|
// (iii) Effective connection type of the network (an enum).
|
|
constexpr size_t kMaxCacheSize = 20u;
|
|
|
|
// Parses |value| into a map of NetworkIDs and CachedNetworkQualities,
|
|
// and returns the map.
|
|
ParsedPrefs ConvertDictionaryValueToMap(const base::DictionaryValue* value) {
|
|
DCHECK_GE(kMaxCacheSize, value->size());
|
|
|
|
ParsedPrefs read_prefs;
|
|
for (const auto& it : value->DictItems()) {
|
|
nqe::internal::NetworkID network_id =
|
|
nqe::internal::NetworkID::FromString(it.first);
|
|
|
|
std::string effective_connection_type_string;
|
|
const bool effective_connection_type_available =
|
|
it.second.GetAsString(&effective_connection_type_string);
|
|
DCHECK(effective_connection_type_available);
|
|
|
|
base::Optional<EffectiveConnectionType> effective_connection_type =
|
|
GetEffectiveConnectionTypeForName(effective_connection_type_string);
|
|
DCHECK(effective_connection_type.has_value());
|
|
|
|
nqe::internal::CachedNetworkQuality cached_network_quality(
|
|
effective_connection_type.value_or(EFFECTIVE_CONNECTION_TYPE_UNKNOWN));
|
|
read_prefs[network_id] = cached_network_quality;
|
|
}
|
|
return read_prefs;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
NetworkQualitiesPrefsManager::NetworkQualitiesPrefsManager(
|
|
std::unique_ptr<PrefDelegate> pref_delegate)
|
|
: pref_delegate_(std::move(pref_delegate)),
|
|
pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
|
prefs_(pref_delegate_->GetDictionaryValue()),
|
|
network_quality_estimator_(nullptr),
|
|
read_prefs_startup_(ConvertDictionaryValueToMap(prefs_.get())),
|
|
pref_weak_ptr_factory_(this) {
|
|
DCHECK(pref_delegate_);
|
|
DCHECK(pref_task_runner_);
|
|
DCHECK_GE(kMaxCacheSize, prefs_->size());
|
|
|
|
pref_weak_ptr_ = pref_weak_ptr_factory_.GetWeakPtr();
|
|
}
|
|
|
|
NetworkQualitiesPrefsManager::~NetworkQualitiesPrefsManager() {
|
|
if (!network_task_runner_)
|
|
return;
|
|
DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
|
|
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);
|
|
|
|
// Notify network quality estimator of the read prefs.
|
|
network_quality_estimator_->OnPrefsRead(read_prefs_startup_);
|
|
}
|
|
|
|
void NetworkQualitiesPrefsManager::OnChangeInCachedNetworkQuality(
|
|
const nqe::internal::NetworkID& network_id,
|
|
const nqe::internal::CachedNetworkQuality& cached_network_quality) {
|
|
DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
|
|
|
|
// Notify |this| on the pref thread.
|
|
pref_task_runner_->PostTask(
|
|
FROM_HERE,
|
|
base::Bind(&NetworkQualitiesPrefsManager::
|
|
OnChangeInCachedNetworkQualityOnPrefSequence,
|
|
pref_weak_ptr_, network_id, cached_network_quality));
|
|
}
|
|
|
|
void NetworkQualitiesPrefsManager::ShutdownOnPrefSequence() {
|
|
DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
|
|
pref_weak_ptr_factory_.InvalidateWeakPtrs();
|
|
pref_delegate_.reset();
|
|
}
|
|
|
|
void NetworkQualitiesPrefsManager::ClearPrefs() {
|
|
DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
|
|
prefs_->Clear();
|
|
DCHECK_EQ(0u, prefs_->size());
|
|
pref_delegate_->SetDictionaryValue(*prefs_);
|
|
}
|
|
|
|
void NetworkQualitiesPrefsManager::OnChangeInCachedNetworkQualityOnPrefSequence(
|
|
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_->RunsTasksInCurrentSequence());
|
|
DCHECK_GE(kMaxCacheSize, prefs_->size());
|
|
|
|
std::string network_id_string = network_id.ToString();
|
|
|
|
// If the network ID contains a period, then return early since the dictionary
|
|
// prefs cannot contain period in the path.
|
|
if (network_id_string.find('.') != std::string::npos)
|
|
return;
|
|
|
|
prefs_->SetString(network_id_string,
|
|
GetNameForEffectiveConnectionType(
|
|
cached_network_quality.effective_connection_type()));
|
|
|
|
if (prefs_->size() > kMaxCacheSize) {
|
|
// Delete one randomly selected value that has a key that is different from
|
|
// |network_id|.
|
|
DCHECK_EQ(kMaxCacheSize + 1, prefs_->size());
|
|
// Generate a random number in the range [0, |kMaxCacheSize| - 1] since the
|
|
// number of network IDs in |prefs_| other than |network_id| is
|
|
// |kMaxCacheSize|.
|
|
int index_to_delete = base::RandInt(0, kMaxCacheSize - 1);
|
|
|
|
for (const auto& it : prefs_->DictItems()) {
|
|
// Delete the kth element in the dictionary, not including the element
|
|
// that represents the current network. k == |index_to_delete|.
|
|
if (nqe::internal::NetworkID::FromString(it.first) == network_id)
|
|
continue;
|
|
|
|
if (index_to_delete == 0) {
|
|
prefs_->RemoveKey(it.first);
|
|
break;
|
|
}
|
|
index_to_delete--;
|
|
}
|
|
}
|
|
DCHECK_GE(kMaxCacheSize, prefs_->size());
|
|
|
|
// Notify the pref delegate so that it updates the prefs on the disk.
|
|
pref_delegate_->SetDictionaryValue(*prefs_);
|
|
}
|
|
|
|
ParsedPrefs NetworkQualitiesPrefsManager::ForceReadPrefsForTesting() const {
|
|
DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
|
|
std::unique_ptr<base::DictionaryValue> value(
|
|
pref_delegate_->GetDictionaryValue());
|
|
return ConvertDictionaryValueToMap(value.get());
|
|
}
|
|
|
|
} // namespace net
|