// 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 "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/prefs/pref_member.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "components/data_reduction_proxy/browser/data_reduction_proxy_configurator.h"
#include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h"
#include "components/data_reduction_proxy/common/data_reduction_proxy_pref_names.h"
#include "components/data_reduction_proxy/common/data_reduction_proxy_switches.h"
#include "crypto/random.h"
#include "net/base/auth.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_auth.h"
#include "net/http/http_auth_cache.h"
#include "net/http/http_network_session.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_status.h"
#include "url/gurl.h"


using base::StringPrintf;

namespace {

// Key of the UMA DataReductionProxy.StartupState histogram.
const char kUMAProxyStartupStateHistogram[] =
    "DataReductionProxy.StartupState";

// Key of the UMA DataReductionProxy.ProbeURL histogram.
const char kUMAProxyProbeURL[] = "DataReductionProxy.ProbeURL";

// TODO(marq): Factor this string out into a constant here and in
//             http_auth_handler_spdyproxy.
const char kAuthenticationRealmName[] = "SpdyProxy";

int64 GetInt64PrefValue(const base::ListValue& list_value, size_t index) {
  int64 val = 0;
  std::string pref_value;
  bool rv = list_value.GetString(index, &pref_value);
  DCHECK(rv);
  if (rv) {
    rv = base::StringToInt64(pref_value, &val);
    DCHECK(rv);
  }
  return val;
}

}  // namespace

namespace data_reduction_proxy {

DataReductionProxySettings::DataReductionProxySettings(
    DataReductionProxyParams* params)
    : restricted_by_carrier_(false),
      enabled_by_user_(false),
      prefs_(NULL),
      local_state_prefs_(NULL),
      url_request_context_getter_(NULL) {
  DCHECK(params);
  params_.reset(params);
}

DataReductionProxySettings::~DataReductionProxySettings() {
  if (params_->allowed())
    spdy_proxy_auth_enabled_.Destroy();
}

void DataReductionProxySettings::InitPrefMembers() {
  DCHECK(thread_checker_.CalledOnValidThread());
  spdy_proxy_auth_enabled_.Init(
      prefs::kDataReductionProxyEnabled,
      GetOriginalProfilePrefs(),
      base::Bind(&DataReductionProxySettings::OnProxyEnabledPrefChange,
                 base::Unretained(this)));
  data_reduction_proxy_alternative_enabled_.Init(
      prefs::kDataReductionProxyAltEnabled,
      GetOriginalProfilePrefs(),
      base::Bind(
          &DataReductionProxySettings::OnProxyAlternativeEnabledPrefChange,
          base::Unretained(this)));
}

void DataReductionProxySettings::InitDataReductionProxySettings(
    PrefService* prefs,
    PrefService* local_state_prefs,
    net::URLRequestContextGetter* url_request_context_getter) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(prefs);
  DCHECK(local_state_prefs);
  DCHECK(url_request_context_getter);
  prefs_ = prefs;
  local_state_prefs_ = local_state_prefs;
  url_request_context_getter_ = url_request_context_getter;
  InitPrefMembers();
  RecordDataReductionInit();

  // Disable the proxy if it is not allowed to be used.
  if (!params_->allowed())
    return;

  AddDefaultProxyBypassRules();
  net::NetworkChangeNotifier::AddIPAddressObserver(this);

  // We set or reset the proxy pref at startup.
  MaybeActivateDataReductionProxy(true);
}

void DataReductionProxySettings::InitDataReductionProxySettings(
    PrefService* prefs,
    PrefService* local_state_prefs,
    net::URLRequestContextGetter* url_request_context_getter,
    scoped_ptr<DataReductionProxyConfigurator> configurator) {
  InitDataReductionProxySettings(prefs,
                                 local_state_prefs,
                                 url_request_context_getter);
  SetProxyConfigurator(configurator.Pass());
}

void DataReductionProxySettings::SetProxyConfigurator(
    scoped_ptr<DataReductionProxyConfigurator> configurator) {
  DCHECK(configurator);
  configurator_ = configurator.Pass();
}

// static
void DataReductionProxySettings::InitDataReductionProxySession(
    net::HttpNetworkSession* session,
    const DataReductionProxyParams* params) {
// This is a no-op unless the authentication parameters are compiled in.
// (even though values for them may be specified on the command line).
// Authentication will still work if the command line parameters are used,
// however there will be a round-trip overhead for each challenge/response
// (typically once per session).
// TODO(bengr):Pass a configuration struct into DataReductionProxyConfigurator's
// constructor. The struct would carry everything in the preprocessor flags.
  DCHECK(session);
  net::HttpAuthCache* auth_cache = session->http_auth_cache();
  DCHECK(auth_cache);
  InitDataReductionAuthentication(auth_cache, params);
}

