1
/*
2
 * AT-SPI - Assistive Technology Service Provider Interface
3
 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4
 *
5
 * Copyright 2008, 2010 Codethink Ltd.
6
 * Copyright 2001, 2002 Sun Microsystems Inc.,
7
 * Copyright 2001, 2002 Ximian, Inc.
8
 *
9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with this library; if not, write to the
21
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22
 * Boston, MA 02110-1301, USA.
23
 */
24

            
25
#include <config.h>
26
#include <ctype.h>
27
#include <string.h>
28

            
29
#include "introspection.h"
30
#include "paths.h"
31
#include "registry.h"
32

            
33
typedef struct
34
{
35
  gchar *listener_bus_name;
36
  gchar *app_bus_name;
37
  gchar **data;
38
  GSList *properties;
39
} EventData;
40

            
41
/*---------------------------------------------------------------------------*/
42

            
43
typedef struct
44
{
45
  gchar *name;
46
  gchar *path;
47
} SpiReference;
48

            
49
static SpiReference *
50
330
spi_reference_new (const gchar *name, const gchar *path)
51
{
52
  SpiReference *ref;
53

            
54
330
  ref = g_new0 (SpiReference, 1);
55
330
  ref->name = g_strdup (name);
56
330
  ref->path = g_strdup (path);
57

            
58
330
  return ref;
59
}
60

            
61
static SpiReference *
62
6
spi_reference_null (const char *bus_name)
63
{
64
6
  return spi_reference_new (bus_name, SPI_DBUS_PATH_NULL);
65
}
66

            
67
static void
68
330
spi_reference_free (SpiReference *ref)
69
{
70
330
  g_free (ref->name);
71
330
  g_free (ref->path);
72
330
  g_free (ref);
73
330
}
74

            
75
/*---------------------------------------------------------------------------*/
76

            
77
28
G_DEFINE_TYPE (SpiRegistry, spi_registry, G_TYPE_OBJECT)
78

            
79
static void
80
28
spi_registry_finalize (GObject *object)
81
{
82
28
  SpiRegistry *registry = SPI_REGISTRY (object);
83

            
84
28
  g_clear_pointer (&registry->bus_unique_name, g_free);
85

            
86
28
  G_OBJECT_CLASS (spi_registry_parent_class)->finalize (object);
87
28
}
88

            
89
static void
90
28
spi_registry_class_init (SpiRegistryClass *klass)
91
{
92
  GObjectClass *gobject_class;
93

            
94
28
  spi_registry_parent_class = g_type_class_ref (G_TYPE_OBJECT);
95

            
96
28
  gobject_class = G_OBJECT_CLASS (klass);
97
28
  gobject_class->finalize = spi_registry_finalize;
98
28
}
99

            
100
static void
101
28
spi_registry_init (SpiRegistry *registry)
102
{
103
28
  registry->apps = g_ptr_array_new_with_free_func ((GDestroyNotify) spi_reference_free);
104
28
}
105

            
106
/*---------------------------------------------------------------------------*/
107

            
108
static void
109
5
return_v_string (DBusMessageIter *iter, const gchar *str)
110
{
111
  DBusMessageIter variant;
112

            
113
5
  if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "s",
114
                                         &variant))
115
    {
116
      g_error ("Out of memory");
117
    }
118

            
119
5
  dbus_message_iter_append_basic (&variant, DBUS_TYPE_STRING, &str);
120
5
  dbus_message_iter_close_container (iter, &variant);
121
5
}
122

            
123
static void
124
684
append_reference (DBusMessageIter *iter, SpiReference *ref)
125
{
126
  DBusMessageIter iter_struct;
127

            
128
684
  if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL,
129
                                         &iter_struct))
130
    {
131
      g_error ("Out of memory");
132
    }
133

            
134
684
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &ref->name);
135
684
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &ref->path);
136
684
  dbus_message_iter_close_container (iter, &iter_struct);
137
684
}
138

            
139
/*---------------------------------------------------------------------------*/
140

            
141
static gboolean
142
compare_reference (const SpiReference *one, const SpiReference *two)
143
{
144
  if (g_strcmp0 (one->name, two->name) == 0 &&
145
      g_strcmp0 (one->path, two->path) == 0)
146
    return TRUE;
147
  else
148
    return FALSE;
149
}
150

            
151
static gboolean
152
find_index_of_reference (GPtrArray *arr, const SpiReference *ref, guint *index)
153
{
154
  gboolean found = FALSE;
155
  guint i = 0;
156

            
157
  for (i = 0; i < arr->len; i++)
158
    {
159
      if (compare_reference (ref, g_ptr_array_index (arr, i)))
160
        {
161
          found = TRUE;
162
          break;
163
        }
164
    }
165

            
166
  *index = i;
167
  return found;
168
}
169

            
170
static void
171
324
emit_children_changed (DBusConnection *bus,
172
                       const char *operation,
173
                       dbus_int32_t index,
174
                       SpiReference *app)
175
{
176
  DBusMessage *sig;
177
  DBusMessageIter iter, iter_variant, iter_array;
178
324
  dbus_int32_t unused = 0;
179

            
180
324
  sig = dbus_message_new_signal (SPI_DBUS_PATH_ROOT,
181
                                 SPI_DBUS_INTERFACE_EVENT_OBJECT,
182
                                 "ChildrenChanged");
183

            
184
324
  dbus_message_iter_init_append (sig, &iter);
185

            
186
324
  dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &operation);
187
324
  dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &index);
188
324
  dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &unused);
189

            
190
324
  dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "(so)",
191
                                    &iter_variant);
192
324
  append_reference (&iter_variant, app);
193
324
  dbus_message_iter_close_container (&iter, &iter_variant);
194

            
195
324
  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sv}",
196
                                    &iter_array);
197
324
  dbus_message_iter_close_container (&iter, &iter_array);
198

            
199
324
  dbus_connection_send (bus, sig, NULL);
200
324
  dbus_message_unref (sig);
