Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: ppapi/proxy/serialized_var.cc

Issue 4096008: Var serialization-related proxy stuff. This allows vars to be sent over IPC... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ppapi/proxy/serialized_var.h ('k') | ppapi/proxy/var_serialization_rules.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 #include "ppapi/proxy/serialized_var.h"
6
7 #include "base/logging.h"
8 #include "ipc/ipc_message_utils.h"
9 #include "ppapi/proxy/dispatcher.h"
10 #include "ppapi/proxy/ppapi_param_traits.h"
11 #include "ppapi/proxy/var_serialization_rules.h"
12
13 namespace pp {
14 namespace proxy {
15
16 // SerializedVar::Inner --------------------------------------------------------
17
18 SerializedVar::Inner::Inner()
19 : serialization_rules_(NULL),
20 var_(PP_MakeUndefined()),
21 cleanup_mode_(CLEANUP_NONE) {
22 #ifndef NDEBUG
23 has_been_serialized_ = false;
24 has_been_deserialized_ = false;
25 #endif
26 }
27
28 SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules)
29 : serialization_rules_(serialization_rules),
30 var_(PP_MakeUndefined()),
31 cleanup_mode_(CLEANUP_NONE) {
32 #ifndef NDEBUG
33 has_been_serialized_ = false;
34 has_been_deserialized_ = false;
35 #endif
36 }
37
38 SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules,
39 const PP_Var& var)
40 : serialization_rules_(serialization_rules),
41 var_(var),
42 cleanup_mode_(CLEANUP_NONE) {
43 #ifndef NDEBUG
44 has_been_serialized_ = false;
45 has_been_deserialized_ = false;
46 #endif
47 }
48
49 SerializedVar::Inner::~Inner() {
50 switch (cleanup_mode_) {
51 case END_SEND_PASS_REF:
52 serialization_rules_->EndSendPassRef(var_);
53 break;
54 case END_RECEIVE_CALLER_OWNED:
55 serialization_rules_->EndReceiveCallerOwned(var_);
56 break;
57 default:
58 break;
59 }
60 }
61
62 PP_Var SerializedVar::Inner::GetVar() const {
63 DCHECK(serialization_rules_);
64
65 // If we're a string var, we should have already converted the string value
66 // to a var ID.
67 DCHECK(var_.type != PP_VARTYPE_STRING || var_.value.as_id != 0);
68 return var_;
69 }
70
71 PP_Var SerializedVar::Inner::GetIncompleteVar() const {
72 DCHECK(serialization_rules_);
73 return var_;
74 }
75
76 void SerializedVar::Inner::SetVar(PP_Var var) {
77 // Sanity check, when updating the var we should have received a
78 // serialization rules pointer already.
79 DCHECK(serialization_rules_);
80 var_ = var;
81 }
82
83 const std::string& SerializedVar::Inner::GetString() const {
84 DCHECK(serialization_rules_);
85 return string_value_;
86 }
87
88 std::string* SerializedVar::Inner::GetStringPtr() {
89 DCHECK(serialization_rules_);
90 return &string_value_;
91 }
92
93 void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
94 // When writing to the IPC messages, a serization rules handler should
95 // always have been set.
96 //
97 // When sending a message, it should be difficult to trigger this if you're
98 // using the SerializedVarSendInput class and giving a non-NULL dispatcher.
99 // Make sure you're using the proper "Send" helper class.
100 //
101 // It should be more common to see this when handling an incoming message
102 // that returns a var. This means the message handler didn't write to the
103 // output parameter, or possibly you used the wrong helper class
104 // (normally SerializedVarReturnValue).
105 DCHECK(serialization_rules_);
106
107 #ifndef NDEBUG
108 // We should only be serializing something once.
109 DCHECK(!has_been_serialized_);
110 has_been_serialized_ = true;
111 #endif
112
113 // If the var is not a string type, we should not have ended up with any
114 // string data.
115 DCHECK(var_.type == PP_VARTYPE_STRING || string_value_.empty());
116
117 m->WriteInt(static_cast<int>(var_.type));
118 switch (var_.type) {
119 case PP_VARTYPE_UNDEFINED:
120 case PP_VARTYPE_NULL:
121 // These don't need any data associated with them other than the type we
122 // just serialized.
123 break;
124 case PP_VARTYPE_BOOL:
125 m->WriteBool(var_.value.as_bool);
126 break;
127 case PP_VARTYPE_INT32:
128 m->WriteInt(var_.value.as_int);
129 break;
130 case PP_VARTYPE_DOUBLE:
131 IPC::ParamTraits<double>::Write(m, var_.value.as_double);
132 break;
133 case PP_VARTYPE_STRING:
134 // TODO(brettw) in the case of an invalid string ID, it would be nice
135 // to send something to the other side such that a 0 ID would be
136 // generated there. Then the function implementing the interface can
137 // handle the invalid string as if it was in process rather than seeing
138 // what looks like a valid empty string.
139 m->WriteString(string_value_);
140 break;
141 case PP_VARTYPE_OBJECT:
142 m->WriteInt64(var_.value.as_id);
143 break;
144 }
145 }
146
147 bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m, void** iter) {
148 #ifndef NDEBUG
149 // We should only deserialize something once or will end up with leaked
150 // references.
151 //
152 // One place this has happened in the past is using
153 // std::vector<SerializedVar>.resize(). If you're doing this manually instead
154 // of using the helper classes for handling in/out vectors of vars, be
155 // sure you use the same pattern as the SerializedVarVector classes.
156 DCHECK(!has_been_deserialized_);
157 has_been_deserialized_ = true;
158 #endif
159
160 // When reading, the dispatcher should be set when we get a Deserialize
161 // call (which will supply a dispatcher).
162 int type;
163 if (!m->ReadInt(iter, &type))
164 return false;
165
166 bool success = false;
167 switch (type) {
168 case PP_VARTYPE_UNDEFINED:
169 case PP_VARTYPE_NULL:
170 // These don't have any data associated with them other than the type we
171 // just serialized.
172 success = true;
173 break;
174 case PP_VARTYPE_BOOL:
175 success = m->ReadBool(iter, &var_.value.as_bool);
176 break;
177 case PP_VARTYPE_INT32:
178 success = m->ReadInt(iter, &var_.value.as_int);
179 break;
180 case PP_VARTYPE_DOUBLE:
181 success = IPC::ParamTraits<double>::Read(m, iter, &var_.value.as_double);
182 break;
183 case PP_VARTYPE_STRING:
184 success = m->ReadString(iter, &string_value_);
185 var_.value.as_id = 0;
186 break;
187 case PP_VARTYPE_OBJECT:
188 success = m->ReadInt64(iter, &var_.value.as_id);
189 break;
190 default:
191 // Leave success as false.
192 break;
193 }
194
195 // All success cases get here. We avoid writing the type above so that the
196 // output param is untouched (defaults to VARTYPE_UNDEFINED) even in the
197 // failure case.
198 if (success)
199 var_.type = static_cast<PP_VarType>(type);
200 return success;
201 }
202
203 // SerializedVar ---------------------------------------------------------------
204
205 SerializedVar::SerializedVar() : inner_(new Inner) {
206 }
207
208 SerializedVar::SerializedVar(VarSerializationRules* serialization_rules)
209 : inner_(new Inner(serialization_rules)) {
210 }
211
212 SerializedVar::SerializedVar(VarSerializationRules* serialization_rules,
213 const PP_Var& var)
214 : inner_(new Inner(serialization_rules, var)) {
215 }
216
217 SerializedVar::~SerializedVar() {
218 }
219
220 // SerializedVarSendInput ------------------------------------------------------
221
222 SerializedVarSendInput::SerializedVarSendInput(Dispatcher* dispatcher,
223 const PP_Var& var)
224 : SerializedVar(dispatcher->serialization_rules(), var) {
225 dispatcher->serialization_rules()->SendCallerOwned(var,
226 inner_->GetStringPtr());
227 }
228
229 // static
230 void SerializedVarSendInput::ConvertVector(Dispatcher* dispatcher,
231 const PP_Var* input,
232 size_t input_count,
233 std::vector<SerializedVar>* output) {
234 output->resize(input_count);
235 for (size_t i = 0; i < input_count; i++) {
236 (*output)[i] = SerializedVar(dispatcher->serialization_rules(), input[i]);
237 dispatcher->serialization_rules()->SendCallerOwned(
238 input[i], (*output)[i].inner_->GetStringPtr());
239 }
240 }
241
242 // ReceiveSerializedVarReturnValue ---------------------------------------------
243
244 ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue() {
245 }
246
247 PP_Var ReceiveSerializedVarReturnValue::Return(Dispatcher* dispatcher) {
248 inner_->set_serialization_rules(dispatcher->serialization_rules());
249 inner_->SetVar(inner_->serialization_rules()->ReceivePassRef(
250 inner_->GetIncompleteVar(), inner_->GetString()));
251 return inner_->GetVar();
252 }
253
254 // ReceiveSerializedException --------------------------------------------------
255
256 ReceiveSerializedException::ReceiveSerializedException(Dispatcher* dispatcher,
257 PP_Var* exception)
258 : SerializedVar(dispatcher->serialization_rules()),
259 exception_(exception) {
260 }
261
262 ReceiveSerializedException::~ReceiveSerializedException() {
263 if (exception_) {
264 // When an output exception is specified, it will take ownership of the
265 // reference.
266 inner_->SetVar(inner_->serialization_rules()->ReceivePassRef(
267 inner_->GetIncompleteVar(), inner_->GetString()));
268 *exception_ = inner_->GetVar();
269 } else {
270 // When no output exception is specified, the browser thinks we have a ref
271 // to an object that we don't want (this will happen only in the plugin
272 // since the browser will always specify an out exception for the plugin to
273 // write into).
274 //
275 // Strings don't need this handling since we can just avoid creating a
276 // Var from the std::string in the first place.
277 if (inner_->GetVar().type == PP_VARTYPE_OBJECT)
278 inner_->serialization_rules()->ReleaseObjectRef(inner_->GetVar());
279 }
280 }
281
282 bool ReceiveSerializedException::IsThrown() const {
283 return exception_ && exception_->type != PP_VARTYPE_UNDEFINED;
284 }
285
286 // ReceiveSerializedVarVectorOutParam ------------------------------------------
287
288 ReceiveSerializedVarVectorOutParam::ReceiveSerializedVarVectorOutParam(
289 Dispatcher* dispatcher,
290 uint32_t* output_count,
291 PP_Var** output)
292 : dispatcher_(dispatcher),
293 output_count_(output_count),
294 output_(output) {
295 }
296
297 ReceiveSerializedVarVectorOutParam::~ReceiveSerializedVarVectorOutParam() {
298 *output_count_ = static_cast<uint32_t>(vector_.size());
299 if (!vector_.size()) {
300 *output_ = NULL;
301 return;
302 }
303
304 *output_ = static_cast<PP_Var*>(malloc(vector_.size() * sizeof(PP_Var)));
305 for (size_t i = 0; i < vector_.size(); i++) {
306 // Here we just mimic what happens when returning a value.
307 ReceiveSerializedVarReturnValue converted;
308 SerializedVar* serialized = &converted;
309 *serialized = vector_[i];
310 (*output_)[i] = converted.Return(dispatcher_);
311 }
312 }
313
314 std::vector<SerializedVar>* ReceiveSerializedVarVectorOutParam::OutParam() {
315 return &vector_;
316 }
317
318 // SerializedVarReceiveInput ---------------------------------------------------
319
320 SerializedVarReceiveInput::SerializedVarReceiveInput(
321 const SerializedVar& serialized)
322 : serialized_(serialized),
323 dispatcher_(NULL),
324 var_(PP_MakeUndefined()) {
325 }
326
327 SerializedVarReceiveInput::~SerializedVarReceiveInput() {
328 }
329
330 PP_Var SerializedVarReceiveInput::Get(Dispatcher* dispatcher) {
331 serialized_.inner_->set_serialization_rules(
332 dispatcher->serialization_rules());
333
334 // Ensure that when the serialized var goes out of scope it cleans up the
335 // stuff we're making in BeginReceiveCallerOwned.
336 serialized_.inner_->set_cleanup_mode(SerializedVar::END_RECEIVE_CALLER_OWNED);
337
338 serialized_.inner_->SetVar(
339 serialized_.inner_->serialization_rules()->BeginReceiveCallerOwned(
340 serialized_.inner_->GetIncompleteVar(),
341 serialized_.inner_->GetStringPtr()));
342 return serialized_.inner_->GetVar();
343 }
344
345 // SerializedVarVectorReceiveInput ---------------------------------------------
346
347 SerializedVarVectorReceiveInput::SerializedVarVectorReceiveInput(
348 const std::vector<SerializedVar>& serialized)
349 : serialized_(serialized) {
350 }
351
352 SerializedVarVectorReceiveInput::~SerializedVarVectorReceiveInput() {
353 for (size_t i = 0; i < deserialized_.size(); i++) {
354 serialized_[i].inner_->serialization_rules()->EndReceiveCallerOwned(
355 deserialized_[i]);
356 }
357 }
358
359 PP_Var* SerializedVarVectorReceiveInput::Get(Dispatcher* dispatcher,
360 uint32_t* array_size) {
361 deserialized_.resize(serialized_.size());
362 for (size_t i = 0; i < serialized_.size(); i++) {
363 // The vector must be able to clean themselves up after this call is
364 // torn down.
365 serialized_[i].inner_->set_serialization_rules(
366 dispatcher->serialization_rules());
367
368 serialized_[i].inner_->SetVar(
369 serialized_[i].inner_->serialization_rules()->BeginReceiveCallerOwned(
370 serialized_[i].inner_->GetIncompleteVar(),
371 serialized_[i].inner_->GetStringPtr()));
372 deserialized_[i] = serialized_[i].inner_->GetVar();
373 }
374
375 *array_size = static_cast<uint32_t>(serialized_.size());
376 return deserialized_.size() > 0 ? &deserialized_[0] : NULL;
377 }
378
379 // SerializedVarReturnValue ----------------------------------------------------
380
381 SerializedVarReturnValue::SerializedVarReturnValue(SerializedVar* serialized)
382 : serialized_(serialized) {
383 }
384
385 void SerializedVarReturnValue::Return(Dispatcher* dispatcher,
386 const PP_Var& var) {
387 serialized_->inner_->set_serialization_rules(
388 dispatcher->serialization_rules());
389 serialized_->inner_->SetVar(var);
390
391 // Var must clean up after our BeginSendPassRef call.
392 serialized_->inner_->set_cleanup_mode(SerializedVar::END_SEND_PASS_REF);
393
394 dispatcher->serialization_rules()->BeginSendPassRef(
395 serialized_->inner_->GetIncompleteVar(),
396 serialized_->inner_->GetStringPtr());
397 }
398
399 // SerializedVarOutParam -------------------------------------------------------
400
401 SerializedVarOutParam::SerializedVarOutParam(SerializedVar* serialized)
402 : serialized_(serialized),
403 writable_var_(PP_MakeUndefined()) {
404 }
405
406 SerializedVarOutParam::~SerializedVarOutParam() {
407 if (serialized_->inner_->serialization_rules()) {
408 // When unset, OutParam wasn't called. We'll just leave the var untouched
409 // in that case.
410 serialized_->inner_->SetVar(writable_var_);
411 serialized_->inner_->serialization_rules()->BeginSendPassRef(
412 writable_var_, serialized_->inner_->GetStringPtr());
413
414 // Normally the current object will be created on the stack to wrap a
415 // SerializedVar and won't have a scope around the actual IPC send. So we
416 // need to tell the SerializedVar to do the begin/end send pass ref calls.
417 serialized_->inner_->set_cleanup_mode(SerializedVar::END_SEND_PASS_REF);
418 }
419 }
420
421 PP_Var* SerializedVarOutParam::OutParam(Dispatcher* dispatcher) {
422 serialized_->inner_->set_serialization_rules(
423 dispatcher->serialization_rules());
424 return &writable_var_;
425 }
426
427 // SerializedVarVectorOutParam -------------------------------------------------
428
429 SerializedVarVectorOutParam::SerializedVarVectorOutParam(
430 std::vector<SerializedVar>* serialized)
431 : dispatcher_(NULL),
432 serialized_(serialized),
433 count_(0),
434 array_(NULL) {
435 }
436
437 SerializedVarVectorOutParam::~SerializedVarVectorOutParam() {
438 DCHECK(dispatcher_);
439
440 // Convert the array written by the pepper code to the serialized structure.
441 // Note we can't use resize here, we have to allocate a new SerializedVar
442 // for each serialized item. See ParamTraits<vector<SerializedVar>>::Read.
443 serialized_->reserve(count_);
444 for (uint32_t i = 0; i < count_; i++) {
445 // Just mimic what we do for regular OutParams.
446 SerializedVar var;
447 SerializedVarOutParam out(&var);
448 *out.OutParam(dispatcher_) = array_[i];
449 serialized_->push_back(var);
450 }
451
452 // When returning arrays, the pepper code expects the caller to take
453 // ownership of the array.
454 free(array_);
455 }
456
457 PP_Var** SerializedVarVectorOutParam::ArrayOutParam(Dispatcher* dispatcher) {
458 DCHECK(!dispatcher_); // Should only be called once.
459 dispatcher_ = dispatcher;
460 return &array_;
461 }
462
463 } // namespace proxy
464 } // namespace pp
465
OLDNEW
« no previous file with comments | « ppapi/proxy/serialized_var.h ('k') | ppapi/proxy/var_serialization_rules.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698