summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ppapi/api/dev/ppb_var_dictionary_dev.idl89
-rw-r--r--ppapi/c/dev/ppb_var_dictionary_dev.h106
-rw-r--r--ppapi/cpp/dev/var_dictionary_dev.cc97
-rw-r--r--ppapi/cpp/dev/var_dictionary_dev.h87
-rw-r--r--ppapi/cpp/var.cc10
-rw-r--r--ppapi/cpp/var.h12
-rw-r--r--ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c58
-rw-r--r--ppapi/ppapi_shared.gypi5
-rw-r--r--ppapi/ppapi_sources.gypi3
-rw-r--r--ppapi/ppapi_tests.gypi1
-rw-r--r--ppapi/proxy/interface_list.cc1
-rw-r--r--ppapi/proxy/serialized_var.cc4
-rw-r--r--ppapi/shared_impl/dictionary_var.cc101
-rw-r--r--ppapi/shared_impl/dictionary_var.h63
-rw-r--r--ppapi/shared_impl/scoped_pp_var.cc6
-rw-r--r--ppapi/shared_impl/var.cc10
-rw-r--r--ppapi/shared_impl/var.h2
-rw-r--r--ppapi/shared_impl/var_tracker.cc2
-rw-r--r--ppapi/shared_impl/var_value_conversions.cc298
-rw-r--r--ppapi/shared_impl/var_value_conversions.h41
-rw-r--r--ppapi/shared_impl/var_value_conversions_unittest.cc241
-rw-r--r--ppapi/tests/all_c_includes.h1
-rw-r--r--ppapi/tests/all_cpp_includes.h1
-rw-r--r--ppapi/thunk/interfaces_ppb_public_dev.h2
-rw-r--r--ppapi/thunk/ppb_var_dictionary_thunk.cc86
-rw-r--r--webkit/plugins/ppapi/plugin_module.cc1
26 files changed, 1322 insertions, 6 deletions
diff --git a/ppapi/api/dev/ppb_var_dictionary_dev.idl b/ppapi/api/dev/ppb_var_dictionary_dev.idl
new file mode 100644
index 0000000..f3e7407
--- /dev/null
+++ b/ppapi/api/dev/ppb_var_dictionary_dev.idl
@@ -0,0 +1,89 @@
+/* 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.
+ */
+
+/**
+ * This file defines the <code>PPB_VarDictionary_Dev</code> struct providing
+ * a way to interact with dictionary vars.
+ */
+
+label Chrome {
+ M27 = 0.1
+};
+
+/**
+ * A dictionary var contains key-value pairs with unique keys. The keys are
+ * strings while the values can be arbitrary vars. Key comparison is always
+ * done by value instead of by reference.
+ */
+[macro="PPB_VAR_DICTIONARY_DEV_INTERFACE"]
+interface PPB_VarDictionary_Dev {
+ /**
+ * Creates a dictionary var, i.e., a <code>PP_Var</code> with type set to
+ * <code>PP_VARTYPE_DICTIONARY</code>.
+ *
+ * @return An empty dictionary var, whose reference count is set to 1 on
+ * behalf of the caller.
+ */
+ PP_Var Create();
+
+ /**
+ * Gets the value associated with the specified key.
+ *
+ * @param[in] dict A dictionary var.
+ * @param[in] key A string var.
+ *
+ * @return The value that is associated with <code>key</code>. The reference
+ * count is incremented on behalf of the caller. If <code>key</code> is not a
+ * string var, or it doesn't exist in <code>dict</code>, an undefined var is
+ * returned.
+ */
+ PP_Var Get([in] PP_Var dict, [in] PP_Var key);
+
+ /**
+ * Sets the value associated with the specified key. The dictionary is
+ * responsible for holding references to its children to keep them alive.
+ *
+ * @param[in] dict A dictionary var.
+ * @param[in] key A string var. If this key hasn't existed in
+ * <code>dict</code>, it is added and associated with <code>value</code>;
+ * otherwise, the previous value is replaced with <code>value</code>.
+ * @param[in] value The value to set.
+ *
+ * @return A <code>PP_Bool</code> indicating whether the operation succeeds.
+ */
+ PP_Bool Set([in] PP_Var dict, [in] PP_Var key, [in] PP_Var value);
+
+ /**
+ * Deletes the specified key and its associated value, if the key exists.
+ *
+ * @param[in] dict A dictionary var.
+ * @param[in] key A string var.
+ */
+ void Delete([in] PP_Var dict, [in] PP_Var key);
+
+ /**
+ * Checks whether a key exists.
+ *
+ * @param[in] dict A dictionary var.
+ * @param[in] key A string var.
+ *
+ * @return A <code>PP_Bool</code> indicating whether the key exists.
+ */
+ PP_Bool HasKey([in] PP_Var dict, [in] PP_Var key);
+
+ /**
+ * Gets all the keys in a dictionary. Please note that for each key that you
+ * set into the dictionary, a string var with the same contents is returned;
+ * but it may not be the same string var (i.e., <code>value.as_id</code> may
+ * be different).
+ *
+ * @param[in] dict A dictionary var.
+ *
+ * @return An array var which contains all the keys of <code>dict</code>. Its
+ * reference count is incremented on behalf of the caller. The elements are
+ * string vars. Returns a null var if failed.
+ */
+ PP_Var GetKeys([in] PP_Var dict);
+};
diff --git a/ppapi/c/dev/ppb_var_dictionary_dev.h b/ppapi/c/dev/ppb_var_dictionary_dev.h
new file mode 100644
index 0000000..d601071
--- /dev/null
+++ b/ppapi/c/dev/ppb_var_dictionary_dev.h
@@ -0,0 +1,106 @@
+/* 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.
+ */
+
+/* From dev/ppb_var_dictionary_dev.idl modified Wed Mar 13 21:47:05 2013. */
+
+#ifndef PPAPI_C_DEV_PPB_VAR_DICTIONARY_DEV_H_
+#define PPAPI_C_DEV_PPB_VAR_DICTIONARY_DEV_H_
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_macros.h"
+#include "ppapi/c/pp_stdint.h"
+#include "ppapi/c/pp_var.h"
+
+#define PPB_VAR_DICTIONARY_DEV_INTERFACE_0_1 "PPB_VarDictionary(Dev);0.1"
+#define PPB_VAR_DICTIONARY_DEV_INTERFACE PPB_VAR_DICTIONARY_DEV_INTERFACE_0_1
+
+/**
+ * @file
+ * This file defines the <code>PPB_VarDictionary_Dev</code> struct providing
+ * a way to interact with dictionary vars.
+ */
+
+
+/**
+ * @addtogroup Interfaces
+ * @{
+ */
+/**
+ * A dictionary var contains key-value pairs with unique keys. The keys are
+ * strings while the values can be arbitrary vars. Key comparison is always
+ * done by value instead of by reference.
+ */
+struct PPB_VarDictionary_Dev_0_1 {
+ /**
+ * Creates a dictionary var, i.e., a <code>PP_Var</code> with type set to
+ * <code>PP_VARTYPE_DICTIONARY</code>.
+ *
+ * @return An empty dictionary var, whose reference count is set to 1 on
+ * behalf of the caller.
+ */
+ struct PP_Var (*Create)(void);
+ /**
+ * Gets the value associated with the specified key.
+ *
+ * @param[in] dict A dictionary var.
+ * @param[in] key A string var.
+ *
+ * @return The value that is associated with <code>key</code>. The reference
+ * count is incremented on behalf of the caller. If <code>key</code> is not a
+ * string var, or it doesn't exist in <code>dict</code>, an undefined var is
+ * returned.
+ */
+ struct PP_Var (*Get)(struct PP_Var dict, struct PP_Var key);
+ /**
+ * Sets the value associated with the specified key. The dictionary is
+ * responsible for holding references to its children to keep them alive.
+ *
+ * @param[in] dict A dictionary var.
+ * @param[in] key A string var. If this key hasn't existed in
+ * <code>dict</code>, it is added and associated with <code>value</code>;
+ * otherwise, the previous value is replaced with <code>value</code>.
+ * @param[in] value The value to set.
+ *
+ * @return A <code>PP_Bool</code> indicating whether the operation succeeds.
+ */
+ PP_Bool (*Set)(struct PP_Var dict, struct PP_Var key, struct PP_Var value);
+ /**
+ * Deletes the specified key and its associated value, if the key exists.
+ *
+ * @param[in] dict A dictionary var.
+ * @param[in] key A string var.
+ */
+ void (*Delete)(struct PP_Var dict, struct PP_Var key);
+ /**
+ * Checks whether a key exists.
+ *
+ * @param[in] dict A dictionary var.
+ * @param[in] key A string var.
+ *
+ * @return A <code>PP_Bool</code> indicating whether the key exists.
+ */
+ PP_Bool (*HasKey)(struct PP_Var dict, struct PP_Var key);
+ /**
+ * Gets all the keys in a dictionary. Please note that for each key that you
+ * set into the dictionary, a string var with the same contents is returned;
+ * but it may not be the same string var (i.e., <code>value.as_id</code> may
+ * be different).
+ *
+ * @param[in] dict A dictionary var.
+ *
+ * @return An array var which contains all the keys of <code>dict</code>. Its
+ * reference count is incremented on behalf of the caller. The elements are
+ * string vars. Returns a null var if failed.
+ */
+ struct PP_Var (*GetKeys)(struct PP_Var dict);
+};
+
+typedef struct PPB_VarDictionary_Dev_0_1 PPB_VarDictionary_Dev;
+/**
+ * @}
+ */
+
+#endif /* PPAPI_C_DEV_PPB_VAR_DICTIONARY_DEV_H_ */
+
diff --git a/ppapi/cpp/dev/var_dictionary_dev.cc b/ppapi/cpp/dev/var_dictionary_dev.cc
new file mode 100644
index 0000000..cb0ba5c
--- /dev/null
+++ b/ppapi/cpp/dev/var_dictionary_dev.cc
@@ -0,0 +1,97 @@
+// 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/cpp/dev/var_dictionary_dev.h"
+
+#include "ppapi/c/dev/ppb_var_dictionary_dev.h"
+#include "ppapi/cpp/logging.h"
+#include "ppapi/cpp/module_impl.h"
+
+namespace pp {
+
+namespace {
+
+template <> const char* interface_name<PPB_VarDictionary_Dev_0_1>() {
+ return PPB_VAR_DICTIONARY_DEV_INTERFACE_0_1;
+}
+
+} // namespace
+
+VarDictionary_Dev::VarDictionary_Dev() : Var(Null()) {
+ if (has_interface<PPB_VarDictionary_Dev_0_1>())
+ var_ = get_interface<PPB_VarDictionary_Dev_0_1>()->Create();
+ else
+ PP_NOTREACHED();
+}
+
+VarDictionary_Dev::VarDictionary_Dev(const Var& var) : Var(var) {
+ if (!var.is_dictionary()) {
+ PP_NOTREACHED();
+
+ // This takes care of releasing the reference that this object holds.
+ Var::operator=(Var(Null()));
+ }
+}
+
+VarDictionary_Dev::VarDictionary_Dev(const VarDictionary_Dev& other)
+ : Var(other) {
+}
+
+VarDictionary_Dev::~VarDictionary_Dev() {
+}
+
+VarDictionary_Dev& VarDictionary_Dev::operator=(
+ const VarDictionary_Dev& other) {
+ Var::operator=(other);
+ return *this;
+}
+
+Var& VarDictionary_Dev::operator=(const Var& other) {
+ if (other.is_dictionary()) {
+ Var::operator=(other);
+ } else {
+ PP_NOTREACHED();
+ Var::operator=(Var(Null()));
+ }
+ return *this;
+}
+
+Var VarDictionary_Dev::Get(const Var& key) const {
+ if (!has_interface<PPB_VarDictionary_Dev_0_1>())
+ return Var();
+
+ return Var(
+ PASS_REF,
+ get_interface<PPB_VarDictionary_Dev_0_1>()->Get(var_, key.pp_var()));
+}
+
+PP_Bool VarDictionary_Dev::Set(const Var& key, const Var& value) {
+ if (!has_interface<PPB_VarDictionary_Dev_0_1>())
+ return PP_FALSE;
+
+ return get_interface<PPB_VarDictionary_Dev_0_1>()->Set(var_, key.pp_var(),
+ value.pp_var());
+}
+
+void VarDictionary_Dev::Delete(const Var& key) {
+ if (has_interface<PPB_VarDictionary_Dev_0_1>())
+ get_interface<PPB_VarDictionary_Dev_0_1>()->Delete(var_, key.pp_var());
+}
+
+PP_Bool VarDictionary_Dev::HasKey(const Var& key) const {
+ if (!has_interface<PPB_VarDictionary_Dev_0_1>())
+ return PP_FALSE;
+
+ return get_interface<PPB_VarDictionary_Dev_0_1>()->HasKey(var_, key.pp_var());
+}
+
+Var VarDictionary_Dev::GetKeys() const {
+ if (!has_interface<PPB_VarDictionary_Dev_0_1>())
+ return Var(Null());
+
+ return Var(PASS_REF,
+ get_interface<PPB_VarDictionary_Dev_0_1>()->GetKeys(var_));
+}
+
+} // namespace pp
diff --git a/ppapi/cpp/dev/var_dictionary_dev.h b/ppapi/cpp/dev/var_dictionary_dev.h
new file mode 100644
index 0000000..a7f3abf
--- /dev/null
+++ b/ppapi/cpp/dev/var_dictionary_dev.h
@@ -0,0 +1,87 @@
+// 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.
+
+#ifndef PPAPI_CPP_DEV_VAR_DICTIONARY_DEV_H_
+#define PPAPI_CPP_DEV_VAR_DICTIONARY_DEV_H_
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/cpp/var.h"
+
+/// @file
+/// This file defines the API for interacting with dictionary vars.
+
+namespace pp {
+
+class VarDictionary_Dev : public Var {
+ public:
+ /// Constructs a new dictionary var.
+ VarDictionary_Dev();
+
+ /// Contructs a <code>VarDictionary_Dev</code> given a var for which
+ /// is_dictionary() is true. This will refer to the same dictionary var, but
+ /// allow you to access methods specific to dictionary.
+ ///
+ /// @param[in] var A dictionary var.
+ explicit VarDictionary_Dev(const Var& var);
+
+ /// Copy constructor.
+ VarDictionary_Dev(const VarDictionary_Dev& other);
+
+ virtual ~VarDictionary_Dev();
+
+ /// Assignment operator.
+ VarDictionary_Dev& operator=(const VarDictionary_Dev& other);
+
+ /// The <code>Var</code> assignment operator is overridden here so that we can
+ /// check for assigning a non-dictionary var to a
+ /// <code>VarDictionary_Dev</code>.
+ ///
+ /// @param[in] other The dictionary var to be assigned.
+ ///
+ /// @return The resulting <code>VarDictionary_Dev</code> (as a
+ /// <code>Var</code>&).
+ virtual Var& operator=(const Var& other);
+
+ /// Gets the value associated with the specified key.
+ ///
+ /// @param[in] key A string var.
+ ///
+ /// @return The value that is associated with <code>key</code>. If
+ /// <code>key</code> is not a string var, or it doesn't exist in the
+ /// dictionary, an undefined var is returned.
+ Var Get(const Var& key) const;
+
+ /// Sets the value associated with the specified key.
+ ///
+ /// @param[in] key A string var. If this key hasn't existed in the dictionary,
+ /// it is added and associated with <code>value</code>; otherwise, the
+ /// previous value is replaced with <code>value</code>.
+ /// @param[in] value The value to set.
+ ///
+ /// @return A <code>PP_Bool</code> indicating whether the operation succeeds.
+ PP_Bool Set(const Var& key, const Var& value);
+
+ /// Deletes the specified key and its associated value, if the key exists.
+ ///
+ /// @param[in] key A string var.
+ void Delete(const Var& key);
+
+ /// Checks whether a key exists.
+ ///
+ /// @param[in] key A string var.
+ ///
+ /// @return A <code>PP_Bool</code> indicating whether the key exists.
+ PP_Bool HasKey(const Var& key) const;
+
+ /// Gets all the keys in the dictionary.
+ ///
+ /// @return An array var which contains all the keys of the dictionary.
+ /// The elements are string vars. Returns a null var if failed.
+ /// TODO(yzshen): Change Var to VarArray_Dev once it is supported.
+ Var GetKeys() const;
+};
+
+} // namespace pp
+
+#endif // PPAPI_CPP_DEV_VAR_DICTIONARY_DEV_H_
diff --git a/ppapi/cpp/var.cc b/ppapi/cpp/var.cc
index 09a8fe3..1108e05 100644
--- a/ppapi/cpp/var.cc
+++ b/ppapi/cpp/var.cc
@@ -241,10 +241,16 @@ std::string Var::DebugString() const {
str.append("...");
}
snprintf(buf, sizeof(buf), format, str.c_str());
- } else if (is_array_buffer()) {
- snprintf(buf, sizeof(buf), "Var(ARRAY_BUFFER)");
} else if (is_object()) {
snprintf(buf, sizeof(buf), "Var(OBJECT)");
+ } else if (is_array()) {
+ snprintf(buf, sizeof(buf), "Var(ARRAY)");
+ } else if (is_dictionary()) {
+ snprintf(buf, sizeof(buf), "Var(DICTIONARY)");
+ } else if (is_array_buffer()) {
+ snprintf(buf, sizeof(buf), "Var(ARRAY_BUFFER)");
+ } else {
+ buf[0] = '\0';
}
return buf;
}
diff --git a/ppapi/cpp/var.h b/ppapi/cpp/var.h
index d114054..77bb5d8 100644
--- a/ppapi/cpp/var.h
+++ b/ppapi/cpp/var.h
@@ -122,9 +122,19 @@ class Var {
/// This function determines if this <code>Var</code> is an object.
///
- /// @return true if this <code>Var</code> is an object, otherwise false.
+ /// @return true if this <code>Var</code> is an object, otherwise false.
bool is_object() const { return var_.type == PP_VARTYPE_OBJECT; }
+ /// This function determines if this <code>Var</code> is an array.
+ ///
+ /// @return true if this <code>Var</code> is an array, otherwise false.
+ bool is_array() const { return var_.type == PP_VARTYPE_ARRAY; }
+
+ /// This function determines if this <code>Var</code> is a dictionary.
+ ///
+ /// @return true if this <code>Var</code> is a dictinoary, otherwise false.
+ bool is_dictionary() const { return var_.type == PP_VARTYPE_DICTIONARY; }
+
/// This function determines if this <code>Var</code> is an integer value.
/// The <code>is_int</code> function returns the internal representation.
/// The JavaScript runtime may convert between the two as needed, so the
diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
index 310f946..1777207 100644
--- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
+++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
@@ -28,6 +28,7 @@
#include "ppapi/c/dev/ppb_trace_event_dev.h"
#include "ppapi/c/dev/ppb_truetype_font_dev.h"
#include "ppapi/c/dev/ppb_url_util_dev.h"
+#include "ppapi/c/dev/ppb_var_dictionary_dev.h"
#include "ppapi/c/dev/ppb_video_capture_dev.h"
#include "ppapi/c/dev/ppb_video_decoder_dev.h"
#include "ppapi/c/dev/ppb_view_dev.h"
@@ -209,6 +210,7 @@ static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_TextInput_Dev_0_2;
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_Trace_Event_Dev_0_1;
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_TrueTypeFont_Dev_0_1;
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_URLUtil_Dev_0_6;
+static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_VarDictionary_Dev_0_1;
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_VideoCapture_Dev_0_2;
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_VideoCapture_Dev_0_3;
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_VideoDecoder_Dev_0_16;
@@ -2085,6 +2087,46 @@ struct PP_Var Pnacl_M17_PPB_URLUtil_Dev_GetPluginInstanceURL(PP_Instance instanc
/* End wrapper methods for PPB_URLUtil_Dev_0_6 */
+/* Begin wrapper methods for PPB_VarDictionary_Dev_0_1 */
+
+static __attribute__((pnaclcall))
+struct PP_Var Pnacl_M27_PPB_VarDictionary_Dev_Create(void) {
+ const struct PPB_VarDictionary_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_VarDictionary_Dev_0_1.real_iface;
+ return iface->Create();
+}
+
+static __attribute__((pnaclcall))
+struct PP_Var Pnacl_M27_PPB_VarDictionary_Dev_Get(struct PP_Var dict, struct PP_Var key) {
+ const struct PPB_VarDictionary_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_VarDictionary_Dev_0_1.real_iface;
+ return iface->Get(dict, key);
+}
+
+static __attribute__((pnaclcall))
+PP_Bool Pnacl_M27_PPB_VarDictionary_Dev_Set(struct PP_Var dict, struct PP_Var key, struct PP_Var value) {
+ const struct PPB_VarDictionary_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_VarDictionary_Dev_0_1.real_iface;
+ return iface->Set(dict, key, value);
+}
+
+static __attribute__((pnaclcall))
+void Pnacl_M27_PPB_VarDictionary_Dev_Delete(struct PP_Var dict, struct PP_Var key) {
+ const struct PPB_VarDictionary_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_VarDictionary_Dev_0_1.real_iface;
+ iface->Delete(dict, key);
+}
+
+static __attribute__((pnaclcall))
+PP_Bool Pnacl_M27_PPB_VarDictionary_Dev_HasKey(struct PP_Var dict, struct PP_Var key) {
+ const struct PPB_VarDictionary_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_VarDictionary_Dev_0_1.real_iface;
+ return iface->HasKey(dict, key);
+}
+
+static __attribute__((pnaclcall))
+struct PP_Var Pnacl_M27_PPB_VarDictionary_Dev_GetKeys(struct PP_Var dict) {
+ const struct PPB_VarDictionary_Dev_0_1 *iface = Pnacl_WrapperInfo_PPB_VarDictionary_Dev_0_1.real_iface;
+ return iface->GetKeys(dict);
+}
+
+/* End wrapper methods for PPB_VarDictionary_Dev_0_1 */
+
/* Begin wrapper methods for PPB_VideoCapture_Dev_0_2 */
static __attribute__((pnaclcall))
@@ -4180,6 +4222,15 @@ struct PPB_URLUtil_Dev_0_6 Pnacl_Wrappers_PPB_URLUtil_Dev_0_6 = {
.GetPluginInstanceURL = (struct PP_Var (*)(PP_Instance instance, struct PP_URLComponents_Dev* components))&Pnacl_M17_PPB_URLUtil_Dev_GetPluginInstanceURL
};
+struct PPB_VarDictionary_Dev_0_1 Pnacl_Wrappers_PPB_VarDictionary_Dev_0_1 = {
+ .Create = (struct PP_Var (*)(void))&Pnacl_M27_PPB_VarDictionary_Dev_Create,
+ .Get = (struct PP_Var (*)(struct PP_Var dict, struct PP_Var key))&Pnacl_M27_PPB_VarDictionary_Dev_Get,
+ .Set = (PP_Bool (*)(struct PP_Var dict, struct PP_Var key, struct PP_Var value))&Pnacl_M27_PPB_VarDictionary_Dev_Set,
+ .Delete = (void (*)(struct PP_Var dict, struct PP_Var key))&Pnacl_M27_PPB_VarDictionary_Dev_Delete,
+ .HasKey = (PP_Bool (*)(struct PP_Var dict, struct PP_Var key))&Pnacl_M27_PPB_VarDictionary_Dev_HasKey,
+ .GetKeys = (struct PP_Var (*)(struct PP_Var dict))&Pnacl_M27_PPB_VarDictionary_Dev_GetKeys
+};
+
struct PPB_VideoCapture_Dev_0_2 Pnacl_Wrappers_PPB_VideoCapture_Dev_0_2 = {
.Create = (PP_Resource (*)(PP_Instance instance))&Pnacl_M19_PPB_VideoCapture_Dev_Create,
.IsVideoCapture = (PP_Bool (*)(PP_Resource video_capture))&Pnacl_M19_PPB_VideoCapture_Dev_IsVideoCapture,
@@ -5054,6 +5105,12 @@ static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_URLUtil_Dev_0_6 = {
.real_iface = NULL
};
+static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_VarDictionary_Dev_0_1 = {
+ .iface_macro = PPB_VAR_DICTIONARY_DEV_INTERFACE_0_1,
+ .wrapped_iface = (void *) &Pnacl_Wrappers_PPB_VarDictionary_Dev_0_1,
+ .real_iface = NULL
+};
+
static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_VideoCapture_Dev_0_2 = {
.iface_macro = PPB_VIDEOCAPTURE_DEV_INTERFACE_0_2,
.wrapped_iface = (void *) &Pnacl_Wrappers_PPB_VideoCapture_Dev_0_2,
@@ -5489,6 +5546,7 @@ static struct __PnaclWrapperInfo *s_ppb_wrappers[] = {
&Pnacl_WrapperInfo_PPB_Trace_Event_Dev_0_1,
&Pnacl_WrapperInfo_PPB_TrueTypeFont_Dev_0_1,
&Pnacl_WrapperInfo_PPB_URLUtil_Dev_0_6,
+ &Pnacl_WrapperInfo_PPB_VarDictionary_Dev_0_1,
&Pnacl_WrapperInfo_PPB_VideoCapture_Dev_0_2,
&Pnacl_WrapperInfo_PPB_VideoCapture_Dev_0_3,
&Pnacl_WrapperInfo_PPB_VideoDecoder_Dev_0_16,
diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi
index 6bfb2d9..699ef08 100644
--- a/ppapi/ppapi_shared.gypi
+++ b/ppapi/ppapi_shared.gypi
@@ -24,6 +24,8 @@
'shared_impl/array_writer.h',
'shared_impl/callback_tracker.cc',
'shared_impl/callback_tracker.h',
+ 'shared_impl/dictionary_var.cc',
+ 'shared_impl/dictionary_var.h',
'shared_impl/file_io_state_manager.cc',
'shared_impl/file_io_state_manager.h',
'shared_impl/file_path.cc',
@@ -111,6 +113,8 @@
'shared_impl/var.h',
'shared_impl/var_tracker.cc',
'shared_impl/var_tracker.h',
+ 'shared_impl/var_value_conversions.cc',
+ 'shared_impl/var_value_conversions.h',
# TODO(viettrungluu): Split these out; it won't be used in NaCl.
'shared_impl/private/net_address_private_impl.cc',
'shared_impl/private/net_address_private_impl.h',
@@ -229,6 +233,7 @@
'thunk/ppb_url_response_info_api.h',
'thunk/ppb_url_response_info_thunk.cc',
'thunk/ppb_url_util_thunk.cc',
+ 'thunk/ppb_var_dictionary_thunk.cc',
'thunk/ppb_video_capture_api.h',
'thunk/ppb_video_capture_thunk.cc',
'thunk/ppb_video_decoder_api.h',
diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi
index 185cbb9..73e7a3f 100644
--- a/ppapi/ppapi_sources.gypi
+++ b/ppapi/ppapi_sources.gypi
@@ -77,6 +77,7 @@
'c/dev/ppb_text_input_dev.h',
'c/dev/ppb_truetype_font_dev.h',
'c/dev/ppb_url_util_dev.h',
+ 'c/dev/ppb_var_dictionary_dev.h',
'c/dev/ppb_video_decoder_dev.h',
'c/dev/ppb_widget_dev.h',
'c/dev/ppb_zoom_dev.h',
@@ -243,6 +244,8 @@
'cpp/dev/truetype_font_dev.h',
'cpp/dev/url_util_dev.cc',
'cpp/dev/url_util_dev.h',
+ 'cpp/dev/var_dictionary_dev.cc',
+ 'cpp/dev/var_dictionary_dev.h',
'cpp/dev/video_capture_client_dev.cc',
'cpp/dev/video_capture_client_dev.h',
'cpp/dev/video_capture_dev.cc',
diff --git a/ppapi/ppapi_tests.gypi b/ppapi/ppapi_tests.gypi
index c805ef6..a400e98 100644
--- a/ppapi/ppapi_tests.gypi
+++ b/ppapi/ppapi_tests.gypi
@@ -166,6 +166,7 @@
'shared_impl/time_conversion_unittest.cc',
'shared_impl/tracked_callback_unittest.cc',
'shared_impl/var_tracker_unittest.cc',
+ 'shared_impl/var_value_conversions_unittest.cc',
],
'conditions': [
[ 'os_posix == 1 and OS != "mac" and OS != "android" and OS != "ios"', {
diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc
index 4beeaab..9a4fd20 100644
--- a/ppapi/proxy/interface_list.cc
+++ b/ppapi/proxy/interface_list.cc
@@ -28,6 +28,7 @@
#include "ppapi/c/dev/ppb_truetype_font_dev.h"
#include "ppapi/c/dev/ppb_url_util_dev.h"
#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/dev/ppb_var_dictionary_dev.h"
#include "ppapi/c/dev/ppb_video_capture_dev.h"
#include "ppapi/c/dev/ppb_view_dev.h"
#include "ppapi/c/ppb_audio_config.h"
diff --git a/ppapi/proxy/serialized_var.cc b/ppapi/proxy/serialized_var.cc
index ad416db..5352e8f 100644
--- a/ppapi/proxy/serialized_var.cc
+++ b/ppapi/proxy/serialized_var.cc
@@ -140,7 +140,7 @@ void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
break;
case PP_VARTYPE_ARRAY:
case PP_VARTYPE_DICTIONARY:
- // TODO(brettw) when these are supported, implement this.
+ // TODO(yzshen) when these are supported, implement this.
NOTIMPLEMENTED();
break;
}
@@ -210,7 +210,7 @@ bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m,
break;
case PP_VARTYPE_ARRAY:
case PP_VARTYPE_DICTIONARY:
- // TODO(brettw) when these types are supported, implement this.
+ // TODO(yzshen) when these types are supported, implement this.
NOTIMPLEMENTED();
break;
default:
diff --git a/ppapi/shared_impl/dictionary_var.cc b/ppapi/shared_impl/dictionary_var.cc
new file mode 100644
index 0000000..9bfebb9
--- /dev/null
+++ b/ppapi/shared_impl/dictionary_var.cc
@@ -0,0 +1,101 @@
+// 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/shared_impl/dictionary_var.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/string_util.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/var_tracker.h"
+
+namespace ppapi {
+
+DictionaryVar::DictionaryVar() {
+}
+
+DictionaryVar::~DictionaryVar() {
+}
+
+// static
+DictionaryVar* DictionaryVar::FromPPVar(const PP_Var& var) {
+ if (var.type != PP_VARTYPE_DICTIONARY)
+ return NULL;
+
+ scoped_refptr<Var> var_object(
+ PpapiGlobals::Get()->GetVarTracker()->GetVar(var));
+ if (!var_object.get())
+ return NULL;
+ return var_object->AsDictionaryVar();
+}
+
+DictionaryVar* DictionaryVar::AsDictionaryVar() {
+ return this;
+}
+
+PP_VarType DictionaryVar::GetType() const {
+ return PP_VARTYPE_DICTIONARY;
+}
+
+PP_Var DictionaryVar::Get(const PP_Var& key) const {
+ StringVar* string_var = StringVar::FromPPVar(key);
+ if (!string_var)
+ return PP_MakeUndefined();
+
+ KeyValueMap::const_iterator iter = key_value_map_.find(string_var->value());
+ if (iter != key_value_map_.end()) {
+ if (PpapiGlobals::Get()->GetVarTracker()->AddRefVar(iter->second.get()))
+ return iter->second.get();
+ else
+ return PP_MakeUndefined();
+ } else {
+ return PP_MakeUndefined();
+ }
+}
+
+PP_Bool DictionaryVar::Set(const PP_Var& key, const PP_Var& value) {
+ StringVar* string_var = StringVar::FromPPVar(key);
+ if (!string_var)
+ return PP_FALSE;
+
+ key_value_map_[string_var->value()] = value;
+ return PP_TRUE;
+}
+
+void DictionaryVar::Delete(const PP_Var& key) {
+ StringVar* string_var = StringVar::FromPPVar(key);
+ if (!string_var)
+ return;
+
+ key_value_map_.erase(string_var->value());
+}
+
+PP_Bool DictionaryVar::HasKey(const PP_Var& key) const {
+ StringVar* string_var = StringVar::FromPPVar(key);
+ if (!string_var)
+ return PP_FALSE;
+
+ bool result =
+ key_value_map_.find(string_var->value()) != key_value_map_.end();
+ return PP_FromBool(result);
+}
+
+PP_Var DictionaryVar::GetKeys() const {
+ // TODO(yzshen): Implement once array PP_Var is supported.
+ return PP_MakeNull();
+}
+
+bool DictionaryVar::SetWithStringKey(const std::string& utf8_key,
+ const PP_Var& value) {
+ if (!IsStringUTF8(utf8_key))
+ return false;
+
+ key_value_map_[utf8_key] = value;
+ return true;
+}
+
+void DictionaryVar::DeleteWithStringKey(const std::string& utf8_key) {
+ key_value_map_.erase(utf8_key);
+}
+
+} // namespace ppapi
diff --git a/ppapi/shared_impl/dictionary_var.h b/ppapi/shared_impl/dictionary_var.h
new file mode 100644
index 0000000..cdc63bd
--- /dev/null
+++ b/ppapi/shared_impl/dictionary_var.h
@@ -0,0 +1,63 @@
+// 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.
+
+#ifndef PPAPI_SHARED_IMPL_DICTIONARY_VAR_H_
+#define PPAPI_SHARED_IMPL_DICTIONARY_VAR_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/shared_impl/ppapi_shared_export.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+
+class PPAPI_SHARED_EXPORT DictionaryVar : public Var {
+ public:
+ typedef std::map<std::string, ScopedPPVar> KeyValueMap;
+
+ DictionaryVar();
+
+ // Helper function that converts a PP_Var to a DictionaryVar. This will
+ // return NULL if the PP_Var is not of type PP_VARTYPE_DICTIONARY or the
+ // dictionary cannot be found from the var tracker.
+ static DictionaryVar* FromPPVar(const PP_Var& var);
+
+ // Var overrides.
+ virtual DictionaryVar* AsDictionaryVar() OVERRIDE;
+ virtual PP_VarType GetType() const OVERRIDE;
+
+ // The returned PP_Var has had a ref added on behalf of the caller.
+ PP_Var Get(const PP_Var& key) const;
+ PP_Bool Set(const PP_Var& key, const PP_Var& value);
+ void Delete(const PP_Var& key);
+ PP_Bool HasKey(const PP_Var& key) const;
+ // The returned PP_Var has had a ref added on behalf of the caller.
+ PP_Var GetKeys() const;
+
+ // Returns false and keeps the dictionary unchanged if |key| is not a valid
+ // UTF-8 string.
+ bool SetWithStringKey(const std::string& utf8_key, const PP_Var& value);
+ void DeleteWithStringKey(const std::string& utf8_key);
+
+ const KeyValueMap& key_value_map() const {
+ return key_value_map_;
+ }
+
+ protected:
+ virtual ~DictionaryVar();
+
+ private:
+ KeyValueMap key_value_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(DictionaryVar);
+};
+
+} // namespace ppapi
+
+#endif // PPAPI_SHARED_IMPL_DICTIONARY_VAR_H_
diff --git a/ppapi/shared_impl/scoped_pp_var.cc b/ppapi/shared_impl/scoped_pp_var.cc
index fcd6806..3ae13b0 100644
--- a/ppapi/shared_impl/scoped_pp_var.cc
+++ b/ppapi/shared_impl/scoped_pp_var.cc
@@ -47,4 +47,10 @@ ScopedPPVar& ScopedPPVar::operator=(const PP_Var& v) {
return *this;
}
+PP_Var ScopedPPVar::Release() {
+ PP_Var result = var_;
+ var_ = PP_MakeUndefined();
+ return result;
+}
+
} // namespace ppapi
diff --git a/ppapi/shared_impl/var.cc b/ppapi/shared_impl/var.cc
index 2e63dbe..8870e3e 100644
--- a/ppapi/shared_impl/var.cc
+++ b/ppapi/shared_impl/var.cc
@@ -56,6 +56,12 @@ std::string Var::PPVarToLogString(PP_Var var) {
}
case PP_VARTYPE_OBJECT:
return "[Object]";
+ case PP_VARTYPE_ARRAY:
+ return "[Array]";
+ case PP_VARTYPE_DICTIONARY:
+ return "[Dictionary]";
+ case PP_VARTYPE_ARRAY_BUFFER:
+ return "[Array buffer]";
default:
return "[Invalid var]";
}
@@ -77,6 +83,10 @@ ProxyObjectVar* Var::AsProxyObjectVar() {
return NULL;
}
+DictionaryVar* Var::AsDictionaryVar() {
+ return NULL;
+}
+
PP_Var Var::GetPPVar() {
int32 id = GetOrCreateVarID();
if (!id)
diff --git a/ppapi/shared_impl/var.h b/ppapi/shared_impl/var.h
index 77f707c..76654b4 100644
--- a/ppapi/shared_impl/var.h
+++ b/ppapi/shared_impl/var.h
@@ -15,6 +15,7 @@
namespace ppapi {
class ArrayBufferVar;
+class DictionaryVar;
class NPObjectVar;
class ProxyObjectVar;
class StringVar;
@@ -34,6 +35,7 @@ class PPAPI_SHARED_EXPORT Var : public base::RefCounted<Var> {
virtual ArrayBufferVar* AsArrayBufferVar();
virtual NPObjectVar* AsNPObjectVar();
virtual ProxyObjectVar* AsProxyObjectVar();
+ virtual DictionaryVar* AsDictionaryVar();
// Creates a PP_Var corresponding to this object. The return value will have
// one reference addrefed on behalf of the caller.
diff --git a/ppapi/shared_impl/var_tracker.cc b/ppapi/shared_impl/var_tracker.cc
index 6bc0261..a704c3a 100644
--- a/ppapi/shared_impl/var_tracker.cc
+++ b/ppapi/shared_impl/var_tracker.cc
@@ -90,7 +90,7 @@ bool VarTracker::AddRefVar(const PP_Var& var) {
ProxyLock::AssertAcquired();
if (!IsVarTypeRefcounted(var.type))
- return false;
+ return true;
return AddRefVar(static_cast<int32>(var.value.as_id));
}
diff --git a/ppapi/shared_impl/var_value_conversions.cc b/ppapi/shared_impl/var_value_conversions.cc
new file mode 100644
index 0000000..a54c726
--- /dev/null
+++ b/ppapi/shared_impl/var_value_conversions.cc
@@ -0,0 +1,298 @@
+// 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/shared_impl/var_value_conversions.h"
+
+#include <limits>
+#include <set>
+#include <stack>
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/stl_util.h"
+#include "base/values.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_stdint.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"
+
+namespace ppapi {
+
+namespace {
+
+// In CreateValueFromVar(), a stack is used to keep track of conversion progress
+// of array and dictionary vars. VarNode represents elements of that stack.
+struct VarNode {
+ VarNode(const PP_Var& in_var, base::Value* in_value)
+ : var(in_var),
+ value(in_value),
+ sentinel(false) {
+ }
+
+ // This object doesn't hold a reference to it.
+ PP_Var var;
+ // It is not owned by this object.
+ base::Value* value;
+ // When this is set to true for a node in the stack, it means that we have
+ // finished processing the node itself. However, we keep it in the stack as
+ // a sentinel. When it becomes the top element of the stack again, we know
+ // that we have processed all the descendants of this node.
+ bool sentinel;
+};
+
+// In CreateVarFromValue(), a stack is used to keep track of conversion progress
+// of list and dictionary values. ValueNode represents elements of that stack.
+struct ValueNode {
+ ValueNode(const PP_Var& in_var, const base::Value* in_value)
+ : var(in_var),
+ value(in_value) {
+ }
+
+ // This object doesn't hold a reference to it.
+ PP_Var var;
+ // It is not owned by this object.
+ const base::Value* value;
+};
+
+// Helper function for CreateValueFromVar(). It only looks at |var| but not its
+// descendants. The conversion result is stored in |value|. If |var| is array or
+// dictionary, a new node is pushed onto |state|.
+//
+// Returns false on failure.
+bool CreateValueFromVarHelper(const std::set<int64_t>& parent_ids,
+ const PP_Var& var,
+ scoped_ptr<base::Value>* value,
+ std::stack<VarNode>* state) {
+ switch (var.type) {
+ case PP_VARTYPE_UNDEFINED:
+ case PP_VARTYPE_NULL: {
+ value->reset(base::Value::CreateNullValue());
+ return true;
+ }
+ case PP_VARTYPE_BOOL: {
+ value->reset(new base::FundamentalValue(PP_ToBool(var.value.as_bool)));
+ return true;
+ }
+ case PP_VARTYPE_INT32: {
+ value->reset(new base::FundamentalValue(var.value.as_int));
+ return true;
+ }
+ case PP_VARTYPE_DOUBLE: {
+ value->reset(new base::FundamentalValue(var.value.as_double));
+ return true;
+ }
+ case PP_VARTYPE_STRING: {
+ StringVar* string_var = StringVar::FromPPVar(var);
+ if (!string_var)
+ return false;
+
+ value->reset(new base::StringValue(string_var->value()));
+ return true;
+ }
+ case PP_VARTYPE_OBJECT: {
+ return false;
+ }
+ case PP_VARTYPE_ARRAY: {
+ // TODO(yzshen): Implement it once array var is supported.
+ return false;
+ }
+ case PP_VARTYPE_DICTIONARY: {
+ if (ContainsKey(parent_ids, var.value.as_id)) {
+ // A circular reference is found.
+ return false;
+ }
+
+ value->reset(new base::DictionaryValue());
+ state->push(VarNode(var, value->get()));
+ return true;
+ }
+ case PP_VARTYPE_ARRAY_BUFFER: {
+ ArrayBufferVar* array_buffer = ArrayBufferVar::FromPPVar(var);
+ if (!array_buffer)
+ return false;
+
+ base::BinaryValue* binary_value =
+ base::BinaryValue::CreateWithCopiedBuffer(
+ static_cast<const char*>(array_buffer->Map()),
+ array_buffer->ByteLength());
+ array_buffer->Unmap();
+ value->reset(binary_value);
+ return true;
+ }
+ }
+ NOTREACHED();
+ return false;
+}
+
+// Helper function for CreateVarFromValue(). It only looks at |value| but not
+// its descendants. The conversion result is stored in |var|. If |value| is list
+// or dictionary, a new node is pushed onto |state|.
+//
+// Returns false on failure.
+bool CreateVarFromValueHelper(const base::Value& value,
+ ScopedPPVar* var,
+ std::stack<ValueNode>* state) {
+ switch (value.GetType()) {
+ case base::Value::TYPE_NULL: {
+ *var = PP_MakeNull();
+ return true;
+ }
+ case base::Value::TYPE_BOOLEAN: {
+ bool result = false;
+ if (value.GetAsBoolean(&result)) {
+ *var = PP_MakeBool(PP_FromBool(result));
+ return true;
+ }
+ return false;
+ }
+ case base::Value::TYPE_INTEGER: {
+ int result = 0;
+ if (value.GetAsInteger(&result)) {
+ *var = PP_MakeInt32(result);
+ return true;
+ }
+ return false;
+ }
+ case base::Value::TYPE_DOUBLE: {
+ double result = 0;
+ if (value.GetAsDouble(&result)) {
+ *var = PP_MakeDouble(result);
+ return true;
+ }
+ return false;
+ }
+ case base::Value::TYPE_STRING: {
+ std::string result;
+ if (value.GetAsString(&result)) {
+ *var = ScopedPPVar(ScopedPPVar::PassRef(),
+ StringVar::StringToPPVar(result));
+ return true;
+ }
+ return false;
+ }
+ case base::Value::TYPE_BINARY: {
+ const base::BinaryValue& binary_value =
+ static_cast<const base::BinaryValue&>(value);
+
+ size_t size = binary_value.GetSize();
+ if (size > std::numeric_limits<uint32>::max())
+ return false;
+
+ ScopedPPVar temp(
+ ScopedPPVar::PassRef(),
+ PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
+ static_cast<uint32>(size), binary_value.GetBuffer()));
+ if (temp.get().type == PP_VARTYPE_ARRAY_BUFFER) {
+ *var = temp;
+ return true;
+ }
+ return false;
+ }
+ case base::Value::TYPE_DICTIONARY: {
+ scoped_refptr<DictionaryVar> dict_var(new DictionaryVar());
+ *var = ScopedPPVar(ScopedPPVar::PassRef(), dict_var->GetPPVar());
+ state->push(ValueNode(var->get(), &value));
+ return true;
+ }
+ case base::Value::TYPE_LIST: {
+ // TODO(yzshen): Add support once array var is supported.
+ return false;
+ }
+ }
+ NOTREACHED();
+ return false;
+}
+
+} // namespace
+
+base::Value* CreateValueFromVar(const PP_Var& var) {
+ // Used to detect circular references.
+ std::set<int64_t> parent_ids;
+ std::stack<VarNode> state;
+ scoped_ptr<base::Value> root_value;
+
+ if (!CreateValueFromVarHelper(parent_ids, var, &root_value, &state))
+ return NULL;
+
+ while (!state.empty()) {
+ VarNode& top = state.top();
+ if (top.sentinel) {
+ parent_ids.erase(top.var.value.as_id);
+ state.pop();
+ } else if (top.var.type == PP_VARTYPE_DICTIONARY) {
+ parent_ids.insert(top.var.value.as_id);
+ top.sentinel = true;
+
+ DictionaryVar* dict_var = DictionaryVar::FromPPVar(top.var);
+ if (!dict_var)
+ return NULL;
+
+ DCHECK(top.value->GetType() == base::Value::TYPE_DICTIONARY);
+ base::DictionaryValue* dict_value =
+ static_cast<base::DictionaryValue*>(top.value);
+
+ for (DictionaryVar::KeyValueMap::const_iterator iter =
+ dict_var->key_value_map().begin();
+ iter != dict_var->key_value_map().end();
+ ++iter) {
+ // Skip the key-value pair if the value is undefined.
+ if (iter->second.get().type == PP_VARTYPE_UNDEFINED)
+ continue;
+
+ scoped_ptr<base::Value> child_value;
+ if (!CreateValueFromVarHelper(parent_ids, iter->second.get(),
+ &child_value, &state)) {
+ return NULL;
+ }
+
+ dict_value->SetWithoutPathExpansion(iter->first, child_value.release());
+ }
+ } else {
+ NOTREACHED();
+ return NULL;
+ }
+ }
+ DCHECK(parent_ids.empty());
+ return root_value.release();
+}
+
+PP_Var CreateVarFromValue(const base::Value& value) {
+ std::stack<ValueNode> state;
+ ScopedPPVar root_var;
+
+ if (!CreateVarFromValueHelper(value, &root_var, &state))
+ return PP_MakeUndefined();
+
+ while (!state.empty()) {
+ ValueNode top = state.top();
+ state.pop();
+
+ if (top.value->GetType() == base::Value::TYPE_DICTIONARY) {
+ const base::DictionaryValue* dict_value =
+ static_cast<const base::DictionaryValue*>(top.value);
+ DictionaryVar* dict_var = DictionaryVar::FromPPVar(top.var);
+ DCHECK(dict_var);
+ for (base::DictionaryValue::Iterator iter(*dict_value);
+ !iter.IsAtEnd();
+ iter.Advance()) {
+ ScopedPPVar child_var;
+ if (!CreateVarFromValueHelper(iter.value(), &child_var, &state) ||
+ !dict_var->SetWithStringKey(iter.key(), child_var.get())) {
+ return PP_MakeUndefined();
+ }
+ }
+ } else {
+ NOTREACHED();
+ return PP_MakeUndefined();
+ }
+ }
+
+ return root_var.Release();
+}
+} // namespace ppapi
+
diff --git a/ppapi/shared_impl/var_value_conversions.h b/ppapi/shared_impl/var_value_conversions.h
new file mode 100644
index 0000000..09145ce
--- /dev/null
+++ b/ppapi/shared_impl/var_value_conversions.h
@@ -0,0 +1,41 @@
+// 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.
+
+#ifndef PPAPI_SHARED_IMPL_VAR_VALUE_CONVERSIONS_H_
+#define PPAPI_SHARED_IMPL_VAR_VALUE_CONVERSIONS_H_
+
+#include "ppapi/c/pp_var.h"
+#include "ppapi/shared_impl/ppapi_shared_export.h"
+
+namespace base {
+class Value;
+}
+
+namespace ppapi {
+
+// Converts a PP_Var to a base::Value object. The caller takes ownership of the
+// returned object.
+//
+// Both PP_VARTYPE_UNDEFINED and PP_VARTYPE_NULL are converted to
+// base::Value::TYPE_NULL. In dictionary vars, key-value pairs whose value is
+// undefined (PP_VARTYPE_UNDEFINED) are ignored. If a node in |var| appears more
+// than once, it is duplicated in the result. For example, if |var| is an array
+// and it has two elements pointing to the same dictionary, the resulting list
+// value will have two copies of the dictionary.
+//
+// The conversion fails and returns NULL if
+// - |var| is object (PP_VARTYPE_OBJECT); or
+// - |var| is an array or dictionary, and calling CreateValueFromVar() on any of
+// the array elements or dictionary values fails; or
+// - there exist circular references, i.e., an array or dictionary is its own
+// ancestor/descendant.
+PPAPI_SHARED_EXPORT base::Value* CreateValueFromVar(const PP_Var& var);
+
+// The returned var has been added ref on behalf of the caller.
+// Returns an undefined var if the conversion fails.
+PPAPI_SHARED_EXPORT PP_Var CreateVarFromValue(const base::Value& value);
+
+} // namespace ppapi
+
+#endif // PPAPI_SHARED_IMPL_VAR_VALUE_CONVERSIONS_H_
diff --git a/ppapi/shared_impl/var_value_conversions_unittest.cc b/ppapi/shared_impl/var_value_conversions_unittest.cc
new file mode 100644
index 0000000..d9a2769
--- /dev/null
+++ b/ppapi/shared_impl/var_value_conversions_unittest.cc
@@ -0,0 +1,241 @@
+// 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/shared_impl/var_value_conversions.h"
+
+#include <cmath>
+#include <cstring>
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/shared_impl/dictionary_var.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "ppapi/shared_impl/test_globals.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/shared_impl/var_tracker.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ppapi {
+namespace {
+
+bool Equals(const base::Value& value, const PP_Var& var) {
+ switch (value.GetType()) {
+ case base::Value::TYPE_NULL: {
+ return var.type == PP_VARTYPE_NULL || var.type == PP_VARTYPE_UNDEFINED;
+ }
+ case base::Value::TYPE_BOOLEAN: {
+ bool result = false;
+ return var.type == PP_VARTYPE_BOOL &&
+ value.GetAsBoolean(&result) &&
+ result == PP_ToBool(var.value.as_bool);
+ }
+ case base::Value::TYPE_INTEGER: {
+ int result = 0;
+ return var.type == PP_VARTYPE_INT32 &&
+ value.GetAsInteger(&result) &&
+ result == var.value.as_int;
+ }
+ case base::Value::TYPE_DOUBLE: {
+ double result = 0;
+ return var.type == PP_VARTYPE_DOUBLE &&
+ value.GetAsDouble(&result) &&
+ fabs(result - var.value.as_double) < 1.0e-4;
+ }
+ case base::Value::TYPE_STRING: {
+ std::string result;
+ StringVar* string_var = StringVar::FromPPVar(var);
+ return string_var &&
+ value.GetAsString(&result) &&
+ result == string_var->value();
+ }
+ case base::Value::TYPE_BINARY: {
+ const base::BinaryValue& binary_value =
+ static_cast<const base::BinaryValue&>(value);
+ ArrayBufferVar* array_buffer_var = ArrayBufferVar::FromPPVar(var);
+ if (!array_buffer_var ||
+ binary_value.GetSize() != array_buffer_var->ByteLength()) {
+ return false;
+ }
+
+ bool result = !memcmp(binary_value.GetBuffer(), array_buffer_var->Map(),
+ binary_value.GetSize());
+ array_buffer_var->Unmap();
+ return result;
+ }
+ case base::Value::TYPE_DICTIONARY: {
+ const base::DictionaryValue& dict_value =
+ static_cast<const base::DictionaryValue&>(value);
+ DictionaryVar* dict_var = DictionaryVar::FromPPVar(var);
+ if (!dict_var)
+ return false;
+
+ size_t non_undefined_count = 0;
+ for (DictionaryVar::KeyValueMap::const_iterator iter =
+ dict_var->key_value_map().begin();
+ iter != dict_var->key_value_map().end();
+ ++iter) {
+ if (iter->second.get().type == PP_VARTYPE_UNDEFINED)
+ continue;
+
+ ++non_undefined_count;
+ const base::Value* sub_value = NULL;
+ if (!dict_value.GetWithoutPathExpansion(iter->first, &sub_value) ||
+ !Equals(*sub_value, iter->second.get())) {
+ return false;
+ }
+ }
+ return non_undefined_count == dict_value.size();
+ }
+ case base::Value::TYPE_LIST: {
+ // TODO(yzshen): add support once array var is supported.
+ return false;
+ }
+ }
+ NOTREACHED();
+ return false;
+}
+
+class VarValueConversionsTest : public testing::Test {
+ public:
+ VarValueConversionsTest() {
+ }
+ virtual ~VarValueConversionsTest() {
+ }
+
+ // testing::Test implementation.
+ virtual void SetUp() {
+ ProxyLock::Acquire();
+ }
+ virtual void TearDown() {
+ ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty());
+ ProxyLock::Release();
+ }
+
+ private:
+ TestGlobals globals_;
+};
+
+} // namespace
+
+TEST_F(VarValueConversionsTest, CreateValueFromVar) {
+ {
+ // Var holding a ref to itself is not a valid input.
+ scoped_refptr<DictionaryVar> dict_var_1(new DictionaryVar());
+ ScopedPPVar var_1(ScopedPPVar::PassRef(), dict_var_1->GetPPVar());
+ scoped_refptr<DictionaryVar> dict_var_2(new DictionaryVar());
+ ScopedPPVar var_2(ScopedPPVar::PassRef(), dict_var_2->GetPPVar());
+
+ ASSERT_TRUE(dict_var_1->SetWithStringKey("key_1", var_2.get()));
+ scoped_ptr<base::Value> value(CreateValueFromVar(var_1.get()));
+ ASSERT_TRUE(value.get());
+
+ ASSERT_TRUE(dict_var_2->SetWithStringKey("key_2", var_1.get()));
+ value.reset(CreateValueFromVar(var_1.get()));
+ ASSERT_EQ(NULL, value.get());
+
+ // Make sure |var_1| doesn't indirectly hold a ref to itself, otherwise it
+ // is leaked.
+ dict_var_1->DeleteWithStringKey("key_1");
+ }
+
+ // Vars of null or undefined type are converted to null values.
+ {
+ scoped_ptr<base::Value> value(CreateValueFromVar(PP_MakeNull()));
+ ASSERT_TRUE(value.get());
+ ASSERT_TRUE(Equals(*value, PP_MakeNull()));
+
+ value.reset(CreateValueFromVar(PP_MakeUndefined()));
+ ASSERT_TRUE(value.get());
+ ASSERT_TRUE(Equals(*value, PP_MakeUndefined()));
+ }
+
+ {
+ // Key-value pairs whose value is undefined are ignored.
+ scoped_refptr<DictionaryVar> dict_var(new DictionaryVar());
+ ASSERT_TRUE(dict_var->SetWithStringKey("key_1", PP_MakeUndefined()));
+ ASSERT_TRUE(dict_var->SetWithStringKey("key_2", PP_MakeInt32(1)));
+ ScopedPPVar var(ScopedPPVar::PassRef(), dict_var->GetPPVar());
+
+ scoped_ptr<base::Value> value(CreateValueFromVar(var.get()));
+ ASSERT_TRUE(value.get());
+ ASSERT_TRUE(Equals(*value, var.get()));
+ }
+
+ {
+ // The same PP_Var is allowed to appear multiple times.
+ scoped_refptr<DictionaryVar> dict_var_1(new DictionaryVar());
+ ScopedPPVar dict_pp_var_1(ScopedPPVar::PassRef(), dict_var_1->GetPPVar());
+ scoped_refptr<DictionaryVar> dict_var_2(new DictionaryVar());
+ ScopedPPVar dict_pp_var_2(ScopedPPVar::PassRef(), dict_var_2->GetPPVar());
+ scoped_refptr<StringVar> string_var(new StringVar("string_value"));
+ ScopedPPVar string_pp_var(ScopedPPVar::PassRef(), string_var->GetPPVar());
+
+ ASSERT_TRUE(dict_var_1->SetWithStringKey("key_1", dict_pp_var_2.get()));
+ ASSERT_TRUE(dict_var_1->SetWithStringKey("key_2", dict_pp_var_2.get()));
+ ASSERT_TRUE(dict_var_1->SetWithStringKey("key_3", string_pp_var.get()));
+ ASSERT_TRUE(dict_var_2->SetWithStringKey("key_4", string_pp_var.get()));
+
+ scoped_ptr<base::Value> value(CreateValueFromVar(dict_pp_var_1.get()));
+ ASSERT_TRUE(value.get());
+ ASSERT_TRUE(Equals(*value, dict_pp_var_1.get()));
+ }
+
+ {
+ // Test more complex inputs.
+ scoped_refptr<DictionaryVar> dict_var_1(new DictionaryVar());
+ ScopedPPVar dict_pp_var_1(ScopedPPVar::PassRef(), dict_var_1->GetPPVar());
+ scoped_refptr<DictionaryVar> dict_var_2(new DictionaryVar());
+ ScopedPPVar dict_pp_var_2(ScopedPPVar::PassRef(), dict_var_2->GetPPVar());
+ scoped_refptr<StringVar> string_var(new StringVar("string_value"));
+ ScopedPPVar string_pp_var(ScopedPPVar::PassRef(), string_var->GetPPVar());
+
+ ASSERT_TRUE(dict_var_1->SetWithStringKey("null_key", PP_MakeNull()));
+ ASSERT_TRUE(dict_var_1->SetWithStringKey("string_key",
+ string_pp_var.get()));
+ ASSERT_TRUE(dict_var_1->SetWithStringKey("dict_key", dict_pp_var_2.get()));
+
+ ASSERT_TRUE(dict_var_2->SetWithStringKey("undefined_key",
+ PP_MakeUndefined()));
+ ASSERT_TRUE(dict_var_2->SetWithStringKey("double_key", PP_MakeDouble(1)));
+ ASSERT_TRUE(dict_var_2->SetWithStringKey("int_key", PP_MakeInt32(2)));
+ ASSERT_TRUE(dict_var_2->SetWithStringKey("bool_key", PP_MakeBool(PP_TRUE)));
+
+ scoped_ptr<base::Value> value(CreateValueFromVar(dict_pp_var_1.get()));
+ ASSERT_TRUE(value.get());
+ ASSERT_TRUE(Equals(*value, dict_pp_var_1.get()));
+ }
+
+ {
+ // Test that dictionary keys containing '.' are handled correctly.
+ scoped_refptr<DictionaryVar> dict_var(new DictionaryVar());
+ ScopedPPVar dict_pp_var(ScopedPPVar::PassRef(), dict_var->GetPPVar());
+
+ ASSERT_TRUE(dict_var->SetWithStringKey("double.key", PP_MakeDouble(1)));
+ ASSERT_TRUE(dict_var->SetWithStringKey("int.key..name", PP_MakeInt32(2)));
+
+ scoped_ptr<base::Value> value(CreateValueFromVar(dict_pp_var.get()));
+ ASSERT_TRUE(value.get());
+ ASSERT_TRUE(Equals(*value, dict_pp_var.get()));
+ }
+}
+
+TEST_F(VarValueConversionsTest, CreateVarFromValue) {
+ base::DictionaryValue dict_value;
+ dict_value.Set("null_key", base::Value::CreateNullValue());
+ dict_value.SetString("string_key", "string_value");
+ dict_value.SetDouble("dict_key.double_key", 1);
+ dict_value.SetInteger("dict_key.int_key", 2);
+ dict_value.SetBoolean("dict_key.bool_key", true);
+
+ ScopedPPVar var(ScopedPPVar::PassRef(), CreateVarFromValue(dict_value));
+ ASSERT_TRUE(Equals(dict_value, var.get()));
+}
+
+} // namespace ppapi
diff --git a/ppapi/tests/all_c_includes.h b/ppapi/tests/all_c_includes.h
index 7d7a690..1f004d9 100644
--- a/ppapi/tests/all_c_includes.h
+++ b/ppapi/tests/all_c_includes.h
@@ -32,6 +32,7 @@
#include "ppapi/c/dev/ppb_truetype_font_dev.h"
#include "ppapi/c/dev/ppb_url_util_dev.h"
#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/dev/ppb_var_dictionary_dev.h"
#include "ppapi/c/dev/ppb_video_decoder_dev.h"
#include "ppapi/c/dev/ppb_view_dev.h"
#include "ppapi/c/dev/ppb_widget_dev.h"
diff --git a/ppapi/tests/all_cpp_includes.h b/ppapi/tests/all_cpp_includes.h
index e00e53a..6f643ad 100644
--- a/ppapi/tests/all_cpp_includes.h
+++ b/ppapi/tests/all_cpp_includes.h
@@ -29,6 +29,7 @@
#include "ppapi/cpp/dev/selection_dev.h"
#include "ppapi/cpp/dev/text_input_dev.h"
#include "ppapi/cpp/dev/url_util_dev.h"
+#include "ppapi/cpp/dev/var_dictionary_dev.h"
#include "ppapi/cpp/dev/video_decoder_dev.h"
#include "ppapi/cpp/dev/view_dev.h"
#include "ppapi/cpp/dev/widget_client_dev.h"
diff --git a/ppapi/thunk/interfaces_ppb_public_dev.h b/ppapi/thunk/interfaces_ppb_public_dev.h
index d0570d9..27f3b9c 100644
--- a/ppapi/thunk/interfaces_ppb_public_dev.h
+++ b/ppapi/thunk/interfaces_ppb_public_dev.h
@@ -30,6 +30,8 @@ PROXIED_IFACE(PPB_Instance, PPB_TEXTINPUT_DEV_INTERFACE_0_2,
PPB_TextInput_Dev_0_2)
PROXIED_IFACE(NoAPIName, PPB_TRUETYPEFONT_DEV_INTERFACE_0_1,
PPB_TrueTypeFont_Dev_0_1)
+PROXIED_IFACE(NoAPIName, PPB_VAR_DICTIONARY_DEV_INTERFACE_0_1,
+ PPB_VarDictionary_Dev_0_1)
PROXIED_IFACE(NoAPIName, PPB_VIEW_DEV_INTERFACE_0_1,
PPB_View_Dev_0_1)
UNPROXIED_IFACE(PPB_Instance, PPB_ZOOM_DEV_INTERFACE_0_2, PPB_Zoom_Dev_0_2)
diff --git a/ppapi/thunk/ppb_var_dictionary_thunk.cc b/ppapi/thunk/ppb_var_dictionary_thunk.cc
new file mode 100644
index 0000000..25a8224
--- /dev/null
+++ b/ppapi/thunk/ppb_var_dictionary_thunk.cc
@@ -0,0 +1,86 @@
+// 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/c/dev/ppb_var_dictionary_dev.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/shared_impl/dictionary_var.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace ppapi {
+namespace thunk {
+
+namespace {
+
+PP_Var Create() {
+ ProxyAutoLock lock;
+
+ // Var tracker will hold a reference to this object.
+ DictionaryVar* var = new DictionaryVar();
+ return var->GetPPVar();
+}
+
+PP_Var Get(PP_Var dict, PP_Var key) {
+ ProxyAutoLock lock;
+
+ DictionaryVar* dict_var = DictionaryVar::FromPPVar(dict);
+ if (!dict_var)
+ return PP_MakeUndefined();
+ return dict_var->Get(key);
+}
+
+PP_Bool Set(PP_Var dict, PP_Var key, PP_Var value) {
+ ProxyAutoLock lock;
+
+ DictionaryVar* dict_var = DictionaryVar::FromPPVar(dict);
+ if (!dict_var)
+ return PP_FALSE;
+
+ return dict_var->Set(key, value);
+}
+
+void Delete(PP_Var dict, PP_Var key) {
+ ProxyAutoLock lock;
+
+ DictionaryVar* dict_var = DictionaryVar::FromPPVar(dict);
+ if (dict_var)
+ dict_var->Delete(key);
+}
+
+PP_Bool HasKey(PP_Var dict, PP_Var key) {
+ ProxyAutoLock lock;
+
+ DictionaryVar* dict_var = DictionaryVar::FromPPVar(dict);
+ if (!dict_var)
+ return PP_FALSE;
+ return dict_var->HasKey(key);
+}
+
+PP_Var GetKeys(PP_Var dict) {
+ ProxyAutoLock lock;
+
+ DictionaryVar* dict_var = DictionaryVar::FromPPVar(dict);
+ if (!dict_var)
+ return PP_MakeNull();
+ return dict_var->GetKeys();
+}
+
+const PPB_VarDictionary_Dev_0_1 g_ppb_vardictionary_0_1_thunk = {
+ &Create,
+ &Get,
+ &Set,
+ &Delete,
+ &HasKey,
+ &GetKeys
+};
+
+} // namespace
+
+const PPB_VarDictionary_Dev_0_1* GetPPB_VarDictionary_Dev_0_1_Thunk() {
+ return &g_ppb_vardictionary_0_1_thunk;
+}
+
+} // namespace thunk
+} // namespace ppapi
diff --git a/webkit/plugins/ppapi/plugin_module.cc b/webkit/plugins/ppapi/plugin_module.cc
index 983c11d..4a9735c 100644
--- a/webkit/plugins/ppapi/plugin_module.cc
+++ b/webkit/plugins/ppapi/plugin_module.cc
@@ -36,6 +36,7 @@
#include "ppapi/c/dev/ppb_truetype_font_dev.h"
#include "ppapi/c/dev/ppb_url_util_dev.h"
#include "ppapi/c/dev/ppb_var_deprecated.h"
+#include "ppapi/c/dev/ppb_var_dictionary_dev.h"
#include "ppapi/c/dev/ppb_video_capture_dev.h"
#include "ppapi/c/dev/ppb_video_decoder_dev.h"
#include "ppapi/c/dev/ppb_view_dev.h"