// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/proxy/ppapi_proxy_test.h"

#include <memory>
#include <tuple>

#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/message_loop/message_pump_type.h"
#include "base/observer_list.h"
#include "base/process/process_handle.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_runner.h"
#include "ipc/ipc_sync_channel.h"
#include "ipc/message_filter.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_proxy_private.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/ppb_message_loop_proxy.h"

namespace ppapi {
namespace proxy {

namespace {
// HostDispatcher requires a PPB_Proxy_Private, so we always provide a fallback
// do-nothing implementation.
void PluginCrashed(PP_Module module) {
  NOTREACHED();
}

PP_Instance GetInstanceForResource(PP_Resource resource) {
  // If a test relies on this, we need to implement it.
  NOTREACHED();
  return 0;
}

void SetReserveInstanceIDCallback(PP_Module module,
                                  PP_Bool (*is_seen)(PP_Module, PP_Instance)) {
  // This function gets called in HostDispatcher's constructor.  We simply don't
  // worry about Instance uniqueness in tests, so we can ignore the call.
}

void AddRefModule(PP_Module module) {}
void ReleaseModule(PP_Module module) {}
PP_Bool IsInModuleDestructor(PP_Module module) { return PP_FALSE; }

PPB_Proxy_Private ppb_proxy_private = {
  &PluginCrashed,
  &GetInstanceForResource,
  &SetReserveInstanceIDCallback,
  &AddRefModule,
  &ReleaseModule,
  &IsInModuleDestructor
};

// We allow multiple harnesses at a time to respond to 'GetInterface' calls.
// We assume that only 1 harness's GetInterface function will ever support a
// given interface name. In practice, there will either be only 1 GetInterface
// handler (for PluginProxyTest or HostProxyTest), or there will be only 2
// GetInterface handlers (for TwoWayTest).  In the latter case, one handler is
// for the PluginProxyTestHarness and should only respond for PPP interfaces,
// and the other handler is for the HostProxyTestHarness which should only
// ever respond for PPB interfaces.
base::ObserverList<ProxyTestHarnessBase>::Unchecked get_interface_handlers_;

const void* MockGetInterface(const char* name) {
  for (auto& observer : get_interface_handlers_) {
    const void* interface = observer.GetInterface(name);
    if (interface)
      return interface;
  }
  if (strcmp(name, PPB_PROXY_PRIVATE_INTERFACE) == 0)
    return &ppb_proxy_private;
  return NULL;
}

void SetUpRemoteHarness(ProxyTestHarnessBase* harness,
                        const IPC::ChannelHandle& handle,
                        base::SingleThreadTaskRunner* ipc_task_runner,
                        base::WaitableEvent* shutdown_event,
                        base::WaitableEvent* harness_set_up) {
  harness->SetUpHarnessWithChannel(handle, ipc_task_runner, shutdown_event,
                                   false);
  harness_set_up->Signal();
}

void TearDownRemoteHarness(ProxyTestHarnessBase* harness,
                           base::WaitableEvent* harness_torn_down) {
  harness->TearDownHarness();
  harness_torn_down->Signal();
}

void RunTaskOnRemoteHarness(base::OnceClosure task,
                            base::WaitableEvent* task_complete) {
  std::move(task).Run();
  task_complete->Signal();
}

}  // namespace

// ProxyTestHarnessBase --------------------------------------------------------

ProxyTestHarnessBase::ProxyTestHarnessBase() : pp_module_(0x98765),
                                               pp_instance_(0x12345) {
  get_interface_handlers_.AddObserver(this);
}

ProxyTestHarnessBase::~ProxyTestHarnessBase() {
  get_interface_handlers_.RemoveObserver(this);
}

const void* ProxyTestHarnessBase::GetInterface(const char* name) {
  return registered_interfaces_[name];
}

void ProxyTestHarnessBase::RegisterTestInterface(const char* name,
                                                 const void* test_interface) {
  registered_interfaces_[name] = test_interface;
}

bool ProxyTestHarnessBase::SupportsInterface(const char* name) {
  sink().ClearMessages();

  // IPC doesn't actually write to this when we send a message manually
  // not actually using IPC.
  bool unused_result = false;
  PpapiMsg_SupportsInterface msg(name, &unused_result);
  GetDispatcher()->OnMessageReceived(msg);

  const IPC::Message* reply_msg =
      sink().GetUniqueMessageMatching(IPC_REPLY_ID);
  EXPECT_TRUE(reply_msg);
  if (!reply_msg)
    return false;

  PpapiMsg_SupportsInterface::ReplyParam reply_data;
  EXPECT_TRUE(PpapiMsg_SupportsInterface::ReadReplyParam(
      reply_msg, &reply_data));

  sink().ClearMessages();
  return std::get<0>(reply_data);
}

// PluginProxyTestHarness ------------------------------------------------------

PluginProxyTestHarness::PluginProxyTestHarness(
    GlobalsConfiguration globals_config)
    : globals_config_(globals_config) {
}

PluginProxyTestHarness::~PluginProxyTestHarness() {
}

PpapiGlobals* PluginProxyTestHarness::GetGlobals() {
  return plugin_globals_.get();
}

Dispatcher* PluginProxyTestHarness::GetDispatcher() {
  return plugin_dispatcher_.get();
}

void PluginProxyTestHarness::SetUpHarness() {
  // These must be first since the dispatcher set-up uses them.
  CreatePluginGlobals(nullptr /* ipc_task_runner */);
  // Some of the methods called during set-up check that the lock is held.
  ProxyAutoLock lock;

  resource_tracker().DidCreateInstance(pp_instance());

  plugin_dispatcher_ = std::make_unique<PluginDispatcher>(
      &MockGetInterface, PpapiPermissions(), false);
  plugin_dispatcher_->InitWithTestSink(&sink());
  // The plugin proxy delegate is needed for
  // |PluginProxyDelegate::GetBrowserSender| which is used
  // in |ResourceCreationProxy::GetConnection| to get the channel to the
  // browser. In this case we just use the |plugin_dispatcher_| as the channel
  // for test purposes.
  plugin_delegate_mock_.set_browser_sender(plugin_dispatcher_.get());
  PluginGlobals::Get()->SetPluginProxyDelegate(&plugin_delegate_mock_);
  plugin_dispatcher_->DidCreateInstance(pp_instance());
}

void PluginProxyTestHarness::SetUpHarnessWithChannel(
    const IPC::ChannelHandle& channel_handle,
    base::SingleThreadTaskRunner* ipc_task_runner,
    base::WaitableEvent* shutdown_event,
    bool is_client) {
  // These must be first since the dispatcher set-up uses them.
  CreatePluginGlobals(ipc_task_runner);
  // Some of the methods called during set-up check that the lock is held.
  ProxyAutoLock lock;

  resource_tracker().DidCreateInstance(pp_instance());
  plugin_delegate_mock_.Init(ipc_task_runner, shutdown_event);

  plugin_dispatcher_ = std::make_unique<PluginDispatcher>(
      &MockGetInterface, PpapiPermissions(), false);
  plugin_dispatcher_->InitPluginWithChannel(&plugin_delegate_mock_,
                                            base::kNullProcessId,
                                            channel_handle,
                                            is_client);
  plugin_delegate_mock_.set_browser_sender(plugin_dispatcher_.get());
  PluginGlobals::Get()->SetPluginProxyDelegate(&plugin_delegate_mock_);
  plugin_dispatcher_->DidCreateInstance(pp_instance());
}

void PluginProxyTestHarness::TearDownHarness() {
  {
    // Some of the methods called during tear-down check that the lock is held.
    ProxyAutoLock lock;

    plugin_dispatcher_->DidDestroyInstance(pp_instance());
    plugin_dispatcher_.reset();

    resource_tracker().DidDeleteInstance(pp_instance());
  }
  plugin_globals_.reset();
}

void PluginProxyTestHarness::CreatePluginGlobals(
    const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
  if (globals_config_ == PER_THREAD_GLOBALS) {
    plugin_globals_ = std::make_unique<PluginGlobals>(
        PpapiGlobals::PerThreadForTest(), ipc_task_runner);
    PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
  } else {
    plugin_globals_ = std::make_unique<PluginGlobals>(ipc_task_runner);
  }
}

base::SingleThreadTaskRunner*
PluginProxyTestHarness::PluginDelegateMock::GetIPCTaskRunner() {
  return ipc_task_runner_;
}

base::WaitableEvent*
PluginProxyTestHarness::PluginDelegateMock::GetShutdownEvent() {
  return shutdown_event_;
}

IPC::PlatformFileForTransit
PluginProxyTestHarness::PluginDelegateMock::ShareHandleWithRemote(
    base::PlatformFile handle,
    base::ProcessId /* remote_pid */,
    bool should_close_source) {
  return IPC::GetPlatformFileForTransit(handle,
                                        should_close_source);
}

base::UnsafeSharedMemoryRegion PluginProxyTestHarness::PluginDelegateMock::
    ShareUnsafeSharedMemoryRegionWithRemote(
        const base::UnsafeSharedMemoryRegion& region,
        base::ProcessId /* remote_pid */) {
  return region.Duplicate();
}

base::ReadOnlySharedMemoryRegion PluginProxyTestHarness::PluginDelegateMock::
    ShareReadOnlySharedMemoryRegionWithRemote(
        const base::ReadOnlySharedMemoryRegion& region,
        base::ProcessId /* remote_pid */) {
  return region.Duplicate();
}

std::set<PP_Instance>*
PluginProxyTestHarness::PluginDelegateMock::GetGloballySeenInstanceIDSet() {
  return &instance_id_set_;
}

uint32_t PluginProxyTestHarness::PluginDelegateMock::Register(
    PluginDispatcher* plugin_dispatcher) {
  return 0;
}

void PluginProxyTestHarness::PluginDelegateMock::Unregister(
    uint32_t plugin_dispatcher_id) {}

IPC::Sender* PluginProxyTestHarness::PluginDelegateMock::GetBrowserSender() {
  return browser_sender_;
}

std::string PluginProxyTestHarness::PluginDelegateMock::GetUILanguage() {
  return std::string("en-US");
}

void PluginProxyTestHarness::PluginDelegateMock::SetActiveURL(
    const std::string& url) {
}

PP_Resource PluginProxyTestHarness::PluginDelegateMock::CreateBrowserFont(
    Connection connection,
    PP_Instance instance,
    const PP_BrowserFont_Trusted_Description& desc,
    const Preferences& prefs) {
  return 0;
}

// PluginProxyTest -------------------------------------------------------------

PluginProxyTest::PluginProxyTest() : PluginProxyTestHarness(SINGLETON_GLOBALS) {
}

PluginProxyTest::~PluginProxyTest() {
}

void PluginProxyTest::SetUp() {
  SetUpHarness();
}

void PluginProxyTest::TearDown() {
  TearDownHarness();
}

// PluginProxyMultiThreadTest --------------------------------------------------

PluginProxyMultiThreadTest::PluginProxyMultiThreadTest() {
}

PluginProxyMultiThreadTest::~PluginProxyMultiThreadTest() {
}

void PluginProxyMultiThreadTest::RunTest() {
  main_thread_task_runner_ = PpapiGlobals::Get()->GetMainThreadMessageLoop();
  ASSERT_EQ(main_thread_task_runner_.get(),
            base::SingleThreadTaskRunner::GetCurrentDefault().get());
  nested_main_thread_message_loop_ = std::make_unique<base::RunLoop>();

  secondary_thread_ = std::make_unique<base::DelegateSimpleThread>(
      this, "PluginProxyMultiThreadTest");

  {
    ProxyAutoLock auto_lock;

    // MessageLoopResource assumes that the proxy lock has been acquired.
    secondary_thread_message_loop_ = new MessageLoopResource(pp_instance());

    ASSERT_EQ(PP_OK,
        secondary_thread_message_loop_->PostWork(
            PP_MakeCompletionCallback(
                &PluginProxyMultiThreadTest::InternalSetUpTestOnSecondaryThread,
                this),
            0));
  }

  SetUpTestOnMainThread();

  secondary_thread_->Start();
  nested_main_thread_message_loop_->Run();
  secondary_thread_->Join();

  {
    ProxyAutoLock auto_lock;

    // The destruction requires a valid PpapiGlobals instance, so we should
    // explicitly release it.
    secondary_thread_message_loop_.reset();
  }

  secondary_thread_.reset(NULL);
  nested_main_thread_message_loop_.reset(NULL);
  main_thread_task_runner_.reset();
}

void PluginProxyMultiThreadTest::CheckOnThread(ThreadType thread_type) {
  ProxyAutoLock auto_lock;
  if (thread_type == MAIN_THREAD) {
    ASSERT_TRUE(MessageLoopResource::GetCurrent()->is_main_thread_loop());
  } else {
    ASSERT_EQ(secondary_thread_message_loop_.get(),
              MessageLoopResource::GetCurrent());
  }
}

void PluginProxyMultiThreadTest::PostQuitForMainThread() {
  main_thread_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&PluginProxyMultiThreadTest::QuitNestedLoop,
                                base::Unretained(this)));
}

