diff options
-rw-r--r-- | libempathy/empathy-dispatcher.c | 124 | ||||
-rw-r--r-- | libempathy/empathy-dispatcher.h | 6 | ||||
-rw-r--r-- | libempathy/empathy-ft-handler.c | 146 | ||||
-rw-r--r-- | libempathy/empathy-tp-chat.c | 24 | ||||
-rw-r--r-- | src/empathy-chat-manager.c | 8 | ||||
-rw-r--r-- | src/empathy-event-manager.c | 4 |
6 files changed, 101 insertions, 211 deletions
diff --git a/libempathy/empathy-dispatcher.c b/libempathy/empathy-dispatcher.c index 2a009b34a..558767751 100644 --- a/libempathy/empathy-dispatcher.c +++ b/libempathy/empathy-dispatcher.c @@ -59,7 +59,6 @@ typedef struct GHashTable *connections; GHashTable *outstanding_classes_requests; - GHashTable *request_channel_class_async_ids; /* reffed (TpAccount *) => gulong * Signal handler ID of the "status-changed" signal */ GHashTable *status_changed_handlers; @@ -262,17 +261,6 @@ dispatcher_status_changed_cb (TpAccount *account, dispatcher_init_connection_if_needed (self, conn); } -static void -remove_idle_handlers (gpointer key, - gpointer value, - gpointer user_data) -{ - guint source_id; - - source_id = GPOINTER_TO_UINT (value); - g_source_remove (source_id); -} - static GObject * dispatcher_constructor (GType type, guint n_construct_params, @@ -329,13 +317,6 @@ dispatcher_finalize (GObject *object) GList *list; gpointer account, id; - if (priv->request_channel_class_async_ids != NULL) - { - g_hash_table_foreach (priv->request_channel_class_async_ids, - remove_idle_handlers, NULL); - g_hash_table_destroy (priv->request_channel_class_async_ids); - } - g_hash_table_iter_init (&iter, priv->outstanding_classes_requests); while (g_hash_table_iter_next (&iter, &connection, (gpointer *) &list)) { @@ -473,8 +454,6 @@ empathy_dispatcher_init (EmpathyDispatcher *self) "account-validity-changed", G_CALLBACK (account_validity_changed_cb), self, 0); - priv->request_channel_class_async_ids = g_hash_table_new (g_direct_hash, - g_direct_equal); priv->status_changed_handlers = g_hash_table_new_full (NULL, NULL, (GDestroyNotify) g_object_unref, NULL); } @@ -679,48 +658,6 @@ empathy_dispatcher_find_channel_classes (EmpathyDispatcher *self, return matching_classes; } -static gboolean -find_channel_class_idle_cb (gpointer user_data) -{ - GList *retval; - GList *requests; - FindChannelRequest *request = user_data; - ConnectionData *cd; - gboolean is_ready = TRUE; - EmpathyDispatcherPriv *priv = GET_PRIV (request->dispatcher); - - g_hash_table_remove (priv->request_channel_class_async_ids, request); - - cd = g_hash_table_lookup (priv->connections, request->connection); - - if (cd == NULL) - is_ready = FALSE; - else if (cd->requestable_channels == NULL) - is_ready = FALSE; - - if (is_ready) - { - retval = empathy_dispatcher_find_channel_classes (request->dispatcher, - request->connection, request->channel_type, request->handle_type, - request->properties); - - request->callback (retval, request->user_data); - free_find_channel_request (request); - g_list_free (retval); - - return FALSE; - } - - requests = g_hash_table_lookup (priv->outstanding_classes_requests, - request->connection); - requests = g_list_prepend (requests, request); - - g_hash_table_insert (priv->outstanding_classes_requests, - request->connection, requests); - - return FALSE; -} - static GArray * setup_varargs (va_list var_args, const char *channel_namespace, @@ -822,64 +759,3 @@ empathy_dispatcher_find_requestable_channel_classes return retval; } - -/** - * empathy_dispatcher_find_requestable_channel_classes_async: - * @dispatcher: an #EmpathyDispatcher - * @connection: a #TpConnection - * @channel_type: a string identifying the type of the channel to lookup - * @handle_type: the handle type for the channel - * @callback: the callback to call when @connection is ready - * @user_data: the user data to pass to @callback - * @first_property_name: %NULL, or the name of the first fixed property, - * followed optionally by more names, followed by %NULL. - * - * Please see the documentation of - * empathy_dispatcher_find_requestable_channel_classes() for a detailed - * description of this function. - */ -void -empathy_dispatcher_find_requestable_channel_classes_async - (EmpathyDispatcher *self, - TpConnection *connection, - const gchar *channel_type, - guint handle_type, - EmpathyDispatcherFindChannelClassCb callback, - gpointer user_data, - const char *first_property_name, - ...) -{ - va_list var_args; - GArray *properties; - FindChannelRequest *request; - EmpathyDispatcherPriv *priv; - guint source_id; - - g_return_if_fail (EMPATHY_IS_DISPATCHER (self)); - g_return_if_fail (TP_IS_CONNECTION (connection)); - g_return_if_fail (channel_type != NULL); - g_return_if_fail (handle_type != 0); - - priv = GET_PRIV (self); - - va_start (var_args, first_property_name); - - properties = setup_varargs (var_args, channel_type, first_property_name); - - va_end (var_args); - - /* append another request for this connection */ - request = g_slice_new0 (FindChannelRequest); - request->dispatcher = g_object_ref (self); - request->channel_type = g_strdup (channel_type); - request->handle_type = handle_type; - request->connection = connection; - request->callback = callback; - request->user_data = user_data; - request->properties = properties; - - source_id = g_idle_add (find_channel_class_idle_cb, request); - - g_hash_table_insert (priv->request_channel_class_async_ids, - request, GUINT_TO_POINTER (source_id)); -} diff --git a/libempathy/empathy-dispatcher.h b/libempathy/empathy-dispatcher.h index cd54fa5d1..2f786db7a 100644 --- a/libempathy/empathy-dispatcher.h +++ b/libempathy/empathy-dispatcher.h @@ -70,12 +70,6 @@ void empathy_dispatcher_join_muc (TpAccount *account, const gchar *roomname, gint64 timestamp); -void empathy_dispatcher_find_requestable_channel_classes_async - (EmpathyDispatcher *dispatcher, TpConnection *connection, - const gchar *channel_type, guint handle_type, - EmpathyDispatcherFindChannelClassCb callback, gpointer user_data, - const char *first_property_name, ...); - GList * empathy_dispatcher_find_requestable_channel_classes (EmpathyDispatcher *dispatcher, TpConnection *connection, const gchar *channel_type, guint handle_type, diff --git a/libempathy/empathy-ft-handler.c b/libempathy/empathy-ft-handler.c index f18278a71..9b77abffd 100644 --- a/libempathy/empathy-ft-handler.c +++ b/libempathy/empathy-ft-handler.c @@ -773,46 +773,26 @@ static void ft_handler_populate_outgoing_request (EmpathyFTHandler *handler) { guint contact_handle; - GHashTable *request; - GValue *value; EmpathyFTHandlerPriv *priv = GET_PRIV (handler); - request = priv->request = g_hash_table_new_full (g_str_hash, g_str_equal, - NULL, (GDestroyNotify) tp_g_value_slice_free); - contact_handle = empathy_contact_get_handle (priv->contact); - /* org.freedesktop.Telepathy.Channel.ChannelType */ - value = tp_g_value_slice_new_string (TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER); - g_hash_table_insert (request, TP_IFACE_CHANNEL ".ChannelType", value); - - /* org.freedesktop.Telepathy.Channel.TargetHandleType */ - value = tp_g_value_slice_new_uint (TP_HANDLE_TYPE_CONTACT); - g_hash_table_insert (request, TP_IFACE_CHANNEL ".TargetHandleType", value); - - /* org.freedesktop.Telepathy.Channel.TargetHandle */ - value = tp_g_value_slice_new_uint (contact_handle); - g_hash_table_insert (request, TP_IFACE_CHANNEL ".TargetHandle", value); - - /* org.freedesktop.Telepathy.Channel.Type.FileTransfer.ContentType */ - value = tp_g_value_slice_new_string (priv->content_type); - g_hash_table_insert (request, - TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentType", value); - - /* org.freedesktop.Telepathy.Channel.Type.FileTransfer.Filename */ - value = tp_g_value_slice_new_string (priv->filename); - g_hash_table_insert (request, - TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Filename", value); - - /* org.freedesktop.Telepathy.Channel.Type.FileTransfer.Size */ - value = tp_g_value_slice_new_uint64 (priv->total_bytes); - g_hash_table_insert (request, - TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Size", value); - - /* org.freedesktop.Telepathy.Channel.Type.FileTransfer.Date */ - value = tp_g_value_slice_new_uint64 ((guint64) priv->mtime); - g_hash_table_insert (request, - TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Date", value); + priv->request = tp_asv_new ( + TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, + TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, + TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, + TP_HANDLE_TYPE_CONTACT, + TP_PROP_CHANNEL_TARGET_HANDLE, G_TYPE_UINT, + contact_handle, + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_CONTENT_TYPE, G_TYPE_STRING, + priv->content_type, + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_FILENAME, G_TYPE_STRING, + priv->filename, + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_SIZE, G_TYPE_UINT64, + priv->total_bytes, + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_DATE, G_TYPE_UINT64, + priv->mtime, + NULL); } static gboolean @@ -822,7 +802,6 @@ hash_job_done (gpointer user_data) EmpathyFTHandler *handler = hash_data->handler; EmpathyFTHandlerPriv *priv; GError *error = NULL; - GValue *value; DEBUG ("Closing stream after hashing."); @@ -864,10 +843,9 @@ hash_job_done (gpointer user_data) /* set the checksum in the request... * org.freedesktop.Telepathy.Channel.Type.FileTransfer.ContentHash */ - value = tp_g_value_slice_new_string - (g_checksum_get_string (hash_data->checksum)); - g_hash_table_insert (priv->request, - TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentHash", value); + tp_asv_set_string (priv->request, + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_CONTENT_HASH, + g_checksum_get_string (hash_data->checksum)); } cleanup: @@ -987,7 +965,6 @@ ft_handler_read_async_cb (GObject *source, GFileInputStream *stream; GError *error = NULL; HashingData *hash_data; - GValue *value; EmpathyFTHandler *handler = user_data; EmpathyFTHandlerPriv *priv = GET_PRIV (handler); @@ -1009,10 +986,9 @@ ft_handler_read_async_cb (GObject *source, /* FIXME: MD5 is the only ContentHashType supported right now */ hash_data->checksum = g_checksum_new (G_CHECKSUM_MD5); - /* org.freedesktop.Telepathy.Channel.Type.FileTransfer.ContentHashType */ - value = tp_g_value_slice_new_uint (TP_FILE_HASH_TYPE_MD5); - g_hash_table_insert (priv->request, - TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentHashType", value); + tp_asv_set_uint32 (priv->request, + TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_CONTENT_HASH_TYPE, + TP_FILE_HASH_TYPE_MD5); g_signal_emit (handler, signals[HASHING_STARTED], 0); @@ -1031,35 +1007,53 @@ callbacks_data_free (gpointer user_data) g_slice_free (CallbacksData, data); } -static void +static gboolean set_content_hash_type_from_classes (EmpathyFTHandler *handler, - GList *classes) + GPtrArray *classes) { - GValueArray *class; - GValue *v; - GList *l; GArray *possible_values; guint value; - GHashTable *fprops; gboolean valid; EmpathyFTHandlerPriv *priv = GET_PRIV (handler); + gboolean support_ft = FALSE; + guint i; possible_values = g_array_new (TRUE, TRUE, sizeof (guint)); - for (l = classes; l != NULL; l = l->next) + for (i = 0; i < classes->len; i++) { - class = l->data; - v = g_value_array_get_nth (class, 0); - fprops = g_value_get_boxed (v); + GHashTable *fixed; + GStrv allowed; + const gchar *chan_type; + + tp_value_array_unpack (g_ptr_array_index (classes, i), 2, + &fixed, &allowed); + + chan_type = tp_asv_get_string (fixed, TP_PROP_CHANNEL_CHANNEL_TYPE); + + if (tp_strdiff (chan_type, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER)) + continue; + + if (tp_asv_get_uint32 (fixed, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL) != + TP_HANDLE_TYPE_CONTACT) + continue; + + support_ft = TRUE; value = tp_asv_get_uint32 - (fprops, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentHashType", + (fixed, TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_CONTENT_HASH_TYPE, &valid); if (valid) g_array_append_val (possible_values, value); } + if (!support_ft) + { + g_array_free (possible_values, TRUE); + return FALSE; + } + if (possible_values->len == 0) { /* there are no channel classes with hash support, disable it. */ @@ -1093,18 +1087,35 @@ out: DEBUG ("Hash enabled %s; setting content hash type as %u", priv->use_hash ? "True" : "False", priv->content_hash_type); + + return TRUE; } static void -find_ft_channel_classes_cb (GList *channel_classes, +conn_prepared_cb (GObject *conn, + GAsyncResult *result, gpointer user_data) { CallbacksData *data = user_data; EmpathyFTHandler *handler = data->handler; EmpathyFTHandlerPriv *priv = GET_PRIV (handler); GError *myerr = NULL; + TpCapabilities *caps; + GPtrArray *classes; - if (channel_classes == NULL) + if (!tp_proxy_prepare_finish (conn, result, &myerr)) + { + DEBUG ("Failed to prepare connection: %s", myerr->message); + + data->callback (handler, myerr, data->user_data); + goto out; + } + + caps = tp_connection_get_capabilities (TP_CONNECTION (conn)); + classes = tp_capabilities_get_channel_classes (caps); + + /* set whether we support hash and the type of it */ + if (!set_content_hash_type_from_classes (handler, classes)) { g_set_error_literal (&myerr, EMPATHY_FT_ERROR_QUARK, EMPATHY_FT_ERROR_NOT_SUPPORTED, @@ -1118,13 +1129,11 @@ find_ft_channel_classes_cb (GList *channel_classes, } else { - /* set whether we support hash and the type of it */ - set_content_hash_type_from_classes (handler, channel_classes); - /* get back to the caller now */ data->callback (handler, NULL, data->user_data); } +out: callbacks_data_free (data); } @@ -1202,11 +1211,14 @@ out: else { /* see if FT/hashing are allowed */ - empathy_dispatcher_find_requestable_channel_classes_async - (priv->dispatcher, empathy_contact_get_connection (priv->contact), - TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, TP_HANDLE_TYPE_CONTACT, - find_ft_channel_classes_cb, cb_data, - TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentHashType", NULL); + TpConnection *connection; + GQuark features[] = { TP_CONNECTION_FEATURE_CAPABILITIES, 0 }; + + connection = empathy_contact_get_connection (priv->contact); + g_assert (connection != NULL); + + tp_proxy_prepare_async (connection, features, + conn_prepared_cb, cb_data); } } diff --git a/libempathy/empathy-tp-chat.c b/libempathy/empathy-tp-chat.c index c1e911e65..f1351049a 100644 --- a/libempathy/empathy-tp-chat.c +++ b/libempathy/empathy-tp-chat.c @@ -30,7 +30,6 @@ #include "empathy-tp-chat.h" #include "empathy-tp-contact-factory.h" #include "empathy-contact-list.h" -#include "empathy-dispatcher.h" #include "empathy-marshal.h" #include "empathy-time.h" #include "empathy-utils.h" @@ -1272,6 +1271,9 @@ tp_chat_constructor (GType type, G_CALLBACK (tp_chat_invalidated_cb), chat, 0); + g_assert (tp_proxy_is_prepared (priv->connection, + TP_CONNECTION_FEATURE_CAPABILITIES)); + if (tp_proxy_has_interface_by_id (priv->channel, TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP)) { const TpIntSet *members; @@ -1295,8 +1297,9 @@ tp_chat_constructor (GType type, tp_g_signal_connect_object (priv->channel, "group-members-changed", G_CALLBACK (tp_chat_group_members_changed_cb), chat, 0); } else { - EmpathyDispatcher *dispatcher = empathy_dispatcher_dup_singleton (); - GList *list, *ptr; + TpCapabilities *caps; + GPtrArray *classes; + guint i; /* Get the self contact from the connection's self handle */ handle = tp_connection_get_self_handle (priv->connection); @@ -1310,13 +1313,13 @@ tp_chat_constructor (GType type, handle, tp_chat_got_remote_contact_cb, NULL, NULL, chat); - list = empathy_dispatcher_find_requestable_channel_classes ( - dispatcher, priv->connection, - tp_channel_get_channel_type (priv->channel), - TP_UNKNOWN_HANDLE_TYPE, NULL); + caps = tp_connection_get_capabilities (priv->connection); + g_assert (caps != NULL); + + classes = tp_capabilities_get_channel_classes (caps); - for (ptr = list; ptr; ptr = ptr->next) { - GValueArray *array = ptr->data; + for (i = 0; i < classes->len; i++) { + GValueArray *array = g_ptr_array_index (classes, i); const char **oprops = g_value_get_boxed ( g_value_array_get_nth (array, 1)); @@ -1325,9 +1328,6 @@ tp_chat_constructor (GType type, break; } } - - g_list_free (list); - g_object_unref (dispatcher); } if (tp_proxy_has_interface_by_id (priv->channel, diff --git a/src/empathy-chat-manager.c b/src/empathy-chat-manager.c index cfa38ec84..d16be299d 100644 --- a/src/empathy-chat-manager.c +++ b/src/empathy-chat-manager.c @@ -255,8 +255,12 @@ empathy_chat_manager_init (EmpathyChatManager *self) } /* Text channels handler */ - priv->handler = tp_simple_handler_new (dbus, FALSE, FALSE, "Empathy", FALSE, - handle_channels, self, NULL); + priv->handler = tp_simple_handler_new (dbus, FALSE, FALSE, "Empathy", + FALSE, handle_channels, self, NULL); + + /* EmpathyTpChat relies on this feature being prepared */ + tp_base_client_add_connection_features_varargs (priv->handler, + TP_CONNECTION_FEATURE_CAPABILITIES, 0); g_object_unref (dbus); diff --git a/src/empathy-event-manager.c b/src/empathy-event-manager.c index fdd0672ee..0216eeab4 100644 --- a/src/empathy-event-manager.c +++ b/src/empathy-event-manager.c @@ -1206,6 +1206,10 @@ empathy_event_manager_init (EmpathyEventManager *manager) priv->approver = tp_simple_approver_new (dbus, "Empathy.EventManager", FALSE, approve_channels, manager, NULL); + /* EmpathyTpChat relies on this feature being prepared */ + tp_base_client_add_connection_features_varargs (priv->approver, + TP_CONNECTION_FEATURE_CAPABILITIES, 0); + /* Private text channels */ tp_base_client_take_approver_filter (priv->approver, tp_asv_new ( |