|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef PPAPI_PROXY_SERIALIZED_VAR_H_ | 
|  | #define PPAPI_PROXY_SERIALIZED_VAR_H_ | 
|  |  | 
|  | #include <stddef.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <memory> | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/macros.h" | 
|  | #include "base/memory/ref_counted.h" | 
|  | #include "ppapi/c/pp_instance.h" | 
|  | #include "ppapi/c/pp_var.h" | 
|  | #include "ppapi/proxy/ppapi_proxy_export.h" | 
|  | #include "ppapi/proxy/raw_var_data.h" | 
|  | #include "ppapi/proxy/serialized_handle.h" | 
|  | #include "ppapi/proxy/serialized_structs.h" | 
|  | #include "ppapi/proxy/var_serialization_rules.h" | 
|  |  | 
|  | namespace base { | 
|  | class PickleIterator; | 
|  | } | 
|  |  | 
|  | namespace IPC { | 
|  | class Message; | 
|  | } | 
|  |  | 
|  | namespace ppapi { | 
|  | namespace proxy { | 
|  |  | 
|  | class Dispatcher; | 
|  | class VarSerializationRules; | 
|  |  | 
|  | // This class encapsulates a var so that we can serialize and deserialize it. | 
|  | // The problem is that for strings, serialization and deserialization requires | 
|  | // knowledge from outside about how to get at or create a string. So this | 
|  | // object groups the var with a dispatcher so that string values can be set or | 
|  | // gotten. | 
|  | // | 
|  | // Declare IPC messages as using this type, but don't use it directly (it has | 
|  | // no useful public methods). Instead, instantiate one of the helper classes | 
|  | // below which are conveniently named for each use case to prevent screwups. | 
|  | // | 
|  | // Design background | 
|  | // ----------------- | 
|  | // This is sadly super complicated. The IPC system needs a consistent type to | 
|  | // use for sending and receiving vars (this is a SerializedVar). But there are | 
|  | // different combinations of reference counting for sending and receiving | 
|  | // objects and for dealing with strings | 
|  | // | 
|  | // This makes SerializedVar complicated and easy to mess up. To make it | 
|  | // reasonable to use, all functions are protected and there are use-specific | 
|  | // classes that each encapsulate exactly one type of use in a way that typically | 
|  | // won't compile if you do the wrong thing. | 
|  | // | 
|  | // The IPC system is designed to pass things around and will make copies in | 
|  | // some cases, so our system must be designed so that this stuff will work. | 
|  | // This is challenging when the SerializedVar must do some cleanup after the | 
|  | // message is sent. To work around this, we create an inner class using a | 
|  | // linked_ptr so all copies of a SerializedVar can share and we can guarantee | 
|  | // that the actual data will get cleaned up on shutdown. | 
|  | // | 
|  | // Constness | 
|  | // --------- | 
|  | // SerializedVar basically doesn't support const. Everything is mutable and | 
|  | // most functions are declared const. This unfortunateness is because of the | 
|  | // way the IPC system works. When deserializing, it will have a const | 
|  | // SerializedVar in a Tuple and this will be given to the function. We kind of | 
|  | // want to modify that to convert strings and do refcounting. | 
|  | // | 
|  | // The helper classes used for accessing the SerializedVar have more reasonable | 
|  | // behavior and will enforce that you don't do stupid things. | 
|  | class PPAPI_PROXY_EXPORT SerializedVar { | 
|  | public: | 
|  | SerializedVar(); | 
|  | ~SerializedVar(); | 
|  |  | 
|  | // Backend implementation for IPC::ParamTraits<SerializedVar>. | 
|  | void WriteToMessage(base::Pickle* m) const { inner_->WriteToMessage(m); } | 
|  | // If ReadFromMessage has been called, WriteDataToMessage will write the var | 
|  | // that has been read from ReadFromMessage back to a message. This is used | 
|  | // when converting handles for use in NaCl. | 
|  | void WriteDataToMessage(base::Pickle* m, | 
|  | const HandleWriter& handle_writer) const { | 
|  | inner_->WriteDataToMessage(m, handle_writer); | 
|  | } | 
|  | bool ReadFromMessage(const base::Pickle* m, base::PickleIterator* iter) { | 
|  | return inner_->ReadFromMessage(m, iter); | 
|  | } | 
|  |  | 
|  | bool is_valid_var() const { | 
|  | return inner_->is_valid_var(); | 
|  | } | 
|  |  | 
|  | // Returns the shared memory handles associated with this SerializedVar. | 
|  | std::vector<SerializedHandle*> GetHandles() const { | 
|  | return inner_->GetHandles(); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | friend class SerializedVarReceiveInput; | 
|  | friend class SerializedVarReturnValue; | 
|  | friend class SerializedVarOutParam; | 
|  | friend class SerializedVarSendInput; | 
|  | friend class SerializedVarSendInputShmem; | 
|  | friend class SerializedVarTestConstructor; | 
|  | friend class SerializedVarVectorReceiveInput; | 
|  |  | 
|  | class PPAPI_PROXY_EXPORT Inner : public base::RefCounted<Inner> { | 
|  | public: | 
|  | Inner(); | 
|  | Inner(VarSerializationRules* serialization_rules); | 
|  | ~Inner(); | 
|  |  | 
|  | VarSerializationRules* serialization_rules() { | 
|  | return serialization_rules_.get(); | 
|  | } | 
|  | void set_serialization_rules(VarSerializationRules* serialization_rules) { | 
|  | serialization_rules_ = serialization_rules; | 
|  | } | 
|  |  | 
|  | bool is_valid_var() const { | 
|  | return is_valid_var_; | 
|  | } | 
|  |  | 
|  | std::vector<SerializedHandle*> GetHandles() { | 
|  | return (raw_var_data_ ? raw_var_data_->GetHandles() : | 
|  | std::vector<SerializedHandle*>()); | 
|  | } | 
|  |  | 
|  | // See outer class's declarations above. | 
|  | PP_Var GetVar(); | 
|  | void SetVar(PP_Var var); | 
|  | void SetInstance(PP_Instance instance); | 
|  |  | 
|  | // For the SerializedVarTestConstructor, this writes the Var value as if | 
|  | // it was just received off the wire, without any serialization rules. | 
|  | void ForceSetVarValueForTest(PP_Var value); | 
|  |  | 
|  | void WriteToMessage(base::Pickle* m) const; | 
|  | void WriteDataToMessage(base::Pickle* m, | 
|  | const HandleWriter& handle_writer) const; | 
|  | bool ReadFromMessage(const base::Pickle* m, base::PickleIterator* iter); | 
|  |  | 
|  | // Sets the cleanup mode. See the CleanupMode enum below. | 
|  | void SetCleanupModeToEndSendPassRef(); | 
|  | void SetCleanupModeToEndReceiveCallerOwned(); | 
|  |  | 
|  | private: | 
|  | enum CleanupMode { | 
|  | // The serialized var won't do anything special in the destructor | 
|  | // (default). | 
|  | CLEANUP_NONE, | 
|  |  | 
|  | // The serialized var will call EndSendPassRef in the destructor. | 
|  | END_SEND_PASS_REF, | 
|  |  | 
|  | // The serialized var will call EndReceiveCallerOwned in the destructor. | 
|  | END_RECEIVE_CALLER_OWNED | 
|  | }; | 
|  |  | 
|  | // Rules for serializing and deserializing vars for this process type. | 
|  | // This may be NULL, but must be set before trying to serialize to IPC when | 
|  | // sending, or before converting back to a PP_Var when receiving. | 
|  | scoped_refptr<VarSerializationRules> serialization_rules_; | 
|  |  | 
|  | // If this is set to VARTYPE_STRING and the 'value.id' is 0, then the | 
|  | // string_from_ipc_ holds the string. This means that the caller hasn't | 
|  | // called Deserialize with a valid Dispatcher yet, which is how we can | 
|  | // convert the serialized string value to a PP_Var string ID. | 
|  | // | 
|  | // This var may not be complete until the serialization rules are set when | 
|  | // reading from IPC since we'll need that to convert the string_value to | 
|  | // a string ID. Before this, the as_id will be 0 for VARTYPE_STRING. | 
|  | PP_Var var_; | 
|  |  | 
|  | PP_Instance instance_; | 
|  |  | 
|  | CleanupMode cleanup_mode_; | 
|  |  | 
|  | // If the var is not properly serialized, this will be false. | 
|  | bool is_valid_var_; | 
|  |  | 
|  | #ifndef NDEBUG | 
|  | // When being sent or received over IPC, we should only be serialized or | 
|  | // deserialized once. These flags help us assert this is true. | 
|  | mutable bool has_been_serialized_; | 
|  | mutable bool has_been_deserialized_; | 
|  | #endif | 
|  |  | 
|  | // ReadFromMessage() may be called on the I/O thread, e.g., when reading the | 
|  | // reply to a sync message. We cannot use the var tracker on the I/O thread, | 
|  | // which means we cannot create some types of PP_Var | 
|  | // (e.g. PP_VARTYPE_STRING). The data is stored in |raw_var_data_| and the | 
|  | // PP_Var is constructed when |GetVar()| is called. | 
|  | std::unique_ptr<RawVarDataGraph> raw_var_data_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(Inner); | 
|  | }; | 
|  |  | 
|  | SerializedVar(VarSerializationRules* serialization_rules); | 
|  |  | 
|  | mutable scoped_refptr<Inner> inner_; | 
|  | }; | 
|  |  | 
|  | // Helpers for message sending side -------------------------------------------- | 
|  |  | 
|  | // For sending a value to the remote side. | 
|  | // | 
|  | // Example for API: | 
|  | //   void MyFunction(PP_Var) | 
|  | // IPC message: | 
|  | //   IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar); | 
|  | // Sender would be: | 
|  | //   void MyFunctionProxy(PP_Var param) { | 
|  | //     Send(new MyFunctionMsg(SerializedVarSendInput(dispatcher, param)); | 
|  | //   } | 
|  | class PPAPI_PROXY_EXPORT SerializedVarSendInput : public SerializedVar { | 
|  | public: | 
|  | SerializedVarSendInput(Dispatcher* dispatcher, const PP_Var& var); | 
|  |  | 
|  | // Helper function for serializing a vector of input vars for serialization. | 
|  | static void ConvertVector(Dispatcher* dispatcher, | 
|  | const PP_Var* input, | 
|  | size_t input_count, | 
|  | std::vector<SerializedVar>* output); | 
|  |  | 
|  | private: | 
|  | // Disallow the empty constructor, but keep the default copy constructor | 
|  | // which is required to send the object to the IPC system. | 
|  | SerializedVarSendInput(); | 
|  | }; | 
|  |  | 
|  | // Specialization for optionally sending over shared memory. | 
|  | class PPAPI_PROXY_EXPORT SerializedVarSendInputShmem : public SerializedVar { | 
|  | public: | 
|  | SerializedVarSendInputShmem(Dispatcher* dispatcher, const PP_Var& var, | 
|  | const PP_Instance& instance); | 
|  |  | 
|  | private: | 
|  | // Disallow the empty constructor, but keep the default copy constructor | 
|  | // which is required to send the object to the IPC system. | 
|  | SerializedVarSendInputShmem(); | 
|  | }; | 
|  |  | 
|  |  | 
|  | // For the calling side of a function returning a var. The sending side uses | 
|  | // SerializedVarReturnValue. | 
|  | // | 
|  | // Example for API: | 
|  | //   PP_Var MyFunction() | 
|  | // IPC message: | 
|  | //   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); | 
|  | // Message handler would be: | 
|  | //   PP_Var MyFunctionProxy() { | 
|  | //     ReceiveSerializedVarReturnValue result; | 
|  | //     Send(new MyFunctionMsg(&result)); | 
|  | //     return result.Return(dispatcher()); | 
|  | //   } | 
|  | // | 
|  | // TODO(yzshen): Move the dispatcher parameter to the constructor and store a | 
|  | // VarSerializationRules reference instead, in case the dispatcher is destroyed | 
|  | // while waiting for reply to the sync message. | 
|  | class PPAPI_PROXY_EXPORT ReceiveSerializedVarReturnValue | 
|  | : public SerializedVar { | 
|  | public: | 
|  | // Note that we can't set the dispatcher in the constructor because the | 
|  | // data will be overridden when the return value is set. This constructor is | 
|  | // normally used in the pattern above (operator= will be implicitly invoked | 
|  | // when the sync message writes the output values). | 
|  | ReceiveSerializedVarReturnValue(); | 
|  |  | 
|  | // This constructor can be used when deserializing manually. This is useful | 
|  | // when you're getting strings "returned" via a struct and need to manually | 
|  | // get the PP_Vars out. In this case just do: | 
|  | //   ReceiveSerializedVarReturnValue(serialized).Return(dispatcher); | 
|  | explicit ReceiveSerializedVarReturnValue(const SerializedVar& serialized); | 
|  |  | 
|  | PP_Var Return(Dispatcher* dispatcher); | 
|  |  | 
|  | private: | 
|  | DISALLOW_COPY_AND_ASSIGN(ReceiveSerializedVarReturnValue); | 
|  | }; | 
|  |  | 
|  | // Example for API: | 
|  | //   "void MyFunction(PP_Var* exception);" | 
|  | // IPC message: | 
|  | //   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); | 
|  | // Message handler would be: | 
|  | //   void OnMsgMyFunction(PP_Var* exception) { | 
|  | //     ReceiveSerializedException se(dispatcher(), exception) | 
|  | //     Send(new PpapiHostMsg_Foo(&se)); | 
|  | //   } | 
|  | class PPAPI_PROXY_EXPORT ReceiveSerializedException : public SerializedVar { | 
|  | public: | 
|  | ReceiveSerializedException(Dispatcher* dispatcher, PP_Var* exception); | 
|  | ~ReceiveSerializedException(); | 
|  |  | 
|  | // Returns true if the exception passed in the constructor is set. Check | 
|  | // this before actually issuing the IPC. | 
|  | bool IsThrown() const; | 
|  |  | 
|  | private: | 
|  | // The input/output exception we're wrapping. May be NULL. | 
|  | PP_Var* exception_; | 
|  |  | 
|  | DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedException); | 
|  | }; | 
|  |  | 
|  | // Helper class for when we're returning a vector of Vars. When it goes out | 
|  | // of scope it will automatically convert the vector filled by the IPC layer | 
|  | // into the array specified by the constructor params. | 
|  | // | 
|  | // Example for API: | 
|  | //   "void MyFunction(uint32_t* count, PP_Var** vars);" | 
|  | // IPC message: | 
|  | //   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, std::vector<SerializedVar>); | 
|  | // Proxy function: | 
|  | //   void MyFunction(uint32_t* count, PP_Var** vars) { | 
|  | //     ReceiveSerializedVarVectorOutParam vect(dispatcher, count, vars); | 
|  | //     Send(new MyMsg(vect.OutParam())); | 
|  | //   } | 
|  | class PPAPI_PROXY_EXPORT ReceiveSerializedVarVectorOutParam { | 
|  | public: | 
|  | ReceiveSerializedVarVectorOutParam(Dispatcher* dispatcher, | 
|  | uint32_t* output_count, | 
|  | PP_Var** output); | 
|  | ~ReceiveSerializedVarVectorOutParam(); | 
|  |  | 
|  | std::vector<SerializedVar>* OutParam(); | 
|  |  | 
|  | private: | 
|  | Dispatcher* dispatcher_; | 
|  | uint32_t* output_count_; | 
|  | PP_Var** output_; | 
|  |  | 
|  | std::vector<SerializedVar> vector_; | 
|  |  | 
|  | DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedVarVectorOutParam); | 
|  | }; | 
|  |  | 
|  | // Helpers for message receiving side ------------------------------------------ | 
|  |  | 
|  | // For receiving a value from the remote side. | 
|  | // | 
|  | // Example for API: | 
|  | //   void MyFunction(PP_Var) | 
|  | // IPC message: | 
|  | //   IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar); | 
|  | // Message handler would be: | 
|  | //   void OnMsgMyFunction(SerializedVarReceiveInput param) { | 
|  | //     MyFunction(param.Get()); | 
|  | //   } | 
|  | class PPAPI_PROXY_EXPORT SerializedVarReceiveInput { | 
|  | public: | 
|  | // We rely on the implicit constructor here since the IPC layer will call | 
|  | // us with a SerializedVar. Pass this object by value, the copy constructor | 
|  | // will pass along the pointer (as cheap as passing a pointer arg). | 
|  | SerializedVarReceiveInput(const SerializedVar& serialized); | 
|  | ~SerializedVarReceiveInput(); | 
|  |  | 
|  | PP_Var Get(Dispatcher* dispatcher); | 
|  | PP_Var GetForInstance(Dispatcher* dispatcher, PP_Instance instance); | 
|  | bool is_valid_var() { return serialized_.is_valid_var(); } | 
|  |  | 
|  | private: | 
|  | const SerializedVar& serialized_; | 
|  | }; | 
|  |  | 
|  | // For receiving an input vector of vars from the remote side. | 
|  | // | 
|  | // Example: | 
|  | //   OnMsgMyFunction(SerializedVarVectorReceiveInput vector) { | 
|  | //     uint32_t size; | 
|  | //     PP_Var* array = vector.Get(dispatcher, &size); | 
|  | //     MyFunction(size, array); | 
|  | //   } | 
|  | class PPAPI_PROXY_EXPORT SerializedVarVectorReceiveInput { | 
|  | public: | 
|  | SerializedVarVectorReceiveInput(const std::vector<SerializedVar>& serialized); | 
|  | ~SerializedVarVectorReceiveInput(); | 
|  |  | 
|  | // Only call Get() once. It will return a pointer to the converted array and | 
|  | // place the array size in the out param. Will return NULL when the array is | 
|  | // empty. | 
|  | PP_Var* Get(Dispatcher* dispatcher, uint32_t* array_size); | 
|  |  | 
|  | private: | 
|  | const std::vector<SerializedVar>& serialized_; | 
|  |  | 
|  | // Filled by Get(). | 
|  | std::vector<PP_Var> deserialized_; | 
|  | }; | 
|  |  | 
|  | // For the receiving side of a function returning a var. The calling side uses | 
|  | // ReceiveSerializedVarReturnValue. | 
|  | // | 
|  | // Example for API: | 
|  | //   PP_Var MyFunction() | 
|  | // IPC message: | 
|  | //   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); | 
|  | // Message handler would be: | 
|  | //   void OnMsgMyFunction(SerializedVarReturnValue result) { | 
|  | //     result.Return(dispatcher(), MyFunction()); | 
|  | //   } | 
|  | class PPAPI_PROXY_EXPORT SerializedVarReturnValue { | 
|  | public: | 
|  | // We rely on the implicit constructor here since the IPC layer will call | 
|  | // us with a SerializedVar*. Pass this object by value, the copy constructor | 
|  | // will pass along the pointer (as cheap as passing a pointer arg). | 
|  | SerializedVarReturnValue(SerializedVar* serialized); | 
|  |  | 
|  | void Return(Dispatcher* dispatcher, const PP_Var& var); | 
|  |  | 
|  | // Helper function for code that doesn't use the pattern above, but gets | 
|  | // a return value from the remote side via a struct. You can pass in the | 
|  | // SerializedVar and a PP_Var will be created with return value semantics. | 
|  | static SerializedVar Convert(Dispatcher* dispatcher, const PP_Var& var); | 
|  |  | 
|  | private: | 
|  | SerializedVar* serialized_; | 
|  | }; | 
|  |  | 
|  | // For writing an out param to the remote side. | 
|  | // | 
|  | // Example for API: | 
|  | //   "void MyFunction(PP_Var* out);" | 
|  | // IPC message: | 
|  | //   IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar); | 
|  | // Message handler would be: | 
|  | //   void OnMsgMyFunction(SerializedVarOutParam out_param) { | 
|  | //     MyFunction(out_param.OutParam(dispatcher())); | 
|  | //   } | 
|  | class PPAPI_PROXY_EXPORT SerializedVarOutParam { | 
|  | public: | 
|  | // We rely on the implicit constructor here since the IPC layer will call | 
|  | // us with a SerializedVar*. Pass this object by value, the copy constructor | 
|  | // will pass along the pointer (as cheap as passing a pointer arg). | 
|  | SerializedVarOutParam(SerializedVar* serialized); | 
|  | ~SerializedVarOutParam(); | 
|  |  | 
|  | // Call this function only once. The caller should write its result to the | 
|  | // returned var pointer before this class goes out of scope. The var's | 
|  | // initial value will be VARTYPE_UNDEFINED. | 
|  | PP_Var* OutParam(Dispatcher* dispatcher); | 
|  |  | 
|  | private: | 
|  | SerializedVar* serialized_; | 
|  |  | 
|  | // This is the value actually written by the code and returned by OutParam. | 
|  | // We'll write this into serialized_ in our destructor. | 
|  | PP_Var writable_var_; | 
|  |  | 
|  | Dispatcher* dispatcher_; | 
|  | }; | 
|  |  | 
|  | // For returning an array of PP_Vars to the other side and transferring | 
|  | // ownership. | 
|  | // | 
|  | class PPAPI_PROXY_EXPORT SerializedVarVectorOutParam { | 
|  | public: | 
|  | SerializedVarVectorOutParam(std::vector<SerializedVar>* serialized); | 
|  | ~SerializedVarVectorOutParam(); | 
|  |  | 
|  | uint32_t* CountOutParam() { return &count_; } | 
|  | PP_Var** ArrayOutParam(Dispatcher* dispatcher); | 
|  |  | 
|  | private: | 
|  | Dispatcher* dispatcher_; | 
|  | std::vector<SerializedVar>* serialized_; | 
|  |  | 
|  | uint32_t count_; | 
|  | PP_Var* array_; | 
|  | }; | 
|  |  | 
|  | // For tests that just want to construct a SerializedVar for giving it to one | 
|  | // of the other classes. This emulates a SerializedVar just received over the | 
|  | // wire from another process. | 
|  | class PPAPI_PROXY_EXPORT SerializedVarTestConstructor : public SerializedVar { | 
|  | public: | 
|  | // For POD-types and objects. | 
|  | explicit SerializedVarTestConstructor(const PP_Var& pod_var); | 
|  |  | 
|  | // For strings. | 
|  | explicit SerializedVarTestConstructor(const std::string& str); | 
|  | }; | 
|  |  | 
|  | // For tests that want to read what's in a SerializedVar. | 
|  | class PPAPI_PROXY_EXPORT SerializedVarTestReader : public SerializedVar { | 
|  | public: | 
|  | explicit SerializedVarTestReader(const SerializedVar& var); | 
|  |  | 
|  | PP_Var GetVar() const { return inner_->GetVar(); } | 
|  | }; | 
|  |  | 
|  | }  // namespace proxy | 
|  | }  // namespace ppapi | 
|  |  | 
|  | #endif  // PPAPI_PROXY_SERIALIZED_VAR_H_ |