// Copyright (c) 2019 The Chromium Embedded Framework 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 "libcef/browser/net_service/resource_handler_wrapper.h"

#include "libcef/browser/net_service/proxy_url_loader_factory.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/net_service/net_service_util.h"
#include "libcef/common/request_impl.h"

#include "base/strings/string_number_conversions.h"
#include "net/http/http_status_code.h"

namespace net_service {

namespace {

class SkipCallbackWrapper : public CefResourceSkipCallback {
 public:
  explicit SkipCallbackWrapper(InputStream::SkipCallback callback)
      : callback_(std::move(callback)),
        work_thread_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}

  ~SkipCallbackWrapper() override {
    if (!callback_.is_null()) {
      // Make sure it executes on the correct thread.
      work_thread_task_runner_->PostTask(
          FROM_HERE, base::BindOnce(std::move(callback_), net::ERR_FAILED));
    }
  }

  void Continue(int64 bytes_skipped) override {
    if (!work_thread_task_runner_->RunsTasksInCurrentSequence()) {
      work_thread_task_runner_->PostTask(
          FROM_HERE,
          base::BindOnce(&SkipCallbackWrapper::Continue, this, bytes_skipped));
      return;
    }
    if (!callback_.is_null()) {
      std::move(callback_).Run(bytes_skipped);
    }
  }

  void Disconnect() { callback_.Reset(); }

 private:
  InputStream::SkipCallback callback_;

  scoped_refptr<base::SequencedTaskRunner> work_thread_task_runner_;

  IMPLEMENT_REFCOUNTING(SkipCallbackWrapper);
  DISALLOW_COPY_AND_ASSIGN(SkipCallbackWrapper);
};

class ReadCallbackWrapper : public CefResourceReadCallback {
 public:
  explicit ReadCallbackWrapper(InputStream::ReadCallback callback)
      : callback_(std::move(callback)),
        work_thread_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}

  ~ReadCallbackWrapper() override {
    if (!callback_.is_null()) {
      // Make sure it executes on the correct thread.
      work_thread_task_runner_->PostTask(
          FROM_HERE, base::BindOnce(std::move(callback_), net::ERR_FAILED));
    }
  }

  void Continue(int bytes_read) override {
    if (!work_thread_task_runner_->RunsTasksInCurrentSequence()) {
      work_thread_task_runner_->PostTask(
          FROM_HERE,
          base::BindOnce(&ReadCallbackWrapper::Continue, this, bytes_read));
      return;
    }
    if (!callback_.is_null()) {
      std::move(callback_).Run(bytes_read);
    }
  }

  void Disconnect() { callback_.Reset(); }

 private:
  InputStream::ReadCallback callback_;

  scoped_refptr<base::SequencedTaskRunner> work_thread_task_runner_;

  IMPLEMENT_REFCOUNTING(ReadCallbackWrapper);
  DISALLOW_COPY_AND_ASSIGN(ReadCallbackWrapper);
};

// Helper for accessing a CefResourceHandler without creating reference loops.
class HandlerProvider : public base::RefCountedThreadSafe<HandlerProvider> {
 public:
  explicit HandlerProvider(CefRefPtr<CefResourceHandler> handler)
      : handler_(handler) {
    DCHECK(handler_);
  }
  virtual ~HandlerProvider() {
    // Detach should have been called.
    DCHECK(!handler_);
  }

  CefRefPtr<CefResourceHandler> handler() const {
    base::AutoLock lock_scope(lock_);
    return handler_;
  }

  void Detach() {
    base::AutoLock lock_scope(lock_);
    if (!handler_)
      return;

    // Execute on the expected thread.
    CEF_POST_TASK(CEF_IOT,
                  base::BindOnce(&CefResourceHandler::Cancel, handler_));

    handler_ = nullptr;
  }

 private:
  mutable base::Lock lock_;
  CefRefPtr<CefResourceHandler> handler_;
};

