// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/cronet/cronet_context.h"

#include <limits.h>
#include <stddef.h>
#include <stdint.h>

#include <limits>
#include <map>
#include <memory>
#include <set>
#include <utility>

#include "base/base64.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/message_loop/message_pump_type.h"
#include "base/metrics/statistics_recorder.h"
#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/cronet/cronet_global_state.h"
#include "components/cronet/cronet_prefs_manager.h"
#include "components/cronet/host_cache_persistence_manager.h"
#include "components/cronet/url_request_context_config.h"
#include "net/base/completion_once_callback.h"
#include "net/base/ip_address.h"
#include "net/base/load_flags.h"
#include "net/base/logging_network_change_observer.h"
#include "net/base/net_errors.h"
#include "net/base/network_delegate_impl.h"
#include "net/base/network_isolation_key.h"
#include "net/base/proxy_delegate.h"
#include "net/base/url_util.h"
#include "net/cert/caching_cert_verifier.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/x509_certificate.h"
#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_setting_override.h"
#include "net/first_party_sets/first_party_set_metadata.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/transport_security_state.h"
#include "net/log/file_net_log_observer.h"
#include "net/log/net_log_util.h"
#include "net/net_buildflags.h"
#include "net/nqe/network_quality_estimator_params.h"
#include "net/proxy_resolution/proxy_config_service_fixed.h"
#include "net/proxy_resolution/proxy_resolution_service.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_versions.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 "net/url_request/url_request_interceptor.h"

#if BUILDFLAG(ENABLE_REPORTING)
#include "net/network_error_logging/network_error_logging_service.h"
#include "net/reporting/reporting_service.h"
#endif  // BUILDFLAG(ENABLE_REPORTING)

namespace {

// When enabled Cronet advertises zstd support. Suffixed with V2 to avoid
// clashing with previous feature flag that was rolled back in
// https://crrev.com/c/6458938.
BASE_FEATURE(kEnableZstd, "EnableZstdV2", base::FEATURE_DISABLED_BY_DEFAULT);

// This class wraps a NetLog that also contains network change events.
class NetLogWithNetworkChangeEvents {
 public:
  NetLogWithNetworkChangeEvents() : net_log_(net::NetLog::Get()) {}

  NetLogWithNetworkChangeEvents(const NetLogWithNetworkChangeEvents&) = delete;
  NetLogWithNetworkChangeEvents& operator=(
      const NetLogWithNetworkChangeEvents&) = delete;

  net::NetLog* net_log() { return net_log_; }
  // This function registers with the NetworkChangeNotifier and so must be
  // called *after* the NetworkChangeNotifier is created. Should only be
  // called on the init thread as it is not thread-safe and the init thread is
  // the thread the NetworkChangeNotifier is created on. This function is
  // not thread-safe because accesses to `net_change_logger_` are not atomic.
  // There might be multiple CronetEngines each with a network thread so
  // so the init thread is used. `net_log_` also outlives the network threads
  // so it would be unsafe to receive callbacks on the network threads without
  // a complicated thread-safe reference-counting system to control callback
  // registration.
  void EnsureInitializedOnInitThread() {
    DCHECK(cronet::OnInitThread());
    if (net_change_logger_)
      return;
    net_change_logger_ =
        std::make_unique<net::LoggingNetworkChangeObserver>(net_log_);
  }

 private:
  raw_ptr<net::NetLog> net_log_;
  // LoggingNetworkChangeObserver logs network change events to a NetLog.
  // This class bundles one LoggingNetworkChangeObserver with one NetLog,
  // so network change event are logged just once in the NetLog.
  std::unique_ptr<net::LoggingNetworkChangeObserver> net_change_logger_;
};

// Use a global NetLog instance. See crbug.com/486120.
NetLogWithNetworkChangeEvents& GetNetLog() {
  static base::NoDestructor<NetLogWithNetworkChangeEvents> net_log;
  return *net_log;
}

class BasicNetworkDelegate : public net::NetworkDelegateImpl {
 public:
  BasicNetworkDelegate() = default;

  BasicNetworkDelegate(const BasicNetworkDelegate&) = delete;
  BasicNetworkDelegate& operator=(const BasicNetworkDelegate&) = delete;

  ~BasicNetworkDelegate() override {}

