- add sources.
[platform/framework/web/crosswalk.git] / src / ppapi / proxy / ppp_class_proxy.cc
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
17 namespace ppapi {
18 namespace proxy {
19
20 namespace {
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.
26 struct 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
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;
45 }
46
47 bool HasProperty(void* object, PP_Var name, PP_Var* exception) {
48   ObjectProxy* obj = ToObjectProxy(object);
49   if (!obj)
50     return false;
51
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;
58 }
59
60 bool HasMethod(void* object, PP_Var name, PP_Var* exception) {
61   ObjectProxy* obj = ToObjectProxy(object);
62   if (!obj)
63     return false;
64
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;
71 }
72
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();
79
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);
86 }
87
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.
94 }
95
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;
103
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));
109 }
110
111 void RemoveProperty(void* object,
112                     PP_Var name,
113                     PP_Var* exception) {
114   ObjectProxy* obj = ToObjectProxy(object);
115   if (!obj)
116     return;
117
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));
122 }
123
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();
132
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);
138
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);
144 }
145
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();
153
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);
159
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);
164 }
165
166 void Deallocate(void* object) {
167   ObjectProxy* obj = ToObjectProxy(object);
168   if (!obj)
169     return;
170
171   obj->dispatcher->Send(new PpapiMsg_PPPClass_Deallocate(
172       API_ID_PPP_CLASS, obj->ppp_class, obj->user_data));
173   delete obj;
174 }
175
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
186 };
187
188 // Plugin helper functions -----------------------------------------------------
189
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));
195 }
196
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));
201 }
202
203 }  // namespace
204
205 // PPP_Class_Proxy -------------------------------------------------------------
206
207 PPP_Class_Proxy::PPP_Class_Proxy(Dispatcher* dispatcher)
208     : InterfaceProxy(dispatcher) {
209 }
210
211 PPP_Class_Proxy::~PPP_Class_Proxy() {
212 }
213
214 // static
215 InterfaceProxy* PPP_Class_Proxy::Create(Dispatcher* dispatcher) {
216   return new PPP_Class_Proxy(dispatcher);
217 }
218
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);
228 }
229
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;
243     }
244   }
245   return PP_FALSE;
246 }
247
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.
251
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;
273 }
274
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()));
285 }
286
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()));
297 }
298
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())));
309 }
310
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.
319 }
320
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()));
330 }
331
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()));
340 }
341
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())));
355 }
356
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())));
369 }
370
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));
377 }
378
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;
391   }
392   return true;
393 }
394
395 }  // namespace proxy
396 }  // namespace ppapi