// 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/http/http_server_properties_manager.h"

#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
#include "base/prefs/pref_service.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/thread_task_runner_handle.h"
#include "base/values.h"
#include "net/base/ip_address_number.h"
#include "net/base/port_util.h"

namespace net {

namespace {

// Time to wait before starting an update the http_server_properties_impl_ cache
// from preferences. Scheduling another update during this period will reset the
// timer.
const int64 kUpdateCacheDelayMs = 1000;

// Time to wait before starting an update the preferences from the
// http_server_properties_impl_ cache. Scheduling another update during this
// period will reset the timer.
const int64 kUpdatePrefsDelayMs = 60000;

// "version" 0 indicates, http_server_properties doesn't have "version"
// property.
const int kMissingVersion = 0;

// The version number of persisted http_server_properties.
const int kVersionNumber = 3;

typedef std::vector<std::string> StringVector;

// Persist 200 MRU AlternateProtocolHostPortPairs.
const int kMaxAlternateProtocolHostsToPersist = 200;

// Persist 200 MRU SpdySettingsHostPortPairs.
const int kMaxSpdySettingsHostsToPersist = 200;

// Persist 300 MRU SupportsSpdyServerHostPortPairs.
const int kMaxSupportsSpdyServerHostsToPersist = 300;

// Persist 200 ServerNetworkStats.
const int kMaxServerNetworkStatsHostsToPersist = 200;

const char kVersionKey[] = "version";
const char kServersKey[] = "servers";
const char kSupportsSpdyKey[] = "supports_spdy";
const char kSettingsKey[] = "settings";
const char kSupportsQuicKey[] = "supports_quic";
const char kUsedQuicKey[] = "used_quic";
const char kAddressKey[] = "address";
const char kAlternateProtocolKey[] = "alternate_protocol";
const char kAlternativeServiceKey[] = "alternative_service";
const char kProtocolKey[] = "protocol_str";
const char kHostKey[] = "host";
const char kPortKey[] = "port";
const char kProbabilityKey[] = "probability";
const char kExpirationKey[] = "expiration";
const char kNetworkStatsKey[] = "network_stats";
const char kSrttKey[] = "srtt";

}  // namespace

////////////////////////////////////////////////////////////////////////////////
//  HttpServerPropertiesManager

HttpServerPropertiesManager::HttpServerPropertiesManager(
    PrefService* pref_service,
    const char* pref_path,
    scoped_refptr<base::SequencedTaskRunner> network_task_runner)
    : pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
      pref_service_(pref_service),
      setting_prefs_(false),
      path_(pref_path),
      network_task_runner_(network_task_runner) {
  DCHECK(pref_service);
  pref_weak_ptr_factory_.reset(
      new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
  pref_weak_ptr_ = pref_weak_ptr_factory_->GetWeakPtr();
  pref_cache_update_timer_.reset(
      new base::OneShotTimer<HttpServerPropertiesManager>);
  pref_change_registrar_.Init(pref_service_);
  pref_change_registrar_.Add(
      path_,
      base::Bind(&HttpServerPropertiesManager::OnHttpServerPropertiesChanged,
                 base::Unretained(this)));
}

HttpServerPropertiesManager::~HttpServerPropertiesManager() {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  network_weak_ptr_factory_.reset();
}

void HttpServerPropertiesManager::InitializeOnNetworkThread() {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  network_weak_ptr_factory_.reset(
      new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
  http_server_properties_impl_.reset(new HttpServerPropertiesImpl());

  network_prefs_update_timer_.reset(
      new base::OneShotTimer<HttpServerPropertiesManager>);

  pref_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread,
                 pref_weak_ptr_));
}

void HttpServerPropertiesManager::ShutdownOnPrefThread() {
  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
  // Cancel any pending updates, and stop listening for pref change updates.
  pref_cache_update_timer_->Stop();
  pref_weak_ptr_factory_.reset();
  pref_change_registrar_.RemoveAll();
}

// static
void HttpServerPropertiesManager::SetVersion(
    base::DictionaryValue* http_server_properties_dict,
    int version_number) {
  if (version_number < 0)
    version_number = kVersionNumber;
  DCHECK_LE(version_number, kVersionNumber);
  if (version_number <= kVersionNumber)
    http_server_properties_dict->SetInteger(kVersionKey, version_number);
}

// This is required for conformance with the HttpServerProperties interface.
base::WeakPtr<HttpServerProperties> HttpServerPropertiesManager::GetWeakPtr() {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return network_weak_ptr_factory_->GetWeakPtr();
}

void HttpServerPropertiesManager::Clear() {
  Clear(base::Closure());
}

void HttpServerPropertiesManager::Clear(const base::Closure& completion) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());

  http_server_properties_impl_->Clear();
  UpdatePrefsFromCacheOnNetworkThread(completion);
}

bool HttpServerPropertiesManager::SupportsRequestPriority(
    const HostPortPair& server) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return http_server_properties_impl_->SupportsRequestPriority(server);
}

