summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-04-22 14:27:15 +0200
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-05-16 11:03:55 +0200
commit59b10772153ec4cef86131193c1c5342b674b0ae (patch)
tree02376e5cabe7ff65c5b20c495ca31d8ec4bd3bec
parent235742058d624f9b90507bb47ce53a9c0ec17cda (diff)
add tp_base_client_delegate_channels_{async,finish} (fdo #34610)
-rw-r--r--docs/reference/telepathy-glib-sections.txt2
-rw-r--r--telepathy-glib/base-client.c123
-rw-r--r--telepathy-glib/base-client.h11
-rw-r--r--tests/dbus/base-client.c104
-rw-r--r--tests/lib/simple-channel-dispatcher.c13
5 files changed, 253 insertions, 0 deletions
diff --git a/docs/reference/telepathy-glib-sections.txt b/docs/reference/telepathy-glib-sections.txt
index cac884b5..c188be73 100644
--- a/docs/reference/telepathy-glib-sections.txt
+++ b/docs/reference/telepathy-glib-sections.txt
@@ -4806,6 +4806,8 @@ tp_base_client_add_channel_features
tp_base_client_add_channel_features_varargs
tp_base_client_get_handled_channels
tp_base_client_is_handling_channel
+tp_base_client_delegate_channels_async
+tp_base_client_delegate_channels_finish
tp_base_client_get_pending_requests
tp_base_client_set_handler_bypass_approval
tp_base_client_set_handler_request_notification
diff --git a/telepathy-glib/base-client.c b/telepathy-glib/base-client.c
index 9f82b905..d6ef3596 100644
--- a/telepathy-glib/base-client.c
+++ b/telepathy-glib/base-client.c
@@ -169,6 +169,7 @@
#include <telepathy-glib/add-dispatch-operation-context-internal.h>
#include <telepathy-glib/automatic-proxy-factory.h>
#include <telepathy-glib/channel-dispatch-operation-internal.h>
+#include <telepathy-glib/channel-dispatcher.h>
#include <telepathy-glib/channel-request.h>
#include <telepathy-glib/channel.h>
#include <telepathy-glib/dbus-internal.h>
@@ -2805,3 +2806,125 @@ _tp_base_client_now_handling_channels (TpBaseClient *self,
if (self->priv->flags & CLIENT_IS_HANDLER)
add_handled_channels (self, channels);
}
+
+static void
+delegate_channels_cb (TpChannelDispatcher *cd,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ GSimpleAsyncResult *result = user_data;
+ TpBaseClient *self = (TpBaseClient *) weak_object;
+
+ if (error != NULL)
+ {
+ g_simple_async_result_set_from_error (result, error);
+ }
+ else
+ {
+ /* We are not longer handling the channels */
+ GPtrArray *chans;
+ guint i;
+
+ chans = g_simple_async_result_get_op_res_gpointer (result);
+
+ for (i = 0; i < chans->len; i++)
+ {
+ const gchar *path = g_ptr_array_index (chans, i);
+
+ g_hash_table_remove (self->priv->my_chans, path);
+ }
+ }
+
+ g_simple_async_result_complete (result);
+}
+
+/**
+ * tp_base_client_delegate_channels_async:
+ * @self: a #TpBaseClient
+ * @channels: (element-type TelepathyGLib.Channel): a #GList of #TpChannel
+ * handled by @self
+ * @user_action_time: the time at which user action occurred,
+ * or #TP_USER_ACTION_TIME_NOT_USER_ACTION if this delegation request is
+ * for some reason not involving user action.
+ * @preferred_handler: Either the well-known bus name (starting with
+ * %TP_CLIENT_BUS_NAME_BASE) of the preferred handler for the channels,
+ * or %NULL to indicate that any handler but @self would be acceptable.
+ * @callback: a callback to call when the request is satisfied
+ * @user_data: data to pass to @callback
+ *
+ * Asynchronously calls DelegateChannels on the ChannelDispatcher to try
+ * stopping handling @channels and pass them to another Handler.
+ * You can then call tp_base_client_delegate_channels_finish() to
+ * get the result of the operation.
+ *
+ * Since: 0.15.UNRELEASED
+ */
+void
+tp_base_client_delegate_channels_async (TpBaseClient *self,
+ GList *channels,
+ gint64 user_action_time,
+ const gchar *preferred_handler,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ TpChannelDispatcher *cd;
+ GPtrArray *chans;
+ GList *l;
+ GSimpleAsyncResult *result;
+
+ g_return_if_fail (TP_IS_BASE_CLIENT (self));
+ g_return_if_fail (self->priv->flags & CLIENT_IS_HANDLER);
+
+ cd = tp_channel_dispatcher_new (self->priv->dbus);
+
+ chans = g_ptr_array_sized_new (g_list_length (channels));
+ g_ptr_array_set_free_func (chans, g_free);
+
+ for (l = channels; l != NULL; l = g_list_next (l))
+ {
+ TpChannel *channel = l->data;
+
+ g_return_if_fail (TP_IS_CHANNEL (channel));
+
+ g_ptr_array_add (chans, g_strdup (tp_proxy_get_object_path (channel)));
+ }
+
+ result = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ tp_base_client_delegate_channels_async);
+
+ g_simple_async_result_set_op_res_gpointer (result, chans,
+ (GDestroyNotify) g_ptr_array_unref);
+
+ /* DelegateChannels() can takes a while if, for example, some clients are
+ * crashing and so MC has to wait for them to time out before calling the
+ * next handler. Set a timeout of 2 minutes. */
+ tp_cli_channel_dispatcher_call_delegate_channels (cd, 1000 * 60 * 2,
+ chans, user_action_time,
+ preferred_handler == NULL ? "" : preferred_handler,
+ delegate_channels_cb, result, g_object_unref, G_OBJECT (self));
+
+ g_object_unref (cd);
+}
+
+/**
+ * tp_base_client_delegate_channels_finish:
+ * @self: a #TpBaseClient
+ * @result: a #GAsyncResult
+ * @error: a #GError to fill
+ *
+ * Finishes an async channels delegation request started using
+ * tp_base_client_delegate_channels_async().
+ *
+ * Returns: %TRUE if @self is not longer the handler of the channels,
+ * otherwise %FALSE.
+ *
+ * Since: 0.15.UNRELEASED
+ */
+gboolean
+tp_base_client_delegate_channels_finish (TpBaseClient *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ _tp_implement_finish_void (self, tp_base_client_delegate_channels_async)
+}
diff --git a/telepathy-glib/base-client.h b/telepathy-glib/base-client.h
index 192a3222..b1dc48a0 100644
--- a/telepathy-glib/base-client.h
+++ b/telepathy-glib/base-client.h
@@ -176,6 +176,17 @@ GList *tp_base_client_get_handled_channels (TpBaseClient *self);
gboolean tp_base_client_is_handling_channel (TpBaseClient *self,
TpChannel *channel);
+void tp_base_client_delegate_channels_async (TpBaseClient *self,
+ GList *channels,
+ gint64 user_action_time,
+ const gchar *preferred_handler,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean tp_base_client_delegate_channels_finish (TpBaseClient *self,
+ GAsyncResult *result,
+ GError **error);
+
const gchar *tp_base_client_get_name (TpBaseClient *self);
gboolean tp_base_client_get_uniquify_name (TpBaseClient *self);
const gchar *tp_base_client_get_bus_name (TpBaseClient *self);
diff --git a/tests/dbus/base-client.c b/tests/dbus/base-client.c
index 6e3c2581..cf48e02f 100644
--- a/tests/dbus/base-client.c
+++ b/tests/dbus/base-client.c
@@ -22,6 +22,7 @@
#include "tests/lib/util.h"
#include "tests/lib/simple-account.h"
#include "tests/lib/simple-channel-dispatch-operation.h"
+#include "tests/lib/simple-channel-dispatcher.h"
#include "tests/lib/simple-client.h"
#include "tests/lib/simple-conn.h"
#include "tests/lib/textchan-null.h"
@@ -38,6 +39,7 @@ typedef struct {
TpTestsTextChannelNull *text_chan_service;
TpTestsTextChannelNull *text_chan_service_2;
TpTestsSimpleChannelDispatchOperation *cdo_service;
+ TpTestsSimpleChannelDispatcher *cd_service;
/* Client side objects */
TpAccountManager *account_mgr;
@@ -179,6 +181,15 @@ setup (Test *test,
g_assert (tp_dbus_daemon_request_name (test->dbus,
TP_CHANNEL_DISPATCHER_BUS_NAME, FALSE, NULL));
+
+ /* Create and register CD */
+ test->cd_service = tp_tests_object_new_static_class (
+ TP_TESTS_TYPE_SIMPLE_CHANNEL_DISPATCHER,
+ "connection", test->base_connection,
+ NULL);
+
+ tp_dbus_daemon_register_object (test->dbus, TP_CHANNEL_DISPATCHER_OBJECT_PATH,
+ test->cd_service);
}
static void
@@ -251,6 +262,8 @@ teardown (Test *test,
g_object_unref (test->connection);
g_object_unref (test->base_connection);
+
+ tp_clear_object (&test->cd_service);
}
/* Test Basis */
@@ -1214,6 +1227,95 @@ test_channel_dispatch_operation_claim_with_async (Test *test,
g_hash_table_unref (properties);
}
+static void
+delegate_channels_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ Test *test = user_data;
+
+ tp_base_client_delegate_channels_finish (
+ TP_BASE_CLIENT (source), result, &test->error);
+
+ test->wait--;
+ if (test->wait == 0)
+ g_main_loop_quit (test->mainloop);
+}
+
+static void
+test_delegate_channels (Test *test,
+ gconstpointer data G_GNUC_UNUSED)
+{
+ GPtrArray *channels;
+ GPtrArray *requests_satisified;
+ GHashTable *info;
+ GList *chans;
+
+ tp_base_client_be_a_handler (test->base_client);
+
+ tp_base_client_register (test->base_client, &test->error);
+ g_assert_no_error (test->error);
+
+ /* Call HandleChannels */
+ channels = g_ptr_array_sized_new (2);
+ add_channel_to_ptr_array (channels, test->text_chan);
+ add_channel_to_ptr_array (channels, test->text_chan_2);
+
+ requests_satisified = g_ptr_array_sized_new (0);
+ info = g_hash_table_new (NULL, NULL);
+
+ tp_proxy_add_interface_by_id (TP_PROXY (test->client),
+ TP_IFACE_QUARK_CLIENT_HANDLER);
+
+ tp_cli_client_handler_call_handle_channels (test->client, -1,
+ tp_proxy_get_object_path (test->account),
+ tp_proxy_get_object_path (test->connection),
+ channels, requests_satisified, 0, info,
+ no_return_cb, test, NULL, NULL);
+
+ test->wait++;
+ g_main_loop_run (test->mainloop);
+ g_assert_no_error (test->error);
+
+ /* The client is handling the 2 channels */
+ chans = tp_base_client_get_handled_channels (test->base_client);
+ g_assert_cmpuint (g_list_length (chans), ==, 2);
+ g_list_free (chans);
+
+ g_assert (tp_base_client_is_handling_channel (test->base_client,
+ test->text_chan));
+ g_assert (tp_base_client_is_handling_channel (test->base_client,
+ test->text_chan_2));
+
+ /* Try to delegate the first one */
+ chans = g_list_append (NULL, test->text_chan);
+
+ tp_base_client_delegate_channels_async (test->base_client,
+ chans, TP_USER_ACTION_TIME_CURRENT_TIME, NULL,
+ delegate_channels_cb, test);
+
+ g_list_free (chans);
+
+ test->wait++;
+ g_main_loop_run (test->mainloop);
+ g_assert_no_error (test->error);
+
+ /* Client is not handling the channel any more */
+ chans = tp_base_client_get_handled_channels (test->base_client);
+ g_assert_cmpuint (g_list_length (chans), ==, 1);
+ g_list_free (chans);
+
+ g_assert (!tp_base_client_is_handling_channel (test->base_client,
+ test->text_chan));
+ g_assert (tp_base_client_is_handling_channel (test->base_client,
+ test->text_chan_2));
+
+ g_ptr_array_foreach (channels, free_channel_details, NULL);
+ g_ptr_array_free (channels, TRUE);
+ g_ptr_array_free (requests_satisified, TRUE);
+ g_hash_table_unref (info);
+}
+
int
main (int argc,
char **argv)
@@ -1235,6 +1337,8 @@ main (int argc,
test_handler_requests, teardown);
g_test_add ("/cdo/claim_with", Test, NULL, setup,
test_channel_dispatch_operation_claim_with_async, teardown);
+ g_test_add ("/base-client/delegate-channels", Test, NULL, setup,
+ test_delegate_channels, teardown);
return g_test_run ();
}
diff --git a/tests/lib/simple-channel-dispatcher.c b/tests/lib/simple-channel-dispatcher.c
index 9b2c9664..03873cd7 100644
--- a/tests/lib/simple-channel-dispatcher.c
+++ b/tests/lib/simple-channel-dispatcher.c
@@ -246,6 +246,18 @@ tp_tests_simple_channel_dispatcher_ensure_channel_with_hints (
g_free (path);
}
+
+static void
+tp_tests_simple_channel_dispatcher_delegate_channels (
+ TpSvcChannelDispatcher *dispatcher,
+ const GPtrArray *channels,
+ gint64 user_action_time,
+ const gchar *preferred_handler,
+ DBusGMethodInvocation *context)
+{
+ tp_svc_channel_dispatcher_return_from_delegate_channels (context);
+}
+
static void
channel_dispatcher_iface_init (gpointer klass,
gpointer unused G_GNUC_UNUSED)
@@ -256,6 +268,7 @@ channel_dispatcher_iface_init (gpointer klass,
IMPLEMENT (ensure_channel);
IMPLEMENT (create_channel_with_hints);
IMPLEMENT (ensure_channel_with_hints);
+ IMPLEMENT (delegate_channels);
#undef IMPLEMENT
}