[gnome-control-center] user-accounts: Add fingerprint manager



commit 9d1038db1f0c8b675b99980b1beba9c737a0c0cf
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Mon Apr 6 22:47:06 2020 +0200

    user-accounts: Add fingerprint manager
    
    This is a wrapper to read the state of the fingerprint devices and to check
    asynchronously whether we have them and if they have enrolled prints we can
    use to log-in.

 panels/user-accounts/cc-fingerprint-manager.c      | 490 +++++++++++++++++
 panels/user-accounts/cc-fingerprint-manager.h      |  63 +++
 .../data/net.reactivated.Fprint.Device.xml         | 585 +++++++++++++++++++++
 .../data/net.reactivated.Fprint.Manager.xml        |  50 ++
 panels/user-accounts/meson.build                   |  21 +
 5 files changed, 1209 insertions(+)
---
diff --git a/panels/user-accounts/cc-fingerprint-manager.c b/panels/user-accounts/cc-fingerprint-manager.c
new file mode 100644
index 000000000..c9cb7f362
--- /dev/null
+++ b/panels/user-accounts/cc-fingerprint-manager.c
@@ -0,0 +1,490 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2020 Canonical Ltd.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ * Authors: Marco Trevisan <marco trevisan canonical com>
+ */
+
+#include "cc-fingerprint-manager.h"
+
+#include "cc-fprintd-generated.h"
+#include "cc-user-accounts-enum-types.h"
+
+#define CC_FPRINTD_NAME "net.reactivated.Fprint"
+#define CC_FPRINTD_MANAGER_PATH "/net/reactivated/Fprint/Manager"
+
+struct _CcFingerprintManager
+{
+  GObject parent_instance;
+};
+
+typedef struct
+{
+  ActUser           *user;
+  GTask             *current_task;
+  CcFingerprintState state;
+} CcFingerprintManagerPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (CcFingerprintManager, cc_fingerprint_manager, G_TYPE_OBJECT)
+
+enum {
+  PROP_0,
+  PROP_USER,
+  PROP_STATE,
+  N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
+CcFingerprintManager *
+cc_fingerprint_manager_new (ActUser *user)
+{
+  return g_object_new (CC_TYPE_FINGERPRINT_MANAGER, "user", user, NULL);
+}
+
+static void
+cc_fingerprint_manager_dispose (GObject *object)
+{
+  CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object);
+  CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+
+  if (priv->current_task)
+    {
+      g_cancellable_cancel (g_task_get_cancellable (priv->current_task));
+      priv->current_task = NULL;
+    }
+
+  g_clear_object (&priv->user);
+
+  G_OBJECT_CLASS (cc_fingerprint_manager_parent_class)->dispose (object);
+}
+
+static void
+cc_fingerprint_manager_get_property (GObject    *object,
+                                     guint       prop_id,
+                                     GValue     *value,
+                                     GParamSpec *pspec)
+{
+  CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object);
+  CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+
+  switch (prop_id)
+    {
+    case PROP_STATE:
+      g_value_set_enum (value, priv->state);
+      break;
+
+    case PROP_USER:
+      g_value_set_object (value, priv->user);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+cc_fingerprint_manager_set_property (GObject      *object,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+  CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object);
+  CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+
+  switch (prop_id)
+    {
+    case PROP_USER:
+      g_set_object (&priv->user, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+cc_fingerprint_manager_constructed (GObject *object)
+{
+  cc_fingerprint_manager_update_state (CC_FINGERPRINT_MANAGER (object));
+}
+
+static void
+cc_fingerprint_manager_class_init (CcFingerprintManagerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed = cc_fingerprint_manager_constructed;
+  object_class->dispose = cc_fingerprint_manager_dispose;
+  object_class->get_property = cc_fingerprint_manager_get_property;
+  object_class->set_property = cc_fingerprint_manager_set_property;
+
+  properties[PROP_USER] =
+    g_param_spec_object ("user",
+                         "User",
+                         "The user account we manage the fingerprint for",
+                         ACT_TYPE_USER,
+                         G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+
+  properties[PROP_STATE] =
+    g_param_spec_enum ("state",
+                       "State",
+                       "The state of the fingerprint for the user",
+                       CC_TYPE_FINGERPRINT_STATE, CC_FINGERPRINT_STATE_NONE,
+                       G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+cc_fingerprint_manager_init (CcFingerprintManager *self)
+{
+}
+
+typedef struct
+{
+  guint  waiting_devices;
+  GList *devices;
+} DeviceListData;
+
+static void
+object_list_destroy_notify (gpointer data)
+{
+  GList *list = data;
+  g_list_free_full (list, g_object_unref);
+}
+
+static void
+on_device_proxy (GObject *object, GAsyncResult *res, gpointer user_data)
+{
+  g_autoptr(CcFprintdDevice) fprintd_device = NULL;
+  g_autoptr(GTask) task = G_TASK (user_data);
+  g_autoptr(GError) error = NULL;
+  DeviceListData *list_data = g_task_get_task_data (task);
+
+  fprintd_device = cc_fprintd_device_proxy_new_for_bus_finish (res, &error);
+  list_data->waiting_devices--;
+
+  if (error)
+    {
+      if (list_data->waiting_devices == 0)
+        g_task_return_error (task, g_steal_pointer (&error));
+      else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        g_warning ("Impossible to ge the device proxy: %s", error->message);
+
+      return;
+    }
+
+  g_debug ("Got fingerprint device %s", cc_fprintd_device_get_name (fprintd_device));
+
+  list_data->devices = g_list_append (list_data->devices, g_steal_pointer (&fprintd_device));
+
+  if (list_data->waiting_devices == 0)
+    g_task_return_pointer (task, g_steal_pointer (&list_data->devices), object_list_destroy_notify);
+}
+
+static void
+on_devices_list (GObject *object, GAsyncResult *res, gpointer user_data)
+{
+  CcFprintdManager *fprintd_manager = CC_FPRINTD_MANAGER (object);
+  g_autoptr(GTask) task = G_TASK (user_data);
+  g_autoptr(GError) error = NULL;
+  g_auto(GStrv) devices_list = NULL;
+  DeviceListData *list_data;
+  guint i;
+
+  cc_fprintd_manager_call_get_devices_finish (fprintd_manager, &devices_list, res, &error);
+
+  if (error)
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      return;
+    }
+
+  if (!devices_list || !devices_list[0])
+    {
+      g_task_return_pointer (task, NULL, NULL);
+      return;
+    }
+
+  list_data = g_new0 (DeviceListData, 1);
+  g_task_set_task_data (task, list_data, g_free);
+
+  g_debug ("Fprintd replied with %u device(s)", g_strv_length (devices_list));
+
+  for (i = 0; devices_list[i] != NULL; ++i)
+    {
+      const char *device_path = devices_list[i];
+
+      list_data->waiting_devices++;
+
+      cc_fprintd_device_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+                                           G_DBUS_PROXY_FLAGS_NONE,
+                                           CC_FPRINTD_NAME,
+                                           device_path,
+                                           g_task_get_cancellable (task),
+                                           on_device_proxy,
+                                           g_object_ref (task));
+    }
+}
+
+static void
+on_manager_proxy (GObject *object, GAsyncResult *res, gpointer user_data)
+{
+  g_autoptr(GTask) task = G_TASK (user_data);
+  g_autoptr(CcFprintdManager) fprintd_manager = NULL;
+  g_autoptr(GError) error = NULL;
+
+  fprintd_manager = cc_fprintd_manager_proxy_new_for_bus_finish (res, &error);
+
+  if (error)
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      return;
+    }
+
+  g_debug ("Fprintd manager connected");
+
+  cc_fprintd_manager_call_get_devices (fprintd_manager,
+                                       g_task_get_cancellable (task),
+                                       on_devices_list,
+                                       g_object_ref (task));
+}
+
+static void
+fprintd_manager_connect (CcFingerprintManager *self,
+                         GAsyncReadyCallback   callback,
+                         GTask                *task)
+{
+  g_assert (G_IS_TASK (task));
+
+  cc_fprintd_manager_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
+                                        CC_FPRINTD_NAME, CC_FPRINTD_MANAGER_PATH,
+                                        g_task_get_cancellable (task),
+                                        callback,
+                                        task);
+}
+
+void
+cc_fingerprint_manager_get_devices (CcFingerprintManager *self,
+                                    GCancellable         *cancellable,
+                                    GAsyncReadyCallback   callback,
+                                    gpointer              user_data)
+{
+  g_autoptr(GTask) task = NULL;
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, cc_fingerprint_manager_get_devices);
+
+  fprintd_manager_connect (self, on_manager_proxy, g_steal_pointer (&task));
+}
+
+/**
+ * cc_fingerprint_manager_get_devices_finish:
+ * @self: The #CcFingerprintManager
+ * @result: A #GAsyncResult
+ * @error: Return location for errors, or %NULL to ignore
+ *
+ * Finish an asynchronous operation to list all devices.
+ *
+ * Returns: (element-type CcFprintdDevice) (transfer full): List of prints or %NULL on error
+ */
+GList *
+cc_fingerprint_manager_get_devices_finish (CcFingerprintManager *self,
+                                           GAsyncResult         *res,
+                                           GError              **error)
+{
+  g_return_val_if_fail (g_task_is_valid (res, self), NULL);
+
+  return g_task_propagate_pointer (G_TASK (res), error);
+}
+
+static void
+set_state (CcFingerprintManager *self,
+           CcFingerprintState    state)
+{
+  CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+
+  if (priv->state == state)
+    return;
+
+  g_debug ("Fingerprint manager state changed to %d", state);
+
+  priv->state = state;
+  g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATE]);
+}
+
+
+static void
+update_state_callback (GObject      *object,
+                       GAsyncResult *res,
+                       gpointer      user_data)
+{
+  CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object);
+  CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+  g_autoptr(GError) error = NULL;
+  CcFingerprintState state;
+
+  g_return_if_fail (g_task_is_valid (res, self));
+
+  priv->current_task = NULL;
+  state = g_task_propagate_int (G_TASK (res), &error);
+
+  if (error)
+    {
+      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+        return;
+
+      g_warning ("Impossible to update fingerprint manager state: %s",
+                 error->message);
+
+      state = CC_FINGERPRINT_STATE_NONE;
+    }
+
+  set_state (self, state);
+}
+
+static void
+on_device_list_enrolled (GObject      *object,
+                         GAsyncResult *res,
+                         gpointer      user_data)
+{
+  CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object);
+  g_autoptr(GTask) task = G_TASK (user_data);
+  g_autoptr(GError) error = NULL;
+  g_auto(GStrv) enrolled_fingers = NULL;
+  guint waiting_devices;
+  guint num_enrolled_fingers;
+
+  waiting_devices = GPOINTER_TO_UINT (g_task_get_task_data (task));
+
+  cc_fprintd_device_call_list_enrolled_fingers_finish (fprintd_device,
+                                                       &enrolled_fingers,
+                                                       res, &error);
+  waiting_devices--;
+  g_task_set_task_data (task, GUINT_TO_POINTER (waiting_devices), NULL);
+
+  if (g_task_get_completed (task))
+    return;
+
+  if (error)
+    {
+      g_autofree char *dbus_error = g_dbus_error_get_remote_error (error);
+
+      if (!g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.NoEnrolledPrints"))
+        {
+          if (waiting_devices == 0)
+            g_task_return_error (task, g_steal_pointer (&error));
+          else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+            g_warning ("Impossible to list enrolled fingers: %s", error->message);
+
+          return;
+        }
+    }
+
+  num_enrolled_fingers = enrolled_fingers ? g_strv_length (enrolled_fingers) : 0;
+
+  g_debug ("Device %s has %u enrolled fingers",
+           cc_fprintd_device_get_name (fprintd_device),
+           num_enrolled_fingers);
+
+  if (num_enrolled_fingers > 0)
+    g_task_return_int (task, CC_FINGERPRINT_STATE_ENABLED);
+  else if (waiting_devices == 0)
+    g_task_return_int (task, CC_FINGERPRINT_STATE_DISABLED);
+}
+
+static void
+on_manager_devices_list (GObject      *object,
+                         GAsyncResult *res,
+                         gpointer      user_data)
+{
+  CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object);
+  CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+  g_autolist(CcFprintdDevice) fprintd_devices = NULL;
+  g_autoptr(GTask) task = G_TASK (user_data);
+  g_autoptr(GError) error = NULL;
+  const char *user_name;
+  GList *l;
+
+  fprintd_devices = cc_fingerprint_manager_get_devices_finish (self, res, &error);
+
+  if (error)
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      return;
+    }
+
+  if (fprintd_devices == NULL)
+    {
+      g_debug ("No fingerprint devices found");
+      g_task_return_int (task, CC_FINGERPRINT_STATE_NONE);
+      return;
+    }
+
+  user_name = act_user_get_user_name (priv->user);
+  g_task_set_task_data (task, GUINT_TO_POINTER (g_list_length (fprintd_devices)), NULL);
+
+  for (l = fprintd_devices; l; l = l->next)
+    {
+      CcFprintdDevice *device = l->data;
+
+      g_debug ("Connected to device %s, looking for enrolled fingers",
+               cc_fprintd_device_get_name (device));
+
+      cc_fprintd_device_call_list_enrolled_fingers (device, user_name,
+                                                    g_task_get_cancellable (task),
+                                                    on_device_list_enrolled,
+                                                    g_object_ref (task));
+    }
+}
+
+void
+cc_fingerprint_manager_update_state (CcFingerprintManager *self)
+{
+  CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+  g_autoptr(GCancellable) cancellable = NULL;
+
+  g_return_if_fail (priv->current_task == NULL);
+
+  if (act_user_get_uid (priv->user) != getuid () ||
+      !act_user_is_local_account (priv->user))
+    {
+      set_state (self, CC_FINGERPRINT_STATE_NONE);
+      return;
+    }
+
+
+  cancellable = g_cancellable_new ();
+
+  priv->current_task = g_task_new (self, cancellable, update_state_callback, NULL);
+  g_task_set_source_tag (priv->current_task, cc_fingerprint_manager_update_state);
+
+  cc_fingerprint_manager_get_devices (self, cancellable, on_manager_devices_list,
+                                      priv->current_task);
+}
+
+CcFingerprintState
+cc_fingerprint_manager_get_state (CcFingerprintManager *self)
+{
+  CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self);
+
+  g_return_val_if_fail (CC_IS_FINGERPRINT_MANAGER (self), CC_FINGERPRINT_STATE_NONE);
+
+  return priv->state;
+}
diff --git a/panels/user-accounts/cc-fingerprint-manager.h b/panels/user-accounts/cc-fingerprint-manager.h
new file mode 100644
index 000000000..89c958929
--- /dev/null
+++ b/panels/user-accounts/cc-fingerprint-manager.h
@@ -0,0 +1,63 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2020 Canonical Ltd.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ * Authors: Marco Trevisan <marco trevisan canonical com>
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <act/act.h>
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_FINGERPRINT_MANAGER (cc_fingerprint_manager_get_type ())
+
+G_DECLARE_FINAL_TYPE (CcFingerprintManager, cc_fingerprint_manager, CC, FINGERPRINT_MANAGER, GObject)
+
+/**
+ * CcFingerprintManager:
+ * @CC_FINGERPRINT_STATE_NONE: Fingerprint recognition is not available
+ * @CC_FINGERPRINT_STATE_ENABLED: Fingerprint recognition is enabled
+ * @CC_FINGERPRINT_STATE_DISABLED: Fingerprint recognition is disabled
+ *
+ * The status of the fingerprint support.
+ */
+typedef enum {
+  CC_FINGERPRINT_STATE_NONE,
+  CC_FINGERPRINT_STATE_ENABLED,
+  CC_FINGERPRINT_STATE_DISABLED,
+} CcFingerprintState;
+
+CcFingerprintManager * cc_fingerprint_manager_new (ActUser *user);
+
+CcFingerprintState cc_fingerprint_manager_get_state (CcFingerprintManager *fp_manager);
+
+void cc_fingerprint_manager_update_state (CcFingerprintManager *fp_manager);
+
+void cc_fingerprint_manager_get_devices (CcFingerprintManager *fp_manager,
+                                         GCancellable         *cancellable,
+                                         GAsyncReadyCallback   res,
+                                         gpointer              user_data);
+
+GList *cc_fingerprint_manager_get_devices_finish (CcFingerprintManager *fp_manager,
+                                                  GAsyncResult         *res,
+                                                  GError              **error);
+
+G_END_DECLS
diff --git a/panels/user-accounts/data/net.reactivated.Fprint.Device.xml 
b/panels/user-accounts/data/net.reactivated.Fprint.Device.xml
new file mode 100644
index 000000000..786d89c3d
--- /dev/null
+++ b/panels/user-accounts/data/net.reactivated.Fprint.Device.xml
@@ -0,0 +1,585 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"; [
+<!ENTITY ERROR_CLAIM_DEVICE "net.reactivated.Fprint.Error.ClaimDevice">
+<!ENTITY ERROR_ALREADY_IN_USE "net.reactivated.Fprint.Error.AlreadyInUse">
+<!ENTITY ERROR_INTERNAL "net.reactivated.Fprint.Error.Internal">
+<!ENTITY ERROR_PERMISSION_DENIED "net.reactivated.Fprint.Error.PermissionDenied">
+<!ENTITY ERROR_NO_ENROLLED_PRINTS "net.reactivated.Fprint.Error.NoEnrolledPrints">
+<!ENTITY ERROR_NO_ACTION_IN_PROGRESS "net.reactivated.Fprint.Error.NoActionInProgress">
+<!ENTITY ERROR_INVALID_FINGERNAME "net.reactivated.Fprint.Error.InvalidFingername">
+]>
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd";>
+       <interface name="net.reactivated.Fprint.Device">
+                       value="fprint_device" />
+
+               <doc:doc>
+                       <doc:title id="polkit-integration">
+                               PolicyKit integration
+                       </doc:title>
+                       <doc:para>
+                               fprintd uses PolicyKit to check whether users are allowed to access 
fingerprint data, or the
+                               fingerprint readers itself.
+                               <doc:list>
+                                       <doc:item>
+                                               <doc:term>net.reactivated.fprint.device.verify</doc:term>
+                                               <doc:definition>
+                                                       Whether the user is allowed to verify fingers against 
saved fingerprints.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>net.reactivated.fprint.device.enroll</doc:term>
+                                               <doc:definition>
+                                                       Whether the user is allowed to enroll new 
fingerprints.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>net.reactivated.fprint.device.setusername</doc:term>
+                                               <doc:definition>
+                                                       Whether the user is allowed to query, verify, or 
enroll fingerprints for users other than itself.
+                                               </doc:definition>
+                                       </doc:item>
+                               </doc:list>
+                       </doc:para>
+
+                       <doc:title id="usernames">
+                               Usernames
+                       </doc:title>
+                       <doc:para>
+                               When a username argument is used for a method, a PolicyKit check is done on 
the
+                               <doc:tt>net.reactivated.fprint.device.setusername</doc:tt> PolicyKit
+                               action to see whether the user the client is running as is allowed to access 
data from other users.
+                       </doc:para>
+                       <doc:para>
+                               By default, only root is allowed to access fingerprint data for users other 
than itself. For a normal user,
+                               it is recommended that you use an empty string for the username, which will 
mean "the client the user is
+                               running as".
+                       </doc:para>
+                       <doc:para>
+                               See <doc:ref type="description" to="polkit-integration">PolicyKit 
integration</doc:ref>.
+                       </doc:para>
+
+                       <doc:title id="fingerprint-names">
+                               Fingerprint names
+                       </doc:title>
+                       <doc:para>
+                               When a finger name argument is used for a method, it refers to either a 
single finger, or
+                               "any" finger. See the list of possible values below:
+                               <doc:list>
+                                       <doc:item>
+                                               <doc:term>left-thumb</doc:term>
+                                               <doc:definition>
+                                                       Left thumb
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>left-index-finger</doc:term>
+                                               <doc:definition>
+                                                       Left index finger
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>left-middle-finger</doc:term>
+                                               <doc:definition>
+                                                       Left middle finger
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>left-ring-finger</doc:term>
+                                               <doc:definition>
+                                                       Left ring finger
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>left-little-finger</doc:term>
+                                               <doc:definition>
+                                                       Left little finger
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>right-thumb</doc:term>
+                                               <doc:definition>
+                                                       Right thumb
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>right-index-finger</doc:term>
+                                               <doc:definition>
+                                                       Right index finger
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>right-middle-finger</doc:term>
+                                               <doc:definition>
+                                                       Right middle finger
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>right-ring-finger</doc:term>
+                                               <doc:definition>
+                                                       Right ring finger
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>right-little-finger</doc:term>
+                                               <doc:definition>
+                                                       Right little finger
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>any</doc:term>
+                                               <doc:definition>
+                                                       Any finger. This is only used for <doc:ref 
type="method" to="Device.VerifyStart">Device.VerifyStart</doc:ref>
+                                                       (select the first finger with a fingerprint 
associated, or all the fingerprints available for the user when
+                                                       the device supports it) and <doc:ref type="signal" 
to="Device::VerifyFingerSelected">Device::VerifyFingerSelected</doc:ref>
+                                                       (any finger with an associated fingerprint can be 
used).
+                                               </doc:definition>
+                                       </doc:item>
+                               </doc:list>
+                       </doc:para>
+
+                       <doc:title id="verify-statuses">
+                               Verify Statuses
+                       </doc:title>
+                       <doc:para>
+                               <doc:list>
+                                       Possible values for the result passed through <doc:ref type="signal" 
to="Device::VerifyResult">Device::VerifyResult</doc:ref> are:
+                                       <doc:item>
+                                               <doc:term>verify-no-match</doc:term>
+                                               <doc:definition>
+                                                       The verification did not match, <doc:ref 
type="method" to="Device.VerifyStop">Device.VerifyStop</doc:ref> should now be called.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>verify-match</doc:term>
+                                               <doc:definition>
+                                                       The verification succeeded, <doc:ref type="method" 
to="Device.VerifyStop">Device.VerifyStop</doc:ref> should now be called.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>verify-retry-scan</doc:term>
+                                               <doc:definition>
+                                                       The user should retry scanning their finger, the 
verification is still ongoing.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>verify-swipe-too-short</doc:term>
+                                               <doc:definition>
+                                                       The user's swipe was too short. The user should retry 
scanning their finger, the verification is still ongoing.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>verify-finger-not-centered</doc:term>
+                                               <doc:definition>
+                                                       The user's finger was not centered on the reader. The 
user should retry scanning their finger, the verification is still ongoing.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>verify-remove-and-retry</doc:term>
+                                               <doc:definition>
+                                                       The user should remove their finger from the reader 
and retry scanning their finger, the verification is still ongoing.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>verify-disconnected</doc:term>
+                                               <doc:definition>
+                                                       The device was disconnected during the verification, 
no other actions should be taken, and you shouldn't use the device any more.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>verify-unknown-error</doc:term>
+                                               <doc:definition>
+                                                       An unknown error occurred (usually a driver problem), 
<doc:ref type="method" to="Device.VerifyStop">Device.VerifyStop</doc:ref> should now be called.
+                                               </doc:definition>
+                                       </doc:item>
+                               </doc:list>
+                       </doc:para>
+
+                       <doc:title id="enroll-statuses">
+                               Enroll Statuses
+                       </doc:title>
+                       <doc:para>
+                               <doc:list>
+                                       Possible values for the result passed through <doc:ref type="signal" 
to="Device::EnrollResult">Device::EnrollResult</doc:ref> are:
+                                       <doc:item>
+                                               <doc:term>enroll-completed</doc:term>
+                                               <doc:definition>
+                                                       The enrollment successfully completed, <doc:ref 
type="method" to="Device.EnrollStop">Device.EnrollStop</doc:ref> should now be called.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>enroll-failed</doc:term>
+                                               <doc:definition>
+                                                       The enrollment failed, <doc:ref type="method" 
to="Device.EnrollStop">Device.EnrollStop</doc:ref> should now be called.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>enroll-stage-passed</doc:term>
+                                               <doc:definition>
+                                                       One stage of the enrollment passed, the enrollment is 
still ongoing.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>enroll-retry-scan</doc:term>
+                                               <doc:definition>
+                                                       The user should retry scanning their finger, the 
enrollment is still ongoing.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>enroll-swipe-too-short</doc:term>
+                                               <doc:definition>
+                                                       The user's swipe was too short. The user should retry 
scanning their finger, the enrollment is still ongoing.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>enroll-finger-not-centered</doc:term>
+                                               <doc:definition>
+                                                       The user's finger was not centered on the reader. The 
user should retry scanning their finger, the enrollment is still ongoing.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>enroll-remove-and-retry</doc:term>
+                                               <doc:definition>
+                                                       The user should remove their finger from the reader 
and retry scanning their finger, the enrollment is still ongoing.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>enroll-data-full</doc:term>
+                                               <doc:definition>
+                                                       No further prints can be enrolled on this device, 
<doc:ref type="method" to="Device.EnrollStop">Device.EnrollStop</doc:ref> should now be called.
+
+                                                       <doc:ref type="method" 
to="DeleteEnrolledFingers2">Delete other prints</doc:ref> from the device first to continue
+                                                       (e.g. from other users). Note that old prints or 
prints from other operating systems may be deleted automatically
+                                                       to resolve this error without any notification.
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>enroll-disconnected</doc:term>
+                                               <doc:definition>
+                                                       The device was disconnected during the enrollment, no 
other actions should be taken, and you shouldn't use the device any more.
+
+                                               </doc:definition>
+                                       </doc:item>
+                                       <doc:item>
+                                               <doc:term>enroll-unknown-error</doc:term>
+                                               <doc:definition>
+                                                       An unknown error occurred (usually a driver problem), 
<doc:ref type="method" to="Device.EnrollStop">Device.EnrollStop</doc:ref> should now be called.
+
+                                               </doc:definition>
+                                       </doc:item>
+                               </doc:list>
+                       </doc:para>
+               </doc:doc>
+
+               <!-- ************************************************************ -->
+
+               <method name="ListEnrolledFingers">
+                       <arg type="s" name="username" direction="in">
+                               <doc:doc><doc:summary>The username for whom to list the enrolled 
fingerprints. See <doc:ref type="description" to="usernames">Usernames</doc:ref>.</doc:summary></doc:doc>
+                       </arg>
+                       <arg type="as" name="enrolled_fingers" direction="out">
+                               <doc:doc><doc:summary>An array of strings representing the enrolled 
fingerprints. See <doc:ref type="description" to="fingerprint-names">Fingerprint 
names</doc:ref>.</doc:summary></doc:doc>
+                       </arg>
+
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               List all the enrolled fingerprints for the chosen user.
+                                       </doc:para>
+                               </doc:description>
+
+                               <doc:errors>
+                                       <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the 
appropriate PolicyKit authorization</doc:error>
+                                       <doc:error name="&ERROR_NO_ENROLLED_PRINTS;">if the chosen user 
doesn't have any fingerprints enrolled</doc:error>
+                               </doc:errors>
+                       </doc:doc>
+               </method>
+
+               <!-- ************************************************************ -->
+
+               <method name="DeleteEnrolledFingers">
+                       <arg type="s" name="username" direction="in">
+                               <doc:doc><doc:summary>The username for whom to delete the enrolled 
fingerprints. See <doc:ref type="description" to="usernames">Usernames</doc:ref>.</doc:summary></doc:doc>
+                       </arg>
+
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               Delete all the enrolled fingerprints for the chosen user.
+                                       </doc:para>
+                                       <doc:para>
+                                               This call only exists for compatibility reasons, you should 
instead claim the device using
+                                               <doc:ref type="method" 
to="Device.Claim">Device.Claim</doc:ref> and then call
+                                               <doc:ref type="method" 
to="DeleteEnrolledFingers2">DeleteEnrolledFingers2</doc:ref>.
+                                       </doc:para>
+                               </doc:description>
+
+                               <doc:errors>
+                                       <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the 
appropriate PolicyKit authorization</doc:error>
+                               </doc:errors>
+                       </doc:doc>
+               </method>
+
+               <!-- ************************************************************ -->
+
+               <method name="DeleteEnrolledFingers2">
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               Delete all the enrolled fingerprints for the user currently 
claiming the device with <doc:ref type="method" to="Device.Claim">Device.Claim</doc:ref>.
+                                       </doc:para>
+                               </doc:description>
+
+                               <doc:errors>
+                                       <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the 
appropriate PolicyKit authorization</doc:error>
+                               </doc:errors>
+                       </doc:doc>
+               </method>
+
+               <!-- ************************************************************ -->
+
+               <method name="Claim">
+                       <arg type="s" name="username" direction="in">
+                               <doc:doc><doc:summary>The username for whom to claim the device. See <doc:ref 
type="description" to="usernames">Usernames</doc:ref>.</doc:summary></doc:doc>
+                       </arg>
+
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               Claim the device for the chosen user.
+                                       </doc:para>
+                               </doc:description>
+
+                               <doc:errors>
+                                       <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the 
appropriate PolicyKit authorization</doc:error>
+                                       <doc:error name="&ERROR_ALREADY_IN_USE;">if the device is already 
claimed</doc:error>
+                                       <doc:error name="&ERROR_INTERNAL;">if the device couldn't be 
claimed</doc:error>
+                               </doc:errors>
+                       </doc:doc>
+               </method>
+
+               <!-- ************************************************************ -->
+
+               <method name="Release">
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               Release a device claimed with <doc:ref type="method" 
to="Device.Claim">Device.Claim</doc:ref>.
+                                       </doc:para>
+                               </doc:description>
+
+                               <doc:errors>
+                                       <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the 
appropriate PolicyKit authorization</doc:error>
+                                       <doc:error name="&ERROR_CLAIM_DEVICE;">if the device was not 
claimed</doc:error>
+                               </doc:errors>
+                       </doc:doc>
+               </method>
+
+               <!-- ************************************************************ -->
+
+               <method name="VerifyStart">
+                       <arg type="s" name="finger_name" direction="in">
+                               <doc:doc><doc:summary>A string representing the finger to verify. See 
<doc:ref type="description" to="fingerprint-names">Fingerprint names</doc:ref>.</doc:summary></doc:doc>
+                       </arg>
+
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               Check the chosen finger against a saved fingerprint. You need 
to have claimed the device using
+                                               <doc:ref type="method" 
to="Device.Claim">Device.Claim</doc:ref>. The finger selected is sent to the front-end
+                                               using <doc:ref type="signal" 
to="Device::VerifyFingerSelected">Device::VerifyFingerSelected</doc:ref> and
+                                               verification status through <doc:ref type="signal" 
to="Device::VerifyStatus">Device::VerifyStatus</doc:ref>.
+                                       </doc:para>
+                               </doc:description>
+
+                               <doc:errors>
+                                       <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the 
appropriate PolicyKit authorization</doc:error>
+                                       <doc:error name="&ERROR_CLAIM_DEVICE;">if the device was not 
claimed</doc:error>
+                                       <doc:error name="&ERROR_ALREADY_IN_USE;">if the device was already 
being used</doc:error>
+                                       <doc:error name="&ERROR_NO_ENROLLED_PRINTS;">if there are no enrolled 
prints for the chosen user</doc:error>
+                                       <doc:error name="&ERROR_INTERNAL;">if there was an internal 
error</doc:error>
+                               </doc:errors>
+                       </doc:doc>
+               </method>
+
+               <!-- ************************************************************ -->
+
+               <method name="VerifyStop">
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               Stop an on-going fingerprint verification started with 
<doc:ref type="method" to="Device.VerifyStart">Device.VerifyStart</doc:ref>.
+                                       </doc:para>
+                               </doc:description>
+
+                               <doc:errors>
+                                       <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the 
appropriate PolicyKit authorization</doc:error>
+                                       <doc:error name="&ERROR_CLAIM_DEVICE;">if the device was not 
claimed</doc:error>
+                                       <doc:error name="&ERROR_NO_ACTION_IN_PROGRESS;">if there was no 
ongoing verification</doc:error>
+                                       <doc:error name="&ERROR_INTERNAL;">if there was an internal 
error</doc:error>
+                               </doc:errors>
+                       </doc:doc>
+               </method>
+
+               <!-- ************************************************************ -->
+
+               <signal name="VerifyFingerSelected">
+                       <arg type="s" name="finger_name">
+                               <doc:doc>
+                                       <doc:summary>
+                                               <doc:para>
+                                                       A string representing the finger select to be 
verified.
+                                               </doc:para>
+                                       </doc:summary>
+                               </doc:doc>
+                       </arg>
+                       <doc:doc>
+                               <doc:seealso>
+                                       <doc:ref type="description" to="fingerprint-names">Fingerprint 
names</doc:ref>.
+                               </doc:seealso>
+                       </doc:doc>
+               </signal>
+
+               <!-- ************************************************************ -->
+
+               <signal name="VerifyStatus">
+                       <arg type="s" name="result">
+                               <doc:doc>
+                                       <doc:summary>
+                                               A string representing the status of the verification.
+                                       </doc:summary>
+                               </doc:doc>
+                       </arg>
+
+                       <arg type="b" name="done">
+                               <doc:doc>
+                                       <doc:summary>
+                                               Whether the verification finished and can be stopped.
+                                       </doc:summary>
+                               </doc:doc>
+                       </arg>
+
+                       <doc:doc>
+                               <doc:seealso>
+                                       <doc:ref type="description" to="verify-statuses">Verify 
Statuses</doc:ref> and <doc:ref type="method" to="Device.VerifyStop">Device.VerifyStop</doc:ref>.
+                               </doc:seealso>
+                       </doc:doc>
+               </signal>
+
+               <!-- ************************************************************ -->
+
+               <method name="EnrollStart">
+                       <arg type="s" name="finger_name" direction="in">
+                               <doc:doc><doc:summary>A string representing the finger to enroll. See
+                               <doc:ref type="description" to="fingerprint-names">Fingerprint 
names</doc:ref>.
+                               Note that "any" is not a valid finger name for this 
method.</doc:summary></doc:doc>
+                       </arg>
+
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               Start enrollment for the selected finger. You need to have 
claimed the device using
+                                               <doc:ref type="method" 
to="Device.Claim">Device.Claim</doc:ref> before calling
+                                               this method. Enrollment status is sent through <doc:ref 
type="signal" to="Device::EnrollStatus">Device::EnrollStatus</doc:ref>.
+                                       </doc:para>
+                               </doc:description>
+
+                               <doc:errors>
+                                       <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the 
appropriate PolicyKit authorization</doc:error>
+                                       <doc:error name="&ERROR_CLAIM_DEVICE;">if the device was not 
claimed</doc:error>
+                                       <doc:error name="&ERROR_ALREADY_IN_USE;">if the device was already 
being used</doc:error>
+                                       <doc:error name="&ERROR_INVALID_FINGERNAME;">if the finger name 
passed is invalid</doc:error>
+                                       <doc:error name="&ERROR_INTERNAL;">if there was an internal 
error</doc:error>
+                               </doc:errors>
+
+                       </doc:doc>
+               </method>
+
+               <!-- ************************************************************ -->
+
+               <method name="EnrollStop">
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               Stop an on-going fingerprint enrollment started with <doc:ref 
type="method" to="Device.EnrollStart">Device.EnrollStart</doc:ref>.
+                                       </doc:para>
+                               </doc:description>
+
+                               <doc:errors>
+                                       <doc:error name="&ERROR_PERMISSION_DENIED;">if the caller lacks the 
appropriate PolicyKit authorization</doc:error>
+                                       <doc:error name="&ERROR_CLAIM_DEVICE;">if the device was not 
claimed</doc:error>
+                                       <doc:error name="&ERROR_NO_ACTION_IN_PROGRESS;">if there was no 
ongoing verification</doc:error>
+                                       <doc:error name="&ERROR_INTERNAL;">if there was an internal 
error</doc:error>
+                               </doc:errors>
+                       </doc:doc>
+               </method>
+
+               <!-- ************************************************************ -->
+
+               <signal name="EnrollStatus">
+                       <arg type="s" name="result">
+                               <doc:doc>
+                                       <doc:summary>
+                                               A string representing the status of the enrollment.
+                                       </doc:summary>
+                               </doc:doc>
+                       </arg>
+
+                       <arg type="b" name="done">
+                               <doc:doc>
+                                       <doc:summary>
+                                               Whether the enrollment finished and can be stopped.
+                                       </doc:summary>
+                               </doc:doc>
+                       </arg>
+
+                       <doc:doc>
+                               <doc:seealso>
+                                       <doc:ref type="description" to="enroll-statuses">Enrollment 
Statuses</doc:ref> and <doc:ref type="method" to="Device.EnrollStop">Device.EnrollStop</doc:ref>.
+                               </doc:seealso>
+                       </doc:doc>
+               </signal>
+
+               <!-- ************************************************************ -->
+
+               <property name="name" type="s" access="read">
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               The product name of the device.
+                                       </doc:para>
+                               </doc:description>
+                       </doc:doc>
+               </property>
+
+               <!-- ************************************************************ -->
+
+               <property name="num-enroll-stages" type="i" access="read">
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               The number of enrollment stages for the device. This is only 
available when the device has been claimed, otherwise it will be undefined (-1).
+                                       </doc:para>
+                                       <doc:seealso>
+                                               <doc:ref type="method" 
to="Device.Claim">Device.Claim</doc:ref> and <doc:ref type="method" 
to="Device.EnrollStart">Device.EnrollStart</doc:ref>.
+                                       </doc:seealso>
+                               </doc:description>
+                       </doc:doc>
+               </property>
+
+               <!-- ************************************************************ -->
+
+               <property name="scan-type" type="s" access="read">
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               The scan type of the device, either "press" if you place your 
finger on the device, or "swipe" if you have to swipe your finger.
+                                       </doc:para>
+                               </doc:description>
+                       </doc:doc>
+               </property>
+
+       </interface>
+</node>
+
diff --git a/panels/user-accounts/data/net.reactivated.Fprint.Manager.xml 
b/panels/user-accounts/data/net.reactivated.Fprint.Manager.xml
new file mode 100644
index 000000000..f4a38c700
--- /dev/null
+++ b/panels/user-accounts/data/net.reactivated.Fprint.Manager.xml
@@ -0,0 +1,50 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"; [
+<!ENTITY ERROR_NO_SUCH_DEVICE "net.reactivated.Fprint.Error.NoSuchDevice">
+]>
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd";>
+       <interface name="net.reactivated.Fprint.Manager">
+               <annotation name="org.freedesktop.DBus.GLib.CSymbol"
+                       value="fprint_manager" />
+
+               <!-- ************************************************************ -->
+
+               <method name="GetDevices">
+                       <arg type="ao" name="devices" direction="out">
+                               <doc:doc><doc:summary>An array of object paths for 
devices.</doc:summary></doc:doc>
+                       </arg>
+
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               Enumerate all the fingerprint readers attached to the system. 
If there are
+                                               no devices available, an empty array is returned.
+                                       </doc:para>
+                               </doc:description>
+                       </doc:doc>
+               </method>
+
+               <!-- ************************************************************ -->
+
+               <method name="GetDefaultDevice">
+                       <arg type="o" name="device" direction="out">
+                               <doc:doc><doc:summary>The object path for the default 
device.</doc:summary></doc:doc>
+                       </arg>
+
+                       <doc:doc>
+                               <doc:description>
+                                       <doc:para>
+                                               Returns the default fingerprint reader device.
+                                       </doc:para>
+                               </doc:description>
+
+                               <doc:errors>
+                                       <doc:error name="&ERROR_NO_SUCH_DEVICE;">if the device does not 
exist</doc:error>
+                               </doc:errors>
+                       </doc:doc>
+               </method>
+
+       </interface>
+</node>
+
diff --git a/panels/user-accounts/meson.build b/panels/user-accounts/meson.build
index 03b20a6a5..de54ee14e 100644
--- a/panels/user-accounts/meson.build
+++ b/panels/user-accounts/meson.build
@@ -144,10 +144,27 @@ common_sources += gnome.gdbus_codegen(
   annotations: ['org.freedesktop.realmd.Realm', 'org.gtk.GDBus.C.Name', 'Common']
 )
 
+fprintd_namespace = 'net.reactivated.Fprint'
+common_sources += gnome.gdbus_codegen(
+  'cc-fprintd-generated',
+  sources: [
+    'data' / fprintd_namespace + '.Manager.xml',
+    'data' / fprintd_namespace + '.Device.xml',
+  ],
+  interface_prefix: fprintd_namespace + '.',
+  namespace: 'CcFprintd',
+  autocleanup: 'all',
+)
+
+enum_headers = [
+  'cc-fingerprint-manager.h',
+]
+
 sources = common_sources + files(
   'cc-avatar-chooser.c',
   'cc-carousel.c',
   'cc-crop-area.c',
+  'cc-fingerprint-manager.c',
   'cc-login-history-dialog.c',
   'cc-password-dialog.c',
   'cc-user-image.c',
@@ -156,6 +173,10 @@ sources = common_sources + files(
   'um-fingerprint-dialog.c',
 )
 
+sources += gnome.mkenums_simple(
+  'cc-user-accounts-enum-types',
+  sources: files(enum_headers))
+
 # Kerberos support
 krb_dep = dependency('krb5', required: false)
 assert(krb_dep.found(), 'kerberos libraries not found in your path')



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]