[gnome-control-center] applications: Make async file operations cancellable



commit 3565216b5bb664ba590c0a6907896b14f1934cf8
Author: Robert Ancell <robert ancell canonical com>
Date:   Wed Mar 13 16:40:46 2019 +1300

    applications: Make async file operations cancellable
    
    The previous operations could crash if the panel was changed during an operation.

 panels/applications/cc-applications-panel.c | 38 +++++++++++++++++++-------
 panels/applications/utils.c                 | 42 ++++++++++++++++++++++++++---
 panels/applications/utils.h                 | 11 ++++++++
 3 files changed, 78 insertions(+), 13 deletions(-)
---
diff --git a/panels/applications/cc-applications-panel.c b/panels/applications/cc-applications-panel.c
index de6730547..2ab0c321d 100644
--- a/panels/applications/cc-applications-panel.c
+++ b/panels/applications/cc-applications-panel.c
@@ -1221,10 +1221,16 @@ set_cache_size (GObject      *source,
 {
   CcApplicationsPanel *self = data;
   g_autofree gchar *formatted_size = NULL;
-  guint64 *size;
+  guint64 size;
+  g_autoptr(GError) error = NULL;
 
-  size = g_object_get_data (G_OBJECT (res), "size");
-  self->cache_size = *size;
+  if (!file_size_finish (G_FILE (source), res, &size, &error))
+    {
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        g_warning ("Failed to get flatpak cache size: %s", error->message);
+      return;
+    }
+  self->cache_size = size;
 
   formatted_size = g_format_size (self->cache_size);
   g_object_set (self->cache, "info", formatted_size, NULL);
@@ -1240,7 +1246,7 @@ update_cache_row (CcApplicationsPanel *self,
 {
   g_autoptr(GFile) dir = get_flatpak_app_dir (app_id, "cache");
   g_object_set (self->cache, "info", "...", NULL);
-  file_size_async (dir, set_cache_size, self);
+  file_size_async (dir, self->cancellable, set_cache_size, self);
 }
 
 static void
@@ -1250,10 +1256,16 @@ set_data_size (GObject      *source,
 {
   CcApplicationsPanel *self = data;
   g_autofree gchar *formatted_size = NULL;
-  guint64 *size;
+  guint64 size;
+  g_autoptr(GError) error = NULL;
 
-  size = g_object_get_data (G_OBJECT (res), "size");
-  self->data_size = *size;
+  if (!file_size_finish (G_FILE (source), res, &size, &error))
+    {
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        g_warning ("Failed to get flatpak data size: %s", error->message);
+      return;
+    }
+  self->data_size = size;
 
   formatted_size = g_format_size (self->data_size);
   g_object_set (self->data, "info", formatted_size, NULL);
@@ -1268,7 +1280,7 @@ update_data_row (CcApplicationsPanel *self,
   g_autoptr(GFile) dir = get_flatpak_app_dir (app_id, "data");
 
   g_object_set (self->data, "info", "...", NULL);
-  file_size_async (dir, set_data_size, self);
+  file_size_async (dir, self->cancellable, set_data_size, self);
 }
 
 static void
@@ -1277,6 +1289,14 @@ cache_cleared (GObject      *source,
                gpointer      data)
 {
   CcApplicationsPanel *self = data;
+  g_autoptr(GError) error = NULL;
+
+  if (!file_remove_finish (G_FILE (source), res, &error))
+    {
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        g_warning ("Failed to remove cache: %s", error->message);
+      return;
+    }
 
   update_cache_row (self, self->current_app_id);
 }
@@ -1290,7 +1310,7 @@ clear_cache_cb (CcApplicationsPanel *self)
     return;
 
   dir = get_flatpak_app_dir (self->current_app_id, "cache");
-  file_remove_async (dir, cache_cleared, self);
+  file_remove_async (dir, self->cancellable, cache_cleared, self);
 }
 static void
 update_app_row (CcApplicationsPanel *self,
diff --git a/panels/applications/utils.c b/panels/applications/utils.c
index 0f8cc2976..622a94368 100644
--- a/panels/applications/utils.c
+++ b/panels/applications/utils.c
@@ -42,7 +42,7 @@ ftw_remove_cb (const gchar       *path,
 }
 
 static void
-file_remove_thread_func (GTask       *task,
+file_remove_thread_func (GTask        *task,
                          gpointer      source_object,
                          gpointer      task_data,
                          GCancellable *cancellable)
@@ -51,17 +51,31 @@ file_remove_thread_func (GTask       *task,
   g_autofree gchar *path = g_file_get_path (file);
 
   nftw (path, ftw_remove_cb, 20, FTW_DEPTH);
+
+  if (g_task_set_return_on_cancel (task, FALSE))
+    g_task_return_boolean (task, TRUE);
 }
 
 void
 file_remove_async (GFile               *file,
+                   GCancellable        *cancellable,
                    GAsyncReadyCallback  callback,
                    gpointer             data)
 {
-  g_autoptr(GTask) task = g_task_new (file, NULL, callback, data);
+  g_autoptr(GTask) task = g_task_new (file, cancellable, callback, data);
+  g_task_set_return_on_cancel (task, TRUE);
   g_task_run_in_thread (task, file_remove_thread_func);
 }
 
+gboolean
+file_remove_finish (GFile        *file,
+                    GAsyncResult *result,
+                    GError      **error)
+{
+  g_return_val_if_fail (g_task_is_valid (result, file), FALSE);
+  return g_task_propagate_boolean (G_TASK (result), error);
+}
+
 static GPrivate size_key = G_PRIVATE_INIT (g_free);
 
 static gint
@@ -93,18 +107,38 @@ file_size_thread_func (GTask        *task,
   total = g_new0 (guint64, 1);
   *total = *(guint64*)g_private_get (&size_key);
 
-  g_object_set_data_full (G_OBJECT (task), "size", total, g_free);
+  if (g_task_set_return_on_cancel (task, FALSE))
+    g_task_return_pointer (task, total, g_free);
 }
 
 void
 file_size_async (GFile               *file,
+                 GCancellable        *cancellable,
                  GAsyncReadyCallback  callback,
                  gpointer             data)
 {
-  g_autoptr(GTask) task = g_task_new (file, NULL, callback, data);
+  g_autoptr(GTask) task = g_task_new (file, cancellable, callback, data);
+  g_task_set_return_on_cancel (task, TRUE);
   g_task_run_in_thread (task, file_size_thread_func);
 }
 
+gboolean
+file_size_finish (GFile        *file,
+                  GAsyncResult *result,
+                  guint64      *size,
+                  GError      **error)
+{
+  g_autofree guint64 *data = NULL;
+
+  g_return_val_if_fail (g_task_is_valid (result, file), FALSE);
+  data = g_task_propagate_pointer (G_TASK (result), error);
+  if (data == NULL)
+    return FALSE;
+  if (size != NULL)
+    *size = *data;
+  return TRUE;
+}
+
 void
 container_remove_all (GtkContainer *container)
 {
diff --git a/panels/applications/utils.h b/panels/applications/utils.h
index 557e455b6..a2e39229a 100644
--- a/panels/applications/utils.h
+++ b/panels/applications/utils.h
@@ -26,13 +26,24 @@
 G_BEGIN_DECLS
 
 void      file_remove_async    (GFile               *file,
+                                GCancellable        *cancellable,
                                 GAsyncReadyCallback  callback,
                                 gpointer             data);
 
+gboolean  file_remove_finish   (GFile               *file,
+                                GAsyncResult        *result,
+                                GError             **error);
+
 void      file_size_async      (GFile               *file,
+                                GCancellable        *cancellable,
                                 GAsyncReadyCallback  callback,
                                 gpointer             data);
 
+gboolean  file_size_finish     (GFile               *file,
+                                GAsyncResult        *result,
+                                guint64             *size,
+                                GError             **error);
+
 void      container_remove_all (GtkContainer        *container);
 
 GKeyFile* get_flatpak_metadata (const gchar         *app_id);


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