1 # Copyright 2015 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. 3 4 import dbus 5 import dbus.service 6 import logging 7 8 9 class ObjectManager(dbus.service.Object): 10 """Exports the org.freedesktop.DBus.ObjectManager interface: 11 12 GetManagedObjects( 13 out DICT<OBJPATH,DICT<STRING,DICT<STRING,VARIANT>>> 14 objpath_interfaces_and_properties); 15 16 The return value of this method is a dict whose keys are object 17 paths. All returned object paths are children of the object path 18 implementing this interface, i.e. their object paths start with 19 the ObjectManager's object path plus '/'. 20 21 Each value is a dict whose keys are interfaces names. Each value 22 in this inner dict is the same dict that would be returned by the 23 org.freedesktop.DBus.Properties.GetAll() method for that 24 combination of object path and interface. If an interface has no 25 properties, the empty dict is returned. 26 27 Changes are emitted using the following two signals: 28 29 InterfacesAdded( 30 OBJPATH object_path, 31 DICT<STRING,DICT<STRING,VARIANT>> interfaces_and_properties); 32 33 InterfacesRemoved (OBJPATH object_path, ARRAY<STRING> interfaces); 34 35 """ 36 37 OBJECT_MANAGER_INTERFACE = 'org.freedesktop.DBus.ObjectManager' 38 39 40 def __init__(self, bus, path): 41 super(ObjectManager, self).__init__(bus, path) 42 self._paths = dict() 43 44 45 def claim_interface(self, path, interface_name, property_getter): 46 """Claim an interface for an object exposed under this ObjectManager. 47 48 @param path: string object path of object exposed. 49 @param interface_name: string DBus interface name of exposed object. 50 @param property_getter: function that takes no objects and returns 51 a dictionary mapping from property name to property value. 52 Both property names and values must be DBus types. 53 54 """ 55 logging.debug('claim_interface(%s, %s, ...)', path, interface_name) 56 if path in self._paths: 57 self._paths[path][interface_name] = property_getter 58 else: 59 self._paths[path] = {interface_name: property_getter} 60 interface2properties = dbus.Dictionary( 61 {dbus.String(interface_name): property_getter()}, 'sa{sv}') 62 self.InterfacesAdded(dbus.ObjectPath(path), interface2properties) 63 64 65 def release_interface(self, path, interface_name): 66 """Release an interface previously claimed for a particular |path|. 67 68 You may call this method even if the interface has not been claimed. 69 This is intended to simplify destruction patterns. 70 71 @param path: string path exposed previously. 72 @param interface_name: string DBus interface name previously claimed. 73 74 """ 75 logging.debug('release_interface(%s, %s)', path, interface_name) 76 if path not in self._paths or interface_name not in self._paths[path]: 77 return 78 self._paths[path].pop(interface_name) 79 if not self._paths[path]: 80 self._paths.pop(path) 81 self.InterfacesRemoved(dbus.ObjectPath(path), 82 dbus.Array([dbus.String(interface_name)])) 83 84 85 @dbus.service.method(dbus_interface=OBJECT_MANAGER_INTERFACE, 86 in_signature='', out_signature='a{oa{sa{sv}}}') 87 def GetManagedObjects(self): 88 """Implementation of DBus interface method of the same name. 89 90 @return see class documentation. 91 92 """ 93 logging.debug('Received call to GetManagedObjects()') 94 result = dbus.Dictionary(dict(), 'oa{sa{sv}}') 95 for path, interfaces in self._paths.iteritems(): 96 dbus_path = dbus.ObjectPath(path) 97 result[dbus_path] = dbus.Dictionary(dict(), 'sa{sv}') 98 for interface_name, property_getter in interfaces.iteritems(): 99 dbus_if_name = dbus.String(interface_name) 100 result[dbus_path][dbus_if_name] = property_getter() 101 return result 102 103 104 @dbus.service.signal(dbus_interface=OBJECT_MANAGER_INTERFACE, 105 signature='oa{sa{sv}}') 106 def InterfacesAdded(self, object_path, interfaces2properties): 107 """Implementation of DBus interface signal. 108 109 @param object_path: dbus.ObjectPath object. 110 @param interfaces2properties: see class documentation. 111 112 """ 113 114 115 @dbus.service.signal(dbus_interface=OBJECT_MANAGER_INTERFACE, 116 signature='oas') 117 def InterfacesRemoved(self, object_path, interfaces): 118 """Implementation of DBus interface signal. 119 120 @param object_path: dbus.ObjectPath object. 121 @param interfaces: see class documentation. 122 123 """ 124