[gtk+/portal-race: 2/2] Avoid a race in the print portal



commit d9e38198c7774a466203e7229fe241f417306a65
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Jul 1 20:14:15 2017 -0400

    Avoid a race in the print portal
    
    Same as the previous commit; use the new predictable request
    object path to connect to the Response signal early.

 gtk/gtkprintoperation-portal.c |   55 ++++++++++++++++++++++++++++++++--------
 1 files changed, 44 insertions(+), 11 deletions(-)
---
diff --git a/gtk/gtkprintoperation-portal.c b/gtk/gtkprintoperation-portal.c
index 1272767..faeee25 100644
--- a/gtk/gtkprintoperation-portal.c
+++ b/gtk/gtkprintoperation-portal.c
@@ -53,6 +53,7 @@ typedef struct {
   GVariant *settings;
   GVariant *setup;
   GVariant *options;
+  char *prepare_print_handle;
 } PortalData;
 
 static void
@@ -70,7 +71,7 @@ portal_data_free (gpointer data)
     g_variant_unref (portal->setup);
   if (portal->options)
     g_variant_unref (portal->options);
-
+  g_free (portal->prepare_print_handle);
   g_free (portal);
 }
 
@@ -453,16 +454,23 @@ prepare_print_called (GObject      *source,
   else
     g_variant_get (ret, "(&o)", &handle);
 
-  portal->response_signal_id =
-    g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
-                                        "org.freedesktop.portal.Desktop",
-                                        "org.freedesktop.portal.Request",
-                                        "Response",
-                                        handle,
-                                        NULL,
-                                        G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
-                                        prepare_print_response,
-                                        portal, NULL);
+  if (strcmp (portal->prepare_print_handle, handle) != 0)
+    {
+      g_free (portal->prepare_print_handle);
+      portal->prepare_print_handle = g_strdup (handle);
+      g_dbus_connection_signal_unsubscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
+                                            portal->response_signal_id);
+      portal->response_signal_id =
+        g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
+                                            "org.freedesktop.portal.Desktop",
+                                            "org.freedesktop.portal.Request",
+                                            "Response",
+                                            handle,
+                                            NULL,
+                                            G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
+                                            prepare_print_response,
+                                            portal, NULL);
+     }
 
   g_variant_unref (ret);
 }
@@ -547,8 +555,33 @@ call_prepare_print (GtkPrintOperation *op,
 {
   GtkPrintOperationPrivate *priv = op->priv;
   GVariantBuilder opt_builder;
+  char *token;
+  char *sender;
+  int i;
+
+  token = g_strdup_printf ("gtk%d", g_random_int_range (0, G_MAXINT));
+  sender = g_strdup (g_dbus_connection_get_unique_name (g_dbus_proxy_get_connection (portal->proxy)) + 1);
+  for (i = 0; sender[i]; i++)
+    if (sender[i] == '.')
+      sender[i] = '_';
+
+  portal->prepare_print_handle = g_strdup_printf ("/org/fredesktop/portal/desktop/request/%s/%s", sender, 
token);
+  g_free (sender);
+
+  portal->response_signal_id =
+    g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (G_DBUS_PROXY (portal->proxy)),
+                                        "org.freedesktop.portal.Desktop",
+                                        "org.freedesktop.portal.Request",
+                                        "Response",
+                                        portal->prepare_print_handle,
+                                        NULL,
+                                        G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
+                                        prepare_print_response,
+                                        portal, NULL);
 
   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);
   portal->options = g_variant_builder_end (&opt_builder);
 
   if (priv->print_settings)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]