summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-05-27 13:05:27 +0200
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-05-27 13:05:27 +0200
commit396d10c4d48f9b36822ec4a34f104473d7e013c7 (patch)
tree20c95f87b30cf8dac8dc9bb64534eb869fa17735
parent4054e4d9d2d0c325f9a9ba545f3d58545d9a97ff (diff)
parentded16605feb6f6bc70b57e9cf8a9674b1176cba3 (diff)
downloadtelepathy-glib-396d10c4d48f9b36822ec4a34f104473d7e013c7.tar.gz
Merge branch 'cdo-reject-28015'
-rw-r--r--docs/reference/telepathy-glib-sections.txt2
-rw-r--r--telepathy-glib/channel-dispatch-operation.c210
-rw-r--r--telepathy-glib/channel-dispatch-operation.h12
-rw-r--r--tests/dbus/channel-dispatch-operation.c53
4 files changed, 255 insertions, 22 deletions
diff --git a/docs/reference/telepathy-glib-sections.txt b/docs/reference/telepathy-glib-sections.txt
index 8084b2f77..fc49aac63 100644
--- a/docs/reference/telepathy-glib-sections.txt
+++ b/docs/reference/telepathy-glib-sections.txt
@@ -4548,6 +4548,8 @@ tp_channel_dispatch_operation_claim_async
tp_channel_dispatch_operation_claim_finish
tp_channel_dispatch_operation_claim_with_async
tp_channel_dispatch_operation_claim_with_finish
+tp_channel_dispatch_operation_close_channels_async
+tp_channel_dispatch_operation_close_channels_finish
<SUBSECTION Standard>
TP_CHANNEL_DISPATCH_OPERATION
TP_CHANNEL_DISPATCH_OPERATION_CLASS
diff --git a/telepathy-glib/channel-dispatch-operation.c b/telepathy-glib/channel-dispatch-operation.c
index 340616ecb..a3bbe1294 100644
--- a/telepathy-glib/channel-dispatch-operation.c
+++ b/telepathy-glib/channel-dispatch-operation.c
@@ -1394,50 +1394,129 @@ gboolean
}
static void
-claim_with_cb (GObject *source,
+claim_with_cb (TpChannelDispatchOperation *self,
+ GSimpleAsyncResult *result)
+{
+ TpBaseClient *client;
+
+ client = g_simple_async_result_get_op_res_gpointer (result);
+
+ _tp_base_client_now_handling_channels (client, self->priv->channels);
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+}
+
+typedef void (*PrepareCoreAndClaimCb) (TpChannelDispatchOperation *self,
+ GSimpleAsyncResult *result);
+
+typedef struct
+{
+ GSimpleAsyncResult *result;
+ PrepareCoreAndClaimCb callback;
+} PrepareCoreAndClaimCtx;
+
+static PrepareCoreAndClaimCtx *
+prepare_core_and_claim_ctx_new (GSimpleAsyncResult *result,
+ PrepareCoreAndClaimCb callback)
+{
+ PrepareCoreAndClaimCtx *ctx = g_slice_new (PrepareCoreAndClaimCtx);
+
+ ctx->result = g_object_ref (result);
+ ctx->callback = callback;
+ return ctx;
+}
+
+static void
+prepare_core_and_claim_ctx_free (PrepareCoreAndClaimCtx *ctx)
+{
+ g_object_unref (ctx->result);
+ g_slice_free (PrepareCoreAndClaimCtx, ctx);
+}
+
+/* Takes ownership of @error */
+static void
+prepare_core_and_claim_ctx_failed (PrepareCoreAndClaimCtx *ctx,
+ GError *error)
+{
+ g_simple_async_result_take_error (ctx->result, error);
+ g_simple_async_result_complete (ctx->result);
+
+ /* We received a reference on result from the caller and was supposed to
+ * give it back when calling the callback. But as something went wrong, we
+ * terminate the operation ourself and so don't call the callback, so we
+ * have to drop this reference. */
+ g_object_unref (ctx->result);
+ prepare_core_and_claim_ctx_free (ctx);
+}
+
+static void
+prepare_core_claim_cb (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
TpChannelDispatchOperation *self = (TpChannelDispatchOperation *) source;
- GSimpleAsyncResult *main_result = user_data;
+ PrepareCoreAndClaimCtx *ctx = user_data;
GError *error = NULL;
- TpBaseClient *client;
if (!tp_channel_dispatch_operation_claim_finish (self, result, &error))
{
- g_simple_async_result_take_error (main_result, error);
- goto out;
- }
+ DEBUG ("Failed to Claim %s: %s",
+ tp_proxy_get_object_path (self), error->message);
- client = g_simple_async_result_get_op_res_gpointer (main_result);
+ prepare_core_and_claim_ctx_failed (ctx, error);
+ return;
+ }
- _tp_base_client_now_handling_channels (client, self->priv->channels);
+ /* Pass back the ref we got from the caller */
+ ctx->callback (self, ctx->result);
-out:
- g_simple_async_result_complete (main_result);
- g_object_unref (main_result);
+ prepare_core_and_claim_ctx_free (ctx);
}
static void
-claim_with_prepare_cb (GObject *source,
+prepare_core_cb (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
TpChannelDispatchOperation *self = (TpChannelDispatchOperation *) source;
- GSimpleAsyncResult *main_result = user_data;
+ PrepareCoreAndClaimCtx *ctx = user_data;
GError *error = NULL;
if (!tp_proxy_prepare_finish (self, result, &error))
{
- g_simple_async_result_take_error (main_result, error);
- g_simple_async_result_complete (main_result);
- g_object_unref (main_result);
+ DEBUG ("Failed to prepare CORE on %s: %s",
+ tp_proxy_get_object_path (self), error->message);
+
+ prepare_core_and_claim_ctx_failed (ctx, error);
return;
}
- tp_channel_dispatch_operation_claim_async (self, claim_with_cb, main_result);
+ tp_channel_dispatch_operation_claim_async (self, prepare_core_claim_cb, ctx);
}
+/* Prepare CORE feature on @self and then call Claim() on it.
+ * If either the preparation or the call failed, complete @result with the
+ * error.
+ * If everything goes fine call @callback.
+ *
+ * Takes the reference on @result and pass it back to @callback.
+ */
+static void
+prepare_core_and_claim (TpChannelDispatchOperation *self,
+ PrepareCoreAndClaimCb callback,
+ GSimpleAsyncResult *result)
+{
+ GQuark features[] = { TP_CHANNEL_DISPATCH_OPERATION_FEATURE_CORE, 0 };
+ PrepareCoreAndClaimCtx *ctx;
+
+ ctx = prepare_core_and_claim_ctx_new (result, callback);
+
+ /* We have to prepare the CDO to be able to get the list of its channels.
+ * We prepare it *before* calling Claim() as MC will destroy the CDO once it
+ * has been claimed. */
+ tp_proxy_prepare_async (self, features, prepare_core_cb, ctx);
+}
/**
* tp_channel_dispatch_operation_claim_with_async:
@@ -1472,7 +1551,6 @@ tp_channel_dispatch_operation_claim_with_async (
gpointer user_data)
{
GSimpleAsyncResult *result;
- GQuark features[] = { TP_CHANNEL_DISPATCH_OPERATION_FEATURE_CORE, 0 };
g_return_if_fail (TP_IS_CHANNEL_DISPATCH_OPERATION (self));
@@ -1483,10 +1561,7 @@ tp_channel_dispatch_operation_claim_with_async (
g_simple_async_result_set_op_res_gpointer (result, g_object_ref (client),
g_object_unref);
- /* We have to prepare the CDO to be able to get the list of its channels.
- * We prepare it *before* calling Claim() as MC will destroy the CDO once it
- * has been claimed. */
- tp_proxy_prepare_async (self, features, claim_with_prepare_cb, result);
+ prepare_core_and_claim (self, claim_with_cb, result);
}
/**
@@ -1511,3 +1586,94 @@ tp_channel_dispatch_operation_claim_with_finish (
_tp_implement_finish_void (self, \
tp_channel_dispatch_operation_claim_with_async)
}
+
+static void
+channel_close_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ if (!tp_channel_close_finish (TP_CHANNEL (source), result, &error))
+ {
+ DEBUG ("Failed to close %s: %s", tp_proxy_get_object_path (source),
+ error->message);
+
+ g_error_free (error);
+ }
+}
+
+static void
+claim_close_channels_cb (TpChannelDispatchOperation *self,
+ GSimpleAsyncResult *result)
+{
+ guint i;
+
+ for (i = 0; i < self->priv->channels->len; i++)
+ {
+ TpChannel *channel = g_ptr_array_index (self->priv->channels, i);
+
+ tp_channel_close_async (channel, channel_close_cb, NULL);
+ }
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+}
+
+/**
+ * tp_channel_dispatch_operation_close_channels_async:
+ * @self: a #TpChannelDispatchOperation
+ * @callback: a callback to call when the request has been satisfied
+ * @user_data: data to pass to @callback
+ *
+ * Called by an approver to claim channels and close them all right away.
+ * If this method is called successfully, @self has been claimed and
+ * tp_channel_close_async() has been called on all of its channels.
+ *
+ * If successful, this method will cause the #TpProxy::invalidated signal
+ * to be emitted, in the same way as for
+ * tp_channel_dispatch_operation_handle_with_async().
+ *
+ * This method may fail because the dispatch operation has already
+ * been completed. Again, see tp_channel_dispatch_operation_handle_with_async()
+ * for more details.
+ *
+ * Since: 0.15.UNRELEASED
+ */
+void
+tp_channel_dispatch_operation_close_channels_async (
+ TpChannelDispatchOperation *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+
+ result = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ tp_channel_dispatch_operation_close_channels_async);
+
+ prepare_core_and_claim (self, claim_close_channels_cb, result);
+}
+
+/**
+ * tp_channel_dispatch_operation_close_channels_finish:
+ * @self: a #TpChannelDispatchOperation
+ * @result: a #GAsyncResult
+ * @error: a #GError to fill
+ *
+ * Finishes an async operation initiated using
+ * tp_channel_dispatch_operation_close_channels_finish().
+ *
+ * Returns: %TRUE if the Claim() call was successful and
+ * Close() has at least been attempted on all the channels, otherwise %FALSE
+ *
+ * Since: 0.15.UNRELEASED
+ */
+gboolean
+tp_channel_dispatch_operation_close_channels_finish (
+ TpChannelDispatchOperation *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ _tp_implement_finish_void (self, \
+ tp_channel_dispatch_operation_close_channels_async)
+}
diff --git a/telepathy-glib/channel-dispatch-operation.h b/telepathy-glib/channel-dispatch-operation.h
index 605f98f0d..387496d9a 100644
--- a/telepathy-glib/channel-dispatch-operation.h
+++ b/telepathy-glib/channel-dispatch-operation.h
@@ -142,6 +142,18 @@ gboolean tp_channel_dispatch_operation_claim_with_finish (
GAsyncResult *result,
GError **error);
+/* Reject API */
+
+void tp_channel_dispatch_operation_close_channels_async (
+ TpChannelDispatchOperation *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean tp_channel_dispatch_operation_close_channels_finish (
+ TpChannelDispatchOperation *self,
+ GAsyncResult *result,
+ GError **error);
+
G_END_DECLS
#include <telepathy-glib/_gen/tp-cli-channel-dispatch-operation.h>
diff --git a/tests/dbus/channel-dispatch-operation.c b/tests/dbus/channel-dispatch-operation.c
index 4f7f9e277..fa57d5da8 100644
--- a/tests/dbus/channel-dispatch-operation.c
+++ b/tests/dbus/channel-dispatch-operation.c
@@ -779,6 +779,57 @@ test_handle_with_time (Test *test,
g_assert_no_error (test->error);
}
+static void
+close_channels_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ Test *test = user_data;
+
+ tp_channel_dispatch_operation_close_channels_finish (
+ TP_CHANNEL_DISPATCH_OPERATION (source), result, &test->error);
+
+ test->sig--;
+ if (test->sig == 0)
+ g_main_loop_quit (test->mainloop);
+}
+
+static void
+channel_invalidated_cb (TpProxy *proxy,
+ guint domain,
+ gint code,
+ gchar *message,
+ gpointer user_data)
+{
+ Test *test = user_data;
+
+ test->sig--;
+ if (test->sig == 0)
+ g_main_loop_quit (test->mainloop);
+}
+
+static void
+test_close_channels (Test *test,
+ gconstpointer data G_GNUC_UNUSED)
+{
+ test->cdo = tp_channel_dispatch_operation_new (test->dbus,
+ "/whatever", NULL, &test->error);
+ g_assert_no_error (test->error);
+
+ g_signal_connect (test->text_chan, "invalidated",
+ G_CALLBACK (channel_invalidated_cb), test);
+ g_signal_connect (test->text_chan_2, "invalidated",
+ G_CALLBACK (channel_invalidated_cb), test);
+
+ tp_channel_dispatch_operation_close_channels_async (test->cdo,
+ close_channels_cb, test);
+
+ test->sig = 3;
+ g_main_loop_run (test->mainloop);
+
+ g_assert_no_error (test->error);
+}
+
int
main (int argc,
char **argv)
@@ -805,6 +856,8 @@ main (int argc,
test_finished_preparing, teardown_services);
g_test_add ("/cdo/handle-with-time", Test, NULL, setup_services,
test_handle_with_time, teardown_services);
+ g_test_add ("/cdo/close-channels", Test, NULL, setup_services,
+ test_close_channels, teardown_services);
return g_test_run ();
}