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 #ifndef PPAPI_PROXY_SERIALIZED_VAR_H_ 6 #define PPAPI_PROXY_SERIALIZED_VAR_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/shared_memory.h" 15 #include "ppapi/c/pp_instance.h" 16 #include "ppapi/c/pp_var.h" 17 #include "ppapi/proxy/ppapi_proxy_export.h" 18 #include "ppapi/proxy/raw_var_data.h" 19 #include "ppapi/proxy/serialized_handle.h" 20 #include "ppapi/proxy/serialized_structs.h" 21 #include "ppapi/proxy/var_serialization_rules.h" 22 23 class PickleIterator; 24 25 namespace IPC { 26 class Message; 27 } 28 29 namespace ppapi { 30 namespace proxy { 31 32 class Dispatcher; 33 class VarSerializationRules; 34 35 // This class encapsulates a var so that we can serialize and deserialize it. 36 // The problem is that for strings, serialization and deserialization requires 37 // knowledge from outside about how to get at or create a string. So this 38 // object groups the var with a dispatcher so that string values can be set or 39 // gotten. 40 // 41 // Declare IPC messages as using this type, but don't use it directly (it has 42 // no useful public methods). Instead, instantiate one of the helper classes 43 // below which are conveniently named for each use case to prevent screwups. 44 // 45 // Design background 46 // ----------------- 47 // This is sadly super complicated. The IPC system needs a consistent type to 48 // use for sending and receiving vars (this is a SerializedVar). But there are 49 // different combinations of reference counting for sending and receiving 50 // objects and for dealing with strings 51 // 52 // This makes SerializedVar complicated and easy to mess up. To make it 53 // reasonable to use, all functions are protected and there are use-specific 54 // classes that each encapsulate exactly one type of use in a way that typically 55 // won't compile if you do the wrong thing. 56 // 57 // The IPC system is designed to pass things around and will make copies in 58 // some cases, so our system must be designed so that this stuff will work. 59 // This is challenging when the SerializedVar must do some cleanup after the 60 // message is sent. To work around this, we create an inner class using a 61 // linked_ptr so all copies of a SerializedVar can share and we can guarantee 62 // that the actual data will get cleaned up on shutdown. 63 // 64 // Constness 65 // --------- 66 // SerializedVar basically doesn't support const. Everything is mutable and 67 // most functions are declared const. This unfortunateness is because of the 68 // way the IPC system works. When deserializing, it will have a const 69 // SerializedVar in a Tuple and this will be given to the function. We kind of 70 // want to modify that to convert strings and do refcounting. 71 // 72 // The helper classes used for accessing the SerializedVar have more reasonable 73 // behavior and will enforce that you don't do stupid things. 74 class PPAPI_PROXY_EXPORT SerializedVar { 75 public: 76 SerializedVar(); 77 ~SerializedVar(); 78 79 // Backend implementation for IPC::ParamTraits<SerializedVar>. WriteToMessage(IPC::Message * m)80 void WriteToMessage(IPC::Message* m) const { 81 inner_->WriteToMessage(m); 82 } 83 // If ReadFromMessage has been called, WriteDataToMessage will write the var 84 // that has been read from ReadFromMessage back to a message. This is used 85 // when converting handles for use in NaCl. WriteDataToMessage(IPC::Message * m,const HandleWriter & handle_writer)86 void WriteDataToMessage(IPC::Message* m, 87 const HandleWriter& handle_writer) const { 88 inner_->WriteDataToMessage(m, handle_writer); 89 } ReadFromMessage(const IPC::Message * m,PickleIterator * iter)90 bool ReadFromMessage(const IPC::Message* m, PickleIterator* iter) { 91 return inner_->ReadFromMessage(m, iter); 92 } 93 is_valid_var()94 bool is_valid_var() const { 95 return inner_->is_valid_var(); 96 } 97 98 // Returns the shared memory handles associated with this SerializedVar. GetHandles()99 std::vector<SerializedHandle*> GetHandles() const { 100 return inner_->GetHandles(); 101 } 102 103 protected: 104 friend class SerializedVarReceiveInput; 105 friend class SerializedVarReturnValue; 106 friend class SerializedVarOutParam; 107 friend class SerializedVarSendInput; 108 friend class SerializedVarSendInputShmem; 109 friend class SerializedVarTestConstructor; 110 friend class SerializedVarVectorReceiveInput; 111 112 class PPAPI_PROXY_EXPORT Inner : public base::RefCounted<Inner> { 113 public: 114 Inner(); 115 Inner(VarSerializationRules* serialization_rules); 116 ~Inner(); 117 serialization_rules()118 VarSerializationRules* serialization_rules() { 119 return serialization_rules_.get(); 120 } set_serialization_rules(VarSerializationRules * serialization_rules)121 void set_serialization_rules(VarSerializationRules* serialization_rules) { 122 serialization_rules_ = serialization_rules; 123 } 124 is_valid_var()125 bool is_valid_var() const { 126 return is_valid_var_; 127 } 128 GetHandles()129 std::vector<SerializedHandle*> GetHandles() { 130 return (raw_var_data_ ? raw_var_data_->GetHandles() : 131 std::vector<SerializedHandle*>()); 132 } 133 134 // See outer class's declarations above. 135 PP_Var GetVar(); 136 void SetVar(PP_Var var); 137 void SetInstance(PP_Instance instance); 138 139 // For the SerializedVarTestConstructor, this writes the Var value as if 140 // it was just received off the wire, without any serialization rules. 141 void ForceSetVarValueForTest(PP_Var value); 142 143 void WriteToMessage(IPC::Message* m) const; 144 void WriteDataToMessage(IPC::Message* m, 145 const HandleWriter& handle_writer) const; 146 bool ReadFromMessage(const IPC::Message* m, PickleIterator* iter); 147 148 // Sets the cleanup mode. See the CleanupMode enum below. 149 void SetCleanupModeToEndSendPassRef(); 150 void SetCleanupModeToEndReceiveCallerOwned(); 151 152 private: 153 enum CleanupMode { 154 // The serialized var won't do anything special in the destructor 155 // (default). 156 CLEANUP_NONE, 157 158 // The serialized var will call EndSendPassRef in the destructor. 159 END_SEND_PASS_REF, 160 161 // The serialized var will call EndReceiveCallerOwned in the destructor. 162 END_RECEIVE_CALLER_OWNED 163 }; 164 165 // Rules for serializing and deserializing vars for this process type. 166 // This may be NULL, but must be set before trying to serialize to IPC when 167 // sending, or before converting back to a PP_Var when receiving. 168 scoped_refptr<VarSerializationRules> serialization_rules_; 169 170 // If this is set to VARTYPE_STRING and the 'value.id' is 0, then the 171 // string_from_ipc_ holds the string. This means that the caller hasn't 172 // called Deserialize with a valid Dispatcher yet, which is how we can 173 // convert the serialized string value to a PP_Var string ID. 174 // 175 // This var may not be complete until the serialization rules are set when 176 // reading from IPC since we'll need that to convert the string_value to 177 // a string ID. Before this, the as_id will be 0 for VARTYPE_STRING. 178 PP_Var var_; 179 180 PP_Instance instance_; 181 182 CleanupMode cleanup_mode_; 183 184 // If the var is not properly serialized, this will be false. 185 bool is_valid_var_; 186 187 #ifndef NDEBUG 188 // When being sent or received over IPC, we should only be serialized or 189 // deserialized once. These flags help us assert this is true. 190 mutable bool has_been_serialized_; 191 mutable bool has_been_deserialized_; 192 #endif 193 194 // ReadFromMessage() may be called on the I/O thread, e.g., when reading the 195 // reply to a sync message. We cannot use the var tracker on the I/O thread, 196 // which means we cannot create some types of PP_Var 197 // (e.g. PP_VARTYPE_STRING). The data is stored in |raw_var_data_| and the 198 // PP_Var is constructed when |GetVar()| is called. 199 scoped_ptr<RawVarDataGraph> raw_var_data_; 200 201 DISALLOW_COPY_AND_ASSIGN(Inner); 202 }; 203 204 SerializedVar(VarSerializationRules* serialization_rules); 205 206 mutable scoped_refptr<Inner> inner_; 207 }; 208 209 // Helpers for message sending side -------------------------------------------- 210 211 // For sending a value to the remote side. 212 // 213 // Example for API: 214 // void MyFunction(PP_Var) 215 // IPC message: 216 // IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar); 217 // Sender would be: 218 // void MyFunctionProxy(PP_Var param) { 219 // Send(new MyFunctionMsg(SerializedVarSendInput(dispatcher, param)); 220 // } 221 class PPAPI_PROXY_EXPORT SerializedVarSendInput : public SerializedVar { 222 public: 223 SerializedVarSendInput(Dispatcher* dispatcher, const PP_Var& var); 224 225 // Helper function for serializing a vector of input vars for serialization. 226 static void ConvertVector(Dispatcher* dispatcher, 227 const PP_Var* input, 228 size_t input_count, 229 std::vector<SerializedVar>* output); 230 231 private: 232 // Disallow the empty constructor, but keep the default copy constructor 233 // which is required to send the object to the IPC system. 234 SerializedVarSendInput(); 235 }; 236 237 // Specialization for optionally sending over shared memory. 238 class PPAPI_PROXY_EXPORT SerializedVarSendInputShmem : public SerializedVar { 239 public: 240 SerializedVarSendInputShmem(Dispatcher* dispatcher, const PP_Var& var, 241 const PP_Instance& instance); 242 243 private: 244 // Disallow the empty constructor, but keep the default copy constructor 245 // which is required to send the object to the IPC system. 246 SerializedVarSendInputShmem(); 247 }; 248 249 250 // For the calling side of a function returning a var. The sending side uses 251 // SerializedVarReturnValue. 252 // 253 // Example for API: 254 // PP_Var MyFunction() 255 // IPC message: 256 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); 257 // Message handler would be: 258 // PP_Var MyFunctionProxy() { 259 // ReceiveSerializedVarReturnValue result; 260 // Send(new MyFunctionMsg(&result)); 261 // return result.Return(dispatcher()); 262 // } 263 // 264 // TODO(yzshen): Move the dispatcher parameter to the constructor and store a 265 // VarSerializationRules reference instead, in case the dispatcher is destroyed 266 // while waiting for reply to the sync message. 267 class PPAPI_PROXY_EXPORT ReceiveSerializedVarReturnValue 268 : public SerializedVar { 269 public: 270 // Note that we can't set the dispatcher in the constructor because the 271 // data will be overridden when the return value is set. This constructor is 272 // normally used in the pattern above (operator= will be implicitly invoked 273 // when the sync message writes the output values). 274 ReceiveSerializedVarReturnValue(); 275 276 // This constructor can be used when deserializing manually. This is useful 277 // when you're getting strings "returned" via a struct and need to manually 278 // get the PP_Vars out. In this case just do: 279 // ReceiveSerializedVarReturnValue(serialized).Return(dispatcher); 280 explicit ReceiveSerializedVarReturnValue(const SerializedVar& serialized); 281 282 PP_Var Return(Dispatcher* dispatcher); 283 284 private: 285 DISALLOW_COPY_AND_ASSIGN(ReceiveSerializedVarReturnValue); 286 }; 287 288 // Example for API: 289 // "void MyFunction(PP_Var* exception);" 290 // IPC message: 291 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); 292 // Message handler would be: 293 // void OnMsgMyFunction(PP_Var* exception) { 294 // ReceiveSerializedException se(dispatcher(), exception) 295 // Send(new PpapiHostMsg_Foo(&se)); 296 // } 297 class PPAPI_PROXY_EXPORT ReceiveSerializedException : public SerializedVar { 298 public: 299 ReceiveSerializedException(Dispatcher* dispatcher, PP_Var* exception); 300 ~ReceiveSerializedException(); 301 302 // Returns true if the exception passed in the constructor is set. Check 303 // this before actually issuing the IPC. 304 bool IsThrown() const; 305 306 private: 307 // The input/output exception we're wrapping. May be NULL. 308 PP_Var* exception_; 309 310 DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedException); 311 }; 312 313 // Helper class for when we're returning a vector of Vars. When it goes out 314 // of scope it will automatically convert the vector filled by the IPC layer 315 // into the array specified by the constructor params. 316 // 317 // Example for API: 318 // "void MyFunction(uint32_t* count, PP_Var** vars);" 319 // IPC message: 320 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, std::vector<SerializedVar>); 321 // Proxy function: 322 // void MyFunction(uint32_t* count, PP_Var** vars) { 323 // ReceiveSerializedVarVectorOutParam vect(dispatcher, count, vars); 324 // Send(new MyMsg(vect.OutParam())); 325 // } 326 class PPAPI_PROXY_EXPORT ReceiveSerializedVarVectorOutParam { 327 public: 328 ReceiveSerializedVarVectorOutParam(Dispatcher* dispatcher, 329 uint32_t* output_count, 330 PP_Var** output); 331 ~ReceiveSerializedVarVectorOutParam(); 332 333 std::vector<SerializedVar>* OutParam(); 334 335 private: 336 Dispatcher* dispatcher_; 337 uint32_t* output_count_; 338 PP_Var** output_; 339 340 std::vector<SerializedVar> vector_; 341 342 DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedVarVectorOutParam); 343 }; 344 345 // Helpers for message receiving side ------------------------------------------ 346 347 // For receiving a value from the remote side. 348 // 349 // Example for API: 350 // void MyFunction(PP_Var) 351 // IPC message: 352 // IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar); 353 // Message handler would be: 354 // void OnMsgMyFunction(SerializedVarReceiveInput param) { 355 // MyFunction(param.Get()); 356 // } 357 class PPAPI_PROXY_EXPORT SerializedVarReceiveInput { 358 public: 359 // We rely on the implicit constructor here since the IPC layer will call 360 // us with a SerializedVar. Pass this object by value, the copy constructor 361 // will pass along the pointer (as cheap as passing a pointer arg). 362 SerializedVarReceiveInput(const SerializedVar& serialized); 363 ~SerializedVarReceiveInput(); 364 365 PP_Var Get(Dispatcher* dispatcher); 366 PP_Var GetForInstance(Dispatcher* dispatcher, PP_Instance instance); is_valid_var()367 bool is_valid_var() { return serialized_.is_valid_var(); } 368 369 private: 370 const SerializedVar& serialized_; 371 }; 372 373 // For receiving an input vector of vars from the remote side. 374 // 375 // Example: 376 // OnMsgMyFunction(SerializedVarVectorReceiveInput vector) { 377 // uint32_t size; 378 // PP_Var* array = vector.Get(dispatcher, &size); 379 // MyFunction(size, array); 380 // } 381 class PPAPI_PROXY_EXPORT SerializedVarVectorReceiveInput { 382 public: 383 SerializedVarVectorReceiveInput(const std::vector<SerializedVar>& serialized); 384 ~SerializedVarVectorReceiveInput(); 385 386 // Only call Get() once. It will return a pointer to the converted array and 387 // place the array size in the out param. Will return NULL when the array is 388 // empty. 389 PP_Var* Get(Dispatcher* dispatcher, uint32_t* array_size); 390 391 private: 392 const std::vector<SerializedVar>& serialized_; 393 394 // Filled by Get(). 395 std::vector<PP_Var> deserialized_; 396 }; 397 398 // For the receiving side of a function returning a var. The calling side uses 399 // ReceiveSerializedVarReturnValue. 400 // 401 // Example for API: 402 // PP_Var MyFunction() 403 // IPC message: 404 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); 405 // Message handler would be: 406 // void OnMsgMyFunction(SerializedVarReturnValue result) { 407 // result.Return(dispatcher(), MyFunction()); 408 // } 409 class PPAPI_PROXY_EXPORT SerializedVarReturnValue { 410 public: 411 // We rely on the implicit constructor here since the IPC layer will call 412 // us with a SerializedVar*. Pass this object by value, the copy constructor 413 // will pass along the pointer (as cheap as passing a pointer arg). 414 SerializedVarReturnValue(SerializedVar* serialized); 415 416 void Return(Dispatcher* dispatcher, const PP_Var& var); 417 418 // Helper function for code that doesn't use the pattern above, but gets 419 // a return value from the remote side via a struct. You can pass in the 420 // SerializedVar and a PP_Var will be created with return value semantics. 421 static SerializedVar Convert(Dispatcher* dispatcher, const PP_Var& var); 422 423 private: 424 SerializedVar* serialized_; 425 }; 426 427 // For writing an out param to the remote side. 428 // 429 // Example for API: 430 // "void MyFunction(PP_Var* out);" 431 // IPC message: 432 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); 433 // Message handler would be: 434 // void OnMsgMyFunction(SerializedVarOutParam out_param) { 435 // MyFunction(out_param.OutParam(dispatcher())); 436 // } 437 class PPAPI_PROXY_EXPORT SerializedVarOutParam { 438 public: 439 // We rely on the implicit constructor here since the IPC layer will call 440 // us with a SerializedVar*. Pass this object by value, the copy constructor 441 // will pass along the pointer (as cheap as passing a pointer arg). 442 SerializedVarOutParam(SerializedVar* serialized); 443 ~SerializedVarOutParam(); 444 445 // Call this function only once. The caller should write its result to the 446 // returned var pointer before this class goes out of scope. The var's 447 // initial value will be VARTYPE_UNDEFINED. 448 PP_Var* OutParam(Dispatcher* dispatcher); 449 450 private: 451 SerializedVar* serialized_; 452 453 // This is the value actually written by the code and returned by OutParam. 454 // We'll write this into serialized_ in our destructor. 455 PP_Var writable_var_; 456 457 Dispatcher* dispatcher_; 458 }; 459 460 // For returning an array of PP_Vars to the other side and transferring 461 // ownership. 462 // 463 class PPAPI_PROXY_EXPORT SerializedVarVectorOutParam { 464 public: 465 SerializedVarVectorOutParam(std::vector<SerializedVar>* serialized); 466 ~SerializedVarVectorOutParam(); 467 CountOutParam()468 uint32_t* CountOutParam() { return &count_; } 469 PP_Var** ArrayOutParam(Dispatcher* dispatcher); 470 471 private: 472 Dispatcher* dispatcher_; 473 std::vector<SerializedVar>* serialized_; 474 475 uint32_t count_; 476 PP_Var* array_; 477 }; 478 479 // For tests that just want to construct a SerializedVar for giving it to one 480 // of the other classes. This emulates a SerializedVar just received over the 481 // wire from another process. 482 class PPAPI_PROXY_EXPORT SerializedVarTestConstructor : public SerializedVar { 483 public: 484 // For POD-types and objects. 485 explicit SerializedVarTestConstructor(const PP_Var& pod_var); 486 487 // For strings. 488 explicit SerializedVarTestConstructor(const std::string& str); 489 }; 490 491 // For tests that want to read what's in a SerializedVar. 492 class PPAPI_PROXY_EXPORT SerializedVarTestReader : public SerializedVar { 493 public: 494 explicit SerializedVarTestReader(const SerializedVar& var); 495 GetVar()496 PP_Var GetVar() const { return inner_->GetVar(); } 497 }; 498 499 } // namespace proxy 500 } // namespace ppapi 501 502 #endif // PPAPI_PROXY_SERIALIZED_VAR_H_ 503