From adcd571386d6b1af1c939bbe72af0b6de1a516bb Mon Sep 17 00:00:00 2001 From: Luc Fauvel Date: Wed, 23 Sep 2026 17:31:17 -0400 Subject: [PATCH] daemon: Skip UI service activation when already running Bus implementations reject StartServiceByName for names without an activation file, even if the name is already owned. This broke running credentialsd-ui manually during development, since the daemon failed every request with "The name is not activatable". Look up the owner of the UI Control name first, and only request activation if it has no owner yet. Co-Authored-By: Claude Opus 5.5 (1M context) --- CHANGELOG.md | 1 + credentialsd/src/dbus/ui_control.rs | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbce1c2..fe9c9b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Improvements +- daemon: Fix UI service failing to launch when started manually instead of via D-Bus activation. - daemon: Allow Firefox to contact daemon on more distros with different app IDs (Thank you, @michaelbeaumont!) - ui: Add Bulgarian translation (Thank you, @salif!) - webext: Try to read app ID from associated desktop entry (Thank you, @michaelbeaumont!) diff --git a/credentialsd/src/dbus/ui_control.rs b/credentialsd/src/dbus/ui_control.rs index 788ad60..f5fa2ee 100644 --- a/credentialsd/src/dbus/ui_control.rs +++ b/credentialsd/src/dbus/ui_control.rs @@ -405,12 +405,20 @@ impl UiController for UiControlServiceClient { // events according to the sender. // Therefore, we call `start_service_by_name()` explicitly, then subscribe, then // issue the function call. - let service_name = WellKnownName::try_from(backend_proxy.as_ref().destination().clone()) - .expect("UiControl destination is a well-known name"); - dbus_proxy.start_service_by_name(service_name, 0).await?; - let sender = dbus_proxy - .get_name_owner(backend_proxy.as_ref().destination().clone()) - .await?; + // Only activate the service if it isn't already running: bus implementations + // reject `StartServiceByName` for names without an activation file, even if the + // name is owned, which breaks running the UI manually. + let destination = backend_proxy.as_ref().destination().clone(); + let sender = match dbus_proxy.get_name_owner(destination.clone()).await { + Ok(sender) => sender, + Err(fdo::Error::NameHasNoOwner(_)) => { + let service_name = WellKnownName::try_from(destination.clone()) + .expect("UiControl destination is a well-known name"); + dbus_proxy.start_service_by_name(service_name, 0).await?; + dbus_proxy.get_name_owner(destination).await? + } + Err(err) => return Err(err.into()), + }; subscribe_ui_events( self.conn.clone(), sender,