From 23b49ea6ed68e056d1d8de4756293ca026ec09ce Mon Sep 17 00:00:00 2001 From: Pawel Kurowski Date: Thu, 1 Jun 2017 12:45:08 +0200 Subject: [PATCH 01/16] Add relation-dump option to at_spi2_tool Flags -d and -c now inform when object has relations to list. Change-Id: I0c9a03c8d18ddf965c72ceac2bb804742c4540bf --- test/at_spi2_tool.c | 155 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 110 insertions(+), 45 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index dfbc051..15adca5 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -5,6 +5,7 @@ #include #include #include +#include #define ERROR_STATE -1 #define SAFE_BUFFER_SIZE 2048 @@ -18,6 +19,8 @@ #define DUMP 0 #define CHECK 1 #define FIRST_MATCH 2 +#define RELATION_TABLE_COLUMN_COUNT 7 +#define RELATION_COLUMN_WIDTH 20 #define VERSION "1.1" static unsigned indent_width = 2; @@ -80,12 +83,6 @@ typedef struct _Box_Size { char *width; } Box_Size; -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); @@ -100,7 +97,7 @@ static char *_multiply_string(char c, unsigned number) static void _print_module_legend() { - printf("\n[[node],[node role name],[attributes list],[x,y,width,height],[node name],[states list][flow to node, flow from node]\n\n"); + printf("\n[[node],[node role name],[attributes list],[x,y,width,height],[node name],[states list][relations]\n\n"); } static void _print_atspi_states_legend() @@ -251,7 +248,7 @@ static char *_get_states(AtspiAccessible *node, int length_limit) state_type = g_array_index(states, AtspiStateType, i); char node_state_str[8]; - sprintf(node_state_str, "(%d)", state_type); + snprintf(node_state_str, 8, "(%d)", state_type); _combine_strings(&state_string, node_state_str); } @@ -289,32 +286,6 @@ static char *_get_attributes(AtspiAccessible *node, int length_limit) return result; } -static char *_get_object_in_relation(AtspiAccessible *source, AtspiRelationType search_type) -{ - if (source == NULL) - return ""; - - GArray *relations = atspi_accessible_get_relation_set(source, NULL); - - if (relations == NULL) - return ""; - - 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); - - if (type == search_type) { - ret = atspi_relation_get_target(relation, 0); - break; - } - } - - g_array_free(relations, TRUE); - - return ret ? atspi_accessible_get_unique_id(ret, NULL) : g_strdup(""); -} - static char *_get_info(AtspiAccessible *node, int length_limit) { if (!node) @@ -328,11 +299,10 @@ static char *_get_info(AtspiAccessible *node, int 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); + GArray *relations = atspi_accessible_get_relation_set(node, NULL); char result[SAFE_BUFFER_SIZE]; - int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s],[%s,%s,%s,%s],[%s],[%s],[%s,%s]]", + int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s],[%s,%s,%s,%s],[%s],[%s],[%s]]", unique_id, node_role_name, attributes, @@ -342,8 +312,7 @@ static char *_get_info(AtspiAccessible *node, int length_limit) box_size->height, node_name, states, - flows_to, - flows_from); + (relations && relations->len) ? "*" : ""); if (ret >= SAFE_BUFFER_SIZE) fprintf(stderr, "\n%s, %s %d: generated string is too long. Buffer overflow\n", __FILE__, __FUNCTION__, __LINE__); @@ -358,10 +327,9 @@ static char *_get_info(AtspiAccessible *node, int length_limit) free(box_size); } free(states); - free(flows_to); - free(flows_from); + g_array_free(relations, TRUE); - return _strdup(result); + return g_strdup(result); } static void _test_atspi_parent_child_relation(AtspiAccessible *obj, AtspiAccessible *parent_candidate, int parent_candidate_index) @@ -374,7 +342,7 @@ static void _test_atspi_parent_child_relation(AtspiAccessible *obj, AtspiAccessi char parent_status[NUMBER_WIDTH]; if (parent == NULL) - strcpy(parent_status, "_"); + strncpy(parent_status, "_", NUMBER_WIDTH); else snprintf(parent_status, NUMBER_WIDTH, "%d", parent_index); @@ -441,11 +409,105 @@ 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 _print_horizontal_line_in_relation_table() { + for (int i = 0; i < RELATION_TABLE_COLUMN_COUNT; i++) { + for (int j = 0; j < RELATION_COLUMN_WIDTH; j++) + printf("-"); + printf("+"); + } + printf("\n"); +} + +static void _print_legend_for_relation_table() { + char *table[] = {"OBJECT", "CONTROLLER_FOR", "CONTROLLED_BY", "FLOWS_TO", "FLOWS_FROM", "DESCRIBED_BY", "OTHER RELATION [ID]"}; + assert(ARRAY_SIZE(table) == RELATION_TABLE_COLUMN_COUNT); + for(int i = 0; i < RELATION_TABLE_COLUMN_COUNT; i++) + printf("%*s|", RELATION_COLUMN_WIDTH , table[i]); + printf("\n"); + _print_horizontal_line_in_relation_table(); +} + +static char *_get_unique_id_of_object_in_relation(AtspiRelation *relation) { + if (!relation) + return NULL; + + gint last_index = atspi_relation_get_n_targets(relation) - 1; + AtspiAccessible *target = atspi_relation_get_target(relation, last_index); + return atspi_accessible_get_unique_id(target, NULL); +} + +static void _print_relations_for_object(AtspiAccessible *node) { + GArray *relations = atspi_accessible_get_relation_set(node, NULL); + if (!relations) + return; + + if (!relations->len) { + g_array_free(relations, FALSE); + return; + } + + char **table = calloc(RELATION_TABLE_COLUMN_COUNT, sizeof(char *)); + if (!table) { + fprintf(stderr, "Calloc failed. Can't alloc memory for object relations string\n"); + return; + } + + table[0] = atspi_accessible_get_unique_id(node, 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); + int idx; + switch (type) { + case ATSPI_RELATION_CONTROLLER_FOR: idx = 1; break; + case ATSPI_RELATION_CONTROLLED_BY: idx = 2; break; + case ATSPI_RELATION_FLOWS_TO: idx = 3; break; + case ATSPI_RELATION_FLOWS_FROM: idx = 4; break; + case ATSPI_RELATION_DESCRIBED_BY: idx = 5; break; + default: idx = 0; + } + + if (idx > 0) + table[idx] = _get_unique_id_of_object_in_relation(relation); + else { + char buf[16]; + snprintf(buf, sizeof(buf), " [%d]", type); + _combine_strings(&table[RELATION_TABLE_COLUMN_COUNT - 1], buf); + } + } + + for (int i = 0; i < RELATION_TABLE_COLUMN_COUNT; i++) { + printf("%*s|", RELATION_COLUMN_WIDTH, table[i] ? table[i] : ""); + free(table[i]); + } + free(table); + + printf("\n"); + _print_horizontal_line_in_relation_table(); + g_array_free(relations, TRUE); +} + +static void _print_relations_for_objects_in_tree(AtspiAccessible *node) { + _print_relations_for_object(node); + + int count = atspi_accessible_get_child_count(node, NULL); + for (int i = 0; i < count; i++) { + AtspiAccessible *child = atspi_accessible_get_child_at_index(node, i, NULL); + if (child) + _print_relations_for_objects_in_tree(child); + } +} + +static void _print_relations_table(AtspiAccessible *node) { + _print_legend_for_relation_table(); + _print_relations_for_objects_in_tree(node); +} + static void _atspi_tree_traverse(const char *app_name, bool dump, bool check, bool first_match, int length_limit) { @@ -460,7 +522,7 @@ static void _atspi_tree_traverse(const char *app_name, bool dump, bool check, bo for (int i = 0; i < count; i++) { AtspiAccessible *child = atspi_accessible_get_child_at_index(desktop, i, NULL); if (child == NULL) { - fprintf(stderr, "\n%s, %s %d: Null child occured. Results may be misleading.\n", __FILE__, __FUNCTION__, __LINE__); + fprintf(stderr, "\n%s, %s %d: Null application occured. Results may be misleading.\n", __FILE__, __FUNCTION__, __LINE__); continue; } @@ -478,12 +540,15 @@ static void _atspi_tree_traverse(const char *app_name, bool dump, bool check, bo _test_atspi_parent_child_relation(child, desktop, i); _print_atspi_tree_verify_maybe_r(0, child, check, length_limit); + printf("\n"); + _print_relations_table(child); if (first_match) { free(name); break; - } else + } else { printf("\n"); + } free(name); } -- 2.7.4 From 73e22e1f4da152c9b77ecd2f5a0face5692c2a51 Mon Sep 17 00:00:00 2001 From: Pawel Kurowski Date: Mon, 17 Jul 2017 22:15:35 +0200 Subject: [PATCH 02/16] add attributes table to at_spi2_tool atributes table will be printed, when atributes string is too long add relations_found flag which tells if relation table legend should be printed Change-Id: I2a0b71f5e8b439881f5b83e9b7f1a17556f9e713 --- test/at_spi2_tool.c | 161 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 127 insertions(+), 34 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index 15adca5..08c2af5 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -20,7 +20,9 @@ #define CHECK 1 #define FIRST_MATCH 2 #define RELATION_TABLE_COLUMN_COUNT 7 -#define RELATION_COLUMN_WIDTH 20 +#define ATTRIBUTE_TABLE_COLUMN_COUNT 3 +#define RELATION_TABLE_COLUMN_WIDTH 20 +#define ATTRIBUTE_TABLE_BASE_COLUMN_WIDTH 20 #define VERSION "1.1" static unsigned indent_width = 2; @@ -260,7 +262,7 @@ static char *_get_states(AtspiAccessible *node, int length_limit) return state_string; } -static char *_get_attributes(AtspiAccessible *node, int length_limit) +static char *_get_attributes(AtspiAccessible *node, int length_limit, bool *attributes_are_too_long) { GHashTable *attributes = atspi_accessible_get_attributes(node, NULL); @@ -273,20 +275,24 @@ static char *_get_attributes(AtspiAccessible *node, int length_limit) 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, "\n_get_attributes: generated string is too long. Buffer overflow\n"); + char attributes_string[SAFE_BUFFER_SIZE]; + int ret = snprintf(attributes_string, SAFE_BUFFER_SIZE, "(%s=%s)", (char *)attr_key, (char *)attr_value); + if (ret >= SAFE_BUFFER_SIZE) + fprintf(stderr, "\n%s, %s %d: generated string is too long. Buffer overflow\n", __FILE__, __FUNCTION__, __LINE__); _combine_strings(&result, attributes_string); } g_hash_table_unref(attributes); - _truncate_string(result, length_limit); + int real_truncate_size = (length_limit < ATTR_WIDTH && length_limit > MINIMAL_MODULE_WIDTH) ? length_limit : ATTR_WIDTH; + if (result && attributes_are_too_long && strlen(result) > real_truncate_size) + *attributes_are_too_long = true; + + _truncate_string(result, real_truncate_size); return result; } -static char *_get_info(AtspiAccessible *node, int length_limit) +static char *_get_info(AtspiAccessible *node, int length_limit, bool *attributes_are_too_long, bool *app_has_relations) { if (!node) return NULL; @@ -295,11 +301,12 @@ static char *_get_info(AtspiAccessible *node, int length_limit) 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); + char *attributes = _get_attributes(node, length_limit, attributes_are_too_long); Box_Size *box_size = _get_box_size(node); char *states = _get_states(node, length_limit); GArray *relations = atspi_accessible_get_relation_set(node, NULL); + bool current_node_has_relations = (relations && relations->len); char result[SAFE_BUFFER_SIZE]; int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s],[%s,%s,%s,%s],[%s],[%s],[%s]]", @@ -312,11 +319,14 @@ static char *_get_info(AtspiAccessible *node, int length_limit) box_size->height, node_name, states, - (relations && relations->len) ? "*" : ""); + current_node_has_relations ? "*" : ""); if (ret >= SAFE_BUFFER_SIZE) fprintf(stderr, "\n%s, %s %d: generated string is too long. Buffer overflow\n", __FILE__, __FUNCTION__, __LINE__); + if (current_node_has_relations) + *app_has_relations = true; + free(node_name); free(node_role_name); free(unique_id); @@ -360,7 +370,8 @@ static void _test_atspi_parent_child_relation(AtspiAccessible *obj, AtspiAccessi printf("%-*s\t", CHECK_OUTPUT_WIDTH, output); } -static int _print_atspi_tree_verify_maybe_r(int indent_number, AtspiAccessible *object, bool check_integrity, int length_limit) +static int _print_atspi_tree_verify_maybe_r(int indent_number, AtspiAccessible *object, bool check_integrity, int length_limit, + bool *attributes_are_too_long, bool *app_has_relations) { char *indent = _multiply_string(' ', indent_number*indent_width); if (indent != NULL) { @@ -368,7 +379,7 @@ static int _print_atspi_tree_verify_maybe_r(int indent_number, AtspiAccessible * free(indent); } - char *node_info = _get_info(object, length_limit); + char *node_info = _get_info(object, length_limit, attributes_are_too_long, app_has_relations); if (node_info != NULL) { printf("%s\n", node_info); free(node_info); @@ -381,7 +392,7 @@ static int _print_atspi_tree_verify_maybe_r(int indent_number, AtspiAccessible * if (check_integrity) _test_atspi_parent_child_relation(child, object, i); - _print_atspi_tree_verify_maybe_r(indent_number + 1, child, check_integrity, length_limit); + _print_atspi_tree_verify_maybe_r(indent_number + 1, child, check_integrity, length_limit, attributes_are_too_long, app_has_relations); } } return 0; @@ -415,24 +426,15 @@ void _print_version() printf("AT-SPI2-CORE-UTIL v%s\n", VERSION); } -static void _print_horizontal_line_in_relation_table() { +static void _print_horizontal_line_in_relations_table() { for (int i = 0; i < RELATION_TABLE_COLUMN_COUNT; i++) { - for (int j = 0; j < RELATION_COLUMN_WIDTH; j++) + for (int j = 0; j < RELATION_TABLE_COLUMN_WIDTH; j++) printf("-"); printf("+"); } printf("\n"); } -static void _print_legend_for_relation_table() { - char *table[] = {"OBJECT", "CONTROLLER_FOR", "CONTROLLED_BY", "FLOWS_TO", "FLOWS_FROM", "DESCRIBED_BY", "OTHER RELATION [ID]"}; - assert(ARRAY_SIZE(table) == RELATION_TABLE_COLUMN_COUNT); - for(int i = 0; i < RELATION_TABLE_COLUMN_COUNT; i++) - printf("%*s|", RELATION_COLUMN_WIDTH , table[i]); - printf("\n"); - _print_horizontal_line_in_relation_table(); -} - static char *_get_unique_id_of_object_in_relation(AtspiRelation *relation) { if (!relation) return NULL; @@ -482,32 +484,116 @@ static void _print_relations_for_object(AtspiAccessible *node) { } for (int i = 0; i < RELATION_TABLE_COLUMN_COUNT; i++) { - printf("%*s|", RELATION_COLUMN_WIDTH, table[i] ? table[i] : ""); + printf("%*s|", RELATION_TABLE_COLUMN_WIDTH, table[i] ? table[i] : ""); free(table[i]); } free(table); printf("\n"); - _print_horizontal_line_in_relation_table(); + _print_horizontal_line_in_relations_table(); g_array_free(relations, TRUE); } -static void _print_relations_for_objects_in_tree(AtspiAccessible *node) { - _print_relations_for_object(node); +typedef void (*print_information_about_object_function)(AtspiAccessible *); + +static void _iterate_over_tree(print_information_about_object_function func, AtspiAccessible *node) { + func(node); int count = atspi_accessible_get_child_count(node, NULL); for (int i = 0; i < count; i++) { AtspiAccessible *child = atspi_accessible_get_child_at_index(node, i, NULL); if (child) - _print_relations_for_objects_in_tree(child); + _iterate_over_tree(func, child); } } +static void _print_relations_for_objects_in_tree(AtspiAccessible *node) { + _iterate_over_tree(_print_relations_for_object, node); +} + +static void _print_header_for_relation_table() { + char *table[] = {"OBJECT", "CONTROLLER_FOR", "CONTROLLED_BY", "FLOWS_TO", "FLOWS_FROM", "DESCRIBED_BY", "OTHER RELATION [ID]"}; + assert(ARRAY_SIZE(table) == RELATION_TABLE_COLUMN_COUNT); + + _print_horizontal_line_in_relations_table(); + + for (int i = 0; i < RELATION_TABLE_COLUMN_COUNT; i++) + printf("%*s|", RELATION_TABLE_COLUMN_WIDTH , table[i]); + + printf("\n"); + _print_horizontal_line_in_relations_table(); +} + static void _print_relations_table(AtspiAccessible *node) { - _print_legend_for_relation_table(); + printf("\nRELATIONS TABLE\n"); + _print_header_for_relation_table(); _print_relations_for_objects_in_tree(node); } +static void _print_horizontal_line_in_attributes_table() { + int size_factor = 1; + for (int i = 0; i < ATTRIBUTE_TABLE_COLUMN_COUNT; i++) { + if (i == ATTRIBUTE_TABLE_COLUMN_COUNT - 1) + size_factor = 4; + for (int j = 0; j < ATTRIBUTE_TABLE_BASE_COLUMN_WIDTH * size_factor; j++) + printf("-"); + printf("+"); + } + printf("\n"); +} + +static void _print_attributes_for_object(AtspiAccessible *node) { + GHashTable *attributes = atspi_accessible_get_attributes(node, NULL); + + if (!attributes) + return; + + char *unique_id = atspi_accessible_get_unique_id(node, NULL); + GHashTableIter attributes_iter; + gpointer attr_key; + gpointer attr_value; + + g_hash_table_iter_init (&attributes_iter, attributes); + while (g_hash_table_iter_next (&attributes_iter, &attr_key, &attr_value)) { + printf("%*s|", ATTRIBUTE_TABLE_BASE_COLUMN_WIDTH, unique_id ? unique_id : ""); + printf("%*s|", ATTRIBUTE_TABLE_BASE_COLUMN_WIDTH, attr_key ? (char *) attr_key : ""); + printf("%*s|\n", ATTRIBUTE_TABLE_BASE_COLUMN_WIDTH * 4, attr_value ? (char *) attr_value : ""); + } + + if (g_hash_table_size (attributes)) + _print_horizontal_line_in_attributes_table(); + + g_hash_table_unref(attributes); + free(unique_id); +} + +static void _print_attributes_for_objects_in_tree(AtspiAccessible *node) { + _iterate_over_tree(_print_attributes_for_object, node); +} + +static void _print_header_for_attributes_table() { + char *table[] = {"OBJECT", "ATTRIBUTE KEY", "ATTRIBUTE VALUE"}; + assert(ARRAY_SIZE(table) == ATTRIBUTE_TABLE_COLUMN_COUNT); + + _print_horizontal_line_in_attributes_table(); + + int size_factor = 1; + for (int i = 0; i < ATTRIBUTE_TABLE_COLUMN_COUNT; i++) { + if (i == ATTRIBUTE_TABLE_COLUMN_COUNT - 1) + size_factor = 4; + printf("%*s|", ATTRIBUTE_TABLE_BASE_COLUMN_WIDTH * size_factor , table[i]); + } + + printf("\n"); + _print_horizontal_line_in_attributes_table(); +} + +static void _print_attributes_table(AtspiAccessible *node) { + printf("\nATTRIBUTES TABLE\n"); + _print_header_for_attributes_table(); + _print_attributes_for_objects_in_tree(node); +} + static void _atspi_tree_traverse(const char *app_name, bool dump, bool check, bool first_match, int length_limit) { @@ -519,6 +605,7 @@ static void _atspi_tree_traverse(const char *app_name, bool dump, bool check, bo 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) { @@ -527,6 +614,8 @@ static void _atspi_tree_traverse(const char *app_name, bool dump, bool check, bo } char *name = atspi_accessible_get_name(child, NULL); + bool attributes_are_too_long = false; + bool app_has_relations = false; if (!dump && !check) printf("%s\n", name); @@ -539,9 +628,13 @@ static void _atspi_tree_traverse(const char *app_name, bool dump, bool check, bo if (check) _test_atspi_parent_child_relation(child, desktop, i); - _print_atspi_tree_verify_maybe_r(0, child, check, length_limit); - printf("\n"); - _print_relations_table(child); + _print_atspi_tree_verify_maybe_r(0, child, check, length_limit, &attributes_are_too_long, &app_has_relations); + + if (app_has_relations) + _print_relations_table(child); + + if (attributes_are_too_long) + _print_attributes_table(child); if (first_match) { free(name); @@ -647,7 +740,7 @@ static void _run_command(int argc, char *argv[]) case 'a': enable_at_spi_client = TRUE; - if(optarg[0] == 'f' || optarg[0] == '0') + if (optarg[0] == 'f' || optarg[0] == '0') enable_at_spi_client = FALSE; _at_spi_client_enable(enable_at_spi_client); -- 2.7.4 From 2c0f9a891f49d36cb5d133dd0f54d96e77283cf2 Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Wed, 19 Jul 2017 15:15:28 +0900 Subject: [PATCH 03/16] bus: follow D-bus policy Tizen D-bus policy does not support Smack rule. The following patch set of D-bus probably affects dbus-daemon which is used for accessibility. https://review.tizen.org/gerrit/#/c/133270/ It was not possilbe to launch dbus-daemon with following error message. org.a11y.Bus[2457]: Failed to start message bus: Attribute "smack" is invalid on element in this context org.a11y.Bus[2457]: Failed to launch bus: Bus exited with code 1 Change-Id: I67435b1a27f91193348d1e699805b6d09be8fddc --- bus/accessibility.conf.in | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/bus/accessibility.conf.in b/bus/accessibility.conf.in index 77f12f8..9336ad7 100644 --- a/bus/accessibility.conf.in +++ b/bus/accessibility.conf.in @@ -8,28 +8,11 @@ unix:tmpdir=/tmp - owner - - - - - - - + - - - - - - - - - - -- 2.7.4 From 87ea2e308098bb8fb316fc5fc7fd39141dfbc51d Mon Sep 17 00:00:00 2001 From: Mariusz Wachowicz Date: Thu, 10 Aug 2017 11:29:48 +0200 Subject: [PATCH 04/16] move ref_accessible function to public scope this function is needed outside at-spi library (other projects, e.g. universal-switch), to get AtspiAccessible object after it has been received as application name and path name Change-Id: I51e72af3f191d4a14174cd0b4819522154e3e1ba --- atspi/atspi-misc.c | 10 +++++----- atspi/atspi-misc.h | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c index 193257b..02eab8c 100644 --- a/atspi/atspi-misc.c +++ b/atspi/atspi-misc.c @@ -260,7 +260,7 @@ get_application (const char *bus_name) return app; } -static AtspiAccessible * +AtspiAccessible * ref_accessible (const char *app_name, const char *path) { AtspiApplication *app; @@ -1149,11 +1149,12 @@ out: process_deferred_messages (); if (dbus_error_is_set (&err)) { - /* TODO: Set gerror */ + g_set_error_literal(error, ATSPI_ERROR, ATSPI_ERROR_IPC, err.message); dbus_error_free (&err); + if (reply) + dbus_message_unref(reply); } - - if (reply && dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) + else if (reply && dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { const char *err_str = NULL; dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &err_str, DBUS_TYPE_INVALID); @@ -1162,7 +1163,6 @@ out: dbus_message_unref (reply); return NULL; } - return reply; } diff --git a/atspi/atspi-misc.h b/atspi/atspi-misc.h index f13596f..e39d7b8 100644 --- a/atspi/atspi-misc.h +++ b/atspi/atspi-misc.h @@ -47,6 +47,9 @@ void atspi_set_main_context (GMainContext *cnx); gchar * atspi_role_get_name (AtspiRole role); + +AtspiAccessible *ref_accessible(const char *app_name, const char *path); + G_END_DECLS #endif /* _ATSPI_MISC_H_ */ -- 2.7.4 From 9dc6aaf0f801e52d145783e15125148efec16bae Mon Sep 17 00:00:00 2001 From: Bowon Ryu Date: Fri, 11 Aug 2017 16:10:56 +0900 Subject: [PATCH 05/16] at_spi2_tool: Apply ASLR to executable files. Change-Id: I86b9dd51723548d1b888eed7847668ca9e318110 Signed-off-by: Bowon Ryu --- test/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Makefile.am b/test/Makefile.am index 828f126..bb9acb9 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -3,8 +3,8 @@ 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 = $(GIO_CFLAGS) $(GLIB_CFLAGS) --std=c99 -Wall $(GOBJ_LIBS) $(DBUS_CFLAGS) -at_spi2_tool_LDFLAGS = $(GIO_LIBS) +at_spi2_tool_CFLAGS = $(GIO_CFLAGS) $(GLIB_CFLAGS) --std=c99 -Wall -fPIE $(GOBJ_LIBS) $(DBUS_CFLAGS) +at_spi2_tool_LDFLAGS = $(GIO_LIBS) -pie noinst_PROGRAMS = memory -- 2.7.4 From adf4836bec89de9e7a93a6988c7ae6ea7870936c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pawe=C5=82=20Stawicki?= Date: Mon, 5 Jun 2017 17:40:47 +0200 Subject: [PATCH 06/16] at-spi-bus-launcher: launch universal-switch Change-Id: I16bff1e30b2c72c812be767f1b21f88a65ee1787 --- bus/at-spi-bus-launcher.c | 197 +++++++++++++++++++++++++++++----------------- 1 file changed, 125 insertions(+), 72 deletions(-) diff --git a/bus/at-spi-bus-launcher.c b/bus/at-spi-bus-launcher.c index bb6f9f9..7948d1b 100644 --- a/bus/at-spi-bus-launcher.c +++ b/bus/at-spi-bus-launcher.c @@ -35,7 +35,11 @@ #include #endif +//TODO: move to vconf/vconf-internal-setting-keys.h? +#define VCONFKEY_SETAPPL_ACCESSIBILITY_UNIVERSAL_SWITCH "db/setting/accessibility/universal-switch" + #define APP_CONTROL_OPERATION_SCREEN_READ "http://tizen.org/appcontrol/operation/read_screen" +#define APP_CONTROL_OPERATION_UNIVERSAL_SWITCH "http://tizen.org/appcontrol/operation/universal_switch" #include #include @@ -64,7 +68,7 @@ FILE *log_file; #define LOGD(arg...) do {if (log_file) {fprintf(log_file, ##arg);fprintf(log_file, "\n"); fflush(log_file);}} while(0) #endif -static gboolean _launch_screen_reader_repeat_until_success(gpointer user_data); +static gboolean _launch_process_repeat_until_success(gpointer user_data); typedef enum { A11Y_BUS_STATE_IDLE = 0, @@ -74,6 +78,14 @@ typedef enum { } A11yBusState; typedef struct { + const char * name; + const char * app_control_operation; + const char * vconf_key; + int launch_repeats; + int pid; +} A11yBusClient; + +typedef struct { GMainLoop *loop; gboolean launch_immediately; gboolean a11y_enabled; @@ -83,9 +95,8 @@ typedef struct { GSettings *a11y_schema; GSettings *interface_schema; - int launch_screen_reader_repeats; - gboolean screen_reader_needed; - int pid; + A11yBusClient screen_reader; + A11yBusClient universal_switch; A11yBusState state; @@ -662,24 +673,43 @@ gsettings_key_changed (GSettings *gsettings, const gchar *key, void *user_data) } static int -_screen_reader_dead_tracker (int pid, void *data) +_process_dead_tracker (int pid, void *data) { A11yBusLauncher *app = data; - if (app->pid > 0 && pid == app->pid) + if (app->screen_reader.pid > 0 && pid == app->screen_reader.pid) { LOGE("screen reader is dead, pid: %d, restarting", pid); - app->pid = 0; - g_timeout_add_seconds (2, _launch_screen_reader_repeat_until_success, app); + app->screen_reader.pid = 0; + g_timeout_add_seconds (2, _launch_process_repeat_until_success, &app->screen_reader); + } + + if (app->universal_switch.pid > 0 && pid == app->universal_switch.pid) + { + LOGE("universal switch is dead, pid: %d, restarting", pid); + app->universal_switch.pid = 0; + g_timeout_add_seconds (2, _launch_process_repeat_until_success, &app->universal_switch); } return 0; } +static void +_register_process_dead_tracker () +{ + if(_global_app->screen_reader.pid > 0 || _global_app->universal_switch.pid > 0) { + LOGD("registering process dead tracker"); + aul_listen_app_dead_signal(_process_dead_tracker, _global_app); + } else { + LOGD("unregistering process dead tracker"); + aul_listen_app_dead_signal(NULL, NULL); + } +} + + static gboolean -_launch_screen_reader(gpointer user_data, gboolean by_vconf_change) +_launch_client(A11yBusClient *client, gboolean by_vconf_change) { - A11yBusLauncher *bl = user_data; - LOGD("Launching screen reader"); + LOGD("Launching %s", client->name); bundle *kb = NULL; gboolean ret = FALSE; @@ -700,120 +730,147 @@ _launch_screen_reader(gpointer user_data, gboolean by_vconf_change) } } - int operation_error = appsvc_set_operation(kb, APP_CONTROL_OPERATION_SCREEN_READ); + int operation_error = appsvc_set_operation(kb, client->app_control_operation); LOGD("appsvc_set_operation: %i", operation_error); - bl->pid = appsvc_run_service(kb, 0, NULL, NULL); + client->pid = appsvc_run_service(kb, 0, NULL, NULL); - if (bl->pid > 0) + if (client->pid > 0) { - LOGD("Screen reader launched with pid: %i", bl->pid); - LOGD("registering screen reader dead tracker"); - aul_listen_app_dead_signal(_screen_reader_dead_tracker, bl); + LOGD("Process launched with pid: %i", client->pid); + _register_process_dead_tracker(); ret = TRUE; } else { - LOGD("Can't start screen-reader - error code: %i", bl->pid); + LOGD("Can't start %s - error code: %i", client->name, client->pid); } - bundle_free(kb); return ret; } static gboolean -_launch_screen_reader_repeat_until_success(gpointer user_data) { - A11yBusLauncher *bl = user_data; +_launch_process_repeat_until_success(gpointer user_data) { + A11yBusClient *client = user_data; - if (bl->launch_screen_reader_repeats > 100 || bl->pid > 0) + if (client->launch_repeats > 100 || client->pid > 0) { //do not try anymore return FALSE; } - gboolean ret = _launch_screen_reader(user_data, FALSE); + gboolean ret = _launch_client(client, FALSE); if (ret) { //we managed to - bl->launch_screen_reader_repeats = 0; + client->launch_repeats = 0; return FALSE; } + client->launch_repeats++; //try again return TRUE; } static gboolean -_terminate_screen_reader(A11yBusLauncher *bl) +_terminate_process(int pid) { - LOGD("Terminating screen reader"); int ret; int ret_aul; - if (bl->pid <= 0) + if (pid <= 0) return FALSE; - - LOGD("unregistering screen reader dead tracker"); - aul_listen_app_dead_signal(NULL, NULL); - - int status = aul_app_get_status_bypid(bl->pid); + int status = aul_app_get_status_bypid(pid); if (status < 0) { - LOGD("App with pid %d already terminated", bl->pid); - bl->pid = 0; + LOGD("App with pid %d already terminated", pid); return TRUE; } - LOGD("terminate process with pid %d", bl->pid); - ret_aul = aul_terminate_pid(bl->pid); + LOGD("terminate process with pid %d", pid); + ret_aul = aul_terminate_pid(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); + ret = kill(pid, SIGTERM); if (!ret) { - bl->pid = 0; return TRUE; } - LOGD("Unable to terminate process: %d with api or signal.", bl->pid); + LOGD("Unable to terminate process: %d with api or signal.", pid); return FALSE; } -void screen_reader_cb(keynode_t *node, void *user_data) +static gboolean +_terminate_client(A11yBusClient *client) { - A11yBusLauncher *bl = user_data; - int ret; + LOGD("Terminating %s", client->name); + int pid = client->pid; + client->pid = 0; + _register_process_dead_tracker(); + gboolean ret = _terminate_process(pid); + return ret; +} - ret = vconf_keynode_get_bool(node); - LOGD("vconf_keynode_get_bool(node): %i", ret); - if (ret < 0) +void vconf_client_cb(keynode_t *node, void *user_data) +{ + A11yBusClient *client = user_data; + int client_needed = vconf_keynode_get_bool(node); + LOGD("vconf_keynode_get_bool(node): %i", client_needed); + if (client_needed < 0) return; //check if process really exists (e.g didn't crash) - if (bl->pid > 0) + if (client->pid > 0) { - int err = kill(bl->pid,0); + int err = kill(client->pid,0); //process doesn't exist if (err == ESRCH) - bl->pid = 0; + client->pid = 0; } - bl->screen_reader_needed = ret; - LOGD("bl->screen_reader_needed: %i, bl->pid: %i", ret, bl->pid); - if (!bl->screen_reader_needed && (bl->pid > 0)) - _terminate_screen_reader(bl); - else if (bl->screen_reader_needed && (bl->pid <= 0)) - _launch_screen_reader(bl, TRUE); + LOGD("client_needed: %i, client->pid: %i", client_needed, client->pid); + if (!client_needed && (client->pid > 0)) + _terminate_client(client); + else if (client_needed && (client->pid <= 0)) + _launch_client(client, TRUE); +} + + +static gboolean register_client(A11yBusClient *client) +{ + gboolean client_needed = FALSE; + + if(!client->vconf_key) { + LOGE("Vconf_key missing for client: %s \n", client->vconf_key); + return FALSE; + } + + int ret = vconf_get_bool(client->vconf_key, &client_needed); + if (ret != 0) + { + LOGD("Could not read %s key value.\n", client->vconf_key); + return FALSE; + } + ret = vconf_notify_key_changed(client->vconf_key, vconf_client_cb, client); + if(ret != 0) + { + LOGD("Could not add information level callback\n"); + return FALSE; + } + + if (client_needed) + g_timeout_add_seconds(2,_launch_process_repeat_until_success, client); + return TRUE; } int @@ -825,7 +882,6 @@ main (int argc, #endif LOGD("Starting atspi bus launcher"); - int name_owner_id; gboolean a11y_set = FALSE; gboolean screen_reader_set = FALSE; gint i; @@ -838,9 +894,16 @@ main (int argc, _global_app = g_slice_new0 (A11yBusLauncher); _global_app->loop = g_main_loop_new (NULL, FALSE); - _global_app->launch_screen_reader_repeats = 0; _global_app->client_watcher_id = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + _global_app->screen_reader.name = "screen-reader"; + _global_app->screen_reader.app_control_operation = APP_CONTROL_OPERATION_SCREEN_READ; + _global_app->screen_reader.vconf_key = VCONFKEY_SETAPPL_ACCESSIBILITY_TTS; + + _global_app->universal_switch.name = "universal-switch"; + _global_app->universal_switch.app_control_operation = APP_CONTROL_OPERATION_UNIVERSAL_SWITCH; + _global_app->universal_switch.vconf_key = VCONFKEY_SETAPPL_ACCESSIBILITY_UNIVERSAL_SWITCH; + for (i = 1; i < argc; i++) { if (!strcmp (argv[i], "--launch-immediately")) @@ -886,7 +949,7 @@ main (int argc, introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); g_assert (introspection_data != NULL); - name_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, + g_bus_own_name (G_BUS_TYPE_SESSION, "org.a11y.Bus", G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, on_bus_acquired, @@ -895,20 +958,10 @@ main (int argc, _global_app, NULL); - int ret = vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &_global_app->screen_reader_needed); - if (ret != 0) - { - LOGD("Could not read VCONFKEY_SETAPPL_ACCESSIBILITY_TTS key value.\n"); - return FALSE; - } - ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, screen_reader_cb, _global_app); - if(ret != 0) - { - LOGD("Could not add information level callback\n"); - return FALSE; - } - if (_global_app->screen_reader_needed) - g_timeout_add_seconds(2,_launch_screen_reader_repeat_until_success, _global_app); + if(!register_client(&_global_app->screen_reader)) + return FALSE; + if(!register_client(&_global_app->universal_switch)) + return FALSE; g_main_loop_run (_global_app->loop); -- 2.7.4 From f0a290a4980997257594fd44f0ba4b71689edb7b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pawe=C5=82=20Stawicki?= Date: Thu, 7 Sep 2017 12:37:38 +0200 Subject: [PATCH 07/16] bugfix: at-spi-bus-launcher terminates when unviersal-switch vconf key not defined Change-Id: I4a891f300aeb4261938a9e5dbdf4cdf5749c7d05 --- bus/at-spi-bus-launcher.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bus/at-spi-bus-launcher.c b/bus/at-spi-bus-launcher.c index 7948d1b..d180a15 100644 --- a/bus/at-spi-bus-launcher.c +++ b/bus/at-spi-bus-launcher.c @@ -958,10 +958,8 @@ main (int argc, _global_app, NULL); - if(!register_client(&_global_app->screen_reader)) - return FALSE; - if(!register_client(&_global_app->universal_switch)) - return FALSE; + register_client (&_global_app->screen_reader); + register_client (&_global_app->universal_switch); g_main_loop_run (_global_app->loop); -- 2.7.4 From 5e6b82550dd2635f9a18eb82ab72fced8e3e3fcc Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Tue, 12 Sep 2017 20:37:56 +0900 Subject: [PATCH 08/16] check reply message of "GetNeighbor" The dbus_message_iter_init makes a crash if a message(reply) is NULL. The message(reply) is NULL with following error message. error message: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken. Change-Id: I64c9f468f26299af86ee52dff3714b03112d49e3 --- atspi/atspi-accessible.c | 1 + 1 file changed, 1 insertion(+) diff --git a/atspi/atspi-accessible.c b/atspi/atspi-accessible.c index 40053f2..752001c 100644 --- a/atspi/atspi-accessible.c +++ b/atspi/atspi-accessible.c @@ -617,6 +617,7 @@ atspi_accessible_get_neighbor (AtspiAccessible *root, const char *path = are_objects_on_the_same_bus(root, start) ? root_path : ""; DBusMessage *reply = _atspi_dbus_call_partial (start, atspi_interface_accessible, "GetNeighbor", error, "sii", path, (int)direction, (int)search_mode); + _ATSPI_DBUS_CHECK_SIG (reply, "(so)y", error, NULL); dbus_message_iter_init (reply, &iter); AtspiAccessible *ret = _atspi_dbus_return_accessible_from_iter (&iter); -- 2.7.4 From 616b87d69d8938f13ded9c6298c9f8b5256d617a Mon Sep 17 00:00:00 2001 From: Radoslaw Cybulski Date: Tue, 12 Sep 2017 14:45:33 +0200 Subject: [PATCH 09/16] Fix crash, when dbus call in GetNeighbor fails Failed dbus call would cause a crash by trying to get an iterator to a reply message, which is null. This patch cleans up _atspi_dbus_call_partial function to always return NULL on failure and fixes NULL reply handling in atspi_accessible_get_neighbor and atspi_accessible_get_navigable_at_point functions. Change-Id: Ie158a79f8f1452c9a5685137c9b42104563dc717 --- atspi/atspi-accessible.c | 10 ++++++++-- atspi/atspi-misc.c | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/atspi/atspi-accessible.c b/atspi/atspi-accessible.c index 752001c..7e889e9 100644 --- a/atspi/atspi-accessible.c +++ b/atspi/atspi-accessible.c @@ -346,7 +346,12 @@ atspi_accessible_get_navigable_at_point (AtspiAccessible *root, g_return_val_if_fail (root != NULL, NULL); do { reply = _atspi_dbus_call_partial (root, atspi_interface_accessible, "GetNavigableAtPoint", error, "iiu", d_x, d_y, d_ctype); - + // call failed, error is set, so we bail out + if (!reply) { + if (deputy) g_object_unref(deputy); + if (return_value) g_object_unref(return_value); + return NULL; + } _ATSPI_DBUS_CHECK_SIG (reply, "(so)y(so)", NULL, NULL); dbus_message_iter_init (reply, &iter); @@ -616,6 +621,8 @@ atspi_accessible_get_neighbor (AtspiAccessible *root, while(1) { const char *path = are_objects_on_the_same_bus(root, start) ? root_path : ""; DBusMessage *reply = _atspi_dbus_call_partial (start, atspi_interface_accessible, "GetNeighbor", error, "sii", path, (int)direction, (int)search_mode); + // call failed, error is set, so we bail out + if (!reply) break; _ATSPI_DBUS_CHECK_SIG (reply, "(so)y", error, NULL); dbus_message_iter_init (reply, &iter); @@ -684,7 +691,6 @@ atspi_accessible_get_neighbor (AtspiAccessible *root, // nothing found g_object_unref(start); - return_value = NULL; break; } while(!g_queue_is_empty(children_root_stack)) diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c index 02eab8c..5895935 100644 --- a/atspi/atspi-misc.c +++ b/atspi/atspi-misc.c @@ -1153,6 +1153,7 @@ out: dbus_error_free (&err); if (reply) dbus_message_unref(reply); + return NULL; } else if (reply && dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { -- 2.7.4 From c9981714ce932e989ab9e5bc0cb5011ff67eaeb3 Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Tue, 19 Sep 2017 19:59:53 +0900 Subject: [PATCH 10/16] Add atspi_accessible_get_default_label_info It is not possible to support default label feature using current at-spi2-core APIs without much of IPC. The following would be difficult case to cover. (top of accessible tree) - (bottom side) PageTab1 - Panel1 - PageTab2 - Panel2 - PageTab3 - Panel3(currently showing) Application could make as below: PageTab1 - Panel1 - PageTab3 - Panel3 - PageTab2 - Panel2(currently showing) or following tree would normally be possilbe: PageTab1 - Panel1 - PageTab2 - Panel2(currently showing) There are much of complicated case over there. So we are handling the default label object stack on toolkit(Elementary) side. The atspi_accessible_get_default_label_info returns default label information to be used screen-reader side. This is not stable. And this depends on toolkit side UI definition. The candidate of default label object could be changed by UI definition. AtspiAccessibleDefaultLabelInfo *dli; dli = atspi_accessible_get_default_label_info(root, &error); You have to free alocated resource as below, if it is not necessary any more. g_object_unref(dli->obj); free(dli); Change-Id: I444906e6d020ea6fe2536a73473e0e796a015d05 --- atspi/atspi-accessible.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ atspi/atspi-accessible.h | 8 ++++++++ atspi/atspi-types.h | 1 + 3 files changed, 57 insertions(+) diff --git a/atspi/atspi-accessible.c b/atspi/atspi-accessible.c index 7e889e9..6612a21 100644 --- a/atspi/atspi-accessible.c +++ b/atspi/atspi-accessible.c @@ -565,6 +565,54 @@ atspi_accessible_get_reading_material (AtspiAccessible *obj, GError **error) return reading_material; } +/** + * atspi_accessible_get_default_label_info: + * @obj: a pointer to the #AtspiAccessible object would be window. + * + * Gets default label information + * + * Returns: default label information to be used screen-reader side. + * This is not stable. And this depends on toolkit side UI definition. + * The candidate of default label object could be changed by UI definition. + * You have to handle all alocated memory as below on screen-reader side. + * + * AtspiAccessibleDefaultLabelInfo *dli + * g_object_unref(dli->obj); + * free(dli); + **/ +AtspiAccessibleDefaultLabelInfo * +atspi_accessible_get_default_label_info (AtspiAccessible *obj, GError **error) +{ + AtspiAccessibleDefaultLabelInfo *default_label_info = NULL; + AtspiAccessible *default_label_object; + dbus_uint32_t role; + DBusMessage *reply; + DBusMessageIter iter; + + g_return_val_if_fail (obj != NULL, NULL); + + reply = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetDefaultLabelInfo", error, ""); + + _ATSPI_DBUS_CHECK_SIG (reply, "(so)u", NULL, NULL); + + default_label_info = calloc(1, sizeof(AtspiAccessibleDefaultLabelInfo)); + if (!default_label_info) + { + return default_label_info; + } + + dbus_message_iter_init (reply, &iter); + + default_label_object = _atspi_dbus_return_accessible_from_iter (&iter); + default_label_info->obj = default_label_object; + + dbus_message_iter_get_basic (&iter, &role); + default_label_info->role = role; + dbus_message_iter_next (&iter); + + return default_label_info; +} + static unsigned char are_objects_on_the_same_bus(AtspiAccessible *obj1, AtspiAccessible *obj2) { const char *bus_name_1 = obj1->parent.app->bus_name; diff --git a/atspi/atspi-accessible.h b/atspi/atspi-accessible.h index 0b5152b..9efc168 100644 --- a/atspi/atspi-accessible.h +++ b/atspi/atspi-accessible.h @@ -45,6 +45,12 @@ G_BEGIN_DECLS typedef struct _AtspiAccessiblePrivate AtspiAccessiblePrivate; +struct _AtspiAccessibleDefaultLabelInfo +{ + AtspiAccessible *obj; + AtspiRole role; +}; + struct _AtspiAccessibleReadingMaterial { AtspiAccessible *parent; @@ -115,6 +121,8 @@ AtspiAccessible *atspi_accessible_get_neighbor (AtspiAccessible *root, AtspiAcce AtspiAccessibleReadingMaterial *atspi_accessible_get_reading_material (AtspiAccessible *obj, GError **error); +AtspiAccessibleDefaultLabelInfo *atspi_accessible_get_default_label_info (AtspiAccessible *obj, GError **error); + AtspiAccessible * atspi_accessible_get_parent (AtspiAccessible *obj, GError **error); gint atspi_accessible_get_child_count (AtspiAccessible *obj, GError **error); diff --git a/atspi/atspi-types.h b/atspi/atspi-types.h index 45b815c..d09a972 100644 --- a/atspi/atspi-types.h +++ b/atspi/atspi-types.h @@ -44,6 +44,7 @@ typedef struct _AtspiTableCell AtspiTableCell; typedef struct _AtspiText AtspiText; typedef struct _AtspiValue AtspiValue; typedef struct _AtspiAccessibleReadingMaterial AtspiAccessibleReadingMaterial; +typedef struct _AtspiAccessibleDefaultLabelInfo AtspiAccessibleDefaultLabelInfo; typedef guint AtspiControllerEventMask; -- 2.7.4 From 819f38462c452c3cd7d7fb08adae1f4e018a9c01 Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Tue, 17 Oct 2017 21:02:32 +0900 Subject: [PATCH 11/16] test: enhance accessible tree information Enhance node information using eo address expression Change-Id: I02e057013812073e7b7484cf3d87516f6a9d9053 --- test/at_spi2_tool.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index 08c2af5..c391003 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -6,6 +6,7 @@ #include #include #include +#include #define ERROR_STATE -1 #define SAFE_BUFFER_SIZE 2048 @@ -300,6 +301,9 @@ static char *_get_info(AtspiAccessible *node, int length_limit, bool *attributes 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 *path = atspi_accessible_get_path(node, NULL); + unsigned long long eo_ptr = 0; + sscanf(path, "%llu", &eo_ptr); char *attributes = _get_attributes(node, length_limit, attributes_are_too_long); Box_Size *box_size = _get_box_size(node); @@ -309,8 +313,8 @@ static char *_get_info(AtspiAccessible *node, int length_limit, bool *attributes bool current_node_has_relations = (relations && relations->len); char result[SAFE_BUFFER_SIZE]; - int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s],[%s],[%s],[%s,%s,%s,%s],[%s],[%s],[%s]]", - unique_id, + int ret = snprintf(result, SAFE_BUFFER_SIZE, "[[%s(%p)],[%s],[%s],[%s,%s,%s,%s],[%s],[%s],[%s]]", + unique_id, (uintptr_t)eo_ptr, node_role_name, attributes, box_size->x, @@ -330,6 +334,7 @@ static char *_get_info(AtspiAccessible *node, int length_limit, bool *attributes free(node_name); free(node_role_name); free(unique_id); + free(path); free(attributes); if (box_size) { free(box_size->width); -- 2.7.4 From a97cc93731bec6122888c929726a0bdb864be0bb Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Wed, 18 Oct 2017 17:23:17 +0900 Subject: [PATCH 12/16] test : enhance accessible state information Change-Id: I112a34525f66e204aa5dbab51ad0faadbf25d3da --- test/at_spi2_tool.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index 08c2af5..cdbc141 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -249,8 +249,11 @@ static char *_get_states(AtspiAccessible *node, int length_limit) for (int i = 0; i < states->len; i++) { state_type = g_array_index(states, AtspiStateType, i); - char node_state_str[8]; - snprintf(node_state_str, 8, "(%d)", state_type); + char node_state_str[27] = ""; + strncat(node_state_str, "(", sizeof(node_state_str) - strlen(node_state_str) - 1); + strncat(node_state_str, atspi_state_names[state_type], sizeof(node_state_str) - strlen(node_state_str) - 1); + strncat(node_state_str, ")", sizeof(node_state_str) - strlen(node_state_str) - 1); + _combine_strings(&state_string, node_state_str); } -- 2.7.4 From b5105db0d1f719f5b0fd45d0fd02e9ca1b8b9b51 Mon Sep 17 00:00:00 2001 From: Radoslaw Cybulski Date: Tue, 6 Mar 2018 18:24:49 +0100 Subject: [PATCH 13/16] Fixes glib runtime warnings on freeing empty arrays Change-Id: Iba679a3cfbcdcdfd252c291d5f8bcf433c4d7198 --- test/at_spi2_tool.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index 81bf021..c0daae4 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -258,7 +258,8 @@ static char *_get_states(AtspiAccessible *node, int length_limit) _combine_strings(&state_string, node_state_str); } - g_array_free(states, 0); + if (states) + g_array_free(states, 0); g_object_unref(node_state_set); _truncate_string(state_string, length_limit); @@ -345,7 +346,8 @@ static char *_get_info(AtspiAccessible *node, int length_limit, bool *attributes free(box_size); } free(states); - g_array_free(relations, TRUE); + if (relations) + g_array_free(relations, TRUE); return g_strdup(result); } @@ -499,7 +501,8 @@ static void _print_relations_for_object(AtspiAccessible *node) { printf("\n"); _print_horizontal_line_in_relations_table(); - g_array_free(relations, TRUE); + if (relations) + g_array_free(relations, TRUE); } typedef void (*print_information_about_object_function)(AtspiAccessible *); -- 2.7.4 From 3627a21a62fe61592d92968e3dc67a78fde63bf0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pawe=C5=82=20Stawicki?= Date: Thu, 15 Mar 2018 18:21:04 +0100 Subject: [PATCH 14/16] [prevent][109656] Fix for resource leakage Change-Id: Ic2abd2a7c7eafd530d147711d8881fb87788e140 --- test/memory.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/memory.c b/test/memory.c index df5e0a1..2db9871 100644 --- a/test/memory.c +++ b/test/memory.c @@ -13,18 +13,17 @@ basic (AtspiAccessible *obj) gint count; gint i; AtspiAccessible *accessible; - GError *error = NULL; - str = atspi_accessible_get_name (obj, &error); + str = atspi_accessible_get_name (obj, NULL); if (str) g_free (str); accessible = atspi_accessible_get_parent (obj, NULL); if (accessible) g_object_unref (accessible); - count = atspi_accessible_get_child_count (obj, &error); + count = atspi_accessible_get_child_count (obj, NULL); for (i = 0; i < count; i++) { - accessible = atspi_accessible_get_child_at_index (obj, i, &error); + accessible = atspi_accessible_get_child_at_index (obj, i, NULL); if (accessible) g_object_unref (accessible); } -- 2.7.4 From 0e73668f07348218afa69f07adbf848908eaf4a4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pawe=C5=82=20Stawicki?= Date: Thu, 15 Mar 2018 19:17:23 +0100 Subject: [PATCH 15/16] [prevent][36724] Fix for resource leakage Change-Id: Ib0407cf3cf1de81e7c78c9d969daa067e0af428a --- test/at_spi2_tool.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index c0daae4..d7b91d5 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -241,7 +241,10 @@ 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; + if (!states) { + g_clear_object(&node_state_set); + return NULL; + } g_array_sort(states, _int_sort_function); AtspiStateType state_type; @@ -258,9 +261,8 @@ static char *_get_states(AtspiAccessible *node, int length_limit) _combine_strings(&state_string, node_state_str); } - if (states) - g_array_free(states, 0); - g_object_unref(node_state_set); + g_array_free(states, 0); + g_clear_object(&node_state_set); _truncate_string(state_string, length_limit); -- 2.7.4 From d73e6b21e10f2a3d1f6e313b40f66c009c09a79c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pawe=C5=82=20Stawicki?= Date: Fri, 16 Mar 2018 13:05:20 +0100 Subject: [PATCH 16/16] [prevent][42870] Fix for null pointer dereference Change-Id: I74e51363d0e6ec34e9b771f605d283f1311af803 --- test/at_spi2_tool.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/at_spi2_tool.c b/test/at_spi2_tool.c index d7b91d5..63a3adb 100644 --- a/test/at_spi2_tool.c +++ b/test/at_spi2_tool.c @@ -323,10 +323,10 @@ static char *_get_info(AtspiAccessible *node, int length_limit, bool *attributes unique_id, (uintptr_t)eo_ptr, node_role_name, attributes, - box_size->x, - box_size->y, - box_size->width, - box_size->height, + box_size ? box_size->x : "nil", + box_size ? box_size->y : "nil", + box_size ? box_size->width : "nil", + box_size ? box_size->height : "nil", node_name, states, current_node_has_relations ? "*" : ""); -- 2.7.4