// static
void DataReductionProxySettings::InitDataReductionAuthentication(
    net::HttpAuthCache* auth_cache,
    const DataReductionProxyParams* params) {
  DCHECK(auth_cache);
  DCHECK(params);
  int64 timestamp =
      (base::Time::Now() - base::Time::UnixEpoch()).InMilliseconds() / 1000;

  DataReductionProxyParams::DataReductionProxyList proxies =
      params->GetAllowedProxies();
  for (DataReductionProxyParams::DataReductionProxyList::iterator it =
           proxies.begin();
       it != proxies.end(); ++it) {
    GURL auth_origin = (*it).GetOrigin();

    int32 rand[3];
    crypto::RandBytes(rand, 3 * sizeof(rand[0]));

    std::string realm =
        base::StringPrintf("%s%lld", kAuthenticationRealmName,
                           static_cast<long long>(timestamp));
    std::string challenge = base::StringPrintf(
        "%s realm=\"%s\", ps=\"%lld-%u-%u-%u\"",
        kAuthenticationRealmName,
        realm.data(),
        static_cast<long long>(timestamp),
        rand[0],
        rand[1],
        rand[2]);
    base::string16 password = AuthHashForSalt(timestamp, params->key());

    DVLOG(1) << "origin: [" << auth_origin << "] realm: [" << realm
        << "] challenge: [" << challenge << "] password: [" << password << "]";

    net::AuthCredentials credentials(base::string16(), password);
    // |HttpAuthController| searches this cache by origin and path, the latter
    // being '/' in the case of the data reduction proxy.
    auth_cache->Add(auth_origin,
                    realm,
                    net::HttpAuth::AUTH_SCHEME_SPDYPROXY,
                    challenge,
                    credentials,
                    std::string("/"));
  }
}

bool DataReductionProxySettings::IsAcceptableAuthChallenge(
    net::AuthChallengeInfo* auth_info) {
  // Challenge realm must start with the authentication realm name.
  std::string realm_prefix =
      auth_info->realm.substr(0, strlen(kAuthenticationRealmName));
  if (realm_prefix != kAuthenticationRealmName)
    return false;

  // The challenger must be one of the configured proxies.
  DataReductionProxyParams::DataReductionProxyList proxies =
      params_->GetAllowedProxies();
  for (DataReductionProxyParams::DataReductionProxyList::iterator it =
       proxies.begin();
       it != proxies.end(); ++it) {
    net::HostPortPair origin_host = net::HostPortPair::FromURL(*it);
    if (origin_host.Equals(auth_info->challenger))
      return true;
  }
  return false;
}

base::string16 DataReductionProxySettings::GetTokenForAuthChallenge(
    net::AuthChallengeInfo* auth_info) {
  if (auth_info->realm.length() > strlen(kAuthenticationRealmName)) {
    int64 salt;
    std::string realm_suffix =
        auth_info->realm.substr(strlen(kAuthenticationRealmName));
    if (base::StringToInt64(realm_suffix, &salt)) {
      return AuthHashForSalt(salt, params_->key());
    } else {
      DVLOG(1) << "Unable to parse realm name " << auth_info->realm
               << "into an int for salting.";
      return base::string16();
    }
  } else {
    return base::string16();
  }
}

bool DataReductionProxySettings::IsDataReductionProxyEnabled() {
  // We should not check for DataReductionProxyParams::IsKeySetOnCommandLine()
  // here because when we enable drp in cmd and supply a wrong key to drp,
  // drp is supposed to disable itself and fallback to direct loading after
  // repeated authentication failures.
  return spdy_proxy_auth_enabled_.GetValue();
}

bool
DataReductionProxySettings::IsDataReductionProxyAlternativeEnabled() const {
  return data_reduction_proxy_alternative_enabled_.GetValue();
}

bool DataReductionProxySettings::IsDataReductionProxyManaged() {
  return spdy_proxy_auth_enabled_.IsManaged();
}

void DataReductionProxySettings::SetDataReductionProxyEnabled(bool enabled) {
  DCHECK(thread_checker_.CalledOnValidThread());
  // Prevent configuring the proxy when it is not allowed to be used.
  if (!params_->allowed())
    return;

  if (spdy_proxy_auth_enabled_.GetValue() != enabled) {
    spdy_proxy_auth_enabled_.SetValue(enabled);
    OnProxyEnabledPrefChange();
  }
}

