From 3701174621efd15d06dcfccdca6e5aa8d2a37e41 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
Date: Sat, 2 Jun 2018 19:34:08 +0200
Subject: [PATCH 09/15] libgdb: Try to reuse connections from the available
proxies
Instead of using the hard-to-maintain shared pointer to the dbus connection
to the manager and reset it when the proxies that use it are deleted, just
look which proxy is currently available and try to reuse the connection
from it.
Fixes #386
---
libgdm/gdm-client.c | 70 +++++++++++++++++++++++++--------------------
1 file changed, 39 insertions(+), 31 deletions(-)
diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c
index 7b42b6c99..acf016a48 100644
--- a/libgdm/gdm-client.c
+++ b/libgdm/gdm-client.c
@@ -19,85 +19,106 @@
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib-object.h>
#include "gdm-client.h"
#include "gdm-client-glue.h"
#include "gdm-manager-glue.h"
#define GDM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_CLIENT, GdmClientPrivate))
#define SESSION_DBUS_PATH "/org/gnome/DisplayManager/Session"
struct GdmClientPrivate
{
GdmUserVerifier *user_verifier;
GHashTable *user_verifier_extensions;
GdmGreeter *greeter;
GdmRemoteGreeter *remote_greeter;
GdmChooser *chooser;
- GDBusConnection *connection;
char *address;
char **enabled_extensions;
};
static void gdm_client_class_init (GdmClientClass *klass);
static void gdm_client_init (GdmClient *client);
static void gdm_client_finalize (GObject *object);
G_DEFINE_TYPE (GdmClient, gdm_client, G_TYPE_OBJECT);
static gpointer client_object = NULL;
GQuark
gdm_client_error_quark (void)
{
static GQuark error_quark = 0;
if (error_quark == 0)
error_quark = g_quark_from_static_string ("gdm-client");
return error_quark;
}
+static GDBusConnection *
+gdm_client_get_open_connection (GdmClient *client)
+{
+ GDBusProxy *proxy = NULL;
+
+ if (client->priv->user_verifier != NULL) {
+ proxy = G_DBUS_PROXY (client->priv->user_verifier);
+ } else if (client->priv->greeter != NULL) {
+ proxy = G_DBUS_PROXY (client->priv->greeter);
+ } else if (client->priv->remote_greeter != NULL) {
+ proxy = G_DBUS_PROXY (client->priv->remote_greeter);
+ } else if (client->priv->chooser != NULL) {
+ proxy = G_DBUS_PROXY (client->priv->chooser);
+ }
+
+ if (proxy != NULL) {
+ return g_dbus_proxy_get_connection (proxy);
+ }
+
+ return NULL;
+}
+
static void
on_got_manager (GObject *object,
GAsyncResult *result,
GTask *task)
{
GdmClient *client;
GError *error;
g_autoptr(GdmManager) manager = NULL;
client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (task)));
error = NULL;
manager = gdm_manager_proxy_new_finish (result, &error);
if (error != NULL) {
g_task_return_error (task, error);
} else {
g_task_return_pointer (task,
g_object_ref (manager),
(GDestroyNotify) g_object_unref);
}
g_object_unref (task);
g_object_unref (client);
}
static void
get_manager (GdmClient *client,
GCancellable *cancellable,
GAsyncReadyCallback callback,
@@ -372,107 +393,106 @@ on_got_manager_for_reauthentication (GdmClient *client,
GCancellable *cancellable;
GdmManager *manager;
char *username;
GError *error;
error = NULL;
manager = g_task_propagate_pointer (G_TASK (result), &error);
if (manager == NULL) {
g_task_return_error (task, error);
g_object_unref (task);
return;
}
cancellable = g_task_get_cancellable (task);
username = g_object_get_data (G_OBJECT (task), "username");
gdm_manager_call_open_reauthentication_channel (manager,
username,
cancellable,
(GAsyncReadyCallback)
on_reauthentication_channel_opened,
task);
g_object_unref (manager);
}
static GDBusConnection *
gdm_client_get_connection_sync (GdmClient *client,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GdmManager) manager = NULL;
+ GDBusConnection *connection;
gboolean ret;
g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE);
- if (client->priv->connection != NULL) {
- return g_object_ref (client->priv->connection);
+ connection = gdm_client_get_open_connection (client);
+
+ if (connection != NULL) {
+ return g_object_ref (connection);
}
manager = gdm_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
"org.gnome.DisplayManager",
"/org/gnome/DisplayManager/Manager",
cancellable,
error);
if (manager == NULL) {
goto out;
}
ret = gdm_manager_call_open_session_sync (manager,
&client->priv->address,
cancellable,
error);
if (!ret) {
goto out;
}
g_debug ("GdmClient: connecting to address: %s", client->priv->address);
- client->priv->connection = g_dbus_connection_new_for_address_sync (client->priv->address,
- G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
- NULL,
- cancellable,
- error);
+ connection = g_dbus_connection_new_for_address_sync (client->priv->address,
+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
+ NULL,
+ cancellable,
+ error);
- if (client->priv->connection == NULL) {
+ if (connection == NULL) {
g_clear_pointer (&client->priv->address, g_free);
goto out;
}
- g_object_add_weak_pointer (G_OBJECT (client->priv->connection),
- (gpointer *)
- &client->priv->connection);
-
out:
- return client->priv->connection;
+ return connection;
}
static void
on_connected (GObject *source_object,
GAsyncResult *result,
GTask *task)
{
GDBusConnection *connection;
GError *error;
error = NULL;
connection = g_dbus_connection_new_for_address_finish (result, &error);
if (!connection) {
g_task_return_error (task, error);
g_object_unref (task);
return;
}
g_task_return_pointer (task,
g_object_ref (connection),
(GDestroyNotify) g_object_unref);
g_object_unref (task);
g_object_unref (connection);
}
static void
on_session_opened (GdmManager *manager,
GAsyncResult *result,
GTask *task)
{
@@ -518,87 +538,83 @@ on_got_manager_for_opening_connection (GdmClient *client,
if (manager == NULL) {
g_task_return_error (task, error);
g_object_unref (task);
return;
}
cancellable = g_task_get_cancellable (task);
gdm_manager_call_open_session (manager,
cancellable,
(GAsyncReadyCallback)
on_session_opened,
task);
g_object_unref (manager);
}
static GDBusConnection *
gdm_client_get_connection_finish (GdmClient *client,
GAsyncResult *result,
GError **error)
{
GDBusConnection *connection;
g_return_val_if_fail (GDM_IS_CLIENT (client), FALSE);
connection = g_task_propagate_pointer (G_TASK (result), error);
if (connection == NULL) {
return NULL;
}
- if (client->priv->connection == NULL) {
- client->priv->connection = connection;
- g_object_add_weak_pointer (G_OBJECT (client->priv->connection),
- (gpointer *) &client->priv->connection);
- }
-
return connection;
}
static void
gdm_client_get_connection (GdmClient *client,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
+ GDBusConnection *connection;
g_return_if_fail (GDM_IS_CLIENT (client));
task = g_task_new (G_OBJECT (client),
cancellable,
callback,
user_data);
- if (client->priv->connection != NULL) {
+ connection = gdm_client_get_open_connection (client);
+ if (connection != NULL) {
g_task_return_pointer (task,
- g_object_ref (client->priv->connection),
+ g_object_ref (connection),
(GDestroyNotify) g_object_unref);
g_object_unref (task);
return;
}
get_manager (client,
cancellable,
(GAsyncReadyCallback)
on_got_manager_for_opening_connection,
task);
}
/**
* gdm_client_open_reauthentication_channel_sync:
* @client: a #GdmClient
* @username: user to reauthenticate
* @cancellable: a #GCancellable
* @error: a #GError
*
* Gets a #GdmUserVerifier object that can be used to
* reauthenticate an already logged in user. Free with
* g_object_unref to close reauthentication channel.
*
* Returns: (transfer full): #GdmUserVerifier or %NULL if @username is not
* already logged in.
*/
GdmUserVerifier *
gdm_client_open_reauthentication_channel_sync (GdmClient *client,
const char *username,
GCancellable *cancellable,
@@ -748,61 +764,61 @@ gdm_client_get_user_verifier_sync (GdmClient *client,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
SESSION_DBUS_PATH,
cancellable,
error);
if (client->priv->user_verifier != NULL) {
g_object_add_weak_pointer (G_OBJECT (client->priv->user_verifier),
(gpointer *)
&client->priv->user_verifier);
if (client->priv->enabled_extensions != NULL) {
gboolean res;
client->priv->user_verifier_extensions = g_hash_table_new_full (g_str_hash,
g_str_equal,
NULL,
(GDestroyNotify)
free_interface_skeleton);
res = gdm_user_verifier_call_enable_extensions_sync (client->priv->user_verifier,
(const char * const *)
client->priv->enabled_extensions,
cancellable,
NULL);
if (res) {
size_t i;
for (i = 0; client->priv->enabled_extensions[i] != NULL; i++) {
if (strcmp (client->priv->enabled_extensions[i],
gdm_user_verifier_choice_list_interface_info ()->name) == 0) {
GdmUserVerifierChoiceList *choice_list_interface;
- choice_list_interface = gdm_user_verifier_choice_list_proxy_new_sync (client->priv->connection,
+ choice_list_interface = gdm_user_verifier_choice_list_proxy_new_sync (connection,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
SESSION_DBUS_PATH,
cancellable,
NULL);
if (choice_list_interface != NULL)
g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], choice_list_interface);
}
}
}
}
}
return client->priv->user_verifier;
}
static void
on_connection_for_user_verifier (GdmClient *client,
GAsyncResult *result,
GTask *task)
{
g_autoptr(GDBusConnection) connection = NULL;
GCancellable *cancellable;
GError *error;
error = NULL;
connection = gdm_client_get_connection_finish (client, result, &error);
if (connection == NULL) {
g_task_return_error (task, error);
@@ -1482,68 +1498,60 @@ gdm_client_finalize (GObject *object)
g_return_if_fail (GDM_IS_CLIENT (object));
client = GDM_CLIENT (object);
g_return_if_fail (client->priv != NULL);
if (client->priv->user_verifier != NULL) {
g_object_remove_weak_pointer (G_OBJECT (client->priv->user_verifier),
(gpointer *)
&client->priv->user_verifier);
}
if (client->priv->greeter != NULL) {
g_object_remove_weak_pointer (G_OBJECT (client->priv->greeter),
(gpointer *)
&client->priv->greeter);
}
if (client->priv->remote_greeter != NULL) {
g_object_remove_weak_pointer (G_OBJECT (client->priv->remote_greeter),
(gpointer *)
&client->priv->remote_greeter);
}
if (client->priv->chooser != NULL) {
g_object_remove_weak_pointer (G_OBJECT (client->priv->chooser),
(gpointer *)
&client->priv->chooser);
}
- if (client->priv->connection != NULL) {
- g_object_remove_weak_pointer (G_OBJECT (client->priv->connection),
- (gpointer *)
- &client->priv->connection);
- }
-
- g_clear_object (&client->priv->connection);
-
g_strfreev (client->priv->enabled_extensions);
g_free (client->priv->address);
G_OBJECT_CLASS (gdm_client_parent_class)->finalize (object);
}
GdmClient *
gdm_client_new (void)
{
if (client_object != NULL) {
g_object_ref (client_object);
} else {
client_object = g_object_new (GDM_TYPE_CLIENT, NULL);
g_object_add_weak_pointer (client_object,
(gpointer *) &client_object);
}
return GDM_CLIENT (client_object);
}
/**
* gdm_client_set_enabled_extensions:
* @client: a #GdmClient
* @extensions: (array zero-terminated=1) (element-type utf8): a list of extensions
*
* Enables GDM's pam extensions. Currently, only
* org.gnome.DisplayManager.UserVerifier.ChoiceList is supported.
*/
void
--
2.25.1