buffet: Add ExportedObjectManager delegate
This makes it easy to export an object manager. We'll use this very
soon to implement the ObjectManager interface on the root Buffet
object.
BUG=chromium:359190
TEST=Unittests
Change-Id: I19d2da33b81557431c5787937c49a18e7d7bacb2
Reviewed-on: https://chromium-review.googlesource.com/196387
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Christopher Wiley <wiley@chromium.org>
Tested-by: Christopher Wiley <wiley@chromium.org>
diff --git a/buffet/exported_object_manager.cc b/buffet/exported_object_manager.cc
new file mode 100644
index 0000000..6458128
--- /dev/null
+++ b/buffet/exported_object_manager.cc
@@ -0,0 +1,133 @@
+// 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_object_manager.h"
+
+#include <dbus/object_manager.h>
+
+#include "buffet/async_event_sequencer.h"
+
+namespace buffet {
+
+namespace dbus_utils {
+
+ExportedObjectManager::ExportedObjectManager(dbus::Bus* bus,
+ const dbus::ObjectPath& path)
+ : bus_(bus), exported_object_(bus->GetExportedObject(path)),
+ weak_ptr_factory_(this) {}
+
+void ExportedObjectManager::Init(const OnInitFinish& cb) {
+ bus_->AssertOnOriginThread();
+ scoped_refptr<dbus_utils::AsyncEventSequencer> sequencer(
+ new dbus_utils::AsyncEventSequencer());
+ exported_object_->ExportMethod(
+ dbus::kObjectManagerInterface,
+ dbus::kObjectManagerGetManagedObjects,
+ base::Bind(&ExportedObjectManager::HandleGetManagedObjects,
+ weak_ptr_factory_.GetWeakPtr()),
+ sequencer->GetExportHandler(
+ dbus::kObjectManagerInterface,
+ dbus::kObjectManagerGetManagedObjects,
+ "Failed exporting GetManagedObjects method of ObjectManager",
+ false));
+}
+
+void ExportedObjectManager::ClaimInterface(
+ const dbus::ObjectPath& path,
+ const std::string& interface_name,
+ const PropertyWriter& property_writer) {
+ bus_->AssertOnOriginThread();
+ // We're sending signals that look like:
+ // org.freedesktop.DBus.ObjectManager.InterfacesAdded (
+ // OBJPATH object_path,
+ // DICT<STRING,DICT<STRING,VARIANT>> interfaces_and_properties);
+ dbus::Signal signal(dbus::kObjectManagerInterface,
+ dbus::kObjectManagerInterfacesAdded);
+ dbus::MessageWriter signal_writer(&signal);
+ dbus::MessageWriter all_interfaces(&signal);
+ dbus::MessageWriter each_interface(&signal);
+ signal_writer.AppendObjectPath(path);
+ signal_writer.OpenArray("{sa{sv}}", &all_interfaces);
+ all_interfaces.OpenDictEntry(&each_interface);
+ each_interface.AppendString(interface_name);
+ property_writer.Run(&each_interface);
+ all_interfaces.CloseContainer(&each_interface);
+ signal_writer.CloseContainer(&all_interfaces);
+ exported_object_->SendSignal(&signal);
+ registered_objects_[path][interface_name] = property_writer;
+}
+
+void ExportedObjectManager::ReleaseInterface(
+ const dbus::ObjectPath& path, const std::string& interface_name) {
+ bus_->AssertOnOriginThread();
+ auto interfaces_for_path_itr = registered_objects_.find(path);
+ CHECK(interfaces_for_path_itr != registered_objects_.end())
+ << "Attempting to signal interface removal for path " << path.value()
+ << " which was never registered.";
+ auto interfaces_for_path = interfaces_for_path_itr->second;
+ auto property_for_interface_itr = interfaces_for_path.find(interface_name);
+ CHECK(property_for_interface_itr != interfaces_for_path.end())
+ << "Attempted to remove interface " << interface_name << " from "
+ << path.value() << ", but this interface was never registered.";
+ interfaces_for_path.erase(interface_name);
+ if (interfaces_for_path.size() < 1) {
+ registered_objects_.erase(path);
+ }
+ // We're sending signals that look like:
+ // org.freedesktop.DBus.ObjectManager.InterfacesRemoved (
+ // OBJPATH object_path, ARRAY<STRING> interfaces);
+ dbus::Signal signal(dbus::kObjectManagerInterface,
+ dbus::kObjectManagerInterfacesRemoved);
+ dbus::MessageWriter signal_writer(&signal);
+ signal_writer.AppendObjectPath(path);
+ dbus::MessageWriter interface_writer(nullptr);
+ signal_writer.OpenArray("s", &interface_writer);
+ interface_writer.AppendString(interface_name);
+ signal_writer.CloseContainer(&interface_writer);
+ exported_object_->SendSignal(&signal);
+}
+
+void ExportedObjectManager::HandleGetManagedObjects(
+ dbus::MethodCall* method_call,
+ dbus::ExportedObject::ResponseSender response_sender) const {
+ // Implements the GetManagedObjects method:
+ //
+ // org.freedesktop.DBus.ObjectManager.GetManagedObjects (
+ // out DICT<OBJPATH,
+ // DICT<STRING,
+ // DICT<STRING,VARIANT>>> )
+ bus_->AssertOnOriginThread();
+ scoped_ptr<dbus::Response> response(
+ dbus::Response::FromMethodCall(method_call));
+ dbus::MessageWriter response_writer(response.get());
+ dbus::MessageWriter all_object_paths(nullptr);
+ dbus::MessageWriter each_object_path(nullptr);
+ dbus::MessageWriter all_interfaces(nullptr);
+ dbus::MessageWriter each_interface(nullptr);
+
+ response_writer.OpenArray("{oa{sa{sv}}}", &all_object_paths);
+ for (const auto path_pair : registered_objects_) {
+ const dbus::ObjectPath& path = path_pair.first;
+ const InterfaceProperties& interface2properties = path_pair.second;
+ all_object_paths.OpenDictEntry(&each_object_path);
+ each_object_path.AppendObjectPath(path);
+ each_object_path.OpenArray("{sa{sv}}", &all_interfaces);
+ for (const auto interface : interface2properties) {
+ const std::string& interface_name = interface.first;
+ const PropertyWriter& property_writer = interface.second;
+ all_interfaces.OpenDictEntry(&each_interface);
+ each_interface.AppendString(interface_name);
+ property_writer.Run(&each_interface);
+ all_interfaces.CloseContainer(&each_interface);
+ }
+ each_object_path.CloseContainer(&all_interfaces);
+ all_object_paths.CloseContainer(&each_object_path);
+ }
+ response_writer.CloseContainer(&all_object_paths);
+ response_sender.Run(response.Pass());
+}
+
+} // namespace dbus_utils
+
+} // namespace buffet