void DataReductionProxySettings::SetDataReductionProxyAlternativeEnabled(
    bool enabled) {
  DCHECK(thread_checker_.CalledOnValidThread());
  // Prevent configuring the proxy when it is not allowed to be used.
  if (!params_->alternative_allowed())
    return;
  if (data_reduction_proxy_alternative_enabled_.GetValue() != enabled) {
    data_reduction_proxy_alternative_enabled_.SetValue(enabled);
    OnProxyAlternativeEnabledPrefChange();
  }
}

int64 DataReductionProxySettings::GetDataReductionLastUpdateTime() {
  DCHECK(thread_checker_.CalledOnValidThread());
  PrefService* local_state = GetLocalStatePrefs();
  int64 last_update_internal =
      local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate);
  base::Time last_update = base::Time::FromInternalValue(last_update_internal);
  return static_cast<int64>(last_update.ToJsTime());
}

DataReductionProxySettings::ContentLengthList
DataReductionProxySettings::GetDailyOriginalContentLengths() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return GetDailyContentLengths(prefs::kDailyHttpOriginalContentLength);
}

DataReductionProxySettings::ContentLengthList
DataReductionProxySettings::GetDailyReceivedContentLengths() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return GetDailyContentLengths(prefs::kDailyHttpReceivedContentLength);
}

void DataReductionProxySettings::OnURLFetchComplete(
    const net::URLFetcher* source) {
  DCHECK(thread_checker_.CalledOnValidThread());

  // The purpose of sending a request for the warmup URL is to warm the
  // connection to the data_reduction_proxy. The result is ignored.
  if (source == warmup_fetcher_.get())
    return;

  DCHECK(source == fetcher_.get());
  net::URLRequestStatus status = source->GetStatus();
  if (status.status() == net::URLRequestStatus::FAILED &&
      status.error() == net::ERR_INTERNET_DISCONNECTED) {
    RecordProbeURLFetchResult(INTERNET_DISCONNECTED);
    return;
  }

  std::string response;
  source->GetResponseAsString(&response);

  if ("OK" == response.substr(0, 2)) {
    DVLOG(1) << "The data reduction proxy is unrestricted.";

    if (enabled_by_user_) {
      if (restricted_by_carrier_) {
        // The user enabled the proxy, but sometime previously in the session,
        // the network operator had blocked the canary and restricted the user.
        // The current network doesn't block the canary, so don't restrict the
        // proxy configurations.
        SetProxyConfigs(true /* enabled */,
                        IsDataReductionProxyAlternativeEnabled(),
                        false /* restricted */,
                        false /* at_startup */);
        RecordProbeURLFetchResult(SUCCEEDED_PROXY_ENABLED);
      } else {
        RecordProbeURLFetchResult(SUCCEEDED_PROXY_ALREADY_ENABLED);
      }
    }
    restricted_by_carrier_ = false;
    return;
  }
  DVLOG(1) << "The data reduction proxy is restricted to the configured "
           << "fallback proxy.";
  if (enabled_by_user_) {
    if (!restricted_by_carrier_) {
      // Restrict the proxy.
      SetProxyConfigs(true /* enabled */,
                      IsDataReductionProxyAlternativeEnabled(),
                      true /* restricted */,
                      false /* at_startup */);
      RecordProbeURLFetchResult(FAILED_PROXY_DISABLED);
    } else {
      RecordProbeURLFetchResult(FAILED_PROXY_ALREADY_DISABLED);
    }
  }
  restricted_by_carrier_ = true;
}

PrefService* DataReductionProxySettings::GetOriginalProfilePrefs() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return prefs_;
}

PrefService* DataReductionProxySettings::GetLocalStatePrefs() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return local_state_prefs_;
}

void DataReductionProxySettings::AddDefaultProxyBypassRules() {
  // localhost
  configurator_->AddHostPatternToBypass("<local>");
  // RFC1918 private addresses.
  configurator_->AddHostPatternToBypass("10.0.0.0/8");
  configurator_->AddHostPatternToBypass("172.16.0.0/12");
  configurator_->AddHostPatternToBypass("192.168.0.0/16");
  // RFC4193 private addresses.
  configurator_->AddHostPatternToBypass("fc00::/7");
  // IPV6 probe addresses.
  configurator_->AddHostPatternToBypass("*-ds.metric.gstatic.com");
  configurator_->AddHostPatternToBypass("*-v4.metric.gstatic.com");
}

