// Copyright 2018 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 "fuchsia/http/url_loader_impl.h"

#include "base/fuchsia/fuchsia_logging.h"
#include "base/task/current_thread.h"
#include "base/task/post_task.h"
#include "fuchsia/base/mem_buffer_util.h"
#include "net/base/chunked_upload_data_stream.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/redirect_info.h"

namespace oldhttp = ::fuchsia::net::oldhttp;

namespace {
// Capacity, in bytes, for buffers used to move data from client requests or
// server responses.
const size_t kReadCapacity = 1024;

// The number of active requests. Used for testing.
int g_active_requests = 0;

// Converts |buffer| into a URLBody with the body set to a buffer. Returns
// nullptr when an error occurs.
oldhttp::URLBodyPtr CreateURLBodyFromBuffer(net::GrowableIOBuffer* buffer) {
  oldhttp::URLBodyPtr body = oldhttp::URLBody::New();

  // The response buffer size is exactly the offset.
  size_t total_size = buffer->offset();

  body->set_buffer(cr_fuchsia::MemBufferFromString(
      base::StringPiece(buffer->StartOfBuffer(), total_size),
      "cr-http-url-body"));

  return body;
}

int NetErrorToHttpError(int net_error) {
  // TODO(https://crbug.com/875533): Convert the Chromium //net error to their
  // Fuchsia counterpart.
  return net_error;
}

oldhttp::HttpErrorPtr BuildError(int net_error) {
  if (net_error == net::OK) {
    return nullptr;
  }

  oldhttp::HttpErrorPtr error = oldhttp::HttpError::New();
  error->code = NetErrorToHttpError(net_error);
  error->description = net::ErrorToString(net_error);
  return error;
}

std::unique_ptr<net::UploadDataStream> UploadDataStreamFromZxSocket(
    zx::socket stream) {
  // TODO(http://crbug.com/875534): Write a ZxStreamUploadStream class.
  std::unique_ptr<net::ChunkedUploadDataStream> upload_stream =
      std::make_unique<net::ChunkedUploadDataStream>(0);
  char buffer[kReadCapacity];
  size_t size = 0;
  zx_status_t result = ZX_OK;
  while (true) {
    result = stream.read(0, buffer, kReadCapacity, &size);
    if (result != ZX_OK) {
      ZX_DLOG(WARNING, result) << "zx_socket_read";
      return nullptr;
    }
    if (size < kReadCapacity) {
      upload_stream->AppendData(buffer, size, false);
      break;
    }
    upload_stream->AppendData(buffer, size, true);
  }

  return upload_stream;
}

std::unique_ptr<net::UploadDataStream> UploadDataStreamFromMemBuffer(
    fuchsia::mem::Buffer mem_buffer) {
  // TODO(http://crbug.com/875534): Write a ZxMemBufferUploadStream class.
  std::unique_ptr<net::ChunkedUploadDataStream> upload_stream =
      std::make_unique<net::ChunkedUploadDataStream>(0);

  char buffer[kReadCapacity];
  size_t size = mem_buffer.size;
  size_t offset = 0;
  zx_status_t result = ZX_OK;
  while (offset != size) {
    size_t length = std::min(size - offset, kReadCapacity);
    result = mem_buffer.vmo.read(buffer, offset, length);
    if (result != ZX_OK) {
      ZX_DLOG(WARNING, result) << "zx_vmo_read";
      return nullptr;
    }
    upload_stream->AppendData(buffer, length, false);
    offset += length;
  }

  return upload_stream;
}

}  // namespace

URLLoaderImpl::URLLoaderImpl(std::unique_ptr<net::URLRequestContext> context,
                             fidl::InterfaceRequest<oldhttp::URLLoader> request)
    : binding_(this, std::move(request)),
      context_(std::move(context)),
      buffer_(new net::GrowableIOBuffer()),
      write_watch_(FROM_HERE) {
  binding_.set_error_handler([this](zx_status_t status) {
    ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status)
        << " URLLoader disconnected.";
    delete this;
  });
  g_active_requests++;
}

URLLoaderImpl::~URLLoaderImpl() {
  g_active_requests--;
}

int URLLoaderImpl::GetNumActiveRequestsForTests() {
  return g_active_requests;
}

