// Copyright 2015 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/core/browser/data_reduction_proxy_io_data.h"

#include <string>
#include <utility>

#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_mutable_config_values.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
#include "components/data_reduction_proxy/core/browser/network_properties_manager.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_throttle_manager.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_builder.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/network_context.mojom.h"

namespace data_reduction_proxy {

DataReductionProxyIOData::DataReductionProxyIOData(
    Client client,
    PrefService* prefs,
    network::NetworkConnectionTracker* network_connection_tracker,
    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
    bool enabled,
    const std::string& user_agent,
    const std::string& channel)
    : client_(client),
      network_connection_tracker_(network_connection_tracker),
      io_task_runner_(io_task_runner),
      ui_task_runner_(ui_task_runner),
      data_use_observer_(nullptr),
      enabled_(enabled),
      url_request_context_getter_(nullptr),
      channel_(channel),
      effective_connection_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
      weak_factory_(this) {
  DCHECK(io_task_runner_);
  DCHECK(ui_task_runner_);
  configurator_.reset(new DataReductionProxyConfigurator());
  configurator_->SetConfigUpdatedCallback(base::BindRepeating(
      &DataReductionProxyIOData::OnProxyConfigUpdated, base::Unretained(this)));
  DataReductionProxyMutableConfigValues* raw_mutable_config = nullptr;
    std::unique_ptr<DataReductionProxyMutableConfigValues> mutable_config =
        std::make_unique<DataReductionProxyMutableConfigValues>();
    raw_mutable_config = mutable_config.get();
    config_.reset(new DataReductionProxyConfig(
        io_task_runner, ui_task_runner, network_connection_tracker_,
        std::move(mutable_config), configurator_.get()));

    // It is safe to use base::Unretained here, since it gets executed
    // synchronously on the IO thread, and |this| outlives the caller (since the
    // caller is owned by |this|.
    bypass_stats_.reset(new DataReductionProxyBypassStats(
        config_.get(),
        base::BindRepeating(&DataReductionProxyIOData::SetUnreachable,
                            base::Unretained(this)),
        network_connection_tracker_));
    request_options_.reset(
        new DataReductionProxyRequestOptions(client_, config_.get()));
    request_options_->Init();
    // It is safe to use base::Unretained here, since it gets executed
    // synchronously on the IO thread, and |this| outlives the caller (since the
    // caller is owned by |this|.
    request_options_->SetUpdateHeaderCallback(base::BindRepeating(
        &DataReductionProxyIOData::UpdateProxyRequestHeaders,
        base::Unretained(this)));

    // It is safe to use base::Unretained here, since it gets executed
    // synchronously on the IO thread, and |this| outlives the caller (since the
    // caller is owned by |this|.
    config_client_.reset(new DataReductionProxyConfigServiceClient(
        GetBackoffPolicy(), request_options_.get(), raw_mutable_config,
        config_.get(), this, network_connection_tracker_,
        base::BindRepeating(&DataReductionProxyIOData::StoreSerializedConfig,
                            base::Unretained(this))));

    proxy_delegate_.reset(new DataReductionProxyDelegate(
        config_.get(), configurator_.get(), bypass_stats_.get()));
    network_properties_manager_.reset(new NetworkPropertiesManager(
        base::DefaultClock::GetInstance(), prefs, ui_task_runner_));
}

DataReductionProxyIOData::DataReductionProxyIOData(
    PrefService* prefs,
    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
    : client_(Client::UNKNOWN),
      network_connection_tracker_(nullptr),
      io_task_runner_(io_task_runner),
      ui_task_runner_(ui_task_runner),
      url_request_context_getter_(nullptr),
      effective_connection_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
      weak_factory_(this) {
  DCHECK(ui_task_runner_);
  DCHECK(io_task_runner_);
  network_properties_manager_.reset(new NetworkPropertiesManager(
      base::DefaultClock::GetInstance(), prefs, ui_task_runner_));
}

DataReductionProxyIOData::~DataReductionProxyIOData() {
  // Guaranteed to be destroyed on IO thread if the IO thread is still
  // available at the time of destruction. If the IO thread is unavailable,
  // then the destruction will happen on the UI thread.
}

void DataReductionProxyIOData::ShutdownOnUIThread() {
  DCHECK(ui_task_runner_->BelongsToCurrentThread());
  network_properties_manager_->ShutdownOnUIThread();
}

void DataReductionProxyIOData::SetDataReductionProxyService(
    base::WeakPtr<DataReductionProxyService> data_reduction_proxy_service) {
  DCHECK(ui_task_runner_->BelongsToCurrentThread());
  service_ = data_reduction_proxy_service;
  url_request_context_getter_ = service_->url_request_context_getter();
  url_loader_factory_info_ = service_->url_loader_factory_info();
  // Using base::Unretained is safe here, unless the browser is being shut down
  // before the Initialize task can be executed. The task is only created as
  // part of class initialization.
  if (io_task_runner_->BelongsToCurrentThread()) {
    InitializeOnIOThread();
    return;
  }
  io_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&DataReductionProxyIOData::InitializeOnIOThread,
                                base::Unretained(this)));
}

