From f1f4e8bc7f58bb8e4c551bbc0c98674cfa0dc1c7 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Thu, 20 Oct 2011 15:23:50 +0200 Subject: Add internal API to get connection capabilities without having core prepared --- telepathy-glib/connection-internal.h | 10 ++++++ telepathy-glib/connection.c | 70 +++++++++++++++++++++++++++++++----- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/telepathy-glib/connection-internal.h b/telepathy-glib/connection-internal.h index 6e3c3b5b2..8df5281b0 100644 --- a/telepathy-glib/connection-internal.h +++ b/telepathy-glib/connection-internal.h @@ -59,6 +59,7 @@ struct _TpConnectionPrivate { GHashTable *contacts; TpCapabilities *capabilities; + GQueue capabilities_queue; TpAvatarRequirements *avatar_requirements; GArray *avatar_request_queue; @@ -115,6 +116,15 @@ void _tp_connection_status_reason_to_gerror (TpConnectionStatusReason reason, const gchar **ret_str, GError **error); +/* Internal hook to break potential dependency loop between Connection and + * Contacts */ +void _tp_connection_get_capabilities_async (TpConnection *self, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean _tp_connection_get_capabilities_finish (TpConnection *self, + GAsyncResult *result, GError **error); + void _tp_connection_add_contact (TpConnection *self, TpHandle handle, TpContact *contact); void _tp_connection_remove_contact (TpConnection *self, TpHandle handle, diff --git a/telepathy-glib/connection.c b/telepathy-glib/connection.c index 9b08fc3c2..62f86a8ae 100644 --- a/telepathy-glib/connection.c +++ b/telepathy-glib/connection.c @@ -500,7 +500,7 @@ tp_connection_get_rcc_cb (TpProxy *proxy, GObject *weak_object) { TpConnection *self = (TpConnection *) proxy; - GSimpleAsyncResult *result = user_data; + GSimpleAsyncResult *result; if (error != NULL) { @@ -530,11 +530,65 @@ tp_connection_get_rcc_cb (TpProxy *proxy, FALSE); finally: - g_simple_async_result_complete (result); + while ((result = g_queue_pop_head (&self->priv->capabilities_queue)) != NULL) + { + g_simple_async_result_complete (result); + g_object_unref (result); + } g_object_notify ((GObject *) self, "capabilities"); } +static void +_tp_connection_do_get_capabilities_async (TpConnection *self, + GSimpleAsyncResult *result) +{ + if (self->priv->capabilities != NULL) + { + /* been there, done that, bored now */ + g_simple_async_result_complete_in_idle (result); + g_object_unref (result); + } + else + { + g_queue_push_tail (&self->priv->capabilities_queue, result); + if (g_queue_get_length (&self->priv->capabilities_queue) == 1) + { + DEBUG ("%s: Retrieving capabilities", + tp_proxy_get_object_path (self)); + + /* We don't check whether we actually have this interface here. The + * quark is dbus properties quark is guaranteed to be on every + * TpProxy and only very very old CMs won't have Requests, in case + * someone still has such a relic we'll we'll just handle it when + * they reply to us with an error */ + tp_cli_dbus_properties_call_get (self, -1, + TP_IFACE_CONNECTION_INTERFACE_REQUESTS, + "RequestableChannelClasses", + tp_connection_get_rcc_cb, NULL, NULL, NULL); + } + } +} + +void +_tp_connection_get_capabilities_async (TpConnection *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + + result = g_simple_async_result_new ((GObject *) self, callback, user_data, + _tp_connection_get_capabilities_async); + _tp_connection_do_get_capabilities_async (self, result); +} + +gboolean +_tp_connection_get_capabilities_finish (TpConnection *self, + GAsyncResult *result, GError **error) +{ + _tp_implement_finish_void (self, _tp_connection_get_capabilities_async); +} + static void tp_connection_prepare_capabilities_async (TpProxy *proxy, const TpProxyFeature *feature, @@ -544,14 +598,12 @@ tp_connection_prepare_capabilities_async (TpProxy *proxy, TpConnection *self = (TpConnection *) proxy; GSimpleAsyncResult *result; - result = g_simple_async_result_new ((GObject *) proxy, callback, user_data, - tp_connection_prepare_capabilities_async); + DEBUG ("%s: Preparing capabilities", tp_proxy_get_object_path (self)); - g_assert (self->priv->capabilities == NULL); + result = g_simple_async_result_new ((GObject *) self, callback, user_data, + tp_connection_prepare_capabilities_async); - tp_cli_dbus_properties_call_get (self, -1, - TP_IFACE_CONNECTION_INTERFACE_REQUESTS, "RequestableChannelClasses", - tp_connection_get_rcc_cb, result, g_object_unref, NULL); + _tp_connection_do_get_capabilities_async (self, result); } static void @@ -1399,6 +1451,8 @@ tp_connection_init (TpConnection *self) self->priv->roster = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); self->priv->contacts_changed_queue = g_queue_new (); + + g_queue_init (&self->priv->capabilities_queue); } static void -- cgit v1.2.1