201
324
}
202

            
203
static void
204
162
add_application (SpiRegistry *registry, SpiReference *app_root)
205
{
206
  gint index;
207

            
208
162
  g_ptr_array_add (registry->apps, app_root);
209
162
  index = registry->apps->len - 1;
210

            
211
162
  emit_children_changed (registry->bus, "add", index, app_root);
212
162
}
213

            
214
static void
215
162
call_set_id (SpiRegistry *registry, SpiReference *app, dbus_int32_t id)
216
{
217
  DBusMessage *message;
218
  DBusMessageIter iter, iter_variant;
219
162
  const char *iface_application = "org.a11y.atspi.Application";
220
162
  const char *id_str = "Id";
221

            
222
162
  message = dbus_message_new_method_call (app->name, app->path,
223
                                          DBUS_INTERFACE_PROPERTIES, "Set");
224
162
  if (!message)
225
    return;
226
162
  dbus_message_iter_init_append (message, &iter);
227
162
  dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &iface_application);
228
162
  dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &id_str);
229
162
  dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "i", &iter_variant);
230
162
  dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_INT32, &id);
231
162
  dbus_message_iter_close_container (&iter, &iter_variant);
232
162
  dbus_connection_send (registry->bus, message, NULL);
233
162
  dbus_message_unref (message);
234
}
235

            
236
static void
237
162
remove_application (SpiRegistry *registry, guint index)
238
{
239
162
  SpiReference *ref = g_ptr_array_index (registry->apps, index);
240

            
241
162
  spi_remove_device_listeners (registry->dec, ref->name);
242
162
  emit_children_changed (registry->bus, "remove", index, ref);
243
162
  g_ptr_array_remove_index (registry->apps, index);
244
162
}
245

            
246
static gboolean
247
2
event_is_subtype (gchar **needle, gchar **haystack)
248
{
249
2
  while (*haystack && **haystack)
250
    {
251
      if (g_strcmp0 (*needle, *haystack))
252
        return FALSE;
253
      needle++;
254
      haystack++;
255
    }
256
2
  return TRUE;
257
}
258

            
259
static gboolean
260
324
needs_mouse_poll (char **event)
261
{
262
324
  if (g_strcmp0 (event[0], "Mouse") != 0)
263
324
    return FALSE;
264
  if (!event[1] || !event[1][0])
265
    return TRUE;
266
  return (g_strcmp0 (event[1], "Abs") == 0);
267
}
268

            
269
static void
270
325
remove_events (SpiRegistry *registry, const char *bus_name, const char *event)
271
{
272
  gchar **remove_data;
273
  GList *list;
274
325
  gboolean mouse_found = FALSE;
275
  DBusMessage *signal;
276

            
277
325
  remove_data = g_strsplit (event, ":", 3);
278
325
  if (!remove_data)
279
    {
280
      return;
281
    }
282

            
283
649
  for (list = registry->events; list;)
284
    {
285
324
      EventData *evdata = list->data;
286
324
      list = list->next;
287
326
      if (!g_strcmp0 (evdata->listener_bus_name, bus_name) &&
288
2
          event_is_subtype (evdata->data, remove_data))
289
        {
290
2
          g_strfreev (evdata->data);
291
2
          g_free (evdata->listener_bus_name);
292
2
          g_free (evdata->app_bus_name);
293
2
          g_slist_free_full (evdata->properties, g_free);
294
2
          registry->events = g_list_remove (registry->events, evdata);
295
2
          g_free (evdata);
296
        }
297
      else
298
        {
299
322
          if (needs_mouse_poll (evdata->data))
300
            mouse_found = TRUE;
301
        }
302
    }
303

            
304
325
  if (!mouse_found)
305
325
    spi_device_event_controller_stop_poll_mouse (registry->dec);
306

            
307
325
  g_strfreev (remove_data);
308

            
309
325
  signal = dbus_message_new_signal (SPI_DBUS_PATH_REGISTRY,
310
                                    SPI_DBUS_INTERFACE_REGISTRY,
311
                                    "EventListenerDeregistered");
312
325
  dbus_message_append_args (signal, DBUS_TYPE_STRING, &bus_name,
313
                            DBUS_TYPE_STRING, &event, DBUS_TYPE_INVALID);
314
325
  dbus_connection_send (registry->bus, signal, NULL);
315
325
  dbus_message_unref (signal);
316
}
317

            
318
static void
319
649
handle_disconnection (SpiRegistry *registry, DBusMessage *message)
320
{
321
  char *name, *old, *new;
322

            
323
649
  if (dbus_message_get_args (message, NULL,
324
                             DBUS_TYPE_STRING, &name,
325
                             DBUS_TYPE_STRING, &old,
326
                             DBUS_TYPE_STRING, &new,
327
                             DBUS_TYPE_INVALID))
328
    {
329
649
      if (*old != '\0' && *new == '\0')
330
        {
331
          /* Remove all children with the application name the same as the disconnected application. */
332
          guint i;
333
489
          for (i = 0; i < registry->apps->len; i++)
334
            {
335
164
              SpiReference *ref = g_ptr_array_index (registry->apps, i);
336
164
              if (!g_strcmp0 (old, ref->name))
337
                {
338
162
                  remove_application (registry, i);
339
162
                  i--;
340
                }
341
            }
342

            
343
325
          remove_events (registry, old, "");
344
        }
345
    }
346
649
}
347

            
348
/*
349
 * Converts names of the form "active-descendant-changed" to
350
 *" ActiveDescendantChanged"
351
 */
