// Copyright 2018 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/native/engine.h"

#include <unordered_set>
#include <utility>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/no_destructor.h"
#include "base/notimplemented.h"
#include "build/build_config.h"
#include "components/cronet/cronet_context.h"
#include "components/cronet/cronet_global_state.h"
#include "components/cronet/native/generated/cronet.idl_impl_struct.h"
#include "components/cronet/native/include/cronet_c.h"
#include "components/cronet/native/runnables.h"
#include "components/cronet/url_request_context_config.h"
#include "components/cronet/version.h"
#include "components/grpc_support/include/bidirectional_stream_c.h"
#include "net/base/completion_once_callback.h"
#include "net/base/hash_value.h"
#include "net/base/proxy_delegate.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"

namespace {

class SharedEngineState {
 public:
  SharedEngineState()
      : default_user_agent_(cronet::CreateDefaultUserAgent(CRONET_VERSION)) {}

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

  // Marks |storage_path| in use, so multiple engines would not use it at the
  // same time. Returns |true| if marked successfully, |false| if it is in use
  // by another engine.
  bool MarkStoragePathInUse(const std::string& storage_path)
      LOCKS_EXCLUDED(lock_) {
    base::AutoLock lock(lock_);
    return in_use_storage_paths_.emplace(storage_path).second;
  }

  // Unmarks |storage_path| in use, so another engine could use it.
  void UnmarkStoragePathInUse(const std::string& storage_path)
      LOCKS_EXCLUDED(lock_) {
    base::AutoLock lock(lock_);
    in_use_storage_paths_.erase(storage_path);
  }

  // Returns default user agent, based on Cronet version, application info and
  // platform-specific additional information.
  Cronet_String GetDefaultUserAgent() const {
    return default_user_agent_.c_str();
  }

  static SharedEngineState* GetInstance();

 private:
  const std::string default_user_agent_;
  // Protecting shared state.
  base::Lock lock_;
  std::unordered_set<std::string> in_use_storage_paths_ GUARDED_BY(lock_);
};

SharedEngineState* SharedEngineState::GetInstance() {
  static base::NoDestructor<SharedEngineState> instance;
  return instance.get();
}

// Does basic validation of host name for PKP and returns |true| if
// host is valid.
bool IsValidHostnameForPkp(const std::string& host) {
  if (host.empty())
    return false;
  if (host.size() > 255)
    return false;
  if (host.find_first_of(":\\/=\'\",") != host.npos)
    return false;
  return true;
}

}  // namespace

namespace cronet {

// The struct stream_engine for grpc support.
// Holds net::URLRequestContextGetter and app-specific annotation.
class Cronet_EngineImpl::StreamEngineImpl : public stream_engine {
 public:
  explicit StreamEngineImpl(net::URLRequestContextGetter* context_getter) {
    context_getter_ = context_getter;
    obj = context_getter_.get();
    annotation = nullptr;
  }

  ~StreamEngineImpl() {
    obj = nullptr;
    annotation = nullptr;
  }

 private:
  scoped_refptr<net::URLRequestContextGetter> context_getter_;
};

// Callback is owned by CronetContext. It is invoked and deleted
// on the network thread.
class Cronet_EngineImpl::Callback : public CronetContext::Callback {
 public:
  explicit Callback(Cronet_EngineImpl* engine);

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

  ~Callback() override;

  // CronetContext::Callback implementation:
  void OnInitNetworkThread() override LOCKS_EXCLUDED(engine_->lock_);
  void OnDestroyNetworkThread() override;
  void OnEffectiveConnectionTypeChanged(
      net::EffectiveConnectionType effective_connection_type) override;
  void OnRTTOrThroughputEstimatesComputed(
      int32_t http_rtt_ms,
      int32_t transport_rtt_ms,
      int32_t downstream_throughput_kbps) override;
  void OnRTTObservation(int32_t rtt_ms,
                        int32_t timestamp_ms,
                        net::NetworkQualityObservationSource source) override;
  void OnThroughputObservation(
      int32_t throughput_kbps,
      int32_t timestamp_ms,
      net::NetworkQualityObservationSource source) override;
  void OnStopNetLogCompleted() override LOCKS_EXCLUDED(engine_->lock_);
  void OnBeforeTunnelRequest(
      int chain_id,
      net::ProxyDelegate::OnBeforeTunnelRequestCallback callback) override {
    NOTREACHED();
  }
  void OnTunnelHeadersReceived(int chain_id,
                               const net::HttpResponseHeaders& response_headers,
                               net::CompletionOnceCallback callback) override {
    NOTREACHED();
  }

 private:
  // The engine which owns context that owns |this| callback.
  const raw_ptr<Cronet_EngineImpl> engine_;

