diff options
author | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2011-04-22 14:27:15 +0200 |
---|---|---|
committer | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2011-05-16 11:03:55 +0200 |
commit | 59b10772153ec4cef86131193c1c5342b674b0ae (patch) | |
tree | 02376e5cabe7ff65c5b20c495ca31d8ec4bd3bec | |
parent | 235742058d624f9b90507bb47ce53a9c0ec17cda (diff) |
add tp_base_client_delegate_channels_{async,finish} (fdo #34610)
-rw-r--r-- | docs/reference/telepathy-glib-sections.txt | 2 | ||||
-rw-r--r-- | telepathy-glib/base-client.c | 123 | ||||
-rw-r--r-- | telepathy-glib/base-client.h | 11 | ||||
-rw-r--r-- | tests/dbus/base-client.c | 104 | ||||
-rw-r--r-- | tests/lib/simple-channel-dispatcher.c | 13 |
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 } |