Branch data Line data Source code
1 : : /* libsecret - GLib wrapper for Secret Service
2 : : *
3 : : * Copyright 2012 Red Hat Inc.
4 : : *
5 : : * This program is free software: you can redistribute it and/or modify
6 : : * it under the terms of the GNU Lesser General Public License as published
7 : : * by the Free Software Foundation; either version 2.1 of the licence or (at
8 : : * your option) any later version.
9 : : *
10 : : * See the included COPYING file for more information.
11 : : *
12 : : * Author: Stef Walter <stefw@gnome.org>
13 : : */
14 : :
15 : : #include "config.h"
16 : :
17 : : #include "secret-collection.h"
18 : : #include "secret-dbus-generated.h"
19 : : #include "secret-item.h"
20 : : #include "secret-paths.h"
21 : : #include "secret-private.h"
22 : : #include "secret-retrievable.h"
23 : : #include "secret-service.h"
24 : : #include "secret-types.h"
25 : : #include "secret-value.h"
26 : :
27 : : #include "libsecret/secret-enum-types.h"
28 : :
29 : : #include <glib/gi18n-lib.h>
30 : :
31 : : /**
32 : : * SecretItem:
33 : : *
34 : : * A secret item
35 : : *
36 : : * #SecretItem represents a secret item stored in the Secret Service.
37 : : *
38 : : * Each item has a value, represented by a [struct@Value], which can be
39 : : * retrieved by [method@Item.get_secret] or set by [method@Item.set_secret].
40 : : * The item is only available when the item is not locked.
41 : : *
42 : : * Items can be locked or unlocked using the [method@Service.lock] or
43 : : * [method@Service.unlock] functions. The Secret Service may not be able to
44 : : * unlock individual items, and may unlock an entire collection when a single
45 : : * item is unlocked.
46 : : *
47 : : * Each item has a set of attributes, which are used to locate the item later.
48 : : * These are not stored or transferred in a secure manner. Each attribute has
49 : : * a string name and a string value. Use [method@Service.search] to search for
50 : : * items based on their attributes, and [method@Item.set_attributes] to change
51 : : * the attributes associated with an item.
52 : : *
53 : : * Items can be created with [func@Item.create] or [method@Service.store].
54 : : *
55 : : * Stability: Stable
56 : : */
57 : :
58 : : /**
59 : : * SecretItemClass:
60 : : * @parent_class: the parent class
61 : : *
62 : : * The class for #SecretItem.
63 : : */
64 : :
65 : : /**
66 : : * SecretItemFlags:
67 : : * @SECRET_ITEM_NONE: no flags
68 : : * @SECRET_ITEM_LOAD_SECRET: a secret has been (or should be) loaded for #SecretItem
69 : : *
70 : : * Flags which determine which parts of the #SecretItem proxy are initialized.
71 : : */
72 : :
73 : : /**
74 : : * SecretItemCreateFlags:
75 : : * @SECRET_ITEM_CREATE_NONE: no flags
76 : : * @SECRET_ITEM_CREATE_REPLACE: replace an item with the same attributes.
77 : : *
78 : : * Flags for [func@Item.create].
79 : : */
80 : :
81 : : enum {
82 : : PROP_0,
83 : : PROP_SERVICE,
84 : : PROP_FLAGS,
85 : : PROP_ATTRIBUTES,
86 : : PROP_LABEL,
87 : : PROP_LOCKED,
88 : : PROP_CREATED,
89 : : PROP_MODIFIED
90 : : };
91 : :
92 : : struct _SecretItemPrivate {
93 : : /* No changes between construct and finalize */
94 : : SecretService *service;
95 : : SecretItemFlags init_flags;
96 : :
97 : : /* Locked by mutex */
98 : : GMutex mutex;
99 : : SecretValue *value;
100 : : gint disposed;
101 : : };
102 : :
103 : : static SecretRetrievableInterface *secret_item_retrievable_parent_iface = NULL;
104 : :
105 : : static GInitableIface *secret_item_initable_parent_iface = NULL;
106 : :
107 : : static GAsyncInitableIface *secret_item_async_initable_parent_iface = NULL;
108 : :
109 : : static void secret_item_retrievable_iface (SecretRetrievableInterface *iface);
110 : :
111 : : static void secret_item_initable_iface (GInitableIface *iface);
112 : :
113 : : static void secret_item_async_initable_iface (GAsyncInitableIface *iface);
114 : :
115 [ + + + - : 1278 : G_DEFINE_TYPE_WITH_CODE (SecretItem, secret_item, G_TYPE_DBUS_PROXY,
+ + ]
116 : : G_ADD_PRIVATE (SecretItem)
117 : : G_IMPLEMENT_INTERFACE (SECRET_TYPE_RETRIEVABLE, secret_item_retrievable_iface);
118 : : G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, secret_item_initable_iface);
119 : : G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, secret_item_async_initable_iface);
120 : : );
121 : :
122 : : static void
123 : 144 : secret_item_init (SecretItem *self)
124 : : {
125 : 144 : self->pv = secret_item_get_instance_private (self);
126 : 144 : g_mutex_init (&self->pv->mutex);
127 : 144 : }
128 : :
129 : : static void
130 : 1 : on_set_attributes (GObject *source,
131 : : GAsyncResult *result,
132 : : gpointer user_data)
133 : : {
134 : 1 : SecretItem *self = SECRET_ITEM (user_data);
135 : 1 : GError *error = NULL;
136 : :
137 [ + - ]: 1 : if (!g_atomic_int_get (&self->pv->disposed)) {
138 : 1 : secret_item_set_attributes_finish (self, result, &error);
139 [ - + ]: 1 : if (error != NULL) {
140 : 0 : g_warning ("couldn't set SecretItem Attributes: %s", error->message);
141 : 0 : g_error_free (error);
142 : : }
143 : : }
144 : :
145 : 1 : g_object_unref (self);
146 : 1 : }
147 : :
148 : : static void
149 : 1 : on_set_label (GObject *source,
150 : : GAsyncResult *result,
151 : : gpointer user_data)
152 : : {
153 : 1 : SecretItem *self = SECRET_ITEM (user_data);
154 : 1 : GError *error = NULL;
155 : :
156 [ + - ]: 1 : if (!g_atomic_int_get (&self->pv->disposed)) {
157 : 1 : secret_item_set_label_finish (self, result, &error);
158 [ - + ]: 1 : if (error != NULL) {
159 : 0 : g_warning ("couldn't set SecretItem Label: %s", error->message);
160 : 0 : g_error_free (error);
161 : : }
162 : : }
163 : :
164 : 1 : g_object_unref (self);
165 : 1 : }
166 : :
167 : :
168 : : static void
169 : 144 : item_take_service (SecretItem *self,
170 : : SecretService *service)
171 : : {
172 [ - + ]: 144 : if (service == NULL)
173 : 0 : return;
174 : :
175 [ - + ]: 144 : g_return_if_fail (self->pv->service == NULL);
176 : :
177 : 144 : self->pv->service = service;
178 : 144 : g_object_add_weak_pointer (G_OBJECT (self->pv->service),
179 : 144 : (gpointer *)&self->pv->service);
180 : :
181 : : /* Yes, we expect that the service will stay around */
182 : 144 : g_object_unref (service);
183 : : }
184 : :
185 : : static void
186 : 290 : secret_item_set_property (GObject *obj,
187 : : guint prop_id,
188 : : const GValue *value,
189 : : GParamSpec *pspec)
190 : : {
191 : 290 : SecretItem *self = SECRET_ITEM (obj);
192 : :
193 [ + + + + : 290 : switch (prop_id) {
- ]
194 : 144 : case PROP_SERVICE:
195 : 144 : item_take_service (self, g_value_dup_object (value));
196 : 144 : break;
197 : 144 : case PROP_FLAGS:
198 : 144 : self->pv->init_flags = g_value_get_flags (value);
199 : 144 : break;
200 : 1 : case PROP_ATTRIBUTES:
201 : 1 : secret_item_set_attributes (self, NULL, g_value_get_boxed (value),
202 : : NULL, on_set_attributes,
203 : : g_object_ref (self));
204 : 1 : break;
205 : 1 : case PROP_LABEL:
206 : 1 : secret_item_set_label (self, g_value_get_string (value),
207 : : NULL, on_set_label,
208 : : g_object_ref (self));
209 : 1 : break;
210 : 0 : default:
211 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
212 : 0 : break;
213 : : }
214 : 290 : }
215 : :
216 : : static void
217 : 6 : secret_item_get_property (GObject *obj,
218 : : guint prop_id,
219 : : GValue *value,
220 : : GParamSpec *pspec)
221 : : {
222 : 6 : SecretItem *self = SECRET_ITEM (obj);
223 : :
224 [ + - + + : 6 : switch (prop_id) {
+ + + - ]
225 : 1 : case PROP_SERVICE:
226 : 1 : g_value_set_object (value, self->pv->service);
227 : 1 : break;
228 : 0 : case PROP_FLAGS:
229 : 0 : g_value_set_flags (value, secret_item_get_flags (self));
230 : 0 : break;
231 : 1 : case PROP_ATTRIBUTES:
232 : 1 : g_value_take_boxed (value, secret_item_get_attributes (self));
233 : 1 : break;
234 : 1 : case PROP_LABEL:
235 : 1 : g_value_take_string (value, secret_item_get_label (self));
236 : 1 : break;
237 : 1 : case PROP_LOCKED:
238 : 1 : g_value_set_boolean (value, secret_item_get_locked (self));
239 : 1 : break;
240 : 1 : case PROP_CREATED:
241 : 1 : g_value_set_uint64 (value, secret_item_get_created (self));
242 : 1 : break;
243 : 1 : case PROP_MODIFIED:
244 : 1 : g_value_set_uint64 (value, secret_item_get_modified (self));
245 : 1 : break;
246 : 0 : default:
247 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
248 : 0 : break;
249 : : }
250 : 6 : }
251 : :
252 : : static void
253 : 144 : secret_item_dispose (GObject *obj)
254 : : {
255 : 144 : SecretItem *self = SECRET_ITEM (obj);
256 : :
257 : 144 : g_atomic_int_inc (&self->pv->disposed);
258 : :
259 : 144 : G_OBJECT_CLASS (secret_item_parent_class)->dispose (obj);
260 : 144 : }
261 : :
262 : : static void
263 : 144 : secret_item_finalize (GObject *obj)
264 : : {
265 : 144 : SecretItem *self = SECRET_ITEM (obj);
266 : :
267 [ + + ]: 144 : if (self->pv->service)
268 : 64 : g_object_remove_weak_pointer (G_OBJECT (self->pv->service),
269 : 64 : (gpointer *)&self->pv->service);
270 : :
271 [ + + ]: 144 : if (self->pv->value != NULL)
272 : 12 : secret_value_unref (self->pv->value);
273 : :
274 : 144 : g_mutex_clear (&self->pv->mutex);
275 : :
276 : 144 : G_OBJECT_CLASS (secret_item_parent_class)->finalize (obj);
277 : 144 : }
278 : :
279 : : static void
280 : 844 : handle_property_changed (GObject *object,
281 : : const gchar *property_name)
282 : : {
283 [ + + ]: 844 : if (g_str_equal (property_name, "Attributes"))
284 : 142 : g_object_notify (object, "attributes");
285 : :
286 [ + + ]: 702 : else if (g_str_equal (property_name, "Label"))
287 : 142 : g_object_notify (object, "label");
288 : :
289 [ + + ]: 560 : else if (g_str_equal (property_name, "Locked"))
290 : 140 : g_object_notify (object, "locked");
291 : :
292 [ + + ]: 420 : else if (g_str_equal (property_name, "Created"))
293 : 140 : g_object_notify (object, "created");
294 : :
295 [ + + ]: 280 : else if (g_str_equal (property_name, "Modified"))
296 : 140 : g_object_notify (object, "modified");
297 : 844 : }
298 : :
299 : : static void
300 : 144 : secret_item_properties_changed (GDBusProxy *proxy,
301 : : GVariant *changed_properties,
302 : : const gchar* const *invalidated_properties)
303 : : {
304 : 144 : GObject *obj = G_OBJECT (proxy);
305 : : gchar *property_name;
306 : : GVariantIter iter;
307 : : GVariant *value;
308 : :
309 : 144 : g_object_freeze_notify (obj);
310 : :
311 : 144 : g_variant_iter_init (&iter, changed_properties);
312 [ + + ]: 988 : while (g_variant_iter_loop (&iter, "{sv}", &property_name, &value))
313 : 844 : handle_property_changed (obj, property_name);
314 : :
315 : 144 : g_object_thaw_notify (obj);
316 : 144 : }
317 : :
318 : : static void
319 : 6 : secret_item_class_init (SecretItemClass *klass)
320 : : {
321 : 6 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
322 : 6 : GDBusProxyClass *proxy_class = G_DBUS_PROXY_CLASS (klass);
323 : :
324 : 6 : gobject_class->get_property = secret_item_get_property;
325 : 6 : gobject_class->set_property = secret_item_set_property;
326 : 6 : gobject_class->dispose = secret_item_dispose;
327 : 6 : gobject_class->finalize = secret_item_finalize;
328 : :
329 : 6 : proxy_class->g_properties_changed = secret_item_properties_changed;
330 : :
331 : : /**
332 : : * SecretItem:service: (attributes org.gtk.Property.get=secret_item_get_service)
333 : : *
334 : : * The [class@Service] object that this item is associated with and
335 : : * uses to interact with the actual D-Bus Secret Service.
336 : : */
337 : 6 : g_object_class_install_property (gobject_class, PROP_SERVICE,
338 : : g_param_spec_object ("service", "Service", "Secret Service",
339 : : SECRET_TYPE_SERVICE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
340 : :
341 : : /**
342 : : * SecretItem:flags: (attributes org.gtk.Property.get=secret_item_get_flags)
343 : : *
344 : : * A set of flags describing which parts of the secret item have
345 : : * been initialized.
346 : : */
347 : 6 : g_object_class_install_property (gobject_class, PROP_FLAGS,
348 : : g_param_spec_flags ("flags", "Flags", "Item flags",
349 : : secret_item_flags_get_type (), SECRET_ITEM_NONE,
350 : : G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
351 : :
352 : : /**
353 : : * SecretItem:attributes: (type GLib.HashTable(utf8,utf8)) (transfer full)
354 : : *
355 : : * The attributes set on this item. Attributes are used to locate an
356 : : * item.
357 : : *
358 : : * They are not guaranteed to be stored or transferred securely.
359 : : */
360 : 6 : g_object_class_override_property (gobject_class, PROP_ATTRIBUTES, "attributes");
361 : :
362 : : /**
363 : : * SecretItem:label:
364 : : *
365 : : * The human readable label for the item.
366 : : *
367 : : * Setting this property will result in the label of the item being
368 : : * set asynchronously. To properly track the changing of the label use the
369 : : * [method@Item.set_label] function.
370 : : */
371 : 6 : g_object_class_override_property (gobject_class, PROP_LABEL, "label");
372 : :
373 : : /**
374 : : * SecretItem:locked: (attributes org.gtk.Property.get=secret_item_get_locked)
375 : : *
376 : : * Whether the item is locked or not.
377 : : *
378 : : * An item may not be independently lockable separate from other items in
379 : : * its collection.
380 : : *
381 : : * To lock or unlock a item use the [method@Service.lock] or
382 : : * [method@Service.unlock] functions.
383 : : */
384 : 6 : g_object_class_install_property (gobject_class, PROP_LOCKED,
385 : : g_param_spec_boolean ("locked", "Locked", "Item locked",
386 : : TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
387 : :
388 : : /**
389 : : * SecretItem:created:
390 : : *
391 : : * The date and time (in seconds since the UNIX epoch) that this
392 : : * item was created.
393 : : */
394 : 6 : g_object_class_override_property (gobject_class, PROP_CREATED, "created");
395 : :
396 : : /**
397 : : * SecretItem:modified:
398 : : *
399 : : * The date and time (in seconds since the UNIX epoch) that this
400 : : * item was last modified.
401 : : */
402 : 6 : g_object_class_override_property (gobject_class, PROP_MODIFIED, "modified");
403 : 6 : }
404 : :
405 : : static gboolean
406 : 67 : item_ensure_for_flags_sync (SecretItem *self,
407 : : SecretItemFlags flags,
408 : : GCancellable *cancellable,
409 : : GError **error)
410 : : {
411 [ - + - - ]: 67 : if (flags & SECRET_ITEM_LOAD_SECRET && !secret_item_get_locked (self)) {
412 [ # # ]: 0 : if (!secret_item_load_secret_sync (self, cancellable, error))
413 : 0 : return FALSE;
414 : : }
415 : :
416 : 67 : return TRUE;
417 : : }
418 : :
419 : :
420 : : static void
421 : 0 : on_init_load_secret (GObject *source,
422 : : GAsyncResult *result,
423 : : gpointer user_data)
424 : : {
425 : 0 : GTask *task = G_TASK (user_data);
426 : 0 : SecretItem *self = SECRET_ITEM (source);
427 : 0 : GError *error = NULL;
428 : :
429 [ # # ]: 0 : if (!secret_item_load_secret_finish (self, result, &error))
430 : 0 : g_task_return_error (task, g_steal_pointer (&error));
431 : : else
432 : 0 : g_task_return_boolean (task, TRUE);
433 : :
434 [ # # ]: 0 : g_clear_object (&task);
435 : 0 : }
436 : :
437 : : static void
438 : 73 : item_ensure_for_flags_async (SecretItem *self,
439 : : SecretItemFlags flags,
440 : : GTask *task)
441 : : {
442 : 73 : GCancellable *cancellable = g_task_get_cancellable (task);
443 : :
444 [ - + - - ]: 73 : if (flags & SECRET_ITEM_LOAD_SECRET && !secret_item_get_locked (self))
445 : 0 : secret_item_load_secret (self, cancellable, on_init_load_secret,
446 : : g_object_ref (task));
447 : :
448 : : else
449 : 73 : g_task_return_boolean (task, TRUE);
450 : 73 : }
451 : :
452 : : static gboolean
453 : 70 : secret_item_initable_init (GInitable *initable,
454 : : GCancellable *cancellable,
455 : : GError **error)
456 : : {
457 : : SecretItem *self;
458 : : SecretService *service;
459 : : GDBusProxy *proxy;
460 : :
461 [ - + ]: 70 : if (!secret_item_initable_parent_iface->init (initable, cancellable, error))
462 : 0 : return FALSE;
463 : :
464 : 70 : proxy = G_DBUS_PROXY (initable);
465 : :
466 [ + + ]: 70 : if (!_secret_util_have_cached_properties (proxy)) {
467 : 3 : g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
468 : : "No such secret item at path: %s",
469 : : g_dbus_proxy_get_object_path (proxy));
470 : 3 : return FALSE;
471 : : }
472 : :
473 : 67 : self = SECRET_ITEM (initable);
474 [ - + ]: 67 : if (!self->pv->service) {
475 : 0 : service = secret_service_get_sync (SECRET_SERVICE_NONE, cancellable, error);
476 [ # # ]: 0 : if (service == NULL)
477 : 0 : return FALSE;
478 : : else
479 : 0 : item_take_service (self, service);
480 : : }
481 : :
482 : 67 : return item_ensure_for_flags_sync (self, self->pv->init_flags, cancellable, error);
483 : : }
484 : :
485 : : static void
486 : 6 : secret_item_initable_iface (GInitableIface *iface)
487 : : {
488 : 6 : secret_item_initable_parent_iface = g_type_interface_peek_parent (iface);
489 : :
490 : 6 : iface->init = secret_item_initable_init;
491 : 6 : }
492 : :
493 : : static void
494 : 0 : on_init_service (GObject *source,
495 : : GAsyncResult *result,
496 : : gpointer user_data)
497 : : {
498 : 0 : GTask *task = G_TASK (user_data);
499 : 0 : SecretItem *self = SECRET_ITEM (g_task_get_source_object (task));
500 : : SecretService *service;
501 : 0 : GError *error = NULL;
502 : :
503 : 0 : service = secret_service_get_finish (result, &error);
504 [ # # ]: 0 : if (error == NULL) {
505 : 0 : item_take_service (self, g_steal_pointer (&service));
506 : 0 : item_ensure_for_flags_async (self, self->pv->init_flags, task);
507 : :
508 : : } else {
509 : 0 : g_task_return_error (task, g_steal_pointer (&error));
510 : : }
511 : :
512 [ # # ]: 0 : g_clear_object (&task);
513 : 0 : }
514 : :
515 : : typedef struct {
516 : : GAsyncReadyCallback callback;
517 : : gpointer user_data;
518 : : } InitBaseClosure;
519 : :
520 : : static void
521 : : secret_item_async_initable_init_async (GAsyncInitable *initable,
522 : : int io_priority,
523 : : GCancellable *cancellable,
524 : : GAsyncReadyCallback callback,
525 : : gpointer user_data);
526 : :
527 : : static void
528 : 74 : on_init_base (GObject *source,
529 : : GAsyncResult *result,
530 : : gpointer user_data)
531 : : {
532 : 74 : GTask *base_task = G_TASK (user_data);
533 : 74 : InitBaseClosure *base = g_task_get_task_data (base_task);
534 : 74 : GCancellable *cancellable = g_task_get_cancellable (base_task);
535 : : GTask *task;
536 : 74 : SecretItem *self = SECRET_ITEM (source);
537 : 74 : GDBusProxy *proxy = G_DBUS_PROXY (self);
538 : 74 : GError *error = NULL;
539 : :
540 : 74 : task = g_task_new (source, cancellable, base->callback, base->user_data);
541 [ + - ]: 74 : g_task_set_source_tag (task, secret_item_async_initable_init_async);
542 [ + - ]: 74 : g_clear_object (&base_task);
543 : :
544 [ - + ]: 74 : if (!secret_item_async_initable_parent_iface->init_finish (G_ASYNC_INITABLE (self),
545 : : result, &error)) {
546 : 0 : g_task_return_error (task, g_steal_pointer (&error));
547 : :
548 [ + + ]: 74 : } else if (!_secret_util_have_cached_properties (proxy)) {
549 : 1 : g_task_return_new_error (task, G_DBUS_ERROR,
550 : : G_DBUS_ERROR_UNKNOWN_METHOD,
551 : : "No such secret item at path: %s",
552 : : g_dbus_proxy_get_object_path (proxy));
553 : :
554 [ - + ]: 73 : } else if (self->pv->service == NULL) {
555 : 0 : secret_service_get (SECRET_SERVICE_NONE, cancellable,
556 : : on_init_service, g_steal_pointer (&task));
557 : :
558 : : } else {
559 : 73 : item_ensure_for_flags_async (self, self->pv->init_flags, task);
560 : : }
561 : :
562 [ + - ]: 74 : g_clear_object (&task);
563 : 74 : }
564 : :
565 : : static void
566 : 74 : secret_item_async_initable_init_async (GAsyncInitable *initable,
567 : : int io_priority,
568 : : GCancellable *cancellable,
569 : : GAsyncReadyCallback callback,
570 : : gpointer user_data)
571 : : {
572 : : GTask *task;
573 : : InitBaseClosure *base;
574 : :
575 : 74 : task = g_task_new (initable, cancellable, NULL, NULL);
576 [ + - ]: 74 : g_task_set_source_tag (task, secret_item_async_initable_init_async);
577 : :
578 : 74 : base = g_new0 (InitBaseClosure, 1);
579 : 74 : base->callback = callback;
580 : 74 : base->user_data = user_data;
581 : 74 : g_task_set_task_data (task, base, g_free);
582 : :
583 : 74 : secret_item_async_initable_parent_iface->init_async (initable, io_priority,
584 : : cancellable,
585 : : on_init_base,
586 : : g_steal_pointer (&task));
587 : :
588 [ - + ]: 74 : g_clear_object (&task);
589 : 74 : }
590 : :
591 : : static gboolean
592 : 74 : secret_item_async_initable_init_finish (GAsyncInitable *initable,
593 : : GAsyncResult *result,
594 : : GError **error)
595 : : {
596 [ - + ]: 74 : g_return_val_if_fail (g_task_is_valid (result, initable), FALSE);
597 : :
598 [ + + ]: 74 : if (!g_task_propagate_boolean (G_TASK (result), error)) {
599 : 1 : _secret_util_strip_remote_error (error);
600 : 1 : return FALSE;
601 : : }
602 : :
603 : 73 : return TRUE;
604 : : }
605 : :
606 : : static void
607 : 6 : secret_item_async_initable_iface (GAsyncInitableIface *iface)
608 : : {
609 : 6 : secret_item_async_initable_parent_iface = g_type_interface_peek_parent (iface);
610 : :
611 : 6 : iface->init_async = secret_item_async_initable_init_async;
612 : 6 : iface->init_finish = secret_item_async_initable_init_finish;
613 : 6 : }
614 : :
615 : : /**
616 : : * secret_item_refresh:
617 : : * @self: the collection
618 : : *
619 : : * Refresh the properties on this item.
620 : : *
621 : : * This fires off a request to refresh, and the properties will be updated
622 : : * later.
623 : : *
624 : : * Calling this method is not normally necessary, as the secret service
625 : : * will notify the client when properties change.
626 : : */
627 : : void
628 : 0 : secret_item_refresh (SecretItem *self)
629 : : {
630 [ # # # # : 0 : g_return_if_fail (SECRET_IS_ITEM (self));
# # # # ]
631 : :
632 : 0 : _secret_util_get_properties (G_DBUS_PROXY (self),
633 : : secret_item_refresh,
634 : : NULL, NULL, NULL);
635 : : }
636 : :
637 : : void
638 : 13 : _secret_item_set_cached_secret (SecretItem *self,
639 : : SecretValue *value)
640 : : {
641 : 13 : SecretValue *other = NULL;
642 : 13 : gboolean updated = FALSE;
643 : :
644 [ - + + - : 13 : g_return_if_fail (SECRET_IS_ITEM (self));
+ - - + ]
645 : :
646 [ + - ]: 13 : if (value != NULL)
647 : 13 : secret_value_ref (value);
648 : :
649 : 13 : g_mutex_lock (&self->pv->mutex);
650 : :
651 [ + - ]: 13 : if (value != self->pv->value) {
652 : 13 : other = self->pv->value;
653 : 13 : self->pv->value = value;
654 : 13 : updated = TRUE;
655 : : } else {
656 : 0 : other = value;
657 : : }
658 : :
659 : 13 : g_mutex_unlock (&self->pv->mutex);
660 : :
661 [ + + ]: 13 : if (other != NULL)
662 : 1 : secret_value_unref (other);
663 : :
664 [ + - ]: 13 : if (updated)
665 : 13 : g_object_notify (G_OBJECT (self), "flags");
666 : : }
667 : :
668 : : static void
669 : 1 : on_create_item (GObject *source,
670 : : GAsyncResult *result,
671 : : gpointer user_data)
672 : : {
673 : 1 : GTask *task = G_TASK (user_data);
674 : 1 : SecretValue *value = g_task_get_task_data (task);
675 : : SecretItem *item;
676 : 1 : GError *error = NULL;
677 : :
678 : 1 : item = secret_item_new_for_dbus_path_finish (result, &error);
679 [ + - ]: 1 : if (item) {
680 : : /* As a convenience mark down the SecretValue on the item */
681 : 1 : _secret_item_set_cached_secret (item, value);
682 : 1 : g_task_return_pointer (task, item, g_object_unref);
683 : : } else {
684 : 0 : g_task_return_error (task, g_steal_pointer (&error));
685 : : }
686 : :
687 [ + - ]: 1 : g_clear_object (&task);
688 : 1 : }
689 : :
690 : : static void
691 : 1 : on_create_path (GObject *source,
692 : : GAsyncResult *result,
693 : : gpointer user_data)
694 : : {
695 : 1 : GTask *task = G_TASK (user_data);
696 : 1 : GCancellable *cancellable = g_task_get_cancellable (task);
697 : 1 : SecretService *service = SECRET_SERVICE (source);
698 : 1 : GError *error = NULL;
699 : : gchar *path;
700 : :
701 : 1 : path = secret_service_create_item_dbus_path_finish (service, result, &error);
702 [ + - ]: 1 : if (error == NULL) {
703 : 1 : secret_item_new_for_dbus_path (service, path, SECRET_ITEM_NONE,
704 : : cancellable, on_create_item,
705 : : g_steal_pointer (&task));
706 : : } else {
707 : 0 : g_task_return_error (task, g_steal_pointer (&error));
708 : : }
709 : 1 : g_free (path);
710 : :
711 [ - + ]: 1 : g_clear_object (&task);
712 : 1 : }
713 : :
714 : : static GHashTable *
715 : 2 : item_properties_new (const gchar *label,
716 : : const SecretSchema *schema,
717 : : GHashTable *attributes)
718 : : {
719 : 2 : const gchar *schema_name = NULL;
720 : : GHashTable *properties;
721 : : GVariant *value;
722 : :
723 [ + - ]: 2 : if (schema != NULL)
724 : 2 : schema_name = schema->name;
725 : :
726 : 2 : properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
727 : : (GDestroyNotify)g_variant_unref);
728 : :
729 : 2 : value = g_variant_new_string (label);
730 : 2 : g_hash_table_insert (properties,
731 : : SECRET_ITEM_INTERFACE ".Label",
732 : 2 : g_variant_ref_sink (value));
733 : :
734 : 2 : value = _secret_attributes_to_variant (attributes, schema_name);
735 : 2 : g_hash_table_insert (properties,
736 : : SECRET_ITEM_INTERFACE ".Attributes",
737 : 2 : g_variant_ref_sink (value));
738 : :
739 : 2 : return properties;
740 : : }
741 : :
742 : : /**
743 : : * secret_item_create:
744 : : * @collection: a secret collection to create this item in
745 : : * @schema: (nullable): the schema for the attributes
746 : : * @attributes: (element-type utf8 utf8): attributes for the new item
747 : : * @label: label for the new item
748 : : * @value: secret value for the new item
749 : : * @flags: flags for the creation of the new item
750 : : * @cancellable: (nullable): optional cancellation object
751 : : * @callback: called when the operation completes
752 : : * @user_data: data to pass to the callback
753 : : *
754 : : * Create a new item in the secret service.
755 : : *
756 : : * If the @flags contains %SECRET_ITEM_CREATE_REPLACE, then the secret
757 : : * service will search for an item matching the @attributes, and update that item
758 : : * instead of creating a new one.
759 : : *
760 : : * This method may block indefinitely and should not be used in user interface
761 : : * threads. The secret service may prompt the user. [method@Service.prompt]
762 : : * will be used to handle any prompts that are required.
763 : : */
764 : : void
765 : 1 : secret_item_create (SecretCollection *collection,
766 : : const SecretSchema *schema,
767 : : GHashTable *attributes,
768 : : const gchar *label,
769 : : SecretValue *value,
770 : : SecretItemCreateFlags flags,
771 : : GCancellable *cancellable,
772 : : GAsyncReadyCallback callback,
773 : : gpointer user_data)
774 : : {
775 : 1 : SecretService *service = NULL;
776 : : const gchar *collection_path;
777 : : GTask *task;
778 : : GHashTable *properties;
779 : :
780 [ - + + - : 1 : g_return_if_fail (SECRET_IS_COLLECTION (collection));
+ - - + ]
781 [ - + ]: 1 : g_return_if_fail (label != NULL);
782 [ - + ]: 1 : g_return_if_fail (attributes != NULL);
783 [ - + ]: 1 : g_return_if_fail (value != NULL);
784 [ - + - - : 1 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - -
- ]
785 : :
786 : : /* Warnings raised already */
787 [ + - - + ]: 1 : if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
788 : 0 : return;
789 : :
790 : 1 : task = g_task_new (NULL, cancellable, callback, user_data);
791 [ + - ]: 1 : g_task_set_source_tag (task, secret_item_create);
792 : 1 : g_task_set_task_data (task, secret_value_ref (value), secret_value_unref);
793 : :
794 : 1 : properties = item_properties_new (label, schema, attributes);
795 : 1 : g_object_get (collection, "service", &service, NULL);
796 : :
797 : 1 : collection_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (collection));
798 : :
799 : 1 : secret_service_create_item_dbus_path (service, collection_path, properties,
800 : : value, flags, cancellable,
801 : : on_create_path,
802 : : g_steal_pointer (&task));
803 : :
804 : 1 : g_hash_table_unref (properties);
805 : 1 : g_object_unref (service);
806 [ - + ]: 1 : g_clear_object (&task);
807 : : }
808 : :
809 : : /**
810 : : * secret_item_create_finish:
811 : : * @result: the asynchronous result passed to the callback
812 : : * @error: location to place an error on failure
813 : : *
814 : : * Finish operation to create a new item in the secret service.
815 : : *
816 : : * Returns: (transfer full): the new item, which should be unreferenced
817 : : * with [method@GObject.Object.unref]
818 : : */
819 : : SecretItem *
820 : 1 : secret_item_create_finish (GAsyncResult *result,
821 : : GError **error)
822 : : {
823 : : SecretItem *retval;
824 : :
825 [ - + ]: 1 : g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
826 [ + - - + ]: 1 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
827 : :
828 : 1 : retval = g_task_propagate_pointer (G_TASK (result), error);
829 [ - + ]: 1 : if (!retval) {
830 : 0 : _secret_util_strip_remote_error (error);
831 : 0 : return NULL;
832 : : }
833 : :
834 : 1 : return g_steal_pointer (&retval);
835 : : }
836 : :
837 : : /**
838 : : * secret_item_create_sync:
839 : : * @collection: a secret collection to create this item in
840 : : * @schema: (nullable): the schema for the attributes
841 : : * @attributes: (element-type utf8 utf8): attributes for the new item
842 : : * @label: label for the new item
843 : : * @value: secret value for the new item
844 : : * @flags: flags for the creation of the new item
845 : : * @cancellable: (nullable): optional cancellation object
846 : : * @error: location to place an error on failure
847 : : *
848 : : * Create a new item in the secret service.
849 : : *
850 : : * If the @flags contains %SECRET_ITEM_CREATE_REPLACE, then the secret
851 : : * service will search for an item matching the @attributes, and update that item
852 : : * instead of creating a new one.
853 : : *
854 : : * This method may block indefinitely and should not be used in user interface
855 : : * threads. The secret service may prompt the user. [method@Service.prompt]
856 : : * will be used to handle any prompts that are required.
857 : : *
858 : : * Returns: (transfer full): the new item, which should be unreferenced
859 : : * with [method@GObject.Object.unref]
860 : : */
861 : : SecretItem *
862 : 1 : secret_item_create_sync (SecretCollection *collection,
863 : : const SecretSchema *schema,
864 : : GHashTable *attributes,
865 : : const gchar *label,
866 : : SecretValue *value,
867 : : SecretItemCreateFlags flags,
868 : : GCancellable *cancellable,
869 : : GError **error)
870 : : {
871 : 1 : SecretService *service = NULL;
872 : : const gchar *collection_path;
873 : 1 : SecretItem *item = NULL;
874 : : GHashTable *properties;
875 : : gchar *path;
876 : :
877 [ - + + - : 1 : g_return_val_if_fail (SECRET_IS_COLLECTION (collection), NULL);
+ - - + ]
878 [ - + ]: 1 : g_return_val_if_fail (label != NULL, NULL);
879 [ - + ]: 1 : g_return_val_if_fail (attributes != NULL, NULL);
880 [ - + ]: 1 : g_return_val_if_fail (value != NULL, NULL);
881 [ - + - - : 1 : g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
- - - - -
- ]
882 [ + - - + ]: 1 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
883 : :
884 : : /* Warnings raised already */
885 [ + - - + ]: 1 : if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
886 : 0 : return NULL;
887 : :
888 : 1 : properties = item_properties_new (label, schema, attributes);
889 : 1 : g_object_get (collection, "service", &service, NULL);
890 : :
891 : 1 : collection_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (collection));
892 : :
893 : 1 : path = secret_service_create_item_dbus_path_sync (service, collection_path, properties,
894 : : value, flags, cancellable, error);
895 : :
896 [ + - ]: 1 : if (path != NULL) {
897 : 1 : item = secret_item_new_for_dbus_path_sync (service, path, SECRET_ITEM_NONE,
898 : : cancellable, error);
899 : 1 : g_free (path);
900 : : }
901 : :
902 : 1 : g_hash_table_unref (properties);
903 : 1 : g_object_unref (service);
904 : :
905 : 1 : return item;
906 : : }
907 : :
908 : : static void
909 : 2 : on_item_deleted (GObject *source,
910 : : GAsyncResult *result,
911 : : gpointer user_data)
912 : : {
913 : 2 : GTask *task = G_TASK (user_data);
914 : 2 : SecretService *service = SECRET_SERVICE (source);
915 : 2 : GError *error = NULL;
916 : :
917 [ - + ]: 2 : if (!_secret_service_delete_path_finish (service, result, &error))
918 : 0 : g_task_return_error (task, g_steal_pointer (&error));
919 : : else
920 : 2 : g_task_return_boolean (task, TRUE);
921 : :
922 [ + - ]: 2 : g_clear_object (&task);
923 : 2 : }
924 : :
925 : : /**
926 : : * secret_item_delete:
927 : : * @self: an item
928 : : * @cancellable: (nullable): optional cancellation object
929 : : * @callback: called when the operation completes
930 : : * @user_data: data to pass to the callback
931 : : *
932 : : * Delete this item.
933 : : *
934 : : * This method returns immediately and completes asynchronously. The secret
935 : : * service may prompt the user. [method@Service.prompt] will be used to handle
936 : : * any prompts that show up.
937 : : */
938 : : void
939 : 2 : secret_item_delete (SecretItem *self,
940 : : GCancellable *cancellable,
941 : : GAsyncReadyCallback callback,
942 : : gpointer user_data)
943 : : {
944 : : GTask *task;
945 : : const gchar *object_path;
946 : :
947 [ - + + - : 2 : g_return_if_fail (SECRET_IS_ITEM (self));
+ - - + ]
948 [ - + - - : 2 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - -
- ]
949 : :
950 : 2 : object_path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (self));
951 : 2 : task = g_task_new (self, cancellable, callback, user_data);
952 [ + - ]: 2 : g_task_set_source_tag (task, secret_item_delete);
953 : :
954 : 2 : _secret_service_delete_path (self->pv->service, object_path, TRUE,
955 : : cancellable, on_item_deleted,
956 : : g_steal_pointer (&task));
957 : :
958 [ - + ]: 2 : g_clear_object (&task);
959 : : }
960 : :
961 : : /**
962 : : * secret_item_delete_finish:
963 : : * @self: an item
964 : : * @result: asynchronous result passed to the callback
965 : : * @error: location to place an error on failure
966 : : *
967 : : * Complete asynchronous operation to delete the secret item.
968 : : *
969 : : * Returns: whether the item was successfully deleted or not
970 : : */
971 : : gboolean
972 : 2 : secret_item_delete_finish (SecretItem *self,
973 : : GAsyncResult *result,
974 : : GError **error)
975 : : {
976 [ - + + - : 2 : g_return_val_if_fail (SECRET_IS_ITEM (self), FALSE);
+ - - + ]
977 [ + - - + ]: 2 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
978 [ - + ]: 2 : g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
979 : :
980 [ - + ]: 2 : if (!g_task_propagate_boolean (G_TASK (result), error)) {
981 : 0 : _secret_util_strip_remote_error (error);
982 : 0 : return FALSE;
983 : : }
984 : :
985 : 2 : return TRUE;
986 : : }
987 : :
988 : : /**
989 : : * secret_item_delete_sync:
990 : : * @self: an item
991 : : * @cancellable: (nullable): optional cancellation object
992 : : * @error: location to place an error on failure
993 : : *
994 : : * Delete this secret item.
995 : : *
996 : : * This method may block indefinitely and should not be used in user
997 : : * interface threads. The secret service may prompt the user.
998 : : * [method@Service.prompt] will be used to handle any prompts that show up.
999 : : *
1000 : : * Returns: whether the item was successfully deleted or not
1001 : : */
1002 : : gboolean
1003 : 1 : secret_item_delete_sync (SecretItem *self,
1004 : : GCancellable *cancellable,
1005 : : GError **error)
1006 : : {
1007 : : SecretSync *sync;
1008 : : gboolean ret;
1009 : :
1010 [ - + + - : 1 : g_return_val_if_fail (SECRET_IS_ITEM (self), FALSE);
+ - - + ]
1011 [ - + - - : 1 : g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- - - - -
- ]
1012 [ + - - + ]: 1 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1013 : :
1014 : 1 : sync = _secret_sync_new ();
1015 : 1 : g_main_context_push_thread_default (sync->context);
1016 : :
1017 : 1 : secret_item_delete (self, cancellable, _secret_sync_on_result, sync);
1018 : :
1019 : 1 : g_main_loop_run (sync->loop);
1020 : :
1021 : 1 : ret = secret_item_delete_finish (self, sync->result, error);
1022 : :
1023 : 1 : g_main_context_pop_thread_default (sync->context);
1024 : 1 : _secret_sync_free (sync);
1025 : :
1026 : 1 : return ret;
1027 : : }
1028 : :
1029 : : /**
1030 : : * secret_item_get_flags: (attributes org.gtk.Method.get_property=flags)
1031 : : * @self: the secret item proxy
1032 : : *
1033 : : * Get the flags representing what features of the #SecretItem proxy
1034 : : * have been initialized.
1035 : : *
1036 : : * Use [method@Item.load_secret] to initialize further features
1037 : : * and change the flags.
1038 : : *
1039 : : * Returns: the flags for features initialized
1040 : : */
1041 : : SecretItemFlags
1042 : 0 : secret_item_get_flags (SecretItem *self)
1043 : : {
1044 : 0 : SecretServiceFlags flags = 0;
1045 : :
1046 [ # # # # : 0 : g_return_val_if_fail (SECRET_IS_ITEM (self), SECRET_ITEM_NONE);
# # # # ]
1047 : :
1048 : 0 : g_mutex_lock (&self->pv->mutex);
1049 : :
1050 [ # # ]: 0 : if (self->pv->value)
1051 : 0 : flags |= SECRET_ITEM_LOAD_SECRET;
1052 : :
1053 : 0 : g_mutex_unlock (&self->pv->mutex);
1054 : :
1055 : 0 : return flags;
1056 : :
1057 : : }
1058 : :
1059 : : /**
1060 : : * secret_item_get_service: (attributes org.gtk.Method.get_property=service)
1061 : : * @self: an item
1062 : : *
1063 : : * Get the Secret Service object that this item was created with.
1064 : : *
1065 : : * Returns: (transfer none): the Secret Service object
1066 : : */
1067 : : SecretService *
1068 : 6 : secret_item_get_service (SecretItem *self)
1069 : : {
1070 [ - + + - : 6 : g_return_val_if_fail (SECRET_IS_ITEM (self), NULL);
+ - - + ]
1071 : 6 : return self->pv->service;
1072 : : }
1073 : :
1074 : :
1075 : : /**
1076 : : * secret_item_get_secret:
1077 : : * @self: an item
1078 : : *
1079 : : * Get the secret value of this item.
1080 : : *
1081 : : * If this item is locked or the secret has not yet been loaded then this will
1082 : : * return %NULL.
1083 : : *
1084 : : * To load the secret call the [method@Item.load_secret] method.
1085 : : *
1086 : : * Returns: (transfer full) (nullable): the secret value which should be
1087 : : * released with [method@Value.unref], or %NULL
1088 : : */
1089 : : SecretValue *
1090 : 34 : secret_item_get_secret (SecretItem *self)
1091 : : {
1092 : 34 : SecretValue *value = NULL;
1093 : :
1094 [ - + + - : 34 : g_return_val_if_fail (SECRET_IS_ITEM (self), NULL);
+ - - + ]
1095 : :
1096 : 34 : g_mutex_lock (&self->pv->mutex);
1097 : :
1098 [ + + ]: 34 : if (self->pv->value)
1099 : 12 : value = secret_value_ref (self->pv->value);
1100 : :
1101 : 34 : g_mutex_unlock (&self->pv->mutex);
1102 : :
1103 : 34 : return value;
1104 : : }
1105 : :
1106 : : static void
1107 : 3 : on_item_load_secret (GObject *source,
1108 : : GAsyncResult *result,
1109 : : gpointer user_data)
1110 : : {
1111 : 3 : GTask *task = G_TASK (user_data);
1112 : 3 : SecretItem *self = SECRET_ITEM (g_task_get_source_object (task));
1113 : : SecretSession *session;
1114 : 3 : GError *error = NULL;
1115 : : SecretValue *value;
1116 : : GVariant *retval;
1117 : : GVariant *child;
1118 : :
1119 : 3 : retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
1120 [ + - ]: 3 : if (error == NULL) {
1121 : 3 : child = g_variant_get_child_value (retval, 0);
1122 : 3 : g_variant_unref (retval);
1123 : :
1124 : 3 : session = _secret_service_get_session (self->pv->service);
1125 : 3 : value = _secret_session_decode_secret (session, child);
1126 : 3 : g_variant_unref (child);
1127 : :
1128 [ - + ]: 3 : if (value == NULL) {
1129 : 0 : g_set_error (&error, SECRET_ERROR, SECRET_ERROR_PROTOCOL,
1130 : : _("Received invalid secret from the secret storage"));
1131 : : } else {
1132 : 3 : _secret_item_set_cached_secret (self, value);
1133 : 3 : secret_value_unref (value);
1134 : : }
1135 : : }
1136 : :
1137 [ + - ]: 3 : if (error == NULL)
1138 : 3 : g_task_return_boolean (task, TRUE);
1139 : : else
1140 : 0 : g_task_return_error (task, g_steal_pointer (&error));
1141 : :
1142 [ + - ]: 3 : g_clear_object (&task);
1143 : 3 : }
1144 : :
1145 : : static void
1146 : 3 : on_load_ensure_session (GObject *source,
1147 : : GAsyncResult *result,
1148 : : gpointer user_data)
1149 : : {
1150 : 3 : GTask *task = G_TASK (user_data);
1151 : 3 : SecretItem *self = SECRET_ITEM (g_task_get_source_object (task));
1152 : 3 : GCancellable *cancellable = g_task_get_cancellable (task);
1153 : : const gchar *session_path;
1154 : 3 : GError *error = NULL;
1155 : :
1156 : 3 : secret_service_ensure_session_finish (self->pv->service, result, &error);
1157 [ - + ]: 3 : if (error != NULL) {
1158 : 0 : g_task_return_error (task, g_steal_pointer (&error));
1159 : :
1160 : : } else {
1161 : 3 : session_path = secret_service_get_session_dbus_path (self->pv->service);
1162 [ + - + - ]: 3 : g_assert (session_path != NULL && session_path[0] != '\0');
1163 : 3 : g_dbus_proxy_call (G_DBUS_PROXY (self), "GetSecret",
1164 : : g_variant_new ("(o)", session_path),
1165 : : G_DBUS_CALL_FLAGS_NONE, -1, cancellable,
1166 : : on_item_load_secret, g_steal_pointer (&task));
1167 : : }
1168 : :
1169 [ - + ]: 3 : g_clear_object (&task);
1170 : 3 : }
1171 : :
1172 : : /**
1173 : : * secret_item_load_secret:
1174 : : * @self: an item proxy
1175 : : * @cancellable: (nullable): optional cancellation object
1176 : : * @callback: called when the operation completes
1177 : : * @user_data: data to pass to the callback
1178 : : *
1179 : : * Load the secret value of this item.
1180 : : *
1181 : : * Each item has a single secret which might be a password or some
1182 : : * other secret binary value.
1183 : : *
1184 : : * This function will fail if the secret item is locked.
1185 : : *
1186 : : * This function returns immediately and completes asynchronously.
1187 : : */
1188 : : void
1189 : 3 : secret_item_load_secret (SecretItem *self,
1190 : : GCancellable *cancellable,
1191 : : GAsyncReadyCallback callback,
1192 : : gpointer user_data)
1193 : : {
1194 : : GTask *task;
1195 : :
1196 [ - + + - : 3 : g_return_if_fail (SECRET_IS_ITEM (self));
+ - - + ]
1197 [ - + - - : 3 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - -
- ]
1198 : :
1199 : 3 : task = g_task_new (self, cancellable, callback, user_data);
1200 [ + - ]: 3 : g_task_set_source_tag (task, secret_item_load_secret);
1201 : :
1202 : 3 : secret_service_ensure_session (self->pv->service, cancellable,
1203 : : on_load_ensure_session,
1204 : : g_steal_pointer (&task));
1205 : :
1206 [ - + ]: 3 : g_clear_object (&task);
1207 : : }
1208 : :
1209 : : /**
1210 : : * secret_item_load_secret_finish:
1211 : : * @self: an item proxy
1212 : : * @result: asynchronous result passed to callback
1213 : : * @error: location to place error on failure
1214 : : *
1215 : : * Complete asynchronous operation to load the secret value of this item.
1216 : : *
1217 : : * The newly loaded secret value can be accessed by calling
1218 : : * [method@Item.get_secret].
1219 : : *
1220 : : * Returns: whether the secret item successfully loaded or not
1221 : : */
1222 : : gboolean
1223 : 3 : secret_item_load_secret_finish (SecretItem *self,
1224 : : GAsyncResult *result,
1225 : : GError **error)
1226 : : {
1227 [ - + ]: 3 : g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
1228 : :
1229 [ - + ]: 3 : if (!g_task_propagate_boolean (G_TASK (result), error)) {
1230 : 0 : _secret_util_strip_remote_error (error);
1231 : 0 : return FALSE;
1232 : : }
1233 : :
1234 : 3 : return TRUE;
1235 : : }
1236 : :
1237 : : /**
1238 : : * secret_item_load_secret_sync:
1239 : : * @self: an item
1240 : : * @cancellable: (nullable): optional cancellation object
1241 : : * @error: location to place error on failure
1242 : : *
1243 : : * Load the secret value of this item.
1244 : : *
1245 : : * Each item has a single secret which might be a password or some
1246 : : * other secret binary value.
1247 : : *
1248 : : * This function may block indefinitely. Use the asynchronous version
1249 : : * in user interface threads.
1250 : : *
1251 : : * Returns: whether the secret item successfully loaded or not
1252 : : */
1253 : : gboolean
1254 : 2 : secret_item_load_secret_sync (SecretItem *self,
1255 : : GCancellable *cancellable,
1256 : : GError **error)
1257 : : {
1258 : : SecretSync *sync;
1259 : : gboolean result;
1260 : :
1261 [ - + + - : 2 : g_return_val_if_fail (SECRET_IS_ITEM (self), FALSE);
+ - - + ]
1262 [ - + - - : 2 : g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- - - - -
- ]
1263 [ + - - + ]: 2 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1264 : :
1265 : 2 : sync = _secret_sync_new ();
1266 : 2 : g_main_context_push_thread_default (sync->context);
1267 : :
1268 : 2 : secret_item_load_secret (self, cancellable, _secret_sync_on_result, sync);
1269 : :
1270 : 2 : g_main_loop_run (sync->loop);
1271 : :
1272 : 2 : result = secret_item_load_secret_finish (self, sync->result, error);
1273 : :
1274 : 2 : g_main_context_pop_thread_default (sync->context);
1275 : 2 : _secret_sync_free (sync);
1276 : :
1277 : 2 : return result;
1278 : : }
1279 : :
1280 : : static void
1281 : 0 : on_retrieve_load (GObject *source_object,
1282 : : GAsyncResult *res,
1283 : : gpointer user_data)
1284 : : {
1285 : 0 : SecretItem *self = SECRET_ITEM (source_object);
1286 : 0 : GTask *task = G_TASK (user_data);
1287 : 0 : GError *error = NULL;
1288 : :
1289 [ # # ]: 0 : if (secret_item_load_secret_finish (self, res, &error)) {
1290 : 0 : g_task_return_pointer (task,
1291 : 0 : secret_item_get_secret (self),
1292 : : secret_value_unref);
1293 : 0 : g_object_unref (task);
1294 : : } else {
1295 : 0 : g_task_return_error (task, error);
1296 : 0 : g_object_unref (task);
1297 : : }
1298 : 0 : }
1299 : :
1300 : : static void
1301 : 0 : secret_item_retrieve_secret (SecretRetrievable *self,
1302 : : GCancellable *cancellable,
1303 : : GAsyncReadyCallback callback,
1304 : : gpointer user_data)
1305 : : {
1306 : 0 : GTask *task = g_task_new (self, cancellable, callback, user_data);
1307 : :
1308 : 0 : secret_item_load_secret (SECRET_ITEM (self), cancellable, on_retrieve_load, task);
1309 : 0 : }
1310 : :
1311 : : static SecretValue *
1312 : 0 : secret_item_retrieve_secret_finish (SecretRetrievable *self,
1313 : : GAsyncResult *result,
1314 : : GError **error)
1315 : : {
1316 [ # # ]: 0 : g_return_val_if_fail (g_task_is_valid (result, self), NULL);
1317 : :
1318 : 0 : return g_task_propagate_pointer (G_TASK (result), error);
1319 : : }
1320 : :
1321 : : static void
1322 : 6 : secret_item_retrievable_iface (SecretRetrievableInterface *iface)
1323 : : {
1324 : 6 : secret_item_retrievable_parent_iface = g_type_interface_peek_parent (iface);
1325 : 6 : iface->retrieve_secret = secret_item_retrieve_secret;
1326 : 6 : iface->retrieve_secret_finish = secret_item_retrieve_secret_finish;
1327 : 6 : }
1328 : :
1329 : : typedef struct {
1330 : : SecretService *service;
1331 : : GVariant *in;
1332 : : GHashTable *items;
1333 : : } LoadsClosure;
1334 : :
1335 : : static void
1336 : 6 : loads_closure_free (gpointer data)
1337 : : {
1338 : 6 : LoadsClosure *loads = data;
1339 [ + - ]: 6 : if (loads->in)
1340 : 6 : g_variant_unref (loads->in);
1341 [ + - ]: 6 : if (loads->service)
1342 : 6 : g_object_unref (loads->service);
1343 : 6 : g_hash_table_destroy (loads->items);
1344 : 6 : g_free (loads);
1345 : 6 : }
1346 : :
1347 : : static void
1348 : 6 : on_get_secrets_complete (GObject *source,
1349 : : GAsyncResult *result,
1350 : : gpointer user_data)
1351 : : {
1352 : 6 : GTask *task = G_TASK (user_data);
1353 : 6 : LoadsClosure *loads = g_task_get_task_data (task);
1354 : : GHashTable *with_paths;
1355 : 6 : GError *error = NULL;
1356 : : GHashTableIter iter;
1357 : : const gchar *path;
1358 : : SecretValue *value;
1359 : : SecretItem *item;
1360 : : GVariant *retval;
1361 : :
1362 : 6 : retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
1363 [ + - ]: 6 : if (retval != NULL) {
1364 : 6 : with_paths = _secret_service_decode_get_secrets_all (loads->service, retval);
1365 [ - + ]: 6 : g_return_if_fail (with_paths != NULL);
1366 : :
1367 : 6 : g_hash_table_iter_init (&iter, with_paths);
1368 [ + + ]: 20 : while (g_hash_table_iter_next (&iter, (gpointer *)&path, (gpointer *)&value)) {
1369 : 8 : item = g_hash_table_lookup (loads->items, path);
1370 [ + - ]: 8 : if (item != NULL)
1371 : 8 : _secret_item_set_cached_secret (item, value);
1372 : : }
1373 : :
1374 : 6 : g_hash_table_unref (with_paths);
1375 : 6 : g_variant_unref (retval);
1376 : : }
1377 : :
1378 [ - + ]: 6 : if (error != NULL)
1379 : 0 : g_task_return_error (task, g_steal_pointer (&error));
1380 : : else
1381 : 6 : g_task_return_boolean (task, TRUE);
1382 : :
1383 [ + - ]: 6 : g_clear_object (&task);
1384 : : }
1385 : :
1386 : : static void
1387 : 6 : on_loads_secrets_session (GObject *source,
1388 : : GAsyncResult *result,
1389 : : gpointer user_data)
1390 : : {
1391 : 6 : GTask *task = G_TASK (user_data);
1392 : 6 : LoadsClosure *loads = g_task_get_task_data (task);
1393 : 6 : GError *error = NULL;
1394 : : const gchar *session;
1395 : :
1396 : 6 : secret_service_ensure_session_finish (SECRET_SERVICE (source), result, &error);
1397 [ - + ]: 6 : if (error != NULL) {
1398 : 0 : g_task_return_error (task, g_steal_pointer (&error));
1399 [ # # ]: 0 : g_clear_object (&task);
1400 : 0 : return;
1401 : : }
1402 : :
1403 : 6 : session = secret_service_get_session_dbus_path (SECRET_SERVICE (source));
1404 : 6 : g_dbus_proxy_call (G_DBUS_PROXY (source), "GetSecrets",
1405 : : g_variant_new ("(@aoo)", loads->in, session),
1406 : : G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
1407 : : g_task_get_cancellable (task),
1408 : : on_get_secrets_complete,
1409 : : g_object_ref (task));
1410 : :
1411 [ + - ]: 6 : g_clear_object (&task);
1412 : : }
1413 : :
1414 : : /**
1415 : : * secret_item_load_secrets:
1416 : : * @items: (element-type Secret.Item): the items to retrieve secrets for
1417 : : * @cancellable: (nullable): optional cancellation object
1418 : : * @callback: called when the operation completes
1419 : : * @user_data: data to pass to the callback
1420 : : *
1421 : : * Load the secret values for a secret item stored in the service.
1422 : : *
1423 : : * The @items must all have the same [property@Item:service] property.
1424 : : *
1425 : : * This function returns immediately and completes asynchronously.
1426 : : */
1427 : : void
1428 : 6 : secret_item_load_secrets (GList *items,
1429 : : GCancellable *cancellable,
1430 : : GAsyncReadyCallback callback,
1431 : : gpointer user_data)
1432 : : {
1433 : : GTask *task;
1434 : : LoadsClosure *loads;
1435 : : GPtrArray *paths;
1436 : : const gchar *path;
1437 : : GList *l;
1438 : :
1439 [ - + - - : 6 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - -
- ]
1440 : :
1441 [ + - + + ]: 18 : for (l = items; l != NULL; l = g_list_next (l))
1442 [ - + + - : 12 : g_return_if_fail (SECRET_IS_ITEM (l->data));
+ - - + ]
1443 : :
1444 : 6 : task = g_task_new (NULL, cancellable, callback, user_data);
1445 [ + - ]: 6 : g_task_set_source_tag (task, secret_item_load_secrets);
1446 : 6 : loads = g_new0 (LoadsClosure, 1);
1447 : 6 : loads->items = g_hash_table_new_full (g_str_hash, g_str_equal,
1448 : : g_free, g_object_unref);
1449 : :
1450 : 6 : paths = g_ptr_array_new ();
1451 [ + - + + ]: 18 : for (l = items; l != NULL; l = g_list_next (l)) {
1452 [ + + ]: 12 : if (secret_item_get_locked (l->data))
1453 : 4 : continue;
1454 : :
1455 [ + + ]: 8 : if (loads->service == NULL) {
1456 : 6 : loads->service = secret_item_get_service (l->data);
1457 [ + - ]: 6 : if (loads->service)
1458 : 6 : g_object_ref (loads->service);
1459 : : }
1460 : :
1461 : 8 : path = g_dbus_proxy_get_object_path (l->data);
1462 : 16 : g_hash_table_insert (loads->items, g_strdup (path), g_object_ref (l->data));
1463 : 8 : g_ptr_array_add (paths, (gpointer)path);
1464 : : }
1465 : :
1466 : 6 : loads->in = g_variant_new_objv ((const gchar * const *)paths->pdata, paths->len);
1467 : 6 : g_variant_ref_sink (loads->in);
1468 : :
1469 : 6 : g_ptr_array_free (paths, TRUE);
1470 : 6 : g_task_set_task_data (task, loads, loads_closure_free);
1471 : :
1472 [ + - ]: 6 : if (loads->service) {
1473 : 6 : secret_service_ensure_session (loads->service, cancellable,
1474 : : on_loads_secrets_session,
1475 : : g_object_ref (task));
1476 : : } else {
1477 : 0 : g_task_return_boolean (task, TRUE);
1478 : : }
1479 : :
1480 [ + - ]: 6 : g_clear_object (&task);
1481 : : }
1482 : :
1483 : : /**
1484 : : * secret_item_load_secrets_finish:
1485 : : * @result: asynchronous result passed to callback
1486 : : * @error: location to place an error on failure
1487 : : *
1488 : : * Complete asynchronous operation to load the secret values for
1489 : : * secret items stored in the service.
1490 : : *
1491 : : * Items that are locked will not have their secrets loaded.
1492 : : *
1493 : : * Returns: whether the operation succeeded or not
1494 : : */
1495 : : gboolean
1496 : 6 : secret_item_load_secrets_finish (GAsyncResult *result,
1497 : : GError **error)
1498 : : {
1499 [ - + ]: 6 : g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE);
1500 : :
1501 [ - + ]: 6 : if (!g_task_propagate_boolean (G_TASK (result), error)) {
1502 : 0 : _secret_util_strip_remote_error (error);
1503 : 0 : return FALSE;
1504 : : }
1505 : :
1506 : 6 : return TRUE;
1507 : : }
1508 : :
1509 : : /**
1510 : : * secret_item_load_secrets_sync:
1511 : : * @items: (element-type Secret.Item): the items to retrieve secrets for
1512 : : * @cancellable: (nullable): optional cancellation object
1513 : : * @error: location to place an error on failure
1514 : : *
1515 : : * Load the secret values for a secret item stored in the service.
1516 : : *
1517 : : * The @items must all have the same [property@Item:service] property.
1518 : : *
1519 : : * This method may block indefinitely and should not be used in user interface
1520 : : * threads.
1521 : : *
1522 : : * Items that are locked will not have their secrets loaded.
1523 : : *
1524 : : * Returns: whether the operation succeeded or not
1525 : : */
1526 : : gboolean
1527 : 3 : secret_item_load_secrets_sync (GList *items,
1528 : : GCancellable *cancellable,
1529 : : GError **error)
1530 : : {
1531 : : SecretSync *sync;
1532 : : gboolean ret;
1533 : : GList *l;
1534 : :
1535 [ + - + + ]: 9 : for (l = items; l != NULL; l = g_list_next (l))
1536 [ - + + - : 6 : g_return_val_if_fail (SECRET_IS_ITEM (l->data), FALSE);
+ - - + ]
1537 : :
1538 [ - + - - : 3 : g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- - - - -
- ]
1539 [ + + - + ]: 3 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1540 : :
1541 : 3 : sync = _secret_sync_new ();
1542 : 3 : g_main_context_push_thread_default (sync->context);
1543 : :
1544 : 3 : secret_item_load_secrets (items, cancellable,
1545 : : _secret_sync_on_result, sync);
1546 : :
1547 : 3 : g_main_loop_run (sync->loop);
1548 : :
1549 : 3 : ret = secret_item_load_secrets_finish (sync->result, error);
1550 : :
1551 : 3 : g_main_context_pop_thread_default (sync->context);
1552 : 3 : _secret_sync_free (sync);
1553 : :
1554 : 3 : return ret;
1555 : : }
1556 : :
1557 : : static void
1558 : 1 : on_item_set_secret (GObject *source,
1559 : : GAsyncResult *result,
1560 : : gpointer user_data)
1561 : : {
1562 : 1 : GTask *task = G_TASK (user_data);
1563 : 1 : SecretItem *self = SECRET_ITEM (g_task_get_source_object (task));
1564 : 1 : SecretValue *value = g_task_get_task_data (task);
1565 : 1 : GError *error = NULL;
1566 : : GVariant *retval;
1567 : :
1568 : 1 : retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
1569 : :
1570 [ - + ]: 1 : if (error) {
1571 : 0 : g_task_return_error (task, g_steal_pointer (&error));
1572 [ # # ]: 0 : g_clear_object (&task);
1573 : 0 : return;
1574 : : }
1575 : :
1576 : 1 : _secret_item_set_cached_secret (self, value);
1577 [ + - ]: 1 : g_clear_pointer (&retval, g_variant_unref);
1578 : :
1579 : 1 : g_task_return_boolean (task, TRUE);
1580 [ + - ]: 1 : g_clear_object (&task);
1581 : : }
1582 : :
1583 : : static void
1584 : 1 : on_set_ensure_session (GObject *source,
1585 : : GAsyncResult *result,
1586 : : gpointer user_data)
1587 : : {
1588 : 1 : GTask *task = G_TASK (user_data);
1589 : 1 : SecretItem *self = SECRET_ITEM (g_task_get_source_object (task));
1590 : 1 : SecretValue *value = g_task_get_task_data (task);
1591 : : SecretSession *session;
1592 : : GVariant *encoded;
1593 : 1 : GError *error = NULL;
1594 : :
1595 : 1 : secret_service_ensure_session_finish (self->pv->service, result, &error);
1596 [ - + ]: 1 : if (error != NULL) {
1597 : 0 : g_task_return_error (task, g_steal_pointer (&error));
1598 [ # # ]: 0 : g_clear_object (&task);
1599 : 0 : return;
1600 : : }
1601 : :
1602 : 1 : session = _secret_service_get_session (self->pv->service);
1603 : 1 : encoded = _secret_session_encode_secret (session, value);
1604 : 1 : g_dbus_proxy_call (G_DBUS_PROXY (self), "SetSecret",
1605 : : g_variant_new ("(@(oayays))", encoded),
1606 : : G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
1607 : : g_task_get_cancellable (task),
1608 : : on_item_set_secret, g_object_ref (task));
1609 : :
1610 [ + - ]: 1 : g_clear_object (&task);
1611 : : }
1612 : :
1613 : : /**
1614 : : * secret_item_set_secret:
1615 : : * @self: an item
1616 : : * @value: a new secret value
1617 : : * @cancellable: (nullable): optional cancellation object
1618 : : * @callback: called when the operation completes
1619 : : * @user_data: data to pass to the callback
1620 : : *
1621 : : * Set the secret value of this item.
1622 : : *
1623 : : * Each item has a single secret which might be a password or some
1624 : : * other secret binary value.
1625 : : *
1626 : : * This function returns immediately and completes asynchronously.
1627 : : */
1628 : : void
1629 : 1 : secret_item_set_secret (SecretItem *self,
1630 : : SecretValue *value,
1631 : : GCancellable *cancellable,
1632 : : GAsyncReadyCallback callback,
1633 : : gpointer user_data)
1634 : : {
1635 : 1 : GTask *task = NULL;
1636 : :
1637 [ - + + - : 1 : g_return_if_fail (SECRET_IS_ITEM (self));
+ - - + ]
1638 [ - + ]: 1 : g_return_if_fail (value != NULL);
1639 [ - + - - : 1 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - -
- ]
1640 : :
1641 : 1 : task = g_task_new (self, cancellable, callback, user_data);
1642 [ + - ]: 1 : g_task_set_source_tag (task, secret_item_set_secret);
1643 : 1 : g_task_set_task_data (task, secret_value_ref (value), secret_value_unref);
1644 : :
1645 : 1 : secret_service_ensure_session (self->pv->service, cancellable,
1646 : : on_set_ensure_session,
1647 : : g_steal_pointer (&task));
1648 : :
1649 [ - + ]: 1 : g_clear_object (&task);
1650 : : }
1651 : :
1652 : : /**
1653 : : * secret_item_set_secret_finish:
1654 : : * @self: an item
1655 : : * @result: asynchronous result passed to callback
1656 : : * @error: location to place error on failure
1657 : : *
1658 : : * Complete asynchronous operation to set the secret value of this item.
1659 : : *
1660 : : * Returns: whether the change was successful or not
1661 : : */
1662 : : gboolean
1663 : 1 : secret_item_set_secret_finish (SecretItem *self,
1664 : : GAsyncResult *result,
1665 : : GError **error)
1666 : : {
1667 [ - + ]: 1 : g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
1668 : :
1669 [ - + ]: 1 : if (!g_task_propagate_boolean (G_TASK (result), error)) {
1670 : 0 : _secret_util_strip_remote_error (error);
1671 : 0 : return FALSE;
1672 : : }
1673 : :
1674 : 1 : return TRUE;
1675 : : }
1676 : :
1677 : : /**
1678 : : * secret_item_set_secret_sync:
1679 : : * @self: an item
1680 : : * @value: a new secret value
1681 : : * @cancellable: (nullable): optional cancellation object
1682 : : * @error: location to place error on failure
1683 : : *
1684 : : * Set the secret value of this item.
1685 : : *
1686 : : * Each item has a single secret which might be a password or some
1687 : : * other secret binary value.
1688 : : *
1689 : : * This function may block indefinitely. Use the asynchronous version
1690 : : * in user interface threads.
1691 : : *
1692 : : * Returns: whether the change was successful or not
1693 : : */
1694 : : gboolean
1695 : 1 : secret_item_set_secret_sync (SecretItem *self,
1696 : : SecretValue *value,
1697 : : GCancellable *cancellable,
1698 : : GError **error)
1699 : : {
1700 : : SecretSync *sync;
1701 : : gboolean ret;
1702 : :
1703 [ - + + - : 1 : g_return_val_if_fail (SECRET_IS_ITEM (self), FALSE);
+ - - + ]
1704 [ - + - - : 1 : g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
- - - - -
- ]
1705 [ + - - + ]: 1 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1706 : :
1707 : 1 : sync = _secret_sync_new ();
1708 : 1 : g_main_context_push_thread_default (sync->context);
1709 : :
1710 : 1 : secret_item_set_secret (self, value, cancellable, _secret_sync_on_result, sync);
1711 : :
1712 : 1 : g_main_loop_run (sync->loop);
1713 : :
1714 : 1 : ret = secret_item_set_secret_finish (self, sync->result, error);
1715 : :
1716 : 1 : g_main_context_pop_thread_default (sync->context);
1717 : 1 : _secret_sync_free (sync);
1718 : :
1719 : 1 : return ret;
1720 : : }
1721 : :
1722 : : /**
1723 : : * secret_item_get_schema_name:
1724 : : * @self: an item
1725 : : *
1726 : : * Gets the name of the schema that this item was stored with. This is also
1727 : : * available at the `xdg:schema` attribute.
1728 : : *
1729 : : * Returns: (nullable) (transfer full): the schema name
1730 : : */
1731 : : gchar *
1732 : 4 : secret_item_get_schema_name (SecretItem *self)
1733 : : {
1734 : 4 : gchar *schema_name = NULL;
1735 : : GVariant *variant;
1736 : :
1737 [ - + + - : 4 : g_return_val_if_fail (SECRET_IS_ITEM (self), NULL);
+ - - + ]
1738 : :
1739 : 4 : variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Attributes");
1740 [ - + ]: 4 : g_return_val_if_fail (variant != NULL, NULL);
1741 : :
1742 : 4 : g_variant_lookup (variant, "xdg:schema", "s", &schema_name);
1743 : 4 : g_variant_unref (variant);
1744 : :
1745 : 4 : return schema_name;
1746 : : }
1747 : :
1748 : : /**
1749 : : * secret_item_get_attributes:
1750 : : * @self: an item
1751 : : *
1752 : : * Set the attributes of this item.
1753 : : *
1754 : : * The @attributes are a mapping of string keys to string values.
1755 : : * Attributes are used to search for items. Attributes are not stored
1756 : : * or transferred securely by the secret service.
1757 : : *
1758 : : * Do not modify the attributes returned by this method. Use
1759 : : * [method@Item.set_attributes] instead.
1760 : : *
1761 : : * Returns: (transfer full) (element-type utf8 utf8): a new reference
1762 : : * to the attributes, which should not be modified, and
1763 : : * released with [func@GLib.HashTable.unref]
1764 : : */
1765 : : GHashTable *
1766 : 8 : secret_item_get_attributes (SecretItem *self)
1767 : : {
1768 : : GHashTable *attributes;
1769 : : GVariant *variant;
1770 : :
1771 [ - + + - : 8 : g_return_val_if_fail (SECRET_IS_ITEM (self), NULL);
+ - - + ]
1772 : :
1773 : 8 : variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Attributes");
1774 [ - + ]: 8 : g_return_val_if_fail (variant != NULL, NULL);
1775 : :
1776 : 8 : attributes = _secret_attributes_for_variant (variant);
1777 : 8 : g_variant_unref (variant);
1778 : :
1779 : 8 : return attributes;
1780 : : }
1781 : :
1782 : : /**
1783 : : * secret_item_set_attributes:
1784 : : * @self: an item
1785 : : * @schema: (nullable): the schema for the attributes
1786 : : * @attributes: (element-type utf8 utf8): a new set of attributes
1787 : : * @cancellable: (nullable): optional cancellation object
1788 : : * @callback: called when the asynchronous operation completes
1789 : : * @user_data: data to pass to the callback
1790 : : *
1791 : : * Set the attributes of this item.
1792 : : *
1793 : : * The @attributes are a mapping of string keys to string values.
1794 : : * Attributes are used to search for items. Attributes are not stored
1795 : : * or transferred securely by the secret service.
1796 : : *
1797 : : * This function returns immediately and completes asynchronously.
1798 : : */
1799 : : void
1800 : 2 : secret_item_set_attributes (SecretItem *self,
1801 : : const SecretSchema *schema,
1802 : : GHashTable *attributes,
1803 : : GCancellable *cancellable,
1804 : : GAsyncReadyCallback callback,
1805 : : gpointer user_data)
1806 : : {
1807 : 2 : const gchar *schema_name = NULL;
1808 : :
1809 [ - + + - : 2 : g_return_if_fail (SECRET_IS_ITEM (self));
+ - - + ]
1810 [ - + ]: 2 : g_return_if_fail (attributes != NULL);
1811 : :
1812 [ + + ]: 2 : if (schema != NULL) {
1813 [ - + ]: 1 : if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
1814 : 0 : return; /* Warnings raised already */
1815 : 1 : schema_name = schema->name;
1816 : : }
1817 : :
1818 : 2 : _secret_util_set_property (G_DBUS_PROXY (self), "Attributes",
1819 : : _secret_attributes_to_variant (attributes, schema_name),
1820 : : secret_item_set_attributes, cancellable,
1821 : : callback, user_data);
1822 : : }
1823 : :
1824 : : /**
1825 : : * secret_item_set_attributes_finish:
1826 : : * @self: an item
1827 : : * @result: asynchronous result passed to the callback
1828 : : * @error: location to place error on failure
1829 : : *
1830 : : * Complete operation to set the attributes of this item.
1831 : : *
1832 : : * Returns: whether the change was successful or not
1833 : : */
1834 : : gboolean
1835 : 2 : secret_item_set_attributes_finish (SecretItem *self,
1836 : : GAsyncResult *result,
1837 : : GError **error)
1838 : : {
1839 [ - + + - : 2 : g_return_val_if_fail (SECRET_IS_ITEM (self), FALSE);
+ - - + ]
1840 : :
1841 : 2 : return _secret_util_set_property_finish (G_DBUS_PROXY (self),
1842 : : secret_item_set_attributes,
1843 : : result, error);
1844 : : }
1845 : :
1846 : : /**
1847 : : * secret_item_set_attributes_sync:
1848 : : * @self: an item
1849 : : * @schema: (nullable): the schema for the attributes
1850 : : * @attributes: (element-type utf8 utf8): a new set of attributes
1851 : : * @cancellable: (nullable): optional cancellation object
1852 : : * @error: location to place error on failure
1853 : : *
1854 : : * Set the attributes of this item.
1855 : : *
1856 : : * The @attributes are a mapping of string keys to string values.
1857 : : * Attributes are used to search for items. Attributes are not stored
1858 : : * or transferred securely by the secret service.
1859 : : *
1860 : : * This function may block indefinitely. Use the asynchronous version
1861 : : * in user interface threads.
1862 : : *
1863 : : * Returns: whether the change was successful or not
1864 : : */
1865 : : gboolean
1866 : 1 : secret_item_set_attributes_sync (SecretItem *self,
1867 : : const SecretSchema *schema,
1868 : : GHashTable *attributes,
1869 : : GCancellable *cancellable,
1870 : : GError **error)
1871 : : {
1872 : 1 : const gchar *schema_name = NULL;
1873 : :
1874 [ - + + - : 1 : g_return_val_if_fail (SECRET_IS_ITEM (self), FALSE);
+ - - + ]
1875 [ - + ]: 1 : g_return_val_if_fail (attributes != NULL, FALSE);
1876 : :
1877 [ + - ]: 1 : if (schema != NULL) {
1878 [ - + ]: 1 : if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
1879 : 0 : return FALSE; /* Warnings raised already */
1880 : 1 : schema_name = schema->name;
1881 : : }
1882 : :
1883 : 1 : return _secret_util_set_property_sync (G_DBUS_PROXY (self), "Attributes",
1884 : : _secret_attributes_to_variant (attributes, schema_name),
1885 : : cancellable, error);
1886 : : }
1887 : :
1888 : : /**
1889 : : * secret_item_get_label:
1890 : : * @self: an item
1891 : : *
1892 : : * Get the label of this item.
1893 : : *
1894 : : * Returns: (transfer full): the label, which should be freed with [func@GLib.free]
1895 : : */
1896 : : gchar *
1897 : 10 : secret_item_get_label (SecretItem *self)
1898 : : {
1899 : : GVariant *variant;
1900 : : gchar *label;
1901 : :
1902 [ - + + - : 10 : g_return_val_if_fail (SECRET_IS_ITEM (self), NULL);
+ - - + ]
1903 : :
1904 : 10 : variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Label");
1905 [ - + ]: 10 : g_return_val_if_fail (variant != NULL, NULL);
1906 : :
1907 : 10 : label = g_variant_dup_string (variant, NULL);
1908 : 10 : g_variant_unref (variant);
1909 : :
1910 : 10 : return label;
1911 : : }
1912 : :
1913 : : /**
1914 : : * secret_item_set_label:
1915 : : * @self: an item
1916 : : * @label: a new label
1917 : : * @cancellable: (nullable): optional cancellation object
1918 : : * @callback: called when the operation completes
1919 : : * @user_data: data to pass to the callback
1920 : : *
1921 : : * Set the label of this item.
1922 : : *
1923 : : * This function returns immediately and completes asynchronously.
1924 : : */
1925 : : void
1926 : 2 : secret_item_set_label (SecretItem *self,
1927 : : const gchar *label,
1928 : : GCancellable *cancellable,
1929 : : GAsyncReadyCallback callback,
1930 : : gpointer user_data)
1931 : : {
1932 [ - + + - : 2 : g_return_if_fail (SECRET_IS_ITEM (self));
+ - - + ]
1933 [ - + ]: 2 : g_return_if_fail (label != NULL);
1934 : :
1935 : 2 : _secret_util_set_property (G_DBUS_PROXY (self), "Label",
1936 : : g_variant_new_string (label),
1937 : : secret_item_set_label,
1938 : : cancellable, callback, user_data);
1939 : : }
1940 : :
1941 : : /**
1942 : : * secret_item_set_label_finish:
1943 : : * @self: an item
1944 : : * @result: asynchronous result passed to callback
1945 : : * @error: location to place error on failure
1946 : : *
1947 : : * Complete asynchronous operation to set the label of this collection.
1948 : : *
1949 : : * Returns: whether the change was successful or not
1950 : : */
1951 : : gboolean
1952 : 2 : secret_item_set_label_finish (SecretItem *self,
1953 : : GAsyncResult *result,
1954 : : GError **error)
1955 : : {
1956 [ - + + - : 2 : g_return_val_if_fail (SECRET_IS_ITEM (self), FALSE);
+ - - + ]
1957 : :
1958 : 2 : return _secret_util_set_property_finish (G_DBUS_PROXY (self),
1959 : : secret_item_set_label,
1960 : : result, error);
1961 : : }
1962 : :
1963 : : /**
1964 : : * secret_item_set_label_sync:
1965 : : * @self: an item
1966 : : * @label: a new label
1967 : : * @cancellable: (nullable): optional cancellation object
1968 : : * @error: location to place error on failure
1969 : : *
1970 : : * Set the label of this item.
1971 : : *
1972 : : * This function may block indefinitely. Use the asynchronous version
1973 : : * in user interface threads.
1974 : : *
1975 : : * Returns: whether the change was successful or not
1976 : : */
1977 : : gboolean
1978 : 1 : secret_item_set_label_sync (SecretItem *self,
1979 : : const gchar *label,
1980 : : GCancellable *cancellable,
1981 : : GError **error)
1982 : : {
1983 [ - + + - : 1 : g_return_val_if_fail (SECRET_IS_ITEM (self), FALSE);
+ - - + ]
1984 [ - + ]: 1 : g_return_val_if_fail (label != NULL, FALSE);
1985 : :
1986 : 1 : return _secret_util_set_property_sync (G_DBUS_PROXY (self), "Label",
1987 : : g_variant_new_string (label),
1988 : : cancellable, error);
1989 : : }
1990 : :
1991 : : /**
1992 : : * secret_item_get_locked:
1993 : : * @self: an item
1994 : : *
1995 : : * Get whether the item is locked or not.
1996 : : *
1997 : : * Depending on the secret service an item may not be able to be locked
1998 : : * independently from the collection that it is in.
1999 : : *
2000 : : * Returns: whether the item is locked or not
2001 : : */
2002 : : gboolean
2003 : 32 : secret_item_get_locked (SecretItem *self)
2004 : : {
2005 : : GVariant *variant;
2006 : : gboolean locked;
2007 : :
2008 [ - + + - : 32 : g_return_val_if_fail (SECRET_IS_ITEM (self), TRUE);
+ - - + ]
2009 : :
2010 : 32 : variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Locked");
2011 [ - + ]: 32 : g_return_val_if_fail (variant != NULL, TRUE);
2012 : :
2013 : 32 : locked = g_variant_get_boolean (variant);
2014 : 32 : g_variant_unref (variant);
2015 : :
2016 : 32 : return locked;
2017 : : }
2018 : :
2019 : : /**
2020 : : * secret_item_get_created:
2021 : : * @self: an item
2022 : : *
2023 : : * Get the created date and time of the item.
2024 : : *
2025 : : * The return value is the number of seconds since the unix epoch, January 1st
2026 : : * 1970.
2027 : : *
2028 : : * Returns: the created date and time
2029 : : */
2030 : : guint64
2031 : 2 : secret_item_get_created (SecretItem *self)
2032 : : {
2033 : : GVariant *variant;
2034 : : guint64 created;
2035 : :
2036 [ - + + - : 2 : g_return_val_if_fail (SECRET_IS_ITEM (self), TRUE);
+ - - + ]
2037 : :
2038 : 2 : variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Created");
2039 [ - + ]: 2 : g_return_val_if_fail (variant != NULL, 0);
2040 : :
2041 : 2 : created = g_variant_get_uint64 (variant);
2042 : 2 : g_variant_unref (variant);
2043 : :
2044 : 2 : return created;
2045 : : }
2046 : :
2047 : : /**
2048 : : * secret_item_get_modified:
2049 : : * @self: an item
2050 : : *
2051 : : * Get the modified date and time of the item.
2052 : : *
2053 : : * The return value is the number of seconds since the unix epoch, January 1st
2054 : : * 1970.
2055 : : *
2056 : : * Returns: the modified date and time
2057 : : */
2058 : : guint64
2059 : 2 : secret_item_get_modified (SecretItem *self)
2060 : : {
2061 : : GVariant *variant;
2062 : : guint64 modified;
2063 : :
2064 [ - + + - : 2 : g_return_val_if_fail (SECRET_IS_ITEM (self), TRUE);
+ - - + ]
2065 : :
2066 : 2 : variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (self), "Modified");
2067 [ - + ]: 2 : g_return_val_if_fail (variant != NULL, 0);
2068 : :
2069 : 2 : modified = g_variant_get_uint64 (variant);
2070 : 2 : g_variant_unref (variant);
2071 : :
2072 : 2 : return modified;
2073 : : }
|