Skip to content

Commit

Permalink
app-info: Transition host apps to registered
Browse files Browse the repository at this point in the history
If a host app is created due an early D-Bus, then the registration
happens, transition it from "guessed" to registered. But only do it
once.

This allows smoother recovery of apps if the portal service disappears
for some reason, e.g. crashes or restarts.

Adjust the registry tests to exercise this code path.

Closes: #1612
  • Loading branch information
GeorgesStavracas committed Feb 4, 2025
1 parent 53cb9dd commit e9a3b5f
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 10 deletions.
68 changes: 65 additions & 3 deletions src/xdp-app-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,60 @@ xdp_invocation_ensure_app_info_sync (GDBusMethodInvocation *invocation,
cancellable,
error);
}
static XdpAppInfo *
transition_host_app_info_to_registered (GDBusMethodInvocation *invocation,
const char *app_id,
GCancellable *cancellable,
GError **error)
{
GDBusConnection *connection = g_dbus_method_invocation_get_connection (invocation);
const char *sender = g_dbus_method_invocation_get_sender (invocation);
g_autoptr(XdpAppInfo) registered_app_info = NULL;
XdpAppInfo *app_info;

g_assert (app_info_by_unique_name != NULL);

G_LOCK (app_infos);
app_info = g_hash_table_lookup (app_info_by_unique_name, sender);
G_UNLOCK (app_infos);

g_assert (XDP_IS_APP_INFO (app_info));

if (!xdp_app_info_is_host (app_info))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"App is not a host system app");
return NULL;
}

if (xdp_app_info_is_registered (app_info))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Connection already associated and registered with an application ID");
return NULL;
}

registered_app_info = maybe_create_registered_test_app_info (app_id);

if (!registered_app_info)
{
g_autofd int pidfd = -1;
uint32_t pid;

if (!xdp_connection_get_pidfd (connection, sender, cancellable, &pidfd, &pid, error))
return NULL;

registered_app_info = xdp_app_info_host_new_registered (pidfd, app_id, error);
if (!registered_app_info)
return NULL;
}

g_debug ("Replacing host app info with a registered one for '%s'", xdp_app_info_get_id (registered_app_info));

cache_insert_app_info (sender, registered_app_info);

return g_steal_pointer (&registered_app_info);
}

XdpAppInfo *
xdp_invocation_register_host_app_info_sync (GDBusMethodInvocation *invocation,
Expand All @@ -1116,9 +1170,17 @@ xdp_invocation_register_host_app_info_sync (GDBusMethodInvocation *invocation,

if (cache_has_app_info_by_sender (sender))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Connection already associated with an application ID");
return NULL;
g_autoptr(XdpAppInfo) app_info = NULL;

app_info = transition_host_app_info_to_registered (invocation,
app_id,
cancellable,
error);

if (!app_info)
return NULL;

return g_steal_pointer (&app_info);
}

return xdp_connection_create_host_app_info_sync (connection,
Expand Down
13 changes: 6 additions & 7 deletions tests/test_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,14 @@ def test_late_register(self, portals, dbus_con, app_id):
registry_intf = xdp.get_portal_iface(dbus_con, "Registry", domain="host")
mock_intf = xdp.get_mock_iface(dbus_con)

expected_app_id = app_id
unexpected_app_id = "org.example.CorrectAppId"

session = self.create_dummy_session(dbus_con)

expected_app_id = "org.example.WrongAppId"
app_id = mock_intf.GetSessionAppId(session.handle)
assert app_id == expected_app_id

with pytest.raises(dbus.exceptions.DBusException) as exc_info:
registry_intf.Register(unexpected_app_id, {})
exc_info.match(".*Connection already associated with an application ID.*")
expected_app_id = "org.example.CorrectAppId"
registry_intf.Register(expected_app_id, {})

new_session = self.create_dummy_session(dbus_con)

Expand Down Expand Up @@ -138,4 +135,6 @@ def test_no_reregister(self, portals, dbus_con):

with pytest.raises(dbus.exceptions.DBusException) as exc_info:
registry_intf.Register(expected_app_id, {})
exc_info.match(".*Connection already associated with an application ID.*")
exc_info.match(
".*Connection already associated and registered with an application ID.*"
)

0 comments on commit e9a3b5f

Please sign in to comment.