 private:
  // net::NetworkDelegate implementation.
  bool OnAnnotateAndMoveUserBlockedCookies(
      const net::URLRequest& request,
      const net::FirstPartySetMetadata& first_party_set_metadata,
      net::CookieAccessResultList& maybe_included_cookies,
      net::CookieAccessResultList& excluded_cookies) override {
    // Disallow sending cookies by default.
    ExcludeAllCookies(
        net::CookieInclusionStatus::ExclusionReason::EXCLUDE_USER_PREFERENCES,
        maybe_included_cookies, excluded_cookies);
    return false;
  }

  bool OnCanSetCookie(
      const net::URLRequest& request,
      const net::CanonicalCookie& cookie,
      net::CookieOptions* options,
      const net::FirstPartySetMetadata& first_party_set_metadata,
      net::CookieInclusionStatus* inclusion_status) override {
    // Disallow saving cookies by default.
    return false;
  }
};

// Helper function to make a net::URLRequestContext aware of a QUIC hint.
void SetQuicHint(net::URLRequestContext* context,
                 const cronet::URLRequestContextConfig::QuicHint* quic_hint) {
  if (quic_hint->host.empty()) {
    LOG(ERROR) << "Empty QUIC hint host: " << quic_hint->host;
    return;
  }

  url::CanonHostInfo host_info;
  std::string canon_host(net::CanonicalizeHost(quic_hint->host, &host_info));
  if (!host_info.IsIPAddress() &&
      !net::IsCanonicalizedHostCompliant(canon_host)) {
    LOG(ERROR) << "Invalid QUIC hint host: " << quic_hint->host;
    return;
  }

  if (quic_hint->port <= std::numeric_limits<uint16_t>::min() ||
      quic_hint->port > std::numeric_limits<uint16_t>::max()) {
    LOG(ERROR) << "Invalid QUIC hint port: " << quic_hint->port;
    return;
  }

  if (quic_hint->alternate_port <= std::numeric_limits<uint16_t>::min() ||
      quic_hint->alternate_port > std::numeric_limits<uint16_t>::max()) {
    LOG(ERROR) << "Invalid QUIC hint alternate port: "
               << quic_hint->alternate_port;
    return;
  }

  url::SchemeHostPort quic_server("https", canon_host, quic_hint->port);
  net::AlternativeService alternative_service(
      net::NextProto::kProtoQUIC, "",
      static_cast<uint16_t>(quic_hint->alternate_port));
  context->http_server_properties()->SetQuicAlternativeService(
      quic_server, net::NetworkAnonymizationKey(), alternative_service,
      base::Time::Max(), quic::ParsedQuicVersionVector());
}

// net::NetworkChangeNotifier doesn't provide an API to query if a specific
// network has become disconnected. For these network though, it will return
// CONNECTION_UNKNOWN as their connection type. This should be a good enough
// approximation for the time being.
bool IsNetworkNoLongerConnected(net::handles::NetworkHandle network) {
  return net::NetworkChangeNotifier::GetNetworkConnectionType(network) ==
         net::NetworkChangeNotifier::CONNECTION_UNKNOWN;
}

}  // namespace

