// Copyright 2014 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/embedded_worker_test_helper.h"

#include <map>
#include <string>

#include "base/bind.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {

EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(int mock_render_process_id)
    : wrapper_(new ServiceWorkerContextWrapper(NULL)),
      next_thread_id_(0),
      mock_render_process_id_(mock_render_process_id),
      weak_factory_(this) {
  wrapper_->InitInternal(base::FilePath(),
                         base::MessageLoopProxy::current(),
                         base::MessageLoopProxy::current(),
                         base::MessageLoopProxy::current(),
                         NULL);
  wrapper_->process_manager()->SetProcessIdForTest(mock_render_process_id);
  registry()->AddChildProcessSender(mock_render_process_id, this);
}

EmbeddedWorkerTestHelper::~EmbeddedWorkerTestHelper() {
  if (wrapper_)
    wrapper_->Shutdown();
}

void EmbeddedWorkerTestHelper::SimulateAddProcessToWorker(
    int embedded_worker_id,
    int process_id) {
  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
  ASSERT_TRUE(worker);
  registry()->AddChildProcessSender(process_id, this);
  worker->AddProcessReference(process_id);
}

bool EmbeddedWorkerTestHelper::Send(IPC::Message* message) {
  OnMessageReceived(*message);
  delete message;
  return true;
}

bool EmbeddedWorkerTestHelper::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerTestHelper, message)
    IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StartWorker, OnStartWorkerStub)
    IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StopWorker, OnStopWorkerStub)
    IPC_MESSAGE_HANDLER(EmbeddedWorkerContextMsg_MessageToWorker,
                        OnMessageToWorkerStub)
    IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_ResumeAfterDownload,
                        OnResumeAfterDownloadStub)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()

  // IPC::TestSink only records messages that are not handled by filters,
  // so we just forward all messages to the separate sink.
  sink_.OnMessageReceived(message);

  return handled;
}

ServiceWorkerContextCore* EmbeddedWorkerTestHelper::context() {
  return wrapper_->context();
}

void EmbeddedWorkerTestHelper::ShutdownContext() {
  wrapper_->Shutdown();
  wrapper_ = NULL;
}

void EmbeddedWorkerTestHelper::OnStartWorker(
    int embedded_worker_id,
    int64 service_worker_version_id,
    const GURL& scope,
    const GURL& script_url,
    bool pause_after_download) {
  if (pause_after_download) {
    SimulatePausedAfterDownload(embedded_worker_id);
    return;
  }
  SimulateWorkerScriptLoaded(embedded_worker_id);
  SimulateWorkerStarted(next_thread_id_++, embedded_worker_id);
}

void EmbeddedWorkerTestHelper::OnResumeAfterDownload(int embedded_worker_id) {
  SimulateWorkerScriptLoaded(embedded_worker_id);
  SimulateWorkerStarted(next_thread_id_++, embedded_worker_id);
}

void EmbeddedWorkerTestHelper::OnStopWorker(int embedded_worker_id) {
  // By default just notify the sender that the worker is stopped.
  SimulateWorkerStopped(embedded_worker_id);
}

bool EmbeddedWorkerTestHelper::OnMessageToWorker(
    int thread_id,
    int embedded_worker_id,
    const IPC::Message& message) {
  bool handled = true;
  current_embedded_worker_id_ = embedded_worker_id;
  IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerTestHelper, message)
    IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ActivateEvent, OnActivateEventStub)
    IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent, OnInstallEventStub)
    IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent, OnFetchEventStub)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  // Record all messages directed to inner script context.
  inner_sink_.OnMessageReceived(message);
  return handled;
}

void EmbeddedWorkerTestHelper::OnActivateEvent(int embedded_worker_id,
                                               int request_id) {
  SimulateSend(
      new ServiceWorkerHostMsg_ActivateEventFinished(
          embedded_worker_id, request_id,
          blink::WebServiceWorkerEventResultCompleted));
}

void EmbeddedWorkerTestHelper::OnInstallEvent(int embedded_worker_id,
                                              int request_id,
                                              int active_version_id) {
  SimulateSend(
      new ServiceWorkerHostMsg_InstallEventFinished(
          embedded_worker_id, request_id,
          blink::WebServiceWorkerEventResultCompleted));
}

void EmbeddedWorkerTestHelper::OnFetchEvent(
    int embedded_worker_id,
    int request_id,
    const ServiceWorkerFetchRequest& request) {
  SimulateSend(
      new ServiceWorkerHostMsg_FetchEventFinished(
          embedded_worker_id,
          request_id,
          SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
          ServiceWorkerResponse(GURL(""),
                                200,
                                "OK",
                                std::map<std::string, std::string>(),
                                std::string())));
}

