Flutter Windows Embedder
accessibility_plugin.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 
6 
7 #include <variant>
8 
9 #include "flutter/fml/logging.h"
10 #include "flutter/fml/platform/win/wstring_conversion.h"
14 
15 namespace flutter {
16 
17 namespace {
18 
19 static constexpr char kAccessibilityChannelName[] = "flutter/accessibility";
20 static constexpr char kTypeKey[] = "type";
21 static constexpr char kDataKey[] = "data";
22 static constexpr char kMessageKey[] = "message";
23 static constexpr char kViewIdKey[] = "viewId";
24 static constexpr char kAnnounceValue[] = "announce";
25 
26 // Handles messages like:
27 // {"type": "announce", "data": {"message": "Hello"}}
28 void HandleMessage(AccessibilityPlugin* plugin, const EncodableValue& message) {
29  const auto* map = std::get_if<EncodableMap>(&message);
30  if (!map) {
31  FML_LOG(ERROR) << "Accessibility message must be a map.";
32  return;
33  }
34  const auto& type_itr = map->find(EncodableValue{kTypeKey});
35  const auto& data_itr = map->find(EncodableValue{kDataKey});
36  if (type_itr == map->end()) {
37  FML_LOG(ERROR) << "Accessibility message must have a 'type' property.";
38  return;
39  }
40  if (data_itr == map->end()) {
41  FML_LOG(ERROR) << "Accessibility message must have a 'data' property.";
42  return;
43  }
44  const auto* type = std::get_if<std::string>(&type_itr->second);
45  const auto* data = std::get_if<EncodableMap>(&data_itr->second);
46  if (!type) {
47  FML_LOG(ERROR) << "Accessibility message 'type' property must be a string.";
48  return;
49  }
50  if (!data) {
51  FML_LOG(ERROR) << "Accessibility message 'data' property must be a map.";
52  return;
53  }
54 
55  if (type->compare(kAnnounceValue) == 0) {
56  const auto& message_itr = data->find(EncodableValue{kMessageKey});
57  if (message_itr == data->end()) {
58  return;
59  }
60  const auto* message = std::get_if<std::string>(&message_itr->second);
61  if (!message) {
62  return;
63  }
64 
65  const auto& view_itr = data->find(EncodableValue{kViewIdKey});
66  if (view_itr == data->end()) {
67  FML_LOG(ERROR) << "Announce message 'viewId' property is missing.";
68  return;
69  }
70 
71  const auto* view_id_val = std::get_if<FlutterViewId>(&view_itr->second);
72  if (!view_id_val) {
73  FML_LOG(ERROR)
74  << "Announce message 'viewId' property must be a FlutterViewId.";
75  return;
76  }
77 
78  plugin->Announce(*view_id_val, *message);
79  } else {
80  FML_LOG(WARNING) << "Accessibility message type '" << *type
81  << "' is not supported.";
82  }
83 }
84 
85 } // namespace
86 
88  : engine_(engine) {}
89 
91  AccessibilityPlugin* plugin) {
92  BasicMessageChannel<> channel{binary_messenger, kAccessibilityChannelName,
94 
95  channel.SetMessageHandler(
96  [plugin](const EncodableValue& message,
97  const MessageReply<EncodableValue>& reply) {
98  HandleMessage(plugin, message);
99 
100  // The accessibility channel does not support error handling.
101  // Always return an empty response even on failure.
102  reply(EncodableValue{std::monostate{}});
103  });
104 }
105 
107  const std::string_view message) {
108  if (!engine_->semantics_enabled()) {
109  return;
110  }
111 
112  auto view = engine_->view(view_id);
113  if (!view) {
114  return;
115  }
116 
117  std::wstring wide_text = fml::Utf8ToWideString(message);
118  view->AnnounceAlert(wide_text);
119 }
120 
121 } // namespace flutter
AccessibilityPlugin(FlutterWindowsEngine *engine)
static void SetUp(BinaryMessenger *binary_messenger, AccessibilityPlugin *plugin)
virtual void Announce(const FlutterViewId view_id, const std::string_view message)
FlutterWindowsView * view(FlutterViewId view_id) const
static const StandardMessageCodec & GetInstance(const StandardCodecSerializer *serializer=nullptr)
static constexpr char kAccessibilityChannelName[]
enum flutter::testing::@93::KeyboardChange::Type type
Win32Message message
int64_t FlutterViewId
std::function< void(const T &reply)> MessageReply