// 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/renderer/service_worker/web_service_worker_provider_impl.h"

#include <memory>
#include <utility>

#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/renderer/service_worker/service_worker_dispatcher.h"
#include "content/renderer/service_worker/service_worker_handle_reference.h"
#include "content/renderer/service_worker/service_worker_provider_context.h"
#include "content/renderer/service_worker/web_service_worker_impl.h"
#include "content/renderer/service_worker/web_service_worker_registration_impl.h"
#include "third_party/WebKit/common/message_port/message_port_channel.h"
#include "third_party/WebKit/common/service_worker/service_worker_provider_type.mojom.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProviderClient.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom.h"

using blink::WebURL;

namespace content {

namespace {

const char kLostConnectionErrorMessage[] =
    "Lost connection to the service worker system.";

}  // anonymous namespace

WebServiceWorkerProviderImpl::WebServiceWorkerProviderImpl(
    ThreadSafeSender* thread_safe_sender,
    ServiceWorkerProviderContext* context)
    : thread_safe_sender_(thread_safe_sender),
      context_(context),
      provider_client_(nullptr),
      weak_factory_(this) {
  DCHECK(context_);
  switch (context_->provider_type()) {
    case blink::mojom::ServiceWorkerProviderType::kForWindow:
      DCHECK(context_->container_host());
      context_->SetWebServiceWorkerProvider(weak_factory_.GetWeakPtr());
      break;
    case blink::mojom::ServiceWorkerProviderType::kForServiceWorker:
      // Do nothing.
      break;
    case blink::mojom::ServiceWorkerProviderType::kForSharedWorker:
    case blink::mojom::ServiceWorkerProviderType::kUnknown:
      NOTREACHED() << "Unimplemented type: " << context_->provider_type();
      break;
  }
}

WebServiceWorkerProviderImpl::~WebServiceWorkerProviderImpl() = default;

void WebServiceWorkerProviderImpl::SetClient(
    blink::WebServiceWorkerProviderClient* client) {
  provider_client_ = client;
  if (!provider_client_)
    return;

  std::unique_ptr<ServiceWorkerHandleReference> controller =
      context_->TakeController();
  if (!controller)
    return;
  SetController(std::move(controller), context_->used_features(),
                false /* notify_controllerchange */);
}

void WebServiceWorkerProviderImpl::RegisterServiceWorker(
    const WebURL& web_pattern,
    const WebURL& web_script_url,
    blink::mojom::ServiceWorkerUpdateViaCache update_via_cache,
    std::unique_ptr<WebServiceWorkerRegistrationCallbacks> callbacks) {
  DCHECK(callbacks);

  GURL pattern(web_pattern);
  GURL script_url(web_script_url);
  if (pattern.possibly_invalid_spec().size() > url::kMaxURLChars ||
      script_url.possibly_invalid_spec().size() > url::kMaxURLChars) {
    std::string error_message(kServiceWorkerRegisterErrorPrefix);
    error_message += "The provided scriptURL or scope is too long.";
    callbacks->OnError(blink::WebServiceWorkerError(
        blink::mojom::ServiceWorkerErrorType::kSecurity,
        blink::WebString::FromASCII(error_message)));
    return;
  }

  if (!context_->container_host()) {
    std::string error_message(kServiceWorkerRegisterErrorPrefix);
    error_message += kLostConnectionErrorMessage;
    callbacks->OnError(blink::WebServiceWorkerError(
        blink::mojom::ServiceWorkerErrorType::kAbort,
        blink::WebString::FromASCII(error_message)));
    return;
  }

  TRACE_EVENT_ASYNC_BEGIN2(
      "ServiceWorker", "WebServiceWorkerProviderImpl::RegisterServiceWorker",
      this, "Scope", pattern.spec(), "Script URL", script_url.spec());
  auto options = blink::mojom::ServiceWorkerRegistrationOptions::New(
      pattern, update_via_cache);
  context_->container_host()->Register(
      script_url, std::move(options),
      base::BindOnce(&WebServiceWorkerProviderImpl::OnRegistered,
                     weak_factory_.GetWeakPtr(), std::move(callbacks)));
}

void WebServiceWorkerProviderImpl::GetRegistration(
    const blink::WebURL& web_document_url,
    std::unique_ptr<WebServiceWorkerGetRegistrationCallbacks> callbacks) {
  DCHECK(callbacks);
  GURL document_url(web_document_url);
  if (document_url.possibly_invalid_spec().size() > url::kMaxURLChars) {
    std::string error_message(kServiceWorkerGetRegistrationErrorPrefix);
    error_message += "The provided documentURL is too long.";
    callbacks->OnError(blink::WebServiceWorkerError(
        blink::mojom::ServiceWorkerErrorType::kSecurity,
        blink::WebString::FromASCII(error_message)));
    return;
  }

  if (!context_->container_host()) {
    std::string error_message(kServiceWorkerGetRegistrationErrorPrefix);
    error_message += kLostConnectionErrorMessage;
    callbacks->OnError(blink::WebServiceWorkerError(
        blink::mojom::ServiceWorkerErrorType::kAbort,
        blink::WebString::FromASCII(error_message)));
    return;
  }

  TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
                           "WebServiceWorkerProviderImpl::GetRegistration",
                           this, "Document URL", document_url.spec());
  context_->container_host()->GetRegistration(
      document_url,
      base::BindOnce(&WebServiceWorkerProviderImpl::OnDidGetRegistration,
                     weak_factory_.GetWeakPtr(), std::move(callbacks)));
}

