| # Copyright 2015 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. |
| |
| import dbus |
| import dbus.service |
| import logging |
| |
| |
| class ObjectManager(dbus.service.Object): |
| """Exports the org.freedesktop.DBus.ObjectManager interface: |
| |
| GetManagedObjects( |
| out DICT<OBJPATH,DICT<STRING,DICT<STRING,VARIANT>>> |
| objpath_interfaces_and_properties); |
| |
| The return value of this method is a dict whose keys are object |
| paths. All returned object paths are children of the object path |
| implementing this interface, i.e. their object paths start with |
| the ObjectManager's object path plus '/'. |
| |
| Each value is a dict whose keys are interfaces names. Each value |
| in this inner dict is the same dict that would be returned by the |
| org.freedesktop.DBus.Properties.GetAll() method for that |
| combination of object path and interface. If an interface has no |
| properties, the empty dict is returned. |
| |
| Changes are emitted using the following two signals: |
| |
| InterfacesAdded( |
| OBJPATH object_path, |
| DICT<STRING,DICT<STRING,VARIANT>> interfaces_and_properties); |
| |
| InterfacesRemoved (OBJPATH object_path, ARRAY<STRING> interfaces); |
| |
| """ |
| |
| OBJECT_MANAGER_INTERFACE = 'org.freedesktop.DBus.ObjectManager' |
| |
| |
| def __init__(self, bus, path): |
| super(ObjectManager, self).__init__(bus, path) |
| self._paths = dict() |
| |
| |
| def claim_interface(self, path, interface_name, property_getter): |
| """Claim an interface for an object exposed under this ObjectManager. |
| |
| @param path: string object path of object exposed. |
| @param interface_name: string DBus interface name of exposed object. |
| @param property_getter: function that takes no objects and returns |
| a dictionary mapping from property name to property value. |
| Both property names and values must be DBus types. |
| |
| """ |
| logging.debug('claim_interface(%s, %s, ...)', path, interface_name) |
| if path in self._paths: |
| self._paths[path][interface_name] = property_getter |
| else: |
| self._paths[path] = {interface_name: property_getter} |
| interface2properties = dbus.Dictionary( |
| {dbus.String(interface_name): property_getter()}, 'sa{sv}') |
| self.InterfacesAdded(dbus.ObjectPath(path), interface2properties) |
| |
| |
| def release_interface(self, path, interface_name): |
| """Release an interface previously claimed for a particular |path|. |
| |
| You may call this method even if the interface has not been claimed. |
| This is intended to simplify destruction patterns. |
| |
| @param path: string path exposed previously. |
| @param interface_name: string DBus interface name previously claimed. |
| |
| """ |
| logging.debug('release_interface(%s, %s)', path, interface_name) |
| if path not in self._paths or interface_name not in self._paths[path]: |
| return |
| self._paths[path].pop(interface_name) |
| if not self._paths[path]: |
| self._paths.pop(path) |
| self.InterfacesRemoved(dbus.ObjectPath(path), |
| dbus.Array([dbus.String(interface_name)])) |
| |
| |
| @dbus.service.method(dbus_interface=OBJECT_MANAGER_INTERFACE, |
| in_signature='', out_signature='a{oa{sa{sv}}}') |
| def GetManagedObjects(self): |
| """Implementation of DBus interface method of the same name. |
| |
| @return see class documentation. |
| |
| """ |
| logging.debug('Received call to GetManagedObjects()') |
| result = dbus.Dictionary(dict(), 'oa{sa{sv}}') |
| for path, interfaces in self._paths.iteritems(): |
| dbus_path = dbus.ObjectPath(path) |
| result[dbus_path] = dbus.Dictionary(dict(), 'sa{sv}') |
| for interface_name, property_getter in interfaces.iteritems(): |
| dbus_if_name = dbus.String(interface_name) |
| result[dbus_path][dbus_if_name] = property_getter() |
| return result |
| |
| |
| @dbus.service.signal(dbus_interface=OBJECT_MANAGER_INTERFACE, |
| signature='oa{sa{sv}}') |
| def InterfacesAdded(self, object_path, interfaces2properties): |
| """Implementation of DBus interface signal. |
| |
| @param object_path: dbus.ObjectPath object. |
| @param interfaces2properties: see class documentation. |
| |
| """ |
| |
| |
| @dbus.service.signal(dbus_interface=OBJECT_MANAGER_INTERFACE, |
| signature='oas') |
| def InterfacesRemoved(self, object_path, interfaces): |
| """Implementation of DBus interface signal. |
| |
| @param object_path: dbus.ObjectPath object. |
| @param interfaces: see class documentation. |
| |
| """ |