• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/containers/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/resource_var.h"
17 #include "ppapi/shared_impl/scoped_pp_var.h"
18 #include "ppapi/shared_impl/var.h"
19 #include "ppapi/shared_impl/var_tracker.h"
20 
21 using std::make_pair;
22 
23 namespace ppapi {
24 namespace proxy {
25 
26 namespace {
27 
28 // When sending array buffers, if the size is over 256K, we use shared
29 // memory instead of sending the data over IPC. Light testing suggests
30 // shared memory is much faster for 256K and larger messages.
31 static const uint32 kMinimumArrayBufferSizeForShmem = 256 * 1024;
32 static uint32 g_minimum_array_buffer_size_for_shmem =
33     kMinimumArrayBufferSizeForShmem;
34 
35 struct StackEntry {
StackEntryppapi::proxy::__anonc397dedb0111::StackEntry36   StackEntry(PP_Var v, size_t i) : var(v), data_index(i) {}
37   PP_Var var;
38   size_t data_index;
39 };
40 
41 // For a given PP_Var, returns the RawVarData associated with it, or creates a
42 // new one if there is no existing one. The data is appended to |data| if it
43 // is newly created. The index into |data| pointing to the result is returned.
44 // |visited_map| keeps track of RawVarDatas that have already been created.
GetOrCreateRawVarData(const PP_Var & var,base::hash_map<int64_t,size_t> * visited_map,ScopedVector<RawVarData> * data)45 size_t GetOrCreateRawVarData(const PP_Var& var,
46                              base::hash_map<int64_t, size_t>* visited_map,
47                              ScopedVector<RawVarData>* data) {
48   if (VarTracker::IsVarTypeRefcounted(var.type)) {
49     base::hash_map<int64_t, size_t>::iterator it = visited_map->find(
50         var.value.as_id);
51     if (it != visited_map->end()) {
52       return it->second;
53     } else {
54       data->push_back(RawVarData::Create(var.type));
55       (*visited_map)[var.value.as_id] = data->size() - 1;
56     }
57   } else {
58     data->push_back(RawVarData::Create(var.type));
59   }
60   return data->size() - 1;
61 }
62 
CanHaveChildren(PP_Var var)63 bool CanHaveChildren(PP_Var var) {
64   return var.type == PP_VARTYPE_ARRAY || var.type == PP_VARTYPE_DICTIONARY;
65 }
66 
67 }  // namespace
68 
69 // RawVarDataGraph ------------------------------------------------------------
RawVarDataGraph()70 RawVarDataGraph::RawVarDataGraph() {
71 }
72 
~RawVarDataGraph()73 RawVarDataGraph::~RawVarDataGraph() {
74 }
75 
76 // This function uses a stack-based DFS search to traverse the var graph. Each
77 // iteration, the top node on the stack examined. If the node has not been
78 // visited yet (i.e. !initialized()) then it is added to the list of
79 // |parent_ids| which contains all of the nodes on the path from the start node
80 // to the current node. Each of that nodes children are examined. If they appear
81 // in the list of |parent_ids| it means we have a cycle and we return NULL.
82 // Otherwise, if they haven't been visited yet we add them to the stack, If the
83 // node at the top of the stack has already been visited, then we pop it off the
84 // stack and erase it from |parent_ids|.
85 // static
Create(const PP_Var & var,PP_Instance instance)86 scoped_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var,
87                                                     PP_Instance instance) {
88   scoped_ptr<RawVarDataGraph> graph(new RawVarDataGraph);
89   // Map of |var.value.as_id| to a RawVarData index in RawVarDataGraph.
90   base::hash_map<int64_t, size_t> visited_map;
91   base::hash_set<int64_t> parent_ids;
92 
93   std::stack<StackEntry> stack;
94   stack.push(StackEntry(var, GetOrCreateRawVarData(var, &visited_map,
95                                                    &graph->data_)));
96 
97   while (!stack.empty()) {
98     PP_Var current_var = stack.top().var;
99     RawVarData* current_var_data = graph->data_[stack.top().data_index];
100 
101     if (current_var_data->initialized()) {
102       stack.pop();
103       if (CanHaveChildren(current_var))
104         parent_ids.erase(current_var.value.as_id);
105       continue;
106     }
107 
108     if (CanHaveChildren(current_var))
109       parent_ids.insert(current_var.value.as_id);
110     if (!current_var_data->Init(current_var, instance)) {
111       NOTREACHED();
112       return scoped_ptr<RawVarDataGraph>();
113     }
114 
115     // Add child nodes to the stack.
116     if (current_var.type == PP_VARTYPE_ARRAY) {
117       ArrayVar* array_var = ArrayVar::FromPPVar(current_var);
118       if (!array_var) {
119         NOTREACHED();
120         return scoped_ptr<RawVarDataGraph>();
121       }
122       for (ArrayVar::ElementVector::const_iterator iter =
123                array_var->elements().begin();
124            iter != array_var->elements().end();
125            ++iter) {
126         const PP_Var& child = iter->get();
127         // If a child of this node is already in parent_ids, we have a cycle so
128         // we just return null.
129         if (CanHaveChildren(child) && parent_ids.count(child.value.as_id) != 0)
130           return scoped_ptr<RawVarDataGraph>();
131         size_t child_id = GetOrCreateRawVarData(child, &visited_map,
132                                                 &graph->data_);
133         static_cast<ArrayRawVarData*>(current_var_data)->AddChild(child_id);
134         if (!graph->data_[child_id]->initialized())
135           stack.push(StackEntry(child, child_id));
136       }
137     } else if (current_var.type == PP_VARTYPE_DICTIONARY) {
138       DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var);
139       if (!dict_var) {
140         NOTREACHED();
141         return scoped_ptr<RawVarDataGraph>();
142       }
143       for (DictionaryVar::KeyValueMap::const_iterator iter =
144                dict_var->key_value_map().begin();
145            iter != dict_var->key_value_map().end();
146            ++iter) {
147         const PP_Var& child = iter->second.get();
148         if (CanHaveChildren(child) && parent_ids.count(child.value.as_id) != 0)
149           return scoped_ptr<RawVarDataGraph>();
150         size_t child_id = GetOrCreateRawVarData(child, &visited_map,
151                                                 &graph->data_);
152         static_cast<DictionaryRawVarData*>(
153             current_var_data)->AddChild(iter->first, child_id);
154         if (!graph->data_[child_id]->initialized())
155           stack.push(StackEntry(child, child_id));
156       }
157     }
158   }
159   return graph.Pass();
160 }
161 
CreatePPVar(PP_Instance instance)162 PP_Var RawVarDataGraph::CreatePPVar(PP_Instance instance) {
163   // Create and initialize each node in the graph.
164   std::vector<PP_Var> graph;
165   for (size_t i = 0; i < data_.size(); ++i)
166     graph.push_back(data_[i]->CreatePPVar(instance));
167   for (size_t i = 0; i < data_.size(); ++i)
168     data_[i]->PopulatePPVar(graph[i], graph);
169   // Everything except the root will have one extra ref. Remove that ref.
170   for (size_t i = 1; i < data_.size(); ++i)
171     ScopedPPVar(ScopedPPVar::PassRef(), graph[i]);
172   // The first element is the root.
173   return graph[0];
174 }
175 
Write(IPC::Message * m,const HandleWriter & handle_writer)176 void RawVarDataGraph::Write(IPC::Message* m,
177                             const HandleWriter& handle_writer) {
178   // Write the size, followed by each node in the graph.
179   m->WriteUInt32(static_cast<uint32_t>(data_.size()));
180   for (size_t i = 0; i < data_.size(); ++i) {
181     m->WriteInt(data_[i]->Type());
182     data_[i]->Write(m, handle_writer);
183   }
184 }
185 
186 // static
Read(const IPC::Message * m,PickleIterator * iter)187 scoped_ptr<RawVarDataGraph> RawVarDataGraph::Read(const IPC::Message* m,
188                                                   PickleIterator* iter) {
189   scoped_ptr<RawVarDataGraph> result(new RawVarDataGraph);
190   uint32_t size = 0;
191   if (!m->ReadUInt32(iter, &size))
192     return scoped_ptr<RawVarDataGraph>();
193   for (uint32_t i = 0; i < size; ++i) {
194     int32_t type;
195     if (!m->ReadInt(iter, &type))
196       return scoped_ptr<RawVarDataGraph>();
197     PP_VarType var_type = static_cast<PP_VarType>(type);
198     result->data_.push_back(RawVarData::Create(var_type));
199     if (!result->data_.back()->Read(var_type, m, iter))
200       return scoped_ptr<RawVarDataGraph>();
201   }
202   return result.Pass();
203 }
204 
GetHandles()205 std::vector<SerializedHandle*> RawVarDataGraph::GetHandles() {
206   std::vector<SerializedHandle*> result;
207   for (size_t i = 0; i < data_.size(); ++i) {
208     SerializedHandle* handle = data_[i]->GetHandle();
209     if (handle)
210       result.push_back(handle);
211   }
212   return result;
213 }
214 
215 // static
SetMinimumArrayBufferSizeForShmemForTest(uint32 threshold)216 void RawVarDataGraph::SetMinimumArrayBufferSizeForShmemForTest(
217     uint32 threshold) {
218   if (threshold == 0)
219     g_minimum_array_buffer_size_for_shmem = kMinimumArrayBufferSizeForShmem;
220   else
221     g_minimum_array_buffer_size_for_shmem = threshold;
222 }
223 
224 // RawVarData ------------------------------------------------------------------
225 
226 // static
Create(PP_VarType type)227 RawVarData* RawVarData::Create(PP_VarType type) {
228   switch (type) {
229     case PP_VARTYPE_UNDEFINED:
230     case PP_VARTYPE_NULL:
231     case PP_VARTYPE_BOOL:
232     case PP_VARTYPE_INT32:
233     case PP_VARTYPE_DOUBLE:
234     case PP_VARTYPE_OBJECT:
235       return new BasicRawVarData();
236     case PP_VARTYPE_STRING:
237       return new StringRawVarData();
238     case PP_VARTYPE_ARRAY_BUFFER:
239       return new ArrayBufferRawVarData();
240     case PP_VARTYPE_ARRAY:
241       return new ArrayRawVarData();
242     case PP_VARTYPE_DICTIONARY:
243       return new DictionaryRawVarData();
244     case PP_VARTYPE_RESOURCE:
245       return new ResourceRawVarData();
246   }
247   NOTREACHED();
248   return NULL;
249 }
250 
RawVarData()251 RawVarData::RawVarData() : initialized_(false) {
252 }
253 
~RawVarData()254 RawVarData::~RawVarData() {
255 }
256 
GetHandle()257 SerializedHandle* RawVarData::GetHandle() {
258   return NULL;
259 }
260 
261 // BasicRawVarData -------------------------------------------------------------
BasicRawVarData()262 BasicRawVarData::BasicRawVarData() {
263 }
264 
~BasicRawVarData()265 BasicRawVarData::~BasicRawVarData() {
266 }
267 
Type()268 PP_VarType BasicRawVarData::Type() {
269   return var_.type;
270 }
271 
Init(const PP_Var & var,PP_Instance)272 bool BasicRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
273   var_ = var;
274   initialized_ = true;
275   return true;
276 }
277 
CreatePPVar(PP_Instance instance)278 PP_Var BasicRawVarData::CreatePPVar(PP_Instance instance) {
279   return var_;
280 }
281 
PopulatePPVar(const PP_Var & var,const std::vector<PP_Var> & graph)282 void BasicRawVarData::PopulatePPVar(const PP_Var& var,
283                                     const std::vector<PP_Var>& graph) {
284 }
285 
Write(IPC::Message * m,const HandleWriter & handle_writer)286 void BasicRawVarData::Write(
287     IPC::Message* m,
288     const HandleWriter& handle_writer) {
289   switch (var_.type) {
290     case PP_VARTYPE_UNDEFINED:
291     case PP_VARTYPE_NULL:
292       // These don't need any data associated with them other than the type we
293       // just serialized.
294       break;
295     case PP_VARTYPE_BOOL:
296       m->WriteBool(PP_ToBool(var_.value.as_bool));
297       break;
298     case PP_VARTYPE_INT32:
299       m->WriteInt(var_.value.as_int);
300       break;
301     case PP_VARTYPE_DOUBLE:
302       IPC::ParamTraits<double>::Write(m, var_.value.as_double);
303       break;
304     case PP_VARTYPE_OBJECT:
305       m->WriteInt64(var_.value.as_id);
306       break;
307     default:
308       NOTREACHED();
309       break;
310   }
311 }
312 
Read(PP_VarType type,const IPC::Message * m,PickleIterator * iter)313 bool BasicRawVarData::Read(PP_VarType type,
314                            const IPC::Message* m,
315                            PickleIterator* iter) {
316   PP_Var result;
317   result.type = type;
318   switch (type) {
319     case PP_VARTYPE_UNDEFINED:
320     case PP_VARTYPE_NULL:
321       // These don't have any data associated with them other than the type we
322       // just deserialized.
323       break;
324     case PP_VARTYPE_BOOL: {
325       bool bool_value;
326       if (!m->ReadBool(iter, &bool_value))
327         return false;
328       result.value.as_bool = PP_FromBool(bool_value);
329       break;
330     }
331     case PP_VARTYPE_INT32:
332       if (!m->ReadInt(iter, &result.value.as_int))
333         return false;
334       break;
335     case PP_VARTYPE_DOUBLE:
336       if (!IPC::ParamTraits<double>::Read(m, iter, &result.value.as_double))
337         return false;
338       break;
339     case PP_VARTYPE_OBJECT:
340       if (!m->ReadInt64(iter, &result.value.as_id))
341         return false;
342       break;
343     default:
344       NOTREACHED();
345       return false;
346   }
347   var_ = result;
348   return true;
349 }
350 
351 // StringRawVarData ------------------------------------------------------------
StringRawVarData()352 StringRawVarData::StringRawVarData() {
353 }
354 
~StringRawVarData()355 StringRawVarData::~StringRawVarData() {
356 }
357 
Type()358 PP_VarType StringRawVarData::Type() {
359   return PP_VARTYPE_STRING;
360 }
361 
Init(const PP_Var & var,PP_Instance)362 bool StringRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
363   DCHECK(var.type == PP_VARTYPE_STRING);
364   StringVar* string_var = StringVar::FromPPVar(var);
365   if (!string_var)
366     return false;
367   data_ = string_var->value();
368   initialized_ = true;
369   return true;
370 }
371 
CreatePPVar(PP_Instance instance)372 PP_Var StringRawVarData::CreatePPVar(PP_Instance instance) {
373   return StringVar::SwapValidatedUTF8StringIntoPPVar(&data_);
374 }
375 
PopulatePPVar(const PP_Var & var,const std::vector<PP_Var> & graph)376 void StringRawVarData::PopulatePPVar(const PP_Var& var,
377                                      const std::vector<PP_Var>& graph) {
378 }
379 
Write(IPC::Message * m,const HandleWriter & handle_writer)380 void StringRawVarData::Write(IPC::Message* m,
381                              const HandleWriter& handle_writer) {
382   m->WriteString(data_);
383 }
384 
Read(PP_VarType type,const IPC::Message * m,PickleIterator * iter)385 bool StringRawVarData::Read(PP_VarType type,
386                             const IPC::Message* m,
387                             PickleIterator* iter) {
388   if (!m->ReadString(iter, &data_))
389     return false;
390   return true;
391 }
392 
393 // ArrayBufferRawVarData -------------------------------------------------------
ArrayBufferRawVarData()394 ArrayBufferRawVarData::ArrayBufferRawVarData() {
395 }
396 
~ArrayBufferRawVarData()397 ArrayBufferRawVarData::~ArrayBufferRawVarData() {
398 }
399 
Type()400 PP_VarType ArrayBufferRawVarData::Type() {
401   return PP_VARTYPE_ARRAY_BUFFER;
402 }
403 
Init(const PP_Var & var,PP_Instance instance)404 bool ArrayBufferRawVarData::Init(const PP_Var& var,
405                                  PP_Instance instance) {
406   DCHECK(var.type == PP_VARTYPE_ARRAY_BUFFER);
407   ArrayBufferVar* buffer_var = ArrayBufferVar::FromPPVar(var);
408   if (!buffer_var)
409     return false;
410   bool using_shmem = false;
411   if (buffer_var->ByteLength() >= g_minimum_array_buffer_size_for_shmem &&
412       instance != 0) {
413     int host_handle_id;
414     base::SharedMemoryHandle plugin_handle;
415     using_shmem = buffer_var->CopyToNewShmem(instance,
416                                              &host_handle_id,
417                                              &plugin_handle);
418     if (using_shmem) {
419       if (host_handle_id != -1) {
420         DCHECK(!base::SharedMemory::IsHandleValid(plugin_handle));
421         DCHECK(PpapiGlobals::Get()->IsPluginGlobals());
422         type_ = ARRAY_BUFFER_SHMEM_HOST;
423         host_shm_handle_id_ = host_handle_id;
424       } else {
425         DCHECK(base::SharedMemory::IsHandleValid(plugin_handle));
426         DCHECK(PpapiGlobals::Get()->IsHostGlobals());
427         type_ = ARRAY_BUFFER_SHMEM_PLUGIN;
428         plugin_shm_handle_ = SerializedHandle(plugin_handle,
429                                               buffer_var->ByteLength());
430       }
431     }
432   }
433   if (!using_shmem) {
434     type_ = ARRAY_BUFFER_NO_SHMEM;
435     data_ = std::string(static_cast<const char*>(buffer_var->Map()),
436                         buffer_var->ByteLength());
437   }
438   initialized_ = true;
439   return true;
440 }
441 
CreatePPVar(PP_Instance instance)442 PP_Var ArrayBufferRawVarData::CreatePPVar(PP_Instance instance) {
443   PP_Var result = PP_MakeUndefined();
444   switch (type_) {
445     case ARRAY_BUFFER_SHMEM_HOST: {
446       base::SharedMemoryHandle host_handle;
447       uint32 size_in_bytes;
448       bool ok = PpapiGlobals::Get()->GetVarTracker()->
449           StopTrackingSharedMemoryHandle(host_shm_handle_id_,
450                                          instance,
451                                          &host_handle,
452                                          &size_in_bytes);
453       if (ok) {
454         result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
455             size_in_bytes, host_handle);
456       } else {
457         LOG(ERROR) << "Couldn't find array buffer id: " << host_shm_handle_id_;
458         return PP_MakeUndefined();
459       }
460       break;
461     }
462     case ARRAY_BUFFER_SHMEM_PLUGIN: {
463       result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
464           plugin_shm_handle_.size(),
465           plugin_shm_handle_.shmem());
466       break;
467     }
468     case ARRAY_BUFFER_NO_SHMEM: {
469       result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
470           static_cast<uint32>(data_.size()), data_.data());
471       break;
472     }
473     default:
474       NOTREACHED();
475       return PP_MakeUndefined();
476   }
477   DCHECK(result.type == PP_VARTYPE_ARRAY_BUFFER);
478   return result;
479 }
480 
PopulatePPVar(const PP_Var & var,const std::vector<PP_Var> & graph)481 void ArrayBufferRawVarData::PopulatePPVar(const PP_Var& var,
482                                           const std::vector<PP_Var>& graph) {
483 }
484 
Write(IPC::Message * m,const HandleWriter & handle_writer)485 void ArrayBufferRawVarData::Write(
486     IPC::Message* m,
487     const HandleWriter& handle_writer) {
488   m->WriteInt(type_);
489   switch (type_) {
490     case ARRAY_BUFFER_SHMEM_HOST:
491       m->WriteInt(host_shm_handle_id_);
492       break;
493     case ARRAY_BUFFER_SHMEM_PLUGIN:
494       handle_writer.Run(m, plugin_shm_handle_);
495       break;
496     case ARRAY_BUFFER_NO_SHMEM:
497       m->WriteString(data_);
498       break;
499   }
500 }
501 
Read(PP_VarType type,const IPC::Message * m,PickleIterator * iter)502 bool ArrayBufferRawVarData::Read(PP_VarType type,
503                                  const IPC::Message* m,
504                                  PickleIterator* iter) {
505   int shmem_type;
506   if (!m->ReadInt(iter, &shmem_type))
507     return false;
508   type_ = static_cast<ShmemType>(shmem_type);
509   switch (type_) {
510     case ARRAY_BUFFER_SHMEM_HOST:
511       if (!m->ReadInt(iter, &host_shm_handle_id_))
512         return false;
513       break;
514     case ARRAY_BUFFER_SHMEM_PLUGIN:
515       if (!IPC::ParamTraits<SerializedHandle>::Read(
516               m, iter, &plugin_shm_handle_)) {
517         return false;
518       }
519       break;
520     case ARRAY_BUFFER_NO_SHMEM:
521       if (!m->ReadString(iter, &data_))
522         return false;
523       break;
524     default:
525       // We read an invalid ID.
526       NOTREACHED();
527       return false;
528   }
529   return true;
530 }
531 
GetHandle()532 SerializedHandle* ArrayBufferRawVarData::GetHandle() {
533   if (type_ == ARRAY_BUFFER_SHMEM_PLUGIN && plugin_shm_handle_.size() != 0)
534     return &plugin_shm_handle_;
535   return NULL;
536 }
537 
538 // ArrayRawVarData -------------------------------------------------------------
ArrayRawVarData()539 ArrayRawVarData::ArrayRawVarData() {
540 }
541 
~ArrayRawVarData()542 ArrayRawVarData::~ArrayRawVarData() {
543 }
544 
AddChild(size_t element)545 void ArrayRawVarData::AddChild(size_t element) {
546   children_.push_back(element);
547 }
548 
Type()549 PP_VarType ArrayRawVarData::Type() {
550   return PP_VARTYPE_ARRAY;
551 }
552 
Init(const PP_Var & var,PP_Instance)553 bool ArrayRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
554   initialized_ = true;
555   DCHECK(var.type == PP_VARTYPE_ARRAY);
556   initialized_ = true;
557   return true;
558 }
559 
CreatePPVar(PP_Instance instance)560 PP_Var ArrayRawVarData::CreatePPVar(PP_Instance instance) {
561   return (new ArrayVar())->GetPPVar();
562 }
563 
PopulatePPVar(const PP_Var & var,const std::vector<PP_Var> & graph)564 void ArrayRawVarData::PopulatePPVar(const PP_Var& var,
565                                     const std::vector<PP_Var>& graph) {
566   if (var.type != PP_VARTYPE_ARRAY) {
567     NOTREACHED();
568     return;
569   }
570   ArrayVar* array_var = ArrayVar::FromPPVar(var);
571   DCHECK(array_var->elements().empty());
572   for (size_t i = 0; i < children_.size(); ++i)
573     array_var->elements().push_back(ScopedPPVar(graph[children_[i]]));
574 }
575 
Write(IPC::Message * m,const HandleWriter & handle_writer)576 void ArrayRawVarData::Write(IPC::Message* m,
577                             const HandleWriter& handle_writer) {
578   m->WriteUInt32(static_cast<uint32_t>(children_.size()));
579   for (size_t i = 0; i < children_.size(); ++i)
580     m->WriteUInt32(static_cast<uint32_t>(children_[i]));
581 }
582 
Read(PP_VarType type,const IPC::Message * m,PickleIterator * iter)583 bool ArrayRawVarData::Read(PP_VarType type,
584                            const IPC::Message* m,
585                            PickleIterator* iter) {
586   uint32_t size;
587   if (!m->ReadUInt32(iter, &size))
588     return false;
589   for (uint32_t i = 0; i < size; ++i) {
590     uint32_t index;
591     if (!m->ReadUInt32(iter, &index))
592       return false;
593     children_.push_back(index);
594   }
595   return true;
596 }
597 
598 // DictionaryRawVarData --------------------------------------------------------
DictionaryRawVarData()599 DictionaryRawVarData::DictionaryRawVarData() {
600 }
601 
~DictionaryRawVarData()602 DictionaryRawVarData::~DictionaryRawVarData() {
603 }
604 
AddChild(const std::string & key,size_t value)605 void DictionaryRawVarData::AddChild(const std::string& key,
606                                     size_t value) {
607   children_.push_back(make_pair(key, value));
608 }
609 
Type()610 PP_VarType DictionaryRawVarData::Type() {
611   return PP_VARTYPE_DICTIONARY;
612 }
613 
Init(const PP_Var & var,PP_Instance)614 bool DictionaryRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
615   DCHECK(var.type == PP_VARTYPE_DICTIONARY);
616   initialized_ = true;
617   return true;
618 }
619 
CreatePPVar(PP_Instance instance)620 PP_Var DictionaryRawVarData::CreatePPVar(PP_Instance instance) {
621   return (new DictionaryVar())->GetPPVar();
622 }
623 
PopulatePPVar(const PP_Var & var,const std::vector<PP_Var> & graph)624 void DictionaryRawVarData::PopulatePPVar(const PP_Var& var,
625                                          const std::vector<PP_Var>& graph) {
626   if (var.type != PP_VARTYPE_DICTIONARY) {
627     NOTREACHED();
628     return;
629   }
630   DictionaryVar* dictionary_var = DictionaryVar::FromPPVar(var);
631   DCHECK(dictionary_var->key_value_map().empty());
632   for (size_t i = 0; i < children_.size(); ++i) {
633     bool success = dictionary_var->SetWithStringKey(children_[i].first,
634                                                     graph[children_[i].second]);
635     DCHECK(success);
636   }
637 }
638 
Write(IPC::Message * m,const HandleWriter & handle_writer)639 void DictionaryRawVarData::Write(
640     IPC::Message* m,
641     const HandleWriter& handle_writer) {
642   m->WriteUInt32(static_cast<uint32_t>(children_.size()));
643   for (size_t i = 0; i < children_.size(); ++i) {
644     m->WriteString(children_[i].first);
645     m->WriteUInt32(static_cast<uint32_t>(children_[i].second));
646   }
647 }
648 
Read(PP_VarType type,const IPC::Message * m,PickleIterator * iter)649 bool DictionaryRawVarData::Read(PP_VarType type,
650                                 const IPC::Message* m,
651                                 PickleIterator* iter) {
652   uint32_t size;
653   if (!m->ReadUInt32(iter, &size))
654     return false;
655   for (uint32_t i = 0; i < size; ++i) {
656     std::string key;
657     uint32_t value;
658     if (!m->ReadString(iter, &key))
659       return false;
660     if (!m->ReadUInt32(iter, &value))
661       return false;
662     children_.push_back(make_pair(key, value));
663   }
664   return true;
665 }
666 
667 // ResourceRawVarData ----------------------------------------------------------
ResourceRawVarData()668 ResourceRawVarData::ResourceRawVarData()
669     : pp_resource_(0),
670       pending_renderer_host_id_(0),
671       pending_browser_host_id_(0) {}
672 
~ResourceRawVarData()673 ResourceRawVarData::~ResourceRawVarData() {
674 }
675 
Type()676 PP_VarType ResourceRawVarData::Type() {
677   return PP_VARTYPE_RESOURCE;
678 }
679 
Init(const PP_Var & var,PP_Instance)680 bool ResourceRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
681   DCHECK(var.type == PP_VARTYPE_RESOURCE);
682   ResourceVar* resource_var = ResourceVar::FromPPVar(var);
683   if (!resource_var)
684     return false;
685   pp_resource_ = resource_var->GetPPResource();
686   const IPC::Message* message = resource_var->GetCreationMessage();
687   if (message)
688     creation_message_.reset(new IPC::Message(*message));
689   else
690     creation_message_.reset();
691   pending_renderer_host_id_ = resource_var->GetPendingRendererHostId();
692   pending_browser_host_id_ = resource_var->GetPendingBrowserHostId();
693   initialized_ = true;
694   return true;
695 }
696 
CreatePPVar(PP_Instance instance)697 PP_Var ResourceRawVarData::CreatePPVar(PP_Instance instance) {
698   // If this is not a pending resource host, just create the var.
699   if (pp_resource_ || !creation_message_) {
700     return PpapiGlobals::Get()->GetVarTracker()->MakeResourcePPVar(
701         pp_resource_);
702   }
703 
704   // This is a pending resource host, so create the resource and var.
705   return PpapiGlobals::Get()->GetVarTracker()->MakeResourcePPVarFromMessage(
706       instance,
707       *creation_message_,
708       pending_renderer_host_id_,
709       pending_browser_host_id_);
710 }
711 
PopulatePPVar(const PP_Var & var,const std::vector<PP_Var> & graph)712 void ResourceRawVarData::PopulatePPVar(const PP_Var& var,
713                                        const std::vector<PP_Var>& graph) {
714 }
715 
Write(IPC::Message * m,const HandleWriter & handle_writer)716 void ResourceRawVarData::Write(IPC::Message* m,
717                                const HandleWriter& handle_writer) {
718   m->WriteInt(static_cast<int>(pp_resource_));
719   m->WriteInt(pending_renderer_host_id_);
720   m->WriteInt(pending_browser_host_id_);
721   m->WriteBool(creation_message_);
722   if (creation_message_)
723     IPC::ParamTraits<IPC::Message>::Write(m, *creation_message_);
724 }
725 
Read(PP_VarType type,const IPC::Message * m,PickleIterator * iter)726 bool ResourceRawVarData::Read(PP_VarType type,
727                               const IPC::Message* m,
728                               PickleIterator* iter) {
729   int value;
730   if (!m->ReadInt(iter, &value))
731     return false;
732   pp_resource_ = static_cast<PP_Resource>(value);
733   if (!m->ReadInt(iter, &pending_renderer_host_id_))
734     return false;
735   if (!m->ReadInt(iter, &pending_browser_host_id_))
736     return false;
737   bool has_creation_message;
738   if (!m->ReadBool(iter, &has_creation_message))
739     return false;
740   if (has_creation_message) {
741     creation_message_.reset(new IPC::Message());
742     if (!IPC::ParamTraits<IPC::Message>::Read(m, iter, creation_message_.get()))
743       return false;
744   } else {
745     creation_message_.reset();
746   }
747   return true;
748 }
749 
750 }  // namespace proxy
751 }  // namespace ppapi
752