void DataReductionProxySettings::LogProxyState(
    bool enabled, bool restricted, bool at_startup) {
  // This must stay a LOG(WARNING); the output is used in processing customer
  // feedback.
  const char kAtStartup[] = "at startup";
  const char kByUser[] = "by user action";
  const char kOn[] = "ON";
  const char kOff[] = "OFF";
  const char kRestricted[] = "(Restricted)";
  const char kUnrestricted[] = "(Unrestricted)";

  std::string annotated_on =
      kOn + std::string(" ") + (restricted ? kRestricted : kUnrestricted);

  LOG(WARNING) << "SPDY proxy " << (enabled ? annotated_on : kOff)
               << " " << (at_startup ? kAtStartup : kByUser);
}

void DataReductionProxySettings::OnIPAddressChanged() {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (enabled_by_user_) {
    DCHECK(params_->allowed());
    ProbeWhetherDataReductionProxyIsAvailable();
    WarmProxyConnection();
  }
}

void DataReductionProxySettings::OnProxyEnabledPrefChange() {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!params_->allowed())
    return;
  MaybeActivateDataReductionProxy(false);
}

void DataReductionProxySettings::OnProxyAlternativeEnabledPrefChange() {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!params_->alternative_allowed())
    return;
  MaybeActivateDataReductionProxy(false);
}

void DataReductionProxySettings::ResetDataReductionStatistics() {
  DCHECK(thread_checker_.CalledOnValidThread());
  PrefService* prefs = GetLocalStatePrefs();
  if (!prefs)
    return;
  ListPrefUpdate original_update(prefs, prefs::kDailyHttpOriginalContentLength);
  ListPrefUpdate received_update(prefs, prefs::kDailyHttpReceivedContentLength);
  original_update->Clear();
  received_update->Clear();
  for (size_t i = 0; i < kNumDaysInHistory; ++i) {
    original_update->AppendString(base::Int64ToString(0));
    received_update->AppendString(base::Int64ToString(0));
  }
}

void DataReductionProxySettings::MaybeActivateDataReductionProxy(
    bool at_startup) {
  DCHECK(thread_checker_.CalledOnValidThread());
  PrefService* prefs = GetOriginalProfilePrefs();
  // TODO(marq): Consider moving this so stats are wiped the first time the
  // proxy settings are actually (not maybe) turned on.
  if (spdy_proxy_auth_enabled_.GetValue() &&
      !prefs->GetBoolean(prefs::kDataReductionProxyWasEnabledBefore)) {
    prefs->SetBoolean(prefs::kDataReductionProxyWasEnabledBefore, true);
    ResetDataReductionStatistics();
  }

  // Configure use of the data reduction proxy if it is enabled.
  enabled_by_user_= IsDataReductionProxyEnabled();
  SetProxyConfigs(enabled_by_user_,
                  IsDataReductionProxyAlternativeEnabled(),
                  restricted_by_carrier_,
                  at_startup);

  // Check if the proxy has been restricted explicitly by the carrier.
  if (enabled_by_user_) {
    ProbeWhetherDataReductionProxyIsAvailable();
    WarmProxyConnection();
  }
}

void DataReductionProxySettings::SetProxyConfigs(bool enabled,
                                                 bool alternative_enabled,
                                                 bool restricted,
                                                 bool at_startup) {
  DCHECK(thread_checker_.CalledOnValidThread());
  LogProxyState(enabled, restricted, at_startup);
  // The alternative is only configured if the standard configuration is
  // is enabled.
  if (enabled) {
    if (alternative_enabled) {
      configurator_->Enable(restricted,
                            !params_->fallback_allowed(),
                            params_->alt_origin().spec(),
                            params_->alt_fallback_origin().spec(),
                            params_->ssl_origin().spec());
    } else {
      configurator_->Enable(restricted,
                            !params_->fallback_allowed(),
                            params_->origin().spec(),
                            params_->fallback_origin().spec(),
                            std::string());
    }
  } else {
    configurator_->Disable();
  }
}

// Metrics methods
void DataReductionProxySettings::RecordDataReductionInit() {
  DCHECK(thread_checker_.CalledOnValidThread());
  ProxyStartupState state = PROXY_NOT_AVAILABLE;
  if (params_->allowed()) {
    if (IsDataReductionProxyEnabled())
      state = PROXY_ENABLED;
    else
      state = PROXY_DISABLED;
  }

  RecordStartupState(state);
}

void DataReductionProxySettings::RecordProbeURLFetchResult(
    ProbeURLFetchResult result) {
  UMA_HISTOGRAM_ENUMERATION(kUMAProxyProbeURL,
                            result,
                            PROBE_URL_FETCH_RESULT_COUNT);
}