bool HttpServerPropertiesManager::GetSupportsSpdy(const HostPortPair& server) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return http_server_properties_impl_->GetSupportsSpdy(server);
}

void HttpServerPropertiesManager::SetSupportsSpdy(const HostPortPair& server,
                                                  bool support_spdy) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());

  bool old_support_spdy = http_server_properties_impl_->GetSupportsSpdy(server);
  http_server_properties_impl_->SetSupportsSpdy(server, support_spdy);
  bool new_support_spdy = http_server_properties_impl_->GetSupportsSpdy(server);
  if (old_support_spdy != new_support_spdy)
    ScheduleUpdatePrefsOnNetworkThread(SUPPORTS_SPDY);
}

bool HttpServerPropertiesManager::RequiresHTTP11(const HostPortPair& server) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return http_server_properties_impl_->RequiresHTTP11(server);
}

void HttpServerPropertiesManager::SetHTTP11Required(
    const HostPortPair& server) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());

  http_server_properties_impl_->SetHTTP11Required(server);
  ScheduleUpdatePrefsOnNetworkThread(HTTP_11_REQUIRED);
}

void HttpServerPropertiesManager::MaybeForceHTTP11(const HostPortPair& server,
                                                   SSLConfig* ssl_config) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  http_server_properties_impl_->MaybeForceHTTP11(server, ssl_config);
}

AlternativeServiceVector HttpServerPropertiesManager::GetAlternativeServices(
    const HostPortPair& origin) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return http_server_properties_impl_->GetAlternativeServices(origin);
}

bool HttpServerPropertiesManager::SetAlternativeService(
    const HostPortPair& origin,
    const AlternativeService& alternative_service,
    double alternative_probability,
    base::Time expiration) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  const bool changed = http_server_properties_impl_->SetAlternativeService(
      origin, alternative_service, alternative_probability, expiration);
  if (changed) {
    ScheduleUpdatePrefsOnNetworkThread(SET_ALTERNATIVE_SERVICES);
  }
  return changed;
}

bool HttpServerPropertiesManager::SetAlternativeServices(
    const HostPortPair& origin,
    const AlternativeServiceInfoVector& alternative_service_info_vector) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  const bool changed = http_server_properties_impl_->SetAlternativeServices(
      origin, alternative_service_info_vector);
  if (changed) {
    ScheduleUpdatePrefsOnNetworkThread(SET_ALTERNATIVE_SERVICES);
  }
  return changed;
}

void HttpServerPropertiesManager::MarkAlternativeServiceBroken(
    const AlternativeService& alternative_service) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  http_server_properties_impl_->MarkAlternativeServiceBroken(
      alternative_service);
  ScheduleUpdatePrefsOnNetworkThread(MARK_ALTERNATIVE_SERVICE_BROKEN);
}

void HttpServerPropertiesManager::MarkAlternativeServiceRecentlyBroken(
    const AlternativeService& alternative_service) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  http_server_properties_impl_->MarkAlternativeServiceRecentlyBroken(
      alternative_service);
  ScheduleUpdatePrefsOnNetworkThread(MARK_ALTERNATIVE_SERVICE_RECENTLY_BROKEN);
}

bool HttpServerPropertiesManager::IsAlternativeServiceBroken(
    const AlternativeService& alternative_service) const {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return http_server_properties_impl_->IsAlternativeServiceBroken(
      alternative_service);
}

bool HttpServerPropertiesManager::WasAlternativeServiceRecentlyBroken(
    const AlternativeService& alternative_service) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return http_server_properties_impl_->WasAlternativeServiceRecentlyBroken(
      alternative_service);
}

void HttpServerPropertiesManager::ConfirmAlternativeService(
    const AlternativeService& alternative_service) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  bool old_value = http_server_properties_impl_->IsAlternativeServiceBroken(
      alternative_service);
  http_server_properties_impl_->ConfirmAlternativeService(alternative_service);
  bool new_value = http_server_properties_impl_->IsAlternativeServiceBroken(
      alternative_service);
  // For persisting, we only care about the value returned by
  // IsAlternativeServiceBroken. If that value changes, then call persist.
  if (old_value != new_value)
    ScheduleUpdatePrefsOnNetworkThread(CONFIRM_ALTERNATIVE_SERVICE);
}

void HttpServerPropertiesManager::ClearAlternativeServices(
    const HostPortPair& origin) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  const AlternativeServiceMap& map =
      http_server_properties_impl_->alternative_service_map();
  size_t old_size = map.size();
  http_server_properties_impl_->ClearAlternativeServices(origin);
  size_t new_size = map.size();
  // Persist only if we have deleted an entry.
  if (old_size != new_size)
    ScheduleUpdatePrefsOnNetworkThread(CLEAR_ALTERNATIVE_SERVICE);
}

const AlternativeServiceMap&
HttpServerPropertiesManager::alternative_service_map() const {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return http_server_properties_impl_->alternative_service_map();
}

