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