• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/serialized_var.h"
6 
7 #include "base/logging.h"
8 #include "ipc/ipc_message_utils.h"
9 #include "ppapi/c/pp_instance.h"
10 #include "ppapi/proxy/dispatcher.h"
11 #include "ppapi/proxy/interface_proxy.h"
12 #include "ppapi/proxy/ppapi_param_traits.h"
13 #include "ppapi/proxy/ppb_buffer_proxy.h"
14 #include "ppapi/shared_impl/ppapi_globals.h"
15 #include "ppapi/shared_impl/var.h"
16 #include "ppapi/thunk/enter.h"
17 
18 namespace ppapi {
19 namespace proxy {
20 
21 namespace {
DefaultHandleWriter(IPC::Message * m,const SerializedHandle & handle)22 void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) {
23   IPC::ParamTraits<SerializedHandle>::Write(m, handle);
24 }
25 }  // namespace
26 
27 // SerializedVar::Inner --------------------------------------------------------
28 
Inner()29 SerializedVar::Inner::Inner()
30     : serialization_rules_(NULL),
31       var_(PP_MakeUndefined()),
32       instance_(0),
33       cleanup_mode_(CLEANUP_NONE),
34       is_valid_var_(true) {
35 #ifndef NDEBUG
36   has_been_serialized_ = false;
37   has_been_deserialized_ = false;
38 #endif
39 }
40 
Inner(VarSerializationRules * serialization_rules)41 SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules)
42     : serialization_rules_(serialization_rules),
43       var_(PP_MakeUndefined()),
44       instance_(0),
45       cleanup_mode_(CLEANUP_NONE) {
46 #ifndef NDEBUG
47   has_been_serialized_ = false;
48   has_been_deserialized_ = false;
49 #endif
50 }
51 
~Inner()52 SerializedVar::Inner::~Inner() {
53   switch (cleanup_mode_) {
54     case END_SEND_PASS_REF:
55       serialization_rules_->EndSendPassRef(var_);
56       break;
57     case END_RECEIVE_CALLER_OWNED:
58       serialization_rules_->EndReceiveCallerOwned(var_);
59       break;
60     default:
61       break;
62   }
63 }
64 
GetVar()65 PP_Var SerializedVar::Inner::GetVar() {
66   DCHECK(serialization_rules_.get());
67 
68 #if defined(NACL_WIN64)
69   NOTREACHED();
70   return PP_MakeUndefined();
71 #else
72   if (raw_var_data_.get()) {
73     var_ = raw_var_data_->CreatePPVar(instance_);
74     raw_var_data_.reset(NULL);
75   }
76 
77   return var_;
78 #endif
79 }
80 
SetVar(PP_Var var)81 void SerializedVar::Inner::SetVar(PP_Var var) {
82   // Sanity check, when updating the var we should have received a
83   // serialization rules pointer already.
84   DCHECK(serialization_rules_.get());
85   var_ = var;
86   raw_var_data_.reset(NULL);
87 }
88 
SetInstance(PP_Instance instance)89 void SerializedVar::Inner::SetInstance(PP_Instance instance) {
90   instance_ = instance;
91 }
92 
ForceSetVarValueForTest(PP_Var value)93 void SerializedVar::Inner::ForceSetVarValueForTest(PP_Var value) {
94   var_ = value;
95   raw_var_data_.reset(NULL);
96 }
97 
WriteToMessage(IPC::Message * m) const98 void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
99   // When writing to the IPC messages, a serialization rules handler should
100   // always have been set.
101   //
102   // When sending a message, it should be difficult to trigger this if you're
103   // using the SerializedVarSendInput class and giving a non-NULL dispatcher.
104   // Make sure you're using the proper "Send" helper class.
105   //
106   // It should be more common to see this when handling an incoming message
107   // that returns a var. This means the message handler didn't write to the
108   // output parameter, or possibly you used the wrong helper class
109   // (normally SerializedVarReturnValue).
110   DCHECK(serialization_rules_.get());
111 
112 #ifndef NDEBUG
113   // We should only be serializing something once.
114   DCHECK(!has_been_serialized_);
115   has_been_serialized_ = true;
116 #endif
117   scoped_ptr<RawVarDataGraph> data = RawVarDataGraph::Create(var_, instance_);
118   if (data) {
119     m->WriteBool(true);  // Success.
120     data->Write(m, base::Bind(&DefaultHandleWriter));
121   } else {
122     m->WriteBool(false);  // Failure.
123   }
124 }
125 
WriteDataToMessage(IPC::Message * m,const HandleWriter & handle_writer) const126 void SerializedVar::Inner::WriteDataToMessage(
127     IPC::Message* m,
128     const HandleWriter& handle_writer) const {
129   if (raw_var_data_) {
130     m->WriteBool(true);  // Success.
131     raw_var_data_->Write(m, handle_writer);
132   } else {
133     m->WriteBool(false);  // Failure.
134   }
135 }
136 
ReadFromMessage(const IPC::Message * m,PickleIterator * iter)137 bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m,
138                                            PickleIterator* iter) {
139 #ifndef NDEBUG
140   // We should only deserialize something once or will end up with leaked
141   // references.
142   //
143   // One place this has happened in the past is using
144   // std::vector<SerializedVar>.resize(). If you're doing this manually instead
145   // of using the helper classes for handling in/out vectors of vars, be
146   // sure you use the same pattern as the SerializedVarVector classes.
147   DCHECK(!has_been_deserialized_);
148   has_been_deserialized_ = true;
149 #endif
150   // When reading, the dispatcher should be set when we get a Deserialize
151   // call (which will supply a dispatcher).
152   if (!m->ReadBool(iter, &is_valid_var_))
153       return false;
154   if (is_valid_var_) {
155     raw_var_data_ = RawVarDataGraph::Read(m, iter);
156     if (!raw_var_data_)
157       return false;
158   }
159 
160   return true;
161 }
162 
SetCleanupModeToEndSendPassRef()163 void SerializedVar::Inner::SetCleanupModeToEndSendPassRef() {
164   cleanup_mode_ = END_SEND_PASS_REF;
165 }
166 
SetCleanupModeToEndReceiveCallerOwned()167 void SerializedVar::Inner::SetCleanupModeToEndReceiveCallerOwned() {
168   cleanup_mode_ = END_RECEIVE_CALLER_OWNED;
169 }
170 
171 // SerializedVar ---------------------------------------------------------------
172 
SerializedVar()173 SerializedVar::SerializedVar() : inner_(new Inner) {
174 }
175 
SerializedVar(VarSerializationRules * serialization_rules)176 SerializedVar::SerializedVar(VarSerializationRules* serialization_rules)
177     : inner_(new Inner(serialization_rules)) {
178 }
179 
~SerializedVar()180 SerializedVar::~SerializedVar() {
181 }
182 
183 // SerializedVarSendInput ------------------------------------------------------
184 
SerializedVarSendInput(Dispatcher * dispatcher,const PP_Var & var)185 SerializedVarSendInput::SerializedVarSendInput(Dispatcher* dispatcher,
186                                                const PP_Var& var)
187     : SerializedVar(dispatcher->serialization_rules()) {
188   inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(var));
189 }
190 
191 // static
ConvertVector(Dispatcher * dispatcher,const PP_Var * input,size_t input_count,std::vector<SerializedVar> * output)192 void SerializedVarSendInput::ConvertVector(Dispatcher* dispatcher,
193                                            const PP_Var* input,
194                                            size_t input_count,
195                                            std::vector<SerializedVar>* output) {
196   output->reserve(input_count);
197   for (size_t i = 0; i < input_count; i++)
198     output->push_back(SerializedVarSendInput(dispatcher, input[i]));
199 }
200 
201 // SerializedVarSendInputShmem -------------------------------------------------
202 
SerializedVarSendInputShmem(Dispatcher * dispatcher,const PP_Var & var,const PP_Instance & instance)203 SerializedVarSendInputShmem::SerializedVarSendInputShmem(
204     Dispatcher* dispatcher,
205     const PP_Var& var,
206     const PP_Instance& instance)
207     : SerializedVar(dispatcher->serialization_rules()) {
208   inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(var));
209   inner_->SetInstance(instance);
210 }
211 
212 // ReceiveSerializedVarReturnValue ---------------------------------------------
213 
ReceiveSerializedVarReturnValue()214 ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue() {
215 }
216 
ReceiveSerializedVarReturnValue(const SerializedVar & serialized)217 ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue(
218     const SerializedVar& serialized)
219     : SerializedVar(serialized) {
220 }
221 
Return(Dispatcher * dispatcher)222 PP_Var ReceiveSerializedVarReturnValue::Return(Dispatcher* dispatcher) {
223   inner_->set_serialization_rules(dispatcher->serialization_rules());
224   inner_->SetVar(inner_->serialization_rules()->ReceivePassRef(
225       inner_->GetVar()));
226   return inner_->GetVar();
227 }
228 
229 // ReceiveSerializedException --------------------------------------------------
230 
ReceiveSerializedException(Dispatcher * dispatcher,PP_Var * exception)231 ReceiveSerializedException::ReceiveSerializedException(Dispatcher* dispatcher,
232                                                        PP_Var* exception)
233     : SerializedVar(dispatcher->serialization_rules()),
234       exception_(exception) {
235 }
236 
~ReceiveSerializedException()237 ReceiveSerializedException::~ReceiveSerializedException() {
238   if (exception_) {
239     // When an output exception is specified, it will take ownership of the
240     // reference.
241     inner_->SetVar(
242         inner_->serialization_rules()->ReceivePassRef(inner_->GetVar()));
243     *exception_ = inner_->GetVar();
244   } else {
245     // When no output exception is specified, the browser thinks we have a ref
246     // to an object that we don't want (this will happen only in the plugin
247     // since the browser will always specify an out exception for the plugin to
248     // write into).
249     //
250     // Strings don't need this handling since we can just avoid creating a
251     // Var from the std::string in the first place.
252     if (inner_->GetVar().type == PP_VARTYPE_OBJECT)
253       inner_->serialization_rules()->ReleaseObjectRef(inner_->GetVar());
254   }
255 }
256 
IsThrown() const257 bool ReceiveSerializedException::IsThrown() const {
258   return exception_ && exception_->type != PP_VARTYPE_UNDEFINED;
259 }
260 
261 // ReceiveSerializedVarVectorOutParam ------------------------------------------
262 
ReceiveSerializedVarVectorOutParam(Dispatcher * dispatcher,uint32_t * output_count,PP_Var ** output)263 ReceiveSerializedVarVectorOutParam::ReceiveSerializedVarVectorOutParam(
264     Dispatcher* dispatcher,
265     uint32_t* output_count,
266     PP_Var** output)
267     : dispatcher_(dispatcher),
268       output_count_(output_count),
269       output_(output) {
270 }
271 
~ReceiveSerializedVarVectorOutParam()272 ReceiveSerializedVarVectorOutParam::~ReceiveSerializedVarVectorOutParam() {
273   *output_count_ = static_cast<uint32_t>(vector_.size());
274   if (!vector_.size()) {
275     *output_ = NULL;
276     return;
277   }
278 
279   *output_ = static_cast<PP_Var*>(malloc(vector_.size() * sizeof(PP_Var)));
280   for (size_t i = 0; i < vector_.size(); i++) {
281     // Here we just mimic what happens when returning a value.
282     ReceiveSerializedVarReturnValue converted;
283     SerializedVar* serialized = &converted;
284     *serialized = vector_[i];
285     (*output_)[i] = converted.Return(dispatcher_);
286   }
287 }
288 
OutParam()289 std::vector<SerializedVar>* ReceiveSerializedVarVectorOutParam::OutParam() {
290   return &vector_;
291 }
292 
293 // SerializedVarReceiveInput ---------------------------------------------------
294 
SerializedVarReceiveInput(const SerializedVar & serialized)295 SerializedVarReceiveInput::SerializedVarReceiveInput(
296     const SerializedVar& serialized)
297     : serialized_(serialized) {
298 }
299 
~SerializedVarReceiveInput()300 SerializedVarReceiveInput::~SerializedVarReceiveInput() {
301 }
302 
Get(Dispatcher * dispatcher)303 PP_Var SerializedVarReceiveInput::Get(Dispatcher* dispatcher) {
304   serialized_.inner_->set_serialization_rules(
305       dispatcher->serialization_rules());
306 
307   // Ensure that when the serialized var goes out of scope it cleans up the
308   // stuff we're making in BeginReceiveCallerOwned.
309   serialized_.inner_->SetCleanupModeToEndReceiveCallerOwned();
310 
311   serialized_.inner_->SetVar(
312       serialized_.inner_->serialization_rules()->BeginReceiveCallerOwned(
313           serialized_.inner_->GetVar()));
314   return serialized_.inner_->GetVar();
315 }
316 
317 
GetForInstance(Dispatcher * dispatcher,PP_Instance instance)318 PP_Var SerializedVarReceiveInput::GetForInstance(Dispatcher* dispatcher,
319                                                  PP_Instance instance) {
320   serialized_.inner_->SetInstance(instance);
321   return Get(dispatcher);
322 }
323 
324 // SerializedVarVectorReceiveInput ---------------------------------------------
325 
SerializedVarVectorReceiveInput(const std::vector<SerializedVar> & serialized)326 SerializedVarVectorReceiveInput::SerializedVarVectorReceiveInput(
327     const std::vector<SerializedVar>& serialized)
328     : serialized_(serialized) {
329 }
330 
~SerializedVarVectorReceiveInput()331 SerializedVarVectorReceiveInput::~SerializedVarVectorReceiveInput() {
332   for (size_t i = 0; i < deserialized_.size(); i++) {
333     serialized_[i].inner_->serialization_rules()->EndReceiveCallerOwned(
334         deserialized_[i]);
335   }
336 }
337 
Get(Dispatcher * dispatcher,uint32_t * array_size)338 PP_Var* SerializedVarVectorReceiveInput::Get(Dispatcher* dispatcher,
339                                              uint32_t* array_size) {
340   deserialized_.resize(serialized_.size());
341   for (size_t i = 0; i < serialized_.size(); i++) {
342     // The vectors must be able to clean themselves up after this call is
343     // torn down.
344     serialized_[i].inner_->set_serialization_rules(
345         dispatcher->serialization_rules());
346 
347     serialized_[i].inner_->SetVar(
348         serialized_[i].inner_->serialization_rules()->BeginReceiveCallerOwned(
349             serialized_[i].inner_->GetVar()));
350     deserialized_[i] = serialized_[i].inner_->GetVar();
351   }
352 
353   *array_size = static_cast<uint32_t>(serialized_.size());
354   return deserialized_.empty() ? NULL : &deserialized_[0];
355 }
356 
357 // SerializedVarReturnValue ----------------------------------------------------
358 
SerializedVarReturnValue(SerializedVar * serialized)359 SerializedVarReturnValue::SerializedVarReturnValue(SerializedVar* serialized)
360     : serialized_(serialized) {
361 }
362 
Return(Dispatcher * dispatcher,const PP_Var & var)363 void SerializedVarReturnValue::Return(Dispatcher* dispatcher,
364                                       const PP_Var& var) {
365   serialized_->inner_->set_serialization_rules(
366       dispatcher->serialization_rules());
367 
368   // Var must clean up after our BeginSendPassRef call.
369   serialized_->inner_->SetCleanupModeToEndSendPassRef();
370 
371   serialized_->inner_->SetVar(
372       dispatcher->serialization_rules()->BeginSendPassRef(var));
373 }
374 
375 // static
Convert(Dispatcher * dispatcher,const PP_Var & var)376 SerializedVar SerializedVarReturnValue::Convert(Dispatcher* dispatcher,
377                                                 const PP_Var& var) {
378   // Mimic what happens in the normal case.
379   SerializedVar result;
380   SerializedVarReturnValue retvalue(&result);
381   retvalue.Return(dispatcher, var);
382   return result;
383 }
384 
385 // SerializedVarOutParam -------------------------------------------------------
386 
SerializedVarOutParam(SerializedVar * serialized)387 SerializedVarOutParam::SerializedVarOutParam(SerializedVar* serialized)
388     : serialized_(serialized),
389       writable_var_(PP_MakeUndefined()),
390       dispatcher_(NULL) {
391 }
392 
~SerializedVarOutParam()393 SerializedVarOutParam::~SerializedVarOutParam() {
394   if (serialized_->inner_->serialization_rules()) {
395     // When unset, OutParam wasn't called. We'll just leave the var untouched
396     // in that case.
397     serialized_->inner_->SetVar(
398         serialized_->inner_->serialization_rules()->BeginSendPassRef(
399             writable_var_));
400 
401     // Normally the current object will be created on the stack to wrap a
402     // SerializedVar and won't have a scope around the actual IPC send. So we
403     // need to tell the SerializedVar to do the begin/end send pass ref calls.
404     serialized_->inner_->SetCleanupModeToEndSendPassRef();
405   }
406 }
407 
OutParam(Dispatcher * dispatcher)408 PP_Var* SerializedVarOutParam::OutParam(Dispatcher* dispatcher) {
409   dispatcher_ = dispatcher;
410   serialized_->inner_->set_serialization_rules(
411       dispatcher->serialization_rules());
412   return &writable_var_;
413 }
414 
415 // SerializedVarVectorOutParam -------------------------------------------------
416 
SerializedVarVectorOutParam(std::vector<SerializedVar> * serialized)417 SerializedVarVectorOutParam::SerializedVarVectorOutParam(
418     std::vector<SerializedVar>* serialized)
419     : dispatcher_(NULL),
420       serialized_(serialized),
421       count_(0),
422       array_(NULL) {
423 }
424 
~SerializedVarVectorOutParam()425 SerializedVarVectorOutParam::~SerializedVarVectorOutParam() {
426   DCHECK(dispatcher_);
427 
428   // Convert the array written by the pepper code to the serialized structure.
429   // Note we can't use resize here, we have to allocate a new SerializedVar
430   // for each serialized item. See ParamTraits<vector<SerializedVar>>::Read.
431   serialized_->reserve(count_);
432   for (uint32_t i = 0; i < count_; i++) {
433     // Just mimic what we do for regular OutParams.
434     SerializedVar var;
435     SerializedVarOutParam out(&var);
436     *out.OutParam(dispatcher_) = array_[i];
437     serialized_->push_back(var);
438   }
439 
440   // When returning arrays, the pepper code expects the caller to take
441   // ownership of the array.
442   free(array_);
443 }
444 
ArrayOutParam(Dispatcher * dispatcher)445 PP_Var** SerializedVarVectorOutParam::ArrayOutParam(Dispatcher* dispatcher) {
446   DCHECK(!dispatcher_);  // Should only be called once.
447   dispatcher_ = dispatcher;
448   return &array_;
449 }
450 
SerializedVarTestConstructor(const PP_Var & pod_var)451 SerializedVarTestConstructor::SerializedVarTestConstructor(
452     const PP_Var& pod_var) {
453   DCHECK(pod_var.type != PP_VARTYPE_STRING);
454   inner_->ForceSetVarValueForTest(pod_var);
455 }
456 
SerializedVarTestConstructor(const std::string & str)457 SerializedVarTestConstructor::SerializedVarTestConstructor(
458     const std::string& str) {
459   inner_->ForceSetVarValueForTest(StringVar::StringToPPVar(str));
460 }
461 
SerializedVarTestReader(const SerializedVar & var)462 SerializedVarTestReader::SerializedVarTestReader(const SerializedVar& var)
463     : SerializedVar(var) {
464 }
465 
466 }  // namespace proxy
467 }  // namespace ppapi
468