// Copyright 2014 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/sdch/sdch_owner.h"

#include <utility>

#include "base/bind.h"
#include "base/debug/alias.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/time/default_clock.h"
#include "base/values.h"
#include "net/base/sdch_manager.h"
#include "net/base/sdch_net_log_params.h"

namespace net {

namespace {

// Dictionaries that haven't been touched in 24 hours may be evicted
// to make room for new dictionaries.
const int kFreshnessLifetimeHours = 24;

// Dictionaries that have never been used only stay fresh for one hour.
const int kNeverUsedFreshnessLifetimeHours = 1;

void RecordPersistenceFailure(
    SdchOwner::PrefStorage::ReadError failure_reason) {
  UMA_HISTOGRAM_ENUMERATION(
      "Sdch3.PersistenceFailureReason", failure_reason,
      SdchOwner::PrefStorage::PERSISTENCE_FAILURE_REASON_MAX);
}

// Schema specifications and access routines.

// The persistent prefs store is conceptually shared with any other network
// stack systems that want to persist data over browser restarts, and so
// use of it must be namespace restricted.
// Schema:
//      pref_store_->GetValue() -> Dictionary {
//          'version' -> 2 [int]
//          'dictionaries' -> Dictionary {
//              server_hash -> {
//                  'url' -> URL [string]
//                  'last_used' -> seconds since unix epoch [double]
//                  'created_time' -> seconds since unix epoch [double]
//                  'use_count' -> use count [int]
//                  'size' -> size [int]
//          }
//      }
const char kVersionKey[] = "version";
const char kDictionariesKey[] = "dictionaries";
const char kDictionaryUrlKey[] = "url";
const char kDictionaryLastUsedKey[] = "last_used";
const char kDictionaryCreatedTimeKey[] = "created_time";
const char kDictionaryUseCountKey[] = "use_count";
const char kDictionarySizeKey[] = "size";

const int kVersion = 2;

// A simple implementation of pref storage that just stores the value in
// memory.
class ValueMapPrefStorage : public SdchOwner::PrefStorage {
 public:
  ValueMapPrefStorage() {}
  ~ValueMapPrefStorage() override {}

  ReadError GetReadError() const override { return PERSISTENCE_FAILURE_NONE; }

  bool GetValue(const base::DictionaryValue** result) const override {
    *result = &storage_;
    return true;
  }
  bool GetMutableValue(base::DictionaryValue** result) override {
    *result = &storage_;
    return true;
  }
  void SetValue(std::unique_ptr<base::DictionaryValue> value) override {
    storage_.Clear();
    storage_.MergeDictionary(value.get());
  }

  void ReportValueChanged() override {}

  // This storage class requires no special initialization.
  bool IsInitializationComplete() override { return true; }
  void StartObservingInit(SdchOwner* observer) override {}
  void StopObservingInit() override {}

 private:
  base::DictionaryValue storage_;

  DISALLOW_COPY_AND_ASSIGN(ValueMapPrefStorage);
};

// This function returns store[kPreferenceName/kDictionariesKey].  The caller
// is responsible for making sure any needed calls to
// |store->ReportValueChanged()| occur.
base::DictionaryValue* GetPersistentStoreDictionaryMap(
    SdchOwner::PrefStorage* store) {
  base::DictionaryValue* preference_dictionary = nullptr;
  bool success = store->GetMutableValue(&preference_dictionary);
  DCHECK(success);

  base::DictionaryValue* dictionary_list_dictionary = nullptr;
  success = preference_dictionary->GetDictionary(kDictionariesKey,
                                                 &dictionary_list_dictionary);
  DCHECK(success);
  DCHECK(dictionary_list_dictionary);

  return dictionary_list_dictionary;
}

// This function initializes a pref store with an empty version of the
// above schema, removing anything previously in the store under
// kPreferenceName.
void InitializePrefStore(SdchOwner::PrefStorage* store) {
  std::unique_ptr<base::DictionaryValue> empty_store(new base::DictionaryValue);
  empty_store->SetInteger(kVersionKey, kVersion);
  empty_store->Set(kDictionariesKey,
                   base::WrapUnique(new base::DictionaryValue));
  store->SetValue(std::move(empty_store));
}

// A class to allow iteration over all dictionaries in the pref store, and
// easy lookup of the information associated with those dictionaries.
// Note that this is an "Iterator" in the same sense (and for the same
// reasons) that base::Dictionary::Iterator is an iterator--it allows
// iterating over all the dictionaries in the preference store, but it
// does not allow use as an STL iterator because the container it
// is iterating over does not export begin()/end() methods. This iterator can
// only be safely used on sanitized pref stores that are known to conform to the
// pref store schema.
class DictionaryPreferenceIterator {
 public:
  explicit DictionaryPreferenceIterator(SdchOwner::PrefStorage* pref_store);

