// Copyright 2016 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/cronet/ios/cronet_environment.h"

#include <utility>

#include "base/atomicops.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/mac/foundation_util.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_restrictions.h"
#include "components/cronet/cronet_buildflags.h"
#include "components/cronet/cronet_global_state.h"
#include "components/cronet/cronet_prefs_manager.h"
#include "components/cronet/histogram_manager.h"
#include "components/prefs/pref_filter.h"
#include "ios/net/cookies/cookie_store_ios.h"
#include "ios/net/cookies/cookie_store_ios_client.h"
#include "ios/web/public/global_state/ios_global_state.h"
#include "ios/web/public/global_state/ios_global_state_configuration.h"
#include "ios/web/public/user_agent.h"
#include "net/base/network_change_notifier.h"
#include "net/base/url_util.h"
#include "net/cert/cert_verifier.h"
#include "net/dns/host_resolver.h"
#include "net/dns/mapped_host_resolver.h"
#include "net/http/http_server_properties_impl.h"
#include "net/http/http_stream_factory.h"
#include "net/http/http_transaction_factory.h"
#include "net/http/http_util.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/proxy_resolution/proxy_resolution_service.h"
#include "net/socket/ssl_client_socket.h"
#include "net/ssl/channel_id_service.h"
#include "net/ssl/ssl_key_logger_impl.h"
#include "net/third_party/quic/core/quic_versions.h"
#include "net/url_request/http_user_agent_settings.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_storage.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "url/scheme_host_port.h"
#include "url/url_util.h"

#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif

namespace {

// Request context getter for Cronet.
class CronetURLRequestContextGetter : public net::URLRequestContextGetter {
 public:
  CronetURLRequestContextGetter(
      cronet::CronetEnvironment* environment,
      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
      : environment_(environment), task_runner_(task_runner) {}

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

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

 private:
  // Must be called on the IO thread.
  ~CronetURLRequestContextGetter() override {}

  cronet::CronetEnvironment* environment_;
  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  DISALLOW_COPY_AND_ASSIGN(CronetURLRequestContextGetter);
};

// Cronet implementation of net::CookieStoreIOSClient.
// Used to provide Cronet Network IO TaskRunner.
class CronetCookieStoreIOSClient : public net::CookieStoreIOSClient {
 public:
  CronetCookieStoreIOSClient(
      const scoped_refptr<base::SequencedTaskRunner>& task_runner)
      : task_runner_(task_runner) {}

  scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() const override {
    return task_runner_;
  }

 private:
  ~CronetCookieStoreIOSClient() override {}