void URLLoaderImpl::Start(oldhttp::URLRequest request, Callback callback) {
  if (net_request_) {
    callback(BuildResponse(net::ERR_IO_PENDING));
    return;
  }

  done_callback_ = std::move(callback);
  net_error_ = net::OK;

  // Create the URLRequest and set this object as the delegate.
  net_request_ = context_->CreateRequest(GURL(request.url),
                                         net::RequestPriority::MEDIUM, this);
  net_request_->set_method(request.method);

  // Set extra headers.
  if (request.headers) {
    for (oldhttp::HttpHeader header : *(request.headers)) {
      net_request_->SetExtraRequestHeaderByName(header.name, header.value,
                                                false);
    }
  }
  if (request.cache_mode == oldhttp::CacheMode::BYPASS_CACHE) {
    net_request_->SetExtraRequestHeaderByName("Cache-Control", "nocache",
                                              false);
  }

  std::unique_ptr<net::UploadDataStream> upload_stream;
  // Set body.
  if (request.body) {
    if (request.body->is_stream()) {
      upload_stream =
          UploadDataStreamFromZxSocket(std::move(request.body->stream()));
    } else {
      upload_stream =
          UploadDataStreamFromMemBuffer(std::move(request.body->buffer()));
    }

    if (!upload_stream) {
      std::move(done_callback_)(BuildResponse(net::ERR_ACCESS_DENIED));
      return;
    }
    net_request_->set_upload(std::move(upload_stream));
  }

  auto_follow_redirects_ = request.auto_follow_redirects;
  response_body_mode_ = request.response_body_mode;

  // Start the request.
  net_request_->Start();
  is_loading_ = true;
}

void URLLoaderImpl::FollowRedirect(Callback callback) {
  if (!net_request_ || auto_follow_redirects_ ||
      !net_request_->is_redirecting()) {
    callback(BuildResponse(net::ERR_INVALID_HANDLE));
    return;
  }

  done_callback_ = std::move(callback);
  net_request_->FollowDeferredRedirect(base::nullopt /* removed_headers */,
                                       base::nullopt /* modified_headers */);
}

void URLLoaderImpl::QueryStatus(QueryStatusCallback callback) {
  oldhttp::URLLoaderStatus status;

  status.is_loading = is_loading_;
  if (net_request_ && !is_loading_) {
    status.error = BuildError(net_error_);
  }
  callback(std::move(status));
}

void URLLoaderImpl::OnReceivedRedirect(net::URLRequest* request,
                                       const net::RedirectInfo& redirect_info,
                                       bool* defer_redirect) {
  DCHECK_EQ(net_request_.get(), request);
  // Follow redirect depending on policy.
  *defer_redirect = !auto_follow_redirects_;

  if (!auto_follow_redirects_) {
    oldhttp::URLResponse response = BuildResponse(net::OK);
    response.redirect_method = redirect_info.new_method;
    response.redirect_url = redirect_info.new_url.spec();
    response.redirect_referrer = redirect_info.new_referrer;
    std::move(done_callback_)(std::move(response));
  }
}

void URLLoaderImpl::OnAuthRequired(net::URLRequest* request,
                                   const net::AuthChallengeInfo& auth_info) {
  NOTIMPLEMENTED();
  DCHECK_EQ(net_request_.get(), request);
  request->CancelAuth();
}

void URLLoaderImpl::OnCertificateRequested(
    net::URLRequest* request,
    net::SSLCertRequestInfo* cert_request_info) {
  NOTIMPLEMENTED();
  DCHECK_EQ(net_request_.get(), request);
  request->ContinueWithCertificate(nullptr, nullptr);
}

void URLLoaderImpl::OnSSLCertificateError(net::URLRequest* request,
                                          int net_error,
                                          const net::SSLInfo& ssl_info,
                                          bool fatal) {
  NOTIMPLEMENTED();
  DCHECK_EQ(net_request_.get(), request);
  request->Cancel();
}

void URLLoaderImpl::OnResponseStarted(net::URLRequest* request, int net_error) {
  DCHECK_EQ(net_request_.get(), request);
  net_error_ = net_error;

  // Return early if the request failed.
  if (net_error_ != net::OK) {
    is_loading_ = false;
    std::move(done_callback_)(BuildResponse(net_error_));
    return;
  }

  // In stream mode, call the callback now and write to the socket.
  if (response_body_mode_ == oldhttp::ResponseBodyMode::STREAM ||
      response_body_mode_ == oldhttp::ResponseBodyMode::BUFFER_OR_STREAM) {
    zx::socket read_socket;
    zx_status_t result = zx::socket::create(0, &read_socket, &write_socket_);
    if (result != ZX_OK) {
      is_loading_ = false;
      net_error_ = net::ERR_INSUFFICIENT_RESOURCES;
      ZX_DLOG(WARNING, result) << "zx_socket_create";
      std::move(done_callback_)(BuildResponse(net_error_));
      return;
    }
    oldhttp::URLResponse response = BuildResponse(net_error_);
    response.body = oldhttp::URLBody::New();
    response.body->set_stream(std::move(read_socket));
    std::move(done_callback_)(std::move(response));
  }

  // In stream mode, the buffer is used as a temporary buffer to write to the
  // socket. In buffer mode, it is expanded as more of the response is read.
  buffer_->SetCapacity(kReadCapacity);

  ReadNextBuffer();
}

void URLLoaderImpl::OnReadCompleted(net::URLRequest* request, int bytes_read) {
  DCHECK_EQ(net_request_.get(), request);
  if (WriteResponseBytes(bytes_read)) {
    ReadNextBuffer();
  }
}