class ReadResponseCallbackWrapper : public CefCallback {
 public:
  ~ReadResponseCallbackWrapper() override {
    if (callback_) {
      // This will post to the correct thread if necessary.
      callback_->Continue(net::ERR_FAILED);
    }
  }

  void Continue() override {
    CEF_POST_TASK(CEF_IOT,
                  base::BindOnce(&ReadResponseCallbackWrapper::DoRead, this));
  }

  void Cancel() override {
    CEF_POST_TASK(CEF_IOT,
                  base::BindOnce(&ReadResponseCallbackWrapper::DoCancel, this));
  }

  static void ReadResponse(scoped_refptr<HandlerProvider> handler_provider,
                           net::IOBuffer* dest,
                           int length,
                           CefRefPtr<ReadCallbackWrapper> callback) {
    CEF_POST_TASK(
        CEF_IOT,
        base::BindOnce(ReadResponseCallbackWrapper::ReadResponseOnIOThread,
                       handler_provider, base::Unretained(dest), length,
                       callback));
  }

 private:
  ReadResponseCallbackWrapper(scoped_refptr<HandlerProvider> handler_provider,
                              net::IOBuffer* dest,
                              int length,
                              CefRefPtr<ReadCallbackWrapper> callback)
      : handler_provider_(handler_provider),
        dest_(dest),
        length_(length),
        callback_(callback) {}

  static void ReadResponseOnIOThread(
      scoped_refptr<HandlerProvider> handler_provider,
      net::IOBuffer* dest,
      int length,
      CefRefPtr<ReadCallbackWrapper> callback) {
    CEF_REQUIRE_IOT();
    CefRefPtr<ReadResponseCallbackWrapper> callbackWrapper =
        new ReadResponseCallbackWrapper(handler_provider, dest, length,
                                        callback);
    callbackWrapper->DoRead();
  }

  void DoRead() {
    CEF_REQUIRE_IOT();
    if (!callback_)
      return;

    auto handler = handler_provider_->handler();
    if (!handler) {
      DoCancel();
      return;
    }

    int bytes_read = 0;
    bool result =
        handler->ReadResponse(dest_->data(), length_, bytes_read, this);
    if (result) {
      if (bytes_read > 0) {
        // Continue immediately.
        callback_->Continue(bytes_read);
        callback_ = nullptr;
      }
      return;
    }

    // Signal response completion immediately.
    callback_->Continue(0);
    callback_ = nullptr;
  }

  void DoCancel() {
    CEF_REQUIRE_IOT();
    if (callback_) {
      callback_->Continue(net::ERR_FAILED);
      callback_ = nullptr;
    }
  }

  scoped_refptr<HandlerProvider> handler_provider_;
  net::IOBuffer* const dest_;
  int length_;
  CefRefPtr<ReadCallbackWrapper> callback_;

  IMPLEMENT_REFCOUNTING(ReadResponseCallbackWrapper);
  DISALLOW_COPY_AND_ASSIGN(ReadResponseCallbackWrapper);
};

class InputStreamWrapper : public InputStream {
 public:
  explicit InputStreamWrapper(scoped_refptr<HandlerProvider> handler_provider)
      : handler_provider_(handler_provider) {}

  ~InputStreamWrapper() override { Cancel(); }

  // InputStream methods:
  bool Skip(int64_t n, int64_t* bytes_skipped, SkipCallback callback) override {
    auto handler = handler_provider_->handler();
    if (!handler) {
      // Cancel immediately.
      *bytes_skipped = net::ERR_FAILED;
      return false;
    }

    CefRefPtr<SkipCallbackWrapper> callbackWrapper =
        new SkipCallbackWrapper(std::move(callback));
    bool result = handler->Skip(n, *bytes_skipped, callbackWrapper.get());
    if (result) {
      if (*bytes_skipped > 0) {
        // Continue immediately.
        callbackWrapper->Disconnect();
      }
      return true;
    }

    // Cancel immediately.
    return false;
  }