  scoped_refptr<base::SequencedTaskRunner> task_runner_;
  DISALLOW_COPY_AND_ASSIGN(CronetCookieStoreIOSClient);
};

void SignalEvent(base::WaitableEvent* event) {
  event->Signal();
}

// TODO(eroman): Creating the file(s) for a netlog is an internal detail for
// FileNetLogObsever. This code assumes that the unbounded format is being used,
// which writes a single file at |path| (creating or overwriting it).
bool IsNetLogPathValid(const base::FilePath& path) {
  base::ScopedFILE file(base::OpenFile(path, "w"));
  return !!file;
}

}  // namespace

namespace cronet {

const double CronetEnvironment::kKeepDefaultThreadPriority = -1;

base::SingleThreadTaskRunner* CronetEnvironment::GetNetworkThreadTaskRunner()
    const {
  if (network_io_thread_) {
    return network_io_thread_->task_runner().get();
  }
  return ios_global_state::GetSharedNetworkIOThreadTaskRunner().get();
}

void CronetEnvironment::PostToNetworkThread(const base::Location& from_here,
                                            const base::Closure& task) {
  GetNetworkThreadTaskRunner()->PostTask(from_here, task);
}

net::URLRequestContext* CronetEnvironment::GetURLRequestContext() const {
  return main_context_.get();
}

net::URLRequestContextGetter* CronetEnvironment::GetURLRequestContextGetter()
    const {
  return main_context_getter_.get();
}

bool CronetEnvironment::StartNetLog(base::FilePath::StringType file_name,
                                    bool log_bytes) {
  if (file_name.empty())
    return false;

  base::FilePath path(file_name);
  if (!IsNetLogPathValid(path)) {
    LOG(ERROR) << "Can not start NetLog to " << path.value() << ": "
               << strerror(errno);
    return false;
  }

  LOG(WARNING) << "Starting NetLog to " << path.value();
  PostToNetworkThread(FROM_HERE,
                      base::Bind(&CronetEnvironment::StartNetLogOnNetworkThread,
                                 base::Unretained(this), path, log_bytes));

  return true;
}

void CronetEnvironment::StartNetLogOnNetworkThread(const base::FilePath& path,
                                                   bool log_bytes) {
  DCHECK(net_log_);

  if (file_net_log_observer_)
    return;

  net::NetLogCaptureMode capture_mode =
      log_bytes ? net::NetLogCaptureMode::IncludeSocketBytes()
                : net::NetLogCaptureMode::Default();

  file_net_log_observer_ =
      net::FileNetLogObserver::CreateUnbounded(path, nullptr);
  file_net_log_observer_->StartObserving(main_context_->net_log(),
                                         capture_mode);
  LOG(WARNING) << "Started NetLog";
}

void CronetEnvironment::StopNetLog() {
  base::WaitableEvent log_stopped_event(
      base::WaitableEvent::ResetPolicy::MANUAL,
      base::WaitableEvent::InitialState::NOT_SIGNALED);
  PostToNetworkThread(FROM_HERE,
                      base::Bind(&CronetEnvironment::StopNetLogOnNetworkThread,
                                 base::Unretained(this), &log_stopped_event));
  log_stopped_event.Wait();
}

void CronetEnvironment::StopNetLogOnNetworkThread(
    base::WaitableEvent* log_stopped_event) {
  if (file_net_log_observer_) {
    DLOG(WARNING) << "Stopped NetLog.";
    file_net_log_observer_->StopObserving(
        GetNetLogInfo(), base::BindOnce(&SignalEvent, log_stopped_event));
    file_net_log_observer_.reset();
  } else {
    log_stopped_event->Signal();
  }
}

std::unique_ptr<base::DictionaryValue> CronetEnvironment::GetNetLogInfo()
    const {
  std::unique_ptr<base::DictionaryValue> net_info =
      net::GetNetInfo(main_context_.get(), net::NET_INFO_ALL_SOURCES);
  if (effective_experimental_options_) {
    net_info->Set("cronetExperimentalParams",
                  effective_experimental_options_->CreateDeepCopy());
  }
  return net_info;
}

net::HttpNetworkSession* CronetEnvironment::GetHttpNetworkSession(
    net::URLRequestContext* context) {
  DCHECK(context);
  if (!context->http_transaction_factory())
    return nullptr;

  return context->http_transaction_factory()->GetSession();
}

void CronetEnvironment::AddQuicHint(const std::string& host,
                                    int port,
                                    int alternate_port) {
  DCHECK(port == alternate_port);
  quic_hints_.push_back(net::HostPortPair(host, port));
}

CronetEnvironment::CronetEnvironment(const std::string& user_agent,
                                     bool user_agent_partial)
    : http2_enabled_(false),
      quic_enabled_(false),
      brotli_enabled_(false),
      http_cache_(URLRequestContextConfig::HttpCacheType::DISK),
      user_agent_(user_agent),
      user_agent_partial_(user_agent_partial),
      net_log_(new net::NetLog),
      enable_pkp_bypass_for_local_trust_anchors_(true),
      network_thread_priority_(kKeepDefaultThreadPriority) {}

void CronetEnvironment::Start() {
  // Threads setup.
  file_thread_.reset(new base::Thread("Chrome File Thread"));
  file_thread_->StartWithOptions(
      base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
  // Fetching the task_runner will create the shared thread if necessary.
  scoped_refptr<base::SingleThreadTaskRunner> task_runner =
      ios_global_state::GetSharedNetworkIOThreadTaskRunner();
  if (!task_runner) {
    network_io_thread_.reset(
        new CronetNetworkThread("Chrome Network IO Thread", this));
    network_io_thread_->StartWithOptions(
        base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
  }

  net::SetCookieStoreIOSClient(new CronetCookieStoreIOSClient(
      CronetEnvironment::GetNetworkThreadTaskRunner()));

  main_context_getter_ = new CronetURLRequestContextGetter(
      this, CronetEnvironment::GetNetworkThreadTaskRunner());
  base::subtle::MemoryBarrier();
  PostToNetworkThread(FROM_HERE,
                      base::Bind(&CronetEnvironment::InitializeOnNetworkThread,
                                 base::Unretained(this)));
}

void CronetEnvironment::CleanUpOnNetworkThread() {
  // TODO(lilyhoughton) make unregistering of this work.
  // net::HTTPProtocolHandlerDelegate::SetInstance(nullptr);

  // TODO(lilyhoughton) this can only be run once, so right now leaking it.
  // Should be be called when the _last_ CronetEnvironment is destroyed.
  // base::TaskScheduler* ts = base::TaskScheduler::GetInstance();
  // if (ts)
  //  ts->Shutdown();

  if (cronet_prefs_manager_) {
    cronet_prefs_manager_->PrepareForShutdown();
  }

  // TODO(lilyhoughton) this should be smarter about making sure there are no
  // pending requests, etc.
  main_context_.reset();

  // cronet_prefs_manager_ should be deleted on the network thread.
  cronet_prefs_manager_.reset();
}

CronetEnvironment::~CronetEnvironment() {
  // Deleting a thread blocks the current thread and waits until all pending
  // tasks are completed.
  network_io_thread_.reset();
  file_thread_.reset();
}

void CronetEnvironment::InitializeOnNetworkThread() {
  DCHECK(GetNetworkThreadTaskRunner()->BelongsToCurrentThread());
  base::DisallowBlocking();

  static bool ssl_key_log_file_set = false;
  if (!ssl_key_log_file_set && !ssl_key_log_file_name_.empty()) {
    ssl_key_log_file_set = true;
    base::FilePath ssl_key_log_file(ssl_key_log_file_name_);
    net::SSLClientSocket::SetSSLKeyLogger(
        std::make_unique<net::SSLKeyLoggerImpl>(ssl_key_log_file));
  }

  if (user_agent_partial_)
    user_agent_ = web::BuildUserAgentFromProduct(user_agent_);

  // Cache
  base::FilePath storage_path;
  if (!base::PathService::Get(base::DIR_CACHE, &storage_path))
    return;
  storage_path = storage_path.Append(FILE_PATH_LITERAL("cronet"));

  URLRequestContextConfigBuilder context_config_builder;
  context_config_builder.enable_quic = quic_enabled_;   // Enable QUIC.
  context_config_builder.quic_user_agent_id =
      getDefaultQuicUserAgentId();                      // QUIC User Agent ID.
  context_config_builder.enable_spdy = http2_enabled_;  // Enable HTTP/2.
  context_config_builder.http_cache = http_cache_;      // Set HTTP cache.
  context_config_builder.storage_path =
      storage_path.value();  // Storage path for http cache and prefs storage.
  context_config_builder.accept_language =
      accept_language_;  // Accept-Language request header field.
  context_config_builder.user_agent =
      user_agent_;  // User-Agent request header field.
  context_config_builder.experimental_options =
      experimental_options_;  // Set experimental Cronet options.
  context_config_builder.mock_cert_verifier = std::move(
      mock_cert_verifier_);  // MockCertVerifier to use for testing purposes.
  if (network_thread_priority_ != kKeepDefaultThreadPriority)
    context_config_builder.network_thread_priority = network_thread_priority_;
  std::unique_ptr<URLRequestContextConfig> config =
      context_config_builder.Build();

  config->pkp_list = std::move(pkp_list_);

  net::URLRequestContextBuilder context_builder;

  // 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_path in the
  // future.
  context_builder.set_transport_security_persister_path(base::FilePath());

  config->ConfigureURLRequestContextBuilder(&context_builder, net_log_.get());

  effective_experimental_options_ =
      std::move(config->effective_experimental_options);

  std::unique_ptr<net::MappedHostResolver> mapped_host_resolver(
      new net::MappedHostResolver(
          net::HostResolver::CreateDefaultResolver(nullptr)));

  if (!config->storage_path.empty()) {
    cronet_prefs_manager_ = std::make_unique<CronetPrefsManager>(
        config->storage_path, GetNetworkThreadTaskRunner(),
        file_thread_->task_runner(), false /* nqe */, false /* host_cache */,
        net_log_.get(), &context_builder);
  }

  context_builder.set_host_resolver(std::move(mapped_host_resolver));

  // TODO(690969): This behavior matches previous behavior of CookieStoreIOS in
  // CrNet, but should change to adhere to App's Cookie Accept Policy instead
  // of changing it.
  [[NSHTTPCookieStorage sharedHTTPCookieStorage]
      setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
  auto cookie_store = std::make_unique<net::CookieStoreIOS>(
      [NSHTTPCookieStorage sharedHTTPCookieStorage], nullptr /* net_log */);
  context_builder.SetCookieStore(std::move(cookie_store));

  context_builder.set_enable_brotli(brotli_enabled_);
  main_context_ = context_builder.Build();

  for (const auto& quic_hint : quic_hints_) {
    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();
      continue;
    }

    net::AlternativeService alternative_service(net::kProtoQUIC, "",
                                                quic_hint.port());

    url::SchemeHostPort quic_hint_server("https", quic_hint.host(),
                                         quic_hint.port());
    main_context_->http_server_properties()->SetQuicAlternativeService(
        quic_hint_server, alternative_service, base::Time::Max(),
        quic::QuicTransportVersionVector());
  }

  main_context_->transport_security_state()
      ->SetEnablePublicKeyPinningBypassForLocalTrustAnchors(
          enable_pkp_bypass_for_local_trust_anchors_);

  // Iterate trhough PKP configuration for every host.
  for (const auto& pkp : config->pkp_list) {
    // Add the host pinning.
    main_context_->transport_security_state()->AddHPKP(
        pkp->host, pkp->expiration_date, pkp->include_subdomains,
        pkp->pin_hashes, GURL::EmptyGURL());
  }
}

void CronetEnvironment::SetNetworkThreadPriority(double priority) {
  DCHECK_LE(priority, 1.0);
  DCHECK_GE(priority, 0.0);
  network_thread_priority_ = priority;
  if (network_io_thread_) {
    PostToNetworkThread(
        FROM_HERE,
        base::BindRepeating(
            &CronetEnvironment::SetNetworkThreadPriorityOnNetworkThread,
            base::Unretained(this), priority));
  }
}

std::string CronetEnvironment::user_agent() {
  const net::HttpUserAgentSettings* user_agent_settings =
      main_context_->http_user_agent_settings();
  if (!user_agent_settings) {
    return nullptr;
  }

  return user_agent_settings->GetUserAgent();
}

std::vector<uint8_t> CronetEnvironment::GetHistogramDeltas() {
  std::vector<uint8_t> data;
#if BUILDFLAG(DISABLE_HISTOGRAM_SUPPORT)
  NOTREACHED() << "Histogram support is disabled";
#else   // BUILDFLAG(DISABLE_HISTOGRAM_SUPPORT)
  if (!HistogramManager::GetInstance()->GetDeltas(&data))
    return std::vector<uint8_t>();
#endif  // BUILDFLAG(DISABLE_HISTOGRAM_SUPPORT)
  return data;
}

void CronetEnvironment::SetHostResolverRules(const std::string& rules) {
  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                            base::WaitableEvent::InitialState::NOT_SIGNALED);
  PostToNetworkThread(
      FROM_HERE,
      base::Bind(&CronetEnvironment::SetHostResolverRulesOnNetworkThread,
                 base::Unretained(this), rules, &event));
  event.Wait();
}

void CronetEnvironment::SetHostResolverRulesOnNetworkThread(
    const std::string& rules,
    base::WaitableEvent* event) {
  static_cast<net::MappedHostResolver*>(main_context_->host_resolver())
      ->SetRulesFromString(rules);
  event->Signal();
}

void CronetEnvironment::SetNetworkThreadPriorityOnNetworkThread(
    double priority) {
  DCHECK(GetNetworkThreadTaskRunner()->BelongsToCurrentThread());
  cronet::SetNetworkThreadPriorityOnNetworkThread(priority);
}

std::string CronetEnvironment::getDefaultQuicUserAgentId() const {
  return base::SysNSStringToUTF8([[NSBundle mainBundle]
             objectForInfoDictionaryKey:@"CFBundleDisplayName"]) +
         " Cronet/" + CRONET_VERSION;
}

base::SingleThreadTaskRunner* CronetEnvironment::GetFileThreadRunnerForTesting()
    const {
  return file_thread_->task_runner().get();
}

base::SingleThreadTaskRunner*
CronetEnvironment::GetNetworkThreadRunnerForTesting() const {
  return GetNetworkThreadTaskRunner();
}

CronetEnvironment::CronetNetworkThread::CronetNetworkThread(
    const std::string& name,
    cronet::CronetEnvironment* cronet_environment)
    : base::Thread(name), cronet_environment_(cronet_environment) {}

CronetEnvironment::CronetNetworkThread::~CronetNetworkThread() {
  Stop();
}

void CronetEnvironment::CronetNetworkThread::CleanUp() {
  cronet_environment_->CleanUpOnNetworkThread();
}

}  // namespace cronet