namespace cronet {

CronetContext::CronetContext(
    std::unique_ptr<URLRequestContextConfig> context_config,
    std::unique_ptr<Callback> callback,
    scoped_refptr<base::SingleThreadTaskRunner> network_task_runner)
    : bidi_stream_detect_broken_connection_(
          context_config->bidi_stream_detect_broken_connection),
      heartbeat_interval_(context_config->heartbeat_interval),
      default_load_flags_(
          net::LOAD_NORMAL |
          (context_config->load_disable_cache ? net::LOAD_DISABLE_CACHE : 0) |
          (context_config->enable_brotli ? net::LOAD_CAN_USE_SHARED_DICTIONARY
                                         : 0)),
      network_tasks_(
          new NetworkTasks(std::move(context_config), std::move(callback))),
      network_task_runner_(network_task_runner) {
  if (!network_task_runner_) {
    network_thread_ = std::make_unique<base::Thread>("CronetNet");
    base::Thread::Options options;
    options.message_pump_type = base::MessagePumpType::IO;
    network_thread_->StartWithOptions(std::move(options));
    network_task_runner_ = network_thread_->task_runner();
  }
}

CronetContext::~CronetContext() {
  DCHECK(!GetNetworkTaskRunner()->BelongsToCurrentThread());
  GetNetworkTaskRunner()->DeleteSoon(FROM_HERE, network_tasks_.get());
}

CronetContext::NetworkTasks::NetworkTasks(
    std::unique_ptr<URLRequestContextConfig> context_config,
    std::unique_ptr<CronetContext::Callback> callback)
    : default_context_(nullptr),
      is_default_context_initialized_(false),
      context_config_(std::move(context_config)),
      callback_(std::move(callback)) {
  DETACH_FROM_THREAD(network_thread_checker_);
}

CronetContext::NetworkTasks::~NetworkTasks() {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  callback_->OnDestroyNetworkThread();

  if (cronet_prefs_manager_)
    cronet_prefs_manager_->PrepareForShutdown();

  if (network_quality_estimator_) {
    network_quality_estimator_->RemoveRTTObserver(this);
    network_quality_estimator_->RemoveThroughputObserver(this);
    network_quality_estimator_->RemoveEffectiveConnectionTypeObserver(this);
    network_quality_estimator_->RemoveRTTAndThroughputEstimatesObserver(this);
  }

  if (net::NetworkChangeNotifier::AreNetworkHandlesSupported())
    net::NetworkChangeNotifier::RemoveNetworkObserver(this);
}

void CronetContext::InitRequestContextOnInitThread() {
  DCHECK(OnInitThread());
  // Cannot create this inside Initialize because Android requires this to be
  // created on the JNI thread.
  auto proxy_config_service =
      cronet::CreateProxyConfigService(GetNetworkTaskRunner());
  GetNetLog().EnsureInitializedOnInitThread();
  GetNetworkTaskRunner()->PostTask(
      FROM_HERE,
      base::BindOnce(&CronetContext::NetworkTasks::Initialize,
                     base::Unretained(network_tasks_), GetNetworkTaskRunner(),
                     GetFileThread()->task_runner(),
                     std::move(proxy_config_service)));
}

void CronetContext::NetworkTasks::ConfigureNetworkQualityEstimatorForTesting(
    bool use_local_host_requests,
    bool use_smaller_responses,
    bool disable_offline_check) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  network_quality_estimator_->SetUseLocalHostRequestsForTesting(
      use_local_host_requests);
  network_quality_estimator_->SetUseSmallResponsesForTesting(
      use_smaller_responses);
  network_quality_estimator_->DisableOfflineCheckForTesting(
      disable_offline_check);
}

void CronetContext::ConfigureNetworkQualityEstimatorForTesting(
    bool use_local_host_requests,
    bool use_smaller_responses,
    bool disable_offline_check) {
  PostTaskToNetworkThread(
      FROM_HERE,
      base::BindOnce(&CronetContext::NetworkTasks::
                         ConfigureNetworkQualityEstimatorForTesting,
                     base::Unretained(network_tasks_), use_local_host_requests,
                     use_smaller_responses, disable_offline_check));
}

bool CronetContext::URLRequestContextExistsForTesting(
    net::handles::NetworkHandle network) {
  DCHECK(IsOnNetworkThread());
  return network_tasks_->URLRequestContextExistsForTesting(network);  // IN-TEST
}

void CronetContext::NetworkTasks::ProvideRTTObservations(bool should) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  if (!network_quality_estimator_)
    return;
  if (should) {
    network_quality_estimator_->AddRTTObserver(this);
  } else {
    network_quality_estimator_->RemoveRTTObserver(this);
  }
}

void CronetContext::ProvideRTTObservations(bool should) {
  PostTaskToNetworkThread(
      FROM_HERE,
      base::BindOnce(&CronetContext::NetworkTasks::ProvideRTTObservations,
                     base::Unretained(network_tasks_), should));
}

void CronetContext::NetworkTasks::ProvideThroughputObservations(bool should) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  if (!network_quality_estimator_)
    return;
  if (should) {
    network_quality_estimator_->AddThroughputObserver(this);
  } else {
    network_quality_estimator_->RemoveThroughputObserver(this);
  }
}