  // All methods are invoked on the network thread.
  THREAD_CHECKER(network_thread_checker_);
};

Cronet_EngineImpl::Callback::Callback(Cronet_EngineImpl* engine)
    : engine_(engine) {
  DETACH_FROM_THREAD(network_thread_checker_);
}

Cronet_EngineImpl::Callback::~Callback() = default;

void Cronet_EngineImpl::Callback::OnInitNetworkThread() {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  // It is possible that engine_->context_ is reset from main thread while
  // being intialized on network thread.
  base::AutoLock lock(engine_->lock_);
  if (engine_->context_) {
    // Initialize bidirectional stream engine for grpc.
    engine_->stream_engine_ = std::make_unique<StreamEngineImpl>(
        engine_->context_->CreateURLRequestContextGetter());
    engine_->init_completed_.Signal();
  }
}

void Cronet_EngineImpl::Callback::OnDestroyNetworkThread() {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  DCHECK(!engine_->stream_engine_);
}

void Cronet_EngineImpl::Callback::OnEffectiveConnectionTypeChanged(
    net::EffectiveConnectionType effective_connection_type) {
  NOTIMPLEMENTED();
}

void Cronet_EngineImpl::Callback::OnRTTOrThroughputEstimatesComputed(
    int32_t http_rtt_ms,
    int32_t transport_rtt_ms,
    int32_t downstream_throughput_kbps) {
  NOTIMPLEMENTED();
}

void Cronet_EngineImpl::Callback::OnRTTObservation(
    int32_t rtt_ms,
    int32_t timestamp_ms,
    net::NetworkQualityObservationSource source) {
  NOTIMPLEMENTED();
}

void Cronet_EngineImpl::Callback::OnThroughputObservation(
    int32_t throughput_kbps,
    int32_t timestamp_ms,
    net::NetworkQualityObservationSource source) {
  NOTIMPLEMENTED();
}

void Cronet_EngineImpl::Callback::OnStopNetLogCompleted() {
  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
  CHECK(engine_);
  base::AutoLock lock(engine_->lock_);
  DCHECK(engine_->is_logging_);
  engine_->is_logging_ = false;
  engine_->stop_netlog_completed_.Signal();
}

Cronet_EngineImpl::Cronet_EngineImpl()
    : init_completed_(base::WaitableEvent::ResetPolicy::MANUAL,
                      base::WaitableEvent::InitialState::NOT_SIGNALED),
      stop_netlog_completed_(base::WaitableEvent::ResetPolicy::MANUAL,
                             base::WaitableEvent::InitialState::NOT_SIGNALED) {}

Cronet_EngineImpl::~Cronet_EngineImpl() {
  Shutdown();
}

Cronet_RESULT Cronet_EngineImpl::StartWithParams(
    Cronet_EngineParamsPtr params) {
  cronet::EnsureInitialized();
  base::AutoLock lock(lock_);

  enable_check_result_ = params->enable_check_result;
  if (context_) {
    return CheckResult(Cronet_RESULT_ILLEGAL_STATE_ENGINE_ALREADY_STARTED);
  }

  URLRequestContextConfigBuilder context_config_builder;
  context_config_builder.enable_quic = params->enable_quic;
  context_config_builder.enable_spdy = params->enable_http2;
  context_config_builder.enable_brotli = params->enable_brotli;
  switch (params->http_cache_mode) {
    case Cronet_EngineParams_HTTP_CACHE_MODE_DISABLED:
      context_config_builder.http_cache = URLRequestContextConfig::DISABLED;
      break;
    case Cronet_EngineParams_HTTP_CACHE_MODE_IN_MEMORY:
      context_config_builder.http_cache = URLRequestContextConfig::MEMORY;
      break;
    case Cronet_EngineParams_HTTP_CACHE_MODE_DISK: {
      context_config_builder.http_cache = URLRequestContextConfig::DISK;
#if BUILDFLAG(IS_WIN)
      const base::FilePath storage_path(
          base::FilePath::FromUTF8Unsafe(params->storage_path));
#else
      const base::FilePath storage_path(params->storage_path);
#endif
      if (!base::DirectoryExists(storage_path)) {
        return CheckResult(
            Cronet_RESULT_ILLEGAL_ARGUMENT_STORAGE_PATH_MUST_EXIST);
      }
      if (!SharedEngineState::GetInstance()->MarkStoragePathInUse(
              params->storage_path)) {
        LOG(ERROR) << "Disk cache path " << params->storage_path
                   << " is already used, cache disabled.";
        return CheckResult(Cronet_RESULT_ILLEGAL_STATE_STORAGE_PATH_IN_USE);
      }
      in_use_storage_path_ = params->storage_path;
      break;
    }
    default:
      context_config_builder.http_cache = URLRequestContextConfig::DISABLED;
  }
  context_config_builder.http_cache_max_size = params->http_cache_max_size;
  context_config_builder.storage_path = params->storage_path;
  context_config_builder.accept_language = params->accept_language;
  context_config_builder.user_agent = params->user_agent;
  context_config_builder.experimental_options = params->experimental_options;
  context_config_builder.bypass_public_key_pinning_for_local_trust_anchors =
      params->enable_public_key_pinning_bypass_for_local_trust_anchors;
  if (!isnan(params->network_thread_priority)) {
    context_config_builder.network_thread_priority =
        params->network_thread_priority;
  }

  // MockCertVerifier to use for testing purposes.
  context_config_builder.mock_cert_verifier = std::move(mock_cert_verifier_);
  std::unique_ptr<URLRequestContextConfig> config =
      context_config_builder.Build();

  for (const auto& public_key_pins : params->public_key_pins) {
    auto pkp = std::make_unique<URLRequestContextConfig::Pkp>(
        public_key_pins.host, public_key_pins.include_subdomains,
        base::Time::FromMillisecondsSinceUnixEpoch(
            public_key_pins.expiration_date));
    if (pkp->host.empty())
      return CheckResult(Cronet_RESULT_NULL_POINTER_HOSTNAME);
    if (!IsValidHostnameForPkp(pkp->host))
      return CheckResult(Cronet_RESULT_ILLEGAL_ARGUMENT_INVALID_HOSTNAME);
    if (pkp->expiration_date.is_null())
      return CheckResult(Cronet_RESULT_NULL_POINTER_EXPIRATION_DATE);
    if (public_key_pins.pins_sha256.empty())
      return CheckResult(Cronet_RESULT_NULL_POINTER_SHA256_PINS);
    for (const auto& pin_sha256 : public_key_pins.pins_sha256) {
      net::HashValue pin_hash;
      if (!pin_hash.FromString(pin_sha256))
        return CheckResult(Cronet_RESULT_ILLEGAL_ARGUMENT_INVALID_PIN);
      pkp->pin_hashes.push_back(pin_hash);
    }
    config->pkp_list.push_back(std::move(pkp));
  }

  for (const auto& quic_hint : params->quic_hints) {
    config->quic_hints.push_back(
        std::make_unique<URLRequestContextConfig::QuicHint>(
            quic_hint.host, quic_hint.port, quic_hint.alternate_port));
  }

  context_ = std::make_unique<CronetContext>(std::move(config),
                                             std::make_unique<Callback>(this));

  // TODO(mef): It'd be nice to remove the java code and this code, and get
  // rid of CronetContextAdapter::InitRequestContextOnInitThread.
  // Could also make CronetContext::InitRequestContextOnInitThread()
  // private and mark CronetLibraryLoader.postToInitThread() as
  // @VisibleForTesting (as the only external use will be in a test).

  // Initialize context on the init thread.
  cronet::PostTaskToInitThread(
      FROM_HERE, base::BindOnce(&CronetContext::InitRequestContextOnInitThread,
                                base::Unretained(context_.get())));
  return CheckResult(Cronet_RESULT_SUCCESS);
}

bool Cronet_EngineImpl::StartNetLogToFile(Cronet_String file_name,
                                          bool log_all) {
  base::AutoLock lock(lock_);
  if (is_logging_ || !context_)
    return false;
  is_logging_ = context_->StartNetLogToFile(file_name, log_all);
  return is_logging_;
}

void Cronet_EngineImpl::StopNetLog() {
  {
    base::AutoLock lock(lock_);
    if (!is_logging_ || !context_)
      return;
    context_->StopNetLog();
    // Release |lock| so it could be acquired in OnStopNetLog.
  }
  stop_netlog_completed_.Wait();
  stop_netlog_completed_.Reset();
}

Cronet_String Cronet_EngineImpl::GetVersionString() {
  return CRONET_VERSION;
}

Cronet_String Cronet_EngineImpl::GetDefaultUserAgent() {
  return SharedEngineState::GetInstance()->GetDefaultUserAgent();
}

Cronet_RESULT Cronet_EngineImpl::Shutdown() {
  {  // Check whether engine is running.
    base::AutoLock lock(lock_);
    if (!context_)
      return CheckResult(Cronet_RESULT_SUCCESS);
  }
  // Wait for init to complete on init and network thread (without lock, so
  // other thread could access it).
  init_completed_.Wait();
  // If not logging, this is a no-op.
  StopNetLog();
  // Stop the engine.
  base::AutoLock lock(lock_);
  if (context_->IsOnNetworkThread()) {
    return CheckResult(
        Cronet_RESULT_ILLEGAL_STATE_CANNOT_SHUTDOWN_ENGINE_FROM_NETWORK_THREAD);
  }

  if (!in_use_storage_path_.empty()) {
    SharedEngineState::GetInstance()->UnmarkStoragePathInUse(
        in_use_storage_path_);
  }

  stream_engine_.reset();
  context_.reset();
  return CheckResult(Cronet_RESULT_SUCCESS);
}

void Cronet_EngineImpl::AddRequestFinishedListener(
    Cronet_RequestFinishedInfoListenerPtr listener,
    Cronet_ExecutorPtr executor) {
  if (listener == nullptr || executor == nullptr) {
    LOG(DFATAL) << "Both listener and executor must be non-null. listener: "
                << listener << " executor: " << executor << ".";
    return;
  }
  base::AutoLock lock(lock_);
  if (request_finished_registrations_.count(listener) > 0) {
    LOG(DFATAL) << "Listener " << listener
                << " already registered with executor "
                << request_finished_registrations_[listener]
                << ", *NOT* changing to new executor " << executor << ".";
    return;
  }
  request_finished_registrations_.insert({listener, executor});
}

void Cronet_EngineImpl::RemoveRequestFinishedListener(
    Cronet_RequestFinishedInfoListenerPtr listener) {
  base::AutoLock lock(lock_);
  if (request_finished_registrations_.erase(listener) != 1) {
    LOG(DFATAL) << "Asked to erase non-existent RequestFinishedInfoListener "
                << listener << ".";
  }
}

namespace {

using RequestFinishedInfo = base::RefCountedData<Cronet_RequestFinishedInfo>;
using UrlResponseInfo = base::RefCountedData<Cronet_UrlResponseInfo>;
using CronetError = base::RefCountedData<Cronet_Error>;

template <typename T>
T* GetData(scoped_refptr<base::RefCountedData<T>> ptr) {
  return ptr == nullptr ? nullptr : &ptr->data;
}

}  // namespace

void Cronet_EngineImpl::ReportRequestFinished(
    scoped_refptr<RequestFinishedInfo> request_info,
    scoped_refptr<UrlResponseInfo> url_response_info,
    scoped_refptr<CronetError> error) {
  base::flat_map<Cronet_RequestFinishedInfoListenerPtr, Cronet_ExecutorPtr>
      registrations;
  {
    base::AutoLock lock(lock_);
    // We copy under to avoid calling callbacks (which may run on direct
    // executors and call Engine methods) with the lock held.
    //
    // The map holds only pointers and shouldn't be very large.
    registrations = request_finished_registrations_;
  }
  for (auto& pair : registrations) {
    auto* request_finished_listener = pair.first;
    auto* request_finished_executor = pair.second;

    request_finished_executor->Execute(
        new cronet::OnceClosureRunnable(base::BindOnce(
            [](Cronet_RequestFinishedInfoListenerPtr request_finished_listener,
               scoped_refptr<RequestFinishedInfo> request_info,
               scoped_refptr<UrlResponseInfo> url_response_info,
               scoped_refptr<CronetError> error) {
              request_finished_listener->OnRequestFinished(
                  GetData(request_info), GetData(url_response_info),
                  GetData(error));
            },
            request_finished_listener, request_info, url_response_info,
            error)));
  }
}

Cronet_RESULT Cronet_EngineImpl::CheckResult(Cronet_RESULT result) {
  if (enable_check_result_)
    CHECK_EQ(Cronet_RESULT_SUCCESS, result);
  return result;
}

bool Cronet_EngineImpl::HasRequestFinishedListener() {
  base::AutoLock lock(lock_);
  return request_finished_registrations_.size() > 0;
}

void Cronet_EngineImpl::SetMockCertVerifierForTesting(
    std::unique_ptr<net::CertVerifier> mock_cert_verifier) {
  CHECK(!context_);
  mock_cert_verifier_ = std::move(mock_cert_verifier);
}

stream_engine* Cronet_EngineImpl::GetBidirectionalStreamEngine() {
  init_completed_.Wait();
  return stream_engine_.get();
}

}  // namespace cronet

CRONET_EXPORT Cronet_EnginePtr Cronet_Engine_Create() {
  return new cronet::Cronet_EngineImpl();
}

CRONET_EXPORT void Cronet_Engine_SetMockCertVerifierForTesting(
    Cronet_EnginePtr engine,
    void* raw_mock_cert_verifier) {
  cronet::Cronet_EngineImpl* engine_impl =
      static_cast<cronet::Cronet_EngineImpl*>(engine);
  std::unique_ptr<net::CertVerifier> cert_verifier;
  cert_verifier.reset(static_cast<net::CertVerifier*>(raw_mock_cert_verifier));
  engine_impl->SetMockCertVerifierForTesting(std::move(cert_verifier));
}

CRONET_EXPORT stream_engine* Cronet_Engine_GetStreamEngine(
    Cronet_EnginePtr engine) {
  cronet::Cronet_EngineImpl* engine_impl =
      static_cast<cronet::Cronet_EngineImpl*>(engine);
  return engine_impl->GetBidirectionalStreamEngine();
}
