Release 0.0.3
[profile/ivi/gsignond.git] / src / daemon / gsignond-identity.c
index 145b68c..cb36fa1 100644 (file)
@@ -33,7 +33,6 @@
 #include "gsignond-identity-enum-types.h"
 #include "gsignond-auth-session.h"
 #include "gsignond/gsignond-config-dbus.h"
-#include "gsignond/gsignond-signonui.h"
 #include "common/gsignond-identity-info-internal.h"
 #include "plugins/gsignond-plugin-proxy-factory.h"
 
@@ -72,8 +71,11 @@ typedef struct _GSignondIdentityCbData
 G_DEFINE_TYPE (GSignondIdentity, gsignond_identity, G_TYPE_OBJECT);
 
 
-static void _on_session_close (gpointer data, GObject *session);
+static void _on_session_dead (gpointer data, GObject *session);
 static void _on_refresh_dialog (GSignondAuthSession *session, GSignondSignonuiData *ui_data, gpointer userdata);
+static void _on_process_canceled (GSignondAuthSession *session, GSignondIdentityCbData *cb_data);
+static void _on_user_action_required (GSignondAuthSession *session, GSignondSignonuiData *ui_data, gpointer userdata);
+static void _on_store_token (GSignondAuthSession *session, GSignondDictionary *token_data, gpointer userdata);
 
 #define GSIGNOND_IDENTITY_PRIV(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_IDENTITY, GSignondIdentityPrivate)
 
