[evolution-data-server/account-mgmt] Support GoaExchange and GoaPasswordBased.



commit 87dd0931f998ab4fa5036cc55834cec1a074adfe
Author: Matthew Barnes <mbarnes redhat com>
Date:   Tue May 29 15:32:58 2012 -0400

    Support GoaExchange and GoaPasswordBased.

 configure.ac                                     |    6 +-
 modules/online-accounts/module-online-accounts.c |  136 ++++++++++++++++++++++
 2 files changed, 141 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 669567e..775c9c0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -38,7 +38,6 @@ m4_define([gtk_minimum_version], [3.2])
 m4_define([gconf_minimum_version], [2.0.0])		dnl XXX Just a Guess
 m4_define([gcr_minimum_version], [3.3])
 m4_define([gnome_keyring_minimum_version], [2.20.1])
-m4_define([goa_minimum_version], [3.1.1])
 m4_define([libxml_minimum_version], [2.0.0])		dnl XXX Just a Guess
 m4_define([libsoup_minimum_version], [2.38.1])
 m4_define([libgdata_minimum_version], [0.10])
@@ -407,6 +406,11 @@ if test "x$enable_goa" = xyes; then
 fi
 AM_CONDITIONAL(HAVE_GOA, [test x$enable_goa = xyes])
 
+dnl GoaPasswordBased was introduced in version 3.5.
+if `$PKG_CONFIG --atleast-version=3.5 goa-1.0`; then
+	AC_DEFINE(HAVE_GOA_PASSWORD_BASED,1,[Have GoaPasswordBased in goa-1.0])
+fi
+
 if test x$os_win32 = xno; then
 	PKG_CHECK_MODULES(GIO_UNIX, [gio-unix-2.0])
 fi
diff --git a/modules/online-accounts/module-online-accounts.c b/modules/online-accounts/module-online-accounts.c
index 76570d2..041c963 100644
--- a/modules/online-accounts/module-online-accounts.c
+++ b/modules/online-accounts/module-online-accounts.c
@@ -19,9 +19,12 @@
 /* XXX Yeah, yeah... */
 #define GOA_API_IS_SUBJECT_TO_CHANGE
 
+#include <config.h>
 #include <goa/goa.h>
+#include <gnome-keyring.h>
 
 #include <libedataserver/e-uid.h>
+#include <libedataserver/e-data-server-util.h>
 #include <libedataserver/e-source-authentication.h>
 #include <libedataserver/e-source-collection.h>
 #include <libedataserver/e-source-goa.h>
@@ -60,6 +63,20 @@ struct _EOnlineAccountsClass {
 	EExtensionClass parent_class;
 };
 
+/* The keyring definintions are copied from e-authentication-session.c */
+
+#define KEYRING_ITEM_ATTRIBUTE_NAME	"e-source-uid"
+#define KEYRING_ITEM_DISPLAY_FORMAT	"Evolution Data Source %s"
+
+static GnomeKeyringPasswordSchema schema = {
+	GNOME_KEYRING_ITEM_GENERIC_SECRET,
+	{
+		{ KEYRING_ITEM_ATTRIBUTE_NAME,
+		  GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
+		{ NULL, 0 }
+	}
+};
+
 /* Module Entry Points */
 void e_module_load (GTypeModule *type_module);
 void e_module_unload (GTypeModule *type_module);
@@ -82,6 +99,9 @@ online_accounts_get_backend_name (const gchar *goa_provider_type)
 	 * of other registry modules, possibly even from 3rd party
 	 * packages.  No way around it. */
 
+	if (g_strcmp0 (goa_provider_type, "exchange") == 0)
+		eds_backend_name = "ews";
+
 	if (g_strcmp0 (goa_provider_type, "google") == 0)
 		eds_backend_name = "google";
 
@@ -176,6 +196,118 @@ online_accounts_new_source (EOnlineAccounts *extension)
 	return source;
 }
 
