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

#include "services/data_decoder/public/cpp/data_decoder.h"

#include <memory>
#include <string>
#include <utility>

#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/no_destructor.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "build/blink_buildflags.h"
#include "build/build_config.h"
#include "net/http/structured_headers.h"
#include "services/data_decoder/public/mojom/gzipper.mojom.h"
#include "services/data_decoder/public/mojom/structured_headers_parser.mojom.h"
#include "services/data_decoder/public/mojom/xml_parser.mojom.h"

#if !BUILDFLAG(USE_BLINK)
#include "services/data_decoder/data_decoder_service.h"  // nogncheck
#endif

namespace data_decoder {

namespace {

// The default amount of idle time to tolerate on a DataDecoder instance. If the
// instance is unused for this period of time, the underlying service process
// (if any) may be killed and only restarted once needed again.
// On platforms (like iOS) or environments (like some unit tests) where
// out-of-process services are not used, this has no effect.
constexpr base::TimeDelta kServiceProcessIdleTimeoutDefault{base::Seconds(5)};

// Encapsulates an in-process data decoder parsing request. This provides shared
// ownership of the caller's callback so that it may be invoked exactly once by
// *either* the successful response handler *or* the parser's disconnection
// handler. This also owns a Remote<T> which is kept alive for the duration of
// the request.
template <typename T, typename V>
class ValueParseRequest : public base::RefCounted<ValueParseRequest<T, V>> {
 public:
  ValueParseRequest(DataDecoder::ResultCallback<V> callback,
                    scoped_refptr<DataDecoder::CancellationFlag> is_cancelled)
      : callback_(std::move(callback)), is_cancelled_(is_cancelled) {}

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

  mojo::Remote<T>& remote() { return remote_; }
  DataDecoder::ResultCallback<V>& callback() { return callback_; }

  // Creates a pipe and binds it to the remote(), and sets up the
  // disconnect handler to invoke callback() with an error.
  mojo::PendingReceiver<T> BindRemote() {
    auto receiver = remote_.BindNewPipeAndPassReceiver();
    remote_.set_disconnect_handler(
        base::BindOnce(&ValueParseRequest::OnRemoteDisconnected, this));
    return receiver;
  }

  void OnServiceValue(std::optional<V> value) {
    OnServiceValueOrError(std::move(value), std::nullopt);
  }

  // Handles a successful parse from the service.
  void OnServiceValueOrError(std::optional<V> value,
                             const std::optional<std::string>& error) {
    if (!callback() || is_cancelled_->data) {
      return;
    }

    base::expected<V, std::string> result;
    if (value) {
      result = std::move(*value);
    } else {
      result = base::unexpected(error.value_or("unknown error"));
    }

    // Copy the callback onto the stack before resetting the Remote, as that may
    // delete |this|.
    auto local_callback = std::move(callback());

    // Reset the |remote_| since we aren't using it again and we don't want it
    // to trip the disconnect handler. May delete |this|.
    remote_.reset();

    // We run the callback after reset just in case it does anything funky like
    // spin a nested RunLoop.
    std::move(local_callback).Run(std::move(result));
  }

 private:
  friend class base::RefCounted<ValueParseRequest>;

  ~ValueParseRequest() = default;

  void OnRemoteDisconnected() {
    if (is_cancelled_->data) {
      return;
    }

    if (callback()) {
      std::move(callback())
          .Run(base::unexpected("Data Decoder terminated unexpectedly"));
    }
  }

