summaryrefslogtreecommitdiff
path: root/telepathy-glib/contact.c
diff options
context:
space:
mode:
Diffstat (limited to 'telepathy-glib/contact.c')
-rw-r--r--telepathy-glib/contact.c280
1 files changed, 85 insertions, 195 deletions
diff --git a/telepathy-glib/contact.c b/telepathy-glib/contact.c
index 25ca59c74..0e283f064 100644
--- a/telepathy-glib/contact.c
+++ b/telepathy-glib/contact.c
@@ -1899,6 +1899,31 @@ contacts_context_fail (ContactsContext *c,
}
}
+static void contact_update_avatar_data (TpContact *self);
+
+static void
+contacts_context_last_step (ContactsContext *c)
+{
+ guint i;
+
+ g_assert (c->handles->len == c->contacts->len);
+
+ /* As last step, request avatars if we want AVATAR_DATA feature. This is done
+ * here because there is no contact attribute for that. */
+ if ((c->wanted & CONTACT_FEATURE_FLAG_AVATAR_DATA) == 0)
+ return;
+
+ for (i = 0; i < c->contacts->len; i++)
+ {
+ TpContact *contact = g_ptr_array_index (c->contacts, i);
+
+ if ((contact->priv->has_features & CONTACT_FEATURE_FLAG_AVATAR_DATA) == 0)
+ {
+ contact->priv->has_features |= CONTACT_FEATURE_FLAG_AVATAR_DATA;
+ contact_update_avatar_data (contact);
+ }
+ }
+}
static gboolean
contacts_context_complete (ContactsContext *c)
@@ -1906,6 +1931,8 @@ contacts_context_complete (ContactsContext *c)
if (c->no_purpose_in_life)
return FALSE;
+ contacts_context_last_step (c);
+
switch (c->signature)
{
case CB_BY_HANDLE:
@@ -3099,12 +3126,6 @@ tp_contact_set_attributes (TpContact *contact,
}
}
- /* There is no attribute for avatar data. If we want it, let's just
- * pretend it is ready. If avatar is in cache, that will be true as
- * soon as the token is set from attributes */
- if (wanted & CONTACT_FEATURE_FLAG_AVATAR_DATA)
- contact->priv->has_features |= CONTACT_FEATURE_FLAG_AVATAR_DATA;
-
if (wanted & CONTACT_FEATURE_FLAG_AVATAR_TOKEN)
{
s = tp_asv_get_string (asv,
@@ -3950,60 +3971,53 @@ tp_connection_get_contacts_by_id (TpConnection *self,
G_GNUC_END_IGNORE_DEPRECATIONS
}
-typedef struct
-{
- GSimpleAsyncResult *result;
- ContactFeatureFlags features;
-} ContactsAsyncData;
-
-static ContactsAsyncData *
-contacts_async_data_new (GSimpleAsyncResult *result,
- ContactFeatureFlags features)
-{
- ContactsAsyncData *data;
-
- data = g_slice_new0 (ContactsAsyncData);
- data->result = g_object_ref (result);
- data->features = features;
-
- return data;
-}
-
static void
-contacts_async_data_free (ContactsAsyncData *data)
-{
- g_object_unref (data->result);
- g_slice_free (ContactsAsyncData, data);
-}
-
-static void
-got_contact_by_id_cb (TpConnection *self,
- TpHandle handle,
- GHashTable *attributes,
+got_contact_by_id_fallback_cb (TpConnection *self,
+ guint n_contacts,
+ TpContact * const *contacts,
+ const gchar * const *requested_ids,
+ GHashTable *failed_id_errors,
const GError *error,
gpointer user_data,
GObject *weak_object)
{
- ContactsAsyncData *data = user_data;
- TpContact *contact;
+ const gchar *id = user_data;
+ GSimpleAsyncResult *result = (GSimpleAsyncResult *) weak_object;
GError *e = NULL;
if (error != NULL)
{
- g_simple_async_result_set_from_error (data->result, error);
- g_simple_async_result_complete (data->result);
- return;
+ g_simple_async_result_set_from_error (result, error);
}
+ else if (g_hash_table_size (failed_id_errors) > 0)
+ {
+ e = g_hash_table_lookup (failed_id_errors, id);
- /* set up the contact with its attributes */
- contact = tp_contact_ensure (self, handle);
- g_simple_async_result_set_op_res_gpointer (data->result,
- contact, g_object_unref);
-
- if (!tp_contact_set_attributes (contact, attributes, data->features, &e))
- g_simple_async_result_take_error (data->result, e);
+ if (e == NULL)
+ {
+ g_set_error (&e, TP_DBUS_ERRORS, TP_DBUS_ERROR_INCONSISTENT,
+ "We requested 1 id, and got an error for another id - Broken CM");
+ g_simple_async_result_take_error (result, e);
+ }
+ else
+ {
+ g_simple_async_result_set_from_error (result, e);
+ }
+ }
+ else if (n_contacts != 1 || contacts[0] == NULL)
+ {
+ g_set_error (&e, TP_DBUS_ERRORS, TP_DBUS_ERROR_INCONSISTENT,
+ "We requested 1 id, but no contacts and no error - Broken CM");
+ g_simple_async_result_take_error (result, e);
+ }
+ else
+ {
+ g_simple_async_result_set_op_res_gpointer (result,
+ g_object_ref (contacts[0]), g_object_unref);
+ }
- g_simple_async_result_complete (data->result);
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
}
/**
@@ -4036,47 +4050,18 @@ tp_connection_dup_contact_by_id_async (TpConnection *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- ContactsAsyncData *data;
GSimpleAsyncResult *result;
- ContactFeatureFlags feature_flags = 0;
- const gchar **supported_interfaces;
-
- g_return_if_fail (tp_proxy_is_prepared (self,
- TP_CONNECTION_FEATURE_CONNECTED));
- g_return_if_fail (id != NULL);
-
- if (features == NULL)
- features = no_quarks;
-
- if (!get_feature_flags (features, &feature_flags))
- return;
result = g_simple_async_result_new ((GObject *) self, callback, user_data,
tp_connection_dup_contact_by_id_async);
- data = contacts_async_data_new (result, feature_flags);
-
- if (tp_proxy_has_interface_by_id (self,
- TP_IFACE_QUARK_CONNECTION_INTERFACE_CONTACTS))
- {
- supported_interfaces = contacts_bind_to_signals (self, feature_flags);
-
- tp_cli_connection_interface_contacts_call_get_contact_by_id (self, -1,
- id, supported_interfaces, got_contact_by_id_cb,
- data, NULL, NULL);
-
- g_free (supported_interfaces);
- }
- else
- {
- g_simple_async_result_set_error (result, TP_DBUS_ERRORS,
- TP_DBUS_ERROR_NO_INTERFACE,
- "Obsolete CM does not have the Contacts interface");
- g_simple_async_result_complete_in_idle (result);
- contacts_async_data_free (data);
- }
-
- g_object_unref (result);
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ tp_connection_get_contacts_by_id (self,
+ 1, &id,
+ features,
+ got_contact_by_id_fallback_cb,
+ g_strdup (id), g_free, G_OBJECT (result));
+ G_GNUC_END_IGNORE_DEPRECATIONS
}
/**
@@ -4100,40 +4085,6 @@ tp_connection_dup_contact_by_id_finish (TpConnection *self,
}
static void
-got_contact_attributes_cb (TpConnection *self,
- GHashTable *attributes,
- const GError *error,
- gpointer user_data,
- GObject *weak_object)
-{
- ContactsAsyncData *data = user_data;
- GHashTableIter iter;
- gpointer key, value;
-
- if (error != NULL)
- {
- g_simple_async_result_set_from_error (data->result, error);
- g_simple_async_result_complete (data->result);
- return;
- }
-
- g_hash_table_iter_init (&iter, attributes);
- while (g_hash_table_iter_next (&iter, &key, &value))
- {
- TpHandle handle = GPOINTER_TO_UINT (key);
- GHashTable *asv = value;
- TpContact *contact;
-
- /* set up the contact with its attributes */
- contact = tp_contact_ensure (self, handle);
- tp_contact_set_attributes (contact, asv, data->features, NULL);
- g_object_unref (contact);
- }
-
- g_simple_async_result_complete (data->result);
-}
-
-static void
upgrade_contacts_async_fallback_cb (TpConnection *self,
guint n_contacts,
TpContact * const *contacts,
@@ -4142,6 +4093,15 @@ upgrade_contacts_async_fallback_cb (TpConnection *self,
GObject *weak_object)
{
GSimpleAsyncResult *result = user_data;
+ GPtrArray *contacts_array;
+ guint i;
+
+ contacts_array = g_ptr_array_new_full (n_contacts, g_object_unref);
+ for (i = 0; i < n_contacts; i++)
+ g_ptr_array_add (contacts_array, g_object_ref (contacts[i]));
+
+ g_simple_async_result_set_op_res_gpointer (result, contacts_array,
+ (GDestroyNotify) g_ptr_array_unref);
if (error != NULL)
g_simple_async_result_set_from_error (result, error);
@@ -4180,88 +4140,18 @@ tp_connection_upgrade_contacts_async (TpConnection *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- ContactsAsyncData *data;
GSimpleAsyncResult *result;
- ContactFeatureFlags feature_flags = 0;
- guint minimal_feature_flags = G_MAXUINT;
- const gchar **supported_interfaces;
- GPtrArray *contacts_array;
- GArray *handles;
- guint i;
-
- g_return_if_fail (tp_proxy_is_prepared (self,
- TP_CONNECTION_FEATURE_CONNECTED));
- g_return_if_fail (n_contacts >= 1);
- g_return_if_fail (contacts != NULL);
-
- for (i = 0; i < n_contacts; i++)
- {
- g_return_if_fail (contacts[i]->priv->connection == self);
- g_return_if_fail (contacts[i]->priv->identifier != NULL);
- }
-
- if (features == NULL)
- features = no_quarks;
-
- if (!get_feature_flags (features, &feature_flags))
- return;
-
- handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), n_contacts);
- contacts_array = g_ptr_array_new_full (n_contacts, g_object_unref);
- for (i = 0; i < n_contacts; i++)
- {
- /* feature flags that all contacts have */
- minimal_feature_flags &= contacts[i]->priv->has_features;
-
- /* Keep handles of contacts that does not already have all features */
- if ((feature_flags & (~contacts[i]->priv->has_features)) != 0)
- g_array_append_val (handles, contacts[i]->priv->handle);
-
- /* Keep a ref on all contacts to ensure they do not disappear
- * while upgrading them */
- g_ptr_array_add (contacts_array, g_object_ref (contacts[i]));
- }
-
- /* Remove features that all contacts have */
- feature_flags &= (~minimal_feature_flags);
result = g_simple_async_result_new ((GObject *) self, callback, user_data,
tp_connection_upgrade_contacts_async);
- g_simple_async_result_set_op_res_gpointer (result, contacts_array,
- (GDestroyNotify) g_ptr_array_unref);
-
- if (tp_proxy_has_interface_by_id (self,
- TP_IFACE_QUARK_CONNECTION_INTERFACE_CONTACTS))
- {
- supported_interfaces = contacts_bind_to_signals (self, feature_flags);
-
- if (handles->len > 0 && supported_interfaces[0] != NULL)
- {
- data = contacts_async_data_new (result, feature_flags);
- tp_cli_connection_interface_contacts_call_get_contact_attributes (
- self, -1, handles, supported_interfaces,
- got_contact_attributes_cb, data,
- (GDestroyNotify) contacts_async_data_free, NULL);
- }
- else
- {
- g_simple_async_result_complete_in_idle (result);
- }
-
- g_free (supported_interfaces);
- }
- else
- {
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- tp_connection_upgrade_contacts (self, n_contacts, contacts,
- features, upgrade_contacts_async_fallback_cb,
- g_object_ref (result), g_object_unref, NULL);
- G_GNUC_END_IGNORE_DEPRECATIONS
- }
-
- g_object_unref (result);
- g_array_unref (handles);
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ tp_connection_upgrade_contacts (self,
+ n_contacts, contacts,
+ features,
+ upgrade_contacts_async_fallback_cb,
+ result, g_object_unref, NULL);
+ G_GNUC_END_IGNORE_DEPRECATIONS
}
/**