// Copyright 2013 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_register_job.h"

#include <stdint.h>

#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_job_coordinator.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/service_worker/service_worker_write_to_cache_job.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/net_errors.h"

namespace content {

namespace {

void RunSoon(const base::Closure& closure) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure);
}

}  // namespace

typedef ServiceWorkerRegisterJobBase::RegistrationJobType RegistrationJobType;

ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
    base::WeakPtr<ServiceWorkerContextCore> context,
    const GURL& pattern,
    const GURL& script_url)
    : context_(context),
      job_type_(REGISTRATION_JOB),
      pattern_(pattern),
      script_url_(script_url),
      phase_(INITIAL),
      doom_installing_worker_(false),
      is_promise_resolved_(false),
      should_uninstall_on_failure_(false),
      force_bypass_cache_(false),
      skip_script_comparison_(false),
      promise_resolved_status_(SERVICE_WORKER_OK),
      weak_factory_(this) {}

ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
    base::WeakPtr<ServiceWorkerContextCore> context,
    ServiceWorkerRegistration* registration,
    bool force_bypass_cache,
    bool skip_script_comparison)
    : context_(context),
      job_type_(UPDATE_JOB),
      pattern_(registration->pattern()),
      phase_(INITIAL),
      doom_installing_worker_(false),
      is_promise_resolved_(false),
      should_uninstall_on_failure_(false),
      force_bypass_cache_(force_bypass_cache),
      skip_script_comparison_(skip_script_comparison),
      promise_resolved_status_(SERVICE_WORKER_OK),
      weak_factory_(this) {
  internal_.registration = registration;
}

ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() {
  DCHECK(!context_ ||
         phase_ == INITIAL || phase_ == COMPLETE || phase_ == ABORT)
      << "Jobs should only be interrupted during shutdown.";
}

void ServiceWorkerRegisterJob::AddCallback(
    const RegistrationCallback& callback,
    ServiceWorkerProviderHost* provider_host) {
  if (!is_promise_resolved_) {
    callbacks_.push_back(callback);
    if (provider_host)
      provider_host->AddScopedProcessReferenceToPattern(pattern_);
    return;
  }
  RunSoon(base::Bind(callback, promise_resolved_status_,
                     promise_resolved_status_message_,
                     base::RetainedRef(promise_resolved_registration_)));
}

void ServiceWorkerRegisterJob::Start() {
  BrowserThread::PostAfterStartupTask(
      FROM_HERE, base::ThreadTaskRunnerHandle::Get(),
      base::Bind(&ServiceWorkerRegisterJob::StartImpl,
                 weak_factory_.GetWeakPtr()));
}

void ServiceWorkerRegisterJob::StartImpl() {
  SetPhase(START);
  ServiceWorkerStorage::FindRegistrationCallback next_step;
  if (job_type_ == REGISTRATION_JOB) {
    next_step = base::Bind(
        &ServiceWorkerRegisterJob::ContinueWithRegistration,
        weak_factory_.GetWeakPtr());
  } else {
    next_step = base::Bind(
        &ServiceWorkerRegisterJob::ContinueWithUpdate,
        weak_factory_.GetWeakPtr());
  }

  scoped_refptr<ServiceWorkerRegistration> registration =
      context_->storage()->GetUninstallingRegistration(pattern_);
  if (registration.get())
    RunSoon(base::Bind(next_step, SERVICE_WORKER_OK, registration));
  else
    context_->storage()->FindRegistrationForPattern(pattern_, next_step);
}

void ServiceWorkerRegisterJob::Abort() {
  SetPhase(ABORT);
  CompleteInternal(SERVICE_WORKER_ERROR_ABORT, std::string());
  // Don't have to call FinishJob() because the caller takes care of removing
  // the jobs from the queue.
}

bool ServiceWorkerRegisterJob::Equals(ServiceWorkerRegisterJobBase* job) const {
  if (job->GetType() != job_type_)
    return false;
  ServiceWorkerRegisterJob* register_job =
      static_cast<ServiceWorkerRegisterJob*>(job);
  if (job_type_ == UPDATE_JOB)
    return register_job->pattern_ == pattern_;
  DCHECK_EQ(REGISTRATION_JOB, job_type_);
  return register_job->pattern_ == pattern_ &&
         register_job->script_url_ == script_url_;
}

RegistrationJobType ServiceWorkerRegisterJob::GetType() const {
  return job_type_;
}