  bool IsAtEnd() const;
  void Advance();

  const std::string& server_hash() const { return server_hash_; }
  const GURL& url() const { return url_; }
  base::Time last_used() const { return last_used_; }
  base::Time created_time() const { return created_time_; }
  int use_count() const { return use_count_; }
  int size() const { return size_; }

 private:
  // Load Dictionary silently skipping any that are malformed.
  void LoadNextDictionary();
  // Try to load Dictionary from current iterator's position. Returns true if
  // succeeded.
  bool TryLoadDictionary();

  std::string server_hash_;
  GURL url_;
  base::Time last_used_;
  base::Time created_time_;
  int use_count_;
  int size_;

  base::DictionaryValue::Iterator dictionary_iterator_;
};

DictionaryPreferenceIterator::DictionaryPreferenceIterator(
    SdchOwner::PrefStorage* pref_store)
    : use_count_(0),
      size_(0),
      dictionary_iterator_(*GetPersistentStoreDictionaryMap(pref_store)) {
  LoadNextDictionary();
}

bool DictionaryPreferenceIterator::IsAtEnd() const {
  return dictionary_iterator_.IsAtEnd();
}

void DictionaryPreferenceIterator::Advance() {
  dictionary_iterator_.Advance();
  LoadNextDictionary();
}

void DictionaryPreferenceIterator::LoadNextDictionary() {
  while (!IsAtEnd()) {
    if (TryLoadDictionary())
      return;
    dictionary_iterator_.Advance();
  }
}

bool DictionaryPreferenceIterator::TryLoadDictionary() {
  const base::DictionaryValue* dict = nullptr;

  bool success = dictionary_iterator_.value().GetAsDictionary(&dict);
  if (!success)
    return false;

  server_hash_ = dictionary_iterator_.key();

  std::string url_spec;
  success = dict->GetString(kDictionaryUrlKey, &url_spec);
  if (!success)
    return false;
  url_ = GURL(url_spec);

  double last_used_seconds_from_epoch = 0;
  success =
      dict->GetDouble(kDictionaryLastUsedKey, &last_used_seconds_from_epoch);
  if (!success)
    return false;
  last_used_ = base::Time::FromDoubleT(last_used_seconds_from_epoch);

  success = dict->GetInteger(kDictionaryUseCountKey, &use_count_);
  if (!success)
    return false;

  success = dict->GetInteger(kDictionarySizeKey, &size_);
  if (!success)
    return false;

  double created_time_seconds = 0;
  success = dict->GetDouble(kDictionaryCreatedTimeKey, &created_time_seconds);
  if (!success)
    return false;
  created_time_ = base::Time::FromDoubleT(created_time_seconds);

  return true;
}

// Triggers a ReportValueChanged() when the object goes out of scope.
class ScopedPrefNotifier {
 public:
  // Caller must guarantee lifetime of |*pref_store| exceeds the
  // lifetime of this object.
  ScopedPrefNotifier(SdchOwner::PrefStorage* pref_store)
      : pref_store_(pref_store) {
    DCHECK(pref_store);
  }
  ~ScopedPrefNotifier() { pref_store_->ReportValueChanged(); }

 private:
  SdchOwner::PrefStorage* pref_store_;