void URLLoaderImpl::OnZxHandleSignalled(zx_handle_t handle,
                                        zx_signals_t signals) {
  // We should never have to process signals we didn't ask for.
  DCHECK((ZX_CHANNEL_WRITABLE | ZX_CHANNEL_PEER_CLOSED) & signals);
  DCHECK_GT(buffered_bytes_, 0);

  if (signals & ZX_CHANNEL_PEER_CLOSED) {
    return;
  }

  if (WriteResponseBytes(buffered_bytes_))
    ReadNextBuffer();
  buffered_bytes_ = 0;
}

void URLLoaderImpl::ReadNextBuffer() {
  int net_result;
  do {
    net_result = net_request_->Read(buffer_.get(), kReadCapacity);
    if (net_result == net::ERR_IO_PENDING) {
      return;
    }
  } while (WriteResponseBytes(net_result));
}

bool URLLoaderImpl::WriteResponseBytes(int result) {
  if (result < 0) {
    is_loading_ = false;
    net_error_ = result;

    // Signal read error back to the client.
    if (write_socket_) {
      DCHECK(response_body_mode_ == oldhttp::ResponseBodyMode::STREAM ||
             response_body_mode_ ==
                 oldhttp::ResponseBodyMode::BUFFER_OR_STREAM);
      // There is no need to check the return value of this call as there is no
      // way to recover from a failed socket close.
      write_socket_ = zx::socket();
    } else {
      DCHECK_EQ(response_body_mode_, oldhttp::ResponseBodyMode::BUFFER);
      std::move(done_callback_)(BuildResponse(result));
    }
    return false;
  }

  if (result == 0) {
    // Read complete.
    is_loading_ = false;

    if (write_socket_) {
      DCHECK(response_body_mode_ == oldhttp::ResponseBodyMode::STREAM ||
             response_body_mode_ ==
                 oldhttp::ResponseBodyMode::BUFFER_OR_STREAM);
      // In socket mode, attempt to shut down the socket and close it.
      write_socket_.shutdown(ZX_SOCKET_SHUTDOWN_WRITE);
      write_socket_ = zx::socket();
    } else {
      DCHECK_EQ(response_body_mode_, oldhttp::ResponseBodyMode::BUFFER);
      // In buffer mode, build the response and call the callback.
      oldhttp::URLBodyPtr body = CreateURLBodyFromBuffer(buffer_.get());
      if (body) {
        oldhttp::URLResponse response = BuildResponse(net::OK);
        response.body = std::move(body);
        std::move(done_callback_)(std::move(response));
      } else {
        net_error_ = net::ERR_INSUFFICIENT_RESOURCES;
        std::move(done_callback_)(BuildResponse(net_error_));
      }
    }
    return false;
  }

  // Write data to the response buffer or socket.
  if (write_socket_) {
    DCHECK(response_body_mode_ == oldhttp::ResponseBodyMode::STREAM ||
           response_body_mode_ == oldhttp::ResponseBodyMode::BUFFER_OR_STREAM);
    // In socket mode, attempt to write to the socket.
    zx_status_t status =
        write_socket_.write(0, buffer_->data(), result, nullptr);
    if (status == ZX_ERR_SHOULD_WAIT) {
      // Wait until the socket is writable again.
      buffered_bytes_ = result;
      base::CurrentIOThread::Get()->WatchZxHandle(
          write_socket_.get(), false /* persistent */,
          ZX_SOCKET_WRITABLE | ZX_SOCKET_PEER_CLOSED, &write_watch_, this);
      return false;
    }
    if (status != ZX_OK) {
      // Something went wrong, attempt to shut down the socket and close it.
      ZX_DLOG(WARNING, status) << "zx_socket_write";
      write_socket_ = zx::socket();
      is_loading_ = false;
      net_error_ = net::ERR_FAILED;
      return false;
    }
  } else {
    DCHECK_EQ(response_body_mode_, oldhttp::ResponseBodyMode::BUFFER);
    // In buffer mode, expand the buffer.
    buffer_->SetCapacity(buffer_->capacity() + result);
    buffer_->set_offset(buffer_->offset() + result);
  }

  return true;
}

oldhttp::URLResponse URLLoaderImpl::BuildResponse(int net_error) {
  oldhttp::URLResponse response;

  response.error = BuildError(net_error);
  if (response.error) {
    return response;
  }

  if (net_request_->url().is_valid()) {
    response.url = net_request_->url().spec();
  }
  response.status_code = net_request_->GetResponseCode();

  net::HttpResponseHeaders* response_headers = net_request_->response_headers();
  if (response_headers) {
    response.status_line = response_headers->GetStatusLine();
    std::string mime_type;
    if (response_headers->GetMimeType(&mime_type)) {
      response.mime_type = mime_type;
    }
    std::string charset;
    if (response_headers->GetCharset(&charset)) {
      response.charset = charset;
    }

    size_t iter = 0;
    std::string header_name;
    std::string header_value;
    response.headers.emplace();
    while (response_headers->EnumerateHeaderLines(&iter, &header_name,
                                                  &header_value)) {
      oldhttp::HttpHeader header;
      header.name = header_name;
      header.value = header_value;
      response.headers->push_back(header);
    }
  }

  return response;
}
