0f9b6d60591d61f3aaba491be7c2adbae4461511
[profile/ivi/libgsignon-glib.git] / libgsignon-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 libgsignon-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_OBJECT_CLASS (signon_identity_parent_class)->dispose (object);
301 }
302
303 static void
304 signon_identity_finalize (GObject *object)
305 {
306     SignonIdentity *identity = SIGNON_IDENTITY (object);
307     if (identity->priv->app_ctx)
308     {
309         g_free(identity->priv->app_ctx);
310         identity->priv->app_ctx = NULL;
311     }
312
313     G_OBJECT_CLASS (signon_identity_parent_class)->finalize (object);
314 }
315
316 static void
317 signon_identity_class_init (SignonIdentityClass *klass)
318 {
319     GObjectClass *object_class = G_OBJECT_CLASS (klass);
320     GParamSpec *pspec;
321
322     object_class->set_property = signon_identity_set_property;
323     object_class->get_property = signon_identity_get_property;
324
325     pspec = g_param_spec_uint ("id",
326                                "Identity ID",
327                                "Set/Get Identity ID",
328                                0,
329                                G_MAXUINT,
330                                0,
331                                G_PARAM_READWRITE);
332     g_object_class_install_property (object_class,
333                                      PROP_ID,
334                                      pspec);
335
336     pspec = g_param_spec_string ("app_ctx",
337                                  "Application Context",
338                                  "Set/Get Application Security Context",
339                                  "",
340                                  G_PARAM_READWRITE);
341     g_object_class_install_property (object_class,
342                                      PROP_APPCTX,
343                                      pspec);
344
345     g_type_class_add_private (object_class, sizeof (SignonIdentityPrivate));
346
347     /**
348      * SignonIdentity::signout:
349      *
350      * Emitted when the identity was signed out.
351      */
352     signals[SIGNEDOUT_SIGNAL] = g_signal_new("signout",
353                                     G_TYPE_FROM_CLASS (klass),
354                                     G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
355                                     0 /* class closure */,
356                                     NULL /* accumulator */,
357                                     NULL /* accu_data */,
358                                     g_cclosure_marshal_VOID__VOID,
359                                     G_TYPE_NONE /* return_type */,
360                                     0);
361
362     object_class->dispose = signon_identity_dispose;
363     object_class->finalize = signon_identity_finalize;
364 }
365
366 static void
367 identity_state_changed_cb (GDBusProxy *proxy,
368                            gint state,
369                            gpointer user_data)
370 {
371     g_return_if_fail (SIGNON_IS_IDENTITY (user_data));
372     SignonIdentity *self = SIGNON_IDENTITY (user_data);
373
374     switch (state) {
375         case DATA_UPDATED:
376             DEBUG ("State changed to DATA_UPDATED");
377             identity_process_updated (self);
378             break;
379         case IDENTITY_REMOVED:
380             DEBUG ("State changed to IDENTITY_REMOVED");
381             identity_process_removed (self);
382             break;
383         case IDENTITY_SIGNED_OUT:
384             DEBUG ("State changed to IDENTITY_SIGNED_OUT");
385             identity_process_signout (self);
386             break;
387         default:
388             g_critical ("wrong state value obtained from signon daemon");
389     };
390 }
391
392 static void
393 identity_remote_object_destroyed_cb(GDBusProxy *proxy,
394                                     gpointer user_data)
395 {
396     g_return_if_fail (SIGNON_IS_IDENTITY (user_data));
397     SignonIdentity *self = SIGNON_IDENTITY (user_data);
398
399     SignonIdentityPrivate *priv = self->priv;
400     g_return_if_fail (priv != NULL);
401
402     if (priv->proxy)
403     {
404         g_object_unref (priv->proxy);
405         priv->proxy = NULL;
406     }
407
408     DEBUG ("%s %d", G_STRFUNC, __LINE__);
409
410     _signon_object_not_ready(self);
411
412     priv->registration_state = NOT_REGISTERED;
413
414     signon_identity_info_free (priv->identity_info);
415     priv->identity_info = NULL;
416
417     priv->removed = FALSE;
418     priv->signed_out = FALSE;
419     priv->updated = FALSE;
420 }
421
422 static void
423 identity_registered (SignonIdentity *identity,
424                      char *object_path, GVariant *identity_data,
425                      GError *error)
426 {
427     g_return_if_fail (SIGNON_IS_IDENTITY (identity));
428
429     SignonIdentityPrivate *priv;
430     priv = identity->priv;
431
432     g_return_if_fail (priv != NULL);
433
434     if (!error)
435     {
436         GDBusConnection *connection;
437         GDBusProxy *auth_service_proxy;
438         const gchar *bus_name;
439         GError *proxy_error = NULL;
440
441         DEBUG("%s: %s", G_STRFUNC, object_path);
442         /*
443          * TODO: as Aurel will finalize the code polishing so we will
444          * need to implement the refresh of the proxy to SignonIdentity
445          * */
446         g_return_if_fail (priv->proxy == NULL);
447
448         auth_service_proxy = (GDBusProxy *)priv->auth_service_proxy;
449         connection = g_dbus_proxy_get_connection (auth_service_proxy);
450         bus_name = g_dbus_proxy_get_name (auth_service_proxy);
451
452         priv->proxy =
453             sso_identity_proxy_new_sync (connection,
454                                          G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
455                                          bus_name,
456                                          object_path,
457                                          priv->cancellable,
458                                          &proxy_error);
459         if (G_UNLIKELY (proxy_error != NULL))
460         {
461             g_warning ("Failed to initialize Identity proxy: %s",
462                        proxy_error->message);
463             g_clear_error (&proxy_error);
464         }
465
466         priv->signal_info_updated =
467             g_signal_connect (priv->proxy,
468                               "info-updated",
469                               G_CALLBACK (identity_state_changed_cb),
470                               identity);
471
472         priv->signal_unregistered =
473             g_signal_connect (priv->proxy,
474                               "unregistered",
475                               G_CALLBACK (identity_remote_object_destroyed_cb),
476                               identity);
477
478         if (identity_data)
479         {
480             DEBUG("%s: ", G_STRFUNC);
481             priv->identity_info =
482                 signon_identity_info_new_from_variant (identity_data);
483             g_variant_unref (identity_data);
484         }
485
486         priv->updated = TRUE;
487     }
488     else
489         g_warning ("%s: %s", G_STRFUNC, error->message);
490
491     /*
492      * execute queued operations or emit errors on each of them
493      * */
494     priv->registration_state = REGISTERED;
495
496     /*
497      * TODO: if we will add a new state for identity: "INVALID"
498      * consider emission of another error, like "invalid"
499      * */
500     _signon_object_ready (identity, identity_object_quark (), error);
501
502     /*
503      * as the registration failed we do not
504      * request for new registration, but emit
505      * same error again and again
506      * */
507 }
508
509 /**
510  * signon_identity_get_last_error:
511  * @identity: the #SignonIdentity.
512  *
513  * Get the most recent error that occurred on @identity.
514  *
515  * Returns: a #GError containing the most recent error, or %NULL on failure.
516  */
517 const GError *
518 signon_identity_get_last_error (SignonIdentity *identity)
519 {
520     g_return_val_if_fail (SIGNON_IS_IDENTITY (identity), NULL);
521     return _signon_object_last_error(identity);
522 }
523
524 static void
525 identity_new_cb (GObject *object, GAsyncResult *res,
526                  gpointer userdata)
527 {
528     SignonIdentity *identity = (SignonIdentity*)userdata;
529     SsoAuthService *proxy = SSO_AUTH_SERVICE (object);
530     gchar *object_path = NULL;
531     GError *error = NULL;
532
533     g_return_if_fail (identity != NULL);
534     DEBUG ("%s", G_STRFUNC);
535
536     sso_auth_service_call_register_new_identity_finish (proxy,
537                                                         &object_path,
538                                                         res,
539                                                         &error);
540     if (SIGNON_IS_NOT_CANCELLED (error))
541     {
542         identity_registered (identity, object_path, NULL, error);
543     }
544     if (object_path) g_free (object_path);
545     g_clear_error (&error);
546 }
547
548 static void
549 identity_new_from_db_cb (GObject *object, GAsyncResult *res,
550                          gpointer userdata)
551 {
552     SignonIdentity *identity = (SignonIdentity*)userdata;
553     SsoAuthService *proxy = SSO_AUTH_SERVICE (object);
554     gchar *object_path = NULL;
555     GVariant *identity_data;
556     GError *error = NULL;
557
558     g_return_if_fail (identity != NULL);
559     DEBUG ("%s", G_STRFUNC);
560
561     sso_auth_service_call_get_identity_finish (proxy,
562                                                &object_path,
563                                                &identity_data,
564                                                res,
565                                                &error);
566     if (SIGNON_IS_NOT_CANCELLED (error))
567     {
568         identity_registered (identity, object_path, identity_data, error);
569     }
570     if (object_path) g_free (object_path);
571     g_clear_error (&error);
572 }
573
574 static void
575 identity_check_remote_registration (SignonIdentity *self)
576 {
577     g_return_if_fail (self != NULL);
578     SignonIdentityPrivate *priv = self->priv;
579
580     g_return_if_fail (priv != NULL);
581
582     if (priv->registration_state != NOT_REGISTERED)
583         return;
584
585     if (priv->id != 0)
586         sso_auth_service_call_get_identity (priv->auth_service_proxy,
587                                             priv->id,
588                                             priv->app_ctx,
589                                             priv->cancellable,
590                                             identity_new_from_db_cb,
591                                             self);
592     else
593         sso_auth_service_call_register_new_identity (priv->auth_service_proxy,
594                                                      priv->app_ctx,
595                                                      priv->cancellable,
596                                                      identity_new_cb,
597                                                      self);
598
599     priv->registration_state = PENDING_REGISTRATION;
600 }
601
602 /**
603  * signon_identity_new_from_db:
604  * @id: identity ID.
605  * @application_context: application security context, can be %NULL.
606  *
607  * Construct an identity object associated with an existing identity
608  * record.
609  *
610  * Returns: an instance of a #SignonIdentity.
611  */
612 SignonIdentity*
613 signon_identity_new_from_db (guint32 id, const gchar *application_context)
614 {
615     SignonIdentity *identity;
616     DEBUG ("%s %d: %d\n", G_STRFUNC, __LINE__, id);
617     if (id == 0)
618         return NULL;
619
620     identity = g_object_new (SIGNON_TYPE_IDENTITY,
621                              "id", id,
622                              "app_ctx", application_context,
623                              NULL);
624     g_return_val_if_fail (SIGNON_IS_IDENTITY (identity), NULL);
625     g_return_val_if_fail (identity->priv != NULL, NULL);
626
627     identity->priv->id = id;
628     identity->priv->app_ctx = (application_context) ?
629         g_strdup (application_context) : g_strdup ("");
630     identity_check_remote_registration (identity);
631
632     return identity;
633 }
634
635 /**
636  * signon_identity_new:
637  * @application_context: application security context, can be %NULL.
638  *
639  * Construct new, empty, identity object.
640  *
641  * Returns: an instance of an #SignonIdentity.
642  */
643 SignonIdentity*
644 signon_identity_new (const gchar *application_context)
645 {
646     DEBUG ("%s %d", G_STRFUNC, __LINE__);
647     SignonIdentity *identity = g_object_new (
648                                      SIGNON_TYPE_IDENTITY,
649                                      "app_ctx", application_context,
650                                      NULL);
651     g_return_val_if_fail (SIGNON_IS_IDENTITY (identity), NULL);
652     g_return_val_if_fail (identity->priv != NULL, NULL);
653
654     identity->priv->app_ctx = (application_context) ?
655         g_strdup (application_context) : g_strdup ("");
656     identity_check_remote_registration (identity);
657
658     return identity;
659 }
660
661 /**
662  * signon_identity_create_session:
663  * @self: the #SignonIdentity.
664  * @method: method.
665  * @error: pointer to a location which will receive the error, if any.
666  *
667  * Creates an authentication session for this identity.
668  *
669  * Returns: (transfer full): a new #SignonAuthSession.
670  */
671 SignonAuthSession *
672 signon_identity_create_session(SignonIdentity *self,
673                                const gchar *method,
674                                GError **error)
675 {
676     g_return_val_if_fail (SIGNON_IS_IDENTITY (self), NULL);
677
678     SignonIdentityPrivate *priv = self->priv;
679     g_return_val_if_fail (priv != NULL, NULL);
680
681     DEBUG ("%s %d", G_STRFUNC, __LINE__);
682
683     if (method == NULL)
684     {
685         DEBUG ("NULL method as input. Aborting.");
686         g_set_error(error,
687                     signon_error_quark(),
688                     SIGNON_ERROR_UNKNOWN,
689                     "NULL input method.");
690         return NULL;
691     }
692
693     GSList *list = priv->sessions;
694     while (list)
695     {
696         SignonAuthSession *session = SIGNON_AUTH_SESSION (priv->sessions->data);
697         const gchar *sessionMethod = signon_auth_session_get_method (session);
698         if (g_strcmp0(sessionMethod, method) == 0)
699         {
700             DEBUG ("Auth Session with method `%s` already created.", method);
701             g_set_error (error,
702                          signon_error_quark(),
703                          SIGNON_ERROR_METHOD_NOT_AVAILABLE,
704                          "Authentication session for this method already requested.");
705             return NULL;
706         }
707
708         list = list->next;
709     }
710
711     SignonAuthSession *session = signon_auth_session_new (G_OBJECT(self),
712                                                           method,
713                                                           error);
714     if (session)
715     {
716         DEBUG ("%s %d - success", G_STRFUNC, __LINE__);
717         priv->sessions = g_slist_append(priv->sessions, session);
718         g_object_weak_ref (G_OBJECT(session),
719                            identity_session_object_destroyed_cb,
720                            self);
721         /*
722          * if you want to delete the identity
723          * you MUST delete all authsessions
724          * first
725          * */
726         g_object_ref (self);
727         priv->signed_out = FALSE;
728     }
729
730     return session;
731 }
732
733 /**
734  * signon_identity_store_credentials_with_info:
735  * @self: the #SignonIdentity.
736  * @info: the #SignonIdentityInfo data to store.
737  * @cb: (scope async): callback.
738  * @user_data: user_data.
739  *
740  * Stores the data from @info into the identity.
741  */
742 void
743 signon_identity_store_credentials_with_info(SignonIdentity *self,
744                                             const SignonIdentityInfo *info,
745                                             SignonIdentityStoreCredentialsCb cb,
746                                             gpointer user_data)
747 {
748     IdentityStoreCredentialsCbData *cb_data;
749     IdentityStoreCredentialsData *operation_data;
750
751     DEBUG ();
752     g_return_if_fail (SIGNON_IS_IDENTITY (self));
753     g_return_if_fail (info != NULL);
754
755     SignonIdentityPrivate *priv = self->priv;
756     if (priv->identity_info)
757         signon_identity_info_free (priv->identity_info);
758     priv->identity_info = signon_identity_info_copy (info);
759
760     cb_data = g_slice_new0 (IdentityStoreCredentialsCbData);
761     cb_data->self = self;
762     cb_data->cb = cb;
763     cb_data->user_data = user_data;
764
765     operation_data = g_slice_new0 (IdentityStoreCredentialsData);
766     operation_data->info_variant = signon_identity_info_to_variant (info);
767     operation_data->cb_data = cb_data;
768
769     identity_check_remote_registration (self);
770     _signon_object_call_when_ready (self,
771                                     identity_object_quark(),
772                                     identity_store_credentials_ready_cb,
773                                     operation_data);
774 }
775
776 /**
777  * signon_identity_store_credentials_with_args:
778  * @self: the #SignonIdentity.
779  * @username: username.
780  * @secret: secret.
781  * @store_secret: whether signond should store the password.
782  * @methods: (transfer none) (element-type utf8 GStrv): methods.
783  * @caption: caption.
784  * @realms: realms.
785  * @owner: owner.
786  * @access_control_list: access control list.
787  * @type: the type of the identity.
788  * @cb: (scope async): callback.
789  * @user_data: user_data.
790  *
791  * Stores the given data into the identity.
792  */
793 void signon_identity_store_credentials_with_args(SignonIdentity *self,
794                                                  const gchar *username,
795                                                  const gchar *secret,
796                                                  const gboolean store_secret,
797                                                  const GHashTable *methods,
798                                                  const gchar *caption,
799                                                  const gchar* const *realms,
800                                                  const SignonSecurityContext *owner,
801                                                  const SignonSecurityContextList *access_control_list,
802                                                  SignonIdentityType type,
803                                                  SignonIdentityStoreCredentialsCb cb,
804                                                  gpointer user_data)
805 {
806     SignonIdentityInfo *info;
807
808     g_return_if_fail (SIGNON_IS_IDENTITY (self));
809
810     info = signon_identity_info_new ();
811     signon_identity_info_set_username (info, username);
812     signon_identity_info_set_secret (info, secret, store_secret);
813     signon_identity_info_set_methods (info, methods);
814     signon_identity_info_set_caption (info, caption);
815     signon_identity_info_set_realms (info, realms);
816     if (owner)
817     {
818         signon_identity_info_set_owner (info, owner);
819     }
820     if (access_control_list)
821     {
822         signon_identity_info_set_access_control_list (info,
823                                                       access_control_list);
824     }
825     signon_identity_info_set_identity_type (info, type);
826
827     signon_identity_store_credentials_with_info (self, info, cb, user_data);
828     signon_identity_info_free (info);
829 }
830
831 static void
832 identity_store_credentials_ready_cb (gpointer object, const GError *error, gpointer user_data)
833 {
834     g_return_if_fail (SIGNON_IS_IDENTITY (object));
835
836     SignonIdentity *self = SIGNON_IDENTITY (object);
837     SignonIdentityPrivate *priv = self->priv;
838     g_return_if_fail (priv != NULL);
839
840     DEBUG ("%s %d", G_STRFUNC, __LINE__);
841
842     IdentityStoreCredentialsData *operation_data =
843         (IdentityStoreCredentialsData *)user_data;
844     g_return_if_fail (operation_data != NULL);
845
846     IdentityStoreCredentialsCbData *cb_data = operation_data->cb_data;
847     g_return_if_fail (cb_data != NULL);
848
849     if (error)
850     {
851         DEBUG ("IdentityError: %s", error->message);
852
853         if (cb_data->cb)
854         {
855             (cb_data->cb) (self, 0, error, cb_data->user_data);
856         }
857
858         g_slice_free (IdentityStoreCredentialsCbData, cb_data);
859     }
860     else
861     {
862         g_return_if_fail (priv->proxy != NULL);
863
864         sso_identity_call_store (priv->proxy,
865                                  operation_data->info_variant,
866                                  priv->cancellable,
867                                  identity_store_credentials_reply,
868                                  cb_data);
869     }
870
871     g_slice_free (IdentityStoreCredentialsData, operation_data);
872 }
873
874 static void
875 identity_store_credentials_reply (GObject *object, GAsyncResult *res,
876                                   gpointer userdata)
877 {
878     IdentityStoreCredentialsCbData *cb_data = (IdentityStoreCredentialsCbData *)userdata;
879     SsoIdentity *proxy = SSO_IDENTITY (object);
880     guint id;
881     GError *error = NULL;
882
883     g_return_if_fail (cb_data != NULL);
884     g_return_if_fail (cb_data->self != NULL);
885     g_return_if_fail (cb_data->self->priv != NULL);
886
887     SignonIdentityPrivate *priv = cb_data->self->priv;
888
889     sso_identity_call_store_finish (proxy, &id, res, &error);
890
891     if (error == NULL)
892     {
893         g_return_if_fail (priv->identity_info == NULL);
894
895         g_object_set (cb_data->self, "id", id, NULL);
896         cb_data->self->priv->id = id;
897
898         /*
899          * if the previous state was REMOVED
900          * then we need to reset it
901          * */
902         priv->removed = FALSE;
903     }
904
905     if (SIGNON_IS_NOT_CANCELLED (error) && cb_data->cb)
906     {
907         (cb_data->cb) (cb_data->self, id, error, cb_data->user_data);
908     }
909
910     g_clear_error(&error);
911     g_slice_free (IdentityStoreCredentialsCbData, cb_data);
912 }
913
914 static void
915 identity_verify_reply (GObject *object, GAsyncResult *res,
916                        gpointer userdata)
917 {
918     SsoIdentity *proxy = SSO_IDENTITY (object);
919     gboolean valid;
920     GError *error = NULL;
921     IdentityVerifyCbData *cb_data = (IdentityVerifyCbData *)userdata;
922
923     g_return_if_fail (cb_data != NULL);
924     g_return_if_fail (cb_data->self != NULL);
925
926     sso_identity_call_verify_secret_finish (proxy, &valid, res, &error);
927
928     if (SIGNON_IS_NOT_CANCELLED (error) && cb_data->cb)
929     {
930         (cb_data->cb) (cb_data->self, valid, error, cb_data->user_data);
931     }
932
933     g_clear_error(&error);
934     g_slice_free (IdentityVerifyCbData, cb_data);
935 }
936
937 static void
938 identity_verify_ready_cb (gpointer object, const GError *error, gpointer user_data)
939 {
940     g_return_if_fail (SIGNON_IS_IDENTITY (object));
941
942     SignonIdentity *self = SIGNON_IDENTITY (object);
943     SignonIdentityPrivate *priv = self->priv;
944     g_return_if_fail (priv != NULL);
945
946     DEBUG ("%s %d", G_STRFUNC, __LINE__);
947
948     IdentityVerifyData *operation_data =
949         (IdentityVerifyData *)user_data;
950     g_return_if_fail (operation_data != NULL);
951
952     IdentityVerifyCbData *cb_data = operation_data->cb_data;
953     g_return_if_fail (cb_data != NULL);
954
955     if (priv->removed == TRUE)
956     {
957         GError *new_error = g_error_new (signon_error_quark(),
958                                          SIGNON_ERROR_IDENTITY_NOT_FOUND,
959                                          "Already removed from database.");
960
961         if (cb_data->cb)
962         {
963             (cb_data->cb) (self, FALSE, new_error, cb_data->user_data);
964         }
965
966         g_error_free (new_error);
967         g_slice_free (IdentityVerifyCbData, cb_data);
968     }
969     else if (error)
970     {
971         DEBUG ("IdentityError: %s", error->message);
972
973         if (cb_data->cb)
974         {
975             (cb_data->cb) (self, FALSE, error, cb_data->user_data);
976         }
977
978         g_slice_free (IdentityVerifyCbData, cb_data);
979     }
980     else
981     {
982         DEBUG ("%s %d", G_STRFUNC, __LINE__);
983         g_return_if_fail (priv->proxy != NULL);
984
985         switch (operation_data->operation) {
986         case SIGNON_VERIFY_SECRET:
987             sso_identity_call_verify_secret (priv->proxy,
988                                              operation_data->data_to_send,
989                                              priv->cancellable,
990                                              identity_verify_reply,
991                                              cb_data);
992             break;
993         default: g_critical ("Wrong operation code");
994         };
995     }
996     g_free (operation_data->params);
997     g_free (operation_data->data_to_send);
998     g_slice_free (IdentityVerifyData, operation_data);
999 }
1000
1001 static void
1002 identity_verify_data(SignonIdentity *self,
1003                      const gchar *data_to_send,
1004                      gint operation,
1005                      SignonIdentityVerifyCb cb,
1006                      gpointer user_data)
1007 {
1008     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1009
1010     SignonIdentityPrivate *priv = self->priv;
1011     g_return_if_fail (priv != NULL);
1012
1013     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1014
1015     IdentityVerifyCbData *cb_data = g_slice_new0 (IdentityVerifyCbData);
1016     cb_data->self = self;
1017     cb_data->cb = cb;
1018     cb_data->user_data = user_data;
1019
1020     IdentityVerifyData *operation_data = g_slice_new0 (IdentityVerifyData);
1021
1022     operation_data->params = NULL;
1023     operation_data->data_to_send = g_strdup (data_to_send);
1024     operation_data->operation = operation;
1025     operation_data->cb_data = cb_data;
1026
1027     identity_check_remote_registration (self);
1028     _signon_object_call_when_ready (self,
1029                                     identity_object_quark(),
1030                                     identity_verify_ready_cb,
1031                                     operation_data);
1032 }
1033
1034 /**
1035  * signon_identity_verify_secret:
1036  * @self: the #SignonIdentity.
1037  * @secret: the secret (password) to be verified.
1038  * @cb: (scope async): callback.
1039  * @user_data: user_data.
1040  *
1041  * Verifies the given secret.
1042  */
1043 void signon_identity_verify_secret(SignonIdentity *self,
1044                                   const gchar *secret,
1045                                   SignonIdentityVerifyCb cb,
1046                                   gpointer user_data)
1047 {
1048     identity_verify_data (self,
1049                           secret,
1050                           SIGNON_VERIFY_SECRET,
1051                           cb,
1052                           user_data);
1053 }
1054
1055 static void
1056 identity_process_updated (SignonIdentity *self)
1057 {
1058     DEBUG ("%d %s", __LINE__, __func__);
1059
1060     g_return_if_fail (self != NULL);
1061     g_return_if_fail (self->priv != NULL);
1062
1063     SignonIdentityPrivate *priv = self->priv;
1064     g_return_if_fail (priv->proxy != NULL);
1065
1066     signon_identity_info_free (priv->identity_info);
1067     priv->identity_info = NULL;
1068     priv->updated = FALSE;
1069
1070     DEBUG ("%s info freed, to be updated", __func__);
1071 }
1072
1073 static void
1074 identity_process_removed (SignonIdentity *self)
1075 {
1076     g_return_if_fail (self != NULL);
1077     g_return_if_fail (self->priv != NULL);
1078
1079     DEBUG ("%d %s", __LINE__, __func__);
1080
1081     SignonIdentityPrivate *priv = self->priv;
1082
1083     if (priv->removed == TRUE)
1084         return;
1085
1086     priv->removed = TRUE;
1087     signon_identity_info_free (priv->identity_info);
1088     priv->identity_info = NULL;
1089
1090     g_object_set (self, "id", 0, NULL);
1091     priv->id = 0;
1092 }
1093
1094 static void
1095 identity_process_signout(SignonIdentity *self)
1096 {
1097     g_return_if_fail (self != NULL);
1098     g_return_if_fail (self->priv != NULL);
1099
1100     DEBUG ("%d %s", __LINE__, __func__);
1101     SignonIdentityPrivate *priv = self->priv;
1102
1103     if (priv->signed_out == TRUE)
1104         return;
1105
1106     GSList *llink = priv->sessions;
1107     while (llink)
1108     {
1109         GSList *next = llink->next;
1110         g_object_unref (G_OBJECT(llink->data));
1111         llink = next;
1112     }
1113
1114     priv->signed_out = TRUE;
1115     g_signal_emit(G_OBJECT(self), signals[SIGNEDOUT_SIGNAL], 0);
1116 }
1117
1118 /*
1119  * TODO: fix the implementation
1120  * of signond: it returns result = TRUE
1121  * in ANY CASE
1122  * */
1123 static void
1124 identity_signout_reply (GObject *object, GAsyncResult *res,
1125                         gpointer userdata)
1126 {
1127     SsoIdentity *proxy = SSO_IDENTITY (object);
1128     gboolean result;
1129     GError *error = NULL;
1130     IdentityVoidCbData *cb_data = (IdentityVoidCbData *)userdata;
1131
1132     g_return_if_fail (cb_data != NULL);
1133     g_return_if_fail (cb_data->self != NULL);
1134     g_return_if_fail (cb_data->self->priv != NULL);
1135
1136     sso_identity_call_sign_out_finish (proxy, &result, res, &error);
1137
1138     if (SIGNON_IS_NOT_CANCELLED (error) && cb_data->cb)
1139     {
1140         (cb_data->cb) (cb_data->self, error, cb_data->user_data);
1141     }
1142
1143     g_clear_error(&error);
1144     g_slice_free (IdentityVoidCbData, cb_data);
1145 }
1146
1147 static void
1148 identity_removed_reply (GObject *object, GAsyncResult *res,
1149                         gpointer userdata)
1150 {
1151     SsoIdentity *proxy = SSO_IDENTITY (object);
1152     GError *error = NULL;
1153     IdentityVoidCbData *cb_data = (IdentityVoidCbData *)userdata;
1154
1155     g_return_if_fail (cb_data != NULL);
1156     g_return_if_fail (cb_data->self != NULL);
1157     g_return_if_fail (cb_data->self->priv != NULL);
1158
1159     sso_identity_call_remove_finish (proxy, res, &error);
1160
1161     if (SIGNON_IS_NOT_CANCELLED (error) && cb_data->cb)
1162     {
1163         (cb_data->cb) (cb_data->self, error, cb_data->user_data);
1164     }
1165
1166     g_clear_error(&error);
1167     g_slice_free (IdentityVoidCbData, cb_data);
1168 }
1169
1170 static void
1171 identity_info_reply(GObject *object, GAsyncResult *res,
1172                     gpointer userdata)
1173 {
1174     SsoIdentity *proxy = SSO_IDENTITY (object);
1175     GVariant *identity_data = NULL;
1176     DEBUG ("%d %s", __LINE__, __func__);
1177
1178     GError *error = NULL;
1179     IdentityInfoCbData *cb_data = (IdentityInfoCbData *)userdata;
1180
1181     g_return_if_fail (cb_data != NULL);
1182     g_return_if_fail (cb_data->self != NULL);
1183     g_return_if_fail (cb_data->self->priv != NULL);
1184
1185     SignonIdentityPrivate *priv = cb_data->self->priv;
1186
1187     sso_identity_call_get_info_finish (proxy, &identity_data, res, &error);
1188
1189     if (identity_data != NULL)
1190     {
1191         priv->identity_info =
1192                 signon_identity_info_new_from_variant (identity_data);
1193         g_variant_unref (identity_data);
1194     }
1195
1196     if (SIGNON_IS_NOT_CANCELLED (error) && cb_data->cb)
1197     {
1198         (cb_data->cb) (cb_data->self, priv->identity_info, error, cb_data->user_data);
1199     }
1200
1201     g_clear_error(&error);
1202     g_slice_free (IdentityInfoCbData, cb_data);
1203
1204     priv->updated = TRUE;
1205 }
1206
1207 static void
1208 identity_info_ready_cb(gpointer object, const GError *error, gpointer user_data)
1209 {
1210     g_return_if_fail (SIGNON_IS_IDENTITY (object));
1211
1212     SignonIdentity *self = SIGNON_IDENTITY (object);
1213     SignonIdentityPrivate *priv = self->priv;
1214     g_return_if_fail (priv != NULL);
1215
1216     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1217
1218     IdentityVoidData *operation_data =
1219         (IdentityVoidData *)user_data;
1220     g_return_if_fail (operation_data != NULL);
1221
1222     IdentityInfoCbData *cb_data = operation_data->cb_data;
1223     g_return_if_fail (cb_data != NULL);
1224
1225     if (priv->removed == TRUE)
1226     {
1227         DEBUG ("%s identity removed", G_STRFUNC);
1228
1229         GError *new_error = g_error_new (signon_error_quark(),
1230                                          SIGNON_ERROR_IDENTITY_NOT_FOUND,
1231                                          "Already removed from database.");
1232         if (cb_data->cb)
1233             (cb_data->cb) (self, NULL, new_error, cb_data->user_data);
1234
1235         g_error_free (new_error);
1236     }
1237     else if (error || priv->id == 0)
1238     {
1239         DEBUG ("%s identity is new", G_STRFUNC);
1240
1241         if (error)
1242             DEBUG ("IdentityError: %s", error->message);
1243         else
1244             DEBUG ("Identity is not stored and has no info yet");
1245
1246         if (cb_data->cb)
1247             (cb_data->cb) (self, NULL, error, cb_data->user_data);
1248     }
1249     else if (priv->updated == FALSE)
1250     {
1251         DEBUG ("%s identity needs update, call daemon", G_STRFUNC);
1252
1253         g_return_if_fail (priv->proxy != NULL);
1254         sso_identity_call_get_info (priv->proxy,
1255                                     priv->cancellable,
1256                                     identity_info_reply,
1257                                     cb_data);
1258         goto free_op_data;
1259     }
1260     else
1261     {
1262         DEBUG ("%s pass existing one", G_STRFUNC);
1263
1264         if (cb_data->cb)
1265             (cb_data->cb) (self, priv->identity_info, error, cb_data->user_data);
1266     }
1267
1268     g_slice_free (IdentityInfoCbData, cb_data);
1269
1270 free_op_data:
1271     g_slice_free (IdentityVoidData, operation_data);
1272 }
1273
1274 static void
1275 identity_signout_ready_cb(gpointer object, const GError *error, gpointer user_data)
1276 {
1277     g_return_if_fail (SIGNON_IS_IDENTITY (object));
1278
1279     SignonIdentity *self = SIGNON_IDENTITY (object);
1280     SignonIdentityPrivate *priv = self->priv;
1281     g_return_if_fail (priv != NULL);
1282
1283     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1284     IdentityVoidCbData *cb_data = (IdentityVoidCbData *)user_data;
1285
1286     g_return_if_fail (cb_data != NULL);
1287
1288     if (priv->removed == TRUE)
1289     {
1290         GError *new_error = g_error_new (signon_error_quark(),
1291                                          SIGNON_ERROR_IDENTITY_NOT_FOUND,
1292                                          "Already removed from database.");
1293         if (cb_data->cb)
1294         {
1295             (cb_data->cb) (self, new_error, cb_data->user_data);
1296         }
1297
1298         g_error_free (new_error);
1299         g_slice_free (IdentityVoidCbData, cb_data);
1300     }
1301     else if (error)
1302     {
1303         DEBUG ("IdentityError: %s", error->message);
1304         if (cb_data->cb)
1305         {
1306             (cb_data->cb) (self, error, cb_data->user_data);
1307         }
1308
1309         g_slice_free (IdentityVoidCbData, cb_data);
1310     }
1311     else
1312     {
1313         g_return_if_fail (priv->proxy != NULL);
1314         sso_identity_call_sign_out (priv->proxy,
1315                                     priv->cancellable,
1316                                     identity_signout_reply,
1317                                     cb_data);
1318     }
1319 }
1320
1321 static void
1322 identity_remove_ready_cb(gpointer object, const GError *error, gpointer user_data)
1323 {
1324     g_return_if_fail (SIGNON_IS_IDENTITY (object));
1325
1326     SignonIdentity *self = SIGNON_IDENTITY (object);
1327     SignonIdentityPrivate *priv = self->priv;
1328     g_return_if_fail (priv != NULL);
1329
1330     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1331     IdentityVoidCbData *cb_data = (IdentityVoidCbData *)user_data;
1332     g_return_if_fail (cb_data != NULL);
1333
1334     if (priv->removed == TRUE)
1335     {
1336         GError *new_error = g_error_new (signon_error_quark(),
1337                                           SIGNON_ERROR_IDENTITY_NOT_FOUND,
1338                                          "Already removed from database.");
1339         if (cb_data->cb)
1340         {
1341             (cb_data->cb) (self, new_error, cb_data->user_data);
1342         }
1343
1344         g_error_free (new_error);
1345         g_slice_free (IdentityVoidCbData, cb_data);
1346     }
1347     else if (error)
1348     {
1349         DEBUG ("IdentityError: %s", error->message);
1350         if (cb_data->cb)
1351         {
1352             (cb_data->cb) (self, error, cb_data->user_data);
1353         }
1354
1355         g_slice_free (IdentityVoidCbData, cb_data);
1356     }
1357     else
1358     {
1359         g_return_if_fail (priv->proxy != NULL);
1360         sso_identity_call_remove (priv->proxy,
1361                                   priv->cancellable,
1362                                   identity_removed_reply,
1363                                   cb_data);
1364     }
1365 }
1366
1367 void static
1368 identity_void_operation(SignonIdentity *self,
1369                         gint operation,
1370                         gpointer cb_data)
1371 {
1372     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1373
1374     SignonIdentityPrivate *priv = self->priv;
1375     g_return_if_fail (priv != NULL);
1376
1377     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1378
1379     IdentityVoidData *operation_data = g_slice_new0 (IdentityVoidData);
1380     operation_data->cb_data = cb_data;
1381     _signon_object_call_when_ready (self,
1382                                     identity_object_quark(),
1383                                     identity_info_ready_cb,
1384                                     operation_data);
1385 }
1386
1387 /**
1388  * signon_identity_remove:
1389  * @self: the #SignonIdentity.
1390  * @cb: (scope async): callback to be called when the operation has completed.
1391  * @user_data: user_data to pass to the callback.
1392  *
1393  * Removes the corresponding credentials record from the database.
1394  */
1395 void signon_identity_remove(SignonIdentity *self,
1396                            SignonIdentityRemovedCb cb,
1397                            gpointer user_data)
1398 {
1399     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1400
1401     SignonIdentityPrivate *priv = self->priv;
1402     g_return_if_fail (priv != NULL);
1403
1404     IdentityVoidCbData *cb_data = g_slice_new0 (IdentityVoidCbData);
1405     cb_data->self = self;
1406     cb_data->cb = (SignonIdentityVoidCb)cb;
1407     cb_data->user_data = user_data;
1408
1409     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1410
1411     identity_check_remote_registration (self);
1412     _signon_object_call_when_ready (self,
1413                                     identity_object_quark(),
1414                                     identity_remove_ready_cb,
1415                                     cb_data);
1416 }
1417
1418 /**
1419  * signon_identity_signout:
1420  * @self: the #SignonIdentity.
1421  * @cb: (scope async): callback.
1422  * @user_data: user_data.
1423  *
1424  * Asks signond to close all authentication sessions for this
1425  * identity, and to remove any stored secrets associated with it (password and
1426  * authentication tokens).
1427  */
1428 void signon_identity_signout(SignonIdentity *self,
1429                              SignonIdentitySignedOutCb cb,
1430                              gpointer user_data)
1431 {
1432     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1433
1434     SignonIdentityPrivate *priv = self->priv;
1435     g_return_if_fail (priv != NULL);
1436
1437     IdentityVoidCbData *cb_data = g_slice_new0 (IdentityVoidCbData);
1438     cb_data->self = self;
1439     cb_data->cb = (SignonIdentityVoidCb)cb;
1440     cb_data->user_data = user_data;
1441
1442     identity_check_remote_registration (self);
1443     _signon_object_call_when_ready (self,
1444                                     identity_object_quark(),
1445                                     identity_signout_ready_cb,
1446                                     cb_data);
1447 }
1448
1449 /**
1450  * signon_identity_add_reference:
1451  * @self: the #SignonIdentity.
1452  * @reference: reference to be added
1453  * @cb: callback
1454  * @user_data: user_data.
1455  *
1456  * Adds named reference to identity
1457  */
1458 void signon_identity_add_reference(SignonIdentity *self,
1459                              const gchar *reference,
1460                              SignonIdentityReferenceAddedCb cb,
1461                              gpointer user_data)
1462 {
1463     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1464
1465     SignonIdentityPrivate *priv = self->priv;
1466     g_return_if_fail (priv != NULL);
1467
1468     //TODO implement
1469
1470     if (cb)
1471         (cb) (self, NULL, user_data);
1472 }
1473
1474 /**
1475  * signon_identity_remove_reference:
1476  * @self: the #SignonIdentity.
1477  * @reference: reference to be removed
1478  * @cb: callback
1479  * @user_data: user_data.
1480  *
1481  * Removes named reference from identity
1482  */
1483 void signon_identity_remove_reference(SignonIdentity *self,
1484                              const gchar *reference,
1485                              SignonIdentityReferenceRemovedCb cb,
1486                              gpointer user_data)
1487 {
1488     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1489
1490     SignonIdentityPrivate *priv = self->priv;
1491     g_return_if_fail (priv != NULL);
1492
1493     //TODO implement
1494
1495     if (cb)
1496         (cb) (self, NULL, user_data);
1497 }
1498
1499 /**
1500  * signon_identity_query_info:
1501  * @self: the #SignonIdentity.
1502  * @cb: (scope async): callback.
1503  * @user_data: user_data.
1504  *
1505  * Fetches the #SignonIdentityInfo data associated with this
1506  * identity.
1507  */
1508 void signon_identity_query_info(SignonIdentity *self,
1509                                 SignonIdentityInfoCb cb,
1510                                 gpointer user_data)
1511 {
1512     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1513
1514     SignonIdentityPrivate *priv = self->priv;
1515     g_return_if_fail (priv != NULL);
1516
1517     IdentityInfoCbData *cb_data = g_slice_new0 (IdentityInfoCbData);
1518     cb_data->self = self;
1519     cb_data->cb = cb;
1520     cb_data->user_data = user_data;
1521
1522     identity_check_remote_registration (self);
1523     identity_void_operation(self,
1524                             SIGNON_INFO,
1525                             cb_data);
1526 }
1527
1528 static void
1529 identity_get_auth_session_reply (GObject *object, GAsyncResult *res,
1530                                  gpointer userdata)
1531 {
1532     SsoIdentity *proxy = SSO_IDENTITY (object);
1533     gchar *object_path = NULL;
1534     GError *error = NULL;
1535
1536     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1537
1538     sso_identity_call_get_auth_session_finish (proxy,
1539                                                &object_path,
1540                                                res,
1541                                                &error);
1542
1543     IdentitySessionCbData *cb_data = (IdentitySessionCbData *) userdata;
1544     g_return_if_fail (cb_data != NULL);
1545     g_return_if_fail (cb_data->cb != NULL);
1546
1547     if (SIGNON_IS_NOT_CANCELLED (error))
1548     {
1549         (cb_data->cb) (cb_data->session,
1550                 error,
1551                 g_dbus_proxy_get_connection ((GDBusProxy *)proxy),
1552                 g_dbus_proxy_get_name ((GDBusProxy *)proxy),
1553                 object_path);
1554     }
1555     g_slice_free (IdentitySessionCbData, cb_data);
1556     if (object_path) g_free (object_path);
1557     g_clear_error (&error);
1558 }
1559
1560 static void
1561 identity_session_ready_cb(gpointer object, const GError *error, gpointer user_data)
1562 {
1563     g_return_if_fail (SIGNON_IS_IDENTITY (object));
1564     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1565
1566     SignonIdentity *self = SIGNON_IDENTITY (object);
1567     SignonIdentityPrivate *priv = self->priv;
1568     g_return_if_fail (priv != NULL);
1569
1570     IdentitySessionData *operation_data = (IdentitySessionData *) user_data;
1571     g_return_if_fail (operation_data != NULL);
1572
1573     IdentitySessionCbData *cb_data = operation_data->cb_data;
1574     g_return_if_fail (cb_data != NULL);
1575     g_return_if_fail (cb_data->cb != NULL);
1576
1577     if (error)
1578     {
1579         (cb_data->cb) (cb_data->session, (GError *)error, NULL, NULL, NULL);
1580     }
1581     else if (priv->removed == TRUE)
1582     {
1583         GError *new_error = g_error_new (signon_error_quark(),
1584                                          SIGNON_ERROR_IDENTITY_NOT_FOUND,
1585                                          "Already removed from database.");
1586         (cb_data->cb) (cb_data->session, new_error, NULL, NULL, NULL);
1587         g_error_free (new_error);
1588     }
1589     else
1590     {
1591         g_return_if_fail (priv->proxy != NULL);
1592
1593         sso_identity_call_get_auth_session (
1594             priv->proxy,
1595             operation_data->method,
1596             priv->cancellable,
1597             identity_get_auth_session_reply,
1598             cb_data);
1599     }
1600
1601     g_slice_free (IdentitySessionData, operation_data);
1602 }
1603
1604 static void
1605 identity_session_object_destroyed_cb(gpointer data,
1606                                      GObject *where_the_session_was)
1607 {
1608     g_return_if_fail (SIGNON_IS_IDENTITY (data));
1609     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1610
1611     SignonIdentity *self = SIGNON_IDENTITY (data);
1612     SignonIdentityPrivate *priv = self->priv;
1613     g_return_if_fail (priv != NULL);
1614
1615     priv->sessions = g_slist_remove(priv->sessions, (gpointer)where_the_session_was);
1616     g_object_unref (self);
1617 }
1618
1619 /**
1620  * signon_identity_get_auth_session:
1621  * @self: the #SignonIdentity.
1622  * @session: the #SignonAuthSession object to get the remote object for.
1623  * @method: method name for the session.
1624  * @cb: (scope async): completion callback.
1625  *
1626  * Obtain a remote object for a local session object.
1627  */
1628 void signon_identity_get_auth_session (SignonIdentity *self,
1629                                        SignonAuthSession *session,
1630                                        const gchar *method,
1631                                        SignonIdentitySessionReadyCb cb)
1632 {
1633     g_return_if_fail (SIGNON_IS_IDENTITY (self));
1634     DEBUG ("%s %d", G_STRFUNC, __LINE__);
1635
1636     SignonIdentityPrivate *priv = self->priv;
1637     g_return_if_fail (priv != NULL);
1638
1639     IdentitySessionCbData *cb_data = g_slice_new0 (IdentitySessionCbData);
1640     cb_data->self = self;
1641     cb_data->session = session;
1642     cb_data->cb = cb;
1643
1644     IdentitySessionData *operation_data = g_slice_new0 (IdentitySessionData);
1645     operation_data->method = method;
1646     operation_data->cb_data = cb_data;
1647
1648     identity_check_remote_registration (self);
1649     _signon_object_call_when_ready (self,
1650                                     identity_object_quark(),
1651                                     identity_session_ready_cb,
1652                                     operation_data);
1653 }
1654