// Copyright 2017 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 "services/network/network_service.h"

#include <map>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/task/post_task.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "components/os_crypt/os_crypt.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/bindings/type_converter.h"
#include "net/base/logging_network_change_observer.h"
#include "net/base/network_change_notifier.h"
#include "net/base/port_util.h"
#include "net/cert/cert_database.h"
#include "net/cert/ct_log_response_parser.h"
#include "net/cert/signed_tree_head.h"
#include "net/dns/dns_config_overrides.h"
#include "net/dns/host_resolver.h"
#include "net/dns/mapped_host_resolver.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/log/file_net_log_observer.h"
#include "net/log/net_log.h"
#include "net/log/net_log_capture_mode.h"
#include "net/log/net_log_util.h"
#include "net/ssl/ssl_key_logger_impl.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_builder.h"
#include "services/network/crl_set_distributor.h"
#include "services/network/cross_origin_read_blocking.h"
#include "services/network/dns_config_change_manager.h"
#include "services/network/http_auth_cache_copier.h"
#include "services/network/net_log_capture_mode_type_converter.h"
#include "services/network/net_log_exporter.h"
#include "services/network/network_context.h"
#include "services/network/network_usage_accumulator.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/url_loader.h"
#include "services/network/url_request_context_builder_mojo.h"

#if BUILDFLAG(IS_CT_SUPPORTED)
#include "components/certificate_transparency/sth_distributor.h"
#endif  // BUILDFLAG(IS_CT_SUPPORTED)

#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
#include "crypto/openssl_util.h"
#include "third_party/boringssl/src/include/openssl/cpu.h"
#endif

#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && !defined(IS_CHROMECAST)
#include "components/os_crypt/key_storage_config_linux.h"
#endif

#if defined(OS_ANDROID)
#include "base/android/application_status_listener.h"
#include "net/android/http_auth_negotiate_android.h"
#endif

namespace network {

namespace {

NetworkService* g_network_service = nullptr;

net::NetLog* GetNetLog() {
  static base::NoDestructor<net::NetLog> instance;
  return instance.get();
}

// The interval for calls to NetworkService::UpdateLoadStates
constexpr auto kUpdateLoadStatesInterval =
    base::TimeDelta::FromMilliseconds(250);

std::unique_ptr<net::NetworkChangeNotifier>
CreateNetworkChangeNotifierIfNeeded() {
  // There is a global singleton net::NetworkChangeNotifier if NetworkService
  // is running inside of the browser process.
  if (!net::NetworkChangeNotifier::HasNetworkChangeNotifier()) {
#if defined(OS_ANDROID)
    // On Android, NetworkChangeNotifier objects are always set up in process
    // before NetworkService is run.
    return nullptr;
#elif defined(OS_IOS) || defined(OS_FUCHSIA)
    // iOS doesn't embed //content. Fuchsia doesn't have an implementation yet.
    // TODO(xunjieli): Figure out what to do for these 2 platforms.
    NOTIMPLEMENTED();
    return nullptr;
#endif
    return base::WrapUnique(net::NetworkChangeNotifier::Create());
  }
  return nullptr;
}

std::unique_ptr<net::HostResolver> CreateHostResolver(net::NetLog* net_log) {
  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();
  std::unique_ptr<net::HostResolver> host_resolver(
      net::HostResolver::CreateDefaultResolver(net_log));
  if (!command_line.HasSwitch(switches::kHostResolverRules))
    return host_resolver;

  std::unique_ptr<net::MappedHostResolver> remapped_host_resolver(
      new net::MappedHostResolver(std::move(host_resolver)));
  remapped_host_resolver->SetRulesFromString(
      command_line.GetSwitchValueASCII(switches::kHostResolverRules));
  return std::move(remapped_host_resolver);
}

// This is duplicated in content/browser/loader/resource_dispatcher_host_impl.cc
bool LoadInfoIsMoreInteresting(const mojom::LoadInfo& a,
                               const mojom::LoadInfo& b) {
  // Set |*_uploading_size| to be the size of the corresponding upload body if
  // it's currently being uploaded.

  uint64_t a_uploading_size = 0;
  if (a.load_state == net::LOAD_STATE_SENDING_REQUEST)
    a_uploading_size = a.upload_size;

  uint64_t b_uploading_size = 0;
  if (b.load_state == net::LOAD_STATE_SENDING_REQUEST)
    b_uploading_size = b.upload_size;

  if (a_uploading_size != b_uploading_size)
    return a_uploading_size > b_uploading_size;

  return a.load_state > b.load_state;
}

#if defined(OS_ANDROID) && BUILDFLAG(USE_KERBEROS)
// Used for Negotiate authentication on Android, which needs to generate tokens
// in the browser process.
class NetworkServiceAuthNegotiateAndroid : public net::HttpNegotiateAuthSystem {
 public:
  NetworkServiceAuthNegotiateAndroid(NetworkService* network_service,
                                     const net::HttpAuthPreferences* prefs)
      : network_service_(network_service), auth_negotiate_(prefs) {}
  ~NetworkServiceAuthNegotiateAndroid() override = default;

