Merge "Support many at-spi clients" into tizen
[platform/upstream/at-spi2-core.git] / test / at_spi2_tool.c
index af7eb97..dfbc051 100644 (file)
@@ -4,6 +4,7 @@
 #include <string.h>
 #include <getopt.h>
 #include <stdbool.h>
+#include <gio/gio.h>
 
 #define ERROR_STATE -1
 #define SAFE_BUFFER_SIZE 2048
@@ -240,12 +241,13 @@ static char *_get_states(AtspiAccessible *node, int length_limit)
 {
        AtspiStateSet *node_state_set = atspi_accessible_get_state_set(node);
        GArray *states = atspi_state_set_get_states(node_state_set);
+       if (!states) return NULL;
        g_array_sort(states, _int_sort_function);
 
        AtspiStateType state_type;
        char *state_string = NULL;
 
-       for (int i = 0; states && (i < states->len); i++) {
+       for (int i = 0; i < states->len; i++) {
                state_type = g_array_index(states, AtspiStateType, i);
 
                char node_state_str[8];
@@ -287,17 +289,17 @@ static char *_get_attributes(AtspiAccessible *node, int length_limit)
        return result;
 }
 
-static AtspiAccessible *_get_object_in_relation(AtspiAccessible *source, AtspiRelationType search_type)
+static char *_get_object_in_relation(AtspiAccessible *source, AtspiRelationType search_type)
 {
        if (source == NULL)
-               return NULL;
+               return "";
 
        GArray *relations = atspi_accessible_get_relation_set(source, NULL);
 
        if (relations == NULL)
-               return NULL;
+               return "";
 
-       AtspiAccessible *ret;
+       AtspiAccessible *ret = NULL;
        for (int i = 0; i < relations->len; ++i) {
                AtspiRelation *relation = g_array_index(relations, AtspiRelation *, i);
                AtspiRelationType type = atspi_relation_get_relation_type(relation);
@@ -310,7 +312,7 @@ static AtspiAccessible *_get_object_in_relation(AtspiAccessible *source, AtspiRe
 
        g_array_free(relations, TRUE);
 
-       return ret;
+       return ret ? atspi_accessible_get_unique_id(ret, NULL) : g_strdup("");
 }
 
 static char *_get_info(AtspiAccessible *node, int length_limit)
@@ -320,14 +322,18 @@ static char *_get_info(AtspiAccessible *node, int length_limit)
 
        char *node_name = atspi_accessible_get_name(node, NULL);
        char *node_role_name = atspi_accessible_get_role_name(node, NULL);
+       char *unique_id = atspi_accessible_get_unique_id(node, NULL);
 
        char *attributes = _get_attributes(node, length_limit);
        Box_Size *box_size = _get_box_size(node);
        char *states = _get_states(node, length_limit);
 
+       char *flows_to = _get_object_in_relation(node, ATSPI_RELATION_FLOWS_TO);
+       char *flows_from = _get_object_in_relation(node, ATSPI_RELATION_FLOWS_FROM);
+
        char result[SAFE_BUFFER_SIZE];
-       int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%p],[%s],[%s],[%s,%s,%s,%s],[%s],[%s],[%p,%p]]",
-                                               node,
+       int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s],[%s,%s,%s,%s],[%s],[%s],[%s,%s]]",
+                                               unique_id,
                                                node_role_name,
                                                attributes,
                                                box_size->x,
@@ -336,14 +342,15 @@ static char *_get_info(AtspiAccessible *node, int length_limit)
                                                box_size->height,
                                                node_name,
                                                states,
-                                               _get_object_in_relation(node, ATSPI_RELATION_FLOWS_TO),
-                                               _get_object_in_relation(node, ATSPI_RELATION_FLOWS_FROM));
+                                               flows_to,
+                                               flows_from);
 
        if (ret >= SAFE_BUFFER_SIZE)
