From 188de7815704c3a94ae02af4bb27156e204cac5c Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Fri, 20 Jan 2012 10:05:35 -0500 Subject: Adapt modules/online-accounts to the new ESource API. --- modules/online-accounts/Makefile.am | 5 +- modules/online-accounts/camel-sasl-xoauth.c | 58 ++- modules/online-accounts/e-online-accounts-google.c | 494 --------------------- modules/online-accounts/e-online-accounts-google.h | 32 -- .../online-accounts/evolution-online-accounts.c | 494 --------------------- 5 files changed, 47 insertions(+), 1036 deletions(-) delete mode 100644 modules/online-accounts/e-online-accounts-google.c delete mode 100644 modules/online-accounts/e-online-accounts-google.h diff --git a/modules/online-accounts/Makefile.am b/modules/online-accounts/Makefile.am index 6c2f16883a..9b30ced4f0 100644 --- a/modules/online-accounts/Makefile.am +++ b/modules/online-accounts/Makefile.am @@ -10,15 +10,14 @@ module_online_accounts_la_CPPFLAGS = \ module_online_accounts_la_SOURCES = \ evolution-online-accounts.c \ - e-online-accounts-google.c \ - e-online-accounts-google.h \ camel-sasl-xoauth.c \ camel-sasl-xoauth.h module_online_accounts_la_LIBADD = \ $(top_builddir)/e-util/libeutil.la \ $(top_builddir)/shell/libeshell.la \ - $(top_builddir)/libemail-utils/libemail-utils.la \ + $(top_builddir)/libemail-engine/libemail-engine.la \ + $(top_builddir)/libemail-utils/libemail-utils.la \ $(EVOLUTION_DATA_SERVER_LIBS) \ $(GNOME_PLATFORM_LIBS) \ $(GOA_LIBS) diff --git a/modules/online-accounts/camel-sasl-xoauth.c b/modules/online-accounts/camel-sasl-xoauth.c index e3cbb69f80..10e3223976 100644 --- a/modules/online-accounts/camel-sasl-xoauth.c +++ b/modules/online-accounts/camel-sasl-xoauth.c @@ -24,7 +24,9 @@ #include -#include +#include + +#include #include "camel-sasl-xoauth.h" @@ -313,6 +315,39 @@ calculate_xoauth_param (const gchar *request_uri, /****************************************************************************/ +static gchar * +sasl_xoauth_find_account_id (ESourceRegistry *registry, + const gchar *uid) +{ + ESource *source; + const gchar *extension_name; + + extension_name = E_SOURCE_EXTENSION_GOA; + + while (uid != NULL) { + ESourceGoa *extension; + gchar *account_id; + + source = e_source_registry_ref_source (registry, uid); + g_return_val_if_fail (source != NULL, NULL); + + if (!e_source_has_extension (source, extension_name)) { + uid = e_source_get_parent (source); + g_object_unref (source); + continue; + } + + extension = e_source_get_extension (source, extension_name); + account_id = e_source_goa_dup_account_id (extension); + + g_object_unref (source); + + return account_id; + } + + return NULL; +} + static GoaObject * sasl_xoauth_get_account_by_id (GoaClient *client, const gchar *account_id) @@ -356,29 +391,26 @@ sasl_xoauth_challenge_sync (CamelSasl *sasl, GoaAccount *goa_account; GByteArray *parameters = NULL; CamelService *service; - EAccount *account; - CamelURL *url; - const gchar *account_id; + CamelSession *session; + ESourceRegistry *registry; const gchar *uid; + gchar *account_id; gchar *xoauth_param = NULL; gboolean success; service = camel_sasl_get_service (sasl); - uid = camel_service_get_uid (service); - account = e_get_account_by_uid (uid); - g_return_val_if_fail (account != NULL, NULL); + session = camel_service_get_session (service); + registry = e_mail_session_get_registry (E_MAIL_SESSION (session)); goa_client = goa_client_new_sync (cancellable, error); if (goa_client == NULL) return NULL; - url = camel_url_new (account->source->url, error); - if (url == NULL) - return NULL; - - account_id = camel_url_get_param (url, GOA_KEY); + uid = camel_service_get_uid (service); + account_id = sasl_xoauth_find_account_id (registry, uid); goa_object = sasl_xoauth_get_account_by_id (goa_client, account_id); - camel_url_free (url); + + g_free (account_id); if (goa_object == NULL) { g_set_error_literal ( diff --git a/modules/online-accounts/e-online-accounts-google.c b/modules/online-accounts/e-online-accounts-google.c deleted file mode 100644 index ab394f622e..0000000000 --- a/modules/online-accounts/e-online-accounts-google.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - * e-online-accounts-google.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 - * - */ - -#include "e-online-accounts-google.h" - -#include -#include - -/* XXX Just use the deprecated APIs for now. - * We'll be switching away soon enough. */ -#undef E_CAL_DISABLE_DEPRECATED -#undef E_BOOK_DISABLE_DEPRECATED - -#include -#include - -#include - -/* This is the property name or URL parameter under which we - * embed the GoaAccount ID into an EAccount or ESource object. */ -#define GOA_KEY "goa-account-id" - -#define GOOGLE_BASE_URI "google://" - -/** - * XXX Once the key-file based ESource API is merged, I'd - * like to structure the ESources something like this: - * - * * Maybe add an "Enabled" key to the [Data Source] group, - * so we have an easy way to hide/show individual sources - * without destroying custom settings. Would replace the - * "Enabled" key in [Mail Account], and rename the same - * key in ESourceSelectable to "Active". - * - * +---------------------------------------------------+ - * | [Data Source] | - * | DisplayName: <> | - * | Backend: google | - * | Enabled: true # What would 'false' mean? | - * | | - * | [GNOME Online Accounts] | - * | Id: <> | - * +---------------------------------------------------+ - * | - * | (child ESources) - * | - * | +------------------------------------------+ - * | | [Data Source] | - * | | DisplayName: (same as parent) | - * | | Enabled: true | - * | | | - * | | [Authentication] | - * | | Host: imap.gmail.com | - * | | blah, blah, blah... | - * | | | - * +----| [Mail Account] | - * | | blah, blah, blah... | - * | | | - * | | [Mail Identity] | - * | | Name: Matthew Barnes | - * | | Address: <> | - * | | blah, blah, blah... | - * | +------------------------------------------+ - * | - * | +------------------------------------------+ - * | | [Data Source] | - * | | DisplayName: GMail SMTP Server | - * | | Enabled: true | - * | | | - * | | [Authentication] | - * | | Host: smtp.gmail.com | - * +----| blah, blah, blah... | - * | | | - * | | [Mail Transport] | - * | | blah, blah, blah... | - * | +------------------------------------------+ - * | - * | +------------------------------------------+ - * | | [Data Source] | - * | | DisplayName: Contacts | - * | | Enabled: true | - * | | | - * | | [Authentication] | - * | | blah, blah, blah... | - * +----| | - * | | [Address Book] | - * | | blah, blah, blah... | - * | +------------------------------------------+ - * | - * | +------------------------------------------+ - * | | [Data Source] | - * | | DisplayName: Calendar | - * | | Backend: caldav | - * | | Enabled: true | - * | | | - * | | [Authentication] | - * | | blah, blah, blah... | - * +----| | - * | [Calendar] | - * | blah, blah, blah... | - * +------------------------------------------+ - */ - -/* XXX Copy part of the private struct here so we can set our own UID. - * Since EAccountList and ESourceList forces the different aspects - * of the Google account to be disjoint, we can reuse the UID to - * link them back together. */ -struct _ESourcePrivate { - ESourceGroup *group; - - gchar *uid; - /* ... yadda, yadda, yadda ... */ -}; - -static void -online_accounts_google_sync_mail (GoaObject *goa_object, - const gchar *evo_id) -{ - GoaMail *goa_mail; - GoaAccount *goa_account; - EAccountList *account_list; - EAccount *account; - CamelURL *url; - const gchar *string; - gboolean new_account = FALSE; - - account_list = e_get_account_list (); - account = e_get_account_by_uid (evo_id); - - if (account) { - /* the account is already configured, - * do not change user's changes */ - return; - } - - /* XXX There's nothing particularly GMail-specific about this. - * Maybe break this off into a more generic IMAP/SMTP sync - * function and then apply any GMail-specific tweaks. */ - - goa_mail = goa_object_get_mail (goa_object); - goa_account = goa_object_get_account (goa_object); - - if (account == NULL) { - account = g_object_new (E_TYPE_ACCOUNT, NULL); - account->uid = g_strdup (evo_id); - account->enabled = TRUE; - new_account = TRUE; - } - - /*** Account Name ***/ - - g_free (account->name); - string = goa_account_get_presentation_identity (goa_account); - account->name = g_strdup (string); - - /*** Mail Identity ***/ - - if (account->id->name == NULL) - account->id->name = g_strdup (g_get_real_name ()); - - g_free (account->id->address); - string = goa_mail_get_email_address (goa_mail); - account->id->address = g_strdup (string); - - /*** Mail Storage ***/ - - /* This quietly handles NULL strings sanely. */ - url = camel_url_new (account->source->url, NULL); - - if (url == NULL) - url = g_new0 (CamelURL, 1); - - camel_url_set_protocol (url, "imapx"); - - string = goa_account_get_identity (goa_account); - camel_url_set_user (url, string); - - string = goa_mail_get_imap_host (goa_mail); - camel_url_set_host (url, string); - - /* Use CamelSaslXOAuth. */ - camel_url_set_authmech (url, "XOAUTH"); - - /* Always == SSL (port 993) */ - if (goa_mail_get_imap_use_tls (goa_mail)) - string = "ssl-on-alternate-port"; - else - string = "none"; - camel_url_set_param (url, "security-method", string); - - string = goa_account_get_id (goa_account); - camel_url_set_param (url, GOA_KEY, string); - - if (new_account) { - e_account_set_bool (account, E_ACCOUNT_SOURCE_AUTO_CHECK, TRUE); - e_account_set_int (account, E_ACCOUNT_SOURCE_AUTO_CHECK_TIME, 10); - - camel_url_set_param (url, "filter-inbox", "true"); - } - - g_free (account->source->url); - account->source->url = camel_url_to_string (url, 0); - - camel_url_free (url); - - /*** Mail Transport ***/ - - /* This quietly handles NULL strings sanely. */ - url = camel_url_new (account->transport->url, NULL); - - if (url == NULL) - url = g_new0 (CamelURL, 1); - - camel_url_set_protocol (url, "smtp"); - - string = goa_account_get_identity (goa_account); - camel_url_set_user (url, string); - - string = goa_mail_get_smtp_host (goa_mail); - camel_url_set_host (url, string); - - /* Message Submission port */ - camel_url_set_port (url, 587); - - /* Use CamelSaslXOAuth. */ - camel_url_set_authmech (url, "XOAUTH"); - - /* When-Possible == STARTTLS */ - if (goa_mail_get_smtp_use_tls (goa_mail)) - string = "starttls-on-standard-port"; - else - string = "none"; - camel_url_set_param (url, "security-method", string); - - string = goa_account_get_id (goa_account); - camel_url_set_param (url, GOA_KEY, string); - - g_free (account->transport->url); - account->transport->url = camel_url_to_string (url, 0); - - camel_url_free (url); - - /* Clean up. */ - - if (new_account) { - e_account_list_add (account_list, account); - g_object_unref (account); - } - - e_account_list_save (account_list); - - g_object_unref (goa_account); - g_object_unref (goa_mail); -} - -static void -online_accounts_google_sync_calendar (GoaObject *goa_object, - const gchar *evo_id) -{ - GoaAccount *goa_account; - ESourceList *source_list = NULL; - ESourceGroup *source_group; - ECalSourceType source_type; - ESource *source; - const gchar *string; - gchar *encoded; - gchar *uri_string; - gboolean new_source = FALSE; - GError *error = NULL; - - source_type = E_CAL_SOURCE_TYPE_EVENT; - - if (!e_cal_get_sources (&source_list, source_type, &error)) { - g_warn_if_fail (source_list == NULL); - g_warn_if_fail (error != NULL); - g_warning ("%s", error->message); - g_error_free (error); - return; - } - - g_return_if_fail (E_IS_SOURCE_LIST (source_list)); - - goa_account = goa_object_get_account (goa_object); - - /* This returns a new reference to the source group. */ - source_group = e_source_list_ensure_group ( - source_list, _("Google"), GOOGLE_BASE_URI, TRUE); - - source = e_source_group_peek_source_by_uid (source_group, evo_id); - - if (source == NULL) { - source = g_object_new (E_TYPE_SOURCE, NULL); - source->priv->uid = g_strdup (evo_id); - e_source_set_name (source, _("Calendar")); - - /* XXX Choose a fixed color from the list in - * calendar-setup.c. I like purple. */ - e_source_set_color_spec (source, "#E2C6E1"); - - new_source = TRUE; - } - - string = goa_account_get_identity (goa_account); - - encoded = camel_url_encode (string, "@"); - uri_string = g_strdup_printf ( - "caldav://%s@www.google.com/calendar/dav/%s/events", - encoded, string); - e_source_set_relative_uri (source, uri_string); - e_source_set_absolute_uri (source, uri_string); - g_free (uri_string); - g_free (encoded); - - e_source_set_property (source, "ssl", "1"); - e_source_set_property (source, "username", string); - e_source_set_property (source, "setup-username", string); - - /* XXX Not sure this needs to be set since the backend - * will authenticate itself if it sees a GOA ID. */ - e_source_set_property (source, "auth", "1"); - - string = goa_account_get_id (goa_account); - e_source_set_property (source, GOA_KEY, string); - - if (new_source) { - e_source_group_add_source (source_group, source, -1); - g_object_unref (source); - } - - e_source_list_sync (source_list, NULL); - - g_object_unref (source_group); - g_object_unref (source_list); - g_object_unref (goa_account); -} - -static void -online_accounts_google_sync_contacts (GoaObject *goa_object, - const gchar *evo_id) -{ - GoaAccount *goa_account; - ESourceList *source_list = NULL; - ESourceGroup *source_group; - ESource *source; - const gchar *string; - gboolean new_source = FALSE; - GError *error = NULL; - - if (!e_book_get_addressbooks (&source_list, &error)) { - g_warn_if_fail (source_list == NULL); - g_warn_if_fail (error != NULL); - g_warning ("%s", error->message); - g_error_free (error); - return; - } - - g_return_if_fail (E_IS_SOURCE_LIST (source_list)); - - goa_account = goa_object_get_account (goa_object); - - /* This returns a new reference to the source group. */ - source_group = e_source_list_ensure_group ( - source_list, _("Google"), GOOGLE_BASE_URI, TRUE); - - source = e_source_group_peek_source_by_uid (source_group, evo_id); - - if (source == NULL) { - source = g_object_new (E_TYPE_SOURCE, NULL); - source->priv->uid = g_strdup (evo_id); - e_source_set_name (source, _("Contacts")); - new_source = TRUE; - } - - string = goa_account_get_identity (goa_account); - - e_source_set_relative_uri (source, string); - - e_source_set_property (source, "use-ssl", "true"); - e_source_set_property (source, "username", string); - - /* XXX Not sure this needs to be set since the backend - * will authenticate itself if it sees a GOA ID. */ - e_source_set_property (source, "auth", "plain/password"); - - string = goa_account_get_id (goa_account); - e_source_set_property (source, GOA_KEY, string); - - if (new_source) { - e_source_group_add_source (source_group, source, -1); - g_object_unref (source); - } - - e_source_list_sync (source_list, NULL); - - g_object_unref (source_group); - g_object_unref (source_list); - g_object_unref (goa_account); -} - -void -e_online_accounts_google_sync (GoaObject *goa_object, - const gchar *evo_id) -{ - GoaMail *goa_mail; - GoaCalendar *goa_calendar; - GoaContacts *goa_contacts; - - g_return_if_fail (GOA_IS_OBJECT (goa_object)); - g_return_if_fail (evo_id != NULL); - - /*** Google Mail ***/ - - goa_mail = goa_object_get_mail (goa_object); - if (goa_mail != NULL) { - online_accounts_google_sync_mail (goa_object, evo_id); - g_object_unref (goa_mail); - } else { - EAccountList *account_list; - EAccount *account; - - account_list = e_get_account_list (); - account = e_get_account_by_uid (evo_id); - - if (account != NULL) { - e_account_list_remove (account_list, account); - e_account_list_save (account_list); - } - } - - /*** Google Calendar ***/ - - goa_calendar = goa_object_get_calendar (goa_object); - if (goa_calendar != NULL) { - online_accounts_google_sync_calendar (goa_object, evo_id); - g_object_unref (goa_calendar); - } else { - ESourceList *source_list = NULL; - ECalSourceType source_type; - GError *error = NULL; - - source_type = E_CAL_SOURCE_TYPE_EVENT; - if (e_cal_get_sources (&source_list, source_type, &error)) { - e_source_list_remove_source_by_uid ( - source_list, evo_id); - e_source_list_sync (source_list, NULL); - g_object_unref (source_list); - } else { - g_warn_if_fail (source_list == NULL); - g_warn_if_fail (error != NULL); - g_warning ("%s", error->message); - g_error_free (error); - } - - /* XXX Would be nice to support Google Tasks as well. */ - } - - /*** Google Contacts ***/ - - goa_contacts = goa_object_get_contacts (goa_object); - if (goa_contacts != NULL) { - online_accounts_google_sync_contacts (goa_object, evo_id); - g_object_unref (goa_contacts); - } else { - ESourceList *source_list = NULL; - GError *error = NULL; - - if (e_book_get_addressbooks (&source_list, &error)) { - e_source_list_remove_source_by_uid ( - source_list, evo_id); - e_source_list_sync (source_list, NULL); - g_object_unref (source_list); - } else { - g_warn_if_fail (source_list == NULL); - g_warn_if_fail (error != NULL); - g_warning ("%s", error->message); - g_error_free (error); - } - } -} diff --git a/modules/online-accounts/e-online-accounts-google.h b/modules/online-accounts/e-online-accounts-google.h deleted file mode 100644 index 10973f3298..0000000000 --- a/modules/online-accounts/e-online-accounts-google.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * e-online-accounts-google.h - * - * 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 - * - */ - -#ifndef E_ONLINE_ACCOUNTS_GOOGLE_H -#define E_ONLINE_ACCOUNTS_GOOGLE_H - -#define GOA_API_IS_SUBJECT_TO_CHANGE -#include - -G_BEGIN_DECLS - -void e_online_accounts_google_sync (GoaObject *goa_object, - const gchar *evo_id); - -G_END_DECLS - -#endif /* E_ONLINE_ACCOUNTS_GOOGLE_H */ diff --git a/modules/online-accounts/evolution-online-accounts.c b/modules/online-accounts/evolution-online-accounts.c index 3cdfc423c7..9f80c93c7a 100644 --- a/modules/online-accounts/evolution-online-accounts.c +++ b/modules/online-accounts/evolution-online-accounts.c @@ -16,509 +16,15 @@ * */ -#include -#include - -/* XXX Just use the deprecated APIs for now. - * We'll be switching away soon enough. */ -#undef E_CAL_DISABLE_DEPRECATED -#undef E_BOOK_DISABLE_DEPRECATED - -#include -#include -#include -#include - -#include - -#include - #include "camel-sasl-xoauth.h" -#include "e-online-accounts-google.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)) - -/* This is the property name or URL parameter under which we - * embed the GoaAccount ID into an EAccount or ESource object. */ -#define GOA_KEY "goa-account-id" - -typedef struct _EOnlineAccounts EOnlineAccounts; -typedef struct _EOnlineAccountsClass EOnlineAccountsClass; - -typedef struct _AccountNode AccountNode; - -struct _EOnlineAccounts { - EExtension parent; - - /* GoaAccount ID -> EAccount/ESource ID */ - GHashTable *accounts; - - GoaClient *goa_client; - EActivity *connecting; -}; - -struct _EOnlineAccountsClass { - EExtensionClass parent_class; -}; - -struct _AccountNode { - gchar *goa_id; /* GoaAccount ID */ - gchar *evo_id; /* EAccount/ESource ID */ -}; /* 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 EShell * -online_accounts_get_shell (EOnlineAccounts *extension) -{ - EExtensible *extensible; - - extensible = e_extension_get_extensible (E_EXTENSION (extension)); - - return E_SHELL (extensible); -} - -static void -online_accounts_account_added_cb (GoaClient *goa_client, - GoaObject *goa_object, - EOnlineAccounts *extension) -{ - GoaAccount *goa_account; - const gchar *provider_type; - const gchar *goa_id; - const gchar *evo_id; - - goa_account = goa_object_get_account (goa_object); - provider_type = goa_account_get_provider_type (goa_account); - - goa_id = goa_account_get_id (goa_account); - evo_id = g_hash_table_lookup (extension->accounts, goa_id); - - if (g_strcmp0 (provider_type, "google") == 0) { - if (evo_id == NULL) { - gchar *uid = e_uid_new (); - g_hash_table_insert ( - extension->accounts, - g_strdup (goa_id), uid); - evo_id = uid; - } - - e_online_accounts_google_sync (goa_object, evo_id); - } - - g_object_unref (goa_account); -} - -static void -online_accounts_account_changed_cb (GoaClient *goa_client, - GoaObject *goa_object, - EOnlineAccounts *extension) -{ - /* XXX We'll be able to handle changes more sanely once we have - * key-file based ESources with proper change notifications. */ - online_accounts_account_added_cb (goa_client, goa_object, extension); -} - -static void -online_accounts_account_removed_cb (GoaClient *goa_client, - GoaObject *goa_object, - EOnlineAccounts *extension) -{ - GoaAccount *goa_account; - EAccountList *account_list; - ESourceList *source_list; - ECalSourceType type; - EAccount *account; - const gchar *goa_id; - const gchar *evo_id; - - goa_account = goa_object_get_account (goa_object); - goa_id = goa_account_get_id (goa_account); - evo_id = g_hash_table_lookup (extension->accounts, goa_id); - - if (evo_id == NULL) - goto exit; - - /* Remove the mail account. */ - - account_list = e_get_account_list (); - account = e_get_account_by_uid (evo_id); - - if (account != NULL) { - e_account_list_remove (account_list, account); - e_account_list_save (account_list); - } - - /* Remove the address book. */ - - if (e_book_get_addressbooks (&source_list, NULL)) { - e_source_list_remove_source_by_uid (source_list, evo_id); - e_source_list_sync (source_list, NULL); - g_object_unref (source_list); - } - - /* Remove the calendar. */ - - for (type = 0; type < E_CAL_SOURCE_TYPE_LAST; type++) { - if (e_cal_get_sources (&source_list, type, NULL)) { - e_source_list_remove_source_by_uid ( - source_list, evo_id); - e_source_list_sync (source_list, NULL); - g_object_unref (source_list); - } - } - -exit: - g_object_unref (goa_account); -} - -static gint -online_accounts_compare_id (GoaObject *goa_object, - const gchar *goa_id) -{ - GoaAccount *goa_account; - gint result; - - goa_account = goa_object_get_account (goa_object); - result = g_strcmp0 (goa_account_get_id (goa_account), goa_id); - g_object_unref (goa_account); - - return result; -} - -static void -online_accounts_handle_uid (EOnlineAccounts *extension, - const gchar *goa_id, - const gchar *evo_id) -{ - const gchar *match; - - /* If the GNOME Online Account ID is already registered, the - * corresponding Evolution ID better match what was passed in. */ - match = g_hash_table_lookup (extension->accounts, goa_id); - g_return_if_fail (match == NULL || g_strcmp0 (match, evo_id) == 0); - - if (match == NULL) - g_hash_table_insert ( - extension->accounts, - g_strdup (goa_id), - g_strdup (evo_id)); -} - -static void -online_accounts_search_source_list (EOnlineAccounts *extension, - GList *goa_objects, - ESourceList *source_list) -{ - GSList *list_a; - - list_a = e_source_list_peek_groups (source_list); - - while (list_a != NULL) { - ESourceGroup *source_group; - GQueue trash = G_QUEUE_INIT; - GSList *list_b; - - source_group = E_SOURCE_GROUP (list_a->data); - list_a = g_slist_next (list_a); - - list_b = e_source_group_peek_sources (source_group); - - while (list_b != NULL) { - ESource *source; - const gchar *property; - const gchar *uid; - GList *match; - - source = E_SOURCE (list_b->data); - list_b = g_slist_next (list_b); - - uid = e_source_get_uid (source); - property = e_source_get_property (source, GOA_KEY); - - if (property == NULL) - continue; - - /* Verify the GOA account still exists. */ - match = g_list_find_custom ( - goa_objects, property, (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) - online_accounts_handle_uid ( - extension, property, uid); - else - g_queue_push_tail (&trash, source); - } - - /* Empty the trash. */ - while (!g_queue_is_empty (&trash)) { - ESource *source = g_queue_pop_head (&trash); - e_source_group_remove_source (source_group, source); - } - } - - e_source_list_sync (source_list, NULL); -} - -static void -online_accounts_populate_accounts_table (EOnlineAccounts *extension, - GList *goa_objects) -{ - EAccountList *account_list; - ESourceList *source_list; - EIterator *iterator; - ECalSourceType type; - GQueue trash = G_QUEUE_INIT; - - /* XXX All this messy logic will be much prettier once the new - * key-file based ESource API is merged. For now though, - * we trudge through it the old and cumbersome way. */ - - /* Search mail accounts. */ - - account_list = e_get_account_list (); - iterator = e_list_get_iterator (E_LIST (account_list)); - - while (e_iterator_is_valid (iterator)) { - EAccount *account; - CamelURL *url; - const gchar *param; - - /* XXX EIterator misuses const. */ - account = (EAccount *) e_iterator_get (iterator); - e_iterator_next (iterator); - - if (account->source == NULL) - continue; - - if (account->source->url == NULL) - continue; - - url = camel_url_new (account->source->url, NULL); - if (url == NULL) - continue; - - param = camel_url_get_param (url, GOA_KEY); - if (param != NULL) { - GList *match; - - /* Verify the GOA account still exists. */ - match = g_list_find_custom ( - goa_objects, param, (GCompareFunc) - online_accounts_compare_id); - - /* If a matching GoaObject was found, add its ID - * to our accounts hash table. Otherwise remove - * the EAccount after we finish looping. */ - if (match != NULL) - online_accounts_handle_uid ( - extension, param, account->uid); - else - g_queue_push_tail (&trash, account); - } - - camel_url_free (url); - } - - g_object_unref (iterator); - - /* Empty the trash. */ - while (!g_queue_is_empty (&trash)) { - EAccount *account = g_queue_pop_head (&trash); - e_account_list_remove (account_list, account); - } - - e_account_list_save (account_list); - - /* Search address book sources. */ - - if (e_book_get_addressbooks (&source_list, NULL)) { - online_accounts_search_source_list ( - extension, goa_objects, source_list); - g_object_unref (source_list); - } - - /* Search calendar-related sources. */ - - for (type = 0; type < E_CAL_SOURCE_TYPE_LAST; type++) { - if (e_cal_get_sources (&source_list, type, NULL)) { - online_accounts_search_source_list ( - extension, goa_objects, source_list); - g_object_unref (source_list); - } - } -} - -static void -online_accounts_connect_done (GObject *source_object, - GAsyncResult *result, - EOnlineAccounts *extension) -{ - GList *list, *link; - GError *error = NULL; - - extension->goa_client = goa_client_new_finish (result, &error); - - /* FIXME Add an EAlert for this? */ - if (error != NULL) { - g_warning ("%s", error->message); - g_error_free (error); - return; - } - - list = goa_client_get_accounts (extension->goa_client); - - /* This populates a hash table of GOA ID -> Evo ID strings by - * searching through all Evolution sources for ones tagged with - * a GOA ID. If a GOA ID tag is found, but no corresponding GOA - * account (presumably meaning the GOA account was deleted between - * Evo sessions), then the EAccount or ESource on which the tag 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-changed", - G_CALLBACK (online_accounts_account_changed_cb), extension); - g_signal_connect ( - extension->goa_client, "account-removed", - G_CALLBACK (online_accounts_account_removed_cb), extension); - - /* This will allow the Evolution Setup Assistant to proceed. */ - g_object_unref (extension->connecting); - extension->connecting = NULL; -} - -static void -online_accounts_connect (EShell *shell, - EActivity *activity, - EOnlineAccounts *extension) -{ - /* This will inhibit the Evolution Setup Assistant until - * we've synchronized with the OnlineAccounts service. */ - extension->connecting = g_object_ref (activity); - - /* We don't really need to reference the extension in the - * async closure since its lifetime is bound to the EShell. */ - goa_client_new ( - NULL, (GAsyncReadyCallback) - online_accounts_connect_done, extension); -} - -static void -online_accounts_dispose (GObject *object) -{ - EOnlineAccounts *extension; - - extension = E_ONLINE_ACCOUNTS (object); - - /* This should never fail... in theory. */ - g_warn_if_fail (extension->connecting == NULL); - - 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; - } - - /* 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->accounts); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (e_online_accounts_parent_class)->finalize (object); -} - -static void -online_accounts_constructed (GObject *object) -{ - EOnlineAccounts *extension; - EShell *shell; - - extension = E_ONLINE_ACCOUNTS (object); - shell = online_accounts_get_shell (extension); - - /* This event is emitted from the "startup-wizard" module. */ - g_signal_connect ( - shell, "event::load-accounts", - G_CALLBACK (online_accounts_connect), 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_SHELL; -} - -static void -e_online_accounts_class_finalize (EOnlineAccountsClass *class) -{ -} - -static void -e_online_accounts_init (EOnlineAccounts *extension) -{ - extension->accounts = 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); camel_sasl_xoauth_type_register (type_module); } -- cgit