diff options
author | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2011-10-24 16:42:51 +0200 |
---|---|---|
committer | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2011-10-24 16:42:51 +0200 |
commit | 54ac9a23387546370652f5c81d2f735d1e294596 (patch) | |
tree | f0da3f27db3254dcf007350a16d66c1f8912c0e3 | |
parent | de32456d8d460b427ab26c489c142a41319d2023 (diff) | |
parent | 60615777a80c190a270e270b1b3972e367ad7dfd (diff) |
Merge branch 'telepathy-glib-0.16'
-rw-r--r-- | telepathy-glib/account-manager.c | 5 | ||||
-rw-r--r-- | telepathy-glib/connection-internal.h | 12 | ||||
-rw-r--r-- | telepathy-glib/connection.c | 77 | ||||
-rw-r--r-- | telepathy-glib/contact.c | 41 | ||||
-rw-r--r-- | tests/lib/contacts-conn.c | 5 |
5 files changed, 108 insertions, 32 deletions
diff --git a/telepathy-glib/account-manager.c b/telepathy-glib/account-manager.c index 107caf17..447f4185 100644 --- a/telepathy-glib/account-manager.c +++ b/telepathy-glib/account-manager.c @@ -371,6 +371,8 @@ _tp_account_manager_check_core_ready (TpAccountManager *manager) { TpAccountManagerPrivate *priv = manager->priv; + DEBUG ("manager has %d accounts left to prepare", + priv->n_preparing_accounts); if (tp_proxy_is_prepared (manager, TP_ACCOUNT_MANAGER_FEATURE_CORE)) return; @@ -416,6 +418,9 @@ account_prepared_cb (GObject *object, insert_account (self, account); } + DEBUG ("Account %s was prepared", + tp_proxy_get_object_path (object)); + OUT: self->priv->n_preparing_accounts--; _tp_account_manager_check_core_ready (self); diff --git a/telepathy-glib/connection-internal.h b/telepathy-glib/connection-internal.h index 6e3c3b5b..cd9a53f9 100644 --- a/telepathy-glib/connection-internal.h +++ b/telepathy-glib/connection-internal.h @@ -59,6 +59,9 @@ struct _TpConnectionPrivate { GHashTable *contacts; TpCapabilities *capabilities; + /* Queue of owned GSimpleAsyncResult, each result being a pending call + * started using _tp_connection_do_get_capabilities_async */ + GQueue capabilities_queue; TpAvatarRequirements *avatar_requirements; GArray *avatar_request_queue; @@ -115,6 +118,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 faf86cdd..62f86a8a 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,12 +530,66 @@ 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, GAsyncReadyCallback callback, @@ -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 @@ -559,7 +611,8 @@ signal_connected (TpConnection *self) { /* we shouldn't have gone to status CONNECTED for any reason * that isn't REQUESTED :-) */ - DEBUG ("%p: CORE and CONNECTED ready", self); + DEBUG ("%s (%p): CORE and CONNECTED ready", + tp_proxy_get_object_path (self), self); self->priv->status = TP_CONNECTION_STATUS_CONNECTED; self->priv->status_reason = TP_CONNECTION_STATUS_REASON_REQUESTED; self->priv->ready = TRUE; @@ -1360,6 +1413,8 @@ tp_connection_constructed (GObject *object) if (object_class->constructed != NULL) object_class->constructed (object); + DEBUG ("%s (%p) constructed", tp_proxy_get_object_path (object), object); + _tp_proxy_ensure_factory (self, NULL); /* Connect to my own StatusChanged signal. @@ -1383,8 +1438,6 @@ tp_connection_constructed (GObject *object) static void tp_connection_init (TpConnection *self) { - DEBUG ("%p", self); - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TYPE_CONNECTION, TpConnectionPrivate); @@ -1398,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 diff --git a/telepathy-glib/contact.c b/telepathy-glib/contact.c index 2be525b5..70c0100a 100644 --- a/telepathy-glib/contact.c +++ b/telepathy-glib/contact.c @@ -2487,38 +2487,38 @@ set_conn_capabilities_on_contacts (GPtrArray *contacts, TpConnection *connection) { guint i; + TpCapabilities *conn_caps = tp_connection_get_capabilities (connection); + GPtrArray *rcc; + + /* If the connection has no capabilities then don't bother setting them on + * the contact and pretend we just don't know.. In practise this will only + * happen if there was an error in getting the connections capabilities so + * claiming ignorance seems the most sensible thing to do */ + if (conn_caps == NULL) + return; + + rcc = tp_capabilities_get_channel_classes (conn_caps); + if (rcc == NULL || rcc->len == 0) + return; for (i = 0; i < contacts->len; i++) { TpContact *contact = g_ptr_array_index (contacts, i); - contact_set_capabilities (contact, tp_connection_get_capabilities ( - connection)); + contact_set_capabilities (contact, conn_caps); } } static void -connection_capabilities_prepare_cb (GObject *object, +connection_capabilities_fetched_cb (GObject *object, GAsyncResult *res, gpointer user_data) { - GError *error = NULL; ContactsContext *c = user_data; - if (!tp_proxy_prepare_finish (object, res, &error)) - { - DEBUG ("Failed to prepare Connection capabilities feature: %s %u: %s", - g_quark_to_string (error->domain), error->code, error->message); - } - else if (!tp_proxy_is_prepared (object, TP_CONNECTION_FEATURE_CAPABILITIES)) - { - DEBUG ("Connection capabilities feature has not been actually prepared"); - } - else - { - set_conn_capabilities_on_contacts (c->contacts, c->connection); - } + DEBUG ("Connection capabilities prepared"); + set_conn_capabilities_on_contacts (c->contacts, c->connection); contacts_context_continue (c); contacts_context_unref (c); } @@ -2526,12 +2526,13 @@ connection_capabilities_prepare_cb (GObject *object, static void contacts_get_conn_capabilities (ContactsContext *c) { - GQuark features[] = { TP_CONNECTION_FEATURE_CAPABILITIES, 0 }; g_assert (c->handles->len == c->contacts->len); + DEBUG ("Getting connection capabilities"); + c->refcount++; - tp_proxy_prepare_async (c->connection, features, - connection_capabilities_prepare_cb, c); + _tp_connection_get_capabilities_async (c->connection, + connection_capabilities_fetched_cb, c); } static void diff --git a/tests/lib/contacts-conn.c b/tests/lib/contacts-conn.c index 82eb2321..1d1b5ee1 100644 --- a/tests/lib/contacts-conn.c +++ b/tests/lib/contacts-conn.c @@ -362,6 +362,7 @@ client_types_fill_contact_attributes ( static void constructed (GObject *object) { + TpTestsContactsConnection *self = TP_TESTS_CONTACTS_CONNECTION (object); TpBaseConnection *base = TP_BASE_CONNECTION (object); void (*parent_impl) (GObject *) = G_OBJECT_CLASS (tp_tests_contacts_connection_parent_class)->constructed; @@ -372,7 +373,8 @@ constructed (GObject *object) tp_contacts_mixin_init (object, G_STRUCT_OFFSET (TpTestsContactsConnection, contacts_mixin)); tp_base_connection_register_with_contacts_mixin (base); - tp_base_contact_list_mixin_register_with_contacts_mixin (base); + if (self->priv->list_manager) + tp_base_contact_list_mixin_register_with_contacts_mixin (base); tp_contacts_mixin_add_contact_attributes_iface (object, TP_IFACE_CONNECTION_INTERFACE_ALIASING, aliasing_fill_contact_attributes); @@ -1346,4 +1348,5 @@ tp_tests_no_requests_connection_class_init ( (TpBaseConnectionClass *) klass; base_class->interfaces_always_present = interfaces_always_present; + base_class->create_channel_managers = NULL; } |