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