+/* Helper for online_accounts_config_collection() */
+static void
+online_accounts_config_exchange (EOnlineAccounts *extension,
+                                 ESource *source,
+                                 GoaObject *goa_object)
+{
+#ifdef HAVE_GOA_PASSWORD_BASED
+	GoaExchange *goa_exchange;
+	ESourceExtension *source_extension;
+	const gchar *extension_name;
+
+	goa_exchange = goa_object_get_exchange (goa_object);
+
+	if (goa_exchange == NULL)
+		return;
+
+	extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+	source_extension = e_source_get_extension (source, extension_name);
+
+	g_object_bind_property (
+		goa_exchange, "host",
+		source_extension, "host",
+		G_BINDING_SYNC_CREATE);
+
+	g_object_unref (goa_exchange);
+#endif /* HAVE_GOA_PASSWORD_BASED */
+}
+
+/* Helper for online_accounts_config_collection() */
+static void
+online_accounts_config_password (EOnlineAccounts *extension,
+                                 ESource *source,
+                                 GoaObject *goa_object)
+{
+#ifdef HAVE_GOA_PASSWORD_BASED
+	GoaAccount *goa_account;
+	GoaPasswordBased *goa_password_based;
+	GnomeKeyringResult keyring_result;
+	EAsyncClosure *closure;
+	GAsyncResult *result;
+	const gchar *uid;
+	gchar *arg_id;
+	gchar *display_name;
+	gchar *password = NULL;
+	GError *error = NULL;
+
+	/* If the GNOME Online Account is password-based, we use its
+	 * password to seed our own keyring entry for the collection
+	 * source which avoids having to special-case authentication
+	 * like we do for OAuth.  Plus, if the stored password is no
+	 * good we'll prompt for a new one instead of just giving up. */
+
+	goa_password_based = goa_object_get_password_based (goa_object);
+
+	if (goa_password_based == NULL)
+		return;
+
+	closure = e_async_closure_new ();
+
+	/* XXX The GOA documentation doesn't explain the string
+	 *     argument in goa_password_based_get_password() so
+	 *     we'll pass in the identity and hope for the best. */
+	goa_account = goa_object_get_account (goa_object);
+	arg_id = goa_account_dup_identity (goa_account);
+	g_object_unref (goa_account);
+
+	goa_password_based_call_get_password (
+		goa_password_based, arg_id, NULL,
+		e_async_closure_callback, closure);
+
+	g_free (arg_id);
+
+	result = e_async_closure_wait (closure);
+
+	goa_password_based_call_get_password_finish (
+		goa_password_based, &password, result, &error);
+
+	if (error != NULL) {
+		g_warning ("%s: %s", G_STRFUNC, error->message);
+		g_error_free (error);
+		goto exit;
+	}
+
+	uid = e_source_get_uid (source);
+	display_name = g_strdup_printf (KEYRING_ITEM_DISPLAY_FORMAT, uid);
+
+	/* XXX Just call gnome-keyring synchronously.  I know it's
+	 *     evil, but I want to know the password has been stored
+	 *     before returning from this function.  We'll be moving
+	 *     to libsecret soon anyway, which is more GIO-based, so
+	 *     we could then reuse the EAsyncClosure here. */
+	keyring_result = gnome_keyring_store_password_sync (
+		&schema, GNOME_KEYRING_DEFAULT, display_name,
+		password, KEYRING_ITEM_ATTRIBUTE_NAME, uid, NULL);
+
+	g_free (display_name);
+
+	/* If we fail to store the password, we'll just end up prompting
+	 * for a password like normal.  Annoying, maybe, but not the end
+	 * of the world.  Still leave a breadcrumb for debugging though. */
+	if (keyring_result != GNOME_KEYRING_RESULT_OK) {
+		const gchar *message;
+		message = gnome_keyring_result_to_message (keyring_result);
+		g_warning ("%s: %s", G_STRFUNC, message);
+	}
+
+exit:
+	e_async_closure_free (closure);
+	g_object_unref (goa_password_based);
+#endif /* HAVE_GOA_PASSWORD_BASED */
+}
+
 static void
 online_accounts_config_collection (EOnlineAccounts *extension,
                                    ESource *source,
@@ -242,6 +374,10 @@ online_accounts_config_collection (EOnlineAccounts *extension,
 
 	g_object_unref (goa_account);
 
+	/* Handle optional GOA interfaces. */
+	online_accounts_config_exchange (extension, source, goa_object);
+	online_accounts_config_password (extension, source, goa_object);
+
 	/* The data source should not be removable by clients. */
 	e_server_side_source_set_removable (
 		E_SERVER_SIDE_SOURCE (source), FALSE);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]