// 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/bind.h"
#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::BindOnce(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