void ServiceWorkerRegisterJob::DoomInstallingWorker() {
  doom_installing_worker_ = true;
  if (phase_ == INSTALL)
    Complete(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED, std::string());
}

ServiceWorkerRegisterJob::Internal::Internal() {}

ServiceWorkerRegisterJob::Internal::~Internal() {}

void ServiceWorkerRegisterJob::set_registration(
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK(phase_ == START || phase_ == REGISTER) << phase_;
  DCHECK(!internal_.registration.get());
  internal_.registration = std::move(registration);
}

ServiceWorkerRegistration* ServiceWorkerRegisterJob::registration() {
  DCHECK(phase_ >= REGISTER || job_type_ == UPDATE_JOB) << phase_;
  return internal_.registration.get();
}

void ServiceWorkerRegisterJob::set_new_version(
    ServiceWorkerVersion* version) {
  DCHECK(phase_ == UPDATE) << phase_;
  DCHECK(!internal_.new_version.get());
  internal_.new_version = version;
}

ServiceWorkerVersion* ServiceWorkerRegisterJob::new_version() {
  DCHECK(phase_ >= UPDATE) << phase_;
  return internal_.new_version.get();
}

void ServiceWorkerRegisterJob::SetPhase(Phase phase) {
  switch (phase) {
    case INITIAL:
      NOTREACHED();
      break;
    case START:
      DCHECK(phase_ == INITIAL) << phase_;
      break;
    case REGISTER:
      DCHECK(phase_ == START) << phase_;
      break;
    case UPDATE:
      DCHECK(phase_ == START || phase_ == REGISTER) << phase_;
      break;
    case INSTALL:
      DCHECK(phase_ == UPDATE) << phase_;
      break;
    case STORE:
      DCHECK(phase_ == INSTALL) << phase_;
      break;
    case COMPLETE:
      DCHECK(phase_ != INITIAL && phase_ != COMPLETE) << phase_;
      break;
    case ABORT:
      break;
  }
  phase_ = phase;
}

// This function corresponds to the steps in [[Register]] following
// "Let registration be the result of running the [[GetRegistration]] algorithm.
// Throughout this file, comments in quotes are excerpts from the spec.
void ServiceWorkerRegisterJob::ContinueWithRegistration(
    ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> existing_registration) {
  DCHECK_EQ(REGISTRATION_JOB, job_type_);
  if (status != SERVICE_WORKER_ERROR_NOT_FOUND && status != SERVICE_WORKER_OK) {
    Complete(status);
    return;
  }

  if (!existing_registration.get() || existing_registration->is_uninstalled()) {
    RegisterAndContinue();
    return;
  }

  DCHECK(existing_registration->GetNewestVersion());
  // "If scriptURL is equal to registration.[[ScriptURL]], then:"
  if (existing_registration->GetNewestVersion()->script_url() == script_url_) {
    // "Set registration.[[Uninstalling]] to false."
    existing_registration->AbortPendingClear(base::Bind(
        &ServiceWorkerRegisterJob::ContinueWithRegistrationForSameScriptUrl,
        weak_factory_.GetWeakPtr(),
        existing_registration));
    return;
  }

  if (existing_registration->is_uninstalling()) {
    existing_registration->AbortPendingClear(base::Bind(
        &ServiceWorkerRegisterJob::ContinueWithUninstallingRegistration,
        weak_factory_.GetWeakPtr(),
        existing_registration));
    return;
  }

  // "Return the result of running the [[Update]] algorithm, or its equivalent,
  // passing registration as the argument."
  set_registration(existing_registration);
  UpdateAndContinue();
}

void ServiceWorkerRegisterJob::ContinueWithUpdate(
    ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> existing_registration) {
  DCHECK_EQ(UPDATE_JOB, job_type_);
  if (status != SERVICE_WORKER_OK) {
    Complete(status);
    return;
  }

  if (existing_registration.get() != registration()) {
    Complete(SERVICE_WORKER_ERROR_NOT_FOUND);
    return;
  }

  // A previous job may have unregistered this registration.
  if (registration()->is_uninstalling() ||
      !registration()->GetNewestVersion()) {
    Complete(SERVICE_WORKER_ERROR_NOT_FOUND);
    return;
  }

  DCHECK(script_url_.is_empty());
  script_url_ = registration()->GetNewestVersion()->script_url();

  // TODO(michaeln): If the last update check was less than 24 hours
  // ago, depending on the freshness of the cached worker script we
  // may be able to complete the update job right here.

  UpdateAndContinue();
}

