From 3412be1f63df2a5967ef92c27028368df1646b5c Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Sun, 24 Jan 2021 12:41:20 -0500 Subject: [PATCH 15/15] subman: Clean up notification behavior Notifications were only displayed for some status transitions. This commit introduces some booleans based on the old and new statuses to make the code clearer and to make it easier to hit all the cases. --- plugins/subman/gsd-subman-common.h | 1 + plugins/subman/gsd-subscription-manager.c | 141 ++++++++++++++++++---- 2 files changed, 120 insertions(+), 22 deletions(-) diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h index 88226564..9397dbe4 100644 --- a/plugins/subman/gsd-subman-common.h +++ b/plugins/subman/gsd-subman-common.h @@ -1,40 +1,41 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2019 Richard Hughes * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * */ #ifndef __GSD_SUBMAN_COMMON_H #define __GSD_SUBMAN_COMMON_H #include G_BEGIN_DECLS typedef enum { + GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ = -1, GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN, GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID, GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS, } GsdSubmanSubscriptionStatus; const gchar *gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status); G_END_DECLS #endif /* __GSD_SUBMAN_COMMON_H */ diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c index 6d80bfa9..aaccbbc6 100644 --- a/plugins/subman/gsd-subscription-manager.c +++ b/plugins/subman/gsd-subscription-manager.c @@ -243,60 +243,61 @@ _client_installed_products_update (GsdSubscriptionManager *manager, GError **err product->version = g_strdup (json_array_get_string_element (json_product, 2)); product->arch = g_strdup (json_array_get_string_element (json_product, 3)); product->status = g_strdup (json_array_get_string_element (json_product, 4)); product->starts = g_strdup (json_array_get_string_element (json_product, 6)); product->ends = g_strdup (json_array_get_string_element (json_product, 7)); g_ptr_array_add (priv->installed_products, g_steal_pointer (&product)); } /* emit notification for g-c-c */ _emit_property_changed (manager, "InstalledProducts", _make_installed_products_variant (priv->installed_products)); return TRUE; } static gboolean _client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) { GsdSubscriptionManagerPrivate *priv = manager->priv; g_autoptr(GVariant) uuid = NULL; const gchar *uuid_txt = NULL; JsonNode *json_root; JsonObject *json_obj; const gchar *json_txt = NULL; g_autoptr(GVariant) status = NULL; g_autoptr(JsonParser) json_parser = json_parser_new (); /* save old value */ priv->subscription_status_last = priv->subscription_status; + if (!_client_installed_products_update (manager, error)) goto out; if (priv->installed_products->len == 0) { priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS; goto out; } uuid = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONSUMER], "GetUuid", g_variant_new ("(s)", "C.UTF-8"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); if (uuid == NULL) return FALSE; g_variant_get (uuid, "(&s)", &uuid_txt); if (uuid_txt[0] == '\0') { priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; goto out; } status = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], "GetStatus", g_variant_new ("(ss)", "", /* assumed as 'now' */ "C.UTF-8"), G_DBUS_CALL_FLAGS_NONE, @@ -485,109 +486,203 @@ typedef enum { static void _show_notification (GsdSubscriptionManager *manager, _NotifyKind notify_kind) { GsdSubscriptionManagerPrivate *priv = manager->priv; switch (notify_kind) { case _NOTIFY_EXPIRED: notify_notification_close (priv->notification_registered, NULL); notify_notification_close (priv->notification_registration_required, NULL); notify_notification_show (priv->notification_expired, NULL); break; case _NOTIFY_REGISTRATION_REQUIRED: notify_notification_close (priv->notification_registered, NULL); notify_notification_close (priv->notification_expired, NULL); notify_notification_show (priv->notification_registration_required, NULL); break; case _NOTIFY_REGISTERED: notify_notification_close (priv->notification_expired, NULL); notify_notification_close (priv->notification_registration_required, NULL); notify_notification_show (priv->notification_registered, NULL); break; default: break; } g_timer_reset (priv->timer_last_notified); } static void _client_maybe__show_notification (GsdSubscriptionManager *manager) { GsdSubscriptionManagerPrivate *priv = manager->priv; + gboolean was_read, was_registered, had_subscriptions, needed_subscriptions; + gboolean is_read, is_registered, has_subscriptions, needs_subscriptions; + + switch (priv->subscription_status_last) { + case GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ: + was_read = FALSE; + was_registered = FALSE; + needed_subscriptions = TRUE; + had_subscriptions = FALSE; + break; + case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: + was_read = TRUE; + was_registered = FALSE; + needed_subscriptions = TRUE; + had_subscriptions = FALSE; + break; + case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: + was_read = TRUE; + was_registered = TRUE; + needed_subscriptions = TRUE; + had_subscriptions = TRUE; + break; + case GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID: + was_read = TRUE; + was_registered = TRUE; + needed_subscriptions = TRUE; + had_subscriptions = FALSE; + break; + case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: + was_read = TRUE; + was_registered = TRUE; + needed_subscriptions = FALSE; + had_subscriptions = FALSE; + break; + case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: + was_read = TRUE; + was_registered = TRUE; + needed_subscriptions = TRUE; + had_subscriptions = FALSE; + case GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS: + was_read = TRUE; + was_registered = FALSE; + needed_subscriptions = FALSE; + had_subscriptions = FALSE; + break; + } + + switch (priv->subscription_status) { + case GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ: + is_read = FALSE; + is_registered = FALSE; + needs_subscriptions = TRUE; + has_subscriptions = FALSE; + break; + case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: + is_read = TRUE; + is_registered = FALSE; + needs_subscriptions = TRUE; + has_subscriptions = FALSE; + break; + case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: + is_read = TRUE; + is_registered = TRUE; + needs_subscriptions = TRUE; + has_subscriptions = TRUE; + break; + case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: + case GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID: + is_read = TRUE; + is_registered = TRUE; + needs_subscriptions = TRUE; + has_subscriptions = FALSE; + break; + case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: + is_read = TRUE; + is_registered = TRUE; + needs_subscriptions = FALSE; + has_subscriptions = FALSE; + break; + case GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS: + is_read = TRUE; + is_registered = FALSE; + needs_subscriptions = FALSE; + has_subscriptions = FALSE; + break; + } /* startup */ - if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && - priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { + if (!was_read && is_read && priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); return; } /* something changed */ - if (priv->subscription_status_last != priv->subscription_status) { + if (was_read && is_read && priv->subscription_status_last != priv->subscription_status) { g_debug ("transisition from subscription status '%s' to '%s'", gsd_subman_subscription_status_to_string (priv->subscription_status_last), gsd_subman_subscription_status_to_string (priv->subscription_status)); - /* needs registration */ - if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && - priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) { - _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); + /* needs subscription */ + if (is_registered && needs_subscriptions && !has_subscriptions) { + _show_notification (manager, _NOTIFY_EXPIRED); return; } /* was unregistered */ - if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && - priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { + if (was_registered && !is_registered) { _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); return; } - /* registered */ - if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && - priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && - g_timer_elapsed (priv->timer_last_notified, NULL) > 60) { - _show_notification (manager, _NOTIFY_REGISTERED); - return; + /* just registered */ + if (!was_registered && is_registered) { + if (!needs_subscriptions || has_subscriptions) { + _show_notification (manager, _NOTIFY_REGISTERED); + return; + } + } + + /* subscriptions changed */ + if (was_registered && is_registered) { + /* subscribed */ + if (!had_subscriptions && + needs_subscriptions && has_subscriptions) { + _show_notification (manager, _NOTIFY_REGISTERED); + return; + } + + /* simple content access enabled */ + if (needed_subscriptions && !had_subscriptions && !needs_subscriptions) { + _show_notification (manager, _NOTIFY_REGISTERED); + return; + } } } /* nag again */ - if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && + if (!is_registered && g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); return; } - if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID && - g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { - _show_notification (manager, _NOTIFY_EXPIRED); - return; - } - if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID && + if (is_registered && !has_subscriptions && needs_subscriptions && g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { _show_notification (manager, _NOTIFY_EXPIRED); return; } } static gboolean _client_register_with_keys (GsdSubscriptionManager *manager, const gchar *hostname, const gchar *organisation, const gchar *activation_key, GError **error) { GsdSubscriptionManagerPrivate *priv = manager->priv; g_autoptr(GSubprocess) subprocess = NULL; g_autoptr(GBytes) stdin_buf = g_bytes_new (activation_key, strlen (activation_key) + 1); g_autoptr(GBytes) stderr_buf = NULL; gint rc; /* apparently: "we can't send registration credentials over the regular * system or session bus since those aren't really locked down..." */ if (!_client_register_start (manager, error)) return FALSE; g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, error, "pkexec", LIBEXECDIR "/gsd-subman-helper", "--kind", "register-with-key", "--address", priv->address, "--hostname", hostname, "--organisation", organisation, @@ -914,60 +1009,62 @@ gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass) static void _launch_info_overview (void) { const gchar *argv[] = { "gnome-control-center", "info-overview", NULL }; g_debug ("Running gnome-control-center info-overview"); g_spawn_async (NULL, (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL); } static void _notify_closed_cb (NotifyNotification *notification, gpointer user_data) { /* FIXME: only launch when clicking on the main body, not the window close */ if (notify_notification_get_closed_reason (notification) == 0x400) _launch_info_overview (); } static void _notify_clicked_cb (NotifyNotification *notification, char *action, gpointer user_data) { _launch_info_overview (); } static void gsd_subscription_manager_init (GsdSubscriptionManager *manager) { GsdSubscriptionManagerPrivate *priv = manager->priv = GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE (manager); priv->installed_products = g_ptr_array_new_with_free_func ((GDestroyNotify) product_data_free); priv->timer_last_notified = g_timer_new (); + priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ; + priv->subscription_status_last = GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ; /* expired */ priv->notification_expired = notify_notification_new (_("Subscription Has Expired"), _("Add or renew a subscription to continue receiving software updates."), NULL); notify_notification_set_app_name (priv->notification_expired, _("Subscription")); notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "subman-panel"); notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system"); notify_notification_set_urgency (priv->notification_expired, NOTIFY_URGENCY_CRITICAL); notify_notification_add_action (priv->notification_expired, "info-overview", _("Subscribe System…"), _notify_clicked_cb, manager, NULL); g_signal_connect (priv->notification_expired, "closed", G_CALLBACK (_notify_closed_cb), manager); /* registered */ priv->notification_registered = notify_notification_new (_("Registration Successful"), _("The system has been registered and software updates have been enabled."), NULL); notify_notification_set_app_name (priv->notification_registered, _("Subscription")); notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "subman-panel"); notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system"); notify_notification_set_urgency (priv->notification_registered, NOTIFY_URGENCY_CRITICAL); g_signal_connect (priv->notification_registered, "closed", G_CALLBACK (_notify_closed_cb), manager); /* registration required */ -- 2.30.0