buffet: libchromeos: Migrate ExportedPropertySet to libchromeos We want to reuse this in peerd. As a side effect, we're forced to pull parts of dbus_utils, and patch up a bunch of namespace issues. BUG=chromium:398626 TEST=libchromeos/buffet unittests. Change-Id: Id7f40c95d1677ec0460ce1677c0933478a315d8c Reviewed-on: https://chromium-review.googlesource.com/211483 Tested-by: Christopher Wiley <wiley@chromium.org> Reviewed-by: Alex Vakulenko <avakulenko@chromium.org> Commit-Queue: Christopher Wiley <wiley@chromium.org>
diff --git a/buffet/buffet.gyp b/buffet/buffet.gyp index 7870fc7..6254e56 100644 --- a/buffet/buffet.gyp +++ b/buffet/buffet.gyp
@@ -43,7 +43,6 @@ 'error.cc', 'error_codes.cc', 'exported_object_manager.cc', - 'exported_property_set.cc', 'http_request.cc', 'http_connection_curl.cc', 'http_transport_curl.cc', @@ -99,7 +98,6 @@ 'device_registration_info_unittest.cc', 'error_unittest.cc', 'exported_object_manager_unittest.cc', - 'exported_property_set_unittest.cc', 'http_connection_fake.cc', 'http_transport_fake.cc', 'http_utils_unittest.cc',
diff --git a/buffet/dbus_utils.cc b/buffet/dbus_utils.cc index 5c02fb3..099abc1 100644 --- a/buffet/dbus_utils.cc +++ b/buffet/dbus_utils.cc
@@ -4,6 +4,8 @@ #include "buffet/dbus_utils.h" +#include <string> + #include <base/bind.h> #include <base/logging.h> @@ -29,14 +31,6 @@ } // namespace -scoped_ptr<dbus::Response> GetBadArgsError(dbus::MethodCall* method_call, - const std::string& message) { - LOG(ERROR) << "Error while handling DBus call: " << message; - scoped_ptr<dbus::ErrorResponse> resp(dbus::ErrorResponse::FromMethodCall( - method_call, "org.freedesktop.DBus.Error.InvalidArgs", message)); - return scoped_ptr<dbus::Response>(resp.release()); -} - scoped_ptr<dbus::Response> GetDBusError(dbus::MethodCall* method_call, const Error* error) { std::string message;
diff --git a/buffet/dbus_utils.h b/buffet/dbus_utils.h index 6314531..ed4a76c 100644 --- a/buffet/dbus_utils.h +++ b/buffet/dbus_utils.h
@@ -5,8 +5,6 @@ #ifndef BUFFET_DBUS_UTILS_H_ #define BUFFET_DBUS_UTILS_H_ -#include <string> - #include <base/memory/scoped_ptr.h> #include <dbus/exported_object.h> #include <dbus/message.h> @@ -17,13 +15,9 @@ namespace dbus_utils { -scoped_ptr<dbus::Response> GetBadArgsError(dbus::MethodCall* method_call, - const std::string& message); - scoped_ptr<dbus::Response> GetDBusError(dbus::MethodCall* method_call, const Error* error); - dbus::ExportedObject::MethodCallCallback GetExportableDBusMethod( base::Callback<scoped_ptr<dbus::Response>(dbus::MethodCall*)> handler);
diff --git a/buffet/exported_object_manager.h b/buffet/exported_object_manager.h index d483db0..212609e 100644 --- a/buffet/exported_object_manager.h +++ b/buffet/exported_object_manager.h
@@ -11,10 +11,9 @@ #include <base/memory/weak_ptr.h> #include <dbus/bus.h> #include <dbus/exported_object.h> +#include <dbus/message.h> #include <dbus/object_path.h> -#include "buffet/exported_property_set.h" - namespace buffet { namespace dbus_utils {
diff --git a/buffet/exported_property_set.cc b/buffet/exported_property_set.cc deleted file mode 100644 index 3ab3c2d..0000000 --- a/buffet/exported_property_set.cc +++ /dev/null
@@ -1,340 +0,0 @@ -// Copyright 2014 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 "buffet/exported_property_set.h" - -#include <base/bind.h> -#include <chromeos/async_event_sequencer.h> -#include <dbus/bus.h> // For kPropertyInterface -#include <dbus/property.h> // For kPropertyInterface - -#include "buffet/dbus_utils.h" - -using chromeos::dbus_utils::AsyncEventSequencer; - -namespace buffet { - -namespace dbus_utils { - -namespace { -const char kExportFailedMessage[] = "Failed to register DBus method."; -} // namespace - -ExportedPropertySet::ExportedPropertySet(dbus::Bus* bus, - const dbus::ObjectPath& path) - : bus_(bus), exported_object_(bus->GetExportedObject(path)), - weak_ptr_factory_(this) { } - -void ExportedPropertySet::Init(const OnInitFinish& cb) { - bus_->AssertOnOriginThread(); - scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer()); - exported_object_->ExportMethod( - dbus::kPropertiesInterface, dbus::kPropertiesGetAll, - base::Bind(&ExportedPropertySet::HandleGetAll, - weak_ptr_factory_.GetWeakPtr()), - sequencer->GetExportHandler( - dbus::kPropertiesInterface, dbus::kPropertiesGetAll, - kExportFailedMessage, false)); - exported_object_->ExportMethod( - dbus::kPropertiesInterface, dbus::kPropertiesGet, - base::Bind(&ExportedPropertySet::HandleGet, - weak_ptr_factory_.GetWeakPtr()), - sequencer->GetExportHandler( - dbus::kPropertiesInterface, dbus::kPropertiesGet, - kExportFailedMessage, false)); - exported_object_->ExportMethod( - dbus::kPropertiesInterface, dbus::kPropertiesSet, - base::Bind(&ExportedPropertySet::HandleSet, - weak_ptr_factory_.GetWeakPtr()), - sequencer->GetExportHandler( - dbus::kPropertiesInterface, dbus::kPropertiesSet, - kExportFailedMessage, false)); - sequencer->OnAllTasksCompletedCall({cb}); -} - -ExportedPropertySet::PropertyWriter ExportedPropertySet::GetPropertyWriter( - const std::string& interface) { - return base::Bind(&ExportedPropertySet::WritePropertiesDictToMessage, - weak_ptr_factory_.GetWeakPtr(), - interface); -} - -void ExportedPropertySet::RegisterProperty( - const std::string& interface_name, - const std::string& property_name, - ExportedPropertyBase* exported_property) { - bus_->AssertOnOriginThread(); - properties_[interface_name][property_name] = exported_property; - // Technically, the property set exists longer than the properties themselves, - // so we could use Unretained here rather than a weak pointer. - ExportedPropertyBase::OnUpdateCallback cb = base::Bind( - &ExportedPropertySet::HandlePropertyUpdated, - weak_ptr_factory_.GetWeakPtr(), - interface_name, property_name); - exported_property->SetUpdateCallback(cb); -} - -void ExportedPropertySet::HandleGetAll( - dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - bus_->AssertOnOriginThread(); - dbus::MessageReader reader(method_call); - std::string interface_name; - if (!reader.PopString(&interface_name)) { - response_sender.Run( - GetBadArgsError(method_call, "No interface name specified.")); - return; - } - if (reader.HasMoreData()) { - response_sender.Run( - GetBadArgsError(method_call, "Too many arguments to GetAll.")); - return; - } - scoped_ptr<dbus::Response> response( - dbus::Response::FromMethodCall(method_call)); - dbus::MessageWriter resp_writer(response.get()); - WritePropertiesDictToMessage(interface_name, &resp_writer); - response_sender.Run(response.Pass()); -} - -void ExportedPropertySet::WritePropertiesDictToMessage( - const std::string& interface_name, - dbus::MessageWriter* writer) { - dbus::MessageWriter dict_writer(nullptr); - writer->OpenArray("{sv}", &dict_writer); - auto property_map_itr = properties_.find(interface_name); - if (property_map_itr != properties_.end()) { - for (const auto& kv : property_map_itr->second) { - dbus::MessageWriter entry_writer(nullptr); - dict_writer.OpenDictEntry(&entry_writer); - entry_writer.AppendString(kv.first); - kv.second->AppendValueToWriter(&entry_writer); - dict_writer.CloseContainer(&entry_writer); - } - } else { - LOG(WARNING) << "No properties found for interface interface_name"; - } - writer->CloseContainer(&dict_writer); -} - -void ExportedPropertySet::HandleGet( - dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - bus_->AssertOnOriginThread(); - dbus::MessageReader reader(method_call); - std::string interface_name, property_name; - if (!reader.PopString(&interface_name)) { - response_sender.Run( - GetBadArgsError(method_call, "No interface name specified.")); - return; - } - if (!reader.PopString(&property_name)) { - response_sender.Run( - GetBadArgsError(method_call, "No property name specified.")); - return; - } - if (reader.HasMoreData()) { - response_sender.Run( - GetBadArgsError(method_call, "Too many arguments to Get.")); - return; - } - auto property_map_itr = properties_.find(interface_name); - if (property_map_itr == properties_.end()) { - response_sender.Run( - GetBadArgsError(method_call, "No such interface on object.")); - return; - } - LOG(ERROR) << "Looking for " << property_name << " on " << interface_name; - auto property_itr = property_map_itr->second.find(property_name); - if (property_itr == property_map_itr->second.end()) { - response_sender.Run( - GetBadArgsError(method_call, "No such property on interface.")); - return; - } - scoped_ptr<dbus::Response> response( - dbus::Response::FromMethodCall(method_call)); - dbus::MessageWriter resp_writer(response.get()); - property_itr->second->AppendValueToWriter(&resp_writer); - response_sender.Run(response.Pass()); -} - -void ExportedPropertySet::HandleSet( - dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - bus_->AssertOnOriginThread(); - scoped_ptr<dbus::ErrorResponse> error_resp( - dbus::ErrorResponse::FromMethodCall( - method_call, "org.freedesktop.DBus.Error.NotSupported", "")); - scoped_ptr<dbus::Response> response(error_resp.release()); - response_sender.Run(response.Pass()); -} - -void ExportedPropertySet::HandlePropertyUpdated( - const std::string& interface, - const std::string& name, - const ExportedPropertyBase* property) { - bus_->AssertOnOriginThread(); - dbus::Signal signal(dbus::kPropertiesInterface, dbus::kPropertiesChanged); - dbus::MessageWriter writer(&signal); - dbus::MessageWriter array_writer(nullptr); - dbus::MessageWriter dict_writer(nullptr); - writer.AppendString(interface); - writer.OpenArray("{sv}", &array_writer); - array_writer.OpenDictEntry(&dict_writer); - dict_writer.AppendString(name); - property->AppendValueToWriter(&dict_writer); - array_writer.CloseContainer(&dict_writer); - writer.CloseContainer(&array_writer); - // The interface specification tells us to include this list of properties - // which have changed, but for whom no value is conveyed. Currently, we - // don't do anything interesting here. - writer.OpenArray("s", &array_writer); - writer.CloseContainer(&array_writer); - // This sends the signal asyncronously. However, the raw message inside - // the signal object is ref-counted, so we're fine to allocate the Signal - // object on our local stack. - exported_object_->SendSignal(&signal); -} - -template <typename T> -void AppendPropertyToWriter(dbus::MessageWriter* writer, const T& value); - -template <> -void AppendPropertyToWriter(dbus::MessageWriter* writer, const bool& value) { - writer->AppendVariantOfBool(value); -} - -template <> -void AppendPropertyToWriter(dbus::MessageWriter* writer, const uint8& value) { - writer->AppendVariantOfByte(value); -} - -template <> -void AppendPropertyToWriter(dbus::MessageWriter* writer, const int16& value) { - writer->AppendVariantOfInt16(value); -} - -template <> -void AppendPropertyToWriter(dbus::MessageWriter* writer, const uint16& value) { - writer->AppendVariantOfUint16(value); -} - -template <> -void AppendPropertyToWriter(dbus::MessageWriter* writer, const int32& value) { - writer->AppendVariantOfInt32(value); -} - -template <> -void AppendPropertyToWriter(dbus::MessageWriter* writer, const uint32& value) { - writer->AppendVariantOfUint32(value); -} - -template <> -void AppendPropertyToWriter(dbus::MessageWriter* writer, const int64& value) { - writer->AppendVariantOfInt64(value); -} - -template <> -void AppendPropertyToWriter(dbus::MessageWriter* writer, const uint64& value) { - writer->AppendVariantOfUint64(value); -} - -template <> -void AppendPropertyToWriter(dbus::MessageWriter* writer, const double& value) { - writer->AppendVariantOfDouble(value); -} - -template <> -void AppendPropertyToWriter( - dbus::MessageWriter* writer, const std::string& value) { - writer->AppendVariantOfString(value); -} - -template <> -void AppendPropertyToWriter( - dbus::MessageWriter* writer, const dbus::ObjectPath& value) { - writer->AppendVariantOfObjectPath(value); -} - -template <> -void AppendPropertyToWriter( - dbus::MessageWriter* writer, const std::vector<std::string>& value) { - dbus::MessageWriter variant_writer(nullptr); - writer->OpenVariant("as", &variant_writer); - variant_writer.AppendArrayOfStrings(value); - writer->CloseContainer(&variant_writer); -} - -template <> -void AppendPropertyToWriter( - dbus::MessageWriter* writer, const std::vector<dbus::ObjectPath>& value) { - dbus::MessageWriter variant_writer(nullptr); - writer->OpenVariant("ao", &variant_writer); - variant_writer.AppendArrayOfObjectPaths(value); - writer->CloseContainer(&variant_writer); -} - -template <> -void AppendPropertyToWriter( - dbus::MessageWriter* writer, const std::vector<uint8>& value) { - dbus::MessageWriter variant_writer(nullptr); - writer->OpenVariant("ay", &variant_writer); - variant_writer.AppendArrayOfBytes(value.data(), value.size()); - writer->CloseContainer(&variant_writer); -} - -template <typename T> -ExportedProperty<T>::ExportedProperty() {} - -template <typename T> -ExportedProperty<T>::~ExportedProperty() {} - -template <typename T> -const T& ExportedProperty<T>::value() const { return value_; } - -template <typename T> -void ExportedProperty<T>::SetValue(const T& new_value) { - if (value_ == new_value) { - return; - } - value_ = new_value; - // These is a brief period after the construction of an ExportedProperty - // when this callback is not initialized because the property has not - // been registered with the parent ExportedPropertySet. During this period - // users should be initializing values via SetValue, and no notifications - // should be triggered by the ExportedPropertySet. - if (!on_update_.is_null()) { - on_update_.Run(this); - } -} - -template <typename T> -void ExportedProperty<T>::SetUpdateCallback(const OnUpdateCallback& cb) { - on_update_ = cb; -} - -template <typename T> -void ExportedProperty<T>::AppendValueToWriter( - dbus::MessageWriter* writer) const { - AppendPropertyToWriter(writer, value_); -} - -template class ExportedProperty<bool>; -template class ExportedProperty<uint8>; -template class ExportedProperty<int16>; -template class ExportedProperty<uint16>; -template class ExportedProperty<int32>; -template class ExportedProperty<uint32>; -template class ExportedProperty<int64>; -template class ExportedProperty<uint64>; -template class ExportedProperty<double>; -template class ExportedProperty<std::string>; -template class ExportedProperty<dbus::ObjectPath>; -template class ExportedProperty<std::vector<std::string>>; -template class ExportedProperty<std::vector<dbus::ObjectPath>>; -template class ExportedProperty<std::vector<uint8>>; - -} // namespace dbus_utils - -} // namespace buffet
diff --git a/buffet/exported_property_set.h b/buffet/exported_property_set.h deleted file mode 100644 index d91415f..0000000 --- a/buffet/exported_property_set.h +++ /dev/null
@@ -1,200 +0,0 @@ -// Copyright 2014 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 BUFFET_EXPORTED_PROPERTY_SET_H_ -#define BUFFET_EXPORTED_PROPERTY_SET_H_ - -#include <map> -#include <string> -#include <vector> - -#include <base/memory/weak_ptr.h> -#include <dbus/exported_object.h> -#include <dbus/message.h> - -namespace buffet { - -namespace dbus_utils { - -// This class may be used to implement the org.freedesktop.DBus.Properties -// interface. It sends the update signal on property updates: -// -// org.freedesktop.DBus.Properties.PropertiesChanged ( -// STRING interface_name, -// DICT<STRING,VARIANT> changed_properties, -// ARRAY<STRING> invalidated_properties); -// -// -// and implements the required methods of the interface: -// -// org.freedesktop.DBus.Properties.Get(in STRING interface_name, -// in STRING property_name, -// out VARIANT value); -// org.freedesktop.DBus.Properties.Set(in STRING interface_name, -// in STRING property_name, -// in VARIANT value); -// org.freedesktop.DBus.Properties.GetAll(in STRING interface_name, -// out DICT<STRING,VARIANT> props); -// -// This class is very similar to the PropertySet class in Chrome, except that -// it allows objects to expose properties rather than to consume them. -// -// Example usage: -// -// class ExampleObjectExportingProperties { -// public: -// ExampleObjectExportingProperties(ExportedObject* exported_object) -// : p_(exported_object) { -// // Initialize properties appropriately. Do this before -// // claiming the Properties interface so that daemons watching -// // this object don't see partial or inaccurate state. -// p_.ClaimPropertiesInterface(); -// } -// -// private: -// struct Properties : public buffet::dbus::ExportedPropertySet { -// public: -// buffet::dbus::ExportedProperty<std::string> name_; -// buffet::dbus::ExportedProperty<uint16> version_; -// buffet::dbus::ExportedProperty<dbus::ObjectPath> parent_; -// buffet::dbus::ExportedProperty<std::vector<std::string>> children_; -// -// Properties(dbus::ExportedObject* exported_object) -// : buffet::dbus::ExportedPropertySet(exported_object) { -// RegisterProperty(kExampleInterfaceName, "Name", &name_); -// RegisterProperty(kExampleInterfaceName, "Version", &version_); -// RegisterProperty(kExampleInterfaceName, "Parent", &parent_); -// RegisterProperty(kExampleInterfaceName, "Children", &children_); -// } -// virtual ~Properties() {} -// }; -// -// Properties p_; -// }; - -class ExportedPropertyBase { - public: - ExportedPropertyBase() {} - virtual ~ExportedPropertyBase() {} - - typedef base::Callback<void(const ExportedPropertyBase*)> OnUpdateCallback; - - // Called by ExportedPropertySet to register a callback. This callback - // triggers ExportedPropertySet to send a signal from the properties - // interface of the exported object. - virtual void SetUpdateCallback(const OnUpdateCallback& cb) = 0; - - // Appends a variant of the contained value to the writer. This is - // needed to write out properties to Get and GetAll methods implemented - // by the ExportedPropertySet since it doesn't actually know the type - // of each property. - virtual void AppendValueToWriter(dbus::MessageWriter* writer) const = 0; -}; - -class ExportedPropertySet { - public: - typedef base::Callback<void(bool success)> OnInitFinish; - typedef base::Callback<void(dbus::MessageWriter* writer)> PropertyWriter; - - ExportedPropertySet(dbus::Bus* bus, const dbus::ObjectPath& path); - virtual ~ExportedPropertySet() = default; - - // Claims the method associated with the org.freedesktop.DBus.Properties - // interface. This needs to be done after all properties are initialized to - // appropriate values. This method will call |cb| when all methods - // are exported to the DBus object. |cb| will be called on the origin - // thread. - void Init(const OnInitFinish& cb); - - // Return a callback that knows how to write this property set's properties - // to a message. This writer retains a weak pointer to this, and must - // only be invoked on the same thread as the rest of ExportedPropertySet. - PropertyWriter GetPropertyWriter(const std::string& interface); - - protected: - void RegisterProperty(const std::string& interface_name, - const std::string& property_name, - ExportedPropertyBase* exported_property); - - private: - // Used to write the dictionary of string->variant to a message. - // This dictionary represents the property name/value pairs for the - // given interface. - void WritePropertiesDictToMessage(const std::string& interface_name, - dbus::MessageWriter* writer); - void HandleGetAll(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender); - void HandleGet(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender); - // While Properties.Set has a handler to complete the interface, we don't - // support writable properties. This is almost a feature, since bindings for - // many languages don't support errors coming back from invalid writes. - // Instead, use setters in exposed interfaces. - void HandleSet(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender); - void HandlePropertyUpdated(const std::string& interface, - const std::string& name, - const ExportedPropertyBase* property); - - dbus::Bus* bus_; - dbus::ExportedObject* exported_object_; // weak; owned by the Bus object. - // This is a map from interface name -> property name -> pointer to property. - std::map<std::string, - std::map<std::string, ExportedPropertyBase*>> properties_; - - // D-Bus callbacks may last longer the property set exporting those methods. - base::WeakPtrFactory<ExportedPropertySet> weak_ptr_factory_; - - friend class ExportedPropertySetTest; - DISALLOW_COPY_AND_ASSIGN(ExportedPropertySet); -}; - -template <typename T> -class ExportedProperty : public ExportedPropertyBase { - public: - ExportedProperty(); - virtual ~ExportedProperty() override; - - // Retrieves the current value. - const T& value() const; - - // Set the value exposed to remote applications. This triggers notifications - // of changes over the Properties interface. - void SetValue(const T& new_value); - - // Called by ExportedPropertySet. This update callback triggers - // ExportedPropertySet to send a signal from the properties interface of the - // exported object. - virtual void SetUpdateCallback(const OnUpdateCallback& cb) override; - - // Implementation provided by specialization. - virtual void AppendValueToWriter(dbus::MessageWriter* writer) const override; - - private: - OnUpdateCallback on_update_; - T value_{}; - - DISALLOW_COPY_AND_ASSIGN(ExportedProperty); -}; - -extern template class ExportedProperty<bool>; -extern template class ExportedProperty<uint8>; -extern template class ExportedProperty<int16>; -extern template class ExportedProperty<uint16>; -extern template class ExportedProperty<int32>; -extern template class ExportedProperty<uint32>; -extern template class ExportedProperty<int64>; -extern template class ExportedProperty<uint64>; -extern template class ExportedProperty<double>; -extern template class ExportedProperty<std::string>; -extern template class ExportedProperty<dbus::ObjectPath>; -extern template class ExportedProperty<std::vector<std::string>>; -extern template class ExportedProperty<std::vector<dbus::ObjectPath>>; -extern template class ExportedProperty<std::vector<uint8>>; - -} // namespace dbus_utils - -} // namespace buffet - -#endif // BUFFET_EXPORTED_PROPERTY_SET_H_
diff --git a/buffet/exported_property_set_unittest.cc b/buffet/exported_property_set_unittest.cc deleted file mode 100644 index ce8a3fe..0000000 --- a/buffet/exported_property_set_unittest.cc +++ /dev/null
@@ -1,506 +0,0 @@ -// Copyright 2014 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 "buffet/exported_property_set.h" - -#include <string> -#include <vector> - -#include <base/basictypes.h> -#include <base/bind.h> -#include <dbus/message.h> -#include <dbus/property.h> -#include <dbus/object_path.h> -#include <dbus/mock_bus.h> -#include <dbus/mock_exported_object.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -using ::testing::AnyNumber; -using ::testing::Return; -using ::testing::Invoke; -using ::testing::_; - -namespace buffet { - -namespace dbus_utils { - -namespace { - -const char kBoolPropName[] = "BoolProp"; -const char kUint8PropName[] = "Uint8Prop"; -const char kInt16PropName[] = "Int16Prop"; -const char kUint16PropName[] = "Uint16Prop"; -const char kInt32PropName[] = "Int32Prop"; -const char kUint32PropName[] = "Uint32Prop"; -const char kInt64PropName[] = "Int64Prop"; -const char kUint64PropName[] = "Uint64Prop"; -const char kDoublePropName[] = "DoubleProp"; -const char kStringPropName[] = "StringProp"; -const char kPathPropName[] = "PathProp"; -const char kStringListPropName[] = "StringListProp"; -const char kPathListPropName[] = "PathListProp"; -const char kUint8ListPropName[] = "Uint8ListProp"; - -const char kTestInterface1[] = "org.chromium.TestInterface1"; -const char kTestInterface2[] = "org.chromium.TestInterface2"; -const char kTestInterface3[] = "org.chromium.TestInterface3"; - -const std::string kTestString("lies"); -const dbus::ObjectPath kMethodsExportedOnPath(std::string("/export")); -const dbus::ObjectPath kTestObjectPathInit(std::string("/path_init")); -const dbus::ObjectPath kTestObjectPathUpdate(std::string("/path_update")); - -} // namespace - -class ExportedPropertySetTest : public ::testing::Test { - public: - struct Properties : public ExportedPropertySet { - public: - ExportedProperty<bool> bool_prop_; - ExportedProperty<uint8> uint8_prop_; - ExportedProperty<int16> int16_prop_; - ExportedProperty<uint16> uint16_prop_; - ExportedProperty<int32> int32_prop_; - ExportedProperty<uint32> uint32_prop_; - ExportedProperty<int64> int64_prop_; - ExportedProperty<uint64> uint64_prop_; - ExportedProperty<double> double_prop_; - ExportedProperty<std::string> string_prop_; - ExportedProperty<dbus::ObjectPath> path_prop_; - ExportedProperty<std::vector<std::string>> stringlist_prop_; - ExportedProperty<std::vector<dbus::ObjectPath>> pathlist_prop_; - ExportedProperty<std::vector<uint8>> uint8list_prop_; - - Properties(dbus::Bus* bus, const dbus::ObjectPath& path) - : ExportedPropertySet(bus, path) { - // The empty string is not a valid value for an ObjectPath. - path_prop_.SetValue(kTestObjectPathInit); - RegisterProperty(kTestInterface1, kBoolPropName, &bool_prop_); - RegisterProperty(kTestInterface1, kUint8PropName, &uint8_prop_); - RegisterProperty(kTestInterface1, kInt16PropName, &int16_prop_); - // I chose this weird grouping because N=2 is about all the permutations - // of GetAll that I want to anticipate. - RegisterProperty(kTestInterface2, kUint16PropName, &uint16_prop_); - RegisterProperty(kTestInterface2, kInt32PropName, &int32_prop_); - RegisterProperty(kTestInterface3, kUint32PropName, &uint32_prop_); - RegisterProperty(kTestInterface3, kInt64PropName, &int64_prop_); - RegisterProperty(kTestInterface3, kUint64PropName, &uint64_prop_); - RegisterProperty(kTestInterface3, kDoublePropName, &double_prop_); - RegisterProperty(kTestInterface3, kStringPropName, &string_prop_); - RegisterProperty(kTestInterface3, kPathPropName, &path_prop_); - RegisterProperty(kTestInterface3, kStringListPropName, &stringlist_prop_); - RegisterProperty(kTestInterface3, kPathListPropName, &pathlist_prop_); - RegisterProperty(kTestInterface3, kUint8ListPropName, &uint8list_prop_); - } - virtual ~Properties() {} - - void CallHandleGetAll( - dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - HandleGetAll(method_call, response_sender); - } - - void CallHandleGet(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - HandleGet(method_call, response_sender); - } - - void CallHandleSet(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - HandleSet(method_call, response_sender); - } - }; - - virtual void SetUp() { - dbus::Bus::Options options; - options.bus_type = dbus::Bus::SYSTEM; - bus_ = new dbus::MockBus(options); - // By default, don't worry about threading assertions. - EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber()); - EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber()); - // Use a mock exported object. - mock_exported_object_ = new dbus::MockExportedObject( - bus_.get(), kMethodsExportedOnPath); - EXPECT_CALL(*bus_, GetExportedObject(kMethodsExportedOnPath)) - .Times(1).WillOnce(Return(mock_exported_object_.get())); - p_.reset(new Properties(bus_.get(), kMethodsExportedOnPath)); - } - - void StoreResponse(scoped_ptr<dbus::Response> method_response) { - last_response_.reset(method_response.release()); - } - - void AssertGetAllReturnsError(dbus::MethodCall* method_call) { - auto response_sender = base::Bind(&ExportedPropertySetTest::StoreResponse, - base::Unretained(this)); - method_call->SetSerial(123); - p_->CallHandleGetAll(method_call, response_sender); - ASSERT_NE(dynamic_cast<dbus::ErrorResponse*>(last_response_.get()), - nullptr); - } - - void AssertGetReturnsError(dbus::MethodCall* method_call) { - auto response_sender = base::Bind(&ExportedPropertySetTest::StoreResponse, - base::Unretained(this)); - method_call->SetSerial(123); - p_->CallHandleGet(method_call, response_sender); - ASSERT_NE(dynamic_cast<dbus::ErrorResponse*>(last_response_.get()), - nullptr); - } - - scoped_ptr<dbus::Response> GetPropertyOnInterface( - const std::string& interface_name, const std::string& property_name) { - dbus::MethodCall method_call(dbus::kPropertiesInterface, - dbus::kPropertiesGet); - method_call.SetSerial(123); - dbus::MessageWriter writer(&method_call); - writer.AppendString(interface_name); - writer.AppendString(property_name); - auto response_sender = base::Bind(&ExportedPropertySetTest::StoreResponse, - base::Unretained(this)); - p_->CallHandleGet(&method_call, response_sender); - return last_response_.Pass(); - } - - scoped_ptr<dbus::Response> last_response_; - scoped_refptr<dbus::MockBus> bus_; - scoped_refptr<dbus::MockExportedObject> mock_exported_object_; - scoped_ptr<Properties> p_; -}; - -TEST_F(ExportedPropertySetTest, UpdateNotifications) { - EXPECT_CALL(*mock_exported_object_, SendSignal(_)).Times(14); - p_->bool_prop_.SetValue(true); - p_->uint8_prop_.SetValue(1); - p_->int16_prop_.SetValue(1); - p_->uint16_prop_.SetValue(1); - p_->int32_prop_.SetValue(1); - p_->uint32_prop_.SetValue(1); - p_->int64_prop_.SetValue(1); - p_->uint64_prop_.SetValue(1); - p_->double_prop_.SetValue(1.0); - p_->string_prop_.SetValue(kTestString); - p_->path_prop_.SetValue(kTestObjectPathUpdate); - p_->stringlist_prop_.SetValue({kTestString}); - p_->pathlist_prop_.SetValue({kTestObjectPathUpdate}); - p_->uint8list_prop_.SetValue({1}); -} - -TEST_F(ExportedPropertySetTest, UpdateToSameValue) { - EXPECT_CALL(*mock_exported_object_, SendSignal(_)).Times(1); - p_->bool_prop_.SetValue(true); - p_->bool_prop_.SetValue(true); -} - -TEST_F(ExportedPropertySetTest, GetAllNoArgs) { - dbus::MethodCall method_call(dbus::kPropertiesInterface, - dbus::kPropertiesGetAll); - AssertGetAllReturnsError(&method_call); -} - -TEST_F(ExportedPropertySetTest, GetAllInvalidInterface) { - dbus::MethodCall method_call( - dbus::kPropertiesInterface, dbus::kPropertiesGetAll); - method_call.SetSerial(123); - dbus::MessageWriter writer(&method_call); - writer.AppendString("org.chromium.BadInterface"); - auto response_sender = base::Bind(&ExportedPropertySetTest::StoreResponse, - base::Unretained(this)); - p_->CallHandleGetAll(&method_call, response_sender); - dbus::MessageReader response_reader(last_response_.get()); - dbus::MessageReader dict_reader(nullptr); - ASSERT_TRUE(response_reader.PopArray(&dict_reader)); - // The response should just be a an empty array, since there are no properties - // on this interface. The spec doesn't say much about error conditions here, - // so I'm going to assume this is a valid implementation. - ASSERT_FALSE(dict_reader.HasMoreData()); - ASSERT_FALSE(response_reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetAllExtraArgs) { - dbus::MethodCall method_call(dbus::kPropertiesInterface, - dbus::kPropertiesGetAll); - dbus::MessageWriter writer(&method_call); - writer.AppendString(kTestInterface1); - writer.AppendString(kTestInterface1); - AssertGetAllReturnsError(&method_call); -} - -TEST_F(ExportedPropertySetTest, GetAllCorrectness) { - dbus::MethodCall method_call( - dbus::kPropertiesInterface, dbus::kPropertiesGetAll); - method_call.SetSerial(123); - dbus::MessageWriter writer(&method_call); - writer.AppendString(kTestInterface2); - auto response_sender = base::Bind(&ExportedPropertySetTest::StoreResponse, - base::Unretained(this)); - p_->CallHandleGetAll(&method_call, response_sender); - dbus::MessageReader response_reader(last_response_.get()); - dbus::MessageReader dict_reader(nullptr); - dbus::MessageReader entry_reader(nullptr); - ASSERT_TRUE(response_reader.PopArray(&dict_reader)); - ASSERT_TRUE(dict_reader.PopDictEntry(&entry_reader)); - std::string property_name; - ASSERT_TRUE(entry_reader.PopString(&property_name)); - uint16 value16; - int32 value32; - if (property_name.compare(kUint16PropName) == 0) { - ASSERT_TRUE(entry_reader.PopVariantOfUint16(&value16)); - ASSERT_FALSE(entry_reader.HasMoreData()); - ASSERT_TRUE(dict_reader.PopDictEntry(&entry_reader)); - ASSERT_TRUE(entry_reader.PopString(&property_name)); - ASSERT_EQ(property_name.compare(kInt32PropName), 0); - ASSERT_TRUE(entry_reader.PopVariantOfInt32(&value32)); - } else { - ASSERT_EQ(property_name.compare(kInt32PropName), 0); - ASSERT_TRUE(entry_reader.PopVariantOfInt32(&value32)); - ASSERT_FALSE(entry_reader.HasMoreData()); - ASSERT_TRUE(dict_reader.PopDictEntry(&entry_reader)); - ASSERT_TRUE(entry_reader.PopString(&property_name)); - ASSERT_EQ(property_name.compare(kUint16PropName), 0); - ASSERT_TRUE(entry_reader.PopVariantOfUint16(&value16)); - } - ASSERT_FALSE(entry_reader.HasMoreData()); - ASSERT_FALSE(dict_reader.HasMoreData()); - ASSERT_FALSE(response_reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetNoArgs) { - dbus::MethodCall method_call(dbus::kPropertiesInterface, - dbus::kPropertiesGet); - AssertGetReturnsError(&method_call); -} - -TEST_F(ExportedPropertySetTest, GetInvalidInterface) { - dbus::MethodCall method_call(dbus::kPropertiesInterface, - dbus::kPropertiesGet); - dbus::MessageWriter writer(&method_call); - writer.AppendString("org.chromium.BadInterface"); - writer.AppendString(kInt16PropName); - AssertGetReturnsError(&method_call); -} - -TEST_F(ExportedPropertySetTest, GetBadPropertyName) { - dbus::MethodCall method_call(dbus::kPropertiesInterface, - dbus::kPropertiesGet); - dbus::MessageWriter writer(&method_call); - writer.AppendString(kTestInterface1); - writer.AppendString("IAmNotAProperty"); - AssertGetReturnsError(&method_call); -} - -TEST_F(ExportedPropertySetTest, GetPropIfMismatch) { - dbus::MethodCall method_call(dbus::kPropertiesInterface, - dbus::kPropertiesGet); - dbus::MessageWriter writer(&method_call); - writer.AppendString(kTestInterface1); - writer.AppendString(kStringPropName); - AssertGetReturnsError(&method_call); -} - -TEST_F(ExportedPropertySetTest, GetNoPropertyName) { - dbus::MethodCall method_call(dbus::kPropertiesInterface, - dbus::kPropertiesGet); - dbus::MessageWriter writer(&method_call); - writer.AppendString(kTestInterface1); - AssertGetReturnsError(&method_call); -} - -TEST_F(ExportedPropertySetTest, GetExtraArgs) { - dbus::MethodCall method_call(dbus::kPropertiesInterface, - dbus::kPropertiesGet); - dbus::MessageWriter writer(&method_call); - writer.AppendString(kTestInterface1); - writer.AppendString(kBoolPropName); - writer.AppendString("Extra param"); - AssertGetReturnsError(&method_call); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithBool) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface1, kBoolPropName); - dbus::MessageReader reader(response.get()); - bool value; - ASSERT_TRUE(reader.PopVariantOfBool(&value)); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithUint8) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface1, kUint8PropName); - dbus::MessageReader reader(response.get()); - uint8 value; - ASSERT_TRUE(reader.PopVariantOfByte(&value)); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithInt16) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface1, kInt16PropName); - dbus::MessageReader reader(response.get()); - int16 value; - ASSERT_TRUE(reader.PopVariantOfInt16(&value)); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithUint16) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface2, kUint16PropName); - dbus::MessageReader reader(response.get()); - uint16 value; - ASSERT_TRUE(reader.PopVariantOfUint16(&value)); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithInt32) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface2, kInt32PropName); - dbus::MessageReader reader(response.get()); - int32 value; - ASSERT_TRUE(reader.PopVariantOfInt32(&value)); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithUint32) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface3, kUint32PropName); - dbus::MessageReader reader(response.get()); - uint32 value; - ASSERT_TRUE(reader.PopVariantOfUint32(&value)); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithInt64) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface3, kInt64PropName); - dbus::MessageReader reader(response.get()); - int64 value; - ASSERT_TRUE(reader.PopVariantOfInt64(&value)); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithUint64) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface3, kUint64PropName); - dbus::MessageReader reader(response.get()); - uint64 value; - ASSERT_TRUE(reader.PopVariantOfUint64(&value)); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithDouble) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface3, kDoublePropName); - dbus::MessageReader reader(response.get()); - double value; - ASSERT_TRUE(reader.PopVariantOfDouble(&value)); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithString) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface3, kStringPropName); - dbus::MessageReader reader(response.get()); - std::string value; - ASSERT_TRUE(reader.PopVariantOfString(&value)); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithPath) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface3, kPathPropName); - dbus::MessageReader reader(response.get()); - dbus::ObjectPath value; - ASSERT_TRUE(reader.PopVariantOfObjectPath(&value)); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithStringList) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface3, kStringListPropName); - dbus::MessageReader reader(response.get()); - dbus::MessageReader variant_reader(nullptr); - std::vector<std::string> value; - ASSERT_TRUE(reader.PopVariant(&variant_reader)); - ASSERT_TRUE(variant_reader.PopArrayOfStrings(&value)); - ASSERT_FALSE(variant_reader.HasMoreData()); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithPathList) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface3, kPathListPropName); - dbus::MessageReader reader(response.get()); - dbus::MessageReader variant_reader(nullptr); - std::vector<dbus::ObjectPath> value; - ASSERT_TRUE(reader.PopVariant(&variant_reader)); - ASSERT_TRUE(variant_reader.PopArrayOfObjectPaths(&value)); - ASSERT_FALSE(variant_reader.HasMoreData()); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, GetWorksWithUint8List) { - scoped_ptr<dbus::Response> response = GetPropertyOnInterface( - kTestInterface3, kPathListPropName); - dbus::MessageReader reader(response.get()); - dbus::MessageReader variant_reader(nullptr); - const uint8* buffer; - size_t buffer_len; - ASSERT_TRUE(reader.PopVariant(&variant_reader)); - // |buffer| remains under the control of the MessageReader. - ASSERT_TRUE(variant_reader.PopArrayOfBytes(&buffer, &buffer_len)); - ASSERT_FALSE(variant_reader.HasMoreData()); - ASSERT_FALSE(reader.HasMoreData()); -} - -TEST_F(ExportedPropertySetTest, SetFailsGracefully) { - dbus::MethodCall method_call(dbus::kPropertiesInterface, - dbus::kPropertiesSet); - method_call.SetSerial(123); - auto response_sender = base::Bind(&ExportedPropertySetTest::StoreResponse, - base::Unretained(this)); - p_->CallHandleSet(&method_call, response_sender); - ASSERT_TRUE( - dynamic_cast<dbus::ErrorResponse*>(last_response_.get()) != nullptr); -} - -namespace { - -void VerifySignal(dbus::Signal* signal) { - ASSERT_NE(signal, nullptr); - std::string interface_name; - std::string property_name; - uint8 value; - dbus::MessageReader reader(signal); - dbus::MessageReader array_reader(signal); - dbus::MessageReader dict_reader(signal); - ASSERT_TRUE(reader.PopString(&interface_name)); - ASSERT_TRUE(reader.PopArray(&array_reader)); - ASSERT_TRUE(array_reader.PopDictEntry(&dict_reader)); - ASSERT_TRUE(dict_reader.PopString(&property_name)); - ASSERT_TRUE(dict_reader.PopVariantOfByte(&value)); - ASSERT_FALSE(dict_reader.HasMoreData()); - ASSERT_FALSE(array_reader.HasMoreData()); - ASSERT_TRUE(reader.HasMoreData()); - // Read the (empty) list of invalidated property names. - ASSERT_TRUE(reader.PopArray(&array_reader)); - ASSERT_FALSE(array_reader.HasMoreData()); - ASSERT_FALSE(reader.HasMoreData()); - ASSERT_EQ(value, 57); - ASSERT_EQ(property_name, std::string(kUint8PropName)); - ASSERT_EQ(interface_name, std::string(kTestInterface1)); -} - -} // namespace - -TEST_F(ExportedPropertySetTest, SignalsAreParsable) { - EXPECT_CALL(*mock_exported_object_, SendSignal(_)) - .Times(1).WillOnce(Invoke(&VerifySignal)); - p_->uint8_prop_.SetValue(57); -} - -} // namespace dbus_utils - -} // namespace buffet
diff --git a/buffet/manager.cc b/buffet/manager.cc index 0a6af31..39ccf7d 100644 --- a/buffet/manager.cc +++ b/buffet/manager.cc
@@ -11,6 +11,7 @@ #include <base/bind_helpers.h> #include <base/json/json_writer.h> #include <chromeos/async_event_sequencer.h> +#include <chromeos/dbus_utils.h> #include <dbus/bus.h> #include <dbus/object_path.h> #include <dbus/values_util.h> @@ -22,7 +23,7 @@ #include "buffet/exported_object_manager.h" using chromeos::dbus_utils::AsyncEventSequencer; -using buffet::dbus_utils::GetBadArgsError; +using chromeos::dbus_utils::GetBadArgsError; using buffet::dbus_utils::GetDBusError; namespace buffet {
diff --git a/buffet/manager.h b/buffet/manager.h index 6f2f8a6..08e7656 100644 --- a/buffet/manager.h +++ b/buffet/manager.h
@@ -12,12 +12,13 @@ #include <base/memory/scoped_ptr.h> #include <base/memory/weak_ptr.h> #include <base/values.h> +#include <chromeos/exported_property_set.h> +#include <dbus/bus.h> #include <dbus/message.h> #include <dbus/object_path.h> #include "buffet/dbus_constants.h" #include "buffet/device_registration_info.h" -#include "buffet/exported_property_set.h" namespace buffet { @@ -40,11 +41,11 @@ void Init(const OnInitFinish& cb); private: - struct Properties: public dbus_utils::ExportedPropertySet { + struct Properties: public chromeos::dbus_utils::ExportedPropertySet { public: - dbus_utils::ExportedProperty<std::string> state_; + chromeos::dbus_utils::ExportedProperty<std::string> state_; explicit Properties(dbus::Bus* bus) - : dbus_utils::ExportedPropertySet( + : chromeos::dbus_utils::ExportedPropertySet( bus, dbus::ObjectPath(dbus_constants::kManagerServicePath)) { RegisterProperty(dbus_constants::kManagerInterface, "State", &state_); }