Release 2.0.2
[profile/ivi/libgsignon-glib.git] / libgsignon-glib / signon-auth-session.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-auth-session
30  * @title: SignonAuthSession
31  * @short_description: the authentication session object
32  *
33  * The #SignonAuthSession object is responsible for handling the client
34  * authentication. #SignonAuthSession objects should be created from existing
35  * identities (via signon_identity_create_session() or by passing a non-NULL identity
36  * to signon_auth_session_new()), in which case the authentication data such as
37  * username and password will be implicitly taken from the identity.
38  */
39
40 #include "signon-internals.h"
41 #include "signon-auth-session.h"
42 #include "signon-dbus-queue.h"
43 #include "signon-errors.h"
44 #include "signon-marshal.h"
45 #include "signon-utils.h"
46 #include "signon-identity.h"
47 #include "sso-auth-service.h"
48 #include "sso-auth-session-gen.h"
49
50
51 G_DEFINE_TYPE (SignonAuthSession, signon_auth_session, G_TYPE_OBJECT);
52
53 enum
54 {
55     PROP_0,
56     PROP_IDENTITY,
57     PROP_APPCTX
58 };
59
60 /* Signals */
61 enum
62 {
63     STATE_CHANGED,
64     LAST_SIGNAL
65 };
66
67 static guint auth_session_signals[LAST_SIGNAL] = { 0 };
68 static const gchar auth_session_process_pending_message[] =
69     "The request is added to queue.";
70 static const gchar data_key_process[] = "signon-process";
71
72 struct _SignonAuthSessionPrivate
73 {
74     SsoAuthSession *proxy;
75     SignonIdentity *identity;
76     GCancellable *cancellable;
77
78     guint id;
79     gchar *method_name;
80
81     gboolean registering;
82     gboolean busy;
83     gboolean canceled;
84     gboolean dispose_has_run;
85
86     guint signal_state_changed;
87     guint signal_unregistered;
88 };
89
90 typedef struct _AuthSessionQueryAvailableMechanismsData
91 {
92     gchar **wanted_mechanisms;
93     gpointer cb_data;
94 } AuthSessionQueryAvailableMechanismsData;
95
96 typedef struct _AuthSessionProcessData
97 {
98     GVariant *session_data;
99     gchar *mechanism;
100     GCancellable *cancellable;
101 } AuthSessionProcessData;
102
103 typedef struct _AuthSessionQueryAvailableMechanismsCbData
104 {
105     SignonAuthSession *self;
106     SignonAuthSessionQueryAvailableMechanismsCb cb;
107     gpointer user_data;
108 } AuthSessionQueryAvailableMechanismsCbData;
109
110 typedef struct _AuthSessionProcessCbData
111 {
112     SignonAuthSessionProcessCb cb;
113     gpointer user_data;
114 } AuthSessionProcessCbData;
115
116 #define SIGNON_AUTH_SESSION_PRIV(obj) (SIGNON_AUTH_SESSION(obj)->priv)
117 #define SIGNON_AUTH_SESSION_GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SIGNON_TYPE_AUTH_SESSION, SignonAuthSessionPrivate))
118
119
120 static void auth_session_state_changed_cb (GDBusProxy *proxy, gint state, gchar *message, gpointer user_data);
121 static void auth_session_remote_object_destroyed_cb (GDBusProxy *proxy, gpointer user_data);
122
123 static gboolean auth_session_priv_init (SignonAuthSession *self, const gchar *method_name, GError **err);
124
125 static void auth_session_query_available_mechanisms_ready_cb (gpointer object, const GError *error, gpointer user_data);
126 static void auth_session_cancel_ready_cb (gpointer object, const GError *error, gpointer user_data);
127
128 static void auth_session_check_remote_object(SignonAuthSession *self);
129
130 static void
131 auth_session_process_data_free (AuthSessionProcessData *process_data)
132 {
133     g_free (process_data->mechanism);
134     g_variant_unref (process_data->session_data);
135     g_slice_free (AuthSessionProcessData, process_data);
136 }
137
138 static void
139 auth_session_process_reply (GObject *object, GAsyncResult *res,
140                             gpointer userdata)
141 {
142     SignonAuthSession *self;
143     SsoAuthSession *proxy = SSO_AUTH_SESSION (object);
144     GSimpleAsyncResult *res_process = (GSimpleAsyncResult *)userdata;
145     GVariant *reply;
146     GError *error = NULL;
147
148     g_return_if_fail (res_process != NULL);
149     DEBUG ("%s %d", G_STRFUNC, __LINE__);
150
151     sso_auth_session_call_process_finish (proxy, &reply, res, &error);
152
153     self = SIGNON_AUTH_SESSION (g_async_result_get_source_object (
154         (GAsyncResult *)res_process));
155     self->priv->busy = FALSE;
156
157     if (G_LIKELY (error == NULL))
158     {
159         g_simple_async_result_set_op_res_gpointer (res_process, reply,
160                                                    (GDestroyNotify)
161                                                    g_variant_unref);
162     }
163     else
164     {
165         g_simple_async_result_take_error (res_process, error);
166     }
167
168     /* We use the idle variant in order to avoid the following critical
169      * message:
170      * g_main_context_pop_thread_default: assertion `g_queue_peek_head (stack) == context' failed
171      */
172     g_simple_async_result_complete_in_idle (res_process);
173     g_object_unref (res_process);
174     g_object_unref (self);
175 }
176
177 static void
178 auth_session_process_ready_cb (gpointer object, const GError *error, gpointer user_data)
179 {
180     SignonAuthSession *self = SIGNON_AUTH_SESSION (object);
181     SignonAuthSessionPrivate *priv;
182     GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
183     AuthSessionProcessData *process_data;
184
185     g_return_if_fail (self != NULL);
186     priv = self->priv;
187
188     if (error != NULL)
189     {
190         DEBUG ("AuthSessionError: %s", error->message);
191         g_simple_async_result_set_from_error (res, error);
192         g_simple_async_result_complete (res);
193         g_object_unref (res);
194         return;
195     }
196
197     if (priv->canceled)
198     {
199         priv->busy = FALSE;
200         priv->canceled = FALSE;
201         g_simple_async_result_set_error (res,
202                                          signon_error_quark (),
203                                          SIGNON_ERROR_SESSION_CANCELED,
204                                          "Authentication session was canceled");
205         g_simple_async_result_complete (res);
206         g_object_unref (res);
207         return;
208     }
209
210     DEBUG ("%s %d", G_STRFUNC, __LINE__);
211
212     process_data = g_object_get_data ((GObject *)res, data_key_process);
213     g_return_if_fail (process_data != NULL);
214
215     sso_auth_session_call_process (priv->proxy,
216                                    process_data->session_data,
217                                    process_data->mechanism,
218                                    process_data->cancellable,
219                                    auth_session_process_reply,
220                                    res);
221 }
222
223 static void
224 process_async_cb_wrapper (GObject *object, GAsyncResult *res,
225                           gpointer user_data)
226 {
227     AuthSessionProcessCbData *cb_data = user_data;
228     SignonAuthSession *self = SIGNON_AUTH_SESSION (object);
229     GVariant *v_reply;
230     GHashTable *reply = NULL;
231     GError *error = NULL;
232     gboolean cancelled;
233
234     DEBUG ("%s %d", G_STRFUNC, __LINE__);
235
236     v_reply = signon_auth_session_process_finish (self, res, &error);
237
238     cancelled = error != NULL &&
239         error->domain == G_IO_ERROR &&
240         error->code == G_IO_ERROR_CANCELLED;
241
242     /* Do not invoke the callback if the operation was cancelled */
243     if (cb_data->cb != NULL && !cancelled)
244     {
245         if (v_reply != NULL)
246             reply = signon_hash_table_from_variant (v_reply);
247
248         cb_data->cb (self, reply, error, cb_data->user_data);
249     }
250     g_variant_unref (v_reply);
251
252     g_slice_free (AuthSessionProcessCbData, cb_data);
253     g_clear_error (&error);
254 }
255
256 static GQuark
257 auth_session_object_quark ()
258 {
259   static GQuark quark = 0;
260
261   if (!quark)
262     quark = g_quark_from_static_string ("auth_session_object_quark");
263
264   return quark;
265 }
266
267 static void
268 signon_auth_session_set_property (GObject *object,
269                                   guint property_id,
270                                   const GValue *value,
271                                   GParamSpec *pspec)
272 {
273     SignonAuthSession *self = SIGNON_AUTH_SESSION (object);
274
275     switch (property_id)
276     {
277         case PROP_IDENTITY:
278             self->priv->identity = g_value_dup_object (value);
279             break;
280         default:
281             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
282     }
283 }
284
285 static void
286 signon_auth_session_get_property (GObject *object,
287                                   guint property_id,
288                                   GValue *value,
289                                   GParamSpec *pspec)
290 {
291     SignonAuthSession *self = SIGNON_AUTH_SESSION (object);
292
293     switch (property_id)
294     {
295         case PROP_IDENTITY:
296             g_value_set_object (value, self->priv->identity);
297             break;
298         default:
299             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
300     }
301 }
302
303 static void
304 signon_auth_session_init (SignonAuthSession *self)
305 {
306     self->priv = SIGNON_AUTH_SESSION_GET_PRIV (self);
307     self->priv->cancellable = g_cancellable_new ();
308 }
309
310 static void
311 signon_auth_session_dispose (GObject *object)
312 {
313     g_return_if_fail (SIGNON_IS_AUTH_SESSION (object));
314     SignonAuthSession *self = SIGNON_AUTH_SESSION (object);
315     SignonAuthSessionPrivate *priv = self->priv;
316     g_return_if_fail (priv != NULL);
317
318     if (priv->dispose_has_run)
319         return;
320
321     if (priv->cancellable)
322     {
323         g_cancellable_cancel (priv->cancellable);
324         g_object_unref (priv->cancellable);
325         priv->cancellable = NULL;
326     }
327
328     if (priv->proxy)
329     {
330         g_signal_handler_disconnect (priv->proxy, priv->signal_state_changed);
331         g_signal_handler_disconnect (priv->proxy, priv->signal_unregistered);
332         g_object_unref (priv->proxy);
333
334         priv->proxy = NULL;
335     }
336
337     G_OBJECT_CLASS (signon_auth_session_parent_class)->dispose (object);
338
339     priv->dispose_has_run = TRUE;
340 }
341
342 static void
343 signon_auth_session_finalize (GObject *object)
344 {
345     g_return_if_fail (SIGNON_IS_AUTH_SESSION(object));
346
347     SignonAuthSession *self = SIGNON_AUTH_SESSION(object);
348     SignonAuthSessionPrivate *priv = self->priv;
349     g_return_if_fail (priv != NULL);
350
351     g_free (priv->method_name);
352     g_object_unref (priv->identity);
353
354     G_OBJECT_CLASS (signon_auth_session_parent_class)->finalize (object);
355 }
356
357 static void
358 signon_auth_session_class_init (SignonAuthSessionClass *klass)
359 {
360     GObjectClass *object_class = G_OBJECT_CLASS (klass);
361     GParamSpec *pspec;
362
363     object_class->set_property = signon_auth_session_set_property;
364     object_class->get_property = signon_auth_session_get_property;
365
366     pspec = g_param_spec_object ("identity",
367                                  "Identity Object",
368                                  "Identity Object construct parameter",
369                                  SIGNON_TYPE_IDENTITY,
370                                  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
371     g_object_class_install_property (object_class,
372                                      PROP_IDENTITY,
373                                      pspec);
374
375     g_type_class_add_private (object_class, sizeof (SignonAuthSessionPrivate));
376
377     /**
378      * SignonAuthSession::state-changed:
379      * @auth_session: the #SignonAuthSession
380      * @state: the current state of the #SignonAuthSession
381      * @message: the message associated with the state change
382      *
383      * Emitted when the state of the #SignonAuthSession changes.
384      * FIXME: @state should be registered as a GLib type (or use one from
385      * libgsignond-common)
386      */
387     auth_session_signals[STATE_CHANGED] =
388             g_signal_new ("state-changed",
389                           G_TYPE_FROM_CLASS (klass),
390                           G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
391                           0,
392                           NULL,
393                           NULL,
394                           _signon_marshal_VOID__INT_STRING,
395                           G_TYPE_NONE, 2,
396                           G_TYPE_INT,
397                           G_TYPE_STRING);
398
399     object_class->dispose = signon_auth_session_dispose;
400     object_class->finalize = signon_auth_session_finalize;
401 }
402
403 /**
404  * signon_auth_session_new:
405  * @parent: #SignonIdentity parent object.
406  * @method_name: the name of the authentication method to be used.
407  * @err: a pointer to a location which will contain the error, in case this
408  * function fails.
409  *
410  * Creates a new #SignonAuthSession, which can be used to authenticate using
411  * the specified method.
412  *
413  * Returns: a new #SignonAuthSession.
414  */
415 SignonAuthSession *
416 signon_auth_session_new (GObject *parent,
417                          const gchar *method_name,
418                          GError **err)
419 {
420     if (!SIGNON_IS_IDENTITY(parent))
421     {
422         g_set_error (err,
423                      signon_error_quark(),
424                      SIGNON_ERROR_UNKNOWN,
425                      "Parent object is wrong type");
426         return NULL;
427     }
428     SignonIdentity *identity = SIGNON_IDENTITY(parent);
429
430     DEBUG ("%s %d", G_STRFUNC, __LINE__);
431
432     SignonAuthSession *self = SIGNON_AUTH_SESSION(g_object_new (
433                                      SIGNON_TYPE_AUTH_SESSION,
434                                      "identity", identity,
435                                      NULL));
436     g_return_val_if_fail (self != NULL, NULL);
437
438     if (!auth_session_priv_init(self, method_name, err))
439     {
440         if (*err)
441             g_warning ("%s returned error: %s", G_STRFUNC, (*err)->message);
442
443         g_object_unref (self);
444         return NULL;
445     }
446
447     return self;
448 }
449
450 /**
451  * signon_auth_session_get_method:
452  * @self: the #SignonAuthSession.
453  *
454  * Get the current authentication method.
455  *
456  * Returns: the authentication method being used, or %NULL on failure.
457  */
458 const gchar *
459 signon_auth_session_get_method (SignonAuthSession *self)
460 {
461     g_return_val_if_fail (SIGNON_IS_AUTH_SESSION (self), NULL);
462     SignonAuthSessionPrivate *priv = self->priv;
463
464     g_return_val_if_fail (priv != NULL, NULL);
465
466     return priv->method_name;
467 }
468
469 /**
470  * SignonAuthSessionQueryAvailableMechanismsCb:
471  * @self: the #SignonAuthSession.
472  * @mechanisms: (transfer full) (type GStrv): list of available mechanisms.
473  * @error: a #GError if an error occurred, %NULL otherwise.
474  * @user_data: the user data that was passed when installing this callback.
475  *
476  * Callback to be passed to signon_auth_session_query_available_mechanisms().
477  */
478
479 /**
480  * signon_auth_session_query_available_mechanisms:
481  * @self: the #SignonAuthSession.
482  * @wanted_mechanisms: a %NULL-terminated list of mechanisms supported by the client.
483  * @cb: (scope async): a callback which will be called with the result.
484  * @user_data: user data to be passed to the callback.
485  *
486  * Queries the mechanisms available for this authentication session. The result
487  * will be the intersection between @wanted_mechanisms and the mechanisms
488  * supported by the authentication plugin (and allowed by the #SignonIdentity that this
489  * session belongs to).
490  */
491 void
492 signon_auth_session_query_available_mechanisms (SignonAuthSession *self,
493                                                 const gchar **wanted_mechanisms,
494                                                 SignonAuthSessionQueryAvailableMechanismsCb cb,
495                                                 gpointer user_data)
496 {
497     g_return_if_fail (SIGNON_IS_AUTH_SESSION (self));
498     SignonAuthSessionPrivate* priv = self->priv;
499
500     g_return_if_fail (priv != NULL);
501
502     AuthSessionQueryAvailableMechanismsCbData *cb_data = g_slice_new0 (AuthSessionQueryAvailableMechanismsCbData);
503     cb_data->self = self;
504     cb_data->cb = cb;
505     cb_data->user_data = user_data;
506
507     AuthSessionQueryAvailableMechanismsData *operation_data = g_slice_new0 (AuthSessionQueryAvailableMechanismsData);
508     operation_data->wanted_mechanisms = g_strdupv ((gchar **)wanted_mechanisms);
509     operation_data->cb_data = cb_data;
510
511     auth_session_check_remote_object(self);
512     _signon_object_call_when_ready (self,
513                                     auth_session_object_quark(),
514                                     auth_session_query_available_mechanisms_ready_cb,
515                                     operation_data);
516 }
517
518 /**
519  * SignonAuthSessionProcessCb:
520  * @self: the #SignonAuthSession.
521  * @session_data: (transfer full) (element-type utf8 GValue): a dictionary with
522  * the response.
523  * @error: a #GError if an error occurred, %NULL otherwise.
524  * @user_data: the user data that was passed when installing this callback.
525  *
526  * This callback is invoked when the authentication plugin delivers the result
527  * of the signon_auth_session_process() operation.
528  */
529
530 /**
531  * signon_auth_session_process:
532  * @self: the #SignonAuthSession.
533  * @session_data: (transfer none) (element-type utf8 GValue): a dictionary of parameters.
534  * @mechanism: the authentication mechanism to be used.
535  * @cb: (scope async): a callback which will be called with the result.
536  * @user_data: user data to be passed to the callback.
537  *
538  * Performs one step of the authentication process. If the #SignonIdentity that
539  * this session belongs to contains a username and a password, they will be also 
540  * passed to the authentication plugin, otherwise they should be set directly in
541  * @session_data.
542  * @session_data should be used to add additional authentication parameters to the
543  * session, or to override the parameters otherwise taken from the identity.
544  *
545  * Deprecated: 1.8: Use signon_auth_session_process_async() instead.
546  */
547 void
548 signon_auth_session_process (SignonAuthSession *self,
549                              const GHashTable *session_data,
550                              const gchar* mechanism,
551                              SignonAuthSessionProcessCb cb,
552                              gpointer user_data)
553 {
554     GVariant *v_session_data;
555
556     g_return_if_fail (SIGNON_IS_AUTH_SESSION (self));
557     DEBUG ("%s %d", G_STRFUNC, __LINE__);
558
559     AuthSessionProcessCbData *cb_data = g_slice_new0 (AuthSessionProcessCbData);
560     cb_data->cb = cb;
561     cb_data->user_data = user_data;
562
563     v_session_data = signon_hash_table_to_variant (session_data);
564
565     signon_auth_session_process_async (self, v_session_data, mechanism, NULL,
566                                        process_async_cb_wrapper, cb_data);
567 }
568
569 /**
570  * signon_auth_session_process_async:
571  * @self: the #SignonAuthSession.
572  * @session_data: (transfer full): a dictionary of parameters.
573  * @mechanism: the authentication mechanism to be used.
574  * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
575  * @callback: (scope async): a callback which will be called when the
576  * authentication reply is available.
577  * @user_data: user data to be passed to the callback.
578  *
579  * Performs one step of the authentication process. If the #SignonIdentity that
580  * this session belongs to contains a username and a password, the daemon will
581  * pass them to the authentication plugin, otherwise they should be set directly in
582  * @session_data.
583  * @session_data should be used to add additional authentication parameters to the
584  * session, or to override the parameters otherwise taken from the identity.
585  * 
586  * What specific parameters should be used can be found from authentication plugins'
587  * documentation (look for parameters that are expected in gsignond_plugin_request_initial()
588  * for the first step, and parameters that are expected in gsignond_plugin_request() for
589  * the subsequent steps). See, for example, #GSignondPasswordPlugin and #GSignondDigestPlugin.
590  *
591  * Since: 1.8
592  */
593 void
594 signon_auth_session_process_async (SignonAuthSession *self,
595                                    GVariant *session_data,
596                                    const gchar *mechanism,
597                                    GCancellable *cancellable,
598                                    GAsyncReadyCallback callback,
599                                    gpointer user_data)
600 {
601     SignonAuthSessionPrivate *priv;
602     AuthSessionProcessData *process_data;
603     GSimpleAsyncResult *res;
604
605     g_return_if_fail (SIGNON_IS_AUTH_SESSION (self));
606     priv = self->priv;
607
608     g_return_if_fail (session_data != NULL);
609
610     res = g_simple_async_result_new ((GObject *)self, callback, user_data,
611                                      signon_auth_session_process_async);
612     g_simple_async_result_set_check_cancellable (res, cancellable);
613
614     process_data = g_slice_new0 (AuthSessionProcessData);
615     process_data->session_data = g_variant_ref_sink (session_data);
616     process_data->mechanism = g_strdup (mechanism);
617     process_data->cancellable = cancellable;
618     g_object_set_data_full ((GObject *)res, data_key_process, process_data,
619                             (GDestroyNotify)auth_session_process_data_free);
620
621     priv->busy = TRUE;
622
623     auth_session_check_remote_object(self);
624     _signon_object_call_when_ready (self,
625                                     auth_session_object_quark(),
626                                     auth_session_process_ready_cb,
627                                     res);
628 }
629
630 /**
631  * signon_auth_session_process_finish:
632  * @self: the #SignonAuthSession.
633  * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to
634  * signon_auth_session_process_async().
635  * @error: return location for error, or %NULL.
636  *
637  * Collect the result of the signon_auth_session_process_async() operation.
638  *
639  * Returns: a #GVariant of type %G_VARIANT_TYPE_VARDICT containing the
640  * authentication reply. As with signon_auth_session_process_async(), specific
641  * parameters contained in the #GVariant can be found from plugins' documentation:
642  * #GSignondPlugin::response-final for the final response, and #GSignondPlugin::response
643  * for the intermediate responses. See, for example, #GSignondPasswordPlugin 
644  * and #GSignondDigestPlugin.
645  *
646  * Since: 1.8
647  */
648 GVariant *
649 signon_auth_session_process_finish (SignonAuthSession *self, GAsyncResult *res,
650                                     GError **error)
651 {
652     GSimpleAsyncResult *async_result;
653     GVariant *reply;
654
655     g_return_val_if_fail (SIGNON_IS_AUTH_SESSION (self), NULL);
656
657     async_result = (GSimpleAsyncResult *)res;
658     if (g_simple_async_result_propagate_error (async_result, error))
659         return NULL;
660
661     reply = g_simple_async_result_get_op_res_gpointer (async_result);
662     return g_variant_ref (reply);
663 }
664
665 /**
666  * signon_auth_session_cancel:
667  * @self: the #SignonAuthSession.
668  *
669  * Cancel the authentication session.
670  */
671 void
672 signon_auth_session_cancel (SignonAuthSession *self)
673 {
674     g_return_if_fail (SIGNON_IS_AUTH_SESSION (self));
675     SignonAuthSessionPrivate *priv = self->priv;
676
677     g_return_if_fail (priv != NULL);
678
679     auth_session_check_remote_object(self);
680
681     if (!priv->busy)
682         return;
683
684     priv->canceled = TRUE;
685     _signon_object_call_when_ready (self,
686                                     auth_session_object_quark(),
687                                     auth_session_cancel_ready_cb,
688                                     NULL);
689 }
690
691 static void
692 auth_session_state_changed_cb (GDBusProxy *proxy,
693                                gint state,
694                                gchar *message,
695                                gpointer user_data)
696 {
697     g_return_if_fail (SIGNON_IS_AUTH_SESSION (user_data));
698     SignonAuthSession *self = SIGNON_AUTH_SESSION (user_data);
699
700     g_signal_emit ((GObject *)self,
701                     auth_session_signals[STATE_CHANGED],
702                     0,
703                     state,
704                     message);
705 }
706
707 static void auth_session_remote_object_destroyed_cb (GDBusProxy *proxy,
708                                                      gpointer user_data)
709 {
710     g_return_if_fail (SIGNON_IS_AUTH_SESSION (user_data));
711     SignonAuthSession *self = SIGNON_AUTH_SESSION (user_data);
712     SignonAuthSessionPrivate *priv = self->priv;
713     g_return_if_fail (priv != NULL);
714     DEBUG ("remote object unregistered");
715
716     if (priv->proxy)
717     {
718         g_object_unref (priv->proxy);
719         priv->proxy = NULL;
720     }
721
722     /*
723      * as remote object is destroyed only
724      * when the session core is destroyed,
725      * so there should not be any processes
726      * running
727      * */
728     priv->busy = FALSE;
729     priv->canceled = FALSE;
730     _signon_object_not_ready(self);
731 }
732
733 static gboolean
734 auth_session_priv_init (SignonAuthSession *self,
735                         const gchar *method_name, GError **err)
736 {
737     g_return_val_if_fail (SIGNON_IS_AUTH_SESSION (self), FALSE);
738     SignonAuthSessionPrivate *priv = SIGNON_AUTH_SESSION_PRIV (self);
739     g_return_val_if_fail (priv, FALSE);
740
741     priv->method_name = g_strdup (method_name);
742
743     priv->registering = FALSE;
744     priv->busy = FALSE;
745     priv->canceled = FALSE;
746     return TRUE;
747 }
748
749 static void
750 auth_session_query_mechanisms_reply (GObject *object, GAsyncResult *res,
751                                      gpointer userdata)
752 {
753     SsoAuthSession *proxy = SSO_AUTH_SESSION (object);
754     gchar **mechanisms = NULL;
755     GError *error = NULL;
756     AuthSessionQueryAvailableMechanismsCbData *cb_data =
757         (AuthSessionQueryAvailableMechanismsCbData *)userdata;
758     g_return_if_fail (cb_data != NULL);
759
760     sso_auth_session_call_query_available_mechanisms_finish (proxy,
761                                                              &mechanisms,
762                                                              res,
763                                                              &error);
764     if (SIGNON_IS_NOT_CANCELLED (error))
765     {
766         (cb_data->cb) (cb_data->self, mechanisms, error, cb_data->user_data);
767     }
768
769     g_clear_error (&error);
770     g_slice_free (AuthSessionQueryAvailableMechanismsCbData, cb_data);
771 }
772
773 static void
774 auth_session_query_available_mechanisms_ready_cb (gpointer object, const GError *error,
775                                                   gpointer user_data)
776 {
777     g_return_if_fail (SIGNON_IS_AUTH_SESSION (object));
778     SignonAuthSession *self = SIGNON_AUTH_SESSION (object);
779     SignonAuthSessionPrivate *priv = self->priv;
780     g_return_if_fail (priv != NULL);
781
782     AuthSessionQueryAvailableMechanismsData *operation_data =
783         (AuthSessionQueryAvailableMechanismsData *)user_data;
784     g_return_if_fail (operation_data != NULL);
785
786     AuthSessionQueryAvailableMechanismsCbData *cb_data = operation_data->cb_data;
787     g_return_if_fail (cb_data != NULL);
788
789     if (error)
790     {
791         (cb_data->cb)
792             (self, NULL, error, cb_data->user_data);
793
794         g_slice_free (AuthSessionQueryAvailableMechanismsCbData, cb_data);
795     }
796     else
797     {
798         g_return_if_fail (priv->proxy != NULL);
799         sso_auth_session_call_query_available_mechanisms (
800             priv->proxy,
801             (const char **)operation_data->wanted_mechanisms,
802             priv->cancellable,
803             auth_session_query_mechanisms_reply,
804             cb_data);
805
806         g_signal_emit (self,
807                        auth_session_signals[STATE_CHANGED],
808                        0,
809                        SIGNON_AUTH_SESSION_STATE_PROCESS_PENDING,
810                        auth_session_process_pending_message);
811     }
812
813     g_strfreev (operation_data->wanted_mechanisms);
814     g_slice_free (AuthSessionQueryAvailableMechanismsData, operation_data);
815 }
816
817 static void
818 auth_session_cancel_ready_cb (gpointer object, const GError *error, gpointer user_data)
819 {
820     g_return_if_fail (SIGNON_IS_AUTH_SESSION (object));
821     g_return_if_fail (user_data == NULL);
822
823     SignonAuthSession *self = SIGNON_AUTH_SESSION (object);
824     SignonAuthSessionPrivate *priv = self->priv;
825     g_return_if_fail (priv != NULL);
826
827     if (error)
828     {
829         //TODO: in general this function does not return any values,
830         // that is why I think it should not emit anything for this particular case
831         DEBUG("error during initialization");
832     }
833     else if (priv->proxy && priv->busy)
834         sso_auth_session_call_cancel_sync (priv->proxy,
835                                            priv->cancellable,
836                                            NULL);
837
838     priv->busy = FALSE;
839     priv->canceled = FALSE;
840 }
841
842 static void
843 signon_auth_session_complete (SignonAuthSession *self,
844                               GError *error,
845                               GDBusConnection *connection,
846                               const gchar *bus_name,
847                               const gchar *object_path)
848 {
849     SignonAuthSessionPrivate *priv = self->priv;
850     g_return_if_fail (priv != NULL);
851
852     DEBUG ("%s %d", G_STRFUNC, __LINE__);
853
854     priv->registering = FALSE;
855     if (!g_strcmp0(object_path, "") || error)
856     {
857         if (error)
858             DEBUG ("Error message is %s", error->message);
859         else
860             error = g_error_new (signon_error_quark(),
861                                  SIGNON_ERROR_RUNTIME,
862                                  "Cannot create remote AuthSession object");
863     }
864     else
865     {
866         GError *proxy_error = NULL;
867
868         priv->proxy =
869             sso_auth_session_proxy_new_sync (connection,
870                                              G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
871                                              bus_name,
872                                              object_path,
873                                              priv->cancellable,
874                                              &proxy_error);
875         if (G_UNLIKELY (proxy_error != NULL))
876         {
877             g_warning ("Failed to initialize AuthSession proxy: %s",
878                        proxy_error->message);
879             g_clear_error (&proxy_error);
880         }
881
882         g_dbus_proxy_set_default_timeout ((GDBusProxy *)priv->proxy,
883                                           G_MAXINT);
884
885         priv->signal_state_changed =
886             g_signal_connect (priv->proxy,
887                               "state-changed",
888                               G_CALLBACK (auth_session_state_changed_cb),
889                               self);
890
891         priv->signal_unregistered =
892            g_signal_connect (priv->proxy,
893                              "unregistered",
894                              G_CALLBACK (auth_session_remote_object_destroyed_cb),
895                              self);
896     }
897
898     DEBUG ("Object path received: %s", object_path);
899     _signon_object_ready (self, auth_session_object_quark (), error);
900 }
901
902 static void
903 auth_session_check_remote_object(SignonAuthSession *self)
904 {
905     g_return_if_fail (self != NULL);
906     SignonAuthSessionPrivate *priv = self->priv;
907     g_return_if_fail (priv != NULL);
908
909     if (priv->proxy != NULL)
910         return;
911
912     g_return_if_fail (priv->identity != NULL);
913
914     if (!priv->registering)
915     {
916         DEBUG ("%s %d", G_STRFUNC, __LINE__);
917
918         priv->registering = TRUE;
919         signon_identity_get_auth_session (priv->identity,
920                                           self,
921                                           priv->method_name,
922                                           signon_auth_session_complete);
923
924     }
925 }
926