1 // 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 <brillo/dbus/exported_object_manager.h> 6 7 #include <vector> 8 9 #include <brillo/dbus/async_event_sequencer.h> 10 #include <dbus/object_manager.h> 11 12 using brillo::dbus_utils::AsyncEventSequencer; 13 14 namespace brillo { 15 16 namespace dbus_utils { 17 18 ExportedObjectManager::ExportedObjectManager(scoped_refptr<dbus::Bus> bus, 19 const dbus::ObjectPath& path) 20 : bus_(bus), dbus_object_(nullptr, bus, path) { 21 } 22 23 void ExportedObjectManager::RegisterAsync( 24 const AsyncEventSequencer::CompletionAction& completion_callback) { 25 VLOG(1) << "Registering object manager"; 26 bus_->AssertOnOriginThread(); 27 DBusInterface* itf = 28 dbus_object_.AddOrGetInterface(dbus::kObjectManagerInterface); 29 itf->AddSimpleMethodHandler(dbus::kObjectManagerGetManagedObjects, 30 base::Unretained(this), 31 &ExportedObjectManager::HandleGetManagedObjects); 32 33 signal_itf_added_ = itf->RegisterSignalOfType<SignalInterfacesAdded>( 34 dbus::kObjectManagerInterfacesAdded); 35 signal_itf_removed_ = itf->RegisterSignalOfType<SignalInterfacesRemoved>( 36 dbus::kObjectManagerInterfacesRemoved); 37 dbus_object_.RegisterAsync(completion_callback); 38 } 39 40 void ExportedObjectManager::ClaimInterface( 41 const dbus::ObjectPath& path, 42 const std::string& interface_name, 43 const ExportedPropertySet::PropertyWriter& property_writer) { 44 bus_->AssertOnOriginThread(); 45 // We're sending signals that look like: 46 // org.freedesktop.DBus.ObjectManager.InterfacesAdded ( 47 // OBJPATH object_path, 48 // DICT<STRING,DICT<STRING,VARIANT>> interfaces_and_properties); 49 VariantDictionary property_dict; 50 property_writer.Run(&property_dict); 51 std::map<std::string, VariantDictionary> interfaces_and_properties{ 52 {interface_name, property_dict} 53 }; 54 signal_itf_added_.lock()->Send(path, interfaces_and_properties); 55 registered_objects_[path][interface_name] = property_writer; 56 } 57 58 void ExportedObjectManager::ReleaseInterface( 59 const dbus::ObjectPath& path, 60 const std::string& interface_name) { 61 bus_->AssertOnOriginThread(); 62 auto interfaces_for_path_itr = registered_objects_.find(path); 63 CHECK(interfaces_for_path_itr != registered_objects_.end()) 64 << "Attempting to signal interface removal for path " << path.value() 65 << " which was never registered."; 66 auto& interfaces_for_path = interfaces_for_path_itr->second; 67 auto property_for_interface_itr = interfaces_for_path.find(interface_name); 68 CHECK(property_for_interface_itr != interfaces_for_path.end()) 69 << "Attempted to remove interface " << interface_name << " from " 70 << path.value() << ", but this interface was never registered."; 71 interfaces_for_path.erase(interface_name); 72 if (interfaces_for_path.empty()) 73 registered_objects_.erase(path); 74 75 // We're sending signals that look like: 76 // org.freedesktop.DBus.ObjectManager.InterfacesRemoved ( 77 // OBJPATH object_path, ARRAY<STRING> interfaces); 78 signal_itf_removed_.lock()->Send(path, 79 std::vector<std::string>{interface_name}); 80 } 81 82 ExportedObjectManager::ObjectMap 83 ExportedObjectManager::HandleGetManagedObjects() { 84 // Implements the GetManagedObjects method: 85 // 86 // org.freedesktop.DBus.ObjectManager.GetManagedObjects ( 87 // out DICT<OBJPATH, 88 // DICT<STRING, 89 // DICT<STRING,VARIANT>>> ) 90 bus_->AssertOnOriginThread(); 91 ExportedObjectManager::ObjectMap objects; 92 for (const auto path_pair : registered_objects_) { 93 std::map<std::string, VariantDictionary>& interfaces = 94 objects[path_pair.first]; 95 const InterfaceProperties& interface2properties = path_pair.second; 96 for (const auto interface : interface2properties) { 97 interface.second.Run(&interfaces[interface.first]); 98 } 99 } 100 return objects; 101 } 102 103 } // namespace dbus_utils 104 105 } // namespace brillo 106