• 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