• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #ifndef PPAPI_PROXY_SERIALIZED_VAR_H_
6 #define PPAPI_PROXY_SERIALIZED_VAR_H_
7 
8 #include <string>
9 #include <vector>
10 
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"
22 
23 class PickleIterator;
24 
25 namespace IPC {
26 class Message;
27 }
28 
29 namespace ppapi {
30 namespace proxy {
31 
32 class Dispatcher;
33 class VarSerializationRules;
34 
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.
40 //
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.
44 //
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
51 //
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.
56 //
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.
63 //
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.
71 //
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();
78 
79   // Backend implementation for IPC::ParamTraits<SerializedVar>.
WriteToMessage(IPC::Message * m)80   void WriteToMessage(IPC::Message* m) const {
81     inner_->WriteToMessage(m);
82   }
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.
WriteDataToMessage(IPC::Message * m,const HandleWriter & handle_writer)86   void WriteDataToMessage(IPC::Message* m,
87                           const HandleWriter& handle_writer) const {
88     inner_->WriteDataToMessage(m, handle_writer);
89   }
ReadFromMessage(const IPC::Message * m,PickleIterator * iter)90   bool ReadFromMessage(const IPC::Message* m, PickleIterator* iter) {
91     return inner_->ReadFromMessage(m, iter);
92   }
93 
is_valid_var()94   bool is_valid_var() const {
95     return inner_->is_valid_var();
96   }
97 
98   // Returns the shared memory handles associated with this SerializedVar.
GetHandles()99   std::vector<SerializedHandle*> GetHandles() const {
100     return inner_->GetHandles();
101   }
102 
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;
111 
112   class PPAPI_PROXY_EXPORT Inner : public base::RefCounted<Inner> {
113    public:
114     Inner();
115     Inner(VarSerializationRules* serialization_rules);
116     ~Inner();
117 
serialization_rules()118     VarSerializationRules* serialization_rules() {
119       return serialization_rules_.get();
120     }
set_serialization_rules(VarSerializationRules * serialization_rules)121     void set_serialization_rules(VarSerializationRules* serialization_rules) {
122       serialization_rules_ = serialization_rules;
123     }
124 
is_valid_var()125     bool is_valid_var() const {
126       return is_valid_var_;
127     }
128 
GetHandles()129     std::vector<SerializedHandle*> GetHandles() {
130       return (raw_var_data_ ? raw_var_data_->GetHandles() :
131           std::vector<SerializedHandle*>());
132     }
133 
134     // See outer class's declarations above.
135     PP_Var GetVar();
136     void SetVar(PP_Var var);
137     void SetInstance(PP_Instance instance);
138 
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);
142 
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);
147 
148     // Sets the cleanup mode. See the CleanupMode enum below.
149     void SetCleanupModeToEndSendPassRef();
150     void SetCleanupModeToEndReceiveCallerOwned();
151 
152    private:
153     enum CleanupMode {
154       // The serialized var won't do anything special in the destructor
155       // (default).
156       CLEANUP_NONE,
157 
158       // The serialized var will call EndSendPassRef in the destructor.
159       END_SEND_PASS_REF,
160 
161       // The serialized var will call EndReceiveCallerOwned in the destructor.
162       END_RECEIVE_CALLER_OWNED
163     };
164 
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_;
169 
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.
174     //
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_;
179 
180     PP_Instance instance_;
181 
182     CleanupMode cleanup_mode_;
183 
184     // If the var is not properly serialized, this will be false.
185     bool is_valid_var_;
186 
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
193 
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_;
200 
201     DISALLOW_COPY_AND_ASSIGN(Inner);
202   };
203 
204   SerializedVar(VarSerializationRules* serialization_rules);
205 
206   mutable scoped_refptr<Inner> inner_;
207 };
208 
209 // Helpers for message sending side --------------------------------------------
210 
211 // For sending a value to the remote side.
212 //
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);
224 
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);
230 
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();
235 };
236 
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);
242 
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();
247 };
248 
249 
250 // For the calling side of a function returning a var. The sending side uses
251 // SerializedVarReturnValue.
252 //
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 //   }
263 //
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();
275 
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);
281 
282   PP_Var Return(Dispatcher* dispatcher);
283 
284  private:
285   DISALLOW_COPY_AND_ASSIGN(ReceiveSerializedVarReturnValue);
286 };
287 
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();
301 
302   // Returns true if the exception passed in the constructor is set. Check
303   // this before actually issuing the IPC.
304   bool IsThrown() const;
305 
306  private:
307   // The input/output exception we're wrapping. May be NULL.
308   PP_Var* exception_;
309 
310   DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedException);
311 };
312 
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.
316 //
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();
332 
333   std::vector<SerializedVar>* OutParam();
334 
335  private:
336   Dispatcher* dispatcher_;
337   uint32_t* output_count_;
338   PP_Var** output_;
339 
340   std::vector<SerializedVar> vector_;
341 
342   DISALLOW_IMPLICIT_CONSTRUCTORS(ReceiveSerializedVarVectorOutParam);
343 };
344 
345 // Helpers for message receiving side ------------------------------------------
346 
347 // For receiving a value from the remote side.
348 //
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();
364 
365   PP_Var Get(Dispatcher* dispatcher);
366   PP_Var GetForInstance(Dispatcher* dispatcher, PP_Instance instance);
is_valid_var()367   bool is_valid_var() { return serialized_.is_valid_var(); }
368 
369  private:
370   const SerializedVar& serialized_;
371 };
372 
373 // For receiving an input vector of vars from the remote side.
374 //
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();
385 
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);
390 
391  private:
392   const std::vector<SerializedVar>& serialized_;
393 
394   // Filled by Get().
395   std::vector<PP_Var> deserialized_;
396 };
397 
398 // For the receiving side of a function returning a var. The calling side uses
399 // ReceiveSerializedVarReturnValue.
400 //
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);
415 
416   void Return(Dispatcher* dispatcher, const PP_Var& var);
417 
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);
422 
423  private:
424   SerializedVar* serialized_;
425 };
426 
427 // For writing an out param to the remote side.
428 //
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();
444 
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);
449 
450  private:
451   SerializedVar* serialized_;
452 
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_;
456 
457   Dispatcher* dispatcher_;
458 };
459 
460 // For returning an array of PP_Vars to the other side and transferring
461 // ownership.
462 //
463 class PPAPI_PROXY_EXPORT SerializedVarVectorOutParam {
464  public:
465   SerializedVarVectorOutParam(std::vector<SerializedVar>* serialized);
466   ~SerializedVarVectorOutParam();
467 
CountOutParam()468   uint32_t* CountOutParam() { return &count_; }
469   PP_Var** ArrayOutParam(Dispatcher* dispatcher);
470 
471  private:
472   Dispatcher* dispatcher_;
473   std::vector<SerializedVar>* serialized_;
474 
475   uint32_t count_;
476   PP_Var* array_;
477 };
478 
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);
486 
487   // For strings.
488   explicit SerializedVarTestConstructor(const std::string& str);
489 };
490 
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);
495 
GetVar()496   PP_Var GetVar() const { return inner_->GetVar(); }
497 };
498 
499 }  // namespace proxy
500 }  // namespace ppapi
501 
502 #endif  // PPAPI_PROXY_SERIALIZED_VAR_H_
503