352
static gchar *
353
2
ensure_proper_format (const char *name)
354
{
355
2
  gchar *ret = (gchar *) g_malloc (strlen (name) * 2 + 2);
356
2
  gchar *p = ret;
357
2
  gboolean need_upper = TRUE;
358

            
359
2
  if (!ret)
360
    return NULL;
361
48
  while (*name)
362
    {
363
46
      if (need_upper)
364
        {
365
6
          *p++ = toupper (*name);
366
6
          need_upper = FALSE;
367
        }
368
40
      else if (*name == '-')
369
2
        need_upper = TRUE;
370
38
      else if (*name == ':')
371
        {
372
2
          need_upper = TRUE;
373
2
          *p++ = *name;
374
        }
375
      else
376
36
        *p++ = *name;
377
46
      name++;
378
    }
379
2
  *p = '\0';
380
2
  return ret;
381
}
382

            
383
static DBusHandlerResult
384
2074
signal_filter (DBusConnection *bus, DBusMessage *message, void *user_data)
385
{
386
2074
  SpiRegistry *reg = SPI_REGISTRY (user_data);
387
2074
  guint res = DBUS_HANDLER_RESULT_HANDLED;
388

            
389
2074
  const gint type = dbus_message_get_type (message);
390
2074
  const char *iface = dbus_message_get_interface (message);
391
2074
  const char *member = dbus_message_get_member (message);
392

            
393
2074
  if (type != DBUS_MESSAGE_TYPE_SIGNAL)
394
1369
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
395

            
396
1410
  if (!g_strcmp0 (iface, DBUS_INTERFACE_DBUS) &&
397
705
      !g_strcmp0 (member, "NameOwnerChanged"))
398
649
    handle_disconnection (reg, message);
399
  else
400
56
    res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
401

            
402
705
  return res;
403
}
404

            
405
typedef enum
406
{
407
  DEMARSHAL_STATUS_SUCCESS,
408
  DEMARSHAL_STATUS_INVALID_SIGNATURE,
409
  DEMARSHAL_STATUS_INVALID_VALUE,
410
} DemarshalStatus;
411

            
412
/* org.at_spi.Socket interface */
413
/*---------------------------------------------------------------------------*/
414

            
415
static DemarshalStatus
416
162
demarshal_reference (DBusMessage *message, SpiReference **out_reference)
417
{
418
  DBusMessageIter iter, iter_struct;
419
  const gchar *app_name, *obj_path;
420

            
421
162
  *out_reference = NULL;
422

            
423
162
  dbus_message_iter_init (message, &iter);
424
162
  dbus_message_iter_recurse (&iter, &iter_struct);
425
162
  if (!(dbus_message_iter_get_arg_type (&iter_struct) == DBUS_TYPE_STRING))
426
    return DEMARSHAL_STATUS_INVALID_SIGNATURE;
427
162
  dbus_message_iter_get_basic (&iter_struct, &app_name);
428
162
  if (!app_name)
429
    app_name = dbus_message_get_sender (message);
430
162
  if (!dbus_message_iter_next (&iter_struct))
431
    return DEMARSHAL_STATUS_INVALID_SIGNATURE;
432
162
  if (!(dbus_message_iter_get_arg_type (&iter_struct) == DBUS_TYPE_OBJECT_PATH))
433
    return DEMARSHAL_STATUS_INVALID_SIGNATURE;
434
162
  dbus_message_iter_get_basic (&iter_struct, &obj_path);
435

            
436
162
  *out_reference = spi_reference_new (app_name, obj_path);
437

            
438
162
  return DEMARSHAL_STATUS_SUCCESS;
439
}
440

            
441
static SpiReference *
442
162
socket_embed (SpiRegistry *registry, SpiReference *app_root)
443
{
444
162
  add_application (registry, app_root);
445
162
  call_set_id (registry, app_root, registry->id);
446
  /* TODO: This will cause problems if we cycle through 2^31 ids */
447
162
  registry->id++;
448
162
  return spi_reference_new (registry->bus_unique_name, SPI_DBUS_PATH_ROOT);
449
}
450

            
451
static DBusMessage *
452
162
impl_Embed (DBusMessage *message, SpiRegistry *registry)
453
{
454
162
  SpiReference *app_root = NULL;
455
  SpiReference *result;
456

            
457
162
  if (demarshal_reference (message, &app_root) != DEMARSHAL_STATUS_SUCCESS)
458
    {
459
      return dbus_message_new_error (message, DBUS_ERROR_FAILED, "Invalid arguments");
460
    }
461

            
462
162
  DBusMessage *reply = NULL;
463
  DBusMessageIter reply_iter;
464

            
465
162
  result = socket_embed (registry, app_root); /* takes ownership of the app_root */
466

            
467
162
  reply = dbus_message_new_method_return (message);
468
162
  dbus_message_iter_init_append (reply, &reply_iter);
469
162
  append_reference (&reply_iter, result);
470
162
  spi_reference_free (result);
471

            
472
162
  return reply;
473
}
474

            
475
static DBusMessage *
476
impl_Unembed (DBusMessage *message, SpiRegistry *registry)
477
{
478
  SpiReference *app_reference;
479
  guint index;
480

            
481
  if (demarshal_reference (message, &app_reference) != DEMARSHAL_STATUS_SUCCESS)
482
    {
483
      return dbus_message_new_error (message, DBUS_ERROR_FAILED, "Invalid arguments");
484
    }
485

            
486
  if (find_index_of_reference (registry->apps, app_reference, &index))
487
    remove_application (registry, index);
488

            
489
  spi_reference_free (app_reference);
490

            
491
  return NULL;
492
}
493

            
494
/* org.at_spi.Component interface */
495
/*---------------------------------------------------------------------------*/
496

            
497
static DBusMessage *
498
1
impl_Contains (DBusMessage *message, SpiRegistry *registry)
499
{
500
1
  dbus_bool_t retval = FALSE;
501
  DBusMessage *reply;
502

            
503
1
  reply = dbus_message_new_method_return (message);
504
1
  dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &retval,
505
                            DBUS_TYPE_INVALID);
506
1
  return reply;
507
}
508

            
509
static DBusMessage *
510
1
impl_GetAccessibleAtPoint (DBusMessage *message, SpiRegistry *registry)
511
{
512
1
  DBusMessage *reply = NULL;
513
  DBusMessageIter iter;
514
1
  SpiReference *null_ref = spi_reference_null (registry->bus_unique_name);
515

            
516
1
  reply = dbus_message_new_method_return (message);
517
1
  dbus_message_iter_init_append (reply, &iter);
518
1
  append_reference (&iter, null_ref);
519
1
  spi_reference_free (null_ref);
520

            
521
1
  return reply;
522
}
523

            
524
static DBusMessage *
525
1
impl_GetExtents (DBusMessage *message, SpiRegistry *registry)
526
{
527
1
  dbus_int32_t x = 0, y = 0, width = 1024, height = 768;
528
  DBusMessage *reply;
529
  DBusMessageIter iter, iter_struct;
530

            
531
1
  reply = dbus_message_new_method_return (message);
532
1
  dbus_message_iter_init_append (reply, &iter);
533
1
  dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL,
534
                                    &iter_struct);
535
1
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &x);
536
1
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &y);
537
1
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &width);
538
1
  dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &height);
539
1
  dbus_message_iter_close_container (&iter, &iter_struct);
540
1
  return reply;
