Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ppapi / proxy / ppp_class_proxy.cc
blob3c28d0d54c0a888a214f0df7d226799fdf96f20c
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.
5 #include "ppapi/proxy/ppp_class_proxy.h"
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"
17 namespace ppapi {
18 namespace proxy {
20 namespace {
22 // PPP_Class in the browser implementation -------------------------------------
24 // Represents a plugin-implemented class in the browser process. This just
25 // stores the data necessary to call back the plugin.
26 struct ObjectProxy {
27 ObjectProxy(Dispatcher* d, int64 p, int64 ud)
28 : dispatcher(d),
29 ppp_class(p),
30 user_data(ud) {
33 Dispatcher* dispatcher;
34 int64 ppp_class;
35 int64 user_data;
38 ObjectProxy* ToObjectProxy(void* data) {
39 ObjectProxy* obj = reinterpret_cast<ObjectProxy*>(data);
40 if (!obj || !obj->dispatcher)
41 return NULL;
42 if (!obj->dispatcher->permissions().HasPermission(PERMISSION_DEV))
43 return NULL;
44 return obj;
47 bool HasProperty(void* object, PP_Var name, PP_Var* exception) {
48 ObjectProxy* obj = ToObjectProxy(object);
49 if (!obj)
50 return false;
52 bool result = false;
53 ReceiveSerializedException se(obj->dispatcher, exception);
54 obj->dispatcher->Send(new PpapiMsg_PPPClass_HasProperty(
55 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
56 SerializedVarSendInput(obj->dispatcher, name), &se, &result));
57 return result;
60 bool HasMethod(void* object, PP_Var name, PP_Var* exception) {
61 ObjectProxy* obj = ToObjectProxy(object);
62 if (!obj)
63 return false;
65 bool result = false;
66 ReceiveSerializedException se(obj->dispatcher, exception);
67 obj->dispatcher->Send(new PpapiMsg_PPPClass_HasMethod(
68 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
69 SerializedVarSendInput(obj->dispatcher, name), &se, &result));
70 return result;
73 PP_Var GetProperty(void* object,
74 PP_Var name,
75 PP_Var* exception) {
76 ObjectProxy* obj = ToObjectProxy(object);
77 if (!obj)
78 return PP_MakeUndefined();
80 ReceiveSerializedException se(obj->dispatcher, exception);
81 ReceiveSerializedVarReturnValue result;
82 obj->dispatcher->Send(new PpapiMsg_PPPClass_GetProperty(
83 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
84 SerializedVarSendInput(obj->dispatcher, name), &se, &result));
85 return result.Return(obj->dispatcher);
88 void GetAllPropertyNames(void* object,
89 uint32_t* property_count,
90 PP_Var** properties,
91 PP_Var* exception) {
92 NOTIMPLEMENTED();
93 // TODO(brettw) implement this.
96 void SetProperty(void* object,
97 PP_Var name,
98 PP_Var value,
99 PP_Var* exception) {
100 ObjectProxy* obj = ToObjectProxy(object);
101 if (!obj)
102 return;
104 ReceiveSerializedException se(obj->dispatcher, exception);
105 obj->dispatcher->Send(new PpapiMsg_PPPClass_SetProperty(
106 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
107 SerializedVarSendInput(obj->dispatcher, name),
108 SerializedVarSendInput(obj->dispatcher, value), &se));
111 void RemoveProperty(void* object,
112 PP_Var name,
113 PP_Var* exception) {
114 ObjectProxy* obj = ToObjectProxy(object);
115 if (!obj)
116 return;
118 ReceiveSerializedException se(obj->dispatcher, exception);
119 obj->dispatcher->Send(new PpapiMsg_PPPClass_RemoveProperty(
120 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
121 SerializedVarSendInput(obj->dispatcher, name), &se));
124 PP_Var Call(void* object,
125 PP_Var method_name,
126 uint32_t argc,
127 PP_Var* argv,
128 PP_Var* exception) {
129 ObjectProxy* obj = ToObjectProxy(object);
130 if (!obj)
131 return PP_MakeUndefined();
133 ReceiveSerializedVarReturnValue result;
134 ReceiveSerializedException se(obj->dispatcher, exception);
135 std::vector<SerializedVar> argv_vect;
136 SerializedVarSendInput::ConvertVector(obj->dispatcher, argv, argc,
137 &argv_vect);
139 obj->dispatcher->Send(new PpapiMsg_PPPClass_Call(
140 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data,
141 SerializedVarSendInput(obj->dispatcher, method_name), argv_vect,
142 &se, &result));
143 return result.Return(obj->dispatcher);
146 PP_Var Construct(void* object,
147 uint32_t argc,
148 PP_Var* argv,
149 PP_Var* exception) {
150 ObjectProxy* obj = ToObjectProxy(object);
151 if (!obj)
152 return PP_MakeUndefined();
154 ReceiveSerializedVarReturnValue result;
155 ReceiveSerializedException se(obj->dispatcher, exception);
156 std::vector<SerializedVar> argv_vect;
157 SerializedVarSendInput::ConvertVector(obj->dispatcher, argv, argc,
158 &argv_vect);
160 obj->dispatcher->Send(new PpapiMsg_PPPClass_Construct(
161 API_ID_PPP_CLASS,
162 obj->ppp_class, obj->user_data, argv_vect, &se, &result));
163 return result.Return(obj->dispatcher);
166 void Deallocate(void* object) {
167 ObjectProxy* obj = ToObjectProxy(object);
168 if (!obj)
169 return;
171 obj->dispatcher->Send(new PpapiMsg_PPPClass_Deallocate(
172 API_ID_PPP_CLASS, obj->ppp_class, obj->user_data));
173 delete obj;
176 const PPP_Class_Deprecated class_interface = {
177 &HasProperty,
178 &HasMethod,
179 &GetProperty,
180 &GetAllPropertyNames,
181 &SetProperty,
182 &RemoveProperty,
183 &Call,
184 &Construct,
185 &Deallocate
188 // Plugin helper functions -----------------------------------------------------
190 // Converts an int64 object from IPC to a PPP_Class* for calling into the
191 // plugin's implementation.
192 const PPP_Class_Deprecated* ToPPPClass(int64 value) {
193 return reinterpret_cast<const PPP_Class_Deprecated*>(
194 static_cast<intptr_t>(value));
197 // Converts an int64 object from IPC to a void* for calling into the plugin's
198 // implementation as the user data.
199 void* ToUserData(int64 value) {
200 return reinterpret_cast<void*>(static_cast<intptr_t>(value));
203 } // namespace
205 // PPP_Class_Proxy -------------------------------------------------------------
207 PPP_Class_Proxy::PPP_Class_Proxy(Dispatcher* dispatcher)
208 : InterfaceProxy(dispatcher) {
211 PPP_Class_Proxy::~PPP_Class_Proxy() {
214 // static
215 InterfaceProxy* PPP_Class_Proxy::Create(Dispatcher* dispatcher) {
216 return new PPP_Class_Proxy(dispatcher);
219 // static
220 PP_Var PPP_Class_Proxy::CreateProxiedObject(const PPB_Var_Deprecated* var,
221 Dispatcher* dispatcher,
222 PP_Instance instance_id,
223 int64 ppp_class,
224 int64 class_data) {
225 ObjectProxy* object_proxy = new ObjectProxy(dispatcher,
226 ppp_class, class_data);
227 return var->CreateObject(instance_id, &class_interface, object_proxy);
230 // static
231 PP_Bool PPP_Class_Proxy::IsInstanceOf(const PPB_Var_Deprecated* ppb_var_impl,
232 const PP_Var& var,
233 int64 ppp_class,
234 int64* ppp_class_data) {
235 void* proxied_object = NULL;
236 if (ppb_var_impl->IsInstanceOf(var,
237 &class_interface,
238 &proxied_object)) {
239 if (static_cast<ObjectProxy*>(proxied_object)->ppp_class == ppp_class) {
240 DCHECK(ppp_class_data);
241 *ppp_class_data = static_cast<ObjectProxy*>(proxied_object)->user_data;
242 return PP_TRUE;
245 return PP_FALSE;
248 bool PPP_Class_Proxy::OnMessageReceived(const IPC::Message& msg) {
249 if (!dispatcher()->IsPlugin())
250 return false; // These messages are only valid from host->plugin.
252 bool handled = true;
253 IPC_BEGIN_MESSAGE_MAP(PPP_Class_Proxy, msg)
254 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_HasProperty,
255 OnMsgHasProperty)
256 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_HasMethod,
257 OnMsgHasMethod)
258 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_GetProperty,
259 OnMsgGetProperty)
260 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_EnumerateProperties,
261 OnMsgEnumerateProperties)
262 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_SetProperty,
263 OnMsgSetProperty)
264 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Call,
265 OnMsgCall)
266 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Construct,
267 OnMsgConstruct)
268 IPC_MESSAGE_HANDLER(PpapiMsg_PPPClass_Deallocate,
269 OnMsgDeallocate)
270 IPC_MESSAGE_UNHANDLED(handled = false)
271 IPC_END_MESSAGE_MAP()
272 return handled;
275 void PPP_Class_Proxy::OnMsgHasProperty(int64 ppp_class, int64 object,
276 SerializedVarReceiveInput property,
277 SerializedVarOutParam exception,
278 bool* result) {
279 if (!ValidateUserData(ppp_class, object, &exception))
280 return;
281 *result = CallWhileUnlocked(ToPPPClass(ppp_class)->HasProperty,
282 ToUserData(object),
283 property.Get(dispatcher()),
284 exception.OutParam(dispatcher()));
287 void PPP_Class_Proxy::OnMsgHasMethod(int64 ppp_class, int64 object,
288 SerializedVarReceiveInput property,
289 SerializedVarOutParam exception,
290 bool* result) {
291 if (!ValidateUserData(ppp_class, object, &exception))
292 return;
293 *result = CallWhileUnlocked(ToPPPClass(ppp_class)->HasMethod,
294 ToUserData(object),
295 property.Get(dispatcher()),
296 exception.OutParam(dispatcher()));
299 void PPP_Class_Proxy::OnMsgGetProperty(int64 ppp_class, int64 object,
300 SerializedVarReceiveInput property,
301 SerializedVarOutParam exception,
302 SerializedVarReturnValue result) {
303 if (!ValidateUserData(ppp_class, object, &exception))
304 return;
305 result.Return(dispatcher(), CallWhileUnlocked(
306 ToPPPClass(ppp_class)->GetProperty,
307 ToUserData(object), property.Get(dispatcher()),
308 exception.OutParam(dispatcher())));
311 void PPP_Class_Proxy::OnMsgEnumerateProperties(
312 int64 ppp_class, int64 object,
313 std::vector<SerializedVar>* props,
314 SerializedVarOutParam exception) {
315 if (!ValidateUserData(ppp_class, object, &exception))
316 return;
317 NOTIMPLEMENTED();
318 // TODO(brettw) implement this.
321 void PPP_Class_Proxy::OnMsgSetProperty(int64 ppp_class, int64 object,
322 SerializedVarReceiveInput property,
323 SerializedVarReceiveInput value,
324 SerializedVarOutParam exception) {
325 if (!ValidateUserData(ppp_class, object, &exception))
326 return;
327 CallWhileUnlocked(ToPPPClass(ppp_class)->SetProperty,
328 ToUserData(object), property.Get(dispatcher()), value.Get(dispatcher()),
329 exception.OutParam(dispatcher()));
332 void PPP_Class_Proxy::OnMsgRemoveProperty(int64 ppp_class, int64 object,
333 SerializedVarReceiveInput property,
334 SerializedVarOutParam exception) {
335 if (!ValidateUserData(ppp_class, object, &exception))
336 return;
337 CallWhileUnlocked(ToPPPClass(ppp_class)->RemoveProperty,
338 ToUserData(object), property.Get(dispatcher()),
339 exception.OutParam(dispatcher()));
342 void PPP_Class_Proxy::OnMsgCall(
343 int64 ppp_class, int64 object,
344 SerializedVarReceiveInput method_name,
345 SerializedVarVectorReceiveInput arg_vector,
346 SerializedVarOutParam exception,
347 SerializedVarReturnValue result) {
348 if (!ValidateUserData(ppp_class, object, &exception))
349 return;
350 uint32_t arg_count = 0;
351 PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
352 result.Return(dispatcher(), CallWhileUnlocked(ToPPPClass(ppp_class)->Call,
353 ToUserData(object), method_name.Get(dispatcher()),
354 arg_count, args, exception.OutParam(dispatcher())));
357 void PPP_Class_Proxy::OnMsgConstruct(
358 int64 ppp_class, int64 object,
359 SerializedVarVectorReceiveInput arg_vector,
360 SerializedVarOutParam exception,
361 SerializedVarReturnValue result) {
362 if (!ValidateUserData(ppp_class, object, &exception))
363 return;
364 uint32_t arg_count = 0;
365 PP_Var* args = arg_vector.Get(dispatcher(), &arg_count);
366 result.Return(dispatcher(), CallWhileUnlocked(
367 ToPPPClass(ppp_class)->Construct,
368 ToUserData(object), arg_count, args, exception.OutParam(dispatcher())));
371 void PPP_Class_Proxy::OnMsgDeallocate(int64 ppp_class, int64 object) {
372 if (!ValidateUserData(ppp_class, object, NULL))
373 return;
374 PluginGlobals::Get()->plugin_var_tracker()->PluginImplementedObjectDestroyed(
375 ToUserData(object));
376 CallWhileUnlocked(ToPPPClass(ppp_class)->Deallocate, ToUserData(object));
379 bool PPP_Class_Proxy::ValidateUserData(int64 ppp_class, int64 class_data,
380 SerializedVarOutParam* exception) {
381 if (!PluginGlobals::Get()->plugin_var_tracker()->ValidatePluginObjectCall(
382 ToPPPClass(ppp_class), ToUserData(class_data))) {
383 // Set the exception. This is so the caller will know about the error and
384 // also that we won't assert that somebody forgot to call OutParam on the
385 // output parameter. Although this exception of "1" won't be very useful
386 // this shouldn't happen in normal usage, only when the renderer is being
387 // malicious.
388 if (exception)
389 *exception->OutParam(dispatcher()) = PP_MakeInt32(1);
390 return false;
392 return true;
395 } // namespace proxy
396 } // namespace ppapi