Skip to content

Commit

Permalink
registry: Allow redundant calls to Register
Browse files Browse the repository at this point in the history
This allows e.g. GtkApplication to automatically register, as well as
using libportal. Only when the app ID conflicts will it result in an
error.
  • Loading branch information
jadahl committed Jan 15, 2025
1 parent bd47696 commit 93995c1
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 73 deletions.
32 changes: 13 additions & 19 deletions src/registry.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,28 +60,22 @@ handle_register (XdpDbusHostRegistry *object,
const char *arg_app_id,
GVariant *arg_options)
{
g_autoptr(XdpAppInfo) app_info = NULL;
g_autoptr(GError) error = NULL;

app_info = xdp_invocation_register_host_app_info_sync (invocation, arg_app_id,
NULL, &error);
if (!app_info)
if (!xdp_invocation_register_host_app_info_sync (invocation, arg_app_id,
NULL, &error))
{
g_dbus_method_invocation_return_error (invocation,
XDG_DESKTOP_PORTAL_ERROR,
XDG_DESKTOP_PORTAL_ERROR_FAILED,
"Could not register app ID: %s",
error->message);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

if (g_strcmp0 (xdp_app_info_get_id (app_info), arg_app_id) != 0)
{
g_dbus_method_invocation_return_error (invocation,
XDG_DESKTOP_PORTAL_ERROR,
XDG_DESKTOP_PORTAL_ERROR_INVALID_ARGUMENT,
"Registered too late");
return G_DBUS_METHOD_INVOCATION_HANDLED;
if (!g_error_matches (error,
XDP_APP_INFO_ERROR,
XDP_APP_INFO_ERROR_REDUNDANT_REGISTRATION))
{
g_dbus_method_invocation_return_error (invocation,
XDG_DESKTOP_PORTAL_ERROR,
XDG_DESKTOP_PORTAL_ERROR_FAILED,
"Could not register app ID: %s",
error->message);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
}

xdp_dbus_host_registry_complete_register (object, invocation);
Expand Down
111 changes: 61 additions & 50 deletions src/xdp-app-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -755,8 +755,10 @@ xdp_connection_get_pidfd (GDBusConnection *connection,
}

static XdpAppInfo *
cache_lookup_app_info_by_pid_and_extend (pid_t pid,
const char *sender)
cache_lookup_app_info_by_pid_and_extend (pid_t pid,
const char *sender,
const char *expected_app_id,
GError **error)
{
XdpAppInfo *app_info = NULL;

Expand All @@ -768,11 +770,21 @@ cache_lookup_app_info_by_pid_and_extend (pid_t pid,
peer = g_hash_table_lookup (peer_by_pid, GINT_TO_POINTER (pid));
if (peer)
{
app_info = g_object_ref (peer->app_info);
if (!expected_app_id ||
g_strcmp0 (xdp_app_info_get_id (peer->app_info),
expected_app_id) == 0)
{
app_info = g_object_ref (peer->app_info);

xdp_peer_add_peer_name (peer, sender);
g_hash_table_insert (peer_by_unique_name, g_strdup (sender),
xdp_peer_ref (peer));
xdp_peer_add_peer_name (peer, sender);
g_hash_table_insert (peer_by_unique_name, g_strdup (sender),
xdp_peer_ref (peer));
}
else
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Tried to extend peer with different application ID");
}
}
}
G_UNLOCK (app_infos);
Expand All @@ -799,32 +811,6 @@ cache_lookup_app_info_by_sender (const char *sender)
return app_info;
}

static gboolean
cache_has_app_info_by_sender (const char *sender)
{
gboolean has_app_info = FALSE;

G_LOCK (app_infos);
if (peer_by_unique_name)
has_app_info = !!g_hash_table_lookup (peer_by_unique_name, sender);
G_UNLOCK (app_infos);

return has_app_info;
}

static gboolean
cache_has_app_info_by_pid (pid_t pid)
{
gboolean has_app_info = FALSE;

G_LOCK (app_infos);
if (peer_by_pid)
has_app_info = !!g_hash_table_lookup (peer_by_pid, GINT_TO_POINTER (pid));
G_UNLOCK (app_infos);

return has_app_info;
}

static void
ensure_app_info_cache (void)
{
Expand Down Expand Up @@ -1066,7 +1052,7 @@ xdp_invocation_ensure_app_info_sync (GDBusMethodInvocation *invocation,
&pidfd, &pid, error))
return NULL;

app_info = cache_lookup_app_info_by_pid_and_extend (pid, sender);
app_info = cache_lookup_app_info_by_pid_and_extend (pid, sender, NULL, NULL);
if (app_info)
{
g_debug ("Using existing app info '%s' for peer %s from pid %d",
Expand All @@ -1083,40 +1069,65 @@ xdp_invocation_ensure_app_info_sync (GDBusMethodInvocation *invocation,
error);
}

XdpAppInfo *
gboolean
xdp_invocation_register_host_app_info_sync (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) app_info = NULL;
g_autofd int pidfd = -1;
uint32_t pid;
g_autoptr(GError) local_error = NULL;

if (cache_has_app_info_by_sender (sender))
app_info = cache_lookup_app_info_by_sender (sender);
if (app_info)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Connection already associated with an application ID");
return NULL;
if (g_strcmp0 (xdp_app_info_get_id (app_info), app_id) == 0)
{
g_set_error (error, XDP_APP_INFO_ERROR,
XDP_APP_INFO_ERROR_REDUNDANT_REGISTRATION,
"Connection already registered with the same application ID");
}
else
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Connection already associated with a different application ID");
}
return FALSE;
}

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

if (cache_has_app_info_by_pid (pid))
app_info = cache_lookup_app_info_by_pid_and_extend (pid, sender, app_id,
&local_error);
if (local_error)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"PID already associated with an application ID");
return NULL;
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}