541
}
542

            
543
static DBusMessage *
544
1
impl_GetPosition (DBusMessage *message, SpiRegistry *registry)
545
{
546
  DBusMessage *reply;
547
1
  dbus_int32_t x = 0, y = 0;
548

            
549
1
  reply = dbus_message_new_method_return (message);
550
1
  dbus_message_append_args (reply, DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32,
551
                            &y, DBUS_TYPE_INVALID);
552
1
  return reply;
553
}
554

            
555
static DBusMessage *
556
1
impl_GetSize (DBusMessage *message, SpiRegistry *registry)
557
{
558
  /* TODO - Get the screen size */
559
  DBusMessage *reply;
560
1
  dbus_int32_t width = 1024, height = 768;
561

            
562
1
  reply = dbus_message_new_method_return (message);
563
1
  dbus_message_append_args (reply, DBUS_TYPE_INT32, &width,
564
                            DBUS_TYPE_INT32, &height, DBUS_TYPE_INVALID);
565
1
  return reply;
566
}
567

            
568
#define LAYER_WIDGET 3;
569

            
570
static DBusMessage *
571
1
impl_GetLayer (DBusMessage *message, SpiRegistry *registry)
572
{
573
  DBusMessage *reply;
574
1
  dbus_uint32_t rv = LAYER_WIDGET;
575

            
576
1
  reply = dbus_message_new_method_return (message);
577
1
  dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv,
578
                            DBUS_TYPE_INVALID);
579
1
  return reply;
580
}
581

            
582
static DBusMessage *
583
1
impl_GetMDIZOrder (DBusMessage *message, SpiRegistry *registry)
584
{
585
  DBusMessage *reply;
586
1
  dbus_int16_t rv = 0;
587

            
588
1
  reply = dbus_message_new_method_return (message);
589
1
  dbus_message_append_args (reply, DBUS_TYPE_INT16, &rv,
590
                            DBUS_TYPE_INVALID);
591
1
  return reply;
592
}
593

            
594
static DBusMessage *
595
1
impl_GrabFocus (DBusMessage *message, SpiRegistry *registry)
596
{
597
  DBusMessage *reply;
598
1
  dbus_bool_t retval = FALSE;
599

            
600
1
  reply = dbus_message_new_method_return (message);
601
1
  dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &retval,
602
                            DBUS_TYPE_INVALID);
603
1
  return reply;
604
}
605

            
606
static DBusMessage *
607
1
impl_GetAlpha (DBusMessage *message, SpiRegistry *registry)
608
{
609
1
  double rv = 1.0;
610
  DBusMessage *reply;
611

            
612
1
  reply = dbus_message_new_method_return (message);
613
1
  dbus_message_append_args (reply, DBUS_TYPE_DOUBLE, &rv,
614
                            DBUS_TYPE_INVALID);
615
1
  return reply;
616
}
617

            
618
/* org.at_spi.Accessible interface */
619
/*---------------------------------------------------------------------------*/
620

            
621
static void
622
2
impl_get_Name (DBusMessageIter *iter, SpiRegistry *registry)
623
{
624
2
  const gchar *name = "main";
625
2
  return_v_string (iter, name);
626
2
}
627

            
628
static void
629
1
impl_get_Description (DBusMessageIter *iter, SpiRegistry *registry)
630
{
631
1
  const gchar *description = "";
632
1
  return_v_string (iter, description);
633
1
}
634

            
635
static dbus_bool_t
636
2
impl_get_Parent (DBusMessageIter *iter, SpiRegistry *registry)
637
{
638
  DBusMessageIter iter_variant;
639
2
  SpiReference *null_ref = spi_reference_null ("");
640

            
641
2
  dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "(so)",
642
                                    &iter_variant);
643
2
  append_reference (&iter_variant, null_ref);
644
2
  spi_reference_free (null_ref);
645
2
  dbus_message_iter_close_container (iter, &iter_variant);
646
2
  return TRUE;
647
}
648

            
649
static dbus_bool_t
650
163
impl_get_ChildCount (DBusMessageIter *iter, SpiRegistry *registry)
651
{
652
163
  dbus_int32_t rv = registry->apps->len;
653
  dbus_bool_t result;
654
  DBusMessageIter iter_variant;
655

            
656
163
  if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "i",
657
                                         &iter_variant))
658
    return FALSE;
659
163
  result = dbus_message_iter_append_basic (&iter_variant, DBUS_TYPE_INT32, &rv);
660
163
  dbus_message_iter_close_container (iter, &iter_variant);
661
163
  return result;
662
}
663

            
664
static void
665
1
impl_get_ToolkitName (DBusMessageIter *iter, SpiRegistry *registry)
666
{
667
1
  return_v_string (iter, "at-spi-registry");
668
1
}
669

            
670
static void
671
1
impl_get_ToolkitVersion (DBusMessageIter *iter, SpiRegistry *registry)
672
{
673
1
  return_v_string (iter, "2.0");
674
1
}
675

            
676
static DBusMessage *
677
164
impl_GetChildAtIndex (DBusMessage *message, SpiRegistry *registry)
678
{
679
  DBusMessage *reply;
680
  DBusMessageIter iter;
681
  DBusError error;
682
  SpiReference *ref;
683
  dbus_int32_t i;
684

            
685
164
  dbus_error_init (&error);
686
164
  if (!dbus_message_get_args (message, &error, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID))
687
    {
688
      return dbus_message_new_error (message, DBUS_ERROR_FAILED, "Invalid arguments");
689
    }
690

            
691
164
  reply = dbus_message_new_method_return (message);
692
164
  dbus_message_iter_init_append (reply, &iter);
693

            
694
164
  if (i < 0 || i >= registry->apps->len)
695
2
    {
696
2
      SpiReference *null_ref = spi_reference_null (SPI_DBUS_NAME_REGISTRY);
697
2
      append_reference (&iter, null_ref);
698
2
      spi_reference_free (null_ref);
699
    }
700
  else
701
    {
702
162
      ref = g_ptr_array_index (registry->apps, i);
703
162
      append_reference (&iter, ref);
704
    }
705

            
706
164
  return reply;
707
}
708

            
709
static DBusMessage *
710
3
impl_GetChildren (DBusMessage *message, SpiRegistry *registry)
711
{
712
3
  DBusMessage *reply = NULL;
713
  DBusMessageIter iter, iter_array;
714
  int i;
715

            
716
3
  reply = dbus_message_new_method_return (message);
717

            
718
3
  dbus_message_iter_init_append (reply, &iter);
719
3
  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(so)", &iter_array);
720
5
  for (i = 0; i < registry->apps->len; i++)
721
    {
722
2
      SpiReference *current = g_ptr_array_index (registry->apps, i);
723
2
      append_reference (&iter_array, current);
724
    }
725
3
  dbus_message_iter_close_container (&iter, &iter_array);
726
3
  return reply;
727
}
728

            
729
static DBusMessage *
730
1
impl_GetIndexInParent (DBusMessage *message, SpiRegistry *registry)
731
{
732
  DBusMessage *reply;
733
1
  dbus_uint32_t rv = 0;
734

            
735
1
  reply = dbus_message_new_method_return (message);
736
1
  dbus_message_append_args (reply, DBUS_TYPE_INT32, &rv, DBUS_TYPE_INVALID);
737
1
  return reply;
738
}
739

            
740
static DBusMessage *
741
1
impl_GetRelationSet (DBusMessage *message, SpiRegistry *registry)
742
{
743
  DBusMessage *reply;
744
  DBusMessageIter iter, iter_array;
745

            
746
1
  reply = dbus_message_new_method_return (message);
747
1
  dbus_message_iter_init_append (reply, &iter);
748
1
  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ua(so))", &iter_array);
