static void
uoa_get_account_password (TpAccount *tp_account,
    GSimpleAsyncResult *result)
{
  AgAccountService *service;
  AgAuthData *auth_data;
  guint cred_id;
  SignonIdentity *identity;
  SignonAuthSession *session;
  GError *error = NULL;

  DEBUG ("Store password for %s in signond",
      tp_account_get_path_suffix (tp_account));

  service = uoa_password_common (tp_account, result, &auth_data);
  if (service == NULL)
    return;

  cred_id = ag_auth_data_get_credentials_id (auth_data);
  if (cred_id == 0)
    {
      g_simple_async_result_set_error (result,
          TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
          "AgAccount has no CredentialsId");
      g_simple_async_result_complete_in_idle (result);
      goto out;
    }

  identity = signon_identity_new_from_db (cred_id);
  session = signon_identity_create_session (identity,
      ag_auth_data_get_method (auth_data), &error);
  g_object_unref (identity);

  if (session == NULL)
    {
      g_simple_async_result_set_from_error (result, error);
      g_simple_async_result_complete_in_idle (result);
      goto out;
    }

  signon_auth_session_process_async (session,
      ag_auth_data_get_login_parameters (auth_data, NULL),
      ag_auth_data_get_mechanism (auth_data),
      NULL,
      uoa_session_process_cb,
      g_object_ref (result));

  g_object_unref (session);

out:
  ag_auth_data_unref (auth_data);
  g_object_unref (service);
}
static void
request_password (AuthContext *ctx)
{
  GVariantBuilder builder;

  DEBUG ("Invalid credentials, request user action");

  /* Inform SSO that the access token (or password) didn't work and it should
   * ask user to re-grant access (or retype password). */
  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
  g_variant_builder_add (&builder, "{sv}",
      SIGNON_SESSION_DATA_UI_POLICY,
      g_variant_new_int32 (SIGNON_POLICY_REQUEST_PASSWORD));

  signon_auth_session_process_async (ctx->session,
      ag_auth_data_get_login_parameters (ctx->auth_data,
          g_variant_builder_end (&builder)),
      ag_auth_data_get_mechanism (ctx->auth_data),
      NULL,
      request_password_session_process_cb, ctx);
}
static void
identity_query_info_cb (SignonIdentity *identity,
    const SignonIdentityInfo *info,
    const GError *error,
    gpointer user_data)
{
  AuthContext *ctx = user_data;

  if (error != NULL)
    {
      DEBUG ("Error querying info from identity: %s", error->message);
      auth_context_done (ctx);
      return;
    }

  ctx->username = g_strdup (signon_identity_info_get_username (info));

  signon_auth_session_process_async (ctx->session,
      ag_auth_data_get_login_parameters (ctx->auth_data, NULL),
      ag_auth_data_get_mechanism (ctx->auth_data),
      NULL,
      session_process_cb,
      ctx);
}
static AgAccountService *
uoa_password_common (TpAccount *tp_account,
    GSimpleAsyncResult *result,
    AgAuthData **ret_auth_data)
{
  const GValue *storage_id;
  AgAccountId account_id;
  AgManager *manager = NULL;
  AgAccount *account = NULL;
  GList *l;
  AgAccountService *service = NULL;
  AgAuthData *auth_data = NULL;

  g_assert (ret_auth_data != NULL);
  *ret_auth_data = NULL;

  storage_id = tp_account_get_storage_identifier (tp_account);
  account_id = g_value_get_uint (storage_id);
  if (account_id == 0)
    {
      g_simple_async_result_set_error (result,
          TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
          "StorageId is invalid, cannot get the AgAccount for this TpAccount");
      g_simple_async_result_complete_in_idle (result);
      goto error;
    }

  manager = empathy_uoa_manager_dup ();
  account = ag_manager_get_account (manager, account_id);

  /* Assuming there is only one IM service */
  l = ag_account_list_services_by_type (account, EMPATHY_UOA_SERVICE_TYPE);
  if (l == NULL)
    {
      g_simple_async_result_set_error (result,
          TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
          "AgAccount has no IM service");
      g_simple_async_result_complete_in_idle (result);
      goto error;
    }
  service = ag_account_service_new (account, l->data);
  ag_service_list_free (l);

  auth_data = ag_account_service_get_auth_data (service);
  if (auth_data == NULL)
    {
      g_simple_async_result_set_error (result,
          TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
          "Service has no AgAuthData");
      g_simple_async_result_complete_in_idle (result);
      goto error;
    }

  if (tp_strdiff (ag_auth_data_get_mechanism (auth_data), "password") ||
      tp_strdiff (ag_auth_data_get_method (auth_data), "password"))
    {
      g_simple_async_result_set_error (result,
          TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
          "Service does not use password authentication");
      g_simple_async_result_complete_in_idle (result);
      goto error;
    }

  g_object_unref (manager);
  g_object_unref (account);

  *ret_auth_data = auth_data;
  return service;

error:
  g_clear_object (&manager);
  g_clear_object (&account);
  g_clear_object (&service);
  tp_clear_pointer (&auth_data, ag_auth_data_unref);
  return NULL;
}