// Copyright (c) 2011 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 "base/message_loop_proxy.h"
#include "base/observer_list.h"
#include "ipc/ipc_sync_channel.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_proxy_private.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/ppapi_preferences.cc"

namespace pp {
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.
}

int32_t GetURLLoaderBufferedBytes(PP_Resource url_loader) {
  NOTREACHED();
  return 0;
}

void AddRefModule(PP_Module module) {}
void ReleaseModule(PP_Module module) {}

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

// 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.
ObserverList<ProxyTestHarnessBase> get_interface_handlers_;

const void* MockGetInterface(const char* name) {
  ObserverList<ProxyTestHarnessBase>::Iterator it =
      get_interface_handlers_;
  while (ProxyTestHarnessBase* observer = it.GetNext()) {
    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::MessageLoopProxy* ipc_message_loop_proxy,
                        base::WaitableEvent* shutdown_event,
                        base::WaitableEvent* harness_set_up) {
  harness->SetUpHarnessWithChannel(handle, ipc_message_loop_proxy,
                                   shutdown_event, false);
  harness_set_up->Signal();
}

void TearDownRemoteHarness(ProxyTestHarnessBase* harness,
                           base::WaitableEvent* harness_torn_down) {
  harness->TearDownHarness();
  harness_torn_down->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* interface) {
  registered_interfaces_[name] = 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;

  TupleTypes<PpapiMsg_SupportsInterface::ReplyParam>::ValueTuple reply_data;
  EXPECT_TRUE(PpapiMsg_SupportsInterface::ReadReplyParam(
      reply_msg, &reply_data));

  sink().ClearMessages();
  return reply_data.a;
}

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

PluginProxyTestHarness::PluginProxyTestHarness() {
}

PluginProxyTestHarness::~PluginProxyTestHarness() {
}

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

void PluginProxyTestHarness::SetUpHarness() {
  // These must be first since the dispatcher set-up uses them.
  PluginResourceTracker::SetInstanceForTest(&resource_tracker_);
  PluginVarTracker::SetInstanceForTest(&var_tracker_);

  plugin_dispatcher_.reset(new PluginDispatcher(
      base::Process::Current().handle(),
      &MockGetInterface));
  plugin_dispatcher_->InitWithTestSink(&sink());
  plugin_dispatcher_->DidCreateInstance(pp_instance());
}

void PluginProxyTestHarness::SetUpHarnessWithChannel(
    const IPC::ChannelHandle& channel_handle,
    base::MessageLoopProxy* ipc_message_loop,
    base::WaitableEvent* shutdown_event,
    bool is_client) {
  // These must be first since the dispatcher set-up uses them.
  PluginResourceTracker::SetInstanceForTest(&resource_tracker_);
  PluginVarTracker::SetInstanceForTest(&var_tracker_);
  plugin_delegate_mock_.Init(ipc_message_loop, shutdown_event);

  plugin_dispatcher_.reset(new PluginDispatcher(
      base::Process::Current().handle(),
      &MockGetInterface));
  plugin_dispatcher_->InitPluginWithChannel(&plugin_delegate_mock_,
                                            channel_handle,
                                            is_client);
  plugin_dispatcher_->DidCreateInstance(pp_instance());
}

void PluginProxyTestHarness::TearDownHarness() {
  plugin_dispatcher_->DidDestroyInstance(pp_instance());
  plugin_dispatcher_.reset();

  PluginVarTracker::SetInstanceForTest(NULL);
  PluginResourceTracker::SetInstanceForTest(NULL);
}

base::MessageLoopProxy*
PluginProxyTestHarness::PluginDelegateMock::GetIPCMessageLoop() {
  return ipc_message_loop_;
}

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

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

ppapi::WebKitForwarding*
PluginProxyTestHarness::PluginDelegateMock::GetWebKitForwarding() {
  NOTREACHED();
  return NULL;
}

void PluginProxyTestHarness::PluginDelegateMock::PostToWebKitThread(
    const tracked_objects::Location& from_here, const base::Closure& task) {
  NOTREACHED();
}

bool PluginProxyTestHarness::PluginDelegateMock::SendToBrowser(
    IPC::Message* msg) {
  NOTREACHED();
  return false;
}

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

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

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

PluginProxyTest::PluginProxyTest() {
}

PluginProxyTest::~PluginProxyTest() {
}

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

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

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

HostProxyTestHarness::HostProxyTestHarness() {
}

HostProxyTestHarness::~HostProxyTestHarness() {
}

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

void HostProxyTestHarness::SetUpHarness() {
  host_dispatcher_.reset(new HostDispatcher(
      base::Process::Current().handle(),
      pp_module(),
      &MockGetInterface));
  host_dispatcher_->InitWithTestSink(&sink());
  HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get());
}

void HostProxyTestHarness::SetUpHarnessWithChannel(
    const IPC::ChannelHandle& channel_handle,
    base::MessageLoopProxy* ipc_message_loop,
    base::WaitableEvent* shutdown_event,
    bool is_client) {
  delegate_mock_.Init(ipc_message_loop, shutdown_event);
  host_dispatcher_.reset(new HostDispatcher(
      base::Process::Current().handle(),
      pp_module(),
      &MockGetInterface));
  ppapi::Preferences preferences;
  host_dispatcher_->InitHostWithChannel(&delegate_mock_, channel_handle,
                                        is_client, preferences);
  HostDispatcher::SetForInstance(pp_instance(), host_dispatcher_.get());
}

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

base::MessageLoopProxy*
HostProxyTestHarness::DelegateMock::GetIPCMessageLoop() {
  return ipc_message_loop_;
}

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


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

HostProxyTest::HostProxyTest() {
}

HostProxyTest::~HostProxyTest() {
}

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

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

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

TwoWayTest::TwoWayTest(TwoWayTest::TwoWayTestMode test_mode)
    : test_mode_(test_mode),
      io_thread_("TwoWayTest_IOThread"),
      plugin_thread_("TwoWayTest_PluginThread"),
      remote_harness_(NULL),
      local_harness_(NULL),
      channel_created_(true, false),
      shutdown_event_(true, false) {
  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 = MessageLoop::TYPE_IO;
  io_thread_.StartWithOptions(options);
  plugin_thread_.Start();

  IPC::ChannelHandle handle;
  handle.name = "TwoWayTestChannel";

  base::WaitableEvent remote_harness_set_up(true, false);
  plugin_thread_.message_loop_proxy()->PostTask(
      FROM_HERE,
      NewRunnableFunction(&SetUpRemoteHarness,
                          remote_harness_,
                          handle,
                          io_thread_.message_loop_proxy(),
                          &shutdown_event_,
                          &remote_harness_set_up));
  remote_harness_set_up.Wait();
  local_harness_->SetUpHarnessWithChannel(handle,
                                          io_thread_.message_loop_proxy(),
                                          &shutdown_event_,
                                          true);  // is_client
}

void TwoWayTest::TearDown() {
  base::WaitableEvent remote_harness_torn_down(true, false);
  plugin_thread_.message_loop_proxy()->PostTask(
      FROM_HERE,
      NewRunnableFunction(&TearDownRemoteHarness,
                          remote_harness_,
                          &remote_harness_torn_down));
  remote_harness_torn_down.Wait();

  local_harness_->TearDownHarness();

  io_thread_.Stop();
}


}  // namespace proxy
}  // namespace pp