// Creates a new ServiceWorkerRegistration.
void ServiceWorkerRegisterJob::RegisterAndContinue() {
  SetPhase(REGISTER);

  int64_t registration_id = context_->storage()->NewRegistrationId();
  if (registration_id == kInvalidServiceWorkerRegistrationId) {
    Complete(SERVICE_WORKER_ERROR_ABORT);
    return;
  }

  set_registration(
      new ServiceWorkerRegistration(pattern_, registration_id, context_));
  AddRegistrationToMatchingProviderHosts(registration());
  UpdateAndContinue();
}

void ServiceWorkerRegisterJob::ContinueWithUninstallingRegistration(
    scoped_refptr<ServiceWorkerRegistration> existing_registration,
    ServiceWorkerStatusCode status) {
  if (status != SERVICE_WORKER_OK) {
    Complete(status);
    return;
  }
  should_uninstall_on_failure_ = true;
  set_registration(existing_registration);
  UpdateAndContinue();
}

void ServiceWorkerRegisterJob::ContinueWithRegistrationForSameScriptUrl(
    scoped_refptr<ServiceWorkerRegistration> existing_registration,
    ServiceWorkerStatusCode status) {
  if (status != SERVICE_WORKER_OK) {
    Complete(status);
    return;
  }
  set_registration(existing_registration);

  // "If newestWorker is not null, and scriptURL is equal to
  // newestWorker.scriptURL, then:
  // Return a promise resolved with registration."
  // We resolve only if there's an active version. If there's not,
  // then there is either no version or only a waiting version from
  // the last browser session; it makes sense to proceed with registration in
  // either case.
  DCHECK(!existing_registration->installing_version());
  if (existing_registration->active_version()) {
    ResolvePromise(status, std::string(), existing_registration.get());
    Complete(SERVICE_WORKER_OK);
    return;
  }

  // "Return the result of running the [[Update]] algorithm, or its equivalent,
  // passing registration as the argument."
  UpdateAndContinue();
}

// This function corresponds to the spec's [[Update]] algorithm.
void ServiceWorkerRegisterJob::UpdateAndContinue() {
  SetPhase(UPDATE);
  context_->storage()->NotifyInstallingRegistration(registration());

  int64_t version_id = context_->storage()->NewVersionId();
  if (version_id == kInvalidServiceWorkerVersionId) {
    Complete(SERVICE_WORKER_ERROR_ABORT);
    return;
  }

  // "Let worker be a new ServiceWorker object..." and start
  // the worker.
  set_new_version(new ServiceWorkerVersion(registration(), script_url_,
                                           version_id, context_));
  new_version()->set_force_bypass_cache_for_scripts(force_bypass_cache_);
  if (registration()->has_installed_version() && !skip_script_comparison_) {
    new_version()->set_pause_after_download(true);
    new_version()->embedded_worker()->AddListener(this);
  } else {
    new_version()->set_pause_after_download(false);
  }
  new_version()->StartWorker(
      ServiceWorkerMetrics::EventType::INSTALL,
      base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished,
                 weak_factory_.GetWeakPtr()));
}

void ServiceWorkerRegisterJob::OnStartWorkerFinished(
    ServiceWorkerStatusCode status) {
  BumpLastUpdateCheckTimeIfNeeded();

  if (status == SERVICE_WORKER_OK) {
    InstallAndContinue();
    return;
  }

  // "If serviceWorker fails to start up..." then reject the promise with an
  // error and abort.
  if (status == SERVICE_WORKER_ERROR_TIMEOUT) {
    Complete(status, "Timed out while trying to start the Service Worker.");
    return;
  }

  const net::URLRequestStatus& main_script_status =
      new_version()->script_cache_map()->main_script_status();
  std::string message;
  if (main_script_status.status() != net::URLRequestStatus::SUCCESS) {
    message = new_version()->script_cache_map()->main_script_status_message();
    if (message.empty())
      message = kFetchScriptError;
  }
  Complete(status, message);
}