void CronetContext::ProvideThroughputObservations(bool should) {
  PostTaskToNetworkThread(
      FROM_HERE,
      base::BindOnce(
          &CronetContext::NetworkTasks::ProvideThroughputObservations,
          base::Unretained(network_tasks_), should));
}

void CronetContext::NetworkTasks::SpawnNetworkBoundURLRequestContextForTesting(
    net::handles::NetworkHandle network) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  DCHECK(!contexts_.contains(network));
  contexts_[network] = BuildNetworkBoundURLRequestContext(network);
}

bool CronetContext::NetworkTasks::URLRequestContextExistsForTesting(
    net::handles::NetworkHandle network) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  return contexts_.contains(network);
}

std::unique_ptr<net::URLRequestContext>
CronetContext::NetworkTasks::BuildDefaultURLRequestContext(
    std::unique_ptr<net::ProxyConfigService> proxy_config_service) {
  DCHECK(!network_quality_estimator_);
  DCHECK(!cronet_prefs_manager_);
  net::URLRequestContextBuilder context_builder;
  context_config_->ConfigureURLRequestContextBuilder(&context_builder, this);
  SetSharedURLRequestContextBuilderConfig(&context_builder);

  context_builder.set_proxy_resolution_service(
      cronet::CreateProxyResolutionService(std::move(proxy_config_service),
                                           GetNetLog().net_log()));

  if (context_config_->enable_network_quality_estimator) {
    std::unique_ptr<net::NetworkQualityEstimatorParams> nqe_params =
        std::make_unique<net::NetworkQualityEstimatorParams>(
            std::map<std::string, std::string>());
    if (context_config_->nqe_forced_effective_connection_type) {
      nqe_params->SetForcedEffectiveConnectionType(
          context_config_->nqe_forced_effective_connection_type.value());
    }

    network_quality_estimator_ = std::make_unique<net::NetworkQualityEstimator>(
        std::move(nqe_params), GetNetLog().net_log());
    network_quality_estimator_->AddEffectiveConnectionTypeObserver(this);
    network_quality_estimator_->AddRTTAndThroughputEstimatesObserver(this);

    context_builder.set_network_quality_estimator(
        network_quality_estimator_.get());
  }

  // Set up pref file if storage path is specified.
  if (!context_config_->storage_path.empty()) {
#if BUILDFLAG(IS_WIN)
    base::FilePath storage_path(
        base::FilePath::FromUTF8Unsafe(context_config_->storage_path));
#else
    base::FilePath storage_path(context_config_->storage_path);
#endif
    // Currently only the default context uses a PrefManager, this means that
    // contexts for specific networks do not maintain state between restarts.
    // Part of that is by design, part of that is due to CronetPrefsManager's
    // current interface: it assumes that a single URLRequestContext exists
    // and, under that assumption, mixes NQE, HostCache, and
    // HttpServerProperties management persistence. The former two should
    // apply only to the default context, while the latter could also be
    // applied to network-bound contexts.
    // TODO(stefanoduo): Decouple CronetPrefManager management of NQE,
    // HostCache and HttpServerProperties and apply HttpServerProperties to
    // network bound contexts.
    cronet_prefs_manager_ = std::make_unique<CronetPrefsManager>(
        context_config_->storage_path, network_task_runner_, file_task_runner_,
        context_config_->enable_network_quality_estimator,
        context_config_->enable_host_cache_persistence, GetNetLog().net_log(),
        &context_builder);
  }

  auto context = context_builder.Build();

  // Set up host cache persistence if it's enabled. Happens after building the
  // URLRequestContext to get access to the HostCache.
  if (context_config_->enable_host_cache_persistence && cronet_prefs_manager_) {
    net::HostCache* host_cache = context->host_resolver()->GetHostCache();
    cronet_prefs_manager_->SetupHostCachePersistence(
        host_cache, context_config_->host_cache_persistence_delay_ms,
        GetNetLog().net_log());
  }

  SetSharedURLRequestContextConfig(context.get());
  return context;
}

