diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-03 03:10:13 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-03 03:10:13 +0000 |
commit | 4bcab1c571c6b11a51e4493e3387733a6c95bbac (patch) | |
tree | 49c5a05d14c81b4061eda1a5f07d46d9545b46cb /ppapi/proxy/serialized_var.h | |
parent | 6ed2a5a54b7bb8ccd33da7bc948fee169f128459 (diff) | |
download | chromium_src-4bcab1c571c6b11a51e4493e3387733a6c95bbac.zip chromium_src-4bcab1c571c6b11a51e4493e3387733a6c95bbac.tar.gz chromium_src-4bcab1c571c6b11a51e4493e3387733a6c95bbac.tar.bz2 |
Core PPAPI proxy files. This includes the dispatcher which is the control point
on each end of the IPC channel. It includes the IPC message definitions. It
also includes the base class for the interface proxying, and the core resource
and var tracking.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/4229002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64869 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy/serialized_var.h')
-rw-r--r-- | ppapi/proxy/serialized_var.h | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/ppapi/proxy/serialized_var.h b/ppapi/proxy/serialized_var.h new file mode 100644 index 0000000..4d4230d --- /dev/null +++ b/ppapi/proxy/serialized_var.h @@ -0,0 +1,451 @@ +// Copyright (c) 2010 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 <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/linked_ptr.h" +#include "ppapi/c/pp_var.h" + +namespace IPC { +class Message; +} + +namespace pp { +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 must all use the same type and it +// must include a var and a dispatcher (this is a SerializedVar). But there are +// many combinations of proper reference counting for sending and receiving +// different types and when different data is avaliable (like the Dispatcher is +// not available at IPC read time). So SerializedVar has to encapsulate all of +// these modes. +// +// This makes SerializedVar complicate and easy to mess up. To make it +// reasonable to use all functions are protected and there are a use-specific +// classes that 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 to 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 SerializedVar { + public: + 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 + }; + + SerializedVar(); + ~SerializedVar(); + + // Backend implementation for IPC::ParamTraits<SerializedVar>. + void WriteToMessage(IPC::Message* m) const { + inner_->WriteToMessage(m); + } + bool ReadFromMessage(const IPC::Message* m, void** iter) { + return inner_->ReadFromMessage(m, iter); + } + + protected: + friend class SerializedVarReceiveInput; + friend class SerializedVarReturnValue; + friend class SerializedVarOutParam; + friend class SerializedVarSendInput; + friend class SerializedVarVectorReceiveInput; + + SerializedVar(VarSerializationRules* serialization_rules); + SerializedVar(VarSerializationRules* serialization, const PP_Var& var); + + VarSerializationRules* serialization_rules() const { + return inner_->serialization_rules(); + } + void set_serialization_rules(VarSerializationRules* s) const { + inner_->set_serialization_rules(s); + } + + void set_cleanup_mode(CleanupMode cm) const { + inner_->set_cleanup_mode(cm); + } + + // Returns the completed var for this object. The serialization rules must + // have been set already, and any string conversions must already have + // happened. + PP_Var GetVar() const { + return inner_->GetVar(); + } + + // Returns the var which has not had a string serialization happen yet. This + // is used for actually converting a string PP_Var to the string literal. + PP_Var GetIncompleteVar() const { + return inner_->GetIncompleteVar(); + } + + void SetVar(const PP_Var& var) const { + inner_->SetVar(var); + } + + // When this serialized var is a string var, returns the associated string. + // with the value. This can be called if the var isn't a string, but will + // just return the empty string in this case. + const std::string& GetString() const { + return inner_->GetString(); + } + + // Returns a pointer to the inner string associated with this class. The + // derived classes will use this when converting a PP_Var to the string + // literal. This can be called if the var isn't a string, but the value + // should not be written to (this simplifies the callers who can always pass + // the result of this function call to the VarSerializationRules classes). + std::string* GetStringPtr() const { + return inner_->GetStringPtr(); + } + + private: + class Inner { + public: + Inner(); + Inner(VarSerializationRules* serialization_rules); + Inner(VarSerializationRules* serialization_rules, const PP_Var& var); + ~Inner(); + + VarSerializationRules* serialization_rules() { + return serialization_rules_; + } + void set_serialization_rules(VarSerializationRules* serialization_rules) { + serialization_rules_ = serialization_rules; + } + + void set_cleanup_mode(CleanupMode cm) { cleanup_mode_ = cm; } + + // See outer class's declarations above. + PP_Var GetVar() const; + PP_Var GetIncompleteVar() const; + void SetVar(PP_Var var); + const std::string& GetString() const; + std::string* GetStringPtr(); + + void WriteToMessage(IPC::Message* m) const; + bool ReadFromMessage(const IPC::Message* m, void** iter); + + private: + // 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. + VarSerializationRules* serialization_rules_; + + // If this is set to VARTYPE_STRING and the 'value.id' is 0, then the + // string_value_ contains 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_; + + // Holds the literal string value to/from IPC. This will be valid of the + // var_ is VARTYPE_STRING. + std::string string_value_; + + CleanupMode cleanup_mode_; + +#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 + + DISALLOW_COPY_AND_ASSIGN(Inner); + }; + + mutable linked_ptr<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(param)); +// } +class 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(); +}; + +// 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()); +// } +class 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. + ReceiveSerializedVarReturnValue(); + + 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 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 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 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); + + private: + const SerializedVar& serialized_; + + // Since the SerializedVar is const, we can't set its dispatcher (which is + // OK since we don't need to). But since we need it for our own uses, we + // track it here. Will be NULL before Get() is called. + Dispatcher* dispatcher_; + PP_Var var_; +}; + +// 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 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 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); + + 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 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_; +}; + +// For returning an array of PP_Vars to the other side and transferring +// ownership. +// +class 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_; +}; + +} // namespace proxy +} // namespace pp + +#endif // PPAPI_PROXY_SERIALIZED_VAR_H_ + |