@@ -163,7 +165,10 @@ _set_property (GObject *object, guint property_id, const GValue *value,
 static void
 _release_weak_ref_on_session (gpointer key, gpointer value, gpointer data)
 {
-    g_object_weak_unref (G_OBJECT (value), _on_session_close, data);
+    GObject *session = G_OBJECT (value);
+    g_signal_handlers_disconnect_by_func (session, G_CALLBACK (_on_user_action_required), data);
+    g_signal_handlers_disconnect_by_func (session, G_CALLBACK (_on_store_token), data);
+    g_object_weak_unref (session, _on_session_dead, data);
 }
 
 static void
@@ -334,8 +339,10 @@ _on_refresh_dialog (GSignondAuthSession *session, GSignondSignonuiData *ui_data,
 {
     GSignondIdentityCbData *cb_data = (GSignondIdentityCbData *) userdata;
 
-    gsignond_daemon_refresh_dialog (GSIGNOND_DAEMON (cb_data->identity->priv->owner), 
-            G_OBJECT (cb_data->session), ui_data, _on_dialog_refreshed, userdata);
+    if (!gsignond_daemon_refresh_dialog (GSIGNOND_DAEMON (cb_data->identity->priv->owner), 
+            G_OBJECT (cb_data->session), ui_data, _on_dialog_refreshed, userdata)) {
+        WARN ("Dialog Refresh Failed");
+    }
 }
 
 static void
@@ -355,21 +362,31 @@ _on_user_action_completed (GSignondSignonuiData *reply, GError *error, gpointer
     GSignondIdentityPrivate *priv = GSIGNOND_IDENTITY_PRIV (cb_data->identity);
     GSignondSignonuiError ui_error = SIGNONUI_ERROR_NONE;
 
+    g_return_if_fail (cb_data && GSIGNOND_IS_AUTH_SESSION (cb_data->session));
+
     g_signal_handlers_disconnect_by_func(cb_data->session, _on_refresh_dialog, user_data);
+    g_signal_handlers_disconnect_by_func(cb_data->session, _on_process_canceled, user_data);
 
     if (error) {
         WARN ("UI-Error: %s on identity %d",
               error->message,
               gsignond_identity_info_get_id (priv->info));
+        if (cb_data->session) {
+            GSignondSignonuiData *reply = gsignond_dictionary_new();
+            gsignond_signonui_data_set_query_error (reply, SIGNONUI_ERROR_GENERAL);
+            gsignond_auth_session_user_action_finished (cb_data->session, reply);
+            gsignond_dictionary_unref(reply);
+        }
         g_error_free (error);
         g_slice_free (GSignondIdentityCbData, cb_data);
         return;
     }
 
-    if (!gsignond_signonui_data_get_query_error (reply, &ui_error))
+    if (gsignond_signonui_data_get_query_error (reply, &ui_error)
+        && ui_error != SIGNONUI_ERROR_NONE) {
         WARN ("signonui error %d for identity %d",
-              ui_error,
-              gsignond_identity_info_get_id (priv->info));
+              ui_error, gsignond_identity_info_get_id (priv->info));
+    }
 
     if (!gsignond_identity_info_get_validated (priv->info) &&
         ui_error == SIGNONUI_ERROR_NONE) {
@@ -407,12 +424,27 @@ _on_user_action_completed (GSignondSignonuiData *reply, GError *error, gpointer
     if (cb_data->session) {
         gsignond_auth_session_user_action_finished (cb_data->session, reply);
     }
-    else if (reply) gsignond_signonui_data_unref (reply);
 
     g_slice_free (GSignondIdentityCbData, cb_data);
 }
 
 static void
+_on_process_canceled (GSignondAuthSession *session, GSignondIdentityCbData *cb_data)
+{
+    g_signal_handlers_disconnect_by_func(session, G_CALLBACK(_on_process_canceled), cb_data);
+
+    if (!cb_data) {
+        WARN ("assert (cb_data)");
+        return;
+    }
+    if (!gsignond_daemon_cancel_dialog (
+            cb_data->identity->priv->owner, G_OBJECT(session), NULL, NULL)) {
+        WARN ("Fail to cancel dialog");
+    }
+    g_slice_free (GSignondIdentityCbData, cb_data);
+}
+
+static void
 _on_user_action_required (GSignondAuthSession *session, GSignondSignonuiData *ui_data, gpointer userdata)
 {
     GSignondIdentity *identity = GSIGNOND_IDENTITY (userdata);
@@ -422,7 +454,9 @@ _on_user_action_required (GSignondAuthSession *session, GSignondSignonuiData *ui
     cb_data->session = session;
 
     gsignond_daemon_show_dialog (GSIGNOND_DAEMON (identity->priv->owner), G_OBJECT(session), 
-            ui_data, _on_user_action_completed, _on_refresh_requested_by_ui, userdata);
+            ui_data, _on_user_action_completed, _on_refresh_requested_by_ui, cb_data);
+
+    g_signal_connect (session, "process-canceled", G_CALLBACK(_on_process_canceled), cb_data);
 }
 
 static void
@@ -448,7 +482,7 @@ _compare_session_by_pointer (gpointer key, gpointer value, gpointer dead_object)
 }
 
 static void
-_on_session_close (gpointer data, GObject *session)
+_on_session_dead (gpointer data, GObject *session)
 {
     GSignondIdentity *identity = GSIGNOND_IDENTITY (data);
 
@@ -524,6 +558,7 @@ gsignond_identity_get_auth_session (GSignondIdentity *identity,
             GSIGNOND_IDENTITY_INFO_NEW_IDENTITY) {
         token_data = gsignond_daemon_load_identity_data (identity->priv->owner, identity_id, method);
     } 
+    if (!token_data) token_data = gsignond_dictionary_new();
 
     session = gsignond_auth_session_new (identity->priv->info, method, token_data);
 
@@ -539,7 +574,7 @@ gsignond_identity_get_auth_session (GSignondIdentity *identity,
     g_signal_connect (session, "process-store", G_CALLBACK (_on_store_token), identity);
 
     g_hash_table_insert (identity->priv->auth_sessions, g_strdup (method), session);
-    g_object_weak_ref (G_OBJECT (session), _on_session_close, identity);
+    g_object_weak_ref (G_OBJECT (session), _on_session_dead, identity);
 
     DBG ("session %p creation for method '%s' complete", session, method);
 
@@ -547,52 +582,55 @@ gsignond_identity_get_auth_session (GSignondIdentity *identity,
 }
 
 static void
-_on_query_dialog_done (GSignondSignonuiData *reply, GError *error, gpointer user_data)
+_on_credentials_updated (GSignondSignonuiData *reply, GError *error, gpointer user_data)
 {
     GSignondIdentity *identity = GSIGNOND_IDENTITY (user_data);
     guint32 id = 0;
     GError *err = NULL;
-    GSignondSignonuiError err_id = 0;
 
     if (error) {
-        WARN ("failed to verfiy user : %s", error->message);
+        WARN ("failed to verify user : %s", error->message);
         g_error_free (error);
 
-        err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED, "Operation cancled");
+        err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED, "Operation canceled");
     }
+    else
+    {
+        GSignondSignonuiError err_id = SIGNONUI_ERROR_NONE;
+        gboolean res = gsignond_signonui_data_get_query_error (reply, &err_id);
+
+        if (!res) {
+            DBG ("No error code set by UI daemon, treating as ERROR_NONE");
+        }
 
-    gboolean res = gsignond_signonui_data_get_query_error (reply, &err_id);
-    g_assert (res == TRUE);
-
-    if (err_id != SIGNONUI_ERROR_NONE) {
-        switch (err_id) {
-            case SIGNONUI_ERROR_CANCELED:
-                err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED,
-                        "Operation cancled");
-                break;
-            default:
-                err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER, 
+        if (err_id != SIGNONUI_ERROR_NONE) {
+            switch (err_id) {
+                case SIGNONUI_ERROR_CANCELED:
+                    err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED,
+                        "Operation canceled");
+                    break;
+                default:
+                    err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER, 
                         "signon ui returned with error : %d", err_id);
-                break;
+                    break;
+            }
         }
-    }
-    else {
-        const gchar *secret = gsignond_signonui_data_get_password (reply);
+        else {
+            const gchar *secret = gsignond_signonui_data_get_password (reply);
 
-        if (!secret) {
-            err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER,
+            if (!secret) {
+                err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER,
                                 "Server internal error occured");
-        } else if (identity->priv->info) {
-            gsignond_identity_info_set_secret (identity->priv->info, secret) ;
+            } else if (identity->priv->info) {
+                gsignond_identity_info_set_secret (identity->priv->info, secret) ;
 
-            /* Save new secret in db */
-            id = gsignond_daemon_store_identity (identity->priv->owner, identity);
-            if (!id) err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_STORE_FAILED, "Failed to store secret");
+                /* Save new secret in db */
+                id = gsignond_daemon_store_identity (identity->priv->owner, identity);
+                if (!id) err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_STORE_FAILED, "Failed to store secret");
+            }
         }
     }
 
