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

#include "ppapi/c/dev/ppb_var_deprecated.h"
#include "ppapi/c/dev/ppp_class_deprecated.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/proxy/dispatcher.h"
#include "ppapi/proxy/plugin_globals.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/serialized_var.h"
#include "ppapi/shared_impl/api_id.h"
#include "ppapi/shared_impl/proxy_lock.h"

namespace ppapi {
namespace proxy {

namespace {

// PPP_Class in the browser implementation -------------------------------------

// Represents a plugin-implemented class in the browser process. This just
// stores the data necessary to call back the plugin.
struct ObjectProxy {
  ObjectProxy(Dispatcher* d, int64_t p, int64_t ud)
      : dispatcher(d), ppp_class(p), user_data(ud) {}

  Dispatcher* dispatcher;
  int64_t ppp_class;
  int64_t user_data;
};

ObjectProxy* ToObjectProxy(void* data) {
  ObjectProxy* obj = reinterpret_cast<ObjectProxy*>(data);
  if (!obj || !obj->dispatcher)
    return NULL;
  if (!obj->dispatcher->permissions().HasPermission(PERMISSION_DEV))
    return NULL;
  return obj;
}

bool HasProperty(void* object, PP_Var name, PP_Var* exception) {
  ObjectProxy* obj = ToObjectProxy(object);
  if (!obj)
    return false;

  bool result = false;
  ReceiveSerializedException se(obj->dispatcher, exception);
  obj->dispatcher->Send(new PpapiMsg_PPPClass_HasProperty(
      API_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
      SerializedVarSendInput(obj->dispatcher, name), &se, &result));
  return result;
}

bool HasMethod(void* object, PP_Var name, PP_Var* exception) {
  ObjectProxy* obj = ToObjectProxy(object);
  if (!obj)
    return false;

  bool result = false;
  ReceiveSerializedException se(obj->dispatcher, exception);
  obj->dispatcher->Send(new PpapiMsg_PPPClass_HasMethod(
      API_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
      SerializedVarSendInput(obj->dispatcher, name), &se, &result));
  return result;
}

PP_Var GetProperty(void* object,
                   PP_Var name,
                   PP_Var* exception) {
  ObjectProxy* obj = ToObjectProxy(object);
  if (!obj)
    return PP_MakeUndefined();

  ReceiveSerializedException se(obj->dispatcher, exception);
  ReceiveSerializedVarReturnValue result;
  obj->dispatcher->Send(new PpapiMsg_PPPClass_GetProperty(
      API_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
      SerializedVarSendInput(obj->dispatcher, name), &se, &result));
  return result.Return(obj->dispatcher);
}

void GetAllPropertyNames(void* object,
                         uint32_t* property_count,
                         PP_Var** properties,
                         PP_Var* exception) {
  NOTIMPLEMENTED();
  // TODO(brettw) implement this.
}

void SetProperty(void* object,
                 PP_Var name,
                 PP_Var value,
                 PP_Var* exception) {
  ObjectProxy* obj = ToObjectProxy(object);
  if (!obj)
    return;

  ReceiveSerializedException se(obj->dispatcher, exception);
  obj->dispatcher->Send(new PpapiMsg_PPPClass_SetProperty(
      API_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
      SerializedVarSendInput(obj->dispatcher, name),
      SerializedVarSendInput(obj->dispatcher, value), &se));
}

void RemoveProperty(void* object,
                    PP_Var name,
                    PP_Var* exception) {
  ObjectProxy* obj = ToObjectProxy(object);
  if (!obj)
    return;

  ReceiveSerializedException se(obj->dispatcher, exception);
  obj->dispatcher->Send(new PpapiMsg_PPPClass_RemoveProperty(
      API_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
      SerializedVarSendInput(obj->dispatcher, name), &se));
}

PP_Var Call(void* object,
            PP_Var method_name,
            uint32_t argc,
            PP_Var* argv,
            PP_Var* exception) {
  ObjectProxy* obj = ToObjectProxy(object);
  if (!obj)
    return PP_MakeUndefined();

  ReceiveSerializedVarReturnValue result;
  ReceiveSerializedException se(obj->dispatcher, exception);
  std::vector<SerializedVar> argv_vect;
  SerializedVarSendInput::ConvertVector(obj->dispatcher, argv, argc,
                                        &argv_vect);

  obj->dispatcher->Send(new PpapiMsg_PPPClass_Call(
      API_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
      SerializedVarSendInput(obj->dispatcher, method_name), argv_vect,
      &se, &result));
  return result.Return(obj->dispatcher);
}

PP_Var Construct(void* object,
                 uint32_t argc,
                 PP_Var* argv,
                 PP_Var* exception) {
  ObjectProxy* obj = ToObjectProxy(object);
  if (!obj)
    return PP_MakeUndefined();

  ReceiveSerializedVarReturnValue result;
  ReceiveSerializedException se(obj->dispatcher, exception);
  std::vector<SerializedVar> argv_vect;
  SerializedVarSendInput::ConvertVector(obj->dispatcher, argv, argc,
                                        &argv_vect);

  obj->dispatcher->Send(new PpapiMsg_PPPClass_Construct(
      API_ID_PPP_CLASS,
      obj->ppp_class, obj->user_data, argv_vect, &se, &result));
  return result.Return(obj->dispatcher);
}

void Deallocate(void* object) {
  ObjectProxy* obj = ToObjectProxy(object);
  if (!obj)
    return;

  obj->dispatcher->Send(new PpapiMsg_PPPClass_Deallocate(
      API_ID_PPP_CLASS, obj->ppp_class, obj->user_data));
  delete obj;
}

const PPP_Class_Deprecated class_interface = {
  &HasProperty,
  &HasMethod,
  &GetProperty,
  &GetAllPropertyNames,
  &SetProperty,
  &RemoveProperty,
  &Call,
  &Construct,
  &Deallocate
};

// Plugin helper functions -----------------------------------------------------

// Converts an int64_t object from IPC to a PPP_Class* for calling into the
// plugin's implementation.
const PPP_Class_Deprecated* ToPPPClass(int64_t value) {
  return reinterpret_cast<const PPP_Class_Deprecated*>(
      static_cast<intptr_t>(value));
}

// Converts an int64_t object from IPC to a void* for calling into the plugin's
// implementation as the user data.
void* ToUserData(int64_t value) {
  return reinterpret_cast<void*>(static_cast<intptr_t>(value));
}

}  // namespace

// PPP_Class_Proxy -------------------------------------------------------------

PPP_Class_Proxy::PPP_Class_Proxy(Dispatcher* dispatcher)
    : InterfaceProxy(dispatcher) {
}

PPP_Class_Proxy::~PPP_Class_Proxy() {
}

// static
InterfaceProxy* PPP_Class_Proxy::Create(Dispatcher* dispatcher) {
  return new PPP_Class_Proxy(dispatcher);
}

// static
PP_Var PPP_Class_Proxy::CreateProxiedObject(const PPB_Var_Deprecated* var,
                                            Dispatcher* dispatcher,
                                            PP_Instance instance_id,
                                            int64_t ppp_class,
                                            int64_t class_data) {
  ObjectProxy* object_proxy = new ObjectProxy(dispatcher,
                                              ppp_class, class_data);
  return var->CreateObject(instance_id, &class_interface, object_proxy);
}

// static
PP_Bool PPP_Class_Proxy::IsInstanceOf(const PPB_Var_Deprecated* ppb_var_impl,
                                      const PP_Var& var,
                                      int64_t ppp_class,
                                      int64_t* ppp_class_data) {
  void* proxied_object = NULL;
  if (ppb_var_impl->IsInstanceOf(var,
                                 &class_interface,
                                 &proxied_object)) {
    if (static_cast<ObjectProxy*>(proxied_object)->ppp_class == ppp_class) {
      DCHECK(ppp_class_data);
      *ppp_class_data = static_cast<ObjectProxy*>(proxied_object)->user_data;
      return PP_TRUE;
    }
  }
  return PP_FALSE;
}

bool PPP_Class_Proxy::OnMessageReceived(const IPC::Message& msg) {
  if (!dispatcher()->IsPlugin())
    return false;  // These messages are only valid from host->plugin.

  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(PPP_Class_Proxy, msg)
    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_HasProperty,
                        OnMsgHasProperty)
    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_HasMethod,
                        OnMsgHasMethod)
    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_GetProperty,
                        OnMsgGetProperty)
    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_EnumerateProperties,
                        OnMsgEnumerateProperties)
    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_SetProperty,
                        OnMsgSetProperty)
    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Call,
                        OnMsgCall)
    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Construct,
                        OnMsgConstruct)
    IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Deallocate,
                        OnMsgDeallocate)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void PPP_Class_Proxy::OnMsgHasProperty(int64_t ppp_class,
                                       int64_t object,
                                       SerializedVarReceiveInput property,
                                       SerializedVarOutParam exception,
                                       bool* result) {
  if (!ValidateUserData(ppp_class, object, &exception))
    return;
  *result = CallWhileUnlocked(ToPPPClass(ppp_class)->HasProperty,
                              ToUserData(object),
                              property.Get(dispatcher()),
                              exception.OutParam(dispatcher()));
}

