// Copyright 2014 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/service_worker/service_worker_write_to_cache_job.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/service_worker/service_worker_cache_writer.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/net/url_request_service_worker_data.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/url_util.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_status.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "third_party/blink/public/web/web_console_message.h"

namespace content {

namespace {

const char kKilledError[] = "The request to fetch the script was interrupted.";
const char kClientAuthenticationError[] =
    "Client authentication was required to fetch the script.";

bool ShouldIgnoreSSLError(net::URLRequest* request) {
  const net::HttpNetworkSession::Params* session_params =
      request->context()->GetNetworkSessionParams();
  if (session_params && session_params->ignore_certificate_errors)
    return true;
  bool allow_localhost = base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kAllowInsecureLocalhost);
  if (allow_localhost && net::IsLocalhost(request->url()))
    return true;
  return false;
}

}  // namespace

const net::Error ServiceWorkerWriteToCacheJob::kIdenticalScriptError =
    net::ERR_FILE_EXISTS;

ServiceWorkerWriteToCacheJob::ServiceWorkerWriteToCacheJob(
    net::URLRequest* request,
    net::NetworkDelegate* network_delegate,
    ResourceType resource_type,
    base::WeakPtr<ServiceWorkerContextCore> context,
    ServiceWorkerVersion* version,
    int extra_load_flags,
    int64_t resource_id,
    int64_t incumbent_resource_id)
    : net::URLRequestJob(request, network_delegate),
      resource_type_(resource_type),
      context_(context),
      url_(request->url()),
      resource_id_(resource_id),
      incumbent_resource_id_(incumbent_resource_id),
      version_(version),
      weak_factory_(this) {
  DCHECK(version_);
  DCHECK(resource_type_ == RESOURCE_TYPE_SCRIPT ||
         (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER &&
          version_->script_url() == url_));
  InitNetRequest(extra_load_flags);
}

ServiceWorkerWriteToCacheJob::~ServiceWorkerWriteToCacheJob() {
  Kill();
  DCHECK_EQ(did_notify_started_, did_notify_finished_);
}

void ServiceWorkerWriteToCacheJob::Start() {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(&ServiceWorkerWriteToCacheJob::StartAsync,
                                weak_factory_.GetWeakPtr()));
}

void ServiceWorkerWriteToCacheJob::StartAsync() {
  TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
                           "ServiceWorkerWriteToCacheJob::ExecutingJob",
                           this,
                           "URL", request_->url().spec());
  if (!context_) {
    // NotifyStartError is not safe to call synchronously in Start().
    NotifyStartError(
        net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED));
    return;
  }

  // Create response readers only when we have to do the byte-for-byte check.
  std::unique_ptr<ServiceWorkerResponseReader> compare_reader;
  std::unique_ptr<ServiceWorkerResponseReader> copy_reader;
  if (ShouldByteForByteCheck()) {
    compare_reader =
        context_->storage()->CreateResponseReader(incumbent_resource_id_);
    copy_reader =
        context_->storage()->CreateResponseReader(incumbent_resource_id_);
  }
  cache_writer_ = std::make_unique<ServiceWorkerCacheWriter>(
      std::move(compare_reader), std::move(copy_reader),
      context_->storage()->CreateResponseWriter(resource_id_),
      false /* pause_when_not_identical */);

  version_->script_cache_map()->NotifyStartedCaching(url_, resource_id_);
  did_notify_started_ = true;
  StartNetRequest();
}

void ServiceWorkerWriteToCacheJob::Kill() {
  if (has_been_killed_)
    return;
  weak_factory_.InvalidateWeakPtrs();
  has_been_killed_ = true;
  net_request_.reset();
  if (did_notify_started_) {
    net::Error error = NotifyFinishedCaching(net::ERR_ABORTED, kKilledError);
    DCHECK_EQ(net::ERR_ABORTED, error);
  }
  writer_.reset();
  context_.reset();
  net::URLRequestJob::Kill();
}

net::LoadState ServiceWorkerWriteToCacheJob::GetLoadState() const {
  if (writer_ && writer_->IsWritePending())
    return net::LOAD_STATE_WAITING_FOR_APPCACHE;
  if (net_request_)
    return net_request_->GetLoadState().state;
  return net::LOAD_STATE_IDLE;
}

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

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

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

