zbus/fdo/object_manager.rs
1//! D-Bus standard interfaces.
2//!
3//! The D-Bus specification defines the message bus messages and some standard interfaces that may
4//! be useful across various D-Bus applications. This module provides their proxy.
5
6use std::{borrow::Cow, collections::HashMap};
7use zbus_names::{InterfaceName, OwnedInterfaceName};
8use zvariant::{ObjectPath, OwnedObjectPath, OwnedValue, Value};
9
10use super::{Error, Result};
11use crate::{interface, message::Header, object_server::SignalEmitter, Connection, ObjectServer};
12
13/// The type returned by the [`ObjectManagerProxy::get_managed_objects`] method.
14pub type ManagedObjects =
15 HashMap<OwnedObjectPath, HashMap<OwnedInterfaceName, HashMap<String, OwnedValue>>>;
16
17/// Service-side [Object Manager][om] interface implementation.
18///
19/// The recommended path to add this interface at is the path form of the well-known name of a D-Bus
20/// service, or below. For example, if a D-Bus service is available at the well-known name
21/// `net.example.ExampleService1`, this interface should typically be registered at
22/// `/net/example/ExampleService1`, or below (to allow for multiple object managers in a service).
23///
24/// It is supported, but not recommended, to add this interface at the root path, `/`.
25///
26/// When added to an `ObjectServer`, the `InterfacesAdded` signal is emitted for all the objects
27/// under the `path` it's added at. You can use this fact to minimize the signal emissions by
28/// populating the entire (sub)tree under `path` before registering an object manager.
29///
30/// [om]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
31#[derive(Debug, Clone)]
32pub struct ObjectManager;
33
34#[interface(
35 name = "org.freedesktop.DBus.ObjectManager",
36 introspection_docs = false,
37 proxy(visibility = "pub")
38)]
39impl ObjectManager {
40 /// The return value of this method is a dict whose keys are object paths. All returned object
41 /// paths are children of the object path implementing this interface, i.e. their object paths
42 /// start with the ObjectManager's object path plus '/'.
43 ///
44 /// Each value is a dict whose keys are interfaces names. Each value in this inner dict is the
45 /// same dict that would be returned by the org.freedesktop.DBus.Properties.GetAll() method for
46 /// that combination of object path and interface. If an interface has no properties, the empty
47 /// dict is returned.
48 async fn get_managed_objects(
49 &self,
50 #[zbus(object_server)] server: &ObjectServer,
51 #[zbus(connection)] connection: &Connection,
52 #[zbus(header)] header: Header<'_>,
53 ) -> Result<ManagedObjects> {
54 let path = header.path().ok_or(crate::Error::MissingField)?;
55 let root = server.root().read().await;
56 let node = root
57 .get_child(path)
58 .ok_or_else(|| Error::UnknownObject(format!("Unknown object '{path}'")))?;
59
60 node.get_managed_objects(server, connection).await
61 }
62
63 /// This signal is emitted when either a new object is added or when an existing object gains
64 /// one or more interfaces. The `interfaces_and_properties` argument contains a map with the
65 /// interfaces and properties (if any) that have been added to the given object path.
66 #[zbus(signal)]
67 pub async fn interfaces_added(
68 emitter: &SignalEmitter<'_>,
69 object_path: ObjectPath<'_>,
70 interfaces_and_properties: HashMap<InterfaceName<'_>, HashMap<&str, Value<'_>>>,
71 ) -> zbus::Result<()>;
72
73 /// This signal is emitted whenever an object is removed or it loses one or more interfaces.
74 /// The `interfaces` parameters contains a list of the interfaces that were removed.
75 #[zbus(signal)]
76 pub async fn interfaces_removed(
77 emitter: &SignalEmitter<'_>,
78 object_path: ObjectPath<'_>,
79 interfaces: Cow<'_, [InterfaceName<'_>]>,
80 ) -> zbus::Result<()>;
81}