Mercurial > projects > package-update-indicator
diff pui-backend.c @ 10:adba37525ee5
Notify about required session or system restarts
Follow all PackageKit transactions and indicate when a session or system
restart is required.
Generate enum types with glib-mkenums.
author | Guido Berhoerster <guido+pui@berhoerster.name> |
---|---|
date | Fri, 06 Jul 2018 14:12:46 +0200 |
parents | 2477a6151087 |
children | 9905d4ae351c |
line wrap: on
line diff
--- a/pui-backend.c Wed Jul 04 17:08:47 2018 +0200 +++ b/pui-backend.c Fri Jul 06 14:12:46 2018 +0200 @@ -34,6 +34,7 @@ #include "pui-common.h" #include "pui-backend.h" #include "pui-get-updates.h" +#include "pui-types.h" #define LOW_BATTERY_THRESHOLD 10.0 @@ -41,6 +42,8 @@ GObject parent_instance; PkControl *pk_control; GCancellable *cancellable; + PkClient *pk_client; + PkTransactionList *transaction_list; UpClient *up_client; UpDevice *up_device; gchar *proxy_http; @@ -58,6 +61,7 @@ gboolean use_mobile_connection; guint important_updates; guint normal_updates; + PuiRestart restart_type; }; static void pui_backend_async_initable_iface_init(gpointer, gpointer); @@ -76,6 +80,7 @@ PROP_0, PROP_IMPORTANT_UPDATES, PROP_NORMAL_UPDATES, + PROP_RESTART_TYPE, PROP_REFRESH_INTERVAL, PROP_USE_MOBILE_CONNECTION, PROP_LAST @@ -276,6 +281,9 @@ case PROP_NORMAL_UPDATES: g_value_set_uint(value, self->normal_updates); break; + case PROP_RESTART_TYPE: + g_value_set_enum(value, self->restart_type); + break; case PROP_REFRESH_INTERVAL: g_value_set_uint(value, self->refresh_interval); break; @@ -298,6 +306,14 @@ self->periodic_check_id = 0; } + if (self->transaction_list != NULL) { + g_clear_object(&self->transaction_list); + } + + if (self->pk_client != NULL) { + g_clear_object(&self->pk_client); + } + if (self->cancellable != NULL) { g_cancellable_cancel(self->cancellable); g_clear_object(&self->cancellable); @@ -353,6 +369,11 @@ "Number of available normal updates", 0, G_MAXUINT, 0, G_PARAM_READABLE); + properties[PROP_RESTART_TYPE] = + g_param_spec_enum("restart-type", "Type of restart required", + "The Type of restart required", PUI_TYPE_RESTART, PUI_RESTART_NONE, + G_PARAM_READABLE); + properties[PROP_REFRESH_INTERVAL] = g_param_spec_uint("refresh-interval", "Refresh interval", "Interval in seconds for refreshing the package cache", 0, @@ -382,6 +403,8 @@ { self->pk_control = pk_control_new(); + self->pk_client = pk_client_new(); + self->inhibited = TRUE; self->up_client = up_client_new(); @@ -470,6 +493,8 @@ { PuiBackend *self = user_data; + g_debug("number of updates changed"); + /* * schedule a check after a short delay so that a rapid succession of * signals is coalesced @@ -489,11 +514,85 @@ { PuiBackend *self = user_data; + /* + * do not restart package-update-indicator if a session or system + * restart is required since that iformation would be lost across the + * restart, rather keep running and risk errors when interacting with + * a newer version of the PackageKit daemon + */ + if (self->restart_type > PUI_RESTART_NONE) { + return; + } + g_debug("emitting signal restart-required"); g_signal_emit(self, signals[RESTART_REQUIRED], 0); } static void +on_transaction_adopt_finish(GObject *source_object, GAsyncResult *result, + gpointer user_data) +{ + PuiBackend *self = user_data; + PkClient *pk_client = PK_CLIENT(source_object); + PkResults *results; + GError *error = NULL; + PkRestartEnum restart; + + results = pk_client_generic_finish(pk_client, result, &error); + if (results == NULL) { + g_warning("failed to get transaction results: %s", + error->message); + g_error_free(error); + goto out; + } + + /* check if transaction requires a restart */ + restart = pk_results_get_require_restart_worst(results); + switch (restart) { + case PK_RESTART_ENUM_SESSION: /* FALLTHROUGH */ + case PK_RESTART_ENUM_SECURITY_SESSION: + if (self->restart_type < PUI_RESTART_SESSION) { + self->restart_type = PUI_RESTART_SESSION; + g_object_notify_by_pspec(G_OBJECT(self), + properties[PROP_RESTART_TYPE]); + g_signal_emit(self, signals[STATE_CHANGED], 0); + } + break; + case PK_RESTART_ENUM_SYSTEM: /* FALLTHROUGH */ + case PK_RESTART_ENUM_SECURITY_SYSTEM: + if (self->restart_type < PUI_RESTART_SYSTEM) { + self->restart_type = PUI_RESTART_SYSTEM; + g_object_notify_by_pspec(G_OBJECT(self), + properties[PROP_RESTART_TYPE]); + g_signal_emit(self, signals[STATE_CHANGED], 0); + } + break; + default: + /* do nothing */ + break; + } + + g_debug("transaction finished, required restart: %s", + pk_restart_enum_to_string(restart)); + +out: + if (results != NULL) { + g_object_unref(results); + } +} + +static void +on_transaction_list_added(PkTransactionList *transaction_list, + const gchar *transaction_id, gpointer user_data) +{ + PuiBackend *self = user_data; + + /* adopt transaction in order to monitor it for restart requirements */ + pk_client_adopt_async(self->pk_client, transaction_id, NULL, NULL, + NULL, on_transaction_adopt_finish, user_data); +} + +static void pui_backend_init_async(GAsyncInitable *initable, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { @@ -546,6 +645,10 @@ /* get notifications when an application restart is required */ g_signal_connect(self->pk_control, "restart-schedule", G_CALLBACK(on_restart_schedule), self); + /* get notifications when a transactions are added */ + self->transaction_list = pk_transaction_list_new(); + g_signal_connect(self->transaction_list, "added", + G_CALLBACK(on_transaction_list_added), self); check_inhibit(self);