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 
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 {
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
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 
97  fl_value_set_string(message, "data", data);
98  fl_value_set_string_take(data, "viewId",
100  fl_value_set_string_take(data, "message", fl_value_new_string("MESSAGE"));
101  fl_value_set_string_take(data, "textDirection",
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;
132 
136  fl_value_set_string(message, "data", data);
137  fl_value_set_string_take(data, "viewId",
139  fl_value_set_string_take(data, "message", fl_value_new_string("MESSAGE"));
140  fl_value_set_string_take(data, "textDirection",
142  // Add optional assertiveness (not used in ATK)
143  fl_value_set_string_take(data, "assertiveness",
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 
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",
183  // Add optional assertiveness (not used in ATK)
184  fl_value_set_string_take(data, "assertiveness",
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.
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 }
FlViewAccessible * accessible
FlView * view
const char * message
g_autoptr(FlEngine) engine
const char FlTextDirection FlAssertiveness gpointer user_data
static void subscribe_signal(FlViewAccessible *accessible, gboolean *signalled, gboolean assertive)
TEST(FlAccessibilityHandlerTest, Announce)
static constexpr int64_t kAssertivenessAssertive
static void announcement_cb(FlViewAccessible *accessible, const gchar *message, gpointer user_data)
static void notification_polite_cb(FlViewAccessible *accessible, const gchar *message, FlAtkLive politeness, gpointer user_data)
static constexpr int64_t kTextDirectionLtr
static void notification_assertive_cb(FlViewAccessible *accessible, const gchar *message, FlAtkLive politeness, gpointer user_data)
static gboolean atk_supports_announce()
void fl_binary_messenger_shutdown(FlBinaryMessenger *self)
return TRUE
FlEngine * fl_engine_new_with_binary_messenger(FlBinaryMessenger *binary_messenger)
Definition: fl_engine.cc:701
G_MODULE_EXPORT void fl_value_set_string(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:639
G_MODULE_EXPORT void fl_value_set_string_take(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:650
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:276
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:466
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:262
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
@ FL_VALUE_TYPE_NULL
Definition: fl_value.h:64
FlViewAccessible * fl_view_get_accessible(FlView *self)
Definition: fl_view.cc:808
G_MODULE_EXPORT FlView * fl_view_new_for_engine(FlEngine *engine)
Definition: fl_view.cc:777
G_MODULE_EXPORT int64_t fl_view_get_id(FlView *self)
Definition: fl_view.cc:796