| Flutter Linux Embedder |

fl_accessibility_handler_test.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Workaround missing C code compatibility in ATK header.
6 // Fixed in https://gitlab.gnome.org/GNOME/at-spi2-core/-/merge_requests/219
7 extern "C" {
8 #include <atk/atk.h>
9 }
10
11 #include "flutter/shell/platform/linux/fl_accessibility_handler.h"
12 #include "flutter/shell/platform/linux/fl_binary_messenger_private.h"
13 #include "flutter/shell/platform/linux/fl_engine_private.h"
14 #include "flutter/shell/platform/linux/fl_view_private.h"
15 #include "flutter/shell/platform/linux/testing/fl_mock_binary_messenger.h"
16 #include "flutter/shell/platform/linux/testing/fl_test_gtk_logs.h"
17 #include "flutter/testing/testing.h"
18
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21
22 static constexpr int64_t kTextDirectionLtr = 0;
23 static constexpr int64_t kAssertivenessAssertive = 1;
24
25 // Enum copied from ATK 2.50, as the version we are building against doesn't
26 // have this.
27 typedef enum {
28 FL_ATK_LIVE_NONE,
29 FL_ATK_LIVE_POLITE,
30 FL_ATK_LIVE_ASSERTIVE
31 } FlAtkLive;
32
33 static void announcement_cb(FlViewAccessible* accessible,
34 const gchar* message,
35 gpointer user_data) {
36 EXPECT_STREQ(message, "MESSAGE");
37 gboolean* signalled = static_cast<gboolean*>(user_data);
38 *signalled = TRUE;
39 }
40
41 static void notification_polite_cb(FlViewAccessible* accessible,
42 const gchar* message,
43 FlAtkLive politeness,
44 gpointer user_data) {
45 EXPECT_STREQ(message, "MESSAGE");
46 EXPECT_EQ(politeness, FL_ATK_LIVE_POLITE);
47 gboolean* signalled = static_cast<gboolean*>(user_data);
48 *signalled = TRUE;
49 }
50
51 static void notification_assertive_cb(FlViewAccessible* accessible,
52 const gchar* message,
53 FlAtkLive politeness,
54 gpointer user_data) {
55 EXPECT_STREQ(message, "MESSAGE");
56 EXPECT_EQ(politeness, FL_ATK_LIVE_ASSERTIVE);
57 gboolean* signalled = static_cast<gboolean*>(user_data);
58 *signalled = TRUE;
59 }
60
61 static gboolean atk_supports_announce() {
62 return atk_get_major_version() == 2 && atk_get_minor_version() >= 46;
63 }
64
65 static void subscribe_signal(FlViewAccessible* accessible,
66 gboolean* signalled,
67 gboolean assertive) {
68 if (!atk_supports_announce()) {
69 return;
70 }
71
72 if (atk_get_major_version() == 2 && atk_get_minor_version() < 50) {
73 g_signal_connect(accessible, "announcement", G_CALLBACK(announcement_cb),
74 signalled);
75 } else {
76 g_signal_connect(accessible, "notification",
77 G_CALLBACK(assertive ? notification_assertive_cb
78 : notification_polite_cb),
79 signalled);
80 }
81 }
82
83 TEST(FlAccessibilityHandlerTest, Announce) {
84 flutter::testing::fl_ensure_gtk_init();
85
86 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
87 g_autoptr(FlEngine) engine =
88 fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
89 FlView* view = fl_view_new_for_engine(engine);
90
91 gboolean signalled = FALSE;
92 subscribe_signal(fl_view_get_accessible(view), &signalled, FALSE);
93
94 g_autoptr(FlValue) message = fl_value_new_map();
95 fl_value_set_string_take(message, "type", fl_value_new_string("announce"));
96 g_autoptr(FlValue) data = fl_value_new_map();
97 fl_value_set_string(message, "data", data);
98 fl_value_set_string_take(data, "viewId",
99 fl_value_new_int(fl_view_get_id(view)));
100 fl_value_set_string_take(data, "message", fl_value_new_string("MESSAGE"));
101 fl_value_set_string_take(data, "textDirection",
102 fl_value_new_int(kTextDirectionLtr));
103
104 gboolean called = FALSE;
105 fl_mock_binary_messenger_send_standard_message(
106 messenger, "flutter/accessibility", message,
107 [](FlMockBinaryMessenger* messenger, FlValue* response,
108 gpointer user_data) {
109 EXPECT_EQ(fl_value_get_type(response), FL_VALUE_TYPE_NULL);
110 gboolean* called = static_cast<gboolean*>(user_data);
111 *called = TRUE;
112 },
113 &called);
114 EXPECT_TRUE(called);
115 if (atk_supports_announce()) {
116 EXPECT_TRUE(signalled);
117 }
118
119 fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
120 }
121
122 TEST(FlAccessibilityHandlerTest, AnnounceAssertive) {
123 flutter::testing::fl_ensure_gtk_init();
124
125 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
126 g_autoptr(FlEngine) engine =
127 fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
128 FlView* view = fl_view_new_for_engine(engine);
129
130 gboolean signalled = FALSE;
131 subscribe_signal(fl_view_get_accessible(view), &signalled, TRUE);
132
133 g_autoptr(FlValue) message = fl_value_new_map();
134 fl_value_set_string_take(message, "type", fl_value_new_string("announce"));
135 g_autoptr(FlValue) data = fl_value_new_map();
136 fl_value_set_string(message, "data", data);
137 fl_value_set_string_take(data, "viewId",
138 fl_value_new_int(fl_view_get_id(view)));
139 fl_value_set_string_take(data, "message", fl_value_new_string("MESSAGE"));
140 fl_value_set_string_take(data, "textDirection",
141 fl_value_new_int(kTextDirectionLtr));
142 // Add optional assertiveness (not used in ATK)
143 fl_value_set_string_take(data, "assertiveness",
144 fl_value_new_int(kAssertivenessAssertive));
145
146 gboolean called = FALSE;
147 fl_mock_binary_messenger_send_standard_message(
148 messenger, "flutter/accessibility", message,
149 [](FlMockBinaryMessenger* messenger, FlValue* response,
150 gpointer user_data) {
151 EXPECT_EQ(fl_value_get_type(response), FL_VALUE_TYPE_NULL);
152 gboolean* called = static_cast<gboolean*>(user_data);
153 *called = TRUE;
154 },
155 &called);
156 EXPECT_TRUE(called);
157 if (atk_supports_announce()) {
158 EXPECT_TRUE(signalled);
159 }
160
161 fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
162 }
163
164 TEST(FlAccessibilityHandlerTest, AnnounceUnknownView) {
165 flutter::testing::fl_ensure_gtk_init();
166
167 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
168 g_autoptr(FlEngine) engine =
169 fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
170 FlView* view = fl_view_new_for_engine(engine);
171
172 gboolean signalled = FALSE;
173 subscribe_signal(fl_view_get_accessible(view), &signalled, FALSE);
174
175 g_autoptr(FlValue) message = fl_value_new_map();
176 fl_value_set_string_take(message, "type", fl_value_new_string("announce"));
177 g_autoptr(FlValue) data = fl_value_new_map();
178 fl_value_set_string(message, "data", data);
179 fl_value_set_string_take(data, "viewId", fl_value_new_int(999));
180 fl_value_set_string_take(data, "message", fl_value_new_string("MESSAGE"));
181 fl_value_set_string_take(data, "textDirection",
182 fl_value_new_int(kTextDirectionLtr));
183 // Add optional assertiveness (not used in ATK)
184 fl_value_set_string_take(data, "assertiveness",
185 fl_value_new_int(kAssertivenessAssertive));
186
187 gboolean called = FALSE;
188 fl_mock_binary_messenger_send_standard_message(
189 messenger, "flutter/accessibility", message,
190 [](FlMockBinaryMessenger* messenger, FlValue* response,
191 gpointer user_data) {
192 EXPECT_EQ(fl_value_get_type(response), FL_VALUE_TYPE_NULL);
193 gboolean* called = static_cast<gboolean*>(user_data);
194 *called = TRUE;
195 },
196 &called);
197 EXPECT_TRUE(called);
198 EXPECT_FALSE(signalled);
199
200 fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
201 }
202
203 TEST(FlAccessibilityHandlerTest, UnknownType) {
204 flutter::testing::fl_ensure_gtk_init();
205
206 g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
207 g_autoptr(FlEngine) engine =
208 fl_engine_new_with_binary_messenger(FL_BINARY_MESSENGER(messenger));
209 FlView* view = fl_view_new_for_engine(engine);
210
211 gboolean signalled = FALSE;
212 subscribe_signal(fl_view_get_accessible(view), &signalled, FALSE);
213
214 // Unknown type, ignored by embedder.
215 g_autoptr(FlValue) message = fl_value_new_map();
216 fl_value_set_string_take(message, "type", fl_value_new_string("UNKNOWN"));
217 fl_value_set_string_take(message, "data", fl_value_new_map());
218
219 gboolean called = FALSE;
220 fl_mock_binary_messenger_send_standard_message(
221 messenger, "flutter/accessibility", message,
222 [](FlMockBinaryMessenger* messenger, FlValue* response,
223 gpointer user_data) {
224 EXPECT_EQ(fl_value_get_type(response), FL_VALUE_TYPE_NULL);
225 gboolean* called = static_cast<gboolean*>(user_data);
226 *called = TRUE;
227 },
228 &called);
229 EXPECT_TRUE(called);
230 EXPECT_FALSE(signalled);
231
232 fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
233 }
accessible
FlViewAccessible * accessible
Definition: fl_accessibility_handler.cc:41
view
FlView * view
Definition: fl_accessibility_handler.cc:40
message
const char * message
Definition: fl_accessibility_handler.cc:21
g_autoptr
g_autoptr(FlEngine) engine
user_data
const char FlTextDirection FlAssertiveness gpointer user_data
Definition: fl_accessibility_handler.cc:24
fl_accessibility_handler.h
subscribe_signal
static void subscribe_signal(FlViewAccessible *accessible, gboolean *signalled, gboolean assertive)
Definition: fl_accessibility_handler_test.cc:65
TEST
TEST(FlAccessibilityHandlerTest, Announce)
Definition: fl_accessibility_handler_test.cc:83
kAssertivenessAssertive
static constexpr int64_t kAssertivenessAssertive
Definition: fl_accessibility_handler_test.cc:23
announcement_cb
static void announcement_cb(FlViewAccessible *accessible, const gchar *message, gpointer user_data)
Definition: fl_accessibility_handler_test.cc:33
notification_polite_cb
static void notification_polite_cb(FlViewAccessible *accessible, const gchar *message, FlAtkLive politeness, gpointer user_data)
Definition: fl_accessibility_handler_test.cc:41
kTextDirectionLtr
static constexpr int64_t kTextDirectionLtr
Definition: fl_accessibility_handler_test.cc:22
FlAtkLive
FlAtkLive
Definition: fl_accessibility_handler_test.cc:27
FL_ATK_LIVE_ASSERTIVE
@ FL_ATK_LIVE_ASSERTIVE
Definition: fl_accessibility_handler_test.cc:30
FL_ATK_LIVE_NONE
@ FL_ATK_LIVE_NONE
Definition: fl_accessibility_handler_test.cc:28
FL_ATK_LIVE_POLITE
@ FL_ATK_LIVE_POLITE
Definition: fl_accessibility_handler_test.cc:29
notification_assertive_cb
static void notification_assertive_cb(FlViewAccessible *accessible, const gchar *message, FlAtkLive politeness, gpointer user_data)
Definition: fl_accessibility_handler_test.cc:51
atk_supports_announce
static gboolean atk_supports_announce()
Definition: fl_accessibility_handler_test.cc:61
fl_binary_messenger_shutdown
void fl_binary_messenger_shutdown(FlBinaryMessenger *self)
Definition: fl_binary_messenger.cc:500
fl_binary_messenger_private.h
TRUE
return TRUE
Definition: fl_compositor_software.cc:68
fl_engine_new_with_binary_messenger
FlEngine * fl_engine_new_with_binary_messenger(FlBinaryMessenger *binary_messenger)
Definition: fl_engine.cc:701
fl_engine_private.h
fl_value_set_string
G_MODULE_EXPORT void fl_value_set_string(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:639
fl_value_set_string_take
G_MODULE_EXPORT void fl_value_set_string_take(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:650
fl_value_new_string
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:276
fl_value_get_type
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:466
fl_value_new_int
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:262
fl_value_new_map
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
FL_VALUE_TYPE_NULL
@ FL_VALUE_TYPE_NULL
Definition: fl_value.h:64
fl_view_get_accessible
FlViewAccessible * fl_view_get_accessible(FlView *self)
Definition: fl_view.cc:808
fl_view_new_for_engine
G_MODULE_EXPORT FlView * fl_view_new_for_engine(FlEngine *engine)
Definition: fl_view.cc:777
fl_view_get_id
G_MODULE_EXPORT int64_t fl_view_get_id(FlView *self)
Definition: fl_view.cc:796
fl_view_private.h