1 // Copyright (c) 2013 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "xwalk/dbus/property_exporter.h"
9 #include "base/stl_util.h"
10 #include "base/values.h"
11 #include "dbus/message.h"
12 #include "dbus/property.h"
16 const char kErrorName[] = "org.freedesktop.DBus.Properties.Error";
22 PropertyExporter::PropertyExporter(ExportedObject* object,
23 const ObjectPath& path)
28 kPropertiesInterface, kPropertiesGet,
29 base::Bind(&PropertyExporter::OnGet, weak_factory_.GetWeakPtr()),
30 base::Bind(&PropertyExporter::OnExported, weak_factory_.GetWeakPtr()));
32 kPropertiesInterface, kPropertiesGetAll,
33 base::Bind(&PropertyExporter::OnGetAll, weak_factory_.GetWeakPtr()),
34 base::Bind(&PropertyExporter::OnExported, weak_factory_.GetWeakPtr()));
37 PropertyExporter::~PropertyExporter() {
38 STLDeleteValues(&interfaces_);
41 void PropertyExporter::Set(const std::string& interface,
42 const std::string& property,
43 scoped_ptr<base::Value> value) {
44 // TODO(cmarcelo): Support more types as we need to use them.
45 if (!value->IsType(base::Value::TYPE_STRING)
46 && !value->IsType(base::Value::TYPE_INTEGER)) {
47 LOG(ERROR) << "PropertyExporter can only can "
48 << "export String and Integer properties";
52 InterfacesMap::iterator it = interfaces_.find(interface);
53 base::DictionaryValue* dict;
54 if (it != interfaces_.end()) {
57 dict = new base::DictionaryValue;
58 interfaces_[interface] = dict;
61 dict->Set(property, value.release());
63 // TODO(cmarcelo): Emit PropertyChanged signal.
68 void AppendVariantOfValue(MessageWriter* writer, const base::Value& value) {
69 switch (value.GetType()) {
70 case base::Value::TYPE_STRING: {
72 value.GetAsString(&s);
73 writer->AppendVariantOfString(s);
76 case base::Value::TYPE_INTEGER: {
78 value.GetAsInteger(&n);
79 writer->AppendVariantOfInt32(n);
83 LOG(ERROR) << "Unsupported base::Value when converting to DBus VARIANT.";
87 scoped_ptr<Response> CreateParseError(MethodCall* method_call) {
88 scoped_ptr<ErrorResponse> error_response = ErrorResponse::FromMethodCall(
89 method_call, kErrorName, "Error parsing arguments.");
90 return error_response.PassAs<Response>();
93 scoped_ptr<Response> CreateInterfaceNotFoundError(
94 MethodCall* method_call, const std::string& interface,
95 const dbus::ObjectPath& path) {
96 scoped_ptr<ErrorResponse> error_response = ErrorResponse::FromMethodCall(
97 method_call, kErrorName,
98 "Interface '" + interface + "' not found for object '"
99 + path.value() + "'.");
100 return error_response.PassAs<Response>();
105 void PropertyExporter::AppendPropertiesToWriter(const std::string& interface,
106 MessageWriter* writer) const {
107 InterfacesMap::const_iterator it = interfaces_.find(interface);
108 if (it == interfaces_.end())
111 MessageWriter dict_writer(NULL);
112 writer->OpenArray("{sv}", &dict_writer);
114 for (base::DictionaryValue::Iterator dict_it(*it->second);
117 MessageWriter entry_writer(NULL);
118 dict_writer.OpenDictEntry(&entry_writer);
119 entry_writer.AppendString(dict_it.key());
120 AppendVariantOfValue(&entry_writer, dict_it.value());
121 dict_writer.CloseContainer(&entry_writer);
124 writer->CloseContainer(&dict_writer);
127 std::vector<std::string> PropertyExporter::interfaces() const {
128 std::vector<std::string> interfaces;
130 InterfacesMap::const_iterator it = interfaces_.begin();
131 for (; it != interfaces_.end(); ++it) {
132 interfaces.push_back(it->first);
138 void PropertyExporter::OnGet(
139 MethodCall* method_call, ExportedObject::ResponseSender response_sender) {
140 MessageReader reader(method_call);
141 std::string interface;
142 std::string property;
143 if (!reader.PopString(&interface) || !reader.PopString(&property)) {
144 scoped_ptr<Response> error_response = CreateParseError(method_call);
145 response_sender.Run(error_response.Pass());
149 InterfacesMap::const_iterator it = interfaces_.find(interface);
150 if (it == interfaces_.end()) {
151 scoped_ptr<Response> error_response =
152 CreateInterfaceNotFoundError(method_call, interface, path_);
153 response_sender.Run(error_response.Pass());
157 const base::DictionaryValue* dict = it->second;
158 const base::Value* value = NULL;
159 if (!dict->Get(property, &value)) {
160 scoped_ptr<ErrorResponse> error_response = ErrorResponse::FromMethodCall(
161 method_call, kErrorName,
162 "Property '" + property + "' of interface '" + interface
163 + "' not found for object '" + path_.value() + "'.");
164 response_sender.Run(error_response.PassAs<Response>());
168 scoped_ptr<Response> response = Response::FromMethodCall(method_call);
169 MessageWriter writer(response.get());
170 AppendVariantOfValue(&writer, *value);
171 response_sender.Run(response.Pass());
174 void PropertyExporter::OnGetAll(
175 MethodCall* method_call, ExportedObject::ResponseSender response_sender) {
176 MessageReader reader(method_call);
177 std::string interface;
178 if (!reader.PopString(&interface)) {
179 scoped_ptr<Response> error_response = CreateParseError(method_call);
180 response_sender.Run(error_response.Pass());
184 InterfacesMap::const_iterator it = interfaces_.find(interface);
185 if (it == interfaces_.end()) {
186 scoped_ptr<Response> error_response =
187 CreateInterfaceNotFoundError(method_call, interface, path_);
188 response_sender.Run(error_response.Pass());
192 scoped_ptr<Response> response = Response::FromMethodCall(method_call);
193 MessageWriter writer(response.get());
194 AppendPropertiesToWriter(interface, &writer);
195 response_sender.Run(response.Pass());
198 void PropertyExporter::OnExported(const std::string& interface_name,
199 const std::string& method_name,
202 LOG(WARNING) << "Error exporting method '" << interface_name
203 << "." << method_name << "' in object '"
204 << path_.value() << "'.";