void PluginProxyMultiThreadTest::PostQuitForSecondaryThread() {
  ProxyAutoLock auto_lock;
  secondary_thread_message_loop_->PostQuit(PP_TRUE);
}

void PluginProxyMultiThreadTest::Run() {
  ProxyAutoLock auto_lock;
  ASSERT_EQ(PP_OK, secondary_thread_message_loop_->AttachToCurrentThread());
  ASSERT_EQ(PP_OK, secondary_thread_message_loop_->Run());
  secondary_thread_message_loop_->DetachFromThread();
}

void PluginProxyMultiThreadTest::QuitNestedLoop() {
  nested_main_thread_message_loop_->Quit();
}

// static
void PluginProxyMultiThreadTest::InternalSetUpTestOnSecondaryThread(
    void* user_data,
    int32_t result) {
  EXPECT_EQ(PP_OK, result);
  PluginProxyMultiThreadTest* thiz =
      static_cast<PluginProxyMultiThreadTest*>(user_data);
  thiz->CheckOnThread(SECONDARY_THREAD);
  thiz->SetUpTestOnSecondaryThread();
}

// HostProxyTestHarness --------------------------------------------------------

HostProxyTestHarness::HostProxyTestHarness(GlobalsConfiguration globals_config)
    : globals_config_(globals_config) {
}