std::unique_ptr<net::URLRequestContext>
CronetContext::NetworkTasks::BuildNetworkBoundURLRequestContext(
    net::handles::NetworkHandle network) {
  net::URLRequestContextBuilder context_builder;
  context_config_->ConfigureURLRequestContextBuilder(&context_builder, this,
                                                     network);
  SetSharedURLRequestContextBuilderConfig(&context_builder);

  // On Android, Cronet doesn't handle PAC URL processing, instead it defers
  // that to the OS (which sets up a local proxy configured correctly w.r.t.
  // Android settings). See crbug.com/432539.
  // TODO(stefanoduo): Confirm if we can keep using this configuration for
  // requests bound to a network (otherwise we might have to query that
  // network's LinkProperties#getHttpProxy).
  // Until then don't support proxies when a network is specified.
  context_builder.set_proxy_config_service(
      std::make_unique<net::ProxyConfigServiceFixed>(
          net::ProxyConfigWithAnnotation::CreateDirect()));

  auto context = context_builder.Build();
  SetSharedURLRequestContextConfig(context.get());
  return context;
}

void CronetContext::NetworkTasks::SetSharedURLRequestContextBuilderConfig(
    net::URLRequestContextBuilder* context_builder) {
  context_builder->set_network_delegate(
      std::make_unique<BasicNetworkDelegate>());
  context_builder->set_net_log(GetNetLog().net_log());

  // Explicitly disable the persister for Cronet to avoid persistence of dynamic
  // HPKP. This is a safety measure ensuring that nobody enables the persistence
  // of HPKP by specifying transport_security_persister_file_path in the future.
  context_builder->set_transport_security_persister_file_path(base::FilePath());

  // Disable net::CookieStore.
  context_builder->SetCookieStore(nullptr);

  context_builder->set_check_cleartext_permitted(true);
  context_builder->set_enable_brotli(context_config_->enable_brotli);
  context_builder->set_enable_zstd(base::FeatureList::IsEnabled(kEnableZstd));
  context_builder->set_enable_shared_dictionary(context_config_->enable_brotli);
}

void CronetContext::NetworkTasks::SetSharedURLRequestContextConfig(
    net::URLRequestContext* context) {
  if (context_config_->enable_quic) {
    for (const auto& quic_hint : context_config_->quic_hints)
      SetQuicHint(context, quic_hint.get());
  }

  // Iterate through PKP configuration for every host.
  for (const auto& pkp : context_config_->pkp_list) {
    // Add the host pinning.
    context->transport_security_state()->AddHPKP(
        pkp->host, pkp->expiration_date, pkp->include_subdomains,
        pkp->pin_hashes);
  }

  context->transport_security_state()
      ->SetEnablePublicKeyPinningBypassForLocalTrustAnchors(
          context_config_->bypass_public_key_pinning_for_local_trust_anchors);

#if BUILDFLAG(ENABLE_REPORTING)
  if (context->reporting_service()) {
    for (const auto& preloaded_header :
         context_config_->preloaded_report_to_headers) {
      context->reporting_service()->ProcessReportToHeader(
          preloaded_header.origin, net::NetworkAnonymizationKey(),
          preloaded_header.value);
    }
  }

  if (context->network_error_logging_service()) {
    for (const auto& preloaded_header :
         context_config_->preloaded_nel_headers) {
      context->network_error_logging_service()->OnHeader(
          net::NetworkAnonymizationKey(), preloaded_header.origin,
          net::IPAddress(), preloaded_header.value);
    }
  }
#endif  // BUILDFLAG(ENABLE_REPORTING)
}

void CronetContext::NetworkTasks::Initialize(
    scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
    scoped_refptr<base::SequencedTaskRunner> file_task_runner,
    std::unique_ptr<net::ProxyConfigService> proxy_config_service) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  DCHECK(!is_default_context_initialized_);

  network_task_runner_ = network_task_runner;
  file_task_runner_ = file_task_runner;
  if (context_config_->network_thread_priority)
    SetNetworkThreadPriorityOnNetworkThread(
        context_config_->network_thread_priority.value());
  base::DisallowBlocking();
  effective_experimental_options_ =
      context_config_->effective_experimental_options.Clone();

  const net::handles::NetworkHandle default_network =
      net::handles::kInvalidNetworkHandle;
  contexts_[default_network] =
      BuildDefaultURLRequestContext(std::move(proxy_config_service));
  default_context_ = contexts_[default_network].get();

  if (net::NetworkChangeNotifier::AreNetworkHandlesSupported())
    net::NetworkChangeNotifier::AddNetworkObserver(this);

  callback_->OnInitNetworkThread();
  is_default_context_initialized_ = true;

  if (context_config_->enable_network_quality_estimator &&
      cronet_prefs_manager_) {
    cronet_prefs_manager_->SetupNqePersistence(
        network_quality_estimator_.get());
  }

  while (!tasks_waiting_for_context_.empty()) {
    std::move(tasks_waiting_for_context_.front()).Run();
    tasks_waiting_for_context_.pop();
  }
}