  // HttpNegotiateAuthSystem implementation:
  bool Init() override { return auth_negotiate_.Init(); }

  bool NeedsIdentity() const override {
    return auth_negotiate_.NeedsIdentity();
  }

  bool AllowsExplicitCredentials() const override {
    return auth_negotiate_.AllowsExplicitCredentials();
  }

  net::HttpAuth::AuthorizationResult ParseChallenge(
      net::HttpAuthChallengeTokenizer* tok) override {
    return auth_negotiate_.ParseChallenge(tok);
  }

  int GenerateAuthToken(const net::AuthCredentials* credentials,
                        const std::string& spn,
                        const std::string& channel_bindings,
                        std::string* auth_token,
                        net::CompletionOnceCallback callback) override {
    network_service_->client()->OnGenerateHttpNegotiateAuthToken(
        auth_negotiate_.server_auth_token(), auth_negotiate_.can_delegate(),
        auth_negotiate_.GetAuthAndroidNegotiateAccountType(), spn,
        base::BindOnce(&NetworkServiceAuthNegotiateAndroid::Finish,
                       weak_factory_.GetWeakPtr(), auth_token,
                       std::move(callback)));
    return net::ERR_IO_PENDING;
  }

  void Delegate() override { auth_negotiate_.Delegate(); }

 private:
  void Finish(std::string* auth_token_out,
              net::CompletionOnceCallback callback,
              int result,
              const std::string& auth_token) {
    *auth_token_out = auth_token;
    std::move(callback).Run(result);
  }