void PPP_Class_Proxy::OnMsgHasMethod(int64_t ppp_class,
                                     int64_t object,
                                     SerializedVarReceiveInput property,
                                     SerializedVarOutParam exception,
                                     bool* result) {
  if (!ValidateUserData(ppp_class, object, &exception))
    return;
  *result = CallWhileUnlocked(ToPPPClass(ppp_class)->HasMethod,
                              ToUserData(object),
                              property.Get(dispatcher()),
                              exception.OutParam(dispatcher()));
}

void PPP_Class_Proxy::OnMsgGetProperty(int64_t ppp_class,
                                       int64_t object,
                                       SerializedVarReceiveInput property,
                                       SerializedVarOutParam exception,
                                       SerializedVarReturnValue result) {
  if (!ValidateUserData(ppp_class, object, &exception))
    return;
  result.Return(dispatcher(), CallWhileUnlocked(
      ToPPPClass(ppp_class)->GetProperty,
      ToUserData(object), property.Get(dispatcher()),
      exception.OutParam(dispatcher())));
}

void PPP_Class_Proxy::OnMsgEnumerateProperties(
    int64_t ppp_class,
    int64_t object,
    std::vector<SerializedVar>* props,
    SerializedVarOutParam exception) {
  if (!ValidateUserData(ppp_class, object, &exception))
    return;
  NOTIMPLEMENTED();
  // TODO(brettw) implement this.
}

