1 // Copyright 2015 The Chromium 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.
5 #include "chrome/browser/chromeos/accessibility/spoken_feedback_event_rewriter.h"
8 #include "ash/test/ash_test_base.h"
9 #include "ui/aura/window.h"
10 #include "ui/aura/window_tree_host.h"
11 #include "ui/events/event.h"
12 #include "ui/events/event_constants.h"
13 #include "ui/events/keycodes/keyboard_codes.h"
14 #include "ui/events/test/event_generator.h"
16 // Records all key events.
17 class EventCapturer
: public ui::EventHandler
{
20 ~EventCapturer() override
{}
22 void Reset() { events_
.clear(); }
24 void OnEvent(ui::Event
* event
) override
{
25 if (event
->IsKeyEvent())
26 events_
.push_back(new ui::KeyEvent(static_cast<ui::KeyEvent
&>(*event
)));
29 const ScopedVector
<ui::KeyEvent
>& captured_events() const { return events_
; }
32 ScopedVector
<ui::KeyEvent
> events_
;
34 DISALLOW_COPY_AND_ASSIGN(EventCapturer
);
37 class TestDelegate
: public SpokenFeedbackEventRewriterDelegate
{
40 : is_spoken_feedback_enabled_(false), dispatch_result_(false) {}
42 ~TestDelegate() override
{}
44 void set_is_spoken_feedback_enabled(bool enabled
) {
45 is_spoken_feedback_enabled_
= enabled
;
48 void set_dispatch_result(bool result
) { dispatch_result_
= result
; }
51 // SpokenFeedbackEventRewriterDelegate:
52 bool IsSpokenFeedbackEnabled() const override
{
53 return is_spoken_feedback_enabled_
;
56 bool DispatchKeyEventToChromeVox(const ui::KeyEvent
& key_event
) override
{
57 return dispatch_result_
;
60 bool is_spoken_feedback_enabled_
;
61 bool dispatch_result_
;
63 DISALLOW_COPY_AND_ASSIGN(TestDelegate
);
66 class SpokenFeedbackEventRewriterTest
: public ash::test::AshTestBase
{
68 SpokenFeedbackEventRewriterTest()
69 : generator_(nullptr),
70 spoken_feedback_event_rewriter_(new SpokenFeedbackEventRewriter()) {
71 delegate_
= new TestDelegate();
72 spoken_feedback_event_rewriter_
->SetDelegateForTest(
73 scoped_ptr
<TestDelegate
>(delegate_
));
76 void SetUp() override
{
77 ash::test::AshTestBase::SetUp();
78 generator_
= &AshTestBase::GetEventGenerator();
79 CurrentContext()->AddPreTargetHandler(&event_capturer_
);
80 CurrentContext()->GetHost()->GetEventSource()->AddEventRewriter(
81 spoken_feedback_event_rewriter_
.get());
84 void TearDown() override
{
85 CurrentContext()->GetHost()->GetEventSource()->RemoveEventRewriter(
86 spoken_feedback_event_rewriter_
.get());
87 CurrentContext()->RemovePreTargetHandler(&event_capturer_
);
89 ash::test::AshTestBase::TearDown();
93 TestDelegate
* delegate_
;
94 ui::test::EventGenerator
* generator_
;
95 EventCapturer event_capturer_
;
98 scoped_ptr
<SpokenFeedbackEventRewriter
> spoken_feedback_event_rewriter_
;
100 DISALLOW_COPY_AND_ASSIGN(SpokenFeedbackEventRewriterTest
);
103 TEST_F(SpokenFeedbackEventRewriterTest
, PressAndReleaseCvoxKeys
) {
104 // Mock ChromeVox enabled.
105 delegate_
->set_is_spoken_feedback_enabled(true);
107 // Send Search+Shift.
108 generator_
->PressKey(ui::VKEY_LWIN
, ui::EF_COMMAND_DOWN
);
109 ASSERT_EQ(1U, event_capturer_
.captured_events().size());
110 generator_
->PressKey(ui::VKEY_SHIFT
, ui::EF_COMMAND_DOWN
| ui::EF_SHIFT_DOWN
);
111 ASSERT_EQ(2U, event_capturer_
.captured_events().size());
113 // Mock successful commands lookup and dispatch.
114 delegate_
->set_dispatch_result(true);
116 // Send the right arrow key, which gets successfully looked up and dispatched
117 // as a ChromeVox command, so the event gets discarded.
118 generator_
->PressKey(ui::VKEY_RIGHT
, ui::EF_COMMAND_DOWN
| ui::EF_SHIFT_DOWN
);
119 ASSERT_EQ(2U, event_capturer_
.captured_events().size());
121 event_capturer_
.Reset();
123 // Released keys previously captured get eaten even without successful
125 delegate_
->set_dispatch_result(false);
126 generator_
->ReleaseKey(ui::VKEY_RIGHT
,
127 ui::EF_COMMAND_DOWN
| ui::EF_SHIFT_DOWN
);
128 ASSERT_EQ(0U, event_capturer_
.captured_events().size());
130 // Modifiers were not discarded, so we let them continue.
131 generator_
->ReleaseKey(ui::VKEY_SHIFT
, ui::EF_COMMAND_DOWN
);
132 generator_
->ReleaseKey(ui::VKEY_LWIN
, 0);
133 ASSERT_EQ(2U, event_capturer_
.captured_events().size());
136 TEST_F(SpokenFeedbackEventRewriterTest
, KeysNotEatenWithChromeVoxDisabled
) {
137 // Send Search+Shift+Right.
138 generator_
->PressKey(ui::VKEY_LWIN
, ui::EF_COMMAND_DOWN
);
139 ASSERT_EQ(1U, event_capturer_
.captured_events().size());
140 generator_
->PressKey(ui::VKEY_SHIFT
, ui::EF_COMMAND_DOWN
| ui::EF_SHIFT_DOWN
);
141 ASSERT_EQ(2U, event_capturer_
.captured_events().size());
143 // Mock successful commands lookup and dispatch; shouldn't matter either way.
144 delegate_
->set_dispatch_result(true);
145 generator_
->PressKey(ui::VKEY_RIGHT
, ui::EF_COMMAND_DOWN
| ui::EF_SHIFT_DOWN
);
146 ASSERT_EQ(3U, event_capturer_
.captured_events().size());
148 // Released keys shouldn't get eaten.
149 delegate_
->set_dispatch_result(false);
150 generator_
->ReleaseKey(ui::VKEY_RIGHT
,
151 ui::EF_COMMAND_DOWN
| ui::EF_SHIFT_DOWN
);
152 generator_
->ReleaseKey(ui::VKEY_SHIFT
, ui::EF_COMMAND_DOWN
);
153 generator_
->ReleaseKey(ui::VKEY_LWIN
, 0);
154 ASSERT_EQ(6U, event_capturer_
.captured_events().size());
156 // Try releasing more keys.
157 generator_
->ReleaseKey(ui::VKEY_RIGHT
, 0);
158 generator_
->ReleaseKey(ui::VKEY_SHIFT
, 0);
159 generator_
->ReleaseKey(ui::VKEY_LWIN
, 0);
160 ASSERT_EQ(9U, event_capturer_
.captured_events().size());