Elim cr-checkbox
[chromium-blink-merge.git] / ppapi / proxy / serialized_var.cc
blob4d3ecff0c4e9f43b39b1332d21f39f2f2876cd01
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 #include "ppapi/proxy/serialized_var.h"
7 #include "base/logging.h"
8 #include "ipc/ipc_message_utils.h"
9 #include "ppapi/c/pp_instance.h"
10 #include "ppapi/proxy/dispatcher.h"
11 #include "ppapi/proxy/interface_proxy.h"
12 #include "ppapi/proxy/ppapi_param_traits.h"
13 #include "ppapi/proxy/ppb_buffer_proxy.h"
14 #include "ppapi/shared_impl/ppapi_globals.h"
15 #include "ppapi/shared_impl/var.h"
16 #include "ppapi/thunk/enter.h"
18 namespace ppapi {
19 namespace proxy {
21 namespace {
22 void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) {
23 IPC::ParamTraits<SerializedHandle>::Write(m, handle);
25 } // namespace
27 // SerializedVar::Inner --------------------------------------------------------
29 SerializedVar::Inner::Inner()
30 : serialization_rules_(NULL),
31 var_(PP_MakeUndefined()),
32 instance_(0),
33 cleanup_mode_(CLEANUP_NONE),
34 is_valid_var_(true) {
35 #ifndef NDEBUG
36 has_been_serialized_ = false;
37 has_been_deserialized_ = false;
38 #endif
41 SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules)
42 : serialization_rules_(serialization_rules),
43 var_(PP_MakeUndefined()),
44 instance_(0),
45 cleanup_mode_(CLEANUP_NONE) {
46 #ifndef NDEBUG
47 has_been_serialized_ = false;
48 has_been_deserialized_ = false;
49 #endif
52 SerializedVar::Inner::~Inner() {
53 switch (cleanup_mode_) {
54 case END_SEND_PASS_REF:
55 serialization_rules_->EndSendPassRef(var_);
56 break;
57 case END_RECEIVE_CALLER_OWNED:
58 serialization_rules_->EndReceiveCallerOwned(var_);
59 break;
60 default:
61 break;
65 PP_Var SerializedVar::Inner::GetVar() {
66 DCHECK(serialization_rules_.get());
68 #if defined(NACL_WIN64)
69 NOTREACHED();
70 return PP_MakeUndefined();
71 #else
72 if (raw_var_data_.get()) {
73 var_ = raw_var_data_->CreatePPVar(instance_);
74 raw_var_data_.reset(NULL);
77 return var_;
78 #endif
81 void SerializedVar::Inner::SetVar(PP_Var var) {
82 // Sanity check, when updating the var we should have received a
83 // serialization rules pointer already.
84 DCHECK(serialization_rules_.get());
85 var_ = var;
86 raw_var_data_.reset(NULL);
89 void SerializedVar::Inner::SetInstance(PP_Instance instance) {
90 instance_ = instance;
93 void SerializedVar::Inner::ForceSetVarValueForTest(PP_Var value) {
94 var_ = value;
95 raw_var_data_.reset(NULL);
98 void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
99 // When writing to the IPC messages, a serialization rules handler should
100 // always have been set.
102 // When sending a message, it should be difficult to trigger this if you're
103 // using the SerializedVarSendInput class and giving a non-NULL dispatcher.
104 // Make sure you're using the proper "Send" helper class.
106 // It should be more common to see this when handling an incoming message
107 // that returns a var. This means the message handler didn't write to the
108 // output parameter, or possibly you used the wrong helper class
109 // (normally SerializedVarReturnValue).
110 DCHECK(serialization_rules_.get());
112 #ifndef NDEBUG
113 // We should only be serializing something once.
114 DCHECK(!has_been_serialized_);
115 has_been_serialized_ = true;
116 #endif
117 scoped_ptr<RawVarDataGraph> data = RawVarDataGraph::Create(var_, instance_);
118 if (data) {
119 m->WriteBool(true); // Success.
120 data->Write(m, base::Bind(&DefaultHandleWriter));
121 } else {
122 m->WriteBool(false); // Failure.
126 void SerializedVar::Inner::WriteDataToMessage(
127 IPC::Message* m,
128 const HandleWriter& handle_writer) const {
129 if (raw_var_data_) {
130 m->WriteBool(true); // Success.
131 raw_var_data_->Write(m, handle_writer);
132 } else {
133 m->WriteBool(false); // Failure.
137 bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m,
138 base::PickleIterator* iter) {
139 #ifndef NDEBUG
140 // We should only deserialize something once or will end up with leaked
141 // references.
143 // One place this has happened in the past is using
144 // std::vector<SerializedVar>.resize(). If you're doing this manually instead
145 // of using the helper classes for handling in/out vectors of vars, be
146 // sure you use the same pattern as the SerializedVarVector classes.
147 DCHECK(!has_been_deserialized_);
148 has_been_deserialized_ = true;
149 #endif
150 // When reading, the dispatcher should be set when we get a Deserialize
151 // call (which will supply a dispatcher).
152 if (!iter->ReadBool(&is_valid_var_))
153 return false;
154 if (is_valid_var_) {
155 raw_var_data_ = RawVarDataGraph::Read(m, iter);
156 if (!raw_var_data_)
157 return false;
160 return true;
163 void SerializedVar::Inner::SetCleanupModeToEndSendPassRef() {
164 cleanup_mode_ = END_SEND_PASS_REF;
167 void SerializedVar::Inner::SetCleanupModeToEndReceiveCallerOwned() {
168 cleanup_mode_ = END_RECEIVE_CALLER_OWNED;
171 // SerializedVar ---------------------------------------------------------------
173 SerializedVar::SerializedVar() : inner_(new Inner) {
176 SerializedVar::SerializedVar(VarSerializationRules* serialization_rules)
177 : inner_(new Inner(serialization_rules)) {
180 SerializedVar::~SerializedVar() {
183 // SerializedVarSendInput ------------------------------------------------------
185 SerializedVarSendInput::SerializedVarSendInput(Dispatcher* dispatcher,
186 const PP_Var& var)
187 : SerializedVar(dispatcher->serialization_rules()) {
188 inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(var));
191 // static
192 void SerializedVarSendInput::ConvertVector(Dispatcher* dispatcher,
193 const PP_Var* input,
194 size_t input_count,
195 std::vector<SerializedVar>* output) {
196 output->reserve(input_count);
197 for (size_t i = 0; i < input_count; i++)
198 output->push_back(SerializedVarSendInput(dispatcher, input[i]));
201 // SerializedVarSendInputShmem -------------------------------------------------
203 SerializedVarSendInputShmem::SerializedVarSendInputShmem(
204 Dispatcher* dispatcher,
205 const PP_Var& var,
206 const PP_Instance& instance)
207 : SerializedVar(dispatcher->serialization_rules()) {
208 inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(var));
209 inner_->SetInstance(instance);
212 // ReceiveSerializedVarReturnValue ---------------------------------------------
214 ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue() {
217 ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue(
218 const SerializedVar& serialized)
219 : SerializedVar(serialized) {
222 PP_Var ReceiveSerializedVarReturnValue::Return(Dispatcher* dispatcher) {
223 inner_->set_serialization_rules(dispatcher->serialization_rules());
224 inner_->SetVar(inner_->serialization_rules()->ReceivePassRef(
225 inner_->GetVar()));
226 return inner_->GetVar();
229 // ReceiveSerializedException --------------------------------------------------
231 ReceiveSerializedException::ReceiveSerializedException(Dispatcher* dispatcher,
232 PP_Var* exception)
233 : SerializedVar(dispatcher->serialization_rules()),
234 exception_(exception) {
237 ReceiveSerializedException::~ReceiveSerializedException() {
238 if (exception_) {
239 // When an output exception is specified, it will take ownership of the
240 // reference.
241 inner_->SetVar(
242 inner_->serialization_rules()->ReceivePassRef(inner_->GetVar()));
243 *exception_ = inner_->GetVar();
244 } else {
245 // When no output exception is specified, the browser thinks we have a ref
246 // to an object that we don't want (this will happen only in the plugin
247 // since the browser will always specify an out exception for the plugin to
248 // write into).
250 // Strings don't need this handling since we can just avoid creating a
251 // Var from the std::string in the first place.
252 if (inner_->GetVar().type == PP_VARTYPE_OBJECT)
253 inner_->serialization_rules()->ReleaseObjectRef(inner_->GetVar());
257 bool ReceiveSerializedException::IsThrown() const {
258 return exception_ && exception_->type != PP_VARTYPE_UNDEFINED;
261 // ReceiveSerializedVarVectorOutParam ------------------------------------------
263 ReceiveSerializedVarVectorOutParam::ReceiveSerializedVarVectorOutParam(
264 Dispatcher* dispatcher,
265 uint32_t* output_count,
266 PP_Var** output)
267 : dispatcher_(dispatcher),
268 output_count_(output_count),
269 output_(output) {
272 ReceiveSerializedVarVectorOutParam::~ReceiveSerializedVarVectorOutParam() {
273 *output_count_ = static_cast<uint32_t>(vector_.size());
274 if (!vector_.size()) {
275 *output_ = NULL;
276 return;
279 *output_ = static_cast<PP_Var*>(malloc(vector_.size() * sizeof(PP_Var)));
280 for (size_t i = 0; i < vector_.size(); i++) {
281 // Here we just mimic what happens when returning a value.
282 ReceiveSerializedVarReturnValue converted;
283 SerializedVar* serialized = &converted;
284 *serialized = vector_[i];
285 (*output_)[i] = converted.Return(dispatcher_);
289 std::vector<SerializedVar>* ReceiveSerializedVarVectorOutParam::OutParam() {
290 return &vector_;
293 // SerializedVarReceiveInput ---------------------------------------------------
295 SerializedVarReceiveInput::SerializedVarReceiveInput(
296 const SerializedVar& serialized)
297 : serialized_(serialized) {
300 SerializedVarReceiveInput::~SerializedVarReceiveInput() {
303 PP_Var SerializedVarReceiveInput::Get(Dispatcher* dispatcher) {
304 serialized_.inner_->set_serialization_rules(
305 dispatcher->serialization_rules());
307 // Ensure that when the serialized var goes out of scope it cleans up the
308 // stuff we're making in BeginReceiveCallerOwned.
309 serialized_.inner_->SetCleanupModeToEndReceiveCallerOwned();
311 serialized_.inner_->SetVar(
312 serialized_.inner_->serialization_rules()->BeginReceiveCallerOwned(
313 serialized_.inner_->GetVar()));
314 return serialized_.inner_->GetVar();
318 PP_Var SerializedVarReceiveInput::GetForInstance(Dispatcher* dispatcher,
319 PP_Instance instance) {
320 serialized_.inner_->SetInstance(instance);
321 return Get(dispatcher);
324 // SerializedVarVectorReceiveInput ---------------------------------------------
326 SerializedVarVectorReceiveInput::SerializedVarVectorReceiveInput(
327 const std::vector<SerializedVar>& serialized)
328 : serialized_(serialized) {
331 SerializedVarVectorReceiveInput::~SerializedVarVectorReceiveInput() {
332 for (size_t i = 0; i < deserialized_.size(); i++) {
333 serialized_[i].inner_->serialization_rules()->EndReceiveCallerOwned(
334 deserialized_[i]);
338 PP_Var* SerializedVarVectorReceiveInput::Get(Dispatcher* dispatcher,
339 uint32_t* array_size) {
340 deserialized_.resize(serialized_.size());
341 for (size_t i = 0; i < serialized_.size(); i++) {
342 // The vectors must be able to clean themselves up after this call is
343 // torn down.
344 serialized_[i].inner_->set_serialization_rules(
345 dispatcher->serialization_rules());
347 serialized_[i].inner_->SetVar(
348 serialized_[i].inner_->serialization_rules()->BeginReceiveCallerOwned(
349 serialized_[i].inner_->GetVar()));
350 deserialized_[i] = serialized_[i].inner_->GetVar();
353 *array_size = static_cast<uint32_t>(serialized_.size());
354 return deserialized_.empty() ? NULL : &deserialized_[0];
357 // SerializedVarReturnValue ----------------------------------------------------
359 SerializedVarReturnValue::SerializedVarReturnValue(SerializedVar* serialized)
360 : serialized_(serialized) {
363 void SerializedVarReturnValue::Return(Dispatcher* dispatcher,
364 const PP_Var& var) {
365 serialized_->inner_->set_serialization_rules(
366 dispatcher->serialization_rules());
368 // Var must clean up after our BeginSendPassRef call.
369 serialized_->inner_->SetCleanupModeToEndSendPassRef();
371 serialized_->inner_->SetVar(
372 dispatcher->serialization_rules()->BeginSendPassRef(var));
375 // static
376 SerializedVar SerializedVarReturnValue::Convert(Dispatcher* dispatcher,
377 const PP_Var& var) {
378 // Mimic what happens in the normal case.
379 SerializedVar result;
380 SerializedVarReturnValue retvalue(&result);
381 retvalue.Return(dispatcher, var);
382 return result;
385 // SerializedVarOutParam -------------------------------------------------------
387 SerializedVarOutParam::SerializedVarOutParam(SerializedVar* serialized)
388 : serialized_(serialized),
389 writable_var_(PP_MakeUndefined()),
390 dispatcher_(NULL) {
393 SerializedVarOutParam::~SerializedVarOutParam() {
394 if (serialized_->inner_->serialization_rules()) {
395 // When unset, OutParam wasn't called. We'll just leave the var untouched
396 // in that case.
397 serialized_->inner_->SetVar(
398 serialized_->inner_->serialization_rules()->BeginSendPassRef(
399 writable_var_));
401 // Normally the current object will be created on the stack to wrap a
402 // SerializedVar and won't have a scope around the actual IPC send. So we
403 // need to tell the SerializedVar to do the begin/end send pass ref calls.
404 serialized_->inner_->SetCleanupModeToEndSendPassRef();
408 PP_Var* SerializedVarOutParam::OutParam(Dispatcher* dispatcher) {
409 dispatcher_ = dispatcher;
410 serialized_->inner_->set_serialization_rules(
411 dispatcher->serialization_rules());
412 return &writable_var_;
415 // SerializedVarVectorOutParam -------------------------------------------------
417 SerializedVarVectorOutParam::SerializedVarVectorOutParam(
418 std::vector<SerializedVar>* serialized)
419 : dispatcher_(NULL),
420 serialized_(serialized),
421 count_(0),
422 array_(NULL) {
425 SerializedVarVectorOutParam::~SerializedVarVectorOutParam() {
426 DCHECK(dispatcher_);
428 // Convert the array written by the pepper code to the serialized structure.
429 // Note we can't use resize here, we have to allocate a new SerializedVar
430 // for each serialized item. See ParamTraits<vector<SerializedVar>>::Read.
431 serialized_->reserve(count_);
432 for (uint32_t i = 0; i < count_; i++) {
433 // Just mimic what we do for regular OutParams.
434 SerializedVar var;
435 SerializedVarOutParam out(&var);
436 *out.OutParam(dispatcher_) = array_[i];
437 serialized_->push_back(var);
440 // When returning arrays, the pepper code expects the caller to take
441 // ownership of the array.
442 free(array_);
445 PP_Var** SerializedVarVectorOutParam::ArrayOutParam(Dispatcher* dispatcher) {
446 DCHECK(!dispatcher_); // Should only be called once.
447 dispatcher_ = dispatcher;
448 return &array_;
451 SerializedVarTestConstructor::SerializedVarTestConstructor(
452 const PP_Var& pod_var) {
453 DCHECK(pod_var.type != PP_VARTYPE_STRING);
454 inner_->ForceSetVarValueForTest(pod_var);
457 SerializedVarTestConstructor::SerializedVarTestConstructor(
458 const std::string& str) {
459 inner_->ForceSetVarValueForTest(StringVar::StringToPPVar(str));
462 SerializedVarTestReader::SerializedVarTestReader(const SerializedVar& var)
463 : SerializedVar(var) {
466 } // namespace proxy
467 } // namespace ppapi