Don't warn if an app returns NULL when referencing a child
[platform/core/uifw/at-spi2-atk.git] / atk-adaptor / adaptors / cache-adaptor.c
index 15595a5..cad7396 100644 (file)
 #include <atk/atk.h>
 #include <droute/droute.h>
 
-#include "common/spi-dbus.h"
+#include "spi-dbus.h"
+#include "accessible-stateset.h"
 #include "accessible-cache.h"
 #include "bridge.h"
 #include "object.h"
+#include "introspection.h"
 
 /* TODO - This should possibly be a common define */
-#define SPI_OBJECT_PREFIX "/org/at_spi"
+#define SPI_OBJECT_PREFIX "/org/a11y/atspi"
 #define SPI_CACHE_OBJECT_SUFFIX "/cache"
 #define SPI_CACHE_OBJECT_PATH SPI_OBJECT_PREFIX SPI_CACHE_OBJECT_SUFFIX
 
@@ -44,7 +46,7 @@
                                        ")"
                                           
 #define SPI_CACHE_ITEM_SIGNATURE "(" \
-                                   DBUS_TYPE_OBJECT_PATH_AS_STRING \
+                                   SPI_OBJECT_REFERENCE_SIGNATURE \
                                    SPI_OBJECT_REFERENCE_SIGNATURE \
                                    SPI_OBJECT_REFERENCE_SIGNATURE \
                                    DBUS_TYPE_ARRAY_AS_STRING \
@@ -98,7 +100,6 @@ append_cache_item (AtkObject * obj, gpointer data)
     parent = atk_object_get_parent (obj);
     if (parent == NULL)
       {
-#ifdef SPI_ATK_PLUG_SOCKET
         /* TODO, move in to a 'Plug' wrapper. */
         if (ATK_IS_PLUG (obj))
           {
@@ -109,22 +110,27 @@ append_cache_item (AtkObject * obj, gpointer data)
             if (id)
               {
                 bus_parent = g_strdup (id);
-              if (bus_parent && (path_parent = g_utf8_strchr (bus_parent + 1, -1, ':')))
-                {
-                  DBusMessageIter iter_parent;
-                  *(path_parent++) = '\0';
-                  dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_STRUCT, NULL,
-                                                    &iter_parent);
-                  dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_STRING, &bus_parent);
-                  dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_OBJECT_PATH, &path_parent);
-                  dbus_message_iter_close_container (&iter_struct, &iter_parent);
-                }
+                if (bus_parent && (path_parent = g_utf8_strchr (bus_parent + 1, -1, ':')))
+                  {
+                    DBusMessageIter iter_parent;
+                    *(path_parent++) = '\0';
+                    dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_STRUCT, NULL,
+                                                      &iter_parent);
+                    dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_STRING, &bus_parent);
+                    dbus_message_iter_append_basic (&iter_parent, DBUS_TYPE_OBJECT_PATH, &path_parent);
+                    dbus_message_iter_close_container (&iter_struct, &iter_parent);
+                  }
+                else
+                  {
+                    spi_object_append_null_reference (&iter_struct);
+                  }
+              }
+            else
+              {
+                spi_object_append_null_reference (&iter_struct);
               }
           }
-        else if (role != Accessibility_ROLE_APPLICATION)
-#else
-        if (role != Accessibility_ROLE_APPLICATION)
-#endif
+        else if (role != ATSPI_ROLE_APPLICATION)
           spi_object_append_null_reference (&iter_struct);
         else
           spi_object_append_desktop_reference (&iter_struct);
@@ -137,7 +143,8 @@ append_cache_item (AtkObject * obj, gpointer data)
     /* Marshall children */
     dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "(so)",
                                       &iter_sub_array);
-    if (!atk_state_set_contains_state (set, ATK_STATE_MANAGES_DESCENDANTS))
+    if (!atk_state_set_contains_state (set, ATK_STATE_MANAGES_DESCENDANTS) &&
+        !atk_state_set_contains_state (set, ATK_STATE_DEFUNCT))
       {
         gint childcount, i;
 
@@ -145,14 +152,15 @@ append_cache_item (AtkObject * obj, gpointer data)
         for (i = 0; i < childcount; i++)
           {
             AtkObject *child;
-            gchar *child_path;
 
             child = atk_object_ref_accessible_child (obj, i);
-            spi_object_append_reference (&iter_sub_array, child);
-            g_object_unref (G_OBJECT (child));
+            if (child)
+              {
+                spi_object_append_reference (&iter_sub_array, child);
+                g_object_unref (G_OBJECT (child));
+              }
           }
       }
-#ifdef SPI_ATK_PLUG_SOCKET
     if (ATK_IS_SOCKET (obj) && atk_socket_is_occupied (ATK_SOCKET (obj)))
       {
         AtkSocket *socket = ATK_SOCKET (obj);
@@ -171,7 +179,6 @@ append_cache_item (AtkObject * obj, gpointer data)
           }
         g_free (child_name);
       }
