Elim cr-checkbox
[chromium-blink-merge.git] / ppapi / proxy / serialized_var.h
blob46f8ed52e560c536851eb586b496c5e74099f28c
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_
8 #include <string>
9 #include <vector>
11 #include "base/basictypes.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "ppapi/c/pp_instance.h"
15 #include "ppapi/c/pp_var.h"
16 #include "ppapi/proxy/ppapi_proxy_export.h"
17 #include "ppapi/proxy/raw_var_data.h"
18 #include "ppapi/proxy/serialized_handle.h"
19 #include "ppapi/proxy/serialized_structs.h"
20 #include "ppapi/proxy/var_serialization_rules.h"
22 namespace base {
23 class PickleIterator;
26 namespace IPC {
27 class Message;
30 namespace ppapi {
31 namespace proxy {
33 class Dispatcher;
34 class VarSerializationRules;
36 // This class encapsulates a var so that we can serialize and deserialize it.
37 // The problem is that for strings, serialization and deserialization requires
38 // knowledge from outside about how to get at or create a string. So this
39 // object groups the var with a dispatcher so that string values can be set or
40 // gotten.
42 // Declare IPC messages as using this type, but don't use it directly (it has
43 // no useful public methods). Instead, instantiate one of the helper classes
44 // below which are conveniently named for each use case to prevent screwups.
46 // Design background
47 // -----------------
48 // This is sadly super complicated. The IPC system needs a consistent type to
49 // use for sending and receiving vars (this is a SerializedVar). But there are
50 // different combinations of reference counting for sending and receiving
51 // objects and for dealing with strings
53 // This makes SerializedVar complicated and easy to mess up. To make it
54 // reasonable to use, all functions are protected and there are use-specific
55 // classes that each encapsulate exactly one type of use in a way that typically
56 // won't compile if you do the wrong thing.
58 // The IPC system is designed to pass things around and will make copies in
59 // some cases, so our system must be designed so that this stuff will work.
60 // This is challenging when the SerializedVar must do some cleanup after the
61 // message is sent. To work around this, we create an inner class using a
62 // linked_ptr so all copies of a SerializedVar can share and we can guarantee
63 // that the actual data will get cleaned up on shutdown.
65 // Constness
66 // ---------
67 // SerializedVar basically doesn't support const. Everything is mutable and
68 // most functions are declared const. This unfortunateness is because of the
69 // way the IPC system works. When deserializing, it will have a const
70 // SerializedVar in a Tuple and this will be given to the function. We kind of
71 // want to modify that to convert strings and do refcounting.
73 // The helper classes used for accessing the SerializedVar have more reasonable
74 // behavior and will enforce that you don't do stupid things.
75 class PPAPI_PROXY_EXPORT SerializedVar {
76 public:
77 SerializedVar();
78 ~SerializedVar();
80 // Backend implementation for IPC::ParamTraits<SerializedVar>.
81 void WriteToMessage(IPC::Message* m) const {
82 inner_->WriteToMessage(m);
84 // If ReadFromMessage has been called, WriteDataToMessage will write the var
85 // that has been read from ReadFromMessage back to a message. This is used
86 // when converting handles for use in NaCl.
87 void WriteDataToMessage(IPC::Message* m,
88 const HandleWriter& handle_writer) const {
89 inner_->WriteDataToMessage(m, handle_writer);
91 bool ReadFromMessage(const IPC::Message* m, base::PickleIterator* iter) {
92 return inner_->ReadFromMessage(m, iter);
95 bool is_valid_var() const {
96 return inner_->is_valid_var();
99 // Returns the shared memory handles associated with this SerializedVar.
100 std::vector<SerializedHandle*> GetHandles() const {
101 return inner_->GetHandles();
104 protected:
105 friend class SerializedVarReceiveInput;
106 friend class SerializedVarReturnValue;
107 friend class SerializedVarOutParam;
108 friend class SerializedVarSendInput;
109 friend class SerializedVarSendInputShmem;
110 friend class SerializedVarTestConstructor;
111 friend class SerializedVarVectorReceiveInput;
113 class PPAPI_PROXY_EXPORT Inner : public base::RefCounted<Inner> {
114 public:
115 Inner();
116 Inner(VarSerializationRules* serialization_rules);
117 ~Inner();
119 VarSerializationRules* serialization_rules() {
120 return serialization_rules_.get();
122 void set_serialization_rules(VarSerializationRules* serialization_rules) {
123 serialization_rules_ = serialization_rules;
126 bool is_valid_var() const {
127 return is_valid_var_;
130 std::vector<SerializedHandle*> GetHandles() {
131 return (raw_var_data_ ? raw_var_data_->GetHandles() :
132 std::vector<SerializedHandle*>());
135 // See outer class's declarations above.
136 PP_Var GetVar();
137 void SetVar(PP_Var var);
138 void SetInstance(PP_Instance instance);
140 // For the SerializedVarTestConstructor, this writes the Var value as if
141 // it was just received off the wire, without any serialization rules.
142 void ForceSetVarValueForTest(PP_Var value);
144 void WriteToMessage(IPC::Message* m) const;
145 void WriteDataToMessage(IPC::Message* m,
146 const HandleWriter& handle_writer) const;
147 bool ReadFromMessage(const IPC::Message* m, base::PickleIterator* iter);
149 // Sets the cleanup mode. See the CleanupMode enum below.
150 void SetCleanupModeToEndSendPassRef();
151 void SetCleanupModeToEndReceiveCallerOwned();
153 private:
154 enum CleanupMode {
155 // The serialized var won't do anything special in the destructor
156 // (default).
157 CLEANUP_NONE,
159 // The serialized var will call EndSendPassRef in the destructor.
160 END_SEND_PASS_REF,
162 // The serialized var will call EndReceiveCallerOwned in the destructor.
163 END_RECEIVE_CALLER_OWNED
166 // Rules for serializing and deserializing vars for this process type.
167 // This may be NULL, but must be set before trying to serialize to IPC when
168 // sending, or before converting back to a PP_Var when receiving.
169 scoped_refptr<VarSerializationRules> serialization_rules_;
171 // If this is set to VARTYPE_STRING and the 'value.id' is 0, then the
172 // string_from_ipc_ holds the string. This means that the caller hasn't
173 // called Deserialize with a valid Dispatcher yet, which is how we can
174 // convert the serialized string value to a PP_Var string ID.
176 // This var may not be complete until the serialization rules are set when
177 // reading from IPC since we'll need that to convert the string_value to
178 // a string ID. Before this, the as_id will be 0 for VARTYPE_STRING.
179 PP_Var var_;
181 PP_Instance instance_;
183 CleanupMode cleanup_mode_;
185 // If the var is not properly serialized, this will be false.
186 bool is_valid_var_;
188 #ifndef NDEBUG
189 // When being sent or received over IPC, we should only be serialized or
190 // deserialized once. These flags help us assert this is true.
191 mutable bool has_been_serialized_;
192 mutable bool has_been_deserialized_;
193 #endif
195 // ReadFromMessage() may be called on the I/O thread, e.g., when reading the
196 // reply to a sync message. We cannot use the var tracker on the I/O thread,
197 // which means we cannot create some types of PP_Var
198 // (e.g. PP_VARTYPE_STRING). The data is stored in |raw_var_data_| and the
199 // PP_Var is constructed when |GetVar()| is called.
200 scoped_ptr<RawVarDataGraph> raw_var_data_;
202 DISALLOW_COPY_AND_ASSIGN(Inner);
205 SerializedVar(VarSerializationRules* serialization_rules);
207 mutable scoped_refptr<Inner> inner_;
210 // Helpers for message sending side --------------------------------------------
212 // For sending a value to the remote side.
214 // Example for API:
215 // void MyFunction(PP_Var)
216 // IPC message:
217 // IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar);
218 // Sender would be:
219 // void MyFunctionProxy(PP_Var param) {
220 // Send(new MyFunctionMsg(SerializedVarSendInput(dispatcher, param));
221 // }
222 class PPAPI_PROXY_EXPORT SerializedVarSendInput : public SerializedVar {
223 public:
224 SerializedVarSendInput(Dispatcher* dispatcher, const PP_Var& var);
226 // Helper function for serializing a vector of input vars for serialization.
227 static void ConvertVector(Dispatcher* dispatcher,
228 const PP_Var* input,
229 size_t input_count,
230 std::vector<SerializedVar>* output);
232 private:
233 // Disallow the empty constructor, but keep the default copy constructor
234 // which is required to send the object to the IPC system.
235 SerializedVarSendInput();
238 // Specialization for optionally sending over shared memory.
239 class PPAPI_PROXY_EXPORT SerializedVarSendInputShmem : public SerializedVar {
240 public:
241 SerializedVarSendInputShmem(Dispatcher* dispatcher, const PP_Var& var,
242 const PP_Instance& instance);
244 private:
245 // Disallow the empty constructor, but keep the default copy constructor
246 // which is required to send the object to the IPC system.
247 SerializedVarSendInputShmem();
251 // For the calling side of a function returning a var. The sending side uses
252 // SerializedVarReturnValue.
254 // Example for API:
255 // PP_Var MyFunction()
256 // IPC message:
257 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
258 // Message handler would be:
259 // PP_Var MyFunctionProxy() {
260 // ReceiveSerializedVarReturnValue result;
261 // Send(new MyFunctionMsg(&result));
262 // return result.Return(dispatcher());
263 // }
265 // TODO(yzshen): Move the dispatcher parameter to the constructor and store a
266 // VarSerializationRules reference instead, in case the dispatcher is destroyed
267 // while waiting for reply to the sync message.
268 class PPAPI_PROXY_EXPORT ReceiveSerializedVarReturnValue
269 : public SerializedVar {
270 public:
271 // Note that we can't set the dispatcher in the constructor because the
272 // data will be overridden when the return value is set. This constructor is
273 // normally used in the pattern above (operator= will be implicitly invoked
274 // when the sync message writes the output values).
275 ReceiveSerializedVarReturnValue();
277 // This constructor can be used when deserializing manually. This is useful
278 // when you're getting strings "returned" via a struct and need to manually
279 // get the PP_Vars out. In this case just do:
280 // ReceiveSerializedVarReturnValue(serialized).Return(dispatcher);
281 explicit ReceiveSerializedVarReturnValue(const SerializedVar& serialized);
283 PP_Var Return(Dispatcher* dispatcher);
285 private:
286 DISALLOW_COPY_AND_ASSIGN(ReceiveSerializedVarReturnValue);
289 // Example for API:
290 // "void MyFunction(PP_Var* exception);"
291 // IPC message:
292 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
293 // Message handler would be:
294 // void OnMsgMyFunction(PP_Var* exception) {
295 // ReceiveSerializedException se(dispatcher(), exception)
296 // Send(new PpapiHostMsg_Foo(&se));
297 // }
298 class PPAPI_PROXY_EXPORT ReceiveSerializedException : public SerializedVar {
299 public:
300 ReceiveSerializedException(Dispatcher* dispatcher, PP_Var* exception);
301 ~ReceiveSerializedException();
303 // Returns true if the exception passed in the constructor is set. Check
304 // this before actually issuing the IPC.
305 bool IsThrown() const;
307 private:
308 // The input/output exception we're wrapping. May be NULL.
309 PP_Var* exception_;
311 DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedException);
314 // Helper class for when we're returning a vector of Vars. When it goes out
315 // of scope it will automatically convert the vector filled by the IPC layer
316 // into the array specified by the constructor params.
318 // Example for API:
319 // "void MyFunction(uint32_t* count, PP_Var** vars);"
320 // IPC message:
321 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, std::vector<SerializedVar>);
322 // Proxy function:
323 // void MyFunction(uint32_t* count, PP_Var** vars) {
324 // ReceiveSerializedVarVectorOutParam vect(dispatcher, count, vars);
325 // Send(new MyMsg(vect.OutParam()));
326 // }
327 class PPAPI_PROXY_EXPORT ReceiveSerializedVarVectorOutParam {
328 public:
329 ReceiveSerializedVarVectorOutParam(Dispatcher* dispatcher,
330 uint32_t* output_count,
331 PP_Var** output);
332 ~ReceiveSerializedVarVectorOutParam();
334 std::vector<SerializedVar>* OutParam();
336 private:
337 Dispatcher* dispatcher_;
338 uint32_t* output_count_;
339 PP_Var** output_;
341 std::vector<SerializedVar> vector_;
343 DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedVarVectorOutParam);
346 // Helpers for message receiving side ------------------------------------------
348 // For receiving a value from the remote side.
350 // Example for API:
351 // void MyFunction(PP_Var)
352 // IPC message:
353 // IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar);
354 // Message handler would be:
355 // void OnMsgMyFunction(SerializedVarReceiveInput param) {
356 // MyFunction(param.Get());
357 // }
358 class PPAPI_PROXY_EXPORT SerializedVarReceiveInput {
359 public:
360 // We rely on the implicit constructor here since the IPC layer will call
361 // us with a SerializedVar. Pass this object by value, the copy constructor
362 // will pass along the pointer (as cheap as passing a pointer arg).
363 SerializedVarReceiveInput(const SerializedVar& serialized);
364 ~SerializedVarReceiveInput();
366 PP_Var Get(Dispatcher* dispatcher);
367 PP_Var GetForInstance(Dispatcher* dispatcher, PP_Instance instance);
368 bool is_valid_var() { return serialized_.is_valid_var(); }
370 private:
371 const SerializedVar& serialized_;
374 // For receiving an input vector of vars from the remote side.
376 // Example:
377 // OnMsgMyFunction(SerializedVarVectorReceiveInput vector) {
378 // uint32_t size;
379 // PP_Var* array = vector.Get(dispatcher, &size);
380 // MyFunction(size, array);
381 // }
382 class PPAPI_PROXY_EXPORT SerializedVarVectorReceiveInput {
383 public:
384 SerializedVarVectorReceiveInput(const std::vector<SerializedVar>& serialized);
385 ~SerializedVarVectorReceiveInput();
387 // Only call Get() once. It will return a pointer to the converted array and
388 // place the array size in the out param. Will return NULL when the array is
389 // empty.
390 PP_Var* Get(Dispatcher* dispatcher, uint32_t* array_size);
392 private:
393 const std::vector<SerializedVar>& serialized_;
395 // Filled by Get().
396 std::vector<PP_Var> deserialized_;
399 // For the receiving side of a function returning a var. The calling side uses
400 // ReceiveSerializedVarReturnValue.
402 // Example for API:
403 // PP_Var MyFunction()
404 // IPC message:
405 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
406 // Message handler would be:
407 // void OnMsgMyFunction(SerializedVarReturnValue result) {
408 // result.Return(dispatcher(), MyFunction());
409 // }
410 class PPAPI_PROXY_EXPORT SerializedVarReturnValue {
411 public:
412 // We rely on the implicit constructor here since the IPC layer will call
413 // us with a SerializedVar*. Pass this object by value, the copy constructor
414 // will pass along the pointer (as cheap as passing a pointer arg).
415 SerializedVarReturnValue(SerializedVar* serialized);
417 void Return(Dispatcher* dispatcher, const PP_Var& var);
419 // Helper function for code that doesn't use the pattern above, but gets
420 // a return value from the remote side via a struct. You can pass in the
421 // SerializedVar and a PP_Var will be created with return value semantics.
422 static SerializedVar Convert(Dispatcher* dispatcher, const PP_Var& var);
424 private:
425 SerializedVar* serialized_;
428 // For writing an out param to the remote side.
430 // Example for API:
431 // "void MyFunction(PP_Var* out);"
432 // IPC message:
433 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
434 // Message handler would be:
435 // void OnMsgMyFunction(SerializedVarOutParam out_param) {
436 // MyFunction(out_param.OutParam(dispatcher()));
437 // }
438 class PPAPI_PROXY_EXPORT SerializedVarOutParam {
439 public:
440 // We rely on the implicit constructor here since the IPC layer will call
441 // us with a SerializedVar*. Pass this object by value, the copy constructor
442 // will pass along the pointer (as cheap as passing a pointer arg).
443 SerializedVarOutParam(SerializedVar* serialized);
444 ~SerializedVarOutParam();
446 // Call this function only once. The caller should write its result to the
447 // returned var pointer before this class goes out of scope. The var's
448 // initial value will be VARTYPE_UNDEFINED.
449 PP_Var* OutParam(Dispatcher* dispatcher);
451 private:
452 SerializedVar* serialized_;
454 // This is the value actually written by the code and returned by OutParam.
455 // We'll write this into serialized_ in our destructor.
456 PP_Var writable_var_;
458 Dispatcher* dispatcher_;
461 // For returning an array of PP_Vars to the other side and transferring
462 // ownership.
464 class PPAPI_PROXY_EXPORT SerializedVarVectorOutParam {
465 public:
466 SerializedVarVectorOutParam(std::vector<SerializedVar>* serialized);
467 ~SerializedVarVectorOutParam();
469 uint32_t* CountOutParam() { return &count_; }
470 PP_Var** ArrayOutParam(Dispatcher* dispatcher);
472 private:
473 Dispatcher* dispatcher_;
474 std::vector<SerializedVar>* serialized_;
476 uint32_t count_;
477 PP_Var* array_;
480 // For tests that just want to construct a SerializedVar for giving it to one
481 // of the other classes. This emulates a SerializedVar just received over the
482 // wire from another process.
483 class PPAPI_PROXY_EXPORT SerializedVarTestConstructor : public SerializedVar {
484 public:
485 // For POD-types and objects.
486 explicit SerializedVarTestConstructor(const PP_Var& pod_var);
488 // For strings.
489 explicit SerializedVarTestConstructor(const std::string& str);
492 // For tests that want to read what's in a SerializedVar.
493 class PPAPI_PROXY_EXPORT SerializedVarTestReader : public SerializedVar {
494 public:
495 explicit SerializedVarTestReader(const SerializedVar& var);
497 PP_Var GetVar() const { return inner_->GetVar(); }
500 } // namespace proxy
501 } // namespace ppapi
503 #endif // PPAPI_PROXY_SERIALIZED_VAR_H_