[gnome-control-center] printers: Make call of DevicesGet cancellable



commit 6e479859ed06316ec7872efbb7c8f48321dfff7b
Author: Marek Kasik <mkasik redhat com>
Date:   Mon Apr 18 16:14:27 2011 +0200

    printers: Make call of DevicesGet cancellable
    
    Pass a GCancellable object to g_dbus_proxy_call() for DevicesGet
    method. This assures that g-c-c won't crash when user cancels addition
    of new printer before the call is finished (rhbz#691931).

 panels/printers/pp-new-printer-dialog.c |  219 +++++++++++++++++--------------
 1 files changed, 120 insertions(+), 99 deletions(-)
---
diff --git a/panels/printers/pp-new-printer-dialog.c b/panels/printers/pp-new-printer-dialog.c
index 0c5a0a5..194afe5 100644
--- a/panels/printers/pp-new-printer-dialog.c
+++ b/panels/printers/pp-new-printer-dialog.c
@@ -112,6 +112,8 @@ struct _PpNewPrinterDialog {
 
   UserResponseCallback user_callback;
   gpointer             user_data;
+
+  GCancellable *cancellable;
 };
 
 static void
@@ -198,11 +200,11 @@ store_device_parameter (gpointer key,
 }
 
 static void
-devices_get_cb (GObject *source_object,
+devices_get_cb (GObject      *source_object,
                 GAsyncResult *res,
-                gpointer user_data)
+                gpointer      user_data)
 {
-  PpNewPrinterDialog *pp = (PpNewPrinterDialog *) user_data;
+  PpNewPrinterDialog *pp = user_data;
   GHashTable         *devices = NULL;
   GtkWidget          *widget = NULL;
   GVariant           *dg_output = NULL;
@@ -214,136 +216,145 @@ devices_get_cb (GObject *source_object,
                                         res,
                                         &error);
 
-  if (dg_output && g_variant_n_children (dg_output) == 2)
+  if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
     {
-      GVariant *devices_variant = NULL;
+      if (dg_output && g_variant_n_children (dg_output) == 2)
+        {
+          GVariant *devices_variant = NULL;
 
-      g_variant_get (dg_output, "(&s a{ss})",
-                     &ret_error,
-                     &devices_variant);
+          g_variant_get (dg_output, "(&s a{ss})",
+                         &ret_error,
+                         &devices_variant);
 
-      if (devices_variant)
-        {
-          if (g_variant_is_of_type (devices_variant, G_VARIANT_TYPE ("a{ss}")))
+          if (devices_variant)
             {
-              GVariantIter *iter;
-              GVariant *item;
-              g_variant_get (devices_variant,
-                             "a{ss}",
-                             &iter);
-              devices = g_hash_table_new (g_str_hash, g_str_equal);
-              while ((item = g_variant_iter_next_value (iter)))
+              if (g_variant_is_of_type (devices_variant, G_VARIANT_TYPE ("a{ss}")))
                 {
-                  gchar *key;
-                  gchar *value;
-                  g_variant_get (item,
-                                 "{ss}",
-                                 &key,
-                                 &value);
-  
-                  g_hash_table_insert (devices, key, value);
+                  GVariantIter *iter;
+                  GVariant *item;
+                  g_variant_get (devices_variant,
+                                 "a{ss}",
+                                 &iter);
+                  devices = g_hash_table_new (g_str_hash, g_str_equal);
+                  while ((item = g_variant_iter_next_value (iter)))
+                    {
+                      gchar *key;
+                      gchar *value;
+                      g_variant_get (item,
+                                     "{ss}",
+                                     &key,
+                                     &value);
+
+                      g_hash_table_insert (devices, key, value);
+                    }
                 }
+              g_variant_unref (devices_variant);
             }
-          g_variant_unref (devices_variant);
+          g_variant_unref (dg_output);
         }
-      g_variant_unref (dg_output);
-    }
-  g_object_unref (source_object);
-
-  if (error || (ret_error && ret_error[0] != '\0'))
-    {
-      if (error)
-        g_warning ("%s", error->message);
-
-      if (ret_error && ret_error[0] != '\0')
-        g_warning ("%s", ret_error);
-    }
+      g_object_unref (source_object);
 
-  free_devices (pp);
-  if (devices)
-    {
-      GList *keys;
-      GList *iter;
-      gchar *cut;
-      gint   max_index = -1;
-      gint   index;
-
-      keys = g_hash_table_get_keys (devices);
-      for (iter = keys; iter; iter = iter->next)
+      if (error || (ret_error && ret_error[0] != '\0'))
         {
-          index = -1;
-
-          cut = g_strrstr ((gchar *)iter->data, ":");
-          if (cut)
-            index = atoi (cut + 1);
+          if (error)
+            g_warning ("%s", error->message);
 
-          if (index > max_index)
-            max_index = index;
+          if (ret_error && ret_error[0] != '\0')
+            g_warning ("%s", ret_error);
         }
 
-      if (max_index >= 0)
+      free_devices (pp);
+      if (devices)
         {
-          pp->num_devices = max_index + 1;
-          pp->devices = g_new0 (CupsDevice, pp->num_devices);
+          GList *keys;
+          GList *iter;
+          gchar *cut;
+          gint   max_index = -1;
+          gint   index;
+
+          keys = g_hash_table_get_keys (devices);
+          for (iter = keys; iter; iter = iter->next)
+            {
+              index = -1;
+
+              cut = g_strrstr ((gchar *)iter->data, ":");
+              if (cut)
+                index = atoi (cut + 1);
 
-          g_hash_table_foreach (devices, store_device_parameter, pp);
+              if (index > max_index)
+                max_index = index;
+            }
 
-          /* Assign names to devices */
-          for (i = 0; i < pp->num_devices; i++)
+          if (max_index >= 0)
             {
-              gchar *name = NULL;
+              pp->num_devices = max_index + 1;
+              pp->devices = g_new0 (CupsDevice, pp->num_devices);
 
-              if (pp->devices[i].device_id)
-                {
-                  name = get_tag_value (pp->devices[i].device_id, "mdl");
-                  name = g_strcanon (name, ALLOWED_CHARACTERS, '-');
-                }
-              else if (pp->devices[i].device_info)
+              g_hash_table_foreach (devices, store_device_parameter, pp);
+
+              /* Assign names to devices */
+              for (i = 0; i < pp->num_devices; i++)
                 {
-                  name = g_strdup (pp->devices[i].device_info);
-                  name = g_strcanon (name, ALLOWED_CHARACTERS, '-');
-                }
+                  gchar *name = NULL;
 
-              pp->devices[i].display_name = name;
-            }
+                  if (pp->devices[i].device_id)
+                    {
+                      name = get_tag_value (pp->devices[i].device_id, "mdl");
+                      name = g_strcanon (name, ALLOWED_CHARACTERS, '-');
+                    }
+                  else if (pp->devices[i].device_info)
+                    {
+                      name = g_strdup (pp->devices[i].device_info);
+                      name = g_strcanon (name, ALLOWED_CHARACTERS, '-');
+                    }
 
-          /* Set show bool
-           * Don't show duplicates.
-           * Show devices with device-id.
-           * Other preferences should apply here.
-           */
-          for (i = 0; i < pp->num_devices; i++)
-            {
-              for (j = 0; j < pp->num_devices; j++)
+                  pp->devices[i].display_name = name;
+                }
+
+              /* Set show bool
+               * Don't show duplicates.
+               * Show devices with device-id.
+               * Other preferences should apply here.
+               */
+              for (i = 0; i < pp->num_devices; i++)
                 {
-                  if (i != j)
+                  for (j = 0; j < pp->num_devices; j++)
                     {
-                      if (g_strcmp0 (pp->devices[i].display_name, pp->devices[j].display_name) == 0)
+                      if (i != j)
                         {
-                          if (pp->devices[i].device_id && !pp->devices[j].show)
+                          if (g_strcmp0 (pp->devices[i].display_name, pp->devices[j].display_name) == 0)
                             {
-                              pp->devices[i].show = TRUE;
+                              if (pp->devices[i].device_id && !pp->devices[j].show)
+                                {
+                                  pp->devices[i].show = TRUE;
+                                }
                             }
                         }
                     }
                 }
             }
+
+          g_hash_table_destroy (devices);
+          actualize_devices_list (pp);
         }
 
-      g_hash_table_destroy (devices);
-      actualize_devices_list (pp);
-    }
+      widget = (GtkWidget*)
+        gtk_builder_get_object (pp->builder, "get-devices-status-label");
+      gtk_label_set_text (GTK_LABEL (widget), " ");
 
-  widget = (GtkWidget*)
-    gtk_builder_get_object (pp->builder, "get-devices-status-label");
-  gtk_label_set_text (GTK_LABEL (widget), " ");
+      widget = (GtkWidget*)
+        gtk_builder_get_object (pp->builder, "spinner");
+      gtk_spinner_stop (GTK_SPINNER (widget));
+      gtk_widget_set_sensitive (widget, FALSE);
 
-  widget = (GtkWidget*)
-    gtk_builder_get_object (pp->builder, "spinner");
-  gtk_spinner_stop (GTK_SPINNER (widget));
-  gtk_widget_set_sensitive (widget, FALSE);
+      if (pp->cancellable != NULL)
+        {
+          g_object_unref (pp->cancellable);
+          pp->cancellable = NULL;
+        }
 
-  g_clear_error (&error);
+      g_clear_error (&error);
+    }
 }
 
 static void