-    gsignond_signonui_data_unref (reply);
-
     g_signal_emit (identity, signals[SIG_CREDENTIALS_UPDATED], 0 , id, err);
 
     if (err) g_error_free (err);
@@ -625,69 +663,70 @@ gsignond_identity_request_credentials_update (GSignondIdentity *identity,
         return FALSE;
     }
 
-    ui_data = gsignond_signonui_data_new ();
+    ui_data = gsignond_dictionary_new ();
 
-    gsignond_signonui_data_set_query_username (ui_data, TRUE);
+    gsignond_signonui_data_set_query_password (ui_data, TRUE);
     gsignond_signonui_data_set_username (ui_data, gsignond_identity_info_get_username (identity->priv->info));
     gsignond_signonui_data_set_caption (ui_data, gsignond_identity_info_get_caption (identity->priv->info));
     gsignond_signonui_data_set_message (ui_data, message);
   
     gsignond_daemon_show_dialog (GSIGNOND_DAEMON (identity->priv->owner), G_OBJECT(identity),
-        ui_data, _on_query_dialog_done, NULL, identity);
+        ui_data, _on_credentials_updated, NULL, identity);
 
-    gsignond_signonui_data_unref (ui_data);
+    gsignond_dictionary_unref (ui_data);
 
     return TRUE;
 }
 
 static void