// This function corresponds to the spec's [[Install]] algorithm.
void ServiceWorkerRegisterJob::InstallAndContinue() {
  SetPhase(INSTALL);

  // "Set registration.installingWorker to worker."
  DCHECK(!registration()->installing_version());
  registration()->SetInstallingVersion(new_version());

  // "Run the Update State algorithm passing registration's installing worker
  // and installing as the arguments."
  new_version()->SetStatus(ServiceWorkerVersion::INSTALLING);

  // "Resolve registrationPromise with registration."
  ResolvePromise(SERVICE_WORKER_OK, std::string(), registration());

  // "Fire a simple event named updatefound..."
  registration()->NotifyUpdateFound();

  // "Fire an event named install..."
  new_version()->RunAfterStartWorker(
      ServiceWorkerMetrics::EventType::INSTALL,
      base::Bind(&ServiceWorkerRegisterJob::DispatchInstallEvent,
                 weak_factory_.GetWeakPtr()),
      base::Bind(&ServiceWorkerRegisterJob::OnInstallFailed,
                 weak_factory_.GetWeakPtr()));

  // A subsequent registration job may terminate our installing worker. It can
  // only do so after we've started the worker and dispatched the install
  // event, as those are atomic substeps in the [[Install]] algorithm.
  if (doom_installing_worker_)
    Complete(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED);
}

void ServiceWorkerRegisterJob::DispatchInstallEvent() {
  DCHECK_EQ(ServiceWorkerVersion::INSTALLING, new_version()->status())
      << new_version()->status();
  DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, new_version()->running_status())
      << "Worker stopped too soon after it was started.";
  int request_id = new_version()->StartRequest(
      ServiceWorkerMetrics::EventType::INSTALL,
      base::Bind(&ServiceWorkerRegisterJob::OnInstallFailed,
                 weak_factory_.GetWeakPtr()));
  new_version()
      ->RegisterRequestCallback<ServiceWorkerHostMsg_InstallEventFinished>(
          request_id, base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished,
                                 weak_factory_.GetWeakPtr()));
  new_version()->DispatchEvent({request_id},
                               ServiceWorkerMsg_InstallEvent(request_id));
}

void ServiceWorkerRegisterJob::OnInstallFinished(
    int request_id,
    blink::WebServiceWorkerEventResult result,
    bool has_fetch_handler) {
  new_version()->FinishRequest(
      request_id, result == blink::WebServiceWorkerEventResultCompleted);

  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
  switch (result) {
    case blink::WebServiceWorkerEventResultCompleted:
      status = SERVICE_WORKER_OK;
      break;
    case blink::WebServiceWorkerEventResultRejected:
      status = SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED;
      break;
    default:
      NOTREACHED();
  }

  if (status != SERVICE_WORKER_OK) {
    OnInstallFailed(status);
    return;
  }

  ServiceWorkerMetrics::RecordInstallEventStatus(status);

  SetPhase(STORE);
  DCHECK(!registration()->last_update_check().is_null());
  new_version()->set_has_fetch_handler(has_fetch_handler);
  context_->storage()->StoreRegistration(
      registration(),
      new_version(),
      base::Bind(&ServiceWorkerRegisterJob::OnStoreRegistrationComplete,
                 weak_factory_.GetWeakPtr()));
}

void ServiceWorkerRegisterJob::OnInstallFailed(ServiceWorkerStatusCode status) {
  ServiceWorkerMetrics::RecordInstallEventStatus(status);

  if (status != SERVICE_WORKER_OK) {
    Complete(status, std::string("ServiceWorker failed to install: ") +
                         ServiceWorkerStatusToString(status));
  } else {
    NOTREACHED() << "OnInstallFailed should not handle SERVICE_WORKER_OK";
  }
}

void ServiceWorkerRegisterJob::OnStoreRegistrationComplete(
    ServiceWorkerStatusCode status) {
  if (status != SERVICE_WORKER_OK) {
    Complete(status);
    return;
  }

  // "9. If registration.waitingWorker is not null, then:..."
  if (registration()->waiting_version()) {
    // 1. Set redundantWorker to registration’s waiting worker.
    // 2. Terminate redundantWorker.
    registration()->waiting_version()->StopWorker(
        base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
    // TODO(falken): Move this further down. The spec says to set status to
    // 'redundant' after promoting the new version to .waiting attribute and
    // 'installed' status.
    registration()->waiting_version()->SetStatus(
        ServiceWorkerVersion::REDUNDANT);
  }

  // "10. Set registration.waitingWorker to registration.installingWorker."
  // "11. Set registration.installingWorker to null."
  registration()->SetWaitingVersion(new_version());

  // "12. Run the [[UpdateState]] algorithm passing registration.waitingWorker
  // and "installed" as the arguments."
  new_version()->SetStatus(ServiceWorkerVersion::INSTALLED);

  // "If registration's waiting worker's skip waiting flag is set:" then
  // activate the worker immediately otherwise "wait until no service worker
  // client is using registration as their service worker registration."
  registration()->ActivateWaitingVersionWhenReady();

  Complete(SERVICE_WORKER_OK);
}

void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status) {
  Complete(status, std::string());
}

