[gnome-software/947-review-timing-and-content-of-software-updates-notifications] gs-update-monitor: Review timing and content of software updates notifications
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/947-review-timing-and-content-of-software-updates-notifications] gs-update-monitor: Review timing and content of software updates notifications
- Date: Tue, 24 Nov 2020 17:55:48 +0000 (UTC)
commit 53df6b4679f3e272fbe7dd1b158b38c09ff305c9
Author: Milan Crha <mcrha redhat com>
Date: Tue Nov 24 17:52:34 2020 +0100
gs-update-monitor: Review timing and content of software updates notifications
Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/947
Closes https://gitlab.gnome.org/GNOME/gnome-software/-/merge_requests/549
data/org.gnome.software.gschema.xml | 4 +
lib/gs-utils.c | 5 +
src/gs-update-monitor.c | 212 +++++++++++++++++++++++-------------
3 files changed, 143 insertions(+), 78 deletions(-)
---
diff --git a/data/org.gnome.software.gschema.xml b/data/org.gnome.software.gschema.xml
index 77192686..5e84925a 100644
--- a/data/org.gnome.software.gschema.xml
+++ b/data/org.gnome.software.gschema.xml
@@ -55,6 +55,10 @@
<default>0</default>
<summary>The last upgrade notification timestamp</summary>
</key>
+ <key name="update-notification-timestamp" type="x">
+ <default>0</default>
+ <summary>The last update notification timestamp</summary>
+ </key>
<key name="security-timestamp" type="x">
<default>0</default>
<summary>The timestamp of the first security update, cleared after update</summary>
diff --git a/lib/gs-utils.c b/lib/gs-utils.c
index 1ba5976a..a66bc496 100644
--- a/lib/gs-utils.c
+++ b/lib/gs-utils.c
@@ -1211,6 +1211,9 @@ gs_utils_parse_evr (const gchar *evr,
* Sets the value of online-updates-timestamp to current epoch. "online-updates-timestamp" represents
* the last time the system was online and got any updates.
*
+ * It also sets the "update-notification-timestamp", to not receive
+ * notifications about available updates too early after the actual
+ * update happened.
**/
void
gs_utils_set_online_updates_timestamp (GSettings *settings)
@@ -1221,6 +1224,8 @@ gs_utils_set_online_updates_timestamp (GSettings *settings)
now = g_date_time_new_now_local ();
g_settings_set (settings, "online-updates-timestamp", "x", g_date_time_to_unix (now));
+
+ g_settings_set (settings, "update-notification-timestamp", "x", g_date_time_to_unix (now));
}
/* vim: set noexpandtab: */
diff --git a/src/gs-update-monitor.c b/src/gs-update-monitor.c
index 296a5127..d1e604db 100644
--- a/src/gs-update-monitor.c
+++ b/src/gs-update-monitor.c
@@ -80,71 +80,42 @@ reenable_offline_update_notification (gpointer data)
}
static void
-notify_offline_update_available (GsUpdateMonitor *monitor)
+check_updates_kind (GsAppList *apps,
+ gboolean *out_has_important,
+ gboolean *out_all_downloaded,
+ gboolean *out_any_downloaded)
{
- const gchar *title;
- const gchar *body;
- guint64 elapsed_security = 0;
- guint64 security_timestamp = 0;
- g_autoptr(GNotification) n = NULL;
+ gboolean has_important, all_downloaded, any_downloaded;
+ guint ii, len;
+ GsApp *app;
- if (gs_application_has_active_window (GS_APPLICATION (monitor->application)))
- return;
- if (monitor->notification_blocked_id > 0)
- return;
+ len = gs_app_list_length (apps);
+ has_important = FALSE;
+ all_downloaded = len > 0;
+ any_downloaded = FALSE;
- /* rate limit update notifications to once per hour */
- monitor->notification_blocked_id = g_timeout_add_seconds (SECONDS_IN_AN_HOUR,
reenable_offline_update_notification, monitor);
+ for (ii = 0; ii < len && (!has_important || all_downloaded || !any_downloaded); ii++) {
+ app = gs_app_list_index (apps, ii);
- /* get time in days since we saw the first unapplied security update */
- g_settings_get (monitor->settings,
- "security-timestamp", "x", &security_timestamp);
- if (security_timestamp > 0) {
- elapsed_security = (guint64) g_get_monotonic_time () - security_timestamp;
- elapsed_security /= G_USEC_PER_SEC;
- elapsed_security /= 60 * 60 * 24;
- }
+ has_important = has_important ||
+ gs_app_get_update_urgency (app) == AS_URGENCY_KIND_CRITICAL ||
+ gs_app_get_update_urgency (app) == AS_URGENCY_KIND_HIGH;
- /* only show the scary warning after the user has ignored
- * security updates for a full day */
- if (elapsed_security > 1) {
- title = _("Security Updates Pending");
- body = _("It is recommended that you install important updates now");
- n = g_notification_new (title);
- g_notification_set_body (n, body);
- g_notification_add_button (n, _("Restart & Install"), "app.reboot-and-install");
- g_notification_set_default_action_and_target (n, "app.set-mode", "s", "updates");
- g_application_send_notification (monitor->application, "updates-available", n);
- } else {
- title = _("Software Updates Available");
- body = _("Important OS and application updates are ready to be installed");
- n = g_notification_new (title);
- g_notification_set_body (n, body);
- g_notification_add_button (n, _("Not Now"), "app.nop");
- g_notification_add_button_with_target (n, _("View"), "app.set-mode", "s", "updates");
- g_notification_set_default_action_and_target (n, "app.set-mode", "s", "updates");
- g_application_send_notification (monitor->application, "updates-available", n);
+ /* took from gs-updates-section.c: _all_offline_updates_downloaded();
+ the app is considered downloaded, when its download size is 0 */
+ if (gs_app_get_size_download (app))
+ all_downloaded = FALSE;
+ else
+ any_downloaded = TRUE;
}
-}
-static gboolean
-has_important_updates (GsAppList *apps)
-{
- guint i;
- GsApp *app;
-
- for (i = 0; i < gs_app_list_length (apps); i++) {
- app = gs_app_list_index (apps, i);
- if (gs_app_get_update_urgency (app) == AS_URGENCY_KIND_CRITICAL ||
- gs_app_get_update_urgency (app) == AS_URGENCY_KIND_HIGH)
- return TRUE;
- }
-
- return FALSE;
+ *out_has_important = has_important;
+ *out_all_downloaded = all_downloaded;
+ *out_any_downloaded = any_downloaded;
}
static gboolean
-check_if_timestamp_more_than_a_week_ago (GsUpdateMonitor *monitor, const gchar *timestamp)
+check_if_timestamp_more_than_days_ago (GsUpdateMonitor *monitor, const gchar *timestamp, guint days)
{
GTimeSpan d;
gint64 tmp;
@@ -163,22 +134,117 @@ check_if_timestamp_more_than_a_week_ago (GsUpdateMonitor *monitor, const gchar *
now = g_date_time_new_now_local ();
d = g_date_time_difference (now, last_update);
- if (d >= 7 * G_TIME_SPAN_DAY)
+ if (d >= days * G_TIME_SPAN_DAY)
return TRUE;
return FALSE;
}
static gboolean
-no_updates_for_a_week (GsUpdateMonitor *monitor)
+no_notification_for_days (GsUpdateMonitor *monitor,
+ guint days)
{
- if (check_if_timestamp_more_than_a_week_ago (monitor, "install-timestamp") ||
- check_if_timestamp_more_than_a_week_ago (monitor, "online-updates-timestamp"))
+ return check_if_timestamp_more_than_days_ago (monitor, "update-notification-timestamp", days);
+}
+
+static gboolean
+should_download_updates (GsUpdateMonitor *monitor)
+{
+#ifdef HAVE_MOGWAI
+ return TRUE;
+#else
+ return g_settings_get_boolean (monitor->settings, "download-updates");
+#endif
+}
+
+static gboolean
+should_notify_about_pending_updates (GsUpdateMonitor *monitor,
+ GsAppList *apps,
+ const gchar **out_title,
+ const gchar **out_body)
+{
+ gboolean has_important = FALSE, all_downloaded = FALSE, any_downloaded = FALSE;
+ gboolean should_download;
+
+ should_download = should_download_updates (monitor);
+ check_updates_kind (apps, &has_important, &all_downloaded, &any_downloaded);
+
+ if (!gs_app_list_length (apps)) {
+ /* Notify only when the download is disabled and it's the 4th day or it's more than 7 days */
+ if (!should_download && (no_notification_for_days (monitor, 7) ||
+ (no_notification_for_days (monitor, 4) && !no_notification_for_days (monitor, 5)))) {
+ *out_title = _("Software Updates Are Out of Date");
+ *out_body = _("Please check for software updates.");
+ return TRUE;
+ }
+ } else if (has_important) {
+ if (no_notification_for_days (monitor, 1)) {
+ if (all_downloaded) {
+ *out_title = _("Critical Software Update Ready to Install");
+ *out_body = _("An important software update is ready to be installed.");
+ return TRUE;
+ } else {
+ *out_title = _("Critical Software Updates Available to Download");
+ *out_body = _("Important: critical software updates are waiting.");
+ return TRUE;
+ }
+ }
+ } else if (all_downloaded) {
+ if (no_notification_for_days (monitor, 3)) {
+ *out_title = _("Software Updates Ready to Install");
+ *out_body = _("Software updates are waiting and ready to be installed.");
+ return TRUE;
+ }
+ /* To not hide downloaded updates for 14 days when new updates were discovered meanwhile */
+ } else if (no_notification_for_days (monitor, any_downloaded ? 3 : 14)) {
+ *out_title = _("Software Updates Available to Download");
+ *out_body = _("Please download waiting software updates.");
return TRUE;
+ }
return FALSE;
}
+static void
+reset_update_notification_timestamp (GsUpdateMonitor *monitor)
+{
+ g_autoptr(GDateTime) now = NULL;
+
+ now = g_date_time_new_now_local ();
+ g_settings_set (monitor->settings, "update-notification-timestamp", "x",
+ g_date_time_to_unix (now));
+}
+
+static void
+notify_about_pending_updates (GsUpdateMonitor *monitor,
+ GsAppList *apps)
+{
+ const gchar *title = NULL, *body = NULL;
+ g_autoptr(GNotification) nn = NULL;
+
+ if (monitor->notification_blocked_id > 0)
+ return;
+
+ /* rate limit update notifications to once per day */
+ monitor->notification_blocked_id = g_timeout_add_seconds (24 * SECONDS_IN_AN_HOUR,
reenable_offline_update_notification, monitor);
+
+ if (!should_notify_about_pending_updates (monitor, apps, &title, &body))
+ return;
+
+ g_debug ("Notify about update: '%s'", title);
+
+ nn = g_notification_new (title);
+ g_notification_set_body (nn, body);
+ g_notification_set_default_action_and_target (nn, "app.set-mode", "s", "updates");
+ g_application_send_notification (monitor->application, "updates-available", nn);
+
+ /* Keep the old notification time when there are no updates and the update download is disabled,
+ to notify the user every day after 7 days of no update check */
+ if (gs_app_list_length (apps) ||
+ should_download_updates (monitor))
+ reset_update_notification_timestamp (monitor);
+}
+
static gboolean
_filter_by_app_kind (GsApp *app, gpointer user_data)
{
@@ -379,12 +445,8 @@ download_finished_cb (GObject *object, GAsyncResult *res, gpointer data)
}
/* show a notification for offline updates */
- if (gs_app_list_length (update_offline) > 0) {
- if (has_important_updates (update_offline) ||
- no_updates_for_a_week (monitor)) {
- notify_offline_update_available (monitor);
- }
- }
+ if (gs_app_list_length (update_offline) > 0)
+ notify_about_pending_updates (monitor, update_offline);
}
static void
@@ -396,7 +458,6 @@ get_updates_finished_cb (GObject *object, GAsyncResult *res, gpointer data)
guint64 security_timestamp_old = 0;
g_autoptr(GError) error = NULL;
g_autoptr(GsAppList) apps = NULL;
- gboolean download_updates;
/* get result */
apps = gs_plugin_loader_job_process_finish (GS_PLUGIN_LOADER (object), res, &error);
@@ -431,13 +492,9 @@ get_updates_finished_cb (GObject *object, GAsyncResult *res, gpointer data)
g_debug ("got %u updates", gs_app_list_length (apps));
-#ifdef HAVE_MOGWAI
- download_updates = TRUE;
-#else
- download_updates = g_settings_get_boolean (monitor->settings, "download-updates");
-#endif
-
- if (download_updates) {
+ if (should_download_updates (monitor) &&
+ (security_timestamp_old != security_timestamp ||
+ no_notification_for_days (monitor, 14))) {
g_autoptr(GsPluginJob) plugin_job = NULL;
/* download any updates; individual plugins are responsible for deciding
@@ -454,11 +511,9 @@ get_updates_finished_cb (GObject *object, GAsyncResult *res, gpointer data)
download_finished_cb,
monitor);
} else {
- /* notify immediately if auto-updates are turned off */
- if (has_important_updates (apps) ||
- no_updates_for_a_week (monitor)) {
- notify_offline_update_available (monitor);
- }
+ notify_about_pending_updates (monitor, apps);
+
+ reset_update_notification_timestamp (monitor);
}
}
@@ -1027,6 +1082,7 @@ get_updates_historical_cb (GObject *object, GAsyncResult *res, gpointer data)
g_settings_set (monitor->settings,
"install-timestamp", "x", gs_app_get_install_date (app));
+ reset_update_notification_timestamp (monitor);
}
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]