  DISALLOW_COPY_AND_ASSIGN(ScopedPrefNotifier);
};

}  // namespace

// Adjust SDCH limits downwards for mobile.
#if defined(OS_ANDROID) || defined(OS_IOS)
// static
const size_t SdchOwner::kMaxTotalDictionarySize = 2 * 500 * 1000;
#else
// static
const size_t SdchOwner::kMaxTotalDictionarySize = 20 * 1000 * 1000;
#endif

SdchOwner::PrefStorage::~PrefStorage() {}

// Somewhat arbitrary, but we assume a dictionary smaller than
// 50K isn't going to do anyone any good.  Note that this still doesn't
// prevent download and addition unless there is less than this
// amount of space available in storage.
const size_t SdchOwner::kMinSpaceForDictionaryFetch = 50 * 1000;

void SdchOwner::RecordDictionaryFate(enum DictionaryFate fate) {
  UMA_HISTOGRAM_ENUMERATION("Sdch3.DictionaryFate", fate, DICTIONARY_FATE_MAX);
}

void SdchOwner::RecordDictionaryEvictionOrUnload(const std::string& server_hash,
                                                 size_t size,
                                                 int use_count,
                                                 DictionaryFate fate) {
  DCHECK(fate == DICTIONARY_FATE_EVICT_FOR_DICT ||
         fate == DICTIONARY_FATE_EVICT_FOR_MEMORY ||
         fate == DICTIONARY_FATE_EVICT_FOR_DESTRUCTION ||
         fate == DICTIONARY_FATE_UNLOAD_FOR_DESTRUCTION);

  UMA_HISTOGRAM_COUNTS_100("Sdch3.DictionaryUseCount", use_count);
  RecordDictionaryFate(fate);

  DCHECK(load_times_.count(server_hash) == 1);
  base::Time now = clock_->Now();
  base::TimeDelta dict_lifetime = now - load_times_[server_hash];
  consumed_byte_seconds_.push_back(size * dict_lifetime.InMilliseconds());
  load_times_.erase(server_hash);
}

SdchOwner::SdchOwner(SdchManager* sdch_manager, URLRequestContext* context)
    : manager_(sdch_manager),
      fetcher_(new SdchDictionaryFetcher(context)),
      total_dictionary_bytes_(0),
      clock_(new base::DefaultClock),
      max_total_dictionary_size_(kMaxTotalDictionarySize),
      min_space_for_dictionary_fetch_(kMinSpaceForDictionaryFetch),
      memory_pressure_listener_(
          base::Bind(&SdchOwner::OnMemoryPressure,
                     // Because |memory_pressure_listener_| is owned by
                     // SdchOwner, the SdchOwner object will be available
                     // for the lifetime of |memory_pressure_listener_|.
                     base::Unretained(this))),
      in_memory_pref_store_(new ValueMapPrefStorage()),
      external_pref_store_(nullptr),
      pref_store_(in_memory_pref_store_.get()),
      creation_time_(clock_->Now()) {
  manager_->AddObserver(this);
  InitializePrefStore(pref_store_);
}

SdchOwner::~SdchOwner() {
  for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd();
       it.Advance()) {
    int new_uses = it.use_count() - use_counts_at_load_[it.server_hash()];
    DictionaryFate fate = IsPersistingDictionaries() ?
                          DICTIONARY_FATE_UNLOAD_FOR_DESTRUCTION :
                          DICTIONARY_FATE_EVICT_FOR_DESTRUCTION;
    RecordDictionaryEvictionOrUnload(it.server_hash(), it.size(), new_uses,
                                     fate);
  }
  manager_->RemoveObserver(this);

  // This object only observes the external store during loading,
  // i.e. before it's made the default preferences store.
  if (external_pref_store_ && pref_store_ != external_pref_store_.get())
    external_pref_store_->StopObservingInit();

  int64_t object_lifetime = (clock_->Now() - creation_time_).InMilliseconds();
  for (const auto& val : consumed_byte_seconds_) {
    if (object_lifetime > 0) {
      // Objects that are created and immediately destroyed don't add any memory
      // pressure over time (and also cause a crash here).
      UMA_HISTOGRAM_MEMORY_KB("Sdch3.TimeWeightedMemoryUse",
                              val / object_lifetime);
    }
  }
}