void DataReductionProxyIOData::InitializeOnIOThread() {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  DCHECK(network_properties_manager_);

  DCHECK(url_loader_factory_info_);
  auto url_loader_factory = network::SharedURLLoaderFactory::Create(
      std::move(url_loader_factory_info_));

  config_->InitializeOnIOThread(
      url_loader_factory,
      base::BindRepeating(&DataReductionProxyIOData::CreateCustomProxyConfig,
                          base::Unretained(this)),
      network_properties_manager_.get());
  bypass_stats_->InitializeOnIOThread();
  proxy_delegate_->InitializeOnIOThread(this);
  if (config_client_)
    config_client_->InitializeOnIOThread(url_loader_factory);
  if (ui_task_runner_->BelongsToCurrentThread()) {
    service_->SetIOData(weak_factory_.GetWeakPtr());
    return;
  }
  ui_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&DataReductionProxyService::SetIOData, service_,
                                weak_factory_.GetWeakPtr()));
}

bool DataReductionProxyIOData::IsEnabled() const {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  return enabled_;
}

void DataReductionProxyIOData::SetPingbackReportingFraction(
    float pingback_reporting_fraction) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  ui_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DataReductionProxyService::SetPingbackReportingFraction,
                     service_, pingback_reporting_fraction));
}

void DataReductionProxyIOData::DeleteBrowsingHistory(const base::Time start,
                                                     const base::Time end) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  network_properties_manager_->DeleteHistory();
}

void DataReductionProxyIOData::OnCacheCleared(const base::Time start,
                                              const base::Time end) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  network_properties_manager_->DeleteHistory();
}

std::unique_ptr<net::URLRequestInterceptor>
DataReductionProxyIOData::CreateInterceptor() {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  return std::make_unique<DataReductionProxyInterceptor>(
      config_.get(), config_client_.get(), bypass_stats_.get());
}

std::unique_ptr<DataReductionProxyNetworkDelegate>
DataReductionProxyIOData::CreateNetworkDelegate(
    std::unique_ptr<net::NetworkDelegate> wrapped_network_delegate,
    bool track_proxy_bypass_statistics) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  std::unique_ptr<DataReductionProxyNetworkDelegate> network_delegate(
      new DataReductionProxyNetworkDelegate(
          std::move(wrapped_network_delegate), config_.get(),
          request_options_.get(), configurator_.get()));
  if (track_proxy_bypass_statistics)
    network_delegate->InitIODataAndUMA(this, bypass_stats_.get());

  return network_delegate;
}

std::unique_ptr<DataReductionProxyDelegate>
DataReductionProxyIOData::CreateProxyDelegate() {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  auto proxy_delegate = std::make_unique<DataReductionProxyDelegate>(
      config_.get(), configurator_.get(), bypass_stats_.get());
  proxy_delegate->InitializeOnIOThread(this);
  return proxy_delegate;
}

// TODO(kundaji): Rename this method to something more descriptive.
// Bug http://crbug/488190.
void DataReductionProxyIOData::SetProxyPrefs(bool enabled, bool at_startup) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  // TODO(crbug.com/721403): DRP is disabled with network service enabled. When
  // DRP is switched to mojo, we won't need URLRequestContext.
  if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
    DCHECK(url_request_context_getter_->GetURLRequestContext()
               ->proxy_resolution_service());
  }
  enabled_ = enabled;
  config_->SetProxyConfig(enabled, at_startup);
  if (config_client_) {
    config_client_->SetEnabled(enabled);
    if (enabled)
      config_client_->RetrieveConfig();
  }

  // If Data Saver is disabled, reset data reduction proxy state.
  if (!enabled) {
    if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
      if (proxy_config_client_)
        proxy_config_client_->ClearBadProxiesCache();
    } else {
      net::ProxyResolutionService* proxy_resolution_service =
          url_request_context_getter_->GetURLRequestContext()
              ->proxy_resolution_service();
      proxy_resolution_service->ClearBadProxiesCache();
    }

    bypass_stats_->ClearRequestCounts();
    bypass_stats_->NotifyUnavailabilityIfChanged();
  }
}

