
The methodology used to generate this CL is documented in https://crbug.com/1098010#c95. No-Try: true Bug: 1098010 Change-Id: I6ae92e5d7ccbf73b176588124b2f8b4067f805b3 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3900575 Reviewed-by: Mark Mentovai <mark@chromium.org> Owners-Override: Avi Drissman <avi@chromium.org> Commit-Queue: Avi Drissman <avi@chromium.org> Auto-Submit: Avi Drissman <avi@chromium.org> Cr-Commit-Position: refs/heads/main@{#1047628}
401 lines
14 KiB
C++
401 lines
14 KiB
C++
// Copyright 2012 The Chromium Authors
|
|
// 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_FLASH))
|
|
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
|