summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2012-05-15 13:44:41 +0200
committerMilan Crha <mcrha@redhat.com>2012-05-15 13:44:41 +0200
commit02898f33d846a9860efd2a2c6c54e00df2ef4aad (patch)
tree411f3077c2b639ea19fdaa1b5efee0260aaf7591
parent0d73790d2a19c87c1cabf536ea5a94e05da0eb9c (diff)
downloadevolution-data-server-02898f33d846a9860efd2a2c6c54e00df2ef4aad.tar.gz
Bug #671603 - Birthday calendar broken since 3.3.4
-rw-r--r--calendar/backends/contacts/e-cal-backend-contacts.c96
1 files changed, 62 insertions, 34 deletions
diff --git a/calendar/backends/contacts/e-cal-backend-contacts.c b/calendar/backends/contacts/e-cal-backend-contacts.c
index f595ece80..242c15213 100644
--- a/calendar/backends/contacts/e-cal-backend-contacts.c
+++ b/calendar/backends/contacts/e-cal-backend-contacts.c
@@ -67,8 +67,9 @@ typedef enum
struct _ECalBackendContactsPrivate {
ESourceList *addressbook_sources;
- GHashTable *addressbooks; /* UID -> BookRecord */
- GHashTable *credentials; /* UID -> ECredentials to use in "authenticate" handler */
+ GMutex *mutex; /* guards 'addressbooks' and 'credentials' */
+ GHashTable *addressbooks; /* UID -> BookRecord */
+ GHashTable *credentials; /* UID -> ECredentials to use in "authenticate" handler */
gboolean loaded;
EBookClientView *book_view;
@@ -137,6 +138,7 @@ book_client_authenticate_cb (EClient *client,
source_uid = e_source_peek_uid (source);
g_return_val_if_fail (source_uid != NULL, FALSE);
+ g_mutex_lock (cbc->priv->mutex);
use_credentials = g_hash_table_lookup (cbc->priv->credentials, source_uid);
if (use_credentials &&
@@ -158,9 +160,13 @@ book_client_authenticate_cb (EClient *client,
e_credentials_set (use_credentials, CBC_CREDENTIALS_KEY_ALREADY_USED, "1");
g_slist_free (keys);
+ g_mutex_unlock (cbc->priv->mutex);
+
return TRUE;
}
+ g_mutex_unlock (cbc->priv->mutex);
+
/* write properties on a copy of original credentials */
credentials = e_credentials_new_clone (credentials);
@@ -333,14 +339,16 @@ book_client_opened_cb (EBookClient *book_client,
source_uid = e_source_peek_uid (source);
g_return_if_fail (source_uid != NULL);
- if (source_uid) {
- br = g_hash_table_lookup (cbc->priv->addressbooks, source_uid);
- if (br && br->book_client != book_client)
- br = NULL;
- }
+ g_mutex_lock (cbc->priv->mutex);
- if (!br)
+ br = g_hash_table_lookup (cbc->priv->addressbooks, source_uid);
+ if (br && br->book_client != book_client)
+ br = NULL;
+
+ if (!br) {
+ g_mutex_unlock (cbc->priv->mutex);
return;
+ }
if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_AUTHENTICATION_FAILED)) {
if (g_hash_table_lookup (cbc->priv->credentials, source_uid)) {
@@ -384,6 +392,8 @@ book_client_opened_cb (EBookClient *book_client,
br->book_view = book_view;
}
+
+ g_mutex_unlock (cbc->priv->mutex);
}
static void
@@ -405,56 +415,72 @@ e_cal_backend_contacts_authenticate_user (ECalBackendSync *backend,
source_uid = e_credentials_peek (credentials, CBC_CREDENTIALS_KEY_SOURCE_UID);
g_return_if_fail (source_uid != NULL);
+ g_mutex_lock (cbc->priv->mutex);
+
br = g_hash_table_lookup (cbc->priv->addressbooks, source_uid);
if (!br || !br->book_client ||
/* no username means user cancelled password prompt */
!e_credentials_has_key (credentials, E_CREDENTIALS_KEY_USERNAME)) {
g_hash_table_remove (cbc->priv->credentials, source_uid);
+ g_mutex_unlock (cbc->priv->mutex);
return;
}
g_hash_table_insert (cbc->priv->credentials, g_strdup (source_uid), e_credentials_new_clone (credentials));
cbc_reopen_book_client (cbc, br->book_client);
+
+ g_mutex_unlock (cbc->priv->mutex);
}
/* BookRecord methods */
-static BookRecord *
-book_record_new (ECalBackendContacts *cbc,
- ESource *source)
+static void
+create_book_record (ECalBackendContacts *cbc,
+ ESource *source)
{
EBookClient *book_client;
BookRecord *br;
GError *error = NULL;
+ const gchar *uid = e_source_peek_uid (source);
+
+ g_return_if_fail (uid != NULL);
book_client = e_book_client_new (source, &error);
if (!book_client) {
g_warning ("%s: Failed to create new book: %s", G_STRFUNC, error ? error->message : "Unknown error");
g_clear_error (&error);
- return NULL;
+ return;
}
g_signal_connect (book_client, "authenticate", G_CALLBACK (book_client_authenticate_cb), cbc);
g_signal_connect (book_client, "opened", G_CALLBACK (book_client_opened_cb), cbc);
+ br = g_new0 (BookRecord, 1);
+ br->cbc = cbc;
+ br->book_client = book_client;
+ br->book_view = NULL;
+
+ g_mutex_lock (cbc->priv->mutex);
+ g_hash_table_insert (cbc->priv->addressbooks, g_strdup (uid), br);
+ g_mutex_unlock (cbc->priv->mutex);
+
if (!e_client_open_sync (E_CLIENT (book_client), TRUE, NULL, &error) || error) {
g_signal_handlers_disconnect_by_func (book_client, G_CALLBACK (book_client_authenticate_cb), cbc);
g_signal_handlers_disconnect_by_func (book_client, G_CALLBACK (book_client_opened_cb), cbc);
- g_object_unref (book_client);
if (error) {
g_warning ("%s: Failed to open book: %s", G_STRFUNC, error->message);
g_error_free (error);
}
- return NULL;
- }
- br = g_new0 (BookRecord, 1);
- br->cbc = cbc;
- br->book_client = book_client;
- br->book_view = NULL;
+ g_mutex_lock (cbc->priv->mutex);
+
+ /* removal also frees the 'br' struct */
+ g_hash_table_remove (cbc->priv->addressbooks, uid);
+ g_hash_table_remove (cbc->priv->credentials, uid);
- return br;
+ g_mutex_unlock (cbc->priv->mutex);
+ }
}
static gboolean
@@ -618,19 +644,6 @@ is_source_usable (ESource *source,
/* SourceList callbacks */
static void
-add_source (ECalBackendContacts *cbc,
- ESource *source)
-{
- BookRecord *br = book_record_new (cbc, source);
- const gchar *uid = e_source_peek_uid (source);
-
- if (!br)
- return;
-
- g_hash_table_insert (cbc->priv->addressbooks, g_strdup (uid), br);
-}
-
-static void
source_added_cb (ESourceGroup *group,
ESource *source,
gpointer user_data)
@@ -640,7 +653,7 @@ source_added_cb (ESourceGroup *group,
g_return_if_fail (cbc);
if (is_source_usable (source, group))
- add_source (cbc, source);
+ create_book_record (cbc, source);
}
static void
@@ -653,8 +666,12 @@ source_removed_cb (ESourceGroup *group,
g_return_if_fail (cbc);
+ g_mutex_lock (cbc->priv->mutex);
+
g_hash_table_remove (cbc->priv->addressbooks, uid);
g_hash_table_remove (cbc->priv->credentials, uid);
+
+ g_mutex_unlock (cbc->priv->mutex);
}
static void
@@ -683,12 +700,16 @@ source_list_changed_cb (ESourceList *source_list,
if (!uid)
continue;
+ g_mutex_lock (cbc->priv->mutex);
+
if (is_source_usable (source, group)) {
if (!g_hash_table_lookup (cbc->priv->addressbooks, uid))
source_added_cb (group, source, cbc);
} else if (g_hash_table_lookup (cbc->priv->addressbooks, uid)) {
source_removed_cb (group, source, cbc);
}
+
+ g_mutex_unlock (cbc->priv->mutex);
}
}
}
@@ -723,6 +744,8 @@ source_group_removed_cb (ESourceList *source_list,
g_return_if_fail (cbc);
+ g_mutex_lock (cbc->priv->mutex);
+
/* Unload all address books from this group */
for (i = e_source_group_peek_sources (group); i; i = i->next) {
ESource *source = E_SOURCE (i->data);
@@ -731,6 +754,8 @@ source_group_removed_cb (ESourceList *source_list,
g_hash_table_remove (cbc->priv->addressbooks, uid);
g_hash_table_remove (cbc->priv->credentials, uid);
}
+
+ g_mutex_unlock (cbc->priv->mutex);
}
/************************************************************************************/
@@ -1526,6 +1551,7 @@ e_cal_backend_contacts_finalize (GObject *object)
gconf_client_notify_remove (priv->conf_client, priv->notifyid3);
g_object_unref (priv->conf_client);
+ g_mutex_free (priv->mutex);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_cal_backend_contacts_parent_class)->finalize (object);
@@ -1540,6 +1566,8 @@ e_cal_backend_contacts_init (ECalBackendContacts *cbc)
if (!e_book_client_get_sources (&cbc->priv->addressbook_sources, NULL))
cbc->priv->addressbook_sources = NULL;
+ cbc->priv->mutex = g_mutex_new ();
+
cbc->priv->addressbooks = g_hash_table_new_full (
(GHashFunc) g_str_hash,
(GEqualFunc) g_str_equal,