void EmbeddedWorkerTestHelper::SimulatePausedAfterDownload(
      int embedded_worker_id) {
  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
  ASSERT_TRUE(worker != NULL);
  registry()->OnPausedAfterDownload(worker->process_id(), embedded_worker_id);
}

void EmbeddedWorkerTestHelper::SimulateWorkerScriptLoaded(
      int embedded_worker_id) {
  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
  ASSERT_TRUE(worker != NULL);
  registry()->OnWorkerScriptLoaded(worker->process_id(), embedded_worker_id);
}

void EmbeddedWorkerTestHelper::SimulateWorkerStarted(
    int thread_id, int embedded_worker_id) {
  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
  ASSERT_TRUE(worker != NULL);
  registry()->OnWorkerStarted(
      worker->process_id(),
      thread_id,
      embedded_worker_id);
}

void EmbeddedWorkerTestHelper::SimulateWorkerStopped(
    int embedded_worker_id) {
  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
  if (worker != NULL)
    registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
}

void EmbeddedWorkerTestHelper::SimulateSend(
    IPC::Message* message) {
  registry()->OnMessageReceived(*message);
  delete message;
}

void EmbeddedWorkerTestHelper::OnStartWorkerStub(
    const EmbeddedWorkerMsg_StartWorker_Params& params) {
  EmbeddedWorkerInstance* worker =
      registry()->GetWorker(params.embedded_worker_id);
  ASSERT_TRUE(worker != NULL);
  EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
  base::MessageLoopProxy::current()->PostTask(
      FROM_HERE,
      base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker,
                  weak_factory_.GetWeakPtr(),
                  params.embedded_worker_id,
                  params.service_worker_version_id,
                  params.scope,
                  params.script_url,
                  params.pause_after_download));
}

void EmbeddedWorkerTestHelper::OnResumeAfterDownloadStub(
      int embedded_worker_id) {
  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
  ASSERT_TRUE(worker != NULL);
  base::MessageLoopProxy::current()->PostTask(
      FROM_HERE,
      base::Bind(&EmbeddedWorkerTestHelper::OnResumeAfterDownload,
                 weak_factory_.GetWeakPtr(),
                 embedded_worker_id));
}

void EmbeddedWorkerTestHelper::OnStopWorkerStub(int embedded_worker_id) {
  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
  ASSERT_TRUE(worker != NULL);
  base::MessageLoopProxy::current()->PostTask(
      FROM_HERE,
      base::Bind(&EmbeddedWorkerTestHelper::OnStopWorker,
                 weak_factory_.GetWeakPtr(),
                 embedded_worker_id));
}

void EmbeddedWorkerTestHelper::OnMessageToWorkerStub(
    int thread_id,
    int embedded_worker_id,
    const IPC::Message& message) {
  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
  ASSERT_TRUE(worker != NULL);
  EXPECT_EQ(worker->thread_id(), thread_id);
  base::MessageLoopProxy::current()->PostTask(
      FROM_HERE,
      base::Bind(
          base::IgnoreResult(&EmbeddedWorkerTestHelper::OnMessageToWorker),
          weak_factory_.GetWeakPtr(),
          thread_id,
          embedded_worker_id,
          message));
}

void EmbeddedWorkerTestHelper::OnActivateEventStub(int request_id) {
  base::MessageLoopProxy::current()->PostTask(
      FROM_HERE,
      base::Bind(&EmbeddedWorkerTestHelper::OnActivateEvent,
                 weak_factory_.GetWeakPtr(),
                 current_embedded_worker_id_,
                 request_id));
}

void EmbeddedWorkerTestHelper::OnInstallEventStub(int request_id,
                                                  int active_version_id) {
  base::MessageLoopProxy::current()->PostTask(
      FROM_HERE,
      base::Bind(&EmbeddedWorkerTestHelper::OnInstallEvent,
                 weak_factory_.GetWeakPtr(),
                 current_embedded_worker_id_,
                 request_id,
                 active_version_id));
}

void EmbeddedWorkerTestHelper::OnFetchEventStub(
    int request_id,
    const ServiceWorkerFetchRequest& request) {
  base::MessageLoopProxy::current()->PostTask(
      FROM_HERE,
      base::Bind(&EmbeddedWorkerTestHelper::OnFetchEvent,
                 weak_factory_.GetWeakPtr(),
                 current_embedded_worker_id_,
                 request_id,
                 request));
}

EmbeddedWorkerRegistry* EmbeddedWorkerTestHelper::registry() {
  DCHECK(context());
  return context()->embedded_worker_registry();
}

}  // namespace content
