]> git.0d.be Git - empathy.git/commitdiff
keyring: move from Empathy to tp-account-widgets
authorMarco Barisione <marco.barisione@collabora.co.uk>
Thu, 25 Jul 2013 15:24:14 +0000 (16:24 +0100)
committerMarco Barisione <marco.barisione@collabora.co.uk>
Tue, 20 Aug 2013 10:03:05 +0000 (11:03 +0100)
https://bugzilla.gnome.org/show_bug.cgi?id=699492

13 files changed:
libempathy-gtk/empathy-chat.c
libempathy/Makefile.am
libempathy/empathy-auth-factory.c
libempathy/empathy-keyring.c [deleted file]
libempathy/empathy-keyring.h [deleted file]
libempathy/empathy-server-sasl-handler.c
libempathy/empathy-uoa-auth-handler.c
src/empathy-sanity-cleaning.c
tests/interactive/Makefile.am
tp-account-widgets/Makefile.am
tp-account-widgets/tpaw-account-settings.c
tp-account-widgets/tpaw-keyring.c [new file with mode: 0644]
tp-account-widgets/tpaw-keyring.h [new file with mode: 0644]

index e0460e527b2bbc733e0d32709cbbc29054f006d9..5bdc7ba1b88334c2aae722e27afd686df2a7c384 100644 (file)
@@ -33,6 +33,7 @@
 #include "empathy-chat.h"
 
 #include <glib/gi18n-lib.h>
+#include <tp-account-widgets/tpaw-keyring.h>
 
 #include "empathy-client-factory.h"
 #include "empathy-gsettings.h"
@@ -40,7 +41,6 @@
 #include "empathy-individual-store-channel.h"
 #include "empathy-individual-view.h"
 #include "empathy-input-text-view.h"
-#include "empathy-keyring.h"
 #include "empathy-request-util.h"
 #include "empathy-search-bar.h"
 #include "empathy-smiley-manager.h"
