// 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 "ppapi/tests/test_message_handler.h"

#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <algorithm>
#include <map>
#include <sstream>

#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppb_file_io.h"
#include "ppapi/c/ppb_messaging.h"
#include "ppapi/c/ppp_message_handler.h"
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/file_io.h"
#include "ppapi/cpp/file_ref.h"
#include "ppapi/cpp/file_system.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/message_handler.h"
#include "ppapi/cpp/module_impl.h"
#include "ppapi/cpp/network_list.h"
#include "ppapi/cpp/network_monitor.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/var_array.h"
#include "ppapi/cpp/var_array_buffer.h"
#include "ppapi/cpp/var_dictionary.h"
#include "ppapi/tests/pp_thread.h"
#include "ppapi/tests/test_utils.h"
#include "ppapi/tests/testing_instance.h"

// Windows defines 'PostMessage', so we have to undef it.
#ifdef PostMessage
#undef PostMessage
#endif

REGISTER_TEST_CASE(MessageHandler);

namespace {

// Created and destroyed on the main thread. All public methods should be called
// on the main thread. Most data members are only accessed on the main thread.
// (Though it handles messages on the background thread).
class MyMessageHandler : public pp::MessageHandler {
 public:
  explicit MyMessageHandler(TestingInstance* instance,
                            const pp::MessageLoop& loop)
      : testing_instance_(instance),
        message_handler_loop_(loop),
        is_registered_(false),
        test_finished_event_(instance->pp_instance()),
        destroy_event_(instance->pp_instance()),
        async_message_received_(instance->pp_instance()) {
    AssertOnMainThread();
  }
  void Register() {
    AssertOnMainThread();
    assert(!is_registered_);
    int32_t result =
        testing_instance_->RegisterMessageHandler(this, message_handler_loop_);
    if (result == PP_OK) {
      is_registered_ = true;
    } else {
      std::ostringstream stream;
      stream << "Failed to register message handler; got error " << result;
      AddError(stream.str());
      test_finished_event_.Signal();
    }
    // Note, at this point, we can't safely read or write errors_ until we wait
    // on destroy_event_.
  }
  void Unregister() {
    AssertOnMainThread();
    assert(is_registered_);
    testing_instance_->UnregisterMessageHandler();
    is_registered_ = false;
  }
  void WaitForTestFinishedMessage() {
    test_finished_event_.Wait();
    test_finished_event_.Reset();
  }
  // Wait for Destroy() to be called on the MessageHandler thread. When it's
  // done, return any errors that occurred during the time the MessageHandler
  // was getting messages.
  std::string WaitForDestroy() {
    AssertOnMainThread();
    // If we haven't called Unregister, we'll be waiting forever.
    assert(!is_registered_);
    destroy_event_.Wait();
    destroy_event_.Reset();
    // Now that we know Destroy() has been called, we know errors_ isn't being
    // written on the MessageHandler thread anymore. So we can safely read it
    // here on the main thread (since destroy_event_ gave us a memory barrier).
    std::string temp_errors;
    errors_.swap(temp_errors);
    return temp_errors;
  }
  pp::Var WaitForAsyncMessage() {
    async_message_received_.Wait();
    pp::Var var_to_return = last_async_message_received_;
    last_async_message_received_ = pp::Var();
    async_message_received_.Reset();
    return var_to_return;
  }
 private:
  static void AssertOnMainThread() {
    assert(pp::MessageLoop::GetForMainThread() ==
           pp::MessageLoop::GetCurrent());
  }
  void AddError(const std::string& error) {
    if (!error.empty()) {
      if (!errors_.empty())
        errors_ += "<p>";
      errors_ += error;
    }
  }
  virtual void HandleMessage(pp::InstanceHandle instance, const pp::Var& var) {
    if (pp::MessageLoop::GetCurrent() != message_handler_loop_)
      AddError("HandleMessage was called on the wrong thread!");
    if (instance.pp_instance() != testing_instance_->pp_instance())
      AddError("HandleMessage was passed the wrong instance!");
    if (var.is_string() && var.AsString() == "FINISHED_TEST") {
      test_finished_event_.Signal();
    } else {
      // Any client causing a message to arrive must wait for the message
      // before continuing. See WaitForAsyncMessage().
      assert(last_async_message_received_.is_undefined());
      last_async_message_received_ = var;
      async_message_received_.Signal();
    }
  }

  virtual pp::Var HandleBlockingMessage(pp::InstanceHandle instance,
                                        const pp::Var& var) {
    if (pp::MessageLoop::GetCurrent() != message_handler_loop_)
      AddError("HandleBlockingMessage was called on the wrong thread!");
    if (instance.pp_instance() != testing_instance_->pp_instance())
      AddError("HandleBlockingMessage was passed the wrong instance!");

    // Attempt a blocking operation; make sure it's disallowed.
    pp::NetworkMonitor monitor(instance);
    PP_Resource out_param = 0;
    pp::CompletionCallbackWithOutput<pp::NetworkList> blocking_callback(
        &out_param);
    int32_t error = monitor.UpdateNetworkList(blocking_callback);
    if (error != PP_ERROR_WOULD_BLOCK_THREAD) {
      AddError("HandleBlockingMessage was allowed to do a blocking call!");
      pp::Module::Get()->core()->ReleaseResource(out_param);
    }

    return var;
  }

