1 // Copyright 2014 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.
4
5 #include <queue>
6
7 #include "ash/shell.h"
8 #include "base/command_line.h"
9 #include "base/strings/string_util.h"
10 #include "chrome/app/chrome_command_ids.h"
11 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
12 #include "chrome/browser/chromeos/accessibility/speech_monitor.h"
13 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
14 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
15 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
16 #include "chrome/browser/chromeos/login/users/user_manager.h"
17 #include "chrome/browser/chromeos/profiles/profile_helper.h"
18 #include "chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h"
19 #include "chrome/browser/speech/tts_controller.h"
20 #include "chrome/browser/speech/tts_platform.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/browser_commands.h"
23 #include "chrome/browser/ui/browser_window.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/test/base/in_process_browser_test.h"
26 #include "chrome/test/base/interactive_test_utils.h"
27 #include "chrome/test/base/testing_profile.h"
28 #include "chrome/test/base/ui_test_utils.h"
29 #include "chromeos/chromeos_switches.h"
30 #include "content/public/common/url_constants.h"
31 #include "content/public/test/test_utils.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 #include "ui/base/test/ui_controls.h"
34 #include "ui/views/widget/widget.h"
35
36 using extensions::api::braille_display_private::StubBrailleController;
37
38 namespace chromeos {
39
40 //
41 // Spoken feedback tests only in a logged in user's window.
42 //
43
44 class LoggedInSpokenFeedbackTest : public InProcessBrowserTest {
45 protected:
LoggedInSpokenFeedbackTest()46 LoggedInSpokenFeedbackTest() {}
~LoggedInSpokenFeedbackTest()47 virtual ~LoggedInSpokenFeedbackTest() {}
48
SetUpInProcessBrowserTestFixture()49 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
50 AccessibilityManager::SetBrailleControllerForTest(&braille_controller_);
51 }
52
CleanUpOnMainThread()53 virtual void CleanUpOnMainThread() OVERRIDE {
54 AccessibilityManager::SetBrailleControllerForTest(NULL);
55 }
56
SendKeyPress(ui::KeyboardCode key)57 void SendKeyPress(ui::KeyboardCode key) {
58 gfx::NativeWindow root_window =
59 ash::Shell::GetInstance()->GetPrimaryRootWindow();
60 ASSERT_TRUE(
61 ui_test_utils::SendKeyPressToWindowSync(
62 root_window, key, false, false, false, false));
63 }
64
65 private:
66 StubBrailleController braille_controller_;
67 DISALLOW_COPY_AND_ASSIGN(LoggedInSpokenFeedbackTest);
68 };
69
IN_PROC_BROWSER_TEST_F(LoggedInSpokenFeedbackTest,AddBookmark)70 IN_PROC_BROWSER_TEST_F(LoggedInSpokenFeedbackTest, AddBookmark) {
71 EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
72
73 SpeechMonitor monitor;
74 AccessibilityManager::Get()->EnableSpokenFeedback(
75 true, ash::A11Y_NOTIFICATION_NONE);
76 EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
77
78 chrome::ExecuteCommand(browser(), IDC_SHOW_BOOKMARK_BAR);
79
80 // Create a bookmark with title "foo".
81 chrome::ExecuteCommand(browser(), IDC_BOOKMARK_PAGE);
82 EXPECT_EQ("Bookmark added!,", monitor.GetNextUtterance());
83 EXPECT_EQ("about blank,", monitor.GetNextUtterance());
84 EXPECT_EQ("Bookmark name,", monitor.GetNextUtterance());
85 EXPECT_EQ("text box", monitor.GetNextUtterance());
86
87 SendKeyPress(ui::VKEY_F);
88 EXPECT_EQ("f", monitor.GetNextUtterance());
89 SendKeyPress(ui::VKEY_O);
90 EXPECT_EQ("o", monitor.GetNextUtterance());
91 SendKeyPress(ui::VKEY_O);
92 EXPECT_EQ("o", monitor.GetNextUtterance());
93
94 SendKeyPress(ui::VKEY_TAB);
95 EXPECT_EQ("Bookmarks bar,", monitor.GetNextUtterance());
96 EXPECT_EQ("Bookmark folder,", monitor.GetNextUtterance());
97 EXPECT_TRUE(MatchPattern(monitor.GetNextUtterance(), "combo box*"));
98
99 SendKeyPress(ui::VKEY_RETURN);
100
101 EXPECT_TRUE(MatchPattern(monitor.GetNextUtterance(), "*oolbar*"));
102 // Wait for active window change to be announced to avoid interference from
103 // that below.
104 while (monitor.GetNextUtterance() != "window about blank tab") {
105 // Do nothing.
106 }
107
108 // Focus bookmarks bar and listen for "foo".
109 chrome::ExecuteCommand(browser(), IDC_FOCUS_BOOKMARKS);
110 while (true) {
111 std::string utterance = monitor.GetNextUtterance();
112 VLOG(0) << "Got utterance: " << utterance;
113 if (utterance == "Bookmarks,")
114 break;
115 }
116 EXPECT_EQ("foo,", monitor.GetNextUtterance());
117 EXPECT_EQ("button", monitor.GetNextUtterance());
118 }
119
120 //
121 // Spoken feedback tests in both a logged in browser window and guest mode.
122 //
123
124 enum SpokenFeedbackTestVariant {
125 kTestAsNormalUser,
126 kTestAsGuestUser
127 };
128
129 class SpokenFeedbackTest
130 : public LoggedInSpokenFeedbackTest,
131 public ::testing::WithParamInterface<SpokenFeedbackTestVariant> {
132 protected:
SpokenFeedbackTest()133 SpokenFeedbackTest() {}
~SpokenFeedbackTest()134 virtual ~SpokenFeedbackTest() {}
135
SetUpCommandLine(CommandLine * command_line)136 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
137 if (GetParam() == kTestAsGuestUser) {
138 command_line->AppendSwitch(chromeos::switches::kGuestSession);
139 command_line->AppendSwitch(::switches::kIncognito);
140 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile,
141 "user");
142 command_line->AppendSwitchASCII(chromeos::switches::kLoginUser,
143 chromeos::UserManager::kGuestUserName);
144 }
145 }
146 };
147
148 INSTANTIATE_TEST_CASE_P(
149 TestAsNormalAndGuestUser,
150 SpokenFeedbackTest,
151 ::testing::Values(kTestAsNormalUser,
152 kTestAsGuestUser));
153
IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest,EnableSpokenFeedback)154 IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, EnableSpokenFeedback) {
155 EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
156
157 SpeechMonitor monitor;
158 AccessibilityManager::Get()->EnableSpokenFeedback(
159 true, ash::A11Y_NOTIFICATION_NONE);
160 EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
161 }
162
IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest,FocusToolbar)163 IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, FocusToolbar) {
164 EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
165
166 SpeechMonitor monitor;
167 AccessibilityManager::Get()->EnableSpokenFeedback(
168 true, ash::A11Y_NOTIFICATION_NONE);
169 EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
170
171 chrome::ExecuteCommand(browser(), IDC_FOCUS_TOOLBAR);
172 // Might be "Google Chrome Toolbar" or "Chromium Toolbar".
173 EXPECT_TRUE(MatchPattern(monitor.GetNextUtterance(), "*oolbar*"));
174 EXPECT_EQ("Reload,", monitor.GetNextUtterance());
175 EXPECT_EQ("button", monitor.GetNextUtterance());
176 }
177
IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest,TypeInOmnibox)178 IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, TypeInOmnibox) {
179 EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
180
181 SpeechMonitor monitor;
182 AccessibilityManager::Get()->EnableSpokenFeedback(
183 true, ash::A11Y_NOTIFICATION_NONE);
184 EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
185
186 // Wait for ChromeVox to finish speaking.
187 chrome::ExecuteCommand(browser(), IDC_FOCUS_LOCATION);
188 while (true) {
189 std::string utterance = monitor.GetNextUtterance();
190 VLOG(0) << "Got utterance: " << utterance;
191 if (utterance == "text box")
192 break;
193 }
194
195 SendKeyPress(ui::VKEY_X);
196 EXPECT_EQ("x", monitor.GetNextUtterance());
197
198 SendKeyPress(ui::VKEY_Y);
199 EXPECT_EQ("y", monitor.GetNextUtterance());
200
201 SendKeyPress(ui::VKEY_Z);
202 EXPECT_EQ("z", monitor.GetNextUtterance());
203
204 SendKeyPress(ui::VKEY_BACK);
205 EXPECT_EQ("z", monitor.GetNextUtterance());
206 }
207
208 //
209 // Spoken feedback tests that run only in guest mode.
210 //
211
212 class GuestSpokenFeedbackTest : public LoggedInSpokenFeedbackTest {
213 protected:
GuestSpokenFeedbackTest()214 GuestSpokenFeedbackTest() {}
~GuestSpokenFeedbackTest()215 virtual ~GuestSpokenFeedbackTest() {}
216
SetUpCommandLine(CommandLine * command_line)217 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
218 command_line->AppendSwitch(chromeos::switches::kGuestSession);
219 command_line->AppendSwitch(::switches::kIncognito);
220 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
221 command_line->AppendSwitchASCII(chromeos::switches::kLoginUser,
222 chromeos::UserManager::kGuestUserName);
223 }
224
225 private:
226 DISALLOW_COPY_AND_ASSIGN(GuestSpokenFeedbackTest);
227 };
228
IN_PROC_BROWSER_TEST_F(GuestSpokenFeedbackTest,FocusToolbar)229 IN_PROC_BROWSER_TEST_F(GuestSpokenFeedbackTest, FocusToolbar) {
230 EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
231
232 SpeechMonitor monitor;
233 AccessibilityManager::Get()->EnableSpokenFeedback(
234 true, ash::A11Y_NOTIFICATION_NONE);
235 EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
236
237 chrome::ExecuteCommand(browser(), IDC_FOCUS_TOOLBAR);
238 // Might be "Google Chrome Toolbar" or "Chromium Toolbar".
239 EXPECT_TRUE(MatchPattern(monitor.GetNextUtterance(), "*oolbar*"));
240 EXPECT_EQ("Reload,", monitor.GetNextUtterance());
241 EXPECT_EQ("button", monitor.GetNextUtterance());
242 }
243
244 //
245 // Spoken feedback tests of the out-of-box experience.
246 //
247
248 class OobeSpokenFeedbackTest : public InProcessBrowserTest {
249 protected:
OobeSpokenFeedbackTest()250 OobeSpokenFeedbackTest() {}
~OobeSpokenFeedbackTest()251 virtual ~OobeSpokenFeedbackTest() {}
252
SetUpCommandLine(CommandLine * command_line)253 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
254 command_line->AppendSwitch(chromeos::switches::kLoginManager);
255 command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
256 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
257 }
258
SetUpOnMainThread()259 virtual void SetUpOnMainThread() OVERRIDE {
260 AccessibilityManager::Get()->
261 SetProfileForTest(ProfileHelper::GetSigninProfile());
262 }
263
264 private:
265 DISALLOW_COPY_AND_ASSIGN(OobeSpokenFeedbackTest);
266 };
267
268 // Test is flaky: http://crbug.com/346797
IN_PROC_BROWSER_TEST_F(OobeSpokenFeedbackTest,DISABLED_SpokenFeedbackInOobe)269 IN_PROC_BROWSER_TEST_F(OobeSpokenFeedbackTest, DISABLED_SpokenFeedbackInOobe) {
270 ui_controls::EnableUIControls();
271 EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
272
273 LoginDisplayHost* login_display_host = LoginDisplayHostImpl::default_host();
274 WebUILoginView* web_ui_login_view = login_display_host->GetWebUILoginView();
275 views::Widget* widget = web_ui_login_view->GetWidget();
276 gfx::NativeWindow window = widget->GetNativeWindow();
277
278 SpeechMonitor monitor;
279 AccessibilityManager::Get()->EnableSpokenFeedback(
280 true, ash::A11Y_NOTIFICATION_NONE);
281 EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
282
283 EXPECT_EQ("Select your language:", monitor.GetNextUtterance());
284 EXPECT_EQ("English ( United States)", monitor.GetNextUtterance());
285 EXPECT_TRUE(MatchPattern(monitor.GetNextUtterance(), "Combo box * of *"));
286 ASSERT_TRUE(
287 ui_test_utils::SendKeyPressToWindowSync(
288 window, ui::VKEY_TAB, false, false, false, false));
289 EXPECT_EQ("Select your keyboard:", monitor.GetNextUtterance());
290 }
291
292 } // namespace chromeos
293