// Copyright (c) 2017 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 "content/browser/appcache/appcache_url_loader_job.h"

#include "base/strings/string_number_conversions.h"
#include "content/browser/appcache/appcache_histograms.h"
#include "content/browser/appcache/appcache_request_handler.h"
#include "content/browser/appcache/appcache_subresource_url_factory.h"
#include "content/browser/appcache/appcache_url_loader_request.h"
#include "content/browser/url_loader_factory_getter.h"
#include "content/public/common/resource_type.h"
#include "net/http/http_status_code.h"
#include "services/network/public/cpp/net_adapters.h"

namespace content {

AppCacheURLLoaderJob::~AppCacheURLLoaderJob() {
  if (storage_.get())
    storage_->CancelDelegateCallbacks(this);
}

bool AppCacheURLLoaderJob::IsStarted() const {
  return delivery_type_ != AWAITING_DELIVERY_ORDERS &&
         delivery_type_ != NETWORK_DELIVERY;
}

void AppCacheURLLoaderJob::DeliverAppCachedResponse(const GURL& manifest_url,
                                                    int64_t cache_id,
                                                    const AppCacheEntry& entry,
                                                    bool is_fallback) {
  if (!storage_.get() || !appcache_request_) {
    DeliverErrorResponse();
    return;
  }

  delivery_type_ = APPCACHED_DELIVERY;

  // In tests we only care about the delivery_type_ state.
  if (AppCacheRequestHandler::IsRunningInTests())
    return;

  load_timing_info_.request_start_time = base::Time::Now();
  load_timing_info_.request_start = base::TimeTicks::Now();

  AppCacheHistograms::AddAppCacheJobStartDelaySample(base::TimeTicks::Now() -
                                                     start_time_tick_);

  manifest_url_ = manifest_url;
  cache_id_ = cache_id;
  entry_ = entry;
  is_fallback_ = is_fallback;

  if (is_fallback_ && loader_callback_)
    CallLoaderCallback();

  InitializeRangeRequestInfo(appcache_request_->GetResourceRequest()->headers);
  storage_->LoadResponseInfo(manifest_url_, entry_.response_id(), this);
}

void AppCacheURLLoaderJob::DeliverNetworkResponse() {
  delivery_type_ = NETWORK_DELIVERY;

  // In tests we only care about the delivery_type_ state.
  if (AppCacheRequestHandler::IsRunningInTests())
    return;

  AppCacheHistograms::AddNetworkJobStartDelaySample(base::TimeTicks::Now() -
                                                    start_time_tick_);

  // We signal our caller with an empy callback that it needs to perform
  // the network load.
  DCHECK(loader_callback_ && !binding_.is_bound());
  std::move(loader_callback_).Run({});
  weak_factory_.InvalidateWeakPtrs();
  is_deleting_soon_ = true;
  base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}

void AppCacheURLLoaderJob::DeliverErrorResponse() {
  delivery_type_ = ERROR_DELIVERY;

  // In tests we only care about the delivery_type_ state.
  if (AppCacheRequestHandler::IsRunningInTests())
    return;

  if (loader_callback_)
    CallLoaderCallback();
  NotifyCompleted(net::ERR_FAILED);

  AppCacheHistograms::AddErrorJobStartDelaySample(base::TimeTicks::Now() -
                                                  start_time_tick_);
}

AppCacheURLLoaderJob* AppCacheURLLoaderJob::AsURLLoaderJob() {
  return this;
}

base::WeakPtr<AppCacheJob> AppCacheURLLoaderJob::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

base::WeakPtr<AppCacheURLLoaderJob> AppCacheURLLoaderJob::GetDerivedWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

void AppCacheURLLoaderJob::FollowRedirect(
    const base::Optional<std::vector<std::string>>&
        to_be_removed_request_headers,
    const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
  NOTREACHED() << "appcache never produces redirects";
}

void AppCacheURLLoaderJob::ProceedWithResponse() {
  // TODO(arthursonzogni):  Implement this if AppCache starts using the
  // AppCacheURLLoader before the Network Service has shipped.
  NOTREACHED();
}

void AppCacheURLLoaderJob::SetPriority(net::RequestPriority priority,
                                       int32_t intra_priority_value) {}
void AppCacheURLLoaderJob::PauseReadingBodyFromNet() {}
void AppCacheURLLoaderJob::ResumeReadingBodyFromNet() {}

void AppCacheURLLoaderJob::DeleteIfNeeded() {
  if (binding_.is_bound() || is_deleting_soon_)
    return;
  delete this;
}

void AppCacheURLLoaderJob::Start(network::mojom::URLLoaderRequest request,
                                 network::mojom::URLLoaderClientPtr client) {
  DCHECK(!binding_.is_bound());
  binding_.Bind(std::move(request));
  client_ = std::move(client);
  binding_.set_connection_error_handler(base::BindOnce(
      &AppCacheURLLoaderJob::OnConnectionError, GetDerivedWeakPtr()));
}

AppCacheURLLoaderJob::AppCacheURLLoaderJob(
    AppCacheURLLoaderRequest* appcache_request,
    AppCacheStorage* storage,
    NavigationLoaderInterceptor::LoaderCallback loader_callback)
    : storage_(storage->GetWeakPtr()),
      start_time_tick_(base::TimeTicks::Now()),
      cache_id_(kAppCacheNoCacheId),
      is_fallback_(false),
      binding_(this),
      writable_handle_watcher_(FROM_HERE,
                               mojo::SimpleWatcher::ArmingPolicy::MANUAL,
                               base::SequencedTaskRunnerHandle::Get()),
      loader_callback_(std::move(loader_callback)),
      appcache_request_(appcache_request->GetWeakPtr()),
      is_main_resource_load_(IsResourceTypeFrame(static_cast<ResourceType>(
          appcache_request->GetResourceRequest()->resource_type))),
      weak_factory_(this) {}

void AppCacheURLLoaderJob::CallLoaderCallback() {
  DCHECK(loader_callback_);
  DCHECK(!binding_.is_bound());
  std::move(loader_callback_)
      .Run(base::BindOnce(&AppCacheURLLoaderJob::Start, GetDerivedWeakPtr()));
  DCHECK(binding_.is_bound());
}

void AppCacheURLLoaderJob::OnResponseInfoLoaded(
    AppCacheResponseInfo* response_info,
    int64_t response_id) {
  DCHECK(IsDeliveringAppCacheResponse());

  if (!storage_.get()) {
    DeliverErrorResponse();
    return;
  }

  if (response_info) {
    if (loader_callback_)
      CallLoaderCallback();

    info_ = response_info;
    reader_.reset(
        storage_->CreateResponseReader(manifest_url_, entry_.response_id()));

    if (is_range_request())
      SetupRangeResponse();

    response_body_stream_ = std::move(data_pipe_.producer_handle);

    // TODO(ananta)
    // Move the asynchronous reading and mojo pipe handling code to a helper
    // class. That would also need a change to BlobURLLoader.

    // Wait for the data pipe to be ready to accept data.
    writable_handle_watcher_.Watch(
        response_body_stream_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
        base::Bind(&AppCacheURLLoaderJob::OnResponseBodyStreamReady,
                   GetDerivedWeakPtr()));

    SendResponseInfo();
    ReadMore();
    return;
  }

  // We failed to load the response headers from the disk cache.
  if (storage_->service()->storage() == storage_.get()) {
    // A resource that is expected to be in the appcache is missing.
    // If the 'check' fails, the corrupt appcache will be deleted.
    // See http://code.google.com/p/chromium/issues/detail?id=50657
    storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_,
                                               entry_.response_id());
    AppCacheHistograms::CountResponseRetrieval(
        false, is_main_resource_load_, url::Origin::Create(manifest_url_));
  }
  cache_entry_not_found_ = true;