  virtual void WasUnregistered(pp::InstanceHandle instance) {
    if (pp::MessageLoop::GetCurrent() != message_handler_loop_)
      AddError("Destroy was called on the wrong thread!");
    if (instance.pp_instance() != testing_instance_->pp_instance())
      AddError("Destroy was passed the wrong instance!");
    destroy_event_.Signal();
  }

  // These data members are initialized on the main thread, but don't change for
  // the life of the object, so are safe to access on the background thread,
  // because there will be a memory barrier before the the MessageHandler calls
  // are invoked.
  TestingInstance* const testing_instance_;
  const pp::MessageLoop message_handler_loop_;
  const pp::MessageLoop main_loop_;

  // is_registered_ is only read/written on the main thread.
  bool is_registered_;

  // errors_ is written on the MessageHandler thread. When Destroy() is
  // called, we stop writing to errors_ and signal destroy_event_. This causes
  // a memory barrier, so it's safe to read errors_ after that.
  std::string errors_;
  NestedEvent test_finished_event_;
  NestedEvent destroy_event_;

  pp::Var last_async_message_received_;
  NestedEvent async_message_received_;

  // Undefined & private to disallow copy and assign.
  MyMessageHandler(const MyMessageHandler&);
  MyMessageHandler& operator=(const MyMessageHandler&);
};

void FakeHandleMessage(PP_Instance instance,
                       void* user_data,
                       const PP_Var* message_data) {}
void FakeHandleBlockingMessage(PP_Instance instance,
                               void* user_data,
                               const PP_Var* message_data,
                               PP_Var* result) {}
void FakeDestroy(PP_Instance instance, void* user_data) {}

}  // namespace

TestMessageHandler::TestMessageHandler(TestingInstance* instance)
    : TestCase(instance),
      message_received_(instance->pp_instance()),
      ppb_messaging_if_(NULL),
      handler_thread_(instance) {
}

TestMessageHandler::~TestMessageHandler() {
  handler_thread_.Join();
}

bool TestMessageHandler::Init() {
  ppb_messaging_if_ = static_cast<const PPB_Messaging_1_2*>(
      pp::Module::Get()->GetBrowserInterface(PPB_MESSAGING_INTERFACE_1_2));
  return ppb_messaging_if_ &&
         CheckTestingInterface() &&
         handler_thread_.Start();
}

void TestMessageHandler::RunTests(const std::string& filter) {
  RUN_TEST(RegisterErrorConditions, filter);
  RUN_TEST(PostMessageAndAwaitResponse, filter);
  RUN_TEST(ArrayBuffer, filter);
  RUN_TEST(Exceptions, filter);
}

void TestMessageHandler::HandleMessage(const pp::Var& message_data) {
  if (instance()->current_test_name() == "Exceptions") {
    // For TestPostMessageAndAwaitResponse(), all messages should go to the
    // background thread message handler.
    assert(false);
  } else {
    // Any subtest causing a message to arrive here must wait for it before
    // continuing. See WaitForMessage().
    assert(last_message_.is_undefined());
    last_message_ = message_data;
    message_received_.Signal();
  }
}

std::string TestMessageHandler::TestRegisterErrorConditions() {
  {
    // Test registering with the main thread as the message loop.
    PPP_MessageHandler_0_2 fake_ppp_message_handler = {
      &FakeHandleMessage, &FakeHandleBlockingMessage, &FakeDestroy
    };
    pp::MessageLoop main_loop = pp::MessageLoop::GetForMainThread();
    int32_t result = ppb_messaging_if_->RegisterMessageHandler(
        instance()->pp_instance(),
        reinterpret_cast<void*>(0xdeadbeef),
        &fake_ppp_message_handler,
        main_loop.pp_resource());
    ASSERT_EQ(PP_ERROR_WRONG_THREAD, result);
  }
  {
    // Test registering with incomplete PPP_Messaging interface.
    PPP_MessageHandler_0_2 bad_ppp_ifs[] = {
        { NULL, &FakeHandleBlockingMessage, &FakeDestroy },
        { &FakeHandleMessage, NULL, &FakeDestroy },
        { &FakeHandleMessage, &FakeHandleBlockingMessage, NULL }};
    for (size_t i = 0; i < sizeof(bad_ppp_ifs)/sizeof(bad_ppp_ifs[0]); ++i) {
      int32_t result = ppb_messaging_if_->RegisterMessageHandler(
          instance()->pp_instance(),
          reinterpret_cast<void*>(0xdeadbeef),
          &bad_ppp_ifs[i],
          handler_thread_.message_loop().pp_resource());
      ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
    }
  }
  PASS();
}

