// Copyright (c) 2012 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_request_job.h"

#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/appcache/appcache.h"
#include "content/browser/appcache/appcache_group.h"
#include "content/browser/appcache/appcache_histograms.h"
#include "content/browser/appcache/appcache_host.h"
#include "content/browser/appcache/appcache_service_impl.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_with_source.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_status.h"

namespace content {

AppCacheURLRequestJob::AppCacheURLRequestJob(
    net::URLRequest* request,
    net::NetworkDelegate* network_delegate,
    AppCacheStorage* storage,
    AppCacheHost* host,
    bool is_main_resource,
    const OnPrepareToRestartCallback& restart_callback)
    : net::URLRequestJob(request, network_delegate),
      host_(host),
      storage_(storage),
      has_been_started_(false),
      has_been_killed_(false),
      delivery_type_(AWAITING_DELIVERY_ORDERS),
      cache_id_(kAppCacheNoCacheId),
      is_fallback_(false),
      is_main_resource_(is_main_resource),
      cache_entry_not_found_(false),
      on_prepare_to_restart_callback_(restart_callback),
      weak_factory_(this) {
  DCHECK(storage_);
}

AppCacheURLRequestJob::~AppCacheURLRequestJob() {
  if (storage_)
    storage_->CancelDelegateCallbacks(this);
}

void AppCacheURLRequestJob::DeliverAppCachedResponse(const GURL& manifest_url,
                                                     int64_t cache_id,
                                                     const AppCacheEntry& entry,
                                                     bool is_fallback) {
  DCHECK(!has_delivery_orders());
  DCHECK(entry.has_response_id());
  delivery_type_ = APPCACHED_DELIVERY;
  manifest_url_ = manifest_url;
  cache_id_ = cache_id;
  entry_ = entry;
  is_fallback_ = is_fallback;
  MaybeBeginDelivery();
}

void AppCacheURLRequestJob::DeliverNetworkResponse() {
  DCHECK(!has_delivery_orders());
  delivery_type_ = NETWORK_DELIVERY;
  storage_ = NULL;  // not needed
  MaybeBeginDelivery();
}

void AppCacheURLRequestJob::DeliverErrorResponse() {
  DCHECK(!has_delivery_orders());
  delivery_type_ = ERROR_DELIVERY;
  storage_ = NULL;  // not needed
  MaybeBeginDelivery();
}

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

void AppCacheURLRequestJob::MaybeBeginDelivery() {
  if (has_been_started() && has_delivery_orders()) {
    // Start asynchronously so that all error reporting and data
    // callbacks happen as they would for network requests.
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::Bind(&AppCacheURLRequestJob::BeginDelivery,
                              weak_factory_.GetWeakPtr()));
  }
}

void AppCacheURLRequestJob::BeginDelivery() {
  DCHECK(has_delivery_orders() && has_been_started());

  if (has_been_killed())
    return;

  switch (delivery_type_) {
    case NETWORK_DELIVERY:
      AppCacheHistograms::AddNetworkJobStartDelaySample(
          base::TimeTicks::Now() - start_time_tick_);
      // To fallthru to the network, we restart the request which will
      // cause a new job to be created to retrieve the resource from the
      // network. Our caller is responsible for arranging to not re-intercept
      // the same request.
      NotifyRestartRequired();
      break;

    case ERROR_DELIVERY:
      AppCacheHistograms::AddErrorJobStartDelaySample(
          base::TimeTicks::Now() - start_time_tick_);
      request()->net_log().AddEvent(
          net::NetLogEventType::APPCACHE_DELIVERING_ERROR_RESPONSE);
      NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
                                             net::ERR_FAILED));
      break;

    case APPCACHED_DELIVERY:
      if (entry_.IsExecutable()) {
        BeginExecutableHandlerDelivery();
        return;
      }
      AppCacheHistograms::AddAppCacheJobStartDelaySample(
          base::TimeTicks::Now() - start_time_tick_);
      request()->net_log().AddEvent(
          is_fallback_
              ? net::NetLogEventType::APPCACHE_DELIVERING_FALLBACK_RESPONSE
              : net::NetLogEventType::APPCACHE_DELIVERING_CACHED_RESPONSE);
      storage_->LoadResponseInfo(manifest_url_, entry_.response_id(), this);
      break;

    default:
      NOTREACHED();
      break;
  }
}

void AppCacheURLRequestJob::BeginExecutableHandlerDelivery() {
  DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
      kEnableExecutableHandlers));
  if (!storage_->service()->handler_factory()) {
    BeginErrorDelivery("missing handler factory");
    return;
  }

  request()->net_log().AddEvent(
      net::NetLogEventType::APPCACHE_DELIVERING_EXECUTABLE_RESPONSE);

  // We defer job delivery until the executable handler is spun up and
  // provides a response. The sequence goes like this...
  //
  // 1. First we load the cache.
  // 2. Then if the handler is not spun up, we load the script resource which
  //    is needed to spin it up.
  // 3. Then we ask then we ask the handler to compute a response.
  // 4. Finally we deilver that response to the caller.
  storage_->LoadCache(cache_id_, this);
}