scoped_ptr<base::Value>
HttpServerPropertiesManager::GetAlternativeServiceInfoAsValue()
    const {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return http_server_properties_impl_->GetAlternativeServiceInfoAsValue();
}

void HttpServerPropertiesManager::SetAlternativeServiceProbabilityThreshold(
    double threshold) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  http_server_properties_impl_->SetAlternativeServiceProbabilityThreshold(
      threshold);
}

const SettingsMap& HttpServerPropertiesManager::GetSpdySettings(
    const HostPortPair& host_port_pair) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return http_server_properties_impl_->GetSpdySettings(host_port_pair);
}

bool HttpServerPropertiesManager::SetSpdySetting(
    const HostPortPair& host_port_pair,
    SpdySettingsIds id,
    SpdySettingsFlags flags,
    uint32 value) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  bool persist = http_server_properties_impl_->SetSpdySetting(
      host_port_pair, id, flags, value);
  if (persist)
    ScheduleUpdatePrefsOnNetworkThread(SET_SPDY_SETTING);
  return persist;
}

void HttpServerPropertiesManager::ClearSpdySettings(
    const HostPortPair& host_port_pair) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  http_server_properties_impl_->ClearSpdySettings(host_port_pair);
  ScheduleUpdatePrefsOnNetworkThread(CLEAR_SPDY_SETTINGS);
}

void HttpServerPropertiesManager::ClearAllSpdySettings() {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  http_server_properties_impl_->ClearAllSpdySettings();
  ScheduleUpdatePrefsOnNetworkThread(CLEAR_ALL_SPDY_SETTINGS);
}

const SpdySettingsMap& HttpServerPropertiesManager::spdy_settings_map()
    const {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return http_server_properties_impl_->spdy_settings_map();
}

bool HttpServerPropertiesManager::GetSupportsQuic(
    IPAddressNumber* last_address) const {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return http_server_properties_impl_->GetSupportsQuic(last_address);
}

void HttpServerPropertiesManager::SetSupportsQuic(
    bool used_quic,
    const IPAddressNumber& address) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  IPAddressNumber old_last_quic_addr;
  http_server_properties_impl_->GetSupportsQuic(&old_last_quic_addr);
  http_server_properties_impl_->SetSupportsQuic(used_quic, address);
  IPAddressNumber new_last_quic_addr;
  http_server_properties_impl_->GetSupportsQuic(&new_last_quic_addr);
  if (old_last_quic_addr != new_last_quic_addr)
    ScheduleUpdatePrefsOnNetworkThread(SET_SUPPORTS_QUIC);
}

void HttpServerPropertiesManager::SetServerNetworkStats(
    const HostPortPair& host_port_pair,
    ServerNetworkStats stats) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  ServerNetworkStats old_stats;
  const ServerNetworkStats* old_stats_ptr =
      http_server_properties_impl_->GetServerNetworkStats(host_port_pair);
  if (http_server_properties_impl_->GetServerNetworkStats(host_port_pair))
    old_stats = *old_stats_ptr;
  http_server_properties_impl_->SetServerNetworkStats(host_port_pair, stats);
  ServerNetworkStats new_stats =
      *(http_server_properties_impl_->GetServerNetworkStats(host_port_pair));
  if (old_stats != new_stats)
    ScheduleUpdatePrefsOnNetworkThread(SET_SERVER_NETWORK_STATS);
}

const ServerNetworkStats* HttpServerPropertiesManager::GetServerNetworkStats(
    const HostPortPair& host_port_pair) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return http_server_properties_impl_->GetServerNetworkStats(host_port_pair);
}

const ServerNetworkStatsMap&
HttpServerPropertiesManager::server_network_stats_map() const {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  return http_server_properties_impl_->server_network_stats_map();
}

//
// Update the HttpServerPropertiesImpl's cache with data from preferences.
//
void HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread() {
  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
  // Cancel pending updates, if any.
  pref_cache_update_timer_->Stop();
  StartCacheUpdateTimerOnPrefThread(
      base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs));
}

void HttpServerPropertiesManager::StartCacheUpdateTimerOnPrefThread(
    base::TimeDelta delay) {
  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
  pref_cache_update_timer_->Start(
      FROM_HERE,
      delay,
      this,
      &HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread);
}

