1 /*
2  * my-conn-proxy.c - a simple subclass of TpConnection
3  *
4  * Copyright (C) 2010-2011 Collabora Ltd. <http://www.collabora.co.uk/>
5  *
6  * Copying and distribution of this file, with or without modification,
7  * are permitted in any medium without royalty provided the copyright
8  * notice and this notice are preserved.
9  */
10 
11 #include "config.h"
12 
13 #include "my-conn-proxy.h"
14 
15 #include <telepathy-glib/telepathy-glib.h>
16 
G_DEFINE_TYPE(TpTestsMyConnProxy,tp_tests_my_conn_proxy,TP_TYPE_CONNECTION)17 G_DEFINE_TYPE  (TpTestsMyConnProxy, tp_tests_my_conn_proxy,
18     TP_TYPE_CONNECTION)
19 
20 static void
21 tp_tests_my_conn_proxy_init (TpTestsMyConnProxy *self)
22 {
23 }
24 
25 enum {
26     FEAT_CORE,
27     FEAT_A,
28     FEAT_B,
29     FEAT_WRONG_IFACE,
30     FEAT_BAD_DEP,
31     FEAT_FAIL,
32     FEAT_FAIL_DEP,
33     FEAT_RETRY,
34     FEAT_RETRY_DEP,
35     FEAT_BEFORE_CONNECTED,
36     FEAT_INTERFACE_LATER,
37     N_FEAT
38 };
39 
40 static void
prepare_core_async(TpProxy * proxy,const TpProxyFeature * feature,GAsyncReadyCallback callback,gpointer user_data)41 prepare_core_async (TpProxy *proxy,
42     const TpProxyFeature *feature,
43     GAsyncReadyCallback callback,
44     gpointer user_data)
45 {
46   GSimpleAsyncResult *result;
47 
48   /* superclass core features are prepared first */
49   g_assert (tp_proxy_is_prepared (proxy, TP_CONNECTION_FEATURE_CORE));
50 
51   result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
52       prepare_core_async);
53 
54   g_simple_async_result_complete_in_idle (result);
55   g_object_unref (result);
56 }
57 
58 static void
prepare_a_async(TpProxy * proxy,const TpProxyFeature * feature,GAsyncReadyCallback callback,gpointer user_data)59 prepare_a_async (TpProxy *proxy,
60     const TpProxyFeature *feature,
61     GAsyncReadyCallback callback,
62     gpointer user_data)
63 {
64   GSimpleAsyncResult *result;
65 
66   g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
67 
68   result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
69       prepare_a_async);
70 
71   g_simple_async_result_complete_in_idle (result);
72   g_object_unref (result);
73 }
74 
75 static void
prepare_b_async(TpProxy * proxy,const TpProxyFeature * feature,GAsyncReadyCallback callback,gpointer user_data)76 prepare_b_async (TpProxy *proxy,
77     const TpProxyFeature *feature,
78     GAsyncReadyCallback callback,
79     gpointer user_data)
80 {
81   GSimpleAsyncResult *result;
82 
83   g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
84   g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_A));
85 
86   result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
87       prepare_b_async);
88 
89   g_simple_async_result_complete_in_idle (result);
90   g_object_unref (result);
91 }
92 
93 static void
cannot_be_prepared_async(TpProxy * proxy,const TpProxyFeature * feature,GAsyncReadyCallback callback,gpointer user_data)94 cannot_be_prepared_async (TpProxy *proxy,
95     const TpProxyFeature *feature,
96     GAsyncReadyCallback callback,
97     gpointer user_data)
98 {
99   g_assert_not_reached ();
100 }
101 
102 static void
prepare_fail_async(TpProxy * proxy,const TpProxyFeature * feature,GAsyncReadyCallback callback,gpointer user_data)103 prepare_fail_async (TpProxy *proxy,
104     const TpProxyFeature *feature,
105     GAsyncReadyCallback callback,
106     gpointer user_data)
107 {
108   GSimpleAsyncResult *result;
109 
110   g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
111 
112   result = g_simple_async_result_new_error ((GObject *) proxy, callback,
113       user_data, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
114       "No feature for you!");
115 
116   g_simple_async_result_complete_in_idle (result);
117   g_object_unref (result);
118 }
119 
120 static void
prepare_retry_async(TpProxy * proxy,const TpProxyFeature * feature,GAsyncReadyCallback callback,gpointer user_data)121 prepare_retry_async (TpProxy *proxy,
122     const TpProxyFeature *feature,
123     GAsyncReadyCallback callback,
124     gpointer user_data)
125 {
126   TpTestsMyConnProxy *self = (TpTestsMyConnProxy *) proxy;
127   GSimpleAsyncResult *result;
128 
129   result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
130       prepare_retry_async);
131 
132   if (!self->retry_feature_success)
133     {
134       /* Fail the first time we try to prepare the feature */
135       g_simple_async_result_set_error (result, TP_ERROR,
136           TP_ERROR_NOT_YET, "Nah");
137     }
138 
139   g_simple_async_result_complete_in_idle (result);
140   g_object_unref (result);
141 }
142 
143 static void
prepare_retry_dep_async(TpProxy * proxy,const TpProxyFeature * feature,GAsyncReadyCallback callback,gpointer user_data)144 prepare_retry_dep_async (TpProxy *proxy,
145     const TpProxyFeature *feature,
146     GAsyncReadyCallback callback,
147     gpointer user_data)
148 {
149   GSimpleAsyncResult *result;
150 
151   g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
152 
153   result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
154       prepare_retry_dep_async);
155 
156   g_simple_async_result_complete_in_idle (result);
157   g_object_unref (result);
158 }
159 
160 static void
prepare_before_connected_async(TpProxy * proxy,const TpProxyFeature * feature,GAsyncReadyCallback callback,gpointer user_data)161 prepare_before_connected_async (TpProxy *proxy,
162     const TpProxyFeature *feature,
163     GAsyncReadyCallback callback,
164     gpointer user_data)
165 {
166   TpTestsMyConnProxy *self = (TpTestsMyConnProxy *) proxy;
167   GSimpleAsyncResult *result;
168 
169   g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
170 
171   result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
172       prepare_before_connected_async);
173 
174   if (tp_connection_get_status (TP_CONNECTION (self), NULL) ==
175         TP_CONNECTION_STATUS_CONNECTED)
176     self->before_connected_state = BEFORE_CONNECTED_STATE_CONNECTED;
177   else
178     self->before_connected_state = BEFORE_CONNECTED_STATE_NOT_CONNECTED;
179 
180   g_simple_async_result_complete_in_idle (result);
181   g_object_unref (result);
182 }
183 
184 static void
prepare_before_connected_before_async(TpProxy * proxy,const TpProxyFeature * feature,GAsyncReadyCallback callback,gpointer user_data)185 prepare_before_connected_before_async (TpProxy *proxy,
186     const TpProxyFeature *feature,
187     GAsyncReadyCallback callback,
188     gpointer user_data)
189 {
190   TpTestsMyConnProxy *self = (TpTestsMyConnProxy *) proxy;
191   GSimpleAsyncResult *result;
192 
193   g_assert (tp_proxy_is_prepared (proxy, TP_TESTS_MY_CONN_PROXY_FEATURE_CORE));
194 
195   g_assert_cmpuint (tp_connection_get_status (TP_CONNECTION (proxy), NULL), ==,
196       TP_CONNECTION_STATUS_CONNECTING);
197 
198   result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
199       prepare_before_connected_before_async);
200 
201   self->before_connected_state = BEFORE_CONNECTED_STATE_CONNECTED;
202 
203   g_simple_async_result_complete_in_idle (result);
204   g_object_unref (result);
205 }
206 
207 static void
prepare_interface_later_async(TpProxy * proxy,const TpProxyFeature * feature,GAsyncReadyCallback callback,gpointer user_data)208 prepare_interface_later_async (TpProxy *proxy,
209     const TpProxyFeature *feature,
210     GAsyncReadyCallback callback,
211     gpointer user_data)
212 {
213   GSimpleAsyncResult *result;
214 
215   result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
216       prepare_interface_later_async);
217 
218   g_simple_async_result_complete_in_idle (result);
219   g_object_unref (result);
220 }
221 
222 static const TpProxyFeature *
list_features(TpProxyClass * cls G_GNUC_UNUSED)223 list_features (TpProxyClass *cls G_GNUC_UNUSED)
224 {
225   static TpProxyFeature features[N_FEAT + 1] = { { 0 } };
226   static GQuark need_a[2] = {0, 0};
227   static GQuark need_channel_core[2] = {0, 0};
228   static GQuark need_wrong_iface[2] = {0, 0};
229   static GQuark need_fail[2] = {0, 0};
230   static GQuark need_retry[2] = {0, 0};
231   static GQuark need_iface_later[2] = {0, 0};
232 
233   if (G_LIKELY (features[0].name != 0))
234     return features;
235 
236   features[FEAT_CORE].name = TP_TESTS_MY_CONN_PROXY_FEATURE_CORE;
237   features[FEAT_CORE].core = TRUE;
238   features[FEAT_CORE].prepare_async = prepare_core_async;
239 
240   features[FEAT_A].name = TP_TESTS_MY_CONN_PROXY_FEATURE_A;
241   features[FEAT_A].prepare_async = prepare_a_async;
242 
243   features[FEAT_B].name = TP_TESTS_MY_CONN_PROXY_FEATURE_B;
244   features[FEAT_B].prepare_async = prepare_b_async;
245   need_a[0] = TP_TESTS_MY_CONN_PROXY_FEATURE_A;
246   features[FEAT_B].depends_on = need_a;
247 
248   features[FEAT_WRONG_IFACE].name = TP_TESTS_MY_CONN_PROXY_FEATURE_WRONG_IFACE;
249   features[FEAT_WRONG_IFACE].prepare_async = cannot_be_prepared_async;
250   need_channel_core[0] = TP_CHANNEL_FEATURE_CORE;
251   features[FEAT_WRONG_IFACE].interfaces_needed = need_channel_core;
252 
253   features[FEAT_BAD_DEP].name = TP_TESTS_MY_CONN_PROXY_FEATURE_BAD_DEP;
254   features[FEAT_BAD_DEP].prepare_async = cannot_be_prepared_async;
255   need_wrong_iface[0] = TP_TESTS_MY_CONN_PROXY_FEATURE_WRONG_IFACE;
256   features[FEAT_BAD_DEP].depends_on = need_wrong_iface;
257 
258   features[FEAT_FAIL].name = TP_TESTS_MY_CONN_PROXY_FEATURE_FAIL;
259   features[FEAT_FAIL].prepare_async = prepare_fail_async;
260 
261   features[FEAT_FAIL_DEP].name = TP_TESTS_MY_CONN_PROXY_FEATURE_FAIL_DEP;
262   features[FEAT_FAIL_DEP].prepare_async = cannot_be_prepared_async;
263   need_fail[0] = TP_TESTS_MY_CONN_PROXY_FEATURE_FAIL;
264   features[FEAT_FAIL_DEP].depends_on = need_fail;
265 
266   features[FEAT_RETRY].name = TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY;
267   features[FEAT_RETRY].prepare_async = prepare_retry_async;
268   features[FEAT_RETRY].can_retry = TRUE;
269 
270   features[FEAT_RETRY_DEP].name = TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY_DEP;
271   need_retry[0] = TP_TESTS_MY_CONN_PROXY_FEATURE_RETRY;
272   features[FEAT_RETRY_DEP].prepare_async = prepare_retry_dep_async;
273   features[FEAT_RETRY_DEP].depends_on = need_retry;
274 
275   features[FEAT_BEFORE_CONNECTED].name =
276     TP_TESTS_MY_CONN_PROXY_FEATURE_BEFORE_CONNECTED;
277   features[FEAT_BEFORE_CONNECTED].prepare_async =
278     prepare_before_connected_async;
279   features[FEAT_BEFORE_CONNECTED].prepare_before_signalling_connected_async =
280     prepare_before_connected_before_async;
281 
282   features[FEAT_INTERFACE_LATER].name =
283     TP_TESTS_MY_CONN_PROXY_FEATURE_INTERFACE_LATER;
284   features[FEAT_INTERFACE_LATER].prepare_async = prepare_interface_later_async;
285   need_iface_later[0] = g_quark_from_static_string (
286       TP_TESTS_MY_CONN_PROXY_IFACE_LATER);
287   features[FEAT_INTERFACE_LATER].interfaces_needed = need_iface_later;
288 
289   return features;
290 }
291 
292 static void
tp_tests_my_conn_proxy_class_init(TpTestsMyConnProxyClass * klass)293 tp_tests_my_conn_proxy_class_init (TpTestsMyConnProxyClass *klass)
294 {
295   TpProxyClass *proxy_class = (TpProxyClass *) klass;
296 
297   proxy_class->list_features = list_features;
298 }
299 
300 GQuark
tp_tests_my_conn_proxy_get_feature_quark_core(void)301 tp_tests_my_conn_proxy_get_feature_quark_core (void)
302 {
303   return g_quark_from_static_string ("tp-my-conn-proxy-feature-core");
304 }
305 
306 GQuark
tp_tests_my_conn_proxy_get_feature_quark_a(void)307 tp_tests_my_conn_proxy_get_feature_quark_a (void)
308 {
309   return g_quark_from_static_string ("tp-my-conn-proxy-feature-a");
310 }
311 
312 GQuark
tp_tests_my_conn_proxy_get_feature_quark_b(void)313 tp_tests_my_conn_proxy_get_feature_quark_b (void)
314 {
315   return g_quark_from_static_string ("tp-my-conn-proxy-feature-b");
316 }
317 
318 GQuark
tp_tests_my_conn_proxy_get_feature_quark_wrong_iface(void)319 tp_tests_my_conn_proxy_get_feature_quark_wrong_iface (void)
320 {
321   return g_quark_from_static_string ("tp-my-conn-proxy-feature-wrong_iface");
322 }
323 
324 GQuark
tp_tests_my_conn_proxy_get_feature_quark_bad_dep(void)325 tp_tests_my_conn_proxy_get_feature_quark_bad_dep (void)
326 {
327   return g_quark_from_static_string ("tp-my-conn-proxy-feature-bad-dep");
328 }
329 
330 GQuark
tp_tests_my_conn_proxy_get_feature_quark_fail(void)331 tp_tests_my_conn_proxy_get_feature_quark_fail (void)
332 {
333   return g_quark_from_static_string ("tp-my-conn-proxy-feature-fail");
334 }
335 
336 GQuark
tp_tests_my_conn_proxy_get_feature_quark_fail_dep(void)337 tp_tests_my_conn_proxy_get_feature_quark_fail_dep (void)
338 {
339   return g_quark_from_static_string ("tp-my-conn-proxy-feature-fail-dep");
340 }
341 
342 GQuark
tp_tests_my_conn_proxy_get_feature_quark_retry(void)343 tp_tests_my_conn_proxy_get_feature_quark_retry (void)
344 {
345   return g_quark_from_static_string ("tp-my-conn-proxy-feature-retry");
346 }
347 
348 GQuark
tp_tests_my_conn_proxy_get_feature_quark_retry_dep(void)349 tp_tests_my_conn_proxy_get_feature_quark_retry_dep (void)
350 {
351   return g_quark_from_static_string ("tp-my-conn-proxy-feature-retry-dep");
352 }
353 
354 GQuark
tp_tests_my_conn_proxy_get_feature_quark_before_connected(void)355 tp_tests_my_conn_proxy_get_feature_quark_before_connected (void)
356 {
357   return g_quark_from_static_string ("tp-my-conn-proxy-feature-before-connected");
358 }
359 
360 GQuark
tp_tests_my_conn_proxy_get_feature_quark_interface_later(void)361 tp_tests_my_conn_proxy_get_feature_quark_interface_later (void)
362 {
363   return g_quark_from_static_string ("tp-my-conn-proxy-feature-interface-later");
364 }
365