[evolution-data-server/account-mgmt: 39/40] Add 'google-accounts' module.



commit 11fbd95bd3010ec48446a795bc28a8506abd5b16
Author: Matthew Barnes <mbarnes redhat com>
Date:   Thu Apr 5 00:22:02 2012 -0400

    Add 'google-accounts' module.

 configure.ac                                     |    1 +
 modules/Makefile.am                              |    1 +
 modules/google-accounts/Makefile.am              |   34 ++
 modules/google-accounts/e-source-caldav.c        |    1 +
 modules/google-accounts/e-source-caldav.h        |    1 +
 modules/google-accounts/module-google-accounts.c |  592 ++++++++++++++++++++++
 6 files changed, 630 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 8337131..1bb86b9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1651,6 +1651,7 @@ libedataserver/libedataserver.pc
 libedataserverui/Makefile
 libedataserverui/libedataserverui.pc
 modules/Makefile
+modules/google-accounts/Makefile
 modules/online-accounts/Makefile
 services/Makefile
 services/evolution-addressbook-factory/Makefile
diff --git a/modules/Makefile.am b/modules/Makefile.am
index 6f7cf42..eda9fb4 100644
--- a/modules/Makefile.am
+++ b/modules/Makefile.am
@@ -5,6 +5,7 @@ ONLINE_ACCOUNTS_DIR = online-accounts
 endif
 
 SUBDIRS = \
+	google-accounts \
 	$(ONLINE_ACCOUNTS_DIR) \
 	$(NULL)
 
