// Copyright (c) 2012 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 "ppapi/proxy/ppapi_proxy_test.h"

#include <tuple>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/observer_list.h"
#include "base/process/process_handle.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.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(const base::Closure& task,
                            base::WaitableEvent* task_complete) {
 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_.reset(new 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_.reset(new 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::TaskRunner>& ipc_task_runner) {
  if (globals_config_ == PER_THREAD_GLOBALS) {
    plugin_globals_.reset(new PluginGlobals(PpapiGlobals::PerThreadForTest(),
                                            ipc_task_runner));
    PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
  } else {
    plugin_globals_.reset(new 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::SharedMemoryHandle
PluginProxyTestHarness::PluginDelegateMock::ShareSharedMemoryHandleWithRemote(
    const base::SharedMemoryHandle& handle,
    base::ProcessId /* remote_pid */) {
  return base::SharedMemory::DuplicateHandle(handle);
}

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::PreCacheFontForFlash(
    const void* logfontw) {
}

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::ThreadTaskRunnerHandle::Get().get());
  nested_main_thread_message_loop_.reset(new base::RunLoop());

  secondary_thread_.reset(new 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_ = NULL;
  }

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

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::Bind(&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_.reset(new 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_.reset(new HostDispatcher(
      pp_module(),
      &MockGetInterface,
      PpapiPermissions::AllPermissions()));
  ppapi::Preferences preferences;
  host_dispatcher_->InitHostWithChannel(&delegate_mock_,
                                        base::kNullProcessId, channel_handle,
                                        is_client, preferences);
  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_.reset(new ProxyLock::LockingDisablerForTest);
  if (globals_config_ == PER_THREAD_GLOBALS) {
    host_globals_.reset(new TestGlobals(PpapiGlobals::PerThreadForTest()));
    PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals());
  } else {
    host_globals_.reset(new 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::SharedMemoryHandle
HostProxyTestHarness::DelegateMock::ShareSharedMemoryHandleWithRemote(
    const base::SharedMemoryHandle& handle,
    base::ProcessId /*remote_pid*/) {
  return base::SharedMemory::DuplicateHandle(handle);
}

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_loop_type = base::MessageLoop::TYPE_IO;
  io_thread_.StartWithOptions(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::Bind(&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::Bind(&TearDownRemoteHarness, remote_harness_,
                            &remote_harness_torn_down));
  remote_harness_torn_down.Wait();

  local_harness_->TearDownHarness();

  io_thread_.Stop();
}

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


}  // namespace proxy
}  // namespace ppapi
