| Index: ppapi/proxy/raw_var_data.cc
|
| diff --git a/ppapi/proxy/raw_var_data.cc b/ppapi/proxy/raw_var_data.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..087f4cd975843936e0b0684b66a878cc21752d81
|
| --- /dev/null
|
| +++ b/ppapi/proxy/raw_var_data.cc
|
| @@ -0,0 +1,609 @@
|
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "ppapi/proxy/raw_var_data.h"
|
| +
|
| +#include <stack>
|
| +
|
| +#include "base/hash_tables.h"
|
| +#include "base/stl_util.h"
|
| +#include "ipc/ipc_message.h"
|
| +#include "ppapi/proxy/ppapi_param_traits.h"
|
| +#include "ppapi/shared_impl/array_var.h"
|
| +#include "ppapi/shared_impl/dictionary_var.h"
|
| +#include "ppapi/shared_impl/ppapi_globals.h"
|
| +#include "ppapi/shared_impl/scoped_pp_var.h"
|
| +#include "ppapi/shared_impl/var.h"
|
| +#include "ppapi/shared_impl/var_tracker.h"
|
| +
|
| +using std::make_pair;
|
| +
|
| +namespace ppapi {
|
| +namespace proxy {
|
| +
|
| +namespace {
|
| +
|
| +// When sending array buffers, if the size is over 256K, we use shared
|
| +// memory instead of sending the data over IPC. Light testing suggests
|
| +// shared memory is much faster for 256K and larger messages.
|
| +static const uint32 kMinimumArrayBufferSizeForShmem = 256 * 1024;
|
| +
|
| +void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) {
|
| + IPC::ParamTraits<SerializedHandle>::Write(m, handle);
|
| +}
|
| +
|
| +// For a given PP_Var, returns the RawVarData associated with it, or creates a
|
| +// new one if there is no existing one. The data is appended to |data| if it
|
| +// is newly created. The index into |data| pointing to the result is returned.
|
| +// |id_map| keeps track of RawVarDatas that have already been created.
|
| +size_t GetOrCreateRawVarData(const PP_Var& var,
|
| + base::hash_map<int64_t, size_t>* id_map,
|
| + ScopedVector<RawVarData>* data) {
|
| + if (VarTracker::IsVarTypeRefcounted(var.type)) {
|
| + base::hash_map<int64_t, size_t>::iterator it = id_map->find(
|
| + var.value.as_id);
|
| + if (it != id_map->end()) {
|
| + return it->second;
|
| + } else {
|
| + data->push_back(RawVarData::Create(var.type));
|
| + (*id_map)[var.value.as_id] = data->size() - 1;
|
| + }
|
| + } else {
|
| + data->push_back(RawVarData::Create(var.type));
|
| + }
|
| + return data->size() - 1;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// RawVarDataGraph ------------------------------------------------------------
|
| +RawVarDataGraph::RawVarDataGraph() {
|
| +}
|
| +
|
| +RawVarDataGraph::~RawVarDataGraph() {
|
| +}
|
| +
|
| +// static
|
| +scoped_ptr<RawVarDataGraph> RawVarDataGraph::Create(const PP_Var& var,
|
| + PP_Instance instance) {
|
| + scoped_ptr<RawVarDataGraph> graph(new RawVarDataGraph);
|
| + // Map of |var.value.as_id| to a RawVarData index in RawVarDataGraph.
|
| + base::hash_map<int64_t, size_t> id_map;
|
| +
|
| + std::stack<std::pair<PP_Var, size_t> > stack;
|
| + stack.push(make_pair(var, GetOrCreateRawVarData(var, &id_map,
|
| + &graph->data_)));
|
| +
|
| + // Traverse the PP_Var graph with DFS.
|
| + while (!stack.empty()) {
|
| + PP_Var current_var = stack.top().first;
|
| + RawVarData* current_var_data = graph->data_[stack.top().second];
|
| + stack.pop();
|
| +
|
| + // If the node is initialized, it means we have visited it.
|
| + if (current_var_data->initialized())
|
| + continue;
|
| +
|
| + if (!current_var_data->Init(current_var, instance)) {
|
| + NOTREACHED();
|
| + return scoped_ptr<RawVarDataGraph>();
|
| + }
|
| +
|
| + // Add child nodes to the stack.
|
| + if (current_var.type == PP_VARTYPE_ARRAY) {
|
| + ArrayVar* array_var = ArrayVar::FromPPVar(current_var);
|
| + if (!array_var) {
|
| + NOTREACHED();
|
| + return scoped_ptr<RawVarDataGraph>();
|
| + }
|
| + for (ArrayVar::ElementVector::const_iterator iter =
|
| + array_var->elements().begin();
|
| + iter != array_var->elements().end();
|
| + ++iter) {
|
| + size_t child_id = GetOrCreateRawVarData(iter->get(), &id_map,
|
| + &graph->data_);
|
| + static_cast<ArrayRawVarData*>(current_var_data)->AddChild(child_id);
|
| + stack.push(make_pair(iter->get(), child_id));
|
| + }
|
| + } else if (current_var.type == PP_VARTYPE_DICTIONARY) {
|
| + DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var);
|
| + if (!dict_var) {
|
| + NOTREACHED();
|
| + return scoped_ptr<RawVarDataGraph>();
|
| + }
|
| + for (DictionaryVar::KeyValueMap::const_iterator iter =
|
| + dict_var->key_value_map().begin();
|
| + iter != dict_var->key_value_map().end();
|
| + ++iter) {
|
| + size_t child_id = GetOrCreateRawVarData(iter->second.get(), &id_map,
|
| + &graph->data_);
|
| + static_cast<DictionaryRawVarData*>(
|
| + current_var_data)->AddChild(iter->first, child_id);
|
| + stack.push(make_pair(iter->second.get(), child_id));
|
| + }
|
| + }
|
| + }
|
| + return graph.Pass();
|
| +}
|
| +
|
| +PP_Var RawVarDataGraph::CreatePPVar(PP_Instance instance) {
|
| + // Create and initialize each node in the graph.
|
| + std::vector<PP_Var> graph;
|
| + for (size_t i = 0; i < data_.size(); ++i)
|
| + graph.push_back(data_[i]->CreatePPVar(instance));
|
| + for (size_t i = 0; i < data_.size(); ++i)
|
| + data_[i]->PopulatePPVar(graph[i], graph);
|
| + // Everything except the root will have one extra ref. Remove that ref.
|
| + for (size_t i = 1; i < data_.size(); ++i)
|
| + ScopedPPVar(ScopedPPVar::PassRef(), graph[i]);
|
| + // The first element is the root.
|
| + return graph[0];
|
| +}
|
| +
|
| +void RawVarDataGraph::Write(IPC::Message* m,
|
| + const HandleWriter& handle_writer) {
|
| + // Write the size, followed by each node in the graph.
|
| + m->WriteUInt32(static_cast<uint32_t>(data_.size()));
|
| + for (size_t i = 0; i < data_.size(); ++i) {
|
| + m->WriteInt(data_[i]->Type());
|
| + data_[i]->Write(m, handle_writer);
|
| + }
|
| +}
|
| +
|
| +void RawVarDataGraph::Write(IPC::Message* m) {
|
| + Write(m, base::Bind(&DefaultHandleWriter));
|
| +}
|
| +
|
| +// static
|
| +scoped_ptr<RawVarDataGraph> RawVarDataGraph::Read(const IPC::Message* m,
|
| + PickleIterator* iter) {
|
| + scoped_ptr<RawVarDataGraph> result(new RawVarDataGraph);
|
| + uint32_t size = 0;
|
| + if (!m->ReadUInt32(iter, &size))
|
| + return scoped_ptr<RawVarDataGraph>();
|
| + for (uint32_t i = 0; i < size; ++i) {
|
| + int32_t type;
|
| + if (!m->ReadInt(iter, &type))
|
| + return scoped_ptr<RawVarDataGraph>();
|
| + PP_VarType var_type = static_cast<PP_VarType>(type);
|
| + result->data_.push_back(RawVarData::Create(var_type));
|
| + if (!result->data_.back()->Read(var_type, m, iter))
|
| + return scoped_ptr<RawVarDataGraph>();
|
| + }
|
| + return result.Pass();
|
| +}
|
| +
|
| +// RawVarData ------------------------------------------------------------------
|
| +
|
| +// static
|
| +RawVarData* RawVarData::Create(PP_VarType type) {
|
| + switch (type) {
|
| + case PP_VARTYPE_UNDEFINED:
|
| + case PP_VARTYPE_NULL:
|
| + case PP_VARTYPE_BOOL:
|
| + case PP_VARTYPE_INT32:
|
| + case PP_VARTYPE_DOUBLE:
|
| + case PP_VARTYPE_OBJECT:
|
| + return new BasicRawVarData();
|
| + case PP_VARTYPE_STRING:
|
| + return new StringRawVarData();
|
| + case PP_VARTYPE_ARRAY_BUFFER:
|
| + return new ArrayBufferRawVarData();
|
| + case PP_VARTYPE_ARRAY:
|
| + return new ArrayRawVarData();
|
| + case PP_VARTYPE_DICTIONARY:
|
| + return new DictionaryRawVarData();
|
| + }
|
| + NOTREACHED();
|
| + return NULL;
|
| +}
|
| +
|
| +RawVarData::RawVarData() : initialized_(false) {
|
| +}
|
| +
|
| +RawVarData::~RawVarData() {
|
| +}
|
| +
|
| +// BasicRawVarData -------------------------------------------------------------
|
| +BasicRawVarData::BasicRawVarData() {
|
| +}
|
| +
|
| +BasicRawVarData::~BasicRawVarData() {
|
| +}
|
| +
|
| +PP_VarType BasicRawVarData::Type() {
|
| + return var_.type;
|
| +}
|
| +
|
| +bool BasicRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
|
| + var_ = var;
|
| + initialized_ = true;
|
| + return true;
|
| +}
|
| +
|
| +PP_Var BasicRawVarData::CreatePPVar(PP_Instance instance) {
|
| + return var_;
|
| +}
|
| +
|
| +void BasicRawVarData::PopulatePPVar(const PP_Var& var,
|
| + const std::vector<PP_Var>& graph) {
|
| +}
|
| +
|
| +void BasicRawVarData::Write(
|
| + IPC::Message* m,
|
| + const HandleWriter& handle_writer) {
|
| + switch (var_.type) {
|
| + case PP_VARTYPE_UNDEFINED:
|
| + case PP_VARTYPE_NULL:
|
| + // These don't need any data associated with them other than the type we
|
| + // just serialized.
|
| + break;
|
| + case PP_VARTYPE_BOOL:
|
| + m->WriteBool(PP_ToBool(var_.value.as_bool));
|
| + break;
|
| + case PP_VARTYPE_INT32:
|
| + m->WriteInt(var_.value.as_int);
|
| + break;
|
| + case PP_VARTYPE_DOUBLE:
|
| + IPC::ParamTraits<double>::Write(m, var_.value.as_double);
|
| + break;
|
| + case PP_VARTYPE_OBJECT:
|
| + m->WriteInt64(var_.value.as_id);
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| +}
|
| +
|
| +bool BasicRawVarData::Read(PP_VarType type,
|
| + const IPC::Message* m,
|
| + PickleIterator* iter) {
|
| + PP_Var result;
|
| + result.type = type;
|
| + switch (type) {
|
| + case PP_VARTYPE_UNDEFINED:
|
| + case PP_VARTYPE_NULL:
|
| + // These don't have any data associated with them other than the type we
|
| + // just serialized.
|
| + break;
|
| + case PP_VARTYPE_BOOL: {
|
| + bool bool_value;
|
| + if (!m->ReadBool(iter, &bool_value))
|
| + return false;
|
| + result.value.as_bool = PP_FromBool(bool_value);
|
| + break;
|
| + }
|
| + case PP_VARTYPE_INT32:
|
| + if (!m->ReadInt(iter, &result.value.as_int))
|
| + return false;
|
| + break;
|
| + case PP_VARTYPE_DOUBLE:
|
| + if (!IPC::ParamTraits<double>::Read(m, iter, &result.value.as_double))
|
| + return false;
|
| + break;
|
| + case PP_VARTYPE_OBJECT:
|
| + if (!m->ReadInt64(iter, &result.value.as_id))
|
| + return false;
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| + var_ = result;
|
| + return true;
|
| +}
|
| +
|
| +// StringRawVarData ------------------------------------------------------------
|
| +StringRawVarData::StringRawVarData() {
|
| +}
|
| +
|
| +StringRawVarData::~StringRawVarData() {
|
| +}
|
| +
|
| +PP_VarType StringRawVarData::Type() {
|
| + return PP_VARTYPE_STRING;
|
| +}
|
| +
|
| +bool StringRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
|
| + DCHECK(var.type == PP_VARTYPE_STRING);
|
| + StringVar* string_var = StringVar::FromPPVar(var);
|
| + if (!string_var)
|
| + return false;
|
| + data_ = string_var->value();
|
| + initialized_ = true;
|
| + return true;
|
| +}
|
| +
|
| +PP_Var StringRawVarData::CreatePPVar(PP_Instance instance) {
|
| + return StringVar::StringToPPVar(data_);
|
| +}
|
| +
|
| +void StringRawVarData::PopulatePPVar(const PP_Var& var,
|
| + const std::vector<PP_Var>& graph) {
|
| +}
|
| +
|
| +void StringRawVarData::Write(IPC::Message* m,
|
| + const HandleWriter& handle_writer) {
|
| + m->WriteString(data_);
|
| +}
|
| +
|
| +bool StringRawVarData::Read(PP_VarType type,
|
| + const IPC::Message* m,
|
| + PickleIterator* iter) {
|
| + if (!m->ReadString(iter, &data_))
|
| + return false;
|
| + return true;
|
| +}
|
| +
|
| +// ArrayBufferRawVarData -------------------------------------------------------
|
| +ArrayBufferRawVarData::ArrayBufferRawVarData() {
|
| +}
|
| +
|
| +ArrayBufferRawVarData::~ArrayBufferRawVarData() {
|
| +}
|
| +
|
| +PP_VarType ArrayBufferRawVarData::Type() {
|
| + return PP_VARTYPE_ARRAY_BUFFER;
|
| +}
|
| +
|
| +bool ArrayBufferRawVarData::Init(const PP_Var& var,
|
| + PP_Instance instance) {
|
| + DCHECK(var.type == PP_VARTYPE_ARRAY_BUFFER);
|
| + ArrayBufferVar* buffer_var = ArrayBufferVar::FromPPVar(var);
|
| + if (!buffer_var)
|
| + return false;
|
| + bool using_shmem = false;
|
| + if (buffer_var->ByteLength() >= kMinimumArrayBufferSizeForShmem &&
|
| + instance != 0) {
|
| + int host_handle_id;
|
| + base::SharedMemoryHandle plugin_handle;
|
| + using_shmem = buffer_var->CopyToNewShmem(instance,
|
| + &host_handle_id,
|
| + &plugin_handle);
|
| + if (using_shmem) {
|
| + if (host_shm_handle_id_ != -1) {
|
| + DCHECK(!base::SharedMemory::IsHandleValid(plugin_handle));
|
| + DCHECK(PpapiGlobals::Get()->IsPluginGlobals());
|
| + type_ = ARRAY_BUFFER_SHMEM_HOST;
|
| + host_shm_handle_id_ = host_handle_id;
|
| + } else {
|
| + DCHECK(base::SharedMemory::IsHandleValid(plugin_handle));
|
| + DCHECK(PpapiGlobals::Get()->IsHostGlobals());
|
| + type_ = ARRAY_BUFFER_SHMEM_PLUGIN;
|
| + plugin_shm_handle_ = SerializedHandle(plugin_handle,
|
| + buffer_var->ByteLength());
|
| + }
|
| + }
|
| + }
|
| + if (!using_shmem) {
|
| + type_ = ARRAY_BUFFER_NO_SHMEM;
|
| + data_ = std::string(static_cast<const char*>(buffer_var->Map()),
|
| + buffer_var->ByteLength());
|
| + }
|
| + initialized_ = true;
|
| + return true;
|
| +}
|
| +
|
| +PP_Var ArrayBufferRawVarData::CreatePPVar(PP_Instance instance) {
|
| + PP_Var result = PP_MakeUndefined();
|
| + switch (type_) {
|
| + case ARRAY_BUFFER_SHMEM_HOST: {
|
| + base::SharedMemoryHandle host_handle;
|
| + uint32 size_in_bytes;
|
| + bool ok = PpapiGlobals::Get()->GetVarTracker()->
|
| + StopTrackingSharedMemoryHandle(host_shm_handle_id_,
|
| + instance,
|
| + &host_handle,
|
| + &size_in_bytes);
|
| + if (ok) {
|
| + result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
|
| + size_in_bytes, host_handle);
|
| + } else {
|
| + LOG(ERROR) << "Couldn't find array buffer id: " << host_shm_handle_id_;
|
| + return PP_MakeUndefined();
|
| + }
|
| + break;
|
| + }
|
| + case ARRAY_BUFFER_SHMEM_PLUGIN: {
|
| + result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
|
| + plugin_shm_handle_.size(),
|
| + plugin_shm_handle_.shmem());
|
| + break;
|
| + }
|
| + case ARRAY_BUFFER_NO_SHMEM: {
|
| + result = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
|
| + static_cast<uint32>(data_.size()), data_.data());
|
| + break;
|
| + }
|
| + default:
|
| + NOTREACHED();
|
| + return PP_MakeUndefined();
|
| + }
|
| + DCHECK(result.type == PP_VARTYPE_ARRAY_BUFFER);
|
| + return result;
|
| +}
|
| +
|
| +void ArrayBufferRawVarData::PopulatePPVar(const PP_Var& var,
|
| + const std::vector<PP_Var>& graph) {
|
| +}
|
| +
|
| +void ArrayBufferRawVarData::Write(
|
| + IPC::Message* m,
|
| + const HandleWriter& handle_writer) {
|
| + m->WriteInt(type_);
|
| + switch (type_) {
|
| + case ARRAY_BUFFER_SHMEM_HOST:
|
| + m->WriteInt(host_shm_handle_id_);
|
| + break;
|
| + case ARRAY_BUFFER_SHMEM_PLUGIN:
|
| + handle_writer.Run(m, plugin_shm_handle_);
|
| + break;
|
| + case ARRAY_BUFFER_NO_SHMEM:
|
| + m->WriteString(data_);
|
| + break;
|
| + }
|
| +}
|
| +
|
| +bool ArrayBufferRawVarData::Read(PP_VarType type,
|
| + const IPC::Message* m,
|
| + PickleIterator* iter) {
|
| + int shmem_type;
|
| + if (!m->ReadInt(iter, &shmem_type))
|
| + return false;
|
| + type_ = static_cast<ShmemType>(shmem_type);
|
| + switch (type_) {
|
| + case ARRAY_BUFFER_SHMEM_HOST:
|
| + if (!m->ReadInt(iter, &host_shm_handle_id_))
|
| + return false;
|
| + break;
|
| + case ARRAY_BUFFER_SHMEM_PLUGIN:
|
| + if (!IPC::ParamTraits<SerializedHandle>::Read(
|
| + m, iter, &plugin_shm_handle_)) {
|
| + return false;
|
| + }
|
| + break;
|
| + case ARRAY_BUFFER_NO_SHMEM:
|
| + if (!m->ReadString(iter, &data_))
|
| + return false;
|
| + break;
|
| + default:
|
| + // We read an invalid ID.
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +// ArrayRawVarData -------------------------------------------------------------
|
| +ArrayRawVarData::ArrayRawVarData() {
|
| +}
|
| +
|
| +ArrayRawVarData::~ArrayRawVarData() {
|
| +}
|
| +
|
| +void ArrayRawVarData::AddChild(size_t element) {
|
| + children_.push_back(element);
|
| +}
|
| +
|
| +PP_VarType ArrayRawVarData::Type() {
|
| + return PP_VARTYPE_ARRAY;
|
| +}
|
| +
|
| +bool ArrayRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
|
| + initialized_ = true;
|
| + DCHECK(var.type == PP_VARTYPE_ARRAY);
|
| + initialized_ = true;
|
| + return true;
|
| +}
|
| +
|
| +PP_Var ArrayRawVarData::CreatePPVar(PP_Instance instance) {
|
| + return (new ArrayVar())->GetPPVar();
|
| +}
|
| +
|
| +void ArrayRawVarData::PopulatePPVar(const PP_Var& var,
|
| + const std::vector<PP_Var>& graph) {
|
| + if (var.type != PP_VARTYPE_ARRAY) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + ArrayVar* array_var = ArrayVar::FromPPVar(var);
|
| + DCHECK(array_var->elements().empty());
|
| + for (size_t i = 0; i < children_.size(); ++i)
|
| + array_var->elements().push_back(ScopedPPVar(graph[children_[i]]));
|
| +}
|
| +
|
| +void ArrayRawVarData::Write(IPC::Message* m,
|
| + const HandleWriter& handle_writer) {
|
| + m->WriteUInt32(static_cast<uint32_t>(children_.size()));
|
| + for (size_t i = 0; i < children_.size(); ++i)
|
| + m->WriteUInt32(static_cast<uint32_t>(children_[i]));
|
| +}
|
| +
|
| +bool ArrayRawVarData::Read(PP_VarType type,
|
| + const IPC::Message* m,
|
| + PickleIterator* iter) {
|
| + uint32_t size;
|
| + if (!m->ReadUInt32(iter, &size))
|
| + return false;
|
| + for (uint32_t i = 0; i < size; ++i) {
|
| + uint32_t index;
|
| + if (!m->ReadUInt32(iter, &index))
|
| + return false;
|
| + children_.push_back(index);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +// DictionaryRawVarData --------------------------------------------------------
|
| +DictionaryRawVarData::DictionaryRawVarData() {
|
| +}
|
| +
|
| +DictionaryRawVarData::~DictionaryRawVarData() {
|
| +}
|
| +
|
| +void DictionaryRawVarData::AddChild(const std::string& key,
|
| + size_t value) {
|
| + children_.push_back(make_pair(key, value));
|
| +}
|
| +
|
| +PP_VarType DictionaryRawVarData::Type() {
|
| + return PP_VARTYPE_DICTIONARY;
|
| +}
|
| +
|
| +bool DictionaryRawVarData::Init(const PP_Var& var, PP_Instance /*instance*/) {
|
| + DCHECK(var.type == PP_VARTYPE_DICTIONARY);
|
| + initialized_ = true;
|
| + return true;
|
| +}
|
| +
|
| +PP_Var DictionaryRawVarData::CreatePPVar(PP_Instance instance) {
|
| + return (new DictionaryVar())->GetPPVar();
|
| +}
|
| +
|
| +void DictionaryRawVarData::PopulatePPVar(const PP_Var& var,
|
| + const std::vector<PP_Var>& graph) {
|
| + if (var.type != PP_VARTYPE_DICTIONARY) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + DictionaryVar* dictionary_var = DictionaryVar::FromPPVar(var);
|
| + DCHECK(dictionary_var->key_value_map().empty());
|
| + for (size_t i = 0; i < children_.size(); ++i) {
|
| + ScopedPPVar key(ScopedPPVar::PassRef(),
|
| + StringVar::StringToPPVar(children_[i].first));
|
| + dictionary_var->Set(key.get(), graph[children_[i].second]);
|
| + }
|
| +}
|
| +
|
| +void DictionaryRawVarData::Write(
|
| + IPC::Message* m,
|
| + const HandleWriter& handle_writer) {
|
| + m->WriteUInt32(static_cast<uint32_t>(children_.size()));
|
| + for (size_t i = 0; i < children_.size(); ++i) {
|
| + m->WriteString(children_[i].first);
|
| + m->WriteUInt32(static_cast<uint32_t>(children_[i].second));
|
| + }
|
| +}
|
| +
|
| +bool DictionaryRawVarData::Read(PP_VarType type,
|
| + const IPC::Message* m,
|
| + PickleIterator* iter) {
|
| + uint32_t size;
|
| + if (!m->ReadUInt32(iter, &size))
|
| + return false;
|
| + for (uint32_t i = 0; i < size; ++i) {
|
| + std::string key;
|
| + uint32_t value;
|
| + if (!m->ReadString(iter, &key))
|
| + return false;
|
| + if (!m->ReadUInt32(iter, &value))
|
| + return false;
|
| + children_.push_back(make_pair(key, value));
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +} // namespace proxy
|
| +} // namespace ppapi
|
|
|