void ServiceWorkerWriteToCacheJob::SetExtraRequestHeaders(
      const net::HttpRequestHeaders& headers) {
  std::string value;
  DCHECK(!headers.GetHeader(net::HttpRequestHeaders::kRange, &value));
  net_request_->SetExtraRequestHeaders(headers);
}

int ServiceWorkerWriteToCacheJob::ReadRawData(net::IOBuffer* buf,
                                              int buf_size) {
  int rv = ReadNetData(buf, buf_size);
  if (rv == net::ERR_IO_PENDING)
    return net::ERR_IO_PENDING;

  if (rv < 0) {
    net::Error error = static_cast<net::Error>(rv);
    error = NotifyFinishedCaching(error, kServiceWorkerFetchScriptError);
    DCHECK_EQ(rv, error);
    return error;
  }

  return HandleNetData(rv);
}

const net::HttpResponseInfo* ServiceWorkerWriteToCacheJob::http_info() const {
  return http_info_.get();
}

void ServiceWorkerWriteToCacheJob::InitNetRequest(
    int extra_load_flags) {
  DCHECK(request());
  net::NetworkTrafficAnnotationTag traffic_annotation =
      net::DefineNetworkTrafficAnnotation("service_worker_write_to_cache_job",
                                          R"(
          semantics {
            sender: "ServiceWorker System"
            description:
              "When a ServiceWorker is registered, its script and immediate "
              "imports are cached for performance and offline access. The "
              "resources are periodically updated."
            trigger:
              "User visits a site which registers a ServiceWorker."
            data: "None"
            destination: WEBSITE
          }
          policy {
            cookies_allowed: YES
            cookies_store: "user"
            setting:
              "Users can control this feature via the 'Cookies' setting under "
              "'Privacy, Content settings'. If cookies are disabled for a "
              "single site, serviceworkers are disabled for the site only. If "
              "they are totally disabled, all serviceworker requests will be "
              "stopped."
            chrome_policy {
              DefaultCookiesSetting {
                policy_options {mode: MANDATORY}
                DefaultCookiesSetting: 2
              }
            }
          })");
  net_request_ = request()->context()->CreateRequest(
      request()->url(), request()->priority(), this, traffic_annotation);
  net_request_->set_site_for_cookies(request()->site_for_cookies());
  net_request_->set_initiator(request()->initiator());
  net_request_->SetReferrer(request()->referrer());
  net_request_->SetUserData(URLRequestServiceWorkerData::kUserDataKey,
                            std::make_unique<URLRequestServiceWorkerData>());
  if (extra_load_flags)
    net_request_->SetLoadFlags(net_request_->load_flags() | extra_load_flags);

  if (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER) {
    // This will get copied into net_request_ when URLRequest::StartJob calls
    // ServiceWorkerWriteToCacheJob::SetExtraRequestHeaders.
    request()->SetExtraRequestHeaderByName("Service-Worker", "script", true);
  }
}

void ServiceWorkerWriteToCacheJob::StartNetRequest() {
  TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
                               "ServiceWorkerWriteToCacheJob::ExecutingJob",
                               this,
                               "NetRequest");
  net_request_->Start();  // We'll continue in OnResponseStarted.
}

int ServiceWorkerWriteToCacheJob::ReadNetData(net::IOBuffer* buf,
                                              int buf_size) {
  DCHECK_GT(buf_size, 0);
  io_buffer_ = buf;
  io_buffer_bytes_ = 0;
  return net_request_->Read(buf, buf_size);
}

void ServiceWorkerWriteToCacheJob::OnReceivedRedirect(
    net::URLRequest* request,
    const net::RedirectInfo& redirect_info,
    bool* defer_redirect) {
  DCHECK_EQ(net_request_.get(), request);
  TRACE_EVENT0("ServiceWorker",
               "ServiceWorkerWriteToCacheJob::OnReceivedRedirect");
  // Script resources can't redirect.
  NotifyStartErrorHelper(net::ERR_UNSAFE_REDIRECT, kServiceWorkerRedirectError);
}

void ServiceWorkerWriteToCacheJob::OnAuthRequired(
    net::URLRequest* request,
    net::AuthChallengeInfo* auth_info) {
  DCHECK_EQ(net_request_.get(), request);
  TRACE_EVENT0("ServiceWorker",
               "ServiceWorkerWriteToCacheJob::OnAuthRequired");
  // TODO(michaeln): Pass this thru to our jobs client.
  NotifyStartErrorHelper(net::ERR_FAILED, kClientAuthenticationError);
}

