fprintd: Use GDBus codegen based implementation

Fprintd is dependent on the deprecated dbus-glib, also this doesn't provide
various features we can take advantage of, like the ones for async
authentication mechanism.

So, remove all the dbus-glib dependencies and simplify the code, but without
any further refactor, and keeping everything as it used to work, while this
will give room for further improvements in subsequent commits.

Internally, we just use dbus-codegen to generate the skeletons, and we
use the generated FprintdDBusManager with composition, while we
implement the device skeleton interface in FprintDevice, so that we
don't have to use it as a proxy, and keep being closer to what it used
to be with dbus-glib.

Fixes: #61
This commit is contained in:
Marco Trevisan (Treviño)
2020-02-03 20:29:56 +01:00
committed by Benjamin Berg
parent e224913b80
commit 93bad82540
15 changed files with 750 additions and 588 deletions

View File

@ -1,6 +1,7 @@
/*
* /net/reactivated/Fprint/Manager object implementation
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
* Copyright (C) 2020 Marco Trevisan <marco.trevisan@canonical.com>
*
* 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
@ -19,7 +20,6 @@
#include <unistd.h>
#include <stdlib.h>
#include <dbus/dbus-glib-bindings.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <fprint.h>
@ -27,17 +27,16 @@
#include "fprintd.h"
extern DBusGConnection *fprintd_dbus_conn;
static void fprint_manager_constructed (GObject *object);
static gboolean fprint_manager_get_devices(FprintManager *manager,
GPtrArray **devices, GError **error);
static gboolean fprint_manager_get_default_device(FprintManager *manager,
const char **device, GError **error);
#include "manager-dbus-glue.h"
typedef struct
{
GDBusConnection *connection;
FprintDBusManager *dbus_manager;
FpContext *context;
GSList *dev_registry;
gboolean no_timeout;
@ -46,28 +45,81 @@ typedef struct
G_DEFINE_TYPE_WITH_CODE(FprintManager, fprint_manager, G_TYPE_OBJECT, G_ADD_PRIVATE (FprintManager))
enum {
PROP_0,
FPRINT_MANAGER_CONNECTION,
N_PROPS
};
static GParamSpec *properties[N_PROPS];
static void fprint_manager_finalize(GObject *object)
{
FprintManagerPrivate *priv = fprint_manager_get_instance_private (FPRINT_MANAGER (object));
g_clear_object (&priv->dbus_manager);
g_clear_object (&priv->connection);
g_clear_object (&priv->context);
g_slist_free(priv->dev_registry);
G_OBJECT_CLASS(fprint_manager_parent_class)->finalize(object);
}
static void fprint_manager_set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
{
FprintManager *self = FPRINT_MANAGER (object);
FprintManagerPrivate *priv = fprint_manager_get_instance_private (self);
switch (property_id) {
case FPRINT_MANAGER_CONNECTION:
priv->connection = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void fprint_manager_get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
{
FprintManager *self = FPRINT_MANAGER (object);
FprintManagerPrivate *priv = fprint_manager_get_instance_private (self);
switch (property_id) {
case FPRINT_MANAGER_CONNECTION:
g_value_set_object (value, priv->connection);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void fprint_manager_class_init(FprintManagerClass *klass)
{
dbus_g_object_type_install_info(FPRINT_TYPE_MANAGER,
&dbus_glib_fprint_manager_object_info);
dbus_g_error_domain_register (FPRINT_ERROR, FPRINT_ERROR_DBUS_INTERFACE, FPRINT_TYPE_ERROR);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
G_OBJECT_CLASS(klass)->finalize = fprint_manager_finalize;
object_class->constructed = fprint_manager_constructed;
object_class->set_property = fprint_manager_set_property;
object_class->get_property = fprint_manager_get_property;
object_class->finalize = fprint_manager_finalize;
properties[FPRINT_MANAGER_CONNECTION] =
g_param_spec_object ("connection",
"Connection",
"Set GDBus connection property",
G_TYPE_DBUS_CONNECTION,
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_READWRITE);
g_object_class_install_properties (object_class, N_PROPS, properties);
}
static gchar *get_device_path(FprintDevice *rdev)
{
return g_strdup_printf("/net/reactivated/Fprint/Device/%d",
return g_strdup_printf (FPRINT_SERVICE_PATH "/Device/%d",
_fprint_device_get_id(rdev));
}
@ -106,6 +158,44 @@ fprint_manager_in_use_notified (FprintDevice *rdev, GParamSpec *spec, FprintMana
priv->timeout_id = g_timeout_add_seconds (TIMEOUT, (GSourceFunc) fprint_manager_timeout_cb, manager);
}
static gboolean
handle_get_devices (FprintManager *manager, GDBusMethodInvocation *invocation,
FprintDBusManager *skeleton)
{
g_autoptr(GPtrArray) devices = NULL;
g_autoptr(GError) error = NULL;
if (!fprint_manager_get_devices (manager, &devices, &error)) {
g_dbus_method_invocation_return_gerror (invocation, error);
return TRUE;
}
fprint_dbus_manager_complete_get_devices (skeleton, invocation,
(const gchar *const *)
devices->pdata);
return TRUE;
}
static gboolean
handle_get_default_device (FprintManager *manager,
GDBusMethodInvocation *invocation,
FprintDBusManager *skeleton)
{
const gchar *device;
g_autoptr(GError) error = NULL;
if (!fprint_manager_get_default_device (manager, &device, &error)) {
g_dbus_method_invocation_return_gerror (invocation, error);
return TRUE;
}
fprint_dbus_manager_complete_get_default_device (skeleton, invocation,
device);
return TRUE;
}
static void
device_added_cb (FprintManager *manager, FpDevice *device, FpContext *context)
{
@ -118,8 +208,9 @@ device_added_cb (FprintManager *manager, FpDevice *device, FpContext *context)
priv->dev_registry = g_slist_prepend (priv->dev_registry, rdev);
path = get_device_path (rdev);
dbus_g_connection_register_g_object(fprintd_dbus_conn, path,
G_OBJECT(rdev));
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (rdev),
priv->connection,
path, NULL);
}
static void
@ -140,7 +231,8 @@ device_removed_cb (FprintManager *manager, FpDevice *device, FpContext *context)
priv->dev_registry = g_slist_delete_link (priv->dev_registry, item);
dbus_g_connection_unregister_g_object(fprintd_dbus_conn, G_OBJECT(rdev));
g_dbus_interface_skeleton_unexport (
G_DBUS_INTERFACE_SKELETON (rdev));
g_signal_handlers_disconnect_by_data (rdev, manager);
g_object_unref (rdev);
@ -154,13 +246,29 @@ device_removed_cb (FprintManager *manager, FpDevice *device, FpContext *context)
fprint_manager_in_use_notified (NULL, NULL, manager);
}
static void
fprint_manager_init (FprintManager *manager)
static void fprint_manager_constructed (GObject *object)
{
FprintManager *manager = FPRINT_MANAGER (object);
FprintManagerPrivate *priv = fprint_manager_get_instance_private (manager);
priv->dbus_manager = fprint_dbus_manager_skeleton_new ();
priv->context = fp_context_new ();
g_signal_connect_object (priv->dbus_manager,
"handle-get-devices",
G_CALLBACK (handle_get_devices),
manager,
G_CONNECT_SWAPPED);
g_signal_connect_object (priv->dbus_manager,
"handle-get-default-device",
G_CALLBACK (handle_get_default_device),
manager,
G_CONNECT_SWAPPED);
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_manager),
priv->connection,
FPRINT_SERVICE_PATH "/Manager", NULL);
/* And register the signals for initial enumeration and hotplug. */
g_signal_connect_object (priv->context,
"device-added",
@ -179,16 +287,20 @@ fprint_manager_init (FprintManager *manager)
*/
fp_context_enumerate (priv->context);
dbus_g_connection_register_g_object(fprintd_dbus_conn,
"/net/reactivated/Fprint/Manager", G_OBJECT(manager));
G_OBJECT_CLASS (fprint_manager_parent_class)->constructed (object);
}
FprintManager *fprint_manager_new(gboolean no_timeout)
static void
fprint_manager_init (FprintManager *manager)
{
}
FprintManager *fprint_manager_new (GDBusConnection *connection, gboolean no_timeout)
{
FprintManagerPrivate *priv;
GObject *object;
object = g_object_new(FPRINT_TYPE_MANAGER, NULL);
object = g_object_new (FPRINT_TYPE_MANAGER, "connection", connection, NULL);
priv = fprint_manager_get_instance_private (FPRINT_MANAGER (object));
priv->no_timeout = no_timeout;
@ -213,10 +325,15 @@ static gboolean fprint_manager_get_devices(FprintManager *manager,
if (num_open > 0) {
for (l = elem; l != NULL; l = l->next) {
FprintDevice *rdev = l->data;
g_ptr_array_add(devs, get_device_path(rdev));
GDBusInterfaceSkeleton *dev_skeleton = l->data;
const char *path;
path = g_dbus_interface_skeleton_get_object_path (
dev_skeleton);
g_ptr_array_add (devs, (char *) path);
}
}
g_ptr_array_add (devs, NULL);
g_slist_free(elem);
@ -235,7 +352,8 @@ static gboolean fprint_manager_get_default_device(FprintManager *manager,
num_open = g_slist_length(elem);
if (num_open > 0) {
*device = get_device_path (g_slist_last (elem)->data);
GDBusInterfaceSkeleton *dev_skeleton = g_slist_last (elem)->data;
*device = g_dbus_interface_skeleton_get_object_path (dev_skeleton);
return TRUE;
} else {
g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE,
@ -245,34 +363,28 @@ static gboolean fprint_manager_get_default_device(FprintManager *manager,
}
}
GQuark fprint_error_quark(void)
#define ERROR_ENTRY(name, dbus_name) \
{ FPRINT_ERROR_ ## name, FPRINT_ERROR_DBUS_INTERFACE "." dbus_name }
GDBusErrorEntry fprint_error_entries[] =
{
static GQuark quark = 0;
if (!quark)
quark = g_quark_from_static_string("fprintd-error-quark");
return quark;
}
ERROR_ENTRY (CLAIM_DEVICE, "ClaimDevice"),
ERROR_ENTRY (ALREADY_IN_USE, "AlreadyInUse"),
ERROR_ENTRY (INTERNAL, "Internal"),
ERROR_ENTRY (PERMISSION_DENIED, "PermissionDenied"),
ERROR_ENTRY (NO_ENROLLED_PRINTS, "NoEnrolledPrints"),
ERROR_ENTRY (NO_ACTION_IN_PROGRESS, "NoActionInProgress"),
ERROR_ENTRY (INVALID_FINGERNAME, "InvalidFingername"),
ERROR_ENTRY (NO_SUCH_DEVICE, "NoSuchDevice"),
};
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
GType
fprint_error_get_type (void)
GQuark fprint_error_quark (void)
{
static GType etype = 0;
if (etype == 0) {
static const GEnumValue values[] =
{
ENUM_ENTRY (FPRINT_ERROR_CLAIM_DEVICE, "ClaimDevice"),
ENUM_ENTRY (FPRINT_ERROR_ALREADY_IN_USE, "AlreadyInUse"),
ENUM_ENTRY (FPRINT_ERROR_INTERNAL, "Internal"),
ENUM_ENTRY (FPRINT_ERROR_PERMISSION_DENIED, "PermissionDenied"),
ENUM_ENTRY (FPRINT_ERROR_NO_ENROLLED_PRINTS, "NoEnrolledPrints"),
ENUM_ENTRY (FPRINT_ERROR_NO_ACTION_IN_PROGRESS, "NoActionInProgress"),
ENUM_ENTRY (FPRINT_ERROR_INVALID_FINGERNAME, "InvalidFingername"),
ENUM_ENTRY (FPRINT_ERROR_NO_SUCH_DEVICE, "NoSuchDevice"),
{ 0, 0, 0 }
};
etype = g_enum_register_static ("FprintError", values);
static volatile gsize quark = 0;
if (!quark) {
g_dbus_error_register_error_domain ("fprintd-error-quark",
&quark,
fprint_error_entries,
G_N_ELEMENTS (fprint_error_entries));
}
return etype;
return (GQuark) quark;
}