void WebServiceWorkerProviderImpl::GetRegistrations(
    std::unique_ptr<WebServiceWorkerGetRegistrationsCallbacks> callbacks) {
  DCHECK(callbacks);
  if (!context_->container_host()) {
    std::string error_message(kServiceWorkerGetRegistrationsErrorPrefix);
    error_message += kLostConnectionErrorMessage;
    callbacks->OnError(blink::WebServiceWorkerError(
        blink::mojom::ServiceWorkerErrorType::kAbort,
        blink::WebString::FromASCII(error_message)));
    return;
  }

  TRACE_EVENT_ASYNC_BEGIN0(
      "ServiceWorker", "WebServiceWorkerProviderImpl::GetRegistrations", this);
  context_->container_host()->GetRegistrations(
      base::BindOnce(&WebServiceWorkerProviderImpl::OnDidGetRegistrations,
                     weak_factory_.GetWeakPtr(), std::move(callbacks)));
}

void WebServiceWorkerProviderImpl::GetRegistrationForReady(
    std::unique_ptr<WebServiceWorkerGetRegistrationForReadyCallbacks>
        callbacks) {
  if (!context_->container_host()) {
    return;
  }

  TRACE_EVENT_ASYNC_BEGIN0(
      "ServiceWorker", "WebServiceWorkerProviderImpl::GetRegistrationForReady",
      this);
  context_->container_host()->GetRegistrationForReady(base::BindOnce(
      &WebServiceWorkerProviderImpl::OnDidGetRegistrationForReady,
      weak_factory_.GetWeakPtr(), std::move(callbacks)));
}

bool WebServiceWorkerProviderImpl::ValidateScopeAndScriptURL(
    const blink::WebURL& scope,
    const blink::WebURL& script_url,
    blink::WebString* error_message) {
  std::string error;
  bool has_error = ServiceWorkerUtils::ContainsDisallowedCharacter(
      scope, script_url, &error);
  if (has_error)
    *error_message = blink::WebString::FromUTF8(error);
  return !has_error;
}

void WebServiceWorkerProviderImpl::SetController(
    std::unique_ptr<ServiceWorkerHandleReference> controller,
    const std::set<blink::mojom::WebFeature>& features,
    bool should_notify_controller_change) {
  if (!provider_client_)
    return;

  for (blink::mojom::WebFeature feature : features)
    provider_client_->CountFeature(feature);
  provider_client_->SetController(
      WebServiceWorkerImpl::CreateHandle(
          GetDispatcher()->GetOrCreateServiceWorker(std::move(controller))),
      should_notify_controller_change);
}

void WebServiceWorkerProviderImpl::PostMessageToClient(
    blink::mojom::ServiceWorkerObjectInfoPtr source,
    const base::string16& message,
    std::vector<mojo::ScopedMessagePipeHandle> message_pipes) {
  if (!provider_client_)
    return;

  scoped_refptr<WebServiceWorkerImpl> worker =
      GetDispatcher()->GetOrCreateServiceWorker(
          ServiceWorkerHandleReference::Create(std::move(source),
                                               thread_safe_sender_.get()));
  auto message_ports =
      blink::MessagePortChannel::CreateFromHandles(std::move(message_pipes));
  provider_client_->DispatchMessageEvent(
      WebServiceWorkerImpl::CreateHandle(std::move(worker)),
      blink::WebString::FromUTF16(message), std::move(message_ports));
}

void WebServiceWorkerProviderImpl::CountFeature(
    blink::mojom::WebFeature feature) {
  if (!provider_client_)
    return;
  provider_client_->CountFeature(feature);
}

int WebServiceWorkerProviderImpl::provider_id() const {
  return context_->provider_id();
}

ServiceWorkerDispatcher* WebServiceWorkerProviderImpl::GetDispatcher() {
  return ServiceWorkerDispatcher::GetThreadSpecificInstance();
}

