// Copyright (c) 2016 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/renderer/service_worker/embedded_worker_instance_client_impl.h"

#include <memory>

#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "content/child/scoped_child_process_reference.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_client.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/service_worker/service_worker_context_client.h"
#include "content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_installed_scripts_manager.h"
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/web/web_embedded_worker.h"
#include "third_party/blink/public/web/web_embedded_worker_start_data.h"

namespace content {

EmbeddedWorkerInstanceClientImpl::WorkerWrapper::WorkerWrapper(
    std::unique_ptr<blink::WebEmbeddedWorker> worker)
    : worker_(std::move(worker)) {}

EmbeddedWorkerInstanceClientImpl::WorkerWrapper::~WorkerWrapper() = default;

// static
void EmbeddedWorkerInstanceClientImpl::Create(
    scoped_refptr<base::SingleThreadTaskRunner> io_thread_runner,
    mojom::EmbeddedWorkerInstanceClientRequest request) {
  // This won't be leaked because the lifetime will be managed internally.
  // See the class documentation for detail.
  new EmbeddedWorkerInstanceClientImpl(std::move(io_thread_runner),
                                       std::move(request));
}

void EmbeddedWorkerInstanceClientImpl::WorkerContextDestroyed() {
  DCHECK(wrapper_);
  TRACE_EVENT0("ServiceWorker",
               "EmbeddedWorkerInstanceClientImpl::WorkerContextDestroyed");
  // Destroys |this|.
  wrapper_.reset();
}

void EmbeddedWorkerInstanceClientImpl::StartWorker(
    mojom::EmbeddedWorkerStartParamsPtr params) {
  DCHECK(ChildThreadImpl::current());
  DCHECK(!wrapper_);
  TRACE_EVENT0("ServiceWorker",
               "EmbeddedWorkerInstanceClientImpl::StartWorker");
  auto start_timing = mojom::EmbeddedWorkerStartTiming::New();
  start_timing->start_worker_received_time = base::TimeTicks::Now();
  DCHECK(!params->provider_info->cache_storage ||
         base::FeatureList::IsEnabled(
             blink::features::kEagerCacheStorageSetupForServiceWorkers));
  blink::mojom::CacheStoragePtrInfo cache_storage =
      std::move(params->provider_info->cache_storage);
  service_manager::mojom::InterfaceProviderPtrInfo interface_provider =
      std::move(params->provider_info->interface_provider);

  auto client = std::make_unique<ServiceWorkerContextClient>(
      params->embedded_worker_id, params->service_worker_version_id,
      params->scope, params->script_url,
      !params->installed_scripts_info.is_null(),
      std::move(params->renderer_preferences),
      std::move(params->service_worker_request),
      std::move(params->controller_request), std::move(params->instance_host),
      std::move(params->provider_info), std::move(temporal_self_),
      std::move(start_timing),
      RenderThreadImpl::current()
          ->GetWebMainThreadScheduler()
          ->DefaultTaskRunner());
  // Record UMA to indicate StartWorker is received on renderer.
  StartWorkerHistogramEnum metric =
      params->is_installed ? StartWorkerHistogramEnum::RECEIVED_ON_INSTALLED
                           : StartWorkerHistogramEnum::RECEIVED_ON_UNINSTALLED;
  UMA_HISTOGRAM_ENUMERATION(
      "ServiceWorker.EmbeddedWorkerInstanceClient.StartWorker", metric,
      StartWorkerHistogramEnum::NUM_TYPES);
  wrapper_ = StartWorkerContext(std::move(params), std::move(client),
                                std::move(cache_storage),
                                std::move(interface_provider));
}

void EmbeddedWorkerInstanceClientImpl::StopWorker() {
  // StopWorker must be called after StartWorker is called.
  DCHECK(ChildThreadImpl::current());
  DCHECK(wrapper_);

  TRACE_EVENT0("ServiceWorker", "EmbeddedWorkerInstanceClientImpl::StopWorker");
  wrapper_->worker()->TerminateWorkerContext();
}

void EmbeddedWorkerInstanceClientImpl::ResumeAfterDownload() {
  DCHECK(wrapper_);
  DCHECK(wrapper_->worker());
  wrapper_->worker()->ResumeAfterDownload();
}

void EmbeddedWorkerInstanceClientImpl::AddMessageToConsole(
    blink::WebConsoleMessage::Level level,
    const std::string& message) {
  DCHECK(wrapper_);
  DCHECK(wrapper_->worker());
  wrapper_->worker()->AddMessageToConsole(
      blink::WebConsoleMessage(level, blink::WebString::FromUTF8(message)));
}

void EmbeddedWorkerInstanceClientImpl::BindDevToolsAgent(
    blink::mojom::DevToolsAgentAssociatedRequest request) {
  DCHECK(wrapper_);
  DCHECK(wrapper_->worker());
  wrapper_->worker()->BindDevToolsAgent(request.PassHandle());
}

EmbeddedWorkerInstanceClientImpl::EmbeddedWorkerInstanceClientImpl(
    scoped_refptr<base::SingleThreadTaskRunner> io_thread_runner,
    mojom::EmbeddedWorkerInstanceClientRequest request)
    : binding_(this, std::move(request)),
      temporal_self_(this),
      io_thread_runner_(std::move(io_thread_runner)) {
  binding_.set_connection_error_handler(base::BindOnce(
      &EmbeddedWorkerInstanceClientImpl::OnError, base::Unretained(this)));
}

EmbeddedWorkerInstanceClientImpl::~EmbeddedWorkerInstanceClientImpl() {}

void EmbeddedWorkerInstanceClientImpl::OnError() {
  // Destroys |this| if |temporal_self_| still owns this (i.e., StartWorker()
  // was not yet called).
  temporal_self_.reset();
}

std::unique_ptr<EmbeddedWorkerInstanceClientImpl::WorkerWrapper>
EmbeddedWorkerInstanceClientImpl::StartWorkerContext(
    mojom::EmbeddedWorkerStartParamsPtr params,
    std::unique_ptr<ServiceWorkerContextClient> context_client,
    blink::mojom::CacheStoragePtrInfo cache_storage,
    service_manager::mojom::InterfaceProviderPtrInfo interface_provider) {
  std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager> manager;
  // |installed_scripts_info| is null if scripts should be served by net layer,
  // when the worker is not installed, or the worker is launched for checking
  // the update.
  if (params->installed_scripts_info) {
    manager = WebServiceWorkerInstalledScriptsManagerImpl::Create(
        std::move(params->installed_scripts_info), io_thread_runner_);
  }

  auto wrapper =
      std::make_unique<WorkerWrapper>(blink::WebEmbeddedWorker::Create(
          std::move(context_client), std::move(manager),
          params->content_settings_proxy.PassHandle(),
          cache_storage.PassHandle(), interface_provider.PassHandle()));

  blink::WebEmbeddedWorkerStartData start_data;
  start_data.script_url = params->script_url;
  start_data.user_agent =
      blink::WebString::FromUTF8(GetContentClient()->GetUserAgent());
  start_data.wait_for_debugger_mode =
      params->wait_for_debugger
          ? blink::WebEmbeddedWorkerStartData::kWaitForDebugger
          : blink::WebEmbeddedWorkerStartData::kDontWaitForDebugger;
  start_data.devtools_worker_token = params->devtools_worker_token;
  start_data.v8_cache_options =
      static_cast<blink::WebSettings::V8CacheOptions>(params->v8_cache_options);
  start_data.pause_after_download_mode =
      params->pause_after_download
          ? blink::WebEmbeddedWorkerStartData::kPauseAfterDownload
          : blink::WebEmbeddedWorkerStartData::kDontPauseAfterDownload;

  wrapper->worker()->StartWorkerContext(start_data);
  return wrapper;
}

}  // namespace content
