summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.co.uk>2012-05-11 17:12:29 +0200
committerXavier Claessens <xavier.claessens@collabora.co.uk>2012-05-11 17:12:29 +0200
commit2619aa81e0d79d79291ca212ab6f839dd12d6c97 (patch)
tree8b308fa3a97a19c354455fe22cecf79d77b03f12
parent5c49347ae31f9bd6316953f0a55d192f9c043032 (diff)
parentdacdc30b38a39ba2500ecfeb223bfb83e464340a (diff)
Merge branch 'master' into next
Conflicts: telepathy-glib/contact.c tests/dbus/contacts.c
-rw-r--r--telepathy-glib/contact.c280
-rw-r--r--tests/dbus/contacts.c136
2 files changed, 179 insertions, 237 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
}
/**
diff --git a/tests/dbus/contacts.c b/tests/dbus/contacts.c
index f987cb438..ee1186311 100644
--- a/tests/dbus/contacts.c
+++ b/tests/dbus/contacts.c
@@ -516,10 +516,11 @@ test_avatar_requirements (Fixture *f,
g_main_loop_unref (result.loop);
}
-static GFile *
+static TpContact *
create_contact_with_fake_avatar (TpTestsContactsConnection *service_conn,
TpConnection *client_conn,
- const gchar *id)
+ const gchar *id,
+ gboolean request_avatar)
{
Result result = { g_main_loop_new (NULL, FALSE), NULL, NULL, NULL };
TpHandleRepoIface *service_repo = tp_base_connection_get_handles (
@@ -531,7 +532,6 @@ create_contact_with_fake_avatar (TpTestsContactsConnection *service_conn,
TpContact *contact;
TpHandle handle;
GArray *array;
- GFile *avatar_file;
gchar *content = NULL;
handle = tp_handle_ensure (service_repo, id, NULL, NULL);
@@ -541,6 +541,11 @@ create_contact_with_fake_avatar (TpTestsContactsConnection *service_conn,
tp_tests_contacts_connection_change_avatar_data (service_conn, handle, array,
avatar_mime_type, avatar_token);
+ if (request_avatar)
+ features[0] = TP_CONTACT_FEATURE_AVATAR_DATA;
+ else
+ features[0] = TP_CONTACT_FEATURE_AVATAR_TOKEN;
+
tp_connection_get_contacts_by_handle (client_conn,
1, &handle,
features,
@@ -549,27 +554,33 @@ create_contact_with_fake_avatar (TpTestsContactsConnection *service_conn,
g_main_loop_run (result.loop);
g_assert_no_error (result.error);
- contact = g_ptr_array_index (result.contacts, 0);
- if (tp_contact_get_avatar_file (contact) == NULL)
- {
- g_signal_connect_swapped (contact, "notify::avatar-file",
- G_CALLBACK (finish), &result);
- g_main_loop_run (result.loop);
- }
+ contact = g_object_ref (g_ptr_array_index (result.contacts, 0));
- g_assert_cmpstr (tp_contact_get_avatar_mime_type (contact), ==,
- avatar_mime_type);
g_assert_cmpstr (tp_contact_get_avatar_token (contact), ==, avatar_token);
- avatar_file = tp_contact_get_avatar_file (contact);
- g_assert (avatar_file != NULL);
- g_file_load_contents (avatar_file, NULL, &content, NULL, NULL, &result.error);
- g_assert_no_error (result.error);
- g_assert_cmpstr (content, ==, avatar_data);
- g_free (content);
+ if (request_avatar)
+ {
+ GFile *avatar_file;
- /* Keep avatar_file alive after contact destruction */
- g_object_ref (avatar_file);
+ /* If we requested avatar, it could come later */
+ if (tp_contact_get_avatar_file (contact) == NULL)
+ {
+ g_signal_connect_swapped (contact, "notify::avatar-file",
+ G_CALLBACK (finish), &result);
+ g_main_loop_run (result.loop);
+ }
+
+ g_assert_cmpstr (tp_contact_get_avatar_mime_type (contact), ==,
+ avatar_mime_type);
+
+ avatar_file = tp_contact_get_avatar_file (contact);
+ g_assert (avatar_file != NULL);
+ g_file_load_contents (avatar_file, NULL, &content, NULL, NULL,
+ &result.error);
+ g_assert_no_error (result.error);
+ g_assert_cmpstr (content, ==, avatar_data);
+ g_free (content);
+ }
reset_result (&result);
g_main_loop_unref (result.loop);
@@ -577,7 +588,7 @@ create_contact_with_fake_avatar (TpTestsContactsConnection *service_conn,
tp_handle_unref (service_repo, handle);
g_array_unref (array);
- return avatar_file;
+ return contact;
}
static void
@@ -636,29 +647,19 @@ haze_remove_directory (const gchar *path)
return ret;
}
-#define RAND_STR_LEN 6
-
static void
test_avatar_data (Fixture *f,
gconstpointer unused G_GNUC_UNUSED)
{
TpTestsContactsConnection *service_conn = f->service_conn;
TpConnection *client_conn = f->client_conn;
- gchar *dir;
gboolean avatar_retrieved_called;
GError *error = NULL;
- GFile *file1, *file2;
+ TpContact *contact1, *contact2;
TpProxySignalConnection *signal_id;
g_message (G_STRFUNC);
- /* Make sure g_get_user_cache_dir() returns a tmp directory, to not mess up
- * user's cache dir. */
- dir = g_dir_make_tmp ("tp-glib-tests-XXXXXX", &error);
- g_assert_no_error (error);
- g_setenv ("XDG_CACHE_HOME", dir, TRUE);
- g_assert_cmpstr (g_get_user_cache_dir (), ==, dir);
-
/* Check if AvatarRetrieved gets called */
signal_id = tp_cli_connection_interface_avatars_connect_to_avatar_retrieved (
client_conn, avatar_retrieved_cb, &avatar_retrieved_called, NULL, NULL,
@@ -668,24 +669,58 @@ test_avatar_data (Fixture *f,
/* First time we create a contact, avatar should not be in cache, so
* AvatarRetrived should be called */
avatar_retrieved_called = FALSE;
- file1 = create_contact_with_fake_avatar (service_conn, client_conn,
- "fake-id1");
+ contact1 = create_contact_with_fake_avatar (service_conn, client_conn,
+ "fake-id1", TRUE);
g_assert (avatar_retrieved_called);
+ g_assert (contact1 != NULL);
+ g_assert (tp_contact_get_avatar_file (contact1) != NULL);
/* Second time we create a contact, avatar should be in cache now, so
* AvatarRetrived should NOT be called */
avatar_retrieved_called = FALSE;
- file2 = create_contact_with_fake_avatar (service_conn, client_conn,
- "fake-id2");
+ contact2 = create_contact_with_fake_avatar (service_conn, client_conn,
+ "fake-id2", TRUE);
g_assert (!avatar_retrieved_called);
+ g_assert (contact2 != NULL);
+ g_assert (tp_contact_get_avatar_file (contact2) != NULL);
- g_assert (g_file_equal (file1, file2));
- g_assert (haze_remove_directory (dir));
+ g_assert (g_file_equal (
+ tp_contact_get_avatar_file (contact1),
+ tp_contact_get_avatar_file (contact2)));
tp_proxy_signal_connection_disconnect (signal_id);
- g_object_unref (file1);
- g_object_unref (file2);
- g_free (dir);
+ g_object_unref (contact1);
+ g_object_unref (contact2);
+}
+
+static void
+test_avatar_data_after_token (Fixture *f,
+ gconstpointer unused G_GNUC_UNUSED)
+{
+ TpTestsContactsConnection *service_conn = f->service_conn;
+ TpConnection *client_conn = f->client_conn;
+ const gchar *id = "avatar-data-after-token";
+ TpContact *contact1, *contact2;
+
+ g_message (G_STRFUNC);
+
+ /* Create a contact with AVATAR_TOKEN feature */
+ contact1 = create_contact_with_fake_avatar (service_conn, client_conn, id,
+ FALSE);
+ g_assert (contact1 != NULL);
+ g_assert (tp_contact_get_avatar_file (contact1) == NULL);
+
+ /* Now create the same contact with AVATAR_DATA feature */
+ contact2 = create_contact_with_fake_avatar (service_conn, client_conn, id,
+ TRUE);
+ g_assert (contact2 != NULL);
+ g_assert (tp_contact_get_avatar_file (contact2) != NULL);
+
+ g_assert (contact1 == contact2);
+
+ /* Cleanup */
+ g_object_unref (contact1);
+ g_object_unref (contact2);
}
static void
@@ -2639,9 +2674,20 @@ int
main (int argc,
char **argv)
{
+ gint ret;
+ gchar *dir;
+ GError *error = NULL;
+
tp_tests_init (&argc, &argv);
g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
+ /* Make sure g_get_user_cache_dir() returns a tmp directory, to not mess up
+ * user's cache dir. */
+ dir = g_dir_make_tmp ("tp-glib-tests-XXXXXX", &error);
+ g_assert_no_error (error);
+ g_setenv ("XDG_CACHE_HOME", dir, TRUE);
+ g_assert_cmpstr (g_get_user_cache_dir (), ==, dir);
+
#define ADD(x) \
g_test_add ("/contacts/" #x, Fixture, NULL, setup, test_ ## x, teardown)
@@ -2655,6 +2701,7 @@ main (int argc,
ADD (by_id);
ADD (avatar_requirements);
ADD (avatar_data);
+ ADD (avatar_data_after_token);
ADD (contact_info);
ADD (dup_if_possible);
ADD (subscription_states);
@@ -2671,5 +2718,10 @@ main (int argc,
g_test_add ("/contacts/self-contact", Fixture, NULL,
setup_no_connect, test_self_contact, teardown);
- return g_test_run ();
+ ret = g_test_run ();
+
+ g_assert (haze_remove_directory (dir));
+ g_free (dir);
+
+ return ret;
}