/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/core/exported/web_shared_worker_impl.h"

#include <memory>
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
#include "third_party/blink/public/web/devtools_agent.mojom-blink.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
#include "third_party/blink/renderer/core/core_initializer.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/loader/threadable_loading_context.h"
#include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h"
#include "third_party/blink/renderer/core/workers/shared_worker_content_settings_proxy.h"
#include "third_party/blink/renderer/core/workers/shared_worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/shared_worker_thread.h"
#include "third_party/blink/renderer/core/workers/worker_classic_script_loader.h"
#include "third_party/blink/renderer/core/workers/worker_content_settings_client.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_inspector_proxy.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"

namespace blink {

WebSharedWorkerImpl::WebSharedWorkerImpl(WebSharedWorkerClient* client)
    : worker_inspector_proxy_(WorkerInspectorProxy::Create()),
      client_(client),
      creation_address_space_(mojom::IPAddressSpace::kPublic),
      weak_ptr_factory_(this) {
  DCHECK(IsMainThread());
}

WebSharedWorkerImpl::~WebSharedWorkerImpl() {
  DCHECK(IsMainThread());
}

void WebSharedWorkerImpl::TerminateWorkerThread() {
  DCHECK(IsMainThread());
  if (asked_to_terminate_)
    return;
  asked_to_terminate_ = true;
  if (shadow_page_ && !shadow_page_->WasInitialized()) {
    client_->WorkerScriptLoadFailed();
    // |this| is deleted at this point.
    return;
  }
  if (main_script_loader_) {
    main_script_loader_->Cancel();
    main_script_loader_ = nullptr;
    client_->WorkerScriptLoadFailed();
    // |this| is deleted at this point.
    return;
  }
  if (worker_thread_)
    worker_thread_->Terminate();
  worker_inspector_proxy_->WorkerThreadTerminated();
}

std::unique_ptr<WebApplicationCacheHost>
WebSharedWorkerImpl::CreateApplicationCacheHost(
    WebApplicationCacheHostClient* appcache_host_client) {
  DCHECK(IsMainThread());
  return client_->CreateApplicationCacheHost(appcache_host_client);
}

void WebSharedWorkerImpl::OnShadowPageInitialized() {
  DCHECK(IsMainThread());
  DCHECK(!main_script_loader_);
  shadow_page_->DocumentLoader()->SetServiceWorkerNetworkProvider(
      client_->CreateServiceWorkerNetworkProvider());
  main_script_loader_ = WorkerClassicScriptLoader::Create();

  network::mojom::FetchRequestMode fetch_request_mode =
      network::mojom::FetchRequestMode::kSameOrigin;
  network::mojom::FetchCredentialsMode fetch_credentials_mode =
      network::mojom::FetchCredentialsMode::kSameOrigin;
  if ((static_cast<KURL>(url_)).ProtocolIsData()) {
    fetch_request_mode = network::mojom::FetchRequestMode::kNoCORS;
    fetch_credentials_mode = network::mojom::FetchCredentialsMode::kInclude;
  }

  main_script_loader_->LoadAsynchronously(
      *shadow_page_->GetDocument(), url_,
      WebURLRequest::kRequestContextSharedWorker, fetch_request_mode,
      fetch_credentials_mode, creation_address_space_,
      Bind(&WebSharedWorkerImpl::DidReceiveScriptLoaderResponse,
           WTF::Unretained(this)),
      Bind(&WebSharedWorkerImpl::OnScriptLoaderFinished,
           WTF::Unretained(this)));
  // Do nothing here since OnScriptLoaderFinished() might have been already
  // invoked and |this| might have been deleted at this point.
}

void WebSharedWorkerImpl::ResumeStartup() {
  DCHECK(IsMainThread());
  bool is_paused_on_start = is_paused_on_start_;
  is_paused_on_start_ = false;
  if (is_paused_on_start) {
    // We'll continue in OnShadowPageInitialized().
    shadow_page_->Initialize(url_);
  }
}

const base::UnguessableToken& WebSharedWorkerImpl::GetDevToolsWorkerToken() {
  return devtools_worker_token_;
}

void WebSharedWorkerImpl::CountFeature(WebFeature feature) {
  DCHECK(IsMainThread());
  client_->CountFeature(feature);
}

void WebSharedWorkerImpl::PostMessageToPageInspector(int session_id,
                                                     const String& message) {
  DCHECK(IsMainThread());
  worker_inspector_proxy_->DispatchMessageFromWorker(session_id, message);
}

void WebSharedWorkerImpl::DidCloseWorkerGlobalScope() {
  DCHECK(IsMainThread());
  client_->WorkerContextClosed();
  TerminateWorkerThread();
}

void WebSharedWorkerImpl::DidTerminateWorkerThread() {
  DCHECK(IsMainThread());
  client_->WorkerContextDestroyed();
  // |this| is deleted at this point.
}

void WebSharedWorkerImpl::Connect(MessagePortChannel web_channel) {
  DCHECK(IsMainThread());
  // The HTML spec requires to queue a connect event using the DOM manipulation
  // task source.
  // https://html.spec.whatwg.org/multipage/workers.html#shared-workers-and-the-sharedworker-interface
  PostCrossThreadTask(
      *GetWorkerThread()->GetTaskRunner(TaskType::kDOMManipulation), FROM_HERE,
      CrossThreadBind(&WebSharedWorkerImpl::ConnectTaskOnWorkerThread,
                      WTF::CrossThreadUnretained(this),
                      WTF::Passed(std::move(web_channel))));
}

void WebSharedWorkerImpl::ConnectTaskOnWorkerThread(
    MessagePortChannel channel) {
  // Wrap the passed-in channel in a MessagePort, and send it off via a connect
  // event.
  DCHECK(worker_thread_->IsCurrentThread());
  WorkerGlobalScope* worker_global_scope =
      ToWorkerGlobalScope(worker_thread_->GlobalScope());
  MessagePort* port = MessagePort::Create(*worker_global_scope);
  port->Entangle(std::move(channel));
  SECURITY_DCHECK(worker_global_scope->IsSharedWorkerGlobalScope());
  worker_global_scope->DispatchEvent(CreateConnectEvent(port));
}

void WebSharedWorkerImpl::StartWorkerContext(
    const WebURL& url,
    const WebString& name,
    const WebString& content_security_policy,
    WebContentSecurityPolicyType policy_type,
    mojom::IPAddressSpace creation_address_space,
    const base::UnguessableToken& devtools_worker_token,
    mojo::ScopedMessagePipeHandle content_settings_handle,
    mojo::ScopedMessagePipeHandle interface_provider) {
  DCHECK(IsMainThread());
  url_ = url;
  name_ = name;
  creation_address_space_ = creation_address_space;
  // Chrome doesn't use interface versioning.
  content_settings_info_ = mojom::blink::WorkerContentSettingsProxyPtrInfo(
      std::move(content_settings_handle), 0u);
  pending_interface_provider_.set_handle(std::move(interface_provider));

  devtools_worker_token_ = devtools_worker_token;
  shadow_page_ = std::make_unique<WorkerShadowPage>(this);

  // If we were asked to pause worker context on start and wait for debugger
  // then now is a good time to do that.
  client_->WorkerReadyForInspection();
  if (pause_worker_context_on_start_) {
    is_paused_on_start_ = true;
    return;
  }

  // We'll continue in OnShadowPageInitialized().
  shadow_page_->Initialize(url_);
}

void WebSharedWorkerImpl::DidReceiveScriptLoaderResponse() {
  DCHECK(IsMainThread());
  probe::didReceiveScriptResponse(shadow_page_->GetDocument(),
                                  main_script_loader_->Identifier());
  client_->SelectAppCacheID(main_script_loader_->AppCacheID());
}

void WebSharedWorkerImpl::OnScriptLoaderFinished() {
  DCHECK(IsMainThread());
  DCHECK(main_script_loader_);
  if (asked_to_terminate_)
    return;
  if (main_script_loader_->Failed()) {
    main_script_loader_->Cancel();
    client_->WorkerScriptLoadFailed();
    // |this| is deleted at this point.
    return;
  }

  // S13nServiceWorker: The browser process is expected to send a
  // SetController IPC before sending the script response, but there is no
  // guarantee of the ordering as the messages arrive on different message
  // pipes. Wait for the SetController IPC to be received before starting the
  // worker; otherwise fetches from the worker might not go through the
  // appropriate controller.
  //
  // (For non-S13nServiceWorker, we don't need to do this step as the controller
  // service worker isn't used directly by the renderer, but to minimize code
  // differences between the flags just do it anyway.)
  client_->WaitForServiceWorkerControllerInfo(
      shadow_page_->DocumentLoader()->GetServiceWorkerNetworkProvider(),
      WTF::Bind(&WebSharedWorkerImpl::ContinueOnScriptLoaderFinished,
                weak_ptr_factory_.GetWeakPtr()));
}

void WebSharedWorkerImpl::ContinueOnScriptLoaderFinished() {
  DCHECK(IsMainThread());
  DCHECK(main_script_loader_);
  DCHECK(!main_script_loader_->Failed());
  if (asked_to_terminate_)
    return;

  // FIXME: this document's origin is pristine and without any extra privileges
  // (e.g. GrantUniversalAccess) that can be overriden in regular documents
  // via WebPreference by embedders. (crbug.com/254993)
  Document* document = shadow_page_->GetDocument();
  const SecurityOrigin* starter_origin = document->GetSecurityOrigin();
  bool starter_secure_context = document->IsSecureContext();

  WorkerClients* worker_clients = WorkerClients::Create();
  CoreInitializer::GetInstance().ProvideLocalFileSystemToWorker(
      *worker_clients);
  CoreInitializer::GetInstance().ProvideIndexedDBClientToWorker(
      *worker_clients);

  ProvideContentSettingsClientToWorker(
      worker_clients, std::make_unique<SharedWorkerContentSettingsProxy>(
                          std::move(content_settings_info_)));

  std::unique_ptr<WebWorkerFetchContext> web_worker_fetch_context =
      client_->CreateWorkerFetchContext(
          shadow_page_->DocumentLoader()->GetServiceWorkerNetworkProvider());
  DCHECK(web_worker_fetch_context);
  web_worker_fetch_context->SetApplicationCacheHostID(
      shadow_page_->GetDocument()
          ->Fetcher()
          ->Context()
          .ApplicationCacheHostID());
  ProvideWorkerFetchContextToWorker(worker_clients,
                                    std::move(web_worker_fetch_context));

  ContentSecurityPolicy* content_security_policy =
      main_script_loader_->ReleaseContentSecurityPolicy();
  ReferrerPolicy referrer_policy = kReferrerPolicyDefault;
  if (!main_script_loader_->GetReferrerPolicy().IsNull()) {
    SecurityPolicy::ReferrerPolicyFromHeaderValue(
        main_script_loader_->GetReferrerPolicy(),
        kDoNotSupportReferrerPolicyLegacyKeywords, &referrer_policy);
  }
  auto worker_settings = std::make_unique<WorkerSettings>(
      shadow_page_->GetDocument()->GetFrame()->GetSettings());

  // TODO(nhiroki); Set the coordinator for module fetch.
  // (https://crbug.com/680046)
  WorkerOrWorkletModuleFetchCoordinator* module_fetch_coordinator = nullptr;

  auto global_scope_creation_params =
      std::make_unique<GlobalScopeCreationParams>(
          url_, document->UserAgent(),
          content_security_policy ? content_security_policy->Headers().get()
                                  : nullptr,
          referrer_policy, starter_origin, starter_secure_context,
          worker_clients, main_script_loader_->ResponseAddressSpace(),
          main_script_loader_->OriginTrialTokens(), devtools_worker_token_,
          std::move(worker_settings), kV8CacheOptionsDefault,
          module_fetch_coordinator, std::move(pending_interface_provider_));
  String source_code = main_script_loader_->SourceText();

  // SharedWorker can sometimes run tasks that are initiated by/associated with
  // a document's frame but these documents can be from a different process. So
  // we intentionally populate the task runners with default task runners of the
  // main thread. Note that |m_document| should not be used as it's a dummy
  // document for loading that doesn't represent the frame of any associated
  // document.
  ParentExecutionContextTaskRunners* task_runners =
      ParentExecutionContextTaskRunners::Create();

  reporting_proxy_ = new SharedWorkerReportingProxy(this, task_runners);
  worker_thread_ = std::make_unique<SharedWorkerThread>(
      name_, ThreadableLoadingContext::Create(*document), *reporting_proxy_);
  probe::scriptImported(document, main_script_loader_->Identifier(),
                        main_script_loader_->SourceText());
  main_script_loader_ = nullptr;

  auto thread_startup_data = WorkerBackingThreadStartupData::CreateDefault();
  thread_startup_data.atomics_wait_mode =
      WorkerBackingThreadStartupData::AtomicsWaitMode::kAllow;

  GetWorkerThread()->Start(
      std::move(global_scope_creation_params), thread_startup_data,
      worker_inspector_proxy_->ShouldPauseOnWorkerStart(document),
      task_runners);
  worker_inspector_proxy_->WorkerThreadCreated(document, GetWorkerThread(),
                                               url_);
  // TODO(nhiroki): Support module workers (https://crbug.com/680046).
  GetWorkerThread()->EvaluateClassicScript(url_, source_code,
                                           nullptr /* cached_meta_data */,
                                           v8_inspector::V8StackTraceId());
  client_->WorkerScriptLoaded();
}

void WebSharedWorkerImpl::TerminateWorkerContext() {
  DCHECK(IsMainThread());
  TerminateWorkerThread();
}

void WebSharedWorkerImpl::PauseWorkerContextOnStart() {
  pause_worker_context_on_start_ = true;
}

void WebSharedWorkerImpl::BindDevToolsAgent(
    mojo::ScopedInterfaceEndpointHandle devtools_agent_request) {
  shadow_page_->BindDevToolsAgent(mojom::blink::DevToolsAgentAssociatedRequest(
      std::move(devtools_agent_request)));
}

std::unique_ptr<WebSharedWorker> WebSharedWorker::Create(
    WebSharedWorkerClient* client) {
  return base::WrapUnique(new WebSharedWorkerImpl(client));
}

}  // namespace blink
