1 /*
2 * protocol.c - SalutProtocol
3 * Copyright © 2007-2010 Collabora Ltd.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "protocol.h"
21
22 #include <config.h>
23
24 #include <dbus/dbus-glib.h>
25 #include <dbus/dbus-protocol.h>
26 #include <telepathy-glib/base-connection-manager.h>
27 #include <telepathy-glib/telepathy-glib.h>
28
29 #include "connection.h"
30 #include "contact-manager.h"
31 #include "ft-manager.h"
32 #include "im-manager.h"
33 #include "muc-manager.h"
34 #include "roomlist-manager.h"
35 #include "tubes-manager.h"
36
37 #ifdef USE_BACKEND_AVAHI
38 #include "avahi-discovery-client.h"
39 #elif defined (USE_BACKEND_DUMMY)
40 #include "dummy-discovery-client.h"
41 #elif defined (USE_BACKEND_BONJOUR)
42 #include "bonjour-discovery-client.h"
43 #endif
44
45 /* there is no appropriate vCard field for this protocol */
46 #define VCARD_FIELD_NAME ""
47
48 G_DEFINE_TYPE (SalutProtocol,
49 salut_protocol,
50 TP_TYPE_BASE_PROTOCOL)
51
52 enum {
53 PROP_BACKEND = 1,
54 PROP_DNSSD_NAME,
55 PROP_ENGLISH_NAME,
56 PROP_ICON_NAME
57 };
58
59 struct _SalutProtocolPrivate
60 {
61 GType backend_type;
62 gchar *english_name;
63 gchar *icon_name;
64 gchar *dnssd_name;
65 };
66
67 static const TpCMParamSpec salut_params[] = {
68 { "nickname", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL, 0,
69 tp_cm_param_filter_string_nonempty, NULL },
70 { "first-name", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
71 TP_CONN_MGR_PARAM_FLAG_REQUIRED, NULL, 0 },
72 { "last-name", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING,
73 TP_CONN_MGR_PARAM_FLAG_REQUIRED, NULL, 0 },
74 { "jid", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL, 0 },
75 { "email", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL, 0 },
76 { "published-name", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL, 0,
77 tp_cm_param_filter_string_nonempty, NULL },
78 { NULL, NULL, 0, 0, NULL, 0 }
79 };
80
81 static void
salut_protocol_init(SalutProtocol * self)82 salut_protocol_init (SalutProtocol *self)
83 {
84 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SALUT_TYPE_PROTOCOL,
85 SalutProtocolPrivate);
86 }
87
88 static const TpCMParamSpec *
get_parameters(TpBaseProtocol * self G_GNUC_UNUSED)89 get_parameters (TpBaseProtocol *self G_GNUC_UNUSED)
90 {
91 return salut_params;
92 }
93
94 static TpBaseConnection *
new_connection(TpBaseProtocol * protocol,GHashTable * params,GError ** error)95 new_connection (TpBaseProtocol *protocol,
96 GHashTable *params,
97 GError **error)
98 {
99 SalutProtocol *self = SALUT_PROTOCOL (protocol);
100 GObject *obj;
101 guint i;
102
103 obj = g_object_new (SALUT_TYPE_CONNECTION,
104 "protocol", tp_base_protocol_get_name (protocol),
105 /* deliberately set :dnssd-name before backend-type */
106 "dnssd-name", self->priv->dnssd_name,
107 "backend-type", self->priv->backend_type,
108 NULL);
109
110 for (i = 0; salut_params[i].name != NULL; i++)
111 {
112 GValue *val = g_hash_table_lookup (params, salut_params[i].name);
113
114 if (val != NULL)
115 {
116 g_object_set_property (obj, salut_params[i].name, val);
117 }
118 }
119
120 return TP_BASE_CONNECTION (obj);
121 }
122
123 static gchar *
normalize_contact(TpBaseProtocol * self G_GNUC_UNUSED,const gchar * contact,GError ** error)124 normalize_contact (TpBaseProtocol *self G_GNUC_UNUSED,
125 const gchar *contact,
126 GError **error)
127 {
128 return salut_normalize_non_empty (contact, error);
129 }
130
131 static gchar *
identify_account(TpBaseProtocol * self G_GNUC_UNUSED,GHashTable * asv,GError ** error)132 identify_account (TpBaseProtocol *self G_GNUC_UNUSED,
133 GHashTable *asv,
134 GError **error)
135 {
136 /* Nothing uniquely identifies a particular Salut account. The published
137 * name is part of our identifier, but can be changed at any time;
138 * the best an account manager can do is to number accounts. */
139 return g_strdup ("");
140 }
141
142 static GStrv
get_interfaces(TpBaseProtocol * self)143 get_interfaces (TpBaseProtocol *self)
144 {
145 return g_new0 (gchar *, 1);
146 }
147
148 static void
get_connection_details(TpBaseProtocol * self,GStrv * connection_interfaces,GType ** channel_managers,gchar ** icon_name,gchar ** english_name,gchar ** vcard_field)149 get_connection_details (TpBaseProtocol *self,
150 GStrv *connection_interfaces,
151 GType **channel_managers,
152 gchar **icon_name,
153 gchar **english_name,
154 gchar **vcard_field)
155 {
156 SalutProtocolPrivate *priv = SALUT_PROTOCOL (self)->priv;
157
158 if (connection_interfaces != NULL)
159 {
160 *connection_interfaces = g_strdupv (
161 (GStrv) salut_connection_get_implemented_interfaces ());
162 }
163
164 if (channel_managers != NULL)
165 {
166 GType types[] = {
167 SALUT_TYPE_CONTACT_MANAGER,
168 SALUT_TYPE_FT_MANAGER,
169 SALUT_TYPE_IM_MANAGER,
170 SALUT_TYPE_MUC_MANAGER,
171 SALUT_TYPE_ROOMLIST_MANAGER,
172 SALUT_TYPE_TUBES_MANAGER,
173 G_TYPE_INVALID };
174
175 *channel_managers = g_memdup (types, sizeof(types));
176 }
177
178 if (icon_name != NULL)
179 {
180 *icon_name = g_strdup (priv->icon_name);
181 }
182
183 if (vcard_field != NULL)
184 {
185 *vcard_field = g_strdup (VCARD_FIELD_NAME);
186 }
187
188 if (english_name != NULL)
189 {
190 *english_name = g_strdup (priv->english_name);
191 }
192 }
193
194 static void
salut_protocol_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)195 salut_protocol_get_property (GObject *object,
196 guint property_id,
197 GValue *value,
198 GParamSpec *pspec)
199 {
200 SalutProtocol *self = SALUT_PROTOCOL (object);
201
202 switch (property_id)
203 {
204 case PROP_BACKEND:
205 g_value_set_gtype (value, self->priv->backend_type);
206 break;
207
208 case PROP_DNSSD_NAME:
209 g_value_set_string (value, self->priv->dnssd_name);
210 break;
211
212 case PROP_ENGLISH_NAME:
213 g_value_set_string (value, self->priv->english_name);
214 break;
215
216 case PROP_ICON_NAME:
217 g_value_set_string (value, self->priv->icon_name);
218 break;
219
220 default:
221 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
222 break;
223 }
224 }
225
226 static void
salut_protocol_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)227 salut_protocol_set_property (GObject *object,
228 guint property_id,
229 const GValue *value,
230 GParamSpec *pspec)
231 {
232 SalutProtocol *self = SALUT_PROTOCOL (object);
233
234 switch (property_id)
235 {
236 case PROP_BACKEND:
237 {
238 GType type = g_value_get_gtype (value);
239
240 if (type == G_TYPE_NONE)
241 #ifdef USE_BACKEND_AVAHI
242 type = SALUT_TYPE_AVAHI_DISCOVERY_CLIENT;
243 #elif defined (USE_BACKEND_DUMMY)
244 type = SALUT_TYPE_DUMMY_DISCOVERY_CLIENT;
245 #elif defined (USE_BACKEND_BONJOUR)
246 type = SALUT_TYPE_BONJOUR_DISCOVERY_CLIENT;
247 #endif
248
249 self->priv->backend_type = type;
250 }
251 break;
252
253 case PROP_DNSSD_NAME:
254 self->priv->dnssd_name = g_value_dup_string (value);
255 break;
256
257 case PROP_ENGLISH_NAME:
258 self->priv->english_name = g_value_dup_string (value);
259 break;
260
261 case PROP_ICON_NAME:
262 self->priv->icon_name = g_value_dup_string (value);
263 break;
264
265 default:
266 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
267 break;
268 }
269 }
270
271 static void
salut_protocol_finalize(GObject * object)272 salut_protocol_finalize (GObject *object)
273 {
274 SalutProtocol *self = SALUT_PROTOCOL (object);
275
276 tp_clear_pointer (&self->priv->english_name, g_free);
277 tp_clear_pointer (&self->priv->icon_name, g_free);
278 tp_clear_pointer (&self->priv->dnssd_name, g_free);
279
280 if (G_OBJECT_CLASS (salut_protocol_parent_class)->finalize)
281 G_OBJECT_CLASS (salut_protocol_parent_class)->finalize (object);
282 }
283
284
285 static void
salut_protocol_class_init(SalutProtocolClass * klass)286 salut_protocol_class_init (SalutProtocolClass *klass)
287 {
288 TpBaseProtocolClass *base_class = (TpBaseProtocolClass *) klass;
289 GObjectClass *object_class = (GObjectClass *) klass;
290 GParamSpec *param_spec;
291
292 g_type_class_add_private (klass, sizeof (SalutProtocolPrivate));
293
294 base_class->get_parameters = get_parameters;
295 base_class->new_connection = new_connection;
296 base_class->normalize_contact = normalize_contact;
297 base_class->identify_account = identify_account;
298 base_class->get_interfaces = get_interfaces;
299 base_class->get_connection_details = get_connection_details;
300
301 object_class->get_property = salut_protocol_get_property;
302 object_class->set_property = salut_protocol_set_property;
303 object_class->finalize = salut_protocol_finalize;
304
305 param_spec = g_param_spec_gtype ("backend-type", "backend type",
306 "a G_TYPE_GTYPE of the backend to use", G_TYPE_NONE,
307 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
308 g_object_class_install_property (object_class, PROP_BACKEND,
309 param_spec);
310
311 param_spec = g_param_spec_string ("dnssd-name", "DNS-SD name",
312 "The DNS-SD name of the protocol", "",
313 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
314 g_object_class_install_property (object_class, PROP_DNSSD_NAME,
315 param_spec);
316
317 param_spec = g_param_spec_string ("english-name", "English name",
318 "The English name of the protocol", "",
319 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
320 g_object_class_install_property (object_class, PROP_ENGLISH_NAME,
321 param_spec);
322
323 param_spec = g_param_spec_string ("icon-name", "Icon name",
324 "The icon name of the protocol", "",
325 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
326 g_object_class_install_property (object_class, PROP_ICON_NAME,
327 param_spec);
328 }
329
330 TpBaseProtocol *
salut_protocol_new(GType backend_type,const gchar * dnssd_name,const gchar * protocol_name,const gchar * english_name,const gchar * icon_name)331 salut_protocol_new (GType backend_type,
332 const gchar *dnssd_name,
333 const gchar *protocol_name,
334 const gchar *english_name,
335 const gchar *icon_name)
336 {
337 return g_object_new (SALUT_TYPE_PROTOCOL,
338 "name", protocol_name,
339 "dnssd-name", dnssd_name,
340 "english-name", english_name,
341 "backend-type", backend_type,
342 "icon-name", icon_name,
343 NULL);
344 }
345