2
* bug16307-conn.c - connection that reproduces the #15307 bug
4
* Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/>
5
* Copyright (C) 2007-2008 Nokia Corporation
7
* Copying and distribution of this file, with or without modification,
8
* are permitted in any medium without royalty provided the copyright
9
* notice and this notice are preserved.
11
#include "bug16307-conn.h"
13
#include <dbus/dbus-glib.h>
15
#include <telepathy-glib/interfaces.h>
16
#include <telepathy-glib/dbus.h>
17
#include <telepathy-glib/errors.h>
18
#include <telepathy-glib/gtypes.h>
19
#include <telepathy-glib/handle-repo-dynamic.h>
20
#include <telepathy-glib/util.h>
22
static void service_iface_init (gpointer, gpointer);
24
G_DEFINE_TYPE_WITH_CODE (TpTestsBug16307Connection,
25
tp_tests_bug16307_connection,
26
TP_TESTS_TYPE_SIMPLE_CONNECTION,
27
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION,
29
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING,
33
/* type definition stuff */
37
SIGNAL_GET_STATUS_RECEIVED,
41
static guint signals[N_SIGNALS] = {0};
43
struct _TpTestsBug16307ConnectionPrivate
45
/* In a real connection manager, the underlying implementation start
46
* connecting, then go to state CONNECTED when finished. Here there isn't
47
* actually a connection, so the connection process is fake and the time
48
* when it connects is, for this test purpose, when the D-Bus method GetStatus
51
* Also, the GetStatus D-Bus reply is delayed until
52
* tp_tests_bug16307_connection_inject_get_status_return() is called
54
DBusGMethodInvocation *get_status_invocation;
58
tp_tests_bug16307_connection_init (TpTestsBug16307Connection *self)
60
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
61
TP_TESTS_TYPE_BUG16307_CONNECTION, TpTestsBug16307ConnectionPrivate);
65
finalize (GObject *object)
67
G_OBJECT_CLASS (tp_tests_bug16307_connection_parent_class)->finalize (object);
71
pretend_connected (gpointer data)
73
TpTestsBug16307Connection *self = TP_TESTS_BUG16307_CONNECTION (data);
74
TpBaseConnection *conn = (TpBaseConnection *) self;
75
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn,
76
TP_HANDLE_TYPE_CONTACT);
79
g_object_get (self, "account", &account, NULL);
81
conn->self_handle = tp_handle_ensure (contact_repo, account,
86
tp_base_connection_change_status (conn, TP_CONNECTION_STATUS_CONNECTED,
87
TP_CONNECTION_STATUS_REASON_REQUESTED);
93
tp_tests_bug16307_connection_inject_get_status_return (TpTestsBug16307Connection *self)
95
TpBaseConnection *self_base = TP_BASE_CONNECTION (self);
96
DBusGMethodInvocation *context;
99
/* if we don't have a pending get_status yet, wait for it */
100
if (self->priv->get_status_invocation == NULL)
102
GMainLoop *loop = g_main_loop_new (NULL, FALSE);
104
get_signal_id = g_signal_connect_swapped (self, "get-status-received",
105
G_CALLBACK (g_main_loop_quit), loop);
107
g_main_loop_run (loop);
109
g_signal_handler_disconnect (self, get_signal_id);
111
g_main_loop_unref (loop);
114
context = self->priv->get_status_invocation;
115
g_assert (context != NULL);
117
if (self_base->status == TP_INTERNAL_CONNECTION_STATUS_NEW)
119
tp_svc_connection_return_from_get_status (
120
context, TP_CONNECTION_STATUS_DISCONNECTED);
124
tp_svc_connection_return_from_get_status (
125
context, self_base->status);
128
self->priv->get_status_invocation = NULL;
132
start_connecting (TpBaseConnection *conn,
135
tp_base_connection_change_status (conn, TP_CONNECTION_STATUS_CONNECTING,
136
TP_CONNECTION_STATUS_REASON_REQUESTED);
142
tp_tests_bug16307_connection_class_init (TpTestsBug16307ConnectionClass *klass)
144
TpBaseConnectionClass *base_class =
145
(TpBaseConnectionClass *) klass;
146
GObjectClass *object_class = (GObjectClass *) klass;
147
static const gchar *interfaces_always_present[] = {
148
TP_IFACE_CONNECTION_INTERFACE_ALIASING,
149
TP_IFACE_CONNECTION_INTERFACE_CAPABILITIES,
150
TP_IFACE_CONNECTION_INTERFACE_PRESENCE,
151
TP_IFACE_CONNECTION_INTERFACE_AVATARS,
153
static TpDBusPropertiesMixinPropImpl connection_properties[] = {
154
{ "Status", "dbus-status-except-i-broke-it", NULL },
158
object_class->finalize = finalize;
159
g_type_class_add_private (klass, sizeof (TpTestsBug16307ConnectionPrivate));
161
base_class->start_connecting = start_connecting;
163
base_class->interfaces_always_present = interfaces_always_present;
165
signals[SIGNAL_GET_STATUS_RECEIVED] = g_signal_new ("get-status-received",
166
G_OBJECT_CLASS_TYPE (klass),
167
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
170
g_cclosure_marshal_VOID__VOID,
173
/* break the Connection D-Bus properties implementation, so that we always
174
* cause the slower introspection codepath (the one that actually calls
175
* GetStatus) in TpConnection to be invoked */
176
tp_dbus_properties_mixin_implement_interface (object_class,
177
TP_IFACE_QUARK_CONNECTION,
178
NULL, NULL, connection_properties);
182
* tp_tests_bug16307_connection_get_status
184
* Implements D-Bus method GetStatus
185
* on interface org.freedesktop.Telepathy.Connection
188
tp_tests_bug16307_connection_get_status (TpSvcConnection *iface,
189
DBusGMethodInvocation *context)
191
TpBaseConnection *self_base = TP_BASE_CONNECTION (iface);
192
TpTestsBug16307Connection *self = TP_TESTS_BUG16307_CONNECTION (iface);
194
/* auto-connect on get_status */
195
if ((self_base->status == TP_INTERNAL_CONNECTION_STATUS_NEW ||
196
self_base->status == TP_CONNECTION_STATUS_DISCONNECTED))
198
pretend_connected (self);
201
/* D-Bus return call later */
202
g_assert (self->priv->get_status_invocation == NULL);
203
g_assert (context != NULL);
204
self->priv->get_status_invocation = context;
206
g_signal_emit (self, signals[SIGNAL_GET_STATUS_RECEIVED], 0);
211
service_iface_init (gpointer g_iface, gpointer iface_data)
213
TpSvcConnectionClass *klass = g_iface;
215
#define IMPLEMENT(prefix,x) tp_svc_connection_implement_##x (klass, \
216
tp_tests_bug16307_connection_##prefix##x)
217
IMPLEMENT(,get_status);