void ServiceWorkerRegisterJob::Complete(ServiceWorkerStatusCode status,
                                        const std::string& status_message) {
  CompleteInternal(status, status_message);
  context_->job_coordinator()->FinishJob(pattern_, this);
}

void ServiceWorkerRegisterJob::CompleteInternal(
    ServiceWorkerStatusCode status,
    const std::string& status_message) {
  SetPhase(COMPLETE);

  if (new_version()) {
    new_version()->set_pause_after_download(false);
    new_version()->embedded_worker()->RemoveListener(this);
  }

  if (status != SERVICE_WORKER_OK) {
    if (registration()) {
      if (should_uninstall_on_failure_)
        registration()->ClearWhenReady();
      if (new_version()) {
        if (status == SERVICE_WORKER_ERROR_EXISTS)
          new_version()->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS);
        else
          new_version()->ReportError(status, status_message);
        registration()->UnsetVersion(new_version());
        new_version()->Doom();
      }
      if (!registration()->waiting_version() &&
          !registration()->active_version()) {
        registration()->NotifyRegistrationFailed();
        context_->storage()->DeleteRegistration(
            registration()->id(),
            registration()->pattern().GetOrigin(),
            base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
      }
    }
    if (!is_promise_resolved_)
      ResolvePromise(status, status_message, NULL);
  }
  DCHECK(callbacks_.empty());
  if (registration()) {
    context_->storage()->NotifyDoneInstallingRegistration(
        registration(), new_version(), status);
    if (registration()->has_installed_version())
      registration()->set_is_uninstalled(false);
  }
}

void ServiceWorkerRegisterJob::ResolvePromise(
    ServiceWorkerStatusCode status,
    const std::string& status_message,
    ServiceWorkerRegistration* registration) {
  DCHECK(!is_promise_resolved_);

  is_promise_resolved_ = true;
  promise_resolved_status_ = status;
  promise_resolved_status_message_ = status_message,
  promise_resolved_registration_ = registration;
  for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin();
       it != callbacks_.end();
       ++it) {
    it->Run(status, status_message, registration);
  }
  callbacks_.clear();
}

void ServiceWorkerRegisterJob::AddRegistrationToMatchingProviderHosts(
    ServiceWorkerRegistration* registration) {
  DCHECK(registration);
  for (std::unique_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
           context_->GetProviderHostIterator();
       !it->IsAtEnd(); it->Advance()) {
    ServiceWorkerProviderHost* host = it->GetProviderHost();
    if (host->IsHostToRunningServiceWorker())
      continue;
    if (!ServiceWorkerUtils::ScopeMatches(registration->pattern(),
                                          host->document_url()))
      continue;
    host->AddMatchingRegistration(registration);
  }
}

void ServiceWorkerRegisterJob::OnScriptLoaded() {
  DCHECK(new_version()->pause_after_download());
  new_version()->set_pause_after_download(false);
  net::URLRequestStatus status =
      new_version()->script_cache_map()->main_script_status();
  if (!status.is_success()) {
    // OnScriptLoaded signifies a successful network load, which translates into
    // a script cache error only in the byte-for-byte identical case.
    DCHECK_EQ(status.error(),
              ServiceWorkerWriteToCacheJob::kIdenticalScriptError);

    BumpLastUpdateCheckTimeIfNeeded();
    ResolvePromise(SERVICE_WORKER_OK, std::string(), registration());
    Complete(SERVICE_WORKER_ERROR_EXISTS,
             "The updated worker is identical to the incumbent.");
    return;
  }

  new_version()->embedded_worker()->ResumeAfterDownload();
}

void ServiceWorkerRegisterJob::BumpLastUpdateCheckTimeIfNeeded() {
  // Bump the last update check time only when the register/update job fetched
  // the version having bypassed the network cache. We assume that the
  // BYPASS_CACHE flag evicts an existing cache entry, so even if the install
  // ultimately failed for whatever reason, we know the version in the HTTP
  // cache is not stale, so it's OK to bump the update check time.
  if (new_version()->embedded_worker()->network_accessed_for_script() ||
      new_version()->force_bypass_cache_for_scripts() ||
      registration()->last_update_check().is_null()) {
    registration()->set_last_update_check(base::Time::Now());

    if (registration()->has_installed_version())
      context_->storage()->UpdateLastUpdateCheckTime(registration());
  }
}

}  // namespace content
