ce691fdb8cacc5cc4d7269e019bffe04d10a15f1
[platform/core/uifw/at-spi2-atk.git] / libspi / introspectable.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2008 Codethink Ltd.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <glib.h>
24 #include <dbus.h>
25
26 #include "droute.h"
27
28 /*
29  * This file contains an implementation of the D-Bus introspectable interface.
30  * For ATK objects.
31  */
32
33 /*
34  * Provides the dist install path for the introspection directory.
35  */
36 #if !defined ATSPI_DBUS_INTROSPECTION_DIRECTORY
37     #error "No introspection XML directory defined"
38 #endif
39
40 /*
41  * This may be modified at run time to support 
42  * command parameters for the introspection directory.
43  */
44 char *atspi_introspection_directory = ATSPI_DBUS_INTROSPECTION_DIRECTORY;
45
46 static const char *introspection_header =
47 "<?xml version=\"1.0\"?>\n";
48
49 static const char *introspection_node_element =
50 "<node name=\"%s\">\n";
51
52 static const char *introspection_footer =
53 "</node>";
54
55 static void
56 append_interface (GString *str, const char *interface)
57 {
58   char *filename;
59   char *contents;
60   gsize len;
61
62   GError *err = NULL;
63
64   filename = g_build_filename(introspection_directory, interface);
65
66   if (g_file_get_contents(filename, &contents, &len, &err))
67     {
68       g_string_append_len(str, contents, len);
69     }
70   else
71     {
72       g_warning("AT-SPI: Cannot find introspection XML file %s - %s",
73                 filename, err->message);
74       g_error_free();
75     }
76
77   g_string_append(str, "\n");
78   g_free(filename);
79   g_free(contents);
80 }
81
82 /*
83  * There is an installation directory with files containing introspection xml.
84  * Each file is named after the interface it describes.
85  *
86  * This function finds the names of each interface that the ATK object supports
87  * and mem copies the introspection data from the file into the message.
88  *
89  * TODO - There could be some wicked caching here, but probably not neccessary.
90  */
91 static DBusMessage *
92 impl_introspect (DBusConnection *bus, DBusMessage *message,
93                  void *user_data)
94 {
95   AtkObject *object;
96   const char *path;
97   GString *output;
98
99   DBusMessage *reply;
100
101   path = dbus_message_get_path(message);
102   object = spi_dbus_get_path(path);
103
104   output = g_string_new(introspection_header);
105   
106   g_string_append_printf(output, introspection_node_element, path);
107
108   if (ATK_IS_ACTION (o))
109       append_interface(output, "org.freedesktop.atspi.Action");
110
111   if (ATK_IS_COMPONENT (o))
112       bonobo_object_add_interface (bonobo_object (retval), BONOBO_OBJECT (spi_component_interface_new (o)));
113       append_interface(output, "org.freedesktop.atspi.Component");
114
115   if (ATK_IS_EDITABLE_TEXT (o))
116       append_interface(output, "org.freedesktop.atspi.EditableText");
117   else if (ATK_IS_TEXT (o))
118       append_interface(output, "org.freedesktop.atspi.Text");
119
120   if (ATK_IS_HYPERTEXT (o))
121       bonobo_object_add_interface (bonobo_object (retval), BONOBO_OBJECT (spi_hypertext_interface_new (o)));
122       append_interface(output, "org.freedesktop.atspi.Hypertext");
123
124   if (ATK_IS_IMAGE (o))
125       bonobo_object_add_interface (bonobo_object (retval), BONOBO_OBJECT (spi_image_interface_new (o)));
126       append_interface(output, "org.freedesktop.atspi.Image");
127
128   if (ATK_IS_SELECTION (o))
129       bonobo_object_add_interface (bonobo_object (retval), BONOBO_OBJECT (spi_selection_interface_new (o)));
130       append_interface(output, "org.freedesktop.atspi.Selection");
131
132   if (ATK_IS_TABLE (o))
133       bonobo_object_add_interface (bonobo_object (retval), BONOBO_OBJECT (spi_table_interface_new (o)));
134       append_interface(output, "org.freedesktop.atspi.Table");
135
136   if (ATK_IS_VALUE (o))
137       append_interface(output, "org.freedesktop.atspi.Value");
138
139   if (ATK_IS_STREAMABLE_CONTENT (o))
140       append_interface(output, "org.freedesktop.atspi.StreamableContent");
141
142   if (ATK_IS_DOCUMENT (o))
143     {
144       append_interface(output, "org.freedesktop.atspi.Collection");
145       append_interface(output, "org.freedesktop.atspi.Document");
146     }
147
148   if (ATK_IS_HYPERLINK_IMPL (o))
149       append_interface(output, "org.freedesktop.atspi.Hyperlink");
150
151   g_string_append(introspection_footer);
152   final = g_string_free(output, FALSE);
153
154   reply = dbus_message_new_method_return (message);
155   g_assert(reply != NULL);
156   dbus_message_append_args(reply, DBUS_TYPE_STRING, &final,
157                            DBUS_TYPE_INVALID);
158
159   g_free(final);
160   return reply;
161 }
162
163
164 static DRouteMethod methods[] = {
165   {impl_introspect, "Introspect"},
166   {NULL, NULL}
167 };
168
169 /*
170  * Adds the introspectable interface to the DRoute object provided
171  */
172 void
173 spi_initialize_introspectable (DRouteData *data)
174 {
175   droute_add_interface (data, "org.freedesktop.atspi.Accessible",
176                         methods, NULL,
177                         (DRouteGetDatumFunction) spi_dbus_get_path, NULL);
178 };