void DataReductionProxyIOData::SetDataReductionProxyConfiguration(
    const std::string& serialized_config) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  if (config_client_)
    config_client_->ApplySerializedConfig(serialized_config);
}

void DataReductionProxyIOData::SetIgnoreLongTermBlackListRules(
    bool ignore_long_term_black_list_rules) {
  ui_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          &DataReductionProxyService::SetIgnoreLongTermBlackListRules, service_,
          ignore_long_term_black_list_rules));
}

void DataReductionProxyIOData::UpdateDataUseForHost(int64_t network_bytes,
                                                    int64_t original_bytes,
                                                    const std::string& host) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());

  ui_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DataReductionProxyService::UpdateDataUseForHost, service_,
                     network_bytes, original_bytes, host));
}

void DataReductionProxyIOData::UpdateContentLengths(
    int64_t data_used,
    int64_t original_size,
    bool data_reduction_proxy_enabled,
    DataReductionProxyRequestType request_type,
    const std::string& mime_type,
    bool is_user_traffic,
    data_use_measurement::DataUseUserData::DataUseContentType content_type,
    int32_t service_hash_code) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());

  ui_task_runner_->PostTask(
      FROM_HERE,
      base::BindRepeating(&DataReductionProxyService::UpdateContentLengths,
                          service_, data_used, original_size,
                          data_reduction_proxy_enabled, request_type, mime_type,
                          is_user_traffic, content_type, service_hash_code));
}

void DataReductionProxyIOData::SetUnreachable(bool unreachable) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  ui_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&DataReductionProxyService::SetUnreachable,
                                service_, unreachable));
}

void DataReductionProxyIOData::SetInt64Pref(const std::string& pref_path,
                                            int64_t value) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  ui_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&DataReductionProxyService::SetInt64Pref,
                                service_, pref_path, value));
}

void DataReductionProxyIOData::SetStringPref(const std::string& pref_path,
                                             const std::string& value) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  ui_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&DataReductionProxyService::SetStringPref,
                                service_, pref_path, value));
}

void DataReductionProxyIOData::StoreSerializedConfig(
    const std::string& serialized_config) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  SetStringPref(prefs::kDataReductionProxyConfig, serialized_config);
  SetInt64Pref(prefs::kDataReductionProxyLastConfigRetrievalTime,
               (base::Time::Now() - base::Time()).InMicroseconds());
}

void DataReductionProxyIOData::SetDataUseAscriber(
    data_use_measurement::DataUseAscriber* data_use_ascriber) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  DCHECK(data_use_ascriber);
  data_use_observer_.reset(
      new DataReductionProxyDataUseObserver(this, data_use_ascriber));

  // Disable data use ascriber when data saver is not enabled.
  if (!IsEnabled()) {
    data_use_ascriber->DisableAscriber();
  }
}

void DataReductionProxyIOData::UpdateProxyRequestHeaders(
    const net::HttpRequestHeaders& headers) {
  ui_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DataReductionProxyService::SetProxyRequestHeadersOnUI,
                     service_, std::move(headers)));
  UpdateCustomProxyConfig();
}

void DataReductionProxyIOData::OnProxyConfigUpdated() {
  ui_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&DataReductionProxyService::SetConfiguredProxiesOnUI,
                     service_, config_->GetAllConfiguredProxies()));
  UpdateCustomProxyConfig();
  UpdateThrottleConfig();
}

network::mojom::CustomProxyConfigPtr
DataReductionProxyIOData::CreateCustomProxyConfig(
    const std::vector<DataReductionProxyServer>& proxies_for_http) const {
  auto config = network::mojom::CustomProxyConfig::New();
  config->rules =
      configurator_
          ->CreateProxyConfig(true /* probe_url_config */,
                              config_->GetNetworkPropertiesManager(),
                              proxies_for_http)
          .proxy_rules();

  // Set an alternate proxy list to be used for media requests which only
  // contains proxies supporting the media resource type.
  std::vector<DataReductionProxyServer> media_proxies;
  for (const auto& proxy : proxies_for_http) {
    if (proxy.SupportsResourceType(ResourceTypeProvider::CONTENT_TYPE_MEDIA))
      media_proxies.push_back(proxy);
  }
  config->alternate_rules =
      configurator_
          ->CreateProxyConfig(true /* probe_url_config */,
                              config_->GetNetworkPropertiesManager(),
                              media_proxies)
          .proxy_rules();

  net::EffectiveConnectionType type = GetEffectiveConnectionType();
  if (type > net::EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
    DCHECK_NE(net::EFFECTIVE_CONNECTION_TYPE_LAST, type);
    config->pre_cache_headers.SetHeader(
        chrome_proxy_ect_header(),
        net::GetNameForEffectiveConnectionType(type));
  }

  request_options_->AddRequestHeader(&config->post_cache_headers,
                                     base::nullopt);
  return config;
}

