| Flutter Windows Embedder |

keyboard_key_channel_handler_unittests.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 #include "flutter/shell/platform/windows/keyboard_key_channel_handler.h"
5
6 #include <memory>
7
8 #include "flutter/shell/platform/common/json_message_codec.h"
9 #include "flutter/shell/platform/windows/flutter_windows_view.h"
10 #include "flutter/shell/platform/windows/testing/test_binary_messenger.h"
11 #include "gmock/gmock.h"
12 #include "gtest/gtest.h"
13
14 namespace flutter {
15 namespace testing {
16
17 namespace {
18 static constexpr char kScanCodeKey[] = "scanCode";
19 static constexpr char kCharacterCodePointKey[] = "characterCodePoint";
20 static constexpr int kHandledScanCode = 0x14;
21 static constexpr int kUnhandledScanCode = 0x15;
22 static constexpr int kUnhandledScanCodeExtended = 0xe015;
23
24 static std::unique_ptr<std::vector<uint8_t>> CreateResponse(bool handled) {
25 auto response_doc =
26 std::make_unique<rapidjson::Document>(rapidjson::kObjectType);
27 auto& allocator = response_doc->GetAllocator();
28 response_doc->AddMember("handled", handled, allocator);
29 return JsonMessageCodec::GetInstance().EncodeMessage(*response_doc);
30 }
31 } // namespace
32
33 TEST(KeyboardKeyChannelHandlerTest, KeyboardHookHandling) {
34 auto handled_message = CreateResponse(true);
35 auto unhandled_message = CreateResponse(false);
36 int received_scancode = 0;
37
38 TestBinaryMessenger messenger(
39 [&received_scancode, &handled_message, &unhandled_message](
40 const std::string& channel, const uint8_t* message,
41 size_t message_size, BinaryReply reply) {
42 if (channel == "flutter/keyevent") {
43 auto message_doc = JsonMessageCodec::GetInstance().DecodeMessage(
44 message, message_size);
45 received_scancode = (*message_doc)[kScanCodeKey].GetInt();
46 if (received_scancode == kHandledScanCode) {
47 reply(handled_message->data(), handled_message->size());
48 } else {
49 reply(unhandled_message->data(), unhandled_message->size());
50 }
51 }
52 });
53
54 KeyboardKeyChannelHandler handler(&messenger);
55 bool last_handled = false;
56
57 handler.KeyboardHook(
58 64, kHandledScanCode, WM_KEYDOWN, L'a', false, false,
59 [&last_handled](bool handled) { last_handled = handled; });
60 EXPECT_EQ(received_scancode, kHandledScanCode);
61 EXPECT_EQ(last_handled, true);
62
63 received_scancode = 0;
64
65 handler.KeyboardHook(
66 64, kUnhandledScanCode, WM_KEYDOWN, L'b', false, false,
67 [&last_handled](bool handled) { last_handled = handled; });
68 EXPECT_EQ(received_scancode, kUnhandledScanCode);
69 EXPECT_EQ(last_handled, false);
70
71 received_scancode = 0;
72
73 handler.KeyboardHook(
74 64, kHandledScanCode, WM_SYSKEYDOWN, L'a', false, false,
75 [&last_handled](bool handled) { last_handled = handled; });
76 EXPECT_EQ(received_scancode, kHandledScanCode);
77 EXPECT_EQ(last_handled, true);
78
79 received_scancode = 0;
80
81 handler.KeyboardHook(
82 64, kUnhandledScanCode, WM_SYSKEYDOWN, L'c', false, false,
83 [&last_handled](bool handled) { last_handled = handled; });
84 EXPECT_EQ(received_scancode, kUnhandledScanCode);
85 EXPECT_EQ(last_handled, false);
86 }
87
88 TEST(KeyboardKeyChannelHandlerTest, ExtendedKeysAreSentToRedispatch) {
89 auto handled_message = CreateResponse(true);
90 auto unhandled_message = CreateResponse(false);
91 int received_scancode = 0;
92
93 TestBinaryMessenger messenger(
94 [&received_scancode, &handled_message, &unhandled_message](
95 const std::string& channel, const uint8_t* message,
96 size_t message_size, BinaryReply reply) {
97 if (channel == "flutter/keyevent") {
98 auto message_doc = JsonMessageCodec::GetInstance().DecodeMessage(
99 message, message_size);
100 received_scancode = (*message_doc)[kScanCodeKey].GetInt();
101 if (received_scancode == kHandledScanCode) {
102 reply(handled_message->data(), handled_message->size());
103 } else {
104 reply(unhandled_message->data(), unhandled_message->size());
105 }
106 }
107 });
108
109 KeyboardKeyChannelHandler handler(&messenger);
110 bool last_handled = true;
111
112 // Extended key flag is passed to redispatched events if set.
113 handler.KeyboardHook(
114 64, kUnhandledScanCode, WM_KEYDOWN, L'b', true, false,
115 [&last_handled](bool handled) { last_handled = handled; });
116 EXPECT_EQ(last_handled, false);
117 EXPECT_EQ(received_scancode, kUnhandledScanCodeExtended);
118
119 last_handled = true;
120 // Extended key flag is not passed to redispatched events if not set.
121 handler.KeyboardHook(
122 64, kUnhandledScanCode, WM_KEYDOWN, L'b', false, false,
123 [&last_handled](bool handled) { last_handled = handled; });
124 EXPECT_EQ(last_handled, false);
125 EXPECT_EQ(received_scancode, kUnhandledScanCode);
126 }
127
128 TEST(KeyboardKeyChannelHandlerTest, DeadKeysDoNotCrash) {
129 bool received = false;
130 TestBinaryMessenger messenger(
131 [&received](const std::string& channel, const uint8_t* message,
132 size_t message_size, BinaryReply reply) {
133 if (channel == "flutter/keyevent") {
134 auto message_doc = JsonMessageCodec::GetInstance().DecodeMessage(
135 message, message_size);
136 uint32_t character = (*message_doc)[kCharacterCodePointKey].GetUint();
137 EXPECT_EQ(character, (uint32_t)'^');
138 received = true;
139 }
140 return true;
141 });
142
143 KeyboardKeyChannelHandler handler(&messenger);
144 // Extended key flag is passed to redispatched events if set.
145 handler.KeyboardHook(0xDD, 0x1a, WM_KEYDOWN, 0x8000005E, false, false,
146 [](bool handled) {});
147
148 // EXPECT is done during the callback above.
149 EXPECT_TRUE(received);
150 }
151
152 TEST(KeyboardKeyChannelHandlerTest, EmptyResponsesDoNotCrash) {
153 bool received = false;
154 TestBinaryMessenger messenger(
155 [&received](const std::string& channel, const uint8_t* message,
156 size_t message_size, BinaryReply reply) {
157 if (channel == "flutter/keyevent") {
158 std::string empty_message = "";
159 std::vector<uint8_t> empty_response(empty_message.begin(),
160 empty_message.end());
161 reply(empty_response.data(), empty_response.size());
162 received = true;
163 }
164 return true;
165 });
166
167 KeyboardKeyChannelHandler handler(&messenger);
168 handler.KeyboardHook(64, kUnhandledScanCode, WM_KEYDOWN, L'b', false, false,
169 [](bool handled) {});
170
171 // Passes if it does not crash.
172 EXPECT_TRUE(received);
173 }
174
175 } // namespace testing
176 } // namespace flutter
flutter::JsonMessageCodec::GetInstance
static const JsonMessageCodec & GetInstance()
Definition: json_message_codec.cc:17
flutter::KeyboardKeyChannelHandler
Definition: keyboard_key_channel_handler.h:25
flutter::MessageCodec::EncodeMessage
std::unique_ptr< std::vector< uint8_t > > EncodeMessage(const T &message) const
Definition: message_codec.h:45
flutter::MessageCodec::DecodeMessage
std::unique_ptr< T > DecodeMessage(const uint8_t *binary_message, const size_t message_size) const
Definition: message_codec.h:29
flutter_windows_view.h
json_message_codec.h
keyboard_key_channel_handler.h
character
char32_t character
Definition: keyboard_key_handler_unittests.cc:117
message
Win32Message message
Definition: keyboard_unittests.cc:137
flutter::testing::TEST
TEST(AccessibilityBridgeWindows, GetParent)
Definition: accessibility_bridge_windows_unittests.cc:243
flutter
Definition: accessibility_bridge_windows.cc:11
flutter::BinaryReply
std::function< void(const uint8_t *reply, size_t reply_size)> BinaryReply
Definition: binary_messenger.h:17