]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-tp-contact-list.c
Initial room list support. It does not works yet.
[empathy.git] / libempathy / empathy-tp-contact-list.c
index e54ebef384168cb0a7fb799c7bcd3ae7ea7e685f..8ecf564e3daeb69af841e031ce5c4c91904d8bdb 100644 (file)
@@ -24,6 +24,7 @@
 #include <config.h>
 
 #include <string.h>
+#include <glib/gi18n.h>
 
 #include <libtelepathy/tp-helpers.h>
 #include <libtelepathy/tp-conn.h>
@@ -35,9 +36,9 @@
 
 #include "empathy-tp-contact-list.h"
 #include "empathy-contact-list.h"
-#include "gossip-telepathy-group.h"
-#include "gossip-debug.h"
-#include "gossip-utils.h"
+#include "empathy-tp-group.h"
+#include "empathy-debug.h"
+#include "empathy-utils.h"
 
 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
                       EMPATHY_TYPE_TP_CONTACT_LIST, EmpathyTpContactListPriv))
 #define MAX_AVATAR_REQUESTS 10
 
 struct _EmpathyTpContactListPriv {
-       TpConn               *tp_conn;
-       McAccount            *account;
-       MissionControl       *mc;
-       GossipContact        *user_contact;
-       gboolean              setup;
-
-       GossipTelepathyGroup *publish;
-       GossipTelepathyGroup *subscribe;
-
-       GHashTable           *groups;
-       GHashTable           *contacts;
-       GList                *local_pending;
-
-       DBusGProxy           *aliasing_iface;
-       DBusGProxy           *avatars_iface;
-       DBusGProxy           *presence_iface;
-
-       GList                *avatar_requests_queue;
+       TpConn         *tp_conn;
+       McAccount      *account;
+       MissionControl *mc;
+       EmpathyContact *user_contact;
+       gboolean        setup;
+       const gchar    *protocol_group;
+
+       EmpathyTpGroup *publish;
+       EmpathyTpGroup *subscribe;
+
+       GHashTable     *groups;
+       GHashTable     *contacts;
+       GList          *members;
+       GList          *local_pending;
+
+       DBusGProxy     *aliasing_iface;
+       DBusGProxy     *avatars_iface;
+       DBusGProxy     *presence_iface;
 };
 
 typedef enum {
@@ -88,137 +89,138 @@ typedef struct {
        guint                *handles;
 } TpContactListAliasesRequestData;
 
-static void                   empathy_tp_contact_list_class_init       (EmpathyTpContactListClass       *klass);
-static void                   tp_contact_list_iface_init               (EmpathyContactListIface         *iface);
-static void                   empathy_tp_contact_list_init             (EmpathyTpContactList            *list);
-static void                   tp_contact_list_finalize                 (GObject                         *object);
-static void                   tp_contact_list_finalize_proxies         (EmpathyTpContactList            *list);
-static void                   tp_contact_list_setup                    (EmpathyContactList              *list);
-static GossipContact *        tp_contact_list_find                     (EmpathyContactList              *list,
-                                                                       const gchar                     *id);
-static void                   tp_contact_list_add                      (EmpathyContactList              *list,
-                                                                       GossipContact                   *contact,
-                                                                       const gchar                     *message);
-static void                   tp_contact_list_remove                   (EmpathyContactList              *list,
-                                                                       GossipContact                   *contact,
-                                                                       const gchar                     *message);
-static GList *                tp_contact_list_get_members              (EmpathyContactList              *list);
-static GList *                tp_contact_list_get_local_pending        (EmpathyContactList              *list);
-static void                   tp_contact_list_remove_local_pending     (EmpathyTpContactList            *list,
-                                                                       GossipContact                   *contact);
-static void                   tp_contact_list_contact_removed_foreach  (guint                            handle,
-                                                                       GossipContact                   *contact,
-                                                                       EmpathyTpContactList            *list);
-static void                   tp_contact_list_destroy_cb               (DBusGProxy                      *proxy,
-                                                                       EmpathyTpContactList            *list);
-static gboolean               tp_contact_list_find_foreach             (guint                            handle,
-                                                                       GossipContact                   *contact,
-                                                                       gchar                           *id);
-static void                   tp_contact_list_newchannel_cb            (DBusGProxy                      *proxy,
-                                                                       const gchar                     *object_path,
-                                                                       const gchar                     *channel_type,
-                                                                       TelepathyHandleType              handle_type,
-                                                                       guint                            channel_handle,
-                                                                       gboolean                         suppress_handle,
-                                                                       EmpathyTpContactList            *list);
-static TpContactListType      tp_contact_list_get_type                 (EmpathyTpContactList            *list,
-                                                                       GossipTelepathyGroup            *group);
-static void                   tp_contact_list_added_cb                 (GossipTelepathyGroup            *group,
-                                                                       GArray                          *handles,
-                                                                       guint                            actor_handle,
-                                                                       guint                            reason,
-                                                                       const gchar                     *message,
-                                                                       EmpathyTpContactList            *list);
-static void                   tp_contact_list_removed_cb               (GossipTelepathyGroup            *group,
-                                                                       GArray                          *handles,
-                                                                       guint                            actor_handle,
-                                                                       guint                            reason,
-                                                                       const gchar                     *message,
-                                                                       EmpathyTpContactList            *list);
-static void                   tp_contact_list_pending_cb               (GossipTelepathyGroup            *group,
-                                                                       GArray                          *handles,
-                                                                       guint                            actor_handle,
-                                                                       guint                            reason,
-                                                                       const gchar                     *message,
-                                                                       EmpathyTpContactList            *list);
-static void                   tp_contact_list_groups_updated_cb        (GossipContact                   *contact,
-                                                                       GParamSpec                      *param,
-                                                                       EmpathyTpContactList            *list);
-static void                   tp_contact_list_name_updated_cb          (GossipContact                   *contact,
-                                                                       GParamSpec                      *param,
-                                                                       EmpathyTpContactList            *list);
-static void                   tp_contact_list_update_groups_foreach    (gchar                           *object_path,
-                                                                       GossipTelepathyGroup            *group,
-                                                                       TpContactListData               *data);
-static GossipTelepathyGroup * tp_contact_list_get_group                (EmpathyTpContactList            *list,
-                                                                       const gchar                     *name);
-static gboolean               tp_contact_list_find_group               (gchar                           *key,
-                                                                       GossipTelepathyGroup            *group,
-                                                                       gchar                           *group_name);
-static void                   tp_contact_list_get_groups_foreach       (gchar                           *key,
-                                                                       GossipTelepathyGroup            *group,
-                                                                       GList                          **groups);
-static void                   tp_contact_list_group_channel_closed_cb  (TpChan                          *channel,
-                                                                       EmpathyTpContactList            *list);
-static void                   tp_contact_list_group_members_added_cb   (GossipTelepathyGroup            *group,
-                                                                       GArray                          *members,
-                                                                       guint                            actor_handle,
-                                                                       guint                            reason,
-                                                                       const gchar                     *message,
-                                                                       EmpathyTpContactList            *list);
-static void                   tp_contact_list_group_members_removed_cb (GossipTelepathyGroup            *group,
-                                                                       GArray                          *members,
-                                                                       guint                            actor_handle,
-                                                                       guint                            reason,
-                                                                       const gchar                     *message,
-                                                                       EmpathyTpContactList            *list);
-static void                   tp_contact_list_get_members_foreach      (guint                            handle,
-                                                                       GossipContact                   *contact,
-                                                                       GList                          **contacts);
-static void                   tp_contact_list_get_info                 (EmpathyTpContactList            *list,
-                                                                       GArray                          *handles);
-static void                   tp_contact_list_request_avatar           (EmpathyTpContactList            *list,
-                                                                       guint                            handle);
-static void                   tp_contact_list_start_avatar_requests    (EmpathyTpContactList            *list);
-static void                   tp_contact_list_avatar_update_cb         (DBusGProxy                      *proxy,
-                                                                       guint                            handle,
-                                                                       gchar                           *new_token,
-                                                                       EmpathyTpContactList            *list);
-static void                   tp_contact_list_request_avatar_cb        (DBusGProxy                      *proxy,
-                                                                       GArray                          *avatar_data,
-                                                                       gchar                           *mime_type,
-                                                                       GError                          *error,
-                                                                       TpContactListAvatarRequestData  *data);
-static void                   tp_contact_list_aliases_update_cb        (DBusGProxy                      *proxy,
-                                                                       GPtrArray                       *handlers,
-                                                                       EmpathyTpContactList            *list);
-static void                   tp_contact_list_request_aliases_cb       (DBusGProxy                      *proxy,
-                                                                       gchar                          **contact_names,
-                                                                       GError                          *error,
-                                                                       TpContactListAliasesRequestData *data);
-static void                   tp_contact_list_presence_update_cb       (DBusGProxy                      *proxy,
-                                                                       GHashTable                      *handle_table,
-                                                                       EmpathyTpContactList            *list);
-static void                   tp_contact_list_parse_presence_foreach   (guint                            handle,
-                                                                       GValueArray                     *presence_struct,
-                                                                       EmpathyTpContactList            *list);
-static void                   tp_contact_list_presences_table_foreach  (const gchar                     *state_str,
-                                                                       GHashTable                      *presences_table,
-                                                                       GossipPresence                 **presence);
-static void                   tp_contact_list_status_changed_cb        (MissionControl                  *mc,
-                                                                       TelepathyConnectionStatus        status,
-                                                                       McPresence                       presence,
-                                                                       TelepathyConnectionStatusReason  reason,
-                                                                       const gchar                     *unique_name,
-                                                                       EmpathyTpContactList            *list);
+static void               empathy_tp_contact_list_class_init       (EmpathyTpContactListClass       *klass);
+static void               tp_contact_list_iface_init               (EmpathyContactListIface         *iface);
+static void               empathy_tp_contact_list_init             (EmpathyTpContactList            *list);
+static void               tp_contact_list_finalize                 (GObject                         *object);
+static void               tp_contact_list_finalize_proxies         (EmpathyTpContactList            *list);
+static void               tp_contact_list_setup                    (EmpathyContactList              *list);
+static EmpathyContact *   tp_contact_list_find                     (EmpathyContactList              *list,
+                                                                   const gchar                     *id);
+static void               tp_contact_list_add                      (EmpathyContactList              *list,
+                                                                   EmpathyContact                  *contact,
+                                                                   const gchar                     *message);
+static void               tp_contact_list_remove                   (EmpathyContactList              *list,
+                                                                   EmpathyContact                  *contact,
+                                                                   const gchar                     *message);
+static GList *            tp_contact_list_get_members              (EmpathyContactList              *list);
+static GList *            tp_contact_list_get_local_pending        (EmpathyContactList              *list);
+static void               tp_contact_list_process_pending          (EmpathyContactList              *list,
+                                                                   EmpathyContact                  *contact,
+                                                                   gboolean                         accept);
+static void               tp_contact_list_remove_local_pending     (EmpathyTpContactList            *list,
+                                                                   EmpathyContact                  *contact);
+static void               tp_contact_list_contact_removed_foreach  (guint                            handle,
+                                                                   EmpathyContact                  *contact,
+                                                                   EmpathyTpContactList            *list);
+static void               tp_contact_list_destroy_cb               (DBusGProxy                      *proxy,
+                                                                   EmpathyTpContactList            *list);
+static gboolean           tp_contact_list_find_foreach             (guint                            handle,
+                                                                   EmpathyContact                  *contact,
+                                                                   gchar                           *id);
+static void               tp_contact_list_newchannel_cb            (DBusGProxy                      *proxy,
+                                                                   const gchar                     *object_path,
+                                                                   const gchar                     *channel_type,
+                                                                   TelepathyHandleType              handle_type,
+                                                                   guint                            channel_handle,
+                                                                   gboolean                         suppress_handle,
+                                                                   EmpathyTpContactList            *list);
+static TpContactListType  tp_contact_list_get_type                 (EmpathyTpContactList            *list,
+                                                                   EmpathyTpGroup                  *group);
+static void               tp_contact_list_added_cb                 (EmpathyTpGroup                  *group,
+                                                                   GArray                          *handles,
+                                                                   guint                            actor_handle,
+                                                                   guint                            reason,
+                                                                   const gchar                     *message,
+                                                                   EmpathyTpContactList            *list);
+static void               tp_contact_list_removed_cb               (EmpathyTpGroup                  *group,
+                                                                   GArray                          *handles,
+                                                                   guint                            actor_handle,
+                                                                   guint                            reason,
+                                                                   const gchar                     *message,
+                                                                   EmpathyTpContactList            *list);
+static void               tp_contact_list_pending_cb               (EmpathyTpGroup                  *group,
+                                                                   GArray                          *handles,
+                                                                   guint                            actor_handle,
+                                                                   guint                            reason,
+                                                                   const gchar                     *message,
+                                                                   EmpathyTpContactList            *list);
+static void               tp_contact_list_groups_updated_cb        (EmpathyContact                  *contact,
+                                                                   GParamSpec                      *param,
+                                                                   EmpathyTpContactList            *list);
+static void               tp_contact_list_name_updated_cb          (EmpathyContact                  *contact,
+                                                                   GParamSpec                      *param,
+                                                                   EmpathyTpContactList            *list);
+static void               tp_contact_list_update_groups_foreach    (gchar                           *object_path,
+                                                                   EmpathyTpGroup                  *group,
+                                                                   TpContactListData               *data);
+static EmpathyTpGroup *   tp_contact_list_get_group                (EmpathyTpContactList            *list,
+                                                                   const gchar                     *name);
+static gboolean           tp_contact_list_find_group               (gchar                           *key,
+                                                                   EmpathyTpGroup                  *group,
+                                                                   gchar                           *group_name);
+static void               tp_contact_list_get_groups_foreach       (gchar                           *key,
+                                                                   EmpathyTpGroup                  *group,
+                                                                   GList                          **groups);
+static void               tp_contact_list_group_channel_closed_cb  (TpChan                          *channel,
+                                                                   EmpathyTpContactList            *list);
+static void               tp_contact_list_group_members_added_cb   (EmpathyTpGroup                  *group,
+                                                                   GArray                          *members,
+                                                                   guint                            actor_handle,
+                                                                   guint                            reason,
+                                                                   const gchar                     *message,
+                                                                   EmpathyTpContactList            *list);
+static void               tp_contact_list_group_members_removed_cb (EmpathyTpGroup                  *group,
+                                                                   GArray                          *members,
+                                                                   guint                            actor_handle,
+                                                                   guint                            reason,
+                                                                   const gchar                     *message,
+                                                                   EmpathyTpContactList            *list);
+static void               tp_contact_list_get_info                 (EmpathyTpContactList            *list,
+                                                                   GArray                          *handles);
+static void               tp_contact_list_request_avatar           (EmpathyTpContactList            *list,
+                                                                   guint                            handle);
+static void               tp_contact_list_start_avatar_requests    (void);
+static void               tp_contact_list_avatar_update_cb         (DBusGProxy                      *proxy,
+                                                                   guint                            handle,
+                                                                   gchar                           *new_token,
+                                                                   EmpathyTpContactList            *list);
+static void               tp_contact_list_request_avatar_cb        (DBusGProxy                      *proxy,
+                                                                   GArray                          *avatar_data,
+                                                                   gchar                           *mime_type,
+                                                                   GError                          *error,
+                                                                   TpContactListAvatarRequestData  *data);
+static void               tp_contact_list_aliases_update_cb        (DBusGProxy                      *proxy,
+                                                                   GPtrArray                       *handlers,
+                                                                   EmpathyTpContactList            *list);
+static void               tp_contact_list_request_aliases_cb       (DBusGProxy                      *proxy,
+                                                                   gchar                          **contact_names,
+                                                                   GError                          *error,
+                                                                   TpContactListAliasesRequestData *data);
+static void               tp_contact_list_presence_update_cb       (DBusGProxy                      *proxy,
+                                                                   GHashTable                      *handle_table,
+                                                                   EmpathyTpContactList            *list);
+static void               tp_contact_list_parse_presence_foreach   (guint                            handle,
+                                                                   GValueArray                     *presence_struct,
+                                                                   EmpathyTpContactList            *list);
+static void               tp_contact_list_presences_table_foreach  (const gchar                     *state_str,
+                                                                   GHashTable                      *presences_table,
+                                                                   EmpathyPresence                 **presence);
+static void               tp_contact_list_status_changed_cb        (MissionControl                  *mc,
+                                                                   TelepathyConnectionStatus        status,
+                                                                   McPresence                       presence,
+                                                                   TelepathyConnectionStatusReason  reason,
+                                                                   const gchar                     *unique_name,
+                                                                   EmpathyTpContactList            *list);
 
 enum {
        DESTROY,
        LAST_SIGNAL
 };
 
-static guint signals[LAST_SIGNAL];
-static guint n_avatar_requests = 0;
+static guint  signals[LAST_SIGNAL];
+GList        *avatar_requests_queue = NULL;
+guint         n_avatar_requests = 0;
 
 G_DEFINE_TYPE_WITH_CODE (EmpathyTpContactList, empathy_tp_contact_list, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CONTACT_LIST,
@@ -253,6 +255,7 @@ tp_contact_list_iface_init (EmpathyContactListIface *iface)
        iface->remove            = tp_contact_list_remove;
        iface->get_members       = tp_contact_list_get_members;
        iface->get_local_pending = tp_contact_list_get_local_pending;
+       iface->process_pending   = tp_contact_list_process_pending;
 }
 
 static void
@@ -281,7 +284,7 @@ tp_contact_list_finalize (GObject *object)
        list = EMPATHY_TP_CONTACT_LIST (object);
        priv = GET_PRIV (list);
 
-       gossip_debug (DEBUG_DOMAIN, "finalize: %p", object);
+       empathy_debug (DEBUG_DOMAIN, "finalize: %p", object);
 
        dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc),
                                        "AccountStatusChanged",
