ppp_class_proxy.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "ppapi/proxy/ppp_class_proxy.h" 6 7#include "ppapi/c/dev/ppb_var_deprecated.h" 8#include "ppapi/c/dev/ppp_class_deprecated.h" 9#include "ppapi/c/pp_var.h" 10#include "ppapi/proxy/dispatcher.h" 11#include "ppapi/proxy/plugin_globals.h" 12#include "ppapi/proxy/ppapi_messages.h" 13#include "ppapi/proxy/serialized_var.h" 14#include "ppapi/shared_impl/proxy_lock.h" 15#include "ppapi/shared_impl/api_id.h" 16 17namespace ppapi { 18namespace proxy { 19 20namespace { 21 22// PPP_Class in the browser implementation ------------------------------------- 23 24// Represents a plugin-implemented class in the browser process. This just 25// stores the data necessary to call back the plugin. 26struct ObjectProxy { 27 ObjectProxy(Dispatcher* d, int64 p, int64 ud) 28 : dispatcher(d), 29 ppp_class(p), 30 user_data(ud) { 31 } 32 33 Dispatcher* dispatcher; 34 int64 ppp_class; 35 int64 user_data; 36}; 37 38ObjectProxy* ToObjectProxy(void* data) { 39 return reinterpret_cast<ObjectProxy*>(data); 40} 41 42bool HasProperty(void* object, PP_Var name, PP_Var* exception) { 43 ObjectProxy* obj = ToObjectProxy(object); 44 bool result = false; 45 ReceiveSerializedException se(obj->dispatcher, exception); 46 obj->dispatcher->Send(new PpapiMsg_PPPClass_HasProperty( 47 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data, 48 SerializedVarSendInput(obj->dispatcher, name), &se, &result)); 49 return result; 50} 51 52bool HasMethod(void* object, PP_Var name, PP_Var* exception) { 53 ObjectProxy* obj = ToObjectProxy(object); 54 bool result = false; 55 ReceiveSerializedException se(obj->dispatcher, exception); 56 obj->dispatcher->Send(new PpapiMsg_PPPClass_HasMethod( 57 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data, 58 SerializedVarSendInput(obj->dispatcher, name), &se, &result)); 59 return result; 60} 61 62PP_Var GetProperty(void* object, 63 PP_Var name, 64 PP_Var* exception) { 65 ObjectProxy* obj = ToObjectProxy(object); 66 ReceiveSerializedException se(obj->dispatcher, exception); 67 ReceiveSerializedVarReturnValue result; 68 obj->dispatcher->Send(new PpapiMsg_PPPClass_GetProperty( 69 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data, 70 SerializedVarSendInput(obj->dispatcher, name), &se, &result)); 71 return result.Return(obj->dispatcher); 72} 73 74void GetAllPropertyNames(void* object, 75 uint32_t* property_count, 76 PP_Var** properties, 77 PP_Var* exception) { 78 NOTIMPLEMENTED(); 79 // TODO(brettw) implement this. 80} 81 82void SetProperty(void* object, 83 PP_Var name, 84 PP_Var value, 85 PP_Var* exception) { 86 ObjectProxy* obj = ToObjectProxy(object); 87 ReceiveSerializedException se(obj->dispatcher, exception); 88 obj->dispatcher->Send(new PpapiMsg_PPPClass_SetProperty( 89 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data, 90 SerializedVarSendInput(obj->dispatcher, name), 91 SerializedVarSendInput(obj->dispatcher, value), &se)); 92} 93 94void RemoveProperty(void* object, 95 PP_Var name, 96 PP_Var* exception) { 97 ObjectProxy* obj = ToObjectProxy(object); 98 ReceiveSerializedException se(obj->dispatcher, exception); 99 obj->dispatcher->Send(new PpapiMsg_PPPClass_RemoveProperty( 100 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data, 101 SerializedVarSendInput(obj->dispatcher, name), &se)); 102} 103 104PP_Var Call(void* object, 105 PP_Var method_name, 106 uint32_t argc, 107 PP_Var* argv, 108 PP_Var* exception) { 109 ObjectProxy* obj = ToObjectProxy(object); 110 111 ReceiveSerializedVarReturnValue result; 112 ReceiveSerializedException se(obj->dispatcher, exception); 113 std::vector<SerializedVar> argv_vect; 114 SerializedVarSendInput::ConvertVector(obj->dispatcher, argv, argc, 115 &argv_vect); 116 117 obj->dispatcher->Send(new PpapiMsg_PPPClass_Call( 118 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data, 119 SerializedVarSendInput(obj->dispatcher, method_name), argv_vect, 120 &se, &result)); 121 return result.Return(obj->dispatcher); 122} 123 124PP_Var Construct(void* object, 125 uint32_t argc, 126 PP_Var* argv, 127 PP_Var* exception) { 128 ObjectProxy* obj = ToObjectProxy(object); 129 130 ReceiveSerializedVarReturnValue result; 131 ReceiveSerializedException se(obj->dispatcher, exception); 132 std::vector<SerializedVar> argv_vect; 133 SerializedVarSendInput::ConvertVector(obj->dispatcher, argv, argc, 134 &argv_vect); 135 136 obj->dispatcher->Send(new PpapiMsg_PPPClass_Construct( 137 API_ID_PPP_CLASS, 138 obj->ppp_class, obj->user_data, argv_vect, &se, &result)); 139 return result.Return(obj->dispatcher); 140} 141 142void Deallocate(void* object) { 143 ObjectProxy* obj = ToObjectProxy(object); 144 obj->dispatcher->Send(new PpapiMsg_PPPClass_Deallocate( 145 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data)); 146 delete obj; 147} 148 149const PPP_Class_Deprecated class_interface = { 150 &HasProperty, 151 &HasMethod, 152 &GetProperty, 153 &GetAllPropertyNames, 154 &SetProperty, 155 &RemoveProperty, 156 &Call, 157 &Construct, 158 &Deallocate 159}; 160 161// Plugin helper functions ----------------------------------------------------- 162 163// Converts an int64 object from IPC to a PPP_Class* for calling into the 164// plugin's implementation. 165const PPP_Class_Deprecated* ToPPPClass(int64 value) { 166 return reinterpret_cast<const PPP_Class_Deprecated*>( 167 static_cast<intptr_t>(value)); 168} 169 170// Converts an int64 object from IPC to a void* for calling into the plugin's 171// implementation as the user data. 172void* ToUserData(int64 value) { 173 return reinterpret_cast<void*>(static_cast<intptr_t>(value)); 174} 175 176} // namespace 177 178// PPP_Class_Proxy ------------------------------------------------------------- 179 180PPP_Class_Proxy::PPP_Class_Proxy(Dispatcher* dispatcher) 181 : InterfaceProxy(dispatcher) { 182} 183 184PPP_Class_Proxy::~PPP_Class_Proxy() { 185} 186 187// static 188InterfaceProxy* PPP_Class_Proxy::Create(Dispatcher* dispatcher) { 189 return new PPP_Class_Proxy(dispatcher); 190} 191 192// static 193PP_Var PPP_Class_Proxy::CreateProxiedObject(const PPB_Var_Deprecated* var, 194 Dispatcher* dispatcher, 195 PP_Instance instance_id, 196 int64 ppp_class, 197 int64 class_data) { 198 ObjectProxy* object_proxy = new ObjectProxy(dispatcher, 199 ppp_class, class_data); 200 return var->CreateObject(instance_id, &class_interface, object_proxy); 201} 202 203// static 204PP_Bool PPP_Class_Proxy::IsInstanceOf(const PPB_Var_Deprecated* ppb_var_impl, 205 const PP_Var& var, 206 int64 ppp_class, 207 int64* ppp_class_data) { 208 void* proxied_object = NULL; 209 if (ppb_var_impl->IsInstanceOf(var, 210 &class_interface, 211 &proxied_object)) { 212 if (static_cast<ObjectProxy*>(proxied_object)->ppp_class == ppp_class) { 213 DCHECK(ppp_class_data); 214 *ppp_class_data = static_cast<ObjectProxy*>(proxied_object)->user_data; 215 return PP_TRUE; 216 } 217 } 218 return PP_FALSE; 219} 220 221bool PPP_Class_Proxy::OnMessageReceived(const IPC::Message& msg) { 222 bool handled = true; 223 IPC_BEGIN_MESSAGE_MAP(PPP_Class_Proxy, msg) 224 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_HasProperty, 225 OnMsgHasProperty) 226 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_HasMethod, 227 OnMsgHasMethod) 228 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_GetProperty, 229 OnMsgGetProperty) 230 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_EnumerateProperties, 231 OnMsgEnumerateProperties) 232 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_SetProperty, 233 OnMsgSetProperty) 234 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Call, 235 OnMsgCall) 236 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Construct, 237 OnMsgConstruct) 238 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Deallocate, 239 OnMsgDeallocate) 240 IPC_MESSAGE_UNHANDLED(handled = false) 241 IPC_END_MESSAGE_MAP() 242 return handled; 243} 244 245void PPP_Class_Proxy::OnMsgHasProperty(int64 ppp_class, int64 object, 246 SerializedVarReceiveInput property, 247 SerializedVarOutParam exception, 248 bool* result) { 249 if (!ValidateUserData(ppp_class, object, &exception)) 250 return; 251 *result = CallWhileUnlocked(ToPPPClass(ppp_class)->HasProperty, 252 ToUserData(object), 253 property.Get(dispatcher()), 254 exception.OutParam(dispatcher())); 255} 256 257void PPP_Class_Proxy::OnMsgHasMethod(int64 ppp_class, int64 object, 258 SerializedVarReceiveInput property, 259 SerializedVarOutParam exception, 260 bool* result) { 261 if (!ValidateUserData(ppp_class, object, &exception)) 262 return; 263 *result = CallWhileUnlocked(ToPPPClass(ppp_class)->HasMethod, 264 ToUserData(object), 265 property.Get(dispatcher()), 266 exception.OutParam(dispatcher())); 267} 268 269void PPP_Class_Proxy::OnMsgGetProperty(int64 ppp_class, int64 object, 270 SerializedVarReceiveInput property, 271 SerializedVarOutParam exception, 272 SerializedVarReturnValue result) { 273 if (!ValidateUserData(ppp_class, object, &exception)) 274 return; 275 result.Return(dispatcher(), CallWhileUnlocked( 276 ToPPPClass(ppp_class)->GetProperty, 277 ToUserData(object), property.Get(dispatcher()), 278 exception.OutParam(dispatcher()))); 279} 280 281void PPP_Class_Proxy::OnMsgEnumerateProperties( 282 int64 ppp_class, int64 object, 283 std::vector<SerializedVar>* props, 284 SerializedVarOutParam exception) { 285 if (!ValidateUserData(ppp_class, object, &exception)) 286 return; 287 NOTIMPLEMENTED(); 288 // TODO(brettw) implement this. 289} 290 291void PPP_Class_Proxy::OnMsgSetProperty(int64 ppp_class, int64 object, 292 SerializedVarReceiveInput property, 293 SerializedVarReceiveInput value, 294 SerializedVarOutParam exception) { 295 if (!ValidateUserData(ppp_class, object, &exception)) 296 return; 297 CallWhileUnlocked(ToPPPClass(ppp_class)->SetProperty, 298 ToUserData(object), property.Get(dispatcher()), value.Get(dispatcher()), 299 exception.OutParam(dispatcher())); 300} 301 302void PPP_Class_Proxy::OnMsgRemoveProperty(int64 ppp_class, int64 object, 303 SerializedVarReceiveInput property, 304 SerializedVarOutParam exception) { 305 if (!ValidateUserData(ppp_class, object, &exception)) 306 return; 307 CallWhileUnlocked(ToPPPClass(ppp_class)->RemoveProperty, 308 ToUserData(object), property.Get(dispatcher()), 309 exception.OutParam(dispatcher())); 310} 311 312void PPP_Class_Proxy::OnMsgCall( 313 int64 ppp_class, int64 object, 314 SerializedVarReceiveInput method_name, 315 SerializedVarVectorReceiveInput arg_vector, 316 SerializedVarOutParam exception, 317 SerializedVarReturnValue result) { 318 if (!ValidateUserData(ppp_class, object, &exception)) 319 return; 320 uint32_t arg_count = 0; 321 PP_Var* args = arg_vector.Get(dispatcher(), &arg_count); 322 result.Return(dispatcher(), CallWhileUnlocked(ToPPPClass(ppp_class)->Call, 323 ToUserData(object), method_name.Get(dispatcher()), 324 arg_count, args, exception.OutParam(dispatcher()))); 325} 326 327void PPP_Class_Proxy::OnMsgConstruct( 328 int64 ppp_class, int64 object, 329 SerializedVarVectorReceiveInput arg_vector, 330 SerializedVarOutParam exception, 331 SerializedVarReturnValue result) { 332 if (!ValidateUserData(ppp_class, object, &exception)) 333 return; 334 uint32_t arg_count = 0; 335 PP_Var* args = arg_vector.Get(dispatcher(), &arg_count); 336 result.Return(dispatcher(), CallWhileUnlocked( 337 ToPPPClass(ppp_class)->Construct, 338 ToUserData(object), arg_count, args, exception.OutParam(dispatcher()))); 339} 340 341void PPP_Class_Proxy::OnMsgDeallocate(int64 ppp_class, int64 object) { 342 if (!ValidateUserData(ppp_class, object, NULL)) 343 return; 344 PluginGlobals::Get()->plugin_var_tracker()->PluginImplementedObjectDestroyed( 345 ToUserData(object)); 346 CallWhileUnlocked(ToPPPClass(ppp_class)->Deallocate, ToUserData(object)); 347} 348 349bool PPP_Class_Proxy::ValidateUserData(int64 ppp_class, int64 class_data, 350 SerializedVarOutParam* exception) { 351 if (!PluginGlobals::Get()->plugin_var_tracker()->ValidatePluginObjectCall( 352 ToPPPClass(ppp_class), ToUserData(class_data))) { 353 // Set the exception. This is so the caller will know about the error and 354 // also that we won't assert that somebody forgot to call OutParam on the 355 // output parameter. Although this exception of "1" won't be very useful 356 // this shouldn't happen in normal usage, only when the renderer is being 357 // malicious. 358 if (exception) 359 *exception->OutParam(dispatcher()) = PP_MakeInt32(1); 360 return false; 361 } 362 return true; 363} 364 365} // namespace proxy 366} // namespace ppapi 367