[gnome-control-center] printers: Cancel async operations properly



commit a6b2db1e178d1f82409966a8ffa772955eea3525
Author: Marek Kasik <mkasik redhat com>
Date:   Tue Aug 7 11:54:11 2012 +0200

    printers: Cancel async operations properly
    
    Don't call callbacks of async functions called
    from Printers panel if they were cancelled.
    User data are not valid in that case (rhbz#845496).

 panels/printers/cc-printers-panel.c |   90 +++++++++++++++++++++++++++++------
 panels/printers/pp-utils.c          |   31 ++++++++++--
 panels/printers/pp-utils.h          |    5 +-
 3 files changed, 103 insertions(+), 23 deletions(-)
---
diff --git a/panels/printers/cc-printers-panel.c b/panels/printers/cc-printers-panel.c
index 9552724..ee7d69b 100644
--- a/panels/printers/cc-printers-panel.c
+++ b/panels/printers/cc-printers-panel.c
@@ -97,11 +97,17 @@ struct _CcPrintersPanelPrivate
   gboolean      getting_ppd_names;
   PPDList      *all_ppds_list;
   GHashTable   *preferred_drivers;
-  gboolean      getting_all_ppds;
+  GCancellable *get_all_ppds_cancellable;
 
   gpointer dummy;
 };
 
+typedef struct
+{
+  gchar        *printer_name;
+  GCancellable *cancellable;
+} SetPPDItem;
+
 static void actualize_jobs_list (CcPrintersPanel *self);
 static void actualize_printers_list (CcPrintersPanel *self);
 static void update_sensitivity (gpointer user_data);
@@ -193,6 +199,31 @@ cc_printers_panel_dispose (GObject *object)
       priv->preferred_drivers = NULL;
     }
 
+  if (priv->get_all_ppds_cancellable)
+    {
+      g_cancellable_cancel (priv->get_all_ppds_cancellable);
+      g_object_unref (priv->get_all_ppds_cancellable);
+      priv->get_all_ppds_cancellable = NULL;
+    }
+
+  if (priv->driver_change_list)
+    {
+      GList *iter;
+
+      for (iter = priv->driver_change_list; iter; iter = iter->next)
+        {
+          SetPPDItem *item = (SetPPDItem *) iter->data;
+
+          g_cancellable_cancel (item->cancellable);
+          g_object_unref (item->cancellable);
+          g_free (item->printer_name);
+          g_free (item);
+        }
+
+      g_list_free (priv->driver_change_list);
+      priv->driver_change_list = NULL;
+    }
+
   G_OBJECT_CLASS (cc_printers_panel_parent_class)->dispose (object);
 }
 
