libweave: Add more Get methods into weave::Command
Added GetID, GetName, GetCategory, GetStatus, GetOrigin, GetParameters,
GetProgress and GetResults methods.
base::DictionaryValue is used as type for complex values.
D-Bus related utilities extracted from schema_utils.* into
dbus_conversion.* files. They will be move out of libweave in future.
BUG=brillo:1245
TEST='FEATURES=test emerge-gizmo buffet'
Change-Id: Iec16b5a820a0a4da8eeef34b73378b35fdc4e638
Reviewed-on: https://chromium-review.googlesource.com/287594
Reviewed-by: Vitaly Buka <vitalybuka@chromium.org>
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
Tested-by: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/buffet/buffet.gyp b/buffet/buffet.gyp
index ca9a11d..ee41d23 100644
--- a/buffet/buffet.gyp
+++ b/buffet/buffet.gyp
@@ -39,6 +39,7 @@
'../libweave/src/commands/command_queue.cc',
'../libweave/src/commands/dbus_command_dispatcher.cc',
'../libweave/src/commands/dbus_command_proxy.cc',
+ '../libweave/src/commands/dbus_conversion.cc',
'../libweave/src/commands/object_schema.cc',
'../libweave/src/commands/prop_constraints.cc',
'../libweave/src/commands/prop_types.cc',
diff --git a/libweave/include/weave/command.h b/libweave/include/weave/command.h
index c27b49d..4a3af6b 100644
--- a/libweave/include/weave/command.h
+++ b/libweave/include/weave/command.h
@@ -5,8 +5,9 @@
#ifndef LIBWEAVE_INCLUDE_WEAVE_COMMAND_H_
#define LIBWEAVE_INCLUDE_WEAVE_COMMAND_H_
+#include <string>
+
#include <base/values.h>
-#include <chromeos/errors/error.h>
namespace weave {
@@ -23,13 +24,38 @@
virtual void OnCommandDestroyed() = 0;
};
- // Returns JSON representation of the command.
- virtual std::unique_ptr<base::DictionaryValue> ToJson() const = 0;
-
// Adds an observer for this command. The observer object is not owned by this
// class.
virtual void AddObserver(Observer* observer) = 0;
+ // Returns the full command ID.
+ virtual const std::string& GetID() const = 0;
+
+ // Returns the full name of the command.
+ virtual const std::string& GetName() const = 0;
+
+ // Returns the command category.
+ virtual const std::string& GetCategory() const = 0;
+
+ // Returns the command status.
+ // TODO(vitalybuka): Status should be enum.
+ virtual const std::string& GetStatus() const = 0;
+
+ // Returns the origin of the command.
+ virtual const std::string& GetOrigin() const = 0;
+
+ // Returns the command parameters.
+ virtual std::unique_ptr<base::DictionaryValue> GetParameters() const = 0;
+
+ // Returns the command progress.
+ virtual std::unique_ptr<base::DictionaryValue> GetProgress() const = 0;
+
+ // Returns the command results.
+ virtual std::unique_ptr<base::DictionaryValue> GetResults() const = 0;
+
+ // Returns JSON representation of the command.
+ virtual std::unique_ptr<base::DictionaryValue> ToJson() const = 0;
+
protected:
virtual ~Command() = default;
};
diff --git a/libweave/src/base_api_handler.cc b/libweave/src/base_api_handler.cc
index e6f9f9c..5e3f559 100644
--- a/libweave/src/base_api_handler.cc
+++ b/libweave/src/base_api_handler.cc
@@ -11,43 +11,6 @@
namespace weave {
-namespace {
-
-// Helps to get parameters from ValueMap representing
-// CommandInstance parameters.
-class ParametersReader final {
- public:
- explicit ParametersReader(const ValueMap* parameters)
- : parameters_{parameters} {}
-
- bool GetParameter(const std::string& name, std::string* value) const {
- auto it = parameters_->find(name);
- if (it == parameters_->end())
- return false;
- const StringValue* string_value = it->second->GetString();
- if (!string_value)
- return false;
- *value = string_value->GetValue();
- return true;
- }
-
- bool GetParameter(const std::string& name, bool* value) const {
- auto it = parameters_->find(name);
- if (it == parameters_->end())
- return false;
- const BooleanValue* bool_value = it->second->GetBoolean();
- if (!bool_value)
- return false;
- *value = bool_value->GetValue();
- return true;
- }
-
- private:
- const ValueMap* parameters_;
-};
-
-} // namespace
-
BaseApiHandler::BaseApiHandler(
const base::WeakPtr<DeviceRegistrationInfo>& device_info,
const std::shared_ptr<StateManager>& state_manager,
@@ -76,11 +39,10 @@
bool discovery_enabled{config.local_discovery_enabled()};
bool pairing_enabled{config.local_pairing_enabled()};
- ParametersReader parameters{&command->GetParameters()};
- parameters.GetParameter("localAnonymousAccessMaxRole",
- &anonymous_access_role);
- parameters.GetParameter("localDiscoveryEnabled", &discovery_enabled);
- parameters.GetParameter("localPairingEnabled", &pairing_enabled);
+ auto parameters = command->GetParameters();
+ parameters->GetString("localAnonymousAccessMaxRole", &anonymous_access_role);
+ parameters->GetBoolean("localDiscoveryEnabled", &discovery_enabled);
+ parameters->GetBoolean("localPairingEnabled", &pairing_enabled);
chromeos::VariantDictionary state{
{"base.localAnonymousAccessMaxRole", anonymous_access_role},
@@ -107,10 +69,10 @@
std::string description{config.description()};
std::string location{config.location()};
- ParametersReader parameters(&command->GetParameters());
- parameters.GetParameter("name", &name);
- parameters.GetParameter("description", &description);
- parameters.GetParameter("location", &location);
+ auto parameters = command->GetParameters();
+ parameters->GetString("name", &name);
+ parameters->GetString("description", &description);
+ parameters->GetString("location", &location);
if (!device_info_->UpdateDeviceInfo(name, description, location, nullptr)) {
return command->Abort();
diff --git a/libweave/src/commands/cloud_command_proxy.cc b/libweave/src/commands/cloud_command_proxy.cc
index cc4d64f..70430c7 100644
--- a/libweave/src/commands/cloud_command_proxy.cc
+++ b/libweave/src/commands/cloud_command_proxy.cc
@@ -31,8 +31,8 @@
void CloudCommandProxy::OnResultsChanged() {
std::unique_ptr<base::DictionaryValue> patch{new base::DictionaryValue};
- auto json = TypedValueToJson(command_instance_->GetResults(), nullptr);
- patch->Set(commands::attributes::kCommand_Results, json.release());
+ patch->Set(commands::attributes::kCommand_Results,
+ command_instance_->GetResults().release());
QueueCommandUpdate(std::move(patch));
}
@@ -45,8 +45,8 @@
void CloudCommandProxy::OnProgressChanged() {
std::unique_ptr<base::DictionaryValue> patch{new base::DictionaryValue};
- auto json = TypedValueToJson(command_instance_->GetProgress(), nullptr);
- patch->Set(commands::attributes::kCommand_Progress, json.release());
+ patch->Set(commands::attributes::kCommand_Progress,
+ command_instance_->GetProgress().release());
QueueCommandUpdate(std::move(patch));
}
diff --git a/libweave/src/commands/command_instance.cc b/libweave/src/commands/command_instance.cc
index 2975937..5782695 100644
--- a/libweave/src/commands/command_instance.cc
+++ b/libweave/src/commands/command_instance.cc
@@ -42,13 +42,36 @@
observer->OnCommandDestroyed();
}
+const std::string& CommandInstance::GetID() const {
+ return id_;
+}
+
+const std::string& CommandInstance::GetName() const {
+ return name_;
+}
+
const std::string& CommandInstance::GetCategory() const {
return command_definition_->GetCategory();
}
-const PropValue* CommandInstance::FindParameter(const std::string& name) const {
- auto p = parameters_.find(name);
- return (p != parameters_.end()) ? p->second.get() : nullptr;
+const std::string& CommandInstance::GetStatus() const {
+ return status_;
+}
+
+const std::string& CommandInstance::GetOrigin() const {
+ return origin_;
+}
+
+std::unique_ptr<base::DictionaryValue> CommandInstance::GetParameters() const {
+ return TypedValueToJson(parameters_, nullptr);
+}
+
+std::unique_ptr<base::DictionaryValue> CommandInstance::GetProgress() const {
+ return TypedValueToJson(progress_, nullptr);
+}
+
+std::unique_ptr<base::DictionaryValue> CommandInstance::GetResults() const {
+ return TypedValueToJson(results_, nullptr);
}
namespace {
diff --git a/libweave/src/commands/command_instance.h b/libweave/src/commands/command_instance.h
index 358cd52..0fdc643 100644
--- a/libweave/src/commands/command_instance.h
+++ b/libweave/src/commands/command_instance.h
@@ -42,22 +42,14 @@
// Command overrides.
std::unique_ptr<base::DictionaryValue> ToJson() const override;
void AddObserver(Observer* observer) override;
-
- // Returns the full command ID.
- const std::string& GetID() const { return id_; }
- // Returns the full name of the command.
- const std::string& GetName() const { return name_; }
- // Returns the command category.
- const std::string& GetCategory() const;
- // Returns the command parameters and their values.
- const ValueMap& GetParameters() const { return parameters_; }
- // Returns the command results and their values.
- const ValueMap& GetResults() const { return results_; }
- // Finds a command parameter value by parameter |name|. If the parameter
- // with given name does not exist, returns nullptr.
- const PropValue* FindParameter(const std::string& name) const;
- // Returns the full name of the command.
- const std::string& GetOrigin() const { return origin_; }
+ const std::string& GetID() const override;
+ const std::string& GetName() const override;
+ const std::string& GetCategory() const override;
+ const std::string& GetStatus() const override;
+ const std::string& GetOrigin() const override;
+ std::unique_ptr<base::DictionaryValue> GetParameters() const override;
+ std::unique_ptr<base::DictionaryValue> GetProgress() const override;
+ std::unique_ptr<base::DictionaryValue> GetResults() const override;
// Returns command definition.
const CommandDefinition* GetCommandDefinition() const {
@@ -100,10 +92,6 @@
// Marks the command as completed successfully.
void Done();
- // Command state getters.
- const ValueMap& GetProgress() const { return progress_; }
- const std::string& GetStatus() const { return status_; }
-
// Values for command execution status.
static const char kStatusQueued[];
static const char kStatusInProgress[];
diff --git a/libweave/src/commands/command_instance_unittest.cc b/libweave/src/commands/command_instance_unittest.cc
index 9d2c019..9fbe315 100644
--- a/libweave/src/commands/command_instance_unittest.cc
+++ b/libweave/src/commands/command_instance_unittest.cc
@@ -85,12 +85,9 @@
EXPECT_EQ("robot.speak", instance.GetName());
EXPECT_EQ("robotd", instance.GetCategory());
EXPECT_EQ("cloud", instance.GetOrigin());
- EXPECT_EQ(params, instance.GetParameters());
- EXPECT_EQ("iPityDaFool",
- instance.FindParameter("phrase")->GetString()->GetValue());
- EXPECT_EQ(5, instance.FindParameter("volume")->GetInt()->GetValue());
- EXPECT_EQ(nullptr, instance.FindParameter("blah"));
- EXPECT_EQ(results, instance.GetResults());
+ EXPECT_JSON_EQ("{'phrase': 'iPityDaFool', 'volume': 5}",
+ *instance.GetParameters());
+ EXPECT_JSON_EQ("{'foo': 239}", *instance.GetResults());
CommandInstance instance2{
"base.reboot", "local", dict_.FindCommand("base.reboot"), {}};
@@ -121,9 +118,8 @@
EXPECT_EQ("abcd", instance->GetID());
EXPECT_EQ("robot.jump", instance->GetName());
EXPECT_EQ("robotd", instance->GetCategory());
- EXPECT_EQ(53, instance->FindParameter("height")->GetInt()->GetValue());
- EXPECT_EQ("_withKick",
- instance->FindParameter("_jumpType")->GetString()->GetValue());
+ EXPECT_JSON_EQ("{'height': 53, '_jumpType': '_withKick'}",
+ *instance->GetParameters());
}
TEST_F(CommandInstanceTest, FromJson_ParamsOmitted) {
@@ -132,7 +128,7 @@
CommandInstance::FromJson(json.get(), "cloud", dict_, nullptr, nullptr);
EXPECT_EQ("base.reboot", instance->GetName());
EXPECT_EQ("robotd", instance->GetCategory());
- EXPECT_TRUE(instance->GetParameters().empty());
+ EXPECT_JSON_EQ("{}", *instance->GetParameters());
}
TEST_F(CommandInstanceTest, FromJson_NotObject) {
diff --git a/libweave/src/commands/dbus_command_dispatcher_unittest.cc b/libweave/src/commands/dbus_command_dispatcher_unittest.cc
index c488d92..b91d24f 100644
--- a/libweave/src/commands/dbus_command_dispatcher_unittest.cc
+++ b/libweave/src/commands/dbus_command_dispatcher_unittest.cc
@@ -148,7 +148,7 @@
ValueMap progress{{"progress", unittests::make_int_prop_value(50)}};
SetProgress(command_proxy, progress);
EXPECT_EQ(CommandInstance::kStatusInProgress, command_instance->GetStatus());
- EXPECT_EQ(progress, command_instance->GetProgress());
+ EXPECT_JSON_EQ("{'progress': 50}", *command_instance->GetProgress());
// Command must be removed from the queue and proxy destroyed after calling
// FinishCommand().
@@ -183,7 +183,7 @@
ValueMap progress{};
SetProgress(command_proxy, progress);
EXPECT_EQ(CommandInstance::kStatusInProgress, command_instance->GetStatus());
- EXPECT_EQ(progress, command_instance->GetProgress());
+ EXPECT_JSON_EQ("{}", *command_instance->GetProgress());
// Command must be removed from the queue and proxy destroyed after calling
// FinishCommand().
diff --git a/libweave/src/commands/dbus_command_proxy.cc b/libweave/src/commands/dbus_command_proxy.cc
index 5ffcd9d..aadf781 100644
--- a/libweave/src/commands/dbus_command_proxy.cc
+++ b/libweave/src/commands/dbus_command_proxy.cc
@@ -36,13 +36,12 @@
dbus_adaptor_.SetId(command_instance_->GetID());
dbus_adaptor_.SetStatus(command_instance_->GetStatus());
dbus_adaptor_.SetProgress(
- ObjectToDBusVariant(command_instance_->GetProgress()));
+ DictionaryToDBusVariantDictionary(*command_instance_->GetProgress()));
dbus_adaptor_.SetOrigin(command_instance_->GetOrigin());
-
dbus_adaptor_.SetParameters(
- ObjectToDBusVariant(command_instance_->GetParameters()));
+ DictionaryToDBusVariantDictionary(*command_instance_->GetParameters()));
dbus_adaptor_.SetResults(
- ObjectToDBusVariant(command_instance_->GetResults()));
+ DictionaryToDBusVariantDictionary(*command_instance_->GetResults()));
// Register the command DBus object and expose its methods and properties.
dbus_object_.RegisterAsync(completion_callback);
@@ -50,7 +49,7 @@
void DBusCommandProxy::OnResultsChanged() {
dbus_adaptor_.SetResults(
- ObjectToDBusVariant(command_instance_->GetResults()));
+ DictionaryToDBusVariantDictionary(*command_instance_->GetResults()));
}
void DBusCommandProxy::OnStatusChanged() {
@@ -59,7 +58,7 @@
void DBusCommandProxy::OnProgressChanged() {
dbus_adaptor_.SetProgress(
- ObjectToDBusVariant(command_instance_->GetProgress()));
+ DictionaryToDBusVariantDictionary(*command_instance_->GetProgress()));
}
void DBusCommandProxy::OnCommandDestroyed() {
diff --git a/libweave/src/commands/dbus_command_proxy_unittest.cc b/libweave/src/commands/dbus_command_proxy_unittest.cc
index ed51387..a289cad 100644
--- a/libweave/src/commands/dbus_command_proxy_unittest.cc
+++ b/libweave/src/commands/dbus_command_proxy_unittest.cc
@@ -6,6 +6,7 @@
#include <functional>
#include <memory>
+#include <vector>
#include <dbus/mock_bus.h>
#include <dbus/mock_exported_object.h>
@@ -70,6 +71,12 @@
},
'bar': {
'type': 'string'
+ },
+ 'resultList': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'integer'
+ }
}
},
'progress': {
@@ -177,11 +184,25 @@
TEST_F(DBusCommandProxyTest, SetResults) {
EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
- const VariantDictionary results = {
- {"foo", int32_t{42}}, {"bar", std::string{"foobar"}},
- };
+ VariantDictionary results = {{"foo", int32_t{42}},
+ {"bar", std::string{"foobar"}},
+ {"resultList", std::vector<int>{1, 2, 3}}};
EXPECT_TRUE(GetCommandInterface()->SetResults(nullptr, results));
EXPECT_EQ(results, GetCommandAdaptor()->GetResults());
+ auto list = chromeos::GetVariantValueOrDefault<std::vector<int>>(
+ GetCommandAdaptor()->GetResults(), "resultList");
+ EXPECT_EQ((std::vector<int>{1, 2, 3}), list);
+}
+
+TEST_F(DBusCommandProxyTest, SetResults_WithEmptyList) {
+ EXPECT_CALL(*mock_exported_object_command_, SendSignal(_)).Times(1);
+ VariantDictionary results = {{"foo", int32_t{42}},
+ {"bar", std::string{"foobar"}},
+ {"resultList", std::vector<int>{}}};
+ EXPECT_TRUE(GetCommandInterface()->SetResults(nullptr, results));
+ auto list = chromeos::GetVariantValueOrDefault<std::vector<int>>(
+ GetCommandAdaptor()->GetResults(), "resultList");
+ EXPECT_EQ(std::vector<int>(), list);
}
TEST_F(DBusCommandProxyTest, SetResults_UnknownProperty) {
diff --git a/libweave/src/commands/dbus_conversion.cc b/libweave/src/commands/dbus_conversion.cc
new file mode 100644
index 0000000..146a46d
--- /dev/null
+++ b/libweave/src/commands/dbus_conversion.cc
@@ -0,0 +1,243 @@
+// Copyright 2015 The Chromium OS 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 "libweave/src/commands/dbus_conversion.h"
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "libweave/src/commands/object_schema.h"
+#include "libweave/src/commands/prop_types.h"
+#include "libweave/src/commands/prop_values.h"
+
+namespace weave {
+
+namespace {
+
+// Helpers for JsonToAny().
+template <typename T>
+chromeos::Any ValueToAny(const base::Value& json,
+ bool (base::Value::*fnc)(T*) const) {
+ T val;
+ CHECK((json.*fnc)(&val));
+ return val;
+}
+
+template <typename T>
+chromeos::Any ListToAny(const base::ListValue& list);
+
+// Converts a JSON value into an Any so it can be sent over D-Bus using
+// UpdateState D-Bus method from Buffet.
+chromeos::Any ValueToAny(const base::Value& json) {
+ chromeos::Any prop_value;
+ switch (json.GetType()) {
+ case base::Value::TYPE_NULL:
+ prop_value = nullptr;
+ break;
+ case base::Value::TYPE_BOOLEAN:
+ prop_value = ValueToAny<bool>(json, &base::Value::GetAsBoolean);
+ break;
+ case base::Value::TYPE_INTEGER:
+ prop_value = ValueToAny<int>(json, &base::Value::GetAsInteger);
+ break;
+ case base::Value::TYPE_DOUBLE:
+ prop_value = ValueToAny<double>(json, &base::Value::GetAsDouble);
+ break;
+ case base::Value::TYPE_STRING:
+ prop_value = ValueToAny<std::string>(json, &base::Value::GetAsString);
+ break;
+ case base::Value::TYPE_BINARY:
+ LOG(FATAL) << "Binary values should not happen";
+ break;
+ case base::Value::TYPE_DICTIONARY: {
+ const base::DictionaryValue* dict = nullptr;
+ CHECK(json.GetAsDictionary(&dict));
+ prop_value = DictionaryToDBusVariantDictionary(*dict);
+ break;
+ }
+ case base::Value::TYPE_LIST: {
+ const base::ListValue* list = nullptr;
+ CHECK(json.GetAsList(&list));
+ if (list->empty()) {
+ prop_value = ListToAny<chromeos::Any>(*list);
+ break;
+ }
+ auto type = (*list->begin())->GetType();
+ for (const base::Value* v : *list)
+ CHECK_EQ(v->GetType(), type);
+
+ switch (type) {
+ case base::Value::TYPE_BOOLEAN:
+ prop_value = ListToAny<bool>(*list);
+ break;
+ case base::Value::TYPE_INTEGER:
+ prop_value = ListToAny<int>(*list);
+ break;
+ case base::Value::TYPE_DOUBLE:
+ prop_value = ListToAny<double>(*list);
+ break;
+ case base::Value::TYPE_STRING:
+ prop_value = ListToAny<std::string>(*list);
+ break;
+ case base::Value::TYPE_DICTIONARY:
+ prop_value = ListToAny<chromeos::VariantDictionary>(*list);
+ break;
+ default:
+ LOG(FATAL) << "Unsupported JSON value type for list element: "
+ << (*list->begin())->GetType();
+ }
+ break;
+ }
+ default:
+ LOG(FATAL) << "Unexpected JSON value type: " << json.GetType();
+ break;
+ }
+ return prop_value;
+}
+
+template <typename T>
+chromeos::Any ListToAny(const base::ListValue& list) {
+ std::vector<T> val;
+ val.reserve(list.GetSize());
+ for (const base::Value* v : list)
+ val.push_back(ValueToAny(*v).Get<T>());
+ return val;
+}
+
+bool ErrorMissingProperty(chromeos::ErrorPtr* error,
+ const tracked_objects::Location& location,
+ const char* param_name) {
+ chromeos::Error::AddToPrintf(error, location, errors::commands::kDomain,
+ errors::commands::kPropertyMissing,
+ "Required parameter missing: %s", param_name);
+ return false;
+}
+
+} // namespace
+
+chromeos::Any PropValueToDBusVariant(const PropValue* value) {
+ if (value->GetType() == ValueType::Object)
+ return ObjectToDBusVariant(value->GetObject()->GetValue());
+
+ if (value->GetType() == ValueType::Array) {
+ const PropType* item_type =
+ value->GetPropType()->GetArray()->GetItemTypePtr();
+ return item_type->ConvertArrayToDBusVariant(value->GetArray()->GetValue());
+ }
+ return value->GetValueAsAny();
+}
+
+chromeos::VariantDictionary ObjectToDBusVariant(const ValueMap& object) {
+ chromeos::VariantDictionary dict;
+ for (const auto& pair : object) {
+ // Since we are inserting the elements from ValueMap which is
+ // a map, the keys are already sorted. So use the "end()" position as a hint
+ // for dict.insert() so the destination map can optimize its insertion
+ // time.
+ chromeos::Any prop = PropValueToDBusVariant(pair.second.get());
+ dict.emplace_hint(dict.end(), pair.first, std::move(prop));
+ }
+ return dict;
+}
+
+std::unique_ptr<const PropValue> PropValueFromDBusVariant(
+ const PropType* type,
+ const chromeos::Any& value,
+ chromeos::ErrorPtr* error) {
+ std::unique_ptr<const PropValue> result;
+ if (type->GetType() == ValueType::Array) {
+ // Special case for array types.
+ // We expect the |value| to contain std::vector<T>, while PropValue must use
+ // ValueVector instead. Do the conversion.
+ ValueVector arr;
+ const PropType* item_type = type->GetArray()->GetItemTypePtr();
+ if (item_type->ConvertDBusVariantToArray(value, &arr, error))
+ result = type->CreateValue(arr, error);
+ } else if (type->GetType() == ValueType::Object) {
+ // Special case for object types.
+ // We expect the |value| to contain chromeos::VariantDictionary, while
+ // PropValue must use ValueMap instead. Do the conversion.
+ if (!value.IsTypeCompatible<chromeos::VariantDictionary>()) {
+ type->GenerateErrorValueTypeMismatch(error);
+ return result;
+ }
+ CHECK(nullptr != type->GetObject()->GetObjectSchemaPtr())
+ << "An object type must have a schema defined for it";
+ ValueMap obj;
+ if (!ObjectFromDBusVariant(type->GetObject()->GetObjectSchemaPtr(),
+ value.Get<chromeos::VariantDictionary>(), &obj,
+ error)) {
+ return result;
+ }
+
+ result = type->CreateValue(std::move(obj), error);
+ } else {
+ result = type->CreateValue(value, error);
+ }
+
+ return result;
+}
+
+bool ObjectFromDBusVariant(const ObjectSchema* object_schema,
+ const chromeos::VariantDictionary& dict,
+ ValueMap* obj,
+ chromeos::ErrorPtr* error) {
+ std::set<std::string> keys_processed;
+ obj->clear();
+ // First go over all object parameters defined by type's object schema and
+ // extract the corresponding parameters from the source dictionary.
+ for (const auto& pair : object_schema->GetProps()) {
+ const PropValue* def_value = pair.second->GetDefaultValue();
+ auto it = dict.find(pair.first);
+ if (it != dict.end()) {
+ const PropType* prop_type = pair.second.get();
+ CHECK(prop_type) << "Value property type must be available";
+ auto prop_value = PropValueFromDBusVariant(prop_type, it->second, error);
+ if (!prop_value) {
+ chromeos::Error::AddToPrintf(
+ error, FROM_HERE, errors::commands::kDomain,
+ errors::commands::kInvalidPropValue,
+ "Invalid value for property '%s'", pair.first.c_str());
+ return false;
+ }
+ obj->emplace_hint(obj->end(), pair.first, std::move(prop_value));
+ } else if (def_value) {
+ obj->emplace_hint(obj->end(), pair.first, def_value->Clone());
+ } else {
+ ErrorMissingProperty(error, FROM_HERE, pair.first.c_str());
+ return false;
+ }
+ keys_processed.insert(pair.first);
+ }
+
+ // Make sure that we processed all the necessary properties and there weren't
+ // any extra (unknown) ones specified, unless the schema allows them.
+ if (!object_schema->GetExtraPropertiesAllowed()) {
+ for (const auto& pair : dict) {
+ if (keys_processed.find(pair.first) == keys_processed.end()) {
+ chromeos::Error::AddToPrintf(
+ error, FROM_HERE, errors::commands::kDomain,
+ errors::commands::kUnknownProperty, "Unrecognized property '%s'",
+ pair.first.c_str());
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+// TODO(vitalybuka): Use in buffet_client.
+chromeos::VariantDictionary DictionaryToDBusVariantDictionary(
+ const base::DictionaryValue& object) {
+ chromeos::VariantDictionary result;
+
+ for (base::DictionaryValue::Iterator it(object); !it.IsAtEnd(); it.Advance())
+ result.emplace(it.key(), ValueToAny(it.value()));
+
+ return result;
+}
+
+} // namespace weave
diff --git a/libweave/src/commands/dbus_conversion.h b/libweave/src/commands/dbus_conversion.h
new file mode 100644
index 0000000..ab49f70
--- /dev/null
+++ b/libweave/src/commands/dbus_conversion.h
@@ -0,0 +1,46 @@
+// Copyright 2015 The Chromium OS 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 LIBWEAVE_SRC_COMMANDS_DBUS_CONVERSION_H_
+#define LIBWEAVE_SRC_COMMANDS_DBUS_CONVERSION_H_
+
+#include <base/values.h>
+#include <chromeos/any.h>
+#include <chromeos/errors/error.h>
+#include <chromeos/variant_dictionary.h>
+
+#include "libweave/src/commands/schema_utils.h"
+
+namespace weave {
+
+// Converts PropValue to Any in a format understood by D-Bus data serialization.
+// Has special handling for Object types where ValueMap are
+// converted to chromeos::VariantDictionary.
+chromeos::Any PropValueToDBusVariant(const PropValue* value);
+
+// Converts ValueMap to chromeos::VariantDictionary
+// with proper conversion of all nested properties.
+chromeos::VariantDictionary ObjectToDBusVariant(const ValueMap& object);
+
+// Converts D-Bus variant to PropValue.
+// Has special handling for Object types where chromeos::VariantDictionary
+// is converted to ValueMap.
+std::unique_ptr<const PropValue> PropValueFromDBusVariant(
+ const PropType* type,
+ const chromeos::Any& value,
+ chromeos::ErrorPtr* error);
+
+// Converts D-Bus variant to ObjectValue.
+bool ObjectFromDBusVariant(const ObjectSchema* object_schema,
+ const chromeos::VariantDictionary& dict,
+ ValueMap* obj,
+ chromeos::ErrorPtr* error);
+
+// Converts DictionaryValue to D-Bus variant dictionary.
+chromeos::VariantDictionary DictionaryToDBusVariantDictionary(
+ const base::DictionaryValue& object);
+
+} // namespace weave
+
+#endif // LIBWEAVE_SRC_COMMANDS_DBUS_CONVERSION_H_
diff --git a/libweave/src/commands/prop_types.h b/libweave/src/commands/prop_types.h
index 7a2e695..09420f1 100644
--- a/libweave/src/commands/prop_types.h
+++ b/libweave/src/commands/prop_types.h
@@ -16,6 +16,7 @@
#include <chromeos/any.h>
#include <chromeos/errors/error.h>
+#include "libweave/src/commands/dbus_conversion.h"
#include "libweave/src/commands/prop_constraints.h"
#include "libweave/src/commands/prop_values.h"
diff --git a/libweave/src/commands/schema_utils.cc b/libweave/src/commands/schema_utils.cc
index ecfd4da..a171109 100644
--- a/libweave/src/commands/schema_utils.cc
+++ b/libweave/src/commands/schema_utils.cc
@@ -51,6 +51,7 @@
"Required parameter missing: %s", param_name);
return false;
}
+
} // namespace
// Specializations of TypedValueToJson<T>() for supported C++ types.
@@ -276,116 +277,4 @@
return str;
}
-chromeos::Any PropValueToDBusVariant(const PropValue* value) {
- if (value->GetType() == ValueType::Object)
- return ObjectToDBusVariant(value->GetObject()->GetValue());
-
- if (value->GetType() == ValueType::Array) {
- const PropType* item_type =
- value->GetPropType()->GetArray()->GetItemTypePtr();
- return item_type->ConvertArrayToDBusVariant(value->GetArray()->GetValue());
- }
- return value->GetValueAsAny();
-}
-
-chromeos::VariantDictionary ObjectToDBusVariant(const ValueMap& object) {
- chromeos::VariantDictionary dict;
- for (const auto& pair : object) {
- // Since we are inserting the elements from ValueMap which is
- // a map, the keys are already sorted. So use the "end()" position as a hint
- // for dict.insert() so the destination map can optimize its insertion
- // time.
- chromeos::Any prop = PropValueToDBusVariant(pair.second.get());
- dict.emplace_hint(dict.end(), pair.first, std::move(prop));
- }
- return dict;
-}
-
-std::unique_ptr<const PropValue> PropValueFromDBusVariant(
- const PropType* type,
- const chromeos::Any& value,
- chromeos::ErrorPtr* error) {
- std::unique_ptr<const PropValue> result;
- if (type->GetType() == ValueType::Array) {
- // Special case for array types.
- // We expect the |value| to contain std::vector<T>, while PropValue must use
- // ValueVector instead. Do the conversion.
- ValueVector arr;
- const PropType* item_type = type->GetArray()->GetItemTypePtr();
- if (item_type->ConvertDBusVariantToArray(value, &arr, error))
- result = type->CreateValue(arr, error);
- } else if (type->GetType() == ValueType::Object) {
- // Special case for object types.
- // We expect the |value| to contain chromeos::VariantDictionary, while
- // PropValue must use ValueMap instead. Do the conversion.
- if (!value.IsTypeCompatible<chromeos::VariantDictionary>()) {
- type->GenerateErrorValueTypeMismatch(error);
- return result;
- }
- CHECK(nullptr != type->GetObject()->GetObjectSchemaPtr())
- << "An object type must have a schema defined for it";
- ValueMap obj;
- if (!ObjectFromDBusVariant(type->GetObject()->GetObjectSchemaPtr(),
- value.Get<chromeos::VariantDictionary>(), &obj,
- error)) {
- return result;
- }
-
- result = type->CreateValue(std::move(obj), error);
- } else {
- result = type->CreateValue(value, error);
- }
-
- return result;
-}
-
-bool ObjectFromDBusVariant(const ObjectSchema* object_schema,
- const chromeos::VariantDictionary& dict,
- ValueMap* obj,
- chromeos::ErrorPtr* error) {
- std::set<std::string> keys_processed;
- obj->clear();
- // First go over all object parameters defined by type's object schema and
- // extract the corresponding parameters from the source dictionary.
- for (const auto& pair : object_schema->GetProps()) {
- const PropValue* def_value = pair.second->GetDefaultValue();
- auto it = dict.find(pair.first);
- if (it != dict.end()) {
- const PropType* prop_type = pair.second.get();
- CHECK(prop_type) << "Value property type must be available";
- auto prop_value = PropValueFromDBusVariant(prop_type, it->second, error);
- if (!prop_value) {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kInvalidPropValue,
- "Invalid value for property '%s'", pair.first.c_str());
- return false;
- }
- obj->emplace_hint(obj->end(), pair.first, std::move(prop_value));
- } else if (def_value) {
- obj->emplace_hint(obj->end(), pair.first, def_value->Clone());
- } else {
- ErrorMissingProperty(error, FROM_HERE, pair.first.c_str());
- return false;
- }
- keys_processed.insert(pair.first);
- }
-
- // Make sure that we processed all the necessary properties and there weren't
- // any extra (unknown) ones specified, unless the schema allows them.
- if (!object_schema->GetExtraPropertiesAllowed()) {
- for (const auto& pair : dict) {
- if (keys_processed.find(pair.first) == keys_processed.end()) {
- chromeos::Error::AddToPrintf(
- error, FROM_HERE, errors::commands::kDomain,
- errors::commands::kUnknownProperty, "Unrecognized property '%s'",
- pair.first.c_str());
- return false;
- }
- }
- }
-
- return true;
-}
-
} // namespace weave
diff --git a/libweave/src/commands/schema_utils.h b/libweave/src/commands/schema_utils.h
index e2efbe3..6d1b342 100644
--- a/libweave/src/commands/schema_utils.h
+++ b/libweave/src/commands/schema_utils.h
@@ -13,9 +13,7 @@
#include <vector>
#include <base/values.h>
-#include <chromeos/any.h>
#include <chromeos/errors/error.h>
-#include <chromeos/variant_dictionary.h>
namespace weave {
@@ -139,26 +137,6 @@
return std::abs(v1 - v2) <= std::numeric_limits<T>::epsilon();
}
-// Converts PropValue to Any in a format understood by D-Bus data serialization.
-// Has special handling for Object types where ValueMap are
-// converted to chromeos::VariantDictionary.
-chromeos::Any PropValueToDBusVariant(const PropValue* value);
-// Converts ValueMap to chromeos::VariantDictionary
-// with proper conversion of all nested properties.
-chromeos::VariantDictionary ObjectToDBusVariant(const ValueMap& object);
-// Converts D-Bus variant to PropValue.
-// Has special handling for Object types where chromeos::VariantDictionary
-// is converted to ValueMap.
-std::unique_ptr<const PropValue> PropValueFromDBusVariant(
- const PropType* type,
- const chromeos::Any& value,
- chromeos::ErrorPtr* error);
-// Converts D-Bus variant to ObjectValue.
-bool ObjectFromDBusVariant(const ObjectSchema* object_schema,
- const chromeos::VariantDictionary& dict,
- ValueMap* obj,
- chromeos::ErrorPtr* error);
-
} // namespace weave
#endif // LIBWEAVE_SRC_COMMANDS_SCHEMA_UTILS_H_