From 7005c4518f99fbe522d1fa95ccdbde076511dff2 Mon Sep 17 00:00:00 2001 From: Julian Bouzas Date: Fri, 24 Sep 2021 09:31:29 -0400 Subject: [PATCH] m-portal-permissionstore: try to reconnect on idle if DBus connection is closed This change also keeps the plugin always activated, regardless of whether the DBus connection is closed or not, which is useful when the dbus service is restarted. --- .../module-portal-permissionstore/plugin.c | 128 +++++++++++++----- 1 file changed, 91 insertions(+), 37 deletions(-) diff --git a/modules/module-portal-permissionstore/plugin.c b/modules/module-portal-permissionstore/plugin.c index 7aac42f2..5f24f17a 100644 --- a/modules/module-portal-permissionstore/plugin.c +++ b/modules/module-portal-permissionstore/plugin.c @@ -12,6 +12,8 @@ #define DBUS_INTERFACE_NAME "org.freedesktop.impl.portal.PermissionStore" #define DBUS_OBJECT_PATH "/org/freedesktop/impl/portal/PermissionStore" +static void setup_connection (WpPortalPermissionStorePlugin *self); + G_DEFINE_TYPE (WpPortalPermissionStorePlugin, wp_portal_permissionstore_plugin, WP_TYPE_PLUGIN) @@ -115,8 +117,7 @@ wp_portal_permissionstore_plugin_finalize (GObject * object) } static void -wp_portal_permissionstore_plugin_disable_internal ( - WpPortalPermissionStorePlugin *self) +clear_connection (WpPortalPermissionStorePlugin *self) { if (self->connection && self->signal_id > 0) g_dbus_connection_signal_unsubscribe (self->connection, self->signal_id); @@ -126,38 +127,81 @@ wp_portal_permissionstore_plugin_disable_internal ( self->state = WP_DBUS_CONNECTION_STATUS_CLOSED; g_object_notify (G_OBJECT (self), "state"); } +} - wp_object_update_features (WP_OBJECT (self), 0, WP_PLUGIN_FEATURE_ENABLED); +static gboolean +do_connect (WpPortalPermissionStorePlugin *self, GAsyncReadyCallback callback, + gpointer data, GError **error) +{ + g_autofree gchar *address = NULL; + + address = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SESSION, NULL, error); + if (!address) { + g_prefix_error (error, "Error acquiring session bus address: "); + return FALSE; + } + + wp_debug_object (self, "Connecting to bus: %s", address); + + self->state = WP_DBUS_CONNECTION_STATUS_CONNECTING; + g_object_notify (G_OBJECT (self), "state"); + + g_dbus_connection_new_for_address (address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | + G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION, + NULL, self->cancellable, callback, data); + return TRUE; +} + +static void +on_reconnect_got_bus (GObject * obj, GAsyncResult * res, gpointer data) +{ + WpPortalPermissionStorePlugin *self = WP_PORTAL_PERMISSIONSTORE_PLUGIN (data); + g_autoptr (GError) error = NULL; + + self->connection = g_dbus_connection_new_for_address_finish (res, &error); + if (!self->connection) { + clear_connection (self); + wp_info_object (self, "Could not reconnect to session bus: %s", + error->message); + return; + } + + wp_debug_object (self, "Reconnected to bus"); + setup_connection (self); +} + +static gboolean +idle_connect (WpPortalPermissionStorePlugin * self) +{ + g_autoptr (GError) error = NULL; + + if (!do_connect (self, on_reconnect_got_bus, self, &error)) + wp_info_object (self, "Cannot reconnect: %s", error->message); + + return G_SOURCE_REMOVE; } static void on_connection_closed (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, gpointer data) { - WpPortalPermissionStorePlugin *self = - WP_PORTAL_PERMISSIONSTORE_PLUGIN (data); + WpPortalPermissionStorePlugin *self = WP_PORTAL_PERMISSIONSTORE_PLUGIN (data); + g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (self)); + wp_info_object (self, "D-Bus connection closed: %s", error->message); - wp_portal_permissionstore_plugin_disable_internal (self); + + clear_connection (self); + + /* try to reconnect on idle if connection was closed */ + if (core) + wp_core_idle_add_closure (core, NULL, g_cclosure_new_object ( + G_CALLBACK (idle_connect), G_OBJECT (self))); } static void -got_bus (GObject * obj, GAsyncResult * res, gpointer data) +setup_connection (WpPortalPermissionStorePlugin *self) { - WpTransition *transition = WP_TRANSITION (data); - WpPortalPermissionStorePlugin *self = - wp_transition_get_source_object (transition); - g_autoptr (GError) error = NULL; - - self->connection = g_dbus_connection_new_for_address_finish (res, &error); - if (!self->connection) { - wp_portal_permissionstore_plugin_disable_internal (self); - g_prefix_error (&error, "Failed to connect to session bus: "); - wp_transition_return_error (transition, g_steal_pointer (&error)); - return; - } - - wp_debug_object (self, "Connected to bus"); - g_signal_connect_object (self->connection, "closed", G_CALLBACK (on_connection_closed), self, 0); g_dbus_connection_set_exit_on_close (self->connection, FALSE); @@ -171,6 +215,27 @@ got_bus (GObject * obj, GAsyncResult * res, gpointer data) G_DBUS_SIGNAL_FLAGS_NONE, wp_portal_permissionstore_plugin_changed, self, NULL); +} + +static void +on_enable_got_bus (GObject * obj, GAsyncResult * res, gpointer data) +{ + WpTransition *transition = WP_TRANSITION (data); + WpPortalPermissionStorePlugin *self = + wp_transition_get_source_object (transition); + g_autoptr (GError) error = NULL; + + self->connection = g_dbus_connection_new_for_address_finish (res, &error); + if (!self->connection) { + clear_connection (self); + g_prefix_error (&error, "Failed to connect to session bus: "); + wp_transition_return_error (transition, g_steal_pointer (&error)); + return; + } + + wp_debug_object (self, "Connected to bus"); + setup_connection (self); + wp_object_update_features (WP_OBJECT (self), WP_PLUGIN_FEATURE_ENABLED, 0); } @@ -181,26 +246,13 @@ wp_portal_permissionstore_plugin_enable (WpPlugin * plugin, WpPortalPermissionStorePlugin *self = WP_PORTAL_PERMISSIONSTORE_PLUGIN (plugin); g_autoptr (GError) error = NULL; - g_autofree gchar *address = NULL; g_return_if_fail (self->state == WP_DBUS_CONNECTION_STATUS_CLOSED); - address = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SESSION, NULL, &error); - if (!address) { - g_prefix_error (&error, "Error acquiring session bus address: "); + if (!do_connect (self, on_enable_got_bus, transition, &error)) { wp_transition_return_error (transition, g_steal_pointer (&error)); return; } - - wp_debug_object (self, "Connecting to bus: %s", address); - - self->state = WP_DBUS_CONNECTION_STATUS_CONNECTING; - g_object_notify (G_OBJECT (self), "state"); - - g_dbus_connection_new_for_address (address, - G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | - G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION, - NULL, self->cancellable, got_bus, transition); } static void @@ -210,9 +262,11 @@ wp_portal_permissionstore_plugin_disable (WpPlugin * plugin) WP_PORTAL_PERMISSIONSTORE_PLUGIN (plugin); g_cancellable_cancel (self->cancellable); - wp_portal_permissionstore_plugin_disable_internal (self); + clear_connection (self); g_clear_object (&self->cancellable); self->cancellable = g_cancellable_new (); + + wp_object_update_features (WP_OBJECT (self), 0, WP_PLUGIN_FEATURE_ENABLED); } static void