// Copyright 2012 The Chromium Authors // 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/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 // scoped_refptr 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 { … }; // 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 { … }; // Specialization for optionally sending over shared memory. class PPAPI_PROXY_EXPORT SerializedVarSendInputShmem : public SerializedVar { … }; // 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 { … }; // 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 { … }; // 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 { … }; // 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 { … }; // 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 { … }; // 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 { … }; // 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 { … }; // For returning an array of PP_Vars to the other side and transferring // ownership. // class PPAPI_PROXY_EXPORT SerializedVarVectorOutParam { … }; // 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 { … }; // For tests that want to read what's in a SerializedVar. class PPAPI_PROXY_EXPORT SerializedVarTestReader : public SerializedVar { … }; } // namespace proxy } // namespace ppapi #endif // PPAPI_PROXY_SERIALIZED_VAR_H_