void DataReductionProxySettings::RecordStartupState(ProxyStartupState state) {
  UMA_HISTOGRAM_ENUMERATION(kUMAProxyStartupStateHistogram,
                            state,
                            PROXY_STARTUP_STATE_COUNT);
}

void DataReductionProxySettings::ResetParamsForTest(
    DataReductionProxyParams* params) {
  params_.reset(params);
}

DataReductionProxySettings::ContentLengthList
DataReductionProxySettings::GetDailyContentLengths(const char* pref_name) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DataReductionProxySettings::ContentLengthList content_lengths;
  const base::ListValue* list_value = GetLocalStatePrefs()->GetList(pref_name);
  if (list_value->GetSize() == kNumDaysInHistory) {
    for (size_t i = 0; i < kNumDaysInHistory; ++i) {
      content_lengths.push_back(GetInt64PrefValue(*list_value, i));
    }
  }
  return content_lengths;
}

void DataReductionProxySettings::GetContentLengths(
    unsigned int days,
    int64* original_content_length,
    int64* received_content_length,
    int64* last_update_time) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_LE(days, kNumDaysInHistory);
  PrefService* local_state = GetLocalStatePrefs();
  if (!local_state) {
    *original_content_length = 0L;
    *received_content_length = 0L;
    *last_update_time = 0L;
    return;
  }

  const base::ListValue* original_list =
      local_state->GetList(prefs::kDailyHttpOriginalContentLength);
  const base::ListValue* received_list =
      local_state->GetList(prefs::kDailyHttpReceivedContentLength);

  if (original_list->GetSize() != kNumDaysInHistory ||
      received_list->GetSize() != kNumDaysInHistory) {
    *original_content_length = 0L;
    *received_content_length = 0L;
    *last_update_time = 0L;
    return;
  }

  int64 orig = 0L;
  int64 recv = 0L;
  // Include days from the end of the list going backwards.
  for (size_t i = kNumDaysInHistory - days;
       i < kNumDaysInHistory; ++i) {
    orig += GetInt64PrefValue(*original_list, i);
    recv += GetInt64PrefValue(*received_list, i);
  }
  *original_content_length = orig;
  *received_content_length = recv;
  *last_update_time =
      local_state->GetInt64(prefs::kDailyHttpContentLengthLastUpdateDate);
}

// static
base::string16 DataReductionProxySettings::AuthHashForSalt(
    int64 salt,
    const std::string& key) {
  std::string salted_key =
      base::StringPrintf("%lld%s%lld",
                         static_cast<long long>(salt),
                         key.c_str(),
                         static_cast<long long>(salt));
  return base::UTF8ToUTF16(base::MD5String(salted_key));
}

net::URLFetcher* DataReductionProxySettings::GetBaseURLFetcher(
    const GURL& gurl,
    int load_flags) {

  net::URLFetcher* fetcher = net::URLFetcher::Create(gurl,
                                                     net::URLFetcher::GET,
                                                     this);
  fetcher->SetLoadFlags(load_flags);
  DCHECK(url_request_context_getter_);
  fetcher->SetRequestContext(url_request_context_getter_);
  // Configure max retries to be at most kMaxRetries times for 5xx errors.
  static const int kMaxRetries = 5;
  fetcher->SetMaxRetriesOn5xx(kMaxRetries);
  fetcher->SetAutomaticallyRetryOnNetworkChanges(kMaxRetries);
  return fetcher;
}


net::URLFetcher*
DataReductionProxySettings::GetURLFetcherForAvailabilityCheck() {
  return GetBaseURLFetcher(params_->probe_url(),
                           net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_PROXY);
}


void DataReductionProxySettings::ProbeWhetherDataReductionProxyIsAvailable() {
  net::URLFetcher* fetcher = GetURLFetcherForAvailabilityCheck();
  if (!fetcher)
    return;
  fetcher_.reset(fetcher);
  fetcher_->Start();
}

net::URLFetcher* DataReductionProxySettings::GetURLFetcherForWarmup() {
  return GetBaseURLFetcher(params_->warmup_url(), net::LOAD_DISABLE_CACHE);
}

void DataReductionProxySettings::WarmProxyConnection() {
  net::URLFetcher* fetcher = GetURLFetcherForWarmup();
  if (!fetcher)
    return;
  warmup_fetcher_.reset(fetcher);
  warmup_fetcher_->Start();
}

}  // namespace data_reduction_proxy
