peer to peer dbus support added
[platform/upstream/libgsignon-glib.git] / libsignon-glib / signon-identity.c
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of libsignon-glib
5  *
6  * Copyright (C) 2009-2010 Nokia Corporation.
7  * Copyright (C) 2012 Canonical Ltd.
8  * Copyright (C) 2012-2013 Intel Corporation.
9  *
10  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
11  * Contact: Jussi Laako <jussi.laako@linux.intel.com>
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public License
15  * version 2.1 as published by the Free Software Foundation.
16  *
17  * This library is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25  * 02110-1301 USA
26  */
27
28 /**
29  * SECTION:signon-identity
30  * @title: SignonIdentity
31  * @short_description: Client side presentation of a credential.
32  *
33  * The #SignonIdentity represents a database entry for a single identity.
34  */
35
36 #include "signon-identity.h"
37 #include "signon-auth-session.h"
38 #include "signon-internals.h"
39 #include "signon-dbus-queue.h"
40 #include "signon-utils.h"
41 #include "signon-errors.h"
42 #include "sso-auth-service.h"
43 #include "sso-identity-gen.h"
44
45 G_DEFINE_TYPE (SignonIdentity, signon_identity, G_TYPE_OBJECT);
46
47 enum
48 {
49     PROP_0,
50     PROP_ID,
51     PROP_APPCTX
52 };
53
54 typedef enum {
55     NOT_REGISTERED,
56     PENDING_REGISTRATION,
57     REGISTERED,
58 } IdentityRegistrationState;
59
60 typedef enum  {
61     DATA_UPDATED = 0,
62     IDENTITY_REMOVED,
63     IDENTITY_SIGNED_OUT
64 } RemoteIdentityState;
65
66 struct _SignonIdentityPrivate
67 {
68     SsoIdentity *proxy;
69     SsoAuthService *auth_service_proxy;
70     GCancellable *cancellable;
71
72     SignonIdentityInfo *identity_info;
73
74     GSList *sessions;
75     IdentityRegistrationState registration_state;
76
77     gboolean removed;
78     gboolean signed_out;
79     gboolean updated;
80
81     guint id;
82     gchar *app_ctx;
83
84     guint signal_info_updated;
85     guint signal_unregistered;
86 };
87
88 enum {
89     SIGNEDOUT_SIGNAL,
90     LAST_SIGNAL
91 };
92
93 static guint signals[LAST_SIGNAL];
94
95 #define SIGNON_IDENTITY_PRIV(obj) (SIGNON_IDENTITY(obj)->priv)
96
97 typedef struct _IdentityStoreCredentialsCbData
98 {
99     SignonIdentity *self;
100     SignonIdentityStoreCredentialsCb cb;
101     gpointer user_data;
102 } IdentityStoreCredentialsCbData;
103
104 typedef struct _IdentityStoreCredentialsData
105 {
106     GVariant *info_variant;
107     gpointer cb_data;
108 } IdentityStoreCredentialsData;
109
110 typedef enum {
111     SIGNON_VERIFY_USER,
112     SIGNON_VERIFY_SECRET,
113     SIGNON_INFO,
114     SIGNON_REMOVE,
115     SIGNON_SIGNOUT
116 } IdentityOperation;
117
118 typedef struct _IdentitySessionCbData
119 {
120     SignonIdentity *self;
121     SignonAuthSession *session;
122     SignonIdentitySessionReadyCb cb;
123 } IdentitySessionCbData;
124
125 typedef struct _IdentitySessionData
126 {
127     const gchar *method;
128     gpointer cb_data;
129 } IdentitySessionData;
130
131 typedef struct _IdentityVerifyCbData
132 {
133     SignonIdentity *self;
134     SignonIdentityVerifyCb cb;
135     gpointer user_data;
136 } IdentityVerifyCbData;
137
138 typedef struct _IdentityVerifyData
139 {
140     gchar *data_to_send;
141     GHashTable *params;
142     IdentityOperation operation;
143     gpointer cb_data;
144 } IdentityVerifyData;
145
146 typedef struct _IdentityInfoCbData
147 {
148     SignonIdentity *self;
149     SignonIdentityInfoCb cb;
150     gpointer user_data;
151 } IdentityInfoCbData;
152
153 typedef struct _IdentityVoidCbData
154 {
155     SignonIdentity *self;
156     SignonIdentityVoidCb cb;
157     gpointer user_data;
158 } IdentityVoidCbData;
159
160 typedef struct _IdentityVoidData
161 {
162     IdentityOperation operation;
163     gpointer cb_data;
164 } IdentityVoidData;
165
166 static void identity_check_remote_registration (SignonIdentity *self);
167 static void identity_store_credentials_ready_cb (gpointer object, const GError *error, gpointer user_data);
168 static void identity_store_credentials_reply (GObject *object,
169                                               GAsyncResult *res,
170                                               gpointer userdata);
171 static void identity_verify_data (SignonIdentity *self, const gchar *data_to_send, gint operation,
172                                     SignonIdentityVerifyCb cb, gpointer user_data);
173 static void identity_verify_ready_cb (gpointer object, const GError *error, gpointer user_data);
174
175 static void identity_remove_ready_cb (gpointer object, const GError *error, gpointer user_data);
176 static void identity_signout_ready_cb (gpointer object, const GError *error, gpointer user_data);
177 static void identity_info_ready_cb (gpointer object, const GError *error, gpointer user_data);
178
179 static void identity_process_signout (SignonIdentity *self);
180 static void identity_process_updated (SignonIdentity *self);
181 static void identity_process_removed (SignonIdentity *self);
182 static void identity_get_auth_session_reply (GObject *object,
183                                              GAsyncResult *res,
184                                              gpointer userdata);
185 static void identity_session_ready_cb (gpointer object, const GError *error,
186                                        gpointer user_data);
187 static void identity_session_object_destroyed_cb (gpointer data,
188                                                   GObject *where_the_session_was);
189
190 static GQuark
191 identity_object_quark ()
192 {
193   static GQuark quark = 0;
194
195   if (!quark)
196     quark = g_quark_from_static_string ("identity_object_quark");
197
198   return quark;
199 }
200
201 static void
202 signon_identity_set_property (GObject *object,
203                               guint property_id,
204                               const GValue *value,
205                               GParamSpec *pspec)
206 {
207     SignonIdentity *self = SIGNON_IDENTITY (object);
208
209     switch (property_id)
210     {
211     case PROP_ID:
212         self->priv->id = g_value_get_uint (value);
213         break;
214     case PROP_APPCTX:
215         g_free (self->priv->app_ctx);
216         self->priv->app_ctx = g_strdup (g_value_get_string (value));
217         break;
218     default:
219         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
220         break;
221     }
222 }
223
224 static void
225 signon_identity_get_property (GObject *object,
226                               guint property_id,
227                               GValue *value,
228                               GParamSpec *pspec)
229 {
230     SignonIdentity *self = SIGNON_IDENTITY (object);
231
232     switch (property_id)
233     {
234     case PROP_ID:
235         g_value_set_uint (value, self->priv->id);
236         break;
237     case PROP_APPCTX:
238         g_value_set_string (value, self->priv->app_ctx);
239         break;
240     default:
241         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
242         break;
243     }
244 }
245
246 static void
247 signon_identity_init (SignonIdentity *identity)
248 {
249     SignonIdentityPrivate *priv;
250
251     identity->priv = G_TYPE_INSTANCE_GET_PRIVATE (identity,
252                                                   SIGNON_TYPE_IDENTITY,
253                                                   SignonIdentityPrivate);
254
255     priv = identity->priv;
256     priv->proxy = NULL;
257     priv->auth_service_proxy = sso_auth_service_get_instance();
258     priv->cancellable = g_cancellable_new ();
259     priv->registration_state = NOT_REGISTERED;
260
261     priv->removed = FALSE;
262     priv->signed_out = FALSE;
263     priv->updated = FALSE;
264
265     priv->app_ctx = NULL;
266 }
267
268 static void
269 signon_identity_dispose (GObject *object)
270 {
271     SignonIdentity *identity = SIGNON_IDENTITY (object);
272     SignonIdentityPrivate *priv = identity->priv;
273
274     if (priv->cancellable)
275     {
276         g_cancellable_cancel (priv->cancellable);
277         g_object_unref (priv->cancellable);
278         priv->cancellable = NULL;
279     }
280
281     if (priv->identity_info)
282     {
283         signon_identity_info_free (priv->identity_info);
284         priv->identity_info = NULL;
285     }
286
287     g_clear_object (&priv->auth_service_proxy);
288
289     if (priv->proxy)
290     {
291         g_signal_handler_disconnect (priv->proxy, priv->signal_info_updated);
292         g_signal_handler_disconnect (priv->proxy, priv->signal_unregistered);
293         g_object_unref (priv->proxy);
294         priv->proxy = NULL;
295     }
296
297     if (priv->sessions)
298         g_critical ("SignonIdentity: the list of AuthSessions MUST be empty");
299
300     g_free(priv->app_ctx);
301
302     G_OBJECT_CLASS (signon_identity_parent_class)->dispose (object);
303 }
304
305 static void
306 signon_identity_finalize (GObject *object)
307 {
308     G_OBJECT_CLASS (signon_identity_parent_class)->finalize (object);
309 }
310
311 static void
312 signon_identity_class_init (SignonIdentityClass *klass)
313 {
314     GObjectClass *object_class = G_OBJECT_CLASS (klass);
315     GParamSpec *pspec;
316
317     object_class->set_property = signon_identity_set_property;
318     object_class->get_property = signon_identity_get_property;
319
320     pspec = g_param_spec_uint ("id",
321                                "Identity ID",
322                                "Set/Get Identity ID",
323                                0,
324                                G_MAXUINT,
325                                0,
326                                G_PARAM_READWRITE);
327     g_object_class_install_property (object_class,
328                                      PROP_ID,
329                                      pspec);
330
331     pspec = g_param_spec_string ("app_ctx",
332                                  "Application Context",
333                                  "Set/Get Application Security Context",
334                                  "",
335                                  G_PARAM_READWRITE);
336     g_object_class_install_property (object_class,
337                                      PROP_APPCTX,
338                                      pspec);
339
340     g_type_class_add_private (object_class, sizeof (SignonIdentityPrivate));
341
342     /**
343      * SignonIdentity::signout:
344      *
345      * Emitted when the identity was signed out.
346      */
347     signals[SIGNEDOUT_SIGNAL] = g_signal_new("signout",
348                                     G_TYPE_FROM_CLASS (klass),
349                                     G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
350                                     0 /* class closure */,
351                                     NULL /* accumulator */,
352                                     NULL /* accu_data */,
353                                     g_cclosure_marshal_VOID__VOID,
354                                     G_TYPE_NONE /* return_type */,
355                                     0);
356
357     object_class->dispose = signon_identity_dispose;
358     object_class->finalize = signon_identity_finalize;
359 }
360
361 static void
362 identity_state_changed_cb (GDBusProxy *proxy,
363                            gint state,
364                            gpointer user_data)
365 {
366     g_return_if_fail (SIGNON_IS_IDENTITY (user_data));
367     SignonIdentity *self = SIGNON_IDENTITY (user_data);
368
369     switch (state) {
370         case DATA_UPDATED:
371             DEBUG ("State changed to DATA_UPDATED");
372             identity_process_updated (self);
373             break;
374         case IDENTITY_REMOVED:
375             DEBUG ("State changed to IDENTITY_REMOVED");
376             identity_process_removed (self);
377             break;
378         case IDENTITY_SIGNED_OUT:
379             DEBUG ("State changed to IDENTITY_SIGNED_OUT");
380             identity_process_signout (self);
381             break;
382         default:
383             g_critical ("wrong state value obtained from signon daemon");
384     };
385 }
386
387 static void
388 identity_remote_object_destroyed_cb(GDBusProxy *proxy,
389                                     gpointer user_data)
390 {
391     g_return_if_fail (SIGNON_IS_IDENTITY (user_data));
392     SignonIdentity *self = SIGNON_IDENTITY (user_data);
393
394     SignonIdentityPrivate *priv = self->priv;
395     g_return_if_fail (priv != NULL);
396
397     if (priv->proxy)
398     {
399         g_object_unref (priv->proxy);
400         priv->proxy = NULL;
401     }
402
403     DEBUG ("%s %d", G_STRFUNC, __LINE__);
404
405     _signon_object_not_ready(self);
406
407     priv->registration_state = NOT_REGISTERED;
408
409     signon_identity_info_free (priv->identity_info);
410     priv->identity_info = NULL;
411
412     priv->removed = FALSE;
413     priv->signed_out = FALSE;
414     priv->updated = FALSE;
415 }
416
417 static void
418 identity_registered (SignonIdentity *identity,
419                      char *object_path, GVariant *identity_data,
420                      GError *error)
421 {
422     g_return_if_fail (SIGNON_IS_IDENTITY (identity));
423
424     SignonIdentityPrivate *priv;
425     priv = identity->priv;
426
427     g_return_if_fail (priv != NULL);
428
429     if (!error)
430     {
431         GDBusConnection *connection;
432         GDBusProxy *auth_service_proxy;
433         const gchar *bus_name;
434         GError *proxy_error = NULL;
435
436         DEBUG("%s: %s", G_STRFUNC, object_path);
437         /*
438          * TODO: as Aurel will finalize the code polishing so we will
439          * need to implement the refresh of the proxy to SignonIdentity
440          * */
441         g_return_if_fail (priv->proxy == NULL);
442
443         auth_service_proxy = (GDBusProxy *)priv->auth_service_proxy;
444         connection = g_dbus_proxy_get_connection (auth_service_proxy);
445         bus_name = g_dbus_proxy_get_name (auth_service_proxy);
446
447         priv->proxy =
448             sso_identity_proxy_new_sync (connection,
449                                          G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
450                                          bus_name,
451                                          object_path,
452                                          priv->cancellable,
453                                          &proxy_error);
454         if (G_UNLIKELY (proxy_error != NULL))
455         {
456             g_warning ("Failed to initialize Identity proxy: %s",
457                        proxy_error->message);
458             g_clear_error (&proxy_error);
459         }
460
461         priv->signal_info_updated =
462             g_signal_connect (priv->proxy,
463                               "info-updated",
464                               G_CALLBACK (identity_state_changed_cb),
465                               identity);
466
467         priv->signal_unregistered =
468             g_signal_connect (priv->proxy,
469                               "unregistered",
470                               G_CALLBACK (identity_remote_object_destroyed_cb),
471                               identity);
472
473         if (identity_data)
474         {
475             DEBUG("%s: ", G_STRFUNC);
476             priv->identity_info =
477                 signon_identity_info_new_from_variant (identity_data);
478             g_variant_unref (identity_data);
479         }
480
481         priv->updated = TRUE;
482     }
483     else
484         g_warning ("%s: %s", G_STRFUNC, error->message);
485
486     /*
487      * execute queued operations or emit errors on each of them
488      * */
489     priv->registration_state = REGISTERED;
490
491     /*
492      * TODO: if we will add a new state for identity: "INVALID"
493      * consider emission of another error, like "invalid"
494      * */
495     _signon_object_ready (identity, identity_object_quark (), error);
496
497     /*
498      * as the registration failed we do not
499      * request for new registration, but emit
500      * same error again and again
501      * */
502 }
503
504 /**
505  * signon_identity_get_last_error:
506  * @identity: the #SignonIdentity.
507  *
508  * Get the most recent error that occurred on @identity.
509  *
510  * Returns: a #GError containing the most recent error, or %NULL on failure.
511  */
512 const GError *
513 signon_identity_get_last_error (SignonIdentity *identity)
514 {
515     g_return_val_if_fail (SIGNON_IS_IDENTITY (identity), NULL);
516     return _signon_object_last_error(identity);
517 }
518
519 static void
520 identity_new_cb (GObject *object, GAsyncResult *res,
521                  gpointer userdata)
522 {
523     SignonIdentity *identity = (SignonIdentity*)userdata;
524     SsoAuthService *proxy = SSO_AUTH_SERVICE (object);
525     gchar *object_path = NULL;
526     GError *error = NULL;
527
528     g_return_if_fail (identity != NULL);
529     DEBUG ("%s", G_STRFUNC);
530
531     sso_auth_service_call_register_new_identity_finish (proxy,
532                                                         &object_path,
533                                                         res,
534                                                         &error);
535     SIGNON_RETURN_IF_CANCELLED (error);
536     identity_registered (identity, object_path, NULL, error);
537     g_free (object_path);
538 }
539
540 static void
541 identity_new_from_db_cb (GObject *object, GAsyncResult *res,
542                          gpointer userdata)
543 {
544     SignonIdentity *identity = (SignonIdentity*)userdata;
545     SsoAuthService *proxy = SSO_AUTH_SERVICE (object);
546     gchar *object_path = NULL;
547     GVariant *identity_data;
548     GError *error = NULL;
549
550     g_return_if_fail (identity != NULL);
551     DEBUG ("%s", G_STRFUNC);
552
553     sso_auth_service_call_get_identity_finish (proxy,
554                                                &object_path,
555                                                &identity_data,
556                                                res,
557                                                &error);
558     SIGNON_RETURN_IF_CANCELLED (error);
559     identity_registered (identity, object_path, identity_data, error);
560     g_free (object_path);
561 }
562
563 static void
564 identity_check_remote_registration (SignonIdentity *self)
565 {
566     g_return_if_fail (self != NULL);
567     SignonIdentityPrivate *priv = self->priv;
568
569     g_return_if_fail (priv != NULL);
570
571     if (priv->registration_state != NOT_REGISTERED)
572         return;
573
574     if (priv->id != 0)
575         sso_auth_service_call_get_identity (priv->auth_service_proxy,
576                                             priv->id,
577                                             priv->app_ctx,
578                                             priv->cancellable,
579                                             identity_new_from_db_cb,
580                                             self);
581     else
582         sso_auth_service_call_register_new_identity (priv->auth_service_proxy,
583                                                      priv->app_ctx,
584                                                      priv->cancellable,
585                                                      identity_new_cb,
586                                                      self);
587
588     priv->registration_state = PENDING_REGISTRATION;
589 }
590
591 /**
592  * signon_identity_new_from_db:
593  * @id: identity ID.
594  * @application_context: application security context, can be %NULL.
595  *
596  * Construct an identity object associated with an existing identity
597  * record.
598  *
599  * Returns: an instance of a #SignonIdentity.
600  */
601 SignonIdentity*
602 signon_identity_new_from_db (guint32 id, const gchar *application_context)
603 {
604     SignonIdentity *identity;
605     DEBUG ("%s %d: %d\n", G_STRFUNC, __LINE__, id);
606     if (id == 0)
607         return NULL;
608
609     identity = g_object_new (SIGNON_TYPE_IDENTITY,
610                              "id", id,
611                              "app_ctx", application_context,
612                              NULL);
613     g_return_val_if_fail (SIGNON_IS_IDENTITY (identity), NULL);
614     g_return_val_if_fail (identity->priv != NULL, NULL);
615
616     identity->priv->id = id;
617     identity->priv->app_ctx = (application_context) ?
618         g_strdup (application_context) : g_strdup ("");
619     identity_check_remote_registration (identity);
620
621     return identity;
622 }
623
624 /**
625  * signon_identity_new:
626  * @application_context: application security context, can be %NULL.
627  *
628  * Construct new, empty, identity object.
629  *
630  * Returns: an instance of an #SignonIdentity.
631  */
632 SignonIdentity*
633 signon_identity_new (const gchar *application_context)
634 {
635     DEBUG ("%s %d", G_STRFUNC, __LINE__);
636     SignonIdentity *identity = g_object_new (
637                                      SIGNON_TYPE_IDENTITY,
638                                      "app_ctx", application_context,
639                                      NULL);
640     g_return_val_if_fail (SIGNON_IS_IDENTITY (identity), NULL);
641     g_return_val_if_fail (identity->priv != NULL, NULL);
642
643     identity->priv->app_ctx = (application_context) ?
644         g_strdup (application_context) : g_strdup ("");
645     identity_check_remote_registration (identity);
646
647     return identity;
648 }
649
650 /**
651  * signon_identity_create_session:
652  * @self: the #SignonIdentity.
653  * @method: method.
654  * @error: pointer to a location which will receive the error, if any.
655  *
656  * Creates an authentication session for this identity.
657  *
658  * Returns: (transfer full): a new #SignonAuthSession.
659  */
660 SignonAuthSession *
661 signon_identity_create_session(SignonIdentity *self,
662                                const gchar *method,
663                                GError **error)
664 {
665     g_return_val_if_fail (SIGNON_IS_IDENTITY (self), NULL);
666
667     SignonIdentityPrivate *priv = self->priv;
668     g_return_val_if_fail (priv != NULL, NULL);
669
670     DEBUG ("%s %d", G_STRFUNC, __LINE__);
671
672     if (method == NULL)
673     {
674         DEBUG ("NULL method as input. Aborting.");
675         g_set_error(error,
676                     signon_error_quark(),
677                     SIGNON_ERROR_UNKNOWN,
678                     "NULL input method.");
679         return NULL;
680     }
681
682     GSList *list = priv->sessions;
683     while (list)
684     {
685         SignonAuthSession *session = SIGNON_AUTH_SESSION (priv->sessions->data);
686         const gchar *sessionMethod = signon_auth_session_get_method (session);
687         if (g_strcmp0(sessionMethod, method) == 0)
688         {
689             DEBUG ("Auth Session with method `%s` already created.", method);
690             g_set_error (error,
691                          signon_error_quark(),
692                          SIGNON_ERROR_METHOD_NOT_AVAILABLE,
693                          "Authentication session for this method already requested.");
694             return NULL;
695         }
696
697         list = list->next;
698     }
699
700     SignonAuthSession *session = signon_auth_session_new (G_OBJECT(self),
701                                                           method,
702                                                           error);
703     if (session)
704     {
705         DEBUG ("%s %d - success", G_STRFUNC, __LINE__);
706         priv->sessions = g_slist_append(priv->sessions, session);
707         g_object_weak_ref (G_OBJECT(session),
708                            identity_session_object_destroyed_cb,
709                            self);
710         /*
711          * if you want to delete the identity
712          * you MUST delete all authsessions
713          * first
714          * */
715         g_object_ref (self);
716         priv->signed_out = FALSE;
717     }
718
719     return session;
720 }
721
722 /**
723  * signon_identity_store_credentials_with_info:
724  * @self: the #SignonIdentity.
725  * @info: the #SignonIdentityInfo data to store.
726  * @cb: (scope async): callback.
727  * @user_data: user_data.
728  *
729  * Stores the data from @info into the identity.
730  */
731 void
732 signon_identity_store_credentials_with_info(SignonIdentity *self,
733                                             const SignonIdentityInfo *info,
734                                             SignonIdentityStoreCredentialsCb cb,
735                                             gpointer user_data)
736 {
737     IdentityStoreCredentialsCbData *cb_data;
738     IdentityStoreCredentialsData *operation_data;
739
740     DEBUG ();
741     g_return_if_fail (SIGNON_IS_IDENTITY (self));
742     g_return_if_fail (info != NULL);
743
744     SignonIdentityPrivate *priv = self->priv;
745     if (priv->identity_info)
746         signon_identity_info_free (priv->identity_info);
747     priv->identity_info = signon_identity_info_copy (info);
748
749     cb_data = g_slice_new0 (IdentityStoreCredentialsCbData);
750     cb_data->self = self;
751     cb_data->cb = cb;
752     cb_data->user_data = user_data;
753
754     operation_data = g_slice_new0 (IdentityStoreCredentialsData);
755     operation_data->info_variant = signon_identity_info_to_variant (info);
756     operation_data->cb_data = cb_data;
757
758     identity_check_remote_registration (self);
759     _signon_object_call_when_ready (self,
760                                     identity_object_quark(),
761                                     identity_store_credentials_ready_cb,
762                                     operation_data);
763 }
764
765 /**
766  * signon_identity_store_credentials_with_args:
767  * @self: the #SignonIdentity.
768  * @username: username.
769  * @secret: secret.
770  * @store_secret: whether signond should store the password.
771  * @methods: (transfer none) (element-type utf8 GStrv): methods.
772  * @caption: caption.
773  * @realms: realms.
774  * @access_control_list: access control list.
775  * @type: the type of the identity.
776  * @cb: (scope async): callback.
777  * @user_data: user_data.
778  *
779  * Stores the given data into the identity.
780  */
781 void signon_identity_store_credentials_with_args(SignonIdentity *self,
782                                                  const gchar *username,
783                                                  const gchar *secret,
784                                                  const gboolean store_secret,
785                                                  const GHashTable *methods,
786                                                  const gchar *caption,
787                                                  const gchar* const *realms,
788                                                  const SignonSecurityContext *owner,
789                                                  const SignonSecurityContextList *access_control_list,
790                                                  SignonIdentityType type,
791                                                  SignonIdentityStoreCredentialsCb cb,
792                                                  gpointer user_data)
793 {
794     SignonIdentityInfo *info;
795
796     g_return_if_fail (SIGNON_IS_IDENTITY (self));
797
798     info = signon_identity_info_new ();
799     signon_identity_info_set_username (info, username);
800     signon_identity_info_set_secret (info, secret, store_secret);
801     signon_identity_info_set_methods (info, methods);
802     signon_identity_info_set_caption (info, caption);
803     signon_identity_info_set_realms (info, realms);
804     if (owner)
805     {
806         signon_identity_info_set_owner (info, owner);
807     }
808     if (access_control_list)
809     {
810         signon_identity_info_set_access_control_list (info,
811                                                       access_control_list);
812     }
813     signon_identity_info_set_identity_type (info, type);
814
815     signon_identity_store_credentials_with_info (self, info, cb, user_data);
816     signon_identity_info_free (info);
817 }
818
819 static void
820 identity_store_credentials_ready_cb (gpointer object, const GError *error, gpointer user_data)
821 {
822     g_return_if_fail (SIGNON_IS_IDENTITY (object));
823
824     SignonIdentity *self = SIGNON_IDENTITY (object);
825     SignonIdentityPrivate *priv = self->priv;
826     g_return_if_fail (priv != NULL);
827
828     DEBUG ("%s %d", G_STRFUNC, __LINE__);
829
830     IdentityStoreCredentialsData *operation_data =
831         (IdentityStoreCredentialsData *)user_data;
832     g_return_if_fail (operation_data != NULL);
833
834     IdentityStoreCredentialsCbData *cb_data = operation_data->cb_data;
835     g_return_if_fail (cb_data != NULL);
836
837     if (error)
838     {
839         DEBUG ("IdentityError: %s", error->message);
840
841         if (cb_data->cb)
842         {
843             (cb_data->cb) (self, 0, error, cb_data->user_data);
844         }
845
846         g_slice_free (IdentityStoreCredentialsCbData, cb_data);
847     }
848     else
849     {
850         g_return_if_fail (priv->proxy != NULL);
851
852         sso_identity_call_store (priv->proxy,
853                                  operation_data->info_variant,
854                                  priv->cancellable,
855                                  identity_store_credentials_reply,
856                                  cb_data);
857     }
858
859     g_slice_free (IdentityStoreCredentialsData, operation_data);
860 }
861
862 static void
863 identity_store_credentials_reply (GObject *object, GAsyncResult *res,
864                                   gpointer userdata)
865 {
866     IdentityStoreCredentialsCbData *cb_data = (IdentityStoreCredentialsCbData *)userdata;
867     SsoIdentity *proxy = SSO_IDENTITY (object);
868     guint id;
869     GError *error = NULL;
870
871     g_return_if_fail (cb_data != NULL);
872     g_return_if_fail (cb_data->self != NULL);
873     g_return_if_fail (cb_data->self->priv != NULL);
874
875     SignonIdentityPrivate *priv = cb_data->self->priv;
876
877     sso_identity_call_store_finish (proxy, &id, res, &error);
878     SIGNON_RETURN_IF_CANCELLED (error);
879
880     if (error == NULL)
881     {
882         g_return_if_fail (priv->identity_info == NULL);
883
884         g_object_set (cb_data->self, "id", id, NULL);
885         cb_data->self->priv->id = id;
886
887         /*
888          * if the previous state was REMOVED
889          * then we need to reset it
890          * */
891         priv->removed = FALSE;
892     }
893
894     if (cb_data->cb)
895     {
896         (cb_data->cb) (cb_data->self, id, error, cb_data->user_data);
897     }
898
899     g_clear_error(&error);
900     g_slice_free (IdentityStoreCredentialsCbData, cb_data);
901 }
902
903 static void
904 identity_verify_reply (GObject *object, GAsyncResult *res,
905                        gpointer userdata)
906 {
907     SsoIdentity *proxy = SSO_IDENTITY (object);
908     gboolean valid;
909     GError *error = NULL;
910     IdentityVerifyCbData *cb_data = (IdentityVerifyCbData *)userdata;
911
912     g_return_if_fail (cb_data != NULL);
913     g_return_if_fail (cb_data->self != NULL);
914
915     sso_identity_call_verify_secret_finish (proxy, &valid, res, &error);
916     SIGNON_RETURN_IF_CANCELLED (error);
917
918     if (cb_data->cb)
919     {
920         (cb_data->cb) (cb_data->self, valid, error, cb_data->user_data);
921     }
922
923     g_clear_error(&error);
924     g_slice_free (IdentityVerifyCbData, cb_data);
925 }
926
927 static void
928 identity_verify_ready_cb (gpointer object, const GError *error, gpointer user_data)
929 {
930     g_return_if_fail (SIGNON_IS_IDENTITY (object));
931
932     SignonIdentity *self = SIGNON_IDENTITY (object);
933     SignonIdentityPrivate *priv = self->priv;
934     g_return_if_fail (priv != NULL);
935
936     DEBUG ("%s %d", G_STRFUNC, __LINE__);
937
938     IdentityVerifyData *operation_data =
939         (IdentityVerifyData *)user_data;
940     g_return_if_fail (operation_data != NULL);
941
942     IdentityVerifyCbData *cb_data = operation_data->cb_data;
943     g_return_if_fail (cb_data != NULL);
944
945     if (priv->removed == TRUE)
946     {
947         GError *new_error = g_error_new (signon_error_quark(),
948                                          SIGNON_ERROR_IDENTITY_NOT_FOUND,
949                                          "Already removed from database.");
950
951         if (cb_data->cb)
952         {
953             (cb_data->cb) (self, FALSE, new_error, cb_data->user_data);
954         }
955
956         g_error_free (new_error);
957         g_slice_free (IdentityVerifyCbData, cb_data);
958     }
959     else if (error)
960     {
961         DEBUG ("IdentityError: %s", error->message);
962
963         if (cb_data->cb)
964         {
965             (cb_data->cb) (self, FALSE, error, cb_data->user_data);
966         }
967
968         g_slice_free (IdentityVerifyCbData, cb_data);
969     }
970     else
971     {
972         DEBUG ("%s %d", G_STRFUNC, __LINE__);
973         g_return_if_fail (priv->proxy != NULL);
974
975         switch (operation_data->operation) {
976         case SIGNON_VERIFY_SECRET:
977             sso_identity_call_verify_secret (priv->proxy,
978                                              operation_data->data_to_send,
979                                              priv->cancellable,
980                                              identity_verify_reply,
981                                              cb_data);
982             break;
983         default: g_critical ("Wrong operation code");
984         };
985     }
986     g_free (operation_data->params);
987     g_free (operation_data->data_to_send);
988     g_slice_free (IdentityVerifyData, operation_data);
989 }
990
991 static void
992 identity_verify_data(SignonIdentity *self,
993                      const gchar *data_to_send,
994                      gint operation,
995                      SignonIdentityVerifyCb cb,
996                      gpointer user_data)
997 {
998     g_return_if_fail (SIGNON_IS_IDENTITY (self));
999
1000     SignonIdentityPrivate *priv = self->priv;
1001     g_return_if_fail (priv != NULL);
1002
1003     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1004
1005     IdentityVerifyCbData *cb_data = g_slice_new0 (IdentityVerifyCbData);
1006     cb_data->self = self;
1007     cb_data->cb = cb;
1008     cb_data->user_data = user_data;
1009
1010     IdentityVerifyData *operation_data = g_slice_new0 (IdentityVerifyData);
1011
1012     operation_data->params = NULL;
1013     operation_data->data_to_send = g_strdup (data_to_send);
1014     operation_data->operation = operation;
1015     operation_data->cb_data = cb_data;
1016
1017     identity_check_remote_registration (self);
1018     _signon_object_call_when_ready (self,
1019                                     identity_object_quark(),
1020                                     identity_verify_ready_cb,
1021                                     operation_data);
1022 }
1023
1024 /**
1025  * signon_identity_verify_secret:
1026  * @self: the #SignonIdentity.
1027  * @secret: the secret (password) to be verified.
1028  * @cb: (scope async): callback.
1029  * @user_data: user_data.
1030  *
1031  * Verifies the given secret.
1032  */
1033 void signon_identity_verify_secret(SignonIdentity *self,
1034                                   const gchar *secret,
1035                                   SignonIdentityVerifyCb cb,
1036                                   gpointer user_data)
1037 {
1038     identity_verify_data (self,
1039                           secret,
1040                           SIGNON_VERIFY_SECRET,
1041                           cb,
1042                           user_data);
1043 }
1044
1045 static void
1046 identity_process_updated (SignonIdentity *self)
1047 {
1048     DEBUG ("%d %s", __LINE__, __func__);
1049
1050     g_return_if_fail (self != NULL);
1051     g_return_if_fail (self->priv != NULL);
1052
1053     SignonIdentityPrivate *priv = self->priv;
1054     g_return_if_fail (priv->proxy != NULL);
1055
1056     signon_identity_info_free (priv->identity_info);
1057     priv->identity_info = NULL;
1058     priv->updated = FALSE;
1059
1060     DEBUG ("%s info freed, to be updated", __func__);
1061 }
1062
1063 static void
1064 identity_process_removed (SignonIdentity *self)
1065 {
1066     g_return_if_fail (self != NULL);
1067     g_return_if_fail (self->priv != NULL);
1068
1069     DEBUG ("%d %s", __LINE__, __func__);
1070
1071     SignonIdentityPrivate *priv = self->priv;
1072
1073     if (priv->removed == TRUE)
1074         return;
1075
1076     priv->removed = TRUE;
1077     signon_identity_info_free (priv->identity_info);
1078     priv->identity_info = NULL;
1079
1080     g_object_set (self, "id", 0, NULL);
1081     priv->id = 0;
1082 }
1083
1084 static void
1085 identity_process_signout(SignonIdentity *self)
1086 {
1087     g_return_if_fail (self != NULL);
1088     g_return_if_fail (self->priv != NULL);
1089
1090     DEBUG ("%d %s", __LINE__, __func__);
1091     SignonIdentityPrivate *priv = self->priv;
1092
1093     if (priv->signed_out == TRUE)
1094         return;
1095
1096     GSList *llink = priv->sessions;
1097     while (llink)
1098     {
1099         GSList *next = llink->next;
1100         g_object_unref (G_OBJECT(llink->data));
1101         llink = next;
1102     }
1103
1104     priv->signed_out = TRUE;
1105     g_signal_emit(G_OBJECT(self), signals[SIGNEDOUT_SIGNAL], 0);
1106 }
1107
1108 /*
1109  * TODO: fix the implementation
1110  * of signond: it returns result = TRUE
1111  * in ANY CASE
1112  * */
1113 static void
1114 identity_signout_reply (GObject *object, GAsyncResult *res,
1115                         gpointer userdata)
1116 {
1117     SsoIdentity *proxy = SSO_IDENTITY (object);
1118     gboolean result;
1119     GError *error = NULL;
1120     IdentityVoidCbData *cb_data = (IdentityVoidCbData *)userdata;
1121
1122     g_return_if_fail (cb_data != NULL);
1123     g_return_if_fail (cb_data->self != NULL);
1124     g_return_if_fail (cb_data->self->priv != NULL);
1125
1126     sso_identity_call_sign_out_finish (proxy, &result, res, &error);
1127     SIGNON_RETURN_IF_CANCELLED (error);
1128
1129     if (cb_data->cb)
1130     {
1131         (cb_data->cb) (cb_data->self, error, cb_data->user_data);
1132     }
1133
1134     g_clear_error(&error);
1135     g_slice_free (IdentityVoidCbData, cb_data);
1136 }
1137
1138 static void
1139 identity_removed_reply (GObject *object, GAsyncResult *res,
1140                         gpointer userdata)
1141 {
1142     SsoIdentity *proxy = SSO_IDENTITY (object);
1143     GError *error = NULL;
1144     IdentityVoidCbData *cb_data = (IdentityVoidCbData *)userdata;
1145
1146     g_return_if_fail (cb_data != NULL);
1147     g_return_if_fail (cb_data->self != NULL);
1148     g_return_if_fail (cb_data->self->priv != NULL);
1149
1150     sso_identity_call_remove_finish (proxy, res, &error);
1151     SIGNON_RETURN_IF_CANCELLED (error);
1152
1153     if (cb_data->cb)
1154     {
1155         (cb_data->cb) (cb_data->self, error, cb_data->user_data);
1156     }
1157
1158     g_clear_error(&error);
1159     g_slice_free (IdentityVoidCbData, cb_data);
1160 }
1161
1162 static void
1163 identity_info_reply(GObject *object, GAsyncResult *res,
1164                     gpointer userdata)
1165 {
1166     SsoIdentity *proxy = SSO_IDENTITY (object);
1167     GVariant *identity_data = NULL;
1168     DEBUG ("%d %s", __LINE__, __func__);
1169
1170     GError *error = NULL;
1171     IdentityInfoCbData *cb_data = (IdentityInfoCbData *)userdata;
1172
1173     g_return_if_fail (cb_data != NULL);
1174     g_return_if_fail (cb_data->self != NULL);
1175     g_return_if_fail (cb_data->self->priv != NULL);
1176
1177     SignonIdentityPrivate *priv = cb_data->self->priv;
1178
1179     sso_identity_call_get_info_finish (proxy, &identity_data, res, &error);
1180     SIGNON_RETURN_IF_CANCELLED (error);
1181     priv->identity_info =
1182         signon_identity_info_new_from_variant (identity_data);
1183     if (identity_data != NULL)
1184         g_variant_unref (identity_data);
1185
1186     if (cb_data->cb)
1187     {
1188         (cb_data->cb) (cb_data->self, priv->identity_info, error, cb_data->user_data);
1189     }
1190
1191     g_clear_error(&error);
1192     g_slice_free (IdentityInfoCbData, cb_data);
1193
1194     priv->updated = TRUE;
1195 }
1196
1197 static void
1198 identity_info_ready_cb(gpointer object, const GError *error, gpointer user_data)
1199 {
1200     g_return_if_fail (SIGNON_IS_IDENTITY (object));
1201
1202     SignonIdentity *self = SIGNON_IDENTITY (object);
1203     SignonIdentityPrivate *priv = self->priv;
1204     g_return_if_fail (priv != NULL);
1205
1206     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1207
1208     IdentityVoidData *operation_data =
1209         (IdentityVoidData *)user_data;
1210     g_return_if_fail (operation_data != NULL);
1211
1212     IdentityInfoCbData *cb_data = operation_data->cb_data;
1213     g_return_if_fail (cb_data != NULL);
1214
1215     if (priv->removed == TRUE)
1216     {
1217         DEBUG ("%s identity removed", G_STRFUNC);
1218
1219         GError *new_error = g_error_new (signon_error_quark(),
1220                                          SIGNON_ERROR_IDENTITY_NOT_FOUND,
1221                                          "Already removed from database.");
1222         if (cb_data->cb)
1223             (cb_data->cb) (self, NULL, new_error, cb_data->user_data);
1224
1225         g_error_free (new_error);
1226     }
1227     else if (error || priv->id == 0)
1228     {
1229         DEBUG ("%s identity is new", G_STRFUNC);
1230
1231         if (error)
1232             DEBUG ("IdentityError: %s", error->message);
1233         else
1234             DEBUG ("Identity is not stored and has no info yet");
1235
1236         if (cb_data->cb)
1237             (cb_data->cb) (self, NULL, error, cb_data->user_data);
1238     }
1239     else if (priv->updated == FALSE)
1240     {
1241         DEBUG ("%s identity needs update, call daemon", G_STRFUNC);
1242
1243         g_return_if_fail (priv->proxy != NULL);
1244         sso_identity_call_get_info (priv->proxy,
1245                                     priv->cancellable,
1246                                     identity_info_reply,
1247                                     cb_data);
1248     }
1249     else
1250     {
1251         DEBUG ("%s pass existing one", G_STRFUNC);
1252
1253         if (cb_data->cb)
1254             (cb_data->cb) (self, priv->identity_info, error, cb_data->user_data);
1255     }
1256
1257     if (priv->updated == TRUE)
1258         g_slice_free (IdentityInfoCbData, cb_data);
1259
1260     g_slice_free (IdentityVoidData, operation_data);
1261 }
1262
1263 static void
1264 identity_signout_ready_cb(gpointer object, const GError *error, gpointer user_data)
1265 {
1266     g_return_if_fail (SIGNON_IS_IDENTITY (object));
1267
1268     SignonIdentity *self = SIGNON_IDENTITY (object);
1269     SignonIdentityPrivate *priv = self->priv;
1270     g_return_if_fail (priv != NULL);
1271
1272     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1273     IdentityVoidCbData *cb_data = (IdentityVoidCbData *)user_data;
1274
1275     g_return_if_fail (cb_data != NULL);
1276
1277     if (priv->removed == TRUE)
1278     {
1279         GError *new_error = g_error_new (signon_error_quark(),
1280                                          SIGNON_ERROR_IDENTITY_NOT_FOUND,
1281                                          "Already removed from database.");
1282         if (cb_data->cb)
1283         {
1284             (cb_data->cb) (self, new_error, cb_data->user_data);
1285         }
1286
1287         g_error_free (new_error);
1288         g_slice_free (IdentityVoidCbData, cb_data);
1289     }
1290     else if (error)
1291     {
1292         DEBUG ("IdentityError: %s", error->message);
1293         if (cb_data->cb)
1294         {
1295             (cb_data->cb) (self, error, cb_data->user_data);
1296         }
1297
1298         g_slice_free (IdentityVoidCbData, cb_data);
1299     }
1300     else
1301     {
1302         g_return_if_fail (priv->proxy != NULL);
1303         sso_identity_call_sign_out (priv->proxy,
1304                                     priv->cancellable,
1305                                     identity_signout_reply,
1306                                     cb_data);
1307     }
1308 }
1309
1310 static void
1311 identity_remove_ready_cb(gpointer object, const GError *error, gpointer user_data)
1312 {
1313     g_return_if_fail (SIGNON_IS_IDENTITY (object));
1314
1315     SignonIdentity *self = SIGNON_IDENTITY (object);
1316     SignonIdentityPrivate *priv = self->priv;
1317     g_return_if_fail (priv != NULL);
1318
1319     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1320     IdentityVoidCbData *cb_data = (IdentityVoidCbData *)user_data;
1321     g_return_if_fail (cb_data != NULL);
1322
1323     if (priv->removed == TRUE)
1324     {
1325         GError *new_error = g_error_new (signon_error_quark(),
1326                                           SIGNON_ERROR_IDENTITY_NOT_FOUND,
1327                                          "Already removed from database.");
1328         if (cb_data->cb)
1329         {
1330             (cb_data->cb) (self, new_error, cb_data->user_data);
1331         }
1332
1333         g_error_free (new_error);
1334         g_slice_free (IdentityVoidCbData, cb_data);
1335     }
1336     else if (error)
1337     {
1338         DEBUG ("IdentityError: %s", error->message);
1339         if (cb_data->cb)
1340         {
1341             (cb_data->cb) (self, error, cb_data->user_data);
1342         }
1343
1344         g_slice_free (IdentityVoidCbData, cb_data);
1345     }
1346     else
1347     {
1348         g_return_if_fail (priv->proxy != NULL);
1349         sso_identity_call_remove (priv->proxy,
1350                                   priv->cancellable,
1351                                   identity_removed_reply,
1352                                   cb_data);
1353     }
1354 }
1355
1356 void static
1357 identity_void_operation(SignonIdentity *self,
1358                         gint operation,
1359                         gpointer cb_data)
1360 {
1361     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1362
1363     SignonIdentityPrivate *priv = self->priv;
1364     g_return_if_fail (priv != NULL);
1365
1366     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1367
1368     IdentityVoidData *operation_data = g_slice_new0 (IdentityVoidData);
1369     operation_data->cb_data = cb_data;
1370     _signon_object_call_when_ready (self,
1371                                     identity_object_quark(),
1372                                     identity_info_ready_cb,
1373                                     operation_data);
1374 }
1375
1376 /**
1377  * signon_identity_remove:
1378  * @self: the #SignonIdentity.
1379  * @cb: (scope async): callback to be called when the operation has completed.
1380  * @user_data: user_data to pass to the callback.
1381  *
1382  * Removes the corresponding credentials record from the database.
1383  */
1384 void signon_identity_remove(SignonIdentity *self,
1385                            SignonIdentityRemovedCb cb,
1386                            gpointer user_data)
1387 {
1388     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1389
1390     SignonIdentityPrivate *priv = self->priv;
1391     g_return_if_fail (priv != NULL);
1392
1393     IdentityVoidCbData *cb_data = g_slice_new0 (IdentityVoidCbData);
1394     cb_data->self = self;
1395     cb_data->cb = (SignonIdentityVoidCb)cb;
1396     cb_data->user_data = user_data;
1397
1398     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1399
1400     identity_check_remote_registration (self);
1401     _signon_object_call_when_ready (self,
1402                                     identity_object_quark(),
1403                                     identity_remove_ready_cb,
1404                                     cb_data);
1405 }
1406
1407 /**
1408  * signon_identity_signout:
1409  * @self: the #SignonIdentity.
1410  * @cb: (scope async): callback.
1411  * @user_data: user_data.
1412  *
1413  * Asks signond to close all authentication sessions for this
1414  * identity, and to remove any stored secrets associated with it (password and
1415  * authentication tokens).
1416  */
1417 void signon_identity_signout(SignonIdentity *self,
1418                              SignonIdentitySignedOutCb cb,
1419                              gpointer user_data)
1420 {
1421     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1422
1423     SignonIdentityPrivate *priv = self->priv;
1424     g_return_if_fail (priv != NULL);
1425
1426     IdentityVoidCbData *cb_data = g_slice_new0 (IdentityVoidCbData);
1427     cb_data->self = self;
1428     cb_data->cb = (SignonIdentityVoidCb)cb;
1429     cb_data->user_data = user_data;
1430
1431     identity_check_remote_registration (self);
1432     _signon_object_call_when_ready (self,
1433                                     identity_object_quark(),
1434                                     identity_signout_ready_cb,
1435                                     cb_data);
1436 }
1437
1438 /**
1439  * signon_identity_add_reference:
1440  * @self: the #SignonIdentity.
1441  * @reference: reference to be added
1442  * @cb: callback
1443  * @user_data: user_data.
1444  *
1445  * Adds named reference to identity
1446  */
1447 void signon_identity_add_reference(SignonIdentity *self,
1448                              const gchar *reference,
1449                              SignonIdentityReferenceAddedCb cb,
1450                              gpointer user_data)
1451 {
1452     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1453
1454     SignonIdentityPrivate *priv = self->priv;
1455     g_return_if_fail (priv != NULL);
1456
1457     //TODO implement
1458
1459     if (cb)
1460         (cb) (self, NULL, user_data);
1461 }
1462
1463 /**
1464  * signon_identity_remove_reference:
1465  * @self: the #SignonIdentity.
1466  * @reference: reference to be removed
1467  * @cb: callback
1468  * @user_data: user_data.
1469  *
1470  * Removes named reference from identity
1471  */
1472 void signon_identity_remove_reference(SignonIdentity *self,
1473                              const gchar *reference,
1474                              SignonIdentityReferenceRemovedCb cb,
1475                              gpointer user_data)
1476 {
1477     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1478
1479     SignonIdentityPrivate *priv = self->priv;
1480     g_return_if_fail (priv != NULL);
1481
1482     //TODO implement
1483
1484     if (cb)
1485         (cb) (self, NULL, user_data);
1486 }
1487
1488 /**
1489  * signon_identity_query_info:
1490  * @self: the #SignonIdentity.
1491  * @cb: (scope async): callback.
1492  * @user_data: user_data.
1493  *
1494  * Fetches the #SignonIdentityInfo data associated with this
1495  * identity.
1496  */
1497 void signon_identity_query_info(SignonIdentity *self,
1498                                 SignonIdentityInfoCb cb,
1499                                 gpointer user_data)
1500 {
1501     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1502
1503     SignonIdentityPrivate *priv = self->priv;
1504     g_return_if_fail (priv != NULL);
1505
1506     IdentityInfoCbData *cb_data = g_slice_new0 (IdentityInfoCbData);
1507     cb_data->self = self;
1508     cb_data->cb = cb;
1509     cb_data->user_data = user_data;
1510
1511     identity_check_remote_registration (self);
1512     identity_void_operation(self,
1513                             SIGNON_INFO,
1514                             cb_data);
1515 }
1516
1517 static void
1518 identity_get_auth_session_reply (GObject *object, GAsyncResult *res,
1519                                  gpointer userdata)
1520 {
1521     SsoIdentity *proxy = SSO_IDENTITY (object);
1522     gchar *object_path = NULL;
1523     GError *error = NULL;
1524
1525     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1526
1527     sso_identity_call_get_auth_session_finish (proxy,
1528                                                &object_path,
1529                                                res,
1530                                                &error);
1531     SIGNON_RETURN_IF_CANCELLED (error);
1532
1533     IdentitySessionCbData *cb_data = (IdentitySessionCbData *) userdata;
1534     g_return_if_fail (cb_data != NULL);
1535     g_return_if_fail (cb_data->cb != NULL);
1536
1537     (cb_data->cb) (cb_data->session,
1538                    error,
1539                    g_dbus_proxy_get_connection ((GDBusProxy *)proxy),
1540                    g_dbus_proxy_get_name ((GDBusProxy *)proxy),
1541                    object_path);
1542
1543     g_slice_free (IdentitySessionCbData, cb_data);
1544     g_free (object_path);
1545     g_clear_error (&error);
1546 }
1547
1548 static void
1549 identity_session_ready_cb(gpointer object, const GError *error, gpointer user_data)
1550 {
1551     g_return_if_fail (SIGNON_IS_IDENTITY (object));
1552     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1553
1554     SignonIdentity *self = SIGNON_IDENTITY (object);
1555     SignonIdentityPrivate *priv = self->priv;
1556     g_return_if_fail (priv != NULL);
1557
1558     IdentitySessionData *operation_data = (IdentitySessionData *) user_data;
1559     g_return_if_fail (operation_data != NULL);
1560
1561     IdentitySessionCbData *cb_data = operation_data->cb_data;
1562     g_return_if_fail (cb_data != NULL);
1563
1564     if (priv->removed == TRUE)
1565     {
1566         GError *new_error = g_error_new (signon_error_quark(),
1567                                          SIGNON_ERROR_IDENTITY_NOT_FOUND,
1568                                          "Already removed from database.");
1569         if (cb_data->cb)
1570         {
1571             (cb_data->cb) (cb_data->session, new_error, NULL, NULL, NULL);
1572         }
1573
1574         g_error_free (new_error);
1575     }
1576     else
1577     {
1578         g_return_if_fail (priv->proxy != NULL);
1579
1580         sso_identity_call_get_auth_session (
1581             priv->proxy,
1582             operation_data->method,
1583             priv->cancellable,
1584             identity_get_auth_session_reply,
1585             cb_data);
1586     }
1587
1588     g_slice_free (IdentitySessionData, operation_data);
1589 }
1590
1591 static void
1592 identity_session_object_destroyed_cb(gpointer data,
1593                                      GObject *where_the_session_was)
1594 {
1595     g_return_if_fail (SIGNON_IS_IDENTITY (data));
1596     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1597
1598     SignonIdentity *self = SIGNON_IDENTITY (data);
1599     SignonIdentityPrivate *priv = self->priv;
1600     g_return_if_fail (priv != NULL);
1601
1602     priv->sessions = g_slist_remove(priv->sessions, (gpointer)where_the_session_was);
1603     g_object_unref (self);
1604 }
1605
1606 void signon_identity_get_auth_session (SignonIdentity *self,
1607                                        SignonAuthSession *session,
1608                                        const gchar *method,
1609                                        SignonIdentitySessionReadyCb cb)
1610 {
1611     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1612     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1613
1614     SignonIdentityPrivate *priv = self->priv;
1615     g_return_if_fail (priv != NULL);
1616
1617     IdentitySessionCbData *cb_data = g_slice_new0 (IdentitySessionCbData);
1618     cb_data->self = self;
1619     cb_data->session = session;
1620     cb_data->cb = cb;
1621
1622     IdentitySessionData *operation_data = g_slice_new0 (IdentitySessionData);
1623     operation_data->method = method;
1624     operation_data->cb_data = cb_data;
1625
1626     identity_check_remote_registration (self);
1627     _signon_object_call_when_ready (self,
1628                                     identity_object_quark(),
1629                                     identity_session_ready_cb,
1630                                     operation_data);
1631 }
1632