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