From 01e74b6239a9822b19e82c2300701987bc429fe4 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 27 Sep 2007 07:25:59 +0000 Subject: Fix leak when loading avatar from cache. Do not request avatar for unknown 2007-09-27 Xavier Claessens * libempathy/empathy-avatar.c: Fix leak when loading avatar from cache. * libempathy/empathy-contact-factory.c: Do not request avatar for unknown tokens, wait for AvatarUpdate signal. svn path=/trunk/; revision=323 --- libempathy/empathy-avatar.c | 21 ++++---- libempathy/empathy-contact-factory.c | 97 +++++++++++++++++------------------- 2 files changed, 58 insertions(+), 60 deletions(-) (limited to 'libempathy') diff --git a/libempathy/empathy-avatar.c b/libempathy/empathy-avatar.c index e08dd28c4..fe4e613c6 100644 --- a/libempathy/empathy-avatar.c +++ b/libempathy/empathy-avatar.c @@ -67,18 +67,18 @@ avatar_get_filename (const gchar *token) } static EmpathyAvatar * -avatar_new (const guchar *data, - const gsize len, - const gchar *format, - const gchar *token) +avatar_new (guchar *data, + gsize len, + gchar *format, + gchar *token) { EmpathyAvatar *avatar; avatar = g_slice_new0 (EmpathyAvatar); - avatar->data = g_memdup (data, len); + avatar->data = data; avatar->len = len; - avatar->format = g_strdup (format); - avatar->token = g_strdup (token); + avatar->format = format; + avatar->token = token; avatar->refcount = 1; return avatar; @@ -99,7 +99,10 @@ empathy_avatar_new (const guchar *data, g_return_val_if_fail (format != NULL, NULL); g_return_val_if_fail (!G_STR_EMPTY (token), NULL); - avatar = avatar_new (data, len, format, token); + avatar = avatar_new (g_memdup (data, len), + len, + g_strdup (format), + g_strdup (token)); /* Save to cache if not yet in it */ filename = avatar_get_filename (token); @@ -142,7 +145,7 @@ empathy_avatar_new_from_cache (const gchar *token) if (data) { empathy_debug (DEBUG_DOMAIN, "Avatar loaded from %s", filename); - avatar = avatar_new (data, len, NULL, token); + avatar = avatar_new (data, len, NULL, g_strdup (token)); } g_free (filename); diff --git a/libempathy/empathy-contact-factory.c b/libempathy/empathy-contact-factory.c index b468ccec2..d6411ed54 100644 --- a/libempathy/empathy-contact-factory.c +++ b/libempathy/empathy-contact-factory.c @@ -335,6 +335,10 @@ contact_factory_avatar_retrieved_cb (DBusGProxy *proxy, return; } + empathy_debug (DEBUG_DOMAIN, "Avatar retrieved for contact %s (%d)", + empathy_contact_get_id (contact), + handle); + avatar = empathy_avatar_new (avatar_data->data, avatar_data->len, mime_type, @@ -378,18 +382,18 @@ contact_factory_avatar_maybe_update (ContactFactoryAccountData *account_data, return TRUE; } - /* Check if the avatar changed */ - avatar = empathy_contact_get_avatar (contact); - if (avatar && !empathy_strdiff (avatar->token, token)) { - return TRUE; - } - /* Check if we have an avatar */ if (G_STR_EMPTY (token)) { empathy_contact_set_avatar (contact, NULL); return TRUE; } + /* Check if the avatar changed */ + avatar = empathy_contact_get_avatar (contact); + if (avatar && !empathy_strdiff (avatar->token, token)) { + return TRUE; + } + /* The avatar changed, search the new one in the cache */ avatar = empathy_avatar_new_from_cache (token); if (avatar) { @@ -399,17 +403,33 @@ contact_factory_avatar_maybe_update (ContactFactoryAccountData *account_data, return TRUE; } + /* Avatar is not up-to-date, we have to request it. */ return FALSE; } +static void +contact_factory_avatar_tokens_foreach (gpointer key, + gpointer value, + gpointer user_data) +{ + TokensData *data = user_data; + const gchar *token = value; + guint handle = GPOINTER_TO_UINT (key); + + if (!contact_factory_avatar_maybe_update (data->account_data, + handle, token)) { + g_array_append_val (data->handles, handle); + } +} + static void contact_factory_get_known_avatar_tokens_cb (DBusGProxy *proxy, GHashTable *tokens, GError *error, gpointer user_data) { - TokensData *data = user_data; - gint i; + ContactFactoryAccountData *account_data = user_data; + TokensData data; if (error) { empathy_debug (DEBUG_DOMAIN, @@ -418,48 +438,28 @@ contact_factory_get_known_avatar_tokens_cb (DBusGProxy *proxy, goto OUT; } - /* Remove handles for which we have an avatar */ - for (i = 0; i < data->handles->len; i++) { - const gchar *token; - guint handle; - - handle = g_array_index (data->handles, guint, i); - token = g_hash_table_lookup (tokens, GUINT_TO_POINTER (handle)); - - /* If we have no token it means CM does not know what's the - * avatar for that contact, we need to request it. */ - if (!token) { - continue; - } - - /* If avatar is not updated it means we don't have it in - * the cache so we need to request it */ - if (!contact_factory_avatar_maybe_update (data->account_data, - handle, token)) { - continue; - } + data.account_data = account_data; + data.handles = g_array_new (FALSE, FALSE, sizeof (guint)); + g_hash_table_foreach (tokens, + contact_factory_avatar_tokens_foreach, + &data); - /* We don't need to request the avatar for this handle, - * remove it from the handles array. We need to check the handle - * that takes the place of the current index we are removing, - * so i-- is needed. */ - g_array_remove_index_fast (data->handles, i); - i--; - } + empathy_debug (DEBUG_DOMAIN, "Got %d tokens, need to request %d avatars", + g_hash_table_size (tokens), + data.handles->len); /* Request needed avatars */ - if (data->handles->len > 0) { - data->account_data->nb_pending_calls++; - tp_conn_iface_avatars_request_avatars_async (data->account_data->avatars_iface, - data->handles, + if (data.handles->len > 0) { + account_data->nb_pending_calls++; + tp_conn_iface_avatars_request_avatars_async (account_data->avatars_iface, + data.handles, contact_factory_request_avatars_cb, - data->account_data); + account_data); } + g_array_free (data.handles, TRUE); OUT: - contact_factory_account_data_return_call (data->account_data); - g_array_free (data->handles, TRUE); - g_slice_free (TokensData, data); + contact_factory_account_data_return_call (account_data); } static void @@ -476,6 +476,8 @@ contact_factory_avatar_updated_cb (DBusGProxy *proxy, return; } + empathy_debug (DEBUG_DOMAIN, "Need to request one avatar"); + handles = g_array_new (FALSE, FALSE, sizeof (guint)); g_array_append_val (handles, handle); @@ -620,18 +622,11 @@ contact_factory_request_everything (ContactFactoryAccountData *account_data, } if (account_data->avatars_iface) { - TokensData *data; - account_data->nb_pending_calls++; - data = g_slice_new (TokensData); - data->account_data = account_data; - data->handles = g_array_new (FALSE, FALSE, sizeof (guint)); - g_array_append_vals (data->handles, handles->data, handles->len); - tp_conn_iface_avatars_get_known_avatar_tokens_async (account_data->avatars_iface, handles, contact_factory_get_known_avatar_tokens_cb, - data); + account_data); } if (account_data->capabilities_iface) { -- cgit v1.2.3