void DataReductionProxyIOData::UpdateCustomProxyConfig() {
  if (!proxy_config_client_)
    return;

  proxy_config_client_->OnCustomProxyConfigUpdated(
      CreateCustomProxyConfig(config_->GetProxiesForHttp()));
}

void DataReductionProxyIOData::UpdateThrottleConfig() {
  if (drp_throttle_config_observers_.empty())
    return;

  auto config = CreateThrottleConfig();

  drp_throttle_config_observers_.ForAllPtrs(
      [&config](mojom::DataReductionProxyThrottleConfigObserver* observer) {
        observer->OnThrottleConfigChanged(config->Clone());
      });
}

mojom::DataReductionProxyThrottleConfigPtr
DataReductionProxyIOData::CreateThrottleConfig() const {
  return DataReductionProxyThrottleManager::CreateConfig(
      config_->GetProxiesForHttp());
}

void DataReductionProxyIOData::OnEffectiveConnectionTypeChanged(
    net::EffectiveConnectionType type) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  effective_connection_type_ = type;
  UpdateCustomProxyConfig();
}

void DataReductionProxyIOData::OnRTTOrThroughputEstimatesComputed(
    base::TimeDelta http_rtt) {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  config_->OnRTTOrThroughputEstimatesComputed(http_rtt);
}

net::EffectiveConnectionType
DataReductionProxyIOData::GetEffectiveConnectionType() const {
  DCHECK(io_task_runner_->BelongsToCurrentThread());
  return effective_connection_type_;
}

void DataReductionProxyIOData::SetCustomProxyConfigClient(
    network::mojom::CustomProxyConfigClientPtrInfo config_client_info) {
  proxy_config_client_.Bind(std::move(config_client_info));
  UpdateCustomProxyConfig();
}

DataReductionProxyThrottleManager*
DataReductionProxyIOData::GetThrottleManager() {
  if (!throttle_manager_) {
    mojom::DataReductionProxyPtr drp;
    Clone(mojo::MakeRequest(&drp));
    throttle_manager_ = std::make_unique<DataReductionProxyThrottleManager>(
        std::move(drp), CreateThrottleConfig());
  }

  return throttle_manager_.get();
}

void DataReductionProxyIOData::MarkProxiesAsBad(
    base::TimeDelta bypass_duration,
    const net::ProxyList& bad_proxies,
    mojom::DataReductionProxy::MarkProxiesAsBadCallback callback) {
  // Sanity check the inputs, as this data may originate from a lower-privilege
  // process (renderer).

  // The current policy sets this to 5 minutes, so don't allow a bigger
  // timespan.
  if (bypass_duration < base::TimeDelta() ||
      bypass_duration > base::TimeDelta::FromMinutes(5)) {
    LOG(ERROR) << "Received bad MarkProxiesAsBad() -- invalid bypass_duration: "
               << bypass_duration;
    std::move(callback).Run();
    return;
  }

  // |bad_proxies| should be DRP servers or this API allows marking arbitrary
  // proxies as bad. It is possible that proxies from an older config are
  // received (FindConfiguredDataReductionProxy() searches recent proxies too).
  for (const auto& proxy : bad_proxies.GetAll()) {
    if (!config_->FindConfiguredDataReductionProxy(proxy)) {
      LOG(ERROR) << "Received bad MarkProxiesAsBad() -- not a DRP server: "
                 << proxy.ToURI();
      std::move(callback).Run();
      return;
    }
  }

  proxy_config_client_->MarkProxiesAsBad(bypass_duration, bad_proxies,
                                         std::move(callback));
}

void DataReductionProxyIOData::AddThrottleConfigObserver(
    mojom::DataReductionProxyThrottleConfigObserverPtr observer) {
  observer->OnThrottleConfigChanged(CreateThrottleConfig());
  drp_throttle_config_observers_.AddPtr(std::move(observer));
}

void DataReductionProxyIOData::Clone(mojom::DataReductionProxyRequest request) {
  drp_bindings_.AddBinding(this, std::move(request));
}

}  // namespace data_reduction_proxy