net::URLRequestContext* CronetContext::NetworkTasks::GetURLRequestContext(
    net::handles::NetworkHandle network) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  DCHECK(is_default_context_initialized_);

  if (network == net::handles::kInvalidNetworkHandle)
    return default_context_;

  // Non-default contexts are created on the fly.
  if (contexts_.find(network) == contexts_.end())
    contexts_[network] = BuildNetworkBoundURLRequestContext(network);
  return contexts_[network].get();
}

void CronetContext::NetworkTasks::MaybeDestroyURLRequestContext(
    net::handles::NetworkHandle network) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);

  // Default network context is never deleted.
  if (network == net::handles::kInvalidNetworkHandle)
    return;
  if (!contexts_.contains(network))
    return;

  auto& context = contexts_[network];
  // For a URLRequestContext to be destroyed, two conditions must be satisfied:
  // 1. The network associated to that context must be no longer connected
  // 2. There must be no URLRequests associated to that context
  if (context->url_requests()->size() == 0 &&
      IsNetworkNoLongerConnected(network)) {
    contexts_.erase(network);
  }
}

// Request context getter for CronetContext.
class CronetContext::ContextGetter : public net::URLRequestContextGetter {
 public:
  explicit ContextGetter(CronetContext* cronet_context)
      : cronet_context_(cronet_context) {
    DCHECK(cronet_context_);
  }

  ContextGetter(const ContextGetter&) = delete;
  ContextGetter& operator=(const ContextGetter&) = delete;

  net::URLRequestContext* GetURLRequestContext() override {
    return cronet_context_->GetURLRequestContext();
  }

  scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
      const override {
    return cronet_context_->GetNetworkTaskRunner();
  }

 private:
  // Must be called on the network thread.
  ~ContextGetter() override { DCHECK(cronet_context_->IsOnNetworkThread()); }

  // CronetContext associated with this ContextGetter.
  const raw_ptr<CronetContext> cronet_context_;
};

net::URLRequestContextGetter* CronetContext::CreateURLRequestContextGetter() {
  DCHECK(IsOnNetworkThread());
  return new ContextGetter(this);
}

net::URLRequestContext* CronetContext::GetURLRequestContext(
    net::handles::NetworkHandle network) {
  DCHECK(IsOnNetworkThread());
  return network_tasks_->GetURLRequestContext(network);
}

void CronetContext::PostTaskToNetworkThread(const base::Location& posted_from,
                                            base::OnceClosure callback) {
  GetNetworkTaskRunner()->PostTask(
      posted_from,
      base::BindOnce(&CronetContext::NetworkTasks::RunTaskAfterContextInit,
                     base::Unretained(network_tasks_), std::move(callback)));
}

void CronetContext::NetworkTasks::RunTaskAfterContextInit(
    base::OnceClosure task_to_run_after_context_init) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  if (is_default_context_initialized_) {
    DCHECK(tasks_waiting_for_context_.empty());
    std::move(task_to_run_after_context_init).Run();
    return;
  }
  tasks_waiting_for_context_.push(std::move(task_to_run_after_context_init));
}

bool CronetContext::IsOnNetworkThread() const {
  return GetNetworkTaskRunner()->BelongsToCurrentThread();
}

scoped_refptr<base::SingleThreadTaskRunner>
CronetContext::GetNetworkTaskRunner() const {
  return network_task_runner_;
}

bool CronetContext::StartNetLogToFile(const std::string& file_name,
                                      bool log_all) {
#if BUILDFLAG(IS_WIN)
  base::FilePath file_path(base::FilePath::FromUTF8Unsafe(file_name));
#else
  base::FilePath file_path(file_name);
#endif
  base::ScopedFILE file(base::OpenFile(file_path, "w"));
  if (!file) {
    LOG(ERROR) << "Failed to open NetLog file for writing.";
    return false;
  }
  PostTaskToNetworkThread(
      FROM_HERE,
      base::BindOnce(&CronetContext::NetworkTasks::StartNetLog,
                     base::Unretained(network_tasks_), file_path, log_all));
  return true;
}