void ServiceWorkerWriteToCacheJob::OnCertificateRequested(
    net::URLRequest* request,
    net::SSLCertRequestInfo* cert_request_info) {
  DCHECK_EQ(net_request_.get(), request);
  TRACE_EVENT0("ServiceWorker",
               "ServiceWorkerWriteToCacheJob::OnCertificateRequested");
  // TODO(michaeln): Pass this thru to our jobs client.
  // see NotifyCertificateRequested.
  NotifyStartErrorHelper(net::ERR_FAILED, kClientAuthenticationError);
}

void ServiceWorkerWriteToCacheJob::OnSSLCertificateError(
    net::URLRequest* request,
    const net::SSLInfo& ssl_info,
    bool fatal) {
  DCHECK_EQ(net_request_.get(), request);
  TRACE_EVENT0("ServiceWorker",
               "ServiceWorkerWriteToCacheJob::OnSSLCertificateError");
  if (ShouldIgnoreSSLError(request)) {
    request->ContinueDespiteLastError();
  } else {
    NotifyStartErrorHelper(
        net::Error(net::MapCertStatusToNetError(ssl_info.cert_status)),
        kServiceWorkerSSLError);
  }
}

void ServiceWorkerWriteToCacheJob::OnResponseStarted(net::URLRequest* request,
                                                     int net_error) {
  DCHECK_NE(net::ERR_IO_PENDING, net_error);
  DCHECK_EQ(net_request_.get(), request);

  if (net_error != net::OK) {
    net::Error error = static_cast<net::Error>(net_error);
    NotifyStartErrorHelper(error, kServiceWorkerFetchScriptError);
    return;
  }
  if (request->GetResponseCode() / 100 != 2) {
    std::string error_message = base::StringPrintf(
        kServiceWorkerBadHTTPResponseError, request->GetResponseCode());
    NotifyStartErrorHelper(net::ERR_INVALID_RESPONSE, error_message);
    // TODO(michaeln): Instead of error'ing immediately, send the net
    // response to our consumer, just don't cache it?
    return;
  }
  // OnSSLCertificateError is not called when the HTTPS connection is reused.
  // So we check cert_status here.
  if (net::IsCertStatusError(request->ssl_info().cert_status) &&
      !ShouldIgnoreSSLError(request)) {
    NotifyStartErrorHelper(net::Error(net::MapCertStatusToNetError(
                               request->ssl_info().cert_status)),
                           kServiceWorkerSSLError);
    return;
  }

  if (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER) {
    std::string mime_type;
    request->GetMimeType(&mime_type);
    if (!blink::IsSupportedJavascriptMimeType(mime_type)) {
      std::string error_message =
          mime_type.empty() ? kServiceWorkerNoMIMEError
                            : base::StringPrintf(kServiceWorkerBadMIMEError,
                                                 mime_type.c_str());
      NotifyStartErrorHelper(net::ERR_INSECURE_RESPONSE, error_message);
      return;
    }

    if (!CheckPathRestriction(request))
      return;

    version_->SetMainScriptHttpResponseInfo(net_request_->response_info());
  }

  if (net_request_->response_info().network_accessed &&
      !(net_request_->response_info().was_cached)) {
    version_->embedded_worker()->OnNetworkAccessedForScriptLoad();
  }

  http_info_ =
      std::make_unique<net::HttpResponseInfo>(net_request_->response_info());
  scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
      base::MakeRefCounted<HttpResponseInfoIOBuffer>(
          std::make_unique<net::HttpResponseInfo>(
              net_request_->response_info()));
  net::Error error = cache_writer_->MaybeWriteHeaders(
      info_buffer.get(),
      base::BindOnce(&ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete,
                     weak_factory_.GetWeakPtr()));
  if (error == net::ERR_IO_PENDING)
    return;
  OnWriteHeadersComplete(error);
}

void ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete(net::Error error) {
  DCHECK_NE(net::ERR_IO_PENDING, error);
  if (error != net::OK) {
    ServiceWorkerMetrics::CountWriteResponseResult(
        ServiceWorkerMetrics::WRITE_HEADERS_ERROR);
    NotifyStartError(net::URLRequestStatus::FromError(error));
    return;
  }
  NotifyHeadersComplete();
}