@@ -309,6 +312,9 @@ tp_contact_list_finalize (GObject *object)
        g_list_foreach (priv->local_pending, (GFunc) empathy_contact_list_info_free, NULL);
        g_list_free (priv->local_pending);
 
+       g_list_foreach (priv->members, (GFunc) g_object_unref, NULL);
+       g_list_free (priv->members);
+
        G_OBJECT_CLASS (empathy_tp_contact_list_parent_class)->finalize (object);
 }
 
@@ -318,12 +324,14 @@ empathy_tp_contact_list_new (McAccount *account)
        EmpathyTpContactListPriv *priv;
        EmpathyTpContactList     *list;
        MissionControl           *mc;
+       McProfile                *profile;
+       const gchar              *protocol_name;
        guint                     handle;
        GError                   *error = NULL;
 
        g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
 
-       mc = gossip_mission_control_new ();
+       mc = empathy_mission_control_new ();
 
        if (mission_control_get_connection_status (mc, account, NULL) != 0) {
                /* The account is not connected, nothing to do. */
@@ -337,6 +345,16 @@ empathy_tp_contact_list_new (McAccount *account)
        priv->account = g_object_ref (account);
        priv->mc = mc;
 
+       /* Check for protocols that does not support contact groups. We can
+        * put all contacts into a special group in that case.
+        * FIXME: Default group should be an information in the profile */
+       profile = mc_account_get_profile (account);
+       protocol_name = mc_profile_get_protocol_name (profile);
+       if (strcmp (protocol_name, "salut") == 0) {
+               priv->protocol_group = _("Local Network");
+       }
+       g_object_unref (profile);
+
        g_signal_connect (priv->tp_conn, "destroy",
                          G_CALLBACK (tp_contact_list_destroy_cb),
                          list);
@@ -376,12 +394,12 @@ empathy_tp_contact_list_new (McAccount *account)
        /* Get our own handle and contact */
        if (!tp_conn_get_self_handle (DBUS_G_PROXY (priv->tp_conn),
                                      &handle, &error)) {
-               gossip_debug (DEBUG_DOMAIN, "GetSelfHandle Error: %s",
+               empathy_debug (DEBUG_DOMAIN, "GetSelfHandle Error: %s",
                              error ? error->message : "No error given");
                g_clear_error (&error);
        } else {
-               /* FIXME: this adds the handle to the roster */
                priv->user_contact = empathy_tp_contact_list_get_from_handle (list, handle);
+               empathy_contact_set_is_user (priv->user_contact, TRUE);
        }
 
        return list;
@@ -399,7 +417,7 @@ tp_contact_list_setup (EmpathyContactList *list)
 
        priv = GET_PRIV (list);
 
-       gossip_debug (DEBUG_DOMAIN, "setup contact list: %p", list);
+       empathy_debug (DEBUG_DOMAIN, "setup contact list: %p", list);
 
        priv->setup = TRUE;
        dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->tp_conn), "NewChannel",
@@ -410,7 +428,7 @@ tp_contact_list_setup (EmpathyContactList *list)
        if (!tp_conn_list_channels (DBUS_G_PROXY (priv->tp_conn),
                                    &channels,
                                    &error)) {
-               gossip_debug (DEBUG_DOMAIN,
+               empathy_debug (DEBUG_DOMAIN,
                              "Failed to get list of open channels: %s",
                              error ? error->message : "No error given");
                g_clear_error (&error);
@@ -442,7 +460,7 @@ tp_contact_list_setup (EmpathyContactList *list)
        g_ptr_array_free (channels, TRUE);
 }
 
-static GossipContact *
+static EmpathyContact *
 tp_contact_list_find (EmpathyContactList *list,
                      const gchar        *id)
 {
@@ -459,7 +477,7 @@ tp_contact_list_find (EmpathyContactList *list,
 
 static void
 tp_contact_list_add (EmpathyContactList *list,
-                    GossipContact      *contact,
+                    EmpathyContact      *contact,
                     const gchar        *message)
 {
        EmpathyTpContactListPriv *priv;
@@ -469,13 +487,13 @@ tp_contact_list_add (EmpathyContactList *list,
 
        priv = GET_PRIV (list);
 
-       handle = gossip_contact_get_handle (contact);
-       gossip_telepathy_group_add_member (priv->subscribe, handle, message);
+       handle = empathy_contact_get_handle (contact);
+       empathy_tp_group_add_member (priv->subscribe, handle, message);
 }
 
 static void
 tp_contact_list_remove (EmpathyContactList *list,
-                       GossipContact      *contact,
+                       EmpathyContact      *contact,
                        const gchar        *message)
 {
        EmpathyTpContactListPriv *priv;
@@ -485,26 +503,21 @@ tp_contact_list_remove (EmpathyContactList *list,
 
        priv = GET_PRIV (list);
 
-       handle = gossip_contact_get_handle (contact);
-       gossip_telepathy_group_remove_member (priv->subscribe, handle, message);
-       gossip_telepathy_group_remove_member (priv->publish, handle, message);
+       handle = empathy_contact_get_handle (contact);
+       empathy_tp_group_remove_member (priv->subscribe, handle, message);
 }
 
 static GList *
 tp_contact_list_get_members (EmpathyContactList *list)
 {
        EmpathyTpContactListPriv *priv;
-       GList                    *contacts = NULL;
 
        g_return_val_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list), NULL);
 
        priv = GET_PRIV (list);
 
-       g_hash_table_foreach (priv->contacts,
-                             (GHFunc) tp_contact_list_get_members_foreach,
-                             &contacts);
-
-       return contacts;
+       g_list_foreach (priv->members, (GFunc) g_object_ref, NULL);
+       return g_list_copy (priv->members);
 }
 
 static GList *
@@ -519,6 +532,28 @@ tp_contact_list_get_local_pending (EmpathyContactList *list)
        return g_list_copy (priv->local_pending);
 }
 
+static void
+tp_contact_list_process_pending (EmpathyContactList *list,
+                                EmpathyContact      *contact,
+                                gboolean            accept)
+{
+       EmpathyTpContactListPriv *priv;
+       guint                     handle;
+
+       g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
+       g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+
+       priv = GET_PRIV (list);
+
+       handle = empathy_contact_get_handle (contact);
+       if (accept) {
+               empathy_tp_group_add_member (priv->publish, handle, NULL);
+               empathy_tp_group_add_member (priv->subscribe, handle, NULL);
+       } else {
+               empathy_tp_group_remove_member (priv->publish, handle, NULL);
+       }
+}
+
 McAccount *
 empathy_tp_contact_list_get_account (EmpathyTpContactList *list)
 {
@@ -531,7 +566,7 @@ empathy_tp_contact_list_get_account (EmpathyTpContactList *list)
        return priv->account;
 }
 
-GossipContact *
+EmpathyContact *
 empathy_tp_contact_list_get_user (EmpathyTpContactList *list)
 {
        EmpathyTpContactListPriv *priv;
@@ -543,12 +578,12 @@ empathy_tp_contact_list_get_user (EmpathyTpContactList *list)
        return priv->user_contact;
 }
 
-GossipContact *
+EmpathyContact *
 empathy_tp_contact_list_get_from_id (EmpathyTpContactList *list,
                                     const gchar          *id)
 {
        EmpathyTpContactListPriv *priv;
-       GossipContact            *contact;
+       EmpathyContact            *contact;
        const gchar              *contact_ids[] = {id, NULL};
        GArray                   *handles;
        guint                     handle;
@@ -561,7 +596,7 @@ empathy_tp_contact_list_get_from_id (EmpathyTpContactList *list,
 
        contact = tp_contact_list_find (EMPATHY_CONTACT_LIST (list), id);
        if (contact) {
-               return contact;
+               return g_object_ref (contact);
        }
 
        /* The id is unknown, requests a new handle */
@@ -569,11 +604,11 @@ empathy_tp_contact_list_get_from_id (EmpathyTpContactList *list,
                                      TP_HANDLE_TYPE_CONTACT,
                                      contact_ids,
                                      &handles, &error)) {
-               gossip_debug (DEBUG_DOMAIN, 
+               empathy_debug (DEBUG_DOMAIN, 
                              "RequestHandle for %s failed: %s", id,
                              error ? error->message : "No error given");
                g_clear_error (&error);
-               return 0;
+               return NULL;
        }
 
        handle = g_array_index(handles, guint, 0);
@@ -582,11 +617,11 @@ empathy_tp_contact_list_get_from_id (EmpathyTpContactList *list,
        return empathy_tp_contact_list_get_from_handle (list, handle);
 }
 
-GossipContact *
+EmpathyContact *
 empathy_tp_contact_list_get_from_handle (EmpathyTpContactList *list,
                                         guint                 handle)
 {
-       GossipContact *contact;
+       EmpathyContact *contact;
        GArray        *handles;
        GList         *contacts;
 
@@ -628,7 +663,7 @@ empathy_tp_contact_list_get_from_handles (EmpathyTpContactList *list,
        /* Search all handles we already have */
        new_handles = g_array_new (FALSE, FALSE, sizeof (guint));
        for (i = 0; i < handles->len; i++) {
-               GossipContact *contact;
+               EmpathyContact *contact;
                guint          handle;
 
                handle = g_array_index (handles, guint, i);
@@ -658,7 +693,7 @@ empathy_tp_contact_list_get_from_handles (EmpathyTpContactList *list,
        if (!tp_conn_hold_handles (DBUS_G_PROXY (priv->tp_conn),
                                   TP_HANDLE_TYPE_CONTACT,
                                   new_handles, &error)) {
-               gossip_debug (DEBUG_DOMAIN, 
+               empathy_debug (DEBUG_DOMAIN, 
                              "HoldHandles Error: %s",
                              error ? error->message : "No error given");
                g_clear_error (&error);
@@ -672,7 +707,7 @@ empathy_tp_contact_list_get_from_handles (EmpathyTpContactList *list,
                                      new_handles,
                                      &handles_names,
                                      &error)) {
-               gossip_debug (DEBUG_DOMAIN, 
+               empathy_debug (DEBUG_DOMAIN, 
                              "InspectHandle Error: %s",
                              error ? error->message : "No error given");
                g_clear_error (&error);
@@ -682,25 +717,29 @@ empathy_tp_contact_list_get_from_handles (EmpathyTpContactList *list,
 
        /* Create contact objects */
        for (i = 0, id = handles_names; *id && i < new_handles->len; id++, i++) {
-               GossipContact *contact;
-               guint          handle;
+               EmpathyContact *contact;
+               guint           handle;
 
                handle = g_array_index (new_handles, guint, i);
-               contact = g_object_new (GOSSIP_TYPE_CONTACT,
+               contact = g_object_new (EMPATHY_TYPE_CONTACT,
                                        "account", priv->account,
                                        "id", *id,
                                        "handle", handle,
                                        NULL);
 
+               if (priv->protocol_group) {
+                       empathy_contact_add_group (contact, priv->protocol_group);
+               }
+
                if (!priv->presence_iface) {
-                       GossipPresence *presence;
+                       EmpathyPresence *presence;
 
                        /* We have no presence iface, set default presence
                         * to available */
-                       presence = gossip_presence_new_full (MC_PRESENCE_AVAILABLE,
+                       presence = empathy_presence_new_full (MC_PRESENCE_AVAILABLE,
                                                             NULL);
 
-                       gossip_contact_set_presence (contact, presence);
+                       empathy_contact_set_presence (contact, presence);
                        g_object_unref (presence);
                }
 
@@ -711,7 +750,7 @@ empathy_tp_contact_list_get_from_handles (EmpathyTpContactList *list,
                                  G_CALLBACK (tp_contact_list_name_updated_cb),
                                  list);
 
-               gossip_debug (DEBUG_DOMAIN, "new contact created: %s (%d)",
+               empathy_debug (DEBUG_DOMAIN, "new contact created: %s (%d)",
                              *id, handle);
 
                g_hash_table_insert (priv->contacts,
@@ -735,7 +774,7 @@ empathy_tp_contact_list_rename_group (EmpathyTpContactList *list,
                                      const gchar          *new_group)
 {
        EmpathyTpContactListPriv *priv;
-       GossipTelepathyGroup     *group;
+       EmpathyTpGroup           *group;
        GArray                   *members;
 
        g_return_if_fail (EMPATHY_IS_TP_CONTACT_LIST (list));
@@ -752,22 +791,22 @@ empathy_tp_contact_list_rename_group (EmpathyTpContactList *list,
                return;
        }
 
-       gossip_debug (DEBUG_DOMAIN, "rename group %s to %s", group, new_group);
+       empathy_debug (DEBUG_DOMAIN, "rename group %s to %s", group, new_group);
 
        /* Remove all members from the old group */
-       members = gossip_telepathy_group_get_members (group);
-       gossip_telepathy_group_remove_members (group, members, "");
+       members = empathy_tp_group_get_members (group);
+       empathy_tp_group_remove_members (group, members, "");
        tp_contact_list_group_members_removed_cb (group, members, 
-                                              0, 
-                                              TP_CHANNEL_GROUP_CHANGE_REASON_NONE, 
-                                              NULL, list);
+                                                 0, 
+                                                 TP_CHANNEL_GROUP_CHANGE_REASON_NONE, 
+                                                 NULL, list);
        g_hash_table_remove (priv->groups,
-                            gossip_telepathy_group_get_object_path (group));
+                            empathy_tp_group_get_object_path (group));
 
        /* Add all members to the new group */
        group = tp_contact_list_get_group (list, new_group);
        if (group) {
-               gossip_telepathy_group_add_members (group, members, "");
+               empathy_tp_group_add_members (group, members, "");
        }
 }
 
@@ -836,7 +875,7 @@ tp_contact_list_destroy_cb (DBusGProxy           *proxy,
 
        priv = GET_PRIV (list);
 
-       gossip_debug (DEBUG_DOMAIN, "Connection destroyed... "
+       empathy_debug (DEBUG_DOMAIN, "Connection destroyed... "
                      "Account disconnected or CM crashed");
 
        /* DBus proxies should NOT be used anymore */
@@ -858,7 +897,7 @@ tp_contact_list_destroy_cb (DBusGProxy           *proxy,
 
 static void
 tp_contact_list_contact_removed_foreach (guint                 handle,
-                                        GossipContact        *contact,
+                                        EmpathyContact        *contact,
                                         EmpathyTpContactList *list)
 {
        g_signal_handlers_disconnect_by_func (contact,
@@ -873,7 +912,7 @@ tp_contact_list_contact_removed_foreach (guint                 handle,
 
 static void
 tp_contact_list_block_contact (EmpathyTpContactList *list,
-                              GossipContact        *contact)
+                              EmpathyContact        *contact)
 {
        g_signal_handlers_block_by_func (contact,
                                         tp_contact_list_groups_updated_cb,
@@ -885,7 +924,7 @@ tp_contact_list_block_contact (EmpathyTpContactList *list,
 
 static void
 tp_contact_list_unblock_contact (EmpathyTpContactList *list,
-                                GossipContact        *contact)
+                                EmpathyContact        *contact)
 {
        g_signal_handlers_unblock_by_func (contact,
                                           tp_contact_list_groups_updated_cb,
@@ -897,10 +936,10 @@ tp_contact_list_unblock_contact (EmpathyTpContactList *list,
 
 static gboolean
 tp_contact_list_find_foreach (guint          handle,
-                             GossipContact *contact,
+                             EmpathyContact *contact,
                              gchar         *id)
 {
-       if (strcmp (gossip_contact_get_id (contact), id) == 0) {
+       if (strcmp (empathy_contact_get_id (contact), id) == 0) {
                return TRUE;
        }
 
@@ -917,7 +956,7 @@ tp_contact_list_newchannel_cb (DBusGProxy           *proxy,
                               EmpathyTpContactList *list)
 {
        EmpathyTpContactListPriv *priv;
-       GossipTelepathyGroup     *group;
+       EmpathyTpGroup           *group;
        TpChan                   *new_chan;
        const gchar              *bus_name;
        GArray                   *members;
@@ -939,19 +978,19 @@ tp_contact_list_newchannel_cb (DBusGProxy           *proxy,
        if (handle_type == TP_HANDLE_TYPE_LIST) {
                TpContactListType list_type;
 
-               group = gossip_telepathy_group_new (new_chan, priv->tp_conn);
+               group = empathy_tp_group_new (priv->account, new_chan);
 
                list_type = tp_contact_list_get_type (list, group);
                if (list_type == TP_CONTACT_LIST_TYPE_UNKNOWN) {
-                       gossip_debug (DEBUG_DOMAIN,
+                       empathy_debug (DEBUG_DOMAIN,
                                      "Type of contact list channel unknown: %s",
-                                     gossip_telepathy_group_get_name (group));
+                                     empathy_tp_group_get_name (group));
 
                        g_object_unref (new_chan);
                        g_object_unref (group);
                        return;
                } else {
-                       gossip_debug (DEBUG_DOMAIN,
+                       empathy_debug (DEBUG_DOMAIN,
                                      "New contact list channel of type: %d",
                                      list_type);
                }
@@ -963,12 +1002,6 @@ tp_contact_list_newchannel_cb (DBusGProxy           *proxy,
                                  G_CALLBACK (tp_contact_list_removed_cb),
                                  list);
 
-               members = gossip_telepathy_group_get_members (group);
-               tp_contact_list_added_cb (group, members, 0,
-                                         TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
-                                         NULL, list);
-               g_array_free (members, TRUE);
-
                if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
                        GList *pendings, *l;
 
@@ -982,13 +1015,13 @@ tp_contact_list_newchannel_cb (DBusGProxy           *proxy,
                                          G_CALLBACK (tp_contact_list_pending_cb),
                                          list);
 
-                       pendings = gossip_telepathy_group_get_local_pending_members_with_info (group);
+                       pendings = empathy_tp_group_get_local_pending_members_with_info (group);
                        if (pendings) {
                                GArray *pending;
 
                                pending = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1);
                                for (l = pendings; l; l = l->next) {
-                                       GossipTpGroupInfo *info;
+                                       EmpathyTpGroupInfo *info;
 
                                        info = l->data;
 
@@ -1000,17 +1033,39 @@ tp_contact_list_newchannel_cb (DBusGProxy           *proxy,
                                                                    list);
                                }
                                g_array_free (pending, TRUE);
-                               gossip_telepathy_group_info_list_free (pendings);
+                               empathy_tp_group_info_list_free (pendings);
                        }
                }
-               else if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
+               if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
+                       GArray *remote_pendings = NULL;
+
                        if (priv->subscribe) {
                                g_object_unref (priv->subscribe);
                        }
                        priv->subscribe = group;
+
+                       /* Makes no sense to be in local-pending */
+                       g_signal_connect (group, "remote-pending",
+                                         G_CALLBACK (tp_contact_list_pending_cb),
+                                         list);
+                       empathy_tp_group_get_all_members (group,
+                                                         &members,
+                                                         NULL,
+                                                         &remote_pendings);
+
+                       tp_contact_list_pending_cb (group, remote_pendings, 0,
+                                                   TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
+                                                   NULL,
+                                                   list);
+                       g_array_free (remote_pendings, TRUE);
                } else {
-                       g_assert_not_reached ();
+                       members = empathy_tp_group_get_members (group);
                }
+
+               tp_contact_list_added_cb (group, members, 0,
+                                         TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
+                                         NULL, list);
+               g_array_free (members, TRUE);
        }
        else if (handle_type == TP_HANDLE_TYPE_GROUP) {
                const gchar *object_path;
@@ -1021,10 +1076,10 @@ tp_contact_list_newchannel_cb (DBusGProxy           *proxy,
                        return;
                }
 
-               group = gossip_telepathy_group_new (new_chan, priv->tp_conn);
+               group = empathy_tp_group_new (priv->account, new_chan);
 
-               gossip_debug (DEBUG_DOMAIN, "New server-side group channel: %s",
-                             gossip_telepathy_group_get_name (group));
+               empathy_debug (DEBUG_DOMAIN, "New server-side group channel: %s",
+                             empathy_tp_group_get_name (group));
 
                dbus_g_proxy_connect_signal (DBUS_G_PROXY (new_chan), "Closed",
                                             G_CALLBACK
@@ -1039,10 +1094,10 @@ tp_contact_list_newchannel_cb (DBusGProxy           *proxy,
                                  G_CALLBACK (tp_contact_list_group_members_removed_cb),
                                  list);
 
-               members = gossip_telepathy_group_get_members (group);
+               members = empathy_tp_group_get_members (group);
                tp_contact_list_group_members_added_cb (group, members, 0,
-                                                    TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
-                                                    NULL, list);
+                                                       TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
+                                                       NULL, list);
                g_array_free (members, TRUE);
        }
 
@@ -1051,15 +1106,15 @@ tp_contact_list_newchannel_cb (DBusGProxy           *proxy,
 
 static TpContactListType
 tp_contact_list_get_type (EmpathyTpContactList *list,
-                         GossipTelepathyGroup *group)
+                         EmpathyTpGroup       *group)
 {
-       EmpathyTpContactListPriv  *priv;
-       TpContactListType          list_type;
-       const gchar               *name;
+       EmpathyTpContactListPriv *priv;
+       TpContactListType         list_type;
+       const gchar              *name;
 
        priv = GET_PRIV (list);
 
-       name = gossip_telepathy_group_get_name (group);
+       name = empathy_tp_group_get_name (group);
        if (strcmp (name, "subscribe") == 0) {
                list_type = TP_CONTACT_LIST_TYPE_SUBSCRIBE;
        } else if (strcmp (name, "publish") == 0) {
@@ -1072,7 +1127,7 @@ tp_contact_list_get_type (EmpathyTpContactList *list,
 }
 
 static void
-tp_contact_list_added_cb (GossipTelepathyGroup *group,
+tp_contact_list_added_cb (EmpathyTpGroup       *group,
                          GArray               *handles,
                          guint                 actor_handle,
                          guint                 reason,
@@ -1089,30 +1144,34 @@ tp_contact_list_added_cb (GossipTelepathyGroup *group,
 
        added_list = empathy_tp_contact_list_get_from_handles (list, handles);
        for (l = added_list; l; l = l->next) {
-               GossipContact      *contact;
-               GossipSubscription  subscription;
+               EmpathyContact      *contact;
+               EmpathySubscription  subscription;
 
-               contact = GOSSIP_CONTACT (l->data);
+               contact = EMPATHY_CONTACT (l->data);
 
-               gossip_debug (DEBUG_DOMAIN, "Contact '%s' added to list type %d",
-                             gossip_contact_get_name (contact),
+               empathy_debug (DEBUG_DOMAIN, "Contact '%s' added to list type %d",
+                             empathy_contact_get_name (contact),
                              list_type);
 
-               subscription = gossip_contact_get_subscription (contact);
+               subscription = empathy_contact_get_subscription (contact);
                if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
-                       subscription |= GOSSIP_SUBSCRIPTION_FROM;
+                       subscription |= EMPATHY_SUBSCRIPTION_FROM;
                }
                else if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
-                       subscription |= GOSSIP_SUBSCRIPTION_TO;
+                       subscription |= EMPATHY_SUBSCRIPTION_TO;
+                       tp_contact_list_remove_local_pending (list, contact);
                }
 
                tp_contact_list_block_contact (list, contact);
-               gossip_contact_set_subscription (contact, subscription);
+               empathy_contact_set_subscription (contact, subscription);
                tp_contact_list_unblock_contact (list, contact);
 
-               if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
-                       tp_contact_list_remove_local_pending (list, contact);
-                       g_signal_emit_by_name (list, "contact-added", contact);
+               if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
+                       if (!g_list_find (priv->members, contact)) {
+                               priv->members = g_list_prepend (priv->members,
+                                                               g_object_ref (contact));
+                               g_signal_emit_by_name (list, "contact-added", contact);
+                       }
                }
 
                g_object_unref (contact);
@@ -1122,7 +1181,7 @@ tp_contact_list_added_cb (GossipTelepathyGroup *group,
 }
 
 static void
-tp_contact_list_removed_cb (GossipTelepathyGroup *group,
+tp_contact_list_removed_cb (EmpathyTpGroup       *group,
                            GArray               *handles,
                            guint                 actor_handle,
                            guint                 reason,
@@ -1139,30 +1198,36 @@ tp_contact_list_removed_cb (GossipTelepathyGroup *group,
 
        removed_list = empathy_tp_contact_list_get_from_handles (list, handles);
        for (l = removed_list; l; l = l->next) {
-               GossipContact      *contact;
-               GossipSubscription  subscription;
+               EmpathyContact      *contact;
+               EmpathySubscription  subscription;
 
-               contact = GOSSIP_CONTACT (l->data);
+               contact = EMPATHY_CONTACT (l->data);
 
-               gossip_debug (DEBUG_DOMAIN, "Contact '%s' removed from list type %d",
-                             gossip_contact_get_name (contact),
+               empathy_debug (DEBUG_DOMAIN, "Contact '%s' removed from list type %d",
+                             empathy_contact_get_name (contact),
                              list_type);
 
-               subscription = gossip_contact_get_subscription (contact);
+               subscription = empathy_contact_get_subscription (contact);
                if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
-                       subscription &= !GOSSIP_SUBSCRIPTION_FROM;
+                       subscription &= !EMPATHY_SUBSCRIPTION_FROM;
                }
                else if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
-                       subscription &= !GOSSIP_SUBSCRIPTION_TO;
+                       subscription &= !EMPATHY_SUBSCRIPTION_TO;
+                       tp_contact_list_remove_local_pending (list, contact);
                }
 
                tp_contact_list_block_contact (list, contact);
-               gossip_contact_set_subscription (contact, subscription);
+               empathy_contact_set_subscription (contact, subscription);
                tp_contact_list_unblock_contact (list, contact);
 
-               if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
-                       tp_contact_list_remove_local_pending (list, contact);
-                       g_signal_emit_by_name (list, "contact-removed", contact);
+               if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
+                       GList *l;
+
+                       if ((l = g_list_find (priv->members, contact))) {
+                               g_signal_emit_by_name (list, "contact-removed", contact);
+                               priv->members = g_list_delete_link (priv->members, l);
+                               g_object_unref (contact);
+                       }
                }
                g_object_unref (contact);
        }
@@ -1171,7 +1236,7 @@ tp_contact_list_removed_cb (GossipTelepathyGroup *group,
 }
 
 static void
-tp_contact_list_pending_cb (GossipTelepathyGroup *group,
+tp_contact_list_pending_cb (EmpathyTpGroup       *group,
                            GArray               *handles,
                            guint                 actor_handle,
                            guint                 reason,
@@ -1188,23 +1253,41 @@ tp_contact_list_pending_cb (GossipTelepathyGroup *group,
 
        pending_list = empathy_tp_contact_list_get_from_handles (list, handles);
        for (l = pending_list; l; l = l->next) {
-               GossipContact *contact;
+               EmpathyContact *contact;
 
-               contact = GOSSIP_CONTACT (l->data);
+               contact = EMPATHY_CONTACT (l->data);
 
-               gossip_debug (DEBUG_DOMAIN, "Contact '%s' pending in list type %d",
-                             gossip_contact_get_name (contact),
+               empathy_debug (DEBUG_DOMAIN, "Contact '%s' pending in list type %d",
+                             empathy_contact_get_name (contact),
                              list_type);
 
                if (list_type == TP_CONTACT_LIST_TYPE_PUBLISH) {
-                       EmpathyContactListInfo *info;
-
-                       info = empathy_contact_list_info_new (contact, message);
-                       priv->local_pending = g_list_prepend (priv->local_pending,
-                                                             info);
-
-                       g_signal_emit_by_name (list, "local-pending",
-                                              contact, message);
+                       if (!g_list_find (priv->members, contact)) {
+                               EmpathyContactListInfo *info;
+
+                               info = empathy_contact_list_info_new (contact, message);
+                               priv->local_pending = g_list_prepend (priv->local_pending,
+                                                                     info);
+
+                               g_signal_emit_by_name (list, "local-pending",
+                                                      contact, message);
+                       } else {
+                               guint handle;
+
+                               /* That contact wants our presence and he is
+                                * in our roster. Accept to publish our presence
+                                * without asking the user. */
+                               handle = empathy_contact_get_handle (contact);
+                               empathy_tp_group_add_member (priv->publish,
+                                                            handle, "");
+                       }
+               }
+               else if (list_type == TP_CONTACT_LIST_TYPE_SUBSCRIBE) {
+                       if (!g_list_find (priv->members, contact)) {
+                               priv->members = g_list_prepend (priv->members,
+                                                               g_object_ref (contact));
+                               g_signal_emit_by_name (list, "contact-added", contact);
+                       }
                }
 
                g_object_unref (contact);
@@ -1215,7 +1298,7 @@ tp_contact_list_pending_cb (GossipTelepathyGroup *group,
 
 static void
 tp_contact_list_remove_local_pending (EmpathyTpContactList *list,
-                                     GossipContact        *contact)
+                                     EmpathyContact        *contact)
 {
        EmpathyTpContactListPriv *priv;
        GList                    *l;
@@ -1226,9 +1309,9 @@ tp_contact_list_remove_local_pending (EmpathyTpContactList *list,
                EmpathyContactListInfo *info;
 
                info = l->data;
-               if (gossip_contact_equal (contact, info->contact)) {
-                       gossip_debug (DEBUG_DOMAIN, "Contact no more local-pending: %s",
-                                     gossip_contact_get_name (contact));
+               if (empathy_contact_equal (contact, info->contact)) {
+                       empathy_debug (DEBUG_DOMAIN, "Contact no more local-pending: %s",
+                                     empathy_contact_get_name (contact));
 
                        priv->local_pending = g_list_delete_link (priv->local_pending, l);
                        empathy_contact_list_info_free (info);
@@ -1238,7 +1321,7 @@ tp_contact_list_remove_local_pending (EmpathyTpContactList *list,
 }
 
 static void
-tp_contact_list_groups_updated_cb (GossipContact        *contact,
+tp_contact_list_groups_updated_cb (EmpathyContact       *contact,
                                   GParamSpec           *param,
                                   EmpathyTpContactList *list)
 {
@@ -1249,12 +1332,12 @@ tp_contact_list_groups_updated_cb (GossipContact        *contact,
        priv = GET_PRIV (list);
 
        /* Make sure all groups are created */
-       groups = gossip_contact_get_groups (contact);
+       groups = empathy_contact_get_groups (contact);
        for (l = groups; l; l = l->next) {
                tp_contact_list_get_group (list, l->data);
        }
 
-       data.handle = gossip_contact_get_handle (contact);
+       data.handle = empathy_contact_get_handle (contact);
        data.new_groups = groups;
 
        g_hash_table_foreach (priv->groups,
@@ -1263,7 +1346,7 @@ tp_contact_list_groups_updated_cb (GossipContact        *contact,
 }
 
 static void
-tp_contact_list_name_updated_cb (GossipContact        *contact,
+tp_contact_list_name_updated_cb (EmpathyContact        *contact,
                                 GParamSpec           *param,
                                 EmpathyTpContactList *list)
 {
@@ -1275,10 +1358,14 @@ tp_contact_list_name_updated_cb (GossipContact        *contact,
 
        priv = GET_PRIV (list);
        
-       handle = gossip_contact_get_handle (contact);
-       new_name = gossip_contact_get_name (contact);
+       if (!priv->aliasing_iface) {
+               return;
+       }
 
-       gossip_debug (DEBUG_DOMAIN, "renaming handle %d to %s",
+       handle = empathy_contact_get_handle (contact);
+       new_name = empathy_contact_get_name (contact);
+
+       empathy_debug (DEBUG_DOMAIN, "renaming handle %d to %s",
                      handle, new_name);
 
        new_alias = g_hash_table_new_full (g_direct_hash,
@@ -1293,7 +1380,7 @@ tp_contact_list_name_updated_cb (GossipContact        *contact,
        if (!tp_conn_iface_aliasing_set_aliases (priv->aliasing_iface,
                                                 new_alias,
                                                 &error)) {
-               gossip_debug (DEBUG_DOMAIN, 
+               empathy_debug (DEBUG_DOMAIN, 
                              "Couldn't rename contact: %s",
                              error ? error->message : "No error given");
                g_clear_error (&error);
@@ -1303,17 +1390,17 @@ tp_contact_list_name_updated_cb (GossipContact        *contact,
 }
 
 static void
-tp_contact_list_update_groups_foreach (gchar                *object_path,
-                                      GossipTelepathyGroup *group,
-                                      TpContactListData    *data)
+tp_contact_list_update_groups_foreach (gchar             *object_path,
+                                      EmpathyTpGroup    *group,
+                                      TpContactListData *data)
 {
        gboolean     is_member;
        gboolean     found = FALSE;
        const gchar *group_name;
        GList       *l;
 
-       is_member = gossip_telepathy_group_is_member (group, data->handle);
-       group_name = gossip_telepathy_group_get_name (group);
+       is_member = empathy_tp_group_is_member (group, data->handle);
+       group_name = empathy_tp_group_get_name (group);
 
        for (l = data->new_groups; l; l = l->next) {
                if (strcmp (group_name, l->data) == 0) {
@@ -1324,25 +1411,25 @@ tp_contact_list_update_groups_foreach (gchar                *object_path,
 
        if (is_member && !found) {
                /* We are no longer member of this group */
-               gossip_debug (DEBUG_DOMAIN, "Contact %d removed from group '%s'",
+               empathy_debug (DEBUG_DOMAIN, "Contact %d removed from group '%s'",
                              data->handle, group_name);
-               gossip_telepathy_group_remove_member (group, data->handle, "");
+               empathy_tp_group_remove_member (group, data->handle, "");
        }
 
        if (!is_member && found) {
                /* We are now member of this group */
-               gossip_debug (DEBUG_DOMAIN, "Contact %d added to group '%s'",
+               empathy_debug (DEBUG_DOMAIN, "Contact %d added to group '%s'",
                              data->handle, group_name);
-               gossip_telepathy_group_add_member (group, data->handle, "");
+               empathy_tp_group_add_member (group, data->handle, "");
        }
 }
 
-static GossipTelepathyGroup *
+static EmpathyTpGroup *
 tp_contact_list_get_group (EmpathyTpContactList *list,
                           const gchar          *name)
 {
        EmpathyTpContactListPriv *priv;
-       GossipTelepathyGroup     *group;
+       EmpathyTpGroup           *group;
        TpChan                   *group_channel;
        GArray                   *handles;
        guint                     group_handle;
@@ -1359,14 +1446,14 @@ tp_contact_list_get_group (EmpathyTpContactList *list,
                return group;
        }
 
-       gossip_debug (DEBUG_DOMAIN, "creating new group: %s", name);
+       empathy_debug (DEBUG_DOMAIN, "creating new group: %s", name);
 
        if (!tp_conn_request_handles (DBUS_G_PROXY (priv->tp_conn),
                                      TP_HANDLE_TYPE_GROUP,
                                      names,
                                      &handles,
                                      &error)) {
-               gossip_debug (DEBUG_DOMAIN,
+               empathy_debug (DEBUG_DOMAIN,
                              "Couldn't request the creation of a new handle for group: %s",
                              error ? error->message : "No error given");
                g_clear_error (&error);
@@ -1382,7 +1469,7 @@ tp_contact_list_get_group (EmpathyTpContactList *list,
                                      FALSE,
                                      &group_object_path,
                                      &error)) {
-               gossip_debug (DEBUG_DOMAIN,
+               empathy_debug (DEBUG_DOMAIN,
                              "Couldn't request the creation of a new group channel: %s",
                              error ? error->message : "No error given");
                g_clear_error (&error);
@@ -1403,7 +1490,7 @@ tp_contact_list_get_group (EmpathyTpContactList *list,
                                     list,
                                     NULL);
 
-       group = gossip_telepathy_group_new (group_channel, priv->tp_conn);
+       group = empathy_tp_group_new (priv->account, group_channel);
        g_hash_table_insert (priv->groups, group_object_path, group);
        g_signal_connect (group, "members-added",
                          G_CALLBACK (tp_contact_list_group_members_added_cb),
@@ -1416,11 +1503,11 @@ tp_contact_list_get_group (EmpathyTpContactList *list,
 }
 
 static gboolean
-tp_contact_list_find_group (gchar                 *key,
-                           GossipTelepathyGroup  *group,
-                           gchar                 *group_name)
+tp_contact_list_find_group (gchar          *key,
+                           EmpathyTpGroup *group,
+                           gchar          *group_name)
 {
-       if (strcmp (group_name, gossip_telepathy_group_get_name (group)) == 0) {
+       if (strcmp (group_name, empathy_tp_group_get_name (group)) == 0) {
                return TRUE;
        }
 
@@ -1428,13 +1515,13 @@ tp_contact_list_find_group (gchar                 *key,
 }
 
 static void
-tp_contact_list_get_groups_foreach (gchar                 *key,
-                                   GossipTelepathyGroup  *group,
-                                   GList                **groups)
+tp_contact_list_get_groups_foreach (gchar          *key,
+                                   EmpathyTpGroup *group,
+                                   GList          **groups)
 {
        const gchar *name;
 
-       name = gossip_telepathy_group_get_name (group);
+       name = empathy_tp_group_get_name (group);
        *groups = g_list_append (*groups, g_strdup (name));
 }
 
@@ -1451,7 +1538,7 @@ tp_contact_list_group_channel_closed_cb (TpChan             *channel,
 }
 
 static void
-tp_contact_list_group_members_added_cb (GossipTelepathyGroup *group,
+tp_contact_list_group_members_added_cb (EmpathyTpGroup       *group,
                                        GArray               *members,
                                        guint                 actor_handle,
                                        guint                 reason,
@@ -1464,29 +1551,17 @@ tp_contact_list_group_members_added_cb (GossipTelepathyGroup *group,
 
        priv = GET_PRIV (list);
 
-       group_name = gossip_telepathy_group_get_name (group);
+       group_name = empathy_tp_group_get_name (group);
        added_list = empathy_tp_contact_list_get_from_handles (list, members);
 
        for (l = added_list; l; l = l->next) {
-               GossipContact *contact;
-               GList         *contact_groups;
-
-               contact = GOSSIP_CONTACT (l->data);
-               contact_groups = gossip_contact_get_groups (contact);
-
-               /* FIXME: this leaks */
-               if (!g_list_find_custom (contact_groups,
-                                        group_name,
-                                        (GCompareFunc) strcmp)) {
-                       gossip_debug (DEBUG_DOMAIN, "Contact %s added to group '%s'",
-                                     gossip_contact_get_name (contact),
-                                     group_name);
-                       contact_groups = g_list_append (contact_groups,
-                                                       g_strdup (group_name));
-                       tp_contact_list_block_contact (list, contact);
-                       gossip_contact_set_groups (contact, contact_groups);
-                       tp_contact_list_unblock_contact (list, contact);
-               }
+               EmpathyContact *contact;
+
+               contact = EMPATHY_CONTACT (l->data);
+
+               tp_contact_list_block_contact (list, contact);
+               empathy_contact_add_group (contact, group_name);
+               tp_contact_list_unblock_contact (list, contact);
 
                g_object_unref (contact);
        }
@@ -1495,7 +1570,7 @@ tp_contact_list_group_members_added_cb (GossipTelepathyGroup *group,
 }
 
 static void
-tp_contact_list_group_members_removed_cb (GossipTelepathyGroup *group,
+tp_contact_list_group_members_removed_cb (EmpathyTpGroup       *group,
                                          GArray               *members,
                                          guint                 actor_handle,
                                          guint                 reason,
@@ -1508,34 +1583,17 @@ tp_contact_list_group_members_removed_cb (GossipTelepathyGroup *group,
 
        priv = GET_PRIV (list);
 
-       group_name = gossip_telepathy_group_get_name (group);
+       group_name = empathy_tp_group_get_name (group);
        removed_list = empathy_tp_contact_list_get_from_handles (list, members);
 
        for (l = removed_list; l; l = l->next) {
-               GossipContact *contact;
-               GList         *contact_groups;
-               GList         *to_remove;
-
-               /* FIXME: Does it leak ? */
-               contact = GOSSIP_CONTACT (l->data);
-               contact_groups = gossip_contact_get_groups (contact);
-               contact_groups = g_list_copy (contact_groups);
-
-               to_remove = g_list_find_custom (contact_groups,
-                                               group_name,
-                                               (GCompareFunc) strcmp);
-               if (to_remove) {
-                       gossip_debug (DEBUG_DOMAIN, "Contact %d removed from group '%s'",
-                                     gossip_contact_get_handle (contact),
-                                     group_name);
-                       contact_groups = g_list_remove_link (contact_groups,
-                                                            to_remove);
-                       tp_contact_list_block_contact (list, contact);
-                       gossip_contact_set_groups (contact, contact_groups);
-                       tp_contact_list_unblock_contact (list, contact);
-               }
+               EmpathyContact *contact;
 
-               g_list_free (contact_groups);
+               contact = l->data;
+
+               tp_contact_list_block_contact (list, contact);
+               empathy_contact_remove_group (contact, group_name);
+               tp_contact_list_unblock_contact (list, contact);
 
                g_object_unref (contact);
        }
@@ -1543,19 +1601,6 @@ tp_contact_list_group_members_removed_cb (GossipTelepathyGroup *group,
        g_list_free (removed_list);
 }
 
-static void
-tp_contact_list_get_members_foreach (guint           handle,
-                                     GossipContact  *contact,
-                                     GList         **contacts)
-{
-       GossipSubscription subscription;
-
-       subscription = gossip_contact_get_subscription (contact);
-       if (subscription & GOSSIP_SUBSCRIPTION_TO) {
-               *contacts = g_list_append (*contacts, g_object_ref (contact));
-       }
-}
-
 static void
 tp_contact_list_get_info (EmpathyTpContactList *list,
                          GArray               *handles)
@@ -1569,7 +1614,7 @@ tp_contact_list_get_info (EmpathyTpContactList *list,
                /* FIXME: We should use GetPresence instead */
                if (!tp_conn_iface_presence_request_presence (priv->presence_iface,
                                                              handles, &error)) {
-                       gossip_debug (DEBUG_DOMAIN, 
+                       empathy_debug (DEBUG_DOMAIN, 
                                      "Could not request presences: %s",
                                      error ? error->message : "No error given");
                        g_clear_error (&error);
@@ -1606,36 +1651,39 @@ static void
 tp_contact_list_request_avatar (EmpathyTpContactList *list,
                                guint                 handle)
 {
-       EmpathyTpContactListPriv *priv;
+       EmpathyTpContactListPriv       *priv;
+       TpContactListAvatarRequestData *data;
 
        priv = GET_PRIV (list);
        
        /* We queue avatar requests to not send too many dbus async
         * calls at once. If we don't we reach the dbus's limit of
         * pending calls */
-       priv->avatar_requests_queue = g_list_append (priv->avatar_requests_queue,
-                                                    GUINT_TO_POINTER (handle));
-       tp_contact_list_start_avatar_requests (list);
+       data = g_slice_new (TpContactListAvatarRequestData);
+       data->list = g_object_ref (list);
+       data->handle = handle;
+       avatar_requests_queue = g_list_append (avatar_requests_queue, data);
+       tp_contact_list_start_avatar_requests ();
 }
 
 static void
-tp_contact_list_start_avatar_requests (EmpathyTpContactList *list)
+tp_contact_list_start_avatar_requests (void)
 {
-       EmpathyTpContactListPriv       *priv;
-       TpContactListAvatarRequestData *data;
+       empathy_debug (DEBUG_DOMAIN, "Start avatar requests, pending calls: %d",
+                      n_avatar_requests);
 
-       priv = GET_PRIV (list);
+       while (n_avatar_requests <  MAX_AVATAR_REQUESTS && avatar_requests_queue) {
+               EmpathyTpContactListPriv       *priv;
+               TpContactListAvatarRequestData *data;
 
-       while (n_avatar_requests <  MAX_AVATAR_REQUESTS &&
-              priv->avatar_requests_queue) {
-               data = g_slice_new (TpContactListAvatarRequestData);
-               data->list = list;
-               data->handle = GPOINTER_TO_UINT (priv->avatar_requests_queue->data);
+               data = avatar_requests_queue->data;
+               priv = GET_PRIV (data->list);
 
                n_avatar_requests++;
-               priv->avatar_requests_queue = g_list_remove (priv->avatar_requests_queue,
-                                                            priv->avatar_requests_queue->data);
+               avatar_requests_queue = g_list_delete_link (avatar_requests_queue,
+                                                           avatar_requests_queue);
 
+               empathy_debug (DEBUG_DOMAIN, "Calling RequestAvatar async");
                tp_conn_iface_avatars_request_avatar_async (priv->avatars_iface,
                                                            data->handle,
                                                            (tp_conn_iface_avatars_request_avatar_reply)
@@ -1659,7 +1707,7 @@ tp_contact_list_avatar_update_cb (DBusGProxy           *proxy,
                return;
        }
 
-       gossip_debug (DEBUG_DOMAIN, "Changing avatar for %d to %s",
+       empathy_debug (DEBUG_DOMAIN, "Changing avatar for %d to %s",
                      handle, new_token);
 
        tp_contact_list_request_avatar (list, handle);
@@ -1672,30 +1720,35 @@ tp_contact_list_request_avatar_cb (DBusGProxy                     *proxy,
                                   GError                         *error,
                                   TpContactListAvatarRequestData *data)
 {
-       GossipContact *contact;
+       EmpathyContact *contact;
 
        contact = empathy_tp_contact_list_get_from_handle (data->list, data->handle);
 
        if (error) {
-               gossip_debug (DEBUG_DOMAIN, "Error requesting avatar for %s: %s",
-                             gossip_contact_get_name (contact),
+               empathy_debug (DEBUG_DOMAIN, "Error requesting avatar for %s: %s",
+                             empathy_contact_get_name (contact),
                              error ? error->message : "No error given");
        } else {
-               GossipAvatar *avatar;
+               EmpathyAvatar *avatar;
+
+               empathy_debug (DEBUG_DOMAIN, "Avatar received for %s (%d)",
+                              empathy_contact_get_id (contact),
+                              data->handle);
 
-               avatar = gossip_avatar_new (avatar_data->data,
+               avatar = empathy_avatar_new (avatar_data->data,
                                            avatar_data->len,
                                            mime_type);
                tp_contact_list_block_contact (data->list, contact);
-               gossip_contact_set_avatar (contact, avatar);
+               empathy_contact_set_avatar (contact, avatar);
                tp_contact_list_unblock_contact (data->list, contact);
-               gossip_avatar_unref (avatar);
+               empathy_avatar_unref (avatar);
        }
 
        n_avatar_requests--;
-       tp_contact_list_start_avatar_requests (data->list);
+       tp_contact_list_start_avatar_requests ();
 
        g_object_unref (contact);
+       g_object_unref (data->list);
        g_slice_free (TpContactListAvatarRequestData, data);
 }
 
@@ -1713,7 +1766,7 @@ tp_contact_list_aliases_update_cb (DBusGProxy           *proxy,
                guint          handle;
                const gchar   *alias;
                GValueArray   *renamed_struct;
-               GossipContact *contact;
+               EmpathyContact *contact;
 
                renamed_struct = g_ptr_array_index (renamed_handlers, i);
                handle = g_value_get_uint(g_value_array_get_nth (renamed_struct, 0));
@@ -1730,11 +1783,11 @@ tp_contact_list_aliases_update_cb (DBusGProxy           *proxy,
 
                contact = empathy_tp_contact_list_get_from_handle (list, handle);
                tp_contact_list_block_contact (list, contact);
-               gossip_contact_set_name (contact, alias);
+               empathy_contact_set_name (contact, alias);
                tp_contact_list_unblock_contact (list, contact);
                g_object_unref (contact);
 
-               gossip_debug (DEBUG_DOMAIN, "contact %d renamed to %s (update cb)",
+               empathy_debug (DEBUG_DOMAIN, "contact %d renamed to %s (update cb)",
                              handle, alias);
        }
 }
@@ -1749,21 +1802,21 @@ tp_contact_list_request_aliases_cb (DBusGProxy                       *proxy,
        gchar **name;
 
        if (error) {
-               gossip_debug (DEBUG_DOMAIN, "Error requesting aliases: %s",
+               empathy_debug (DEBUG_DOMAIN, "Error requesting aliases: %s",
                              error->message);
        }
 
        for (name = contact_names; *name && !error; name++) {
-               GossipContact *contact;
+               EmpathyContact *contact;
 
                contact = empathy_tp_contact_list_get_from_handle (data->list,
                                                                   data->handles[i]);
                tp_contact_list_block_contact (data->list, contact);
-               gossip_contact_set_name (contact, *name);
+               empathy_contact_set_name (contact, *name);
                tp_contact_list_unblock_contact (data->list, contact);
                g_object_unref (contact);
 
-               gossip_debug (DEBUG_DOMAIN, "contact %d renamed to %s (request cb)",
+               empathy_debug (DEBUG_DOMAIN, "contact %d renamed to %s (request cb)",
                              data->handles[i], *name);
 
                i++;
@@ -1790,8 +1843,8 @@ tp_contact_list_parse_presence_foreach (guint                 handle,
 {
        EmpathyTpContactListPriv *priv;
        GHashTable     *presences_table;
-       GossipContact  *contact;
-       GossipPresence *presence = NULL;
+       EmpathyContact  *contact;
+       EmpathyPresence *presence = NULL;
 
        priv = GET_PRIV (list);
 
@@ -1807,14 +1860,14 @@ tp_contact_list_parse_presence_foreach (guint                 handle,
                              (GHFunc) tp_contact_list_presences_table_foreach,
                              &presence);
 
-       gossip_debug (DEBUG_DOMAIN, "Presence changed for %s (%d) to %s (%d)",
-                     gossip_contact_get_name (contact),
+       empathy_debug (DEBUG_DOMAIN, "Presence changed for %s (%d) to %s (%d)",
+                     empathy_contact_get_name (contact),
                      handle,
-                     presence ? gossip_presence_get_status (presence) : "unset",
-                     presence ? gossip_presence_get_state (presence) : MC_PRESENCE_UNSET);
+                     presence ? empathy_presence_get_status (presence) : "unset",
+                     presence ? empathy_presence_get_state (presence) : MC_PRESENCE_UNSET);
 
        tp_contact_list_block_contact (list, contact);
-       gossip_contact_set_presence (contact, presence);
+       empathy_contact_set_presence (contact, presence);
        tp_contact_list_unblock_contact (list, contact);
 
        g_object_unref (contact);
@@ -1823,12 +1876,12 @@ tp_contact_list_parse_presence_foreach (guint                 handle,
 static void
 tp_contact_list_presences_table_foreach (const gchar     *state_str,
                                         GHashTable      *presences_table,
-                                        GossipPresence **presence)
+                                        EmpathyPresence **presence)
 {
        McPresence    state;
        const GValue *message;
 
-       state = gossip_presence_state_from_str (state_str);
+       state = empathy_presence_state_from_str (state_str);
        if ((state == MC_PRESENCE_UNSET) || (state == MC_PRESENCE_OFFLINE)) {
                return;
        }
@@ -1838,12 +1891,12 @@ tp_contact_list_presences_table_foreach (const gchar     *state_str,
                *presence = NULL;
        }
 
-       *presence = gossip_presence_new ();
-       gossip_presence_set_state (*presence, state);
+       *presence = empathy_presence_new ();
+       empathy_presence_set_state (*presence, state);
 
        message = g_hash_table_lookup (presences_table, "message");
        if (message != NULL) {
-               gossip_presence_set_status (*presence,
+               empathy_presence_set_status (*presence,
                                            g_value_get_string (message));
        }
 }
@@ -1863,7 +1916,7 @@ tp_contact_list_status_changed_cb (MissionControl                  *mc,
 
        account = mc_account_lookup (unique_name);
        if (status != TP_CONN_STATUS_DISCONNECTED ||
-           !gossip_account_equal (account, priv->account) ||
+           !empathy_account_equal (account, priv->account) ||
            !priv->tp_conn) {
                g_object_unref (account);
                return;