void CronetContext::StartNetLogToDisk(const std::string& dir_name,
                                      bool log_all,
                                      int max_size) {
  PostTaskToNetworkThread(
      FROM_HERE,
      base::BindOnce(&CronetContext::NetworkTasks::StartNetLogToBoundedFile,
                     base::Unretained(network_tasks_), dir_name, log_all,
                     max_size));
}

void CronetContext::StopNetLog() {
  DCHECK(!GetNetworkTaskRunner()->BelongsToCurrentThread());
  PostTaskToNetworkThread(
      FROM_HERE, base::BindOnce(&CronetContext::NetworkTasks::StopNetLog,
                                base::Unretained(network_tasks_)));
}

void CronetContext::FlushWritePropertiesForTesting() {
  base::WaitableEvent wait_for_callback;
  network_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](NetworkTasks* network_tasks, base::OnceClosure callback) {
            network_tasks
                ->GetURLRequestContext(net::handles::kInvalidNetworkHandle)
                ->http_server_properties()
                ->FlushWritePropertiesForTesting(  // IN-TEST
                    std::move(callback));
          },
          network_tasks_,
          base::BindOnce(&base::WaitableEvent::Signal,
                         base::Unretained(&wait_for_callback))));
  wait_for_callback.Wait();
}

void CronetContext::MaybeDestroyURLRequestContext(
    net::handles::NetworkHandle network) {
  DCHECK(IsOnNetworkThread());
  network_tasks_->MaybeDestroyURLRequestContext(network);
}

int CronetContext::default_load_flags() const {
  return default_load_flags_;
}

base::Thread* CronetContext::GetFileThread() {
  DCHECK(OnInitThread());
  if (!file_thread_) {
    file_thread_ = std::make_unique<base::Thread>("CronetFile");
    file_thread_->Start();
  }
  return file_thread_.get();
}

void CronetContext::NetworkTasks::OnEffectiveConnectionTypeChanged(
    net::EffectiveConnectionType effective_connection_type) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  callback_->OnEffectiveConnectionTypeChanged(effective_connection_type);
}

void CronetContext::NetworkTasks::OnRTTOrThroughputEstimatesComputed(
    base::TimeDelta http_rtt,
    base::TimeDelta transport_rtt,
    int32_t downstream_throughput_kbps) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);

  int32_t http_rtt_ms = http_rtt.InMilliseconds() <= INT32_MAX
                            ? static_cast<int32_t>(http_rtt.InMilliseconds())
                            : INT32_MAX;
  int32_t transport_rtt_ms =
      transport_rtt.InMilliseconds() <= INT32_MAX
          ? static_cast<int32_t>(transport_rtt.InMilliseconds())
          : INT32_MAX;

  callback_->OnRTTOrThroughputEstimatesComputed(http_rtt_ms, transport_rtt_ms,
                                                downstream_throughput_kbps);
}

void CronetContext::NetworkTasks::OnRTTObservation(
    int32_t rtt_ms,
    const base::TimeTicks& timestamp,
    net::NetworkQualityObservationSource source) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);

  callback_->OnRTTObservation(
      rtt_ms, (timestamp - base::TimeTicks::UnixEpoch()).InMilliseconds(),
      source);
}

void CronetContext::NetworkTasks::OnThroughputObservation(
    int32_t throughput_kbps,
    const base::TimeTicks& timestamp,
    net::NetworkQualityObservationSource source) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);

  callback_->OnThroughputObservation(
      throughput_kbps,
      (timestamp - base::TimeTicks::UnixEpoch()).InMilliseconds(), source);
}

void CronetContext::NetworkTasks::OnNetworkDisconnected(
    net::handles::NetworkHandle network) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);

  if (!contexts_.contains(network))
    return;

  auto& context = contexts_[network];
  // After `network` disconnects, we can delete the URLRequestContext
  // associated with it only if it has no pending URLRequests.
  // If there are, their destruction procedure will take care of destroying
  // this context (see MaybeDestroyURLRequestContext for more info).
  if (context->url_requests()->size() == 0)
    contexts_.erase(network);
}