  bool Read(net::IOBuffer* dest,
            int length,
            int* bytes_read,
            ReadCallback callback) override {
    auto handler = handler_provider_->handler();
    if (!handler) {
      // Cancel immediately.
      *bytes_read = net::ERR_FAILED;
      return false;
    }

    CefRefPtr<ReadCallbackWrapper> callbackWrapper =
        new ReadCallbackWrapper(std::move(callback));
    bool result =
        handler->Read(dest->data(), length, *bytes_read, callbackWrapper.get());
    if (result) {
      if (*bytes_read > 0) {
        // Continue immediately.
        callbackWrapper->Disconnect();
      }
      return true;
    }

    if (*bytes_read == -1) {
      // Call ReadResponse on the IO thread.
      ReadResponseCallbackWrapper::ReadResponse(handler_provider_, dest, length,
                                                callbackWrapper);
      *bytes_read = 0;
      return true;
    }

    // Complete or cancel immediately.
    return false;
  }

  void Cancel() {
    // Triggers a call to Cancel on the handler.
    handler_provider_->Detach();
  }

 private:
  scoped_refptr<HandlerProvider> handler_provider_;

  DISALLOW_COPY_AND_ASSIGN(InputStreamWrapper);
};

class OpenCallbackWrapper : public CefCallback {
 public:
  OpenCallbackWrapper(ResourceResponse::OpenCallback callback,
                      std::unique_ptr<InputStreamWrapper> stream)
      : callback_(std::move(callback)),
        stream_(std::move(stream)),
        work_thread_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}

  ~OpenCallbackWrapper() override {
    if (!callback_.is_null()) {
      // Make sure it executes on the correct thread.
      work_thread_task_runner_->PostTask(
          FROM_HERE,
          base::BindOnce(&OpenCallbackWrapper::Execute, std::move(callback_),
                         std::move(stream_), false));
    }
  }

  void Continue() override {
    if (!work_thread_task_runner_->RunsTasksInCurrentSequence()) {
      work_thread_task_runner_->PostTask(
          FROM_HERE, base::BindOnce(&OpenCallbackWrapper::Continue, this));
      return;
    }
    if (!callback_.is_null()) {
      Execute(std::move(callback_), std::move(stream_), true);
    }
  }

  void Cancel() override {
    if (!work_thread_task_runner_->RunsTasksInCurrentSequence()) {
      work_thread_task_runner_->PostTask(
          FROM_HERE, base::BindOnce(&OpenCallbackWrapper::Cancel, this));
      return;
    }
    if (!callback_.is_null()) {
      Execute(std::move(callback_), std::move(stream_), false);
    }
  }

 private:
  static void Execute(ResourceResponse::OpenCallback callback,
                      std::unique_ptr<InputStreamWrapper> stream,
                      bool cont) {
    std::move(callback).Run(cont ? std::move(stream) : nullptr);
  }

  ResourceResponse::OpenCallback callback_;
  std::unique_ptr<InputStreamWrapper> stream_;

  scoped_refptr<base::SequencedTaskRunner> work_thread_task_runner_;

  IMPLEMENT_REFCOUNTING(OpenCallbackWrapper);
  DISALLOW_COPY_AND_ASSIGN(OpenCallbackWrapper);
};

void CallProcessRequestOnIOThread(
    scoped_refptr<HandlerProvider> handler_provider,
    CefRefPtr<CefRequestImpl> request,
    CefRefPtr<OpenCallbackWrapper> callbackWrapper) {
  CEF_REQUIRE_IOT();
  auto handler = handler_provider->handler();
  if (!handler) {
    callbackWrapper->Cancel();
    return;
  }

  if (!handler->ProcessRequest(request.get(), callbackWrapper.get())) {
    callbackWrapper->Cancel();
  }
}

class ResourceResponseWrapper : public ResourceResponse {
 public:
  ResourceResponseWrapper(const RequestId request_id,
                          CefRefPtr<CefResourceHandler> handler)
      : request_id_(request_id),
        handler_provider_(new HandlerProvider(handler)) {}