void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread() {
  // The preferences can only be read on the pref thread.
  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());

  if (!pref_service_->HasPrefPath(path_))
    return;

  bool detected_corrupted_prefs = false;
  const base::DictionaryValue& http_server_properties_dict =
      *pref_service_->GetDictionary(path_);

  int version = kMissingVersion;
  if (!http_server_properties_dict.GetIntegerWithoutPathExpansion(kVersionKey,
                                                                  &version)) {
    DVLOG(1) << "Missing version. Clearing all properties.";
    return;
  }

  // The properties for a given server is in
  // http_server_properties_dict["servers"][server].
  const base::DictionaryValue* servers_dict = NULL;
  if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion(
          kServersKey, &servers_dict)) {
    DVLOG(1) << "Malformed http_server_properties for servers.";
    return;
  }

  IPAddressNumber* addr = new IPAddressNumber;
  ReadSupportsQuic(http_server_properties_dict, addr);

  // String is host/port pair of spdy server.
  scoped_ptr<StringVector> spdy_servers(new StringVector);
  scoped_ptr<SpdySettingsMap> spdy_settings_map(
      new SpdySettingsMap(kMaxSpdySettingsHostsToPersist));
  scoped_ptr<AlternativeServiceMap> alternative_service_map(
      new AlternativeServiceMap(kMaxAlternateProtocolHostsToPersist));
  scoped_ptr<ServerNetworkStatsMap> server_network_stats_map(
      new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist));

  for (base::DictionaryValue::Iterator it(*servers_dict); !it.IsAtEnd();
       it.Advance()) {
    // Get server's host/pair.
    const std::string& server_str = it.key();
    HostPortPair server = HostPortPair::FromString(server_str);
    if (server.host().empty()) {
      DVLOG(1) << "Malformed http_server_properties for server: " << server_str;
      detected_corrupted_prefs = true;
      continue;
    }

    const base::DictionaryValue* server_pref_dict = NULL;
    if (!it.value().GetAsDictionary(&server_pref_dict)) {
      DVLOG(1) << "Malformed http_server_properties server: " << server_str;
      detected_corrupted_prefs = true;
      continue;
    }

    // Get if server supports Spdy.
    bool supports_spdy = false;
    if ((server_pref_dict->GetBoolean(kSupportsSpdyKey, &supports_spdy)) &&
        supports_spdy) {
      spdy_servers->push_back(server_str);
    }

    AddToSpdySettingsMap(server, *server_pref_dict, spdy_settings_map.get());
    if (!AddToAlternativeServiceMap(server, *server_pref_dict,
                                    alternative_service_map.get()) ||
        !AddToNetworkStatsMap(server, *server_pref_dict,
                              server_network_stats_map.get())) {
      detected_corrupted_prefs = true;
    }
  }

  network_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(
          &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread,
          base::Unretained(this), base::Owned(spdy_servers.release()),
          base::Owned(spdy_settings_map.release()),
          base::Owned(alternative_service_map.release()), base::Owned(addr),
          base::Owned(server_network_stats_map.release()),
          detected_corrupted_prefs));
}

void HttpServerPropertiesManager::AddToSpdySettingsMap(
    const HostPortPair& server,
    const base::DictionaryValue& server_pref_dict,
    SpdySettingsMap* spdy_settings_map) {
  // Get SpdySettings.
  DCHECK(spdy_settings_map->Peek(server) == spdy_settings_map->end());
  const base::DictionaryValue* spdy_settings_dict = NULL;
  if (!server_pref_dict.GetDictionaryWithoutPathExpansion(
          kSettingsKey, &spdy_settings_dict)) {
    return;
  }
  SettingsMap settings_map;
  for (base::DictionaryValue::Iterator dict_it(*spdy_settings_dict);
       !dict_it.IsAtEnd(); dict_it.Advance()) {
    const std::string& id_str = dict_it.key();
    int id = 0;
    if (!base::StringToInt(id_str, &id)) {
      DVLOG(1) << "Malformed id in SpdySettings for server: "
               << server.ToString();
      NOTREACHED();
      continue;
    }
    int value = 0;
    if (!dict_it.value().GetAsInteger(&value)) {
      DVLOG(1) << "Malformed value in SpdySettings for server: "
               << server.ToString();
      NOTREACHED();
      continue;
    }
    SettingsFlagsAndValue flags_and_value(SETTINGS_FLAG_PERSISTED, value);
    settings_map[static_cast<SpdySettingsIds>(id)] = flags_and_value;
  }
  spdy_settings_map->Put(server, settings_map);
}

