// 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 "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "ipc/ipc_message.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
#include "ppapi/host/resource_message_filter.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ppapi {
namespace host {
namespace {

base::WaitableEvent g_handler_completion(true, false);

enum TestMessageTypes {
  MSG1_TYPE = 1,
  MSG2_TYPE,
  MSG3_TYPE,
  REPLY_MSG1_TYPE,
  REPLY_MSG2_TYPE,
  REPLY_MSG3_TYPE,
};

// Dummy resource host which simply stores a copy of messages it handles.
// |SendReply| is overridden to store a copy of the outgoing message and the
// message loop on which it was sent.
class MyResourceHost : public ResourceHost {
 public:
  // Messages of type |msg_type| will be handled (simply by replying with a
  // message of type |reply_msg_type|).
  MyResourceHost(PpapiHost* host,
                 PP_Instance instance,
                 PP_Resource resource,
                 uint32 msg_type,
                 uint32 reply_msg_type)
      : ResourceHost(host, instance, resource),
        msg_type_(msg_type),
        reply_msg_type_(reply_msg_type),
        last_reply_message_loop_(NULL) {
  }

  const IPC::Message& last_handled_msg() const { return last_handled_msg_; }
  const IPC::Message& last_reply_msg() const { return last_reply_msg_; }
  base::MessageLoop* last_reply_message_loop() const {
    return last_reply_message_loop_;
  }

  void AddMessageFilter(scoped_refptr<ResourceMessageFilter> filter) {
    AddFilter(filter);
  }

  int32_t OnResourceMessageReceived(const IPC::Message& msg,
                                    HostMessageContext* context) override {
    last_handled_msg_ = msg;
    if (msg.type() == msg_type_) {
      context->reply_msg = IPC::Message(0, reply_msg_type_,
                                        IPC::Message::PRIORITY_NORMAL);
      return PP_OK;
    }
    return PP_ERROR_FAILED;
  }

  void SendReply(const ReplyMessageContext& context,
                 const IPC::Message& msg) override {
    last_reply_msg_ = msg;
    last_reply_message_loop_ = base::MessageLoop::current();
    g_handler_completion.Signal();
  }

 private:
  uint32 msg_type_;
  uint32 reply_msg_type_;

  IPC::Message last_handled_msg_;
  IPC::Message last_reply_msg_;
  base::MessageLoop* last_reply_message_loop_;
};

// Dummy message filter which simply stores a copy of messages it handles.
// The message loop on which the message is handled is also stored for checking
// later.
class MyResourceFilter : public ResourceMessageFilter {
 public:
  // Messages of type |msg_type| will be handled (simply by replying with a
  // message of type |reply_msg_type|). |io_thread| is the thread on which
  // replies should be sent. |bg_thread| is the thread on which the message
  // should be handled.
  MyResourceFilter(const base::Thread& io_thread,
                   const base::Thread& bg_thread,
                   uint32 msg_type,
                   uint32 reply_msg_type)
      : ResourceMessageFilter(io_thread.task_runner()),
        task_runner_(bg_thread.task_runner()),
        msg_type_(msg_type),
        reply_msg_type_(reply_msg_type),
        last_message_loop_(NULL) {}

  const IPC::Message& last_handled_msg() const { return last_handled_msg_; }
  base::MessageLoop* last_message_loop() const { return last_message_loop_; }

  scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
      const IPC::Message& msg) override {
    if (msg.type() == msg_type_)
      return task_runner_;
    return NULL;
  }

  int32_t OnResourceMessageReceived(
      const IPC::Message& msg,
      HostMessageContext* context) override {
    last_handled_msg_ = msg;
    last_message_loop_ = base::MessageLoop::current();
    if (msg.type() == msg_type_) {
      context->reply_msg = IPC::Message(0, reply_msg_type_,
                                        IPC::Message::PRIORITY_NORMAL);
      return PP_OK;
    }
    return PP_ERROR_FAILED;
  }

