OLD | NEW |
---|---|
(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
| |
OLD | NEW |