[evolution-data-server/account-mgmt: 38/42] Add 'online-accounts' module.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/account-mgmt: 38/42] Add 'online-accounts' module.
- Date: Tue, 10 Apr 2012 14:28:29 +0000 (UTC)
commit 92c04cdb33d53134c9e4d3ad2cc4e7e2b84e31b5
Author: Matthew Barnes <mbarnes redhat com>
Date: Sun Apr 1 15:02:27 2012 -0400
Add 'online-accounts' module.
This replaces the 'online-accounts' module in Evolution.
Makefile.am | 2 +-
configure.ac | 8 +
modules/Makefile.am | 11 +
modules/online-accounts/Makefile.am | 28 +
modules/online-accounts/module-online-accounts.c | 765 ++++++++++++++++++++++
5 files changed, 813 insertions(+), 1 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index fafda5e..c7a51bb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS=-I m4
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --with-krb5=/usr --without-weather --enable-introspection
-SUBDIRS = camel data libedataserver libebackend addressbook calendar libedataserverui services tests docs art po
+SUBDIRS = camel data libedataserver libebackend addressbook calendar libedataserverui modules services tests docs art po
if HAVE_INTROSPECTION
if HAVE_VALA
diff --git a/configure.ac b/configure.ac
index 94f68a4..8337131 100644
--- a/configure.ac
+++ b/configure.ac
@@ -45,6 +45,9 @@ m4_define([libgdata_minimum_version], [0.10])
m4_define([oauth_minimum_version], [0.9.4])
m4_define([sqlite_minimum_version], [3.5])
m4_define([libical_minimum_version], [0.43])
+
+dnl Optional Packages
+m4_define([goa_minimum_version], [3.1.1])
m4_define([gweather_minimum_version], [2.90.0])
AC_SUBST([BASE_VERSION],[base_version])
@@ -1495,6 +1498,9 @@ AC_SUBST(privlibdir)
imagesdir='${datadir}'/pixmaps/evolution-data-server
AC_SUBST(imagesdir)
+moduledir='${libdir}'/evolution-data-server/registry-modules
+AC_SUBST(moduledir)
+
ebook_backenddir='${libdir}'/evolution-data-server/addressbook-backends
AC_SUBST(ebook_backenddir)
@@ -1644,6 +1650,8 @@ libedataserver/eds-version.h
libedataserver/libedataserver.pc
libedataserverui/Makefile
libedataserverui/libedataserverui.pc
+modules/Makefile
+modules/online-accounts/Makefile
services/Makefile
services/evolution-addressbook-factory/Makefile
services/evolution-calendar-factory/Makefile
diff --git a/modules/Makefile.am b/modules/Makefile.am
new file mode 100644
index 0000000..6f7cf42
--- /dev/null
+++ b/modules/Makefile.am
@@ -0,0 +1,11 @@
+NULL =
+
+if HAVE_GOA
+ONLINE_ACCOUNTS_DIR = online-accounts
+endif
+
+SUBDIRS = \
+ $(ONLINE_ACCOUNTS_DIR) \
+ $(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/modules/online-accounts/Makefile.am b/modules/online-accounts/Makefile.am
new file mode 100644
index 0000000..43d707d
--- /dev/null
+++ b/modules/online-accounts/Makefile.am
@@ -0,0 +1,28 @@
+NULL =
+
+module_LTLIBRARIES = module-online-accounts.la
+
+module_online_accounts_la_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -I$(top_srcdir) \
+ -DG_LOG_DOMAIN=\"module-online-accounts\" \
+ $(E_BACKEND_CFLAGS) \
+ $(GOA_CFLAGS) \
+ $(NULL)
+
+module_online_accounts_la_SOURCES = \
+ module-online-accounts.c \
+ $(NULL)
+
+module_online_accounts_la_LIBADD = \
+ $(top_builddir)/libebackend/libebackend-1.2.la \
+ $(top_builddir)/libedataserver/libedataserver-1.2.la \
+ $(E_BACKEND_LIBS) \
+ $(GOA_LIBS) \
+ $(NULL)
+
+module_online_accounts_la_LDFLAGS = \
+ -module -avoid-version $(NO_UNDEFINED) \
+ $(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/modules/online-accounts/module-online-accounts.c b/modules/online-accounts/module-online-accounts.c
new file mode 100644
index 0000000..04284e5
--- /dev/null
+++ b/modules/online-accounts/module-online-accounts.c
@@ -0,0 +1,765 @@
+/*
+ * module-online-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/>
+ *
+ */
+
+/* XXX Yeah, yeah... */
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+
+#include <goa/goa.h>
+
+#include <libedataserver/e-uid.h>
+#include <libedataserver/e-source-authentication.h>
+#include <libedataserver/e-source-collection.h>
+#include <libedataserver/e-source-goa.h>
+#include <libedataserver/e-source-mail-account.h>
+#include <libedataserver/e-source-mail-identity.h>
+#include <libedataserver/e-source-mail-submission.h>
+#include <libedataserver/e-source-mail-transport.h>
+
+#include <libebackend/e-extension.h>
+#include <libebackend/e-dbus-source-server.h>
+#include <libebackend/e-server-side-source.h>
+
+/* Standard GObject macros */
+#define E_TYPE_ONLINE_ACCOUNTS \
+ (e_online_accounts_get_type ())
+#define E_ONLINE_ACCOUNTS(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_ONLINE_ACCOUNTS, EOnlineAccounts))
+
+#define CAMEL_OAUTH_MECHANISM_NAME "XOAUTH"
+
+typedef struct _EOnlineAccounts EOnlineAccounts;
+typedef struct _EOnlineAccountsClass EOnlineAccountsClass;
+
+struct _EOnlineAccounts {
+ EExtension parent;
+
+ GoaClient *goa_client;
+ GCancellable *create_client;
+
+ /* GoaAccount ID -> ESource UID */
+ GHashTable *goa_to_eds;
+};
+
+struct _EOnlineAccountsClass {
+ EExtensionClass parent_class;
+};
+
+/* Module Entry Points */
+void e_module_load (GTypeModule *type_module);
+void e_module_unload (GTypeModule *type_module);
+
+/* Forward Declarations */
+GType e_online_accounts_get_type (void);
+
+G_DEFINE_DYNAMIC_TYPE (
+ EOnlineAccounts,
+ e_online_accounts,
+ E_TYPE_EXTENSION)
+
+static EDBusSourceServer *
+online_accounts_get_server (EOnlineAccounts *extension)
+{
+ EExtensible *extensible;
+
+ extensible = e_extension_get_extensible (E_EXTENSION (extension));
+
+ return E_DBUS_SOURCE_SERVER (extensible);
+}
+
+static gboolean
+online_accounts_object_is_non_null (GBinding *binding,
+ const GValue *source_value,
+ GValue *target_value,
+ gpointer unused)
+{
+ gpointer v_object;
+
+ v_object = g_value_get_object (source_value);
+ g_value_set_boolean (target_value, v_object != NULL);
+
+ return TRUE;
+}
+
+static ESource *
+online_accounts_new_source (EOnlineAccounts *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 = online_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 *
+online_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
+online_accounts_config_mail_account (EOnlineAccounts *extension,
+ ESource *collection_source,
+ ESource *mail_identity_source,
+ GoaObject *goa_object)
+{
+ ESource *source;
+ EDBusSourceServer *server;
+ ESourceExtension *source_extension;
+ GoaMail *goa_mail;
+
+ /* If mail is disabled, skip this. */
+ goa_mail = goa_object_get_mail (goa_object);
+ if (goa_mail == NULL)
+ return;
+
+ /* XXX Just for correctness, I guess. Don't know what we're
+ * supposed to do if the provider does not support IMAP. */
+ if (!goa_mail_get_imap_supported (goa_mail)) {
+ g_object_unref (goa_mail);
+ return;
+ }
+
+ source = online_accounts_find_child_source (
+ collection_source, E_SOURCE_EXTENSION_MAIL_ACCOUNT);
+ if (source == NULL) {
+ const gchar *collection_uid;
+ source = online_accounts_new_source (extension);
+ collection_uid = e_source_get_uid (collection_source);
+ e_source_set_parent (source, collection_uid);
+ }
+
+ source_extension = e_source_get_extension (
+ source, E_SOURCE_EXTENSION_MAIL_ACCOUNT);
+
+ e_source_mail_account_set_identity_uid (
+ E_SOURCE_MAIL_ACCOUNT (source_extension),
+ e_source_get_uid (mail_identity_source));
+
+ source_extension = e_source_get_extension (
+ source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+ if (goa_object_peek_oauth_based (goa_object) != NULL)
+ e_source_authentication_set_method (
+ E_SOURCE_AUTHENTICATION (source_extension),
+ CAMEL_OAUTH_MECHANISM_NAME);
+
+ /* XXX Need to defer the network security settings to the
+ * provider-specific module since "imap-use-tls" tells
+ * us neither the port number, nor whether to use IMAP
+ * over SSL versus STARTTLS. The module will know. */
+
+ server = online_accounts_get_server (extension);
+ e_dbus_source_server_add_source (server, source);
+
+ g_object_unref (source);
+
+ g_object_unref (goa_mail);
+}
+
+static void
+online_accounts_config_mail_identity (EOnlineAccounts *extension,
+ ESource *collection_source,
+ ESource *mail_transport_source,
+ GoaObject *goa_object)
+{
+ ESource *source;
+ EDBusSourceServer *server;
+ ESourceExtension *source_extension;
+ GoaMail *goa_mail;
+
+ /* If mail is disabled, skip this. */
+ goa_mail = goa_object_get_mail (goa_object);
+ if (goa_mail == NULL)
+ return;
+
+ source = online_accounts_find_child_source (
+ collection_source, E_SOURCE_EXTENSION_MAIL_IDENTITY);
+ if (source == NULL) {
+ const gchar *collection_uid;
+ source = online_accounts_new_source (extension);
+ collection_uid = e_source_get_uid (collection_source);
+ e_source_set_parent (source, collection_uid);
+ }
+
+ source_extension = e_source_get_extension (
+ source, E_SOURCE_EXTENSION_MAIL_SUBMISSION);
+
+ e_source_mail_submission_set_transport_uid (
+ E_SOURCE_MAIL_SUBMISSION (source_extension),
+ e_source_get_uid (mail_transport_source));
+
+ source_extension = e_source_get_extension (
+ source, E_SOURCE_EXTENSION_MAIL_IDENTITY);
+
+ g_object_bind_property (
+ goa_mail, "email-address",
+ source_extension, "address",
+ G_BINDING_SYNC_CREATE);
+
+ server = online_accounts_get_server (extension);
+ e_dbus_source_server_add_source (server, source);
+
+ online_accounts_config_mail_account (
+ extension, collection_source, source, goa_object);
+
+ g_object_unref (source);
+
+ g_object_unref (goa_mail);
+}
+
+static void
+online_accounts_config_mail_transport (EOnlineAccounts *extension,
+ ESource *collection_source,
+ GoaObject *goa_object)
+{
+ ESource *source;
+ EDBusSourceServer *server;
+ ESourceExtension *source_extension;
+ GoaMail *goa_mail;
+
+ /* If mail is disabled, skip this. */
+ goa_mail = goa_object_get_mail (goa_object);
+ if (goa_mail == NULL)
+ return;
+
+ /* XXX Just for correctness, I guess. Don't know what we're
+ * supposed to do if the provider does not support SMTP. */
+ if (!goa_mail_get_smtp_supported (goa_mail))
+ return;
+
+ source = online_accounts_find_child_source (
+ collection_source, E_SOURCE_EXTENSION_MAIL_TRANSPORT);
+ if (source == NULL) {
+ const gchar *collection_uid;
+ source = online_accounts_new_source (extension);
+ collection_uid = e_source_get_uid (collection_source);
+ e_source_set_parent (source, collection_uid);
+ }
+
+ /* This just makes sure the extension is present
+ * so the source is recognized as a mail transport. */
+ source_extension = e_source_get_extension (
+ source, E_SOURCE_EXTENSION_MAIL_TRANSPORT);
+
+ source_extension = e_source_get_extension (
+ source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+ if (goa_object_peek_oauth_based (goa_object) != NULL)
+ e_source_authentication_set_method (
+ E_SOURCE_AUTHENTICATION (source_extension),
+ CAMEL_OAUTH_MECHANISM_NAME);
+
+ /* XXX Need to defer the network security settings to the
+ * provider-specific module since "smtp-use-tls" tells
+ * us neither the port number, nor whether to use SMTP
+ * over SSL versus STARTTLS. The module will know. */
+
+ server = online_accounts_get_server (extension);
+ e_dbus_source_server_add_source (server, source);
+
+ online_accounts_config_mail_identity (
+ extension, collection_source, source, goa_object);
+
+ g_object_unref (source);
+
+ g_object_unref (goa_mail);
+}
+
+static void
+online_accounts_config_collection (EOnlineAccounts *extension,
+ ESource *collection_source,
+ GoaObject *goa_object)
+{
+ GoaAccount *goa_account;
+ ESourceExtension *source_extension;
+
+ goa_account = goa_object_get_account (goa_object);
+
+ g_object_bind_property (
+ goa_account, "presentation-identity",
+ collection_source, "display-name",
+ G_BINDING_SYNC_CREATE);
+
+ source_extension = e_source_get_extension (
+ collection_source, E_SOURCE_EXTENSION_GOA);
+
+ g_object_bind_property (
+ goa_account, "id",
+ source_extension, "account-id",
+ G_BINDING_SYNC_CREATE);
+
+ source_extension = e_source_get_extension (
+ collection_source, E_SOURCE_EXTENSION_COLLECTION);
+
+ /* XXX Might have to revisit this in the future, but for now
+ * all known GOA provider types are identical to our own
+ * backend names, so we can just use a direct binding. */
+ g_object_bind_property (
+ goa_account, "provider-type",
+ source_extension, "backend-name",
+ G_BINDING_SYNC_CREATE);
+
+ g_object_bind_property (
+ goa_account, "identity",
+ source_extension, "identity",
+ G_BINDING_SYNC_CREATE);
+
+ g_object_bind_property_full (
+ goa_object, "calendar",
+ source_extension, "calendar-enabled",
+ G_BINDING_SYNC_CREATE,
+ online_accounts_object_is_non_null,
+ NULL,
+ NULL, (GDestroyNotify) NULL);
+
+ g_object_bind_property_full (
+ goa_object, "contacts",
+ source_extension, "contacts-enabled",
+ G_BINDING_SYNC_CREATE,
+ online_accounts_object_is_non_null,
+ NULL,
+ NULL, (GDestroyNotify) NULL);
+
+ g_object_bind_property_full (
+ goa_object, "mail",
+ source_extension, "mail-enabled",
+ G_BINDING_SYNC_CREATE,
+ online_accounts_object_is_non_null,
+ NULL,
+ NULL, (GDestroyNotify) NULL);
+
+ g_object_unref (goa_account);
+
+ /* The data source should not be altered by clients. */
+ e_server_side_source_set_writable (
+ E_SERVER_SIDE_SOURCE (collection_source), FALSE);
+ e_server_side_source_set_removable (
+ E_SERVER_SIDE_SOURCE (collection_source), FALSE);
+
+ /* This configures a completes mail account triplet. */
+ online_accounts_config_mail_transport (
+ extension, collection_source, goa_object);
+}
+
+static ESource *
+online_accounts_create_collection (EOnlineAccounts *extension,
+ GoaObject *goa_object)
+{
+ EDBusSourceServer *server;
+ ESource *source;
+
+ source = online_accounts_new_source (extension);
+ g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+
+ online_accounts_config_collection (extension, source, goa_object);
+
+ /* Export the data source. Other server extensions should pick
+ * up the new data source and flesh it out with child sources. */
+ server = online_accounts_get_server (extension);
+ e_dbus_source_server_add_source (server, source);
+
+ return source;
+}
+
+static void
+online_accounts_remove_collection (EOnlineAccounts *extension,
+ ESource *source)
+{
+ GError *error = NULL;
+
+ /* This removes the entire subtree rooted at source.
+ * Deletes the corresponding on-disk key files too. */
+ e_source_remove_sync (source, NULL, &error);
+
+ if (error != NULL) {
+ g_warning ("%s: %s", G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+online_accounts_account_added_cb (GoaClient *goa_client,
+ GoaObject *goa_object,
+ EOnlineAccounts *extension)
+{
+ GoaAccount *goa_account;
+ const gchar *provider_type;
+ const gchar *account_id;
+ const gchar *source_uid;
+ gboolean create_source = FALSE;
+
+ goa_account = goa_object_get_account (goa_object);
+ provider_type = goa_account_get_provider_type (goa_account);
+
+ account_id = goa_account_get_id (goa_account);
+ source_uid = g_hash_table_lookup (extension->goa_to_eds, account_id);
+
+ if (g_strcmp0 (provider_type, "google") == 0)
+ create_source = (source_uid == NULL);
+
+ if (create_source) {
+ ESource *source;
+
+ source = online_accounts_create_collection (
+ extension, goa_object);
+ source_uid = e_source_get_uid (source);
+ g_hash_table_insert (
+ extension->goa_to_eds,
+ g_strdup (account_id),
+ g_strdup (source_uid));
+ g_object_unref (source);
+ }
+
+ g_object_unref (goa_account);
+}
+
+static void
+online_accounts_account_removed_cb (GoaClient *goa_client,
+ GoaObject *goa_object,
+ EOnlineAccounts *extension)
+{
+ ESource *source = NULL;
+ EDBusSourceServer *server;
+ GoaAccount *goa_account;
+ const gchar *account_id;
+ const gchar *source_uid;
+
+ server = online_accounts_get_server (extension);
+
+ goa_account = goa_object_get_account (goa_object);
+
+ account_id = goa_account_get_id (goa_account);
+ source_uid = g_hash_table_lookup (extension->goa_to_eds, account_id);
+
+ if (source_uid != NULL)
+ source = e_dbus_source_server_ref_source (server, source_uid);
+
+ if (source != NULL) {
+ online_accounts_remove_collection (extension, source);
+ g_object_unref (source);
+ }
+
+ g_object_unref (goa_account);
+}
+
+static gint
+online_accounts_compare_id (GoaObject *goa_object,
+ const gchar *target_id)
+{
+ GoaAccount *goa_account;
+ const gchar *account_id;
+ gint result;
+
+ goa_account = goa_object_get_account (goa_object);
+ account_id = goa_account_get_id (goa_account);
+ result = g_strcmp0 (account_id, target_id);
+ g_object_unref (goa_account);
+
+ return result;
+}
+
+static void
+online_accounts_populate_accounts_table (EOnlineAccounts *extension,
+ GList *goa_objects)
+{
+ EDBusSourceServer *server;
+ GQueue trash = G_QUEUE_INIT;
+ GList *list, *link;
+ const gchar *extension_name;
+
+ server = online_accounts_get_server (extension);
+
+ extension_name = E_SOURCE_EXTENSION_GOA;
+ list = e_dbus_source_server_list_sources (server, extension_name);
+
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ ESource *source;
+ ESourceGoa *goa_ext;
+ const gchar *account_id;
+ const gchar *source_uid;
+ GList *match;
+
+ source = E_SOURCE (link->data);
+ source_uid = e_source_get_uid (source);
+
+ goa_ext = e_source_get_extension (source, extension_name);
+ account_id = e_source_goa_get_account_id (goa_ext);
+
+ if (account_id == NULL)
+ continue;
+
+ /* Verify the GOA account still exists. */
+ match = g_list_find_custom (
+ goa_objects, account_id,
+ (GCompareFunc) online_accounts_compare_id);
+
+ /* If a matching GoaObject was found, add its ID
+ * to our accounts hash table. Otherwise remove
+ * the ESource after we finish looping. */
+ if (match != NULL) {
+ GoaObject *goa_object;
+
+ g_hash_table_insert (
+ extension->goa_to_eds,
+ g_strdup (account_id),
+ g_strdup (source_uid));
+
+ goa_object = GOA_OBJECT (match->data);
+ online_accounts_config_collection (
+ extension, source, goa_object);
+ } else {
+ g_queue_push_tail (&trash, source);
+ }
+ }
+
+ /* Empty the trash. */
+ while (!g_queue_is_empty (&trash)) {
+ ESource *source = g_queue_pop_head (&trash);
+ online_accounts_remove_collection (extension, source);
+ }
+
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
+}
+
+static void
+online_accounts_create_client_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ EOnlineAccounts *extension;
+ GoaClient *goa_client;
+ GList *list, *link;
+ GError *error = NULL;
+
+ /* If we get back a G_IO_ERROR_CANCELLED then it means the
+ * EOnlineAccounts is already finalized, so be careful not
+ * to touch it until after we have a valid GoaClient. */
+
+ goa_client = goa_client_new_finish (result, &error);
+
+ if (error != NULL) {
+ g_warn_if_fail (goa_client == NULL);
+ g_warning (
+ "Unable to connect to the GNOME Online "
+ "Accounts service: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ g_return_if_fail (GOA_IS_CLIENT (goa_client));
+
+ /* Should be safe to dereference the EOnlineAccounts now. */
+
+ extension = E_ONLINE_ACCOUNTS (user_data);
+ extension->goa_client = goa_client; /* takes ownership */
+
+ /* Don't need the GCancellable anymore. */
+ g_object_unref (extension->create_client);
+ extension->create_client = NULL;
+
+ list = goa_client_get_accounts (extension->goa_client);
+
+ /* This populates a hash table of GOA ID -> ESource UID strings by
+ * searching through available data sources for ones with a "GNOME
+ * Online Accounts" extension. If such an extension is found, but
+ * no corresponding GoaAccount (presumably meaning the GOA account
+ * was somehow deleted between E-D-S sessions) then the ESource in
+ * which the extension was found gets deleted. */
+ online_accounts_populate_accounts_table (extension, list);
+
+ for (link = list; link != NULL; link = g_list_next (link))
+ online_accounts_account_added_cb (
+ extension->goa_client,
+ GOA_OBJECT (link->data),
+ extension);
+
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+ /* Listen for Online Account changes. */
+ g_signal_connect (
+ extension->goa_client, "account-added",
+ G_CALLBACK (online_accounts_account_added_cb), extension);
+ g_signal_connect (
+ extension->goa_client, "account-removed",
+ G_CALLBACK (online_accounts_account_removed_cb), extension);
+}
+
+static void
+online_accounts_bus_acquired_cb (EDBusServer *server,
+ GDBusConnection *connection,
+ EOnlineAccounts *extension)
+{
+ /* Connect to the GNOME Online Accounts service. */
+
+ /* Note we don't reference the extension. If the
+ * extension gets destroyed before this completes
+ * we cancel the operation from dispose(). */
+ goa_client_new (
+ extension->create_client,
+ online_accounts_create_client_cb,
+ extension);
+}
+
+static void
+online_accounts_dispose (GObject *object)
+{
+ EOnlineAccounts *extension;
+
+ extension = E_ONLINE_ACCOUNTS (object);
+
+ if (extension->goa_client != NULL) {
+ g_signal_handlers_disconnect_matched (
+ extension->goa_client,
+ G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, object);
+ g_object_unref (extension->goa_client);
+ extension->goa_client = NULL;
+ }
+
+ /* This cancels goa_client_new() in case it still
+ * hasn't completed. We're no longer interested. */
+ if (extension->create_client != NULL) {
+ g_cancellable_cancel (extension->create_client);
+ g_object_unref (extension->create_client);
+ extension->create_client = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_online_accounts_parent_class)->dispose (object);
+}
+
+static void
+online_accounts_finalize (GObject *object)
+{
+ EOnlineAccounts *extension;
+
+ extension = E_ONLINE_ACCOUNTS (object);
+
+ g_hash_table_destroy (extension->goa_to_eds);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (e_online_accounts_parent_class)->finalize (object);
+}
+
+static void
+online_accounts_constructed (GObject *object)
+{
+ EExtension *extension;
+ EExtensible *extensible;
+
+ extension = E_EXTENSION (object);
+ extensible = e_extension_get_extensible (extension);
+
+ /* Wait for the registry service to acquire its well-known
+ * bus name so we don't do anything destructive beforehand. */
+
+ g_signal_connect (
+ extensible, "bus-acquired",
+ G_CALLBACK (online_accounts_bus_acquired_cb), extension);
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_online_accounts_parent_class)->constructed (object);
+}
+
+static void
+e_online_accounts_class_init (EOnlineAccountsClass *class)
+{
+ GObjectClass *object_class;
+ EExtensionClass *extension_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->dispose = online_accounts_dispose;
+ object_class->finalize = online_accounts_finalize;
+ object_class->constructed = online_accounts_constructed;
+
+ extension_class = E_EXTENSION_CLASS (class);
+ extension_class->extensible_type = E_TYPE_DBUS_SOURCE_SERVER;
+}
+
+static void
+e_online_accounts_class_finalize (EOnlineAccountsClass *class)
+{
+}
+
+static void
+e_online_accounts_init (EOnlineAccounts *extension)
+{
+ /* Used to cancel unfinished goa_client_new(). */
+ extension->create_client = g_cancellable_new ();
+
+ extension->goa_to_eds = g_hash_table_new_full (
+ (GHashFunc) g_str_hash,
+ (GEqualFunc) g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+}
+
+G_MODULE_EXPORT void
+e_module_load (GTypeModule *type_module)
+{
+ e_online_accounts_register_type (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]