-_on_user_verfied (GSignondSignonuiData *reply, GError *error, gpointer user_data)
+_on_user_verified (GSignondSignonuiData *reply, GError *error, gpointer user_data)
 {
     GSignondIdentity *identity = GSIGNOND_IDENTITY (user_data);
     gboolean res = FALSE;
     GError *err = NULL;
-    GSignondSignonuiError err_id = 0;
 
     if (error) {
-        WARN ("failed to verfiy user : %s", error->message);
+        WARN ("failed to verify user : %s", error->message);
         g_error_free (error);
 
-        err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED, "Operation cancled");
+        err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED, "Operation canceled");
     }
-
-    gboolean query_res = gsignond_signonui_data_get_query_error (reply, &err_id);
-    g_assert (query_res == TRUE);
-
-    if (err_id != SIGNONUI_ERROR_NONE) {
-        switch (err_id) {
-            case SIGNONUI_ERROR_CANCELED:
-                err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED,
-                        "Operation cancled");
-                break;
-            case SIGNONUI_ERROR_FORGOT_PASSWORD:
-                err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_FORGOT_PASSWORD, "Forgot password");
-                break;
-            default:
-                err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER, 
+    else
+    {
+        GSignondSignonuiError err_id = SIGNONUI_ERROR_NONE;
+        gboolean res = gsignond_signonui_data_get_query_error (reply, &err_id);
+        if (!res) {
+            DBG ("No error code set by UI daemon, treating as ERROR_NONE");
+        }
+        if (err_id != SIGNONUI_ERROR_NONE) {
+            switch (err_id) {
+                case SIGNONUI_ERROR_CANCELED:
+                    err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED,
+                        "Operation canceled");
+                    break;
+                case SIGNONUI_ERROR_FORGOT_PASSWORD:
+                    err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_FORGOT_PASSWORD, "Forgot password");
+                    break;
+                default:
+                    err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER, 
                         "signon ui returned error : %d", err_id);
-                break;
+                    break;
+            }
         }
-    }
-    else {
-        const gchar *secret = gsignond_signonui_data_get_password (reply);
+        else {
+            const gchar *secret = gsignond_signonui_data_get_password (reply);
 
-        if (!secret) {
-            err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER,
+            if (!secret) {
+                err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER,
                                 "Server internal error occured");
-        } else if (identity->priv->info) {
-            res = g_strcmp0 (secret, gsignond_identity_info_get_secret 
+            } else if (identity->priv->info) {
+                res = g_strcmp0 (secret, gsignond_identity_info_get_secret 
                                        (identity->priv->info)) == 0;
+            }
         }
     }
 
-    gsignond_signonui_data_unref (reply);
-
-    g_signal_emit (identity, signals[SIG_USER_VERIFIED], 0, res, error);
+    g_signal_emit (identity, signals[SIG_USER_VERIFIED], 0, res, err);
 
     if (err) g_error_free (err);
 }
@@ -722,15 +761,15 @@ gsignond_identity_verify_user (GSignondIdentity *identity,
         return FALSE;
     }
 
-    ui_data = gsignond_signonui_data_new_from_variant (params);
+    ui_data = gsignond_dictionary_new_from_variant (params);
     gsignond_signonui_data_set_query_password (ui_data, TRUE);
     gsignond_signonui_data_set_username (ui_data, gsignond_identity_info_get_username (identity->priv->info));
     gsignond_signonui_data_set_caption (ui_data, gsignond_identity_info_get_caption (identity->priv->info));
-   
+
     gsignond_daemon_show_dialog (GSIGNOND_DAEMON (identity->priv->owner), G_OBJECT (identity),
-        ui_data, _on_user_verfied, NULL, identity);
+        ui_data, _on_user_verified, NULL, identity);
 
-    gsignond_signonui_data_unref (ui_data);
+    gsignond_dictionary_unref (ui_data);
 
     return TRUE;
 }