  mojo::Remote<T> remote_;
  DataDecoder::ResultCallback<V> callback_;
  scoped_refptr<DataDecoder::CancellationFlag> is_cancelled_;
};

#if !BUILDFLAG(USE_BLINK)
void BindInProcessService(
    mojo::PendingReceiver<mojom::DataDecoderService> receiver) {
  static base::NoDestructor<scoped_refptr<base::SequencedTaskRunner>>
      task_runner{base::ThreadPool::CreateSequencedTaskRunner({})};
  if (!(*task_runner)->RunsTasksInCurrentSequence()) {
    (*task_runner)
        ->PostTask(FROM_HERE,
                   base::BindOnce(&BindInProcessService, std::move(receiver)));
    return;
  }

  static base::NoDestructor<DataDecoderService> service;
  service->BindReceiver(std::move(receiver));
}
#endif

}  // namespace

DataDecoder::DataDecoder() : DataDecoder(kServiceProcessIdleTimeoutDefault) {}

DataDecoder::DataDecoder(base::TimeDelta idle_timeout)
    : idle_timeout_(idle_timeout),
      cancel_requests_(new CancellationFlag(false)) {}

DataDecoder::~DataDecoder() {
  cancel_requests_->data = true;
}

mojom::DataDecoderService* DataDecoder::GetService() {
  // Lazily start an instance of the service if possible and necessary.
  if (!service_) {
    auto* provider = ServiceProvider::Get();
    if (provider) {
      provider->BindDataDecoderService(service_.BindNewPipeAndPassReceiver());
    } else {
#if !BUILDFLAG(USE_BLINK)
      BindInProcessService(service_.BindNewPipeAndPassReceiver());
#else
      LOG(FATAL) << "data_decoder::ServiceProvider::Set() must be called "
                 << "before any instances of DataDecoder can be used.";
#endif
    }

    service_.reset_on_disconnect();
    service_.reset_on_idle_timeout(idle_timeout_);
  }

  return service_.get();
}

void DataDecoder::ParseStructuredHeaderItem(
    const std::string& header,
    StructuredHeaderParseItemCallback callback) {
  auto request = base::MakeRefCounted<
      ValueParseRequest<mojom::StructuredHeadersParser,
                        net::structured_headers::ParameterizedItem>>(
      std::move(callback), cancel_requests_);
  GetService()->BindStructuredHeadersParser(request->BindRemote());
  request->remote()->ParseItem(
      header,
      base::BindOnce(
          &ValueParseRequest<
              mojom::StructuredHeadersParser,
              net::structured_headers::ParameterizedItem>::OnServiceValue,
          request));
}

// static
void DataDecoder::ParseStructuredHeaderItemIsolated(
    const std::string& header,
    StructuredHeaderParseItemCallback callback) {
  auto decoder = std::make_unique<DataDecoder>();
  auto* raw_decoder = decoder.get();

  // We bind the DataDecoder's ownership into the result callback to ensure that
  // it stays alive until the operation is complete.
  raw_decoder->ParseStructuredHeaderItem(
      header, base::BindOnce(
                  [](std::unique_ptr<DataDecoder>,
                     StructuredHeaderParseItemCallback callback,
                     base::expected<net::structured_headers::ParameterizedItem,
                                    std::string> result) {
                    std::move(callback).Run(std::move(result));
                  },
                  std::move(decoder), std::move(callback)));
}

void DataDecoder::ParseStructuredHeaderList(
    const std::string& header,
    StructuredHeaderParseListCallback callback) {
  auto request =
      base::MakeRefCounted<ValueParseRequest<mojom::StructuredHeadersParser,
                                             net::structured_headers::List>>(
          std::move(callback), cancel_requests_);
  GetService()->BindStructuredHeadersParser(request->BindRemote());
  request->remote()->ParseList(
      header,
      base::BindOnce(
          &ValueParseRequest<mojom::StructuredHeadersParser,
                             net::structured_headers::List>::OnServiceValue,
          request));
}

// static
void DataDecoder::ParseStructuredHeaderListIsolated(
    const std::string& header,
    StructuredHeaderParseListCallback callback) {
  auto decoder = std::make_unique<DataDecoder>();
  auto* raw_decoder = decoder.get();

  // We bind the DataDecoder's ownership into the result callback to ensure that
  // it stays alive until the operation is complete.
  raw_decoder->ParseStructuredHeaderList(
      header,
      base::BindOnce(
          [](std::unique_ptr<DataDecoder>,
             StructuredHeaderParseListCallback callback,
             base::expected<net::structured_headers::List, std::string>
                 result) { std::move(callback).Run(std::move(result)); },
          std::move(decoder), std::move(callback)));
}

void DataDecoder::ParseStructuredHeaderDictionary(
    const std::string& header,
    StructuredHeaderParseDictionaryCallback callback) {
  auto request = base::MakeRefCounted<ValueParseRequest<
      mojom::StructuredHeadersParser, net::structured_headers::Dictionary>>(
      std::move(callback), cancel_requests_);
  GetService()->BindStructuredHeadersParser(request->BindRemote());
  request->remote()->ParseDictionary(
      header,
      base::BindOnce(&ValueParseRequest<
                         mojom::StructuredHeadersParser,
                         net::structured_headers::Dictionary>::OnServiceValue,
                     request));
}

// static
void DataDecoder::ParseStructuredHeaderDictionaryIsolated(
    const std::string& header,
    StructuredHeaderParseDictionaryCallback callback) {
  auto decoder = std::make_unique<DataDecoder>();
  auto* raw_decoder = decoder.get();

  // We bind the DataDecoder's ownership into the result callback to ensure that
  // it stays alive until the operation is complete.
  raw_decoder->ParseStructuredHeaderDictionary(
      header,
      base::BindOnce(
          [](std::unique_ptr<DataDecoder>,
             StructuredHeaderParseDictionaryCallback callback,
             base::expected<net::structured_headers::Dictionary, std::string>
                 result) { std::move(callback).Run(std::move(result)); },
          std::move(decoder), std::move(callback)));
}

void DataDecoder::ParseXml(
    const std::string& xml,
    mojom::XmlParser::WhitespaceBehavior whitespace_behavior,
    ValueParseCallback callback) {
  auto request =
      base::MakeRefCounted<ValueParseRequest<mojom::XmlParser, base::Value>>(
          std::move(callback), cancel_requests_);
  GetService()->BindXmlParser(request->BindRemote());
  request->remote()->Parse(
      xml, whitespace_behavior,
      base::BindOnce(&ValueParseRequest<mojom::XmlParser,
                                        base::Value>::OnServiceValueOrError,
                     request));
}

// static
void DataDecoder::ParseXmlIsolated(
    const std::string& xml,
    mojom::XmlParser::WhitespaceBehavior whitespace_behavior,
    ValueParseCallback callback) {
  auto decoder = std::make_unique<DataDecoder>();
  auto* raw_decoder = decoder.get();

  // We bind the DataDecoder's ownership into the result callback to ensure that
  // it stays alive until the operation is complete.
  raw_decoder->ParseXml(
      xml, whitespace_behavior,
      base::BindOnce(
          [](std::unique_ptr<DataDecoder>, ValueParseCallback callback,
             ValueOrError result) {
            std::move(callback).Run(std::move(result));
          },
          std::move(decoder), std::move(callback)));
}

void DataDecoder::Deflate(base::span<const uint8_t> data,
                          GzipperCallback callback) {
  auto request = base::MakeRefCounted<
      ValueParseRequest<mojom::Gzipper, mojo_base::BigBuffer>>(
      std::move(callback), cancel_requests_);
  GetService()->BindGzipper(request->BindRemote());
  request->remote()->Deflate(
      data,
      base::BindOnce(&ValueParseRequest<mojom::Gzipper,
                                        mojo_base::BigBuffer>::OnServiceValue,
                     request));
}

void DataDecoder::Inflate(base::span<const uint8_t> data,
                          uint64_t max_uncompressed_size,
                          GzipperCallback callback) {
  auto request = base::MakeRefCounted<
      ValueParseRequest<mojom::Gzipper, mojo_base::BigBuffer>>(
      std::move(callback), cancel_requests_);
  GetService()->BindGzipper(request->BindRemote());
  request->remote()->Inflate(
      data, max_uncompressed_size,
      base::BindOnce(&ValueParseRequest<mojom::Gzipper,
                                        mojo_base::BigBuffer>::OnServiceValue,
                     request));
}

void DataDecoder::GzipCompress(base::span<const uint8_t> data,
                               GzipperCallback callback) {
  auto request = base::MakeRefCounted<
      ValueParseRequest<mojom::Gzipper, mojo_base::BigBuffer>>(
      std::move(callback), cancel_requests_);
  GetService()->BindGzipper(request->BindRemote());
  request->remote()->Compress(
      data,
      base::BindOnce(&ValueParseRequest<mojom::Gzipper,
                                        mojo_base::BigBuffer>::OnServiceValue,
                     request));
}

void DataDecoder::GzipUncompress(base::span<const uint8_t> data,
                                 GzipperCallback callback) {
  auto request = base::MakeRefCounted<
      ValueParseRequest<mojom::Gzipper, mojo_base::BigBuffer>>(
      std::move(callback), cancel_requests_);
  GetService()->BindGzipper(request->BindRemote());
  request->remote()->Uncompress(
      data,
      base::BindOnce(&ValueParseRequest<mojom::Gzipper,
                                        mojo_base::BigBuffer>::OnServiceValue,
                     request));
}

}  // namespace data_decoder