-               fprintf(stderr, "\n_get_info: generated string is too long. Buffer overflow\n");
+               fprintf(stderr, "\n%s, %s %d: generated string is too long. Buffer overflow\n", __FILE__, __FUNCTION__, __LINE__);
 
        free(node_name);
        free(node_role_name);
+       free(unique_id);
        free(attributes);
        if (box_size) {
                free(box_size->width);
@@ -351,6 +358,8 @@ static char *_get_info(AtspiAccessible *node, int length_limit)
                free(box_size);
        }
        free(states);
+       free(flows_to);
+       free(flows_from);
 
        return _strdup(result);
 }
@@ -369,7 +378,12 @@ static void _test_atspi_parent_child_relation(AtspiAccessible *obj, AtspiAccessi
                else
                        snprintf(parent_status, NUMBER_WIDTH, "%d", parent_index);
 
-               snprintf(output, CHECK_OUTPUT_WIDTH, "[FAIL<%d,%s><%p,%p>]", parent_candidate_index, parent_status, parent_candidate, parent);
+               char *parent_unique_id = atspi_accessible_get_unique_id(parent, NULL);
+               char *parent_candidate_unique_id = atspi_accessible_get_unique_id(parent_candidate, NULL);
+               snprintf(output, CHECK_OUTPUT_WIDTH, "[FAIL<%d,%s><%s,%s>]", parent_candidate_index, parent_status,
+                               parent_candidate_unique_id, parent_unique_id);
+               free(parent_unique_id);
+               free(parent_candidate_unique_id);
 
        } else {
                snprintf(output, CHECK_OUTPUT_WIDTH, "[OK]");
@@ -414,6 +428,8 @@ void _print_help()
        printf("-v, --version\t\tshow actual version of tool\n");
        printf("-g, --show-legend\tprint AT-SPI state legend\n");
        printf("-l, --list-apps\t\tlist all applications of desktop\n");
+       printf("-a, --at-spi-client <true|false>\tenable/disable org.a11y.Status.IsEnabled property\n");
+       printf("-s, --sleep <N>\tsleep N seconds\n");
        printf("-d, --tree-dump\t\tdump tree for selected application\n");
        printf("-c, --tree-check\tcheck tree for selected application\n");
        printf("-f, --first-match\tperform dump or check only for first matching application\n");
@@ -430,14 +446,23 @@ void _print_version()
        printf("AT-SPI2-CORE-UTIL v%s\n", VERSION);
 }
 