void ServiceWorkerWriteToCacheJob::OnWriteDataComplete(net::Error error) {
  DCHECK_NE(net::ERR_IO_PENDING, error);
  if (io_buffer_bytes_ == 0)
    error = NotifyFinishedCaching(error, "");
  if (error != net::OK) {
    ServiceWorkerMetrics::CountWriteResponseResult(
        ServiceWorkerMetrics::WRITE_DATA_ERROR);
    ReadRawDataComplete(error);
    return;
  }
  ServiceWorkerMetrics::CountWriteResponseResult(
      ServiceWorkerMetrics::WRITE_OK);
  ReadRawDataComplete(io_buffer_bytes_);
}

void ServiceWorkerWriteToCacheJob::OnReadCompleted(net::URLRequest* request,
                                                   int bytes_read) {
  DCHECK_NE(net::ERR_IO_PENDING, bytes_read);
  DCHECK_EQ(net_request_.get(), request);

  int result;
  if (bytes_read < 0) {
    net::Error error = static_cast<net::Error>(bytes_read);
    result = NotifyFinishedCaching(error, kServiceWorkerFetchScriptError);
  } else {
    result = HandleNetData(bytes_read);
  }

  // ReadRawDataComplete will be called in OnWriteDataComplete, so return early.
  if (result == net::ERR_IO_PENDING)
    return;

  ReadRawDataComplete(result);
}

bool ServiceWorkerWriteToCacheJob::CheckPathRestriction(
    net::URLRequest* request) {
  std::string service_worker_allowed;
  const net::HttpResponseHeaders* headers = request->response_headers();
  bool has_header = headers->EnumerateHeader(nullptr, kServiceWorkerAllowed,
                                             &service_worker_allowed);

  std::string error_message;
  if (!ServiceWorkerUtils::IsPathRestrictionSatisfied(
          version_->scope(), url_,
          has_header ? &service_worker_allowed : nullptr, &error_message)) {
    NotifyStartErrorHelper(net::ERR_INSECURE_RESPONSE, error_message);
    return false;
  }
  return true;
}

int ServiceWorkerWriteToCacheJob::HandleNetData(int bytes_read) {
  io_buffer_bytes_ = bytes_read;
  net::Error error = cache_writer_->MaybeWriteData(
      io_buffer_.get(), bytes_read,
      base::BindOnce(&ServiceWorkerWriteToCacheJob::OnWriteDataComplete,
                     weak_factory_.GetWeakPtr()));

  // In case of ERR_IO_PENDING, this logic is done in OnWriteDataComplete.
  if (error != net::ERR_IO_PENDING && bytes_read == 0) {
    error = NotifyFinishedCaching(error, std::string());
  }
  return error == net::OK ? bytes_read : error;
}

void ServiceWorkerWriteToCacheJob::NotifyStartErrorHelper(
    net::Error net_error,
    const std::string& status_message) {
  NotifyFinishedCaching(net_error, status_message);
  NotifyStartError(net::URLRequestStatus::FromError(net_error));
}

net::Error ServiceWorkerWriteToCacheJob::NotifyFinishedCaching(
    net::Error net_error,
    const std::string& status_message) {
  DCHECK_NE(net::ERR_IO_PENDING, net_error);

  if (did_notify_finished_)
    return net_error;

  int size = -1;
  if (net_error != net::OK) {
    // AddMessageToConsole must be called before this job notifies that an error
    // occurred because the worker stops soon after receiving the error
    // response.
    version_->embedded_worker()->AddMessageToConsole(
        blink::WebConsoleMessage::kLevelError,
        status_message.empty() ? kServiceWorkerFetchScriptError
                               : status_message);
  } else {
    size = cache_writer_->bytes_written();
  }

  // If all the calls to MaybeWriteHeaders/MaybeWriteData succeeded, but the
  // incumbent entry wasn't actually replaced because the new entry was
  // equivalent, the new version didn't actually install because it already
  // exists.
  if (net_error == net::OK && !cache_writer_->did_replace()) {
    version_->SetStartWorkerStatusCode(
        blink::ServiceWorkerStatusCode::kErrorExists);
    version_->script_cache_map()->NotifyFinishedCaching(
        url_, size, kIdenticalScriptError, std::string());
  } else {
    version_->script_cache_map()->NotifyFinishedCaching(url_, size, net_error,
                                                        status_message);
  }

  did_notify_finished_ = true;
  return net_error;
}

bool ServiceWorkerWriteToCacheJob::ShouldByteForByteCheck() const {
  return incumbent_resource_id_ != kInvalidServiceWorkerResourceId &&
         version_->pause_after_download();
}

}  // namespace content