HostProxyTestHarness::~HostProxyTestHarness() {
}

PpapiGlobals* HostProxyTestHarness::GetGlobals() {
  return host_globals_.get();
}

Dispatcher* HostProxyTestHarness::GetDispatcher() {
  return host_dispatcher_.get();
}

void HostProxyTestHarness::SetUpHarness() {
  // These must be first since the dispatcher set-up uses them.
  CreateHostGlobals();

  host_dispatcher_ = std::make_unique<HostDispatcher>(
      pp_module(), &MockGetInterface, PpapiPermissions::AllPermissions());
  host_dispatcher_->InitWithTestSink(&sink());
  HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get());
}

void HostProxyTestHarness::SetUpHarnessWithChannel(
    const IPC::ChannelHandle& channel_handle,
    base::SingleThreadTaskRunner* ipc_task_runner,
    base::WaitableEvent* shutdown_event,
    bool is_client) {
  // These must be first since the dispatcher set-up uses them.
  CreateHostGlobals();

  delegate_mock_.Init(ipc_task_runner, shutdown_event);

  host_dispatcher_ = std::make_unique<HostDispatcher>(
      pp_module(), &MockGetInterface, PpapiPermissions::AllPermissions());
  ppapi::Preferences preferences;
  host_dispatcher_->InitHostWithChannel(
      &delegate_mock_, base::kNullProcessId, channel_handle, is_client,
      preferences, base::SingleThreadTaskRunner::GetCurrentDefault());
  HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get());
}

