changeset 64:a5ed1047ce14

Obtain network state from GNetworkMonitor The PackageKit daemon does not necessarily run continuously and is therefore not a reliable source for network changes. More specifically, if the internet connectivity is not available when the PackageKit daemon shuts down, package-update-indicator will not be notified if connectivity is restored. Thus use GNetworkMonitor instead which is also used internally by PackageKit. This change is based on patches by Cliff <cliffd@gmx.com.br> who discovered and tracked down this issue.
author Guido Berhoerster <guido+pui@berhoerster.name>
date Sun, 14 Jan 2024 18:53:37 +0100
parents 9a6836ab0bc7
children 72f0eea06b7c
files pui-backend.c
diffstat 1 files changed, 53 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/pui-backend.c	Thu Nov 30 18:43:41 2023 +0100
+++ b/pui-backend.c	Sun Jan 14 18:53:37 2024 +0100
@@ -23,6 +23,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <gio/gio.h>
 #include <packagekit-glib2/packagekit.h>
 #include <polkit/polkit.h>
 #include <string.h>
@@ -39,6 +40,27 @@
 #define	LOW_BATTERY_THRESHOLD		10.0	/* % */
 #define	UPDATES_CHANGED_UNBLOCK_DELAY	4	/* s */
 
+typedef enum {
+    NETWORK_STATE_OFFLINE,
+    NETWORK_STATE_ONLINE,
+    NETWORK_STATE_METERED,
+    NETWORK_STATE_LAST
+} NetworkState;
+
+static const gchar *network_state_strings[NETWORK_STATE_LAST] = {
+	[NETWORK_STATE_OFFLINE] = "offline",
+	[NETWORK_STATE_ONLINE] = "online",
+	[NETWORK_STATE_METERED] = "metered"
+};
+
+static const gchar *
+network_state_to_string(NetworkState state)
+{
+	g_assert(state > 0 && state < NETWORK_STATE_LAST);
+
+	return (network_state_strings[state]);
+}
+
 struct _PuiBackend {
 	GObject		parent_instance;
 	PkControl	*pk_control;
@@ -54,7 +76,7 @@
 	gchar		*no_proxy;
 	gchar		*pac;
 	gint64		last_check;
-	PkNetworkEnum	network_state;
+	NetworkState	network_state;
 	gboolean	inhibited;
 	gboolean	is_battery_low;
 	guint		check_id;
@@ -91,6 +113,7 @@
 static guint	signals[SIGNAL_LAST] = { 0 };
 static GParamSpec *properties[PROP_LAST] = { NULL };
 
+static NetworkState get_network_state(GNetworkMonitor *);
 static gboolean	periodic_check(gpointer);
 static void	on_updates_changed(PkControl *, gpointer);
 
@@ -257,9 +280,9 @@
 	guint		elapsed_time;
 	guint		remaining_time;
 
-	is_offline = self->network_state == PK_NETWORK_ENUM_OFFLINE;
+	is_offline = self->network_state == NETWORK_STATE_OFFLINE;
 	is_disallowed_mobile = !self->use_mobile_connection &&
-	    (self->network_state == PK_NETWORK_ENUM_MOBILE);
+	    (self->network_state == NETWORK_STATE_METERED);
 	inhibited = is_offline || is_disallowed_mobile || self->is_battery_low;
 	if (self->inhibited == inhibited) {
 		return;
@@ -492,6 +515,9 @@
 	if (self->up_client) {
 		self->up_device = up_client_get_display_device(self->up_client);
 	}
+
+	self->network_state =
+	    get_network_state(g_network_monitor_get_default());
 }
 
 static void
@@ -515,12 +541,12 @@
 
 	/* check whether the backend supports GetUpdates */
 	g_object_get(control, "backend-name", &backend_name, "roles", &roles,
-	    "network-state", &self->network_state, NULL);
+	    NULL);
 	g_debug("backend: %s", backend_name);
 	roles_str = pk_role_bitfield_to_string(roles);
 	g_debug("roles: %s", roles_str);
 	g_debug("network-state: %s",
-	    pk_network_enum_to_string(self->network_state));
+	    network_state_to_string(self->network_state));
 	if (!pk_bitfield_contain(roles, PK_ROLE_ENUM_GET_UPDATES)) {
 		error = g_error_new(PUI_BACKEND_ERROR,
 		    PUI_BACKEND_ERROR_GET_UPDATES_NOT_IMPLEMENTED,
@@ -557,15 +583,31 @@
 	}
 }
 
+static NetworkState
+get_network_state(GNetworkMonitor *network_monitor)
+{
+	if (!g_network_monitor_get_network_available(network_monitor)) {
+		return (NETWORK_STATE_OFFLINE);
+	} else if (g_network_monitor_get_network_metered(network_monitor)) {
+		return (NETWORK_STATE_METERED);
+	}
+	return (NETWORK_STATE_ONLINE);
+}
+
 static void
-on_notify_network_state(PkControl *pk_control, GParamSpec *pspec,
-    gpointer user_data)
+on_network_changed(GNetworkMonitor *network_monitor,
+    gboolean network_available, gpointer user_data)
 {
 	PuiBackend	*self = user_data;
+	NetworkState	network_state;
 
-	g_object_get(pk_control, "network-state", &self->network_state, NULL);
+	network_state = get_network_state(network_monitor);
+	if (network_state != self->network_state) {
+		return;
+	}
+	self->network_state = network_state;
 	g_debug("network state changed: %s",
-	    pk_network_enum_to_string(self->network_state));
+	    network_state_to_string(self->network_state));
 	check_inhibit(self);
 }
 
@@ -718,8 +760,8 @@
 	}
 
 	/* get notification when the network state changes */
-	g_signal_connect(self->pk_control, "notify::network-state",
-	    G_CALLBACK(on_notify_network_state), self);
+	g_signal_connect(g_network_monitor_get_default(), "network-changed",
+	    G_CALLBACK(on_network_changed), self);
 	/* get notifications when the package metatdata cache is invalidated */
 	g_signal_connect(self->pk_control, "updates-changed",
 	    G_CALLBACK(on_updates_changed), self);