void AppCacheURLRequestJob::OnCacheLoaded(AppCache* cache, int64_t cache_id) {
  DCHECK_EQ(cache_id_, cache_id);
  DCHECK(!has_been_killed());

  if (!cache) {
    BeginErrorDelivery("cache load failed");
    return;
  }

  // Keep references to ensure they don't go out of scope until job completion.
  cache_ = cache;
  group_ = cache->owning_group();

  // If the handler is spun up, ask it to compute a response.
  AppCacheExecutableHandler* handler =
      cache->GetExecutableHandler(entry_.response_id());
  if (handler) {
    InvokeExecutableHandler(handler);
    return;
  }

  // Handler is not spun up yet, load the script resource to do that.
  // NOTE: This is not ideal since multiple jobs may be doing this,
  // concurrently but close enough for now, the first to load the script
  // will win.

  // Read the script data, truncating if its too large.
  // NOTE: we just issue one read and don't bother chaining if the resource
  // is very (very) large, close enough for now.
  const int64_t kLimit = 500 * 1000;
  handler_source_buffer_ = new net::GrowableIOBuffer();
  handler_source_buffer_->SetCapacity(kLimit);
  handler_source_reader_.reset(
      storage_->CreateResponseReader(manifest_url_, entry_.response_id()));
  handler_source_reader_->ReadData(
      handler_source_buffer_.get(),
      kLimit,
      base::Bind(&AppCacheURLRequestJob::OnExecutableSourceLoaded,
                 base::Unretained(this)));
}

void AppCacheURLRequestJob::OnExecutableSourceLoaded(int result) {
  DCHECK(!has_been_killed());
  handler_source_reader_.reset();
  if (result < 0) {
    BeginErrorDelivery("script source load failed");
    return;
  }

  handler_source_buffer_->SetCapacity(result);  // Free up some memory.

  AppCacheExecutableHandler* handler = cache_->GetOrCreateExecutableHandler(
      entry_.response_id(), handler_source_buffer_.get());
  handler_source_buffer_ = NULL;  // not needed anymore
  if (handler) {
    InvokeExecutableHandler(handler);
    return;
  }

  BeginErrorDelivery("factory failed to produce a handler");
}

void AppCacheURLRequestJob::InvokeExecutableHandler(
    AppCacheExecutableHandler* handler) {
  handler->HandleRequest(
      request(),
      base::Bind(&AppCacheURLRequestJob::OnExecutableResponseCallback,
                 weak_factory_.GetWeakPtr()));
}

void AppCacheURLRequestJob::OnExecutableResponseCallback(
    const AppCacheExecutableHandler::Response& response) {
  DCHECK(!has_been_killed());
  if (response.use_network) {
    delivery_type_ = NETWORK_DELIVERY;
    storage_ = NULL;
    BeginDelivery();
    return;
  }

  if (!response.cached_resource_url.is_empty()) {
    AppCacheEntry* entry_ptr = cache_->GetEntry(response.cached_resource_url);
    if (entry_ptr && !entry_ptr->IsExecutable()) {
      entry_ = *entry_ptr;
      BeginDelivery();
      return;
    }
  }

  if (!response.redirect_url.is_empty()) {
    // TODO(michaeln): playback a redirect
    // response_headers_(new HttpResponseHeaders(response_headers)),
    // fallthru for now to deliver an error
  }

  // Otherwise, return an error.
  BeginErrorDelivery("handler returned an invalid response");
}

void AppCacheURLRequestJob::BeginErrorDelivery(const char* message) {
  if (host_)
    host_->frontend()->OnLogMessage(host_->host_id(), APPCACHE_LOG_ERROR,
                                    message);
  delivery_type_ = ERROR_DELIVERY;
  storage_ = NULL;
  BeginDelivery();
}

void AppCacheURLRequestJob::OnResponseInfoLoaded(
    AppCacheResponseInfo* response_info,
    int64_t response_id) {
  DCHECK(is_delivering_appcache_response());
  if (response_info) {
    info_ = response_info;
    reader_.reset(
        storage_->CreateResponseReader(manifest_url_, entry_.response_id()));

    if (is_range_request())
      SetupRangeResponse();

    NotifyHeadersComplete();
  } else {
    if (storage_->service()->storage() == storage_) {
      // A resource that is expected to be in the appcache is missing.
      // See http://code.google.com/p/chromium/issues/detail?id=50657
      // Instead of failing the request, we restart the request. The retry
      // attempt will fallthru to the network instead of trying to load
      // from the appcache.
      storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_,
                                                 entry_.response_id());
      AppCacheHistograms::CountResponseRetrieval(
          false, is_main_resource_, manifest_url_.GetOrigin());
    }
    cache_entry_not_found_ = true;
    NotifyRestartRequired();
  }
}

