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

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

Issue 13887007: Introduce RawVarData and associated classes for serializing PP_Vars (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 months 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/raw_var_data.h ('k') | ppapi/proxy/raw_var_data_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2013 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/raw_var_data.h"
6
7 #include <stack>
8
9 #include "base/hash_tables.h"
10 #include "base/stl_util.h"
11 #include "ipc/ipc_message.h"
12 #include "ppapi/proxy/ppapi_param_traits.h"
13 #include "ppapi/shared_impl/array_var.h"
14 #include "ppapi/shared_impl/dictionary_var.h"
15 #include "ppapi/shared_impl/ppapi_globals.h"
16 #include "ppapi/shared_impl/scoped_pp_var.h"
17 #include "ppapi/shared_impl/var.h"
18 #include "ppapi/shared_impl/var_tracker.h"
19
20 using std::make_pair;
21
22 namespace ppapi {
23 namespace proxy {
24
25 namespace {
26
27 // When sending array buffers, if the size is over 256K, we use shared
28 // memory instead of sending the data over IPC. Light testing suggests
29 // shared memory is much faster for 256K and larger messages.
30 static const uint32 kMinimumArrayBufferSizeForShmem = 256 * 1024;
31
32 void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) {
33 IPC::ParamTraits<SerializedHandle>::Write(m, handle);
34 }
35
36 // For a given PP_Var, returns the RawVarData associated with it, or creates a
37 // new one if there is no existing one. The data is appended to |data| if it
38 // is newly created. The index into |data| pointing to the result is returned.
39 // |id_map| keeps track of RawVarDatas that have already been created.
40 size_t GetOrCreateRawVarData(const PP_Var& var,
41 base::hash_map<int64_t, size_t>* id_map,
42 ScopedVector<RawVarData>* data) {
43 if (VarTracker::IsVarTypeRefcounted(var.type)) {
44 base::hash_map<int64_t, size_t>::iterator it = id_map->find(
45 var.value.as_id);
46 if (it != id_map->end()) {
47 return it->second;
48 } else {
49 data->push_back(RawVarData::Create(var.type));
50 (*id_map)[var.value.as_id] = data->size() - 1;
51 }
52 } else {
53 data->push_back(RawVarData::Create(var.type));
54 }
55 return data->size() - 1;
56 }
57
58 } // namespace
59
60 // RawVarDataGraph ------------------------------------------------------------
61 RawVarDataGraph::RawVarDataGraph() {
62 }
63
64 RawVarDataGraph::~RawVarDataGraph() {
65 }
66
67 // static
68 scoped_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var,
69 PP_Instance instance) {
70 scoped_ptr<RawVarDataGraph> graph(new RawVarDataGraph);
71 // Map of |var.value.as_id| to a RawVarData index in RawVarDataGraph.
72 base::hash_map<int64_t, size_t> id_map;
73
74 std::stack<std::pair<PP_Var, size_t> > stack;
75 stack.push(make_pair(var, GetOrCreateRawVarData(var, &id_map,
76 &graph->data_)));
77
78 // Traverse the PP_Var graph with DFS.
79 while (!stack.empty()) {
80 PP_Var current_var = stack.top().first;
81 RawVarData* current_var_data = graph->data_[stack.top().second];
82 stack.pop();
83
84 // If the node is initialized, it means we have visited it.
85 if (current_var_data->initialized())
86 continue;
87
88 if (!current_var_data->Init(current_var, instance)) {
89 NOTREACHED();
90 return scoped_ptr<RawVarDataGraph>();
91 }
92
93 // Add child nodes to the stack.
94 if (current_var.type == PP_VARTYPE_ARRAY) {
95 ArrayVar* array_var = ArrayVar::FromPPVar(current_var);
96 if (!array_var) {
97 NOTREACHED();
98 return scoped_ptr<RawVarDataGraph>();
99 }
100 for (ArrayVar::ElementVector::const_iterator iter =
101 array_var->elements().begin();
102 iter != array_var->elements().end();
103 ++iter) {
104 size_t child_id = GetOrCreateRawVarData(iter->get(), &id_map,
105 &graph->data_);
106 static_cast<ArrayRawVarData*>(current_var_data)->AddChild(child_id);
107 stack.push(make_pair(iter->get(), child_id));
108 }
109 } else if (current_var.type == PP_VARTYPE_DICTIONARY) {
110 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var);
111 if (!dict_var) {
112 NOTREACHED();
113 return scoped_ptr<RawVarDataGraph>();
114 }
115 for (DictionaryVar::KeyValueMap::const_iterator iter =
116 dict_var->key_value_map().begin();
117 iter != dict_var->key_value_map().end();
118 ++iter) {
119 size_t child_id = GetOrCreateRawVarData(iter->second.get(), &id_map,
120 &graph->data_);
121 static_cast<DictionaryRawVarData*>(
122 current_var_data)->AddChild(iter->first, child_id);
123 stack.push(make_pair(iter->second.get(), child_id));
124 }
125 }
126 }
127 return graph.Pass();
128 }
129
130 PP_Var RawVarDataGraph::CreatePPVar(PP_Instance instance) {
131 // Create and initialize each node in the graph.
132 std::vector<PP_Var> graph;
133 for (size_t i = 0; i < data_.size(); ++i)
134 graph.push_back(data_[i]->CreatePPVar(instance));
135 for (size_t i = 0; i < data_.size(); ++i)
136 data_[i]->PopulatePPVar(graph[i], graph);
137 // Everything except the root will have one extra ref. Remove that ref.
dmichael (off chromium) 2013/04/15 17:40:04 I'm surprised this is the case. I'm expecting they
138 for (size_t i = 1; i < data_.size(); ++i)
139 ScopedPPVar(ScopedPPVar::PassRef(), graph[i]);
140 // The first element is the root.
141 return graph[0];
142 }
143
144 void RawVarDataGraph::Write(IPC::Message* m,
145 const HandleWriter& handle_writer) {
146 // Write the size, followed by each node in the graph.
147 m->WriteUInt32(static_cast<uint32_t>(data_.size()));
148 for (size_t i = 0; i < data_.size(); ++i) {
149 m->WriteInt(data_[i]->Type());
150 data_[i]->Write(m, handle_writer);
151 }
152 }
153
154 void RawVarDataGraph::Write(IPC::Message* m) {
155 Write(m, base::Bind(&DefaultHandleWriter));
156 }
157
158 // static
159 scoped_ptr<RawVarDataGraph> RawVarDataGraph::Read(const IPC::Message* m,
160 PickleIterator* iter) {
161 scoped_ptr<RawVarDataGraph> result(new RawVarDataGraph);
162 uint32_t size = 0;
163 if (!m->ReadUInt32(iter, &size))
164 return scoped_ptr<RawVarDataGraph>();
165 for (uint32_t i = 0; i < size; ++i) {
166 int32_t type;
167 if (!m->ReadInt(iter, &type))
168 return scoped_ptr<RawVarDataGraph>();
169 PP_VarType var_type = static_cast<PP_VarType>(type);
170 result->data_.push_back(RawVarData::Create(var_type));
171 if (!result->data_.back()->Read(var_type, m, iter))
172 return scoped_ptr<RawVarDataGraph>();
173 }
174 return result.Pass();
175 }
176
177 // RawVarData ------------------------------------------------------------------
178
179 // static
180 RawVarData* RawVarData::Create(PP_VarType type) {
181 switch (type) {
182 case PP_VARTYPE_UNDEFINED:
183 case PP_VARTYPE_NULL:
184 case PP_VARTYPE_BOOL:
185 case PP_VARTYPE_INT32:
186 case PP_VARTYPE_DOUBLE:
187 case PP_VARTYPE_OBJECT:
188 return new BasicRawVarData();
189 case PP_VARTYPE_STRING:
190 return new StringRawVarData();
191 case PP_VARTYPE_ARRAY_BUFFER:
192 return new ArrayBufferRawVarData();
193 case PP_VARTYPE_ARRAY:
194 return new ArrayRawVarData();
195 case PP_VARTYPE_DICTIONARY:
196 return new DictionaryRawVarData();
197 }
198 NOTREACHED();
199 return NULL;
200 }
201
202 RawVarData::RawVarData() : initialized_(false) {
203 }
204
205 RawVarData::~RawVarData() {
206 }
207
208 // BasicRawVarData -------------------------------------------------------------
209 BasicRawVarData::BasicRawVarData() {
210 }
211
212 BasicRawVarData::~BasicRawVarData() {
213 }
214
215 PP_VarType BasicRawVarData::Type() {
216 return var_.type;
217 }
218
219 bool BasicRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
220 var_ = var;
221 initialized_ = true;
222 return true;
223 }
224
225 PP_Var BasicRawVarData::CreatePPVar(PP_Instance instance) {
226 return var_;
227 }
228
229 void BasicRawVarData::PopulatePPVar(const PP_Var& var,
230 const std::vector<PP_Var>& graph) {
231 }
232
233 void BasicRawVarData::Write(
234 IPC::Message* m,
235 const HandleWriter& handle_writer) {
236 switch (var_.type) {
237 case PP_VARTYPE_UNDEFINED:
238 case PP_VARTYPE_NULL:
239 // These don't need any data associated with them other than the type we
240 // just serialized.
241 break;
242 case PP_VARTYPE_BOOL:
243 m->WriteBool(PP_ToBool(var_.value.as_bool));
244 break;
245 case PP_VARTYPE_INT32:
246 m->WriteInt(var_.value.as_int);
247 break;
248 case PP_VARTYPE_DOUBLE:
249 IPC::ParamTraits<double>::Write(m, var_.value.as_double);
250 break;
251 case PP_VARTYPE_OBJECT:
252 m->WriteInt64(var_.value.as_id);
253 break;
254 default:
255 NOTREACHED();
256 break;
257 }
258 }
259
260 bool BasicRawVarData::Read(PP_VarType type,
261 const IPC::Message* m,
262 PickleIterator* iter) {
263 PP_Var result;
264 result.type = type;
265 switch (type) {
266 case PP_VARTYPE_UNDEFINED:
267 case PP_VARTYPE_NULL:
268 // These don't have any data associated with them other than the type we
269 // just serialized.
270 break;
271 case PP_VARTYPE_BOOL: {
272 bool bool_value;
273 if (!m->ReadBool(iter, &bool_value))
274 return false;
275 result.value.as_bool = PP_FromBool(bool_value);
276 break;
277 }
278 case PP_VARTYPE_INT32:
279 if (!m->ReadInt(iter, &result.value.as_int))
280 return false;
281 break;
282 case PP_VARTYPE_DOUBLE:
283 if (!IPC::ParamTraits<double>::Read(m, iter, &result.value.as_double))
284 return false;
285 break;
286 case PP_VARTYPE_OBJECT:
287 if (!m->ReadInt64(iter, &result.value.as_id))
288 return false;
289 break;
290 default:
291 NOTREACHED();
292 return false;
293 }
294 var_ = result;
295 return true;
296 }
297
298 // StringRawVarData ------------------------------------------------------------
299 StringRawVarData::StringRawVarData() {
300 }
301
302 StringRawVarData::~StringRawVarData() {
303 }
304
305 PP_VarType StringRawVarData::Type() {
306 return PP_VARTYPE_STRING;
307 }
308
309 bool StringRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
310 DCHECK(var.type == PP_VARTYPE_STRING);
311 StringVar* string_var = StringVar::FromPPVar(var);
312 if (!string_var)
313 return false;
314 data_ = string_var->value();
315 initialized_ = true;
316 return true;
317 }
318
319 PP_Var StringRawVarData::CreatePPVar(PP_Instance instance) {
320 return StringVar::StringToPPVar(data_);
321 }
322
323 void StringRawVarData::PopulatePPVar(const PP_Var& var,
324 const std::vector<PP_Var>& graph) {
325 }
326
327 void StringRawVarData::Write(IPC::Message* m,
328 const HandleWriter& handle_writer) {
329 m->WriteString(data_);
330 }
331
332 bool StringRawVarData::Read(PP_VarType type,
333 const IPC::Message* m,
334 PickleIterator* iter) {
335 if (!m->ReadString(iter, &data_))
336 return false;
337 return true;
338 }
339
340 // ArrayBufferRawVarData -------------------------------------------------------
341 ArrayBufferRawVarData::ArrayBufferRawVarData() {
342 }
343
344 ArrayBufferRawVarData::~ArrayBufferRawVarData() {
345 }
346
347 PP_VarType ArrayBufferRawVarData::Type() {
348 return PP_VARTYPE_ARRAY_BUFFER;
349 }
350
351 bool ArrayBufferRawVarData::Init(const PP_Var& var,
352 PP_Instance instance) {
353 DCHECK(var.type == PP_VARTYPE_ARRAY_BUFFER);
354 ArrayBufferVar* buffer_var = ArrayBufferVar::FromPPVar(var);
355 if (!buffer_var)
356 return false;
357 bool using_shmem = false;
358 if (buffer_var->ByteLength() >= kMinimumArrayBufferSizeForShmem &&
359 instance != 0) {
360 int host_handle_id;
361 base::SharedMemoryHandle plugin_handle;
362 using_shmem = buffer_var->CopyToNewShmem(instance,
363 &host_handle_id,
364 &plugin_handle);
365 if (using_shmem) {
366 if (host_shm_handle_id_ != -1) {
367 DCHECK(!base::SharedMemory::IsHandleValid(plugin_handle));
368 DCHECK(PpapiGlobals::Get()->IsPluginGlobals());
369 type_ = ARRAY_BUFFER_SHMEM_HOST;
370 host_shm_handle_id_ = host_handle_id;
371 } else {
372 DCHECK(base::SharedMemory::IsHandleValid(plugin_handle));
373 DCHECK(PpapiGlobals::Get()->IsHostGlobals());
374 type_ = ARRAY_BUFFER_SHMEM_PLUGIN;
375 plugin_shm_handle_ = SerializedHandle(plugin_handle,
376 buffer_var->ByteLength());
377 }
378 }
379 }
380 if (!using_shmem) {
381 type_ = ARRAY_BUFFER_NO_SHMEM;
382 data_ = std::string(static_cast<const char*>(buffer_var->Map()),
383 buffer_var->ByteLength());
384 }
385 initialized_ = true;
386 return true;
387 }
388
389 PP_Var ArrayBufferRawVarData::CreatePPVar(PP_Instance instance) {
390 PP_Var result = PP_MakeUndefined();
391 switch (type_) {
392 case ARRAY_BUFFER_SHMEM_HOST: {
393 base::SharedMemoryHandle host_handle;
394 uint32 size_in_bytes;
395 bool ok = PpapiGlobals::Get()->GetVarTracker()->
396 StopTrackingSharedMemoryHandle(host_shm_handle_id_,
397 instance,
398 &host_handle,
399 &size_in_bytes);
400 if (ok) {
401 result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
402 size_in_bytes, host_handle);
403 } else {
404 LOG(ERROR) << "Couldn't find array buffer id: " << host_shm_handle_id_;
405 return PP_MakeUndefined();
406 }
407 break;
408 }
409 case ARRAY_BUFFER_SHMEM_PLUGIN: {
410 result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
411 plugin_shm_handle_.size(),
412 plugin_shm_handle_.shmem());
413 break;
414 }
415 case ARRAY_BUFFER_NO_SHMEM: {
416 result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
417 static_cast<uint32>(data_.size()), data_.data());
418 break;
419 }
420 default:
421 NOTREACHED();
422 return PP_MakeUndefined();
423 }
424 DCHECK(result.type == PP_VARTYPE_ARRAY_BUFFER);
425 return result;
426 }
427
428 void ArrayBufferRawVarData::PopulatePPVar(const PP_Var& var,
429 const std::vector<PP_Var>& graph) {
430 }
431
432 void ArrayBufferRawVarData::Write(
433 IPC::Message* m,
434 const HandleWriter& handle_writer) {
435 m->WriteInt(type_);
436 switch (type_) {
437 case ARRAY_BUFFER_SHMEM_HOST:
438 m->WriteInt(host_shm_handle_id_);
439 break;
440 case ARRAY_BUFFER_SHMEM_PLUGIN:
441 handle_writer.Run(m, plugin_shm_handle_);
442 break;
443 case ARRAY_BUFFER_NO_SHMEM:
444 m->WriteString(data_);
445 break;
446 }
447 }
448
449 bool ArrayBufferRawVarData::Read(PP_VarType type,
450 const IPC::Message* m,
451 PickleIterator* iter) {
452 int shmem_type;
453 if (!m->ReadInt(iter, &shmem_type))
454 return false;
455 type_ = static_cast<ShmemType>(shmem_type);
456 switch (type_) {
457 case ARRAY_BUFFER_SHMEM_HOST:
458 if (!m->ReadInt(iter, &host_shm_handle_id_))
459 return false;
460 break;
461 case ARRAY_BUFFER_SHMEM_PLUGIN:
462 if (!IPC::ParamTraits<SerializedHandle>::Read(
463 m, iter, &plugin_shm_handle_)) {
464 return false;
465 }
466 break;
467 case ARRAY_BUFFER_NO_SHMEM:
468 if (!m->ReadString(iter, &data_))
469 return false;
470 break;
471 default:
472 // We read an invalid ID.
473 NOTREACHED();
474 return false;
475 }
476 return true;
477 }
478
479 // ArrayRawVarData -------------------------------------------------------------
480 ArrayRawVarData::ArrayRawVarData() {
481 }
482
483 ArrayRawVarData::~ArrayRawVarData() {
484 }
485
486 void ArrayRawVarData::AddChild(size_t element) {
487 children_.push_back(element);
488 }
489
490 PP_VarType ArrayRawVarData::Type() {
491 return PP_VARTYPE_ARRAY;
492 }
493
494 bool ArrayRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
495 initialized_ = true;
496 DCHECK(var.type == PP_VARTYPE_ARRAY);
497 initialized_ = true;
498 return true;
499 }
500
501 PP_Var ArrayRawVarData::CreatePPVar(PP_Instance instance) {
502 return (new ArrayVar())->GetPPVar();
503 }
504
505 void ArrayRawVarData::PopulatePPVar(const PP_Var& var,
506 const std::vector<PP_Var>& graph) {
507 if (var.type != PP_VARTYPE_ARRAY) {
508 NOTREACHED();
509 return;
510 }
511 ArrayVar* array_var = ArrayVar::FromPPVar(var);
512 DCHECK(array_var->elements().empty());
513 for (size_t i = 0; i < children_.size(); ++i)
514 array_var->elements().push_back(ScopedPPVar(graph[children_[i]]));
515 }
516
517 void ArrayRawVarData::Write(IPC::Message* m,
518 const HandleWriter& handle_writer) {
519 m->WriteUInt32(static_cast<uint32_t>(children_.size()));
520 for (size_t i = 0; i < children_.size(); ++i)
521 m->WriteUInt32(static_cast<uint32_t>(children_[i]));
522 }
523
524 bool ArrayRawVarData::Read(PP_VarType type,
525 const IPC::Message* m,
526 PickleIterator* iter) {
527 uint32_t size;
528 if (!m->ReadUInt32(iter, &size))
529 return false;
530 for (uint32_t i = 0; i < size; ++i) {
531 uint32_t index;
532 if (!m->ReadUInt32(iter, &index))
533 return false;
534 children_.push_back(index);
535 }
536 return true;
537 }
538
539 // DictionaryRawVarData --------------------------------------------------------
540 DictionaryRawVarData::DictionaryRawVarData() {
541 }
542
543 DictionaryRawVarData::~DictionaryRawVarData() {
544 }
545
546 void DictionaryRawVarData::AddChild(const std::string& key,
547 size_t value) {
548 children_.push_back(make_pair(key, value));
549 }
550
551 PP_VarType DictionaryRawVarData::Type() {
552 return PP_VARTYPE_DICTIONARY;
553 }
554
555 bool DictionaryRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
556 DCHECK(var.type == PP_VARTYPE_DICTIONARY);
557 initialized_ = true;
558 return true;
559 }
560
561 PP_Var DictionaryRawVarData::CreatePPVar(PP_Instance instance) {
562 return (new DictionaryVar())->GetPPVar();
563 }
564
565 void DictionaryRawVarData::PopulatePPVar(const PP_Var& var,
566 const std::vector<PP_Var>& graph) {
567 if (var.type != PP_VARTYPE_DICTIONARY) {
568 NOTREACHED();
569 return;
570 }
571 DictionaryVar* dictionary_var = DictionaryVar::FromPPVar(var);
572 DCHECK(dictionary_var->key_value_map().empty());
573 for (size_t i = 0; i < children_.size(); ++i) {
574 dictionary_var->Set(StringVar::StringToPPVar(children_[i].first),
575 graph[children_[i].second]);
576 }
577 }
578
579 void DictionaryRawVarData::Write(
580 IPC::Message* m,
581 const HandleWriter& handle_writer) {
582 m->WriteUInt32(static_cast<uint32_t>(children_.size()));
583 for (size_t i = 0; i < children_.size(); ++i) {
584 m->WriteString(children_[i].first);
585 m->WriteUInt32(static_cast<uint32_t>(children_[i].second));
586 }
587 }
588
589 bool DictionaryRawVarData::Read(PP_VarType type,
590 const IPC::Message* m,
591 PickleIterator* iter) {
592 uint32_t size;
593 if (!m->ReadUInt32(iter, &size))
594 return false;
595 for (uint32_t i = 0; i < size; ++i) {
596 std::string key;
597 uint32_t value;
598 if (!m->ReadString(iter, &key))
599 return false;
600 if (!m->ReadUInt32(iter, &value))
601 return false;
602 children_.push_back(make_pair(key, value));
603 }
604 return true;
605 }
606
607 } // namespace proxy
608 } // namespace ppapi
dmichael (off chromium) 2013/04/15 17:40:04 I notice that you deleted VarGraph and this file i
OLDNEW
« no previous file with comments | « ppapi/proxy/raw_var_data.h ('k') | ppapi/proxy/raw_var_data_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698