void CronetContext::NetworkTasks::OnNetworkConnected(
    net::handles::NetworkHandle network) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
}
void CronetContext::NetworkTasks::OnNetworkSoonToDisconnect(
    net::handles::NetworkHandle network) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
}
void CronetContext::NetworkTasks::OnNetworkMadeDefault(
    net::handles::NetworkHandle network) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
}

void CronetContext::NetworkTasks::StartNetLog(const base::FilePath& file_path,
                                              bool include_socket_bytes) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);

  // Do nothing if already logging to a file.
  if (net_log_file_observer_)
    return;

  net::NetLogCaptureMode capture_mode =
      include_socket_bytes ? net::NetLogCaptureMode::kEverything
                           : net::NetLogCaptureMode::kDefault;
  net_log_file_observer_ = net::FileNetLogObserver::CreateUnbounded(
      file_path, capture_mode, /*constants=*/nullptr);
  std::set<net::URLRequestContext*> contexts;
  for (auto& iter : contexts_)
    contexts.insert(iter.second.get());
  CreateNetLogEntriesForActiveObjects(contexts, net_log_file_observer_.get());
  net_log_file_observer_->StartObserving(GetNetLog().net_log());
}

void CronetContext::NetworkTasks::StartNetLogToBoundedFile(
    const std::string& dir_path,
    bool include_socket_bytes,
    int size) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);

  // Do nothing if already logging to a directory.
  if (net_log_file_observer_) {
    return;
  }

  // TODO(eroman): The cronet API passes a directory here. But it should now
  // just pass a file path.
#if BUILDFLAG(IS_WIN)
  base::FilePath file_path(base::FilePath::FromUTF8Unsafe(dir_path));
#else
  base::FilePath file_path(dir_path);
#endif
  file_path = file_path.AppendASCII("netlog.json");

  {
    base::ScopedAllowBlocking allow_blocking;
    if (!base::PathIsWritable(file_path)) {
      LOG(ERROR) << "Path is not writable: " << file_path.value();
    }
  }

  net::NetLogCaptureMode capture_mode =
      include_socket_bytes ? net::NetLogCaptureMode::kEverything
                           : net::NetLogCaptureMode::kDefault;
  net_log_file_observer_ = net::FileNetLogObserver::CreateBounded(
      file_path, size, capture_mode, /*constants=*/nullptr);

  std::set<net::URLRequestContext*> contexts;
  for (auto& iter : contexts_)
    contexts.insert(iter.second.get());
  CreateNetLogEntriesForActiveObjects(contexts, net_log_file_observer_.get());

  net_log_file_observer_->StartObserving(GetNetLog().net_log());
}

void CronetContext::NetworkTasks::StopNetLog() {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);

  if (!net_log_file_observer_)
    return;
  net_log_file_observer_->StopObserving(
      base::Value::ToUniquePtrValue(GetNetLogInfo()),
      base::BindOnce(&CronetContext::NetworkTasks::StopNetLogCompleted,
                     base::Unretained(this)));
  net_log_file_observer_.reset();
}

void CronetContext::NetworkTasks::StopNetLogCompleted() {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  callback_->OnStopNetLogCompleted();
}

void CronetContext::NetworkTasks::OnBeforeTunnelRequest(
    int chain_id,
    net::ProxyDelegate::OnBeforeTunnelRequestCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  callback_->OnBeforeTunnelRequest(chain_id, std::move(callback));
}

void CronetContext::NetworkTasks::OnTunnelHeadersReceived(
    int chain_id,
    const net::HttpResponseHeaders& response_headers,
    net::CompletionOnceCallback callback) {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  callback_->OnTunnelHeadersReceived(chain_id, response_headers,
                                     std::move(callback));
}

base::Value CronetContext::NetworkTasks::GetNetLogInfo() const {
  base::Value::Dict net_info;
  for (auto& iter : contexts_)
    net_info.Set(base::NumberToString(iter.first),
                 net::GetNetInfo(iter.second.get()));
  if (!effective_experimental_options_.empty()) {
    net_info.Set("cronetExperimentalParams",
                 effective_experimental_options_.Clone());
  }
  return base::Value(std::move(net_info));
}

}  // namespace cronet