bool HttpServerPropertiesManager::ParseAlternativeServiceDict(
    const base::DictionaryValue& alternative_service_dict,
    const std::string& server_str,
    AlternativeServiceInfo* alternative_service_info) {
  // Protocol is mandatory.
  std::string protocol_str;
  if (!alternative_service_dict.GetStringWithoutPathExpansion(kProtocolKey,
                                                              &protocol_str)) {
    DVLOG(1) << "Malformed alternative service protocol string for server: "
             << server_str;
    return false;
  }
  AlternateProtocol protocol = AlternateProtocolFromString(protocol_str);
  if (!IsAlternateProtocolValid(protocol)) {
    DVLOG(1) << "Invalid alternative service protocol string for server: "
             << server_str;
    return false;
  }
  alternative_service_info->alternative_service.protocol = protocol;

  // Host is optional, defaults to "".
  alternative_service_info->alternative_service.host.clear();
  if (alternative_service_dict.HasKey(kHostKey) &&
      !alternative_service_dict.GetStringWithoutPathExpansion(
          kHostKey, &(alternative_service_info->alternative_service.host))) {
    DVLOG(1) << "Malformed alternative service host string for server: "
             << server_str;
    return false;
  }

  // Port is mandatory.
  int port = 0;
  if (!alternative_service_dict.GetInteger(kPortKey, &port) ||
      !IsPortValid(port)) {
    DVLOG(1) << "Malformed alternative service port for server: " << server_str;
    return false;
  }
  alternative_service_info->alternative_service.port =
      static_cast<uint32>(port);

  // Probability is optional, defaults to 1.0.
  alternative_service_info->probability = 1.0;
  if (alternative_service_dict.HasKey(kProbabilityKey) &&
      !alternative_service_dict.GetDoubleWithoutPathExpansion(
          kProbabilityKey, &(alternative_service_info->probability))) {
    DVLOG(1) << "Malformed alternative service probability for server: "
             << server_str;
    return false;
  }

  // Expiration is optional, defaults to one day.
  base::Time expiration;
  if (!alternative_service_dict.HasKey(kExpirationKey)) {
    alternative_service_info->expiration =
        base::Time::Now() + base::TimeDelta::FromDays(1);
    return true;
  }

  std::string expiration_string;
  if (alternative_service_dict.GetStringWithoutPathExpansion(
          kExpirationKey, &expiration_string)) {
    int64 expiration_int64 = 0;
    if (!base::StringToInt64(expiration_string, &expiration_int64)) {
      DVLOG(1) << "Malformed alternative service expiration for server: "
               << server_str;
      return false;
    }
    alternative_service_info->expiration =
        base::Time::FromInternalValue(expiration_int64);
    return true;
  }

  // Early release 46 Dev and Canary versions stored expiration as double.
  // TODO(bnc) Remove the following code parsing double around 2015-10-01.
  double expiration_double;
  if (alternative_service_dict.GetDoubleWithoutPathExpansion(
          kExpirationKey, &expiration_double)) {
    alternative_service_info->expiration =
        base::Time::FromDoubleT(expiration_double);
    return true;
  }

  DVLOG(1) << "Malformed alternative service expiration for server: "
           << server_str;
  return false;
}

bool HttpServerPropertiesManager::AddToAlternativeServiceMap(
    const HostPortPair& server,
    const base::DictionaryValue& server_pref_dict,
    AlternativeServiceMap* alternative_service_map) {
  DCHECK(alternative_service_map->Peek(server) ==
         alternative_service_map->end());
  // Get alternative_services...
  const base::ListValue* alternative_service_list;
  const base::DictionaryValue* alternative_service_dict;
  AlternativeServiceInfoVector alternative_service_info_vector;
  if (server_pref_dict.GetListWithoutPathExpansion(kAlternativeServiceKey,
                                                   &alternative_service_list)) {
    for (const base::Value* alternative_service_list_item :
         *alternative_service_list) {
      if (!alternative_service_list_item->GetAsDictionary(
              &alternative_service_dict))
        return false;
      AlternativeServiceInfo alternative_service_info;
      if (!ParseAlternativeServiceDict(*alternative_service_dict,
                                       server.ToString(),
                                       &alternative_service_info)) {
        return false;
      }
      alternative_service_info_vector.push_back(alternative_service_info);
    }
  } else {
    // ...or alternate_protocol.
    // TODO(bnc): Remove this in M46, we do not need preference migration for
    // long.
    if (!server_pref_dict.GetDictionaryWithoutPathExpansion(
            kAlternateProtocolKey, &alternative_service_dict)) {
      return true;
    }
    AlternativeServiceInfo alternative_service_info;
    if (!ParseAlternativeServiceDict(*alternative_service_dict,
                                     server.ToString(),
                                     &alternative_service_info)) {
      return false;
    }
    alternative_service_info_vector.push_back(alternative_service_info);
  }

  if (alternative_service_info_vector.empty()) {
    return false;
  }

  alternative_service_map->Put(server, alternative_service_info_vector);
  return true;
}

bool HttpServerPropertiesManager::ReadSupportsQuic(
    const base::DictionaryValue& http_server_properties_dict,
    IPAddressNumber* last_quic_address) {
  const base::DictionaryValue* supports_quic_dict = NULL;
  if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion(
          kSupportsQuicKey, &supports_quic_dict)) {
    return true;
  }
  bool used_quic = false;
  if (!supports_quic_dict->GetBooleanWithoutPathExpansion(kUsedQuicKey,
                                                          &used_quic)) {
    DVLOG(1) << "Malformed SupportsQuic";
    return false;
  }
  if (!used_quic)
    return false;

  std::string address;
  if (!supports_quic_dict->GetStringWithoutPathExpansion(kAddressKey,
                                                         &address) ||
      !ParseIPLiteralToNumber(address, last_quic_address)) {
    DVLOG(1) << "Malformed SupportsQuic";
    return false;
  }
  return true;
}

