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 #endif 72 73 if (raw_var_data_.get()) { 74 var_ = raw_var_data_->CreatePPVar(instance_); 75 raw_var_data_.reset(NULL); 76 } 77 78 return var_; 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