749
1
  dbus_message_iter_close_container (&iter, &iter_array);
750

            
751
1
  return reply;
752
}
753

            
754
static DBusMessage *
755
5
impl_GetRole (DBusMessage *message, SpiRegistry *registry)
756
{
757
  DBusMessage *reply;
758
5
  dbus_uint32_t rv = 14; /* TODO: Get DESKTOP_FRAME from somewhere */
759

            
760
5
  reply = dbus_message_new_method_return (message);
761
5
  dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv, DBUS_TYPE_INVALID);
762
5
  return reply;
763
}
764

            
765
static DBusMessage *
766
1
impl_GetRoleName (DBusMessage *message, SpiRegistry *registry)
767
{
768
  DBusMessage *reply;
769
1
  const char *role_name = "desktop frame";
770

            
771
1
  reply = dbus_message_new_method_return (message);
772
1
  dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
773
                            DBUS_TYPE_INVALID);
774
1
  return reply;
775
}
776

            
777
static DBusMessage *
778
1
impl_GetLocalizedRoleName (DBusMessage *message, SpiRegistry *registry)
779
{
780
  /* FIXME - Localize this */
781
  DBusMessage *reply;
782
1
  const char *role_name = "desktop frame";
783

            
784
1
  reply = dbus_message_new_method_return (message);
785
1
  dbus_message_append_args (reply, DBUS_TYPE_STRING, &role_name,
786
                            DBUS_TYPE_INVALID);
787
1
  return reply;
788
}
789

            
790
static DBusMessage *
791
1
impl_GetState (DBusMessage *message, SpiRegistry *registry)
792
{
793
1
  DBusMessage *reply = NULL;
794
  DBusMessageIter iter, iter_array;
795

            
796
1
  dbus_uint32_t states[2] = { 0, 0 };
797
  guint count;
798

            
799
1
  reply = dbus_message_new_method_return (message);
800
1
  dbus_message_iter_init_append (reply, &iter);
801

            
802
1
  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "u", &iter_array);
803
3
  for (count = 0; count < 2; count++)
804
    {
805
2
      dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_UINT32,
806
2
                                      &states[count]);
807
    }
808
1
  dbus_message_iter_close_container (&iter, &iter_array);
809
1
  return reply;
810
}
811

            
812
static DBusMessage *
813
1
impl_GetAttributes (DBusMessage *message, SpiRegistry *registry)
814
{
815
1
  DBusMessage *reply = NULL;
816
  DBusMessageIter iter, array;
817

            
818
1
  reply = dbus_message_new_method_return (message);
819
1
  dbus_message_iter_init_append (reply, &iter);
820
1
  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{ss}", &array);
821
1
  dbus_message_iter_close_container (&iter, &array);
822

            
823
1
  return reply;
824
}
825

            
826
static DBusMessage *
827
1
impl_GetApplication (DBusMessage *message, SpiRegistry *registry)
828
{
829
1
  DBusMessage *reply = NULL;
830
  DBusMessageIter iter;
831
1
  SpiReference *null_ref = spi_reference_null (registry->bus_unique_name);
832

            
833
1
  reply = dbus_message_new_method_return (message);
834
1
  dbus_message_iter_init_append (reply, &iter);
835
1
  append_reference (&iter, null_ref);
836
1
  spi_reference_free (null_ref);
837

            
838
1
  return reply;
839
}
840

            
841
static DBusMessage *
842
1
impl_GetInterfaces (DBusMessage *message, SpiRegistry *registry)
843
{
844
  DBusMessage *reply;
845
  DBusMessageIter iter, iter_array;
846

            
847
1
  const char *acc = SPI_DBUS_INTERFACE_ACCESSIBLE;
848
1
  const char *app = SPI_DBUS_INTERFACE_APPLICATION;
849
1
  const char *com = SPI_DBUS_INTERFACE_COMPONENT;
850
1
  const char *sock = SPI_DBUS_INTERFACE_SOCKET;
851

            
852
1
  reply = dbus_message_new_method_return (message);
853

            
854
1
  dbus_message_iter_init_append (reply, &iter);
855
1
  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s",
856
                                    &iter_array);
857
1
  dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &acc);
858
1
  dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &app);
859
1
  dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &com);
860
1
  dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &sock);
861
1
  dbus_message_iter_close_container (&iter, &iter_array);
862

            
863
1
  return reply;
864
}
865

            
866
static DBusMessage *
867
4
impl_GetItems (DBusMessage *message, SpiRegistry *registry)
868
{
869
  DBusMessage *reply;
870
  DBusMessageIter iter, iter_array;
871

            
872
4
  reply = dbus_message_new_method_return (message);
873

            
874
4
  dbus_message_iter_init_append (reply, &iter);
875
4
  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
876
                                    "((so)(so)(so)a(so)assusau)", &iter_array);
877
4
  dbus_message_iter_close_container (&iter, &iter_array);
878
4
  return reply;
879
}
880

            
881
/* I would rather these two be signals, but I'm not sure that dbus-python
882
 * supports emitting signals except for a service, so implementing as both
883
 * a method call and signal for now.
884
 */