bool HttpServerPropertiesManager::AddToNetworkStatsMap(
    const HostPortPair& server,
    const base::DictionaryValue& server_pref_dict,
    ServerNetworkStatsMap* network_stats_map) {
  DCHECK(network_stats_map->Peek(server) == network_stats_map->end());
  const base::DictionaryValue* server_network_stats_dict = NULL;
  if (!server_pref_dict.GetDictionaryWithoutPathExpansion(
          kNetworkStatsKey, &server_network_stats_dict)) {
    return true;
  }
  int srtt;
  if (!server_network_stats_dict->GetIntegerWithoutPathExpansion(kSrttKey,
                                                                 &srtt)) {
    DVLOG(1) << "Malformed ServerNetworkStats for server: "
             << server.ToString();
    return false;
  }
  ServerNetworkStats server_network_stats;
  server_network_stats.srtt = base::TimeDelta::FromInternalValue(srtt);
  // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
  // bandwidth_estimate.
  network_stats_map->Put(server, server_network_stats);
  return true;
}

void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
    StringVector* spdy_servers,
    SpdySettingsMap* spdy_settings_map,
    AlternativeServiceMap* alternative_service_map,
    IPAddressNumber* last_quic_address,
    ServerNetworkStatsMap* server_network_stats_map,
    bool detected_corrupted_prefs) {
  // Preferences have the master data because admins might have pushed new
  // preferences. Update the cached data with new data from preferences.
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());

  UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers->size());
  http_server_properties_impl_->InitializeSpdyServers(spdy_servers, true);

  // Update the cached data and use the new spdy_settings from preferences.
  UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map->size());
  http_server_properties_impl_->InitializeSpdySettingsServers(
      spdy_settings_map);

  // Update the cached data and use the new alternative service list from
  // preferences.
  UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
                       alternative_service_map->size());
  http_server_properties_impl_->InitializeAlternativeServiceServers(
      alternative_service_map);

  http_server_properties_impl_->InitializeSupportsQuic(last_quic_address);

  http_server_properties_impl_->InitializeServerNetworkStats(
      server_network_stats_map);

  // Update the prefs with what we have read (delete all corrupted prefs).
  if (detected_corrupted_prefs)
    ScheduleUpdatePrefsOnNetworkThread(DETECTED_CORRUPTED_PREFS);
}

//
// Update Preferences with data from the cached data.
//
void HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread(
    Location location) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  // Cancel pending updates, if any.
  network_prefs_update_timer_->Stop();
  StartPrefsUpdateTimerOnNetworkThread(
      base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs));
  // TODO(rtenneti): Delete the following histogram after collecting some data.
  UMA_HISTOGRAM_ENUMERATION("Net.HttpServerProperties.UpdatePrefs", location,
                            HttpServerPropertiesManager::NUM_LOCATIONS);
}

void HttpServerPropertiesManager::StartPrefsUpdateTimerOnNetworkThread(
    base::TimeDelta delay) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
  // This is overridden in tests to post the task without the delay.
  network_prefs_update_timer_->Start(
      FROM_HERE,
      delay,
      this,
      &HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread);
}

// This is required so we can set this as the callback for a timer.
void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread() {
  UpdatePrefsFromCacheOnNetworkThread(base::Closure());
}

void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(
    const base::Closure& completion) {
  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());

  base::ListValue* spdy_server_list = new base::ListValue;
  http_server_properties_impl_->GetSpdyServerList(
      spdy_server_list, kMaxSupportsSpdyServerHostsToPersist);

  SpdySettingsMap* spdy_settings_map =
      new SpdySettingsMap(kMaxSpdySettingsHostsToPersist);
  const SpdySettingsMap& main_map =
      http_server_properties_impl_->spdy_settings_map();
  int count = 0;
  for (SpdySettingsMap::const_iterator it = main_map.begin();
       it != main_map.end() && count < kMaxSpdySettingsHostsToPersist;
       ++it, ++count) {
    spdy_settings_map->Put(it->first, it->second);
  }

  AlternativeServiceMap* alternative_service_map =
      new AlternativeServiceMap(kMaxAlternateProtocolHostsToPersist);
  const AlternativeServiceMap& map =
      http_server_properties_impl_->alternative_service_map();
  count = 0;
  typedef std::map<std::string, bool> CanonicalHostPersistedMap;
  CanonicalHostPersistedMap persisted_map;
  for (AlternativeServiceMap::const_iterator it = map.begin();
       it != map.end() && count < kMaxAlternateProtocolHostsToPersist; ++it) {
    const HostPortPair& server = it->first;
    AlternativeServiceInfoVector notbroken_alternative_service_info_vector;
    for (const AlternativeServiceInfo& alternative_service_info : it->second) {
      if (!IsAlternateProtocolValid(
              alternative_service_info.alternative_service.protocol)) {
        continue;
      }
      AlternativeService alternative_service(
          alternative_service_info.alternative_service);
      if (alternative_service.host.empty()) {
        alternative_service.host = server.host();
      }
      if (IsAlternativeServiceBroken(alternative_service)) {
        continue;
      }
      notbroken_alternative_service_info_vector.push_back(
          alternative_service_info);
    }
    if (notbroken_alternative_service_info_vector.empty()) {
      continue;
    }
    alternative_service_map->Put(server,
                                 notbroken_alternative_service_info_vector);
    std::string canonical_suffix =
        http_server_properties_impl_->GetCanonicalSuffix(server.host());
    if (!canonical_suffix.empty()) {
      if (persisted_map.find(canonical_suffix) != persisted_map.end())
        continue;
      persisted_map[canonical_suffix] = true;
    }
    ++count;
  }

  ServerNetworkStatsMap* server_network_stats_map =
      new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist);
  const ServerNetworkStatsMap& main_server_network_stats_map =
      http_server_properties_impl_->server_network_stats_map();
  for (ServerNetworkStatsMap::const_iterator it =
           main_server_network_stats_map.begin();
       it != main_server_network_stats_map.end(); ++it) {
    server_network_stats_map->Put(it->first, it->second);
  }

  IPAddressNumber* last_quic_addr = new IPAddressNumber;
  http_server_properties_impl_->GetSupportsQuic(last_quic_addr);
  // Update the preferences on the pref thread.
  pref_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(
          &HttpServerPropertiesManager::UpdatePrefsOnPrefThread, pref_weak_ptr_,
          base::Owned(spdy_server_list), base::Owned(spdy_settings_map),
          base::Owned(alternative_service_map), base::Owned(last_quic_addr),
          base::Owned(server_network_stats_map), completion));
}