  NetworkService* network_service_ = nullptr;
  net::android::HttpAuthNegotiateAndroid auth_negotiate_;
  base::WeakPtrFactory<NetworkServiceAuthNegotiateAndroid> weak_factory_{this};
};

std::unique_ptr<net::HttpNegotiateAuthSystem> CreateAuthSystem(
    NetworkService* network_service,
    const net::HttpAuthPreferences* prefs) {
  return std::make_unique<NetworkServiceAuthNegotiateAndroid>(network_service,
                                                              prefs);
}
#endif

}  // namespace

NetworkService::NetworkService(
    std::unique_ptr<service_manager::BinderRegistry> registry,
    mojom::NetworkServiceRequest request,
    net::NetLog* net_log,
    service_manager::mojom::ServiceRequest service_request)
    : registry_(std::move(registry)), binding_(this) {
  DCHECK(!g_network_service);
  g_network_service = this;

  // In testing environments, |service_request| may not be provided.
  if (service_request.is_pending())
    service_binding_.Bind(std::move(service_request));

  // |registry_| is nullptr when an in-process NetworkService is
  // created directly. The latter is done in concert with using
  // CreateNetworkContextWithBuilder to ease the transition to using the
  // network service.
  if (registry_) {
    DCHECK(!request.is_pending());
    registry_->AddInterface<mojom::NetworkService>(
        base::BindRepeating(&NetworkService::Bind, base::Unretained(this)));
  } else if (request.is_pending()) {
    Bind(std::move(request));
  }

#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
  // Make sure OpenSSL is initialized before using it to histogram data.
  crypto::EnsureOpenSSLInit();

  // Measure CPUs with broken NEON units. See https://crbug.com/341598.
  UMA_HISTOGRAM_BOOLEAN("Net.HasBrokenNEON", CRYPTO_has_broken_NEON());
  // Measure Android kernels with missing AT_HWCAP2 auxv fields. See
  // https://crbug.com/boringssl/46.
  UMA_HISTOGRAM_BOOLEAN("Net.NeedsHWCAP2Workaround",
                        CRYPTO_needs_hwcap2_workaround());
#endif

  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();

  // Set-up the global port overrides.
  if (command_line->HasSwitch(switches::kExplicitlyAllowedPorts)) {
    std::string allowed_ports =
        command_line->GetSwitchValueASCII(switches::kExplicitlyAllowedPorts);
    net::SetExplicitlyAllowedPorts(allowed_ports);
  }

  // Record this once per session, though the switch is appled on a
  // per-NetworkContext basis.
  UMA_HISTOGRAM_BOOLEAN(
      "Net.Certificate.IgnoreCertificateErrorsSPKIListPresent",
      command_line->HasSwitch(switches::kIgnoreCertificateErrorsSPKIList));

  network_change_manager_ = std::make_unique<NetworkChangeManager>(
      CreateNetworkChangeNotifierIfNeeded());

  if (net_log) {
    net_log_ = net_log;
  } else {
    net_log_ = GetNetLog();
  }

  trace_net_log_observer_.WatchForTraceStart(net_log_);

  // Add an observer that will emit network change events to the ChromeNetLog.
  // Assuming NetworkChangeNotifier dispatches in FIFO order, we should be
  // logging the network change before other IO thread consumers respond to it.
  network_change_observer_ =
      std::make_unique<net::LoggingNetworkChangeObserver>(net_log_);

  network_quality_estimator_manager_ =
      std::make_unique<NetworkQualityEstimatorManager>(net_log_);

  dns_config_change_manager_ = std::make_unique<DnsConfigChangeManager>();

  host_resolver_ = CreateHostResolver(net_log_);

  network_usage_accumulator_ = std::make_unique<NetworkUsageAccumulator>();

  http_auth_cache_copier_ = std::make_unique<HttpAuthCacheCopier>();

#if BUILDFLAG(IS_CT_SUPPORTED)
  sth_distributor_ =
      std::make_unique<certificate_transparency::STHDistributor>();
#endif  // BUILDFLAG(IS_CT_SUPPORTED)
  crl_set_distributor_ = std::make_unique<CRLSetDistributor>();
}

NetworkService::~NetworkService() {
  DCHECK_EQ(this, g_network_service);
  g_network_service = nullptr;
  // Destroy owned network contexts.
  DestroyNetworkContexts();

  // All NetworkContexts (Owned and unowned) must have been deleted by this
  // point.
  DCHECK(network_contexts_.empty());

  if (file_net_log_observer_) {
    file_net_log_observer_->StopObserving(nullptr /*polled_data*/,
                                          base::OnceClosure());
  }
  trace_net_log_observer_.StopWatchForTraceStart();
}

void NetworkService::set_os_crypt_is_configured() {
  os_crypt_config_set_ = true;
}

std::unique_ptr<NetworkService> NetworkService::Create(
    mojom::NetworkServiceRequest request,
    net::NetLog* net_log,
    service_manager::mojom::ServiceRequest service_request) {
  return std::make_unique<NetworkService>(nullptr, std::move(request), net_log,
                                          std::move(service_request));
}

std::unique_ptr<mojom::NetworkContext>
NetworkService::CreateNetworkContextWithBuilder(
    mojom::NetworkContextRequest request,
    mojom::NetworkContextParamsPtr params,
    std::unique_ptr<URLRequestContextBuilderMojo> builder,
    net::URLRequestContext** url_request_context) {
  std::unique_ptr<NetworkContext> network_context =
      std::make_unique<NetworkContext>(this, std::move(request),
                                       std::move(params), std::move(builder));
  *url_request_context = network_context->url_request_context();
  return network_context;
}

void NetworkService::SetHostResolver(
    std::unique_ptr<net::HostResolver> host_resolver) {
  DCHECK(network_contexts_.empty());
  host_resolver_ = std::move(host_resolver);
}

std::unique_ptr<NetworkService> NetworkService::CreateForTesting() {
  return CreateForTesting(nullptr);
}

std::unique_ptr<NetworkService> NetworkService::CreateForTesting(
    service_manager::mojom::ServiceRequest service_request) {
  return std::make_unique<NetworkService>(
      std::make_unique<service_manager::BinderRegistry>(),
      nullptr /* request */, nullptr /* net_log */, std::move(service_request));
}

void NetworkService::RegisterNetworkContext(NetworkContext* network_context) {
  // If IsPrimaryNetworkContext() is true, there must be no other
  // NetworkContexts created yet.
  DCHECK(!network_context->IsPrimaryNetworkContext() ||
         network_contexts_.empty());

  DCHECK_EQ(0u, network_contexts_.count(network_context));
  network_contexts_.insert(network_context);
  if (quic_disabled_)
    network_context->DisableQuic();
}

void NetworkService::DeregisterNetworkContext(NetworkContext* network_context) {
  // If the NetworkContext is the primary network context, all other
  // NetworkContexts must already have been destroyed.
  DCHECK(!network_context->IsPrimaryNetworkContext() ||
         network_contexts_.size() == 1);

  DCHECK_EQ(1u, network_contexts_.count(network_context));
  network_contexts_.erase(network_context);
}

void NetworkService::CreateNetLogEntriesForActiveObjects(
    net::NetLog::ThreadSafeObserver* observer) {
  std::set<net::URLRequestContext*> contexts;
  for (NetworkContext* nc : network_contexts_)
    contexts.insert(nc->url_request_context());
  return net::CreateNetLogEntriesForActiveObjects(contexts, observer);
}

void NetworkService::SetClient(mojom::NetworkServiceClientPtr client) {
  client_ = std::move(client);
}

void NetworkService::StartNetLog(base::File file,
                                 mojom::NetLogCaptureMode capture_mode,
                                 base::Value client_constants) {
  DCHECK(client_constants.is_dict());
  std::unique_ptr<base::DictionaryValue> constants = net::GetNetConstants();
  constants->MergeDictionary(&client_constants);

  file_net_log_observer_ = net::FileNetLogObserver::CreateUnboundedPreExisting(
      std::move(file), std::move(constants));
  file_net_log_observer_->StartObserving(
      net_log_, mojo::ConvertTo<net::NetLogCaptureMode>(capture_mode));
}

void NetworkService::SetSSLKeyLogFile(const base::FilePath& file) {
  net::SSLClientSocket::SetSSLKeyLogger(
      std::make_unique<net::SSLKeyLoggerImpl>(file));
}

void NetworkService::CreateNetworkContext(
    mojom::NetworkContextRequest request,
    mojom::NetworkContextParamsPtr params) {
  // Only the first created NetworkContext can have |primary_next_context| set
  // to true.
  DCHECK(!params->primary_network_context || network_contexts_.empty());

  owned_network_contexts_.emplace(std::make_unique<NetworkContext>(
      this, std::move(request), std::move(params),
      base::BindOnce(&NetworkService::OnNetworkContextConnectionClosed,
                     base::Unretained(this))));
}

void NetworkService::ConfigureStubHostResolver(
    bool stub_resolver_enabled,
    base::Optional<std::vector<mojom::DnsOverHttpsServerPtr>>
        dns_over_https_servers) {
  // If the stub resolver is not enabled, |dns_over_https_servers| has no
  // effect.
  DCHECK(stub_resolver_enabled || !dns_over_https_servers);
  DCHECK(!dns_over_https_servers || !dns_over_https_servers->empty());

  // Enable or disable the stub resolver, as needed. "DnsClient" is class that
  // implements the stub resolver.
  host_resolver_->SetDnsClientEnabled(stub_resolver_enabled);

  // Configure DNS over HTTPS.
  if (!dns_over_https_servers || dns_over_https_servers.value().empty()) {
    host_resolver_->SetDnsConfigOverrides(net::DnsConfigOverrides());
    return;
  }

  for (auto* network_context : network_contexts_) {
    if (!network_context->IsPrimaryNetworkContext())
      continue;

    host_resolver_->SetRequestContext(network_context->url_request_context());

    net::DnsConfigOverrides overrides;
    overrides.dns_over_https_servers.emplace();
    for (const auto& doh_server : *dns_over_https_servers) {
      overrides.dns_over_https_servers.value().emplace_back(
          doh_server->server_template, doh_server->use_post);
    }
    host_resolver_->SetDnsConfigOverrides(overrides);

    return;
  }

  // Execution should generally not reach this line, but could run into races
  // with teardown, or restarting a crashed network process, that could
  // theoretically result in reaching it.
}

void NetworkService::DisableQuic() {
  quic_disabled_ = true;

  for (auto* network_context : network_contexts_) {
    network_context->DisableQuic();
  }
}

void NetworkService::SetUpHttpAuth(
    mojom::HttpAuthStaticParamsPtr http_auth_static_params) {
  DCHECK(!http_auth_handler_factory_);

  http_auth_handler_factory_ = net::HttpAuthHandlerRegistryFactory::Create(
      host_resolver_.get(), &http_auth_preferences_,
      http_auth_static_params->supported_schemes
#if defined(OS_CHROMEOS)
      ,
      http_auth_static_params->allow_gssapi_library_load
#elif (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_FUCHSIA)
      ,
      http_auth_static_params->gssapi_library_name
#endif
#if defined(OS_ANDROID) && BUILDFLAG(USE_KERBEROS)
      ,
      base::BindRepeating(&CreateAuthSystem, this)
#endif
  );
}

void NetworkService::ConfigureHttpAuthPrefs(
    mojom::HttpAuthDynamicParamsPtr http_auth_dynamic_params) {
  http_auth_preferences_.SetServerWhitelist(
      http_auth_dynamic_params->server_whitelist);
  http_auth_preferences_.SetDelegateWhitelist(
      http_auth_dynamic_params->delegate_whitelist);
  http_auth_preferences_.set_negotiate_disable_cname_lookup(
      http_auth_dynamic_params->negotiate_disable_cname_lookup);
  http_auth_preferences_.set_negotiate_enable_port(
      http_auth_dynamic_params->enable_negotiate_port);

#if defined(OS_POSIX) || defined(OS_FUCHSIA)
  http_auth_preferences_.set_ntlm_v2_enabled(
      http_auth_dynamic_params->ntlm_v2_enabled);
#endif

#if defined(OS_ANDROID)
  http_auth_preferences_.set_auth_android_negotiate_account_type(
      http_auth_dynamic_params->android_negotiate_account_type);
#endif
}

void NetworkService::SetRawHeadersAccess(
    uint32_t process_id,
    const std::vector<url::Origin>& origins) {
  DCHECK(process_id);
  if (!origins.size()) {
    raw_headers_access_origins_by_pid_.erase(process_id);
  } else {
    raw_headers_access_origins_by_pid_[process_id] =
        base::flat_set<url::Origin>(origins.begin(), origins.end());
  }
}

bool NetworkService::HasRawHeadersAccess(uint32_t process_id,
                                         const GURL& resource_url) const {
  // Allow raw headers for browser-initiated requests.
  if (!process_id)
    return true;
  auto it = raw_headers_access_origins_by_pid_.find(process_id);
  if (it == raw_headers_access_origins_by_pid_.end())
    return false;
  return it->second.find(url::Origin::Create(resource_url)) != it->second.end();
}

net::NetLog* NetworkService::net_log() const {
  return net_log_;
}

void NetworkService::GetNetworkChangeManager(
    mojom::NetworkChangeManagerRequest request) {
  network_change_manager_->AddRequest(std::move(request));
}

void NetworkService::GetNetworkQualityEstimatorManager(
    mojom::NetworkQualityEstimatorManagerRequest request) {
  network_quality_estimator_manager_->AddRequest(std::move(request));
}

void NetworkService::GetDnsConfigChangeManager(
    mojom::DnsConfigChangeManagerRequest request) {
  dns_config_change_manager_->AddBinding(std::move(request));
}

void NetworkService::GetTotalNetworkUsages(
    mojom::NetworkService::GetTotalNetworkUsagesCallback callback) {
  std::move(callback).Run(network_usage_accumulator_->GetTotalNetworkUsages());
}

void NetworkService::GetNetworkList(
    uint32_t policy,
    mojom::NetworkService::GetNetworkListCallback callback) {
  net::NetworkInterfaceList networks;
  if (net::GetNetworkList(&networks, policy)) {
    std::move(callback).Run(networks);
  } else {
    std::move(callback).Run(base::nullopt);
  }
}

#if BUILDFLAG(IS_CT_SUPPORTED)
void NetworkService::UpdateSignedTreeHead(const net::ct::SignedTreeHead& sth) {
  sth_distributor_->NewSTHObserved(sth);
}
#endif  // BUILDFLAG(IS_CT_SUPPORTED)

void NetworkService::UpdateCRLSet(base::span<const uint8_t> crl_set) {
  crl_set_distributor_->OnNewCRLSet(crl_set);
}

void NetworkService::OnCertDBChanged() {
  net::CertDatabase::GetInstance()->NotifyObserversCertDBChanged();
}

#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
void NetworkService::SetCryptConfig(mojom::CryptConfigPtr crypt_config) {
#if !defined(IS_CHROMECAST)
  DCHECK(!os_crypt_config_set_);
  auto config = std::make_unique<os_crypt::Config>();
  config->store = crypt_config->store;
  config->product_name = crypt_config->product_name;
  config->main_thread_runner = base::ThreadTaskRunnerHandle::Get();
  config->should_use_preference = crypt_config->should_use_preference;
  config->user_data_path = crypt_config->user_data_path;
  OSCrypt::SetConfig(std::move(config));
  os_crypt_config_set_ = true;
#endif
}
#endif

#if defined(OS_MACOSX) && !defined(OS_IOS)
void NetworkService::SetEncryptionKey(const std::string& encryption_key) {
  OSCrypt::SetRawEncryptionKey(encryption_key);
}
#endif  // OS_MACOSX

void NetworkService::AddCorbExceptionForPlugin(uint32_t process_id) {
  DCHECK_NE(mojom::kBrowserProcessId, process_id);
  CrossOriginReadBlocking::AddExceptionForPlugin(process_id);
}

void NetworkService::RemoveCorbExceptionForPlugin(uint32_t process_id) {
  DCHECK_NE(mojom::kBrowserProcessId, process_id);
  CrossOriginReadBlocking::RemoveExceptionForPlugin(process_id);
}

void NetworkService::OnMemoryPressure(
    base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
  base::MemoryPressureListener::NotifyMemoryPressure(memory_pressure_level);
}

#if defined(OS_ANDROID)
void NetworkService::OnApplicationStateChange(
    base::android::ApplicationState state) {
  for (auto* network_context : network_contexts_)
    network_context->app_status_listener()->Notify(state);
}
#endif

net::HttpAuthHandlerFactory* NetworkService::GetHttpAuthHandlerFactory() {
  if (!http_auth_handler_factory_) {
    http_auth_handler_factory_ = net::HttpAuthHandlerFactory::CreateDefault(
        host_resolver_.get(), &http_auth_preferences_
#if defined(OS_ANDROID) && BUILDFLAG(USE_KERBEROS)
        ,
        base::BindRepeating(&CreateAuthSystem, this)
#endif
    );
  }
  return http_auth_handler_factory_.get();
}

void NetworkService::OnBeforeURLRequest() {
  if (base::FeatureList::IsEnabled(features::kNetworkService))
    MaybeStartUpdateLoadInfoTimer();
}

#if BUILDFLAG(IS_CT_SUPPORTED)
certificate_transparency::STHReporter* NetworkService::sth_reporter() {
  return sth_distributor_.get();
}
#endif  // BUILDFLAG(IS_CT_SUPPORTED)

void NetworkService::OnBindInterface(
    const service_manager::BindSourceInfo& source_info,
    const std::string& interface_name,
    mojo::ScopedMessagePipeHandle interface_pipe) {
  registry_->BindInterface(interface_name, std::move(interface_pipe));
}

void NetworkService::DestroyNetworkContexts() {
  // Delete NetworkContexts. If there's a primary NetworkContext, it must be
  // deleted after all other NetworkContexts, to avoid use-after-frees.
  for (auto it = owned_network_contexts_.begin();
       it != owned_network_contexts_.end();) {
    const auto last = it;
    ++it;
    if (!(*last)->IsPrimaryNetworkContext())
      owned_network_contexts_.erase(last);
  }

  // If DNS over HTTPS is enabled, the HostResolver is currently using the
  // primary NetworkContext to do DNS lookups, so need to tell the HostResolver
  // to stop using DNS over HTTPS before destroying the primary NetworkContext.
  // The SetDnsConfigOverrides() call will will fail any in-progress DNS
  // lookups, but only if there are current config overrides (which there will
  // be if DNS over HTTPS is currently enabled).
  host_resolver_->SetDnsConfigOverrides(net::DnsConfigOverrides());
  host_resolver_->SetRequestContext(nullptr);

  DCHECK_LE(owned_network_contexts_.size(), 1u);
  owned_network_contexts_.clear();
}

void NetworkService::OnNetworkContextConnectionClosed(
    NetworkContext* network_context) {
  if (network_context->IsPrimaryNetworkContext()) {
    DestroyNetworkContexts();
    return;
  }

  auto it = owned_network_contexts_.find(network_context);
  DCHECK(it != owned_network_contexts_.end());
  owned_network_contexts_.erase(it);
}

void NetworkService::MaybeStartUpdateLoadInfoTimer() {
  if (waiting_on_load_state_ack_ || update_load_info_timer_.IsRunning())
    return;

  bool has_loader = false;
  for (auto* network_context : network_contexts_) {
    if (!network_context->url_request_context()->url_requests()->empty()) {
      has_loader = true;
      break;
    }
  }

  if (!has_loader)
    return;

  update_load_info_timer_.Start(FROM_HERE, kUpdateLoadStatesInterval, this,
                                &NetworkService::UpdateLoadInfo);
}

void NetworkService::UpdateLoadInfo() {
  // For requests from the same {process_id, routing_id} pair, pick the most
  // important. For ones from the browser, return all of them.
  std::vector<mojom::LoadInfoPtr> infos;
  std::map<std::pair<uint32_t, uint32_t>, mojom::LoadInfoPtr> frame_infos;

  for (auto* network_context : network_contexts_) {
    for (auto* loader :
         *network_context->url_request_context()->url_requests()) {
      auto* url_loader = URLLoader::ForRequest(*loader);
      if (!url_loader)
        continue;

      auto process_id = url_loader->GetProcessId();
      auto routing_id = url_loader->GetRenderFrameId();
      if (routing_id == static_cast<uint32_t>(MSG_ROUTING_NONE)) {
        // If there is no routing_id, then the browser can't associate this with
        // a page so no need to send.
        continue;
      }

      auto load_info = mojom::LoadInfo::New();
      load_info->process_id = process_id;
      load_info->routing_id = routing_id;
      load_info->host = loader->url().host();
      auto load_state = loader->GetLoadState();
      load_info->load_state = static_cast<uint32_t>(load_state.state);
      load_info->state_param = std::move(load_state.param);
      auto upload_progress = loader->GetUploadProgress();
      load_info->upload_size = upload_progress.size();
      load_info->upload_position = upload_progress.position();

      if (process_id == 0) {
        // Requests from the browser can't be compared to ones from child
        // processes, so send them all without looking for the most interesting.
        infos.push_back(std::move(load_info));
        continue;
      }

      auto key = std::make_pair(process_id, routing_id);
      auto existing = frame_infos.find(key);
      if (existing == frame_infos.end() ||
          LoadInfoIsMoreInteresting(*load_info, *existing->second)) {
        frame_infos[key] = std::move(load_info);
      }
    }
  }

  for (auto& it : frame_infos)
    infos.push_back(std::move(it.second));

  if (infos.empty())
    return;

  DCHECK(!waiting_on_load_state_ack_);
  waiting_on_load_state_ack_ = true;
  client_->OnLoadingStateUpdate(
      std::move(infos), base::BindOnce(&NetworkService::AckUpdateLoadInfo,
                                       base::Unretained(this)));
}

void NetworkService::AckUpdateLoadInfo() {
  DCHECK(waiting_on_load_state_ack_);
  waiting_on_load_state_ack_ = false;
  MaybeStartUpdateLoadInfoTimer();
}

void NetworkService::Bind(mojom::NetworkServiceRequest request) {
  DCHECK(!binding_.is_bound());
  binding_.Bind(std::move(request));
}

NetworkService* NetworkService::GetNetworkServiceForTesting() {
  return g_network_service;
}

}  // namespace network