const net::HttpResponseInfo* AppCacheURLRequestJob::http_info() const {
  if (!info_.get())
    return NULL;
  if (range_response_info_)
    return range_response_info_.get();
  return info_->http_response_info();
}

void AppCacheURLRequestJob::SetupRangeResponse() {
  DCHECK(is_range_request() && info_.get() && reader_.get() &&
         is_delivering_appcache_response());
  int resource_size = static_cast<int>(info_->response_data_size());
  if (resource_size < 0 || !range_requested_.ComputeBounds(resource_size)) {
    range_requested_ = net::HttpByteRange();
    return;
  }

  DCHECK(range_requested_.IsValid());
  int offset = static_cast<int>(range_requested_.first_byte_position());
  int length = static_cast<int>(range_requested_.last_byte_position() -
                                range_requested_.first_byte_position() + 1);

  // Tell the reader about the range to read.
  reader_->SetReadRange(offset, length);

  // Make a copy of the full response headers and fix them up
  // for the range we'll be returning.
  range_response_info_.reset(
      new net::HttpResponseInfo(*info_->http_response_info()));
  net::HttpResponseHeaders* headers = range_response_info_->headers.get();
  headers->UpdateWithNewRange(
      range_requested_, resource_size, true /* replace status line */);
}

void AppCacheURLRequestJob::OnReadComplete(int result) {
  DCHECK(is_delivering_appcache_response());
  if (result == 0) {
    AppCacheHistograms::CountResponseRetrieval(
        true, is_main_resource_, manifest_url_.GetOrigin());
  } else if (result < 0) {
    if (storage_->service()->storage() == storage_) {
      storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_,
                                                 entry_.response_id());
    }
    AppCacheHistograms::CountResponseRetrieval(
        false, is_main_resource_, manifest_url_.GetOrigin());
  }
  ReadRawDataComplete(result);
}

// net::URLRequestJob overrides ------------------------------------------------

void AppCacheURLRequestJob::Start() {
  DCHECK(!has_been_started());
  has_been_started_ = true;
  start_time_tick_ = base::TimeTicks::Now();
  MaybeBeginDelivery();
}

void AppCacheURLRequestJob::Kill() {
  if (!has_been_killed_) {
    has_been_killed_ = true;
    reader_.reset();
    handler_source_reader_.reset();
    if (storage_) {
      storage_->CancelDelegateCallbacks(this);
      storage_ = NULL;
    }
    host_ = NULL;
    info_ = NULL;
    cache_ = NULL;
    group_ = NULL;
    range_response_info_.reset();
    net::URLRequestJob::Kill();
    weak_factory_.InvalidateWeakPtrs();
  }
}

net::LoadState AppCacheURLRequestJob::GetLoadState() const {
  if (!has_been_started())
    return net::LOAD_STATE_IDLE;
  if (!has_delivery_orders())
    return net::LOAD_STATE_WAITING_FOR_APPCACHE;
  if (delivery_type_ != APPCACHED_DELIVERY)
    return net::LOAD_STATE_IDLE;
  if (!info_.get())
    return net::LOAD_STATE_WAITING_FOR_APPCACHE;
  if (reader_.get() && reader_->IsReadPending())
    return net::LOAD_STATE_READING_RESPONSE;
  return net::LOAD_STATE_IDLE;
}

bool AppCacheURLRequestJob::GetMimeType(std::string* mime_type) const {
  if (!http_info())
    return false;
  return http_info()->headers->GetMimeType(mime_type);
}

bool AppCacheURLRequestJob::GetCharset(std::string* charset) {
  if (!http_info())
    return false;
  return http_info()->headers->GetCharset(charset);
}

void AppCacheURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
  if (!http_info())
    return;
  *info = *http_info();
}

int AppCacheURLRequestJob::GetResponseCode() const {
  if (!http_info())
    return -1;
  return http_info()->headers->response_code();
}

int AppCacheURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) {
  DCHECK(is_delivering_appcache_response());
  DCHECK_NE(buf_size, 0);
  DCHECK(!reader_->IsReadPending());
  reader_->ReadData(buf, buf_size,
                    base::Bind(&AppCacheURLRequestJob::OnReadComplete,
                               base::Unretained(this)));
  return net::ERR_IO_PENDING;
}

net::HostPortPair AppCacheURLRequestJob::GetSocketAddress() const {
  if (!http_info())
    return net::HostPortPair();
  return http_info()->socket_address;
}

void AppCacheURLRequestJob::SetExtraRequestHeaders(
    const net::HttpRequestHeaders& headers) {
  std::string value;
  std::vector<net::HttpByteRange> ranges;
  if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &value) ||
      !net::HttpUtil::ParseRangeHeader(value, &ranges)) {
    return;
  }

  // If multiple ranges are requested, we play dumb and
  // return the entire response with 200 OK.
  if (ranges.size() == 1U)
    range_requested_ = ranges[0];
}

void AppCacheURLRequestJob::NotifyRestartRequired() {
  on_prepare_to_restart_callback_.Run();
  URLRequestJob::NotifyRestartRequired();
}

}  // namespace content