  ~ResourceResponseWrapper() override {
    // Triggers a call to Cancel on the handler.
    handler_provider_->Detach();
  }

  // ResourceResponse methods:
  bool OpenInputStream(const RequestId& request_id,
                       const network::ResourceRequest& request,
                       OpenCallback callback) override {
    DCHECK_EQ(request_id, request_id_);

    auto handler = handler_provider_->handler();
    if (!handler) {
      // Cancel immediately.
      return false;
    }

    // May be recreated on redirect.
    request_ = new CefRequestImpl();
    request_->Set(&request, request_id.hash());
    request_->SetReadOnly(true);

    CefRefPtr<OpenCallbackWrapper> callbackWrapper = new OpenCallbackWrapper(
        std::move(callback),
        std::make_unique<InputStreamWrapper>(handler_provider_));
    bool handle_request = false;
    bool result =
        handler->Open(request_.get(), handle_request, callbackWrapper.get());
    if (result) {
      if (handle_request) {
        // Continue immediately.
        callbackWrapper->Continue();
      }
      return true;
    }

    if (handle_request) {
      // Cancel immediately.
      callbackWrapper->Cancel();
      return true;
    }

    // Call ProcessRequest on the IO thread.
    CEF_POST_TASK(
        CEF_IOT, base::BindOnce(CallProcessRequestOnIOThread, handler_provider_,
                                request_, callbackWrapper));
    return true;
  }

  void GetResponseHeaders(const RequestId& request_id,
                          int* status_code,
                          std::string* reason_phrase,
                          std::string* mime_type,
                          std::string* charset,
                          int64_t* content_length,
                          HeaderMap* extra_headers) override {
    DCHECK_EQ(request_id, request_id_);
    CEF_REQUIRE_IOT();

    auto handler = handler_provider_->handler();
    if (!handler) {
      // Cancel immediately.
      *status_code = net::ERR_FAILED;
      return;
    }

    CefRefPtr<CefResponse> response = CefResponse::Create();
    int64_t response_length = -1;
    CefString redirect_url;
    handler->GetResponseHeaders(response, response_length, redirect_url);

    const auto error_code = response->GetError();
    if (error_code != ERR_NONE) {
      // Early exit if the handler reported an error.
      *status_code = error_code;
      return;
    }

    if (!redirect_url.empty()) {
      // Perform a redirect.
      *status_code = net::HTTP_TEMPORARY_REDIRECT;
      *reason_phrase = std::string();
      extra_headers->insert(
          std::make_pair(kHTTPLocationHeaderName, redirect_url));
    } else {
      *status_code = response->GetStatus();
      *reason_phrase = response->GetStatusText();
    }

    if (reason_phrase->empty() && *status_code > 0) {
      *reason_phrase = net::GetHttpReasonPhrase(
          static_cast<net::HttpStatusCode>(*status_code));
    }

    *mime_type = response->GetMimeType();
    *charset = response->GetCharset();

    // A |content_length| value may already be specified if the request included
    // a Range header.
    if (response_length >= 0 && *content_length == -1)
      *content_length = response_length;

    CefResponse::HeaderMap headerMap;
    response->GetHeaderMap(headerMap);
    for (const auto& value : headerMap) {
      extra_headers->insert(std::make_pair(value.first, value.second));
    }
  }

 private:
  const RequestId request_id_;

  CefRefPtr<CefRequestImpl> request_;
  scoped_refptr<HandlerProvider> handler_provider_;

  DISALLOW_COPY_AND_ASSIGN(ResourceResponseWrapper);
};

}  // namespace

std::unique_ptr<ResourceResponse> CreateResourceResponse(
    const RequestId& request_id,
    CefRefPtr<CefResourceHandler> handler) {
  return std::make_unique<ResourceResponseWrapper>(request_id, handler);
}

}  // namespace net_service
