Add signon_auth_session_process_async
authorAlberto Mardegan <alberto.mardegan@canonical.com>
Thu, 29 Nov 2012 11:39:53 +0000 (13:39 +0200)
committerAlberto Mardegan <alberto.mardegan@canonical.com>
Fri, 30 Nov 2012 07:37:43 +0000 (09:37 +0200)
Fixes: http://code.google.com/p/accounts-sso/issues/detail?id=115

docs/reference/libsignon-glib-docs.xml
docs/reference/libsignon-glib-sections.txt
libsignon-glib.pc.in
libsignon-glib/Makefile.am
libsignon-glib/signon-auth-session.c
libsignon-glib/signon-auth-session.h

index 5a1e63e..ae0c471 100644 (file)
       <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
     </index>
 
+    <index id="api-index-1-8" role="1.8">
+      <title>Index of new symbols in 1.8</title>
+      <xi:include href="xml/api-index-1.8.xml"><xi:fallback /></xi:include>
+    </index>
+
     <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
   </part>
 </book>
index 63d626e..dfe5401 100644 (file)
@@ -40,6 +40,8 @@ signon_auth_session_cancel
 signon_auth_session_get_method
 signon_auth_session_new
 signon_auth_session_process
+signon_auth_session_process_async
+signon_auth_session_process_finish
 signon_auth_session_query_available_mechanisms
 <SUBSECTION Private>
 SignonAuthSessionClass
index 513cc28..0c1e247 100644 (file)
@@ -7,7 +7,6 @@ pluginlibdir=@pluginlibdir@
 Name: libsignon-glib
 Description: A low-level library for managing account credentials.
 Version: @VERSION@
-Requires: signond
-Requires.private: gobject-2.0 dbus-glib-1
+Requires: signond glib-2.0 gobject-2.0 gio-unix-2.0
 Libs: -L${libdir} -lsignon-glib
 Cflags: -I${includedir}
index b91c6a9..ec49da1 100644 (file)
@@ -179,7 +179,7 @@ introspection_sources = \
        signon-identity.h
 
 Signon-1.0.gir: libsignon-glib.la
-Signon_1_0_gir_INCLUDES = GObject-2.0
+Signon_1_0_gir_INCLUDES = GObject-2.0 Gio-2.0
 Signon_1_0_gir_SCANNERFLAGS = \
        --identifier-prefix=Signon \
        --symbol-prefix=signon \
index c896ab5..13ec4d9 100644 (file)
@@ -63,6 +63,7 @@ enum
 static guint auth_session_signals[LAST_SIGNAL] = { 0 };
 static const gchar auth_session_process_pending_message[] =
     "The request is added to queue.";