// A local or temporary data structure to hold |supports_spdy|, SpdySettings,
// AlternativeServiceInfoVector, and SupportsQuic preferences for a server. This
// is used only in UpdatePrefsOnPrefThread.
struct ServerPref {
  ServerPref()
      : supports_spdy(false),
        settings_map(NULL),
        alternative_service_info_vector(NULL),
        supports_quic(NULL),
        server_network_stats(NULL) {}
  ServerPref(
      bool supports_spdy,
      const SettingsMap* settings_map,
      const AlternativeServiceInfoVector* alternative_service_info_vector,
      const SupportsQuic* supports_quic,
      const ServerNetworkStats* server_network_stats)
      : supports_spdy(supports_spdy),
        settings_map(settings_map),
        alternative_service_info_vector(alternative_service_info_vector),
        supports_quic(supports_quic),
        server_network_stats(server_network_stats) {}
  bool supports_spdy;
  const SettingsMap* settings_map;
  const AlternativeServiceInfoVector* alternative_service_info_vector;
  const SupportsQuic* supports_quic;
  const ServerNetworkStats* server_network_stats;
};

void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
    base::ListValue* spdy_server_list,
    SpdySettingsMap* spdy_settings_map,
    AlternativeServiceMap* alternative_service_map,
    IPAddressNumber* last_quic_address,
    ServerNetworkStatsMap* server_network_stats_map,
    const base::Closure& completion) {
  typedef std::map<HostPortPair, ServerPref> ServerPrefMap;
  ServerPrefMap server_pref_map;

  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());

  // Add servers that support spdy to server_pref_map.
  std::string s;
  for (base::ListValue::const_iterator list_it = spdy_server_list->begin();
       list_it != spdy_server_list->end();
       ++list_it) {
    if ((*list_it)->GetAsString(&s)) {
      HostPortPair server = HostPortPair::FromString(s);
      server_pref_map[server].supports_spdy = true;
    }
  }

  // Add servers that have SpdySettings to server_pref_map.
  for (SpdySettingsMap::iterator map_it = spdy_settings_map->begin();
       map_it != spdy_settings_map->end(); ++map_it) {
    const HostPortPair& server = map_it->first;
    server_pref_map[server].settings_map = &map_it->second;
  }

  // Add alternative services to server_pref_map.
  for (AlternativeServiceMap::const_iterator map_it =
           alternative_service_map->begin();
       map_it != alternative_service_map->end(); ++map_it) {
    server_pref_map[map_it->first].alternative_service_info_vector =
        &map_it->second;
  }

  // Add ServerNetworkStats servers to server_pref_map.
  for (ServerNetworkStatsMap::const_iterator map_it =
           server_network_stats_map->begin();
       map_it != server_network_stats_map->end(); ++map_it) {
    const HostPortPair& server = map_it->first;
    server_pref_map[server].server_network_stats = &map_it->second;
  }

  // Persist properties to the |path_|.
  base::DictionaryValue http_server_properties_dict;
  base::DictionaryValue* servers_dict = new base::DictionaryValue;
  for (ServerPrefMap::const_iterator map_it = server_pref_map.begin();
       map_it != server_pref_map.end();
       ++map_it) {
    const HostPortPair& server = map_it->first;
    const ServerPref& server_pref = map_it->second;

    base::DictionaryValue* server_pref_dict = new base::DictionaryValue;

    // Save supports_spdy.
    if (server_pref.supports_spdy)
      server_pref_dict->SetBoolean(kSupportsSpdyKey, server_pref.supports_spdy);
    SaveSpdySettingsToServerPrefs(server_pref.settings_map, server_pref_dict);
    SaveAlternativeServiceToServerPrefs(
        server_pref.alternative_service_info_vector, server_pref_dict);
    SaveNetworkStatsToServerPrefs(server_pref.server_network_stats,
                                  server_pref_dict);

    servers_dict->SetWithoutPathExpansion(server.ToString(), server_pref_dict);
  }

  http_server_properties_dict.SetWithoutPathExpansion(kServersKey,
                                                      servers_dict);
  SetVersion(&http_server_properties_dict, kVersionNumber);

  SaveSupportsQuicToPrefs(last_quic_address, &http_server_properties_dict);

  setting_prefs_ = true;
  pref_service_->Set(path_, http_server_properties_dict);
  setting_prefs_ = false;

  // Note that |completion| will be fired after we have written everything to
  // the Preferences, but likely before these changes are serialized to disk.
  // This is not a problem though, as JSONPrefStore guarantees that this will
  // happen, pretty soon, and even in the case we shut down immediately.
  if (!completion.is_null())
    completion.Run();
}

