// 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/proxy/message_handler.h"

#include <utility>

#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "ipc/ipc_message.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/ppb_message_loop_proxy.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/scoped_pp_var.h"
#include "ppapi/thunk/enter.h"

namespace ppapi {
namespace proxy {
namespace {

typedef void (*HandleMessageFunc)(PP_Instance, void*, const PP_Var*);
typedef void (*HandleBlockingMessageFunc)(
    PP_Instance, void*, const PP_Var*, PP_Var*);

void HandleMessageWrapper(HandleMessageFunc function,
                          PP_Instance instance,
                          void* user_data,
                          ScopedPPVar message_data) {
  CallWhileUnlocked(function, instance, user_data,
                    &message_data.get());
}

void HandleBlockingMessageWrapper(HandleBlockingMessageFunc function,
                                  PP_Instance instance,
                                  void* user_data,
                                  ScopedPPVar message_data,
                                  std::unique_ptr<IPC::Message> reply_msg) {
  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
  if (!dispatcher)
    return;
  PP_Var result = PP_MakeUndefined();
  MessageLoopResource::GetCurrent()->
      set_currently_handling_blocking_message(true);
  CallWhileUnlocked(
      function, instance, user_data, &message_data.get(), &result);
  MessageLoopResource::GetCurrent()->
      set_currently_handling_blocking_message(false);
  PpapiMsg_PPPMessageHandler_HandleBlockingMessage::WriteReplyParams(
      reply_msg.get(),
      SerializedVarReturnValue::Convert(dispatcher, result),
      true /* was_handled */);
  dispatcher->Send(reply_msg.release());
}

}  // namespace

// static
std::unique_ptr<MessageHandler> MessageHandler::Create(
    PP_Instance instance,
    const PPP_MessageHandler_0_2* handler_if,
    void* user_data,
    PP_Resource message_loop,
    int32_t* error) {
  std::unique_ptr<MessageHandler> result;
  // The interface and all function pointers must be valid.
  if (!handler_if ||
      !handler_if->HandleMessage ||
      !handler_if->HandleBlockingMessage ||
      !handler_if->Destroy) {
    *error = PP_ERROR_BADARGUMENT;
    return result;
  }
  thunk::EnterResourceNoLock<thunk::PPB_MessageLoop_API>
      enter_loop(message_loop, true);
  if (enter_loop.failed()) {
    *error = PP_ERROR_BADRESOURCE;
    return result;
  }
  scoped_refptr<MessageLoopResource> message_loop_resource(
      static_cast<MessageLoopResource*>(enter_loop.object()));
  if (message_loop_resource->is_main_thread_loop()) {
    *error = PP_ERROR_WRONG_THREAD;
    return result;
  }

  result.reset(new MessageHandler(
      instance, handler_if, user_data, message_loop_resource));
  *error = PP_OK;
  return result;
}

MessageHandler::~MessageHandler() {
  // It's possible the message_loop_proxy is NULL if that loop has been quit.
  // In that case, we unfortunately just can't call Destroy.
  if (message_loop_->task_runner().get()) {
    // The posted task won't have the proxy lock, but that's OK, it doesn't
    // touch any internal state; it's a direct call on the plugin's function.
    message_loop_->task_runner()->PostTask(
        FROM_HERE, base::Bind(handler_if_->Destroy, instance_, user_data_));
  }
}

bool MessageHandler::LoopIsValid() const {
  return !!message_loop_->task_runner().get();
}

void MessageHandler::HandleMessage(ScopedPPVar var) {
  message_loop_->task_runner()->PostTask(
      FROM_HERE, RunWhileLocked(base::Bind(&HandleMessageWrapper,
                                           handler_if_->HandleMessage,
                                           instance_, user_data_, var)));
}

void MessageHandler::HandleBlockingMessage(
    ScopedPPVar var,
    std::unique_ptr<IPC::Message> reply_msg) {
  message_loop_->task_runner()->PostTask(
      FROM_HERE,
      RunWhileLocked(base::Bind(
          &HandleBlockingMessageWrapper, handler_if_->HandleBlockingMessage,
          instance_, user_data_, var, base::Passed(std::move(reply_msg)))));
}

MessageHandler::MessageHandler(
    PP_Instance instance,
    const PPP_MessageHandler_0_2* handler_if,
    void* user_data,
    scoped_refptr<MessageLoopResource> message_loop)
    : instance_(instance),
      handler_if_(handler_if),
      user_data_(user_data),
      message_loop_(message_loop) {
}

}  // namespace proxy
}  // namespace ppapi
