diff options
author | Xavier Claessens <xavier.claessens@collabora.co.uk> | 2012-05-11 17:12:29 +0200 |
---|---|---|
committer | Xavier Claessens <xavier.claessens@collabora.co.uk> | 2012-05-11 17:12:29 +0200 |
commit | 2619aa81e0d79d79291ca212ab6f839dd12d6c97 (patch) | |
tree | 8b308fa3a97a19c354455fe22cecf79d77b03f12 | |
parent | 5c49347ae31f9bd6316953f0a55d192f9c043032 (diff) | |
parent | dacdc30b38a39ba2500ecfeb223bfb83e464340a (diff) |
Merge branch 'master' into next
Conflicts:
telepathy-glib/contact.c
tests/dbus/contacts.c
-rw-r--r-- | telepathy-glib/contact.c | 280 | ||||
-rw-r--r-- | tests/dbus/contacts.c | 136 |
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; } |