|  | // 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/host_cache_persistence_manager.h" | 
|  |  | 
|  | #include <memory> | 
|  |  | 
|  | #include "base/bind.h" | 
|  | #include "base/values.h" | 
|  | #include "components/prefs/pref_service.h" | 
|  | #include "net/log/net_log.h" | 
|  |  | 
|  | namespace cronet { | 
|  |  | 
|  | HostCachePersistenceManager::HostCachePersistenceManager( | 
|  | net::HostCache* cache, | 
|  | PrefService* pref_service, | 
|  | std::string pref_name, | 
|  | base::TimeDelta delay, | 
|  | net::NetLog* net_log) | 
|  | : cache_(cache), | 
|  | pref_service_(pref_service), | 
|  | pref_name_(pref_name), | 
|  | writing_pref_(false), | 
|  | delay_(delay), | 
|  | net_log_(net::NetLogWithSource::Make( | 
|  | net_log, | 
|  | net::NetLogSourceType::HOST_CACHE_PERSISTENCE_MANAGER)) { | 
|  | DCHECK(cache_); | 
|  | DCHECK(pref_service_); | 
|  |  | 
|  | // Get the initial value of the pref if it's already initialized. | 
|  | if (pref_service_->HasPrefPath(pref_name_)) | 
|  | ReadFromDisk(); | 
|  |  | 
|  | registrar_.Init(pref_service_); | 
|  | registrar_.Add(pref_name_, | 
|  | base::BindRepeating(&HostCachePersistenceManager::ReadFromDisk, | 
|  | weak_factory_.GetWeakPtr())); | 
|  | cache_->set_persistence_delegate(this); | 
|  | } | 
|  |  | 
|  | HostCachePersistenceManager::~HostCachePersistenceManager() { | 
|  | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 
|  |  | 
|  | timer_.Stop(); | 
|  | registrar_.RemoveAll(); | 
|  | cache_->set_persistence_delegate(nullptr); | 
|  | } | 
|  |  | 
|  | void HostCachePersistenceManager::ReadFromDisk() { | 
|  | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 
|  |  | 
|  | if (writing_pref_) | 
|  | return; | 
|  |  | 
|  | net_log_.BeginEvent(net::NetLogEventType::HOST_CACHE_PREF_READ); | 
|  | const base::Value::List& pref_value = pref_service_->GetValueList(pref_name_); | 
|  | bool success = cache_->RestoreFromListValue(pref_value); | 
|  | net_log_.AddEntryWithBoolParams(net::NetLogEventType::HOST_CACHE_PREF_READ, | 
|  | net::NetLogEventPhase::END, "success", | 
|  | success); | 
|  | } | 
|  |  | 
|  | void HostCachePersistenceManager::ScheduleWrite() { | 
|  | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 
|  |  | 
|  | if (timer_.IsRunning()) | 
|  | return; | 
|  |  | 
|  | net_log_.AddEvent(net::NetLogEventType::HOST_CACHE_PERSISTENCE_START_TIMER); | 
|  | timer_.Start(FROM_HERE, delay_, | 
|  | base::BindOnce(&HostCachePersistenceManager::WriteToDisk, | 
|  | weak_factory_.GetWeakPtr())); | 
|  | } | 
|  |  | 
|  | void HostCachePersistenceManager::WriteToDisk() { | 
|  | DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); | 
|  |  | 
|  | net_log_.AddEvent(net::NetLogEventType::HOST_CACHE_PREF_WRITE); | 
|  | base::Value::List list; | 
|  | cache_->GetList(list, false, net::HostCache::SerializationType::kRestorable); | 
|  | writing_pref_ = true; | 
|  | pref_service_->SetList(pref_name_, std::move(list)); | 
|  | writing_pref_ = false; | 
|  | } | 
|  |  | 
|  | }  // namespace cronet |