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 #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>.
     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.
     86   void WriteDataToMessage(IPC::Message* m,
     87                           const HandleWriter& handle_writer) const {
     88     inner_->WriteDataToMessage(m, handle_writer);
     89   }
     90   bool ReadFromMessage(const IPC::Message* m, PickleIterator* iter) {
     91     return inner_->ReadFromMessage(m, iter);
     92   }
     93 
     94   bool is_valid_var() const {
     95     return inner_->is_valid_var();
     96   }
     97 
     98   // Returns the shared memory handles associated with this SerializedVar.
     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 
    118     VarSerializationRules* serialization_rules() {
    119       return serialization_rules_.get();
    120     }
    121     void set_serialization_rules(VarSerializationRules* serialization_rules) {
    122       serialization_rules_ = serialization_rules;
    123     }
    124 
    125     bool is_valid_var() const {
    126       return is_valid_var_;
    127     }
    128 
    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);
    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 
    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 
    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