From 124e147d5eb601372f5353a5a65455268f81d2d0 Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Thu, 3 Nov 2011 12:48:10 +0100 Subject: [PATCH] Add TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES This feature is now a dependency on TP_CONNECTION_FEATURE_CONTACT_LIST so it will be automatically prepared when preparing TP_CONNECTION_FEATURE_CONTACT_LIST (so we don't break existing code) https://bugs.freedesktop.org/show_bug.cgi?id=42546 --- docs/reference/telepathy-glib-sections.txt | 2 + telepathy-glib/connection-contact-list.c | 62 ++++++++++++++++++++++++---- telepathy-glib/connection-contact-list.h | 4 ++ telepathy-glib/connection-internal.h | 4 ++ telepathy-glib/connection.c | 24 +++++++++-- tests/dbus/contact-list-client.c | 34 ++++++++++++++- 6 files changed, 114 insertions(+), 16 deletions(-) diff --git a/docs/reference/telepathy-glib-sections.txt b/docs/reference/telepathy-glib-sections.txt index c1dd7f1..4b9345d 100644 --- a/docs/reference/telepathy-glib-sections.txt +++ b/docs/reference/telepathy-glib-sections.txt @@ -3605,6 +3605,7 @@ TP_CONNECTION_FEATURE_AVATAR_REQUIREMENTS TP_CONNECTION_FEATURE_CONTACT_INFO TP_CONNECTION_FEATURE_BALANCE TP_CONNECTION_FEATURE_CONTACT_LIST +TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES TP_CONNECTION_FEATURE_CONTACT_GROUPS TP_CONNECTION_FEATURE_CONTACT_BLOCKING tp_connection_run_until_ready @@ -3664,6 +3665,7 @@ tp_connection_get_feature_quark_avatar_requirements tp_connection_get_feature_quark_contact_info tp_connection_get_feature_quark_balance tp_connection_get_feature_quark_contact_list +tp_connection_get_feature_quark_contact_list_properties tp_connection_get_feature_quark_contact_groups tp_connection_get_feature_quark_contact_blocking diff --git a/telepathy-glib/connection-contact-list.c b/telepathy-glib/connection-contact-list.c index 59b5b04..d0ec85c 100644 --- a/telepathy-glib/connection-contact-list.c +++ b/telepathy-glib/connection-contact-list.c @@ -335,7 +335,8 @@ contact_list_state_changed_cb (TpConnection *self, DEBUG ("contact list state changed: %d", state); /* If state goes to success, delay notification until roster is ready */ - if (state == TP_CONTACT_LIST_STATE_SUCCESS) + if (state == TP_CONTACT_LIST_STATE_SUCCESS && + tp_proxy_is_prepared (self, TP_CONNECTION_FEATURE_CONTACT_LIST)) { prepare_roster (self, NULL); return; @@ -346,7 +347,7 @@ contact_list_state_changed_cb (TpConnection *self, } static void -prepare_contact_list_cb (TpProxy *proxy, +prepare_contact_list_props_cb (TpProxy *proxy, GHashTable *properties, const GError *error, gpointer user_data, @@ -400,6 +401,21 @@ prepare_contact_list_cb (TpProxy *proxy, DEBUG ("Got contact list properties; state=%d", self->priv->contact_list_state); +OUT: + g_simple_async_result_complete (result); +} + +void _tp_connection_prepare_contact_list_async (TpProxy *proxy, + const TpProxyFeature *feature, + GAsyncReadyCallback callback, + gpointer user_data) +{ + TpConnection *self = (TpConnection *) proxy; + GSimpleAsyncResult *result; + + result = g_simple_async_result_new ((GObject *) self, callback, user_data, + _tp_connection_prepare_contact_list_async); + /* If the CM has the contact list, prepare it right away */ if (self->priv->contact_list_state == TP_CONTACT_LIST_STATE_SUCCESS) { @@ -407,11 +423,14 @@ prepare_contact_list_cb (TpProxy *proxy, return; } -OUT: - g_simple_async_result_complete (result); + /* Contacts will be prepared once the contact list has been fetched. + * Complete the preparation as it's not supposed to wait for the contact + * list. */ + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); } -void _tp_connection_prepare_contact_list_async (TpProxy *proxy, +void _tp_connection_prepare_contact_list_props_async (TpProxy *proxy, const TpProxyFeature *feature, GAsyncReadyCallback callback, gpointer user_data) @@ -423,11 +442,11 @@ void _tp_connection_prepare_contact_list_async (TpProxy *proxy, (self, contact_list_state_changed_cb, NULL, NULL, NULL, NULL); result = g_simple_async_result_new ((GObject *) self, callback, user_data, - _tp_connection_prepare_contact_list_async); + _tp_connection_prepare_contact_list_props_async); tp_cli_dbus_properties_call_get_all (self, -1, TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST, - prepare_contact_list_cb, result, g_object_unref, NULL); + prepare_contact_list_props_cb, result, g_object_unref, NULL); } static void @@ -625,8 +644,10 @@ _tp_connection_prepare_contact_groups_async (TpProxy *proxy, * Expands to a call to a function that returns a #GQuark representing the * "contact-list" feature. * - * When this feature is prepared, the contact list properties of the Connection - * has been retrieved. If #TpConnection:contact-list-state is + * When this feature is prepared, the + * TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES has been prepared, so the + * contact list properties of the Connection has been retrieved. + * If #TpConnection:contact-list-state is * %TP_CONTACT_LIST_STATE_SUCCESS, all #TpContact objects will also be created * and prepared with the desired features. See tp_connection_dup_contact_list() * to get the list of contacts, and @@ -1917,3 +1938,26 @@ _tp_connection_blocked_changed_queue_free (GQueue *queue) g_queue_foreach (queue, (GFunc) blocked_changed_item_free, NULL); g_queue_free (queue); } + +/** + * TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES: + * + * Expands to a call to a function that returns a #GQuark representing the + * "contact-list-properties" feature. + * + * When this feature is prepared, the contact list properties of the Connection + * has been retrieved. + * This feature will fail to prepare when using obsolete Telepathy connection + * managers which do not implement the ContactList interface. + * + * One can ask for a feature to be prepared using the + * tp_proxy_prepare_async() function, and waiting for it to callback. + * + * Since: 0.UNRELEASED + */ +GQuark +tp_connection_get_feature_quark_contact_list_properties (void) +{ + return g_quark_from_static_string ( + "tp-connection-feature-contact-list-properties"); +} diff --git a/telepathy-glib/connection-contact-list.h b/telepathy-glib/connection-contact-list.h index d04ba45..ec3ee5c 100644 --- a/telepathy-glib/connection-contact-list.h +++ b/telepathy-glib/connection-contact-list.h @@ -31,6 +31,10 @@ G_BEGIN_DECLS (tp_connection_get_feature_quark_contact_list ()) GQuark tp_connection_get_feature_quark_contact_list (void) G_GNUC_CONST; +#define TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES \ + (tp_connection_get_feature_quark_contact_list_properties ()) +GQuark tp_connection_get_feature_quark_contact_list_properties (void) G_GNUC_CONST; + TpContactListState tp_connection_get_contact_list_state (TpConnection *self); gboolean tp_connection_get_contact_list_persists (TpConnection *self); gboolean tp_connection_get_can_change_contact_list (TpConnection *self); diff --git a/telepathy-glib/connection-internal.h b/telepathy-glib/connection-internal.h index e346c2b..5b48c8f 100644 --- a/telepathy-glib/connection-internal.h +++ b/telepathy-glib/connection-internal.h @@ -166,6 +166,10 @@ void _tp_connection_prepare_contact_list_async (TpProxy *proxy, const TpProxyFeature *feature, GAsyncReadyCallback callback, gpointer user_data); +void _tp_connection_prepare_contact_list_props_async (TpProxy *proxy, + const TpProxyFeature *feature, + GAsyncReadyCallback callback, + gpointer user_data); void _tp_connection_prepare_contact_groups_async (TpProxy *proxy, const TpProxyFeature *feature, GAsyncReadyCallback callback, diff --git a/telepathy-glib/connection.c b/telepathy-glib/connection.c index 82220e4..5e91dfb 100644 --- a/telepathy-glib/connection.c +++ b/telepathy-glib/connection.c @@ -1608,6 +1608,7 @@ enum { FEAT_CONTACT_INFO, FEAT_BALANCE, FEAT_CONTACT_LIST, + FEAT_CONTACT_LIST_PROPS, FEAT_CONTACT_GROUPS, FEAT_CONTACT_BLOCKING, N_FEAT @@ -1624,6 +1625,7 @@ tp_connection_list_features (TpProxyClass *cls G_GNUC_UNUSED) static GQuark need_contact_list[3] = {0, 0, 0}; static GQuark need_contact_groups[2] = {0, 0}; static GQuark need_contact_blocking[2] = {0, 0}; + static GQuark need_contact_list_props[2] = {0, 0}; if (G_LIKELY (features[0].name != 0)) return features; @@ -1661,6 +1663,12 @@ tp_connection_list_features (TpProxyClass *cls G_GNUC_UNUSED) need_contact_list[0] = TP_IFACE_QUARK_CONNECTION_INTERFACE_CONTACT_LIST; need_contact_list[1] = TP_IFACE_QUARK_CONNECTION_INTERFACE_CONTACTS; features[FEAT_CONTACT_LIST].interfaces_needed = need_contact_list; + need_contact_list_props[0] = TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES; + features[FEAT_CONTACT_LIST].depends_on = need_contact_list_props; + + features[FEAT_CONTACT_LIST_PROPS].name = TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES; + features[FEAT_CONTACT_LIST_PROPS].prepare_async = _tp_connection_prepare_contact_list_props_async; + features[FEAT_CONTACT_LIST_PROPS].interfaces_needed = need_contact_list; features[FEAT_CONTACT_GROUPS].name = TP_CONNECTION_FEATURE_CONTACT_GROUPS; features[FEAT_CONTACT_GROUPS].prepare_async = _tp_connection_prepare_contact_groups_async; @@ -1950,7 +1958,9 @@ tp_connection_class_init (TpConnectionClass *klass) * The progress made in retrieving the contact list. * * For this property to be valid, you must first call - * tp_proxy_prepare_async() with the feature %TP_CONNECTION_FEATURE_CONTACT_LIST. + * tp_proxy_prepare_async() with the feature + * %TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES or + * %TP_CONNECTION_FEATURE_CONTACT_LIST. * * Since: 0.15.5 */ @@ -1970,7 +1980,9 @@ tp_connection_class_init (TpConnectionClass *klass) * If false, presence subscriptions on this connection are not stored. * * For this property to be valid, you must first call - * tp_proxy_prepare_async() with the feature %TP_CONNECTION_FEATURE_CONTACT_LIST. + * tp_proxy_prepare_async() with the feature + * %TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES or + * %TP_CONNECTION_FEATURE_CONTACT_LIST. * * Since: 0.15.5 */ @@ -1991,7 +2003,9 @@ tp_connection_class_init (TpConnectionClass *klass) * the local subnet, so the user cannot control their presence publication. * * For this property to be valid, you must first call - * tp_proxy_prepare_async() with the feature %TP_CONNECTION_FEATURE_CONTACT_LIST. + * tp_proxy_prepare_async() with the feature + * %TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES or + * %TP_CONNECTION_FEATURE_CONTACT_LIST. * * Since: 0.15.5 */ @@ -2012,7 +2026,9 @@ tp_connection_class_init (TpConnectionClass *klass) * suitable default. * * For this property to be valid, you must first call - * tp_proxy_prepare_async() with the feature %TP_CONNECTION_FEATURE_CONTACT_LIST. + * tp_proxy_prepare_async() with the feature + * %TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES or + * %TP_CONNECTION_FEATURE_CONTACT_LIST. * * Since: 0.15.5 */ diff --git a/tests/dbus/contact-list-client.c b/tests/dbus/contact-list-client.c index 6f2d5ff..f9eeb6c 100644 --- a/tests/dbus/contact-list-client.c +++ b/tests/dbus/contact-list-client.c @@ -507,11 +507,20 @@ static void test_contact_list_properties (Test *test, gconstpointer data G_GNUC_UNUSED) { - GQuark conn_features[] = { TP_CONNECTION_FEATURE_CONTACT_LIST, 0 }; + gboolean props_only = GPOINTER_TO_UINT (data); + GQuark conn_features[] = { 0, 0 }; + GPtrArray *contacts; + + if (props_only) + conn_features[0] = TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES; + else + conn_features[0] = TP_CONNECTION_FEATURE_CONTACT_LIST; /* Feature isn't prepared yet */ g_assert (!tp_proxy_is_prepared (test->connection, TP_CONNECTION_FEATURE_CONTACT_LIST)); + g_assert (!tp_proxy_is_prepared (test->connection, + TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES)); g_assert_cmpuint (tp_connection_get_contact_list_state (test->connection), ==, TP_CONTACT_LIST_STATE_NONE); @@ -526,9 +535,26 @@ test_contact_list_properties (Test *test, g_main_loop_run (test->mainloop); g_assert_no_error (test->error); + g_assert (tp_proxy_is_prepared (test->connection, + TP_CONNECTION_FEATURE_CONTACT_LIST) == !props_only); + g_assert (tp_proxy_is_prepared (test->connection, + TP_CONNECTION_FEATURE_CONTACT_LIST_PROPERTIES)); + g_assert (tp_connection_get_contact_list_persists (test->connection)); g_assert (tp_connection_get_can_change_contact_list (test->connection)); g_assert (tp_connection_get_request_uses_message (test->connection)); + + contacts = tp_connection_dup_contact_list (test->connection); + if (props_only) + { + /* Contacts haven't be fetched */ + g_assert_cmpuint (contacts->len, ==, 0); + } + else + { + g_assert_cmpuint (contacts->len, >, 0); + } + g_ptr_array_unref (contacts); } int @@ -549,8 +575,10 @@ main (int argc, g_test_add ("/contact-list-client/blocking/is-blocked", Test, NULL, setup, test_is_blocked, teardown); - g_test_add ("/contact-list-client/contact-list/properties", Test, NULL, - setup, test_contact_list_properties, teardown); + g_test_add ("/contact-list-client/contact-list/properties", Test, + GUINT_TO_POINTER (FALSE), setup, test_contact_list_properties, teardown); + g_test_add ("/contact-list-client/contact-list/properties", Test, + GUINT_TO_POINTER (TRUE), setup, test_contact_list_properties, teardown); return g_test_run (); } -- 1.7.4.1