diff --git a/modules/google-accounts/Makefile.am b/modules/google-accounts/Makefile.am
new file mode 100644
index 0000000..feb41b9
--- /dev/null
+++ b/modules/google-accounts/Makefile.am
@@ -0,0 +1,34 @@
+NULL =
+
+module_LTLIBRARIES = module-google-accounts.la
+
+module_google_accounts_la_CPPFLAGS = \
+	$(AM_CPPFLAGS) \
+	-I$(top_srcdir) \
+	-DG_LOG_DOMAIN=\"module-google-accounts\" \
+	$(E_BACKEND_CFLAGS) \
+	$(E_DATA_SERVER_CFLAGS) \
+	$(NULL)
+
+# e-source-caldav.[ch] are symbolic links to
+# ../../calendar/backends/caldav/e-source-caldav.[ch]
+
+module_google_accounts_la_SOURCES = \
+	module-google-accounts.c \
+	e-source-caldav.c \
+	e-source-caldav.h \
+	$(NULL)
+
+module_google_accounts_la_LIBADD = \
+	$(top_builddir)/libebackend/libebackend-1.2.la \
+	$(top_builddir)/libedataserver/libedataserver-1.2.la \
+	$(top_builddir)/camel/libcamel-1.2.la \
+	$(E_BACKEND_LIBS) \
+	$(E_DATA_SERVER_LIBS) \
+	$(NULL)
+
+module_google_accounts_la_LDFLAGS = \
+	-module -avoid-version $(NO_UNDEFINED) \
+	$(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/modules/google-accounts/e-source-caldav.c b/modules/google-accounts/e-source-caldav.c
new file mode 120000
index 0000000..c41cdac
--- /dev/null
+++ b/modules/google-accounts/e-source-caldav.c
@@ -0,0 +1 @@
+../../calendar/backends/caldav/e-source-caldav.c
\ No newline at end of file
diff --git a/modules/google-accounts/e-source-caldav.h b/modules/google-accounts/e-source-caldav.h
new file mode 120000
index 0000000..fb5ef2e
--- /dev/null
+++ b/modules/google-accounts/e-source-caldav.h
@@ -0,0 +1 @@
+../../calendar/backends/caldav/e-source-caldav.h
\ No newline at end of file
diff --git a/modules/google-accounts/module-google-accounts.c b/modules/google-accounts/module-google-accounts.c
new file mode 100644
index 0000000..49e208e
--- /dev/null
+++ b/modules/google-accounts/module-google-accounts.c
@@ -0,0 +1,592 @@
+/*
+ * module-google-accounts.c
+ *
+ * This program 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 of the License, or (at your option) version 3.
+ *
+ * This program 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 the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+
+#include <libedataserver/e-uid.h>
+#include <libedataserver/e-source-address-book.h>
+#include <libedataserver/e-source-authentication.h>
+#include <libedataserver/e-source-calendar.h>
+#include <libedataserver/e-source-camel.h>
+#include <libedataserver/e-source-collection.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-identity.h>
+#include <libedataserver/e-source-mail-transport.h>
+#include <libedataserver/e-source-security.h>
+
+#include <libebackend/e-extension.h>
+#include <libebackend/e-dbus-source-server.h>
+#include <libebackend/e-server-side-source.h>
+
+#include "e-source-caldav.h"
+
+/* Standard GObject macros */
+#define E_TYPE_GOOGLE_ACCOUNTS \
+	(e_google_accounts_get_type ())
+#define E_GOOGLE_ACCOUNTS(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_GOOGLE_ACCOUNTS, EGoogleAccounts))
+
+/* Just for readability... */
+#define METHOD(x) (CAMEL_NETWORK_SECURITY_METHOD_##x)
+
+/* IMAP Configuration Details */
+#define GOOGLE_IMAP_BACKEND_NAME	"imapx"
+#define GOOGLE_IMAP_HOST		"imap.gmail.com"
+#define GOOGLE_IMAP_PORT		993
+#define GOOGLE_IMAP_SECURITY_METHOD	METHOD (SSL_ON_ALTERNATE_PORT)
+
+/* SMTP Configuration Details */
+#define GOOGLE_SMTP_BACKEND_NAME	"smtp"
+#define GOOGLE_SMTP_HOST		"smtp.gmail.com"
+#define GOOGLE_SMTP_PORT		587
+#define GOOGLE_SMTP_SECURITY_METHOD	METHOD (STARTTLS_ON_STANDARD_PORT)
+
+/* Calendar Configuration Details */
+#define GOOGLE_CALENDAR_BACKEND_NAME	"caldav"
+#define GOOGLE_CALENDAR_HOST		"www.google.com"
+#define GOOGLE_CALENDAR_CALDAV_PATH	"/calendar/dav/%s/events"
+
+/* Contacts Configuration Details */
+#define GOOGLE_CONTACTS_BACKEND_NAME	"google"
+
+typedef struct _EGoogleAccounts EGoogleAccounts;
+typedef struct _EGoogleAccountsClass EGoogleAccountsClass;
+
+typedef struct _Closure Closure;
+
+struct _EGoogleAccounts {
+	EExtension parent;
+};
+
+struct _EGoogleAccountsClass {
+	EExtensionClass parent_class;
+};
+
+struct _Closure {
+	EGoogleAccounts *extension;
+	gchar *uid;
+};
+
+/* Module Entry Points */
+void e_module_load (GTypeModule *type_module);
+void e_module_unload (GTypeModule *type_module);
+
+/* Forward Declarations */
+GType e_google_accounts_get_type (void);
+
+G_DEFINE_DYNAMIC_TYPE (
+	EGoogleAccounts,
+	e_google_accounts,
+	E_TYPE_EXTENSION)
+
+static Closure *
+closure_new (EGoogleAccounts *extension,
+             ESource *source)
+{
+	Closure *closure;
+
+	closure = g_slice_new0 (Closure);
+	closure->extension = g_object_ref (extension);
+	closure->uid = g_strdup (e_source_get_uid (source));
+
+	return closure;
+}
+
+static void
+closure_free (Closure *closure)
+{
+	g_object_unref (closure->extension);
+	g_free (closure->uid);
+
+	g_slice_free (Closure, closure);
+}
+
+static EDBusSourceServer *
+google_accounts_get_server (EGoogleAccounts *extension)
+{
+	EExtensible *extensible;
+
+	extensible = e_extension_get_extensible (E_EXTENSION (extension));
+
+	return E_DBUS_SOURCE_SERVER (extensible);
+}
+
+static ESource *
+google_accounts_new_source (EGoogleAccounts *extension)
+{
+	EDBusSourceServer *server;
+	ESource *source;
+	GFile *file;
+	gchar *new_uid;
+	gchar *filename;
+	const gchar *user_dir;
+	GError *error = NULL;
+
+	user_dir = e_server_side_source_get_user_dir ();
+
+	new_uid = e_uid_new ();
+	filename = g_build_filename (user_dir, new_uid, NULL);
+	file = g_file_new_for_path (filename);
+
+	/* This being a brand new data source, creating the instance
+	 * should never fail but we'll check for errors just the same. */
+	server = google_accounts_get_server (extension);
+	source = e_server_side_source_new (server, file, &error);
+
+	g_object_unref (file);
+	g_free (filename);
+	g_free (new_uid);
+
+	if (error != NULL) {
+		g_warn_if_fail (source == NULL);
+		g_warning ("%s: %s", G_STRFUNC, error->message);
+		g_error_free (error);
+	}
+
+	return source;
+}
+
+static ESource *
+google_accounts_find_child_source (ESource *parent_source,
+                                   const gchar *extension_name)
+{
+	GNode *node;
+
+	node = e_server_side_source_get_node (
+		E_SERVER_SIDE_SOURCE (parent_source));
+
+	node = g_node_first_child (node);
+
+	while (node != NULL) {
+		ESource *child_source = E_SOURCE (node->data);
+
+		if (e_source_has_extension (child_source, extension_name))
+			return g_object_ref (child_source);
+
+		node = g_node_next_sibling (node);
+	}
+
+	return NULL;
+}
+
+static void
+google_accounts_config_mail_account (EGoogleAccounts *extension,
+                                     ESource *collection_source)
+{
+	ESource *source;
+	ESourceCamel *camel_extension;
+	ESourceExtension *source_extension;
+	ESourceCollection *collection_extension;
+	CamelSettings *settings;
+	const gchar *backend_name;
+	const gchar *extension_name;
+
+	/* The mail account source should be present and partially
+	 * configured already. XXX Need to clarify which parts are
+	 * expected to be configured. */
+
+	source = google_accounts_find_child_source (
+		collection_source, E_SOURCE_EXTENSION_MAIL_ACCOUNT);
+	g_return_if_fail (E_IS_SOURCE (source));
+
+	/* Add the mail account source to the collection. */
+	collection_extension = e_source_get_extension (
+		collection_source, E_SOURCE_EXTENSION_COLLECTION);
+	e_source_collection_add_mail_source (collection_extension, source);
+
+	/* Configure the mail account source. */
+
+	backend_name = GOOGLE_IMAP_BACKEND_NAME;
+
+	g_object_bind_property (
+		collection_source, "display-name",
+		source, "display-name",
+		G_BINDING_SYNC_CREATE);
+
+	source_extension = e_source_get_extension (
+		source, E_SOURCE_EXTENSION_MAIL_ACCOUNT);
+
+	e_source_backend_set_backend_name (
+		E_SOURCE_BACKEND (source_extension), backend_name);
+
+	extension_name = e_source_camel_get_extension_name (backend_name);
+	camel_extension = e_source_get_extension (source, extension_name);
+	settings = e_source_camel_get_settings (camel_extension);
+
+	/* The "auth-mechanism" should already be set. */
+
+	camel_network_settings_set_host (
+		CAMEL_NETWORK_SETTINGS (settings),
+		GOOGLE_IMAP_HOST);
+
+	camel_network_settings_set_port (
+		CAMEL_NETWORK_SETTINGS (settings),
+		GOOGLE_IMAP_PORT);
+
+	camel_network_settings_set_security_method (
+		CAMEL_NETWORK_SETTINGS (settings),
+		GOOGLE_IMAP_SECURITY_METHOD);
+
+	g_object_bind_property (
+		collection_extension, "identity",
+		settings, "user",
+		G_BINDING_SYNC_CREATE);
+
+	g_object_unref (source);
+}
+
+static void
+google_accounts_config_mail_identity (EGoogleAccounts *extension,
+                                      ESource *collection_source)
+{
+	ESource *source;
+	ESourceCollection *collection_extension;
+
+	/* The mail identity source should be present and partially
+	 * configured already. XXX Need to clarify which parts are
+	 * expected to be configured. */
+
+	source = google_accounts_find_child_source (
+		collection_source, E_SOURCE_EXTENSION_MAIL_IDENTITY);
+	g_return_if_fail (E_IS_SOURCE (source));
+
+	/* Add the mail identity source to the collection. */
+	collection_extension = e_source_get_extension (
+		collection_source, E_SOURCE_EXTENSION_COLLECTION);
+	e_source_collection_add_mail_source (collection_extension, source);
+
+	/* Configure the mail identity source. */
+
+	g_object_bind_property (
+		collection_source, "display-name",
+		source, "display-name",
+		G_BINDING_SYNC_CREATE);
+
+	g_object_unref (source);
+}
+
+static void
+google_accounts_config_mail_transport (EGoogleAccounts *extension,
+                                       ESource *collection_source)
+{
+	ESource *source;
+	ESourceCamel *camel_extension;
+	ESourceExtension *source_extension;
+	ESourceCollection *collection_extension;
+	CamelSettings *settings;
+	const gchar *backend_name;
+	const gchar *extension_name;
+
+	/* The mail transport source should be present and partially
+	 * configured already.  XXX Need to clarify which parts are
+	 * expected to be configured. */
+
+	source = google_accounts_find_child_source (
+		collection_source, E_SOURCE_EXTENSION_MAIL_TRANSPORT);
+	g_return_if_fail (E_IS_SOURCE (source));
+
+	/* Add the mail transport source to the collection. */
+	collection_extension = e_source_get_extension (
+		collection_source, E_SOURCE_EXTENSION_COLLECTION);
+	e_source_collection_add_mail_source (collection_extension, source);
+
+	/* Configure the mail transport source. */
+
+	backend_name = GOOGLE_SMTP_BACKEND_NAME;
+
+	g_object_bind_property (
+		collection_source, "display-name",
+		source, "display-name",
+		G_BINDING_SYNC_CREATE);
+
+	source_extension = e_source_get_extension (
+		source, E_SOURCE_EXTENSION_MAIL_TRANSPORT);
+
+	e_source_backend_set_backend_name (
+		E_SOURCE_BACKEND (source_extension), backend_name);
+
+	extension_name = e_source_camel_get_extension_name (backend_name);
+	camel_extension = e_source_get_extension (source, extension_name);
+	settings = e_source_camel_get_settings (camel_extension);
+
+	/* The "auth-mechanism" should already be set. */
+
+	camel_network_settings_set_host (
+		CAMEL_NETWORK_SETTINGS (settings),
+		GOOGLE_SMTP_HOST);
+
+	camel_network_settings_set_port (
+		CAMEL_NETWORK_SETTINGS (settings),
+		GOOGLE_SMTP_PORT);
+
+	camel_network_settings_set_security_method (
+		CAMEL_NETWORK_SETTINGS (settings),
+		GOOGLE_SMTP_SECURITY_METHOD);
+
+	g_object_bind_property (
+		collection_extension, "identity",
+		settings, "user",
+		G_BINDING_SYNC_CREATE);
+
+	g_object_unref (source);
+}
+
+static void
+google_accounts_config_calendar (EGoogleAccounts *extension,
+                                 ESource *collection_source)
+{
+	ESource *source;
+	EDBusSourceServer *server;
+	ESourceExtension *source_extension;
+	ESourceCollection *collection_extension;
+	const gchar *backend_name;
+	const gchar *identity;
+	gchar *path;
+
+	/* FIXME As a future enhancement, we should query Google
+	 *       for a list of user calendars and add them to the
+	 *       collection with matching display names and colors. */
+
+	source = google_accounts_find_child_source (
+		collection_source, E_SOURCE_EXTENSION_CALENDAR);
+	if (source == NULL) {
+		const gchar *collection_uid;
+		source = google_accounts_new_source (extension);
+		e_source_set_display_name (source, _("Calendar"));
+		collection_uid = e_source_get_uid (collection_source);
+		e_source_set_parent (source, collection_uid);
+	}
+
+	/* Add the calendar source to the collection. */
+	collection_extension = e_source_get_extension (
+		collection_source, E_SOURCE_EXTENSION_COLLECTION);
+	e_source_collection_add_calendar_source (collection_extension, source);
+
+	/* Configure the calendar source. */
+
+	backend_name = GOOGLE_CALENDAR_BACKEND_NAME;
+
+	source_extension = e_source_get_extension (
+		source, E_SOURCE_EXTENSION_CALENDAR);
+
+	e_source_backend_set_backend_name (
+		E_SOURCE_BACKEND (source_extension), backend_name);
+
+	source_extension = e_source_get_extension (
+		source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+	e_source_authentication_set_host (
+		E_SOURCE_AUTHENTICATION (source_extension),
+		GOOGLE_CALENDAR_HOST);
+
+	g_object_bind_property (
+		collection_extension, "identity",
+		source_extension, "user",
+		G_BINDING_SYNC_CREATE);
+
+	source_extension = e_source_get_extension (
+		source, E_SOURCE_EXTENSION_SECURITY);
+
+	e_source_security_set_secure (
+		E_SOURCE_SECURITY (source_extension), TRUE);
+
+	source_extension = e_source_get_extension (
+		source, E_SOURCE_EXTENSION_CALDAV_BACKEND);
+
+	identity = e_source_collection_get_identity (collection_extension);
+	path = g_strdup_printf (GOOGLE_CALENDAR_CALDAV_PATH, identity);
+	g_object_set (source_extension, "path", path, NULL);
+	g_free (path);
+
+	server = google_accounts_get_server (extension);
+	e_dbus_source_server_add_source (server, source);
+
+	g_object_unref (source);
+}
+
+static void
+google_accounts_config_contacts (EGoogleAccounts *extension,
+                                 ESource *collection_source)
+{
+	ESource *source;
+	EDBusSourceServer *server;
+	ESourceExtension *source_extension;
+	ESourceCollection *collection_extension;
+	const gchar *backend_name;
+
+	source = google_accounts_find_child_source (
+		collection_source, E_SOURCE_EXTENSION_ADDRESS_BOOK);
+	if (source == NULL) {
+		const gchar *collection_uid;
+		source = google_accounts_new_source (extension);
+		e_source_set_display_name (source, _("Contacts"));
+		collection_uid = e_source_get_uid (collection_source);
+		e_source_set_parent (source, collection_uid);
+	}
+
+	/* Add the address book source to the collection. */
+	collection_extension = e_source_get_extension (
+		collection_source, E_SOURCE_EXTENSION_COLLECTION);
+	e_source_collection_add_contacts_source (collection_extension, source);
+
+	/* Configure the address book source. */
+
+	backend_name = GOOGLE_CONTACTS_BACKEND_NAME;
+
+	source_extension = e_source_get_extension (
+		source, E_SOURCE_EXTENSION_ADDRESS_BOOK);
+
+	e_source_backend_set_backend_name (
+		E_SOURCE_BACKEND (source_extension), backend_name);
+
+	source_extension = e_source_get_extension (
+		source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+	g_object_bind_property (
+		collection_extension, "identity",
+		source_extension, "user",
+		G_BINDING_SYNC_CREATE);
+
+	source_extension = e_source_get_extension (
+		source, E_SOURCE_EXTENSION_SECURITY);
+
+	e_source_security_set_secure (
+		E_SOURCE_SECURITY (source_extension), TRUE);
+
+	server = google_accounts_get_server (extension);
+	e_dbus_source_server_add_source (server, source);
+
+	g_object_unref (source);
+}
+
+static gboolean
+google_accounts_populate (gpointer user_data)
+{
+	Closure *closure = user_data;
+	EDBusSourceServer *server;
+	ESource *source;
+
+	/* Because the closure struct holds a reference to the EExtension
+	 * until this callback finishes, it's possible that we may outlive
+	 * the EDBusSourceServer instance we're extending.  The EExtension
+	 * only keeps a weak pointer to it.  So just return immediately if
+	 * the server instance is gone. */
+	server = google_accounts_get_server (closure->extension);
+	if (server == NULL)
+		return FALSE;
+
+	/* Now try to fetch the Google account from the EDBusSourceServer.
+	 * It's possible it got removed already, so check for that too. */
+	source = e_dbus_source_server_lookup_by_uid (server, closure->uid);
+	if (source == NULL)
+		return FALSE;
+
+	google_accounts_config_mail_account (closure->extension, source);
+	google_accounts_config_mail_identity (closure->extension, source);
+	google_accounts_config_mail_transport (closure->extension, source);
+	google_accounts_config_calendar (closure->extension, source);
+	google_accounts_config_contacts (closure->extension, source);
+
+	return FALSE;
+}
+
+static void
+google_accounts_source_added_cb (EDBusSourceServer *server,
+                                 ESource *source,
+                                 EGoogleAccounts *extension)
+{
+	ESourceBackend *backend_extension;
+	const gchar *backend_name;
+	const gchar *extension_name;
+
+	/* Determine if this is a Google account by looking for
+	 * a collection extension with a "google" backend name. */
+
+	extension_name = E_SOURCE_EXTENSION_COLLECTION;
+	if (!e_source_has_extension (source, extension_name))
+		return;
+
+	backend_extension = e_source_get_extension (source, extension_name);
+	backend_name = e_source_backend_get_backend_name (backend_extension);
+
+	if (g_strcmp0 (backend_name, "google") != 0)
+		return;
+
+	/* We act on the newly-added Google account from an idle callback
+	 * so child sources for the account have a chance to be added first. */
+	g_idle_add_full (
+		G_PRIORITY_DEFAULT_IDLE,
+		google_accounts_populate,
+		closure_new (extension, source),
+		(GDestroyNotify) closure_free);
+}
+
+static void
+google_accounts_constructed (GObject *object)
+{
+	EExtension *extension;
+	EExtensible *extensible;
+
+	extension = E_EXTENSION (object);
+	extensible = e_extension_get_extensible (extension);
+
+	g_signal_connect (
+		extensible, "source-added",
+		G_CALLBACK (google_accounts_source_added_cb), extension);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_google_accounts_parent_class)->constructed (object);
+}
+
+static void
+e_google_accounts_class_init (EGoogleAccountsClass *class)
+{
+	GObjectClass *object_class;
+	EExtensionClass *extension_class;
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->constructed = google_accounts_constructed;
+
+	extension_class = E_EXTENSION_CLASS (class);
+	extension_class->extensible_type = E_TYPE_DBUS_SOURCE_SERVER;
+}
+
+static void
+e_google_accounts_class_finalize (EGoogleAccountsClass *class)
+{
+}
+
+static void
+e_google_accounts_init (EGoogleAccounts *extension)
+{
+}
+
+G_MODULE_EXPORT void
+e_module_load (GTypeModule *type_module)
+{
+	e_google_accounts_register_type (type_module);
+	e_source_caldav_type_register (type_module);
+}
+
+G_MODULE_EXPORT void
+e_module_unload (GTypeModule *type_module)
+{
+}
+



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