+static const gchar data_key_process[] = "signon-process";
 
 struct _SignonAuthSessionPrivate
 {
@@ -92,7 +93,7 @@ typedef struct _AuthSessionProcessData
 {
     GVariant *session_data;
     gchar *mechanism;
-    gpointer cb_data;
+    GCancellable *cancellable;
 } AuthSessionProcessData;
 
 typedef struct _AuthSessionQueryAvailableMechanismsCbData
@@ -104,7 +105,6 @@ typedef struct _AuthSessionQueryAvailableMechanismsCbData
 
 typedef struct _AuthSessionProcessCbData
 {
-    SignonAuthSession *self;
     SignonAuthSessionProcessCb cb;
     gpointer user_data;
 } AuthSessionProcessCbData;
@@ -120,11 +120,131 @@ static gboolean auth_session_priv_init (SignonAuthSession *self, guint id, const
 
 static void auth_session_set_id_ready_cb (gpointer object, const GError *error, gpointer user_data);
 static void auth_session_query_available_mechanisms_ready_cb (gpointer object, const GError *error, gpointer user_data);
-static void auth_session_process_ready_cb (gpointer object, const GError *error, gpointer user_data);
 static void auth_session_cancel_ready_cb (gpointer object, const GError *error, gpointer user_data);
 
 static void auth_session_check_remote_object(SignonAuthSession *self);
 
+static void
+auth_session_process_data_free (AuthSessionProcessData *process_data)
+{
+    g_free (process_data->mechanism);
+    g_variant_unref (process_data->session_data);
+    g_slice_free (AuthSessionProcessData, process_data);
+}
+
+static void
+auth_session_process_reply (GObject *object, GAsyncResult *res,
+                            gpointer userdata)
+{
+    SignonAuthSession *self;
+    SsoAuthSession *proxy = SSO_AUTH_SESSION (object);
+    GSimpleAsyncResult *res_process = (GSimpleAsyncResult *)userdata;
+    GVariant *reply;
+    GError *error = NULL;
+
+    g_return_if_fail (res_process != NULL);
+
+    sso_auth_session_call_process_finish (proxy, &reply, res, &error);
+
+    self = SIGNON_AUTH_SESSION (g_async_result_get_source_object (
+        (GAsyncResult *)res_process));
+    self->priv->busy = FALSE;
+
+    if (G_LIKELY (error == NULL))
+    {
+        g_simple_async_result_set_op_res_gpointer (res_process, reply,
+                                                   (GDestroyNotify)
+                                                   g_variant_unref);
+        g_simple_async_result_complete (res_process);
+    }
+    else
+    {
+        g_simple_async_result_take_error (res_process, error);
+    }
+
+    g_object_unref (self);
+}
+
+static void
+auth_session_process_ready_cb (gpointer object, const GError *error, gpointer user_data)
+{
+    SignonAuthSession *self = SIGNON_AUTH_SESSION (object);
+    SignonAuthSessionPrivate *priv;
+    GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+    AuthSessionProcessData *process_data;
+
+    g_return_if_fail (self != NULL);
+    priv = self->priv;
+
+    if (error != NULL)
+    {
+        DEBUG ("AuthSessionError: %s", error->message);
+        g_simple_async_result_set_from_error (res, error);
+        return;
+    }
+
+    if (priv->canceled)
+    {
+        priv->busy = FALSE;
+        priv->canceled = FALSE;
+        g_simple_async_result_set_error (res,
+                                         signon_error_quark (),
+                                         SIGNON_ERROR_SESSION_CANCELED,
+                                         "Authentication session was canceled");
+        return;
+    }
+
+    process_data = g_object_get_data ((GObject *)res, data_key_process);
+    g_return_if_fail (process_data != NULL);
+
+    sso_auth_session_call_process (priv->proxy,
+                                   process_data->session_data,
+                                   process_data->mechanism,
+                                   process_data->cancellable,
+                                   auth_session_process_reply,
+                                   res);
+
+    g_signal_emit (self,
+                   auth_session_signals[STATE_CHANGED],
+                   0,
+                   SIGNON_AUTH_SESSION_STATE_PROCESS_PENDING,
+                   auth_session_process_pending_message);
+}
+
+static void
+process_async_cb_wrapper (GObject *object, GAsyncResult *res,
+                          gpointer user_data)
+{
+    AuthSessionProcessCbData *cb_data = user_data;
+    SignonAuthSession *self = SIGNON_AUTH_SESSION (object);
+    GVariant *v_reply;
+    GHashTable *reply = NULL;
+    GError *error = NULL;
+    gboolean cancelled;
+
+    v_reply = signon_auth_session_process_finish (self, res, &error);
+
+    cancelled = error != NULL &&
+        error->domain == G_IO_ERROR &&
+        error->code == G_IO_ERROR_CANCELLED;
+
+    /* Do not invoke the callback if the operation was cancelled */
+    if (cb_data->cb != NULL && !cancelled)
+    {
+        if (v_reply != NULL)
+            reply = signon_hash_table_from_variant (v_reply);
+
+        cb_data->cb (self, reply, error, cb_data->user_data);
+        if (reply != NULL)
+            g_hash_table_unref (reply);
+    }
+    g_variant_unref (v_reply);
+
+    g_slice_free (AuthSessionProcessCbData, cb_data);
+    g_clear_error (&error);
+    g_object_unref (res);
+}
+
 static GQuark
 auth_session_object_quark ()
 {
@@ -400,6 +520,8 @@ signon_auth_session_query_available_mechanisms (SignonAuthSession *self,
  * there's no need to fill them into @session_data.
  * @session_data can be used to add additional authentication parameters to the
  * session, or to override the parameters otherwise taken from the identity.
+ *
+ * Deprecated: 1.8: Use signon_auth_session_process_async() instead.
  */
 void
 signon_auth_session_process (SignonAuthSession *self,
@@ -408,23 +530,66 @@ signon_auth_session_process (SignonAuthSession *self,
                              SignonAuthSessionProcessCb cb,
                              gpointer user_data)
 {
-    g_return_if_fail (SIGNON_IS_AUTH_SESSION (self));
-    SignonAuthSessionPrivate *priv = self->priv;
+    GVariant *v_session_data;
 
-    g_return_if_fail (priv != NULL);
-    g_return_if_fail (session_data != NULL);
+    g_return_if_fail (SIGNON_IS_AUTH_SESSION (self));
 
     AuthSessionProcessCbData *cb_data = g_slice_new0 (AuthSessionProcessCbData);
-    cb_data->self = self;
     cb_data->cb = cb;
     cb_data->user_data = user_data;
 
-    AuthSessionProcessData *operation_data = g_slice_new0 (AuthSessionProcessData);
+    v_session_data = signon_hash_table_to_variant (session_data);
 
-    operation_data->session_data =
-        signon_hash_table_to_variant (session_data);
-    operation_data->mechanism = g_strdup (mechanism);
-    operation_data->cb_data = cb_data;
+    signon_auth_session_process_async (self, v_session_data, mechanism, NULL,
+                                       process_async_cb_wrapper, cb_data);
+}
+
+/**
+ * signon_auth_session_process_async:
+ * @self: the #SignonAuthSession.
+ * @session_data: (transfer floating): a dictionary of parameters.
+ * @mechanism: the authentication mechanism to be used.
+ * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
+ * @callback: (scope async): a callback which will be called when the
+ * authentication reply is available.
+ * @user_data: user data to be passed to the callback.
+ *
+ * Performs one step of the authentication process. If the #SignonAuthSession
+ * object is bound to an existing identity, the identity properties such as
+ * username and password will be also passed to the authentication plugin, so
+ * there's no need to fill them into @session_data.
+ * @session_data can be used to add additional authentication parameters to the
+ * session, or to override the parameters otherwise taken from the identity.
+ *
+ * Since: 1.8
+ */
+void
+signon_auth_session_process_async (SignonAuthSession *self,
+                                   GVariant *session_data,
+                                   const gchar *mechanism,
+                                   GCancellable *cancellable,
+                                   GAsyncReadyCallback callback,
+                                   gpointer user_data)
+{
+    SignonAuthSessionPrivate *priv;
+    AuthSessionProcessData *process_data;
+    GSimpleAsyncResult *res;
+
+    g_return_if_fail (SIGNON_IS_AUTH_SESSION (self));
+    priv = self->priv;
+
+    g_return_if_fail (session_data != NULL);
+
+    res = g_simple_async_result_new ((GObject *)self, callback, user_data,
+                                     signon_auth_session_process_async);
+    g_simple_async_result_set_check_cancellable (res, cancellable);
+
+    process_data = g_slice_new0 (AuthSessionProcessData);
+    process_data->session_data = g_variant_ref_sink (session_data);
+    process_data->mechanism = g_strdup (mechanism);
+    process_data->cancellable = cancellable;
+    g_object_set_data_full ((GObject *)res, data_key_process, process_data,
+                            (GDestroyNotify)auth_session_process_data_free);
 
     priv->busy = TRUE;
 
@@ -432,7 +597,38 @@ signon_auth_session_process (SignonAuthSession *self,
     _signon_object_call_when_ready (self,
                                     auth_session_object_quark(),
                                     auth_session_process_ready_cb,
-                                    operation_data);
+                                    res);
+}
+
+/**
+ * signon_auth_session_process_finish:
+ * @self: the #SignonAuthSession.
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to
+ * signon_auth_session_process_async().
+ * @error: return location for error, or %NULL.
+ *
+ * Collect the result of the signon_auth_session_process_async() operation.
+ *
+ * Returns: a #GVariant of type %G_VARIANT_TYPE_VARDICT containing the
+ * authentication reply.
+ *
+ * Since: 1.8
+ */
+GVariant *
+signon_auth_session_process_finish (SignonAuthSession *self, GAsyncResult *res,
+                                    GError **error)
+{
+    GSimpleAsyncResult *async_result;
+    GVariant *reply;
+
+    g_return_val_if_fail (SIGNON_IS_AUTH_SESSION (self), NULL);
+
+    async_result = (GSimpleAsyncResult *)res;
+    if (g_simple_async_result_propagate_error (async_result, error))
+        return NULL;
+
+    reply = g_simple_async_result_get_op_res_gpointer (async_result);
+    return g_variant_ref (reply);
 }
 
 /**
@@ -626,46 +822,6 @@ auth_session_query_mechanisms_reply (GObject *object, GAsyncResult *res,
 }
 
 static void
-auth_session_process_reply (GObject *object, GAsyncResult *res,
-                            gpointer userdata)
-{
-    SsoAuthSession *proxy = SSO_AUTH_SESSION (object);
-    GVariant *session_data_variant;
-    GHashTable *session_data = NULL;
-    GError *error = NULL;
-    AuthSessionProcessCbData *cb_data = (AuthSessionProcessCbData *)userdata;
-    g_return_if_fail (cb_data != NULL);
-    g_return_if_fail (cb_data->self != NULL);
-    g_return_if_fail (cb_data->self->priv != NULL);
-
-    sso_auth_session_call_process_finish (proxy,
-                                          &session_data_variant,
-                                          res,
-                                          &error);
-    SIGNON_RETURN_IF_CANCELLED (error);
-
-    if (!error)
-    {
-        session_data = signon_hash_table_from_variant (session_data_variant);
-    }
-
-    /* Keep a reference on the SignonAuthSession, because the callback
-     * code might unreference it, while we still need it. */
-    g_object_ref (cb_data->self);
-    (cb_data->cb) (cb_data->self, session_data, error, cb_data->user_data);
-
-    cb_data->self->priv->busy = FALSE;
-    if (error)
-        g_error_free (error);
-
-    if (session_data != NULL)
-        g_hash_table_unref (session_data);
-
-    g_object_unref (cb_data->self);
-    g_slice_free (AuthSessionProcessCbData, cb_data);
-}
-
-static void
 auth_session_query_available_mechanisms_ready_cb (gpointer object, const GError *error,
                                                   gpointer user_data)
 {
@@ -710,63 +866,6 @@ auth_session_query_available_mechanisms_ready_cb (gpointer object, const GError
 }
 
 static void
-auth_session_process_ready_cb (gpointer object, const GError *error, gpointer user_data)
-{
-    g_return_if_fail (SIGNON_IS_AUTH_SESSION (object));
-
-    SignonAuthSession *self = SIGNON_AUTH_SESSION (object);
-    SignonAuthSessionPrivate *priv = SIGNON_AUTH_SESSION_PRIV (self);
-
-    AuthSessionProcessData *operation_data =
-        (AuthSessionProcessData *)user_data;
-    g_return_if_fail (operation_data != NULL);
-
-    AuthSessionProcessCbData *cb_data = operation_data->cb_data;
-    g_return_if_fail (cb_data != NULL);
-
-    if (error || priv->canceled)
-    {
-        GError *err = (error ? (GError *)error :
-                       g_error_new (signon_error_quark (),
-                                    SIGNON_ERROR_SESSION_CANCELED,
-                                    "Authentication session was canceled"));
-
-        DEBUG ("AuthSessionError: %s", err->message);
-
-        (cb_data->cb)
-            (self, NULL, err, cb_data->user_data);
-
-        if (!error)
-            g_clear_error (&err);
-
-        g_slice_free (AuthSessionProcessCbData, cb_data);
-
-        priv->busy = FALSE;
-        priv->canceled = FALSE;
-    }
-    else
-    {
-        g_return_if_fail (priv->proxy != NULL);
-
-        sso_auth_session_call_process (priv->proxy,
-                                       operation_data->session_data,
-                                       operation_data->mechanism,
-                                       priv->cancellable,
-                                       auth_session_process_reply,
-                                       cb_data);
-
-       g_signal_emit (self,
-                       auth_session_signals[STATE_CHANGED],
-                       0,
-                       SIGNON_AUTH_SESSION_STATE_PROCESS_PENDING,
-                       auth_session_process_pending_message);
-    }
-
-    g_free (operation_data->mechanism);
-    g_slice_free (AuthSessionProcessData, operation_data);
-}
-
-static void
 auth_session_cancel_ready_cb (gpointer object, const GError *error, gpointer user_data)
 {
     g_return_if_fail (SIGNON_IS_AUTH_SESSION (object));
index 8024cce..caccce3 100644 (file)
@@ -4,8 +4,9 @@
  * This file is part of libsignon-glib
  *
  * Copyright (C) 2009-2010 Nokia Corporation.
+ * Copyright (C) 2012 Canonical Ltd.
  *
- * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
+ * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -25,6 +26,7 @@
 #ifndef SIGNONAUTHSESSION_H_
 #define SIGNONAUTHSESSION_H_
 
+#include <gio/gio.h>
 #include <glib-object.h>
 
 G_BEGIN_DECLS
@@ -169,6 +171,15 @@ void signon_auth_session_process(SignonAuthSession *self,
                                 const gchar *mechanism,
                                 SignonAuthSessionProcessCb cb,
                                 gpointer user_data);
+void signon_auth_session_process_async (SignonAuthSession *self,
+                                        GVariant *session_data,
+                                        const gchar *mechanism,
+                                        GCancellable *cancellable,
+                                        GAsyncReadyCallback callback,
+                                        gpointer user_data);
+GVariant *signon_auth_session_process_finish (SignonAuthSession *self,
+                                              GAsyncResult *res,
+                                              GError **error);
 
 void signon_auth_session_cancel(SignonAuthSession *self);