void SdchOwner::EnablePersistentStorage(
    std::unique_ptr<PrefStorage> pref_store) {
  DCHECK(!external_pref_store_);
  DCHECK(pref_store);
  external_pref_store_ = std::move(pref_store);
  external_pref_store_->StartObservingInit(this);

  if (external_pref_store_->IsInitializationComplete())
    OnPrefStorageInitializationComplete(true);
}

void SdchOwner::SetMaxTotalDictionarySize(size_t max_total_dictionary_size) {
  max_total_dictionary_size_ = max_total_dictionary_size;
}

void SdchOwner::SetMinSpaceForDictionaryFetch(
    size_t min_space_for_dictionary_fetch) {
  min_space_for_dictionary_fetch_ = min_space_for_dictionary_fetch;
}

void SdchOwner::OnDictionaryFetched(base::Time last_used,
                                    base::Time created_time,
                                    int use_count,
                                    const std::string& dictionary_text,
                                    const GURL& dictionary_url,
                                    const BoundNetLog& net_log,
                                    bool was_from_cache) {
  struct DictionaryItem {
    base::Time last_used;
    std::string server_hash;
    int use_count;
    size_t dictionary_size;

    DictionaryItem() : use_count(0), dictionary_size(0) {}
    DictionaryItem(const base::Time& last_used,
                   const std::string& server_hash,
                   int use_count,
                   size_t dictionary_size)
        : last_used(last_used),
          server_hash(server_hash),
          use_count(use_count),
          dictionary_size(dictionary_size) {}
    DictionaryItem(const DictionaryItem& rhs) = default;
    DictionaryItem& operator=(const DictionaryItem& rhs) = default;
    bool operator<(const DictionaryItem& rhs) const {
      return last_used < rhs.last_used;
    }
  };

  if (!was_from_cache)
    UMA_HISTOGRAM_COUNTS("Sdch3.NetworkBytesSpent", dictionary_text.size());

  // Figure out if there is space for the incoming dictionary; evict
  // stale dictionaries if needed to make space.

  std::vector<DictionaryItem> stale_dictionary_list;
  size_t recoverable_bytes = 0;
  base::Time now(clock_->Now());
  // Dictionaries whose last used time is before |stale_boundary| are candidates
  // for eviction if necessary.
  base::Time stale_boundary(
      now - base::TimeDelta::FromHours(kFreshnessLifetimeHours));
  // Dictionaries that have never been used and are from before
  // |never_used_stale_boundary| are candidates for eviction if necessary.
  base::Time never_used_stale_boundary(
      now - base::TimeDelta::FromHours(kNeverUsedFreshnessLifetimeHours));
  for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd();
       it.Advance()) {
    if (it.last_used() < stale_boundary ||
        (it.use_count() == 0 && it.last_used() < never_used_stale_boundary)) {
      stale_dictionary_list.push_back(DictionaryItem(
          it.last_used(), it.server_hash(), it.use_count(), it.size()));
      recoverable_bytes += it.size();
    }
  }

  if (total_dictionary_bytes_ + dictionary_text.size() - recoverable_bytes >
      max_total_dictionary_size_) {
    RecordDictionaryFate(DICTIONARY_FATE_FETCH_IGNORED_NO_SPACE);
    SdchManager::SdchErrorRecovery(SDCH_DICTIONARY_NO_ROOM);
    net_log.AddEvent(NetLog::TYPE_SDCH_DICTIONARY_ERROR,
                     base::Bind(&NetLogSdchDictionaryFetchProblemCallback,
                                SDCH_DICTIONARY_NO_ROOM, dictionary_url, true));
    return;
  }

  // Add the new dictionary.  This is done before removing the stale
  // dictionaries so that no state change will occur if dictionary addition
  // fails.
  std::string server_hash;
  SdchProblemCode rv = manager_->AddSdchDictionary(
      dictionary_text, dictionary_url, &server_hash);
  if (rv != SDCH_OK) {
    RecordDictionaryFate(DICTIONARY_FATE_FETCH_MANAGER_REFUSED);
    SdchManager::SdchErrorRecovery(rv);
    net_log.AddEvent(NetLog::TYPE_SDCH_DICTIONARY_ERROR,
                     base::Bind(&NetLogSdchDictionaryFetchProblemCallback, rv,
                                dictionary_url, true));
    return;
  }

  base::DictionaryValue* pref_dictionary_map =
      GetPersistentStoreDictionaryMap(pref_store_);
  ScopedPrefNotifier scoped_pref_notifier(pref_store_);

  // Remove the old dictionaries.
  std::sort(stale_dictionary_list.begin(), stale_dictionary_list.end());
  size_t avail_bytes = max_total_dictionary_size_ - total_dictionary_bytes_;
  auto stale_it = stale_dictionary_list.begin();
  while (avail_bytes < dictionary_text.size() &&
         stale_it != stale_dictionary_list.end()) {
    manager_->RemoveSdchDictionary(stale_it->server_hash);

    DCHECK(pref_dictionary_map->HasKey(stale_it->server_hash));
    bool success = pref_dictionary_map->RemoveWithoutPathExpansion(
        stale_it->server_hash, nullptr);
    DCHECK(success);

    avail_bytes += stale_it->dictionary_size;

    int new_uses = stale_it->use_count -
        use_counts_at_load_[stale_it->server_hash];
    RecordDictionaryEvictionOrUnload(stale_it->server_hash,
                                     stale_it->dictionary_size,
                                     new_uses,
                                     DICTIONARY_FATE_EVICT_FOR_DICT);

    ++stale_it;
  }
  DCHECK_GE(avail_bytes, dictionary_text.size());

  RecordDictionaryFate(
      // Distinguish between loads triggered by network responses and
      // loads triggered by persistence.
      last_used.is_null() ? DICTIONARY_FATE_ADD_RESPONSE_TRIGGERED
                          : DICTIONARY_FATE_ADD_PERSISTENCE_TRIGGERED);

  // If a dictionary has never been used, its dictionary addition time
  // is recorded as its last used time.  Never used dictionaries are treated
  // specially in the freshness logic.
  if (last_used.is_null())
    last_used = clock_->Now();

  total_dictionary_bytes_ += dictionary_text.size();

  // Record the addition in the pref store.
  std::unique_ptr<base::DictionaryValue> dictionary_description(
      new base::DictionaryValue());
  dictionary_description->SetString(kDictionaryUrlKey, dictionary_url.spec());
  dictionary_description->SetDouble(kDictionaryLastUsedKey,
                                    last_used.ToDoubleT());
  dictionary_description->SetDouble(kDictionaryCreatedTimeKey,
                                    created_time.ToDoubleT());
  dictionary_description->SetInteger(kDictionaryUseCountKey, use_count);
  dictionary_description->SetInteger(kDictionarySizeKey,
                                     dictionary_text.size());
  pref_dictionary_map->Set(server_hash, std::move(dictionary_description));
  load_times_[server_hash] = clock_->Now();
}