void WebServiceWorkerProviderImpl::OnRegistered(
    std::unique_ptr<WebServiceWorkerRegistrationCallbacks> callbacks,
    blink::mojom::ServiceWorkerErrorType error,
    const base::Optional<std::string>& error_msg,
    blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration) {
  TRACE_EVENT_ASYNC_END2(
      "ServiceWorker", "WebServiceWorkerProviderImpl::RegisterServiceWorker",
      this, "Error", ServiceWorkerUtils::ErrorTypeToString(error), "Message",
      error_msg ? *error_msg : "Success");
  if (error != blink::mojom::ServiceWorkerErrorType::kNone) {
    DCHECK(error_msg);
    DCHECK(!registration);
    callbacks->OnError(blink::WebServiceWorkerError(
        error, blink::WebString::FromASCII(*error_msg)));
    return;
  }

  DCHECK(!error_msg);
  DCHECK(registration);
  DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
            registration->registration_id);
  callbacks->OnSuccess(WebServiceWorkerRegistrationImpl::CreateHandle(
      context_->GetOrCreateRegistrationForServiceWorkerClient(
          std::move(registration))));
}

void WebServiceWorkerProviderImpl::OnDidGetRegistration(
    std::unique_ptr<WebServiceWorkerGetRegistrationCallbacks> callbacks,
    blink::mojom::ServiceWorkerErrorType error,
    const base::Optional<std::string>& error_msg,
    blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration) {
  TRACE_EVENT_ASYNC_END2("ServiceWorker",
                         "WebServiceWorkerProviderImpl::GetRegistration", this,
                         "Error", ServiceWorkerUtils::ErrorTypeToString(error),
                         "Message", error_msg ? *error_msg : "Success");
  if (error != blink::mojom::ServiceWorkerErrorType::kNone) {
    DCHECK(error_msg);
    DCHECK(!registration);
    callbacks->OnError(blink::WebServiceWorkerError(
        error, blink::WebString::FromASCII(*error_msg)));
    return;
  }

  DCHECK(!error_msg);
  // |registration| is nullptr if there is no registration at the scope or it's
  // uninstalling.
  if (!registration) {
    callbacks->OnSuccess(nullptr);
    return;
  }
  DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
            registration->registration_id);
  scoped_refptr<WebServiceWorkerRegistrationImpl> impl =
      context_->GetOrCreateRegistrationForServiceWorkerClient(
          std::move(registration));
  DCHECK(impl);
  callbacks->OnSuccess(
      WebServiceWorkerRegistrationImpl::CreateHandle(std::move(impl)));
}

void WebServiceWorkerProviderImpl::OnDidGetRegistrations(
    std::unique_ptr<WebServiceWorkerGetRegistrationsCallbacks> callbacks,
    blink::mojom::ServiceWorkerErrorType error,
    const base::Optional<std::string>& error_msg,
    base::Optional<
        std::vector<blink::mojom::ServiceWorkerRegistrationObjectInfoPtr>>
        infos) {
  TRACE_EVENT_ASYNC_END2("ServiceWorker",
                         "WebServiceWorkerProviderImpl::GetRegistrations", this,
                         "Error", ServiceWorkerUtils::ErrorTypeToString(error),
                         "Message", error_msg ? *error_msg : "Success");
  if (error != blink::mojom::ServiceWorkerErrorType::kNone) {
    DCHECK(error_msg);
    DCHECK(!infos);
    callbacks->OnError(blink::WebServiceWorkerError(
        error, blink::WebString::FromASCII(*error_msg)));
    return;
  }

  DCHECK(!error_msg);
  DCHECK(infos);
  using WebServiceWorkerRegistrationHandles =
      WebServiceWorkerProvider::WebServiceWorkerRegistrationHandles;
  std::unique_ptr<WebServiceWorkerRegistrationHandles> registrations =
      std::make_unique<WebServiceWorkerRegistrationHandles>(infos->size());
  for (size_t i = 0; i < infos->size(); ++i) {
    DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
              (*infos)[i]->registration_id);
    (*registrations)[i] = WebServiceWorkerRegistrationImpl::CreateHandle(
        context_->GetOrCreateRegistrationForServiceWorkerClient(
            std::move((*infos)[i])));
  }
  callbacks->OnSuccess(std::move(registrations));
}

void WebServiceWorkerProviderImpl::OnDidGetRegistrationForReady(
    std::unique_ptr<WebServiceWorkerGetRegistrationForReadyCallbacks> callbacks,
    blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration) {
  TRACE_EVENT_ASYNC_END0(
      "ServiceWorker", "WebServiceWorkerProviderImpl::GetRegistrationForReady",
      this);
  // TODO(leonhsl): Currently the only reason that we allow nullable
  // |registration| is: impl of the mojo method
  // GetRegistrationForReady() needs to respond some non-sense params even if it
  // has found that the request is a bad message and has called
  // mojo::ReportBadMessage(), this is forced by Mojo, please see
  // content::ServiceWorkerProviderHost::GetRegistrationForReady(). We'll find a
  // better solution once the discussion at
  // https://groups.google.com/a/chromium.org/forum/#!topic/chromium-mojo/NNsogKNurlA
  // settled.
  CHECK(registration);
  DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
            registration->registration_id);
  callbacks->OnSuccess(WebServiceWorkerRegistrationImpl::CreateHandle(
      context_->GetOrCreateRegistrationForServiceWorkerClient(
          std::move(registration))));
}

}  // namespace content
