blob: c1403adcd3dea78225f2f7970949a6defcb9ec82 [file] [log] [blame]
Christopher Wileycec927c2014-04-15 16:26:47 -07001// Copyright 2014 The Chromium OS Authors. 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.
4
5#include "buffet/exported_object_manager.h"
6
7#include <dbus/object_manager.h>
8
9#include "buffet/async_event_sequencer.h"
10
11namespace buffet {
12
13namespace dbus_utils {
14
Christopher Wileyadb901d2014-05-07 09:58:45 -070015ExportedObjectManager::ExportedObjectManager(scoped_refptr<dbus::Bus> bus,
Christopher Wileycec927c2014-04-15 16:26:47 -070016 const dbus::ObjectPath& path)
Christopher Wileyadb901d2014-05-07 09:58:45 -070017 : bus_(bus), exported_object_(bus->GetExportedObject(path)) {}
Christopher Wileycec927c2014-04-15 16:26:47 -070018
19void ExportedObjectManager::Init(const OnInitFinish& cb) {
20 bus_->AssertOnOriginThread();
21 scoped_refptr<dbus_utils::AsyncEventSequencer> sequencer(
22 new dbus_utils::AsyncEventSequencer());
23 exported_object_->ExportMethod(
24 dbus::kObjectManagerInterface,
25 dbus::kObjectManagerGetManagedObjects,
26 base::Bind(&ExportedObjectManager::HandleGetManagedObjects,
Christopher Wileyadb901d2014-05-07 09:58:45 -070027 AsWeakPtr()),
Christopher Wileycec927c2014-04-15 16:26:47 -070028 sequencer->GetExportHandler(
29 dbus::kObjectManagerInterface,
30 dbus::kObjectManagerGetManagedObjects,
31 "Failed exporting GetManagedObjects method of ObjectManager",
32 false));
Christopher Wileyadb901d2014-05-07 09:58:45 -070033 sequencer->OnAllTasksCompletedCall({cb});
Christopher Wileycec927c2014-04-15 16:26:47 -070034}
35
36void ExportedObjectManager::ClaimInterface(
37 const dbus::ObjectPath& path,
38 const std::string& interface_name,
39 const PropertyWriter& property_writer) {
40 bus_->AssertOnOriginThread();
41 // We're sending signals that look like:
42 // org.freedesktop.DBus.ObjectManager.InterfacesAdded (
43 // OBJPATH object_path,
44 // DICT<STRING,DICT<STRING,VARIANT>> interfaces_and_properties);
45 dbus::Signal signal(dbus::kObjectManagerInterface,
46 dbus::kObjectManagerInterfacesAdded);
47 dbus::MessageWriter signal_writer(&signal);
48 dbus::MessageWriter all_interfaces(&signal);
49 dbus::MessageWriter each_interface(&signal);
50 signal_writer.AppendObjectPath(path);
51 signal_writer.OpenArray("{sa{sv}}", &all_interfaces);
52 all_interfaces.OpenDictEntry(&each_interface);
53 each_interface.AppendString(interface_name);
54 property_writer.Run(&each_interface);
55 all_interfaces.CloseContainer(&each_interface);
56 signal_writer.CloseContainer(&all_interfaces);
57 exported_object_->SendSignal(&signal);
58 registered_objects_[path][interface_name] = property_writer;
59}
60
61void ExportedObjectManager::ReleaseInterface(
62 const dbus::ObjectPath& path, const std::string& interface_name) {
63 bus_->AssertOnOriginThread();
64 auto interfaces_for_path_itr = registered_objects_.find(path);
65 CHECK(interfaces_for_path_itr != registered_objects_.end())
66 << "Attempting to signal interface removal for path " << path.value()
67 << " which was never registered.";
68 auto interfaces_for_path = interfaces_for_path_itr->second;
69 auto property_for_interface_itr = interfaces_for_path.find(interface_name);
70 CHECK(property_for_interface_itr != interfaces_for_path.end())
71 << "Attempted to remove interface " << interface_name << " from "
72 << path.value() << ", but this interface was never registered.";
73 interfaces_for_path.erase(interface_name);
74 if (interfaces_for_path.size() < 1) {
75 registered_objects_.erase(path);
76 }
77 // We're sending signals that look like:
78 // org.freedesktop.DBus.ObjectManager.InterfacesRemoved (
79 // OBJPATH object_path, ARRAY<STRING> interfaces);
80 dbus::Signal signal(dbus::kObjectManagerInterface,
81 dbus::kObjectManagerInterfacesRemoved);
82 dbus::MessageWriter signal_writer(&signal);
83 signal_writer.AppendObjectPath(path);
84 dbus::MessageWriter interface_writer(nullptr);
85 signal_writer.OpenArray("s", &interface_writer);
86 interface_writer.AppendString(interface_name);
87 signal_writer.CloseContainer(&interface_writer);
88 exported_object_->SendSignal(&signal);
89}
90
91void ExportedObjectManager::HandleGetManagedObjects(
92 dbus::MethodCall* method_call,
93 dbus::ExportedObject::ResponseSender response_sender) const {
94 // Implements the GetManagedObjects method:
95 //
96 // org.freedesktop.DBus.ObjectManager.GetManagedObjects (
97 // out DICT<OBJPATH,
98 // DICT<STRING,
99 // DICT<STRING,VARIANT>>> )
100 bus_->AssertOnOriginThread();
101 scoped_ptr<dbus::Response> response(
102 dbus::Response::FromMethodCall(method_call));
103 dbus::MessageWriter response_writer(response.get());
104 dbus::MessageWriter all_object_paths(nullptr);
105 dbus::MessageWriter each_object_path(nullptr);
106 dbus::MessageWriter all_interfaces(nullptr);
107 dbus::MessageWriter each_interface(nullptr);
108
109 response_writer.OpenArray("{oa{sa{sv}}}", &all_object_paths);
110 for (const auto path_pair : registered_objects_) {
111 const dbus::ObjectPath& path = path_pair.first;
112 const InterfaceProperties& interface2properties = path_pair.second;
113 all_object_paths.OpenDictEntry(&each_object_path);
114 each_object_path.AppendObjectPath(path);
115 each_object_path.OpenArray("{sa{sv}}", &all_interfaces);
116 for (const auto interface : interface2properties) {
117 const std::string& interface_name = interface.first;
118 const PropertyWriter& property_writer = interface.second;
119 all_interfaces.OpenDictEntry(&each_interface);
120 each_interface.AppendString(interface_name);
121 property_writer.Run(&each_interface);
122 all_interfaces.CloseContainer(&each_interface);
123 }
124 each_object_path.CloseContainer(&all_interfaces);
125 all_object_paths.CloseContainer(&each_object_path);
126 }
127 response_writer.CloseContainer(&all_object_paths);
128 response_sender.Run(response.Pass());
129}
130
131} // namespace dbus_utils
132
133} // namespace buffet