void SdchOwner::OnDictionaryAdded(const GURL& dictionary_url,
                                  const std::string& server_hash) { }

void SdchOwner::OnDictionaryRemoved(const std::string& server_hash) { }

void SdchOwner::OnDictionaryUsed(const std::string& server_hash) {
  base::Time now(clock_->Now());
  base::DictionaryValue* pref_dictionary_map =
      GetPersistentStoreDictionaryMap(pref_store_);
  ScopedPrefNotifier scoped_pref_notifier(pref_store_);

  base::Value* value = nullptr;
  bool success = pref_dictionary_map->Get(server_hash, &value);
  if (!success) {
    // SdchManager::GetDictionarySet() pins the referenced dictionaries in
    // memory past a possible deletion.  For this reason, OnDictionaryUsed()
    // notifications may occur after SdchOwner thinks that dictionaries
    // have been deleted.
    SdchManager::SdchErrorRecovery(SDCH_DICTIONARY_USED_AFTER_DELETION);
    return;
  }
  base::DictionaryValue* specific_dictionary_map = nullptr;
  success = value->GetAsDictionary(&specific_dictionary_map);
  DCHECK(success);

  double last_used_seconds_since_epoch = 0.0;
  success = specific_dictionary_map->GetDouble(kDictionaryLastUsedKey,
                                               &last_used_seconds_since_epoch);
  DCHECK(success);
  int use_count = 0;
  success =
      specific_dictionary_map->GetInteger(kDictionaryUseCountKey, &use_count);
  DCHECK(success);

  if (use_counts_at_load_.count(server_hash) == 0) {
    use_counts_at_load_[server_hash] = use_count;
  }

  base::TimeDelta time_since_last_used(now -
      base::Time::FromDoubleT(last_used_seconds_since_epoch));

  if (use_count) {
    UMA_HISTOGRAM_CUSTOM_TIMES("Sdch3.UsageInterval2", time_since_last_used,
                               base::TimeDelta(), base::TimeDelta::FromDays(7),
                               50);
  } else {
    double created_time = 0;
    success = specific_dictionary_map->GetDouble(kDictionaryCreatedTimeKey,
                                                 &created_time);
    DCHECK(success);
    base::TimeDelta time_since_created(now -
                                       base::Time::FromDoubleT(created_time));
    UMA_HISTOGRAM_CUSTOM_TIMES("Sdch3.FirstUseInterval", time_since_created,
                               base::TimeDelta(), base::TimeDelta::FromDays(7),
                               50);
  }

  specific_dictionary_map->SetDouble(kDictionaryLastUsedKey, now.ToDoubleT());
  specific_dictionary_map->SetInteger(kDictionaryUseCountKey, use_count + 1);
}