void HostProxyTestHarness::TearDownHarness() {
  HostDispatcher::RemoveForInstance(pp_instance());
  host_dispatcher_.reset();
  host_globals_.reset();
}

void HostProxyTestHarness::CreateHostGlobals() {
  disable_locking_ = std::make_unique<ProxyLock::LockingDisablerForTest>();
  if (globals_config_ == PER_THREAD_GLOBALS) {
    host_globals_ =
        std::make_unique<TestGlobals>(PpapiGlobals::PerThreadForTest());
    PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
  } else {
    host_globals_ = std::make_unique<TestGlobals>();
  }
}

base::SingleThreadTaskRunner*
HostProxyTestHarness::DelegateMock::GetIPCTaskRunner() {
  return ipc_task_runner_;
}

base::WaitableEvent* HostProxyTestHarness::DelegateMock::GetShutdownEvent() {
  return shutdown_event_;
}

IPC::PlatformFileForTransit
HostProxyTestHarness::DelegateMock::ShareHandleWithRemote(
    base::PlatformFile handle,
    base::ProcessId /* remote_pid */,
    bool should_close_source) {
  return IPC::GetPlatformFileForTransit(handle,
                                        should_close_source);
}

base::UnsafeSharedMemoryRegion
HostProxyTestHarness::DelegateMock::ShareUnsafeSharedMemoryRegionWithRemote(
    const base::UnsafeSharedMemoryRegion& region,
    base::ProcessId /*remote_pid*/) {
  return region.Duplicate();
}

