123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- // Copyright 2017 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 "components/cronet/cronet_prefs_manager.h"
- #include <memory>
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/files/file_path.h"
- #include "base/files/file_util.h"
- #include "base/location.h"
- #include "base/memory/raw_ptr.h"
- #include "base/metrics/histogram_macros.h"
- #include "base/threading/sequenced_task_runner_handle.h"
- #include "base/threading/thread_restrictions.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "base/time/time.h"
- #include "build/build_config.h"
- #include "components/cronet/host_cache_persistence_manager.h"
- #include "components/prefs/json_pref_store.h"
- #include "components/prefs/pref_change_registrar.h"
- #include "components/prefs/pref_registry_simple.h"
- #include "components/prefs/pref_service.h"
- #include "components/prefs/pref_service_factory.h"
- #include "net/http/http_server_properties.h"
- #include "net/nqe/network_qualities_prefs_manager.h"
- #include "net/url_request/url_request_context_builder.h"
- namespace cronet {
- namespace {
- // Name of the pref used for HTTP server properties persistence.
- const char kHttpServerPropertiesPref[] = "net.http_server_properties";
- // Name of preference directory.
- const base::FilePath::CharType kPrefsDirectoryName[] =
- FILE_PATH_LITERAL("prefs");
- // Name of preference file.
- const base::FilePath::CharType kPrefsFileName[] =
- FILE_PATH_LITERAL("local_prefs.json");
- // Current version of disk storage.
- const int32_t kStorageVersion = 1;
- // Version number used when the version of disk storage is unknown.
- const uint32_t kStorageVersionUnknown = 0;
- // Name of the pref used for host cache persistence.
- const char kHostCachePref[] = "net.host_cache";
- // Name of the pref used for NQE persistence.
- const char kNetworkQualitiesPref[] = "net.network_qualities";
- bool IsCurrentVersion(const base::FilePath& version_filepath) {
- if (!base::PathExists(version_filepath))
- return false;
- base::File version_file(version_filepath,
- base::File::FLAG_OPEN | base::File::FLAG_READ);
- uint32_t version = kStorageVersionUnknown;
- int bytes_read =
- version_file.Read(0, reinterpret_cast<char*>(&version), sizeof(version));
- if (bytes_read != sizeof(version)) {
- DLOG(WARNING) << "Cannot read from version file.";
- return false;
- }
- return version == kStorageVersion;
- }
- // TODO(xunjieli): Handle failures.
- void InitializeStorageDirectory(const base::FilePath& dir) {
- // Checks version file and clear old storage.
- base::FilePath version_filepath(dir.AppendASCII("version"));
- if (IsCurrentVersion(version_filepath)) {
- // The version is up to date, so there is nothing to do.
- return;
- }
- // Delete old directory recursively and create a new directory.
- // base::DeletePathRecursively() returns true if the directory does not exist,
- // so it is fine if there is nothing on disk.
- if (!(base::DeletePathRecursively(dir) && base::CreateDirectory(dir))) {
- DLOG(WARNING) << "Cannot purge directory.";
- return;
- }
- base::File new_version_file(version_filepath, base::File::FLAG_CREATE_ALWAYS |
- base::File::FLAG_WRITE);
- if (!new_version_file.IsValid()) {
- DLOG(WARNING) << "Cannot create a version file.";
- return;
- }
- DCHECK(new_version_file.created());
- uint32_t new_version = kStorageVersion;
- int bytes_written = new_version_file.Write(
- 0, reinterpret_cast<char*>(&new_version), sizeof(new_version));
- if (bytes_written != sizeof(new_version)) {
- DLOG(WARNING) << "Cannot write to version file.";
- return;
- }
- base::FilePath prefs_dir = dir.Append(kPrefsDirectoryName);
- if (!base::CreateDirectory(prefs_dir)) {
- DLOG(WARNING) << "Cannot create prefs directory";
- return;
- }
- }
- // Connects the HttpServerProperties's storage to the prefs.
- class PrefServiceAdapter : public net::HttpServerProperties::PrefDelegate {
- public:
- explicit PrefServiceAdapter(PrefService* pref_service)
- : pref_service_(pref_service), path_(kHttpServerPropertiesPref) {
- pref_change_registrar_.Init(pref_service_);
- }
- PrefServiceAdapter(const PrefServiceAdapter&) = delete;
- PrefServiceAdapter& operator=(const PrefServiceAdapter&) = delete;
- ~PrefServiceAdapter() override {}
- // PrefDelegate implementation.
- const base::Value* GetServerProperties() const override {
- return &pref_service_->GetValue(path_);
- }
- void SetServerProperties(const base::Value& value,
- base::OnceClosure callback) override {
- pref_service_->Set(path_, value);
- if (callback)
- pref_service_->CommitPendingWrite(std::move(callback));
- }
- void WaitForPrefLoad(base::OnceClosure callback) override {
- // Notify the pref manager that settings are already loaded, as a result
- // of initializing the pref store synchronously.
- base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- std::move(callback));
- }
- private:
- raw_ptr<PrefService> pref_service_;
- const std::string path_;
- PrefChangeRegistrar pref_change_registrar_;
- }; // class PrefServiceAdapter
- class NetworkQualitiesPrefDelegateImpl
- : public net::NetworkQualitiesPrefsManager::PrefDelegate {
- public:
- // Caller must guarantee that |pref_service| outlives |this|.
- explicit NetworkQualitiesPrefDelegateImpl(PrefService* pref_service)
- : pref_service_(pref_service), lossy_prefs_writing_task_posted_(false) {
- DCHECK(pref_service_);
- }
- NetworkQualitiesPrefDelegateImpl(const NetworkQualitiesPrefDelegateImpl&) =
- delete;
- NetworkQualitiesPrefDelegateImpl& operator=(
- const NetworkQualitiesPrefDelegateImpl&) = delete;
- ~NetworkQualitiesPrefDelegateImpl() override {}
- // net::NetworkQualitiesPrefsManager::PrefDelegate implementation.
- void SetDictionaryValue(const base::Value::Dict& dict) override {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- pref_service_->SetDict(kNetworkQualitiesPref, dict.Clone());
- if (lossy_prefs_writing_task_posted_)
- return;
- // Post the task that schedules the writing of the lossy prefs.
- lossy_prefs_writing_task_posted_ = true;
- // Delay after which the task that schedules the writing of the lossy prefs.
- // This is needed in case the writing of the lossy prefs is not scheduled
- // automatically. The delay was chosen so that it is large enough that it
- // does not affect the startup performance.
- static const int32_t kUpdatePrefsDelaySeconds = 10;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(
- &NetworkQualitiesPrefDelegateImpl::SchedulePendingLossyWrites,
- weak_ptr_factory_.GetWeakPtr()),
- base::Seconds(kUpdatePrefsDelaySeconds));
- }
- base::Value::Dict GetDictionaryValue() override {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- UMA_HISTOGRAM_EXACT_LINEAR("NQE.Prefs.ReadCount", 1, 2);
- return pref_service_->GetValueDict(kNetworkQualitiesPref).Clone();
- }
- private:
- // Schedules the writing of the lossy prefs.
- void SchedulePendingLossyWrites() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- UMA_HISTOGRAM_EXACT_LINEAR("NQE.Prefs.WriteCount", 1, 2);
- pref_service_->SchedulePendingLossyWrites();
- lossy_prefs_writing_task_posted_ = false;
- }
- raw_ptr<PrefService> pref_service_;
- // True if the task that schedules the writing of the lossy prefs has been
- // posted.
- bool lossy_prefs_writing_task_posted_;
- THREAD_CHECKER(thread_checker_);
- base::WeakPtrFactory<NetworkQualitiesPrefDelegateImpl> weak_ptr_factory_{
- this};
- };
- } // namespace
- CronetPrefsManager::CronetPrefsManager(
- const std::string& storage_path,
- scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
- scoped_refptr<base::SequencedTaskRunner> file_task_runner,
- bool enable_network_quality_estimator,
- bool enable_host_cache_persistence,
- net::NetLog* net_log,
- net::URLRequestContextBuilder* context_builder) {
- DCHECK(network_task_runner->BelongsToCurrentThread());
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- #if BUILDFLAG(IS_WIN)
- base::FilePath storage_file_path(
- base::FilePath::FromUTF8Unsafe(storage_path));
- #else
- base::FilePath storage_file_path(storage_path);
- #endif
- // Make sure storage directory has correct version.
- {
- base::ScopedAllowBlocking allow_blocking;
- InitializeStorageDirectory(storage_file_path);
- }
- base::FilePath filepath =
- storage_file_path.Append(kPrefsDirectoryName).Append(kPrefsFileName);
- json_pref_store_ = new JsonPrefStore(filepath, std::unique_ptr<PrefFilter>(),
- file_task_runner);
- // Register prefs and set up the PrefService.
- PrefServiceFactory factory;
- factory.set_user_prefs(json_pref_store_);
- scoped_refptr<PrefRegistrySimple> registry(new PrefRegistrySimple());
- registry->RegisterDictionaryPref(kHttpServerPropertiesPref);
- if (enable_network_quality_estimator) {
- // Use lossy prefs to limit the overhead of reading/writing the prefs.
- registry->RegisterDictionaryPref(kNetworkQualitiesPref,
- PrefRegistry::LOSSY_PREF);
- }
- if (enable_host_cache_persistence) {
- registry->RegisterListPref(kHostCachePref);
- }
- {
- base::ScopedAllowBlocking allow_blocking;
- pref_service_ = factory.Create(registry.get());
- }
- context_builder->SetHttpServerProperties(
- std::make_unique<net::HttpServerProperties>(
- std::make_unique<PrefServiceAdapter>(pref_service_.get()), net_log));
- }
- CronetPrefsManager::~CronetPrefsManager() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- }
- void CronetPrefsManager::SetupNqePersistence(
- net::NetworkQualityEstimator* nqe) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- network_qualities_prefs_manager_ =
- std::make_unique<net::NetworkQualitiesPrefsManager>(
- std::make_unique<NetworkQualitiesPrefDelegateImpl>(
- pref_service_.get()));
- network_qualities_prefs_manager_->InitializeOnNetworkThread(nqe);
- }
- void CronetPrefsManager::SetupHostCachePersistence(
- net::HostCache* host_cache,
- int host_cache_persistence_delay_ms,
- net::NetLog* net_log) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- host_cache_persistence_manager_ =
- std::make_unique<HostCachePersistenceManager>(
- host_cache, pref_service_.get(), kHostCachePref,
- base::Milliseconds(host_cache_persistence_delay_ms), net_log);
- }
- void CronetPrefsManager::PrepareForShutdown() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (pref_service_)
- pref_service_->CommitPendingWrite();
- // Shutdown managers on the Pref sequence.
- if (network_qualities_prefs_manager_)
- network_qualities_prefs_manager_->ShutdownOnPrefSequence();
- host_cache_persistence_manager_.reset();
- }
- } // namespace cronet
|