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
identity_signout_ready_cb(gpointer object, const GError *error, gpointer user_data)
{
    g_return_if_fail (SIGNON_IS_IDENTITY (object));

    SignonIdentity *self = SIGNON_IDENTITY (object);
    SignonIdentityPrivate *priv = self->priv;
    g_return_if_fail (priv != NULL);

    DEBUG ("%s %d", G_STRFUNC, __LINE__);
    IdentityVoidCbData *cb_data = (IdentityVoidCbData *)user_data;

    g_return_if_fail (cb_data != NULL);

    if (priv->removed == TRUE)
    {
        GError *new_error = g_error_new (signon_error_quark(),
                                         SIGNON_ERROR_IDENTITY_NOT_FOUND,
                                         "Already removed from database.");
        if (cb_data->cb)
        {
            (cb_data->cb) (self, new_error, cb_data->user_data);
        }

        g_error_free (new_error);
        g_slice_free (IdentityVoidCbData, cb_data);
    }
    else if (error)
    {
        DEBUG ("IdentityError: %s", error->message);
        if (cb_data->cb)
        {
            (cb_data->cb) (self, error, cb_data->user_data);
        }

        g_slice_free (IdentityVoidCbData, cb_data);
    }
    else
    {
        g_return_if_fail (priv->proxy != NULL);
        sso_identity_call_sign_out (priv->proxy,
                                    priv->cancellable,
                                    identity_signout_reply,
                                    cb_data);
    }
}
static void
auth_session_get_object_path_reply (GObject *object, GAsyncResult *res,
                                    gpointer userdata)
{
    SsoAuthService *proxy = SSO_AUTH_SERVICE (object);
    gchar *object_path = NULL;
    GError *error = NULL;

    sso_auth_service_call_get_auth_session_object_path_finish (proxy,
                                                               &object_path,
                                                               res,
                                                               &error);
    SIGNON_RETURN_IF_CANCELLED (error);

    g_return_if_fail (SIGNON_IS_AUTH_SESSION (userdata));
    SignonAuthSession *self = SIGNON_AUTH_SESSION (userdata);
    SignonAuthSessionPrivate *priv = self->priv;
    g_return_if_fail (priv != NULL);

    priv->registering = FALSE;
    if (!g_strcmp0(object_path, "") || error)
    {
        if (error)
            DEBUG ("Error message is %s", error->message);
        else
            error = g_error_new (signon_error_quark(),
                                 SIGNON_ERROR_RUNTIME,
                                 "Cannot create remote AuthSession object");
    }
    else
    {
        GDBusConnection *connection;
        const gchar *bus_name;
        GError *proxy_error = NULL;

        connection = g_dbus_proxy_get_connection ((GDBusProxy *)proxy);
        bus_name = g_dbus_proxy_get_name ((GDBusProxy *)proxy);

        priv->proxy =
            sso_auth_session_proxy_new_sync (connection,
                                             G_DBUS_PROXY_FLAGS_NONE,
                                             bus_name,
                                             object_path,
                                             priv->cancellable,
                                             &proxy_error);
        if (G_UNLIKELY (proxy_error != NULL))
        {
            g_warning ("Failed to initialize AuthSession proxy: %s",
                       proxy_error->message);
            g_clear_error (&proxy_error);
        }

        g_dbus_proxy_set_default_timeout ((GDBusProxy *)priv->proxy,
                                          G_MAXINT);

        priv->signal_state_changed =
            g_signal_connect (priv->proxy,
                              "state-changed",
                              G_CALLBACK (auth_session_state_changed_cb),
                              self);

        priv->signal_unregistered =
           g_signal_connect (priv->proxy,
                             "unregistered",
                             G_CALLBACK (auth_session_remote_object_destroyed_cb),
                             self);
    }

    DEBUG ("Object path received: %s", object_path);
    _signon_object_ready (self, auth_session_object_quark (), error);
    g_clear_error (&error);
}
static void
identity_verify_ready_cb (gpointer object, const GError *error, gpointer user_data)
{
    g_return_if_fail (SIGNON_IS_IDENTITY (object));

    SignonIdentity *self = SIGNON_IDENTITY (object);
    SignonIdentityPrivate *priv = self->priv;
    g_return_if_fail (priv != NULL);

    DEBUG ("%s %d", G_STRFUNC, __LINE__);

    IdentityVerifyData *operation_data =
        (IdentityVerifyData *)user_data;
    g_return_if_fail (operation_data != NULL);

    IdentityVerifyCbData *cb_data = operation_data->cb_data;
    g_return_if_fail (cb_data != NULL);

    if (priv->removed == TRUE)
    {
        GError *new_error = g_error_new (signon_error_quark(),
                                         SIGNON_ERROR_IDENTITY_NOT_FOUND,
                                         "Already removed from database.");

        if (cb_data->cb)
        {
            (cb_data->cb) (self, FALSE, new_error, cb_data->user_data);
        }

        g_error_free (new_error);
        g_slice_free (IdentityVerifyCbData, cb_data);
    }
    else if (error)
    {
        DEBUG ("IdentityError: %s", error->message);

        if (cb_data->cb)
        {
            (cb_data->cb) (self, FALSE, error, cb_data->user_data);
        }

        g_slice_free (IdentityVerifyCbData, cb_data);
    }
    else
    {
        DEBUG ("%s %d", G_STRFUNC, __LINE__);
        g_return_if_fail (priv->proxy != NULL);

        switch (operation_data->operation) {
        case SIGNON_VERIFY_SECRET:
            sso_identity_call_verify_secret (priv->proxy,
                                             operation_data->data_to_send,
                                             priv->cancellable,
                                             identity_verify_reply,
                                             cb_data);
            break;
        default: g_critical ("Wrong operation code");
        };
    }
    g_free (operation_data->params);
    g_free (operation_data->data_to_send);
    g_slice_free (IdentityVerifyData, operation_data);
}
/**
 * signon_identity_create_session:
 * @self: the #SignonIdentity.
 * @method: method.
 * @error: pointer to a location which will receive the error, if any.
 *
 * Creates an authentication session for this identity.
 *
 * Returns: (transfer full): a new #SignonAuthSession.
 */
