// 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/android/cronet_context_adapter.h"
#include "components/cronet/android/proto/request_context_config.pb.h"

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

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

#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#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/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.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 "components/cronet/android/buildflags.h"
#include "components/cronet/android/cronet_jni_headers/CronetUrlRequestContext_jni.h"
#include "components/cronet/android/cronet_library_loader.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 "components/metrics/library_support/histogram_manager.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/url_util.h"
#include "net/cert/caching_cert_verifier.h"
#include "net/cert/cert_verifier.h"
#include "net/cookies/cookie_monster.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/log/file_net_log_observer.h"
#include "net/log/net_log_util.h"
#include "net/nqe/network_quality_estimator_params.h"
#include "net/proxy_resolution/proxy_config_service_android.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_interceptor.h"

#if BUILDFLAG(INTEGRATED_MODE)
#include "components/cronet/android/cronet_integrated_mode_state.h"
#endif

using base::android::JavaParamRef;
using base::android::ScopedJavaLocalRef;

namespace cronet {

CronetContextAdapter::CronetContextAdapter(
    std::unique_ptr<URLRequestContextConfig> context_config) {
  // Create context and pass ownership of |this| (self) to the context.
  std::unique_ptr<CronetContextAdapter> self(this);
#if BUILDFLAG(INTEGRATED_MODE)
  // Create CronetContext running in integrated network task runner.
  context_ = new CronetContext(std::move(context_config), std::move(self),
                               GetIntegratedModeNetworkTaskRunner());
#else
  context_ = new CronetContext(std::move(context_config), std::move(self));
#endif
}

CronetContextAdapter::~CronetContextAdapter() = default;

void CronetContextAdapter::InitRequestContextOnInitThread(
    JNIEnv* env,
    const JavaParamRef<jobject>& jcaller) {
  jcronet_url_request_context_.Reset(env, jcaller);
  context_->InitRequestContextOnInitThread();
}

void CronetContextAdapter::ConfigureNetworkQualityEstimatorForTesting(
    JNIEnv* env,
    const JavaParamRef<jobject>& jcaller,
    jboolean use_local_host_requests,
    jboolean use_smaller_responses,
    jboolean disable_offline_check) {
  context_->ConfigureNetworkQualityEstimatorForTesting(
      use_local_host_requests == JNI_TRUE, use_smaller_responses == JNI_TRUE,
      disable_offline_check == JNI_TRUE);
}

bool CronetContextAdapter::URLRequestContextExistsForTesting(
    net::handles::NetworkHandle network) {
  return context_->URLRequestContextExistsForTesting(network);  // IN-TEST
}

void CronetContextAdapter::ProvideRTTObservations(
    JNIEnv* env,
    const JavaParamRef<jobject>& jcaller,
    bool should) {
  context_->ProvideRTTObservations(should == JNI_TRUE);
}

void CronetContextAdapter::ProvideThroughputObservations(
    JNIEnv* env,
    const JavaParamRef<jobject>& jcaller,
    bool should) {
  context_->ProvideThroughputObservations(should == JNI_TRUE);
}

void CronetContextAdapter::OnInitNetworkThread() {
  JNIEnv* env = base::android::AttachCurrentThread();
  Java_CronetUrlRequestContext_initNetworkThread(env,
                                                 jcronet_url_request_context_);
}

void CronetContextAdapter::OnDestroyNetworkThread() {
  // The |context_| is destroyed.
  context_ = nullptr;
}

void CronetContextAdapter::OnEffectiveConnectionTypeChanged(
    net::EffectiveConnectionType effective_connection_type) {
  Java_CronetUrlRequestContext_onEffectiveConnectionTypeChanged(
      base::android::AttachCurrentThread(), jcronet_url_request_context_,
      effective_connection_type);
}

void CronetContextAdapter::OnRTTOrThroughputEstimatesComputed(
    int32_t http_rtt_ms,
    int32_t transport_rtt_ms,
    int32_t downstream_throughput_kbps) {
  Java_CronetUrlRequestContext_onRTTOrThroughputEstimatesComputed(
      base::android::AttachCurrentThread(), jcronet_url_request_context_,
      http_rtt_ms, transport_rtt_ms, downstream_throughput_kbps);
}

void CronetContextAdapter::OnRTTObservation(
    int32_t rtt_ms,
    int32_t timestamp_ms,
    net::NetworkQualityObservationSource source) {
  Java_CronetUrlRequestContext_onRttObservation(
      base::android::AttachCurrentThread(), jcronet_url_request_context_,
      rtt_ms, timestamp_ms, source);
}

void CronetContextAdapter::OnThroughputObservation(
    int32_t throughput_kbps,
    int32_t timestamp_ms,
    net::NetworkQualityObservationSource source) {
  Java_CronetUrlRequestContext_onThroughputObservation(
      base::android::AttachCurrentThread(), jcronet_url_request_context_,
      throughput_kbps, timestamp_ms, source);
}

void CronetContextAdapter::OnStopNetLogCompleted() {
  Java_CronetUrlRequestContext_stopNetLogCompleted(
      base::android::AttachCurrentThread(), jcronet_url_request_context_);
}

void CronetContextAdapter::Destroy(JNIEnv* env,
                                   const JavaParamRef<jobject>& jcaller) {
  // Deleting |context_| on client thread will post cleanup onto network thread,
  // which will in turn delete |this| on network thread.
  delete context_;
}

net::URLRequestContext* CronetContextAdapter::GetURLRequestContext(
    net::handles::NetworkHandle network) {
  return context_->GetURLRequestContext(network);
}

void CronetContextAdapter::PostTaskToNetworkThread(
    const base::Location& posted_from,
    base::OnceClosure callback) {
  context_->PostTaskToNetworkThread(posted_from, std::move(callback));
}

bool CronetContextAdapter::IsOnNetworkThread() const {
  return context_->IsOnNetworkThread();
}

bool CronetContextAdapter::StartNetLogToFile(
    JNIEnv* env,
    const JavaParamRef<jobject>& jcaller,
    const JavaParamRef<jstring>& jfile_name,
    jboolean jlog_all) {
  std::string file_name(
      base::android::ConvertJavaStringToUTF8(env, jfile_name));
  return context_->StartNetLogToFile(file_name, jlog_all == JNI_TRUE);
}

void CronetContextAdapter::StartNetLogToDisk(
    JNIEnv* env,
    const JavaParamRef<jobject>& jcaller,
    const JavaParamRef<jstring>& jdir_name,
    jboolean jlog_all,
    jint jmax_size) {
  std::string dir_name(base::android::ConvertJavaStringToUTF8(env, jdir_name));
  context_->StartNetLogToDisk(dir_name, jlog_all == JNI_TRUE, jmax_size);
}

void CronetContextAdapter::StopNetLog(JNIEnv* env,
                                      const JavaParamRef<jobject>& jcaller) {
  context_->StopNetLog();
}

bool CronetContextAdapter::GetEnableTelemetry(
    JNIEnv* env,
    const JavaParamRef<jobject>& jcaller) {
  return context_->enable_telemetry() ? JNI_TRUE : JNI_FALSE;
}

int CronetContextAdapter::default_load_flags() const {
  return context_->default_load_flags();
}

// Create a URLRequestContextConfig from the given parameters.
static jlong JNI_CronetUrlRequestContext_CreateRequestContextConfig(
    JNIEnv* env,
    const JavaParamRef<jbyteArray>& javaSerializedProto) {
  const int serializedProtoLength = env->GetArrayLength(javaSerializedProto);
  org::chromium::net::RequestContextConfigOptions configOptions;

  std::vector<uint8_t> serializedProto;

  JavaByteArrayToByteVector(env, javaSerializedProto, &serializedProto);

  if (!configOptions.ParseFromArray(serializedProto.data(),
                                    serializedProtoLength)) {
    return 0;
  }

  std::unique_ptr<URLRequestContextConfig> url_request_context_config =
      URLRequestContextConfig::CreateURLRequestContextConfig(
          configOptions.quic_enabled(),
          configOptions.quic_default_user_agent_id(),
          configOptions.http2_enabled(), configOptions.brotli_enabled(),
          static_cast<URLRequestContextConfig::HttpCacheType>(
              configOptions.http_cache_mode()),
          configOptions.http_cache_max_size(), configOptions.disable_cache(),
          configOptions.storage_path(),
          /* accept_languages */ std::string(), configOptions.user_agent(),
          configOptions.experimental_options(),
          base::WrapUnique(reinterpret_cast<net::CertVerifier*>(
              configOptions.mock_cert_verifier())),
          configOptions.enable_network_quality_estimator(),
          configOptions.bypass_public_key_pinning_for_local_trust_anchors(),
          configOptions.network_thread_priority() >= -20 &&
                  configOptions.network_thread_priority() <= 19
              ? absl::optional<double>(configOptions.network_thread_priority())
              : absl::optional<double>());
  return reinterpret_cast<jlong>(url_request_context_config.release());
}

// Add a QUIC hint to a URLRequestContextConfig.
static void JNI_CronetUrlRequestContext_AddQuicHint(
    JNIEnv* env,
    jlong jurl_request_context_config,
    const JavaParamRef<jstring>& jhost,
    jint jport,
    jint jalternate_port) {
  URLRequestContextConfig* config =
      reinterpret_cast<URLRequestContextConfig*>(jurl_request_context_config);
  config->quic_hints.push_back(
      std::make_unique<URLRequestContextConfig::QuicHint>(
          base::android::ConvertJavaStringToUTF8(env, jhost), jport,
          jalternate_port));
}

// Add a public key pin to URLRequestContextConfig.
// |jhost| is the host to apply the pin to.
// |jhashes| is an array of jbyte[32] representing SHA256 key hashes.
// |jinclude_subdomains| indicates if pin should be applied to subdomains.
// |jexpiration_time| is the time that the pin expires, in milliseconds since
// Jan. 1, 1970, midnight GMT.
static void JNI_CronetUrlRequestContext_AddPkp(
    JNIEnv* env,
    jlong jurl_request_context_config,
    const JavaParamRef<jstring>& jhost,
    const JavaParamRef<jobjectArray>& jhashes,
    jboolean jinclude_subdomains,
    jlong jexpiration_time) {
  URLRequestContextConfig* config =
      reinterpret_cast<URLRequestContextConfig*>(jurl_request_context_config);
  std::unique_ptr<URLRequestContextConfig::Pkp> pkp(
      new URLRequestContextConfig::Pkp(
          base::android::ConvertJavaStringToUTF8(env, jhost),
          jinclude_subdomains,
          base::Time::UnixEpoch() + base::Milliseconds(jexpiration_time)));
  for (auto bytes_array : jhashes.ReadElements<jbyteArray>()) {
    static_assert(std::is_pod<net::SHA256HashValue>::value,
                  "net::SHA256HashValue is not POD");
    static_assert(sizeof(net::SHA256HashValue) * CHAR_BIT == 256,
                  "net::SHA256HashValue contains overhead");
    if (env->GetArrayLength(bytes_array.obj()) !=
        sizeof(net::SHA256HashValue)) {
      LOG(ERROR) << "Unable to add public key hash value.";
      continue;
    }
    jbyte* bytes = env->GetByteArrayElements(bytes_array.obj(), nullptr);
    net::HashValue hash(*reinterpret_cast<net::SHA256HashValue*>(bytes));
    pkp->pin_hashes.push_back(hash);
    env->ReleaseByteArrayElements(bytes_array.obj(), bytes, JNI_ABORT);
  }
  config->pkp_list.push_back(std::move(pkp));
}

// Creates RequestContextAdater if config is valid URLRequestContextConfig,
// returns 0 otherwise.
static jlong JNI_CronetUrlRequestContext_CreateRequestContextAdapter(
    JNIEnv* env,
    jlong jconfig) {
  std::unique_ptr<URLRequestContextConfig> context_config(
      reinterpret_cast<URLRequestContextConfig*>(jconfig));

  CronetContextAdapter* context_adapter =
      new CronetContextAdapter(std::move(context_config));
  return reinterpret_cast<jlong>(context_adapter);
}

static jint JNI_CronetUrlRequestContext_SetMinLogLevel(JNIEnv* env,
                                                       jint jlog_level) {
  jint old_log_level = static_cast<jint>(logging::GetMinLogLevel());
  // MinLogLevel is global, shared by all URLRequestContexts.
  logging::SetMinLogLevel(static_cast<int>(jlog_level));
  return old_log_level;
}

static ScopedJavaLocalRef<jbyteArray>
JNI_CronetUrlRequestContext_GetHistogramDeltas(JNIEnv* env) {
  std::vector<uint8_t> data;
  if (!metrics::HistogramManager::GetInstance()->GetDeltas(&data))
    return ScopedJavaLocalRef<jbyteArray>();
  return base::android::ToJavaByteArray(env, data.data(), data.size());
}

}  // namespace cronet