 private:
  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  uint32 msg_type_;
  uint32 reply_msg_type_;

  IPC::Message last_handled_msg_;
  base::MessageLoop* last_message_loop_;
};

}  // namespace

class ResourceMessageFilterTest : public testing::Test {
 public:
  void TestHandleMessageImpl() {
    base::Thread io_thread("test_io_thread");
    ASSERT_TRUE(io_thread.Start());

    base::Thread bg_thread1("test_background_thread1");
    ASSERT_TRUE(bg_thread1.Start());
    scoped_refptr<MyResourceFilter> filter1 =
        new MyResourceFilter(io_thread, bg_thread1, MSG1_TYPE, REPLY_MSG1_TYPE);

    base::Thread bg_thread2("test_background_thread2");
    ASSERT_TRUE(bg_thread2.Start());
    scoped_refptr<MyResourceFilter> filter2 =
        new MyResourceFilter(io_thread, bg_thread2, MSG2_TYPE, REPLY_MSG2_TYPE);

    PP_Instance instance = 12345;
    PP_Resource resource = 67890;
    MyResourceHost host(NULL, instance, resource, MSG3_TYPE, REPLY_MSG3_TYPE);
    host.AddMessageFilter(filter1);
    host.AddMessageFilter(filter2);

    proxy::ResourceMessageCallParams params(resource, 1);
    params.set_has_callback();
    HostMessageContext context(params);
    IPC::Message message1(0, MSG1_TYPE, IPC::Message::PRIORITY_NORMAL);
    IPC::Message message2(0, MSG2_TYPE, IPC::Message::PRIORITY_NORMAL);
    IPC::Message message3(0, MSG3_TYPE, IPC::Message::PRIORITY_NORMAL);

    // Message 1 handled by the first filter.
    host.HandleMessage(message1, &context);
    g_handler_completion.Wait();
    EXPECT_EQ(filter1->last_handled_msg().type(), message1.type());
    EXPECT_EQ(filter1->last_message_loop(), bg_thread1.message_loop());
    EXPECT_EQ(host.last_reply_msg().type(),
              static_cast<uint32>(REPLY_MSG1_TYPE));
    EXPECT_EQ(host.last_reply_message_loop(), io_thread.message_loop());
    g_handler_completion.Reset();

    // Message 2 handled by the second filter.
    host.HandleMessage(message2, &context);
    g_handler_completion.Wait();
    EXPECT_EQ(filter2->last_handled_msg().type(), message2.type());
    EXPECT_EQ(filter2->last_message_loop(), bg_thread2.message_loop());
    EXPECT_EQ(host.last_reply_msg().type(),
              static_cast<uint32>(REPLY_MSG2_TYPE));
    EXPECT_EQ(host.last_reply_message_loop(), io_thread.message_loop());
    g_handler_completion.Reset();

    // Message 3 handled by the resource host.
    host.HandleMessage(message3, &context);
    EXPECT_EQ(host.last_handled_msg().type(), message3.type());
    EXPECT_EQ(host.last_reply_msg().type(),
              static_cast<uint32>(REPLY_MSG3_TYPE));

    io_thread.Stop();
    bg_thread1.Stop();
    bg_thread2.Stop();
  }
};

// Test that messages are filtered correctly and handlers are run on the correct
// threads.
TEST_F(ResourceMessageFilterTest, TestHandleMessage) {
  // ResourceMessageFilter instances need to be created on a thread with message
  // loop. Therefore, we create a message loop and run the testing logic as a
  // task on it.
  base::MessageLoop main_message_loop;

  // It should be safe to use base::Unretained() because the object won't be
  // destroyed before the task is run.
  main_message_loop.task_runner()->PostTask(
      FROM_HERE, base::Bind(&ResourceMessageFilterTest::TestHandleMessageImpl,
                            base::Unretained(this)));

  base::RunLoop().RunUntilIdle();
}

}  // namespace proxy
}  // namespace ppapi