-#endif
 
     dbus_message_iter_close_container (&iter_struct, &iter_sub_array);
 
@@ -213,13 +220,26 @@ append_cache_item (AtkObject * obj, gpointer data)
 
 /*---------------------------------------------------------------------------*/
 
+static void
+ref_accessible_hf (gpointer key, gpointer obj_data, gpointer data)
+{
+  g_object_ref (key);
+}
+
 /* For use as a GHFunc */
 static void
 append_accessible_hf (gpointer key, gpointer obj_data, gpointer data)
 {
   /* Make sure it isn't a hyperlink */
-  if (ATK_IS_OBJECT (obj_data))
-    append_cache_item (ATK_OBJECT (obj_data), data);
+  if (ATK_IS_OBJECT (key))
+    append_cache_item (ATK_OBJECT (key), data);
+}
+
+static void
+add_to_list_hf (gpointer key, gpointer obj_data, gpointer data)
+{
+  GSList **listptr = data;
+  *listptr = g_slist_prepend (*listptr, key);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -230,11 +250,10 @@ emit_cache_remove (SpiCache *cache, GObject * obj)
   DBusMessage *message;
 
   if ((message = dbus_message_new_signal (SPI_CACHE_OBJECT_PATH,
-                                          SPI_DBUS_INTERFACE_CACHE,
+                                          ATSPI_DBUS_INTERFACE_CACHE,
                                           "RemoveAccessible")))
     {
       DBusMessageIter iter;
-      gchar *path;
 
       dbus_message_iter_init_append (message, &iter);
 
@@ -253,13 +272,15 @@ emit_cache_add (SpiCache *cache, GObject * obj)
   DBusMessage *message;
 
   if ((message = dbus_message_new_signal (SPI_CACHE_OBJECT_PATH,
-                                          SPI_DBUS_INTERFACE_CACHE,
+                                          ATSPI_DBUS_INTERFACE_CACHE,
                                           "AddAccessible")))
     {
       DBusMessageIter iter;
 
       dbus_message_iter_init_append (message, &iter);
+      g_object_ref (accessible);
       append_cache_item (accessible, &iter);
+      g_object_unref (accessible);
 
       dbus_connection_send (spi_global_app_data->bus, message, NULL);
 
@@ -273,8 +294,7 @@ emit_cache_add (SpiCache *cache, GObject * obj)
 static DBusMessage *
 impl_GetRoot (DBusConnection * bus, DBusMessage * message, void *user_data)
 {
-  return spi_object_return_reference (message,
-                                      g_object_ref (G_OBJECT (spi_global_app_data->root)));
+  return spi_object_return_reference (message, spi_global_app_data->root);
 }
 
 /*---------------------------------------------------------------------------*/
@@ -284,13 +304,20 @@ impl_GetItems (DBusConnection * bus, DBusMessage * message, void *user_data)
 {
   DBusMessage *reply;
   DBusMessageIter iter, iter_array;
+  GSList *pending_unrefs = NULL;
+
+  if (bus == spi_global_app_data->bus)
+    spi_atk_add_client (dbus_message_get_sender (message));
 
   reply = dbus_message_new_method_return (message);
 
   dbus_message_iter_init_append (reply, &iter);
   dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
                                     SPI_CACHE_ITEM_SIGNATURE, &iter_array);
+  spi_cache_foreach (spi_global_cache, ref_accessible_hf, NULL);
   spi_cache_foreach (spi_global_cache, append_accessible_hf, &iter_array);
+  spi_cache_foreach (spi_global_cache, add_to_list_hf, &pending_unrefs);
+  g_slist_free_full (pending_unrefs, g_object_unref);
   dbus_message_iter_close_container (&iter, &iter_array);
   return reply;
 }
@@ -306,17 +333,13 @@ static DRouteMethod methods[] = {
 void
 spi_initialize_cache (DRoutePath * path)
 {
-  droute_path_add_interface (path, SPI_DBUS_INTERFACE_CACHE, methods, NULL);
+  droute_path_add_interface (path, ATSPI_DBUS_INTERFACE_CACHE, spi_org_a11y_atspi_Cache, methods, NULL);
 
-  g_signal_connect (spi_global_cache,
-                    "object-added",
-                    (GCallback) emit_cache_add,
-                    NULL);
+  g_signal_connect (spi_global_cache, "object-added",
+                    (GCallback) emit_cache_add, NULL);
 
-  g_signal_connect (spi_global_cache,
-                    "object-removed",
-                    (GCallback) emit_cache_remove,
-                    NULL);
+  g_signal_connect (spi_global_cache, "object-removed",
+                    (GCallback) emit_cache_remove, NULL);
 };
 
 /*END------------------------------------------------------------------------*/