void HttpServerPropertiesManager::SaveSpdySettingsToServerPrefs(
    const SettingsMap* settings_map,
    base::DictionaryValue* server_pref_dict) {
  if (!settings_map) {
    return;
  }
  base::DictionaryValue* spdy_settings_dict = new base::DictionaryValue;
  for (SettingsMap::const_iterator it = settings_map->begin();
       it != settings_map->end(); ++it) {
    SpdySettingsIds id = it->first;
    uint32 value = it->second.second;
    std::string key = base::StringPrintf("%u", id);
    spdy_settings_dict->SetInteger(key, value);
  }
  server_pref_dict->SetWithoutPathExpansion(kSettingsKey, spdy_settings_dict);
}

void HttpServerPropertiesManager::SaveAlternativeServiceToServerPrefs(
    const AlternativeServiceInfoVector* alternative_service_info_vector,
    base::DictionaryValue* server_pref_dict) {
  if (!alternative_service_info_vector ||
      alternative_service_info_vector->empty()) {
    return;
  }
  scoped_ptr<base::ListValue> alternative_service_list(new base::ListValue);
  for (const AlternativeServiceInfo& alternative_service_info :
       *alternative_service_info_vector) {
    const AlternativeService alternative_service =
        alternative_service_info.alternative_service;
    DCHECK(IsAlternateProtocolValid(alternative_service.protocol));
    base::DictionaryValue* alternative_service_dict = new base::DictionaryValue;
    alternative_service_dict->SetInteger(kPortKey, alternative_service.port);
    if (!alternative_service.host.empty()) {
      alternative_service_dict->SetString(kHostKey, alternative_service.host);
    }
    alternative_service_dict->SetString(
        kProtocolKey, AlternateProtocolToString(alternative_service.protocol));
    alternative_service_dict->SetDouble(kProbabilityKey,
                                        alternative_service_info.probability);
    // JSON cannot store int64, so expiration is converted to a string.
    alternative_service_dict->SetString(
        kExpirationKey,
        base::Int64ToString(
            alternative_service_info.expiration.ToInternalValue()));
    alternative_service_list->Append(alternative_service_dict);
  }
  if (alternative_service_list->GetSize() == 0)
    return;
  server_pref_dict->SetWithoutPathExpansion(kAlternativeServiceKey,
                                            alternative_service_list.release());
}

void HttpServerPropertiesManager::SaveSupportsQuicToPrefs(
    const IPAddressNumber* last_quic_address,
    base::DictionaryValue* http_server_properties_dict) {
  if (!last_quic_address || last_quic_address->empty())
    return;

  base::DictionaryValue* supports_quic_dict = new base::DictionaryValue;
  supports_quic_dict->SetBoolean(kUsedQuicKey, true);
  supports_quic_dict->SetString(kAddressKey,
                                IPAddressToString(*last_quic_address));
  http_server_properties_dict->SetWithoutPathExpansion(kSupportsQuicKey,
                                                       supports_quic_dict);
}

void HttpServerPropertiesManager::SaveNetworkStatsToServerPrefs(
    const ServerNetworkStats* server_network_stats,
    base::DictionaryValue* server_pref_dict) {
  if (!server_network_stats)
    return;

  base::DictionaryValue* server_network_stats_dict = new base::DictionaryValue;
  // Becasue JSON doesn't support int64, persist int64 as a string.
  server_network_stats_dict->SetInteger(
      kSrttKey, static_cast<int>(server_network_stats->srtt.ToInternalValue()));
  // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
  // bandwidth_estimate.
  server_pref_dict->SetWithoutPathExpansion(kNetworkStatsKey,
                                            server_network_stats_dict);
}

void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
  if (!setting_prefs_)
    ScheduleUpdateCacheOnPrefThread();
}

}  // namespace net
