Home | History | Annotate | Download | only in proxy
      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 {
     22 void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) {
     23   IPC::ParamTraits<SerializedHandle>::Write(m, handle);
     24 }
     25 }  // namespace
     26 
     27 // SerializedVar::Inner --------------------------------------------------------
     28 
     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 
     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 
     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 
     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 
     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 
     89 void SerializedVar::Inner::SetInstance(PP_Instance instance) {
     90   instance_ = instance;
     91 }
     92 
     93 void SerializedVar::Inner::ForceSetVarValueForTest(PP_Var value) {
     94   var_ = value;
     95   raw_var_data_.reset(NULL);
     96 }
     97 
     98 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 
    126 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 
    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 
    163 void SerializedVar::Inner::SetCleanupModeToEndSendPassRef() {
    164   cleanup_mode_ = END_SEND_PASS_REF;
    165 }
    166 
    167 void SerializedVar::Inner::SetCleanupModeToEndReceiveCallerOwned() {
    168   cleanup_mode_ = END_RECEIVE_CALLER_OWNED;
    169 }
    170 
    171 // SerializedVar ---------------------------------------------------------------
    172 
    173 SerializedVar::SerializedVar() : inner_(new Inner) {
    174 }
    175 
    176 SerializedVar::SerializedVar(VarSerializationRules* serialization_rules)
    177     : inner_(new Inner(serialization_rules)) {
    178 }
    179 
    180 SerializedVar::~SerializedVar() {
    181 }
    182 
    183 // SerializedVarSendInput ------------------------------------------------------
    184 
    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
    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 
    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 
    214 ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue() {
    215 }
    216 
    217 ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue(
    218     const SerializedVar& serialized)
    219     : SerializedVar(serialized) {
    220 }
    221 
    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 
    231 ReceiveSerializedException::ReceiveSerializedException(Dispatcher* dispatcher,
    232                                                        PP_Var* exception)
    233     : SerializedVar(dispatcher->serialization_rules()),
    234       exception_(exception) {
    235 }
    236 
    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 
    257 bool ReceiveSerializedException::IsThrown() const {
    258   return exception_ && exception_->type != PP_VARTYPE_UNDEFINED;
    259 }
    260 
    261 // ReceiveSerializedVarVectorOutParam ------------------------------------------
    262 
    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 
    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 
    289 std::vector<SerializedVar>* ReceiveSerializedVarVectorOutParam::OutParam() {
    290   return &vector_;
    291 }
    292 
    293 // SerializedVarReceiveInput ---------------------------------------------------
    294 
    295 SerializedVarReceiveInput::SerializedVarReceiveInput(
    296     const SerializedVar& serialized)
    297     : serialized_(serialized) {
    298 }
    299 
    300 SerializedVarReceiveInput::~SerializedVarReceiveInput() {
    301 }
    302 
    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 
    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 
    326 SerializedVarVectorReceiveInput::SerializedVarVectorReceiveInput(
    327     const std::vector<SerializedVar>& serialized)
    328     : serialized_(serialized) {
    329 }
    330 
    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 
    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 
    359 SerializedVarReturnValue::SerializedVarReturnValue(SerializedVar* serialized)
    360     : serialized_(serialized) {
    361 }
    362 
    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
    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 
    387 SerializedVarOutParam::SerializedVarOutParam(SerializedVar* serialized)
    388     : serialized_(serialized),
    389       writable_var_(PP_MakeUndefined()),
    390       dispatcher_(NULL) {
    391 }
    392 
    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 
    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 
    417 SerializedVarVectorOutParam::SerializedVarVectorOutParam(
    418     std::vector<SerializedVar>* serialized)
    419     : dispatcher_(NULL),
    420       serialized_(serialized),
    421       count_(0),
    422       array_(NULL) {
    423 }
    424 
    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 
    445 PP_Var** SerializedVarVectorOutParam::ArrayOutParam(Dispatcher* dispatcher) {
    446   DCHECK(!dispatcher_);  // Should only be called once.
    447   dispatcher_ = dispatcher;
    448   return &array_;
    449 }
    450 
    451 SerializedVarTestConstructor::SerializedVarTestConstructor(
    452     const PP_Var& pod_var) {
    453   DCHECK(pod_var.type != PP_VARTYPE_STRING);
    454   inner_->ForceSetVarValueForTest(pod_var);
    455 }
    456 
    457 SerializedVarTestConstructor::SerializedVarTestConstructor(
    458     const std::string& str) {
    459   inner_->ForceSetVarValueForTest(StringVar::StringToPPVar(str));
    460 }
    461 
    462 SerializedVarTestReader::SerializedVarTestReader(const SerializedVar& var)
    463     : SerializedVar(var) {
    464 }
    465 
    466 }  // namespace proxy
    467 }  // namespace ppapi
    468