  // We fallback to the network unless this job was falling back to the
  // appcache from the network which had already failed in some way.
  if (!is_fallback_)
    DeliverNetworkResponse();
  else
    DeliverErrorResponse();
}

void AppCacheURLLoaderJob::OnReadComplete(int result) {
  if (result > 0) {
    uint32_t bytes_written = static_cast<uint32_t>(result);
    response_body_stream_ = pending_write_->Complete(bytes_written);
    pending_write_ = nullptr;
    ReadMore();
    return;
  }

  writable_handle_watcher_.Cancel();
  pending_write_->Complete(0);
  pending_write_ = nullptr;
  NotifyCompleted(result);
}

void AppCacheURLLoaderJob::OnResponseBodyStreamReady(MojoResult result) {
  // TODO(ananta)
  // Add proper error handling here.
  if (result != MOJO_RESULT_OK) {
    DCHECK(false);
    NotifyCompleted(net::ERR_FAILED);
    return;
  }
  ReadMore();
}

void AppCacheURLLoaderJob::OnConnectionError() {
  if (storage_.get())
    storage_->CancelDelegateCallbacks(this);
  weak_factory_.InvalidateWeakPtrs();
  is_deleting_soon_ = true;
  base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}

void AppCacheURLLoaderJob::SendResponseInfo() {
  DCHECK(client_);
  // If this is null it means the response information was sent to the client.
  if (!data_pipe_.consumer_handle.is_valid())
    return;

  const net::HttpResponseInfo* http_info = is_range_request()
                                               ? range_response_info_.get()
                                               : info_->http_response_info();
  network::ResourceResponseHead response_head;
  response_head.headers = http_info->headers;
  response_head.appcache_id = cache_id_;
  response_head.appcache_manifest_url = manifest_url_;

  http_info->headers->GetMimeType(&response_head.mime_type);
  http_info->headers->GetCharset(&response_head.charset);

  // TODO(ananta)
  // Verify if the times sent here are correct.
  response_head.request_time = http_info->request_time;
  response_head.response_time = http_info->response_time;
  response_head.content_length =
      is_range_request() ? range_response_info_->headers->GetContentLength()
                         : info_->response_data_size();
  response_head.connection_info = http_info->connection_info;
  response_head.socket_address = http_info->socket_address;
  response_head.was_fetched_via_spdy = http_info->was_fetched_via_spdy;
  response_head.was_alpn_negotiated = http_info->was_alpn_negotiated;
  response_head.alpn_negotiated_protocol = http_info->alpn_negotiated_protocol;
  if (http_info->ssl_info.cert)
    response_head.ssl_info = http_info->ssl_info;
  response_head.load_timing = load_timing_info_;

  client_->OnReceiveResponse(response_head);
  client_->OnStartLoadingResponseBody(std::move(data_pipe_.consumer_handle));
}