void SdchOwner::OnGetDictionary(const GURL& request_url,
                                const GURL& dictionary_url) {
  base::Time stale_boundary(clock_->Now() - base::TimeDelta::FromDays(1));
  size_t avail_bytes = 0;
  for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd();
       it.Advance()) {
    if (it.last_used() < stale_boundary)
      avail_bytes += it.size();
  }

  // Don't initiate the fetch if we wouldn't be able to store any
  // reasonable dictionary.
  // TODO(rdsmith): Maybe do a HEAD request to figure out how much
  // storage we'd actually need?
  if (max_total_dictionary_size_ < (total_dictionary_bytes_ - avail_bytes +
                                    min_space_for_dictionary_fetch_)) {
    RecordDictionaryFate(DICTIONARY_FATE_GET_IGNORED);
    // TODO(rdsmith): Log a net-internals error.  This requires
    // SdchManager to forward the URLRequest that detected the
    // Get-Dictionary header to its observers, which is tricky
    // because SdchManager is layered underneath URLRequest.
    return;
  }

  fetcher_->Schedule(
      dictionary_url,
      base::Bind(&SdchOwner::OnDictionaryFetched,
                 // SdchOwner will outlive its member variables.
                 base::Unretained(this), base::Time(), base::Time::Now(), 0));
}

void SdchOwner::OnClearDictionaries() {
  total_dictionary_bytes_ = 0;
  fetcher_->Cancel();

  InitializePrefStore(pref_store_);
}

void SdchOwner::OnPrefStorageInitializationComplete(bool succeeded) {
  PrefStorage::ReadError error = external_pref_store_->GetReadError();
  // Errors on load are self-correcting; if dictionaries were not
  // persisted from the last instance of the browser, they will be
  // faulted in by user action over time.  However, if a load error
  // means that the dictionary information won't be able to be persisted,
  // the in memory pref store is left in place.
  if (!succeeded) {
    // Failure means a write failed, since read failures are recoverable.
    external_pref_store_->StopObservingInit();
    external_pref_store_ = nullptr;
    RecordPersistenceFailure(
        PrefStorage::PERSISTENCE_FAILURE_REASON_WRITE_FAILED);
    return;
  }

  if (error != PrefStorage::PERSISTENCE_FAILURE_NONE)
    RecordPersistenceFailure(error);

  // Load in what was stored before chrome exited previously.
  const base::DictionaryValue* sdch_persistence_dictionary = nullptr;

  // The GetPersistentStore() routine above assumes data formatted
  // according to the schema described at the top of this file.  Since
  // this data comes from disk, to avoid disk corruption resulting in
  // persistent chrome errors this code avoids those assupmtions.
  if (external_pref_store_->GetValue(&sdch_persistence_dictionary))
    SchedulePersistedDictionaryLoads(*sdch_persistence_dictionary);

  // Reset the persistent store and update it with the accumulated
  // information from the local store.
  InitializePrefStore(external_pref_store_.get());

  ScopedPrefNotifier scoped_pref_notifier(external_pref_store_.get());
  GetPersistentStoreDictionaryMap(external_pref_store_.get())
      ->Swap(GetPersistentStoreDictionaryMap(in_memory_pref_store_.get()));

  // This object can stop waiting on (i.e. observing) the external preference
  // store and switch over to using it as the primary preference store.
  pref_store_ = external_pref_store_.get();
  external_pref_store_->StopObservingInit();
  in_memory_pref_store_ = nullptr;
}

