[gnome-software/wip/rancell/bgo789680] Use the correct GCancellable when switching between apps



commit a13319bba9dfd300bbf1f0dda260852ad9ba112f
Author: Robert Ancell <robert ancell canonical com>
Date:   Tue Oct 31 16:56:49 2017 +1300

    Use the correct GCancellable when switching between apps
    
    Fixes https://bugzilla.gnome.org/show_bug.cgi?id=789680

 lib/gs-plugin-loader.c |   74 ++++++++++++++++++++++++++++++++++++++++++++---
 lib/gs-plugin-loader.h |    2 +
 src/gs-details-page.c  |    7 ++++
 3 files changed, 78 insertions(+), 5 deletions(-)
---
diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c
index 8e0e7a0..62ad0f0 100644
--- a/lib/gs-plugin-loader.c
+++ b/lib/gs-plugin-loader.c
@@ -50,6 +50,7 @@ typedef struct
        GPtrArray               *auth_array;
        GPtrArray               *file_monitors;
        GsPluginStatus           global_status_last;
+       GPtrArray               *tasks;
 
        GMutex                   pending_apps_mutex;
        GPtrArray               *pending_apps;
@@ -1602,6 +1603,52 @@ gs_plugin_loader_job_get_categories_thread_cb (GTask *task,
        g_task_return_pointer (task, g_ptr_array_ref (helper->catlist), (GDestroyNotify) g_ptr_array_unref);
 }
 
+typedef struct
+{
+       GAsyncReadyCallback callback;
+       gpointer user_data;
+} GsTaskHelper;
+
+static GsTaskHelper *
+gs_task_helper_new (GAsyncReadyCallback callback, gpointer user_data)
+{
+       GsTaskHelper *helper = g_slice_new0 (GsTaskHelper);
+       helper->callback = callback;
+       helper->user_data = user_data;
+       return helper;
+}
+
+static void
+gs_task_helper_free (GsTaskHelper *helper)
+{
+       g_slice_free (GsTaskHelper, helper);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GsTaskHelper, gs_task_helper_free)
+
+static void
+task_ready_cb (GObject *object, GAsyncResult *res, gpointer user_data)
+{
+       GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (GS_PLUGIN_LOADER (object));
+       g_autoptr(GsTaskHelper) helper = user_data;
+       helper->callback (object, res, helper->user_data);
+       g_ptr_array_remove (priv->tasks, res);
+}
+
+static GTask *
+create_task (GsPluginLoader *plugin_loader, GCancellable *cancellable, GAsyncReadyCallback callback, 
gpointer user_data)
+{
+       GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (plugin_loader);
+       GsTaskHelper *helper;
+       GTask *task;
+
+       helper = gs_task_helper_new (callback, user_data);
+       task = g_task_new (plugin_loader, cancellable, task_ready_cb, helper);
+       g_ptr_array_add (priv->tasks, task);
+
+       return task;
+}
+
 /**
  * gs_plugin_loader_job_get_categories_async:
  *
@@ -1627,7 +1674,7 @@ gs_plugin_loader_job_get_categories_async (GsPluginLoader *plugin_loader,
        helper->catlist = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
 
        /* run in a thread */
-       task = g_task_new (plugin_loader, cancellable, callback, user_data);
+       task = create_task (plugin_loader, cancellable, callback, user_data);
        g_task_set_task_data (task, helper, (GDestroyNotify) gs_plugin_loader_helper_free);
        g_task_run_in_thread (task, gs_plugin_loader_job_get_categories_thread_cb);
 }
@@ -2702,6 +2749,7 @@ gs_plugin_loader_finalize (GObject *object)
        g_free (priv->language);
        g_object_unref (priv->global_cache);
        g_ptr_array_unref (priv->file_monitors);
+       g_ptr_array_unref (priv->tasks);
        g_hash_table_unref (priv->events_by_id);
        g_hash_table_unref (priv->disallow_updates);
 
@@ -2800,6 +2848,7 @@ gs_plugin_loader_init (GsPluginLoader *plugin_loader)
        priv->pending_apps = g_ptr_array_new_with_free_func ((GFreeFunc) g_object_unref);
        priv->auth_array = g_ptr_array_new_with_free_func ((GFreeFunc) g_object_unref);
        priv->file_monitors = g_ptr_array_new_with_free_func ((GFreeFunc) g_object_unref);
+       priv->tasks = g_ptr_array_new_with_free_func ((GFreeFunc) g_object_unref);
        priv->locations = g_ptr_array_new_with_free_func (g_free);
        priv->profile = as_profile_new ();
        priv->settings = g_settings_new ("org.gnome.software");
@@ -3376,6 +3425,7 @@ static void
 gs_plugin_loader_cancelled_cb (GCancellable *cancellable, GsPluginLoaderHelper *helper)
 {
        /* just proxy this forward */
+  g_printerr ("PROXY CANCEL %p -> %p\n", cancellable, helper->cancellable);
        g_cancellable_cancel (helper->cancellable);
 }
 