@@ -385,12 +396,14 @@ devices_get (PpNewPrinterDialog *pp)
       gtk_spinner_start (GTK_SPINNER (widget));
       gtk_widget_set_sensitive (widget, TRUE);
 
+      pp->cancellable = g_cancellable_new ();
+
       g_dbus_proxy_call (proxy,
                          "DevicesGet",
                          dg_input,
                          G_DBUS_CALL_FLAGS_NONE,
                          60000,
-                         NULL,
+                         pp->cancellable,
                          devices_get_cb,
                          pp);
 
@@ -1101,6 +1114,8 @@ pp_new_printer_dialog_new (GtkWindow            *parent,
   pp->user_callback = user_callback;
   pp->user_data = user_data;
 
+  pp->cancellable = NULL;
+
   /* connect signals */
   g_signal_connect (pp->dialog, "delete-event", G_CALLBACK (gtk_widget_hide_on_delete), NULL);
 
@@ -1145,6 +1160,12 @@ pp_new_printer_dialog_free (PpNewPrinterDialog *pp)
   g_object_unref (pp->builder);
   pp->builder = NULL;
 
+  if (pp->cancellable)
+    {
+      g_cancellable_cancel (pp->cancellable);
+      g_object_unref (pp->cancellable);
+    }
+
   g_free (pp);
 }
 



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