Pepper: Fix crash on allocation failure.
[chromium-blink-merge.git] / ppapi / proxy / raw_var_data.cc
blob97a6d944ae583e969ba74e1ceea2f152db5ebdc9
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.
5 #include "ppapi/proxy/raw_var_data.h"
7 #include <stack>
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"
21 using std::make_pair;
23 namespace ppapi {
24 namespace proxy {
26 namespace {
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;
35 struct StackEntry {
36 StackEntry(PP_Var v, size_t i) : var(v), data_index(i) {}
37 PP_Var var;
38 size_t data_index;
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.
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;
57 } else {
58 data->push_back(RawVarData::Create(var.type));
60 return data->size() - 1;
63 bool CanHaveChildren(PP_Var var) {
64 return var.type == PP_VARTYPE_ARRAY || var.type == PP_VARTYPE_DICTIONARY;
67 } // namespace
69 // RawVarDataGraph ------------------------------------------------------------
70 RawVarDataGraph::RawVarDataGraph() {
73 RawVarDataGraph::~RawVarDataGraph() {
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
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;
93 std::stack<StackEntry> stack;
94 stack.push(StackEntry(var, GetOrCreateRawVarData(var, &visited_map,
95 &graph->data_)));
97 while (!stack.empty()) {
98 PP_Var current_var = stack.top().var;
99 RawVarData* current_var_data = graph->data_[stack.top().data_index];
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;
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>();
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>();
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));
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>();
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));
159 return graph.Pass();
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];
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);
186 // static
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>();
202 return result.Pass();
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);
212 return result;
215 // static
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;
224 // RawVarData ------------------------------------------------------------------
226 // static
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();
247 NOTREACHED();
248 return NULL;
251 RawVarData::RawVarData() : initialized_(false) {
254 RawVarData::~RawVarData() {
257 SerializedHandle* RawVarData::GetHandle() {
258 return NULL;
261 // BasicRawVarData -------------------------------------------------------------
262 BasicRawVarData::BasicRawVarData() {
265 BasicRawVarData::~BasicRawVarData() {
268 PP_VarType BasicRawVarData::Type() {
269 return var_.type;
272 bool BasicRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
273 var_ = var;
274 initialized_ = true;
275 return true;
278 PP_Var BasicRawVarData::CreatePPVar(PP_Instance instance) {
279 return var_;
282 void BasicRawVarData::PopulatePPVar(const PP_Var& var,
283 const std::vector<PP_Var>& graph) {
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;
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;
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;
347 var_ = result;
348 return true;
351 // StringRawVarData ------------------------------------------------------------
352 StringRawVarData::StringRawVarData() {
355 StringRawVarData::~StringRawVarData() {
358 PP_VarType StringRawVarData::Type() {
359 return PP_VARTYPE_STRING;
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;
372 PP_Var StringRawVarData::CreatePPVar(PP_Instance instance) {
373 return StringVar::SwapValidatedUTF8StringIntoPPVar(&data_);
376 void StringRawVarData::PopulatePPVar(const PP_Var& var,
377 const std::vector<PP_Var>& graph) {
380 void StringRawVarData::Write(IPC::Message* m,
381 const HandleWriter& handle_writer) {
382 m->WriteString(data_);
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;
393 // ArrayBufferRawVarData -------------------------------------------------------
394 ArrayBufferRawVarData::ArrayBufferRawVarData() {
397 ArrayBufferRawVarData::~ArrayBufferRawVarData() {
400 PP_VarType ArrayBufferRawVarData::Type() {
401 return PP_VARTYPE_ARRAY_BUFFER;
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());
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());
438 initialized_ = true;
439 return true;
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();
460 break;
462 case ARRAY_BUFFER_SHMEM_PLUGIN: {
463 result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
464 plugin_shm_handle_.size(),
465 plugin_shm_handle_.shmem());
466 break;
468 case ARRAY_BUFFER_NO_SHMEM: {
469 result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
470 static_cast<uint32>(data_.size()), data_.data());
471 break;
473 default:
474 NOTREACHED();
475 return PP_MakeUndefined();
477 DCHECK(result.type == PP_VARTYPE_ARRAY_BUFFER);
478 return result;
481 void ArrayBufferRawVarData::PopulatePPVar(const PP_Var& var,
482 const std::vector<PP_Var>& graph) {
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;
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;
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;
529 return true;
532 SerializedHandle* ArrayBufferRawVarData::GetHandle() {
533 if (type_ == ARRAY_BUFFER_SHMEM_PLUGIN && plugin_shm_handle_.size() != 0)
534 return &plugin_shm_handle_;
535 return NULL;
538 // ArrayRawVarData -------------------------------------------------------------
539 ArrayRawVarData::ArrayRawVarData() {
542 ArrayRawVarData::~ArrayRawVarData() {
545 void ArrayRawVarData::AddChild(size_t element) {
546 children_.push_back(element);
549 PP_VarType ArrayRawVarData::Type() {
550 return PP_VARTYPE_ARRAY;
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;
560 PP_Var ArrayRawVarData::CreatePPVar(PP_Instance instance) {
561 return (new ArrayVar())->GetPPVar();
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;
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]]));
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]));
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);
595 return true;
598 // DictionaryRawVarData --------------------------------------------------------
599 DictionaryRawVarData::DictionaryRawVarData() {
602 DictionaryRawVarData::~DictionaryRawVarData() {
605 void DictionaryRawVarData::AddChild(const std::string& key,
606 size_t value) {
607 children_.push_back(make_pair(key, value));
610 PP_VarType DictionaryRawVarData::Type() {
611 return PP_VARTYPE_DICTIONARY;
614 bool DictionaryRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
615 DCHECK(var.type == PP_VARTYPE_DICTIONARY);
616 initialized_ = true;
617 return true;
620 PP_Var DictionaryRawVarData::CreatePPVar(PP_Instance instance) {
621 return (new DictionaryVar())->GetPPVar();
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;
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);
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));
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));
664 return true;
667 // ResourceRawVarData ----------------------------------------------------------
668 ResourceRawVarData::ResourceRawVarData()
669 : pp_resource_(0),
670 pending_renderer_host_id_(0),
671 pending_browser_host_id_(0) {}
673 ResourceRawVarData::~ResourceRawVarData() {
676 PP_VarType ResourceRawVarData::Type() {
677 return PP_VARTYPE_RESOURCE;
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;
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_);
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_);
712 void ResourceRawVarData::PopulatePPVar(const PP_Var& var,
713 const std::vector<PP_Var>& graph) {
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_);
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();
747 return true;
750 } // namespace proxy
751 } // namespace ppapi