885
static DBusMessage *
886
2
impl_RegisterEvent (DBusMessage *message, SpiRegistry *registry)
887
{
888
  const char *orig_name;
889
  gchar *name;
890
  EventData *evdata;
891
  gchar **data;
892
  DBusMessage *signal;
893
2
  const char *sender = dbus_message_get_sender (message);
894
  DBusMessageIter iter, iter_array;
895
2
  const char *signature = dbus_message_get_signature (message);
896

            
897
2
  if (strcmp (signature, "sas") != 0 &&
898
2
      strcmp (signature, "s") != 0 &&
899
2
      strcmp (signature, "sass") != 0)
900
    {
901
      g_warning ("got RegisterEvent with invalid signature '%s'", signature);
902
      return NULL;
903
    }
904

            
905
2
  dbus_message_iter_init (message, &iter);
906
2
  dbus_message_iter_get_basic (&iter, &orig_name);
907
2
  dbus_message_iter_next (&iter);
908
2
  name = ensure_proper_format (orig_name);
909

            
910
2
  evdata = g_new0 (EventData, 1);
911
2
  data = g_strsplit (name, ":", 3);
912
2
  evdata->listener_bus_name = g_strdup (sender);
913
2
  evdata->data = data;
914

            
915
2
  if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY)
916
    {
917
2
      dbus_message_iter_recurse (&iter, &iter_array);
918
2
      while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
919
        {
920
          const char *property;
921
          dbus_message_iter_get_basic (&iter_array, &property);
922
          evdata->properties = g_slist_append (evdata->properties,
923
                                               g_strdup (property));
924
          dbus_message_iter_next (&iter_array);
925
        }
926
2
      dbus_message_iter_next (&iter);
927
    }
928

            
929
2
  if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING)
930
    {
931
      const char *app;
932
2
      dbus_message_iter_get_basic (&iter, &app);
933
2
      if (app[0])
934
        evdata->app_bus_name = g_strdup (app);
935
2
      dbus_message_iter_next (&iter);
936
    }
937

            
938
2
  registry->events = g_list_append (registry->events, evdata);
939

            
940
2
  if (needs_mouse_poll (evdata->data))
941
    {
942
      spi_device_event_controller_start_poll_mouse (registry->dec);
943
    }
944

            
945
2
  signal = dbus_message_new_signal (SPI_DBUS_PATH_REGISTRY,
946
                                    SPI_DBUS_INTERFACE_REGISTRY,
947
                                    "EventListenerRegistered");
948
2
  if (signal)
949
    {
950
2
      GSList *ls = evdata->properties;
951
2
      if (evdata->app_bus_name)
952
        dbus_message_set_destination (message, evdata->app_bus_name);
953
2
      dbus_message_iter_init_append (signal, &iter);
954
2
      dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &sender);
955
2
      dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &name);
956
2
      dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &iter_array);
957
2
      while (ls)
958
        {
959
          dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &ls->data);
960
          ls = g_slist_next (ls);
961
        }
962
2
      dbus_message_iter_close_container (&iter, &iter_array);
963
2
      dbus_connection_send (registry->bus, signal, NULL);
964
2
      dbus_message_unref (signal);
965
    }
966

            
967
2
  g_free (name);
968
2
  return dbus_message_new_method_return (message);
969
}
970

            
971
static DBusMessage *
972
impl_DeregisterEvent (DBusMessage *message, SpiRegistry *registry)
973
{
974
  const char *orig_name;
975
  gchar *name;
976
  const char *sender = dbus_message_get_sender (message);
977

            
978
  if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &orig_name,
979
                              DBUS_TYPE_INVALID))
980
    return NULL;
981
  name = ensure_proper_format (orig_name);
982

            
983
  remove_events (registry, sender, name);
984

            
985
  g_free (name);
986
  return dbus_message_new_method_return (message);
987
}
988

            
989
static DBusMessage *
990
161
impl_GetRegisteredEvents (DBusMessage *message, SpiRegistry *registry)
991
{
992
  EventData *evdata;
993
  DBusMessage *reply;
994
  DBusMessageIter iter, iter_struct, iter_array;
995
  GList *list;
996
161
  const char *sender = dbus_message_get_sender (message);
997

            
998
161
  reply = dbus_message_new_method_return (message);
999
161
  if (!reply)
    return NULL;
161
  dbus_message_iter_init_append (reply, &iter);
161
  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ss)", &iter_array);
322
  for (list = registry->events; list; list = list->next)
    {
      gchar *str;
161
      evdata = list->data;
161
      if (evdata->app_bus_name && strcmp (evdata->app_bus_name, sender) != 0)
        continue;
322
      str = g_strconcat (evdata->data[0],
161
                         ":", (evdata->data[1] ? evdata->data[1] : ""),
161
                         ":", (evdata->data[1] && evdata->data[2] ? evdata->data[2] : ""), NULL);
161
      dbus_message_iter_open_container (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct);
161
      dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &evdata->listener_bus_name);
161
      dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &str);
161
      dbus_message_iter_close_container (&iter_array, &iter_struct);
161
      g_free (str);
    }
161
  dbus_message_iter_close_container (&iter, &iter_array);
161
  return reply;
}
/*---------------------------------------------------------------------------*/
static void
28
emit_Available (DBusConnection *bus)
{
  DBusMessage *sig;
  DBusMessageIter iter;
28
  SpiReference root_ref = {
    SPI_DBUS_NAME_REGISTRY,
    SPI_DBUS_PATH_ROOT,
  };
28
  sig = dbus_message_new_signal (SPI_DBUS_PATH_ROOT, SPI_DBUS_INTERFACE_SOCKET, "Available");
28
  dbus_message_iter_init_append (sig, &iter);
28
  append_reference (&iter, &root_ref);
28
  dbus_connection_send (bus, sig, NULL);
28
  dbus_message_unref (sig);
28
}
/*---------------------------------------------------------------------------*/
static const char *introspection_header =
    "<?xml version=\"1.0\"?>\n";
static const char *introspection_node_element =
    "<node name=\"%s\">\n";
static const char *introspection_footer =
    "</node>";
