summaryrefslogtreecommitdiff
path: root/gtk/gtkfilechoosernativeportal.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2017-07-01 19:13:03 -0400
committerMatthias Clasen <mclasen@redhat.com>2017-07-07 12:03:55 -0400
commit388078ba88561c64299fe892720452e679e00be3 (patch)
tree0d910ba0f4be093b7f05b1cb8d14d90548facffd /gtk/gtkfilechoosernativeportal.c
parent29ff3c072c61ce227a4b16840282293d74211a35 (diff)
downloadgtk+-388078ba88561c64299fe892720452e679e00be3.tar.gz
Avoid a race in the file chooser portal
Use the new predictable request object path and connect to the Response signal before issuing the portal call. This avoids a race that is pretty unlikely to hit in the filechooser case.
Diffstat (limited to 'gtk/gtkfilechoosernativeportal.c')
-rw-r--r--gtk/gtkfilechoosernativeportal.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/gtk/gtkfilechoosernativeportal.c b/gtk/gtkfilechoosernativeportal.c
index bf29442d09..6f686e434c 100644
--- a/gtk/gtkfilechoosernativeportal.c
+++ b/gtk/gtkfilechoosernativeportal.c
@@ -180,6 +180,7 @@ open_file_msg_cb (GObject *source_object,
GtkFileChooserNative *self = data->self;
GDBusMessage *reply;
GError *error = NULL;
+ g_autofree char *handle = NULL;
reply = g_dbus_connection_send_message_with_reply_finish (data->connection, res, &error);
@@ -197,8 +198,7 @@ open_file_msg_cb (GObject *source_object,
return;
}
- g_variant_get_child (g_dbus_message_get_body (reply), 0, "o",
- &data->portal_handle);
+ g_variant_get_child (g_dbus_message_get_body (reply), 0, "o", &handle);
if (data->hidden)
{
@@ -207,8 +207,13 @@ open_file_msg_cb (GObject *source_object,
filechooser_portal_data_free (data);
self->mode_data = NULL;
}
- else
+ else if (strcmp (handle, data->portal_handle) != 0)
{
+ g_free (data->portal_handle);
+ data->portal_handle = g_steal_pointer (&handle);
+ g_dbus_connection_signal_unsubscribe (data->connection,
+ data->portal_response_signal_id);
+
data->portal_response_signal_id =
g_dbus_connection_signal_subscribe (data->connection,
"org.freedesktop.portal.Desktop",
@@ -289,14 +294,42 @@ show_portal_file_chooser (GtkFileChooserNative *self,
GVariantBuilder opt_builder;
gboolean multiple;
const char *title;
+ char *token;
+ char *sender;
+ int i;
message = g_dbus_message_new_method_call ("org.freedesktop.portal.Desktop",
"/org/freedesktop/portal/desktop",
"org.freedesktop.portal.FileChooser",
data->method_name);
+ token = g_strdup_printf ("gtk%d", g_random_int_range (0, G_MAXINT));
+ sender = g_strdup (g_dbus_connection_get_unique_name (data->connection) + 1);
+ for (i = 0; sender[i]; i++)
+ if (sender[i] == '.')
+ sender[i] = '_';
+
+ data->portal_handle = g_strdup_printf ("/org/fredesktop/portal/desktop/request/%s/%s", sender, token);
+ g_free (sender);
+
+ data->portal_response_signal_id =
+ g_dbus_connection_signal_subscribe (data->connection,
+ "org.freedesktop.portal.Desktop",
+ "org.freedesktop.portal.Request",
+ "Response",
+ data->portal_handle,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
+ response_cb,
+ self, NULL);
+
multiple = gtk_file_chooser_get_select_multiple (GTK_FILE_CHOOSER (self));
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
+
+ g_variant_builder_add (&opt_builder, "{sv}", "handle_token",
+ g_variant_new_string (token));
+ g_free (token);
+
g_variant_builder_add (&opt_builder, "{sv}", "multiple",
g_variant_new_boolean (multiple));
if (self->accept_label)