@@ -3735,7 +3735,7 @@ remember_password_infobar_response_cb (GtkWidget *info_bar,
 
        if (response_id == GTK_RESPONSE_OK) {
                DEBUG ("Saving room password");
-               empathy_keyring_set_room_password_async (priv->account,
+               tpaw_keyring_set_room_password_async (priv->account,
                                                         empathy_tp_chat_get_id (priv->tp_chat),
                                                         data->password,
                                                         NULL, NULL);
@@ -4071,7 +4071,7 @@ chat_room_got_password_cb (GObject *source,
        const gchar *password;
        GError *error = NULL;
 
-       password = empathy_keyring_get_room_password_finish (priv->account,
+       password = tpaw_keyring_get_room_password_finish (priv->account,
            result, &error);
 
        if (error != NULL) {
@@ -4093,7 +4093,7 @@ chat_password_needed_changed_cb (EmpathyChat *self)
        EmpathyChatPriv *priv = GET_PRIV (self);
 
        if (tp_channel_password_needed (TP_CHANNEL (priv->tp_chat))) {
-               empathy_keyring_get_room_password_async (priv->account,
+               tpaw_keyring_get_room_password_async (priv->account,
                                                         empathy_tp_chat_get_id (priv->tp_chat),
                                                         chat_room_got_password_cb, self);
        }
index 13678a2525e6d8d09ca3e2291266a538b626d8d9..faf647a4c4ed7dc3d1797a1dda2ae5a13d449546 100644 (file)
@@ -41,7 +41,6 @@ libempathy_headers =                          \
        empathy-gsettings.h                     \
        empathy-presence-manager.h                              \
        empathy-individual-manager.h            \
-       empathy-keyring.h                       \
        empathy-location.h                      \
        empathy-message.h                       \
        empathy-pkg-kit.h               \
@@ -72,7 +71,6 @@ libempathy_handwritten_source =                               \
        empathy-ft-handler.c                            \
        empathy-presence-manager.c                                      \
        empathy-individual-manager.c                    \
-       empathy-keyring.c                               \
        empathy-message.c                               \
        empathy-pkg-kit.c               \
        empathy-request-util.c                          \
index cba4607a3e44af53b9df386e1e96e69d89cf3104..cbf7020ba47c37ff57bb8b800e8214cff1acebc9 100644 (file)
@@ -21,7 +21,8 @@
 #include "config.h"
 #include "empathy-auth-factory.h"
 
-#include "empathy-keyring.h"
+#include <tp-account-widgets/tpaw-keyring.h>
+
 #include "empathy-sasl-mechanisms.h"
 #include "empathy-server-sasl-handler.h"
 #include "empathy-server-tls-handler.h"
@@ -431,7 +432,7 @@ get_password_cb (GObject *source,
 {
   ObserveChannelsData *data = user_data;
 
-  if (empathy_keyring_get_account_password_finish (TP_ACCOUNT (source), result, NULL) == NULL)
+  if (tpaw_keyring_get_account_password_finish (TP_ACCOUNT (source), result, NULL) == NULL)
     {
       /* We don't actually mind if this fails, just let the approver
        * go ahead and take the channel. */
@@ -584,7 +585,7 @@ observe_channels (TpBaseClient *client,
           return;
         }
 
-      empathy_keyring_get_account_password_async (data->account,
+      tpaw_keyring_get_account_password_async (data->account,
           get_password_cb, data);
       tp_observe_channels_context_delay (context);
       return;
diff --git a/libempathy/empathy-keyring.c b/libempathy/empathy-keyring.c
deleted file mode 100644 (file)
index 367346b..0000000
+++ /dev/null
@@ -1,718 +0,0 @@
-/*
- * Copyright (C) 2010 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "config.h"
-#include "empathy-keyring.h"
-
-#include <glib/gi18n-lib.h>
-#include <libsecret/secret.h>
-
-#ifdef HAVE_UOA
-#include <libaccounts-glib/ag-account.h>
-#include <libaccounts-glib/ag-account-service.h>
-#include <libaccounts-glib/ag-auth-data.h>
-#include <libaccounts-glib/ag-manager.h>
-#include <libaccounts-glib/ag-service.h>
-#include <libsignon-glib/signon-identity.h>
-#include "empathy-uoa-utils.h"
-#endif
-
-#include "empathy-utils.h"
-
-#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
-#include "empathy-debug.h"
-
-static const SecretSchema account_keyring_schema =
-  { "org.gnome.Empathy.Account", SECRET_SCHEMA_DONT_MATCH_NAME,
-    { { "account-id", SECRET_SCHEMA_ATTRIBUTE_STRING },
-      { "param-name", SECRET_SCHEMA_ATTRIBUTE_STRING },
-      { NULL } } };
-
-static const SecretSchema room_keyring_schema =
-  { "org.gnome.Empathy.Room", SECRET_SCHEMA_DONT_MATCH_NAME,
-    { { "account-id", SECRET_SCHEMA_ATTRIBUTE_STRING },
-      { "room-id", SECRET_SCHEMA_ATTRIBUTE_STRING },
-      { NULL } } };
-
-/* get */
-
-static void
-lookup_item_cb (GObject *source,
-    GAsyncResult *result,
-    gpointer user_data)
-{
-  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
-  GError *error = NULL;
-  gchar *password;
-
-  password = secret_password_lookup_finish (result, &error);
-  if (error != NULL)
-    {
-      g_simple_async_result_set_error (simple, TP_ERROR,
-          TP_ERROR_DOES_NOT_EXIST, "%s", error->message);
-      g_clear_error (&error);
-      goto out;
-    }
-
-  if (password == NULL)
-    {
-      g_simple_async_result_set_error (simple, TP_ERROR,
-          TP_ERROR_DOES_NOT_EXIST, _("Password not found"));
-      goto out;
-    }
-
-  g_simple_async_result_set_op_res_gpointer (simple, password,
-      (GDestroyNotify) secret_password_free);
-
-out:
-  g_simple_async_result_complete (simple);
-  g_object_unref (simple);
-}
-
-#ifdef HAVE_UOA
-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;
-}
-
-static void
-uoa_session_process_cb (SignonAuthSession *session,
-    GHashTable *session_data,
-    const GError *error,
-    gpointer user_data)
-{
-  GSimpleAsyncResult *result = user_data;
-  const gchar *password;
-
-  if (error != NULL)
-    {
-      g_simple_async_result_set_from_error (result, error);
-      goto out;
-    }
-
-  password = tp_asv_get_string (session_data, "Secret");
-  if (tp_str_empty (password))
-    {
-      g_simple_async_result_set_error (result, TP_ERROR,
-          TP_ERROR_DOES_NOT_EXIST, _("Password not found"));
-      goto out;
-    }
-
-  g_simple_async_result_set_op_res_gpointer (result, g_strdup (password),
-      g_free);
-
-out:
-  /* libaccounts-glib API does not guarantee the callback happens after
-   * reentering mainloop */
-  g_simple_async_result_complete_in_idle (result);
-  g_object_unref (result);
-  g_object_unref (session);
-}
-
-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 (session,
-      ag_auth_data_get_parameters (auth_data),
-      ag_auth_data_get_mechanism (auth_data),
-      uoa_session_process_cb,
-      g_object_ref (result));
-
-out:
-  ag_auth_data_unref (auth_data);
-  g_object_unref (service);
-}
-#endif
-
-void
-empathy_keyring_get_account_password_async (TpAccount *account,
-    GAsyncReadyCallback callback,
-    gpointer user_data)
-{
-  GSimpleAsyncResult *simple;
-  const gchar *account_id;
-
-  g_return_if_fail (TP_IS_ACCOUNT (account));
-  g_return_if_fail (callback != NULL);
-
-  simple = g_simple_async_result_new (G_OBJECT (account), callback,
-      user_data, empathy_keyring_get_account_password_async);
-
-  account_id = tp_proxy_get_object_path (account) +
-    strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
-
-  DEBUG ("Trying to get password for: %s", account_id);
-
-#ifdef HAVE_UOA
-    {
-      const gchar *provider;
-
-      provider = tp_account_get_storage_provider (account);
-      if (!tp_strdiff (provider, EMPATHY_UOA_PROVIDER))
-        {
-          uoa_get_account_password (account, simple);
-          g_object_unref (simple);
-          return;
-        }
-    }
-#endif
-
-  secret_password_lookup (&account_keyring_schema, NULL,
-          lookup_item_cb, simple,
-          "account-id", account_id,
-          "param-name", "password",
-          NULL);
-}
-
-void
-empathy_keyring_get_room_password_async (TpAccount *account,
-    const gchar *id,
-    GAsyncReadyCallback callback,
-    gpointer user_data)
-{
-  GSimpleAsyncResult *simple;
-  const gchar *account_id;
-
-  g_return_if_fail (TP_IS_ACCOUNT (account));
-  g_return_if_fail (id != NULL);
-  g_return_if_fail (callback != NULL);
-
-  simple = g_simple_async_result_new (G_OBJECT (account), callback,
-      user_data, empathy_keyring_get_room_password_async);
-
-  account_id = tp_proxy_get_object_path (account) +
-    strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
-
-  DEBUG ("Trying to get password for room '%s' on account '%s'",
-      id, account_id);
-
-  secret_password_lookup (&room_keyring_schema, NULL,
-          lookup_item_cb, simple,
-          "account-id", account_id,
-          "room-id", id,
-          NULL);
-}
-
-const gchar *
-empathy_keyring_get_account_password_finish (TpAccount *account,
-    GAsyncResult *result,
-    GError **error)
-{
-  empathy_implement_finish_return_pointer (account,
-      empathy_keyring_get_account_password_async);
-}
-
-const gchar *
-empathy_keyring_get_room_password_finish (TpAccount *account,
-    GAsyncResult *result,
-    GError **error)
-{
-  empathy_implement_finish_return_pointer (account,
-      empathy_keyring_get_room_password_async);
-}
-
-/* set */
-
-static void
-store_password_cb (GObject *source,
-    GAsyncResult *result,
-    gpointer user_data)
-{
-  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
-  GError *error = NULL;
-
-  if (!secret_password_store_finish (result, &error))
-    {
-      g_simple_async_result_set_error (simple, TP_ERROR,
-          TP_ERROR_DOES_NOT_EXIST, "%s", error->message);
-      g_error_free (error);
-    }
-
-  g_simple_async_result_complete (simple);
-  g_object_unref (simple);
-}
-
-#ifdef HAVE_UOA
-typedef struct
-{
-  AgAccountService *service;
-  gchar *password;
-  gboolean remember;
-  GSimpleAsyncResult *result;
-} UoaChangePasswordData;
-
-static UoaChangePasswordData *
-uoa_change_password_data_new (AgAccountService *service,
-    const gchar *password,
-    gboolean remember,
-    GSimpleAsyncResult *result)
-{
-  UoaChangePasswordData *data;
-
-  data = g_slice_new0 (UoaChangePasswordData);
-  data->service = g_object_ref (service);
-  data->password = g_strdup (password);
-  data->remember = remember;
-  data->result = g_object_ref (result);
-
-  return data;
-}
-
-static void
-uoa_change_password_data_free (UoaChangePasswordData *data)
-{
-  g_object_unref (data->service);
-  g_free (data->password);
-  g_object_unref (data->result);
-  g_slice_free (UoaChangePasswordData, data);
-}
-
-static void
-uoa_identity_store_cb (SignonIdentity *identity,
-    guint32 id,
-    const GError *error,
-    gpointer user_data)
-{
-  UoaChangePasswordData *data = user_data;
-
-  if (error != NULL)
-    g_simple_async_result_set_from_error (data->result, error);
-
-  g_simple_async_result_complete (data->result);
-  uoa_change_password_data_free (data);
-  g_object_unref (identity);
-}
-
-static void
-uoa_identity_query_info_cb (SignonIdentity *identity,
-    const SignonIdentityInfo *info,
-    const GError *error,
-    gpointer user_data)
-{
-  UoaChangePasswordData *data = user_data;
-
-  if (error != NULL)
-    {
-      g_simple_async_result_set_from_error (data->result, error);
-      /* libaccounts-glib API does not guarantee the callback happens after
-       * reentering mainloop */
-      g_simple_async_result_complete_in_idle (data->result);
-      uoa_change_password_data_free (data);
-      g_object_unref (identity);
-      return;
-    }
-
-  /* const SignonIdentityInfo is a lie, cast it! - Mardy */
-  signon_identity_info_set_secret ((SignonIdentityInfo *) info,
-      data->password, data->remember);
-
-  signon_identity_store_credentials_with_info (identity, info,
-      uoa_identity_store_cb, data);
-}
-
-static void
-uoa_initial_account_store_cb (AgAccount *account,
-    const GError *error,
-    gpointer user_data)
-{
-  UoaChangePasswordData *data = user_data;
-
-  if (error != NULL)
-    g_simple_async_result_set_from_error (data->result, error);
-
-      /* libaccounts-glib API does not guarantee the callback happens after
-       * reentering mainloop */
-  g_simple_async_result_complete_in_idle (data->result);
-  uoa_change_password_data_free (data);
-}
-
-static void
-uoa_initial_identity_store_cb (SignonIdentity *identity,
-    guint32 id,
-    const GError *error,
-    gpointer user_data)
-{
-  UoaChangePasswordData *data = user_data;
-  AgAccount *account = ag_account_service_get_account (data->service);
-  GValue value = G_VALUE_INIT;
-
-  if (error != NULL)
-    {
-      g_simple_async_result_set_from_error (data->result, error);
-      /* libaccounts-glib API does not guarantee the callback happens after
-       * reentering mainloop */
-      g_simple_async_result_complete_in_idle (data->result);
-      uoa_change_password_data_free (data);
-      g_object_unref (identity);
-      return;
-    }
-
-  g_value_init (&value, G_TYPE_UINT);
-  g_value_set_uint (&value, id);
-  ag_account_select_service (account, NULL);
-  ag_account_set_value (account, "CredentialsId", &value);
-  g_value_unset (&value);
-
-  ag_account_store (account, uoa_initial_account_store_cb, data);
-
-  g_object_unref (identity);
-}
-
-static void
-uoa_set_account_password (TpAccount *tp_account,
-    const gchar *password,
-    gboolean remember,
-    GSimpleAsyncResult *result)
-{
-  AgAccountService *service;
-  AgAuthData *auth_data;
-  guint cred_id;
-  UoaChangePasswordData *data;
-  SignonIdentity *identity;
-
-  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;
-
-  data = uoa_change_password_data_new (service, password, remember, result);
-
-  cred_id = ag_auth_data_get_credentials_id (auth_data);
-  if (cred_id == 0)
-    {
-      SignonIdentityInfo *info;
-      const GHashTable *params;
-      const gchar *username;
-      const gchar *acl_all[] = { "*", NULL };
-
-      /* This is the first time we store password for this account.
-       * First check if we have an 'username' param as this is more accurate
-       * in the tp-idle case. */
-      params = tp_account_get_parameters (tp_account);
-      username = tp_asv_get_string (params, "username");
-      if (username == NULL)
-        username = tp_asv_get_string (params, "account");
-
-      identity = signon_identity_new ();
-      info = signon_identity_info_new ();
-      signon_identity_info_set_username (info, username);
-      signon_identity_info_set_secret (info, password, remember);
-      signon_identity_info_set_access_control_list (info, acl_all);
-
-      /* Give identity and data ownership to the callback */
-      signon_identity_store_credentials_with_info (identity, info,
-          uoa_initial_identity_store_cb, data);
-
-      signon_identity_info_free (info);
-    }
-  else
-    {
-      /* There is already a password stored, query info to update it.
-       * Give identity and data ownership to the callback */
-      identity = signon_identity_new_from_db (cred_id);
-      signon_identity_query_info (identity,
-          uoa_identity_query_info_cb, data);
-    }
-
-  g_object_unref (service);
-  ag_auth_data_unref (auth_data);
-}
-#endif
-
-void
-empathy_keyring_set_account_password_async (TpAccount *account,
-    const gchar *password,
-    gboolean remember,
-    GAsyncReadyCallback callback,
-    gpointer user_data)
-{
-  GSimpleAsyncResult *simple;
-  const gchar *account_id;
-  gchar *name;
-
-  g_return_if_fail (TP_IS_ACCOUNT (account));
-  g_return_if_fail (password != NULL);
-
-  simple = g_simple_async_result_new (G_OBJECT (account), callback,
-      user_data, empathy_keyring_set_account_password_async);
-
-  account_id = tp_proxy_get_object_path (account) +
-    strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
-
-  DEBUG ("Remembering password for %s", account_id);
-
-#ifdef HAVE_UOA
-    {
-      const gchar *provider;
-
-      provider = tp_account_get_storage_provider (account);
-      if (!tp_strdiff (provider, EMPATHY_UOA_PROVIDER))
-        {
-          uoa_set_account_password (account, password, remember, simple);
-          g_object_unref (simple);
-          return;
-        }
-    }
-#endif
-
-  name = g_strdup_printf (_("IM account password for %s (%s)"),
-      tp_account_get_display_name (account), account_id);
-
-  secret_password_store (&account_keyring_schema,
-      remember ? NULL : SECRET_COLLECTION_SESSION,
-      name, password,
-      NULL, store_password_cb, simple,
-      "account-id", account_id,
-      "param-name", "password",
-      NULL);
-
-  g_free (name);
-}
-
-void
-empathy_keyring_set_room_password_async (TpAccount *account,
-    const gchar *id,
-    const gchar *password,
-    GAsyncReadyCallback callback,
-    gpointer user_data)
-{
-  GSimpleAsyncResult *simple;
-  const gchar *account_id;
-  gchar *name;
-
-  g_return_if_fail (TP_IS_ACCOUNT (account));
-  g_return_if_fail (id != NULL);
-  g_return_if_fail (password != NULL);
-
-  simple = g_simple_async_result_new (G_OBJECT (account), callback,
-      user_data, empathy_keyring_set_room_password_async);
-
-  account_id = tp_proxy_get_object_path (account) +
-    strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
-
-  DEBUG ("Remembering password for room '%s' on account '%s'", id, account_id);
-
-  name = g_strdup_printf (_("Password for chatroom '%s' on account %s (%s)"),
-      id, tp_account_get_display_name (account), account_id);
-
-  secret_password_store (&room_keyring_schema, NULL, name, password,
-      NULL, store_password_cb, simple,
-      "account-id", account_id,
-      "room-id", id,
-      NULL);
-
-  g_free (name);
-}
-
-gboolean
-empathy_keyring_set_account_password_finish (TpAccount *account,
-    GAsyncResult *result,
-    GError **error)
-{
-  empathy_implement_finish_void (account, empathy_keyring_set_account_password_async);
-}
-
-gboolean
-empathy_keyring_set_room_password_finish (TpAccount *account,
-    GAsyncResult *result,
-    GError **error)
-{
-  empathy_implement_finish_void (account, empathy_keyring_set_room_password_async);
-}
-
-/* delete */
-
-static void
-items_delete_cb (GObject *source,
-    GAsyncResult *result,
-    gpointer user_data)
-{
-  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
-  GError *error = NULL;
-
-  secret_password_clear_finish (result, &error);
-  if (error != NULL)
-    {
-      g_simple_async_result_set_error (simple, TP_ERROR,
-              TP_ERROR_DOES_NOT_EXIST, "%s", error->message);
-      g_error_free (error);
-    }
-
-  g_simple_async_result_complete (simple);
-  g_object_unref (simple);
-}
-
-void
-empathy_keyring_delete_account_password_async (TpAccount *account,
-    GAsyncReadyCallback callback,
-    gpointer user_data)
-{
-  GSimpleAsyncResult *simple;
-  const gchar *account_id;
-
-  g_return_if_fail (TP_IS_ACCOUNT (account));
-
-  simple = g_simple_async_result_new (G_OBJECT (account), callback,
-      user_data, empathy_keyring_delete_account_password_async);
-
-  account_id = tp_proxy_get_object_path (account) +
-    strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
-
-  DEBUG ("Deleting password for %s", account_id);
-
-#ifdef HAVE_UOA
-    {
-      const gchar *provider;
-
-      provider = tp_account_get_storage_provider (account);
-      if (!tp_strdiff (provider, EMPATHY_UOA_PROVIDER))
-        {
-          /* I see no other way to forget the stored password than overwriting
-           * with an empty one. */
-          uoa_set_account_password (account, "", FALSE, simple);
-          g_object_unref (simple);
-          return;
-        }
-    }
-#endif
-
-  secret_password_clear (&account_keyring_schema, NULL,
-          items_delete_cb, simple,
-          "account-id", account_id,
-          "param-name", "password",
-          NULL);
-}
-
-gboolean
-empathy_keyring_delete_account_password_finish (TpAccount *account,
-    GAsyncResult *result,
-    GError **error)
-{
-  empathy_implement_finish_void (account, empathy_keyring_delete_account_password_async);
-}
diff --git a/libempathy/empathy-keyring.h b/libempathy/empathy-keyring.h
deleted file mode 100644 (file)
index 8a426a0..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2010 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef __EMPATHY_KEYRING_H__
-#define __EMPATHY_KEYRING_H__
-
-#include <gio/gio.h>
-#include <telepathy-glib/telepathy-glib.h>
-
-G_BEGIN_DECLS
-
-void empathy_keyring_get_account_password_async (TpAccount *account,
-    GAsyncReadyCallback callback, gpointer user_data);
-
-const gchar * empathy_keyring_get_account_password_finish (TpAccount *account,
-    GAsyncResult *result, GError **error);
-
-void empathy_keyring_get_room_password_async (TpAccount *account,
-    const gchar *id,
-    GAsyncReadyCallback callback, gpointer user_data);
-
-const gchar * empathy_keyring_get_room_password_finish (TpAccount *account,
-    GAsyncResult *result, GError **error);
-
-void empathy_keyring_set_account_password_async (TpAccount *account,
-    const gchar *password, gboolean remember, GAsyncReadyCallback callback,
-    gpointer user_data);
-
-gboolean empathy_keyring_set_account_password_finish (TpAccount *account,
-    GAsyncResult *result, GError **error);
-
-void empathy_keyring_set_room_password_async (TpAccount *account,
-    const gchar *id, const gchar *password, GAsyncReadyCallback callback,
-    gpointer user_data);
-
-gboolean empathy_keyring_set_room_password_finish (TpAccount *account,
-    GAsyncResult *result, GError **error);
-
-void empathy_keyring_delete_account_password_async (TpAccount *account,
-    GAsyncReadyCallback callback, gpointer user_data);
-
-gboolean empathy_keyring_delete_account_password_finish (TpAccount *account,
-    GAsyncResult *result, GError **error);
-
-G_END_DECLS
-
-#endif /* __EMPATHY_KEYRING_H__ */
-
index b18d1a7356d1b28da91e22934da9ca7c27caa0dc..e98134ebb9eee9f66487d426476ef8703f5ee50c 100644 (file)
@@ -20,7 +20,8 @@
 #include "config.h"
 #include "empathy-server-sasl-handler.h"
 
-#include "empathy-keyring.h"
+#include <tp-account-widgets/tpaw-keyring.h>
+
 #include "empathy-sasl-mechanisms.h"
 #include "extensions.h"
 
@@ -67,7 +68,7 @@ empathy_server_sasl_handler_set_password_cb (GObject *source,
 {
   GError *error = NULL;
 
-  if (!empathy_keyring_set_account_password_finish (TP_ACCOUNT (source), result,
+  if (!tpaw_keyring_set_account_password_finish (TP_ACCOUNT (source), result,
           &error))
     {
       DEBUG ("Failed to set password: %s", error->message);
@@ -102,7 +103,7 @@ empathy_server_sasl_handler_get_password_async_cb (GObject *source,
 
   priv = EMPATHY_SERVER_SASL_HANDLER (user_data)->priv;
 
-  password = empathy_keyring_get_account_password_finish (TP_ACCOUNT (source),
+  password = tpaw_keyring_get_account_password_finish (TP_ACCOUNT (source),
       result, &error);
 
   if (password != NULL)
@@ -133,7 +134,7 @@ empathy_server_sasl_handler_init_async (GAsyncInitable *initable,
   priv->async_init_res = g_simple_async_result_new (G_OBJECT (self),
       callback, user_data, empathy_server_sasl_handler_new_async);
 
-  empathy_keyring_get_account_password_async (priv->account,
+  tpaw_keyring_get_account_password_async (priv->account,
       empathy_server_sasl_handler_get_password_async_cb, self);
 }
 
@@ -354,7 +355,7 @@ auth_cb (GObject *source,
   else
     {
       DEBUG ("Saving password in keyring");
-      empathy_keyring_set_account_password_async (priv->account,
+      tpaw_keyring_set_account_password_async (priv->account,
           priv->password, priv->save_password,
           empathy_server_sasl_handler_set_password_cb,
           NULL);
@@ -429,7 +430,7 @@ empathy_server_sasl_handler_provide_password (
   if (!may_save_response)
     {
       /* delete any password present, it shouldn't be there */
-      empathy_keyring_delete_account_password_async (priv->account, NULL, NULL);
+      tpaw_keyring_delete_account_password_async (priv->account, NULL, NULL);
     }
 
   /* Additionally, if we implement Ch.I.CredentialsStorage, inform that
index 7e17b70894903c3113e64ba8acaca3e98fc0cd22..eff3dd6d496ae89cffe9222bd2e37c176401df37 100644 (file)
@@ -30,7 +30,8 @@
 #include <libsignon-glib/signon-identity.h>
 #include <libsignon-glib/signon-auth-session.h>
 
-#include "empathy-keyring.h"
+#include <tp-account-widgets/tpaw-keyring.h>
+
 #include "empathy-utils.h"
 #include "empathy-uoa-utils.h"
 #include "empathy-sasl-mechanisms.h"
@@ -293,7 +294,7 @@ set_account_password_cb (GObject *source,
   AuthContext *new_ctx;
   GError *error = NULL;
 
-  if (!empathy_keyring_set_account_password_finish (tp_account, result, &error))
+  if (!tpaw_keyring_set_account_password_finish (tp_account, result, &error))
     {
       DEBUG ("Failed to set empty password on UOA account: %s", error->message);
       auth_context_done (ctx);
@@ -360,7 +361,7 @@ empathy_uoa_auth_handler_start (EmpathyUoaAuthHandler *self,
        * To ask user to type his password SSO needs a SignonIdentity bound to
        * our account. Let's store an empty password. */
       DEBUG ("Couldn't create a signon session");
-      empathy_keyring_set_account_password_async (tp_account, "", FALSE,
+      tpaw_keyring_set_account_password_async (tp_account, "", FALSE,
           set_account_password_cb, ctx);
     }
   else
index 827a34ebaa0f448698a0d5cabf9895d467d89395..6ad0990aa6cd84047947c5b4b934393e4d965624 100644 (file)
@@ -28,8 +28,8 @@
 #include <libaccounts-glib/ag-account-service.h>
 #include <libaccounts-glib/ag-manager.h>
 #include <libaccounts-glib/ag-service.h>
+#include <tp-account-widgets/tpaw-keyring.h>
 
-#include "empathy-keyring.h"
 #include "empathy-pkg-kit.h"
 #include "empathy-uoa-utils.h"
 #endif
@@ -318,7 +318,7 @@ uoa_set_account_password_cb (GObject *source,
   UoaMigrationData *data = user_data;
   GError *error = NULL;
 
-  if (!empathy_keyring_set_account_password_finish (data->new_account, result,
+  if (!tpaw_keyring_set_account_password_finish (data->new_account, result,
           &error))
     {
       DEBUG ("Error setting old account's password on the new one: %s\n",
@@ -338,7 +338,7 @@ uoa_get_account_password_cb (GObject *source,
   const gchar *password;
   GError *error = NULL;
 
-  password = empathy_keyring_get_account_password_finish (data->old_account,
+  password = tpaw_keyring_get_account_password_finish (data->old_account,
       result, &error);
   if (password == NULL)
     {
@@ -349,7 +349,7 @@ uoa_get_account_password_cb (GObject *source,
     }
   else
     {
-      empathy_keyring_set_account_password_async (data->new_account, password,
+      tpaw_keyring_set_account_password_async (data->new_account, password,
           TRUE, uoa_set_account_password_cb, data);
     }
 }
@@ -380,7 +380,7 @@ uoa_account_created_cb (GObject *source,
           tp_account_get_path_suffix (data->old_account));
 
       /* Migrate password as well */
-      empathy_keyring_get_account_password_async (data->old_account,
+      tpaw_keyring_get_account_password_async (data->old_account,
           uoa_get_account_password_cb, data);
     }
 }
index 4ca1989eed213a08083264b1246160ad9834e02e..397536b3a3b59eeb15d4e51d20d3f48acdcce0f1 100644 (file)
@@ -1,5 +1,6 @@
 AM_CPPFLAGS =                                          \
        $(ERROR_CFLAGS)                                 \
+       -I$(top_srcdir)/tp-account-widgets              \
        -I$(top_srcdir)/libempathy                      \
        -I$(top_srcdir)/libempathy-gtk                  \
        -DPKGDATADIR=\""$(pkgdatadir)"\"                \
index 7c615e4b0032ca973c0fbf229788d9aed7498d24..dbfffeeb5ad9e1d134cf43f4237c566985e1ac5d 100644 (file)
@@ -22,6 +22,7 @@ libtp_account_widgets_sources =               \
        tpaw-account-widget-private.h           \
        tpaw-account-widget-sip.c               \
        tpaw-connection-managers.c              \
+       tpaw-keyring.c                          \
        tpaw-irc-network-chooser.c              \
        tpaw-irc-network-chooser-dialog.c       \
        tpaw-irc-network-dialog.c               \
@@ -37,6 +38,7 @@ libtp_account_widgets_headers =                       \
        tpaw-account-widget-irc.h               \
        tpaw-account-widget-sip.h               \
        tpaw-connection-managers.h              \
+       tpaw-keyring.h                          \
        tpaw-irc-network-chooser-dialog.h       \
        tpaw-irc-network-chooser.h              \
        tpaw-irc-network-dialog.h               \
index a837a251e691d565af5587f8db82422235b48211..5359cb7bd6b90fd97f9a7e98470e0e26749901ba 100644 (file)
@@ -22,7 +22,7 @@
 #include "tpaw-account-settings.h"
 
 #include "tpaw-connection-managers.h"
-#include "empathy-keyring.h"
+#include "tpaw-keyring.h"
 #include "empathy-presence-manager.h"
 #include "empathy-utils.h"
 
@@ -436,7 +436,7 @@ tpaw_account_settings_get_password_cb (GObject *source,
   const gchar *password;
   GError *error = NULL;
 
-  password = empathy_keyring_get_account_password_finish (TP_ACCOUNT (source),
+  password = tpaw_keyring_get_account_password_finish (TP_ACCOUNT (source),
       result, &error);
 
   if (error != NULL)
@@ -555,7 +555,7 @@ tpaw_account_settings_check_readyness (TpawAccountSettings *self)
 
       /* Make this call but don't block on its readiness. We'll signal
        * if it's updated later with ::password-retrieved. */
-      empathy_keyring_get_account_password_async (priv->account,
+      tpaw_keyring_get_account_password_async (priv->account,
           tpaw_account_settings_get_password_cb, self);
     }
 
@@ -1251,7 +1251,7 @@ tpaw_account_settings_set_password_cb (GObject *source,
     gpointer user_data)
 {
   tpaw_account_settings_processed_password (source, result, user_data,
-      empathy_keyring_set_account_password_finish);
+      tpaw_keyring_set_account_password_finish);
 }
 
 static void
@@ -1260,7 +1260,7 @@ tpaw_account_settings_delete_password_cb (GObject *source,
     gpointer user_data)
 {
   tpaw_account_settings_processed_password (source, result, user_data,
-      empathy_keyring_delete_account_password_finish);
+      tpaw_keyring_delete_account_password_finish);
 }
 
 static void
@@ -1335,13 +1335,13 @@ tpaw_account_settings_account_updated (GObject *source,
           /* FIXME: we shouldn't save the password if we
            * can't (MaySaveResponse=False) but we don't have API to check that
            * at this point (fdo #35382). */
-          empathy_keyring_set_account_password_async (priv->account,
+          tpaw_keyring_set_account_password_async (priv->account,
               priv->password, priv->remember_password,
               tpaw_account_settings_set_password_cb, settings);
         }
       else
         {
-          empathy_keyring_delete_account_password_async (priv->account,
+          tpaw_keyring_delete_account_password_async (priv->account,
               tpaw_account_settings_delete_password_cb, settings);
         }
 
@@ -1384,7 +1384,7 @@ tpaw_account_settings_created_cb (GObject *source,
           /* FIXME: we shouldn't save the password if we
            * can't (MaySaveResponse=False) but we don't have API to check that
            * at this point (fdo #35382). */
-          empathy_keyring_set_account_password_async (priv->account,
+          tpaw_keyring_set_account_password_async (priv->account,
               priv->password, priv->remember_password,
               tpaw_account_settings_set_password_cb,
               settings);
diff --git a/tp-account-widgets/tpaw-keyring.c b/tp-account-widgets/tpaw-keyring.c
new file mode 100644 (file)
index 0000000..cc7eb25
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+#include "tpaw-keyring.h"
+
+#include <glib/gi18n-lib.h>
+#include <libsecret/secret.h>
+
+#ifdef HAVE_UOA
+#include <libaccounts-glib/ag-account.h>
+#include <libaccounts-glib/ag-account-service.h>
+#include <libaccounts-glib/ag-auth-data.h>
+#include <libaccounts-glib/ag-manager.h>
+#include <libaccounts-glib/ag-service.h>
+#include <libsignon-glib/signon-identity.h>
+#include "empathy-uoa-utils.h"
+#endif
+
+#include "empathy-utils.h"
+
+#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
+#include "empathy-debug.h"
+
+static const SecretSchema account_keyring_schema =
+  { "org.gnome.Empathy.Account", SECRET_SCHEMA_DONT_MATCH_NAME,
+    { { "account-id", SECRET_SCHEMA_ATTRIBUTE_STRING },
+      { "param-name", SECRET_SCHEMA_ATTRIBUTE_STRING },
+      { NULL } } };
+
+static const SecretSchema room_keyring_schema =
+  { "org.gnome.Empathy.Room", SECRET_SCHEMA_DONT_MATCH_NAME,
+    { { "account-id", SECRET_SCHEMA_ATTRIBUTE_STRING },
+      { "room-id", SECRET_SCHEMA_ATTRIBUTE_STRING },
+      { NULL } } };
+
+/* get */
+
+static void
+lookup_item_cb (GObject *source,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+  GError *error = NULL;
+  gchar *password;
+
+  password = secret_password_lookup_finish (result, &error);
+  if (error != NULL)
+    {
+      g_simple_async_result_set_error (simple, TP_ERROR,
+          TP_ERROR_DOES_NOT_EXIST, "%s", error->message);
+      g_clear_error (&error);
+      goto out;
+    }
+
+  if (password == NULL)
+    {
+      g_simple_async_result_set_error (simple, TP_ERROR,
+          TP_ERROR_DOES_NOT_EXIST, _("Password not found"));
+      goto out;
+    }
+
+  g_simple_async_result_set_op_res_gpointer (simple, password,
+      (GDestroyNotify) secret_password_free);
+
+out:
+  g_simple_async_result_complete (simple);
+  g_object_unref (simple);
+}
+
+#ifdef HAVE_UOA
+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;
+}
+
+static void
+uoa_session_process_cb (SignonAuthSession *session,
+    GHashTable *session_data,
+    const GError *error,
+    gpointer user_data)
+{
+  GSimpleAsyncResult *result = user_data;
+  const gchar *password;
+
+  if (error != NULL)
+    {
+      g_simple_async_result_set_from_error (result, error);
+      goto out;
+    }
+
+  password = tp_asv_get_string (session_data, "Secret");
+  if (tp_str_empty (password))
+    {
+      g_simple_async_result_set_error (result, TP_ERROR,
+          TP_ERROR_DOES_NOT_EXIST, _("Password not found"));
+      goto out;
+    }
+
+  g_simple_async_result_set_op_res_gpointer (result, g_strdup (password),
+      g_free);
+
+out:
+  /* libaccounts-glib API does not guarantee the callback happens after
+   * reentering mainloop */
+  g_simple_async_result_complete_in_idle (result);
+  g_object_unref (result);
+  g_object_unref (session);
+}
+
+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 (session,
+      ag_auth_data_get_parameters (auth_data),
+      ag_auth_data_get_mechanism (auth_data),
+      uoa_session_process_cb,
+      g_object_ref (result));
+
+out:
+  ag_auth_data_unref (auth_data);
+  g_object_unref (service);
+}
+#endif
+
+void
+tpaw_keyring_get_account_password_async (TpAccount *account,
+    GAsyncReadyCallback callback,
+    gpointer user_data)
+{
+  GSimpleAsyncResult *simple;
+  const gchar *account_id;
+
+  g_return_if_fail (TP_IS_ACCOUNT (account));
+  g_return_if_fail (callback != NULL);
+
+  simple = g_simple_async_result_new (G_OBJECT (account), callback,
+      user_data, tpaw_keyring_get_account_password_async);
+
+  account_id = tp_proxy_get_object_path (account) +
+    strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
+
+  DEBUG ("Trying to get password for: %s", account_id);
+
+#ifdef HAVE_UOA
+    {
+      const gchar *provider;
+
+      provider = tp_account_get_storage_provider (account);
+      if (!tp_strdiff (provider, EMPATHY_UOA_PROVIDER))
+        {
+          uoa_get_account_password (account, simple);
+          g_object_unref (simple);
+          return;
+        }
+    }
+#endif
+
+  secret_password_lookup (&account_keyring_schema, NULL,
+          lookup_item_cb, simple,
+          "account-id", account_id,
+          "param-name", "password",
+          NULL);
+}
+
+void
+tpaw_keyring_get_room_password_async (TpAccount *account,
+    const gchar *id,
+    GAsyncReadyCallback callback,
+    gpointer user_data)
+{
+  GSimpleAsyncResult *simple;
+  const gchar *account_id;
+
+  g_return_if_fail (TP_IS_ACCOUNT (account));
+  g_return_if_fail (id != NULL);
+  g_return_if_fail (callback != NULL);
+
+  simple = g_simple_async_result_new (G_OBJECT (account), callback,
+      user_data, tpaw_keyring_get_room_password_async);
+
+  account_id = tp_proxy_get_object_path (account) +
+    strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
+
+  DEBUG ("Trying to get password for room '%s' on account '%s'",
+      id, account_id);
+
+  secret_password_lookup (&room_keyring_schema, NULL,
+          lookup_item_cb, simple,
+          "account-id", account_id,
+          "room-id", id,
+          NULL);
+}
+
+const gchar *
+tpaw_keyring_get_account_password_finish (TpAccount *account,
+    GAsyncResult *result,
+    GError **error)
+{
+  empathy_implement_finish_return_pointer (account,
+      tpaw_keyring_get_account_password_async);
+}
+
+const gchar *
+tpaw_keyring_get_room_password_finish (TpAccount *account,
+    GAsyncResult *result,
+    GError **error)
+{
+  empathy_implement_finish_return_pointer (account,
+      tpaw_keyring_get_room_password_async);
+}
+
+/* set */
+
+static void
+store_password_cb (GObject *source,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+  GError *error = NULL;
+
+  if (!secret_password_store_finish (result, &error))
+    {
+      g_simple_async_result_set_error (simple, TP_ERROR,
+          TP_ERROR_DOES_NOT_EXIST, "%s", error->message);
+      g_error_free (error);
+    }
+
+  g_simple_async_result_complete (simple);
+  g_object_unref (simple);
+}
+
+#ifdef HAVE_UOA
+typedef struct
+{
+  AgAccountService *service;
+  gchar *password;
+  gboolean remember;
+  GSimpleAsyncResult *result;
+} UoaChangePasswordData;
+
+static UoaChangePasswordData *
+uoa_change_password_data_new (AgAccountService *service,
+    const gchar *password,
+    gboolean remember,
+    GSimpleAsyncResult *result)
+{
+  UoaChangePasswordData *data;
+
+  data = g_slice_new0 (UoaChangePasswordData);
+  data->service = g_object_ref (service);
+  data->password = g_strdup (password);
+  data->remember = remember;
+  data->result = g_object_ref (result);
+
+  return data;
+}
+
+static void
+uoa_change_password_data_free (UoaChangePasswordData *data)
+{
+  g_object_unref (data->service);
+  g_free (data->password);
+  g_object_unref (data->result);
+  g_slice_free (UoaChangePasswordData, data);
+}
+
+static void
+uoa_identity_store_cb (SignonIdentity *identity,
+    guint32 id,
+    const GError *error,
+    gpointer user_data)
+{
+  UoaChangePasswordData *data = user_data;
+
+  if (error != NULL)
+    g_simple_async_result_set_from_error (data->result, error);
+
+  g_simple_async_result_complete (data->result);
+  uoa_change_password_data_free (data);
+  g_object_unref (identity);
+}
+
+static void
+uoa_identity_query_info_cb (SignonIdentity *identity,
+    const SignonIdentityInfo *info,
+    const GError *error,
+    gpointer user_data)
+{
+  UoaChangePasswordData *data = user_data;
+
+  if (error != NULL)
+    {
+      g_simple_async_result_set_from_error (data->result, error);
+      /* libaccounts-glib API does not guarantee the callback happens after
+       * reentering mainloop */
+      g_simple_async_result_complete_in_idle (data->result);
+      uoa_change_password_data_free (data);
+      g_object_unref (identity);
+      return;
+    }
+
+  /* const SignonIdentityInfo is a lie, cast it! - Mardy */
+  signon_identity_info_set_secret ((SignonIdentityInfo *) info,
+      data->password, data->remember);
+
+  signon_identity_store_credentials_with_info (identity, info,
+      uoa_identity_store_cb, data);
+}
+
+static void
+uoa_initial_account_store_cb (AgAccount *account,
+    const GError *error,
+    gpointer user_data)
+{
+  UoaChangePasswordData *data = user_data;
+
+  if (error != NULL)
+    g_simple_async_result_set_from_error (data->result, error);
+
+      /* libaccounts-glib API does not guarantee the callback happens after
+       * reentering mainloop */
+  g_simple_async_result_complete_in_idle (data->result);
+  uoa_change_password_data_free (data);
+}
+
+static void
+uoa_initial_identity_store_cb (SignonIdentity *identity,
+    guint32 id,
+    const GError *error,
+    gpointer user_data)
+{
+  UoaChangePasswordData *data = user_data;
+  AgAccount *account = ag_account_service_get_account (data->service);
+  GValue value = G_VALUE_INIT;
+
+  if (error != NULL)
+    {
+      g_simple_async_result_set_from_error (data->result, error);
+      /* libaccounts-glib API does not guarantee the callback happens after
+       * reentering mainloop */
+      g_simple_async_result_complete_in_idle (data->result);
+      uoa_change_password_data_free (data);
+      g_object_unref (identity);
+      return;
+    }
+
+  g_value_init (&value, G_TYPE_UINT);
+  g_value_set_uint (&value, id);
+  ag_account_select_service (account, NULL);
+  ag_account_set_value (account, "CredentialsId", &value);
+  g_value_unset (&value);
+
+  ag_account_store (account, uoa_initial_account_store_cb, data);
+
+  g_object_unref (identity);
+}
+
+static void
+uoa_set_account_password (TpAccount *tp_account,
+    const gchar *password,
+    gboolean remember,
+    GSimpleAsyncResult *result)
+{
+  AgAccountService *service;
+  AgAuthData *auth_data;
+  guint cred_id;
+  UoaChangePasswordData *data;
+  SignonIdentity *identity;
+
+  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;
+
+  data = uoa_change_password_data_new (service, password, remember, result);
+
+  cred_id = ag_auth_data_get_credentials_id (auth_data);
+  if (cred_id == 0)
+    {
+      SignonIdentityInfo *info;
+      const GHashTable *params;
+      const gchar *username;
+      const gchar *acl_all[] = { "*", NULL };
+
+      /* This is the first time we store password for this account.
+       * First check if we have an 'username' param as this is more accurate
+       * in the tp-idle case. */
+      params = tp_account_get_parameters (tp_account);
+      username = tp_asv_get_string (params, "username");
+      if (username == NULL)
+        username = tp_asv_get_string (params, "account");
+
+      identity = signon_identity_new ();
+      info = signon_identity_info_new ();
+      signon_identity_info_set_username (info, username);
+      signon_identity_info_set_secret (info, password, remember);
+      signon_identity_info_set_access_control_list (info, acl_all);
+
+      /* Give identity and data ownership to the callback */
+      signon_identity_store_credentials_with_info (identity, info,
+          uoa_initial_identity_store_cb, data);
+
+      signon_identity_info_free (info);
+    }
+  else
+    {
+      /* There is already a password stored, query info to update it.
+       * Give identity and data ownership to the callback */
+      identity = signon_identity_new_from_db (cred_id);
+      signon_identity_query_info (identity,
+          uoa_identity_query_info_cb, data);
+    }
+
+  g_object_unref (service);
+  ag_auth_data_unref (auth_data);
+}
+#endif
+
+void
+tpaw_keyring_set_account_password_async (TpAccount *account,
+    const gchar *password,
+    gboolean remember,
+    GAsyncReadyCallback callback,
+    gpointer user_data)
+{
+  GSimpleAsyncResult *simple;
+  const gchar *account_id;
+  gchar *name;
+
+  g_return_if_fail (TP_IS_ACCOUNT (account));
+  g_return_if_fail (password != NULL);
+
+  simple = g_simple_async_result_new (G_OBJECT (account), callback,
+      user_data, tpaw_keyring_set_account_password_async);
+
+  account_id = tp_proxy_get_object_path (account) +
+    strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
+
+  DEBUG ("Remembering password for %s", account_id);
+
+#ifdef HAVE_UOA
+    {
+      const gchar *provider;
+
+      provider = tp_account_get_storage_provider (account);
+      if (!tp_strdiff (provider, EMPATHY_UOA_PROVIDER))
+        {
+          uoa_set_account_password (account, password, remember, simple);
+          g_object_unref (simple);
+          return;
+        }
+    }
+#endif
+
+  name = g_strdup_printf (_("IM account password for %s (%s)"),
+      tp_account_get_display_name (account), account_id);
+
+  secret_password_store (&account_keyring_schema,
+      remember ? NULL : SECRET_COLLECTION_SESSION,
+      name, password,
+      NULL, store_password_cb, simple,
+      "account-id", account_id,
+      "param-name", "password",
+      NULL);
+
+  g_free (name);
+}
+
+void
+tpaw_keyring_set_room_password_async (TpAccount *account,
+    const gchar *id,
+    const gchar *password,
+    GAsyncReadyCallback callback,
+    gpointer user_data)
+{
+  GSimpleAsyncResult *simple;
+  const gchar *account_id;
+  gchar *name;
+
+  g_return_if_fail (TP_IS_ACCOUNT (account));
+  g_return_if_fail (id != NULL);
+  g_return_if_fail (password != NULL);
+
+  simple = g_simple_async_result_new (G_OBJECT (account), callback,
+      user_data, tpaw_keyring_set_room_password_async);
+
+  account_id = tp_proxy_get_object_path (account) +
+    strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
+
+  DEBUG ("Remembering password for room '%s' on account '%s'", id, account_id);
+
+  name = g_strdup_printf (_("Password for chatroom '%s' on account %s (%s)"),
+      id, tp_account_get_display_name (account), account_id);
+
+  secret_password_store (&room_keyring_schema, NULL, name, password,
+      NULL, store_password_cb, simple,
+      "account-id", account_id,
+      "room-id", id,
+      NULL);
+
+  g_free (name);
+}
+
+gboolean
+tpaw_keyring_set_account_password_finish (TpAccount *account,
+    GAsyncResult *result,
+    GError **error)
+{
+  empathy_implement_finish_void (account, tpaw_keyring_set_account_password_async);
+}
+
+gboolean
+tpaw_keyring_set_room_password_finish (TpAccount *account,
+    GAsyncResult *result,
+    GError **error)
+{
+  empathy_implement_finish_void (account, tpaw_keyring_set_room_password_async);
+}
+
+/* delete */
+
+static void
+items_delete_cb (GObject *source,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+  GError *error = NULL;
+
+  secret_password_clear_finish (result, &error);
+  if (error != NULL)
+    {
+      g_simple_async_result_set_error (simple, TP_ERROR,
+              TP_ERROR_DOES_NOT_EXIST, "%s", error->message);
+      g_error_free (error);
+    }
+
+  g_simple_async_result_complete (simple);
+  g_object_unref (simple);
+}
+
+void
+tpaw_keyring_delete_account_password_async (TpAccount *account,
+    GAsyncReadyCallback callback,
+    gpointer user_data)
+{
+  GSimpleAsyncResult *simple;
+  const gchar *account_id;
+
+  g_return_if_fail (TP_IS_ACCOUNT (account));
+
+  simple = g_simple_async_result_new (G_OBJECT (account), callback,
+      user_data, tpaw_keyring_delete_account_password_async);
+
+  account_id = tp_proxy_get_object_path (account) +
+    strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
+
+  DEBUG ("Deleting password for %s", account_id);
+
+#ifdef HAVE_UOA
+    {
+      const gchar *provider;
+
+      provider = tp_account_get_storage_provider (account);
+      if (!tp_strdiff (provider, EMPATHY_UOA_PROVIDER))
+        {
+          /* I see no other way to forget the stored password than overwriting
+           * with an empty one. */
+          uoa_set_account_password (account, "", FALSE, simple);
+          g_object_unref (simple);
+          return;
+        }
+    }
+#endif
+
+  secret_password_clear (&account_keyring_schema, NULL,
+          items_delete_cb, simple,
+          "account-id", account_id,
+          "param-name", "password",
+          NULL);
+}
+
+gboolean
+tpaw_keyring_delete_account_password_finish (TpAccount *account,
+    GAsyncResult *result,
+    GError **error)
+{
+  empathy_implement_finish_void (account, tpaw_keyring_delete_account_password_async);
+}
diff --git a/tp-account-widgets/tpaw-keyring.h b/tp-account-widgets/tpaw-keyring.h
new file mode 100644 (file)
index 0000000..bf2e652
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __TPAW_KEYRING_H__
+#define __TPAW_KEYRING_H__
+
+#include <gio/gio.h>
+#include <telepathy-glib/telepathy-glib.h>
+
+G_BEGIN_DECLS
+
+void tpaw_keyring_get_account_password_async (TpAccount *account,
+    GAsyncReadyCallback callback, gpointer user_data);
+
+const gchar * tpaw_keyring_get_account_password_finish (TpAccount *account,
+    GAsyncResult *result, GError **error);
+
+void tpaw_keyring_get_room_password_async (TpAccount *account,
+    const gchar *id,
+    GAsyncReadyCallback callback, gpointer user_data);
+
+const gchar * tpaw_keyring_get_room_password_finish (TpAccount *account,
+    GAsyncResult *result, GError **error);
+
+void tpaw_keyring_set_account_password_async (TpAccount *account,
+    const gchar *password, gboolean remember, GAsyncReadyCallback callback,
+    gpointer user_data);
+
+gboolean tpaw_keyring_set_account_password_finish (TpAccount *account,
+    GAsyncResult *result, GError **error);
+
+void tpaw_keyring_set_room_password_async (TpAccount *account,
+    const gchar *id, const gchar *password, GAsyncReadyCallback callback,
+    gpointer user_data);
+
+gboolean tpaw_keyring_set_room_password_finish (TpAccount *account,
+    GAsyncResult *result, GError **error);
+
+void tpaw_keyring_delete_account_password_async (TpAccount *account,
+    GAsyncReadyCallback callback, gpointer user_data);
+
+gboolean tpaw_keyring_delete_account_password_finish (TpAccount *account,
+    GAsyncResult *result, GError **error);
+
+G_END_DECLS
+
+#endif /* __TPAW_KEYRING_H__ */