static DBusMessage *
27
impl_Introspect_root (DBusMessage *message, SpiRegistry *registry)
{
  GString *output;
  gchar *final;
27
  const gchar *pathstr = SPI_DBUS_PATH_ROOT;
  DBusMessage *reply;
27
  output = g_string_new (introspection_header);
27
  g_string_append_printf (output, introspection_node_element, pathstr);
27
  g_string_append (output, spi_org_a11y_atspi_Accessible);
27
  g_string_append (output, spi_org_a11y_atspi_Component);
27
  g_string_append (output, spi_org_a11y_atspi_Socket);
27
  g_string_append (output, introspection_footer);
27
  final = g_string_free (output, FALSE);
27
  reply = dbus_message_new_method_return (message);
27
  dbus_message_append_args (reply, DBUS_TYPE_STRING, &final, DBUS_TYPE_INVALID);
27
  g_free (final);
27
  return reply;
}
static DBusMessage *
2
impl_Introspect_registry (DBusMessage *message, SpiRegistry *registry)
{
  GString *output;
  gchar *final;
2
  const gchar *pathstr = SPI_DBUS_PATH_REGISTRY;
  DBusMessage *reply;
2
  output = g_string_new (introspection_header);
2
  g_string_append_printf (output, introspection_node_element, pathstr);
2
  g_string_append (output, spi_org_a11y_atspi_Registry);
2
  g_string_append (output, introspection_footer);
2
  final = g_string_free (output, FALSE);
2
  reply = dbus_message_new_method_return (message);
2
  dbus_message_append_args (reply, DBUS_TYPE_STRING, &final, DBUS_TYPE_INVALID);
2
  g_free (final);
2
  return reply;
}
/*---------------------------------------------------------------------------*/
static DBusHandlerResult
555
handle_method_root (DBusConnection *bus, DBusMessage *message, void *user_data)
{
555
  SpiRegistry *registry = SPI_REGISTRY (user_data);
555
  DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
555
  const gchar *iface = dbus_message_get_interface (message);
555
  const gchar *member = dbus_message_get_member (message);
555
  const gint type = dbus_message_get_type (message);
555
  DBusMessage *reply = NULL;
  /* Check for basic reasons not to handle */
555
  if (type != DBUS_MESSAGE_TYPE_METHOD_CALL ||
555
      member == NULL ||
      iface == NULL)
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
555
  if (!strcmp (iface, "org.freedesktop.DBus.Properties"))
    {
173
      if (!strcmp (member, "Get"))
        {
          const gchar *prop_iface;
          const gchar *prop_member;
          DBusError error;
173
          dbus_error_init (&error);
173
          if (dbus_message_get_args (message,
                                     &error,
                                     DBUS_TYPE_STRING,
                                     &prop_iface,
                                     DBUS_TYPE_STRING,
                                     &prop_member,
                                     DBUS_TYPE_INVALID))
            {
              DBusMessageIter iter;
173
              reply = dbus_message_new_method_return (message);
173
              dbus_message_iter_init_append (reply, &iter);
173
              if (!strcmp (prop_iface, SPI_DBUS_INTERFACE_ACCESSIBLE))
                {
169
                  if (!strcmp (prop_member, "Name"))
2
                    impl_get_Name (&iter, registry);
167
                  else if (!strcmp (prop_member, "Description"))
1
                    impl_get_Description (&iter, registry);
166
                  else if (!strcmp (prop_member, "Parent"))
2
                    impl_get_Parent (&iter, registry);
164
                  else if (!strcmp (prop_member, "ChildCount"))
163
                    impl_get_ChildCount (&iter, registry);
                  else
                    {
1
                      dbus_message_unref (reply);
1
                      reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "Property unavailable");
                    }
                }
4
              else if (!strcmp (prop_iface, SPI_DBUS_INTERFACE_APPLICATION))
                {
3
                  if (!strcmp (prop_member, "ToolkitName"))
1
                    impl_get_ToolkitName (&iter, registry);
2
                  else if (!strcmp (prop_member, "Version"))
1
                    impl_get_ToolkitVersion (&iter, registry);
                  else
                    {
1
                      dbus_message_unref (reply);
1
                      reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "Property unavailable");
                    }
                }
              else
                {
1
                  dbus_message_unref (reply);
1
                  reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, "Property unavailable");
                }
            }
          else
            {
              reply = dbus_message_new_error (message, DBUS_ERROR_FAILED, error.message);
            }
173
          result = DBUS_HANDLER_RESULT_HANDLED;
        }
      else if (!strcmp (member, "GetAll"))
        {
          result = DBUS_HANDLER_RESULT_HANDLED;
        }
    }
555
  if (!strcmp (iface, SPI_DBUS_INTERFACE_ACCESSIBLE))
    {
180
      result = DBUS_HANDLER_RESULT_HANDLED;
180
      if (!strcmp (member, "GetChildAtIndex"))
164
        reply = impl_GetChildAtIndex (message, registry);
16
      else if (!strcmp (member, "GetChildren"))
3
        reply = impl_GetChildren (message, registry);
13
      else if (!strcmp (member, "GetIndexInParent"))
1
        reply = impl_GetIndexInParent (message, registry);
12
      else if (!strcmp (member, "GetRelationSet"))
1
        reply = impl_GetRelationSet (message, registry);
11
      else if (!strcmp (member, "GetRole"))
5
        reply = impl_GetRole (message, registry);
6
      else if (!strcmp (member, "GetRoleName"))
1
        reply = impl_GetRoleName (message, registry);
5
      else if (!strcmp (member, "GetLocalizedRoleName"))
1
        reply = impl_GetLocalizedRoleName (message, registry);
4
      else if (!strcmp (member, "GetState"))
1
        reply = impl_GetState (message, registry);
3
      else if (!strcmp (member, "GetAttributes"))
1
        reply = impl_GetAttributes (message, registry);
2
      else if (!strcmp (member, "GetApplication"))
1
        reply = impl_GetApplication (message, registry);
1
      else if (!strcmp (member, "GetInterfaces"))
1
        reply = impl_GetInterfaces (message, registry);
      else
        result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    }
555
  if (!strcmp (iface, SPI_DBUS_INTERFACE_COMPONENT))
    {
9
      result = DBUS_HANDLER_RESULT_HANDLED;
9
      if (!strcmp (member, "Contains"))
1
        reply = impl_Contains (message, registry);
8
      else if (!strcmp (member, "GetAccessibleAtPoint"))
1
        reply = impl_GetAccessibleAtPoint (message, registry);
7
      else if (!strcmp (member, "GetExtents"))
1
        reply = impl_GetExtents (message, registry);
6
      else if (!strcmp (member, "GetPosition"))
1
        reply = impl_GetPosition (message, registry);
5
      else if (!strcmp (member, "GetSize"))
1
        reply = impl_GetSize (message, registry);
4
      else if (!strcmp (member, "GetLayer"))
1
        reply = impl_GetLayer (message, registry);
3
      else if (!strcmp (member, "GetMDIZOrder"))
1
        reply = impl_GetMDIZOrder (message, registry);
2
      else if (!strcmp (member, "GrabFocus"))
1
        reply = impl_GrabFocus (message, registry);
1
      else if (!strcmp (member, "GetAlpha"))
1
        reply = impl_GetAlpha (message, registry);
      else
        result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    }
