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 { 36 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. 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 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 ------------------------------------------------------------ 70 RawVarDataGraph::RawVarDataGraph() { 71 } 72 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 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 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 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 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 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 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 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 251 RawVarData::RawVarData() : initialized_(false) { 252 } 253 254 RawVarData::~RawVarData() { 255 } 256 257 SerializedHandle* RawVarData::GetHandle() { 258 return NULL; 259 } 260 261 // BasicRawVarData ------------------------------------------------------------- 262 BasicRawVarData::BasicRawVarData() { 263 } 264 265 BasicRawVarData::~BasicRawVarData() { 266 } 267 268 PP_VarType BasicRawVarData::Type() { 269 return var_.type; 270 } 271 272 bool BasicRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) { 273 var_ = var; 274 initialized_ = true; 275 return true; 276 } 277 278 PP_Var BasicRawVarData::CreatePPVar(PP_Instance instance) { 279 return var_; 280 } 281 282 void BasicRawVarData::PopulatePPVar(const PP_Var& var, 283 const std::vector<PP_Var>& graph) { 284 } 285 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 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 serialized. 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 ------------------------------------------------------------ 352 StringRawVarData::StringRawVarData() { 353 } 354 355 StringRawVarData::~StringRawVarData() { 356 } 357 358 PP_VarType StringRawVarData::Type() { 359 return PP_VARTYPE_STRING; 360 } 361 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 372 PP_Var StringRawVarData::CreatePPVar(PP_Instance instance) { 373 return StringVar::SwapValidatedUTF8StringIntoPPVar(&data_); 374 } 375 376 void StringRawVarData::PopulatePPVar(const PP_Var& var, 377 const std::vector<PP_Var>& graph) { 378 } 379 380 void StringRawVarData::Write(IPC::Message* m, 381 const HandleWriter& handle_writer) { 382 m->WriteString(data_); 383 } 384 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 ------------------------------------------------------- 394 ArrayBufferRawVarData::ArrayBufferRawVarData() { 395 } 396 397 ArrayBufferRawVarData::~ArrayBufferRawVarData() { 398 } 399 400 PP_VarType ArrayBufferRawVarData::Type() { 401 return PP_VARTYPE_ARRAY_BUFFER; 402 } 403 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 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 481 void ArrayBufferRawVarData::PopulatePPVar(const PP_Var& var, 482 const std::vector<PP_Var>& graph) { 483 } 484 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 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 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 ------------------------------------------------------------- 539 ArrayRawVarData::ArrayRawVarData() { 540 } 541 542 ArrayRawVarData::~ArrayRawVarData() { 543 } 544 545 void ArrayRawVarData::AddChild(size_t element) { 546 children_.push_back(element); 547 } 548 549 PP_VarType ArrayRawVarData::Type() { 550 return PP_VARTYPE_ARRAY; 551 } 552 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 560 PP_Var ArrayRawVarData::CreatePPVar(PP_Instance instance) { 561 return (new ArrayVar())->GetPPVar(); 562 } 563 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 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 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 -------------------------------------------------------- 599 DictionaryRawVarData::DictionaryRawVarData() { 600 } 601 602 DictionaryRawVarData::~DictionaryRawVarData() { 603 } 604 605 void DictionaryRawVarData::AddChild(const std::string& key, 606 size_t value) { 607 children_.push_back(make_pair(key, value)); 608 } 609 610 PP_VarType DictionaryRawVarData::Type() { 611 return PP_VARTYPE_DICTIONARY; 612 } 613 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 620 PP_Var DictionaryRawVarData::CreatePPVar(PP_Instance instance) { 621 return (new DictionaryVar())->GetPPVar(); 622 } 623 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 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 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 ---------------------------------------------------------- 668 ResourceRawVarData::ResourceRawVarData() 669 : pp_resource_(0), 670 pending_renderer_host_id_(0), 671 pending_browser_host_id_(0) {} 672 673 ResourceRawVarData::~ResourceRawVarData() { 674 } 675 676 PP_VarType ResourceRawVarData::Type() { 677 return PP_VARTYPE_RESOURCE; 678 } 679 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 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 712 void ResourceRawVarData::PopulatePPVar(const PP_Var& var, 713 const std::vector<PP_Var>& graph) { 714 } 715 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 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