@@ -3404,7 +3454,7 @@ gs_plugin_loader_job_process_async (GsPluginLoader *plugin_loader,
        /* check job has valid action */
        if (gs_plugin_job_get_action (plugin_job) == GS_PLUGIN_ACTION_UNKNOWN) {
                g_autofree gchar *job_str = gs_plugin_job_to_string (plugin_job);
-               task = g_task_new (plugin_loader, cancellable_job, callback, user_data);
+               task = create_task (plugin_loader, cancellable_job, callback, user_data);
                g_task_return_new_error (task,
                                         GS_PLUGIN_ERROR,
                                         GS_PLUGIN_ERROR_NOT_SUPPORTED,
@@ -3417,7 +3467,7 @@ gs_plugin_loader_job_process_async (GsPluginLoader *plugin_loader,
        if (action == GS_PLUGIN_ACTION_REMOVE) {
                if (remove_app_from_install_queue (plugin_loader, gs_plugin_job_get_app (plugin_job))) {
                        GsAppList *list = gs_plugin_job_get_list (plugin_job);
-                       task = g_task_new (plugin_loader, cancellable, callback, user_data);
+                       task = create_task (plugin_loader, cancellable, callback, user_data);
                        g_task_return_pointer (task, g_object_ref (list), (GDestroyNotify) g_object_unref);
                        return;
                }
@@ -3426,7 +3476,7 @@ gs_plugin_loader_job_process_async (GsPluginLoader *plugin_loader,
            !gs_plugin_loader_get_network_available (plugin_loader)) {
                GsAppList *list = gs_plugin_job_get_list (plugin_job);
                add_app_to_install_queue (plugin_loader, gs_plugin_job_get_app (plugin_job));
-               task = g_task_new (plugin_loader, cancellable, callback, user_data);
+               task = create_task (plugin_loader, cancellable, callback, user_data);
                g_task_return_pointer (task, g_object_ref (list), (GDestroyNotify) g_object_unref);
                return;
        }
@@ -3480,7 +3530,7 @@ gs_plugin_loader_job_process_async (GsPluginLoader *plugin_loader,
        }
 
        /* check required args */
-       task = g_task_new (plugin_loader, cancellable_job, callback, user_data);
+       task = create_task (plugin_loader, cancellable_job, callback, user_data);
        switch (action) {
        case GS_PLUGIN_ACTION_SEARCH:
        case GS_PLUGIN_ACTION_SEARCH_FILES:
@@ -3652,6 +3702,20 @@ gs_plugin_loader_get_system_app (GsPluginLoader *plugin_loader)
        return gs_plugin_loader_app_create (plugin_loader, "*/*/*/*/system/*");
 }
 
+GCancellable *
+gs_plugin_loader_get_cancellable (GsPluginLoader *plugin_loader, GsApp *app)
+{
+       GsPluginLoaderPrivate *priv = gs_plugin_loader_get_instance_private (plugin_loader);
+       for (guint i = 0; i < priv->tasks->len; i++) {
+               GTask *task = g_ptr_array_index (priv->tasks, i);
+               GsPluginLoaderHelper *helper = g_task_get_task_data (task);
+               if (gs_plugin_job_get_app (helper->plugin_job) == app)
+                       return helper->cancellable;
+       }
+
+       return NULL;
+}
+
 AsProfile *
 gs_plugin_loader_get_profile (GsPluginLoader *plugin_loader)
 {
diff --git a/lib/gs-plugin-loader.h b/lib/gs-plugin-loader.h
index c4d9921..65b45f8 100644
--- a/lib/gs-plugin-loader.h
+++ b/lib/gs-plugin-loader.h
@@ -103,6 +103,8 @@ AsProfile   *gs_plugin_loader_get_profile           (GsPluginLoader *plugin_loader);
 GsApp          *gs_plugin_loader_app_create            (GsPluginLoader *plugin_loader,
                                                         const gchar    *unique_id);
 GsApp          *gs_plugin_loader_get_system_app        (GsPluginLoader *plugin_loader);
+GCancellable   *gs_plugin_loader_get_cancellable       (GsPluginLoader *plugin_loader,
+                                                        GsApp          *app);
 
 /* only useful from the self tests */
 void            gs_plugin_loader_setup_again           (GsPluginLoader *plugin_loader);
diff --git a/src/gs-details-page.c b/src/gs-details-page.c
index 0eb7426..6069d82 100644
--- a/src/gs-details-page.c
+++ b/src/gs-details-page.c
@@ -1727,6 +1727,8 @@ settings_changed_cb (GsDetailsPage *self,
 void
 gs_details_page_set_app (GsDetailsPage *self, GsApp *app)
 {
+       GCancellable *cancellable;
+
        g_return_if_fail (GS_IS_DETAILS_PAGE (self));
        g_return_if_fail (GS_IS_APP (app));
 
@@ -1746,6 +1748,11 @@ gs_details_page_set_app (GsDetailsPage *self, GsApp *app)
        /* save app */
        g_set_object (&self->app, app);
 
+       /* retrieve existing transaction */
+       cancellable = gs_plugin_loader_get_cancellable (self->plugin_loader, app);
+       if (cancellable != NULL)
+               g_set_object (&self->cancellable, cancellable);
+
        g_signal_connect_object (self->app, "notify::state",
                                 G_CALLBACK (gs_details_page_notify_state_changed_cb),
                                 self, 0);


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