555
  if (!strcmp (iface, SPI_DBUS_INTERFACE_SOCKET))
    {
162
      result = DBUS_HANDLER_RESULT_HANDLED;
162
      if (!strcmp (member, "Embed"))
162
        reply = impl_Embed (message, registry);
      else if (!strcmp (member, "Unembed"))
        reply = impl_Unembed (message, registry);
      else
        result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    }
555
  if (!strcmp (iface, "org.freedesktop.DBus.Introspectable"))
    {
27
      result = DBUS_HANDLER_RESULT_HANDLED;
27
      if (!strcmp (member, "Introspect"))
27
        reply = impl_Introspect_root (message, registry);
      else
        result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    }
555
  if (result == DBUS_HANDLER_RESULT_HANDLED)
    {
551
      if (!reply)
        {
          reply = dbus_message_new_method_return (message);
        }
551
      dbus_connection_send (bus, reply, NULL);
551
      dbus_message_unref (reply);
    }
#if 0
  else
    {
      g_print ("Registry | Unhandled message : %s|%s\n", iface, member);
    }
#endif
555
  return result;
}
static DBusHandlerResult
4
handle_method_cache (DBusConnection *bus, DBusMessage *message, void *user_data)
{
4
  SpiRegistry *registry = SPI_REGISTRY (user_data);
4
  DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4
  const gchar *iface = dbus_message_get_interface (message);
4
  const gchar *member = dbus_message_get_member (message);
4
  const gint type = dbus_message_get_type (message);
4
  DBusMessage *reply = NULL;
  /* Check for basic reasons not to handle */
4
  if (type != DBUS_MESSAGE_TYPE_METHOD_CALL ||
4
      member == NULL ||
      iface == NULL)
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
4
  if (!strcmp (iface, SPI_DBUS_INTERFACE_CACHE))
    {
4
      result = DBUS_HANDLER_RESULT_HANDLED;
4
      if (!strcmp (member, "GetItems"))
4
        reply = impl_GetItems (message, registry);
      else
        result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    }
4
  if (result == DBUS_HANDLER_RESULT_HANDLED)
    {
4
      if (!reply)
        {
          reply = dbus_message_new_method_return (message);
        }
4
      dbus_connection_send (bus, reply, NULL);
4
      dbus_message_unref (reply);
    }
4
  return result;
}
static DBusHandlerResult
326
handle_method_registry (DBusConnection *bus, DBusMessage *message, void *user_data)
{
326
  SpiRegistry *registry = SPI_REGISTRY (user_data);
326
  DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
326
  const gchar *iface = dbus_message_get_interface (message);
326
  const gchar *member = dbus_message_get_member (message);
326
  const gint type = dbus_message_get_type (message);
326
  DBusMessage *reply = NULL;
  /* Check for basic reasons not to handle */
326
  if (type != DBUS_MESSAGE_TYPE_METHOD_CALL ||
326
      member == NULL ||
      iface == NULL)
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
326
  if (!strcmp (iface, SPI_DBUS_INTERFACE_REGISTRY))
    {
324
      result = DBUS_HANDLER_RESULT_HANDLED;
324
      if (!strcmp (member, "RegisterEvent"))
2
        reply = impl_RegisterEvent (message, registry);
322
      else if (!strcmp (member, "DeregisterEvent"))
        reply = impl_DeregisterEvent (message, registry);
322
      else if (!strcmp (member, "GetRegisteredEvents"))
161
        reply = impl_GetRegisteredEvents (message, registry);
      else
161
        result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    }
326
  if (!strcmp (iface, "org.freedesktop.DBus.Introspectable"))
    {
2
      result = DBUS_HANDLER_RESULT_HANDLED;
2
      if (!strcmp (member, "Introspect"))
2
        reply = impl_Introspect_registry (message, registry);
      else
        result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    }
326
  if (result == DBUS_HANDLER_RESULT_HANDLED)
    {
165
      if (!reply)
        {
          reply = dbus_message_new_method_return (message);
        }
165
      dbus_connection_send (bus, reply, NULL);
165
      dbus_message_unref (reply);
    }
#if 0
  else
    {
      g_print ("Registry | Unhandled message : %s|%s\n", iface, member);
    }
#endif
326
  return result;
}
/*---------------------------------------------------------------------------*/
static DBusObjectPathVTable root_vtable = {
  NULL,
  &handle_method_root,
  NULL, NULL, NULL, NULL
};
static DBusObjectPathVTable registry_vtable = {
  NULL,
  &handle_method_registry,
  NULL, NULL, NULL, NULL
};
static DBusObjectPathVTable cache_vtable = {
  NULL,
  &handle_method_cache,
  NULL, NULL, NULL, NULL
};
static gchar *app_sig_match_name_owner =
    "type='signal', interface='org.freedesktop.DBus', member='NameOwnerChanged'";
SpiRegistry *
28
spi_registry_new (DBusConnection *bus, SpiDEController *dec)
{
28
  SpiRegistry *registry = g_object_new (SPI_REGISTRY_TYPE, NULL);
  const char *bus_unique_name;
28
  bus_unique_name = dbus_bus_get_unique_name (bus);
28
  g_assert (bus_unique_name != NULL);
28
  registry->bus = bus;
28
  registry->dec = g_object_ref (dec);
28
  registry->bus_unique_name = g_strdup (bus_unique_name);
28
  dbus_bus_add_match (bus, app_sig_match_name_owner, NULL);
28
  dbus_connection_add_filter (bus, signal_filter, registry, NULL);
28
  dbus_connection_register_object_path (bus, SPI_DBUS_PATH_ROOT, &root_vtable, registry);
28
  dbus_connection_register_object_path (bus, SPI_DBUS_PATH_CACHE, &cache_vtable, registry);
28
  dbus_connection_register_object_path (bus, SPI_DBUS_PATH_REGISTRY, &registry_vtable, registry);
28
  emit_Available (bus);
28
  registry->events = NULL;
28
  return registry;
}
/*END------------------------------------------------------------------------*/