From ddb451a71569bdd6b7d9a673d12e8e83eddb818e Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Sat, 22 Jun 2013 19:10:10 +0100 Subject: console: turn it into an actual channel --- plugins/console/channel-manager.c | 103 ++++++++++++++++++++++++++++++++++++-- plugins/console/channel-manager.h | 1 + plugins/console/plugin.c | 59 ---------------------- plugins/console/sidecar.c | 61 +++++++++++----------- tests/twisted/console.py | 7 ++- 5 files changed, 134 insertions(+), 97 deletions(-) diff --git a/plugins/console/channel-manager.c b/plugins/console/channel-manager.c index 44f4a8b6d..b2a17902d 100644 --- a/plugins/console/channel-manager.c +++ b/plugins/console/channel-manager.c @@ -21,6 +21,7 @@ #include "console/channel-manager.h" #include "extensions/extensions.h" +#include "console/sidecar.h" static void channel_manager_iface_init (gpointer, gpointer); @@ -80,6 +81,23 @@ gabble_console_channel_manager_get_property ( } } + +static void +gabble_console_channel_manager_dispose ( + GObject *object) +{ + GabbleConsoleChannelManager *self = GABBLE_CONSOLE_CHANNEL_MANAGER (object); + TpBaseChannel *channel; + + while ((channel = g_queue_peek_head (&self->console_channels)) != NULL) + { + tp_base_channel_close (channel); + } + + G_OBJECT_CLASS (gabble_console_channel_manager_parent_class)->dispose (object); +} + + static void gabble_console_channel_manager_class_init (GabbleConsoleChannelManagerClass *klass) { @@ -87,6 +105,7 @@ gabble_console_channel_manager_class_init (GabbleConsoleChannelManagerClass *kla oclass->set_property = gabble_console_channel_manager_set_property; oclass->get_property = gabble_console_channel_manager_get_property; + oclass->dispose = gabble_console_channel_manager_dispose; g_object_class_install_property (oclass, PROP_CONNECTION, g_param_spec_object ("plugin-connection", "Gabble Plugin Connection", @@ -95,6 +114,13 @@ gabble_console_channel_manager_class_init (GabbleConsoleChannelManagerClass *kla G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); } + +static const gchar * const allowed[] = { + TP_PROP_CHANNEL_CHANNEL_TYPE, + TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, + NULL +}; + static void gabble_console_channel_manager_type_foreach_channel_class (GType type, TpChannelManagerTypeChannelClassFunc func, @@ -110,6 +136,77 @@ gabble_console_channel_manager_type_foreach_channel_class (GType type, g_hash_table_unref (table); } + +static void +console_channel_closed_cb ( + GabbleConsoleSidecar *channel, + gpointer user_data) +{ + GabbleConsoleChannelManager *self = GABBLE_CONSOLE_CHANNEL_MANAGER (user_data); + + tp_channel_manager_emit_channel_closed_for_object (self, + TP_EXPORTABLE_CHANNEL (channel)); + + if (g_queue_remove (&self->console_channels, channel)) + { + g_object_unref (channel); + } +} + + +static gboolean +gabble_console_channel_manager_create_channel ( + TpChannelManager *manager, + gpointer request_token, + GHashTable *request_properties) +{ + GabbleConsoleChannelManager *self = GABBLE_CONSOLE_CHANNEL_MANAGER (manager); + TpBaseChannel *channel = NULL; + GError *error = NULL; + GSList *request_tokens; + + if (tp_strdiff (tp_asv_get_string (request_properties, + TP_IFACE_CHANNEL ".ChannelType"), + GABBLE_IFACE_GABBLE_PLUGIN_CONSOLE)) + return FALSE; + + if (tp_asv_get_uint32 (request_properties, + TP_IFACE_CHANNEL ".TargetHandleType", NULL) != 0) + { + g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, + "Console channels can't have a target handle"); + goto error; + } + + if (tp_channel_manager_asv_has_unknown_properties (request_properties, + allowed, + allowed, + &error)) + goto error; + + channel = g_object_new (GABBLE_TYPE_CONSOLE_SIDECAR, + "connection", self->plugin_connection, + NULL); + tp_base_channel_register (channel); + g_signal_connect (channel, "closed", (GCallback) console_channel_closed_cb, + self); + g_queue_push_tail (&self->console_channels, channel); + + request_tokens = g_slist_prepend (NULL, request_token); + tp_channel_manager_emit_new_channel (self, + TP_EXPORTABLE_CHANNEL (channel), request_tokens); + g_slist_free (request_tokens); + + return TRUE; + +error: + tp_channel_manager_emit_request_failed (self, request_token, + error->domain, error->code, error->message); + g_error_free (error); + return TRUE; +} + + static void channel_manager_iface_init (gpointer g_iface, gpointer iface_data) @@ -117,9 +214,5 @@ channel_manager_iface_init (gpointer g_iface, TpChannelManagerIface *iface = g_iface; iface->type_foreach_channel_class = gabble_console_channel_manager_type_foreach_channel_class; - - /* not requestable. */ - iface->ensure_channel = NULL; - iface->create_channel = NULL; - iface->request_channel = NULL; + iface->create_channel = gabble_console_channel_manager_create_channel; } diff --git a/plugins/console/channel-manager.h b/plugins/console/channel-manager.h index a876a7b14..8ec4adc0a 100644 --- a/plugins/console/channel-manager.h +++ b/plugins/console/channel-manager.h @@ -31,6 +31,7 @@ struct _GabbleConsoleChannelManager { GObject parent; GabblePluginConnection *plugin_connection; + GQueue console_channels; }; GType gabble_console_channel_manager_get_type (void); diff --git a/plugins/console/plugin.c b/plugins/console/plugin.c index 222c58378..52386016d 100644 --- a/plugins/console/plugin.c +++ b/plugins/console/plugin.c @@ -53,62 +53,6 @@ gabble_console_plugin_class_init (GabbleConsolePluginClass *klass) { } -static void -gabble_console_plugin_create_sidecar_async ( - GabblePlugin *plugin, - const gchar *sidecar_interface, - GabblePluginConnection *connection, - WockySession *session, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (plugin), - callback, user_data, - gabble_console_plugin_create_sidecar_async); - GabbleSidecar *sidecar = NULL; - - if (!tp_strdiff (sidecar_interface, GABBLE_IFACE_GABBLE_PLUGIN_CONSOLE)) - { - sidecar = g_object_new (GABBLE_TYPE_CONSOLE_SIDECAR, - "connection", connection, - "session", session, - NULL); - } - else - { - g_simple_async_result_set_error (result, TP_ERROR, - TP_ERROR_NOT_IMPLEMENTED, "'%s' not implemented", sidecar_interface); - } - - if (sidecar != NULL) - g_simple_async_result_set_op_res_gpointer (result, sidecar, - g_object_unref); - - g_simple_async_result_complete_in_idle (result); - g_object_unref (result); -} - -static GabbleSidecar * -gabble_console_plugin_create_sidecar_finish ( - GabblePlugin *plugin, - GAsyncResult *result, - GError **error) -{ - GabbleSidecar *sidecar; - - if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), - error)) - return NULL; - - g_return_val_if_fail (g_simple_async_result_is_valid (result, - G_OBJECT (plugin), gabble_console_plugin_create_sidecar_async), NULL); - - sidecar = GABBLE_SIDECAR (g_simple_async_result_get_op_res_gpointer ( - G_SIMPLE_ASYNC_RESULT (result))); - - return g_object_ref (sidecar); -} - static GPtrArray * gabble_console_plugin_create_channel_managers (GabblePlugin *plugin, GabblePluginConnection *plugin_connection) @@ -132,9 +76,6 @@ plugin_iface_init ( iface->name = "XMPP console"; iface->version = PACKAGE_VERSION; - iface->sidecar_interfaces = sidecar_interfaces; - iface->create_sidecar_async = gabble_console_plugin_create_sidecar_async; - iface->create_sidecar_finish = gabble_console_plugin_create_sidecar_finish; iface->create_channel_managers = gabble_console_plugin_create_channel_managers; } diff --git a/plugins/console/sidecar.c b/plugins/console/sidecar.c index 5484a3ca0..b224b7f48 100644 --- a/plugins/console/sidecar.c +++ b/plugins/console/sidecar.c @@ -29,7 +29,6 @@ enum { PROP_0, - PROP_SESSION, PROP_SPEW }; @@ -50,23 +49,18 @@ struct _GabbleConsoleSidecarPrivate gulong sending_id; }; -static void sidecar_iface_init ( - gpointer g_iface, - gpointer data); static void console_iface_init ( gpointer g_iface, gpointer data); static void gabble_console_sidecar_set_spew ( GabbleConsoleSidecar *self, gboolean spew); +static void gabble_console_sidecar_close (TpBaseChannel *chan); G_DEFINE_TYPE_WITH_CODE (GabbleConsoleSidecar, gabble_console_sidecar, TP_TYPE_BASE_CHANNEL, - G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SIDECAR, sidecar_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_GABBLE_PLUGIN_CONSOLE, console_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, - tp_dbus_properties_mixin_iface_init); ) static void @@ -79,6 +73,25 @@ gabble_console_sidecar_init (GabbleConsoleSidecar *self) self->priv->writer = wocky_xmpp_writer_new_no_stream (); } + +static void +gabble_console_sidecar_constructed (GObject *object) +{ + GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (object); + void (*chain_up)(GObject *) = + G_OBJECT_CLASS (gabble_console_sidecar_parent_class)->constructed; + + if (chain_up != NULL) + chain_up (object); + + self->priv->session = g_object_ref ( + gabble_plugin_connection_get_session ( + GABBLE_PLUGIN_CONNECTION ( + tp_base_channel_get_connection ( + TP_BASE_CHANNEL (self))))); + g_return_if_fail (self->priv->session != NULL); +} + static void gabble_console_sidecar_get_property ( GObject *object, @@ -110,11 +123,6 @@ gabble_console_sidecar_set_property ( switch (property_id) { - case PROP_SESSION: - g_assert (self->priv->session == NULL); /* construct-only */ - self->priv->session = g_value_dup_object (value); - break; - case PROP_SPEW: gabble_console_sidecar_set_spew (self, g_value_get_boolean (value)); break; @@ -145,22 +153,21 @@ static void gabble_console_sidecar_class_init (GabbleConsoleSidecarClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + TpBaseChannelClass *channel_class = TP_BASE_CHANNEL_CLASS (klass); static TpDBusPropertiesMixinPropImpl console_props[] = { { "SpewStanzas", "spew-stanzas", "spew-stanzas" }, { NULL }, }; + object_class->constructed = gabble_console_sidecar_constructed; object_class->get_property = gabble_console_sidecar_get_property; object_class->set_property = gabble_console_sidecar_set_property; object_class->dispose = gabble_console_sidecar_dispose; - g_type_class_add_private (klass, sizeof (GabbleConsoleSidecarPrivate)); + channel_class->channel_type = GABBLE_IFACE_GABBLE_PLUGIN_CONSOLE; + channel_class->close = gabble_console_sidecar_close; - g_object_class_install_property (object_class, PROP_SESSION, - g_param_spec_object ("session", "Session", - "Wocky session", - WOCKY_TYPE_SESSION, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_type_class_add_private (klass, sizeof (GabbleConsoleSidecarPrivate)); g_object_class_install_property (object_class, PROP_SPEW, g_param_spec_boolean ("spew-stanzas", "SpewStanzas", @@ -171,25 +178,17 @@ gabble_console_sidecar_class_init (GabbleConsoleSidecarClass *klass) tp_dbus_properties_mixin_implement_interface (object_class, GABBLE_IFACE_QUARK_GABBLE_PLUGIN_CONSOLE, tp_dbus_properties_mixin_getter_gobject_properties, - /* FIXME: if we were feeling clever, we'd override the setter so that - * we can monitor the bus name of any application which sets - * SpewStanzas to TRUE and flip it back to false when that application - * dies. - * - * Alternatively, we could just replace this sidecar with a channel. - */ tp_dbus_properties_mixin_setter_gobject_properties, console_props); } -static void sidecar_iface_init ( - gpointer g_iface, - gpointer data) +static void +gabble_console_sidecar_close (TpBaseChannel *chan) { - GabbleSidecarInterface *iface = g_iface; + GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (chan); - iface->interface = GABBLE_IFACE_GABBLE_PLUGIN_CONSOLE; - iface->get_immutable_properties = NULL; + gabble_console_sidecar_set_spew (self, FALSE); + tp_base_channel_destroyed (chan); } static gboolean diff --git a/tests/twisted/console.py b/tests/twisted/console.py index 8aab65f76..b2efd658c 100644 --- a/tests/twisted/console.py +++ b/tests/twisted/console.py @@ -38,9 +38,10 @@ def test(q, bus, conn, stream): allowed = [] assertContains((fixed, allowed), rccs) - path, _ = conn.Future.EnsureSidecar(CONSOLE_PLUGIN_IFACE) + path, _ = conn.Requests.CreateChannel({ cs.CHANNEL_TYPE: CONSOLE_PLUGIN_IFACE }) console = ProxyWrapper(bus.get_object(conn.bus_name, path), - CONSOLE_PLUGIN_IFACE) + CONSOLE_PLUGIN_IFACE, + {'Channel': cs.CHANNEL}) assert not console.Properties.Get(CONSOLE_PLUGIN_IFACE, 'SpewStanzas') es = [ @@ -99,5 +100,7 @@ def test(q, bus, conn, stream): assertEquals('body', body.name) assertEquals(ns.CLIENT, body.uri) + console.Channel.Close() + if __name__ == '__main__': exec_test(test) -- cgit v1.2.1