diff options
author | Wim Taymans <wtaymans@redhat.com> | 2017-02-15 09:57:02 +0100 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2017-05-12 17:15:46 +0200 |
commit | 4b2f6ad5d1619e47be727cfed867a4c02ad3021d (patch) | |
tree | 225ee315cfd98d1cca96445db5608e6b63ea6953 | |
parent | 4eb5ededabefc31f63317b205080dd3cf1ebd09e (diff) |
module-flatpak: keep track of pending async checksflatpack
Keep a list of pending async requests indexed by the DBus path name.
When we get a reply, we can find the associated access_data again
and complete the check.
Cancel the portal request when the free callback is called. This can
happen when the client disconnects while we are waiting for the reply.
-rw-r--r-- | src/modules/module-flatpak.c | 84 |
1 files changed, 80 insertions, 4 deletions
diff --git a/src/modules/module-flatpak.c b/src/modules/module-flatpak.c index c7a568814..a5b76b8e4 100644 --- a/src/modules/module-flatpak.c +++ b/src/modules/module-flatpak.c @@ -93,6 +93,14 @@ struct userdata { pa_hashmap *clients; }; +struct async_pending { + PA_LLIST_FIELDS(struct async_pending); + bool handled; + struct client_data *client_data; + char *handle; + pa_access_data *access_data; +}; + struct client_data { struct userdata *u; @@ -101,11 +109,66 @@ struct client_data { pid_t pid; struct async_cache cached[PA_ACCESS_HOOK_MAX]; - pa_access_data *access_data; PA_LLIST_HEAD(struct visible_object, visible_objects); + PA_LLIST_HEAD(struct async_pending, pending); }; +static void close_request(struct async_pending *p) { + DBusMessage *m = NULL; + struct userdata *u = p->client_data->u; + + if (!(m = dbus_message_new_method_call("org.freedesktop.portal.Request", + p->handle, + "org.freedesktop.portal.Request", + "Close"))) { + pa_log_error("Failed to create message\n"); + return; + } + + if (!dbus_connection_send(pa_dbus_connection_get(u->connection), m, NULL)) + pa_log_error("Failed to send message\n"); + + dbus_message_unref(m); +} + +static void free_pending(void *userdata) { + struct async_pending *p = userdata; + struct client_data *cd = p->client_data; + + if (!p->handled) + close_request(p); + + PA_LLIST_REMOVE(struct async_pending, cd->pending, p); + pa_xfree(p->handle); + pa_xfree(p); +} + +static void add_pending(struct client_data *cd, const char *handle, pa_access_data *access_data) { + struct async_pending *p; + + p = pa_xnew0(struct async_pending, 1); + PA_LLIST_INIT(struct async_pending, p); + p->client_data = cd; + p->handle = pa_xstrdup(handle); + p->access_data = access_data; + p->handled = false; + + access_data->userdata = p; + access_data->free_cb = free_pending; + + PA_LLIST_PREPEND(struct async_pending, cd->pending, p); +} + +static struct async_pending *find_pending(struct client_data *cd, const char *handle) { + struct async_pending *p; + + PA_LLIST_FOREACH(p, cd->pending) { + if (pa_streq(p->handle, handle)) + return p; + } + return NULL; +} static void add_object(struct client_data *cd, int facility, uint32_t oidx) { struct visible_object *o; @@ -158,10 +221,14 @@ static struct client_data * client_data_new(struct userdata *u, uint32_t index, static void client_data_free(struct client_data *cd) { struct visible_object *o; + struct async_pending *p; while ((o = cd->visible_objects)) free_object(cd, o); + while ((p = cd->pending)) + free_pending(p); + pa_log_debug("removed client %d", cd->index); pa_xfree(cd); } @@ -227,11 +294,12 @@ static pa_access_result_t rule_block (pa_core *c, pa_access_data *d, void *u) { static DBusHandlerResult portal_response(DBusConnection *connection, DBusMessage *msg, void *user_data) { struct client_data *cd = user_data; - pa_access_data *d = cd->access_data; if (dbus_message_is_signal(msg, "org.freedesktop.portal.Request", "Response")) { uint32_t response = 2; DBusError error; + struct async_pending *p; + pa_access_data *d; dbus_error_init(&error); @@ -242,6 +310,13 @@ static DBusHandlerResult portal_response(DBusConnection *connection, DBusMessage dbus_error_free(&error); } + p = find_pending(cd, dbus_message_get_path(msg)); + if (p == NULL) + return DBUS_HANDLER_RESULT_HANDLED; + + p->handled = true; + d = p->access_data; + cd->cached[d->hook].checked = true; cd->cached[d->hook].result = response == 0 ? PA_ACCESS_GRANTED : PA_ACCESS_DENIED; @@ -273,14 +348,13 @@ static pa_access_result_t rule_check_portal (pa_core *c, pa_access_data *d, void pa_log_info("ask portal for operation %d/%d for client %d", d->hook, d->object_index, d->client_index); - cd->access_data = d; - dbus_error_init(&error); if (!(m = dbus_message_new_method_call("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop", "org.freedesktop.portal.Device", "AccessDevice"))) { + pa_log_error("Failed to create message\n"); return PA_ACCESS_DENIED; } @@ -338,6 +412,8 @@ static pa_access_result_t rule_check_portal (pa_core *c, pa_access_data *d, void dbus_connection_add_filter(pa_dbus_connection_get(u->connection), portal_response, cd, NULL); + add_pending(cd, handle, d); + return PA_ACCESS_ASYNC_CHECK; } |