base::ReadOnlySharedMemoryRegion
HostProxyTestHarness::DelegateMock::ShareReadOnlySharedMemoryRegionWithRemote(
    const base::ReadOnlySharedMemoryRegion& region,
    base::ProcessId /*remote_pid*/) {
  return region.Duplicate();
}

// HostProxyTest ---------------------------------------------------------------

HostProxyTest::HostProxyTest() : HostProxyTestHarness(SINGLETON_GLOBALS) {
}

HostProxyTest::~HostProxyTest() {
}

void HostProxyTest::SetUp() {
  SetUpHarness();
}

void HostProxyTest::TearDown() {
  TearDownHarness();
}

// TwoWayTest ---------------------------------------------------------------

TwoWayTest::TwoWayTest(TwoWayTest::TwoWayTestMode test_mode)
    : test_mode_(test_mode),
      host_(ProxyTestHarnessBase::PER_THREAD_GLOBALS),
      plugin_(ProxyTestHarnessBase::PER_THREAD_GLOBALS),
      io_thread_("TwoWayTest_IOThread"),
      plugin_thread_("TwoWayTest_PluginThread"),
      remote_harness_(NULL),
      local_harness_(NULL),
      channel_created_(base::WaitableEvent::ResetPolicy::MANUAL,
                       base::WaitableEvent::InitialState::NOT_SIGNALED),
      shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL,
                      base::WaitableEvent::InitialState::NOT_SIGNALED) {
  if (test_mode == TEST_PPP_INTERFACE) {
    remote_harness_ = &plugin_;
    local_harness_ = &host_;
  } else {
    remote_harness_ = &host_;
    local_harness_ = &plugin_;
  }
}

TwoWayTest::~TwoWayTest() {
  shutdown_event_.Signal();
}

void TwoWayTest::SetUp() {
  base::Thread::Options options;
  options.message_pump_type = base::MessagePumpType::IO;
  io_thread_.StartWithOptions(std::move(options));
  plugin_thread_.Start();

  mojo::MessagePipe pipe;
  base::WaitableEvent remote_harness_set_up(
      base::WaitableEvent::ResetPolicy::MANUAL,
      base::WaitableEvent::InitialState::NOT_SIGNALED);
  plugin_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&SetUpRemoteHarness, remote_harness_,
                                pipe.handle0.release(),
                                base::RetainedRef(io_thread_.task_runner()),
                                &shutdown_event_, &remote_harness_set_up));
  remote_harness_set_up.Wait();
  local_harness_->SetUpHarnessWithChannel(
      pipe.handle1.release(), io_thread_.task_runner().get(), &shutdown_event_,
      true);  // is_client
}

void TwoWayTest::TearDown() {
  base::WaitableEvent remote_harness_torn_down(
      base::WaitableEvent::ResetPolicy::MANUAL,
      base::WaitableEvent::InitialState::NOT_SIGNALED);
  plugin_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&TearDownRemoteHarness, remote_harness_,
                                &remote_harness_torn_down));
  remote_harness_torn_down.Wait();

  local_harness_->TearDownHarness();

  io_thread_.Stop();
}

void TwoWayTest::PostTaskOnRemoteHarness(base::OnceClosure task) {
  base::WaitableEvent task_complete(
      base::WaitableEvent::ResetPolicy::MANUAL,
      base::WaitableEvent::InitialState::NOT_SIGNALED);
  plugin_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&RunTaskOnRemoteHarness, std::move(task), &task_complete));
  task_complete.Wait();
}

}  // namespace proxy
}  // namespace ppapi
