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..84dc755b78425a87fa9b21c39b6d5766f098d8f3 |
--- /dev/null |
+++ b/ppapi/proxy/raw_var_data.cc |
@@ -0,0 +1,651 @@ |
+// 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 "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_graph.h" |
+#include "ppapi/shared_impl/var_tracker.h" |
+ |
+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; |
+ |
+RawVarData* CreateRawVarData(const PP_Var& var, |
+ const VarGraph* graph, |
dmichael (off chromium)
2013/04/12 22:40:38
Why not const&?
|
+ PP_Instance instance) { |
+ switch (var.type) { |
+ case PP_VARTYPE_UNDEFINED: |
+ case PP_VARTYPE_NULL: |
+ case PP_VARTYPE_BOOL: |
+ case PP_VARTYPE_INT32: |
+ case PP_VARTYPE_DOUBLE: |
+ return new BasicRawVarData(var); |
+ case PP_VARTYPE_STRING: |
+ return new StringRawVarData(var); |
+ case PP_VARTYPE_ARRAY_BUFFER: |
+ return new ArrayBufferRawVarData(var, instance); |
+ case PP_VARTYPE_ARRAY: |
+ return new ArrayRawVarData(var, *graph); |
+ case PP_VARTYPE_DICTIONARY: |
+ return new DictionaryRawVarData(var, *graph); |
+ case PP_VARTYPE_OBJECT: |
+ NOTREACHED(); |
+ return NULL; |
+ } |
+ NOTREACHED(); |
+ return NULL; |
+} |
+ |
+PP_Var ReferenceToVar(const RawVarData::VarReference& ref, |
dmichael (off chromium)
2013/04/12 22:40:38
"Reference" is a little overloaded, given these ar
raymes
2013/04/14 16:32:57
This has all been removed now.
|
+ const std::vector<PP_Var>& graph) { |
+ PP_Var var = ref.var; |
+ if (VarTracker::IsVarTypeRefcounted(var.type)) { |
+ if (!ref.valid_var_ref) { |
+ var.value.as_id = 0; |
+ } else { |
+ if (graph.size() <= ref.ref_id) { |
+ NOTREACHED(); |
+ return PP_MakeUndefined(); |
+ } |
+ var.value.as_id = graph[ref.ref_id].value.as_id; |
+ } |
+ } |
+ return var; |
+} |
+ |
+RawVarData::VarReference VarToReference(const PP_Var& var, |
+ const VarGraph& graph) { |
+ RawVarData::VarReference result; |
dmichael (off chromium)
2013/04/12 22:40:38
Given VarReference has no default constructor, eve
raymes
2013/04/14 16:32:57
"
|
+ result.var = var; |
+ if (VarTracker::IsVarTypeRefcounted(var.type)) { |
+ std::map<int64_t, size_t>::const_iterator iterator = |
+ graph.id_map.find(var.value.as_id); |
+ if (iterator == graph.id_map.end()) { |
+ result.valid_var_ref = false; |
+ return result; |
+ } |
+ result.ref_id = iterator->second; |
+ } |
+ return result; |
+} |
+ |
+PP_Var MakeInvalidRef(PP_VarType type) { |
dmichael (off chromium)
2013/04/12 22:40:38
I don't think we should even serialize invalid var
raymes
2013/04/14 16:32:57
Done - this is all removed.
|
+ DCHECK(VarTracker::IsVarTypeRefcounted(type)); |
+ PP_Var result; |
+ result.type = type; |
+ result.value.as_id = 0; |
+ return result; |
+} |
+ |
+void WriteVarReference(IPC::Message* m, |
+ const HandleWriter handle_writer, |
+ const RawVarData::VarReference& var_reference) { |
+ if (!VarTracker::IsVarTypeRefcounted(var_reference.var.type)) { |
+ BasicRawVarData(var_reference.var).Write(m, handle_writer); |
+ } else { |
+ m->WriteInt(var_reference.var.type); |
+ m->WriteBool(var_reference.valid_var_ref); |
+ m->WriteUInt32(var_reference.ref_id); |
+ } |
+} |
+ |
+bool ReadVarReference(const IPC::Message* m, |
+ PickleIterator* iter, |
+ RawVarData::VarReference* result_out) { |
+ RawVarData::VarReference result; |
+ int32_t type; |
+ if (!m->ReadInt(iter, &type)) |
+ return false; |
+ result.var.type = static_cast<PP_VarType>(type); |
+ if (!VarTracker::IsVarTypeRefcounted(result.var.type)) { |
+ scoped_ptr<BasicRawVarData> data( |
+ BasicRawVarData::Read(result.var.type, m, iter)); |
+ result.var = data->CreatePPVar(0); |
+ } else { |
+ if (!m->ReadBool(iter, &result.valid_var_ref)) |
+ return false; |
+ if (!m->ReadUInt32(iter, &result.ref_id)) |
+ return false; |
+ } |
+ *result_out = result; |
+ return true; |
+} |
+ |
+void DefaultHandleWriter(IPC::Message* m, const SerializedHandle& handle) { |
+ IPC::ParamTraits<SerializedHandle>::Write(m, handle); |
+} |
+ |
+} // namespace |
+ |
+// RawVarDataGraph ------------------------------------------------------------ |
+RawVarDataGraph::RawVarDataGraph() { |
+} |
+ |
+RawVarDataGraph::~RawVarDataGraph() { |
+} |
+ |
+RawVarDataGraph::RawVarDataGraph(const PP_Var& var, PP_Instance instance) { |
+ if (PpapiGlobals::Get()->GetVarTracker()->GetVar(var) == NULL) { |
+ // If the node is a primitive value, just create a single raw var data. |
+ data_.push_back(CreateRawVarData(var, NULL, instance)); |
dmichael (off chromium)
2013/04/12 22:40:38
Why do you need the if at all? (Notes to self: Loo
raymes
2013/04/14 16:32:57
I changed the way this works, hopefully it is clea
|
+ } else { |
+ VarGraph graph; |
+ bool success = VarGraph::Create(var, &graph); |
+ if (!success) { |
+ NOTREACHED(); |
+ return; |
+ } |
+ |
+ for (size_t i = 0; i < graph.nodes.size(); ++i) |
+ data_.push_back(CreateRawVarData(var, &graph, instance)); |
+ } |
+} |
+ |
+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]->InitPPVar(graph[i], graph); |
dmichael (off chromium)
2013/04/12 22:40:38
I found InitPPVar a bit confusing as a name. Maybe
raymes
2013/04/14 16:32:57
See my reply in the header. I changed the name as
|
+ // 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->WriteInt(data_.size()); |
+ for (size_t i = 0; i < data_.size(); ++i) |
+ 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); |
+ int32_t size = 0; |
+ if (!m->ReadInt(iter, &size)) |
+ return scoped_ptr<RawVarDataGraph>(); |
+ for (int32_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); |
+ switch (var_type) { |
+ case PP_VARTYPE_UNDEFINED: |
+ case PP_VARTYPE_NULL: |
+ case PP_VARTYPE_BOOL: |
+ case PP_VARTYPE_INT32: |
+ case PP_VARTYPE_DOUBLE: |
+ result->data_.push_back(BasicRawVarData::Read(var_type, m, iter)); |
dmichael (off chromium)
2013/04/12 22:40:38
Random idea, not sure how hard this is... It woul
raymes
2013/04/14 16:32:57
I think that's a good idea. Done.
|
+ break; |
+ case PP_VARTYPE_STRING: |
+ result->data_.push_back(StringRawVarData::Read(var_type, m, iter)); |
+ break; |
+ case PP_VARTYPE_ARRAY: |
+ result->data_.push_back(ArrayRawVarData::Read(var_type, m, iter)); |
+ break; |
+ case PP_VARTYPE_DICTIONARY: |
+ result->data_.push_back(DictionaryRawVarData::Read(var_type, m, iter)); |
+ break; |
+ case PP_VARTYPE_ARRAY_BUFFER: |
+ result->data_.push_back(ArrayBufferRawVarData::Read(var_type, m, iter)); |
+ break; |
+ case PP_VARTYPE_OBJECT: |
+ NOTREACHED(); |
+ scoped_ptr<RawVarDataGraph>(); |
+ } |
+ } |
+ return result.Pass(); |
+} |
+ |
+// BasicRawVarData ------------------------------------------------------------- |
+BasicRawVarData::BasicRawVarData(const PP_Var& var) : var_(var) { |
+} |
+ |
+BasicRawVarData::~BasicRawVarData() { |
+} |
+ |
+PP_Var BasicRawVarData::CreatePPVar(PP_Instance instance) { |
+ return var_; |
+} |
+ |
+void BasicRawVarData::InitPPVar(const PP_Var& var, |
+ const std::vector<PP_Var>& graph) { |
+} |
+ |
+void BasicRawVarData::Write( |
+ IPC::Message* m, |
+ const HandleWriter& handle_writer) { |
+ m->WriteInt(static_cast<int>(var_.type)); |
+ 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; |
+ default: |
+ NOTREACHED(); |
+ } |
+} |
+ |
+// static |
+BasicRawVarData* 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 NULL; |
+ result.value.as_bool = PP_FromBool(bool_value); |
+ break; |
+ } |
+ case PP_VARTYPE_INT32: |
+ if (!m->ReadInt(iter, &result.value.as_int)) |
+ return NULL; |
+ break; |
+ case PP_VARTYPE_DOUBLE: |
+ if (!IPC::ParamTraits<double>::Read(m, iter, &result.value.as_double)) |
+ return NULL; |
+ break; |
+ default: |
+ NOTREACHED(); |
+ return NULL; |
+ } |
+ return new BasicRawVarData(result); |
+} |
+ |
+// StringRawVarData ------------------------------------------------------------ |
+StringRawVarData::StringRawVarData(const PP_Var& var) : valid_var_ref_(true) { |
+ DCHECK(var.type == PP_VARTYPE_STRING); |
+ StringVar* string_var = StringVar::FromPPVar(var); |
+ if (!string_var) |
+ valid_var_ref_ = false; |
+ else |
+ data_ = *string_var->ptr(); |
dmichael (off chromium)
2013/04/12 22:40:38
It's worth thinking about if there are ways to red
raymes
2013/04/14 16:32:57
I haven't yet addressed any of these comments rela
|
+} |
+ |
+StringRawVarData::~StringRawVarData() { |
+} |
+ |
+PP_Var StringRawVarData::CreatePPVar(PP_Instance instance) { |
+ if (!valid_var_ref_) |
+ return MakeInvalidRef(PP_VARTYPE_STRING); |
+ return StringVar::StringToPPVar(data_); |
dmichael (off chromium)
2013/04/12 22:40:38
I think you should use StringVar::SwapValidatedUTF
raymes
2013/04/14 16:32:57
"
|
+} |
+ |
+void StringRawVarData::InitPPVar(const PP_Var& var, |
+ const std::vector<PP_Var>& graph) { |
+} |
+ |
+void StringRawVarData::Write(IPC::Message* m, |
+ const HandleWriter& handle_writer) { |
+ m->WriteInt(PP_VARTYPE_STRING); |
dmichael (off chromium)
2013/04/12 22:40:38
It feels a little odd that the Write virtual funct
raymes
2013/04/14 16:32:57
Done.
|
+ m->WriteBool(valid_var_ref_); |
+ if (valid_var_ref_) |
+ m->WriteString(data_); |
+} |
+ |
+// static |
+StringRawVarData* StringRawVarData::Read(PP_VarType type, |
+ const IPC::Message* m, |
+ PickleIterator* iter) { |
+ bool valid_var_ref; |
+ std::string data; |
+ if (!m->ReadBool(iter, &valid_var_ref)) |
+ return NULL; |
+ if (valid_var_ref) { |
+ if (!m->ReadString(iter, &data)) |
+ return NULL; |
+ } |
+ return new StringRawVarData(valid_var_ref, data); |
dmichael (off chromium)
2013/04/12 22:40:38
I can't see where this constructor is actually imp
raymes
2013/04/14 16:32:57
"
|
+} |
+ |
+// ArrayBufferRawVarData ------------------------------------------------------- |
+ArrayBufferRawVarData::ArrayBufferRawVarData(const PP_Var& var, |
+ PP_Instance instance) |
+ : valid_var_ref_(true) { |
+ DCHECK(var.type == PP_VARTYPE_ARRAY_BUFFER); |
+ ArrayBufferVar* buffer_var = ArrayBufferVar::FromPPVar(var); |
+ if (!buffer_var) { |
+ valid_var_ref_ = false; |
+ } else { |
+ 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()); |
dmichael (off chromium)
2013/04/12 22:40:38
Same comment as for String... seems like we could
raymes
2013/04/14 16:32:57
"
|
+ } |
+ } |
+} |
+ |
+ArrayBufferRawVarData::ArrayBufferRawVarData(bool valid_var_ref, |
+ ShmemType type) |
+ : valid_var_ref_(valid_var_ref), |
+ type_(type) { |
+} |
+ |
+ArrayBufferRawVarData::~ArrayBufferRawVarData() { |
+} |
+ |
+PP_Var ArrayBufferRawVarData::CreatePPVar(PP_Instance instance) { |
+ if (!valid_var_ref_) |
+ return MakeInvalidRef(PP_VARTYPE_ARRAY_BUFFER); |
+ 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()); |
dmichael (off chromium)
2013/04/12 22:40:38
On the plugin side, if data_ is a vector<uint8_t>,
raymes
2013/04/14 16:32:57
"
|
+ break; |
+ } |
+ default: |
+ NOTREACHED(); |
+ return PP_MakeUndefined(); |
+ } |
+ DCHECK(result.type == PP_VARTYPE_ARRAY_BUFFER); |
+ return result; |
+} |
+ |
+void ArrayBufferRawVarData::InitPPVar(const PP_Var& var, |
+ const std::vector<PP_Var>& graph) { |
+} |
+ |
+void ArrayBufferRawVarData::Write( |
+ IPC::Message* m, |
+ const HandleWriter& handle_writer) { |
+ m->WriteInt(PP_VARTYPE_ARRAY_BUFFER); |
+ m->WriteBool(valid_var_ref_); |
+ if (!valid_var_ref_) |
+ return; |
+ 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; |
+ } |
+} |
+ |
+// static |
+ArrayBufferRawVarData* ArrayBufferRawVarData::Read(PP_VarType type, |
+ const IPC::Message* m, |
+ PickleIterator* iter) { |
+ bool valid_var_ref; |
+ if (!m->ReadBool(iter, &valid_var_ref)) |
+ return NULL; |
+ if (!valid_var_ref) |
+ return new ArrayBufferRawVarData(false, ARRAY_BUFFER_NO_SHMEM); |
+ int shmem_type; |
+ if (!m->ReadInt(iter, &shmem_type)) |
+ return NULL; |
+ scoped_ptr<ArrayBufferRawVarData> result( |
+ new ArrayBufferRawVarData(true, static_cast<ShmemType>(shmem_type))); |
+ switch (static_cast<ShmemType>(shmem_type)) { |
+ case ARRAY_BUFFER_SHMEM_HOST: |
+ if (!m->ReadInt(iter, &result->host_shm_handle_id_)) |
+ return NULL; |
+ break; |
+ case ARRAY_BUFFER_SHMEM_PLUGIN: |
+ if (!IPC::ParamTraits<SerializedHandle>::Read( |
+ m, iter, &result->plugin_shm_handle_)) { |
+ return NULL; |
+ } |
+ break; |
+ case ARRAY_BUFFER_NO_SHMEM: |
+ if (!m->ReadString(iter, &result->data_)) |
+ return NULL; |
+ default: |
+ NOTREACHED(); |
+ return NULL; |
+ } |
+ return result.release(); |
+} |
+ |
+// ArrayRawVarData ------------------------------------------------------------- |
+ArrayRawVarData::ArrayRawVarData(const PP_Var& var, const VarGraph& graph) |
+ : valid_var_ref_(true) { |
+ DCHECK(var.type == PP_VARTYPE_ARRAY); |
+ ArrayVar* array_var = ArrayVar::FromPPVar(var); |
+ if (!array_var) { |
+ valid_var_ref_ = false; |
+ } else { |
+ for (ArrayVar::ElementVector::const_iterator iter = |
+ array_var->elements().begin(); |
+ iter != array_var->elements().end(); |
+ ++iter) { |
+ data_.push_back(VarToReference(iter->get(), graph)); |
dmichael (off chromium)
2013/04/12 22:40:38
It seems strange to me that you have two different
raymes1
2013/04/12 23:21:38
Sort of. The VarGraph gives you 2 things:
1) The t
dmichael (off chromium)
2013/04/15 17:40:04
It looks like you figured out how to avoid the two
|
+ } |
+ } |
+} |
+ |
+ArrayRawVarData::ArrayRawVarData(bool valid_var_ref, |
+ const std::vector<VarReference>& data) |
+ : valid_var_ref_(valid_var_ref), |
+ data_(data) { |
+} |
+ |
+ArrayRawVarData::~ArrayRawVarData() { |
+} |
+ |
+PP_Var ArrayRawVarData::CreatePPVar(PP_Instance instance) { |
+ if (!valid_var_ref_) |
+ return MakeInvalidRef(PP_VARTYPE_ARRAY); |
+ return (new ArrayVar())->GetPPVar(); |
+} |
+ |
+void ArrayRawVarData::InitPPVar(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 < data_.size(); ++i) { |
+ array_var->elements().push_back(ScopedPPVar( |
+ ReferenceToVar(data_[i], graph))); |
+ } |
+} |
+ |
+void ArrayRawVarData::Write(IPC::Message* m, |
+ const HandleWriter& handle_writer) { |
+ m->WriteInt(PP_VARTYPE_ARRAY); |
+ m->WriteBool(valid_var_ref_); |
+ if (!valid_var_ref_) |
+ return; |
+ m->WriteInt(data_.size()); |
+ for (size_t i = 0; i < data_.size(); ++i) |
+ WriteVarReference(m, handle_writer, data_[i]); |
+} |
+ |
+// static |
+ArrayRawVarData* ArrayRawVarData::Read(PP_VarType type, |
+ const IPC::Message* m, |
+ PickleIterator* iter) { |
+ bool valid_var_ref; |
+ std::vector<VarReference> data; |
+ if (!m->ReadBool(iter, &valid_var_ref)) |
+ return NULL; |
+ if (valid_var_ref) { |
+ VarReference current; |
+ if (!ReadVarReference(m, iter, ¤t)) |
+ return NULL; |
+ data.push_back(current); |
+ } |
+ return new ArrayRawVarData(valid_var_ref, data); |
+} |
+ |
+// DictionaryRawVarData -------------------------------------------------------- |
+DictionaryRawVarData::DictionaryRawVarData(const PP_Var& var, |
+ const VarGraph& graph) |
+ : valid_var_ref_(true) { |
+ DCHECK(var.type == PP_VARTYPE_DICTIONARY); |
+ DictionaryVar* dict_var = DictionaryVar::FromPPVar(var); |
+ if (!dict_var) { |
+ valid_var_ref_ = false; |
+ } else { |
+ for (DictionaryVar::KeyValueMap::const_iterator iter = |
+ dict_var->key_value_map().begin(); |
+ iter != dict_var->key_value_map().end(); |
+ ++iter) { |
+ std::pair<std::string, VarReference> reference; |
+ reference.first = iter->first; |
+ reference.second = VarToReference(iter->second.get(), graph); |
+ data_.push_back(reference); |
+ } |
+ } |
+} |
+ |
+DictionaryRawVarData::DictionaryRawVarData( |
+ bool valid_var_ref, |
+ const std::vector<std::pair<std::string, VarReference> >& data) |
+ : valid_var_ref_(valid_var_ref), |
+ data_(data) { |
+} |
+ |
+DictionaryRawVarData::~DictionaryRawVarData() { |
+} |
+ |
+PP_Var DictionaryRawVarData::CreatePPVar(PP_Instance instance) { |
+ if (!valid_var_ref_) |
+ return MakeInvalidRef(PP_VARTYPE_DICTIONARY); |
+ return (new DictionaryVar())->GetPPVar(); |
+} |
+ |
+void DictionaryRawVarData::InitPPVar(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 < data_.size(); ++i) { |
+ PP_Var value = ReferenceToVar(data_[i].second, graph); |
+ dictionary_var->Set(StringVar::StringToPPVar(data_[i].first), value); |
+ } |
+} |
+ |
+void DictionaryRawVarData::Write( |
+ IPC::Message* m, |
+ const HandleWriter& handle_writer) { |
+ m->WriteInt(PP_VARTYPE_DICTIONARY); |
+ m->WriteBool(valid_var_ref_); |
+ if (!valid_var_ref_) |
+ return; |
+ m->WriteInt(data_.size()); |
+ for (size_t i = 0; i < data_.size(); ++i) { |
+ m->WriteString(data_[i].first); |
+ WriteVarReference(m, handle_writer, data_[i].second); |
+ } |
+} |
+ |
+// static |
+DictionaryRawVarData* DictionaryRawVarData::Read(PP_VarType type, |
+ const IPC::Message* m, |
+ PickleIterator* iter) { |
+ bool valid_var_ref; |
+ std::vector<std::pair<std::string, VarReference> > data; |
+ if (!m->ReadBool(iter, &valid_var_ref)) |
+ return NULL; |
+ if (valid_var_ref) { |
+ std::string key; |
+ VarReference value; |
+ if (!m->ReadString(iter, &key)) |
+ return NULL; |
+ if (!ReadVarReference(m, iter, &value)) |
+ return NULL; |
+ data.push_back(make_pair(key, value)); |
+ } |
+ return new DictionaryRawVarData(valid_var_ref, data); |
+} |
+ |
+} // namespace proxy |
+} // namespace ppapi |