Line |
Branch |
Exec |
Source |
1 |
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- |
2 |
|
|
* |
3 |
|
|
* Copyright (C) 2020 Canonical Ltd. |
4 |
|
|
* |
5 |
|
|
* This program is free software; you can redistribute it and/or modify |
6 |
|
|
* it under the terms of the GNU General Public License as published by |
7 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
8 |
|
|
* (at your option) any later version. |
9 |
|
|
* |
10 |
|
|
* This program is distributed in the hope that it will be useful, |
11 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 |
|
|
* GNU General Public License for more details. |
14 |
|
|
* |
15 |
|
|
* You should have received a copy of the GNU General Public License |
16 |
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>. |
17 |
|
|
* |
18 |
|
|
* SPDX-License-Identifier: GPL-3.0-or-later |
19 |
|
|
* |
20 |
|
|
* Authors: Marco Trevisan <marco.trevisan@canonical.com> |
21 |
|
|
*/ |
22 |
|
|
|
23 |
|
|
#include "cc-fingerprint-manager.h" |
24 |
|
|
|
25 |
|
|
#include "cc-fprintd-generated.h" |
26 |
|
|
#include "cc-user-accounts-enum-types.h" |
27 |
|
|
|
28 |
|
|
#define CC_FPRINTD_NAME "net.reactivated.Fprint" |
29 |
|
|
#define CC_FPRINTD_MANAGER_PATH "/net/reactivated/Fprint/Manager" |
30 |
|
|
|
31 |
|
|
struct _CcFingerprintManager |
32 |
|
|
{ |
33 |
|
|
GObject parent_instance; |
34 |
|
|
}; |
35 |
|
|
|
36 |
|
|
typedef struct |
37 |
|
|
{ |
38 |
|
|
ActUser *user; |
39 |
|
|
GTask *current_task; |
40 |
|
|
CcFingerprintState state; |
41 |
|
|
GList *cached_devices; |
42 |
|
|
} CcFingerprintManagerPrivate; |
43 |
|
|
|
44 |
|
✗ |
G_DEFINE_TYPE_WITH_PRIVATE (CcFingerprintManager, cc_fingerprint_manager, G_TYPE_OBJECT) |
45 |
|
|
|
46 |
|
|
enum { |
47 |
|
|
PROP_0, |
48 |
|
|
PROP_USER, |
49 |
|
|
PROP_STATE, |
50 |
|
|
N_PROPS |
51 |
|
|
}; |
52 |
|
|
|
53 |
|
|
static GParamSpec *properties[N_PROPS]; |
54 |
|
|
|
55 |
|
|
static void cleanup_cached_devices (CcFingerprintManager *self); |
56 |
|
|
|
57 |
|
|
CcFingerprintManager * |
58 |
|
✗ |
cc_fingerprint_manager_new (ActUser *user) |
59 |
|
|
{ |
60 |
|
✗ |
return g_object_new (CC_TYPE_FINGERPRINT_MANAGER, "user", user, NULL); |
61 |
|
|
} |
62 |
|
|
|
63 |
|
|
static void |
64 |
|
✗ |
cc_fingerprint_manager_dispose (GObject *object) |
65 |
|
|
{ |
66 |
|
✗ |
CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object); |
67 |
|
✗ |
CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self); |
68 |
|
|
|
69 |
|
✗ |
if (priv->current_task) |
70 |
|
|
{ |
71 |
|
✗ |
g_cancellable_cancel (g_task_get_cancellable (priv->current_task)); |
72 |
|
✗ |
priv->current_task = NULL; |
73 |
|
|
} |
74 |
|
|
|
75 |
|
✗ |
g_clear_object (&priv->user); |
76 |
|
✗ |
cleanup_cached_devices (self); |
77 |
|
|
|
78 |
|
✗ |
G_OBJECT_CLASS (cc_fingerprint_manager_parent_class)->dispose (object); |
79 |
|
✗ |
} |
80 |
|
|
|
81 |
|
|
static void |
82 |
|
✗ |
cc_fingerprint_manager_get_property (GObject *object, |
83 |
|
|
guint prop_id, |
84 |
|
|
GValue *value, |
85 |
|
|
GParamSpec *pspec) |
86 |
|
|
{ |
87 |
|
✗ |
CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object); |
88 |
|
✗ |
CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self); |
89 |
|
|
|
90 |
|
✗ |
switch (prop_id) |
91 |
|
|
{ |
92 |
|
✗ |
case PROP_STATE: |
93 |
|
✗ |
g_value_set_enum (value, priv->state); |
94 |
|
✗ |
break; |
95 |
|
|
|
96 |
|
✗ |
case PROP_USER: |
97 |
|
✗ |
g_value_set_object (value, priv->user); |
98 |
|
✗ |
break; |
99 |
|
|
|
100 |
|
✗ |
default: |
101 |
|
✗ |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
102 |
|
|
} |
103 |
|
✗ |
} |
104 |
|
|
|
105 |
|
|
static void |
106 |
|
✗ |
cc_fingerprint_manager_set_property (GObject *object, |
107 |
|
|
guint prop_id, |
108 |
|
|
const GValue *value, |
109 |
|
|
GParamSpec *pspec) |
110 |
|
|
{ |
111 |
|
✗ |
CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object); |
112 |
|
✗ |
CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self); |
113 |
|
|
|
114 |
|
✗ |
switch (prop_id) |
115 |
|
|
{ |
116 |
|
✗ |
case PROP_USER: |
117 |
|
✗ |
g_set_object (&priv->user, g_value_get_object (value)); |
118 |
|
✗ |
break; |
119 |
|
|
|
120 |
|
✗ |
default: |
121 |
|
✗ |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
122 |
|
|
} |
123 |
|
✗ |
} |
124 |
|
|
|
125 |
|
|
static void |
126 |
|
✗ |
cc_fingerprint_manager_constructed (GObject *object) |
127 |
|
|
{ |
128 |
|
✗ |
cc_fingerprint_manager_update_state (CC_FINGERPRINT_MANAGER (object), NULL, NULL); |
129 |
|
✗ |
} |
130 |
|
|
|
131 |
|
|
static void |
132 |
|
✗ |
cc_fingerprint_manager_class_init (CcFingerprintManagerClass *klass) |
133 |
|
|
{ |
134 |
|
✗ |
GObjectClass *object_class = G_OBJECT_CLASS (klass); |
135 |
|
|
|
136 |
|
✗ |
object_class->constructed = cc_fingerprint_manager_constructed; |
137 |
|
✗ |
object_class->dispose = cc_fingerprint_manager_dispose; |
138 |
|
✗ |
object_class->get_property = cc_fingerprint_manager_get_property; |
139 |
|
✗ |
object_class->set_property = cc_fingerprint_manager_set_property; |
140 |
|
|
|
141 |
|
✗ |
properties[PROP_USER] = |
142 |
|
✗ |
g_param_spec_object ("user", |
143 |
|
|
"User", |
144 |
|
|
"The user account we manage the fingerprint for", |
145 |
|
|
ACT_TYPE_USER, |
146 |
|
|
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); |
147 |
|
|
|
148 |
|
✗ |
properties[PROP_STATE] = |
149 |
|
✗ |
g_param_spec_enum ("state", |
150 |
|
|
"State", |
151 |
|
|
"The state of the fingerprint for the user", |
152 |
|
|
CC_TYPE_FINGERPRINT_STATE, CC_FINGERPRINT_STATE_NONE, |
153 |
|
|
G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); |
154 |
|
|
|
155 |
|
✗ |
g_object_class_install_properties (object_class, N_PROPS, properties); |
156 |
|
✗ |
} |
157 |
|
|
|
158 |
|
|
static void |
159 |
|
✗ |
cc_fingerprint_manager_init (CcFingerprintManager *self) |
160 |
|
|
{ |
161 |
|
✗ |
} |
162 |
|
|
|
163 |
|
|
typedef struct |
164 |
|
|
{ |
165 |
|
|
guint waiting_devices; |
166 |
|
|
GList *devices; |
167 |
|
|
} DeviceListData; |
168 |
|
|
|
169 |
|
|
static void |
170 |
|
✗ |
object_list_destroy_notify (gpointer data) |
171 |
|
|
{ |
172 |
|
✗ |
GList *list = data; |
173 |
|
✗ |
g_list_free_full (list, g_object_unref); |
174 |
|
✗ |
} |
175 |
|
|
|
176 |
|
|
static void |
177 |
|
✗ |
on_device_owner_changed (CcFingerprintManager *self, |
178 |
|
|
GParamSpec *spec, |
179 |
|
|
CcFprintdDevice *device) |
180 |
|
|
{ |
181 |
|
✗ |
g_autofree char *name_owner = NULL; |
182 |
|
|
|
183 |
|
✗ |
name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (device)); |
184 |
|
|
|
185 |
|
✗ |
if (!name_owner) |
186 |
|
|
{ |
187 |
|
✗ |
g_debug ("Fprintd daemon disappeared, cleaning cache..."); |
188 |
|
✗ |
cleanup_cached_devices (self); |
189 |
|
|
} |
190 |
|
✗ |
} |
191 |
|
|
|
192 |
|
|
static void |
193 |
|
✗ |
cleanup_cached_devices (CcFingerprintManager *self) |
194 |
|
|
{ |
195 |
|
✗ |
CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self); |
196 |
|
|
CcFprintdDevice *target_device; |
197 |
|
|
|
198 |
|
✗ |
if (!priv->cached_devices) |
199 |
|
✗ |
return; |
200 |
|
|
|
201 |
|
✗ |
g_return_if_fail (CC_FPRINTD_IS_DEVICE (priv->cached_devices->data)); |
202 |
|
|
|
203 |
|
✗ |
target_device = CC_FPRINTD_DEVICE (priv->cached_devices->data); |
204 |
|
|
|
205 |
|
✗ |
g_signal_handlers_disconnect_by_func (target_device, on_device_owner_changed, self); |
206 |
|
✗ |
g_list_free_full (g_steal_pointer (&priv->cached_devices), g_object_unref); |
207 |
|
|
} |
208 |
|
|
|
209 |
|
|
static void |
210 |
|
✗ |
cache_devices (CcFingerprintManager *self, |
211 |
|
|
GList *devices) |
212 |
|
|
{ |
213 |
|
✗ |
CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self); |
214 |
|
|
CcFprintdDevice *target_device; |
215 |
|
|
|
216 |
|
✗ |
g_return_if_fail (devices && CC_FPRINTD_IS_DEVICE (devices->data)); |
217 |
|
|
|
218 |
|
✗ |
cleanup_cached_devices (self); |
219 |
|
✗ |
priv->cached_devices = g_list_copy_deep (devices, (GCopyFunc) g_object_ref, NULL); |
220 |
|
|
|
221 |
|
|
/* We can monitor just the first device name, as the owner is just the same */ |
222 |
|
✗ |
target_device = CC_FPRINTD_DEVICE (priv->cached_devices->data); |
223 |
|
|
|
224 |
|
✗ |
g_signal_connect_object (target_device, "notify::g-name-owner", |
225 |
|
|
G_CALLBACK (on_device_owner_changed), self, |
226 |
|
|
G_CONNECT_SWAPPED); |
227 |
|
|
} |
228 |
|
|
|
229 |
|
|
static void |
230 |
|
✗ |
on_device_proxy (GObject *object, GAsyncResult *res, gpointer user_data) |
231 |
|
|
{ |
232 |
|
✗ |
g_autoptr(CcFprintdDevice) fprintd_device = NULL; |
233 |
|
✗ |
g_autoptr(GTask) task = G_TASK (user_data); |
234 |
|
✗ |
g_autoptr(GError) error = NULL; |
235 |
|
✗ |
CcFingerprintManager *self = g_task_get_source_object (task); |
236 |
|
✗ |
DeviceListData *list_data = g_task_get_task_data (task); |
237 |
|
|
|
238 |
|
✗ |
fprintd_device = cc_fprintd_device_proxy_new_for_bus_finish (res, &error); |
239 |
|
✗ |
list_data->waiting_devices--; |
240 |
|
|
|
241 |
|
✗ |
if (error) |
242 |
|
|
{ |
243 |
|
✗ |
if (list_data->waiting_devices == 0) |
244 |
|
✗ |
g_task_return_error (task, g_steal_pointer (&error)); |
245 |
|
✗ |
else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
246 |
|
✗ |
g_warning ("Impossible to ge the device proxy: %s", error->message); |
247 |
|
|
|
248 |
|
✗ |
return; |
249 |
|
|
} |
250 |
|
|
|
251 |
|
✗ |
g_debug ("Got fingerprint device %s", cc_fprintd_device_get_name (fprintd_device)); |
252 |
|
|
|
253 |
|
✗ |
list_data->devices = g_list_append (list_data->devices, g_steal_pointer (&fprintd_device)); |
254 |
|
|
|
255 |
|
✗ |
if (list_data->waiting_devices == 0) |
256 |
|
|
{ |
257 |
|
✗ |
cache_devices (self, list_data->devices); |
258 |
|
✗ |
g_task_return_pointer (task, g_steal_pointer (&list_data->devices), object_list_destroy_notify); |
259 |
|
|
} |
260 |
|
|
} |
261 |
|
|
|
262 |
|
|
static void |
263 |
|
✗ |
on_devices_list (GObject *object, GAsyncResult *res, gpointer user_data) |
264 |
|
|
{ |
265 |
|
✗ |
CcFprintdManager *fprintd_manager = CC_FPRINTD_MANAGER (object); |
266 |
|
✗ |
g_autoptr(GTask) task = G_TASK (user_data); |
267 |
|
✗ |
g_autoptr(GError) error = NULL; |
268 |
|
✗ |
g_auto(GStrv) devices_list = NULL; |
269 |
|
|
DeviceListData *list_data; |
270 |
|
|
guint i; |
271 |
|
|
|
272 |
|
✗ |
cc_fprintd_manager_call_get_devices_finish (fprintd_manager, &devices_list, res, &error); |
273 |
|
|
|
274 |
|
✗ |
if (error) |
275 |
|
|
{ |
276 |
|
✗ |
g_task_return_error (task, g_steal_pointer (&error)); |
277 |
|
✗ |
return; |
278 |
|
|
} |
279 |
|
|
|
280 |
|
✗ |
if (!devices_list || !devices_list[0]) |
281 |
|
|
{ |
282 |
|
✗ |
g_task_return_pointer (task, NULL, NULL); |
283 |
|
✗ |
return; |
284 |
|
|
} |
285 |
|
|
|
286 |
|
✗ |
list_data = g_new0 (DeviceListData, 1); |
287 |
|
✗ |
g_task_set_task_data (task, list_data, g_free); |
288 |
|
|
|
289 |
|
✗ |
g_debug ("Fprintd replied with %u device(s)", g_strv_length (devices_list)); |
290 |
|
|
|
291 |
|
✗ |
for (i = 0; devices_list[i] != NULL; ++i) |
292 |
|
|
{ |
293 |
|
✗ |
const char *device_path = devices_list[i]; |
294 |
|
|
|
295 |
|
✗ |
list_data->waiting_devices++; |
296 |
|
|
|
297 |
|
✗ |
cc_fprintd_device_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, |
298 |
|
|
G_DBUS_PROXY_FLAGS_NONE, |
299 |
|
|
CC_FPRINTD_NAME, |
300 |
|
|
device_path, |
301 |
|
|
g_task_get_cancellable (task), |
302 |
|
|
on_device_proxy, |
303 |
|
|
g_object_ref (task)); |
304 |
|
|
} |
305 |
|
|
} |
306 |
|
|
|
307 |
|
|
static void |
308 |
|
✗ |
on_manager_proxy (GObject *object, GAsyncResult *res, gpointer user_data) |
309 |
|
|
{ |
310 |
|
✗ |
g_autoptr(GTask) task = G_TASK (user_data); |
311 |
|
✗ |
g_autoptr(CcFprintdManager) fprintd_manager = NULL; |
312 |
|
✗ |
g_autoptr(GError) error = NULL; |
313 |
|
|
|
314 |
|
✗ |
fprintd_manager = cc_fprintd_manager_proxy_new_for_bus_finish (res, &error); |
315 |
|
|
|
316 |
|
✗ |
if (error) |
317 |
|
|
{ |
318 |
|
✗ |
g_task_return_error (task, g_steal_pointer (&error)); |
319 |
|
✗ |
return; |
320 |
|
|
} |
321 |
|
|
|
322 |
|
✗ |
g_debug ("Fprintd manager connected"); |
323 |
|
|
|
324 |
|
✗ |
cc_fprintd_manager_call_get_devices (fprintd_manager, |
325 |
|
|
g_task_get_cancellable (task), |
326 |
|
|
on_devices_list, |
327 |
|
|
g_object_ref (task)); |
328 |
|
|
} |
329 |
|
|
|
330 |
|
|
static void |
331 |
|
✗ |
fprintd_manager_connect (CcFingerprintManager *self, |
332 |
|
|
GAsyncReadyCallback callback, |
333 |
|
|
GTask *task) |
334 |
|
|
{ |
335 |
|
✗ |
g_assert (G_IS_TASK (task)); |
336 |
|
|
|
337 |
|
✗ |
cc_fprintd_manager_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, |
338 |
|
|
CC_FPRINTD_NAME, CC_FPRINTD_MANAGER_PATH, |
339 |
|
|
g_task_get_cancellable (task), |
340 |
|
|
callback, |
341 |
|
|
task); |
342 |
|
✗ |
} |
343 |
|
|
|
344 |
|
|
void |
345 |
|
✗ |
cc_fingerprint_manager_get_devices (CcFingerprintManager *self, |
346 |
|
|
GCancellable *cancellable, |
347 |
|
|
GAsyncReadyCallback callback, |
348 |
|
|
gpointer user_data) |
349 |
|
|
{ |
350 |
|
✗ |
CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self); |
351 |
|
✗ |
g_autoptr(GTask) task = NULL; |
352 |
|
|
|
353 |
|
✗ |
task = g_task_new (self, cancellable, callback, user_data); |
354 |
|
✗ |
g_task_set_source_tag (task, cc_fingerprint_manager_get_devices); |
355 |
|
|
|
356 |
|
✗ |
if (priv->cached_devices) |
357 |
|
|
{ |
358 |
|
|
GList *devices; |
359 |
|
|
|
360 |
|
✗ |
devices = g_list_copy_deep (priv->cached_devices, (GCopyFunc) g_object_ref, NULL); |
361 |
|
✗ |
g_task_return_pointer (task, devices, object_list_destroy_notify); |
362 |
|
✗ |
return; |
363 |
|
|
} |
364 |
|
|
|
365 |
|
✗ |
fprintd_manager_connect (self, on_manager_proxy, g_steal_pointer (&task)); |
366 |
|
|
} |
367 |
|
|
|
368 |
|
|
/** |
369 |
|
|
* cc_fingerprint_manager_get_devices_finish: |
370 |
|
|
* @self: The #CcFingerprintManager |
371 |
|
|
* @result: A #GAsyncResult |
372 |
|
|
* @error: Return location for errors, or %NULL to ignore |
373 |
|
|
* |
374 |
|
|
* Finish an asynchronous operation to list all devices. |
375 |
|
|
* |
376 |
|
|
* Returns: (element-type CcFprintdDevice) (transfer full): List of prints or %NULL on error |
377 |
|
|
*/ |
378 |
|
|
GList * |
379 |
|
✗ |
cc_fingerprint_manager_get_devices_finish (CcFingerprintManager *self, |
380 |
|
|
GAsyncResult *res, |
381 |
|
|
GError **error) |
382 |
|
|
{ |
383 |
|
✗ |
g_return_val_if_fail (g_task_is_valid (res, self), NULL); |
384 |
|
|
|
385 |
|
✗ |
return g_task_propagate_pointer (G_TASK (res), error); |
386 |
|
|
} |
387 |
|
|
|
388 |
|
|
static void |
389 |
|
✗ |
set_state (CcFingerprintManager *self, |
390 |
|
|
CcFingerprintState state) |
391 |
|
|
{ |
392 |
|
✗ |
CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self); |
393 |
|
|
|
394 |
|
✗ |
if (priv->state == state) |
395 |
|
✗ |
return; |
396 |
|
|
|
397 |
|
✗ |
g_debug ("Fingerprint manager state changed to %d", state); |
398 |
|
|
|
399 |
|
✗ |
priv->state = state; |
400 |
|
✗ |
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATE]); |
401 |
|
|
} |
402 |
|
|
|
403 |
|
|
typedef struct |
404 |
|
|
{ |
405 |
|
|
guint waiting_devices; |
406 |
|
|
CcFingerprintStateUpdated callback; |
407 |
|
|
gpointer user_data; |
408 |
|
|
} UpdateStateData; |
409 |
|
|
|
410 |
|
|
static void |
411 |
|
✗ |
update_state_callback (GObject *object, |
412 |
|
|
GAsyncResult *res, |
413 |
|
|
gpointer user_data) |
414 |
|
|
{ |
415 |
|
✗ |
CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object); |
416 |
|
✗ |
CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self); |
417 |
|
✗ |
g_autoptr(GError) error = NULL; |
418 |
|
|
CcFingerprintState state; |
419 |
|
|
UpdateStateData *data; |
420 |
|
|
GTask *task; |
421 |
|
|
|
422 |
|
✗ |
g_return_if_fail (g_task_is_valid (res, self)); |
423 |
|
|
|
424 |
|
✗ |
task = G_TASK (res); |
425 |
|
✗ |
g_assert (g_steal_pointer (&priv->current_task) == task); |
426 |
|
|
|
427 |
|
✗ |
state = g_task_propagate_int (task, &error); |
428 |
|
✗ |
data = g_task_get_task_data (task); |
429 |
|
|
|
430 |
|
✗ |
if (error) |
431 |
|
|
{ |
432 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
433 |
|
✗ |
return; |
434 |
|
|
|
435 |
|
✗ |
g_warning ("Impossible to update fingerprint manager state: %s", |
436 |
|
|
error->message); |
437 |
|
|
|
438 |
|
✗ |
state = CC_FINGERPRINT_STATE_NONE; |
439 |
|
|
} |
440 |
|
|
|
441 |
|
✗ |
set_state (self, state); |
442 |
|
|
|
443 |
|
✗ |
if (data->callback) |
444 |
|
✗ |
data->callback (self, state, data->user_data, error); |
445 |
|
|
} |
446 |
|
|
|
447 |
|
|
static void |
448 |
|
✗ |
on_device_list_enrolled (GObject *object, |
449 |
|
|
GAsyncResult *res, |
450 |
|
|
gpointer user_data) |
451 |
|
|
{ |
452 |
|
✗ |
CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object); |
453 |
|
✗ |
g_autoptr(GTask) task = G_TASK (user_data); |
454 |
|
✗ |
g_autoptr(GError) error = NULL; |
455 |
|
✗ |
g_auto(GStrv) enrolled_fingers = NULL; |
456 |
|
✗ |
UpdateStateData *data = g_task_get_task_data (task); |
457 |
|
|
guint num_enrolled_fingers; |
458 |
|
|
|
459 |
|
✗ |
cc_fprintd_device_call_list_enrolled_fingers_finish (fprintd_device, |
460 |
|
|
&enrolled_fingers, |
461 |
|
|
res, &error); |
462 |
|
|
|
463 |
|
✗ |
if (data->waiting_devices == 0) |
464 |
|
✗ |
return; |
465 |
|
|
|
466 |
|
✗ |
data->waiting_devices--; |
467 |
|
|
|
468 |
|
✗ |
if (error) |
469 |
|
|
{ |
470 |
|
✗ |
g_autofree char *dbus_error = g_dbus_error_get_remote_error (error); |
471 |
|
|
|
472 |
|
✗ |
if (!g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.NoEnrolledPrints")) |
473 |
|
|
{ |
474 |
|
✗ |
if (data->waiting_devices == 0) |
475 |
|
✗ |
g_task_return_error (task, g_steal_pointer (&error)); |
476 |
|
✗ |
else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
477 |
|
✗ |
g_warning ("Impossible to list enrolled fingers: %s", error->message); |
478 |
|
|
|
479 |
|
✗ |
return; |
480 |
|
|
} |
481 |
|
|
} |
482 |
|
|
|
483 |
|
✗ |
num_enrolled_fingers = enrolled_fingers ? g_strv_length (enrolled_fingers) : 0; |
484 |
|
|
|
485 |
|
✗ |
g_debug ("Device %s has %u enrolled fingers", |
486 |
|
|
cc_fprintd_device_get_name (fprintd_device), |
487 |
|
|
num_enrolled_fingers); |
488 |
|
|
|
489 |
|
✗ |
if (num_enrolled_fingers > 0) |
490 |
|
|
{ |
491 |
|
✗ |
data->waiting_devices = 0; |
492 |
|
✗ |
g_task_return_int (task, CC_FINGERPRINT_STATE_ENABLED); |
493 |
|
|
} |
494 |
|
✗ |
else if (data->waiting_devices == 0) |
495 |
|
|
{ |
496 |
|
✗ |
g_task_return_int (task, CC_FINGERPRINT_STATE_DISABLED); |
497 |
|
|
} |
498 |
|
|
} |
499 |
|
|
|
500 |
|
|
static void |
501 |
|
✗ |
on_manager_devices_list (GObject *object, |
502 |
|
|
GAsyncResult *res, |
503 |
|
|
gpointer user_data) |
504 |
|
|
{ |
505 |
|
✗ |
CcFingerprintManager *self = CC_FINGERPRINT_MANAGER (object); |
506 |
|
✗ |
CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self); |
507 |
|
✗ |
g_autolist(CcFprintdDevice) fprintd_devices = NULL; |
508 |
|
✗ |
g_autoptr(GTask) task = G_TASK (user_data); |
509 |
|
✗ |
g_autoptr(GError) error = NULL; |
510 |
|
✗ |
UpdateStateData *data = g_task_get_task_data (task); |
511 |
|
|
const char *user_name; |
512 |
|
|
GList *l; |
513 |
|
|
|
514 |
|
✗ |
fprintd_devices = cc_fingerprint_manager_get_devices_finish (self, res, &error); |
515 |
|
|
|
516 |
|
✗ |
if (error) |
517 |
|
|
{ |
518 |
|
✗ |
g_task_return_error (task, g_steal_pointer (&error)); |
519 |
|
✗ |
return; |
520 |
|
|
} |
521 |
|
|
|
522 |
|
✗ |
if (fprintd_devices == NULL) |
523 |
|
|
{ |
524 |
|
✗ |
g_debug ("No fingerprint devices found"); |
525 |
|
✗ |
g_task_return_int (task, CC_FINGERPRINT_STATE_NONE); |
526 |
|
✗ |
return; |
527 |
|
|
} |
528 |
|
|
|
529 |
|
✗ |
user_name = act_user_get_user_name (priv->user); |
530 |
|
|
|
531 |
|
✗ |
for (l = fprintd_devices; l; l = l->next) |
532 |
|
|
{ |
533 |
|
✗ |
CcFprintdDevice *device = l->data; |
534 |
|
|
|
535 |
|
✗ |
g_debug ("Connected to device %s, looking for enrolled fingers", |
536 |
|
|
cc_fprintd_device_get_name (device)); |
537 |
|
|
|
538 |
|
✗ |
data->waiting_devices++; |
539 |
|
✗ |
cc_fprintd_device_call_list_enrolled_fingers (device, user_name, |
540 |
|
|
g_task_get_cancellable (task), |
541 |
|
|
on_device_list_enrolled, |
542 |
|
|
g_object_ref (task)); |
543 |
|
|
} |
544 |
|
|
} |
545 |
|
|
|
546 |
|
|
void |
547 |
|
✗ |
cc_fingerprint_manager_update_state (CcFingerprintManager *self, |
548 |
|
|
CcFingerprintStateUpdated callback, |
549 |
|
|
gpointer user_data) |
550 |
|
|
{ |
551 |
|
✗ |
CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self); |
552 |
|
✗ |
g_autoptr(GCancellable) cancellable = NULL; |
553 |
|
|
UpdateStateData *data; |
554 |
|
|
|
555 |
|
✗ |
g_return_if_fail (priv->current_task == NULL); |
556 |
|
|
|
557 |
|
✗ |
if (act_user_get_uid (priv->user) != getuid () || |
558 |
|
✗ |
!act_user_is_local_account (priv->user)) |
559 |
|
|
{ |
560 |
|
✗ |
set_state (self, CC_FINGERPRINT_STATE_NONE); |
561 |
|
✗ |
return; |
562 |
|
|
} |
563 |
|
|
|
564 |
|
✗ |
cancellable = g_cancellable_new (); |
565 |
|
✗ |
data = g_new0 (UpdateStateData, 1); |
566 |
|
✗ |
data->callback = callback; |
567 |
|
✗ |
data->user_data = user_data; |
568 |
|
|
|
569 |
|
✗ |
priv->current_task = g_task_new (self, cancellable, update_state_callback, NULL); |
570 |
|
✗ |
g_task_set_source_tag (priv->current_task, cc_fingerprint_manager_update_state); |
571 |
|
✗ |
g_task_set_task_data (priv->current_task, data, g_free); |
572 |
|
|
|
573 |
|
✗ |
set_state (self, CC_FINGERPRINT_STATE_UPDATING); |
574 |
|
|
|
575 |
|
✗ |
cc_fingerprint_manager_get_devices (self, cancellable, on_manager_devices_list, |
576 |
|
✗ |
priv->current_task); |
577 |
|
|
} |
578 |
|
|
|
579 |
|
|
CcFingerprintState |
580 |
|
✗ |
cc_fingerprint_manager_get_state (CcFingerprintManager *self) |
581 |
|
|
{ |
582 |
|
✗ |
CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self); |
583 |
|
|
|
584 |
|
✗ |
g_return_val_if_fail (CC_IS_FINGERPRINT_MANAGER (self), CC_FINGERPRINT_STATE_NONE); |
585 |
|
|
|
586 |
|
✗ |
return priv->state; |
587 |
|
|
} |
588 |
|
|
|
589 |
|
|
ActUser * |
590 |
|
✗ |
cc_fingerprint_manager_get_user (CcFingerprintManager *self) |
591 |
|
|
{ |
592 |
|
✗ |
CcFingerprintManagerPrivate *priv = cc_fingerprint_manager_get_instance_private (self); |
593 |
|
|
|
594 |
|
✗ |
g_return_val_if_fail (CC_IS_FINGERPRINT_MANAGER (self), NULL); |
595 |
|
|
|
596 |
|
✗ |
return priv->user; |
597 |
|
|
} |
598 |
|
|
|