[gnome-software/gnome-3-30] update monitor: Fix autoupdates triggering in a feedback loop



commit 011626c41a006e66c90037d522e4100f7aef651b
Author: Kalev Lember <klember redhat com>
Date:   Thu Oct 4 12:34:13 2018 +0200

    update monitor: Fix autoupdates triggering in a feedback loop
    
    Only trigger autoupdates once a day, and avoid accidentally triggering
    them when a plugin emits updates-changed. Otherwise it can unexpectedly
    happen that a user installs an app, which triggers updates-changed,
    which in turn triggers autoupdates immediately.
    
    Worse, a plugin might emit updates-changed when it ran into a failure,
    which causes autoupdates to trigger, which in turn runs into another
    failure, which causes updates-changed, and so on.
    
    Instead, make sure autoupdates only get triggered once per day.

 src/gs-application.c    |  2 +-
 src/gs-update-monitor.c | 42 ++++++++++++++++++++++++++++++++++--------
 src/gs-update-monitor.h |  2 +-
 3 files changed, 36 insertions(+), 10 deletions(-)
---
diff --git a/src/gs-application.c b/src/gs-application.c
index b8325746..a19fd261 100644
--- a/src/gs-application.c
+++ b/src/gs-application.c
@@ -759,7 +759,7 @@ autoupdate_activated (GSimpleAction *action, GVariant *parameter, gpointer data)
 {
        GsApplication *app = GS_APPLICATION (data);
        gs_shell_set_mode (app->shell, GS_SHELL_MODE_UPDATES);
-       gs_update_monitor_get_updates (app->update_monitor);
+       gs_update_monitor_autoupdate (app->update_monitor);
 }
 
 static void
diff --git a/src/gs-update-monitor.c b/src/gs-update-monitor.c
index 6466c1ab..9fb545b0 100644
--- a/src/gs-update-monitor.c
+++ b/src/gs-update-monitor.c
@@ -53,6 +53,20 @@ struct _GsUpdateMonitor {
 
 G_DEFINE_TYPE (GsUpdateMonitor, gs_update_monitor, G_TYPE_OBJECT)
 
+typedef struct {
+       GsUpdateMonitor *monitor;
+       gboolean         autoupdate;
+} DownloadUpdatesData;
+
+static void
+download_updates_data_free (DownloadUpdatesData *data)
+{
+       g_clear_object (&data->monitor);
+       g_slice_free (DownloadUpdatesData, data);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(DownloadUpdatesData, download_updates_data_free);
+
 static gboolean
 reenable_offline_update_notification (gpointer data)
 {
@@ -347,7 +361,8 @@ download_finished_cb (GObject *object, GAsyncResult *res, gpointer data)
 static void
 get_updates_finished_cb (GObject *object, GAsyncResult *res, gpointer data)
 {
-       GsUpdateMonitor *monitor = GS_UPDATE_MONITOR (data);
+       g_autoptr(DownloadUpdatesData) download_updates_data = (DownloadUpdatesData *) data;
+       GsUpdateMonitor *monitor = download_updates_data->monitor;
        guint64 security_timestamp = 0;
        guint64 security_timestamp_old = 0;
        g_autoptr(GError) error = NULL;
@@ -387,7 +402,8 @@ get_updates_finished_cb (GObject *object, GAsyncResult *res, gpointer data)
        g_debug ("got %u updates", gs_app_list_length (apps));
 
        /* download any updates if auto-updates are turned on */
-       if (g_settings_get_boolean (monitor->settings, "download-updates")) {
+       if (download_updates_data->autoupdate &&
+           g_settings_get_boolean (monitor->settings, "download-updates")) {
                g_autoptr(GsPluginJob) plugin_job = NULL;
                plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_DOWNLOAD,
                                                 "list", apps,
@@ -401,7 +417,6 @@ get_updates_finished_cb (GObject *object, GAsyncResult *res, gpointer data)
                return;
        }
 
-
        if (has_important_updates (apps) ||
            no_updates_for_a_week (monitor)) {
                notify_offline_update_available (monitor);
@@ -528,10 +543,11 @@ get_upgrades_finished_cb (GObject *object,
        g_application_send_notification (monitor->application, "upgrades-available", n);
 }
 
-void
-gs_update_monitor_get_updates (GsUpdateMonitor *monitor)
+static void
+get_updates (GsUpdateMonitor *monitor, gboolean autoupdate)
 {
        g_autoptr(GsPluginJob) plugin_job = NULL;
+       g_autoptr(DownloadUpdatesData) download_updates_data = NULL;
 
        /* disabled in gsettings or from a plugin */
        if (!gs_plugin_loader_get_allow_updates (monitor->plugin_loader)) {
@@ -539,6 +555,10 @@ gs_update_monitor_get_updates (GsUpdateMonitor *monitor)
                return;
        }
 
+       download_updates_data = g_slice_new0 (DownloadUpdatesData);
+       download_updates_data->monitor = g_object_ref (monitor);
+       download_updates_data->autoupdate = autoupdate;
+
        /* NOTE: this doesn't actually do any network access */
        g_debug ("Getting updates");
        plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_GET_UPDATES,
@@ -549,7 +569,13 @@ gs_update_monitor_get_updates (GsUpdateMonitor *monitor)
                                            plugin_job,
                                            monitor->cancellable,
                                            get_updates_finished_cb,
-                                           monitor);
+                                           g_steal_pointer (&download_updates_data));
+}
+
+void
+gs_update_monitor_autoupdate (GsUpdateMonitor *monitor)
+{
+       get_updates (monitor, TRUE /* autoupdate */);
 }
 
 static void
@@ -613,7 +639,7 @@ refresh_cache_finished_cb (GObject *object,
        g_settings_set (monitor->settings, "check-timestamp", "x",
                        g_date_time_to_unix (now));
 
-       gs_update_monitor_get_updates (monitor);
+       get_updates (monitor, TRUE /* autoupdate */);
 }
 
 typedef enum {
@@ -797,7 +823,7 @@ updates_changed_cb (GsPluginLoader *plugin_loader, GsUpdateMonitor *monitor)
 {
        /* when the list of downloaded-and-ready-to-go updates changes get the
         * new list and perhaps show/hide the notification */
-       gs_update_monitor_get_updates (monitor);
+       get_updates (monitor, FALSE /* autoupdate */);
 }
 
 static void
diff --git a/src/gs-update-monitor.h b/src/gs-update-monitor.h
index 0a3c54b5..edc04bf1 100644
--- a/src/gs-update-monitor.h
+++ b/src/gs-update-monitor.h
@@ -35,7 +35,7 @@ G_BEGIN_DECLS
 G_DECLARE_FINAL_TYPE (GsUpdateMonitor, gs_update_monitor, GS, UPDATE_MONITOR, GObject)
 
 GsUpdateMonitor        *gs_update_monitor_new                  (GsApplication  *app);
-void            gs_update_monitor_get_updates          (GsUpdateMonitor *monitor);
+void            gs_update_monitor_autoupdate           (GsUpdateMonitor *monitor);
 void            gs_update_monitor_show_error           (GsUpdateMonitor *monitor,
                                                         GsShell        *shell);
 


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