/* * /dev/null as a text channel * * Copyright (C) 2008 Collabora Ltd. * Copyright (C) 2008 Nokia Corporation * * Copying and distribution of this file, with or without modification, * are permitted in any medium without royalty provided the copyright * notice and this notice are preserved. */ #include "textchan-null.h" #include #include #include #include #include #include #include static void text_iface_init (gpointer iface, gpointer data); static void channel_iface_init (gpointer iface, gpointer data); G_DEFINE_TYPE_WITH_CODE (TpTestsTextChannelNull, tp_tests_text_channel_null, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TEXT, text_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL)) G_DEFINE_TYPE_WITH_CODE (TpTestsPropsTextChannel, tp_tests_props_text_channel, TP_TESTS_TYPE_TEXT_CHANNEL_NULL, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, tp_dbus_properties_mixin_iface_init)) G_DEFINE_TYPE_WITH_CODE (TpTestsPropsGroupTextChannel, tp_tests_props_group_text_channel, TP_TESTS_TYPE_PROPS_TEXT_CHANNEL, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP, tp_group_mixin_iface_init)) static const char *tp_tests_text_channel_null_interfaces[] = { NULL }; /* type definition stuff */ enum { PROP_OBJECT_PATH = 1, PROP_CHANNEL_TYPE, PROP_HANDLE_TYPE, PROP_HANDLE, PROP_TARGET_ID, PROP_CONNECTION, PROP_INTERFACES, PROP_REQUESTED, PROP_INITIATOR_HANDLE, PROP_INITIATOR_ID, N_PROPS }; struct _TpTestsTextChannelNullPrivate { TpBaseConnection *conn; gchar *object_path; TpHandle handle; unsigned closed:1; unsigned disposed:1; }; static void tp_tests_text_channel_null_init (TpTestsTextChannelNull *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TESTS_TYPE_TEXT_CHANNEL_NULL, TpTestsTextChannelNullPrivate); } static void tp_tests_props_text_channel_init (TpTestsPropsTextChannel *self) { self->dbus_property_interfaces_retrieved = g_hash_table_new (NULL, NULL); } static GObject * constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *object = G_OBJECT_CLASS (tp_tests_text_channel_null_parent_class)->constructor (type, n_props, props); TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (self->priv->conn, TP_HANDLE_TYPE_CONTACT); tp_handle_ref (contact_repo, self->priv->handle); tp_dbus_daemon_register_object ( tp_base_connection_get_dbus_daemon (self->priv->conn), self->priv->object_path, self); tp_text_mixin_init (object, G_STRUCT_OFFSET (TpTestsTextChannelNull, text), contact_repo); tp_text_mixin_set_message_types (object, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE, G_MAXUINT); return object; } static void get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object); switch (property_id) { case PROP_OBJECT_PATH: g_value_set_string (value, self->priv->object_path); break; case PROP_CHANNEL_TYPE: g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_TEXT); break; case PROP_HANDLE_TYPE: g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT); break; case PROP_HANDLE: g_value_set_uint (value, self->priv->handle); break; case PROP_TARGET_ID: { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( self->priv->conn, TP_HANDLE_TYPE_CONTACT); g_value_set_string (value, tp_handle_inspect (contact_repo, self->priv->handle)); } break; case PROP_REQUESTED: g_value_set_boolean (value, TRUE); break; case PROP_INITIATOR_HANDLE: g_value_set_uint (value, self->priv->conn->self_handle); break; case PROP_INITIATOR_ID: { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( self->priv->conn, TP_HANDLE_TYPE_CONTACT); g_value_set_string (value, tp_handle_inspect (contact_repo, self->priv->conn->self_handle)); } break; case PROP_INTERFACES: g_value_set_boxed (value, tp_tests_text_channel_null_interfaces); break; case PROP_CONNECTION: g_value_set_object (value, self->priv->conn); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object); switch (property_id) { case PROP_OBJECT_PATH: g_free (self->priv->object_path); self->priv->object_path = g_value_dup_string (value); break; case PROP_HANDLE: /* we don't ref it here because we don't necessarily have access to the * contact repo yet - instead we ref it in the constructor. */ self->priv->handle = g_value_get_uint (value); break; case PROP_HANDLE_TYPE: case PROP_CHANNEL_TYPE: /* these properties are writable in the interface, but not actually * meaningfully changable on this channel, so we do nothing */ break; case PROP_CONNECTION: self->priv->conn = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } void tp_tests_text_channel_null_close (TpTestsTextChannelNull *self) { if (!self->priv->closed) { self->priv->closed = TRUE; tp_svc_channel_emit_closed (self); tp_dbus_daemon_unregister_object ( tp_base_connection_get_dbus_daemon (self->priv->conn), self); } } static void dispose (GObject *object) { TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object); if (self->priv->disposed) return; self->priv->disposed = TRUE; tp_tests_text_channel_null_close (self); ((GObjectClass *) tp_tests_text_channel_null_parent_class)->dispose (object); } static void finalize (GObject *object) { TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (object); TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (self->priv->conn, TP_HANDLE_TYPE_CONTACT); tp_handle_unref (contact_handles, self->priv->handle); g_free (self->priv->object_path); tp_text_mixin_finalize (object); ((GObjectClass *) tp_tests_text_channel_null_parent_class)->finalize (object); } static void tp_tests_text_channel_null_class_init (TpTestsTextChannelNullClass *klass) { GObjectClass *object_class = (GObjectClass *) klass; GParamSpec *param_spec; g_type_class_add_private (klass, sizeof (TpTestsTextChannelNullPrivate)); object_class->constructor = constructor; object_class->set_property = set_property; object_class->get_property = get_property; object_class->dispose = dispose; object_class->finalize = finalize; g_object_class_override_property (object_class, PROP_OBJECT_PATH, "object-path"); g_object_class_override_property (object_class, PROP_CHANNEL_TYPE, "channel-type"); g_object_class_override_property (object_class, PROP_HANDLE_TYPE, "handle-type"); g_object_class_override_property (object_class, PROP_HANDLE, "handle"); param_spec = g_param_spec_object ("connection", "TpBaseConnection object", "Connection object that owns this channel", TP_TYPE_BASE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces", "Additional Channel.Interface.* interfaces", G_TYPE_STRV, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INTERFACES, param_spec); param_spec = g_param_spec_string ("target-id", "Peer's ID", "The string obtained by inspecting the target handle", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec); param_spec = g_param_spec_uint ("initiator-handle", "Initiator's handle", "The contact who initiated the channel", 0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIATOR_HANDLE, param_spec); param_spec = g_param_spec_string ("initiator-id", "Initiator's ID", "The string obtained by inspecting the initiator-handle", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIATOR_ID, param_spec); param_spec = g_param_spec_boolean ("requested", "Requested?", "True if this channel was requested by the local user", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_REQUESTED, param_spec); tp_text_mixin_class_init (object_class, G_STRUCT_OFFSET (TpTestsTextChannelNullClass, text_class)); } static void tp_tests_props_text_channel_getter_gobject_properties (GObject *object, GQuark interface, GQuark name, GValue *value, gpointer getter_data) { TpTestsPropsTextChannel *self = TP_TESTS_PROPS_TEXT_CHANNEL (object); g_hash_table_insert (self->dbus_property_interfaces_retrieved, GUINT_TO_POINTER (interface), GUINT_TO_POINTER (interface)); tp_dbus_properties_mixin_getter_gobject_properties (object, interface, name, value, getter_data); } static void props_finalize (GObject *object) { TpTestsPropsTextChannel *self = TP_TESTS_PROPS_TEXT_CHANNEL (object); g_hash_table_unref (self->dbus_property_interfaces_retrieved); ((GObjectClass *) tp_tests_props_text_channel_parent_class)->finalize (object); } static void tp_tests_props_text_channel_class_init (TpTestsPropsTextChannelClass *klass) { GObjectClass *object_class = (GObjectClass *) klass; static TpDBusPropertiesMixinPropImpl channel_props[] = { { "TargetHandleType", "handle-type", NULL }, { "TargetHandle", "handle", NULL }, { "ChannelType", "channel-type", NULL }, { "Interfaces", "interfaces", NULL }, { "TargetID", "target-id", NULL }, { "Requested", "requested", NULL }, { "InitiatorHandle", "initiator-handle", NULL }, { "InitiatorID", "initiator-id", NULL }, { NULL } }; static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { { TP_IFACE_CHANNEL, tp_tests_props_text_channel_getter_gobject_properties, NULL, channel_props, }, { NULL } }; object_class->finalize = props_finalize; klass->dbus_properties_class.interfaces = prop_interfaces; tp_dbus_properties_mixin_class_init (object_class, G_STRUCT_OFFSET (TpTestsPropsTextChannelClass, dbus_properties_class)); } static void tp_tests_props_group_text_channel_init (TpTestsPropsGroupTextChannel *self) { } static void group_constructed (GObject *self) { TpBaseConnection *conn = TP_TESTS_TEXT_CHANNEL_NULL (self)->priv->conn; void (*chain_up) (GObject *) = ((GObjectClass *) tp_tests_props_group_text_channel_parent_class)->constructed; if (chain_up != NULL) chain_up (self); tp_group_mixin_init (self, G_STRUCT_OFFSET (TpTestsPropsGroupTextChannel, group), tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT), tp_base_connection_get_self_handle (conn)); tp_group_mixin_change_flags (self, TP_CHANNEL_GROUP_FLAG_PROPERTIES, 0); } static void group_finalize (GObject *self) { tp_group_mixin_finalize (self); ((GObjectClass *) tp_tests_props_group_text_channel_parent_class)->finalize (self); } static gboolean dummy_add_remove_member (GObject *obj, TpHandle handle, const gchar *message, GError **error) { return TRUE; } static void group_iface_props_getter (GObject *object, GQuark interface, GQuark name, GValue *value, gpointer getter_data) { TpTestsPropsTextChannel *self = TP_TESTS_PROPS_TEXT_CHANNEL (object); g_hash_table_insert (self->dbus_property_interfaces_retrieved, GUINT_TO_POINTER (interface), GUINT_TO_POINTER (interface)); tp_group_mixin_get_dbus_property (object, interface, name, value, getter_data); } static void tp_tests_props_group_text_channel_class_init (TpTestsPropsGroupTextChannelClass *klass) { GObjectClass *object_class = (GObjectClass *) klass; static TpDBusPropertiesMixinPropImpl group_props[] = { { "GroupFlags", NULL, NULL }, { "HandleOwners", NULL, NULL }, { "LocalPendingMembers", NULL, NULL }, { "Members", NULL, NULL }, { "RemotePendingMembers", NULL, NULL }, { "SelfHandle", NULL, NULL }, { NULL } }; object_class->constructed = group_constructed; object_class->finalize = group_finalize; tp_group_mixin_class_init (object_class, G_STRUCT_OFFSET (TpTestsPropsGroupTextChannelClass, group_class), dummy_add_remove_member, dummy_add_remove_member); tp_dbus_properties_mixin_implement_interface (object_class, TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP, group_iface_props_getter, NULL, group_props); } static void channel_close (TpSvcChannel *iface, DBusGMethodInvocation *context) { TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (iface); tp_tests_text_channel_null_close (self); tp_svc_channel_return_from_close (context); } static void channel_get_channel_type (TpSvcChannel *iface, DBusGMethodInvocation *context) { TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (iface); self->get_channel_type_called++; tp_svc_channel_return_from_get_channel_type (context, TP_IFACE_CHANNEL_TYPE_TEXT); } static void channel_get_handle (TpSvcChannel *iface, DBusGMethodInvocation *context) { TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (iface); self->get_handle_called++; tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_CONTACT, self->priv->handle); } static void channel_get_interfaces (TpSvcChannel *iface, DBusGMethodInvocation *context) { TpTestsTextChannelNull *self = TP_TESTS_TEXT_CHANNEL_NULL (iface); self->get_interfaces_called++; tp_svc_channel_return_from_get_interfaces (context, tp_tests_text_channel_null_interfaces); } static void channel_iface_init (gpointer iface, gpointer data) { TpSvcChannelClass *klass = iface; #define IMPLEMENT(x) tp_svc_channel_implement_##x (klass, channel_##x) IMPLEMENT (close); IMPLEMENT (get_channel_type); IMPLEMENT (get_handle); IMPLEMENT (get_interfaces); #undef IMPLEMENT } static void text_send (TpSvcChannelTypeText *iface, guint type, const gchar *text, DBusGMethodInvocation *context) { /* silently swallow the message */ tp_svc_channel_type_text_return_from_send (context); } static void text_iface_init (gpointer iface, gpointer data) { TpSvcChannelTypeTextClass *klass = iface; tp_text_mixin_iface_init (iface, data); #define IMPLEMENT(x) tp_svc_channel_type_text_implement_##x (klass, text_##x) IMPLEMENT (send); #undef IMPLEMENT } GHashTable * tp_tests_text_channel_get_props (TpTestsTextChannelNull *self) { GHashTable *props; TpHandleType handle_type; TpHandle handle; gchar *target_id; gboolean requested; TpHandle initiator_handle; gchar *initiator_id; g_object_get (self, "handle-type", &handle_type, "handle", &handle, "target-id", &target_id, "requested", &requested, "initiator-handle", &initiator_handle, "initiator-id", &initiator_id, NULL); props = tp_asv_new ( TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_TEXT, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT, TP_PROP_CHANNEL_TARGET_HANDLE, G_TYPE_UINT, handle, TP_PROP_CHANNEL_TARGET_ID, G_TYPE_STRING, target_id, TP_PROP_CHANNEL_REQUESTED, G_TYPE_BOOLEAN, requested, TP_PROP_CHANNEL_INITIATOR_HANDLE, G_TYPE_UINT, initiator_handle, TP_PROP_CHANNEL_INITIATOR_ID, G_TYPE_STRING, initiator_id, NULL); g_free (target_id); g_free (initiator_id); return props; }