SignonAuthSession *
signon_identity_create_session(SignonIdentity *self,
                               const gchar *method,
                               GError **error)
{
    g_return_val_if_fail (SIGNON_IS_IDENTITY (self), NULL);

    SignonIdentityPrivate *priv = self->priv;
    g_return_val_if_fail (priv != NULL, NULL);

    DEBUG ("%s %d", G_STRFUNC, __LINE__);

    if (method == NULL)
    {
        DEBUG ("NULL method as input. Aborting.");
        g_set_error(error,
                    signon_error_quark(),
                    SIGNON_ERROR_UNKNOWN,
                    "NULL input method.");
        return NULL;
    }

    GSList *list = priv->sessions;
    while (list)
    {
        SignonAuthSession *session = SIGNON_AUTH_SESSION (priv->sessions->data);
        const gchar *sessionMethod = signon_auth_session_get_method (session);
        if (g_strcmp0(sessionMethod, method) == 0)
        {
            DEBUG ("Auth Session with method `%s` already created.", method);
            g_set_error (error,
                         signon_error_quark(),
                         SIGNON_ERROR_METHOD_NOT_AVAILABLE,
                         "Authentication session for this method already requested.");
            return NULL;
        }

        list = list->next;
    }

    SignonAuthSession *session = signon_auth_session_new (priv->id,
                                                          method,
                                                          error);
    if (session)
    {
        DEBUG ("%s %d", G_STRFUNC, __LINE__);
        priv->sessions = g_slist_append(priv->sessions, session);
        g_object_weak_ref (G_OBJECT(session),
                           identity_session_object_destroyed_cb,
                           self);
        /*
         * if you want to delete the identity
         * you MUST delete all authsessions
         * first
         * */
        g_object_ref (self);
        priv->signed_out = FALSE;
    }

    return session;
}
static void
identity_info_ready_cb(gpointer object, const GError *error, gpointer user_data)
{
    g_return_if_fail (SIGNON_IS_IDENTITY (object));

    SignonIdentity *self = SIGNON_IDENTITY (object);
    SignonIdentityPrivate *priv = self->priv;
    g_return_if_fail (priv != NULL);

    DEBUG ("%s %d", G_STRFUNC, __LINE__);

    IdentityVoidData *operation_data =
        (IdentityVoidData *)user_data;
    g_return_if_fail (operation_data != NULL);

    IdentityInfoCbData *cb_data = operation_data->cb_data;
    g_return_if_fail (cb_data != NULL);

    if (priv->removed == TRUE)
    {
        GError *new_error = g_error_new (signon_error_quark(),
                                         SIGNON_ERROR_IDENTITY_NOT_FOUND,
                                         "Already removed from database.");
        if (cb_data->cb)
        {
            (cb_data->cb) (self, NULL, new_error, cb_data->user_data);
        }

        g_error_free (new_error);
    }
    else if (error || priv->id == 0)
    {
        if (error)
            DEBUG ("IdentityError: %s", error->message);
        else
            DEBUG ("Identity is not stored and has no info yet");

        if (cb_data->cb)
        {
            (cb_data->cb) (self, NULL, error, cb_data->user_data);
        }
    }
    else if (priv->updated == FALSE)
    {
        g_return_if_fail (priv->proxy != NULL);
        sso_identity_call_get_info (priv->proxy,
                                    priv->cancellable,
                                    identity_info_reply,
                                    cb_data);
    }
    else
    {
        if (cb_data->cb)
        {
            (cb_data->cb) (self, priv->identity_info, error, cb_data->user_data);
        }
    }

    if (priv->updated == TRUE)
        g_slice_free (IdentityInfoCbData, cb_data);

    g_slice_free (IdentityVoidData, operation_data);
}