Index: ppapi/proxy/serialized_var.h |
=================================================================== |
--- ppapi/proxy/serialized_var.h (revision 0) |
+++ ppapi/proxy/serialized_var.h (revision 0) |
@@ -0,0 +1,404 @@ |
+// 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/ref_counted.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 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 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; |
+ |
+ class Inner : public base::RefCounted<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); |
+ }; |
+ |
+ SerializedVar(VarSerializationRules* serialization_rules); |
+ SerializedVar(VarSerializationRules* serialization, const PP_Var& var); |
+ |
+ 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(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_ |
+ |
Property changes on: ppapi/proxy/serialized_var.h |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |