socket-adaptor: fix memory leak
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / adaptors / socket-adaptor.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2008 Novell, Inc.
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 Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 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  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 #include <atk/atk.h>
26 #include <droute/droute.h>
27
28 #include "spi-dbus.h"
29 #include "accessible-stateset.h"
30 #include "object.h"
31 #include "introspection.h"
32 #include "bridge.h"
33
34 static DBusMessage *
35 new_socket_call_message (AtkComponent *component, const char *member)
36 {
37   char *id = g_object_get_data (G_OBJECT (component), "dbus-plug-parent");
38   char *bus_parent;
39   char *path_parent;
40
41   if (!id)
42     {
43       g_warning ("new_socket_call_message: no id");
44       return NULL;
45     }
46   bus_parent = g_strdup (id);
47   if (bus_parent && (path_parent = g_utf8_strchr (bus_parent + 1, -1, ':')))
48     {
49       DBusMessage *message;
50       *(path_parent++) = '\0';
51       message = dbus_message_new_method_call (bus_parent, path_parent,
52                                               ATSPI_DBUS_INTERFACE_COMPONENT,
53                                               member);
54       g_free (bus_parent);
55       return message;
56     }
57   return NULL;
58 }
59
60 static void
61 atspi_plug_component_get_extents (AtkComponent *component, gint *x, gint *y,
62                                   gint *width, gint *height,
63                                   AtkCoordType coord_type)
64 {
65   DBusMessage *message = new_socket_call_message (component, "GetExtents");
66   DBusMessage *reply;
67   dbus_uint32_t coord_type_dbus = coord_type;
68   DBusError error;
69   const char *signature;
70   DBusMessageIter iter, iter_struct;
71   dbus_int32_t tmp;
72
73   dbus_error_init (&error);
74   dbus_message_append_args (message, DBUS_TYPE_UINT32, &coord_type_dbus, DBUS_TYPE_INVALID);
75   reply = dbus_connection_send_with_reply_and_block (spi_global_app_data->bus,
76                                                      message, -1, &error);
77   dbus_message_unref (message);
78   if (!reply)
79     return;
80   signature = dbus_message_get_signature (reply);
81   if (g_strcmp0 (signature, "(iiii)") != 0)
82   {
83     g_warning ("Got unexpected signature %s from GetExtents\n", signature);
84     dbus_message_unref (reply);
85     return;
86   }
87   dbus_message_iter_init (reply, &iter);
88   dbus_message_iter_recurse (&iter, &iter_struct);
89   dbus_message_iter_get_basic (&iter_struct, &tmp);
90   *x = tmp;
91   dbus_message_iter_next (&iter_struct);
92   dbus_message_iter_get_basic (&iter_struct, &tmp);
93   *y = tmp;
94   dbus_message_iter_next (&iter_struct);
95   dbus_message_iter_get_basic (&iter_struct, &tmp);
96   *width = tmp;
97   dbus_message_iter_next (&iter_struct);
98   dbus_message_iter_get_basic (&iter_struct, &tmp);
99   *height = tmp;
100   dbus_message_unref (reply);
101 }
102
103 static void
104 atspi_plug_component_get_position (AtkComponent *component, gint *x, gint *y,
105                                   AtkCoordType coord_type)
106 {
107   DBusMessage *message = new_socket_call_message (component, "GetPosition");
108   DBusMessage *reply;
109   dbus_uint32_t coord_type_dbus = coord_type;
110   DBusError error;
111   dbus_int32_t x_dbus, y_dbus;
112
113   dbus_error_init (&error);
114   dbus_message_append_args (message, DBUS_TYPE_UINT32, &coord_type_dbus, DBUS_TYPE_INVALID);
115   reply = dbus_connection_send_with_reply_and_block (spi_global_app_data->bus,
116                                                      message, -1, &error);
117   dbus_message_unref (message);
118   if (!reply)
119     return;
120   if (!dbus_message_get_args (reply, &error, DBUS_TYPE_INT32, &x_dbus,
121                               DBUS_TYPE_INT32, &y_dbus, DBUS_TYPE_INVALID))
122     {
123       g_warning ("GetPosition failed: %s", error.message);
124       dbus_error_free (&error);
125     }
126   else
127     {
128       *x = x_dbus;
129       *y = y_dbus;
130     }
131   dbus_message_unref (reply);
132 }
133
134 static void
135 atspi_plug_component_get_size (AtkComponent *component,
136                                gint *width, gint *height)
137 {
138   DBusMessage *message = new_socket_call_message (component, "GetSize");
139   DBusMessage *reply;
140   DBusError error;
141   dbus_uint32_t width_dbus, height_dbus;
142
143   dbus_error_init (&error);
144   reply = dbus_connection_send_with_reply_and_block (spi_global_app_data->bus,
145                                                      message, -1, &error);
146   dbus_message_unref (message);
147   if (!reply)
148     return;
149   if (!dbus_message_get_args (reply, &error, DBUS_TYPE_INT32, &width_dbus,
150                               DBUS_TYPE_INT32, &height_dbus, DBUS_TYPE_INVALID))
151     {
152       g_warning ("GetSize failed: %s", error.message);
153       dbus_error_free (&error);
154     }
155   else
156     {
157       *width = width_dbus;
158       *height = height_dbus;
159     }
160   dbus_message_unref (reply);
161 }
162
163 static DBusMessage *
164 impl_Embedded (DBusConnection *bus,
165                     DBusMessage *message,
166                     void *user_data)
167 {
168   AtkObject *object = (AtkObject *) user_data;
169   char *path;
170   gchar *id;
171
172   if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID))
173     {
174       return droute_invalid_arguments_error (message);
175     }
176   id = g_strconcat (dbus_message_get_sender (message), ":", path, NULL);
177   g_object_set_data_full (G_OBJECT (object), "dbus-plug-parent", id, (GDestroyNotify)g_free);
178
179   if (ATK_IS_COMPONENT (object))
180     {
181       AtkComponent *component = ATK_COMPONENT (object);
182       AtkComponentIface *iface = ATK_COMPONENT_GET_IFACE (component);
183       iface->get_extents = atspi_plug_component_get_extents;
184       iface->get_size = atspi_plug_component_get_size;
185       iface->get_position = atspi_plug_component_get_position;
186     }
187
188   /* Retrieve some info about the children, if they exist, when
189      embedding the plug to ensure the a11y subtree is generated.
190      https://bugzilla.gnome.org/show_bug.cgi?id=663876 */
191   atk_object_get_n_accessible_children (object);
192
193   return dbus_message_new_method_return (message);
194 }
195
196 static DRouteMethod methods[] = {
197   {impl_Embedded, "Embedded"},
198   {NULL, NULL}
199 };
200
201 void
202 spi_initialize_socket (DRoutePath * path)
203 {
204   droute_path_add_interface (path,
205                              ATSPI_DBUS_INTERFACE_SOCKET,
206                              NULL, /* spi_org_a11y_atspi_Socket,         */
207                              methods, NULL);
208 };