[M108 Aura Migration][NaCl][PPFwk] Add error logs + SVACE/DLOG/Static analysis fix
[platform/framework/web/chromium-efl.git] / ppapi / proxy / serialized_var.cc
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ppapi/proxy/serialized_var.h"
6
7 #include "base/bind.h"
8 #include "base/check.h"
9 #include "base/notreached.h"
10 #include "ipc/ipc_message_utils.h"
11 #include "ppapi/c/pp_instance.h"
12 #include "ppapi/proxy/dispatcher.h"
13 #include "ppapi/proxy/interface_proxy.h"
14 #include "ppapi/proxy/ppapi_param_traits.h"
15 #include "ppapi/proxy/ppb_buffer_proxy.h"
16 #include "ppapi/shared_impl/ppapi_globals.h"
17 #include "ppapi/shared_impl/var.h"
18 #include "ppapi/thunk/enter.h"
19
20 namespace ppapi {
21 namespace proxy {
22
23 namespace {
24 void DefaultHandleWriter(base::Pickle* m, const SerializedHandle& handle) {
25   IPC::ParamTraits<SerializedHandle>::Write(m, handle);
26 }
27 }  // namespace
28
29 // SerializedVar::Inner --------------------------------------------------------
30
31 SerializedVar::Inner::Inner()
32     : serialization_rules_(nullptr),
33       var_(PP_MakeUndefined()),
34       instance_(0),
35       cleanup_mode_(CLEANUP_NONE),
36       is_valid_var_(true) {
37 #ifndef NDEBUG
38   has_been_serialized_ = false;
39   has_been_deserialized_ = false;
40 #endif
41 }
42
43 SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules)
44     : serialization_rules_(serialization_rules),
45       var_(PP_MakeUndefined()),
46       instance_(0),
47       cleanup_mode_(CLEANUP_NONE),
48       is_valid_var_(true) {
49 #ifndef NDEBUG
50   has_been_serialized_ = false;
51   has_been_deserialized_ = false;
52 #endif
53 }
54
55 SerializedVar::Inner::~Inner() {
56   switch (cleanup_mode_) {
57     case END_SEND_PASS_REF:
58       serialization_rules_->EndSendPassRef(var_);
59       break;
60     case END_RECEIVE_CALLER_OWNED:
61       serialization_rules_->EndReceiveCallerOwned(var_);
62       break;
63     default:
64       break;
65   }
66 }
67
68 PP_Var SerializedVar::Inner::GetVar() {
69   DCHECK(serialization_rules_.get());
70
71 #if defined(NACL_WIN64)
72   NOTREACHED();
73   return PP_MakeUndefined();
74 #else
75   if (raw_var_data_.get()) {
76     var_ = raw_var_data_->CreatePPVar(instance_);
77     raw_var_data_.reset(nullptr);
78   }
79
80   return var_;
81 #endif
82 }
83
84 void SerializedVar::Inner::SetVar(PP_Var var) {
85   // Sanity check, when updating the var we should have received a
86   // serialization rules pointer already.
87   DCHECK(serialization_rules_.get());
88   var_ = var;
89   raw_var_data_.reset(nullptr);
90 }
91
92 void SerializedVar::Inner::SetInstance(PP_Instance instance) {
93   instance_ = instance;
94 }
95
96 void SerializedVar::Inner::ForceSetVarValueForTest(PP_Var value) {
97   var_ = value;
98   raw_var_data_.reset(nullptr);
99 }
100
101 void SerializedVar::Inner::WriteToMessage(base::Pickle* m) const {
102   // When writing to the IPC messages, a serialization rules handler should
103   // always have been set.
104   //
105   // When sending a message, it should be difficult to trigger this if you're
106   // using the SerializedVarSendInput class and giving a non-null dispatcher.
107   // Make sure you're using the proper "Send" helper class.
108   //
109   // It should be more common to see this when handling an incoming message
110   // that returns a var. This means the message handler didn't write to the
111   // output parameter, or possibly you used the wrong helper class
112   // (normally SerializedVarReturnValue).
113   DCHECK(serialization_rules_.get());
114
115 #ifndef NDEBUG
116   // We should only be serializing something once.
117   DCHECK(!has_been_serialized_);
118   has_been_serialized_ = true;
119 #endif
120   std::unique_ptr<RawVarDataGraph> data =
121       RawVarDataGraph::Create(var_, instance_);
122   if (data) {
123     m->WriteBool(true);  // Success.
124     data->Write(m, base::BindRepeating(&DefaultHandleWriter));
125   } else {
126     m->WriteBool(false);  // Failure.
127   }
128 }
129
130 void SerializedVar::Inner::WriteDataToMessage(
131     base::Pickle* m,
132     const HandleWriter& handle_writer) const {
133   if (raw_var_data_) {
134     m->WriteBool(true);  // Success.
135     raw_var_data_->Write(m, handle_writer);
136   } else {
137     m->WriteBool(false);  // Failure.
138   }
139 }
140
141 bool SerializedVar::Inner::ReadFromMessage(const base::Pickle* m,
142                                            base::PickleIterator* iter) {
143 #ifndef NDEBUG
144   // We should only deserialize something once or will end up with leaked
145   // references.
146   //
147   // One place this has happened in the past is using
148   // std::vector<SerializedVar>.resize(). If you're doing this manually instead
149   // of using the helper classes for handling in/out vectors of vars, be
150   // sure you use the same pattern as the SerializedVarVector classes.
151   DCHECK(!has_been_deserialized_);
152   has_been_deserialized_ = true;
153 #endif
154   // When reading, the dispatcher should be set when we get a Deserialize
155   // call (which will supply a dispatcher).
156   if (!iter->ReadBool(&is_valid_var_))
157       return false;
158   if (is_valid_var_) {
159     raw_var_data_ = RawVarDataGraph::Read(m, iter);
160     if (!raw_var_data_)
161       return false;
162   }
163
164   return true;
165 }
166
167 void SerializedVar::Inner::SetCleanupModeToEndSendPassRef() {
168   cleanup_mode_ = END_SEND_PASS_REF;
169 }
170
171 void SerializedVar::Inner::SetCleanupModeToEndReceiveCallerOwned() {
172   cleanup_mode_ = END_RECEIVE_CALLER_OWNED;
173 }
174
175 // SerializedVar ---------------------------------------------------------------
176
177 SerializedVar::SerializedVar() : inner_(new Inner) {
178 }
179
180 SerializedVar::SerializedVar(VarSerializationRules* serialization_rules)
181     : inner_(new Inner(serialization_rules)) {
182 }
183
184 SerializedVar::~SerializedVar() {
185 }
186
187 // SerializedVarSendInput ------------------------------------------------------
188
189 SerializedVarSendInput::SerializedVarSendInput(Dispatcher* dispatcher,
190                                                const PP_Var& var)
191     : SerializedVar(dispatcher->serialization_rules()) {
192   inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(var));
193 }
194
195 // static
196 void SerializedVarSendInput::ConvertVector(Dispatcher* dispatcher,
197                                            const PP_Var* input,
198                                            size_t input_count,
199                                            std::vector<SerializedVar>* output) {
200   output->reserve(input_count);
201   for (size_t i = 0; i < input_count; i++)
202     output->push_back(SerializedVarSendInput(dispatcher, input[i]));
203 }
204
205 // SerializedVarSendInputShmem -------------------------------------------------
206
207 SerializedVarSendInputShmem::SerializedVarSendInputShmem(
208     Dispatcher* dispatcher,
209     const PP_Var& var,
210     const PP_Instance& instance)
211     : SerializedVar(dispatcher->serialization_rules()) {
212   inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(var));
213   inner_->SetInstance(instance);
214 }
215
216 // ReceiveSerializedVarReturnValue ---------------------------------------------
217
218 ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue() {
219 }
220
221 ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue(
222     const SerializedVar& serialized)
223     : SerializedVar(serialized) {
224 }
225
226 PP_Var ReceiveSerializedVarReturnValue::Return(Dispatcher* dispatcher) {
227   inner_->set_serialization_rules(dispatcher->serialization_rules());
228   inner_->SetVar(inner_->serialization_rules()->ReceivePassRef(
229       inner_->GetVar()));
230   return inner_->GetVar();
231 }
232
233 // ReceiveSerializedException --------------------------------------------------
234
235 ReceiveSerializedException::ReceiveSerializedException(Dispatcher* dispatcher,
236                                                        PP_Var* exception)
237     : SerializedVar(dispatcher->serialization_rules()),
238       exception_(exception) {
239 }
240
241 ReceiveSerializedException::~ReceiveSerializedException() {
242   if (exception_) {
243     // When an output exception is specified, it will take ownership of the
244     // reference.
245     inner_->SetVar(
246         inner_->serialization_rules()->ReceivePassRef(inner_->GetVar()));
247     *exception_ = inner_->GetVar();
248   } else {
249     // When no output exception is specified, the browser thinks we have a ref
250     // to an object that we don't want (this will happen only in the plugin
251     // since the browser will always specify an out exception for the plugin to
252     // write into).
253     //
254     // Strings don't need this handling since we can just avoid creating a
255     // Var from the std::string in the first place.
256     if (inner_->GetVar().type == PP_VARTYPE_OBJECT)
257       inner_->serialization_rules()->ReleaseObjectRef(inner_->GetVar());
258   }
259 }
260
261 bool ReceiveSerializedException::IsThrown() const {
262   return exception_ && exception_->type != PP_VARTYPE_UNDEFINED;
263 }
264
265 // ReceiveSerializedVarVectorOutParam ------------------------------------------
266
267 ReceiveSerializedVarVectorOutParam::ReceiveSerializedVarVectorOutParam(
268     Dispatcher* dispatcher,
269     uint32_t* output_count,
270     PP_Var** output)
271     : dispatcher_(dispatcher),
272       output_count_(output_count),
273       output_(output) {
274 }
275
276 ReceiveSerializedVarVectorOutParam::~ReceiveSerializedVarVectorOutParam() {
277   *output_count_ = static_cast<uint32_t>(vector_.size());
278   if (vector_.empty()) {
279     *output_ = nullptr;
280     return;
281   }
282
283   *output_ = static_cast<PP_Var*>(malloc(vector_.size() * sizeof(PP_Var)));
284   for (size_t i = 0; i < vector_.size(); i++) {
285     // Here we just mimic what happens when returning a value.
286     ReceiveSerializedVarReturnValue converted;
287     SerializedVar* serialized = &converted;
288     *serialized = vector_[i];
289     (*output_)[i] = converted.Return(dispatcher_);
290   }
291 }
292
293 std::vector<SerializedVar>* ReceiveSerializedVarVectorOutParam::OutParam() {
294   return &vector_;
295 }
296
297 // SerializedVarReceiveInput ---------------------------------------------------
298
299 SerializedVarReceiveInput::SerializedVarReceiveInput(
300     const SerializedVar& serialized)
301     : serialized_(serialized) {
302 }
303
304 SerializedVarReceiveInput::~SerializedVarReceiveInput() {
305 }
306
307 PP_Var SerializedVarReceiveInput::Get(Dispatcher* dispatcher) {
308   serialized_.inner_->set_serialization_rules(
309       dispatcher->serialization_rules());
310
311   // Ensure that when the serialized var goes out of scope it cleans up the
312   // stuff we're making in BeginReceiveCallerOwned.
313   serialized_.inner_->SetCleanupModeToEndReceiveCallerOwned();
314
315   serialized_.inner_->SetVar(
316       serialized_.inner_->serialization_rules()->BeginReceiveCallerOwned(
317           serialized_.inner_->GetVar()));
318   return serialized_.inner_->GetVar();
319 }
320
321
322 PP_Var SerializedVarReceiveInput::GetForInstance(Dispatcher* dispatcher,
323                                                  PP_Instance instance) {
324   serialized_.inner_->SetInstance(instance);
325   return Get(dispatcher);
326 }
327
328 // SerializedVarVectorReceiveInput ---------------------------------------------
329
330 SerializedVarVectorReceiveInput::SerializedVarVectorReceiveInput(
331     const std::vector<SerializedVar>& serialized)
332     : serialized_(serialized) {
333 }
334
335 SerializedVarVectorReceiveInput::~SerializedVarVectorReceiveInput() {
336   for (size_t i = 0; i < deserialized_.size(); i++) {
337     serialized_[i].inner_->serialization_rules()->EndReceiveCallerOwned(
338         deserialized_[i]);
339   }
340 }
341
342 PP_Var* SerializedVarVectorReceiveInput::Get(Dispatcher* dispatcher,
343                                              uint32_t* array_size) {
344   deserialized_.resize(serialized_.size());
345   for (size_t i = 0; i < serialized_.size(); i++) {
346     // The vectors must be able to clean themselves up after this call is
347     // torn down.
348     serialized_[i].inner_->set_serialization_rules(
349         dispatcher->serialization_rules());
350
351     serialized_[i].inner_->SetVar(
352         serialized_[i].inner_->serialization_rules()->BeginReceiveCallerOwned(
353             serialized_[i].inner_->GetVar()));
354     deserialized_[i] = serialized_[i].inner_->GetVar();
355   }
356
357   *array_size = static_cast<uint32_t>(serialized_.size());
358   return deserialized_.empty() ? nullptr : &deserialized_[0];
359 }
360
361 // SerializedVarReturnValue ----------------------------------------------------
362
363 SerializedVarReturnValue::SerializedVarReturnValue(SerializedVar* serialized)
364     : serialized_(serialized) {
365 }
366
367 void SerializedVarReturnValue::Return(Dispatcher* dispatcher,
368                                       const PP_Var& var) {
369   serialized_->inner_->set_serialization_rules(
370       dispatcher->serialization_rules());
371
372   // Var must clean up after our BeginSendPassRef call.
373   serialized_->inner_->SetCleanupModeToEndSendPassRef();
374
375   serialized_->inner_->SetVar(
376       dispatcher->serialization_rules()->BeginSendPassRef(var));
377 }
378
379 // static
380 SerializedVar SerializedVarReturnValue::Convert(Dispatcher* dispatcher,
381                                                 const PP_Var& var) {
382   // Mimic what happens in the normal case.
383   SerializedVar result;
384   SerializedVarReturnValue retvalue(&result);
385   retvalue.Return(dispatcher, var);
386   return result;
387 }
388
389 // SerializedVarOutParam -------------------------------------------------------
390
391 SerializedVarOutParam::SerializedVarOutParam(SerializedVar* serialized)
392     : serialized_(serialized),
393       writable_var_(PP_MakeUndefined()),
394       dispatcher_(nullptr) {}
395
396 SerializedVarOutParam::~SerializedVarOutParam() {
397   if (serialized_->inner_->serialization_rules()) {
398     // When unset, OutParam wasn't called. We'll just leave the var untouched
399     // in that case.
400     serialized_->inner_->SetVar(
401         serialized_->inner_->serialization_rules()->BeginSendPassRef(
402             writable_var_));
403
404     // Normally the current object will be created on the stack to wrap a
405     // SerializedVar and won't have a scope around the actual IPC send. So we
406     // need to tell the SerializedVar to do the begin/end send pass ref calls.
407     serialized_->inner_->SetCleanupModeToEndSendPassRef();
408   }
409 }
410
411 PP_Var* SerializedVarOutParam::OutParam(Dispatcher* dispatcher) {
412   dispatcher_ = dispatcher;
413   serialized_->inner_->set_serialization_rules(
414       dispatcher->serialization_rules());
415   return &writable_var_;
416 }
417
418 // SerializedVarVectorOutParam -------------------------------------------------
419
420 SerializedVarVectorOutParam::SerializedVarVectorOutParam(
421     std::vector<SerializedVar>* serialized)
422     : dispatcher_(nullptr),
423       serialized_(serialized),
424       count_(0),
425       array_(nullptr) {}
426
427 SerializedVarVectorOutParam::~SerializedVarVectorOutParam() {
428   DCHECK(dispatcher_);
429
430   // Convert the array written by the pepper code to the serialized structure.
431   // Note we can't use resize here, we have to allocate a new SerializedVar
432   // for each serialized item. See ParamTraits<vector<SerializedVar>>::Read.
433   serialized_->reserve(count_);
434   for (uint32_t i = 0; i < count_; i++) {
435     // Just mimic what we do for regular OutParams.
436     SerializedVar var;
437     SerializedVarOutParam out(&var);
438     *out.OutParam(dispatcher_) = array_[i];
439     serialized_->push_back(var);
440   }
441
442   // When returning arrays, the pepper code expects the caller to take
443   // ownership of the array.
444   free(array_);
445 }
446
447 PP_Var** SerializedVarVectorOutParam::ArrayOutParam(Dispatcher* dispatcher) {
448   DCHECK(!dispatcher_);  // Should only be called once.
449   dispatcher_ = dispatcher;
450   return &array_;
451 }
452
453 SerializedVarTestConstructor::SerializedVarTestConstructor(
454     const PP_Var& pod_var) {
455   DCHECK(pod_var.type != PP_VARTYPE_STRING);
456   inner_->ForceSetVarValueForTest(pod_var);
457 }
458
459 SerializedVarTestConstructor::SerializedVarTestConstructor(
460     const std::string& str) {
461   inner_->ForceSetVarValueForTest(StringVar::StringToPPVar(str));
462 }
463
464 SerializedVarTestReader::SerializedVarTestReader(const SerializedVar& var)
465     : SerializedVar(var) {
466 }
467
468 }  // namespace proxy
469 }  // namespace ppapi