]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-contact-factory.c
Fix leak when loading avatar from cache. Do not request avatar for unknown
[empathy.git] / libempathy / empathy-contact-factory.c
index b468ccec2249967800b3c6d0a2b28dd7b0b87b6e..d6411ed54f3af8366f78cdda047138d058460143 100644 (file)
@@ -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) {