void SdchOwner::SetClockForTesting(std::unique_ptr<base::Clock> clock) {
  clock_ = std::move(clock);
}

int SdchOwner::GetDictionaryCountForTesting() const {
  int count = 0;
  for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd();
       it.Advance()) {
    count++;
  }
  return count;
}

bool SdchOwner::HasDictionaryFromURLForTesting(const GURL& url) const {
  for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd();
       it.Advance()) {
    if (it.url() == url)
      return true;
  }
  return false;
}

void SdchOwner::SetFetcherForTesting(
    std::unique_ptr<SdchDictionaryFetcher> fetcher) {
  fetcher_ = std::move(fetcher);
}

void SdchOwner::OnMemoryPressure(
    base::MemoryPressureListener::MemoryPressureLevel level) {
  DCHECK_NE(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, level);

  for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd();
       it.Advance()) {
    int new_uses = it.use_count() - use_counts_at_load_[it.server_hash()];
    RecordDictionaryEvictionOrUnload(it.server_hash(),
                                     it.size(),
                                     new_uses,
                                     DICTIONARY_FATE_EVICT_FOR_MEMORY);
  }

  // TODO(rdsmith): Make a distinction between moderate and critical
  // memory pressure.
  manager_->ClearData();
}

bool SdchOwner::SchedulePersistedDictionaryLoads(
    const base::DictionaryValue& persisted_info) {
  // Any schema error will result in dropping the persisted info.
  int version = 0;
  if (!persisted_info.GetInteger(kVersionKey, &version))
    return false;

  // Any version mismatch will result in dropping the persisted info;
  // it will be faulted in at small performance cost as URLs using
  // dictionaries for encoding are visited.
  if (version != kVersion)
    return false;

  const base::DictionaryValue* dictionary_set = nullptr;
  if (!persisted_info.GetDictionary(kDictionariesKey, &dictionary_set))
    return false;

  // Any formatting error will result in skipping that particular
  // dictionary.
  for (base::DictionaryValue::Iterator dict_it(*dictionary_set);
       !dict_it.IsAtEnd(); dict_it.Advance()) {
    const base::DictionaryValue* dict_info = nullptr;
    if (!dict_it.value().GetAsDictionary(&dict_info))
      continue;

    std::string url_string;
    if (!dict_info->GetString(kDictionaryUrlKey, &url_string))
      continue;
    GURL dict_url(url_string);

    double last_used = 0;
    if (!dict_info->GetDouble(kDictionaryLastUsedKey, &last_used))
      continue;

    int use_count = 0;
    if (!dict_info->GetInteger(kDictionaryUseCountKey, &use_count))
      continue;

    double created_time = 0;
    if (!dict_info->GetDouble(kDictionaryCreatedTimeKey, &created_time))
      continue;

    fetcher_->ScheduleReload(
        dict_url,
        base::Bind(&SdchOwner::OnDictionaryFetched,
                   // SdchOwner will outlive its member variables.
                   base::Unretained(this), base::Time::FromDoubleT(last_used),
                   base::Time::FromDoubleT(created_time), use_count));
  }

  return true;
}

bool SdchOwner::IsPersistingDictionaries() const {
  return in_memory_pref_store_.get() != nullptr;
}

}  // namespace net