return xdp_connection_create_host_app_info_sync (connection,
sender,
app_id,
pid,
pidfd,
cancellable,
error);
if (app_info)
{
g_set_error (error, XDP_APP_INFO_ERROR,
XDP_APP_INFO_ERROR_REDUNDANT_REGISTRATION,
"Process already registered with the same application ID");
return FALSE;
}

app_info = xdp_connection_create_host_app_info_sync (connection,
sender,
app_id,
pid,
pidfd,
cancellable,
error);
if (!app_info)
return FALSE;

return TRUE;
}
9 changes: 5 additions & 4 deletions src/xdp-app-info.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
typedef enum _XdpAppInfoError
{
XDP_APP_INFO_ERROR_WRONG_APP_KIND,
XDP_APP_INFO_ERROR_REDUNDANT_REGISTRATION,
} XdpAppInfoError;

#define XDP_APP_INFO_ERROR (xdp_app_info_error_quark ())
Expand Down Expand Up @@ -85,7 +86,7 @@ XdpAppInfo * xdp_invocation_ensure_app_info_sync (GDBusMethodInvocation *invoca
GCancellable *cancellable,
GError **error);

XdpAppInfo * xdp_invocation_register_host_app_info_sync (GDBusMethodInvocation *invocation,
const char *app_id,
GCancellable *cancellable,
GError **error);
gboolean xdp_invocation_register_host_app_info_sync (GDBusMethodInvocation *invocation,
const char *app_id,
GCancellable *cancellable,
GError **error);
31 changes: 31 additions & 0 deletions tests/test_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,34 @@ def test_multiple_connections(self, portals, dbus_con):
app_id2 = mock_intf2.GetSessionAppId(session2.handle)
assert app_id2 == expected_app_id
dbus_con2.close()

def test_redundant_register(self, portals, dbus_con):
registry_intf = xdp.get_portal_iface(dbus_con, "Registry", domain="host")
mock_intf = xdp.get_mock_iface(dbus_con)

expected_app_id = "org.example.CorrectAppId"

registry_intf.Register(expected_app_id, {})
session = self.create_dummy_session(dbus_con)
app_id = mock_intf.GetSessionAppId(session.handle)
assert app_id == expected_app_id

registry_intf.Register(expected_app_id, {})
session = self.create_dummy_session(dbus_con)
app_id = mock_intf.GetSessionAppId(session.handle)
assert app_id == expected_app_id

def test_conflicting_register(self, portals, dbus_con):
registry_intf = xdp.get_portal_iface(dbus_con, "Registry", domain="host")
mock_intf = xdp.get_mock_iface(dbus_con)

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

registry_intf.Register(expected_app_id, {})
session = self.create_dummy_session(dbus_con)
app_id = mock_intf.GetSessionAppId(session.handle)
assert app_id == expected_app_id

with pytest.raises(dbus.exceptions.DBusException):
registry_intf.Register(unexpected_app_id, {})

0 comments on commit 93995c1

Please sign in to comment.