/*
 * Copyright (C) 2013 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 "web/WebEmbeddedWorkerImpl.h"

#include <memory>
#include "bindings/core/v8/SourceLocation.h"
#include "core/dom/Document.h"
#include "core/dom/SecurityContext.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/loader/FrameLoadRequest.h"
#include "core/loader/ThreadableLoadingContext.h"
#include "core/probe/CoreProbes.h"
#include "core/workers/ParentFrameTaskRunners.h"
#include "core/workers/WorkerClients.h"
#include "core/workers/WorkerGlobalScope.h"
#include "core/workers/WorkerInspectorProxy.h"
#include "core/workers/WorkerLoaderProxy.h"
#include "core/workers/WorkerScriptLoader.h"
#include "core/workers/WorkerThreadStartupData.h"
#include "modules/serviceworkers/ServiceWorkerContainerClient.h"
#include "modules/serviceworkers/ServiceWorkerThread.h"
#include "platform/Histogram.h"
#include "platform/SharedBuffer.h"
#include "platform/heap/Handle.h"
#include "platform/loader/fetch/SubstituteData.h"
#include "platform/network/ContentSecurityPolicyParsers.h"
#include "platform/network/ContentSecurityPolicyResponseHeaders.h"
#include "platform/network/NetworkUtils.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "platform/wtf/Functional.h"
#include "platform/wtf/PtrUtil.h"
#include "public/platform/Platform.h"
#include "public/platform/WebURLRequest.h"
#include "public/platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h"
#include "public/platform/modules/serviceworker/WebServiceWorkerProvider.h"
#include "public/web/WebConsoleMessage.h"
#include "public/web/WebDevToolsAgent.h"
#include "public/web/WebSettings.h"
#include "public/web/WebView.h"
#include "public/web/WebWorkerContentSettingsClientProxy.h"
#include "public/web/modules/serviceworker/WebServiceWorkerContextClient.h"
#include "web/IndexedDBClientImpl.h"
#include "web/ServiceWorkerGlobalScopeClientImpl.h"
#include "web/ServiceWorkerGlobalScopeProxy.h"
#include "web/WebDataSourceImpl.h"
#include "web/WebLocalFrameImpl.h"
#include "web/WorkerContentSettingsClient.h"

namespace blink {

WebEmbeddedWorker* WebEmbeddedWorker::Create(
    WebServiceWorkerContextClient* client,
    WebWorkerContentSettingsClientProxy* content_settings_client) {
  return new WebEmbeddedWorkerImpl(WTF::WrapUnique(client),
                                   WTF::WrapUnique(content_settings_client));
}

static HashSet<WebEmbeddedWorkerImpl*>& RunningWorkerInstances() {
  DEFINE_STATIC_LOCAL(HashSet<WebEmbeddedWorkerImpl*>, set, ());
  return set;
}

WebEmbeddedWorkerImpl::WebEmbeddedWorkerImpl(
    std::unique_ptr<WebServiceWorkerContextClient> client,
    std::unique_ptr<WebWorkerContentSettingsClientProxy>
        content_settings_client)
    : worker_context_client_(std::move(client)),
      content_settings_client_(std::move(content_settings_client)),
      worker_inspector_proxy_(WorkerInspectorProxy::Create()),
      web_view_(nullptr),
      main_frame_(nullptr),
      loading_shadow_page_(false),
      asked_to_terminate_(false),
      pause_after_download_state_(kDontPauseAfterDownload),
      waiting_for_debugger_state_(kNotWaitingForDebugger) {
  RunningWorkerInstances().insert(this);
}

WebEmbeddedWorkerImpl::~WebEmbeddedWorkerImpl() {
  // Prevent onScriptLoaderFinished from deleting 'this'.
  asked_to_terminate_ = true;

  if (worker_thread_)
    worker_thread_->TerminateAndWait();

  DCHECK(RunningWorkerInstances().Contains(this));
  RunningWorkerInstances().erase(this);
  DCHECK(web_view_);

  // Detach the client before closing the view to avoid getting called back.
  main_frame_->SetClient(0);

  if (worker_global_scope_proxy_) {
    worker_global_scope_proxy_->Detach();
    worker_global_scope_proxy_.Clear();
  }

  web_view_->Close();
  main_frame_->Close();
  if (loader_proxy_)
    loader_proxy_->DetachProvider(this);
}

void WebEmbeddedWorkerImpl::StartWorkerContext(
    const WebEmbeddedWorkerStartData& data) {
  DCHECK(!asked_to_terminate_);
  DCHECK(!main_script_loader_);
  DCHECK_EQ(pause_after_download_state_, kDontPauseAfterDownload);
  worker_start_data_ = data;

  // TODO(mkwst): This really needs to be piped through from the requesting
  // document, like we're doing for SharedWorkers. That turns out to be
  // incredibly convoluted, and since ServiceWorkers are locked to the same
  // origin as the page which requested them, the only time it would come
  // into play is a DNS poisoning attack after the page load. It's something
  // we should fix, but we're taking this shortcut for the prototype.
  //
  // https://crbug.com/590714
  KURL script_url = worker_start_data_.script_url;
  worker_start_data_.address_space = kWebAddressSpacePublic;
  if (NetworkUtils::IsReservedIPAddress(script_url.Host()))
    worker_start_data_.address_space = kWebAddressSpacePrivate;
  if (SecurityOrigin::Create(script_url)->IsLocalhost())
    worker_start_data_.address_space = kWebAddressSpaceLocal;

  if (data.pause_after_download_mode ==
      WebEmbeddedWorkerStartData::kPauseAfterDownload)
    pause_after_download_state_ = kDoPauseAfterDownload;
  PrepareShadowPageForLoader();
}

void WebEmbeddedWorkerImpl::TerminateWorkerContext() {
  if (asked_to_terminate_)
    return;
  asked_to_terminate_ = true;
  if (loading_shadow_page_) {
    // This deletes 'this'.
    worker_context_client_->WorkerContextFailedToStart();
    return;
  }
  if (main_script_loader_) {
    main_script_loader_->Cancel();
    main_script_loader_.Clear();
    // This deletes 'this'.
    worker_context_client_->WorkerContextFailedToStart();
    return;
  }
  if (!worker_thread_) {
    // The worker thread has not been created yet if the worker is asked to
    // terminate during waiting for debugger or paused after download.
    DCHECK(worker_start_data_.wait_for_debugger_mode ==
               WebEmbeddedWorkerStartData::kWaitForDebugger ||
           pause_after_download_state_ == kIsPausedAfterDownload);
    // This deletes 'this'.
    worker_context_client_->WorkerContextFailedToStart();
    return;
  }
  worker_thread_->Terminate();
  worker_inspector_proxy_->WorkerThreadTerminated();
}

void WebEmbeddedWorkerImpl::ResumeAfterDownload() {
  DCHECK(!asked_to_terminate_);
  DCHECK_EQ(pause_after_download_state_, kIsPausedAfterDownload);

  pause_after_download_state_ = kDontPauseAfterDownload;
  StartWorkerThread();
}

void WebEmbeddedWorkerImpl::AttachDevTools(const WebString& host_id,
                                           int session_id) {
  WebDevToolsAgent* devtools_agent = main_frame_->DevToolsAgent();
  if (devtools_agent)
    devtools_agent->Attach(host_id, session_id);
}

void WebEmbeddedWorkerImpl::ReattachDevTools(const WebString& host_id,
                                             int session_id,
                                             const WebString& saved_state) {
  WebDevToolsAgent* devtools_agent = main_frame_->DevToolsAgent();
  if (devtools_agent)
    devtools_agent->Reattach(host_id, session_id, saved_state);
  ResumeStartup();
}

void WebEmbeddedWorkerImpl::DetachDevTools() {
  WebDevToolsAgent* devtools_agent = main_frame_->DevToolsAgent();
  if (devtools_agent)
    devtools_agent->Detach();
}

void WebEmbeddedWorkerImpl::DispatchDevToolsMessage(int session_id,
                                                    int call_id,
                                                    const WebString& method,
                                                    const WebString& message) {
  if (asked_to_terminate_)
    return;
  WebDevToolsAgent* devtools_agent = main_frame_->DevToolsAgent();
  if (devtools_agent)
    devtools_agent->DispatchOnInspectorBackend(session_id, call_id, method,
                                               message);
}

void WebEmbeddedWorkerImpl::AddMessageToConsole(
    const WebConsoleMessage& message) {
  MessageLevel web_core_message_level;
  switch (message.level) {
    case WebConsoleMessage::kLevelVerbose:
      web_core_message_level = kVerboseMessageLevel;
      break;
    case WebConsoleMessage::kLevelInfo:
      web_core_message_level = kInfoMessageLevel;
      break;
    case WebConsoleMessage::kLevelWarning:
      web_core_message_level = kWarningMessageLevel;
      break;
    case WebConsoleMessage::kLevelError:
      web_core_message_level = kErrorMessageLevel;
      break;
    default:
      NOTREACHED();
      return;
  }

  main_frame_->GetFrame()->GetDocument()->AddConsoleMessage(
      ConsoleMessage::Create(
          kOtherMessageSource, web_core_message_level, message.text,
          SourceLocation::Create(message.url, message.line_number,
                                 message.column_number, nullptr)));
}

void WebEmbeddedWorkerImpl::PostMessageToPageInspector(const String& message) {
  worker_inspector_proxy_->DispatchMessageFromWorker(message);
}

void WebEmbeddedWorkerImpl::PostTaskToLoader(
    const WebTraceLocation& location,
    std::unique_ptr<WTF::CrossThreadClosure> task) {
  main_thread_task_runners_->Get(TaskType::kNetworking)
      ->PostTask(BLINK_FROM_HERE, std::move(task));
}

void WebEmbeddedWorkerImpl::PostTaskToWorkerGlobalScope(
    const WebTraceLocation& location,
    std::unique_ptr<WTF::CrossThreadClosure> task) {
  if (asked_to_terminate_ || !worker_thread_)
    return;
  worker_thread_->PostTask(location, std::move(task));
}

ThreadableLoadingContext* WebEmbeddedWorkerImpl::GetThreadableLoadingContext() {
  if (!loading_context_) {
    loading_context_ = ThreadableLoadingContext::Create(
        *main_frame_->GetFrame()->GetDocument());
  }
  return loading_context_;
}

void WebEmbeddedWorkerImpl::PrepareShadowPageForLoader() {
  // Create 'shadow page', which is never displayed and is used mainly to
  // provide a context for loading on the main thread.
  //
  // FIXME: This does mostly same as WebSharedWorkerImpl::initializeLoader.
  // This code, and probably most of the code in this class should be shared
  // with SharedWorker.
  DCHECK(!web_view_);
  web_view_ = WebView::Create(nullptr, kWebPageVisibilityStateVisible);
  WebSettings* settings = web_view_->GetSettings();
  // FIXME: http://crbug.com/363843. This needs to find a better way to
  // not create graphics layers.
  settings->SetAcceleratedCompositingEnabled(false);
  // Currently we block all mixed-content requests from a ServiceWorker.
  // FIXME: When we support FetchEvent.default(), we should relax this
  // restriction.
  settings->SetStrictMixedContentChecking(true);
  settings->SetAllowRunningOfInsecureContent(false);
  settings->SetDataSaverEnabled(worker_start_data_.data_saver_enabled);
  main_frame_ = ToWebLocalFrameImpl(WebLocalFrame::Create(
      WebTreeScopeType::kDocument, this, nullptr, nullptr));
  web_view_->SetMainFrame(main_frame_.Get());
  main_frame_->SetDevToolsAgentClient(this);

  // If we were asked to wait for debugger then it is the good time to do that.
  worker_context_client_->WorkerReadyForInspection();
  if (worker_start_data_.wait_for_debugger_mode ==
      WebEmbeddedWorkerStartData::kWaitForDebugger) {
    waiting_for_debugger_state_ = kWaitingForDebugger;
    return;
  }

  LoadShadowPage();
}

void WebEmbeddedWorkerImpl::LoadShadowPage() {
  // Construct substitute data source for the 'shadow page'. We only need it
  // to have same origin as the worker so the loading checks work correctly.
  CString content("");
  RefPtr<SharedBuffer> buffer(
      SharedBuffer::Create(content.Data(), content.length()));
  loading_shadow_page_ = true;
  main_frame_->GetFrame()->Loader().Load(
      FrameLoadRequest(0, ResourceRequest(worker_start_data_.script_url),
                       SubstituteData(buffer, "text/html", "UTF-8", KURL())));
}

void WebEmbeddedWorkerImpl::DidFinishDocumentLoad(WebLocalFrame* frame) {
  DCHECK_EQ(frame, main_frame_);
  DCHECK(!main_script_loader_);
  DCHECK(main_frame_);
  DCHECK(worker_context_client_);
  DCHECK(loading_shadow_page_);
  DCHECK(!asked_to_terminate_);
  loading_shadow_page_ = false;
  frame->DataSource()->SetServiceWorkerNetworkProvider(WTF::WrapUnique(
      worker_context_client_->CreateServiceWorkerNetworkProvider()));
  main_script_loader_ = WorkerScriptLoader::Create();
  main_script_loader_->SetRequestContext(
      WebURLRequest::kRequestContextServiceWorker);
  main_script_loader_->LoadAsynchronously(
      *main_frame_->GetFrame()->GetDocument(), worker_start_data_.script_url,
      kDenyCrossOriginRequests, worker_start_data_.address_space, nullptr,
      Bind(&WebEmbeddedWorkerImpl::OnScriptLoaderFinished,
           WTF::Unretained(this)));
  // Do nothing here since onScriptLoaderFinished() might have been already
  // invoked and |this| might have been deleted at this point.
}

void WebEmbeddedWorkerImpl::SendProtocolMessage(int session_id,
                                                int call_id,
                                                const WebString& message,
                                                const WebString& state) {
  worker_context_client_->SendDevToolsMessage(session_id, call_id, message,
                                              state);
}

void WebEmbeddedWorkerImpl::ResumeStartup() {
  bool was_waiting = (waiting_for_debugger_state_ == kWaitingForDebugger);
  waiting_for_debugger_state_ = kNotWaitingForDebugger;
  if (was_waiting)
    LoadShadowPage();
}

WebDevToolsAgentClient::WebKitClientMessageLoop*
WebEmbeddedWorkerImpl::CreateClientMessageLoop() {
  return worker_context_client_->CreateDevToolsMessageLoop();
}

void WebEmbeddedWorkerImpl::OnScriptLoaderFinished() {
  DCHECK(main_script_loader_);
  if (asked_to_terminate_)
    return;

  // The browser is expected to associate a registration and then load the
  // script. If there's no associated registration, the browser could not
  // successfully handle the SetHostedVersionID IPC, and the script load came
  // through the normal network stack rather than through service worker
  // loading code.
  if (!worker_context_client_->HasAssociatedRegistration() ||
      main_script_loader_->Failed()) {
    main_script_loader_.Clear();
    // This deletes 'this'.
    worker_context_client_->WorkerContextFailedToStart();
    return;
  }
  worker_context_client_->WorkerScriptLoaded();

  DEFINE_STATIC_LOCAL(CustomCountHistogram, script_size_histogram,
                      ("ServiceWorker.ScriptSize", 1000, 5000000, 50));
  script_size_histogram.Count(main_script_loader_->SourceText().length());
  if (main_script_loader_->CachedMetadata()) {
    DEFINE_STATIC_LOCAL(
        CustomCountHistogram, script_cached_metadata_size_histogram,
        ("ServiceWorker.ScriptCachedMetadataSize", 1000, 50000000, 50));
    script_cached_metadata_size_histogram.Count(
        main_script_loader_->CachedMetadata()->size());
  }

  if (pause_after_download_state_ == kDoPauseAfterDownload) {
    pause_after_download_state_ = kIsPausedAfterDownload;
    return;
  }
  StartWorkerThread();
}

void WebEmbeddedWorkerImpl::StartWorkerThread() {
  DCHECK_EQ(pause_after_download_state_, kDontPauseAfterDownload);
  DCHECK(!asked_to_terminate_);

  Document* document = main_frame_->GetFrame()->GetDocument();

  // FIXME: this document's origin is pristine and without any extra privileges.
  // (crbug.com/254993)
  SecurityOrigin* starter_origin = document->GetSecurityOrigin();

  WorkerClients* worker_clients = WorkerClients::Create();
  ProvideContentSettingsClientToWorker(worker_clients,
                                       std::move(content_settings_client_));
  ProvideIndexedDBClientToWorker(worker_clients,
                                 IndexedDBClientImpl::Create(*worker_clients));
  ProvideServiceWorkerGlobalScopeClientToWorker(
      worker_clients,
      ServiceWorkerGlobalScopeClientImpl::Create(*worker_context_client_));
  ProvideServiceWorkerContainerClientToWorker(
      worker_clients,
      WTF::WrapUnique(worker_context_client_->CreateServiceWorkerProvider()));

  // We need to set the CSP to both the shadow page's document and the
  // ServiceWorkerGlobalScope.
  document->InitContentSecurityPolicy(
      main_script_loader_->ReleaseContentSecurityPolicy());
  if (!main_script_loader_->GetReferrerPolicy().IsNull()) {
    document->ParseAndSetReferrerPolicy(
        main_script_loader_->GetReferrerPolicy());
  }

  KURL script_url = main_script_loader_->Url();
  WorkerThreadStartMode start_mode =
      worker_inspector_proxy_->WorkerStartMode(document);
  std::unique_ptr<WorkerSettings> worker_settings =
      WTF::WrapUnique(new WorkerSettings(document->GetSettings()));

  WorkerV8Settings worker_v8_settings = WorkerV8Settings::Default();
  worker_v8_settings.v8_cache_options_ =
      static_cast<V8CacheOptions>(worker_start_data_.v8_cache_options);

  std::unique_ptr<WorkerThreadStartupData> startup_data =
      WorkerThreadStartupData::Create(
          script_url, worker_start_data_.user_agent,
          main_script_loader_->SourceText(),
          main_script_loader_->ReleaseCachedMetadata(), start_mode,
          document->GetContentSecurityPolicy()->Headers().get(),
          main_script_loader_->GetReferrerPolicy(), starter_origin,
          worker_clients, main_script_loader_->ResponseAddressSpace(),
          main_script_loader_->OriginTrialTokens(), std::move(worker_settings),
          worker_v8_settings);

  main_script_loader_.Clear();

  // We have a dummy document here for loading but it doesn't really represent
  // the document/frame of associated document(s) for this worker. Here we
  // populate the task runners with null document not to confuse the frame
  // scheduler (which will end up using the thread's default task runner).
  main_thread_task_runners_ = ParentFrameTaskRunners::Create(nullptr);

  worker_global_scope_proxy_ = ServiceWorkerGlobalScopeProxy::Create(
      *this, *document, *worker_context_client_);
  loader_proxy_ = WorkerLoaderProxy::Create(this);
  worker_thread_ =
      ServiceWorkerThread::Create(loader_proxy_, *worker_global_scope_proxy_);
  worker_thread_->Start(std::move(startup_data),
                        main_thread_task_runners_.Get());
  worker_inspector_proxy_->WorkerThreadCreated(document, worker_thread_.get(),
                                               script_url);
}

}  // namespace blink
