Roll src/third_party/WebKit ef7cfd7:80927b2 (svn 194570:194575)
[chromium-blink-merge.git] / ppapi / proxy / serialized_var.h
blob13052c91d3834210c0c5ad7e79d2fb9191393612
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 "base/memory/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"
23 class PickleIterator;
25 namespace IPC {
26 class Message;
29 namespace ppapi {
30 namespace proxy {
32 class Dispatcher;
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
39 // gotten.
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.
45 // Design background
46 // -----------------
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.
64 // Constness
65 // ---------
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 {
75 public:
76 SerializedVar();
77 ~SerializedVar();
79 // Backend implementation for IPC::ParamTraits<SerializedVar>.
80 void WriteToMessage(IPC::Message* m) const {
81 inner_->WriteToMessage(m);
83 // If ReadFromMessage has been called, WriteDataToMessage will write the var
84 // that has been read from ReadFromMessage back to a message. This is used
85 // when converting handles for use in NaCl.
86 void WriteDataToMessage(IPC::Message* m,
87 const HandleWriter& handle_writer) const {
88 inner_->WriteDataToMessage(m, handle_writer);
90 bool ReadFromMessage(const IPC::Message* m, PickleIterator* iter) {
91 return inner_->ReadFromMessage(m, iter);
94 bool is_valid_var() const {
95 return inner_->is_valid_var();
98 // Returns the shared memory handles associated with this SerializedVar.
99 std::vector<SerializedHandle*> GetHandles() const {
100 return inner_->GetHandles();
103 protected:
104 friend class SerializedVarReceiveInput;
105 friend class SerializedVarReturnValue;
106 friend class SerializedVarOutParam;
107 friend class SerializedVarSendInput;
108 friend class SerializedVarSendInputShmem;
109 friend class SerializedVarTestConstructor;
110 friend class SerializedVarVectorReceiveInput;
112 class PPAPI_PROXY_EXPORT Inner : public base::RefCounted<Inner> {
113 public:
114 Inner();
115 Inner(VarSerializationRules* serialization_rules);
116 ~Inner();
118 VarSerializationRules* serialization_rules() {
119 return serialization_rules_.get();
121 void set_serialization_rules(VarSerializationRules* serialization_rules) {
122 serialization_rules_ = serialization_rules;
125 bool is_valid_var() const {
126 return is_valid_var_;
129 std::vector<SerializedHandle*> GetHandles() {
130 return (raw_var_data_ ? raw_var_data_->GetHandles() :
131 std::vector<SerializedHandle*>());
134 // See outer class's declarations above.
135 PP_Var GetVar();
136 void SetVar(PP_Var var);
137 void SetInstance(PP_Instance instance);
139 // For the SerializedVarTestConstructor, this writes the Var value as if
140 // it was just received off the wire, without any serialization rules.
141 void ForceSetVarValueForTest(PP_Var value);
143 void WriteToMessage(IPC::Message* m) const;
144 void WriteDataToMessage(IPC::Message* m,
145 const HandleWriter& handle_writer) const;
146 bool ReadFromMessage(const IPC::Message* m, PickleIterator* iter);
148 // Sets the cleanup mode. See the CleanupMode enum below.
149 void SetCleanupModeToEndSendPassRef();
150 void SetCleanupModeToEndReceiveCallerOwned();
152 private:
153 enum CleanupMode {
154 // The serialized var won't do anything special in the destructor
155 // (default).
156 CLEANUP_NONE,
158 // The serialized var will call EndSendPassRef in the destructor.
159 END_SEND_PASS_REF,
161 // The serialized var will call EndReceiveCallerOwned in the destructor.
162 END_RECEIVE_CALLER_OWNED
165 // Rules for serializing and deserializing vars for this process type.
166 // This may be NULL, but must be set before trying to serialize to IPC when
167 // sending, or before converting back to a PP_Var when receiving.
168 scoped_refptr<VarSerializationRules> serialization_rules_;
170 // If this is set to VARTYPE_STRING and the 'value.id' is 0, then the
171 // string_from_ipc_ holds the string. This means that the caller hasn't
172 // called Deserialize with a valid Dispatcher yet, which is how we can
173 // convert the serialized string value to a PP_Var string ID.
175 // This var may not be complete until the serialization rules are set when
176 // reading from IPC since we'll need that to convert the string_value to
177 // a string ID. Before this, the as_id will be 0 for VARTYPE_STRING.
178 PP_Var var_;
180 PP_Instance instance_;
182 CleanupMode cleanup_mode_;
184 // If the var is not properly serialized, this will be false.
185 bool is_valid_var_;
187 #ifndef NDEBUG
188 // When being sent or received over IPC, we should only be serialized or
189 // deserialized once. These flags help us assert this is true.
190 mutable bool has_been_serialized_;
191 mutable bool has_been_deserialized_;
192 #endif
194 // ReadFromMessage() may be called on the I/O thread, e.g., when reading the
195 // reply to a sync message. We cannot use the var tracker on the I/O thread,
196 // which means we cannot create some types of PP_Var
197 // (e.g. PP_VARTYPE_STRING). The data is stored in |raw_var_data_| and the
198 // PP_Var is constructed when |GetVar()| is called.
199 scoped_ptr<RawVarDataGraph> raw_var_data_;
201 DISALLOW_COPY_AND_ASSIGN(Inner);
204 SerializedVar(VarSerializationRules* serialization_rules);
206 mutable scoped_refptr<Inner> inner_;
209 // Helpers for message sending side --------------------------------------------
211 // For sending a value to the remote side.
213 // Example for API:
214 // void MyFunction(PP_Var)
215 // IPC message:
216 // IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar);
217 // Sender would be:
218 // void MyFunctionProxy(PP_Var param) {
219 // Send(new MyFunctionMsg(SerializedVarSendInput(dispatcher, param));
220 // }
221 class PPAPI_PROXY_EXPORT SerializedVarSendInput : public SerializedVar {
222 public:
223 SerializedVarSendInput(Dispatcher* dispatcher, const PP_Var& var);
225 // Helper function for serializing a vector of input vars for serialization.
226 static void ConvertVector(Dispatcher* dispatcher,
227 const PP_Var* input,
228 size_t input_count,
229 std::vector<SerializedVar>* output);
231 private:
232 // Disallow the empty constructor, but keep the default copy constructor
233 // which is required to send the object to the IPC system.
234 SerializedVarSendInput();
237 // Specialization for optionally sending over shared memory.
238 class PPAPI_PROXY_EXPORT SerializedVarSendInputShmem : public SerializedVar {
239 public:
240 SerializedVarSendInputShmem(Dispatcher* dispatcher, const PP_Var& var,
241 const PP_Instance& instance);
243 private:
244 // Disallow the empty constructor, but keep the default copy constructor
245 // which is required to send the object to the IPC system.
246 SerializedVarSendInputShmem();
250 // For the calling side of a function returning a var. The sending side uses
251 // SerializedVarReturnValue.
253 // Example for API:
254 // PP_Var MyFunction()
255 // IPC message:
256 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
257 // Message handler would be:
258 // PP_Var MyFunctionProxy() {
259 // ReceiveSerializedVarReturnValue result;
260 // Send(new MyFunctionMsg(&result));
261 // return result.Return(dispatcher());
262 // }
264 // TODO(yzshen): Move the dispatcher parameter to the constructor and store a
265 // VarSerializationRules reference instead, in case the dispatcher is destroyed
266 // while waiting for reply to the sync message.
267 class PPAPI_PROXY_EXPORT ReceiveSerializedVarReturnValue
268 : public SerializedVar {
269 public:
270 // Note that we can't set the dispatcher in the constructor because the
271 // data will be overridden when the return value is set. This constructor is
272 // normally used in the pattern above (operator= will be implicitly invoked
273 // when the sync message writes the output values).
274 ReceiveSerializedVarReturnValue();
276 // This constructor can be used when deserializing manually. This is useful
277 // when you're getting strings "returned" via a struct and need to manually
278 // get the PP_Vars out. In this case just do:
279 // ReceiveSerializedVarReturnValue(serialized).Return(dispatcher);
280 explicit ReceiveSerializedVarReturnValue(const SerializedVar& serialized);
282 PP_Var Return(Dispatcher* dispatcher);
284 private:
285 DISALLOW_COPY_AND_ASSIGN(ReceiveSerializedVarReturnValue);
288 // Example for API:
289 // "void MyFunction(PP_Var* exception);"
290 // IPC message:
291 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
292 // Message handler would be:
293 // void OnMsgMyFunction(PP_Var* exception) {
294 // ReceiveSerializedException se(dispatcher(), exception)
295 // Send(new PpapiHostMsg_Foo(&se));
296 // }
297 class PPAPI_PROXY_EXPORT ReceiveSerializedException : public SerializedVar {
298 public:
299 ReceiveSerializedException(Dispatcher* dispatcher, PP_Var* exception);
300 ~ReceiveSerializedException();
302 // Returns true if the exception passed in the constructor is set. Check
303 // this before actually issuing the IPC.
304 bool IsThrown() const;
306 private:
307 // The input/output exception we're wrapping. May be NULL.
308 PP_Var* exception_;
310 DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedException);
313 // Helper class for when we're returning a vector of Vars. When it goes out
314 // of scope it will automatically convert the vector filled by the IPC layer
315 // into the array specified by the constructor params.
317 // Example for API:
318 // "void MyFunction(uint32_t* count, PP_Var** vars);"
319 // IPC message:
320 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, std::vector<SerializedVar>);
321 // Proxy function:
322 // void MyFunction(uint32_t* count, PP_Var** vars) {
323 // ReceiveSerializedVarVectorOutParam vect(dispatcher, count, vars);
324 // Send(new MyMsg(vect.OutParam()));
325 // }
326 class PPAPI_PROXY_EXPORT ReceiveSerializedVarVectorOutParam {
327 public:
328 ReceiveSerializedVarVectorOutParam(Dispatcher* dispatcher,
329 uint32_t* output_count,
330 PP_Var** output);
331 ~ReceiveSerializedVarVectorOutParam();
333 std::vector<SerializedVar>* OutParam();
335 private:
336 Dispatcher* dispatcher_;
337 uint32_t* output_count_;
338 PP_Var** output_;
340 std::vector<SerializedVar> vector_;
342 DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedVarVectorOutParam);
345 // Helpers for message receiving side ------------------------------------------
347 // For receiving a value from the remote side.
349 // Example for API:
350 // void MyFunction(PP_Var)
351 // IPC message:
352 // IPC_MESSAGE_ROUTED1(MyFunction, SerializedVar);
353 // Message handler would be:
354 // void OnMsgMyFunction(SerializedVarReceiveInput param) {
355 // MyFunction(param.Get());
356 // }
357 class PPAPI_PROXY_EXPORT SerializedVarReceiveInput {
358 public:
359 // We rely on the implicit constructor here since the IPC layer will call
360 // us with a SerializedVar. Pass this object by value, the copy constructor
361 // will pass along the pointer (as cheap as passing a pointer arg).
362 SerializedVarReceiveInput(const SerializedVar& serialized);
363 ~SerializedVarReceiveInput();
365 PP_Var Get(Dispatcher* dispatcher);
366 PP_Var GetForInstance(Dispatcher* dispatcher, PP_Instance instance);
367 bool is_valid_var() { return serialized_.is_valid_var(); }
369 private:
370 const SerializedVar& serialized_;
373 // For receiving an input vector of vars from the remote side.
375 // Example:
376 // OnMsgMyFunction(SerializedVarVectorReceiveInput vector) {
377 // uint32_t size;
378 // PP_Var* array = vector.Get(dispatcher, &size);
379 // MyFunction(size, array);
380 // }
381 class PPAPI_PROXY_EXPORT SerializedVarVectorReceiveInput {
382 public:
383 SerializedVarVectorReceiveInput(const std::vector<SerializedVar>& serialized);
384 ~SerializedVarVectorReceiveInput();
386 // Only call Get() once. It will return a pointer to the converted array and
387 // place the array size in the out param. Will return NULL when the array is
388 // empty.
389 PP_Var* Get(Dispatcher* dispatcher, uint32_t* array_size);
391 private:
392 const std::vector<SerializedVar>& serialized_;
394 // Filled by Get().
395 std::vector<PP_Var> deserialized_;
398 // For the receiving side of a function returning a var. The calling side uses
399 // ReceiveSerializedVarReturnValue.
401 // Example for API:
402 // PP_Var MyFunction()
403 // IPC message:
404 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
405 // Message handler would be:
406 // void OnMsgMyFunction(SerializedVarReturnValue result) {
407 // result.Return(dispatcher(), MyFunction());
408 // }
409 class PPAPI_PROXY_EXPORT SerializedVarReturnValue {
410 public:
411 // We rely on the implicit constructor here since the IPC layer will call
412 // us with a SerializedVar*. Pass this object by value, the copy constructor
413 // will pass along the pointer (as cheap as passing a pointer arg).
414 SerializedVarReturnValue(SerializedVar* serialized);
416 void Return(Dispatcher* dispatcher, const PP_Var& var);
418 // Helper function for code that doesn't use the pattern above, but gets
419 // a return value from the remote side via a struct. You can pass in the
420 // SerializedVar and a PP_Var will be created with return value semantics.
421 static SerializedVar Convert(Dispatcher* dispatcher, const PP_Var& var);
423 private:
424 SerializedVar* serialized_;
427 // For writing an out param to the remote side.
429 // Example for API:
430 // "void MyFunction(PP_Var* out);"
431 // IPC message:
432 // IPC_SYNC_MESSAGE_ROUTED0_1(MyFunction, SerializedVar);
433 // Message handler would be:
434 // void OnMsgMyFunction(SerializedVarOutParam out_param) {
435 // MyFunction(out_param.OutParam(dispatcher()));
436 // }
437 class PPAPI_PROXY_EXPORT SerializedVarOutParam {
438 public:
439 // We rely on the implicit constructor here since the IPC layer will call
440 // us with a SerializedVar*. Pass this object by value, the copy constructor
441 // will pass along the pointer (as cheap as passing a pointer arg).
442 SerializedVarOutParam(SerializedVar* serialized);
443 ~SerializedVarOutParam();
445 // Call this function only once. The caller should write its result to the
446 // returned var pointer before this class goes out of scope. The var's
447 // initial value will be VARTYPE_UNDEFINED.
448 PP_Var* OutParam(Dispatcher* dispatcher);
450 private:
451 SerializedVar* serialized_;
453 // This is the value actually written by the code and returned by OutParam.
454 // We'll write this into serialized_ in our destructor.
455 PP_Var writable_var_;
457 Dispatcher* dispatcher_;
460 // For returning an array of PP_Vars to the other side and transferring
461 // ownership.
463 class PPAPI_PROXY_EXPORT SerializedVarVectorOutParam {
464 public:
465 SerializedVarVectorOutParam(std::vector<SerializedVar>* serialized);
466 ~SerializedVarVectorOutParam();
468 uint32_t* CountOutParam() { return &count_; }
469 PP_Var** ArrayOutParam(Dispatcher* dispatcher);
471 private:
472 Dispatcher* dispatcher_;
473 std::vector<SerializedVar>* serialized_;
475 uint32_t count_;
476 PP_Var* array_;
479 // For tests that just want to construct a SerializedVar for giving it to one
480 // of the other classes. This emulates a SerializedVar just received over the
481 // wire from another process.
482 class PPAPI_PROXY_EXPORT SerializedVarTestConstructor : public SerializedVar {
483 public:
484 // For POD-types and objects.
485 explicit SerializedVarTestConstructor(const PP_Var& pod_var);
487 // For strings.
488 explicit SerializedVarTestConstructor(const std::string& str);
491 // For tests that want to read what's in a SerializedVar.
492 class PPAPI_PROXY_EXPORT SerializedVarTestReader : public SerializedVar {
493 public:
494 explicit SerializedVarTestReader(const SerializedVar& var);
496 PP_Var GetVar() const { return inner_->GetVar(); }
499 } // namespace proxy
500 } // namespace ppapi
502 #endif // PPAPI_PROXY_SERIALIZED_VAR_H_