GCC Code Coverage Report


Directory: ./
File: panels/privacy/bolt/bolt-client.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 393 0.0%
Functions: 0 42 0.0%
Branches: 0 217 0.0%

Line Branch Exec Source
1 /*
2 * Copyright © 2017 Red Hat, Inc
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authors:
18 * Christian J. Kellner <christian@kellner.me>
19 */
20
21 #include "bolt-client.h"
22
23 #include "bolt-device.h"
24 #include "bolt-error.h"
25 #include "bolt-names.h"
26
27 #include <gio/gio.h>
28
29 static void handle_dbus_device_added (GObject *self,
30 GDBusProxy *bus_proxy,
31 GVariant *params);
32 static void handle_dbus_device_removed (GObject *self,
33 GDBusProxy *bus_proxy,
34 GVariant *params);
35
36 struct _BoltClient
37 {
38 BoltProxy parent;
39 };
40
41 enum {
42 PROP_0,
43
44 /* D-Bus Props */
45 PROP_VERSION,
46 PROP_PROBING,
47 PROP_SECURITY,
48 PROP_AUTHMODE,
49
50 PROP_LAST
51 };
52
53 static GParamSpec *props[PROP_LAST] = {NULL, };
54
55 enum {
56 SIGNAL_DEVICE_ADDED,
57 SIGNAL_DEVICE_REMOVED,
58 SIGNAL_LAST
59 };
60
61 static guint signals[SIGNAL_LAST] = {0};
62
63
64 G_DEFINE_TYPE (BoltClient,
65 bolt_client,
66 BOLT_TYPE_PROXY);
67
68
69 static void
70 bolt_client_get_property (GObject *object,
71 guint prop_id,
72 GValue *value,
73 GParamSpec *pspec)
74 {
75 if (bolt_proxy_get_dbus_property (object, pspec, value))
76 return;
77
78 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
79 }
80
81 static const BoltProxySignal *
82 bolt_client_get_dbus_signals (guint *n)
83 {
84 static BoltProxySignal dbus_signals[] = {
85 {"DeviceAdded", handle_dbus_device_added},
86 {"DeviceRemoved", handle_dbus_device_removed},
87 };
88
89 *n = G_N_ELEMENTS (dbus_signals);
90
91 return dbus_signals;
92 }
93
94
95 static void
96 bolt_client_class_init (BoltClientClass *klass)
97 {
98 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
99 BoltProxyClass *proxy_class = BOLT_PROXY_CLASS (klass);
100
101 gobject_class->get_property = bolt_client_get_property;
102
103 proxy_class->get_dbus_signals = bolt_client_get_dbus_signals;
104
105 props[PROP_VERSION]
106 = g_param_spec_uint ("version",
107 "Version", NULL,
108 0, G_MAXUINT, 0,
109 G_PARAM_READABLE |
110 G_PARAM_STATIC_NAME);
111
112 props[PROP_PROBING]
113 = g_param_spec_boolean ("probing",
114 "Probing", NULL,
115 FALSE,
116 G_PARAM_READABLE |
117 G_PARAM_STATIC_NAME);
118
119 props[PROP_SECURITY]
120 = g_param_spec_enum ("security-level",
121 "SecurityLevel", NULL,
122 BOLT_TYPE_SECURITY,
123 BOLT_SECURITY_UNKNOWN,
124 G_PARAM_READABLE |
125 G_PARAM_STATIC_NAME);
126
127 props[PROP_AUTHMODE] =
128 g_param_spec_flags ("auth-mode", "AuthMode", NULL,
129 BOLT_TYPE_AUTH_MODE,
130 BOLT_AUTH_ENABLED,
131 G_PARAM_READABLE |
132 G_PARAM_STATIC_STRINGS);
133
134 g_object_class_install_properties (gobject_class,
135 PROP_LAST,
136 props);
137
138 /* signals */
139 signals[SIGNAL_DEVICE_ADDED] =
140 g_signal_new ("device-added",
141 G_TYPE_FROM_CLASS (gobject_class),
142 G_SIGNAL_RUN_LAST,
143 0,
144 NULL, NULL,
145 NULL,
146 G_TYPE_NONE,
147 1, G_TYPE_STRING);
148
149 signals[SIGNAL_DEVICE_REMOVED] =
150 g_signal_new ("device-removed",
151 G_TYPE_FROM_CLASS (gobject_class),
152 G_SIGNAL_RUN_LAST,
153 0,
154 NULL, NULL,
155 NULL,
156 G_TYPE_NONE,
157 1, G_TYPE_STRING);
158 }
159
160
161 static void
162 bolt_client_init (BoltClient *cli)
163 {
164 }
165
166 /* dbus signals */
167
168 static void
169 handle_dbus_device_added (GObject *self, GDBusProxy *bus_proxy, GVariant *params)
170 {
171 BoltClient *cli = BOLT_CLIENT (self);
172 const char *opath = NULL;
173
174 g_variant_get_child (params, 0, "&o", &opath);
175 g_signal_emit (cli, signals[SIGNAL_DEVICE_ADDED], 0, opath);
176 }
177
178 static void
179 handle_dbus_device_removed (GObject *self, GDBusProxy *bus_proxy, GVariant *params)
180 {
181 BoltClient *cli = BOLT_CLIENT (self);
182 const char *opath = NULL;
183
184 g_variant_get_child (params, 0, "&o", &opath);
185 g_signal_emit (cli, signals[SIGNAL_DEVICE_REMOVED], 0, opath);
186 }
187
188 /* public methods */
189
190 BoltClient *
191 bolt_client_new (GError **error)
192 {
193 BoltClient *cli;
194 GDBusConnection *bus;
195
196 bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
197 if (bus == NULL)
198 {
199 g_prefix_error (error, "Error connecting to D-Bus: ");
200 return FALSE;
201 }
202
203 cli = g_initable_new (BOLT_TYPE_CLIENT,
204 NULL, error,
205 "g-flags", G_DBUS_PROXY_FLAGS_NONE,
206 "g-connection", bus,
207 "g-name", BOLT_DBUS_NAME,
208 "g-object-path", BOLT_DBUS_PATH,
209 "g-interface-name", BOLT_DBUS_INTERFACE,
210 NULL);
211
212 g_object_unref (bus);
213
214 return cli;
215 }
216
217 static void
218 got_the_client (GObject *source,
219 GAsyncResult *res,
220 gpointer user_data)
221 {
222 GError *error = NULL;
223 GTask *task = user_data;
224 GObject *obj;
225
226 obj = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, &error);
227
228 if (obj == NULL)
229 {
230 /* error ownership gets transferred to the task */
231 g_task_return_error (task, error);
232 g_object_unref (task);
233 return;
234 }
235
236 g_task_return_pointer (task, obj, g_object_unref);
237 g_object_unref (task);
238 }
239
240 static void
241 got_the_bus (GObject *source,
242 GAsyncResult *res,
243 gpointer user_data)
244 {
245 GError *error = NULL;
246 GTask *task = user_data;
247 GCancellable *cancellable;
248 GDBusConnection *bus;
249
250 bus = g_bus_get_finish (res, &error);
251 if (bus == NULL)
252 {
253 g_prefix_error (&error, "could not connect to D-Bus: ");
254 /* error ownership gets transferred to the task */
255 g_task_return_error (task, error);
256 g_object_unref (task);
257 return;
258 }
259
260 cancellable = g_task_get_cancellable (task);
261 g_async_initable_new_async (BOLT_TYPE_CLIENT,
262 G_PRIORITY_DEFAULT,
263 cancellable,
264 got_the_client, task,
265 "g-flags", G_DBUS_PROXY_FLAGS_NONE,
266 "g-connection", bus,
267 "g-name", BOLT_DBUS_NAME,
268 "g-object-path", BOLT_DBUS_PATH,
269 "g-interface-name", BOLT_DBUS_INTERFACE,
270 NULL);
271 g_object_unref (bus);
272 }
273
274 void
275 bolt_client_new_async (GCancellable *cancellable,
276 GAsyncReadyCallback callback,
277 gpointer user_data)
278 {
279 GTask *task;
280
281 task = g_task_new (NULL, cancellable, callback, user_data);
282 g_bus_get (G_BUS_TYPE_SYSTEM, cancellable, got_the_bus, task);
283 }
284
285 BoltClient *
286 bolt_client_new_finish (GAsyncResult *res,
287 GError **error)
288 {
289 g_return_val_if_fail (G_IS_TASK (res), NULL);
290
291 return g_task_propagate_pointer (G_TASK (res), error);
292 }
293
294 GPtrArray *
295 bolt_client_list_devices (BoltClient *client,
296 GCancellable *cancel,
297 GError **error)
298 {
299 g_autoptr(GVariant) val = NULL;
300 g_autoptr(GPtrArray) devices = NULL;
301 g_autoptr(GVariantIter) iter = NULL;
302 GDBusConnection *bus = NULL;
303 const char *d;
304
305 g_return_val_if_fail (BOLT_IS_CLIENT (client), NULL);
306
307 val = g_dbus_proxy_call_sync (G_DBUS_PROXY (client),
308 "ListDevices",
309 NULL,
310 G_DBUS_CALL_FLAGS_NONE,
311 -1,
312 cancel,
313 error);
314 if (val == NULL)
315 return NULL;
316
317 bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client));
318
319 devices = g_ptr_array_new_with_free_func (g_object_unref);
320
321 g_variant_get (val, "(ao)", &iter);
322 while (g_variant_iter_loop (iter, "&o", &d, NULL))
323 {
324 BoltDevice *dev;
325
326 dev = bolt_device_new_for_object_path (bus, d, cancel, error);
327 if (dev == NULL)
328 return NULL;
329
330 g_ptr_array_add (devices, dev);
331 }
332
333 return g_steal_pointer (&devices);
334 }
335
336 BoltDevice *
337 bolt_client_get_device (BoltClient *client,
338 const char *uid,
339 GCancellable *cancel,
340 GError **error)
341 {
342 g_autoptr(GVariant) val = NULL;
343 g_autoptr(GError) err = NULL;
344 BoltDevice *dev = NULL;
345 GDBusConnection *bus = NULL;
346 const char *opath = NULL;
347
348 g_return_val_if_fail (BOLT_IS_CLIENT (client), NULL);
349
350 val = g_dbus_proxy_call_sync (G_DBUS_PROXY (client),
351 "DeviceByUid",
352 g_variant_new ("(s)", uid),
353 G_DBUS_CALL_FLAGS_NONE,
354 -1,
355 cancel,
356 &err);
357
358 if (val == NULL)
359 {
360 bolt_error_propagate_stripped (error, &err);
361 return NULL;
362 }
363
364 bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client));
365 g_variant_get (val, "(&o)", &opath);
366
367 if (opath == NULL)
368 return NULL;
369
370 dev = bolt_device_new_for_object_path (bus, opath, cancel, error);
371 return dev;
372 }
373
374 BoltDevice *
375 bolt_client_enroll_device (BoltClient *client,
376 const char *uid,
377 BoltPolicy policy,
378 BoltAuthCtrl flags,
379 GError **error)
380 {
381 g_autoptr(GVariant) val = NULL;
382 g_autoptr(GError) err = NULL;
383 g_autofree char *fstr = NULL;
384 BoltDevice *dev = NULL;
385 GDBusConnection *bus = NULL;
386 GVariant *params = NULL;
387 const char *opath = NULL;
388 const char *pstr;
389
390 g_return_val_if_fail (BOLT_IS_CLIENT (client), NULL);
391
392 pstr = bolt_enum_to_string (BOLT_TYPE_POLICY, policy, error);
393 if (pstr == NULL)
394 return NULL;
395
396 fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, error);
397 if (fstr == NULL)
398 return NULL;
399
400 params = g_variant_new ("(sss)", uid, pstr, fstr);
401 val = g_dbus_proxy_call_sync (G_DBUS_PROXY (client),
402 "EnrollDevice",
403 params,
404 G_DBUS_CALL_FLAGS_NONE,
405 -1,
406 NULL,
407 &err);
408
409 if (val == NULL)
410 {
411 bolt_error_propagate_stripped (error, &err);
412 return NULL;
413 }
414
415 bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client));
416 g_variant_get (val, "(&o)", &opath);
417
418 if (opath == NULL)
419 return NULL;
420
421 dev = bolt_device_new_for_object_path (bus, opath, NULL, error);
422 return dev;
423 }
424
425 void
426 bolt_client_enroll_device_async (BoltClient *client,
427 const char *uid,
428 BoltPolicy policy,
429 BoltAuthCtrl flags,
430 GCancellable *cancellable,
431 GAsyncReadyCallback callback,
432 gpointer user_data)
433 {
434 g_autofree char *fstr = NULL;
435 GError *err = NULL;
436 GVariant *params;
437 const char *pstr;
438
439 g_return_if_fail (BOLT_IS_CLIENT (client));
440 g_return_if_fail (uid != NULL);
441
442 pstr = bolt_enum_to_string (BOLT_TYPE_POLICY, policy, &err);
443 if (pstr == NULL)
444 {
445 g_task_report_error (client, callback, user_data, NULL, err);
446 return;
447 }
448
449 fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err);
450 if (fstr == NULL)
451 {
452 g_task_report_error (client, callback, user_data, NULL, err);
453 return;
454 }
455
456 params = g_variant_new ("(sss)", uid, pstr, fstr);
457 g_dbus_proxy_call (G_DBUS_PROXY (client),
458 "EnrollDevice",
459 params,
460 G_DBUS_CALL_FLAGS_NONE,
461 -1,
462 cancellable,
463 callback,
464 user_data);
465 }
466
467 gboolean
468 bolt_client_enroll_device_finish (BoltClient *client,
469 GAsyncResult *res,
470 char **path,
471 GError **error)
472 {
473 g_autoptr(GError) err = NULL;
474 g_autoptr(GVariant) val = NULL;
475
476 g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
477
478 val = g_dbus_proxy_call_finish (G_DBUS_PROXY (client), res, &err);
479 if (val == NULL)
480 {
481 bolt_error_propagate_stripped (error, &err);
482 return FALSE;
483 }
484
485 if (path != NULL)
486 g_variant_get (val, "(o)", path);
487
488 return TRUE;
489 }
490
491 typedef struct OpData
492 {
493 const char *iface; /* Manager or Device */
494 const char *method; /* Enroll or Authorize */
495 char *path; /* object path */
496 GVariant *params; /* parameters */
497
498 } OpData;
499
500 static OpData *
501 op_data_new_enroll (const char *uid,
502 const char *policy,
503 const char *flags)
504 {
505 GVariant *params;
506 OpData *op;
507
508 params = g_variant_new ("(sss)", uid, policy, flags);
509
510 op = g_slice_new (OpData);
511 op->iface = BOLT_DBUS_INTERFACE;
512 op->method = "EnrollDevice";
513 op->params = g_variant_ref_sink (params);
514 op->path = g_strdup (BOLT_DBUS_PATH);
515
516 return op;
517 }
518
519
520 static OpData *
521 op_data_new_authorize (const char *uid,
522 const char *flags)
523 {
524 OpData *op = NULL;
525 GVariant *params;
526 char *path;
527
528 path = bolt_gen_object_path (BOLT_DBUS_PATH_DEVICES, uid);
529 params = g_variant_new ("(s)", flags);
530
531 op = g_slice_new (OpData);
532
533 op->iface = BOLT_DBUS_DEVICE_INTERFACE;
534 op->method = "Authorize";
535 op->params = g_variant_ref_sink (params);
536 op->path = path; /* takes ownership */
537
538 return op;
539 }
540
541 static void
542 op_data_free (OpData *op)
543 {
544 g_clear_pointer (&op->params, g_variant_unref);
545 g_clear_pointer (&op->path, g_free);
546 g_slice_free (OpData, op);
547 }
548
549 static void
550 op_queue_free (GQueue *queue)
551 {
552 g_queue_free_full (queue, (GDestroyNotify) op_data_free);
553 }
554
555 static void allop_one_done (GObject *source_object,
556 GAsyncResult *res,
557 gpointer user_data);
558
559 static gboolean
560 allop_continue (BoltClient *client, GTask *task, GQueue *ops)
561 {
562 GDBusConnection *bus;
563 GCancellable *cancel;
564 OpData *op;
565
566 cancel = g_task_get_cancellable (task);
567 bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client));
568
569 op = g_queue_pop_head (ops);
570
571 if (op == NULL)
572 return TRUE;
573
574 g_dbus_connection_call (bus,
575 BOLT_DBUS_NAME,
576 op->path,
577 op->iface,
578 op->method,
579 op->params,
580 NULL,
581 G_DBUS_CALL_FLAGS_NONE,
582 -1,
583 cancel,
584 allop_one_done,
585 task);
586
587 op_data_free (op);
588
589 return FALSE;
590 }
591
592 static void
593 allop_one_done (GObject *source_object,
594 GAsyncResult *res,
595 gpointer user_data)
596 {
597 g_autoptr(GVariant) val = NULL;
598 BoltClient *client;
599 GDBusConnection *bus;
600 gboolean done;
601 GError *err = NULL;
602 GQueue *ops;
603 GTask *task;
604
605 task = G_TASK (user_data);
606
607 ops = g_task_get_task_data (task);
608 client = g_task_get_source_object (task);
609 bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (client));
610
611 val = g_dbus_connection_call_finish (bus, res, &err);
612
613 if (val == NULL)
614 {
615 g_task_return_error (task, err); /* takes ownership */
616 g_object_unref (task);
617 /* we are done (albeit with an error) */
618 return;
619 }
620
621 done = allop_continue (client, task, ops);
622
623 if (done)
624 {
625 /* we are done */
626 g_task_return_boolean (task, TRUE);
627 g_object_unref (task);
628 }
629 }
630
631 void
632 bolt_client_enroll_all_async (BoltClient *client,
633 GPtrArray *uuids,
634 BoltPolicy policy,
635 BoltAuthCtrl flags,
636 GCancellable *cancellable,
637 GAsyncReadyCallback callback,
638 gpointer user_data)
639 {
640 g_autofree char *fstr = NULL;
641 GError *err = NULL;
642 const char *pstr;
643 GQueue *ops;
644 GTask *task;
645
646 g_return_if_fail (BOLT_IS_CLIENT (client));
647 g_return_if_fail (uuids != NULL && uuids->len > 0);
648 g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
649 g_return_if_fail (callback != NULL);
650
651 pstr = bolt_enum_to_string (BOLT_TYPE_POLICY, policy, &err);
652 if (pstr == NULL)
653 {
654 g_task_report_error (client, callback, user_data, NULL, err);
655 return;
656 }
657
658 fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err);
659 if (fstr == NULL)
660 {
661 g_task_report_error (client, callback, user_data, NULL, err);
662 return;
663 }
664
665 task = g_task_new (client, cancellable, callback, user_data);
666 g_task_set_return_on_cancel (task, TRUE);
667
668 ops = g_queue_new ();
669 g_task_set_task_data (task, ops, (GDestroyNotify) op_queue_free);
670
671 for (guint i = 0; i < uuids->len; i++)
672 {
673 const char *uid = g_ptr_array_index (uuids, i);
674 OpData *op;
675
676 op = op_data_new_enroll (uid, pstr, fstr);
677
678 g_queue_push_tail (ops, op);
679 }
680
681 allop_continue (client, task, ops);
682 }
683
684 gboolean
685 bolt_client_enroll_all_finish (BoltClient *client,
686 GAsyncResult *res,
687 GError **error)
688 {
689 g_autoptr(GError) err = NULL;
690 gboolean ok;
691
692 g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
693 g_return_val_if_fail (g_task_is_valid (res, client), FALSE);
694 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
695
696 ok = g_task_propagate_boolean (G_TASK (res), &err);
697
698 if (!ok)
699 bolt_error_propagate_stripped (error, &err);
700
701 return ok;
702 }
703
704 void
705 bolt_client_authorize_all_async (BoltClient *client,
706 GPtrArray *uuids,
707 BoltAuthCtrl flags,
708 GCancellable *cancellable,
709 GAsyncReadyCallback callback,
710 gpointer user_data)
711 {
712 g_autofree char *fstr = NULL;
713 GError *err = NULL;
714 GQueue *ops;
715 GTask *task;
716
717 g_return_if_fail (BOLT_IS_CLIENT (client));
718 g_return_if_fail (uuids != NULL && uuids->len > 0);
719 g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
720 g_return_if_fail (callback != NULL);
721
722 fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err);
723 if (fstr == NULL)
724 {
725 g_task_report_error (client, callback, user_data, NULL, err);
726 return;
727 }
728
729 task = g_task_new (client, cancellable, callback, user_data);
730 g_task_set_return_on_cancel (task, TRUE);
731
732 ops = g_queue_new ();
733 g_task_set_task_data (task, ops, (GDestroyNotify) op_queue_free);
734
735 for (guint i = 0; i < uuids->len; i++)
736 {
737 const char *uid = g_ptr_array_index (uuids, i);
738 OpData *op;
739
740 op = op_data_new_authorize (uid, fstr);
741
742 g_queue_push_tail (ops, op);
743 }
744
745 allop_continue (client, task, ops);
746 }
747
748 gboolean
749 bolt_client_authorize_all_finish (BoltClient *client,
750 GAsyncResult *res,
751 GError **error)
752 {
753 g_autoptr(GError) err = NULL;
754 gboolean ok;
755
756 g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
757 g_return_val_if_fail (g_task_is_valid (res, client), FALSE);
758 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
759
760 ok = g_task_propagate_boolean (G_TASK (res), &err);
761
762 if (!ok)
763 bolt_error_propagate_stripped (error, &err);
764
765 return ok;
766 }
767
768 void
769 bolt_client_connect_all_async (BoltClient *client,
770 GPtrArray *devices,
771 BoltPolicy policy,
772 BoltAuthCtrl flags,
773 GCancellable *cancellable,
774 GAsyncReadyCallback callback,
775 gpointer user_data)
776 {
777 g_autofree char *fstr = NULL;
778 GError *err = NULL;
779 const char *pstr;
780 GQueue *ops;
781 GTask *task;
782
783 g_return_if_fail (BOLT_IS_CLIENT (client));
784 g_return_if_fail (devices != NULL && devices->len > 0);
785 g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
786 g_return_if_fail (callback != NULL);
787
788 pstr = bolt_enum_to_string (BOLT_TYPE_POLICY, policy, &err);
789 if (pstr == NULL)
790 {
791 g_task_report_error (client, callback, user_data, NULL, err);
792 return;
793 }
794
795 fstr = bolt_flags_to_string (BOLT_TYPE_AUTH_CTRL, flags, &err);
796 if (fstr == NULL)
797 {
798 g_task_report_error (client, callback, user_data, NULL, err);
799 return;
800 }
801
802 task = g_task_new (client, cancellable, callback, user_data);
803 g_task_set_return_on_cancel (task, TRUE);
804
805 ops = g_queue_new ();
806 g_task_set_task_data (task, ops, (GDestroyNotify) op_queue_free);
807
808 for (guint i = 0; i < devices->len; i++)
809 {
810 BoltDevice *dev = g_ptr_array_index (devices, i);
811 const char *uid = bolt_device_get_uid (dev);
812 OpData *op;
813
814 if (bolt_device_is_stored (dev))
815 op = op_data_new_authorize (uid, fstr);
816 else
817 op = op_data_new_enroll (uid, pstr, fstr);
818
819 g_queue_push_tail (ops, op);
820 }
821
822 allop_continue (client, task, ops);
823 }
824
825 gboolean
826 bolt_client_connect_all_finish (BoltClient *client,
827 GAsyncResult *res,
828 GError **error)
829 {
830 g_autoptr(GError) err = NULL;
831 gboolean ok;
832
833 g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
834 g_return_val_if_fail (g_task_is_valid (res, client), FALSE);
835 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
836
837 ok = g_task_propagate_boolean (G_TASK (res), &err);
838
839 if (!ok)
840 bolt_error_propagate_stripped (error, &err);
841
842 return ok;
843 }
844
845 gboolean
846 bolt_client_forget_device (BoltClient *client,
847 const char *uid,
848 GError **error)
849 {
850 g_autoptr(GVariant) val = NULL;
851 g_autoptr(GError) err = NULL;
852
853 g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
854
855 val = g_dbus_proxy_call_sync (G_DBUS_PROXY (client),
856 "ForgetDevice",
857 g_variant_new ("(s)", uid),
858 G_DBUS_CALL_FLAGS_NONE,
859 -1,
860 NULL,
861 &err);
862
863 if (val == NULL)
864 {
865 bolt_error_propagate_stripped (error, &err);
866 return FALSE;
867 }
868
869 return TRUE;
870 }
871
872 void
873 bolt_client_forget_device_async (BoltClient *client,
874 const char *uid,
875 GCancellable *cancellable,
876 GAsyncReadyCallback callback,
877 gpointer user_data)
878 {
879 g_return_if_fail (BOLT_IS_CLIENT (client));
880
881 g_dbus_proxy_call (G_DBUS_PROXY (client),
882 "ForgetDevice",
883 g_variant_new ("(s)", uid),
884 G_DBUS_CALL_FLAGS_NONE,
885 -1,
886 cancellable,
887 callback,
888 user_data);
889 }
890
891 gboolean
892 bolt_client_forget_device_finish (BoltClient *client,
893 GAsyncResult *res,
894 GError **error)
895 {
896 g_autoptr(GVariant) val = NULL;
897 g_autoptr(GError) err = NULL;
898
899 g_return_val_if_fail (BOLT_IS_CLIENT (client), FALSE);
900
901 val = g_dbus_proxy_call_finish (G_DBUS_PROXY (client), res, &err);
902 if (val == NULL)
903 {
904 bolt_error_propagate_stripped (error, &err);
905 return FALSE;
906 }
907
908 return TRUE;
909 }
910
911 /* getter */
912 guint
913 bolt_client_get_version (BoltClient *client)
914 {
915 const char *key;
916 guint val = 0;
917 gboolean ok;
918
919 g_return_val_if_fail (BOLT_IS_CLIENT (client), val);
920
921 key = g_param_spec_get_name (props[PROP_VERSION]);
922 ok = bolt_proxy_get_property_uint32 (BOLT_PROXY (client), key, &val);
923
924 if (!ok)
925 g_warning ("failed to get property '%s'", key);
926
927 return val;
928 }
929
930 gboolean
931 bolt_client_is_probing (BoltClient *client)
932 {
933 const char *key;
934 gboolean val = FALSE;
935 gboolean ok;
936
937 g_return_val_if_fail (BOLT_IS_CLIENT (client), val);
938
939 key = g_param_spec_get_name (props[PROP_PROBING]);
940 ok = bolt_proxy_get_property_bool (BOLT_PROXY (client), key, &val);
941
942 if (!ok)
943 g_warning ("failed to get enum property '%s'", key);
944
945 return val;
946 }
947
948 BoltSecurity
949 bolt_client_get_security (BoltClient *client)
950 {
951 const char *key;
952 gboolean ok;
953 gint val = BOLT_SECURITY_UNKNOWN;
954
955 g_return_val_if_fail (BOLT_IS_CLIENT (client), val);
956
957 key = g_param_spec_get_name (props[PROP_SECURITY]);
958 ok = bolt_proxy_get_property_enum (BOLT_PROXY (client), key, &val);
959
960 if (!ok)
961 g_warning ("failed to get enum property '%s'", key);
962
963 return val;
964 }
965
966 BoltAuthMode
967 bolt_client_get_authmode (BoltClient *client)
968 {
969 const char *key;
970 gboolean ok;
971 guint val = BOLT_AUTH_DISABLED;
972
973 g_return_val_if_fail (BOLT_IS_CLIENT (client), val);
974
975 key = g_param_spec_get_name (props[PROP_AUTHMODE]);
976 ok = bolt_proxy_get_property_flags (BOLT_PROXY (client), key, &val);
977
978 if (!ok)
979 g_warning ("failed to get enum property '%s'", key);
980
981 return val;
982 }
983
984 void
985 bolt_client_set_authmode_async (BoltClient *client,
986 BoltAuthMode mode,
987 GCancellable *cancellable,
988 GAsyncReadyCallback callback,
989 gpointer user_data)
990 {
991 g_autofree char *str = NULL;
992 GError *err = NULL;
993 GParamSpec *pspec;
994 GParamSpecFlags *flags_pspec;
995 GFlagsClass *flags_class;
996
997 pspec = props[PROP_AUTHMODE];
998 flags_pspec = G_PARAM_SPEC_FLAGS (pspec);
999 flags_class = flags_pspec->flags_class;
1000 str = bolt_flags_class_to_string (flags_class, mode, &err);
1001
1002 if (str == NULL)
1003 {
1004 g_task_report_error (client, callback, user_data, NULL, err);
1005 return;
1006 }
1007
1008 bolt_proxy_set_property_async (BOLT_PROXY (client),
1009 g_param_spec_get_nick (pspec),
1010 g_variant_new ("s", str),
1011 cancellable,
1012 callback,
1013 user_data);
1014 }
1015
1016 gboolean
1017 bolt_client_set_authmode_finish (BoltClient *client,
1018 GAsyncResult *res,
1019 GError **error)
1020 {
1021 return bolt_proxy_set_property_finish (res, error);
1022 }
1023
1024 /* utility functions */
1025 static gint
1026 device_sort_by_syspath (gconstpointer ap,
1027 gconstpointer bp,
1028 gpointer data)
1029 {
1030 BoltDevice *a = BOLT_DEVICE (*((BoltDevice **) ap));
1031 BoltDevice *b = BOLT_DEVICE (*((BoltDevice **) bp));
1032 gint sort_order = GPOINTER_TO_INT (data);
1033 const char *pa;
1034 const char *pb;
1035
1036 pa = bolt_device_get_syspath (a);
1037 pb = bolt_device_get_syspath (b);
1038
1039 return sort_order * g_strcmp0 (pa, pb);
1040 }
1041
1042 void
1043 bolt_devices_sort_by_syspath (GPtrArray *devices,
1044 gboolean reverse)
1045 {
1046 gpointer sort_order = GINT_TO_POINTER (reverse ? -1 : 1);
1047
1048 if (devices == NULL)
1049 return;
1050
1051 g_ptr_array_sort_with_data (devices,
1052 device_sort_by_syspath,
1053 sort_order);
1054 }
1055