Make chrome/browser/chromeos/accessibility compile on Athena with use_ash=0
[chromium-blink-merge.git] / chrome / browser / chromeos / accessibility / spoken_feedback_browsertest.cc
blob450aa723a2c4b8e92c1ae1a6c5c73dd49bb496ae
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.
5 #include <queue>
7 #include "ash/accelerators/accelerator_controller.h"
8 #include "ash/accelerators/accelerator_table.h"
9 #include "ash/shell.h"
10 #include "ash/system/tray/system_tray.h"
11 #include "base/command_line.h"
12 #include "base/strings/string_util.h"
13 #include "chrome/app/chrome_command_ids.h"
14 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
15 #include "chrome/browser/chromeos/accessibility/speech_monitor.h"
16 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
17 #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h"
18 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
19 #include "chrome/browser/chromeos/profiles/profile_helper.h"
20 #include "chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h"
21 #include "chrome/browser/speech/tts_controller.h"
22 #include "chrome/browser/speech/tts_platform.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_commands.h"
25 #include "chrome/browser/ui/browser_window.h"
26 #include "chrome/browser/ui/tabs/tab_strip_model.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/extensions/extension_constants.h"
29 #include "chrome/test/base/in_process_browser_test.h"
30 #include "chrome/test/base/interactive_test_utils.h"
31 #include "chrome/test/base/testing_profile.h"
32 #include "chrome/test/base/ui_test_utils.h"
33 #include "chromeos/chromeos_switches.h"
34 #include "chromeos/login/user_names.h"
35 #include "content/public/common/url_constants.h"
36 #include "content/public/test/browser_test_utils.h"
37 #include "content/public/test/test_utils.h"
38 #include "extensions/browser/extension_host.h"
39 #include "extensions/browser/process_manager.h"
40 #include "testing/gtest/include/gtest/gtest.h"
41 #include "ui/base/test/ui_controls.h"
42 #include "ui/views/widget/widget.h"
44 using extensions::api::braille_display_private::StubBrailleController;
46 namespace chromeos {
49 // Spoken feedback tests only in a logged in user's window.
52 class LoggedInSpokenFeedbackTest : public InProcessBrowserTest {
53 protected:
54 LoggedInSpokenFeedbackTest() {}
55 virtual ~LoggedInSpokenFeedbackTest() {}
57 virtual void SetUpInProcessBrowserTestFixture() override {
58 AccessibilityManager::SetBrailleControllerForTest(&braille_controller_);
61 virtual void TearDownOnMainThread() override {
62 AccessibilityManager::SetBrailleControllerForTest(NULL);
65 void SendKeyPress(ui::KeyboardCode key) {
66 ASSERT_NO_FATAL_FAILURE(
67 ASSERT_TRUE(
68 ui_test_utils::SendKeyPressToWindowSync(
69 NULL, key, false, false, false, false)));
72 void SendKeyPressWithControl(ui::KeyboardCode key) {
73 ASSERT_NO_FATAL_FAILURE(
74 ASSERT_TRUE(
75 ui_test_utils::SendKeyPressToWindowSync(
76 NULL, key, true, false, false, false)));
79 void SendKeyPressWithSearchAndShift(ui::KeyboardCode key) {
80 ASSERT_NO_FATAL_FAILURE(
81 ASSERT_TRUE(
82 ui_test_utils::SendKeyPressToWindowSync(
83 NULL, key, false, true, false, true)));
86 void RunJavaScriptInChromeVoxBackgroundPage(const std::string& script) {
87 extensions::ExtensionHost* host =
88 extensions::ProcessManager::Get(browser()->profile())
89 ->GetBackgroundHostForExtension(
90 extension_misc::kChromeVoxExtensionId);
91 CHECK(content::ExecuteScript(host->host_contents(), script));
94 void SimulateTouchScreenInChromeVox() {
95 // ChromeVox looks at whether 'ontouchstart' exists to know whether
96 // or not it should respond to hover events. Fake it so that touch
97 // exploration events get spoken.
98 RunJavaScriptInChromeVoxBackgroundPage(
99 "window.ontouchstart = function() {};");
102 bool PerformAcceleratorAction(int action) {
103 ash::AcceleratorController* controller =
104 ash::Shell::GetInstance()->accelerator_controller();
105 return controller->PerformAction(action, ui::Accelerator());
108 void DisableEarcons() {
109 // Playing earcons from within a test is not only annoying if you're
110 // running the test locally, but seems to cause crashes
111 // (http://crbug.com/396507). Work around this by just telling
112 // ChromeVox to not ever play earcons (prerecorded sound effects).
113 RunJavaScriptInChromeVoxBackgroundPage(
114 "cvox.ChromeVox.earcons.playEarcon = function() {};");
117 void EnableChromeVox() {
118 // Test setup.
119 // Enable ChromeVox, skip welcome message, and disable earcons.
120 ASSERT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
122 AccessibilityManager::Get()->EnableSpokenFeedback(
123 true, ui::A11Y_NOTIFICATION_NONE);
124 EXPECT_TRUE(speech_monitor_.SkipChromeVoxEnabledMessage());
125 DisableEarcons();
128 void LoadChromeVoxAndThenNavigateToURL(const GURL& url) {
129 // The goal of this helper function is to avoid race conditions between
130 // the page loading and the ChromeVox extension loading and fully
131 // initializing. To do this, we first load a test url that repeatedly
132 // asks ChromeVox to speak 'ready', then we load ChromeVox and block
133 // until we get that 'ready' speech.
135 ui_test_utils::NavigateToURL(
136 browser(),
137 GURL("data:text/html;charset=utf-8,"
138 "<script>"
139 "window.setInterval(function() {"
140 " try {"
141 " cvox.Api.speak('ready');"
142 " } catch (e) {}"
143 "}, 100);"
144 "</script>"));
145 EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
146 AccessibilityManager::Get()->EnableSpokenFeedback(
147 true, ui::A11Y_NOTIFICATION_NONE);
149 // Block until we get "ready".
150 while (speech_monitor_.GetNextUtterance() != "ready") {
153 // Now load the requested url.
154 ui_test_utils::NavigateToURL(browser(), url);
157 void PressRepeatedlyUntilUtterance(ui::KeyboardCode key,
158 const std::string& expected_utterance) {
159 // This helper function is needed when you want to poll for something
160 // that happens asynchronously. Keep pressing |key|, until
161 // the speech feedback that follows is |expected_utterance|.
162 // Note that this doesn't work if pressing that key doesn't speak anything
163 // at all before the asynchronous event occurred.
164 while (true) {
165 SendKeyPress(key);
166 const std::string& utterance = speech_monitor_.GetNextUtterance();
167 if (utterance == expected_utterance)
168 break;
172 SpeechMonitor speech_monitor_;
174 private:
175 StubBrailleController braille_controller_;
176 DISALLOW_COPY_AND_ASSIGN(LoggedInSpokenFeedbackTest);
179 IN_PROC_BROWSER_TEST_F(LoggedInSpokenFeedbackTest, AddBookmark) {
180 EnableChromeVox();
181 chrome::ExecuteCommand(browser(), IDC_SHOW_BOOKMARK_BAR);
183 // Create a bookmark with title "foo".
184 chrome::ExecuteCommand(browser(), IDC_BOOKMARK_PAGE);
185 EXPECT_EQ("Bookmark added!,", speech_monitor_.GetNextUtterance());
186 EXPECT_EQ("about blank,", speech_monitor_.GetNextUtterance());
187 EXPECT_EQ("Bookmark name,", speech_monitor_.GetNextUtterance());
188 EXPECT_EQ("text box", speech_monitor_.GetNextUtterance());
190 SendKeyPress(ui::VKEY_F);
191 EXPECT_EQ("f", speech_monitor_.GetNextUtterance());
192 SendKeyPress(ui::VKEY_O);
193 EXPECT_EQ("o", speech_monitor_.GetNextUtterance());
194 SendKeyPress(ui::VKEY_O);
195 EXPECT_EQ("o", speech_monitor_.GetNextUtterance());
197 SendKeyPress(ui::VKEY_TAB);
198 EXPECT_EQ("Bookmarks bar,", speech_monitor_.GetNextUtterance());
199 EXPECT_EQ("Bookmark folder,", speech_monitor_.GetNextUtterance());
200 EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "combo box*"));
202 SendKeyPress(ui::VKEY_RETURN);
204 EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "*oolbar*"));
205 // Wait for active window change to be announced to avoid interference from
206 // that below.
207 while (speech_monitor_.GetNextUtterance() != "window about blank tab") {
208 // Do nothing.
211 // Focus bookmarks bar and listen for "foo".
212 chrome::ExecuteCommand(browser(), IDC_FOCUS_BOOKMARKS);
213 while (true) {
214 std::string utterance = speech_monitor_.GetNextUtterance();
215 VLOG(0) << "Got utterance: " << utterance;
216 if (utterance == "Bookmarks,")
217 break;
219 EXPECT_EQ("foo,", speech_monitor_.GetNextUtterance());
220 EXPECT_EQ("button", speech_monitor_.GetNextUtterance());
224 // Spoken feedback tests in both a logged in browser window and guest mode.
227 enum SpokenFeedbackTestVariant {
228 kTestAsNormalUser,
229 kTestAsGuestUser
232 class SpokenFeedbackTest
233 : public LoggedInSpokenFeedbackTest,
234 public ::testing::WithParamInterface<SpokenFeedbackTestVariant> {
235 protected:
236 SpokenFeedbackTest() {}
237 virtual ~SpokenFeedbackTest() {}
239 virtual void SetUpCommandLine(CommandLine* command_line) override {
240 if (GetParam() == kTestAsGuestUser) {
241 command_line->AppendSwitch(chromeos::switches::kGuestSession);
242 command_line->AppendSwitch(::switches::kIncognito);
243 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile,
244 "user");
245 command_line->AppendSwitchASCII(chromeos::switches::kLoginUser,
246 chromeos::login::kGuestUserName);
251 INSTANTIATE_TEST_CASE_P(
252 TestAsNormalAndGuestUser,
253 SpokenFeedbackTest,
254 ::testing::Values(kTestAsNormalUser,
255 kTestAsGuestUser));
257 IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, EnableSpokenFeedback) {
258 EnableChromeVox();
261 IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, FocusToolbar) {
262 EnableChromeVox();
264 chrome::ExecuteCommand(browser(), IDC_FOCUS_TOOLBAR);
265 // Might be "Google Chrome Toolbar" or "Chromium Toolbar".
266 EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "*oolbar*"));
267 EXPECT_EQ("Reload,", speech_monitor_.GetNextUtterance());
268 EXPECT_EQ("button", speech_monitor_.GetNextUtterance());
271 IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, TypeInOmnibox) {
272 EnableChromeVox();
274 // Wait for ChromeVox to finish speaking.
275 chrome::ExecuteCommand(browser(), IDC_FOCUS_LOCATION);
276 while (true) {
277 std::string utterance = speech_monitor_.GetNextUtterance();
278 VLOG(0) << "Got utterance: " << utterance;
279 if (utterance == "text box")
280 break;
283 SendKeyPress(ui::VKEY_X);
284 EXPECT_EQ("x", speech_monitor_.GetNextUtterance());
286 SendKeyPress(ui::VKEY_Y);
287 EXPECT_EQ("y", speech_monitor_.GetNextUtterance());
289 SendKeyPress(ui::VKEY_Z);
290 EXPECT_EQ("z", speech_monitor_.GetNextUtterance());
292 SendKeyPress(ui::VKEY_BACK);
293 EXPECT_EQ("z", speech_monitor_.GetNextUtterance());
296 IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, FocusShelf) {
297 EnableChromeVox();
299 EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF));
301 EXPECT_EQ("Shelf,", speech_monitor_.GetNextUtterance());
302 EXPECT_EQ("Apps,", speech_monitor_.GetNextUtterance());
303 EXPECT_EQ("button", speech_monitor_.GetNextUtterance());
306 IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, ChromeVoxShiftSearch) {
307 LoadChromeVoxAndThenNavigateToURL(
308 GURL("data:text/html;charset=utf-8,<button autofocus>Click me</button>"));
309 while (true) {
310 std::string utterance = speech_monitor_.GetNextUtterance();
311 if (utterance == "Click me")
312 break;
314 EXPECT_EQ("Button", speech_monitor_.GetNextUtterance());
316 // Press Search+Shift+/ to enter ChromeVox's "find in page".
317 SendKeyPressWithSearchAndShift(ui::VKEY_OEM_2);
318 EXPECT_EQ("Find in page.", speech_monitor_.GetNextUtterance());
319 EXPECT_EQ("Enter a search query.", speech_monitor_.GetNextUtterance());
322 IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, ChromeVoxPrefixKey) {
323 LoadChromeVoxAndThenNavigateToURL(
324 GURL("data:text/html;charset=utf-8,<button autofocus>Click me</button>"));
325 while (true) {
326 std::string utterance = speech_monitor_.GetNextUtterance();
327 if (utterance == "Click me")
328 break;
330 EXPECT_EQ("Button", speech_monitor_.GetNextUtterance());
332 // Press the prefix key Ctrl+';' followed by '/'
333 // to enter ChromeVox's "find in page".
334 SendKeyPressWithControl(ui::VKEY_OEM_1);
335 SendKeyPress(ui::VKEY_OEM_2);
336 EXPECT_EQ("Find in page.", speech_monitor_.GetNextUtterance());
337 EXPECT_EQ("Enter a search query.", speech_monitor_.GetNextUtterance());
340 IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, ChromeVoxNavigateAndSelect) {
341 LoadChromeVoxAndThenNavigateToURL(
342 GURL("data:text/html;charset=utf-8,"
343 "<h1>Title</h1>"
344 "<button autofocus>Click me</button>"));
345 while (true) {
346 std::string utterance = speech_monitor_.GetNextUtterance();
347 if (utterance == "Click me")
348 break;
350 EXPECT_EQ("Button", speech_monitor_.GetNextUtterance());
352 // Press Search+Shift+Up to navigate to the previous item.
353 SendKeyPressWithSearchAndShift(ui::VKEY_UP);
354 EXPECT_EQ("Title", speech_monitor_.GetNextUtterance());
355 EXPECT_EQ("Heading 1", speech_monitor_.GetNextUtterance());
357 // Press Search+Shift+S to select the text.
358 SendKeyPressWithSearchAndShift(ui::VKEY_S);
359 EXPECT_EQ("Start selection", speech_monitor_.GetNextUtterance());
360 EXPECT_EQ("Title", speech_monitor_.GetNextUtterance());
361 EXPECT_EQ(", selected", speech_monitor_.GetNextUtterance());
363 // Press again to end the selection.
364 SendKeyPressWithSearchAndShift(ui::VKEY_S);
365 EXPECT_EQ("End selection", speech_monitor_.GetNextUtterance());
366 EXPECT_EQ("Title", speech_monitor_.GetNextUtterance());
369 // flaky: http://crbug.com/418572
370 IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, DISABLED_ChromeVoxStickyMode) {
371 LoadChromeVoxAndThenNavigateToURL(
372 GURL("data:text/html;charset=utf-8,"
373 "<label>Enter your name <input autofocus></label>"
374 "<p>One</p>"
375 "<h2>Two</h2>"));
376 while (speech_monitor_.GetNextUtterance() != "Enter your name") {
378 EXPECT_EQ("Edit text", speech_monitor_.GetNextUtterance());
380 // Press the sticky-key sequence: Search Search.
381 SendKeyPress(ui::VKEY_LWIN);
382 SendKeyPress(ui::VKEY_LWIN);
383 EXPECT_EQ("Sticky mode enabled", speech_monitor_.GetNextUtterance());
385 // Even once we hear "sticky mode enabled" from the ChromeVox background
386 // page, there's a short window of time when the content script still
387 // hasn't switched to sticky mode. That's why we're focused on a text box.
388 // Keep pressing the '/' key. If sticky mode is off, it will echo the word
389 // "slash". If sticky mode is on, it will open "Find in page". Keep pressing
390 // '/' until we get "Find in page.".
391 PressRepeatedlyUntilUtterance(ui::VKEY_OEM_2, "Find in page.");
392 EXPECT_EQ("Enter a search query.", speech_monitor_.GetNextUtterance());
394 // Press Esc to exit Find in Page mode.
395 SendKeyPress(ui::VKEY_ESCAPE);
396 EXPECT_EQ("Exited", speech_monitor_.GetNextUtterance());
397 EXPECT_EQ("Find in page.", speech_monitor_.GetNextUtterance());
399 // Press N H to jump to the next heading. Skip over speech in-between
400 // but make sure we end up at the heading.
401 SendKeyPress(ui::VKEY_N);
402 SendKeyPress(ui::VKEY_H);
403 while (speech_monitor_.GetNextUtterance() != "Two") {
405 EXPECT_EQ("Heading 2", speech_monitor_.GetNextUtterance());
407 // Press the up arrow to go to the previous element.
408 SendKeyPress(ui::VKEY_UP);
409 EXPECT_EQ("One", speech_monitor_.GetNextUtterance());
412 IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, TouchExploreStatusTray) {
413 EnableChromeVox();
414 SimulateTouchScreenInChromeVox();
416 // Send an accessibility hover event on the system tray, which is
417 // what we get when you tap it on a touch screen when ChromeVox is on.
418 ash::SystemTray* tray = ash::Shell::GetInstance()->GetPrimarySystemTray();
419 tray->NotifyAccessibilityEvent(ui::AX_EVENT_HOVER, true);
421 EXPECT_EQ("Status tray,", speech_monitor_.GetNextUtterance());
422 EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "time*,"));
423 EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "Battery*,"));
424 EXPECT_EQ("button", speech_monitor_.GetNextUtterance());
428 // Spoken feedback tests that run only in guest mode.
431 class GuestSpokenFeedbackTest : public LoggedInSpokenFeedbackTest {
432 protected:
433 GuestSpokenFeedbackTest() {}
434 virtual ~GuestSpokenFeedbackTest() {}
436 virtual void SetUpCommandLine(CommandLine* command_line) override {
437 command_line->AppendSwitch(chromeos::switches::kGuestSession);
438 command_line->AppendSwitch(::switches::kIncognito);
439 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
440 command_line->AppendSwitchASCII(chromeos::switches::kLoginUser,
441 chromeos::login::kGuestUserName);
444 private:
445 DISALLOW_COPY_AND_ASSIGN(GuestSpokenFeedbackTest);
448 IN_PROC_BROWSER_TEST_F(GuestSpokenFeedbackTest, FocusToolbar) {
449 EnableChromeVox();
451 chrome::ExecuteCommand(browser(), IDC_FOCUS_TOOLBAR);
452 // Might be "Google Chrome Toolbar" or "Chromium Toolbar".
453 EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "*oolbar*"));
454 EXPECT_EQ("Reload,", speech_monitor_.GetNextUtterance());
455 EXPECT_EQ("button", speech_monitor_.GetNextUtterance());
459 // Spoken feedback tests of the out-of-box experience.
462 class OobeSpokenFeedbackTest : public InProcessBrowserTest {
463 protected:
464 OobeSpokenFeedbackTest() {}
465 virtual ~OobeSpokenFeedbackTest() {}
467 virtual void SetUpCommandLine(CommandLine* command_line) override {
468 command_line->AppendSwitch(chromeos::switches::kLoginManager);
469 command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
470 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
473 virtual void SetUpOnMainThread() override {
474 AccessibilityManager::Get()->
475 SetProfileForTest(ProfileHelper::GetSigninProfile());
478 SpeechMonitor speech_monitor_;
480 private:
481 DISALLOW_COPY_AND_ASSIGN(OobeSpokenFeedbackTest);
484 // Test is flaky: http://crbug.com/346797
485 IN_PROC_BROWSER_TEST_F(OobeSpokenFeedbackTest, DISABLED_SpokenFeedbackInOobe) {
486 ui_controls::EnableUIControls();
487 ASSERT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
489 LoginDisplayHost* login_display_host = LoginDisplayHostImpl::default_host();
490 WebUILoginView* web_ui_login_view = login_display_host->GetWebUILoginView();
491 views::Widget* widget = web_ui_login_view->GetWidget();
492 gfx::NativeWindow window = widget->GetNativeWindow();
494 AccessibilityManager::Get()->EnableSpokenFeedback(
495 true, ui::A11Y_NOTIFICATION_NONE);
496 EXPECT_TRUE(speech_monitor_.SkipChromeVoxEnabledMessage());
498 EXPECT_EQ("Select your language:", speech_monitor_.GetNextUtterance());
499 EXPECT_EQ("English ( United States)", speech_monitor_.GetNextUtterance());
500 EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(),
501 "Combo box * of *"));
502 ASSERT_TRUE(
503 ui_test_utils::SendKeyPressToWindowSync(
504 window, ui::VKEY_TAB, false, false, false, false));
505 EXPECT_EQ("Select your keyboard:", speech_monitor_.GetNextUtterance());
508 } // namespace chromeos