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. |
| 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::SwapValidatedUTF8StringIntoPPVar(&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 DCHECK(dictionary_var->SetWithStringKey(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 |
OLD | NEW |