void PPP_Class_Proxy::OnMsgSetProperty(int64_t ppp_class,
                                       int64_t object,
                                       SerializedVarReceiveInput property,
                                       SerializedVarReceiveInput value,
                                       SerializedVarOutParam exception) {
  if (!ValidateUserData(ppp_class, object, &exception))
    return;
  CallWhileUnlocked(ToPPPClass(ppp_class)->SetProperty,
      ToUserData(object), property.Get(dispatcher()), value.Get(dispatcher()),
      exception.OutParam(dispatcher()));
}

void PPP_Class_Proxy::OnMsgRemoveProperty(int64_t ppp_class,
                                          int64_t object,
                                          SerializedVarReceiveInput property,
                                          SerializedVarOutParam exception) {
  if (!ValidateUserData(ppp_class, object, &exception))
    return;
  CallWhileUnlocked(ToPPPClass(ppp_class)->RemoveProperty,
      ToUserData(object), property.Get(dispatcher()),
      exception.OutParam(dispatcher()));
}

void PPP_Class_Proxy::OnMsgCall(int64_t ppp_class,
                                int64_t object,
                                SerializedVarReceiveInput method_name,
                                SerializedVarVectorReceiveInput arg_vector,
                                SerializedVarOutParam exception,
                                SerializedVarReturnValue result) {
  if (!ValidateUserData(ppp_class, object, &exception))
    return;
  uint32_t arg_count = 0;
  PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
  result.Return(dispatcher(), CallWhileUnlocked(ToPPPClass(ppp_class)->Call,
      ToUserData(object), method_name.Get(dispatcher()),
      arg_count, args, exception.OutParam(dispatcher())));
}

void PPP_Class_Proxy::OnMsgConstruct(int64_t ppp_class,
                                     int64_t object,
                                     SerializedVarVectorReceiveInput arg_vector,
                                     SerializedVarOutParam exception,
                                     SerializedVarReturnValue result) {
  if (!ValidateUserData(ppp_class, object, &exception))
    return;
  uint32_t arg_count = 0;
  PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
  result.Return(dispatcher(), CallWhileUnlocked(
      ToPPPClass(ppp_class)->Construct,
      ToUserData(object), arg_count, args, exception.OutParam(dispatcher())));
}

void PPP_Class_Proxy::OnMsgDeallocate(int64_t ppp_class, int64_t object) {
  if (!ValidateUserData(ppp_class, object, NULL))
    return;
  PluginGlobals::Get()->plugin_var_tracker()->PluginImplementedObjectDestroyed(
      ToUserData(object));
  CallWhileUnlocked(ToPPPClass(ppp_class)->Deallocate, ToUserData(object));
}

bool PPP_Class_Proxy::ValidateUserData(int64_t ppp_class,
                                       int64_t class_data,
                                       SerializedVarOutParam* exception) {
  if (!PluginGlobals::Get()->plugin_var_tracker()->ValidatePluginObjectCall(
          ToPPPClass(ppp_class), ToUserData(class_data))) {
    // Set the exception. This is so the caller will know about the error and
    // also that we won't assert that somebody forgot to call OutParam on the
    // output parameter. Although this exception of "1" won't be very useful
    // this shouldn't happen in normal usage, only when the renderer is being
    // malicious.
    if (exception)
      *exception->OutParam(dispatcher()) = PP_MakeInt32(1);
    return false;
  }
  return true;
}

}  // namespace proxy
}  // namespace ppapi