std::string TestMessageHandler::TestPostMessageAndAwaitResponse() {
  MyMessageHandler handler(instance(),
                           handler_thread_.message_loop());
  handler.Register();
  std::string js_code("var plugin = document.getElementById('plugin');\n");
  js_code += "var result = undefined;\n";
  const char* const values_to_test[] = {
      "5",
      "undefined",
      "1.5",
      "'hello'",
      "{'key': 'value', 'array_key': [1, 2, 3, 4, 5]}",
      NULL
  };
  for (size_t i = 0; values_to_test[i]; ++i) {
    js_code += "result = plugin.postMessageAndAwaitResponse(";
    js_code +=     values_to_test[i];
    js_code += ");\n";
    js_code += "if (!deepCompare(result, ";
    js_code +=     values_to_test[i];
    js_code += "))\n";
    js_code += "  InternalError(\" Failed postMessageAndAwaitResponse for: ";
    js_code +=      values_to_test[i];
    js_code +=    " result: \" + result);\n";
  }
  instance_->EvalScript(js_code);
  instance_->EvalScript("plugin.postMessage('FINISHED_TEST');\n");
  handler.WaitForTestFinishedMessage();
  handler.Unregister();
  ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy());

  PASS();
}

std::string TestMessageHandler::TestArrayBuffer() {
  // Set the array buffer shared memory threshold so that some of the
  // ArrayBuffer values will be sent as shared memory.
  ScopedArrayBufferSizeSetter setter(testing_interface_,
                                     instance_->pp_instance(),
                                     200);
  const char* const sizes[] = { "0", "128", "1024", "4096", NULL };
  MyMessageHandler handler(instance(),
                           handler_thread_.message_loop());
  handler.Register();
  std::string js_code("var plugin = document.getElementById('plugin');\n");
  js_code += "var result = undefined;\n";
  js_code += "var param = undefined;\n";
  for (size_t i = 0; sizes[i]; ++i) {
    js_code += "param = new ArrayBuffer(";
    js_code += sizes[i];
    js_code += ");";
    // TODO(dmichael): It would be better to set specific values in param.
    js_code += "result = plugin.postMessageAndAwaitResponse(param);";
    js_code += "if (!deepCompare(result, param))\n";
    js_code += "  InternalError(\" Failed postMessageAndAwaitResponse for ";
    js_code += "ArrayBuffer of size: ";
    js_code +=     sizes[i];
    js_code += " result: \" + result);\n";
  }
  instance_->EvalScript(js_code);
  instance_->EvalScript("plugin.postMessage('FINISHED_TEST');\n");
  handler.WaitForTestFinishedMessage();
  handler.Unregister();
  ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy());

  PASS();
}

std::string TestMessageHandler::TestExceptions() {
  MyMessageHandler handler(instance(),
                           handler_thread_.message_loop());
  {
    // First, try sending a blocking message when there is no handler
    // registered. It should throw an exception.
    std::string js_code(
        "var plugin = document.getElementById('plugin');\n"
        "var caught_exception = false;\n"
        "try {\n"
        "  plugin.postMessageAndAwaitResponse('Hello!');\n"
        "} catch (err) {\n"
        "  caught_exception = true;\n"
        "}\n"
        "plugin.postMessage(caught_exception ? 'SUCCESS' : 'FAIL');\n");
    instance_->EvalScript(js_code);
    // Note that we want to wait for the Instance to get the SUCCESS/FAIL
    // message here. |message_handler| is not yet registered, so the message
    // goes to the instance instead.
    pp::Var msg = WaitForMessage();
    ASSERT_TRUE(msg.is_string());
    ASSERT_EQ("SUCCESS", msg.AsString());
  }
  handler.Register();
  {
    // Now that a handler is registered, try requesting and sending a
    // FileSystem. It should throw an exception. The file system is opened
    // asynchronously. What *should* happen is that it opens successfully, then
    // we try to send it via postMessageAndAwaitResponse, which fails with an
    // exception. The test could fail either because the filesystem doesn't
    // open or because postMessageAndAwaitResponse doesn't throw an exception.
    std::string js_code(
        "var plugin = document.getElementById('plugin');\n"
        "function gotFileSystem(fs) {\n"
        "  var caught_exception = false;\n"
        "  try {\n"
        "    plugin.postMessageAndAwaitResponse(fs);\n"
        "  } catch (err) {\n"
        "    caught_exception = true;\n"
        "  }\n"
        "  plugin.postMessage(caught_exception ? 'SUCCESS' : 'FAIL');\n"
        "}\n"
        "function fileSystemError() {\n"
        "  plugin.postMessage('Failed to open filesystem');\n"
        "}\n"
        "window.webkitRequestFileSystem(\n"
        "    window.Temporary, 1024, gotFileSystem, fileSystemError)\n");
    instance_->EvalScript(js_code);
    pp::Var msg = handler.WaitForAsyncMessage();
    ASSERT_EQ(PP_VARTYPE_STRING, msg.pp_var().type);
    ASSERT_EQ("SUCCESS", msg.AsString());
  }
  handler.Unregister();
  ASSERT_SUBTEST_SUCCESS(handler.WaitForDestroy());

  PASS();
}

pp::Var TestMessageHandler::WaitForMessage() {
  message_received_.Wait();
  pp::Var var_to_return = last_message_;
  last_message_ = pp::Var();
  message_received_.Reset();
  return var_to_return;
}

