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.
5 #include "ppapi/proxy/serialized_var.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"
24 void DefaultHandleWriter(base::Pickle* m, const SerializedHandle& handle) {
25 IPC::ParamTraits<SerializedHandle>::Write(m, handle);
29 // SerializedVar::Inner --------------------------------------------------------
31 SerializedVar::Inner::Inner()
32 : serialization_rules_(nullptr),
33 var_(PP_MakeUndefined()),
35 cleanup_mode_(CLEANUP_NONE),
38 has_been_serialized_ = false;
39 has_been_deserialized_ = false;
43 SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules)
44 : serialization_rules_(serialization_rules),
45 var_(PP_MakeUndefined()),
47 cleanup_mode_(CLEANUP_NONE),
50 has_been_serialized_ = false;
51 has_been_deserialized_ = false;
55 SerializedVar::Inner::~Inner() {
56 switch (cleanup_mode_) {
57 case END_SEND_PASS_REF:
58 serialization_rules_->EndSendPassRef(var_);
60 case END_RECEIVE_CALLER_OWNED:
61 serialization_rules_->EndReceiveCallerOwned(var_);
68 PP_Var SerializedVar::Inner::GetVar() {
69 DCHECK(serialization_rules_.get());
71 #if defined(NACL_WIN64)
73 return PP_MakeUndefined();
75 if (raw_var_data_.get()) {
76 var_ = raw_var_data_->CreatePPVar(instance_);
77 raw_var_data_.reset(nullptr);
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());
89 raw_var_data_.reset(nullptr);
92 void SerializedVar::Inner::SetInstance(PP_Instance instance) {
96 void SerializedVar::Inner::ForceSetVarValueForTest(PP_Var value) {
98 raw_var_data_.reset(nullptr);
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.
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.
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());
116 // We should only be serializing something once.
117 DCHECK(!has_been_serialized_);
118 has_been_serialized_ = true;
120 std::unique_ptr<RawVarDataGraph> data =
121 RawVarDataGraph::Create(var_, instance_);
123 m->WriteBool(true); // Success.
124 data->Write(m, base::BindRepeating(&DefaultHandleWriter));
126 m->WriteBool(false); // Failure.
130 void SerializedVar::Inner::WriteDataToMessage(
132 const HandleWriter& handle_writer) const {
134 m->WriteBool(true); // Success.
135 raw_var_data_->Write(m, handle_writer);
137 m->WriteBool(false); // Failure.
141 bool SerializedVar::Inner::ReadFromMessage(const base::Pickle* m,
142 base::PickleIterator* iter) {
144 // We should only deserialize something once or will end up with leaked
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;
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_))
159 raw_var_data_ = RawVarDataGraph::Read(m, iter);
167 void SerializedVar::Inner::SetCleanupModeToEndSendPassRef() {
168 cleanup_mode_ = END_SEND_PASS_REF;
171 void SerializedVar::Inner::SetCleanupModeToEndReceiveCallerOwned() {
172 cleanup_mode_ = END_RECEIVE_CALLER_OWNED;
175 // SerializedVar ---------------------------------------------------------------
177 SerializedVar::SerializedVar() : inner_(new Inner) {
180 SerializedVar::SerializedVar(VarSerializationRules* serialization_rules)
181 : inner_(new Inner(serialization_rules)) {
184 SerializedVar::~SerializedVar() {
187 // SerializedVarSendInput ------------------------------------------------------
189 SerializedVarSendInput::SerializedVarSendInput(Dispatcher* dispatcher,
191 : SerializedVar(dispatcher->serialization_rules()) {
192 inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(var));
196 void SerializedVarSendInput::ConvertVector(Dispatcher* dispatcher,
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]));
205 // SerializedVarSendInputShmem -------------------------------------------------
207 SerializedVarSendInputShmem::SerializedVarSendInputShmem(
208 Dispatcher* dispatcher,
210 const PP_Instance& instance)
211 : SerializedVar(dispatcher->serialization_rules()) {
212 inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned(var));
213 inner_->SetInstance(instance);
216 // ReceiveSerializedVarReturnValue ---------------------------------------------
218 ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue() {
221 ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue(
222 const SerializedVar& serialized)
223 : SerializedVar(serialized) {
226 PP_Var ReceiveSerializedVarReturnValue::Return(Dispatcher* dispatcher) {
227 inner_->set_serialization_rules(dispatcher->serialization_rules());
228 inner_->SetVar(inner_->serialization_rules()->ReceivePassRef(
230 return inner_->GetVar();
233 // ReceiveSerializedException --------------------------------------------------
235 ReceiveSerializedException::ReceiveSerializedException(Dispatcher* dispatcher,
237 : SerializedVar(dispatcher->serialization_rules()),
238 exception_(exception) {
241 ReceiveSerializedException::~ReceiveSerializedException() {
243 // When an output exception is specified, it will take ownership of the
246 inner_->serialization_rules()->ReceivePassRef(inner_->GetVar()));
247 *exception_ = inner_->GetVar();
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
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());
261 bool ReceiveSerializedException::IsThrown() const {
262 return exception_ && exception_->type != PP_VARTYPE_UNDEFINED;
265 // ReceiveSerializedVarVectorOutParam ------------------------------------------
267 ReceiveSerializedVarVectorOutParam::ReceiveSerializedVarVectorOutParam(
268 Dispatcher* dispatcher,
269 uint32_t* output_count,
271 : dispatcher_(dispatcher),
272 output_count_(output_count),
276 ReceiveSerializedVarVectorOutParam::~ReceiveSerializedVarVectorOutParam() {
277 *output_count_ = static_cast<uint32_t>(vector_.size());
278 if (vector_.empty()) {
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_);
293 std::vector<SerializedVar>* ReceiveSerializedVarVectorOutParam::OutParam() {
297 // SerializedVarReceiveInput ---------------------------------------------------
299 SerializedVarReceiveInput::SerializedVarReceiveInput(
300 const SerializedVar& serialized)
301 : serialized_(serialized) {
304 SerializedVarReceiveInput::~SerializedVarReceiveInput() {
307 PP_Var SerializedVarReceiveInput::Get(Dispatcher* dispatcher) {
308 serialized_.inner_->set_serialization_rules(
309 dispatcher->serialization_rules());
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();
315 serialized_.inner_->SetVar(
316 serialized_.inner_->serialization_rules()->BeginReceiveCallerOwned(
317 serialized_.inner_->GetVar()));
318 return serialized_.inner_->GetVar();
322 PP_Var SerializedVarReceiveInput::GetForInstance(Dispatcher* dispatcher,
323 PP_Instance instance) {
324 serialized_.inner_->SetInstance(instance);
325 return Get(dispatcher);
328 // SerializedVarVectorReceiveInput ---------------------------------------------
330 SerializedVarVectorReceiveInput::SerializedVarVectorReceiveInput(
331 const std::vector<SerializedVar>& serialized)
332 : serialized_(serialized) {
335 SerializedVarVectorReceiveInput::~SerializedVarVectorReceiveInput() {
336 for (size_t i = 0; i < deserialized_.size(); i++) {
337 serialized_[i].inner_->serialization_rules()->EndReceiveCallerOwned(
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
348 serialized_[i].inner_->set_serialization_rules(
349 dispatcher->serialization_rules());
351 serialized_[i].inner_->SetVar(
352 serialized_[i].inner_->serialization_rules()->BeginReceiveCallerOwned(
353 serialized_[i].inner_->GetVar()));
354 deserialized_[i] = serialized_[i].inner_->GetVar();
357 *array_size = static_cast<uint32_t>(serialized_.size());
358 return deserialized_.empty() ? nullptr : &deserialized_[0];
361 // SerializedVarReturnValue ----------------------------------------------------
363 SerializedVarReturnValue::SerializedVarReturnValue(SerializedVar* serialized)
364 : serialized_(serialized) {
367 void SerializedVarReturnValue::Return(Dispatcher* dispatcher,
369 serialized_->inner_->set_serialization_rules(
370 dispatcher->serialization_rules());
372 // Var must clean up after our BeginSendPassRef call.
373 serialized_->inner_->SetCleanupModeToEndSendPassRef();
375 serialized_->inner_->SetVar(
376 dispatcher->serialization_rules()->BeginSendPassRef(var));
380 SerializedVar SerializedVarReturnValue::Convert(Dispatcher* dispatcher,
382 // Mimic what happens in the normal case.
383 SerializedVar result;
384 SerializedVarReturnValue retvalue(&result);
385 retvalue.Return(dispatcher, var);
389 // SerializedVarOutParam -------------------------------------------------------
391 SerializedVarOutParam::SerializedVarOutParam(SerializedVar* serialized)
392 : serialized_(serialized),
393 writable_var_(PP_MakeUndefined()),
394 dispatcher_(nullptr) {}
396 SerializedVarOutParam::~SerializedVarOutParam() {
397 if (serialized_->inner_->serialization_rules()) {
398 // When unset, OutParam wasn't called. We'll just leave the var untouched
400 serialized_->inner_->SetVar(
401 serialized_->inner_->serialization_rules()->BeginSendPassRef(
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();
411 PP_Var* SerializedVarOutParam::OutParam(Dispatcher* dispatcher) {
412 dispatcher_ = dispatcher;
413 serialized_->inner_->set_serialization_rules(
414 dispatcher->serialization_rules());
415 return &writable_var_;
418 // SerializedVarVectorOutParam -------------------------------------------------
420 SerializedVarVectorOutParam::SerializedVarVectorOutParam(
421 std::vector<SerializedVar>* serialized)
422 : dispatcher_(nullptr),
423 serialized_(serialized),
427 SerializedVarVectorOutParam::~SerializedVarVectorOutParam() {
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.
437 SerializedVarOutParam out(&var);
438 *out.OutParam(dispatcher_) = array_[i];
439 serialized_->push_back(var);
442 // When returning arrays, the pepper code expects the caller to take
443 // ownership of the array.
447 PP_Var** SerializedVarVectorOutParam::ArrayOutParam(Dispatcher* dispatcher) {
448 DCHECK(!dispatcher_); // Should only be called once.
449 dispatcher_ = dispatcher;
453 SerializedVarTestConstructor::SerializedVarTestConstructor(
454 const PP_Var& pod_var) {
455 DCHECK(pod_var.type != PP_VARTYPE_STRING);
456 inner_->ForceSetVarValueForTest(pod_var);
459 SerializedVarTestConstructor::SerializedVarTestConstructor(
460 const std::string& str) {
461 inner_->ForceSetVarValueForTest(StringVar::StringToPPVar(str));
464 SerializedVarTestReader::SerializedVarTestReader(const SerializedVar& var)
465 : SerializedVar(var) {