blob: c1403adcd3dea78225f2f7970949a6defcb9ec82 [file] [log] [blame]
// 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(scoped_refptr<dbus::Bus> bus,
const dbus::ObjectPath& path)
: bus_(bus), exported_object_(bus->GetExportedObject(path)) {}
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,
AsWeakPtr()),
sequencer->GetExportHandler(
dbus::kObjectManagerInterface,
dbus::kObjectManagerGetManagedObjects,
"Failed exporting GetManagedObjects method of ObjectManager",
false));
sequencer->OnAllTasksCompletedCall({cb});
}
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