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"
22 void DefaultHandleWriter(IPC::Message
* m
, const SerializedHandle
& handle
) {
23 IPC::ParamTraits
<SerializedHandle
>::Write(m
, handle
);
27 // SerializedVar::Inner --------------------------------------------------------
29 SerializedVar::Inner::Inner()
30 : serialization_rules_(NULL
),
31 var_(PP_MakeUndefined()),
33 cleanup_mode_(CLEANUP_NONE
),
36 has_been_serialized_
= false;
37 has_been_deserialized_
= false;
41 SerializedVar::Inner::Inner(VarSerializationRules
* serialization_rules
)
42 : serialization_rules_(serialization_rules
),
43 var_(PP_MakeUndefined()),
45 cleanup_mode_(CLEANUP_NONE
) {
47 has_been_serialized_
= false;
48 has_been_deserialized_
= false;
52 SerializedVar::Inner::~Inner() {
53 switch (cleanup_mode_
) {
54 case END_SEND_PASS_REF
:
55 serialization_rules_
->EndSendPassRef(var_
);
57 case END_RECEIVE_CALLER_OWNED
:
58 serialization_rules_
->EndReceiveCallerOwned(var_
);
65 PP_Var
SerializedVar::Inner::GetVar() {
66 DCHECK(serialization_rules_
.get());
68 #if defined(NACL_WIN64)
70 return PP_MakeUndefined();
72 if (raw_var_data_
.get()) {
73 var_
= raw_var_data_
->CreatePPVar(instance_
);
74 raw_var_data_
.reset(NULL
);
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());
86 raw_var_data_
.reset(NULL
);
89 void SerializedVar::Inner::SetInstance(PP_Instance instance
) {
93 void SerializedVar::Inner::ForceSetVarValueForTest(PP_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());
113 // We should only be serializing something once.
114 DCHECK(!has_been_serialized_
);
115 has_been_serialized_
= true;
117 scoped_ptr
<RawVarDataGraph
> data
= RawVarDataGraph::Create(var_
, instance_
);
119 m
->WriteBool(true); // Success.
120 data
->Write(m
, base::Bind(&DefaultHandleWriter
));
122 m
->WriteBool(false); // Failure.
126 void SerializedVar::Inner::WriteDataToMessage(
128 const HandleWriter
& handle_writer
) const {
130 m
->WriteBool(true); // Success.
131 raw_var_data_
->Write(m
, handle_writer
);
133 m
->WriteBool(false); // Failure.
137 bool SerializedVar::Inner::ReadFromMessage(const IPC::Message
* m
,
138 base::PickleIterator
* iter
) {
140 // We should only deserialize something once or will end up with leaked
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;
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_
))
155 raw_var_data_
= RawVarDataGraph::Read(m
, iter
);
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
,
187 : SerializedVar(dispatcher
->serialization_rules()) {
188 inner_
->SetVar(dispatcher
->serialization_rules()->SendCallerOwned(var
));
192 void SerializedVarSendInput::ConvertVector(Dispatcher
* dispatcher
,
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
,
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(
226 return inner_
->GetVar();
229 // ReceiveSerializedException --------------------------------------------------
231 ReceiveSerializedException::ReceiveSerializedException(Dispatcher
* dispatcher
,
233 : SerializedVar(dispatcher
->serialization_rules()),
234 exception_(exception
) {
237 ReceiveSerializedException::~ReceiveSerializedException() {
239 // When an output exception is specified, it will take ownership of the
242 inner_
->serialization_rules()->ReceivePassRef(inner_
->GetVar()));
243 *exception_
= inner_
->GetVar();
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
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
,
267 : dispatcher_(dispatcher
),
268 output_count_(output_count
),
272 ReceiveSerializedVarVectorOutParam::~ReceiveSerializedVarVectorOutParam() {
273 *output_count_
= static_cast<uint32_t>(vector_
.size());
274 if (!vector_
.size()) {
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() {
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(
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
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
,
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
));
376 SerializedVar
SerializedVarReturnValue::Convert(Dispatcher
* dispatcher
,
378 // Mimic what happens in the normal case.
379 SerializedVar result
;
380 SerializedVarReturnValue
retvalue(&result
);
381 retvalue
.Return(dispatcher
, var
);
385 // SerializedVarOutParam -------------------------------------------------------
387 SerializedVarOutParam::SerializedVarOutParam(SerializedVar
* serialized
)
388 : serialized_(serialized
),
389 writable_var_(PP_MakeUndefined()),
393 SerializedVarOutParam::~SerializedVarOutParam() {
394 if (serialized_
->inner_
->serialization_rules()) {
395 // When unset, OutParam wasn't called. We'll just leave the var untouched
397 serialized_
->inner_
->SetVar(
398 serialized_
->inner_
->serialization_rules()->BeginSendPassRef(
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
)
420 serialized_(serialized
),
425 SerializedVarVectorOutParam::~SerializedVarVectorOutParam() {
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.
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.
445 PP_Var
** SerializedVarVectorOutParam::ArrayOutParam(Dispatcher
* dispatcher
) {
446 DCHECK(!dispatcher_
); // Should only be called once.
447 dispatcher_
= dispatcher
;
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
) {