-static void _atspi_tree_traverse(AtspiAccessible *desktop, const char *app_name, bool dump, bool check, bool first_match, int length_limit)
+static void _atspi_tree_traverse(const char *app_name, bool dump, bool check, bool first_match, int length_limit)
 {
+
+       AtspiAccessible *desktop = atspi_get_desktop(0);
+       if (!desktop) {
+               fprintf(stderr, "atspi_get_desktop failed\n");
+               return;
+       }
+
        int count = atspi_accessible_get_child_count(desktop, NULL);
        bool app_name_matched = false;
        for (int i = 0; i < count; i++) {
                AtspiAccessible *child = atspi_accessible_get_child_at_index(desktop, i, NULL);
-               if (child == NULL)
-                       break;
+               if (child == NULL) {
+                       fprintf(stderr, "\n%s, %s %d: Null child occured. Results may be misleading.\n", __FILE__, __FUNCTION__, __LINE__);
+                       continue;
+               }
 
                char *name = atspi_accessible_get_name(child, NULL);
 
@@ -466,15 +491,59 @@ static void _atspi_tree_traverse(AtspiAccessible *desktop, const char *app_name,
 
        if (!app_name_matched && (dump || check))
                fprintf(stderr, "There is no application with name: %s. Try again.\n", app_name);
+
+       g_object_unref(desktop);
 }
 
-static void _run_command(int argc, char *argv[], AtspiAccessible *desktop)
+static void _at_spi_client_enable(gboolean enabled)
+{
+       static GDBusProxy *proxy = NULL; //we keep proxy (dbus connection) until program exits
+       GVariant *result;
+       GError *error = NULL;
+       GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_NONE;
+
+
+       if (!proxy) {
+               proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                       flags,
+                                       NULL, /* GDBusInterfaceInfo */
+                                       "org.a11y.Bus",
+                                       "/org/a11y/bus",
+                                       "org.freedesktop.DBus.Properties",
+                                       NULL, /* GCancellable */
+                                       &error);
+               if (error) {
+                       fprintf(stderr, "Failed to create proxy object for '/org/a11y/bus': %s\n", error->message);
+                       g_error_free(error);
+                       return;
+               }
+       }
+
+       result = g_dbus_proxy_call_sync(proxy,
+                                       "Set",
+                                       g_variant_new ("(ssv)",  "org.a11y.Status", "IsEnabled", g_variant_new_boolean(enabled)),
+                                       G_DBUS_CALL_FLAGS_NONE,
+                                       -1,
+                                       NULL,
+                                       &error);
+       if (result)
+               g_variant_unref(result);
+
+       if (error) {
+               fprintf(stderr, "Fail to call org.freedesktop.DBus.Properties.Set: %s\n", error->message);
+               g_error_free(error);
+       }
+}
+
+static void _run_command(int argc, char *argv[])
 {
        struct option long_options[] = {
                {"help", no_argument, 0, 'h'},
                {"version", no_argument, 0, 'v'},
                {"show-legend", no_argument, 0, 'g'},
                {"list-apps", no_argument, 0, 'l'},
+               {"at-spi-client", no_argument, 0, 'a'},
+               {"sleep", required_argument, 0, 's'},
                {"tree-dump", required_argument, 0, 'd'},
                {"tree-check", required_argument, 0, 'c'},
                {"first-match", no_argument, 0, 'f'},
@@ -486,9 +555,10 @@ static void _run_command(int argc, char *argv[], AtspiAccessible *desktop)
        int option_index = 0;
        bool traverse_flags[FLAG_NO] = {false};
        char *app_name = NULL;
+       gboolean enable_at_spi_client;
 
        while (TRUE) {
-               command = getopt_long(argc, argv, "hvgld:c:ft:i:", long_options, &option_index);
+               command = getopt_long(argc, argv, "hvgla:s:d:c:ft:i:", long_options, &option_index);
 
                if (command == ERROR_STATE)
                        break;
@@ -507,7 +577,19 @@ static void _run_command(int argc, char *argv[], AtspiAccessible *desktop)
                        break;
 
                case 'l':
-                       _atspi_tree_traverse(desktop, NULL, false, false, false, module_name_limit);
+                       _atspi_tree_traverse(NULL, false, false, false, module_name_limit);
+                       break;
+
+               case 'a':
+                       enable_at_spi_client = TRUE;
+                       if(optarg[0] == 'f' || optarg[0] == '0')
+                               enable_at_spi_client = FALSE;
+
+                       _at_spi_client_enable(enable_at_spi_client);
+                       break;
+
+               case 's':
+                       sleep(atoi(optarg));
                        break;
 
                case 'd':
@@ -542,7 +624,7 @@ static void _run_command(int argc, char *argv[], AtspiAccessible *desktop)
        }
 
        if (traverse_flags[DUMP] || traverse_flags[CHECK])
-               _atspi_tree_traverse(desktop, app_name, traverse_flags[DUMP], traverse_flags[CHECK], traverse_flags[FIRST_MATCH], module_name_limit);
+               _atspi_tree_traverse(app_name, traverse_flags[DUMP], traverse_flags[CHECK], traverse_flags[FIRST_MATCH], module_name_limit);
 }
 
 int main(int argc, char *argv[])
@@ -559,13 +641,7 @@ int main(int argc, char *argv[])
                return -1;
        }
 
-       AtspiAccessible *desktop = atspi_get_desktop(0);
-       if (!desktop) {
-               fprintf(stderr, "atspi_get_desktop failed\n");
-               return -1;
-       }
-
-       _run_command(argc, argv, desktop);
+       _run_command(argc, argv);
 
        return 0;
 }