@@ -1977,10 +2008,16 @@ set_ppd_cb (gchar    *printer_name,
 
   for (iter = priv->driver_change_list; iter; iter = iter->next)
     {
-      if (g_strcmp0 ((gchar *) iter->data, printer_name) == 0)
+      SetPPDItem *item = (SetPPDItem *) iter->data;
+
+      if (g_strcmp0 (item->printer_name, printer_name) == 0)
         {
           priv->driver_change_list = g_list_remove_link (priv->driver_change_list, iter);
-          g_list_free_full (iter, g_free);
+
+          g_object_unref (item->cancellable);
+          g_free (item->printer_name);
+          g_free (item);
+          g_list_free (iter);
           break;
         }
     }
@@ -2040,12 +2077,18 @@ select_ppd_manually (GtkMenuItem *menuitem,
 
       if (printer_name && ppd_filename)
         {
+          SetPPDItem *item;
+
+          item = g_new0 (SetPPDItem, 1);
+          item->printer_name = g_strdup (printer_name);
+          item->cancellable = g_cancellable_new ();
+
           priv->driver_change_list =
-            g_list_prepend (priv->driver_change_list, g_strdup (printer_name));
+            g_list_prepend (priv->driver_change_list, item);
           update_sensitivity (self);
           printer_set_ppd_file_async (printer_name,
                                       ppd_filename,
-                                      NULL,
+                                      item->cancellable,
                                       set_ppd_cb,
                                       user_data);
         }
@@ -2080,12 +2123,18 @@ ppd_selection_dialog_response_cb (GtkDialog *dialog,
 
       if (printer_name && ppd_name)
         {
+          SetPPDItem *item;
+
+          item = g_new0 (SetPPDItem, 1);
+          item->printer_name = g_strdup (printer_name);
+          item->cancellable = g_cancellable_new ();
+
           priv->driver_change_list = g_list_prepend (priv->driver_change_list,
-                                                     g_strdup (printer_name));
+                                                     item);
           update_sensitivity (self);
           printer_set_ppd_async (printer_name,
                                  ppd_name,
-                                 NULL,
+                                 item->cancellable,
                                  set_ppd_cb,
                                  user_data);
         }
@@ -2173,12 +2222,18 @@ set_ppd_from_list (GtkMenuItem *menuitem,
 
   if (printer_name && ppd_name)
     {
+      SetPPDItem *item;
+
+      item = g_new0 (SetPPDItem, 1);
+      item->printer_name = g_strdup (printer_name);
+      item->cancellable = g_cancellable_new ();
+
       priv->driver_change_list = g_list_prepend (priv->driver_change_list,
-                                                 g_strdup (printer_name));
+                                                 item);
       update_sensitivity (self);
       printer_set_ppd_async (printer_name,
                              ppd_name,
-                             NULL,
+                             item->cancellable,
                              set_ppd_cb,
                              user_data);
     }
@@ -2607,7 +2662,9 @@ update_sensitivity (gpointer user_data)
 
       for (iter = priv->driver_change_list; iter; iter = iter->next)
         {
-          if (g_strcmp0 ((gchar *) iter->data, priv->dests[priv->current_dest].name) == 0)
+          SetPPDItem *item = (SetPPDItem *) iter->data;
+
+          if (g_strcmp0 (item->printer_name, priv->dests[priv->current_dest].name) == 0)
             {
               is_changing_driver = TRUE;
             }
@@ -2820,11 +2877,12 @@ get_all_ppds_async_cb (PPDList  *ppds,
 
   priv->all_ppds_list = ppds;
 
-  priv->getting_all_ppds = FALSE;
-
   if (priv->pp_ppd_selection_dialog)
     pp_ppd_selection_dialog_set_ppd_list (priv->pp_ppd_selection_dialog,
                                           priv->all_ppds_list);
+
+  g_object_unref (priv->get_all_ppds_cancellable);
+  priv->get_all_ppds_cancellable = NULL;
 }
 
 static void
@@ -2901,7 +2959,7 @@ cc_printers_panel_init (CcPrintersPanel *self)
   priv->getting_ppd_names = FALSE;
 
   priv->all_ppds_list = NULL;
-  priv->getting_all_ppds = FALSE;
+  priv->get_all_ppds_cancellable = NULL;
 
   priv->preferred_drivers = NULL;
 
@@ -3049,8 +3107,10 @@ Please check your installation");
   populate_jobs_list (self);
   attach_to_cups_notifier (self);
 
-  priv->getting_all_ppds = TRUE;
-  get_all_ppds_async (get_all_ppds_async_cb, self);
+  priv->get_all_ppds_cancellable = g_cancellable_new ();
+  get_all_ppds_async (priv->get_all_ppds_cancellable,
+                      get_all_ppds_async_cb,
+                      self);
 
   http = httpConnectEncrypt (cupsServer (), ippPort (), cupsEncryption ());
   if (!http)
diff --git a/panels/printers/pp-utils.c b/panels/printers/pp-utils.c
index 5ca00f2..599bd1a 100644
--- a/panels/printers/pp-utils.c
+++ b/panels/printers/pp-utils.c
@@ -2846,9 +2846,12 @@ printer_set_ppd_async_dbus_cb (GObject      *source_object,
       g_error_free (error);
     }
 
-  data->callback (g_strdup (data->printer_name),
-                  result,
-                  data->user_data);
+  /* Don't call callback if cancelled */
+  if (!data->cancellable ||
+      !g_cancellable_is_cancelled (data->cancellable))
+    data->callback (g_strdup (data->printer_name),
+                    result,
+                    data->user_data);
 
   if (data->cancellable)
     g_object_unref (data->cancellable);
@@ -3770,6 +3773,7 @@ get_ppd_names_async (gchar        *printer_name,
 typedef struct
 {
   PPDList      *result;
+  GCancellable *cancellable;
   GAPCallback   callback;
   gpointer      user_data;
   GMainContext *context;
@@ -3780,7 +3784,17 @@ get_all_ppds_idle_cb (gpointer user_data)
 {
   GAPData *data = (GAPData *) user_data;
 
-  data->callback (data->result, data->user_data);
+  /* Don't call callback if cancelled */
+  if (data->cancellable &&
+      g_cancellable_is_cancelled (data->cancellable))
+    {
+      ppd_list_free (data->result);
+      data->result = NULL;
+    }
+  else
+    {
+      data->callback (data->result, data->user_data);
+    }
 
   return FALSE;
 }
@@ -3792,6 +3806,8 @@ get_all_ppds_data_free (gpointer user_data)
 
   if (data->context)
     g_main_context_unref (data->context);
+  if (data->cancellable)
+    g_object_unref (data->cancellable);
   g_free (data);
 }
 
@@ -4121,14 +4137,17 @@ get_all_ppds_func (gpointer user_data)
  * Get names of all installed PPDs sorted by manufacturers names.
  */
 void
-get_all_ppds_async (GAPCallback callback,
-                    gpointer    user_data)
+get_all_ppds_async (GCancellable *cancellable,
+                    GAPCallback   callback,
+                    gpointer      user_data)
 {
   GAPData *data;
   GThread *thread;
   GError  *error = NULL;
 
   data = g_new0 (GAPData, 1);
+  if (cancellable)
+    data->cancellable = g_object_ref (cancellable);
   data->callback = callback;
   data->user_data = user_data;
   data->context = g_main_context_ref_thread_default ();
diff --git a/panels/printers/pp-utils.h b/panels/printers/pp-utils.h
index 5b4b71e..156b961 100644
--- a/panels/printers/pp-utils.h
+++ b/panels/printers/pp-utils.h
@@ -161,8 +161,9 @@ void        get_ppd_names_async (gchar        *printer_name,
 typedef void (*GAPCallback) (PPDList  *ppds,
                              gpointer  user_data);
 
-void        get_all_ppds_async (GAPCallback callback,
-                                gpointer    user_data);
+void        get_all_ppds_async (GCancellable *cancellable,
+                                GAPCallback   callback,
+                                gpointer      user_data);
 
 PPDList    *ppd_list_copy (PPDList *list);
 void        ppd_list_free (PPDList *list);



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