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.
5 #ifndef PPAPI_PROXY_SERIALIZED_VAR_H_
6 #define PPAPI_PROXY_SERIALIZED_VAR_H_
11 #include "base/basictypes.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/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"
33 class VarSerializationRules
;
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
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.
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
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.
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.
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.
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
{
79 // Backend implementation for IPC::ParamTraits<SerializedVar>.
80 void WriteToMessage(IPC::Message
* m
) const {
81 inner_
->WriteToMessage(m
);
83 bool ReadFromMessage(const IPC::Message
* m
, PickleIterator
* iter
) {
84 return inner_
->ReadFromMessage(m
, iter
);
87 RawVarDataGraph
* raw_var_data() const {
88 return inner_
->raw_var_data();
92 friend class SerializedVarReceiveInput
;
93 friend class SerializedVarReturnValue
;
94 friend class SerializedVarOutParam
;
95 friend class SerializedVarSendInput
;
96 friend class SerializedVarSendInputShmem
;
97 friend class SerializedVarTestConstructor
;
98 friend class SerializedVarVectorReceiveInput
;
100 class PPAPI_PROXY_EXPORT Inner
: public base::RefCounted
<Inner
> {
103 Inner(VarSerializationRules
* serialization_rules
);
106 VarSerializationRules
* serialization_rules() {
107 return serialization_rules_
;
109 void set_serialization_rules(VarSerializationRules
* serialization_rules
) {
110 serialization_rules_
= serialization_rules
;
113 RawVarDataGraph
* raw_var_data() {
114 return raw_var_data_
.get();
117 // See outer class's declarations above.
119 void SetVar(PP_Var var
);
120 void SetInstance(PP_Instance instance
);
122 // For the SerializedVarTestConstructor, this writes the Var value as if
123 // it was just received off the wire, without any serialization rules.
124 void ForceSetVarValueForTest(PP_Var value
);
126 void WriteToMessage(IPC::Message
* m
) const;
127 bool ReadFromMessage(const IPC::Message
* m
, PickleIterator
* iter
);
129 // Sets the cleanup mode. See the CleanupMode enum below.
130 void SetCleanupModeToEndSendPassRef();
131 void SetCleanupModeToEndReceiveCallerOwned();
135 // The serialized var won't do anything special in the destructor
139 // The serialized var will call EndSendPassRef in the destructor.
142 // The serialized var will call EndReceiveCallerOwned in the destructor.
143 END_RECEIVE_CALLER_OWNED
146 // Rules for serializing and deserializing vars for this process type.
147 // This may be NULL, but must be set before trying to serialize to IPC when
148 // sending, or before converting back to a PP_Var when receiving.
149 scoped_refptr
<VarSerializationRules
> serialization_rules_
;
151 // If this is set to VARTYPE_STRING and the 'value.id' is 0, then the
152 // string_from_ipc_ holds the string. This means that the caller hasn't
153 // called Deserialize with a valid Dispatcher yet, which is how we can
154 // convert the serialized string value to a PP_Var string ID.
156 // This var may not be complete until the serialization rules are set when
157 // reading from IPC since we'll need that to convert the string_value to
158 // a string ID. Before this, the as_id will be 0 for VARTYPE_STRING.
161 PP_Instance instance_
;
163 CleanupMode cleanup_mode_
;
166 // When being sent or received over IPC, we should only be serialized or
167 // deserialized once. These flags help us assert this is true.
168 mutable bool has_been_serialized_
;
169 mutable bool has_been_deserialized_
;
172 // ReadFromMessage() may be called on the I/O thread, e.g., when reading the
173 // reply to a sync message. We cannot use the var tracker on the I/O thread,
174 // which means we cannot create some types of PP_Var
175 // (e.g. PP_VARTYPE_STRING). The data is stored in |raw_var_data_| and the
176 // PP_Var is constructed when |GetVar()| is called.
177 scoped_ptr
<RawVarDataGraph
> raw_var_data_
;
179 DISALLOW_COPY_AND_ASSIGN(Inner
);
182 SerializedVar(VarSerializationRules
* serialization_rules
);
184 mutable scoped_refptr
<Inner
> inner_
;
187 // Helpers for message sending side --------------------------------------------
189 // For sending a value to the remote side.
192 // void MyFunction(PP_Var)
194 // IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar);
196 // void MyFunctionProxy(PP_Var param) {
197 // Send(new MyFunctionMsg(SerializedVarSendInput(dispatcher, param));
199 class PPAPI_PROXY_EXPORT SerializedVarSendInput
: public SerializedVar
{
201 SerializedVarSendInput(Dispatcher
* dispatcher
, const PP_Var
& var
);
203 // Helper function for serializing a vector of input vars for serialization.
204 static void ConvertVector(Dispatcher
* dispatcher
,
207 std::vector
<SerializedVar
>* output
);
210 // Disallow the empty constructor, but keep the default copy constructor
211 // which is required to send the object to the IPC system.
212 SerializedVarSendInput();
215 // Specialization for optionally sending over shared memory.
216 class PPAPI_PROXY_EXPORT SerializedVarSendInputShmem
: public SerializedVar
{
218 SerializedVarSendInputShmem(Dispatcher
* dispatcher
, const PP_Var
& var
,
219 const PP_Instance
& instance
);
222 // Disallow the empty constructor, but keep the default copy constructor
223 // which is required to send the object to the IPC system.
224 SerializedVarSendInputShmem();
228 // For the calling side of a function returning a var. The sending side uses
229 // SerializedVarReturnValue.
232 // PP_Var MyFunction()
234 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
235 // Message handler would be:
236 // PP_Var MyFunctionProxy() {
237 // ReceiveSerializedVarReturnValue result;
238 // Send(new MyFunctionMsg(&result));
239 // return result.Return(dispatcher());
242 // TODO(yzshen): Move the dispatcher parameter to the constructor and store a
243 // VarSerializationRules reference instead, in case the dispatcher is destroyed
244 // while waiting for reply to the sync message.
245 class PPAPI_PROXY_EXPORT ReceiveSerializedVarReturnValue
246 : public SerializedVar
{
248 // Note that we can't set the dispatcher in the constructor because the
249 // data will be overridden when the return value is set. This constructor is
250 // normally used in the pattern above (operator= will be implicitly invoked
251 // when the sync message writes the output values).
252 ReceiveSerializedVarReturnValue();
254 // This constructor can be used when deserializing manually. This is useful
255 // when you're getting strings "returned" via a struct and need to manually
256 // get the PP_Vars out. In this case just do:
257 // ReceiveSerializedVarReturnValue(serialized).Return(dispatcher);
258 explicit ReceiveSerializedVarReturnValue(const SerializedVar
& serialized
);
260 PP_Var
Return(Dispatcher
* dispatcher
);
263 DISALLOW_COPY_AND_ASSIGN(ReceiveSerializedVarReturnValue
);
267 // "void MyFunction(PP_Var* exception);"
269 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
270 // Message handler would be:
271 // void OnMsgMyFunction(PP_Var* exception) {
272 // ReceiveSerializedException se(dispatcher(), exception)
273 // Send(new PpapiHostMsg_Foo(&se));
275 class PPAPI_PROXY_EXPORT ReceiveSerializedException
: public SerializedVar
{
277 ReceiveSerializedException(Dispatcher
* dispatcher
, PP_Var
* exception
);
278 ~ReceiveSerializedException();
280 // Returns true if the exception passed in the constructor is set. Check
281 // this before actually issuing the IPC.
282 bool IsThrown() const;
285 // The input/output exception we're wrapping. May be NULL.
288 DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedException
);
291 // Helper class for when we're returning a vector of Vars. When it goes out
292 // of scope it will automatically convert the vector filled by the IPC layer
293 // into the array specified by the constructor params.
296 // "void MyFunction(uint32_t* count, PP_Var** vars);"
298 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, std::vector<SerializedVar>);
300 // void MyFunction(uint32_t* count, PP_Var** vars) {
301 // ReceiveSerializedVarVectorOutParam vect(dispatcher, count, vars);
302 // Send(new MyMsg(vect.OutParam()));
304 class PPAPI_PROXY_EXPORT ReceiveSerializedVarVectorOutParam
{
306 ReceiveSerializedVarVectorOutParam(Dispatcher
* dispatcher
,
307 uint32_t* output_count
,
309 ~ReceiveSerializedVarVectorOutParam();
311 std::vector
<SerializedVar
>* OutParam();
314 Dispatcher
* dispatcher_
;
315 uint32_t* output_count_
;
318 std::vector
<SerializedVar
> vector_
;
320 DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedVarVectorOutParam
);
323 // Helpers for message receiving side ------------------------------------------
325 // For receiving a value from the remote side.
328 // void MyFunction(PP_Var)
330 // IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar);
331 // Message handler would be:
332 // void OnMsgMyFunction(SerializedVarReceiveInput param) {
333 // MyFunction(param.Get());
335 class PPAPI_PROXY_EXPORT SerializedVarReceiveInput
{
337 // We rely on the implicit constructor here since the IPC layer will call
338 // us with a SerializedVar. Pass this object by value, the copy constructor
339 // will pass along the pointer (as cheap as passing a pointer arg).
340 SerializedVarReceiveInput(const SerializedVar
& serialized
);
341 ~SerializedVarReceiveInput();
343 PP_Var
Get(Dispatcher
* dispatcher
);
344 PP_Var
GetForInstance(Dispatcher
* dispatcher
, PP_Instance instance
);
347 const SerializedVar
& serialized_
;
350 // For receiving an input vector of vars from the remote side.
353 // OnMsgMyFunction(SerializedVarVectorReceiveInput vector) {
355 // PP_Var* array = vector.Get(dispatcher, &size);
356 // MyFunction(size, array);
358 class PPAPI_PROXY_EXPORT SerializedVarVectorReceiveInput
{
360 SerializedVarVectorReceiveInput(const std::vector
<SerializedVar
>& serialized
);
361 ~SerializedVarVectorReceiveInput();
363 // Only call Get() once. It will return a pointer to the converted array and
364 // place the array size in the out param. Will return NULL when the array is
366 PP_Var
* Get(Dispatcher
* dispatcher
, uint32_t* array_size
);
369 const std::vector
<SerializedVar
>& serialized_
;
372 std::vector
<PP_Var
> deserialized_
;
375 // For the receiving side of a function returning a var. The calling side uses
376 // ReceiveSerializedVarReturnValue.
379 // PP_Var MyFunction()
381 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
382 // Message handler would be:
383 // void OnMsgMyFunction(SerializedVarReturnValue result) {
384 // result.Return(dispatcher(), MyFunction());
386 class PPAPI_PROXY_EXPORT SerializedVarReturnValue
{
388 // We rely on the implicit constructor here since the IPC layer will call
389 // us with a SerializedVar*. Pass this object by value, the copy constructor
390 // will pass along the pointer (as cheap as passing a pointer arg).
391 SerializedVarReturnValue(SerializedVar
* serialized
);
393 void Return(Dispatcher
* dispatcher
, const PP_Var
& var
);
395 // Helper function for code that doesn't use the pattern above, but gets
396 // a return value from the remote side via a struct. You can pass in the
397 // SerializedVar and a PP_Var will be created with return value semantics.
398 static SerializedVar
Convert(Dispatcher
* dispatcher
, const PP_Var
& var
);
401 SerializedVar
* serialized_
;
404 // For writing an out param to the remote side.
407 // "void MyFunction(PP_Var* out);"
409 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
410 // Message handler would be:
411 // void OnMsgMyFunction(SerializedVarOutParam out_param) {
412 // MyFunction(out_param.OutParam(dispatcher()));
414 class PPAPI_PROXY_EXPORT SerializedVarOutParam
{
416 // We rely on the implicit constructor here since the IPC layer will call
417 // us with a SerializedVar*. Pass this object by value, the copy constructor
418 // will pass along the pointer (as cheap as passing a pointer arg).
419 SerializedVarOutParam(SerializedVar
* serialized
);
420 ~SerializedVarOutParam();
422 // Call this function only once. The caller should write its result to the
423 // returned var pointer before this class goes out of scope. The var's
424 // initial value will be VARTYPE_UNDEFINED.
425 PP_Var
* OutParam(Dispatcher
* dispatcher
);
428 SerializedVar
* serialized_
;
430 // This is the value actually written by the code and returned by OutParam.
431 // We'll write this into serialized_ in our destructor.
432 PP_Var writable_var_
;
434 Dispatcher
* dispatcher_
;
437 // For returning an array of PP_Vars to the other side and transferring
440 class PPAPI_PROXY_EXPORT SerializedVarVectorOutParam
{
442 SerializedVarVectorOutParam(std::vector
<SerializedVar
>* serialized
);
443 ~SerializedVarVectorOutParam();
445 uint32_t* CountOutParam() { return &count_
; }
446 PP_Var
** ArrayOutParam(Dispatcher
* dispatcher
);
449 Dispatcher
* dispatcher_
;
450 std::vector
<SerializedVar
>* serialized_
;
456 // For tests that just want to construct a SerializedVar for giving it to one
457 // of the other classes. This emulates a SerializedVar just received over the
458 // wire from another process.
459 class PPAPI_PROXY_EXPORT SerializedVarTestConstructor
: public SerializedVar
{
461 // For POD-types and objects.
462 explicit SerializedVarTestConstructor(const PP_Var
& pod_var
);
465 explicit SerializedVarTestConstructor(const std::string
& str
);
468 // For tests that want to read what's in a SerializedVar.
469 class PPAPI_PROXY_EXPORT SerializedVarTestReader
: public SerializedVar
{
471 explicit SerializedVarTestReader(const SerializedVar
& var
);
473 PP_Var
GetVar() const { return inner_
->GetVar(); }
479 #endif // PPAPI_PROXY_SERIALIZED_VAR_H_