aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy/empathy-dispatcher.c
diff options
context:
space:
mode:
Diffstat (limited to 'libempathy/empathy-dispatcher.c')
-rw-r--r--libempathy/empathy-dispatcher.c656
1 files changed, 1 insertions, 655 deletions
diff --git a/libempathy/empathy-dispatcher.c b/libempathy/empathy-dispatcher.c
index 558767751..1f7d7f277 100644
--- a/libempathy/empathy-dispatcher.c
+++ b/libempathy/empathy-dispatcher.c
@@ -19,451 +19,21 @@
* Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
*/
-#define DISPATCHER_BUS_NAME TP_CLIENT_BUS_NAME_BASE "Empathy"
-#define DISPATCHER_OBJECT_PATH TP_CLIENT_OBJECT_PATH_BASE "Empathy"
-
#include <config.h>
#include <string.h>
#include <glib/gi18n-lib.h>
-#include <telepathy-glib/account-manager.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/connection.h>
-#include <telepathy-glib/util.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/proxy-subclass.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/defs.h>
-#include <telepathy-glib/interfaces.h>
-
-#include <extensions/extensions.h>
+#include <telepathy-glib/telepathy-glib.h>
#include "empathy-dispatcher.h"
#include "empathy-utils.h"
-#include "empathy-tp-contact-factory.h"
-#include "empathy-chatroom-manager.h"
#include "empathy-utils.h"
#define DEBUG_FLAG EMPATHY_DEBUG_DISPATCHER
#include <libempathy/empathy-debug.h>
-#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyDispatcher)
-typedef struct
-{
- gboolean dispose_has_run;
-
- TpAccountManager *account_manager;
- /* connection to connection data mapping */
- GHashTable *connections;
- GHashTable *outstanding_classes_requests;
-
- /* reffed (TpAccount *) => gulong
- * Signal handler ID of the "status-changed" signal */
- GHashTable *status_changed_handlers;
-} EmpathyDispatcherPriv;
-
-G_DEFINE_TYPE (EmpathyDispatcher, empathy_dispatcher, G_TYPE_OBJECT);
-
-static EmpathyDispatcher *dispatcher = NULL;
-
-static void dispatcher_init_connection_if_needed (
- EmpathyDispatcher *dispatcher,
- TpConnection *connection);
-
-static GList * empathy_dispatcher_find_channel_classes
- (EmpathyDispatcher *dispatcher, TpConnection *connection,
- const gchar *channel_type, guint handle_type, GArray *fixed_properties);
-
-typedef struct
-{
- TpChannel *channel;
- /* Channel type specific wrapper object */
- GObject *channel_wrapper;
-} DispatchData;
-
-typedef struct
-{
- /* List of requestable channel classes */
- GPtrArray *requestable_channels;
-} ConnectionData;
-
-typedef struct
-{
- EmpathyDispatcher *dispatcher;
- TpConnection *connection;
- char *channel_type;
- guint handle_type;
- GArray *properties;
- EmpathyDispatcherFindChannelClassCb *callback;
- gpointer user_data;
-} FindChannelRequest;
-
-static ConnectionData *
-new_connection_data (void)
-{
- return g_slice_new0 (ConnectionData);
-}
-
-static void
-free_connection_data (ConnectionData *cd)
-{
- guint i;
-
- if (cd->requestable_channels != NULL)
- {
- for (i = 0 ; i < cd->requestable_channels->len ; i++)
- g_value_array_free (
- g_ptr_array_index (cd->requestable_channels, i));
- g_ptr_array_free (cd->requestable_channels, TRUE);
- }
-}
-
-static void
-free_find_channel_request (FindChannelRequest *r)
-{
- guint idx;
- char *str;
-
- g_object_unref (r->dispatcher);
- g_free (r->channel_type);
-
- if (r->properties != NULL)
- {
- for (idx = 0; idx < r->properties->len ; idx++)
- {
- str = g_array_index (r->properties, char *, idx);
- g_free (str);
- }
-
- g_array_free (r->properties, TRUE);
- }
-
- g_slice_free (FindChannelRequest, r);
-}
-
-static void
-dispatcher_connection_invalidated_cb (TpConnection *connection,
- guint domain,
- gint code,
- gchar *message,
- EmpathyDispatcher *self)
-{
- EmpathyDispatcherPriv *priv = GET_PRIV (self);
-
- DEBUG ("Error: %s", message);
-
- g_hash_table_remove (priv->connections, connection);
-}
-
-static void
-got_connection_rcc (EmpathyDispatcher *self,
- TpConnection *connection)
-{
- EmpathyDispatcherPriv *priv = GET_PRIV (self);
- TpCapabilities *caps;
- ConnectionData *cd;
- GList *requests, *l;
- FindChannelRequest *request;
- GList *retval;
-
- caps = tp_connection_get_capabilities (connection);
- g_assert (caps != NULL);
-
- cd = g_hash_table_lookup (priv->connections, connection);
- g_assert (cd != NULL);
-
- cd->requestable_channels = g_boxed_copy (
- TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST,
- tp_capabilities_get_channel_classes (caps));
-
- requests = g_hash_table_lookup (priv->outstanding_classes_requests,
- connection);
-
- for (l = requests; l != NULL; l = l->next)
- {
- request = l->data;
-
- retval = empathy_dispatcher_find_channel_classes (self,
- connection, request->channel_type,
- request->handle_type, request->properties);
- request->callback (retval, request->user_data);
-
- free_find_channel_request (request);
- g_list_free (retval);
- }
-
- g_list_free (requests);
-
- g_hash_table_remove (priv->outstanding_classes_requests, connection);
-}
-
-static void
-connection_prepare_cb (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- EmpathyDispatcher *self = EMPATHY_DISPATCHER (user_data);
- GError *error = NULL;
- TpConnection *connection = (TpConnection *) source;
-
- if (!tp_proxy_prepare_finish (source, result, &error))
- {
- DEBUG ("Error: %s", error->message);
-
- g_error_free (error);
- goto out;
- }
-
- got_connection_rcc (self, connection);
-
-out:
- g_object_unref (self);
-}
-
-static void
-dispatcher_init_connection_if_needed (EmpathyDispatcher *self,
- TpConnection *connection)
-{
- EmpathyDispatcherPriv *priv = GET_PRIV (self);
- GQuark features[] = { TP_CONNECTION_FEATURE_CORE,
- TP_CONNECTION_FEATURE_CAPABILITIES,
- 0 };
-
- if (g_hash_table_lookup (priv->connections, connection) != NULL)
- return;
-
- g_hash_table_insert (priv->connections, g_object_ref (connection),
- new_connection_data ());
-
- g_signal_connect (connection, "invalidated",
- G_CALLBACK (dispatcher_connection_invalidated_cb), self);
-
- /* Ensure to keep the self object alive while preparing the connection */
- g_object_ref (self);
-
- tp_proxy_prepare_async (connection, features, connection_prepare_cb, self);
-}
-
-static void
-dispatcher_status_changed_cb (TpAccount *account,
- guint old_status,
- guint new_status,
- guint reason,
- gchar *dbus_error_name,
- GHashTable *details,
- EmpathyDispatcher *self)
-{
- TpConnection *conn = tp_account_get_connection (account);
-
- if (conn != NULL)
- dispatcher_init_connection_if_needed (self, conn);
-}
-
-static GObject *
-dispatcher_constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
-{
- GObject *retval;
- EmpathyDispatcherPriv *priv;
-
- if (dispatcher != NULL)
- return g_object_ref (dispatcher);
-
- retval = G_OBJECT_CLASS (empathy_dispatcher_parent_class)->constructor
- (type, n_construct_params, construct_params);
-
- dispatcher = EMPATHY_DISPATCHER (retval);
- g_object_add_weak_pointer (retval, (gpointer) &dispatcher);
-
- priv = GET_PRIV (dispatcher);
-
- return retval;
-}
-
-static void
-dispatcher_dispose (GObject *object)
-{
- EmpathyDispatcherPriv *priv = GET_PRIV (object);
- GHashTableIter iter;
- gpointer connection;
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- g_hash_table_iter_init (&iter, priv->connections);
- while (g_hash_table_iter_next (&iter, &connection, NULL))
- {
- g_signal_handlers_disconnect_by_func (connection,
- dispatcher_connection_invalidated_cb, object);
- }
-
- g_hash_table_destroy (priv->connections);
- priv->connections = NULL;
-
- G_OBJECT_CLASS (empathy_dispatcher_parent_class)->dispose (object);
-}
-
-static void
-dispatcher_finalize (GObject *object)
-{
- EmpathyDispatcherPriv *priv = GET_PRIV (object);
- GHashTableIter iter;
- gpointer connection;
- GList *list;
- gpointer account, id;
-
- g_hash_table_iter_init (&iter, priv->outstanding_classes_requests);
- while (g_hash_table_iter_next (&iter, &connection, (gpointer *) &list))
- {
- g_list_foreach (list, (GFunc) free_find_channel_request, NULL);
- g_list_free (list);
- }
-
- g_hash_table_iter_init (&iter, priv->status_changed_handlers);
- while (g_hash_table_iter_next (&iter, &account, &id))
- {
- g_signal_handler_disconnect (account, GPOINTER_TO_UINT (id));
- }
- g_hash_table_destroy (priv->status_changed_handlers);
-
- g_object_unref (priv->account_manager);
-
- g_hash_table_destroy (priv->outstanding_classes_requests);
-}
-
-static void
-empathy_dispatcher_class_init (EmpathyDispatcherClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->dispose = dispatcher_dispose;
- object_class->finalize = dispatcher_finalize;
- object_class->constructor = dispatcher_constructor;
-
- g_type_class_add_private (object_class, sizeof (EmpathyDispatcherPriv));
-}
-
-static void
-connect_account (EmpathyDispatcher *self,
- TpAccount *account)
-{
- EmpathyDispatcherPriv *priv = GET_PRIV (self);
- TpConnection *conn = tp_account_get_connection (account);
- gulong id;
-
- id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->status_changed_handlers,
- account));
-
- if (id != 0)
- return;
-
- if (conn != NULL)
- dispatcher_status_changed_cb (account, 0, 0, 0, NULL, NULL, self);
-
- id = g_signal_connect (account, "status-changed",
- G_CALLBACK (dispatcher_status_changed_cb), self);
-
- g_hash_table_insert (priv->status_changed_handlers, g_object_ref (account),
- GUINT_TO_POINTER (id));
-}
-
-static void
-account_manager_prepared_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- GList *accounts, *l;
- EmpathyDispatcher *self = user_data;
- TpAccountManager *account_manager = TP_ACCOUNT_MANAGER (source_object);
- GError *error = NULL;
-
- if (!tp_account_manager_prepare_finish (account_manager, result, &error))
- {
- DEBUG ("Failed to prepare account manager: %s", error->message);
- g_error_free (error);
- return;
- }
-
- accounts = tp_account_manager_get_valid_accounts (account_manager);
- for (l = accounts; l; l = l->next)
- {
- TpAccount *a = l->data;
-
- connect_account (self, a);
- }
-
- g_list_foreach (accounts, (GFunc) g_object_ref, NULL);
- g_list_free (accounts);
-}
-
-static void
-account_prepare_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- EmpathyDispatcher *self = user_data;
- TpAccount *account = TP_ACCOUNT (source_object);
- GError *error = NULL;
-
- if (!tp_account_prepare_finish (account, result, &error))
- {
- DEBUG ("Failed to prepare account: %s", error->message);
- g_error_free (error);
- return;
- }
-
- connect_account (self, account);
-}
-
-static void
-account_validity_changed_cb (TpAccountManager *manager,
- TpAccount *account,
- gboolean valid,
- gpointer user_data)
-{
- if (!valid)
- return;
-
- tp_account_prepare_async (account, NULL, account_prepare_cb, user_data);
-}
-
-static void
-empathy_dispatcher_init (EmpathyDispatcher *self)
-{
- EmpathyDispatcherPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- EMPATHY_TYPE_DISPATCHER, EmpathyDispatcherPriv);
-
- self->priv = priv;
- priv->account_manager = tp_account_manager_dup ();
-
- priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- g_object_unref, (GDestroyNotify) free_connection_data);
-
- priv->outstanding_classes_requests = g_hash_table_new_full (g_direct_hash,
- g_direct_equal, g_object_unref, NULL);
-
- tp_account_manager_prepare_async (priv->account_manager, NULL,
- account_manager_prepared_cb, self);
-
- tp_g_signal_connect_object (priv->account_manager,
- "account-validity-changed", G_CALLBACK (account_validity_changed_cb),
- self, 0);
-
- priv->status_changed_handlers = g_hash_table_new_full (NULL, NULL,
- (GDestroyNotify) g_object_unref, NULL);
-}
-
-EmpathyDispatcher *
-empathy_dispatcher_dup_singleton (void)
-{
- return EMPATHY_DISPATCHER (g_object_new (EMPATHY_TYPE_DISPATCHER, NULL));
-}
-
void
empathy_dispatcher_chat_with_contact (EmpathyContact *contact,
gint64 timestamp)
@@ -535,227 +105,3 @@ empathy_dispatcher_join_muc (TpAccount *account,
g_hash_table_unref (request);
g_object_unref (req);
}
-
-static gboolean
-channel_class_matches (GValueArray *class,
- const char *channel_type,
- guint handle_type,
- GArray *fixed_properties)
-{
- GHashTable *fprops;
- GValue *v;
- const char *c_type;
- guint h_type;
- gboolean valid;
-
- v = g_value_array_get_nth (class, 0);
-
- /* if the class doesn't match channel type discard it. */
- fprops = g_value_get_boxed (v);
- c_type = tp_asv_get_string (fprops, TP_IFACE_CHANNEL ".ChannelType");
-
- if (tp_strdiff (channel_type, c_type))
- return FALSE;
-
- /* we have the right channel type, see if the handle type matches */
- h_type = tp_asv_get_uint32 (fprops,
- TP_IFACE_CHANNEL ".TargetHandleType", &valid);
-
- if (!valid || (handle_type != h_type && handle_type != TP_UNKNOWN_HANDLE_TYPE))
- return FALSE;
-
- if (fixed_properties != NULL)
- {
- gpointer h_key, h_val;
- guint idx;
- GHashTableIter iter;
- gboolean found;
-
- g_hash_table_iter_init (&iter, fprops);
-
- while (g_hash_table_iter_next (&iter, &h_key, &h_val))
- {
- /* discard ChannelType and TargetHandleType, as we already
- * checked them.
- */
- if (!tp_strdiff ((char *) h_key, TP_IFACE_CHANNEL ".ChannelType") ||
- !tp_strdiff
- ((char *) h_key, TP_IFACE_CHANNEL ".TargetHandleType"))
- continue;
-
- found = FALSE;
-
- for (idx = 0; idx < fixed_properties->len; idx++)
- {
- /* if |key| doesn't exist in |fixed_properties|, discard
- * the class.
- */
- if (!tp_strdiff
- ((char *) h_key,
- g_array_index (fixed_properties, char *, idx)))
- {
- found = TRUE;
- /* exit the for() loop */
- break;
- }
- }
-
- if (!found)
- return FALSE;
- }
- }
- else
- {
- /* if no fixed_properties are specified, discard the classes
- * with some fixed properties other than the two we already
- * checked.
- */
- if (g_hash_table_size (fprops) > 2)
- return FALSE;
- }
-
- return TRUE;
-}
-
-static GList *
-empathy_dispatcher_find_channel_classes (EmpathyDispatcher *self,
- TpConnection *connection,
- const gchar *channel_type,
- guint handle_type,
- GArray *fixed_properties)
-{
- EmpathyDispatcherPriv *priv = GET_PRIV (self);
- GValueArray *class;
- GPtrArray *classes;
- GList *matching_classes;
- guint i;
- ConnectionData *cd;
-
- g_return_val_if_fail (channel_type != NULL, NULL);
-
- cd = g_hash_table_lookup (priv->connections, connection);
-
- if (cd == NULL)
- return NULL;
-
- classes = cd->requestable_channels;
- if (classes == NULL)
- return NULL;
-
- matching_classes = NULL;
-
- for (i = 0; i < classes->len; i++)
- {
- class = g_ptr_array_index (classes, i);
-
- if (!channel_class_matches
- (class, channel_type, handle_type, fixed_properties))
- continue;
-
- matching_classes = g_list_prepend (matching_classes, class);
- }
-
- return matching_classes;
-}
-
-static GArray *
-setup_varargs (va_list var_args,
- const char *channel_namespace,
- const char *first_property_name)
-{
- const char *name;
- char *name_full;
- GArray *properties;
-
- if (first_property_name == NULL)
- return NULL;
-
- name = first_property_name;
- properties = g_array_new (TRUE, TRUE, sizeof (char *));
-
- while (name != NULL)
- {
- name_full = g_strdup (name);
- properties = g_array_append_val (properties, name_full);
- name = va_arg (var_args, char *);
- }
-
- return properties;
-}
-
-/**
- * empathy_dispatcher_find_requestable_channel_classes:
- * @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, or %TP_UNKNOWN_HANDLE_TYPE
- * if you don't care about the channel's target handle type
- * @first_property_name: %NULL, or the name of the first fixed property,
- * followed optionally by more names, followed by %NULL.
- *
- * Returns all the channel classes that a client can request for the connection
- * @connection, of the type identified by @channel_type, @handle_type and the
- * fixed properties list.
- * The classes which are compatible with a fixed properties list (i.e. those
- * that will be returned by this function) are intended as those that do not
- * contain any fixed property other than those in the list; note that this
- * doesn't guarantee that all the classes compatible with the list will contain
- * all the requested fixed properties, so the clients will have to filter
- * the returned list themselves.
- * If @first_property_name is %NULL, only the classes with no other fixed
- * properties than ChannelType and TargetHandleType will be returned.
- * Note that this function may return %NULL without performing any lookup if
- * @connection is not ready. To ensure that @connection is always ready,
- * use the empathy_dispatcher_find_requestable_channel_classes_async() variant.
- *
- * Return value: a #GList of #GValueArray objects, where the first element in
- * the array is a #GHashTable of the fixed properties, and the second is
- * a #GStrv of the allowed properties for the class. The list should be free'd
- * with g_list_free() when done, but the objects inside the list are owned
- * by the #EmpathyDispatcher and must not be modified.
- */
-GList *
-empathy_dispatcher_find_requestable_channel_classes
- (EmpathyDispatcher *self,
- TpConnection *connection,
- const gchar *channel_type,
- guint handle_type,
- const char *first_property_name,
- ...)
-{
- va_list var_args;
- GArray *properties;
- EmpathyDispatcherPriv *priv;
- GList *retval;
- guint idx;
- char *str;
-
- g_return_val_if_fail (EMPATHY_IS_DISPATCHER (self), NULL);
- g_return_val_if_fail (TP_IS_CONNECTION (connection), NULL);
- g_return_val_if_fail (channel_type != NULL, NULL);
-
- 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);
-
- retval = empathy_dispatcher_find_channel_classes (self, connection,
- channel_type, handle_type, properties);
-
- if (properties != NULL)
- {
- /* free the properties array */
- for (idx = 0; idx < properties->len ; idx++)
- {
- str = g_array_index (properties, char *, idx);
- g_free (str);
- }
-
- g_array_free (properties, TRUE);
- }
-
- return retval;
-}