OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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/ref_counted.h" |
| 13 #include "ppapi/c/pp_var.h" |
| 14 |
| 15 namespace IPC { |
| 16 class Message; |
| 17 } |
| 18 |
| 19 namespace pp { |
| 20 namespace proxy { |
| 21 |
| 22 class Dispatcher; |
| 23 class VarSerializationRules; |
| 24 |
| 25 // This class encapsulates a var so that we can serialize and deserialize it |
| 26 // The problem is that for strings, serialization and deserialization requires |
| 27 // knowledge from outside about how to get at or create a string. So this |
| 28 // object groups the var with a dispatcher so that string values can be set or |
| 29 // gotten. |
| 30 // |
| 31 // Declare IPC messages as using this type, but don't use it directly (it has |
| 32 // no useful public methods). Instead, instantiate one of the helper classes |
| 33 // below which are conveniently named for each use case to prevent screwups. |
| 34 // |
| 35 // Design background |
| 36 // ----------------- |
| 37 // This is sadly super complicated. The IPC system needs a consistent type to |
| 38 // use for sending and receiving vars (this is a SerializedVar). But there are |
| 39 // different combinations of reference counting for sending and receiving |
| 40 // objects and for dealing with strings |
| 41 // |
| 42 // This makes SerializedVar complicate and easy to mess up. To make it |
| 43 // reasonable to use all functions are protected and there are a use-specific |
| 44 // classes that encapsulate exactly one type of use in a way that typically |
| 45 // won't compile if you do the wrong thing. |
| 46 // |
| 47 // The IPC system is designed to pass things around and will make copies in |
| 48 // some cases, so our system must be designed so that this stuff will work. |
| 49 // This is challenging when the SerializedVar must to some cleanup after the |
| 50 // message is sent. To work around this, we create an inner class using a |
| 51 // linked_ptr so all copies of a SerializedVar can share and we can guarantee |
| 52 // that the actual data will get cleaned up on shutdown. |
| 53 // |
| 54 // Constness |
| 55 // --------- |
| 56 // SerializedVar basically doesn't support const. Everything is mutable and |
| 57 // most functions are declared const. This unfortunateness is because of the |
| 58 // way the IPC system works. When deserializing, it will have a const |
| 59 // SerializedVar in a Tuple and this will be given to the function. We kind of |
| 60 // want to modify that to convert strings and do refcounting. |
| 61 // |
| 62 // The helper classes used for accessing the SerializedVar have more reasonable |
| 63 // behavior and will enforce that you don't do stupid things. |
| 64 class SerializedVar { |
| 65 public: |
| 66 enum CleanupMode { |
| 67 // The serialized var won't do anything special in the destructor (default). |
| 68 CLEANUP_NONE, |
| 69 |
| 70 // The serialized var will call EndSendPassRef in the destructor. |
| 71 END_SEND_PASS_REF, |
| 72 |
| 73 // The serialized var will call EndReceiveCallerOwned in the destructor. |
| 74 END_RECEIVE_CALLER_OWNED |
| 75 }; |
| 76 |
| 77 SerializedVar(); |
| 78 ~SerializedVar(); |
| 79 |
| 80 // Backend implementation for IPC::ParamTraits<SerializedVar>. |
| 81 void WriteToMessage(IPC::Message* m) const { |
| 82 inner_->WriteToMessage(m); |
| 83 } |
| 84 bool ReadFromMessage(const IPC::Message* m, void** iter) { |
| 85 return inner_->ReadFromMessage(m, iter); |
| 86 } |
| 87 |
| 88 protected: |
| 89 friend class SerializedVarReceiveInput; |
| 90 friend class SerializedVarReturnValue; |
| 91 friend class SerializedVarOutParam; |
| 92 friend class SerializedVarSendInput; |
| 93 friend class SerializedVarVectorReceiveInput; |
| 94 |
| 95 class Inner : public base::RefCounted<Inner> { |
| 96 public: |
| 97 Inner(); |
| 98 Inner(VarSerializationRules* serialization_rules); |
| 99 Inner(VarSerializationRules* serialization_rules, const PP_Var& var); |
| 100 ~Inner(); |
| 101 |
| 102 VarSerializationRules* serialization_rules() { |
| 103 return serialization_rules_; |
| 104 } |
| 105 void set_serialization_rules(VarSerializationRules* serialization_rules) { |
| 106 serialization_rules_ = serialization_rules; |
| 107 } |
| 108 |
| 109 void set_cleanup_mode(CleanupMode cm) { cleanup_mode_ = cm; } |
| 110 |
| 111 // See outer class's declarations above. |
| 112 PP_Var GetVar() const; |
| 113 PP_Var GetIncompleteVar() const; |
| 114 void SetVar(PP_Var var); |
| 115 const std::string& GetString() const; |
| 116 std::string* GetStringPtr(); |
| 117 |
| 118 void WriteToMessage(IPC::Message* m) const; |
| 119 bool ReadFromMessage(const IPC::Message* m, void** iter); |
| 120 |
| 121 private: |
| 122 // Rules for serializing and deserializing vars for this process type. |
| 123 // This may be NULL, but must be set before trying to serialize to IPC when |
| 124 // sending, or before converting back to a PP_Var when receiving. |
| 125 VarSerializationRules* serialization_rules_; |
| 126 |
| 127 // If this is set to VARTYPE_STRING and the 'value.id' is 0, then the |
| 128 // string_value_ contains the string. This means that the caller hasn't |
| 129 // called Deserialize with a valid Dispatcher yet, which is how we can |
| 130 // convert the serialized string value to a PP_Var string ID. |
| 131 // |
| 132 // This var may not be complete until the serialization rules are set when |
| 133 // reading from IPC since we'll need that to convert the string_value to |
| 134 // a string ID. Before this, the as_id will be 0 for VARTYPE_STRING. |
| 135 PP_Var var_; |
| 136 |
| 137 // Holds the literal string value to/from IPC. This will be valid of the |
| 138 // var_ is VARTYPE_STRING. |
| 139 std::string string_value_; |
| 140 |
| 141 CleanupMode cleanup_mode_; |
| 142 |
| 143 #ifndef NDEBUG |
| 144 // When being sent or received over IPC, we should only be serialized or |
| 145 // deserialized once. These flags help us assert this is true. |
| 146 mutable bool has_been_serialized_; |
| 147 mutable bool has_been_deserialized_; |
| 148 #endif |
| 149 |
| 150 DISALLOW_COPY_AND_ASSIGN(Inner); |
| 151 }; |
| 152 |
| 153 SerializedVar(VarSerializationRules* serialization_rules); |
| 154 SerializedVar(VarSerializationRules* serialization, const PP_Var& var); |
| 155 |
| 156 mutable scoped_refptr<Inner> inner_; |
| 157 }; |
| 158 |
| 159 // Helpers for message sending side -------------------------------------------- |
| 160 |
| 161 // For sending a value to the remote side. |
| 162 // |
| 163 // Example for API: |
| 164 // void MyFunction(PP_Var) |
| 165 // IPC message: |
| 166 // IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar); |
| 167 // Sender would be: |
| 168 // void MyFunctionProxy(PP_Var param) { |
| 169 // Send(new MyFunctionMsg(SerializedVarSendInput(param)); |
| 170 // } |
| 171 class SerializedVarSendInput : public SerializedVar { |
| 172 public: |
| 173 SerializedVarSendInput(Dispatcher* dispatcher, const PP_Var& var); |
| 174 |
| 175 // Helper function for serializing a vector of input vars for serialization. |
| 176 static void ConvertVector(Dispatcher* dispatcher, |
| 177 const PP_Var* input, |
| 178 size_t input_count, |
| 179 std::vector<SerializedVar>* output); |
| 180 |
| 181 private: |
| 182 // Disallow the empty constructor, but keep the default copy constructor |
| 183 // which is required to send the object to the IPC system. |
| 184 SerializedVarSendInput(); |
| 185 }; |
| 186 |
| 187 // For the calling side of a function returning a var. The sending side uses |
| 188 // SerializedVarReturnValue. |
| 189 // |
| 190 // Example for API: |
| 191 // PP_Var MyFunction() |
| 192 // IPC message: |
| 193 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); |
| 194 // Message handler would be: |
| 195 // PP_Var MyFunctionProxy() { |
| 196 // ReceiveSerializedVarReturnValue result; |
| 197 // Send(new MyFunctionMsg(&result)); |
| 198 // return result.Return(dispatcher()); |
| 199 // } |
| 200 class ReceiveSerializedVarReturnValue : public SerializedVar { |
| 201 public: |
| 202 // Note that we can't set the dispatcher in the constructor because the |
| 203 // data will be overridden when the return value is set. |
| 204 ReceiveSerializedVarReturnValue(); |
| 205 |
| 206 PP_Var Return(Dispatcher* dispatcher); |
| 207 |
| 208 private: |
| 209 DISALLOW_COPY_AND_ASSIGN(ReceiveSerializedVarReturnValue); |
| 210 }; |
| 211 |
| 212 // Example for API: |
| 213 // "void MyFunction(PP_Var* exception);" |
| 214 // IPC message: |
| 215 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); |
| 216 // Message handler would be: |
| 217 // void OnMsgMyFunction(PP_Var* exception) { |
| 218 // ReceiveSerializedException se(dispatcher(), exception) |
| 219 // Send(new PpapiHostMsg_Foo(&se)); |
| 220 // } |
| 221 class ReceiveSerializedException : public SerializedVar { |
| 222 public: |
| 223 ReceiveSerializedException(Dispatcher* dispatcher, PP_Var* exception); |
| 224 ~ReceiveSerializedException(); |
| 225 |
| 226 // Returns true if the exception passed in the constructor is set. Check |
| 227 // this before actually issuing the IPC. |
| 228 bool IsThrown() const; |
| 229 |
| 230 private: |
| 231 // The input/output exception we're wrapping. May be NULL. |
| 232 PP_Var* exception_; |
| 233 |
| 234 DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedException); |
| 235 }; |
| 236 |
| 237 // Helper class for when we're returning a vector of Vars. When it goes out |
| 238 // of scope it will automatically convert the vector filled by the IPC layer |
| 239 // into the array specified by the constructor params. |
| 240 // |
| 241 // Example for API: |
| 242 // "void MyFunction(uint32_t* count, PP_Var** vars);" |
| 243 // IPC message: |
| 244 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, std::vector<SerializedVar>); |
| 245 // Proxy function: |
| 246 // void MyFunction(uint32_t* count, PP_Var** vars) { |
| 247 // ReceiveSerializedVarVectorOutParam vect(dispatcher, count, vars); |
| 248 // Send(new MyMsg(vect.OutParam())); |
| 249 // } |
| 250 class ReceiveSerializedVarVectorOutParam { |
| 251 public: |
| 252 ReceiveSerializedVarVectorOutParam(Dispatcher* dispatcher, |
| 253 uint32_t* output_count, |
| 254 PP_Var** output); |
| 255 ~ReceiveSerializedVarVectorOutParam(); |
| 256 |
| 257 std::vector<SerializedVar>* OutParam(); |
| 258 |
| 259 private: |
| 260 Dispatcher* dispatcher_; |
| 261 uint32_t* output_count_; |
| 262 PP_Var** output_; |
| 263 |
| 264 std::vector<SerializedVar> vector_; |
| 265 |
| 266 DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedVarVectorOutParam); |
| 267 }; |
| 268 |
| 269 // Helpers for message receiving side ------------------------------------------ |
| 270 |
| 271 // For receiving a value from the remote side. |
| 272 // |
| 273 // Example for API: |
| 274 // void MyFunction(PP_Var) |
| 275 // IPC message: |
| 276 // IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar); |
| 277 // Message handler would be: |
| 278 // void OnMsgMyFunction(SerializedVarReceiveInput param) { |
| 279 // MyFunction(param.Get()); |
| 280 // } |
| 281 class SerializedVarReceiveInput { |
| 282 public: |
| 283 // We rely on the implicit constructor here since the IPC layer will call |
| 284 // us with a SerializedVar. Pass this object by value, the copy constructor |
| 285 // will pass along the pointer (as cheap as passing a pointer arg). |
| 286 SerializedVarReceiveInput(const SerializedVar& serialized); |
| 287 ~SerializedVarReceiveInput(); |
| 288 |
| 289 PP_Var Get(Dispatcher* dispatcher); |
| 290 |
| 291 private: |
| 292 const SerializedVar& serialized_; |
| 293 |
| 294 // Since the SerializedVar is const, we can't set its dispatcher (which is |
| 295 // OK since we don't need to). But since we need it for our own uses, we |
| 296 // track it here. Will be NULL before Get() is called. |
| 297 Dispatcher* dispatcher_; |
| 298 PP_Var var_; |
| 299 }; |
| 300 |
| 301 // For receiving an input vector of vars from the remote side. |
| 302 // |
| 303 // Example: |
| 304 // OnMsgMyFunction(SerializedVarVectorReceiveInput vector) { |
| 305 // uint32_t size; |
| 306 // PP_Var* array = vector.Get(dispatcher, &size); |
| 307 // MyFunction(size, array); |
| 308 // } |
| 309 class SerializedVarVectorReceiveInput { |
| 310 public: |
| 311 SerializedVarVectorReceiveInput(const std::vector<SerializedVar>& serialized); |
| 312 ~SerializedVarVectorReceiveInput(); |
| 313 |
| 314 // Only call Get() once. It will return a pointer to the converted array and |
| 315 // place the array size in the out param. Will return NULL when the array is |
| 316 // empty. |
| 317 PP_Var* Get(Dispatcher* dispatcher, uint32_t* array_size); |
| 318 |
| 319 private: |
| 320 const std::vector<SerializedVar>& serialized_; |
| 321 |
| 322 // Filled by Get(). |
| 323 std::vector<PP_Var> deserialized_; |
| 324 }; |
| 325 |
| 326 // For the receiving side of a function returning a var. The calling side uses |
| 327 // ReceiveSerializedVarReturnValue. |
| 328 // |
| 329 // Example for API: |
| 330 // PP_Var MyFunction() |
| 331 // IPC message: |
| 332 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); |
| 333 // Message handler would be: |
| 334 // void OnMsgMyFunction(SerializedVarReturnValue result) { |
| 335 // result.Return(dispatcher(), MyFunction()); |
| 336 // } |
| 337 class SerializedVarReturnValue { |
| 338 public: |
| 339 // We rely on the implicit constructor here since the IPC layer will call |
| 340 // us with a SerializedVar*. Pass this object by value, the copy constructor |
| 341 // will pass along the pointer (as cheap as passing a pointer arg). |
| 342 SerializedVarReturnValue(SerializedVar* serialized); |
| 343 |
| 344 void Return(Dispatcher* dispatcher, const PP_Var& var); |
| 345 |
| 346 private: |
| 347 SerializedVar* serialized_; |
| 348 }; |
| 349 |
| 350 // For writing an out param to the remote side. |
| 351 // |
| 352 // Example for API: |
| 353 // "void MyFunction(PP_Var* out);" |
| 354 // IPC message: |
| 355 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); |
| 356 // Message handler would be: |
| 357 // void OnMsgMyFunction(SerializedVarOutParam out_param) { |
| 358 // MyFunction(out_param.OutParam(dispatcher())); |
| 359 // } |
| 360 class SerializedVarOutParam { |
| 361 public: |
| 362 // We rely on the implicit constructor here since the IPC layer will call |
| 363 // us with a SerializedVar*. Pass this object by value, the copy constructor |
| 364 // will pass along the pointer (as cheap as passing a pointer arg). |
| 365 SerializedVarOutParam(SerializedVar* serialized); |
| 366 ~SerializedVarOutParam(); |
| 367 |
| 368 // Call this function only once. The caller should write its result to the |
| 369 // returned var pointer before this class goes out of scope. The var's |
| 370 // initial value will be VARTYPE_UNDEFINED. |
| 371 PP_Var* OutParam(Dispatcher* dispatcher); |
| 372 |
| 373 private: |
| 374 SerializedVar* serialized_; |
| 375 |
| 376 // This is the value actually written by the code and returned by OutParam. |
| 377 // We'll write this into serialized_ in our destructor. |
| 378 PP_Var writable_var_; |
| 379 }; |
| 380 |
| 381 // For returning an array of PP_Vars to the other side and transferring |
| 382 // ownership. |
| 383 // |
| 384 class SerializedVarVectorOutParam { |
| 385 public: |
| 386 SerializedVarVectorOutParam(std::vector<SerializedVar>* serialized); |
| 387 ~SerializedVarVectorOutParam(); |
| 388 |
| 389 uint32_t* CountOutParam() { return &count_; } |
| 390 PP_Var** ArrayOutParam(Dispatcher* dispatcher); |
| 391 |
| 392 private: |
| 393 Dispatcher* dispatcher_; |
| 394 std::vector<SerializedVar>* serialized_; |
| 395 |
| 396 uint32_t count_; |
| 397 PP_Var* array_; |
| 398 }; |
| 399 |
| 400 } // namespace proxy |
| 401 } // namespace pp |
| 402 |
| 403 #endif // PPAPI_PROXY_SERIALIZED_VAR_H_ |
| 404 |
OLD | NEW |