From 65a8179bd64640d3c76767121dbf45ce9b8422ae Mon Sep 17 00:00:00 2001 From: "shashank.p" Date: Wed, 18 May 2016 14:58:19 +0530 Subject: [PATCH 01/16] Kill Screen-reader via SIGTERM only if aul_terminate_pid fails(returns a negative value) Change-Id: I8e863f3cc0acc11306eeb6a7e2fce50c9e75b65a Signed-off-by: shashank.p --- bus/at-spi-bus-launcher.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bus/at-spi-bus-launcher.c b/bus/at-spi-bus-launcher.c index 73c8a73..3f6c917 100644 --- a/bus/at-spi-bus-launcher.c +++ b/bus/at-spi-bus-launcher.c @@ -663,6 +663,7 @@ _terminate_screen_reader(A11yBusLauncher *bl) { LOGD("Terminating screen reader"); int ret; + int ret_aul; if (bl->pid <= 0) return FALSE; @@ -677,11 +678,15 @@ _terminate_screen_reader(A11yBusLauncher *bl) } LOGD("terminate process with pid %d", bl->pid); - if (!aul_terminate_pid(bl->pid)) + ret_aul = aul_terminate_pid(bl->pid); + if (ret_aul >= 0) { + LOGD("Terminating with aul_terminate_pid: return is %d", ret_aul); bl->pid = 0; return TRUE; } + else + LOGD("aul_terminate_pid failed: return is %d", ret_aul); LOGD("Unable to terminate process using aul api. Sending SIGTERM signal"); ret = kill(bl->pid, SIGTERM); -- 2.7.4 From 632107d94461024f2cdcb6bbe530cc14e96f3fe0 Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Wed, 3 Jun 2015 20:30:57 +0900 Subject: [PATCH 02/16] Apply address space layout randomization (ASLR) Conflicts: bus/Makefile.am Change-Id: Ifbe933b90f357c0a179175333d57edc88b6c2316 --- bus/Makefile.am | 3 ++- registryd/Makefile.am | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/bus/Makefile.am b/bus/Makefile.am index 574e0ad..8e0eec6 100644 --- a/bus/Makefile.am +++ b/bus/Makefile.am @@ -7,8 +7,9 @@ libexec_PROGRAMS = at-spi-bus-launcher at_spi_bus_launcher_SOURCES = at-spi-bus-launcher.c at_spi_bus_launcher_CPPFLAGS = -DSYSCONFDIR=\"$(sysconfdir)\" \ -DDBUS_DAEMON=\"$(DBUS_DAEMON)\" -at_spi_bus_launcher_CFLAGS = $(GIO_CFLAGS) $(APPSVC_CFLAGS) $(VCONF_CFLAGS) $(AUL_CFLAGS) +at_spi_bus_launcher_CFLAGS = $(GIO_CFLAGS) $(APPSVC_CFLAGS) $(VCONF_CFLAGS) $(AUL_CFLAGS) -fPIE at_spi_bus_launcher_LDADD = $(GIO_LIBS) $(X_LIBS) $(APPSVC_LIBS) $(VCONF_LIBS) $(AUL_LIBS) +at_spi_bus_launcher_LDFLAGS = -pie default_sessiondir = $(sysconfdir)/xdg/autostart default_session_DATA = at-spi-dbus-bus.desktop diff --git a/registryd/Makefile.am b/registryd/Makefile.am index c9c9d39..1e2e953 100644 --- a/registryd/Makefile.am +++ b/registryd/Makefile.am @@ -1,6 +1,8 @@ libexec_PROGRAMS = at-spi2-registryd +at_spi2_registryd_LDFLAGS = -pie at_spi2_registryd_CFLAGS = \ + -fPIE \ $(GLIB_CFLAGS) \ $(GIO_CFLAGS) \ $(DBUS_CFLAGS) \ -- 2.7.4 From aa29c756e51d95c2d1611035690cb0c764193c73 Mon Sep 17 00:00:00 2001 From: Lukasz Wlazly Date: Mon, 19 Sep 2016 16:01:38 +0200 Subject: [PATCH 03/16] Tool for checking AT-SPI tree integrity v0.5 Tool is placed in /bin/ To check AT-SPI tree user "owner" must be set: su - owner Change-Id: I5da4bcaba19547695ae46242f5bbf2dbce7c411c --- packaging/at-spi2-core.spec | 3 + test/Makefile.am | 12 +- test/at_spi2_tool.c | 373 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 383 insertions(+), 5 deletions(-) create mode 100644 test/at_spi2_tool.c diff --git a/packaging/at-spi2-core.spec b/packaging/at-spi2-core.spec index ad24f8d..472f089 100644 --- a/packaging/at-spi2-core.spec +++ b/packaging/at-spi2-core.spec @@ -82,6 +82,7 @@ cp %{SOURCE1001} . %install rm -rf %{buildroot} find %{buildroot} -name '*.la' -or -name '*.a' | xargs rm -f + %make_install %find_lang %{name} @@ -97,6 +98,8 @@ rm -fr %{buildroot} %files -f %{name}.lang %manifest %{name}.manifest %defattr(-,root,root) +%{_bindir}/at_spi2_tool + %doc AUTHORS README %license COPYING %{_libexecdir}/at-spi2/at-spi-bus-launcher diff --git a/test/Makefile.am b/test/Makefile.am index 7af2ee0..f233c36 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,8 +1,10 @@ LDADD = $(top_builddir)/atspi/libatspi.la -noinst_PROGRAMS = memory -memory_SOURCES = memory.c -memory_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_builddir)/atspi -memory_CFLAGS = $(GLIB_CFLAGS) $(GOBJ_LIBS) $(DBUS_CFLAGS) -memory_LDFLAGS = +bin_PROGRAMS = at_spi2_tool +at_spi2_tool_SOURCES = at_spi2_tool.c +at_spi2_tool_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_builddir)/atspi +at_spi2_tool_CFLAGS = $(GLIB_CFLAGS) --std=c99 $(GOBJ_LIBS) $(DBUS_CFLAGS) +at_spi2_tool_LDFLAGS = + + -include $(top_srcdir)/git.mk diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c new file mode 100644 index 0000000..f67700d --- /dev/null +++ b/test/at_spi2_tool.c @@ -0,0 +1,373 @@ +#include "atspi/atspi.h" +#include +#include +#include +#include +#include + +#define ERROR_STATE -1 +#define SAFE_BUFFER_SIZE 255 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define COLUMN_NO 3 + +static unsigned indent_width = 2; + +static const char* atspi_state_names[] = { + [ATSPI_STATE_INVALID] = "INVALID", + [ATSPI_STATE_ACTIVE] = "ACTIVE", + [ATSPI_STATE_ARMED] = "ARMED", + [ATSPI_STATE_BUSY] = "BUSY", + [ATSPI_STATE_CHECKED] = "CHECKED", + [ATSPI_STATE_COLLAPSED] = "COLLAPSED", + [ATSPI_STATE_DEFUNCT] = "DEFUNCT", + [ATSPI_STATE_EDITABLE] = "EDITABLE", + [ATSPI_STATE_ENABLED] = "ENABLED", + [ATSPI_STATE_EXPANDABLE] = "EXPANDABLE", + [ATSPI_STATE_EXPANDED] = "EXPANDED", + [ATSPI_STATE_FOCUSABLE] = "FOCUSABLE", + [ATSPI_STATE_FOCUSED] = "FOCUSED", + [ATSPI_STATE_HAS_TOOLTIP] = "HAS_TOOLTIP", + [ATSPI_STATE_HORIZONTAL] = "HORIZONTAL", + [ATSPI_STATE_ICONIFIED] = "ICONIFIED", + [ATSPI_STATE_MULTI_LINE] = "MULTI_LINE", + [ATSPI_STATE_MULTISELECTABLE] = "MULTISELECTABLE", + [ATSPI_STATE_OPAQUE] = "OPAQUE", + [ATSPI_STATE_PRESSED] = "PRESSED", + [ATSPI_STATE_RESIZABLE] = "RESIZABLE", + [ATSPI_STATE_SELECTABLE] = "SELECTABLE", + [ATSPI_STATE_SELECTED] = "SELECTED", + [ATSPI_STATE_SENSITIVE] = "SENSITIVE", + [ATSPI_STATE_SHOWING] = "SHOWING", + [ATSPI_STATE_SINGLE_LINE] = "SINGLE_LINE", + [ATSPI_STATE_STALE] = "STALE", + [ATSPI_STATE_TRANSIENT] = "TRANSIENT", + [ATSPI_STATE_VERTICAL] = "VERTICAL", + [ATSPI_STATE_VISIBLE] = "VISIBLE", + [ATSPI_STATE_MANAGES_DESCENDANTS] = "MANAGES_DESCENDANTS", + [ATSPI_STATE_INDETERMINATE] = "INDETERMINATE", + [ATSPI_STATE_REQUIRED] = "REQUIRED", + [ATSPI_STATE_TRUNCATED] = "TRUNCATED", + [ATSPI_STATE_ANIMATED] = "ANIMATED", + [ATSPI_STATE_INVALID_ENTRY] = "INVALID_ENTRY", + [ATSPI_STATE_SUPPORTS_AUTOCOMPLETION] = "SUPPORTS_AUTOCOMPLETION", + [ATSPI_STATE_SELECTABLE_TEXT] = "SELECTABLE_TEXT", + [ATSPI_STATE_IS_DEFAULT] = "IS_DEFAULT", + [ATSPI_STATE_VISITED] = "VISITED", + [ATSPI_STATE_CHECKABLE] = "CHECKABLE", + [ATSPI_STATE_MODAL] = "MODAL", + [ATSPI_STATE_HIGHLIGHTED] = "HIGHLIGHTED", + [ATSPI_STATE_HIGHLIGHTABLE] = "HIGHLIGHTABLE", + [ATSPI_STATE_HAS_POPUP] = "HAS_POPUP", + [ATSPI_STATE_READ_ONLY] = "READ_ONLY", + [ATSPI_STATE_LAST_DEFINED] = "LAST_DEFINED" +}; + +typedef struct _StringAccumulator { + char *string; + int length; +} StringAccumulator; + +char *strdup(const char *c) { + char *result = (char *)calloc(1, strlen(c) + 1); + return result ? strcpy(result, c) : result; +} + +static char *multiply_string(char c, unsigned number) { + char *result = (char *)calloc(1, number + 1); + + if (result == NULL) + return result; + + memset(result, c, number); + + return result; +} + +static void _print_atspi_states_legend() { + int array_len = ARRAY_SIZE(atspi_state_names); + int line_count = (array_len + COLUMN_NO - 1)/COLUMN_NO; + for (int line_idx = 0; line_idx < line_count; line_idx++) { + if ((line_idx < line_count - 1) || (array_len % 3 == 0)) { + printf("[%d]\t%-24s[%d]\t%-24s[%d]\t%s\n", line_idx * 3, atspi_state_names[line_idx * 3], (line_idx * 3) + 1, atspi_state_names[(line_idx * 3) + 1], (line_idx * 3) + 2, atspi_state_names[(line_idx * 3) + 2]); + } else if (array_len % 3 == 2) { + printf("[%d]\t%-24s[%d]\t%s\n", line_idx * 3, atspi_state_names[line_idx * 3], (line_idx * 3) + 1, atspi_state_names[(line_idx * 3) + 1]); + } else { + printf("[%d]\t%s\n", line_idx * 3, atspi_state_names[line_idx * 3]); + } + } +} + +static void set_indent(int indent_size) +{ + if (indent_size < 0) { + fprintf(stderr, "WARNING: Invalid indent size. Default value retained.\n"); + return; + } + + indent_width = indent_size; +} + +static int _int_sort_function(gconstpointer a, gconstpointer b) +{ + int int_a = GPOINTER_TO_INT (a); + int int_b = GPOINTER_TO_INT (b); + + return int_a - int_b; +} + +static int _accumulate_string(const char *string, StringAccumulator *accumulator) { + if (!accumulator) + return FALSE; + + if (string) { + int length = accumulator->length + strlen(string); + char *rebuffer = realloc(accumulator->string, length + 1); + if (rebuffer) { + strcpy(rebuffer + accumulator->length, string); + accumulator->string = rebuffer; + accumulator->length = length; + } else { + return FALSE; + } + } + return TRUE; +} + +static char *get_info(AtspiAccessible *node) { + if (!node) + return NULL; + + int node_width = -1; + int node_height = -1; + char *node_name = atspi_accessible_get_name(node, NULL); + char *node_role_name = atspi_accessible_get_role_name(node, NULL); + AtspiComponent *component = atspi_accessible_get_component_iface(node); + + AtspiRect *extent = NULL; + if (component != NULL){ + extent = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); + + if (extent != NULL) { + node_width = extent->width; + node_height = extent->height; + } + } + + AtspiStateSet *node_state_set = atspi_accessible_get_state_set(node); + GArray *states = atspi_state_set_get_states(node_state_set); + g_array_sort(states, _int_sort_function); + + AtspiStateType state; + StringAccumulator state_accumulator = {}; + for (int i = 0; states && (i < states->len); i++) { + state = g_array_index(states, AtspiStateType, i); + char node_state_str[8]; + sprintf(node_state_str, "[%d]", state); + _accumulate_string(node_state_str, &state_accumulator); + } + g_array_free(states, 0); + + StringAccumulator attribute_accumulator = {}; + GHashTable *attributes = NULL; + attributes = atspi_accessible_get_attributes(node, NULL); + if (attributes) { + GHashTableIter attributes_iter; + gpointer attr_key, attr_value; + g_hash_table_iter_init (&attributes_iter, attributes); + while (g_hash_table_iter_next (&attributes_iter, &attr_key, &attr_value)) { + _accumulate_string("[", &attribute_accumulator); + _accumulate_string((char*)attr_key, &attribute_accumulator); + _accumulate_string("=", &attribute_accumulator); + _accumulate_string((char*)attr_value, &attribute_accumulator); + _accumulate_string("]", &attribute_accumulator); + } + g_hash_table_unref(attributes); + } + + char result[SAFE_BUFFER_SIZE + 1]; + snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%d,%d],[%s],[%s]]\n", node_role_name, attribute_accumulator.string, node_width, node_height, node_name, state_accumulator.string); + + free(node_name); + free(node_role_name); + + if (state_accumulator.string) + g_free(state_accumulator.string); + + if (attribute_accumulator.string) + g_free(attribute_accumulator.string); + + if (component) + g_object_unref(component); + + if (extent) + g_free(extent); + + if (node_state_set) + g_object_unref(node_state_set); + + return strdup(result); +} + +static void test_atspi_parent_child_relation(AtspiAccessible *obj, AtspiAccessible *parent_candidate, int parent_candidate_index) +{ + int parent_index = atspi_accessible_get_index_in_parent(obj, NULL); + AtspiAccessible *parent = atspi_accessible_get_parent(obj, NULL); + if (parent_index != parent_candidate_index || parent_candidate != parent) { + printf("[FAIL<%d,", parent_candidate_index); + + if (parent == NULL) + printf("_"); + else + printf("%d", parent_index); + + printf(">]\t"); + + } else { + printf("[OK]\t"); + } +} + +static int expand_r(int indent_number, AtspiAccessible *object, bool check_integrity) +{ + char *indent = multiply_string(' ', indent_number*indent_width); + if (indent != NULL) { + printf("%s", indent); + free(indent); + } + + char *node_info = get_info(object); + if (node_info != NULL) { + printf("%s", node_info); + free(node_info); + } + + int count = atspi_accessible_get_child_count(object, NULL); + for (int i = 0; i < count; i++) { + AtspiAccessible *child = atspi_accessible_get_child_at_index(object, i, NULL); + if (child) { + if (check_integrity) + test_atspi_parent_child_relation(child, object, i); + + expand_r(indent_number + 1, child, check_integrity); + } + } + return 0; +} + +void print_help() +{ + printf("AT-SPI2-CORE-UTIL\n\n"); + printf("USAGE: at_spi2_tool [OPTION] [PARAMETER] ...\n\n"); + printf("OPTION LIST:\n"); + printf("-h, --help\t\tshow this message\n"); + printf("-g, --show-legend\tprint AT-SPI state legend\n"); + printf("-l, --list-apps\t\tlist all applications of desktop\n"); + printf("-d, --tree-dump\t\tdump tree for selected application\n"); + printf("-c, --tree-check\tcheck tree for selected application\n"); + printf("-i, --indent\t\tset indentation size\n"); + printf("\nEXAMPLE:\n"); + printf("\tat_spi2_tool -i3 -d quickpanel\n"); + printf("\t show AT-SPI tree for node \"quickpanel\" using three-space indentation\n"); + printf("\tat_spi2_tool -i1 -c starter\n"); + printf("\t show AT-SPI tree with integrity test for node \"starter\" using one-space indentation\n"); +} + +static void atspi_tree_traverse(AtspiAccessible *desktop, const char *app_name, bool dump, bool check) +{ + int count = atspi_accessible_get_child_count(desktop, NULL); + for (int i = 0; i < count; i++) { + AtspiAccessible *child = atspi_accessible_get_child_at_index(desktop, i, NULL); + if (child) { + char *name = atspi_accessible_get_name(child, NULL); + + if (!dump && !check) + printf("%s\n", name); + + if (dump && name && !strcmp(name, app_name)) { + expand_r(0, child, false); + break; + } + + if (check && name && !strcmp(name, app_name)) { + test_atspi_parent_child_relation(child, desktop, i); + expand_r(0, child, true); + break; + } + } + } +} + +static void run_command(int argc, char *argv[], AtspiAccessible *desktop) +{ + struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {"show-legend", no_argument, 0, 'g'}, + {"list-apps", no_argument, 0, 'l'}, + {"tree-dump", required_argument, 0, 'd'}, + {"tree-check", required_argument, 0, 'c'}, + {"indent", required_argument, 0, 'i'}, + }; + + int command = 0; + int option_index = 0; + + while (TRUE) { + command = getopt_long(argc, argv, "hgld:c:i:", long_options, &option_index); + + if (command == ERROR_STATE) + break; + + switch (command) { + case 'h': + print_help(); + break; + + case 'g': + _print_atspi_states_legend(); + break; + + case 'l': + atspi_tree_traverse(desktop, NULL, false, false); + break; + + case 'd': + atspi_tree_traverse(desktop, optarg, true, false); + break; + + case 'c': + atspi_tree_traverse(desktop, optarg, false, true); + break; + + case 'i': + set_indent(atoi(optarg)); + break; + + case '?': + break; + + default: + abort(); + } + } +} + +int main(int argc, char *argv[]) +{ + if (argc < 2) { + printf("Arguments required. Type %s --help.\n", argv[0]); + return -1; + } + + AtspiAccessible *desktop = atspi_get_desktop(0); + + if (!desktop) { + fprintf(stderr, "atspi_get_desktop failed\n"); + return 1; + } + + atspi_init(); + + run_command(argc, argv, desktop); + + return 0; +} -- 2.7.4 From 9ace85989ebf7ac08fd6bf091d18132180ff8dc3 Mon Sep 17 00:00:00 2001 From: Lukasz Wlazly Date: Tue, 27 Sep 2016 14:08:24 +0200 Subject: [PATCH 04/16] Tool for checking AT-SPI tree integrity v0.95 Code has been refactored and some additional features have appeared Change-Id: I4ff2a96f550df3d52116d166e079cc01d4a8b4b1 --- test/Makefile.am | 8 +- test/at_spi2_tool.c | 357 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 252 insertions(+), 113 deletions(-) diff --git a/test/Makefile.am b/test/Makefile.am index f233c36..6725315 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,10 +1,16 @@ LDADD = $(top_builddir)/atspi/libatspi.la + bin_PROGRAMS = at_spi2_tool at_spi2_tool_SOURCES = at_spi2_tool.c at_spi2_tool_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_builddir)/atspi -at_spi2_tool_CFLAGS = $(GLIB_CFLAGS) --std=c99 $(GOBJ_LIBS) $(DBUS_CFLAGS) +at_spi2_tool_CFLAGS = $(GLIB_CFLAGS) --std=c99 -Wall $(GOBJ_LIBS) $(DBUS_CFLAGS) at_spi2_tool_LDFLAGS = +noinst_PROGRAMS = memory +memory_SOURCES = memory.c +memory_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir) -I$(top_builddir)/atspi +memory_CFLAGS = $(GLIB_CFLAGS) $(GOBJ_LIBS) $(DBUS_CFLAGS) +memory_LDFLAGS = -include $(top_srcdir)/git.mk diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index f67700d..252f3e5 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -7,10 +7,19 @@ #define ERROR_STATE -1 #define SAFE_BUFFER_SIZE 255 +#define CHECK_OUTPUT_WIDTH 15 +#define MINIMAL_MODULE_WIDTH 3 +#define ATTR_WIDTH 50 +#define NUMBER_WIDTH 6 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define COLUMN_NO 3 +#define FLAG_NO 3 +#define DUMP 0 +#define CHECK 1 +#define FIRST_MATCH 2 static unsigned indent_width = 2; +static int module_name_limit = -1; static const char* atspi_state_names[] = { [ATSPI_STATE_INVALID] = "INVALID", @@ -62,17 +71,19 @@ static const char* atspi_state_names[] = { [ATSPI_STATE_LAST_DEFINED] = "LAST_DEFINED" }; -typedef struct _StringAccumulator { - char *string; - int length; -} StringAccumulator; +typedef struct _Box_Size { + int height; + int width; +} Box_Size; -char *strdup(const char *c) { +char *_strdup(const char *c) +{ char *result = (char *)calloc(1, strlen(c) + 1); return result ? strcpy(result, c) : result; } -static char *multiply_string(char c, unsigned number) { +static char *_multiply_string(char c, unsigned number) +{ char *result = (char *)calloc(1, number + 1); if (result == NULL) @@ -83,21 +94,39 @@ static char *multiply_string(char c, unsigned number) { return result; } -static void _print_atspi_states_legend() { +static void _print_module_legend() +{ + printf("\n[[node role name],[attributes list],[width,height],[node name],[states list]]\n\n"); +} + +static void _print_atspi_states_legend() +{ + _print_module_legend(); + int array_len = ARRAY_SIZE(atspi_state_names); int line_count = (array_len + COLUMN_NO - 1)/COLUMN_NO; for (int line_idx = 0; line_idx < line_count; line_idx++) { - if ((line_idx < line_count - 1) || (array_len % 3 == 0)) { - printf("[%d]\t%-24s[%d]\t%-24s[%d]\t%s\n", line_idx * 3, atspi_state_names[line_idx * 3], (line_idx * 3) + 1, atspi_state_names[(line_idx * 3) + 1], (line_idx * 3) + 2, atspi_state_names[(line_idx * 3) + 2]); - } else if (array_len % 3 == 2) { - printf("[%d]\t%-24s[%d]\t%s\n", line_idx * 3, atspi_state_names[line_idx * 3], (line_idx * 3) + 1, atspi_state_names[(line_idx * 3) + 1]); + if ((line_idx < line_count - 1) || (array_len % COLUMN_NO == 0)) { + printf("[%d]\t%-24s[%d]\t%-24s[%d]\t%s\n", + line_idx * COLUMN_NO, + atspi_state_names[line_idx * COLUMN_NO], + (line_idx * COLUMN_NO) + 1, + atspi_state_names[(line_idx * COLUMN_NO) + 1], + (line_idx * COLUMN_NO) + 2, + atspi_state_names[(line_idx * COLUMN_NO) + 2]); + } else if (array_len % COLUMN_NO == 2) { + printf("[%d]\t%-24s[%d]\t%s\n", + line_idx * COLUMN_NO, + atspi_state_names[line_idx * COLUMN_NO], + (line_idx * COLUMN_NO) + 1, + atspi_state_names[(line_idx * COLUMN_NO) + 1]); } else { - printf("[%d]\t%s\n", line_idx * 3, atspi_state_names[line_idx * 3]); + printf("[%d]\t%s\n", line_idx * COLUMN_NO, atspi_state_names[line_idx * COLUMN_NO]); } } } -static void set_indent(int indent_size) +static void _set_indent(int indent_size) { if (indent_size < 0) { fprintf(stderr, "WARNING: Invalid indent size. Default value retained.\n"); @@ -107,6 +136,16 @@ static void set_indent(int indent_size) indent_width = indent_size; } +static void _set_module_length_limit(int limit) +{ + if (limit < MINIMAL_MODULE_WIDTH) { + fprintf(stderr, "WARNING: Invalid maximum field size. Default value retained.\n"); + return; + } + + module_name_limit = limit; +} + static int _int_sort_function(gconstpointer a, gconstpointer b) { int int_a = GPOINTER_TO_INT (a); @@ -115,129 +154,187 @@ static int _int_sort_function(gconstpointer a, gconstpointer b) return int_a - int_b; } -static int _accumulate_string(const char *string, StringAccumulator *accumulator) { - if (!accumulator) - return FALSE; - - if (string) { - int length = accumulator->length + strlen(string); - char *rebuffer = realloc(accumulator->string, length + 1); - if (rebuffer) { - strcpy(rebuffer + accumulator->length, string); - accumulator->string = rebuffer; - accumulator->length = length; - } else { - return FALSE; - } +static void _truncate_string(char *string, int length_limit) +{ + if (length_limit < MINIMAL_MODULE_WIDTH || !string) + return; + + int len = strlen(string); + + if (len > length_limit) + memcpy(string + length_limit - 3, "...", 4); +} + +static size_t _combine_strings(char **destination, const char *source) +{ + if (!source || !*source || !destination) + return 0; + + size_t old_len = *destination ? strlen(*destination) : 0; + size_t source_len = strlen(source); + size_t len = old_len + source_len; + char *buf = realloc(*destination, (len + 1) * sizeof(char)); + + if (!buf) { + fprintf(stderr, "_combine_strings: allocation failed"); + return old_len; } - return TRUE; + + memcpy(buf + old_len, source, source_len + 1); + + *destination = buf; + + return len; } -static char *get_info(AtspiAccessible *node) { - if (!node) +static Box_Size *_get_box_size(AtspiAccessible *node) +{ + Box_Size *box_size = (Box_Size *)malloc(sizeof(Box_Size)); + if (box_size == NULL) return NULL; - int node_width = -1; - int node_height = -1; - char *node_name = atspi_accessible_get_name(node, NULL); - char *node_role_name = atspi_accessible_get_role_name(node, NULL); + box_size->width = -1; + box_size->height = -1; + AtspiComponent *component = atspi_accessible_get_component_iface(node); - AtspiRect *extent = NULL; - if (component != NULL){ - extent = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); + if (component == NULL) + return box_size; - if (extent != NULL) { - node_width = extent->width; - node_height = extent->height; - } - } + AtspiRect *extent = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); + if (extent == NULL) + return box_size; + + box_size->width = extent->width; + box_size->height = extent->height; + + g_object_unref(component); + g_free(extent); + return box_size; +} + +static char *_get_states(AtspiAccessible *node) +{ AtspiStateSet *node_state_set = atspi_accessible_get_state_set(node); GArray *states = atspi_state_set_get_states(node_state_set); g_array_sort(states, _int_sort_function); - AtspiStateType state; - StringAccumulator state_accumulator = {}; + AtspiStateType state_type; + char *state_string = NULL; + for (int i = 0; states && (i < states->len); i++) { - state = g_array_index(states, AtspiStateType, i); + state_type = g_array_index(states, AtspiStateType, i); + char node_state_str[8]; - sprintf(node_state_str, "[%d]", state); - _accumulate_string(node_state_str, &state_accumulator); + sprintf(node_state_str, "(%d)", state_type); + _combine_strings(&state_string, node_state_str); } + g_array_free(states, 0); + g_object_unref(node_state_set); + + return state_string; +} - StringAccumulator attribute_accumulator = {}; +static char *_get_attributes(AtspiAccessible *node) +{ GHashTable *attributes = NULL; attributes = atspi_accessible_get_attributes(node, NULL); - if (attributes) { - GHashTableIter attributes_iter; - gpointer attr_key, attr_value; - g_hash_table_iter_init (&attributes_iter, attributes); - while (g_hash_table_iter_next (&attributes_iter, &attr_key, &attr_value)) { - _accumulate_string("[", &attribute_accumulator); - _accumulate_string((char*)attr_key, &attribute_accumulator); - _accumulate_string("=", &attribute_accumulator); - _accumulate_string((char*)attr_value, &attribute_accumulator); - _accumulate_string("]", &attribute_accumulator); - } - g_hash_table_unref(attributes); - } - char result[SAFE_BUFFER_SIZE + 1]; - snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%d,%d],[%s],[%s]]\n", node_role_name, attribute_accumulator.string, node_width, node_height, node_name, state_accumulator.string); + if (!attributes) + return NULL; - free(node_name); - free(node_role_name); + GHashTableIter attributes_iter; + gpointer attr_key; + gpointer attr_value; + g_hash_table_iter_init (&attributes_iter, attributes); + char *result = NULL; + while (g_hash_table_iter_next (&attributes_iter, &attr_key, &attr_value)) { + char attributes_string[ATTR_WIDTH]; + int ret = snprintf(attributes_string, ATTR_WIDTH, "(%s=%s)", (char*)attr_key, (char*)attr_value); + if (ret >= ATTR_WIDTH) { + fprintf(stderr, "_get_attributes: generated string is too long. Buffer overflow"); + abort(); + } + _combine_strings(&result, attributes_string); + } + g_hash_table_unref(attributes); - if (state_accumulator.string) - g_free(state_accumulator.string); + return result; +} - if (attribute_accumulator.string) - g_free(attribute_accumulator.string); +static char *_get_info(AtspiAccessible *node, int length_limit) +{ + if (!node) + return NULL; - if (component) - g_object_unref(component); + char *node_name = atspi_accessible_get_name(node, NULL); + char *node_role_name = atspi_accessible_get_role_name(node, NULL); - if (extent) - g_free(extent); + char *attributes = _get_attributes(node); + _truncate_string(attributes, length_limit); + Box_Size *box_size = _get_box_size(node); + char *states = _get_states(node); + _truncate_string(states, length_limit); + + char result[SAFE_BUFFER_SIZE]; + int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%d,%d],[%s],[%s]]", + node_role_name, + attributes, + box_size->width, + box_size->height, + node_name, + states); + + if (ret >= SAFE_BUFFER_SIZE) { + fprintf(stderr, "_get_info: generated string is too long. Buffer overflow"); + abort(); + } - if (node_state_set) - g_object_unref(node_state_set); + free(node_name); + free(node_role_name); + free(attributes); + free(box_size); + free(states); - return strdup(result); + return _strdup(result); } -static void test_atspi_parent_child_relation(AtspiAccessible *obj, AtspiAccessible *parent_candidate, int parent_candidate_index) +static void _test_atspi_parent_child_relation(AtspiAccessible *obj, AtspiAccessible *parent_candidate, int parent_candidate_index) { int parent_index = atspi_accessible_get_index_in_parent(obj, NULL); AtspiAccessible *parent = atspi_accessible_get_parent(obj, NULL); + + char output[CHECK_OUTPUT_WIDTH]; if (parent_index != parent_candidate_index || parent_candidate != parent) { - printf("[FAIL<%d,", parent_candidate_index); + char parent_status[NUMBER_WIDTH]; if (parent == NULL) - printf("_"); + strcpy(parent_status, "_"); else - printf("%d", parent_index); + snprintf(parent_status, NUMBER_WIDTH, "%d", parent_index); - printf(">]\t"); + snprintf(output, CHECK_OUTPUT_WIDTH, "[FAIL<%d,%s>]", parent_candidate_index, parent_status); } else { - printf("[OK]\t"); + snprintf(output, CHECK_OUTPUT_WIDTH, "[OK]"); } + + printf("%-*s\t", CHECK_OUTPUT_WIDTH, output); } -static int expand_r(int indent_number, AtspiAccessible *object, bool check_integrity) +static int _print_atspi_tree_verify_maybe_r(int indent_number, AtspiAccessible *object, bool check_integrity, int length_limit) { - char *indent = multiply_string(' ', indent_number*indent_width); + char *indent = _multiply_string(' ', indent_number*indent_width); if (indent != NULL) { printf("%s", indent); free(indent); } - char *node_info = get_info(object); + char *node_info = _get_info(object, length_limit); if (node_info != NULL) { - printf("%s", node_info); + printf("%s\n", node_info); free(node_info); } @@ -246,15 +343,15 @@ static int expand_r(int indent_number, AtspiAccessible *object, bool check_integ AtspiAccessible *child = atspi_accessible_get_child_at_index(object, i, NULL); if (child) { if (check_integrity) - test_atspi_parent_child_relation(child, object, i); + _test_atspi_parent_child_relation(child, object, i); - expand_r(indent_number + 1, child, check_integrity); + _print_atspi_tree_verify_maybe_r(indent_number + 1, child, check_integrity, length_limit); } } return 0; } -void print_help() +void _print_help() { printf("AT-SPI2-CORE-UTIL\n\n"); printf("USAGE: at_spi2_tool [OPTION] [PARAMETER] ...\n\n"); @@ -264,7 +361,9 @@ void print_help() printf("-l, --list-apps\t\tlist all applications of desktop\n"); printf("-d, --tree-dump\t\tdump tree for selected application\n"); printf("-c, --tree-check\tcheck tree for selected application\n"); - printf("-i, --indent\t\tset indentation size\n"); + printf("-f, --first-match\tperform dump or check only for first matching application\n"); + printf("-i, --indent\t\tset indentation size, default value stands at 2\n"); + printf("-t, --truncate\t\tset maximum single field size, default value stands at 30\n"); printf("\nEXAMPLE:\n"); printf("\tat_spi2_tool -i3 -d quickpanel\n"); printf("\t show AT-SPI tree for node \"quickpanel\" using three-space indentation\n"); @@ -272,32 +371,44 @@ void print_help() printf("\t show AT-SPI tree with integrity test for node \"starter\" using one-space indentation\n"); } -static void atspi_tree_traverse(AtspiAccessible *desktop, const char *app_name, bool dump, bool check) +static void _atspi_tree_traverse(AtspiAccessible *desktop, const char *app_name, bool dump, bool check, bool first_match, int length_limit) { 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) { char *name = atspi_accessible_get_name(child, NULL); - if (!dump && !check) + if (!dump && !check) { printf("%s\n", name); - - if (dump && name && !strcmp(name, app_name)) { - expand_r(0, child, false); - break; } - if (check && name && !strcmp(name, app_name)) { - test_atspi_parent_child_relation(child, desktop, i); - expand_r(0, child, true); - break; + if ((check || dump) && name && !strcmp(name, app_name)) { + app_name_matched = true; + + _print_module_legend(); + + if (check) + _test_atspi_parent_child_relation(child, desktop, i); + + _print_atspi_tree_verify_maybe_r(0, child, check, length_limit); + + if (first_match) { + free(name); + break; + } else + printf("\n"); } + free(name); } } + + if (!app_name_matched && (dump || check)) + fprintf(stderr, "There is no application with name: %s. Try again.\n", app_name); } -static void run_command(int argc, char *argv[], AtspiAccessible *desktop) +static void _run_command(int argc, char *argv[], AtspiAccessible *desktop) { struct option long_options[] = { {"help", no_argument, 0, 'h'}, @@ -305,21 +416,25 @@ static void run_command(int argc, char *argv[], AtspiAccessible *desktop) {"list-apps", no_argument, 0, 'l'}, {"tree-dump", required_argument, 0, 'd'}, {"tree-check", required_argument, 0, 'c'}, + {"first-match", no_argument, 0, 'f'}, {"indent", required_argument, 0, 'i'}, + {"truncate", required_argument, 0, 't'}, }; int command = 0; int option_index = 0; + bool traverse_flags[FLAG_NO] = {false}; + char *app_name = NULL; while (TRUE) { - command = getopt_long(argc, argv, "hgld:c:i:", long_options, &option_index); + command = getopt_long(argc, argv, "hgld:c:ft:i:", long_options, &option_index); if (command == ERROR_STATE) break; switch (command) { case 'h': - print_help(); + _print_help(); break; case 'g': @@ -327,28 +442,42 @@ static void run_command(int argc, char *argv[], AtspiAccessible *desktop) break; case 'l': - atspi_tree_traverse(desktop, NULL, false, false); + _atspi_tree_traverse(desktop, NULL, false, false, false, module_name_limit); break; case 'd': - atspi_tree_traverse(desktop, optarg, true, false); + traverse_flags[DUMP] = true; + app_name = optarg; break; case 'c': - atspi_tree_traverse(desktop, optarg, false, true); + traverse_flags[CHECK] = true; + app_name = optarg; + break; + + case 'f': + traverse_flags[FIRST_MATCH] = true; break; case 'i': - set_indent(atoi(optarg)); + _set_indent(atoi(optarg)); + break; + + case 't': + _set_module_length_limit(atoi(optarg)); break; case '?': + fprintf(stderr, "Invalid parameter. Use: \"--help\"\n"); break; default: abort(); } } + + 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); } int main(int argc, char *argv[]) @@ -358,16 +487,20 @@ int main(int argc, char *argv[]) return -1; } - AtspiAccessible *desktop = atspi_get_desktop(0); + int result = atspi_init(); + if (result != 0) + { + fprintf(stderr, "Unable to initilize AT-SPI infrastructure, atspi_init failed\n"); + return -1; + } + AtspiAccessible *desktop = atspi_get_desktop(0); if (!desktop) { fprintf(stderr, "atspi_get_desktop failed\n"); - return 1; + return -1; } - atspi_init(); - - run_command(argc, argv, desktop); + _run_command(argc, argv, desktop); return 0; } -- 2.7.4 From b82529fc524ce440a1b7b034361f37aee8b1664d Mon Sep 17 00:00:00 2001 From: Lukasz Wlazly Date: Thu, 6 Oct 2016 16:20:46 +0200 Subject: [PATCH 05/16] Tool for checking AT-SPI tree integrity v1.0 now, in case of fail, except nodes' indexes pointers are also printed Change-Id: I8823fbad9243c1969ed81f35ef6968858846fed2 --- test/at_spi2_tool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index 252f3e5..a520412 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -7,7 +7,7 @@ #define ERROR_STATE -1 #define SAFE_BUFFER_SIZE 255 -#define CHECK_OUTPUT_WIDTH 15 +#define CHECK_OUTPUT_WIDTH 38 #define MINIMAL_MODULE_WIDTH 3 #define ATTR_WIDTH 50 #define NUMBER_WIDTH 6 @@ -315,7 +315,7 @@ 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>]", parent_candidate_index, parent_status); + snprintf(output, CHECK_OUTPUT_WIDTH, "[FAIL<%d,%s><%p,%p>]", parent_candidate_index, parent_status, parent_candidate, parent); } else { snprintf(output, CHECK_OUTPUT_WIDTH, "[OK]"); -- 2.7.4 From 3d23188a026eafde59f85e70f9ead9d830f67a21 Mon Sep 17 00:00:00 2001 From: Lukasz Wlazly Date: Thu, 6 Oct 2016 16:52:59 +0200 Subject: [PATCH 06/16] Tool for checking AT-SPI tree integrity v1.01 Only one macro redefined Change-Id: I5e85f455e6f1a5ae89d8dddd3d352488b5a1122e --- test/at_spi2_tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index a520412..8c6bc6f 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -7,7 +7,7 @@ #define ERROR_STATE -1 #define SAFE_BUFFER_SIZE 255 -#define CHECK_OUTPUT_WIDTH 38 +#define CHECK_OUTPUT_WIDTH 42 #define MINIMAL_MODULE_WIDTH 3 #define ATTR_WIDTH 50 #define NUMBER_WIDTH 6 -- 2.7.4 From af2668010904f4be11e42b3683b9129ababc1d4c Mon Sep 17 00:00:00 2001 From: Lukasz Wlazly Date: Wed, 12 Oct 2016 15:28:33 +0200 Subject: [PATCH 07/16] Tool for checking tree integrity v1.02 Change-Id: I1fe9ca1f3eaf7af2325d3248cacaa8cabc6d14cd --- test/at_spi2_tool.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index 8c6bc6f..1a951da 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -17,6 +17,7 @@ #define DUMP 0 #define CHECK 1 #define FIRST_MATCH 2 +#define VERSION "1.02" static unsigned indent_width = 2; static int module_name_limit = -1; @@ -357,6 +358,7 @@ void _print_help() printf("USAGE: at_spi2_tool [OPTION] [PARAMETER] ...\n\n"); printf("OPTION LIST:\n"); printf("-h, --help\t\tshow this message\n"); + 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("-d, --tree-dump\t\tdump tree for selected application\n"); @@ -370,6 +372,10 @@ void _print_help() printf("\tat_spi2_tool -i1 -c starter\n"); printf("\t show AT-SPI tree with integrity test for node \"starter\" using one-space indentation\n"); } +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) { @@ -412,6 +418,7 @@ static void _run_command(int argc, char *argv[], AtspiAccessible *desktop) { 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'}, {"tree-dump", required_argument, 0, 'd'}, @@ -427,7 +434,7 @@ static void _run_command(int argc, char *argv[], AtspiAccessible *desktop) char *app_name = NULL; while (TRUE) { - command = getopt_long(argc, argv, "hgld:c:ft:i:", long_options, &option_index); + command = getopt_long(argc, argv, "hvgld:c:ft:i:", long_options, &option_index); if (command == ERROR_STATE) break; @@ -437,6 +444,10 @@ static void _run_command(int argc, char *argv[], AtspiAccessible *desktop) _print_help(); break; + case 'v': + _print_version(); + break; + case 'g': _print_atspi_states_legend(); break; -- 2.7.4 From 960f8b5d524b9145c9230ad1ce99a46920091aee Mon Sep 17 00:00:00 2001 From: Lukasz Wlazly Date: Fri, 14 Oct 2016 13:35:57 +0200 Subject: [PATCH 08/16] Tool for checking AT-SPI tree integrity v1.1 Change-Id: Id46b609f80f36b93bb7af938937e4893d51ac1d7 --- test/at_spi2_tool.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index 1a951da..b47d432 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -17,7 +17,7 @@ #define DUMP 0 #define CHECK 1 #define FIRST_MATCH 2 -#define VERSION "1.02" +#define VERSION "1.1" static unsigned indent_width = 2; static int module_name_limit = -1; @@ -73,8 +73,8 @@ static const char* atspi_state_names[] = { }; typedef struct _Box_Size { - int height; - int width; + char *height; + char *width; } Box_Size; char *_strdup(const char *c) @@ -194,8 +194,14 @@ static Box_Size *_get_box_size(AtspiAccessible *node) if (box_size == NULL) return NULL; - box_size->width = -1; - box_size->height = -1; + char *width = NULL; + char *height = NULL; + + _combine_strings(&width, "_"); + _combine_strings(&height, "_"); + + box_size->width = width; + box_size->height = height; AtspiComponent *component = atspi_accessible_get_component_iface(node); @@ -206,12 +212,23 @@ static Box_Size *_get_box_size(AtspiAccessible *node) if (extent == NULL) return box_size; - box_size->width = extent->width; - box_size->height = extent->height; + *width = '\0'; + *height = '\0'; + + char temp_buff[NUMBER_WIDTH]; + + snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->width); + _combine_strings(&width, temp_buff); + + snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->height); + _combine_strings(&height, temp_buff); g_object_unref(component); g_free(extent); + box_size->width = width; + box_size->height = height; + return box_size; } @@ -280,7 +297,7 @@ static char *_get_info(AtspiAccessible *node, int length_limit) _truncate_string(states, length_limit); char result[SAFE_BUFFER_SIZE]; - int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%d,%d],[%s],[%s]]", + int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s,%s],[%s],[%s]]", node_role_name, attributes, box_size->width, @@ -296,7 +313,11 @@ static char *_get_info(AtspiAccessible *node, int length_limit) free(node_name); free(node_role_name); free(attributes); - free(box_size); + if (box_size) { + free(box_size->width); + free(box_size->height); + free(box_size); + } free(states); return _strdup(result); -- 2.7.4 From 7ee42a9a5a8207541df3c51a386dcca8e7244c73 Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Sat, 12 Nov 2016 15:01:18 +0900 Subject: [PATCH 09/16] [at_spi2_tool] report x, y information of accessible object Change-Id: Ibcfab40ef65f91617303e86c4fb1b5275de89be7 --- test/at_spi2_tool.c | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index b47d432..7a7b9a5 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -73,6 +73,8 @@ static const char* atspi_state_names[] = { }; typedef struct _Box_Size { + char *x; + char *y; char *height; char *width; } Box_Size; @@ -97,7 +99,7 @@ static char *_multiply_string(char c, unsigned number) static void _print_module_legend() { - printf("\n[[node role name],[attributes list],[width,height],[node name],[states list]]\n\n"); + printf("\n[[node role name],[attributes list],[x,y,width,height],[node name],[states list]]\n\n"); } static void _print_atspi_states_legend() @@ -194,38 +196,40 @@ static Box_Size *_get_box_size(AtspiAccessible *node) if (box_size == NULL) return NULL; + char *x = NULL; + char *y = NULL; char *width = NULL; char *height = NULL; - _combine_strings(&width, "_"); - _combine_strings(&height, "_"); - - box_size->width = width; - box_size->height = height; - AtspiComponent *component = atspi_accessible_get_component_iface(node); + AtspiRect *extent = component ? atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL) : NULL; - if (component == NULL) - return box_size; - - AtspiRect *extent = atspi_component_get_extents(component, ATSPI_COORD_TYPE_SCREEN, NULL); - if (extent == NULL) - return box_size; + if (extent == NULL) { + _combine_strings(&x, "_"); + _combine_strings(&y, "_"); + _combine_strings(&width, "_"); + _combine_strings(&height, "_"); + } else { + char temp_buff[NUMBER_WIDTH]; - *width = '\0'; - *height = '\0'; + snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->x); + _combine_strings(&x, temp_buff); - char temp_buff[NUMBER_WIDTH]; + snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->y); + _combine_strings(&y, temp_buff); - snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->width); - _combine_strings(&width, temp_buff); + snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->width); + _combine_strings(&width, temp_buff); - snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->height); - _combine_strings(&height, temp_buff); + snprintf(temp_buff, NUMBER_WIDTH, "%d", extent->height); + _combine_strings(&height, temp_buff); - g_object_unref(component); - g_free(extent); + g_object_unref(component); + g_free(extent); + } + box_size->x = x; + box_size->y = y; box_size->width = width; box_size->height = height; @@ -297,9 +301,11 @@ static char *_get_info(AtspiAccessible *node, int length_limit) _truncate_string(states, length_limit); char result[SAFE_BUFFER_SIZE]; - int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s,%s],[%s],[%s]]", + int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s,%s,%s,%s],[%s],[%s]]", node_role_name, attributes, + box_size->x, + box_size->y, box_size->width, box_size->height, node_name, -- 2.7.4 From 7fee13e56871be0449fa26088711c99ab43129d3 Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Sat, 12 Nov 2016 15:00:05 +0900 Subject: [PATCH 10/16] Build DEBUG package Change-Id: Id6ce145487550d1a5cca2e7c893b1cd4e8b59793 --- packaging/at-spi2-core.spec | 3 --- 1 file changed, 3 deletions(-) diff --git a/packaging/at-spi2-core.spec b/packaging/at-spi2-core.spec index 472f089..bdb6b7c 100644 --- a/packaging/at-spi2-core.spec +++ b/packaging/at-spi2-core.spec @@ -1,4 +1,3 @@ -%define debug_package %{nil} %bcond_with x Name: at-spi2-core @@ -86,8 +85,6 @@ find %{buildroot} -name '*.la' -or -name '*.a' | xargs rm -f %make_install %find_lang %{name} -%check - %clean rm -fr %{buildroot} -- 2.7.4 From 011b9f8e62f1b61a168f4ec7d4224952fba07805 Mon Sep 17 00:00:00 2001 From: Radoslaw Cybulski Date: Tue, 6 Dec 2016 18:34:15 +0100 Subject: [PATCH 11/16] fix for non-navigatable end call window in call-ui application, by Mr Shin-Woo Kim Change-Id: I3c6fc0163e1bacac5ea3518c181cc7ef69cec62f --- atspi/atspi-misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c index 4cf7732..fdb4e9b 100644 --- a/atspi/atspi-misc.c +++ b/atspi/atspi-misc.c @@ -387,7 +387,7 @@ handle_name_owner_changed (DBusConnection *bus, DBusMessage *message, void *user else if (app_hash) { AtspiApplication *app = g_hash_table_lookup (app_hash, old); - if (app) + if (app && name && app->bus_name && !strcmp(app->bus_name, name)) g_object_run_dispose (G_OBJECT (app)); } return DBUS_HANDLER_RESULT_HANDLED; -- 2.7.4 From f584cba35f374effd21e652c80a8bf6b72ec6911 Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Tue, 13 Dec 2016 10:34:13 +0900 Subject: [PATCH 12/16] Fix SVACE issue WID164553 - name is not NULL always Change-Id: Idff718d0416e98a0556f9421f1d3c76235756ab7 --- atspi/atspi-misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c index fdb4e9b..48759ca 100644 --- a/atspi/atspi-misc.c +++ b/atspi/atspi-misc.c @@ -387,7 +387,7 @@ handle_name_owner_changed (DBusConnection *bus, DBusMessage *message, void *user else if (app_hash) { AtspiApplication *app = g_hash_table_lookup (app_hash, old); - if (app && name && app->bus_name && !strcmp(app->bus_name, name)) + if (app && app->bus_name && !strcmp(app->bus_name, name)) g_object_run_dispose (G_OBJECT (app)); } return DBUS_HANDLER_RESULT_HANDLED; -- 2.7.4 From 2658d2c2bdf3a8d50d10bb290151151652caf369 Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Tue, 13 Dec 2016 19:00:35 +0900 Subject: [PATCH 13/16] at_spi2_tool: return node pointer, relation flow to/from information Do not abort even though the information is too long. It was not possilbe to get next launchpad-loader application. Change-Id: Ia7e5c6ad7a989bff3425b922ef4d80cf7667be1c --- test/at_spi2_tool.c | 54 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index 7a7b9a5..b8f051f 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -6,7 +6,7 @@ #include #define ERROR_STATE -1 -#define SAFE_BUFFER_SIZE 255 +#define SAFE_BUFFER_SIZE 2048 #define CHECK_OUTPUT_WIDTH 42 #define MINIMAL_MODULE_WIDTH 3 #define ATTR_WIDTH 50 @@ -99,7 +99,7 @@ static char *_multiply_string(char c, unsigned number) static void _print_module_legend() { - printf("\n[[node role name],[attributes list],[x,y,width,height],[node name],[states list]]\n\n"); + printf("\n[[node],[node role name],[attributes list],[x,y,width,height],[node name],[states list][flow to node, flow from node]\n\n"); } static void _print_atspi_states_legend() @@ -277,7 +277,7 @@ static char *_get_attributes(AtspiAccessible *node) int ret = snprintf(attributes_string, ATTR_WIDTH, "(%s=%s)", (char*)attr_key, (char*)attr_value); if (ret >= ATTR_WIDTH) { fprintf(stderr, "_get_attributes: generated string is too long. Buffer overflow"); - abort(); + attributes_string[ATTR_WIDTH - 1] = '\n'; } _combine_strings(&result, attributes_string); } @@ -286,6 +286,31 @@ static char *_get_attributes(AtspiAccessible *node) return result; } +static AtspiAccessible *_get_object_in_relation(AtspiAccessible * source, AtspiRelationType search_type) +{ + GArray *relations; + AtspiAccessible *ret = NULL; + AtspiRelation *relation; + AtspiRelationType type; + int i; + if (source) { + relations = atspi_accessible_get_relation_set(source, NULL); + if (relations) { + for (i = 0; i < relations->len; i++) { + relation = g_array_index(relations, AtspiRelation *, i); + type = atspi_relation_get_relation_type(relation); + + if (type == search_type) { + ret = atspi_relation_get_target(relation, 0); + break; + } + } + g_array_free(relations, TRUE); + } + } + return ret; +} + static char *_get_info(AtspiAccessible *node, int length_limit) { if (!node) @@ -301,19 +326,22 @@ static char *_get_info(AtspiAccessible *node, int length_limit) _truncate_string(states, length_limit); char result[SAFE_BUFFER_SIZE]; - int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s,%s,%s,%s],[%s],[%s]]", - node_role_name, - attributes, - box_size->x, - box_size->y, - box_size->width, - box_size->height, - node_name, - states); + int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%p],[%s],[%s],[%s,%s,%s,%s],[%s],[%s],[%p,%p]]", + node, + node_role_name, + attributes, + box_size->x, + box_size->y, + box_size->width, + box_size->height, + node_name, + states, + _get_object_in_relation(node, ATSPI_RELATION_FLOWS_TO), + _get_object_in_relation(node, ATSPI_RELATION_FLOWS_FROM)); if (ret >= SAFE_BUFFER_SIZE) { fprintf(stderr, "_get_info: generated string is too long. Buffer overflow"); - abort(); + result[SAFE_BUFFER_SIZE - 1] = '\n'; } free(node_name); -- 2.7.4 From 582f80f5874e357d19bbbc2e5884260e7e11e04e Mon Sep 17 00:00:00 2001 From: Lukasz Wlazly Date: Fri, 16 Dec 2016 15:54:58 +0100 Subject: [PATCH 14/16] [at_spi2_tool] truncation of states string added; small refactor works Change-Id: I2b3b139ae33d575951a7faa9ff96df6e285f6a1c --- test/at_spi2_tool.c | 105 ++++++++++++++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index b8f051f..af7eb97 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -236,7 +236,7 @@ static Box_Size *_get_box_size(AtspiAccessible *node) return box_size; } -static char *_get_states(AtspiAccessible *node) +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); @@ -256,13 +256,14 @@ static char *_get_states(AtspiAccessible *node) g_array_free(states, 0); g_object_unref(node_state_set); + _truncate_string(state_string, length_limit); + return state_string; } -static char *_get_attributes(AtspiAccessible *node) +static char *_get_attributes(AtspiAccessible *node, int length_limit) { - GHashTable *attributes = NULL; - attributes = atspi_accessible_get_attributes(node, NULL); + GHashTable *attributes = atspi_accessible_get_attributes(node, NULL); if (!attributes) return NULL; @@ -274,40 +275,41 @@ static char *_get_attributes(AtspiAccessible *node) char *result = NULL; while (g_hash_table_iter_next (&attributes_iter, &attr_key, &attr_value)) { char attributes_string[ATTR_WIDTH]; - int ret = snprintf(attributes_string, ATTR_WIDTH, "(%s=%s)", (char*)attr_key, (char*)attr_value); - if (ret >= ATTR_WIDTH) { - fprintf(stderr, "_get_attributes: generated string is too long. Buffer overflow"); - attributes_string[ATTR_WIDTH - 1] = '\n'; - } + int ret = snprintf(attributes_string, ATTR_WIDTH, "(%s=%s)", (char *)attr_key, (char *)attr_value); + if (ret >= ATTR_WIDTH) + fprintf(stderr, "\n_get_attributes: generated string is too long. Buffer overflow\n"); + _combine_strings(&result, attributes_string); } g_hash_table_unref(attributes); + _truncate_string(result, length_limit); return result; } -static AtspiAccessible *_get_object_in_relation(AtspiAccessible * source, AtspiRelationType search_type) +static AtspiAccessible *_get_object_in_relation(AtspiAccessible *source, AtspiRelationType search_type) { - GArray *relations; - AtspiAccessible *ret = NULL; - AtspiRelation *relation; - AtspiRelationType type; - int i; - if (source) { - relations = atspi_accessible_get_relation_set(source, NULL); - if (relations) { - for (i = 0; i < relations->len; i++) { - relation = g_array_index(relations, AtspiRelation *, i); - type = atspi_relation_get_relation_type(relation); - - if (type == search_type) { - ret = atspi_relation_get_target(relation, 0); - break; - } - } - g_array_free(relations, TRUE); + if (source == NULL) + return NULL; + + GArray *relations = atspi_accessible_get_relation_set(source, NULL); + + if (relations == NULL) + return NULL; + + AtspiAccessible *ret; + for (int i = 0; i < relations->len; ++i) { + AtspiRelation *relation = g_array_index(relations, AtspiRelation *, i); + AtspiRelationType type = atspi_relation_get_relation_type(relation); + + if (type == search_type) { + ret = atspi_relation_get_target(relation, 0); + break; } } + + g_array_free(relations, TRUE); + return ret; } @@ -319,11 +321,9 @@ 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 *attributes = _get_attributes(node); - _truncate_string(attributes, length_limit); + char *attributes = _get_attributes(node, length_limit); Box_Size *box_size = _get_box_size(node); - char *states = _get_states(node); - _truncate_string(states, length_limit); + char *states = _get_states(node, length_limit); char result[SAFE_BUFFER_SIZE]; int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%p],[%s],[%s],[%s,%s,%s,%s],[%s],[%s],[%p,%p]]", @@ -339,10 +339,8 @@ static char *_get_info(AtspiAccessible *node, int length_limit) _get_object_in_relation(node, ATSPI_RELATION_FLOWS_TO), _get_object_in_relation(node, ATSPI_RELATION_FLOWS_FROM)); - if (ret >= SAFE_BUFFER_SIZE) { - fprintf(stderr, "_get_info: generated string is too long. Buffer overflow"); - result[SAFE_BUFFER_SIZE - 1] = '\n'; - } + if (ret >= SAFE_BUFFER_SIZE) + fprintf(stderr, "\n_get_info: generated string is too long. Buffer overflow\n"); free(node_name); free(node_role_name); @@ -438,29 +436,30 @@ static void _atspi_tree_traverse(AtspiAccessible *desktop, const char *app_name, 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) { - char *name = atspi_accessible_get_name(child, NULL); + if (child == NULL) + break; + + char *name = atspi_accessible_get_name(child, NULL); + + if (!dump && !check) + printf("%s\n", name); - if (!dump && !check) { - printf("%s\n", name); - } + if ((check || dump) && name && !strcmp(name, app_name)) { + app_name_matched = true; - if ((check || dump) && name && !strcmp(name, app_name)) { - app_name_matched = true; + _print_module_legend(); - _print_module_legend(); + if (check) + _test_atspi_parent_child_relation(child, desktop, i); - if (check) - _test_atspi_parent_child_relation(child, desktop, i); + _print_atspi_tree_verify_maybe_r(0, child, check, length_limit); - _print_atspi_tree_verify_maybe_r(0, child, check, length_limit); + if (first_match) { + free(name); + break; + } else + printf("\n"); - if (first_match) { - free(name); - break; - } else - printf("\n"); - } free(name); } } -- 2.7.4 From 3085427fe057bd89000f828f8bb36c3553508fe8 Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Mon, 13 Feb 2017 18:39:13 +0900 Subject: [PATCH 15/16] at_spi2_tool: initialize data Uninitialized data is read from local variable 'ret' Change-Id: Ib03c2dae19b5f4f87a2a090bc6c4595939e2655d --- test/at_spi2_tool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index af7eb97..594a7c8 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -297,7 +297,7 @@ static AtspiAccessible *_get_object_in_relation(AtspiAccessible *source, AtspiRe if (relations == NULL) return NULL; - 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); -- 2.7.4 From 28359dc838f7b390d33343821e1bfe086d2b9efc Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Wed, 6 Apr 2016 17:10:03 +0200 Subject: [PATCH 16/16] atspi-event-listener: Plug a memory leak https://bugzilla.gnome.org/show_bug.cgi?id=764688 Change-Id: I82281f9f9ad2b8c410d4d713ad12dee1343ab2bc --- atspi/atspi-event-listener.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/atspi/atspi-event-listener.c b/atspi/atspi-event-listener.c index 95af3a0..5c4b442 100644 --- a/atspi/atspi-event-listener.c +++ b/atspi/atspi-event-listener.c @@ -1002,6 +1002,9 @@ _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data) if (e.source == NULL) { g_warning ("Got no valid source accessible for signal for signal %s from interface %s\n", member, category); + g_free (converted_type); + g_free (name); + g_free (detail); return DBUS_HANDLER_RESULT_HANDLED; } -- 2.7.4