void AppCacheURLLoaderJob::ReadMore() {
  DCHECK(!pending_write_.get());

  uint32_t num_bytes;
  // TODO: we should use the abstractions in MojoAsyncResourceHandler.
  MojoResult result = network::NetToMojoPendingBuffer::BeginWrite(
      &response_body_stream_, &pending_write_, &num_bytes);
  if (result == MOJO_RESULT_SHOULD_WAIT) {
    // The pipe is full. We need to wait for it to have more space.
    writable_handle_watcher_.ArmOrNotify();
    return;
  } else if (result != MOJO_RESULT_OK) {
    NotifyCompleted(net::ERR_FAILED);
    writable_handle_watcher_.Cancel();
    response_body_stream_.reset();
    return;
  }

  CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes);
  auto buffer =
      base::MakeRefCounted<network::NetToMojoIOBuffer>(pending_write_.get());

  uint32_t bytes_to_read =
      std::min<uint32_t>(num_bytes, info_->response_data_size());

  reader_->ReadData(buffer.get(), bytes_to_read,
                    base::BindOnce(&AppCacheURLLoaderJob::OnReadComplete,
                                   GetDerivedWeakPtr()));
}

void AppCacheURLLoaderJob::NotifyCompleted(int error_code) {
  if (storage_.get())
    storage_->CancelDelegateCallbacks(this);

  if (AppCacheRequestHandler::IsRunningInTests())
    return;

  network::URLLoaderCompletionStatus status(error_code);
  if (!error_code) {
    const net::HttpResponseInfo* http_info =
        is_range_request() ? range_response_info_.get()
                           : (info_ ? info_->http_response_info() : nullptr);
    status.exists_in_cache = http_info->was_cached;
    status.completion_time = base::TimeTicks::Now();
    status.encoded_body_length =
        is_range_request() ? range_response_info_->headers->GetContentLength()
                           : (info_ ? info_->response_data_size() : 0);
    status.decoded_body_length = status.encoded_body_length;
  }
  client_->OnComplete(status);

  if (delivery_type_ == APPCACHED_DELIVERY) {
    AppCacheHistograms::CountResponseRetrieval(
        error_code == 0, is_main_resource_load_,
        url::Origin::Create(manifest_url_));
  }
}

}  // namespace content
