aboutsummaryrefslogtreecommitdiffstats
path: root/mail/e-mail-ui-session.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail/e-mail-ui-session.c')
-rw-r--r--mail/e-mail-ui-session.c154
1 files changed, 150 insertions, 4 deletions
diff --git a/mail/e-mail-ui-session.c b/mail/e-mail-ui-session.c
index e7b2d8704f..96db4bbb12 100644
--- a/mail/e-mail-ui-session.c
+++ b/mail/e-mail-ui-session.c
@@ -74,6 +74,9 @@ struct _EMailUISessionPrivate {
EMailLabelListStore *label_store;
EPhotoCache *photo_cache;
gboolean check_junk;
+
+ GSList *address_cache; /* data is AddressCacheData struct */
+ GMutex address_cache_mutex;
};
enum {
@@ -102,6 +105,62 @@ struct _SourceContext {
CamelService *service;
};
+typedef struct _AddressCacheData {
+ gchar *email_address;
+ gint64 stamp; /* when it was added to cache, in microseconds */
+ gboolean is_known;
+} AddressCacheData;
+
+static void
+address_cache_data_free (gpointer pdata)
+{
+ AddressCacheData *data = pdata;
+
+ if (data) {
+ g_free (data->email_address);
+ g_free (data);
+ }
+}
+
+static GSList *
+address_cache_data_remove_old_and_test (GSList *items,
+ const gchar *email_address,
+ gboolean *found,
+ gboolean *is_known)
+{
+ gint64 old_when;
+ GSList *iter, *prev = NULL;
+
+ if (!items)
+ return NULL;
+
+ /* let the cache value live for 5 minutes */
+ old_when = g_get_real_time () - 5 * 60 * 1000 * 1000;
+
+ for (iter = items; iter; prev = iter, iter = iter->next) {
+ AddressCacheData *data = iter->data;
+
+ if (!data || data->stamp <= old_when || !data->email_address)
+ break;
+
+ if (g_ascii_strcasecmp (email_address, data->email_address) == 0) {
+ *found = TRUE;
+ *is_known = data->is_known;
+
+ /* a match was found, shorten the list later */
+ return items;
+ }
+ }
+
+ g_slist_free_full (iter, address_cache_data_free);
+ if (prev)
+ prev->next = NULL;
+ else
+ items = NULL;
+
+ return items;
+}
+
/* Support for CamelSession.get_filter_driver () *****************************/
static CamelFolder *
@@ -358,11 +417,29 @@ mail_ui_session_dispose (GObject *object)
priv->photo_cache = NULL;
}
+ g_mutex_lock (&priv->address_cache_mutex);
+ g_slist_free_full (priv->address_cache, address_cache_data_free);
+ priv->address_cache = NULL;
+ g_mutex_unlock (&priv->address_cache_mutex);
+
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (e_mail_ui_session_parent_class)->dispose (object);
}
static void
+mail_ui_session_finalize (GObject *object)
+{
+ EMailUISessionPrivate *priv;
+
+ priv = E_MAIL_UI_SESSION_GET_PRIVATE (object);
+
+ g_mutex_clear (&priv->address_cache_mutex);
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (e_mail_ui_session_parent_class)->finalize (object);
+}
+
+static void
mail_ui_session_constructed (GObject *object)
{
EMailUISessionPrivate *priv;
@@ -581,6 +658,7 @@ e_mail_ui_session_class_init (EMailUISessionClass *class)
object_class->set_property = mail_ui_session_set_property;
object_class->get_property = mail_ui_session_get_property;
object_class->dispose = mail_ui_session_dispose;
+ object_class->finalize = mail_ui_session_finalize;
object_class->constructed = mail_ui_session_constructed;
session_class = CAMEL_SESSION_CLASS (class);
@@ -643,6 +721,7 @@ static void
e_mail_ui_session_init (EMailUISession *session)
{
session->priv = E_MAIL_UI_SESSION_GET_PRIVATE (session);
+ g_mutex_init (&session->priv->address_cache_mutex);
session->priv->label_store = e_mail_label_list_store_new ();
}
@@ -736,6 +815,32 @@ e_mail_ui_session_add_activity (EMailUISession *session,
g_signal_emit (session, signals[ACTIVITY_ADDED], 0, activity);
}
+/* let's test in local books first */
+static gint
+sort_local_books_first_cb (gconstpointer a,
+ gconstpointer b)
+{
+ ESource *asource = (ESource *) a;
+ ESource *bsource = (ESource *) b;
+ ESourceBackend *abackend, *bbackend;
+
+ abackend = e_source_get_extension (asource, E_SOURCE_EXTENSION_ADDRESS_BOOK);
+ bbackend = e_source_get_extension (bsource, E_SOURCE_EXTENSION_ADDRESS_BOOK);
+
+ if (g_strcmp0 (e_source_backend_get_backend_name (abackend), "local") == 0) {
+ if (g_strcmp0 (e_source_backend_get_backend_name (bbackend), "local") == 0)
+ return 0;
+
+ return -1;
+ }
+
+ if (g_strcmp0 (e_source_backend_get_backend_name (bbackend), "local") == 0)
+ return 1;
+
+ return g_strcmp0 (e_source_backend_get_backend_name (abackend),
+ e_source_backend_get_backend_name (bbackend));
+}
+
/**
* e_mail_ui_session_check_known_address_sync:
* @session: an #EMailUISession
@@ -774,7 +879,7 @@ e_mail_ui_session_check_known_address_sync (EMailUISession *session,
const gchar *email_address = NULL;
gchar *book_query_string;
gboolean known_address = FALSE;
- gboolean success = TRUE;
+ gboolean success = FALSE;
g_return_val_if_fail (E_IS_MAIL_UI_SESSION (session), FALSE);
g_return_val_if_fail (CAMEL_IS_INTERNET_ADDRESS (addr), FALSE);
@@ -782,6 +887,21 @@ e_mail_ui_session_check_known_address_sync (EMailUISession *session,
camel_internet_address_get (addr, 0, NULL, &email_address);
g_return_val_if_fail (email_address != NULL, FALSE);
+ g_mutex_lock (&session->priv->address_cache_mutex);
+
+ session->priv->address_cache = address_cache_data_remove_old_and_test (
+ session->priv->address_cache,
+ email_address, &success, &known_address);
+
+ if (success) {
+ g_mutex_unlock (&session->priv->address_cache_mutex);
+
+ if (out_known_address)
+ *out_known_address = known_address;
+
+ return success;
+ }
+
/* XXX EPhotoCache holds a reference on EClientCache, which
* we need. EMailUISession should probably hold its own
* EClientCache reference, but this will do for now. */
@@ -801,14 +921,16 @@ e_mail_ui_session_check_known_address_sync (EMailUISession *session,
list = g_list_prepend (NULL, g_object_ref (source));
g_object_unref (source);
} else {
- list = e_source_registry_list_sources (
+ list = e_source_registry_list_enabled (
registry, E_SOURCE_EXTENSION_ADDRESS_BOOK);
+ list = g_list_sort (list, sort_local_books_first_cb);
}
- for (link = list; link != NULL; link = g_list_next (link)) {
+ for (link = list; link != NULL && !g_cancellable_is_cancelled (cancellable); link = g_list_next (link)) {
ESource *source = E_SOURCE (link->data);
EClient *client;
GSList *uids = NULL;
+ GError *local_error = NULL;
/* Skip disabled sources. */
if (!e_source_get_enabled (source))
@@ -817,9 +939,19 @@ e_mail_ui_session_check_known_address_sync (EMailUISession *session,
client = e_client_cache_get_client_sync (
client_cache, source,
E_SOURCE_EXTENSION_ADDRESS_BOOK,
- cancellable, error);
+ cancellable, &local_error);
if (client == NULL) {
+ /* ignore E_CLIENT_ERROR-s, no need to stop searching if one
+ of the books is temporarily unreachable or any such issue */
+ if (local_error && local_error->domain == E_CLIENT_ERROR) {
+ g_clear_error (&local_error);
+ continue;
+ }
+
+ if (local_error)
+ g_propagate_error (error, local_error);
+
success = FALSE;
break;
}
@@ -852,6 +984,20 @@ e_mail_ui_session_check_known_address_sync (EMailUISession *session,
if (success && out_known_address != NULL)
*out_known_address = known_address;
+ if (!g_cancellable_is_cancelled (cancellable)) {
+ AddressCacheData *data = g_new0 (AddressCacheData, 1);
+
+ data->email_address = g_strdup (email_address);
+ data->stamp = g_get_real_time ();
+ data->is_known = known_address;
+
+ /* this makes the list sorted by time, from newest to oldest */
+ session->priv->address_cache = g_slist_prepend (
+ session->priv->address_cache, data);
+ }
+
+ g_mutex_unlock (&session->priv->address_cache_mutex);
+
return success;
}