No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | tracker-miner-web.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * Copyright (C) 2009, Adrien Bustany <abustany@gnome.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21
22 #include <libtracker-common/tracker-dbus.h>
23
24 #include "tracker-miner-web.h"
25 #include "tracker-miner-dbus.h"
26
27 /* Introspection data for the service we are exporting */
28 static const gchar introspection_xml[] =
29 "<node>"
30 " <interface name='org.freedesktop.Tracker1.Miner.Web'>"
31 " <method name='Authenticate' />"
32 " <method name='GetAssociationData'>"
33 " <arg name='result' type='a{ss}' direction='out' />"
34 " </method>"
35 " <method name='Associate'>"
36 " <arg name='data' type='a{ss}' direction='in' />"
37 " </method>"
38 " <method name='Dissociate' />"
39 " <property name='Associated' type='b' access='read' />"
40 " </interface>"
41 "</node>";
42
43 /**
44 * SECTION:tracker-miner-web
45 * @short_description: Abstract base class for miners using web services
46 * @include: libtracker-miner/tracker-miner.h
47 *
48 * #TrackerMinerWeb is an abstract base class for miners retrieving data
49 * from web services. It's a very thin layer above #TrackerMiner, only
50 * adding virtual methods needed to handle association with the remote
51 * service.
52 **/
53
54 #define TRACKER_MINER_WEB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_MINER_WEB, TrackerMinerWebPrivate))
55
56 struct TrackerMinerWebPrivate {
57 gboolean associated;
58 GDBusNodeInfo *introspection_data;
59 guint registration_id;
60 };
61
62 enum {
63 PROP_0,
64 PROP_ASSOCIATED
65 };
66
67 static void miner_web_set_property (GObject *object,
68 guint param_id,
69 const GValue *value,
70 GParamSpec *pspec);
71 static void miner_web_get_property (GObject *object,
72 guint param_id,
73 GValue *value,
74 GParamSpec *pspec);
75 static void miner_web_initable_iface_init (GInitableIface *iface);
76 static gboolean miner_web_initable_init (GInitable *initable,
77 GCancellable *cancellable,
78 GError **error);
79 static void miner_web_finalize (GObject *object);
80 static void handle_method_call (GDBusConnection *connection,
81 const gchar *sender,
82 const gchar *object_path,
83 const gchar *interface_name,
84 const gchar *method_name,
85 GVariant *parameters,
86 GDBusMethodInvocation *invocation,
87 gpointer user_data);
88 static GVariant *handle_get_property (GDBusConnection *connection,
89 const gchar *sender,
90 const gchar *object_path,
91 const gchar *interface_name,
92 const gchar *property_name,
93 GError **error,
94 gpointer user_data);
95 static gboolean handle_set_property (GDBusConnection *connection,
96 const gchar *sender,
97 const gchar *object_path,
98 const gchar *interface_name,
99 const gchar *property_name,
100 GVariant *value,
101 GError **error,
102 gpointer user_data);
103
104 static GInitableIface* miner_web_initable_parent_iface;
105
106 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (TrackerMinerWeb, tracker_miner_web, TRACKER_TYPE_MINER,
107 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
108 miner_web_initable_iface_init));
109
110 static void
111 tracker_miner_web_class_init (TrackerMinerWebClass *klass)
112 {
113 GObjectClass *object_class = G_OBJECT_CLASS (klass);
114
115 object_class->finalize = miner_web_finalize;
116 object_class->set_property = miner_web_set_property;
117 object_class->get_property = miner_web_get_property;
118
119 g_object_class_install_property (object_class,
120 PROP_ASSOCIATED,
121 g_param_spec_boolean ("associated",
122 "Associated",
123 "Tells if the miner is associated with the remote service",
124 FALSE,
125 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
126
127 g_type_class_add_private (object_class, sizeof (TrackerMinerWebPrivate));
128 }
129
130 static void
131 tracker_miner_web_init (TrackerMinerWeb *miner)
132 {
133 miner->priv = TRACKER_MINER_WEB_GET_PRIVATE (miner);
134 }
135
136 static void
137 miner_web_initable_iface_init (GInitableIface *iface)
138 {
139 miner_web_initable_parent_iface = g_type_interface_peek_parent (iface);
140 iface->init = miner_web_initable_init;
141 }
142
143 static gboolean
144 miner_web_initable_init (GInitable *initable,
145 GCancellable *cancellable,
146 GError **error)
147 {
148 TrackerMiner *miner;
149 TrackerMinerWeb *mw;
150 GError *inner_error = NULL;
151 GDBusInterfaceVTable interface_vtable = {
152 handle_method_call,
153 handle_get_property,
154 handle_set_property
155 };
156
157 miner = TRACKER_MINER (initable);
158 mw = TRACKER_MINER_WEB (initable);
159
160 /* Chain up parent's initable callback before calling child's one */
161 if (!miner_web_initable_parent_iface->init (initable, cancellable, &inner_error)) {
162 g_propagate_error (error, inner_error);
163 return FALSE;
164 }
165
166 /* Setup web-interface introspection data */
167 mw->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, &inner_error);
168 if (!mw->priv->introspection_data) {
169 g_propagate_error (error, inner_error);
170 return FALSE;
171 }
172
173 g_message ("Registering Web interface in D-Bus object...");
174 g_message (" Path:'%s'", tracker_miner_get_dbus_full_path (miner));
175 g_message (" Object Type:'%s'", G_OBJECT_TYPE_NAME (initable));
176
177 mw->priv->registration_id =
178 g_dbus_connection_register_object (tracker_miner_get_dbus_connection (miner),
179 tracker_miner_get_dbus_full_path (miner),
180 mw->priv->introspection_data->interfaces[0],
181 &interface_vtable,
182 mw,
183 NULL,
184 &inner_error);
185 if (inner_error) {
186 g_propagate_error (error, inner_error);
187 g_prefix_error (error,
188 "Could not register the D-Bus object %s. ",
189 tracker_miner_get_dbus_full_path (miner));
190 return FALSE;
191 }
192
193 /* No need to RequestName again as already done by the parent TrackerMiner object */
194
195 return TRUE;
196 }
197
198 static void
199 miner_web_set_property (GObject *object,
200 guint param_id,
201 const GValue *value,
202 GParamSpec *pspec)
203 {
204 TrackerMinerWebPrivate *priv;
205
206 priv = TRACKER_MINER_WEB_GET_PRIVATE (object);
207
208 switch (param_id) {
209 case PROP_ASSOCIATED:
210 priv->associated = g_value_get_boolean (value);
211 g_object_notify (object, "associated");
212 break;
213 default:
214 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
215 break;
216 }
217 }
218
219 static void
220 miner_web_get_property (GObject *object,
221 guint param_id,
222 GValue *value,
223 GParamSpec *pspec)
224 {
225 TrackerMinerWebPrivate *priv;
226
227 priv = TRACKER_MINER_WEB_GET_PRIVATE (object);
228
229 switch (param_id) {
230 case PROP_ASSOCIATED:
231 g_value_set_boolean (value, priv->associated);
232 break;
233 default:
234 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
235 break;
236 }
237 }
238
239 static void
240 miner_web_finalize (GObject *object)
241 {
242 TrackerMinerWebPrivate *priv;
243
244 priv = TRACKER_MINER_WEB_GET_PRIVATE (object);
245
246 if (priv->registration_id != 0) {
247 g_dbus_connection_unregister_object (tracker_miner_get_dbus_connection (TRACKER_MINER (object)),
248 priv->registration_id);
249 }
250
251 if (priv->introspection_data) {
252 g_dbus_node_info_unref (priv->introspection_data);
253 }
254
255 G_OBJECT_CLASS (tracker_miner_web_parent_class)->finalize (object);
256 }
257
258 static void
259 handle_method_call_authenticate (TrackerMinerWeb *miner,
260 GDBusMethodInvocation *invocation,
261 GVariant *parameters)
262 {
263 GError *local_error = NULL;
264 TrackerDBusRequest *request;
265
266 request = tracker_g_dbus_request_begin (invocation, "%s()", __PRETTY_FUNCTION__);
267
268 TRACKER_MINER_WEB_GET_CLASS (miner)->authenticate (miner, &local_error);
269
270 if (local_error != NULL) {
271 tracker_dbus_request_end (request, local_error);
272
273 g_dbus_method_invocation_return_gerror (invocation, local_error);
274
275 g_error_free (local_error);
276 } else {
277 tracker_dbus_request_end (request, NULL);
278 g_dbus_method_invocation_return_value (invocation, NULL);
279 }
280 }
281
282 static GVariant*
283 variant_from_hashtable (GHashTable *table)
284 {
285 GVariantBuilder builder;
286 GHashTableIter iter;
287 gpointer key;
288 gpointer value;
289
290 g_hash_table_iter_init (&iter, table);
291 g_variant_builder_init (&builder, G_VARIANT_TYPE_DICTIONARY);
292
293 while (g_hash_table_iter_next (&iter, &key, &value)) {
294 g_variant_builder_add (&builder, "{?*}",
295 g_variant_new_string ((const gchar*) key),
296 g_variant_new_string ((const gchar *) value));
297 }
298
299 return g_variant_ref_sink (g_variant_builder_end (&builder));
300 }
301
302 static GHashTable*
303 hashtable_from_variant (GVariant *variant)
304 {
305 GHashTable* table;
306 GVariantIter iter;
307 GVariant* variant1;
308 GVariant* variant2;
309
310 table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
311 g_variant_iter_init (&iter, variant);
312
313 while (g_variant_iter_loop (&iter, "{?*}", &variant1, &variant2)) {
314 g_hash_table_insert (table,
315 g_variant_dup_string (variant1, NULL),
316 g_variant_dup_string (variant2, NULL));
317 }
318
319 return table;
320 }
321
322 static void
323 handle_method_call_get_association_data (TrackerMinerWeb *miner,
324 GDBusMethodInvocation *invocation,
325 GVariant *parameters)
326 {
327 GHashTable *association_data;
328 GError *local_error = NULL;
329 TrackerDBusRequest *request;
330
331 g_return_if_fail (TRACKER_IS_MINER_WEB (miner));
332
333 request = tracker_g_dbus_request_begin (invocation, "%s()", __PRETTY_FUNCTION__);
334
335 association_data = TRACKER_MINER_WEB_GET_CLASS (miner)->get_association_data (miner, &local_error);
336
337 if (local_error != NULL) {
338 tracker_dbus_request_end (request, local_error);
339
340 g_dbus_method_invocation_return_gerror (invocation, local_error);
341
342 g_error_free (local_error);
343 } else {
344 tracker_dbus_request_end (request, NULL);
345 g_dbus_method_invocation_return_value (invocation, variant_from_hashtable (association_data));
346
347 /* This was commented out before GDBus port too
348 * g_hash_table_unref (association_data); */
349 }
350 }
351
352 static void
353 handle_method_call_associate (TrackerMinerWeb *miner,
354 GDBusMethodInvocation *invocation,
355 GVariant *parameters)
356 {
357 GHashTable *association_data;
358 GError *local_error = NULL;
359 TrackerDBusRequest *request;
360
361 association_data = hashtable_from_variant (parameters);
362
363 request = tracker_g_dbus_request_begin (invocation, "%s()", __PRETTY_FUNCTION__);
364
365 TRACKER_MINER_WEB_GET_CLASS (miner)->associate (miner, association_data, &local_error);
366
367 g_hash_table_unref (association_data);
368
369 if (local_error != NULL) {
370 tracker_dbus_request_end (request, local_error);
371
372 g_dbus_method_invocation_return_gerror (invocation, local_error);
373
374 g_error_free (local_error);
375 } else {
376 tracker_dbus_request_end (request, NULL);
377 g_dbus_method_invocation_return_value (invocation, NULL);
378 }
379 }
380
381 static void
382 handle_method_call_dissociate (TrackerMinerWeb *miner,
383 GDBusMethodInvocation *invocation,
384 GVariant *parameters)
385 {
386 GError *local_error = NULL;
387 TrackerDBusRequest *request;
388
389 request = tracker_g_dbus_request_begin (invocation, "%s()", __PRETTY_FUNCTION__);
390
391 TRACKER_MINER_WEB_GET_CLASS (miner)->dissociate (miner, &local_error);
392
393 if (local_error != NULL) {
394 tracker_dbus_request_end (request, local_error);
395
396 g_dbus_method_invocation_return_gerror (invocation, local_error);
397
398 g_error_free (local_error);
399 } else {
400 tracker_dbus_request_end (request, NULL);
401 g_dbus_method_invocation_return_value (invocation, NULL);
402 }
403 }
404
405 static void
406 handle_method_call (GDBusConnection *connection,
407 const gchar *sender,
408 const gchar *object_path,
409 const gchar *interface_name,
410 const gchar *method_name,
411 GVariant *parameters,
412 GDBusMethodInvocation *invocation,
413 gpointer user_data)
414 {
415 TrackerMinerWeb *miner = user_data;
416
417 tracker_gdbus_async_return_if_fail (miner != NULL, invocation);
418 tracker_gdbus_async_return_if_fail (TRACKER_IS_MINER_WEB (miner), invocation);
419
420 if (g_strcmp0 (method_name, "Authenticate") == 0) {
421 handle_method_call_authenticate (miner, invocation, parameters);
422 } else
423 if (g_strcmp0 (method_name, "GetAssociationData") == 0) {
424 handle_method_call_get_association_data (miner, invocation, parameters);
425 } else
426 if (g_strcmp0 (method_name, "Associate") == 0) {
427 handle_method_call_associate (miner, invocation, parameters);
428 } else
429 if (g_strcmp0 (method_name, "Dissociate") == 0) {
430 handle_method_call_dissociate (miner, invocation, parameters);
431 } else {
432 g_assert_not_reached ();
433 }
434 }
435
436 static GVariant *
437 handle_get_property (GDBusConnection *connection,
438 const gchar *sender,
439 const gchar *object_path,
440 const gchar *interface_name,
441 const gchar *property_name,
442 GError **error,
443 gpointer user_data)
444 {
445 GVariant *ret = NULL;
446 TrackerMinerWeb *miner = user_data;
447 TrackerMinerWebPrivate *priv;
448
449 priv = TRACKER_MINER_WEB_GET_PRIVATE (miner);
450
451 if (g_strcmp0 (property_name, "Associated") == 0) {
452 ret = g_variant_new ("b", priv->associated);
453 } else {
454 g_assert_not_reached ();
455 }
456
457 return ret;
458 }
459
460 static gboolean
461 handle_set_property (GDBusConnection *connection,
462 const gchar *sender,
463 const gchar *object_path,
464 const gchar *interface_name,
465 const gchar *property_name,
466 GVariant *value,
467 GError **error,
468 gpointer user_data)
469 {
470 g_assert_not_reached ();
471 return TRUE;
472 }
473
474 /**
475 * tracker_miner_web_error_quark:
476 *
477 * Returns: the #GQuark used to identify miner web errors in GError
478 * structures.
479 *
480 * Since: 0.8
481 **/
482 GQuark
483 tracker_miner_web_error_quark (void)
484 {
485 return g_quark_from_static_string (TRACKER_MINER_WEB_ERROR_DOMAIN);
486 }
487
488 /**
489 * tracker_miner_web_authenticate:
490 * @miner: a #TrackerMinerWeb
491 * @error: (out callee-allocates) (transfer full) (allow-none): return location for errors
492 *
493 * Asks @miner to authenticate with a remote service. On failure
494 * @error will be set.
495 *
496 * Since: 0.8
497 **/
498 void
499 tracker_miner_web_authenticate (TrackerMinerWeb *miner,
500 GError **error)
501 {
502 g_return_if_fail (TRACKER_IS_MINER_WEB (miner));
503
504 TRACKER_MINER_WEB_GET_CLASS (miner)->authenticate (miner, error);
505 }
506
507 /**
508 * tracker_miner_web_get_association_data:
509 * @miner: a #TrackerMinerWeb
510 * @error: (out callee-allocates) (transfer full) (allow-none): return location for errors
511 *
512 * Asks @miner to retrieve association_data for. The data returned in
513 * the %GHashTable depends on the @miner implementation and the type
514 * of authentication. See <classname>TrackerMinerWebClass</classname>
515 * for more information.
516 *
517 * Returns: (transfer full): a %GHashTable with the data. On failure @error will be set
518 * and %NULL will be returned.
519 *
520 * Since: 0.8
521 **/
522 GHashTable *
523 tracker_miner_web_get_association_data (TrackerMinerWeb *miner,
524 GError **error)
525 {
526 g_return_val_if_fail (TRACKER_IS_MINER_WEB (miner), NULL);
527
528 return TRACKER_MINER_WEB_GET_CLASS (miner)->get_association_data (miner, error);
529 }
530
531 /**
532 * tracker_miner_web_associate:
533 * @miner: a #TrackerMinerWeb
534 * @association_data: a %GHashTable with the data to use for
535 * associating with a remote service.
536 * @error: (out callee-allocates) (transfer full) (allow-none): return location for errors
537 *
538 * Asks @miner to associate with a remote service using
539 * @association_data. To know what data to put into @association_data,
540 * see <classname>TrackerMinerWebClass</classname> for more
541 * information.
542 *
543 * On failure @error will be set.
544 *
545 * Since: 0.8
546 **/
547 void
548 tracker_miner_web_associate (TrackerMinerWeb *miner,
549 GHashTable *association_data,
550 GError **error)
551 {
552 g_return_if_fail (TRACKER_IS_MINER_WEB (miner));
553 g_return_if_fail (association_data != NULL);
554
555 TRACKER_MINER_WEB_GET_CLASS (miner)->associate (miner, association_data, error);
556 }
557
558 /**
559 * tracker_miner_web_dissociate:
560 * @miner: a #TrackerMinerWeb
561 * @error: (out callee-allocates) (transfer full) (allow-none): return location for errors
562 *
563 * Asks @miner to dissociate from a remote service. At this point, the
564 * miner should stop storing any credentials or sensitive information
565 * which could be used to authenticate with the remote service.
566 *
567 * On failure @error will be set.
568 *
569 * Since: 0.8
570 **/
571 void
572 tracker_miner_web_dissociate (TrackerMinerWeb *miner,
573 GError **error)
574 {
575 g_return_if_fail (TRACKER_IS_MINER_WEB (miner));
576
577 TRACKER_MINER_WEB_GET_CLASS (miner)->dissociate (miner, error);
578 }