| Index: chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
 | 
| diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
 | 
| index ef47cedcffd9de516f4007f7b6a551a17bcfb2f0..c4b85ce30a83df2d4fbe581bf08d103f3e65db67 100644
 | 
| --- a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
 | 
| +++ b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
 | 
| @@ -21,6 +21,7 @@
 | 
|  #include "chrome/browser/ui/browser.h"
 | 
|  #include "chrome/browser/ui/browser_commands.h"
 | 
|  #include "chrome/browser/ui/browser_window.h"
 | 
| +#include "chrome/browser/ui/tabs/tab_strip_model.h"
 | 
|  #include "chrome/common/chrome_switches.h"
 | 
|  #include "chrome/common/extensions/extension_constants.h"
 | 
|  #include "chrome/test/base/in_process_browser_test.h"
 | 
| @@ -60,11 +61,24 @@
 | 
|    }
 | 
|  
 | 
|    void SendKeyPress(ui::KeyboardCode key) {
 | 
| -    gfx::NativeWindow root_window =
 | 
| -        ash::Shell::GetInstance()->GetPrimaryRootWindow();
 | 
| -    ASSERT_TRUE(
 | 
| -        ui_test_utils::SendKeyPressToWindowSync(
 | 
| -            root_window, key, false, false, false, false));
 | 
| +    ASSERT_NO_FATAL_FAILURE(
 | 
| +        ASSERT_TRUE(
 | 
| +            ui_test_utils::SendKeyPressToWindowSync(
 | 
| +                NULL, key, false, false, false, false)));
 | 
| +  }
 | 
| +
 | 
| +  void SendKeyPressWithControl(ui::KeyboardCode key) {
 | 
| +    ASSERT_NO_FATAL_FAILURE(
 | 
| +        ASSERT_TRUE(
 | 
| +            ui_test_utils::SendKeyPressToWindowSync(
 | 
| +                NULL, key, true, false, false, false)));
 | 
| +  }
 | 
| +
 | 
| +  void SendKeyPressWithSearchAndShift(ui::KeyboardCode key) {
 | 
| +    ASSERT_NO_FATAL_FAILURE(
 | 
| +        ASSERT_TRUE(
 | 
| +            ui_test_utils::SendKeyPressToWindowSync(
 | 
| +                NULL, key, false, true, false, true)));
 | 
|    }
 | 
|  
 | 
|    void RunJavaScriptInChromeVoxBackgroundPage(const std::string& script) {
 | 
| @@ -92,6 +106,37 @@
 | 
|          "cvox.ChromeVox.earcons.playEarcon = function() {};");
 | 
|    }
 | 
|  
 | 
| +  void LoadChromeVoxAndThenNavigateToURL(const GURL& url) {
 | 
| +    // The goal of this helper function is to avoid race conditions between
 | 
| +    // the page loading and the ChromeVox extension loading and fully
 | 
| +    // initializing. To do this, we first load a test url that repeatedly
 | 
| +    // asks ChromeVox to speak 'ready', then we load ChromeVox and block
 | 
| +    // until we get that 'ready' speech.
 | 
| +
 | 
| +    ui_test_utils::NavigateToURL(
 | 
| +        browser(),
 | 
| +        GURL("data:text/html;charset=utf-8,"
 | 
| +             "<script>"
 | 
| +             "window.setInterval(function() {"
 | 
| +             "  try {"
 | 
| +             "    cvox.Api.speak('ready');"
 | 
| +             "  } catch (e) {}"
 | 
| +             "}, 100);"
 | 
| +             "</script>"));
 | 
| +    EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
 | 
| +    AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| +        true, ash::A11Y_NOTIFICATION_NONE);
 | 
| +
 | 
| +    // Block until we get "ready".
 | 
| +    while (speech_monitor_.GetNextUtterance() != "ready") {
 | 
| +    }
 | 
| +
 | 
| +    // Now load the requested url.
 | 
| +    ui_test_utils::NavigateToURL(browser(), url);
 | 
| +  }
 | 
| +
 | 
| +  SpeechMonitor speech_monitor_;
 | 
| +
 | 
|   private:
 | 
|    StubBrailleController braille_controller_;
 | 
|    DISALLOW_COPY_AND_ASSIGN(LoggedInSpokenFeedbackTest);
 | 
| @@ -100,52 +145,51 @@
 | 
|  IN_PROC_BROWSER_TEST_F(LoggedInSpokenFeedbackTest, AddBookmark) {
 | 
|    EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
 | 
|  
 | 
| -  SpeechMonitor monitor;
 | 
| -  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| -      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| -  EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
 | 
| +  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| +      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| +  EXPECT_TRUE(speech_monitor_.SkipChromeVoxEnabledMessage());
 | 
|    DisableEarcons();
 | 
|  
 | 
|    chrome::ExecuteCommand(browser(), IDC_SHOW_BOOKMARK_BAR);
 | 
|  
 | 
|    // Create a bookmark with title "foo".
 | 
|    chrome::ExecuteCommand(browser(), IDC_BOOKMARK_PAGE);
 | 
| -  EXPECT_EQ("Bookmark added!,", monitor.GetNextUtterance());
 | 
| -  EXPECT_EQ("about blank,", monitor.GetNextUtterance());
 | 
| -  EXPECT_EQ("Bookmark name,", monitor.GetNextUtterance());
 | 
| -  EXPECT_EQ("text box", monitor.GetNextUtterance());
 | 
| +  EXPECT_EQ("Bookmark added!,", speech_monitor_.GetNextUtterance());
 | 
| +  EXPECT_EQ("about blank,", speech_monitor_.GetNextUtterance());
 | 
| +  EXPECT_EQ("Bookmark name,", speech_monitor_.GetNextUtterance());
 | 
| +  EXPECT_EQ("text box", speech_monitor_.GetNextUtterance());
 | 
|  
 | 
|    SendKeyPress(ui::VKEY_F);
 | 
| -  EXPECT_EQ("f", monitor.GetNextUtterance());
 | 
| +  EXPECT_EQ("f", speech_monitor_.GetNextUtterance());
 | 
|    SendKeyPress(ui::VKEY_O);
 | 
| -  EXPECT_EQ("o", monitor.GetNextUtterance());
 | 
| +  EXPECT_EQ("o", speech_monitor_.GetNextUtterance());
 | 
|    SendKeyPress(ui::VKEY_O);
 | 
| -  EXPECT_EQ("o", monitor.GetNextUtterance());
 | 
| +  EXPECT_EQ("o", speech_monitor_.GetNextUtterance());
 | 
|  
 | 
|    SendKeyPress(ui::VKEY_TAB);
 | 
| -  EXPECT_EQ("Bookmarks bar,", monitor.GetNextUtterance());
 | 
| -  EXPECT_EQ("Bookmark folder,", monitor.GetNextUtterance());
 | 
| -  EXPECT_TRUE(MatchPattern(monitor.GetNextUtterance(), "combo box*"));
 | 
| +  EXPECT_EQ("Bookmarks bar,", speech_monitor_.GetNextUtterance());
 | 
| +  EXPECT_EQ("Bookmark folder,", speech_monitor_.GetNextUtterance());
 | 
| +  EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "combo box*"));
 | 
|  
 | 
|    SendKeyPress(ui::VKEY_RETURN);
 | 
|  
 | 
| -  EXPECT_TRUE(MatchPattern(monitor.GetNextUtterance(), "*oolbar*"));
 | 
| +  EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "*oolbar*"));
 | 
|    // Wait for active window change to be announced to avoid interference from
 | 
|    // that below.
 | 
| -  while (monitor.GetNextUtterance() != "window about blank tab") {
 | 
| +  while (speech_monitor_.GetNextUtterance() != "window about blank tab") {
 | 
|      // Do nothing.
 | 
|    }
 | 
|  
 | 
|    // Focus bookmarks bar and listen for "foo".
 | 
|    chrome::ExecuteCommand(browser(), IDC_FOCUS_BOOKMARKS);
 | 
|    while (true) {
 | 
| -    std::string utterance = monitor.GetNextUtterance();
 | 
| +    std::string utterance = speech_monitor_.GetNextUtterance();
 | 
|      VLOG(0) << "Got utterance: " << utterance;
 | 
|      if (utterance == "Bookmarks,")
 | 
|        break;
 | 
|    }
 | 
| -  EXPECT_EQ("foo,", monitor.GetNextUtterance());
 | 
| -  EXPECT_EQ("button", monitor.GetNextUtterance());
 | 
| +  EXPECT_EQ("foo,", speech_monitor_.GetNextUtterance());
 | 
| +  EXPECT_EQ("button", speech_monitor_.GetNextUtterance());
 | 
|  }
 | 
|  
 | 
|  //
 | 
| @@ -185,66 +229,96 @@
 | 
|  IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, EnableSpokenFeedback) {
 | 
|    EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
 | 
|  
 | 
| -  SpeechMonitor monitor;
 | 
| -  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| -      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| -  EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
 | 
| +  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| +      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| +  EXPECT_TRUE(speech_monitor_.SkipChromeVoxEnabledMessage());
 | 
|  }
 | 
|  
 | 
|  IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, FocusToolbar) {
 | 
|    EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
 | 
|  
 | 
| -  SpeechMonitor monitor;
 | 
| -  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| -      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| -  EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
 | 
| +  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| +      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| +  EXPECT_TRUE(speech_monitor_.SkipChromeVoxEnabledMessage());
 | 
|    DisableEarcons();
 | 
|  
 | 
|    chrome::ExecuteCommand(browser(), IDC_FOCUS_TOOLBAR);
 | 
|    // Might be "Google Chrome Toolbar" or "Chromium Toolbar".
 | 
| -  EXPECT_TRUE(MatchPattern(monitor.GetNextUtterance(), "*oolbar*"));
 | 
| -  EXPECT_EQ("Reload,", monitor.GetNextUtterance());
 | 
| -  EXPECT_EQ("button", monitor.GetNextUtterance());
 | 
| +  EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "*oolbar*"));
 | 
| +  EXPECT_EQ("Reload,", speech_monitor_.GetNextUtterance());
 | 
| +  EXPECT_EQ("button", speech_monitor_.GetNextUtterance());
 | 
|  }
 | 
|  
 | 
|  IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, TypeInOmnibox) {
 | 
|    EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
 | 
|  
 | 
| -  SpeechMonitor monitor;
 | 
| -  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| -      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| -  EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
 | 
| +  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| +      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| +  EXPECT_TRUE(speech_monitor_.SkipChromeVoxEnabledMessage());
 | 
|    DisableEarcons();
 | 
|  
 | 
|    // Wait for ChromeVox to finish speaking.
 | 
|    chrome::ExecuteCommand(browser(), IDC_FOCUS_LOCATION);
 | 
|    while (true) {
 | 
| -    std::string utterance = monitor.GetNextUtterance();
 | 
| +    std::string utterance = speech_monitor_.GetNextUtterance();
 | 
|      VLOG(0) << "Got utterance: " << utterance;
 | 
|      if (utterance == "text box")
 | 
|        break;
 | 
|    }
 | 
|  
 | 
|    SendKeyPress(ui::VKEY_X);
 | 
| -  EXPECT_EQ("x", monitor.GetNextUtterance());
 | 
| +  EXPECT_EQ("x", speech_monitor_.GetNextUtterance());
 | 
|  
 | 
|    SendKeyPress(ui::VKEY_Y);
 | 
| -  EXPECT_EQ("y", monitor.GetNextUtterance());
 | 
| +  EXPECT_EQ("y", speech_monitor_.GetNextUtterance());
 | 
|  
 | 
|    SendKeyPress(ui::VKEY_Z);
 | 
| -  EXPECT_EQ("z", monitor.GetNextUtterance());
 | 
| +  EXPECT_EQ("z", speech_monitor_.GetNextUtterance());
 | 
|  
 | 
|    SendKeyPress(ui::VKEY_BACK);
 | 
| -  EXPECT_EQ("z", monitor.GetNextUtterance());
 | 
| +  EXPECT_EQ("z", speech_monitor_.GetNextUtterance());
 | 
| +}
 | 
| +
 | 
| +IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, ChromeVoxShiftSearch) {
 | 
| +  LoadChromeVoxAndThenNavigateToURL(
 | 
| +      GURL("data:text/html;charset=utf-8,<button autofocus>Click me</button>"));
 | 
| +  while (true) {
 | 
| +    std::string utterance = speech_monitor_.GetNextUtterance();
 | 
| +    if (utterance == "Click me")
 | 
| +      break;
 | 
| +  }
 | 
| +  EXPECT_EQ("Button", speech_monitor_.GetNextUtterance());
 | 
| +
 | 
| +  // Press Search+Shift+/ to enter ChromeVox's "find in page".
 | 
| +  SendKeyPressWithSearchAndShift(ui::VKEY_OEM_2);
 | 
| +  EXPECT_EQ("Find in page.", speech_monitor_.GetNextUtterance());
 | 
| +  EXPECT_EQ("Enter a search query.", speech_monitor_.GetNextUtterance());
 | 
| +}
 | 
| +
 | 
| +IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, ChromeVoxPrefixKey) {
 | 
| +  LoadChromeVoxAndThenNavigateToURL(
 | 
| +      GURL("data:text/html;charset=utf-8,<button autofocus>Click me</button>"));
 | 
| +  while (true) {
 | 
| +    std::string utterance = speech_monitor_.GetNextUtterance();
 | 
| +    if (utterance == "Click me")
 | 
| +      break;
 | 
| +  }
 | 
| +  EXPECT_EQ("Button", speech_monitor_.GetNextUtterance());
 | 
| +
 | 
| +  // Press the prefix key Ctrl+';' followed by '/'
 | 
| +  // to enter ChromeVox's "find in page".
 | 
| +  SendKeyPressWithControl(ui::VKEY_OEM_1);
 | 
| +  SendKeyPress(ui::VKEY_OEM_2);
 | 
| +  EXPECT_EQ("Find in page.", speech_monitor_.GetNextUtterance());
 | 
| +  EXPECT_EQ("Enter a search query.", speech_monitor_.GetNextUtterance());
 | 
|  }
 | 
|  
 | 
|  IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, TouchExploreStatusTray) {
 | 
|    EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
 | 
|  
 | 
| -  SpeechMonitor monitor;
 | 
| -  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| -      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| -  EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
 | 
| +  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| +      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| +  EXPECT_TRUE(speech_monitor_.SkipChromeVoxEnabledMessage());
 | 
|    DisableEarcons();
 | 
|  
 | 
|    SimulateTouchScreenInChromeVox();
 | 
| @@ -254,10 +328,10 @@
 | 
|    ash::SystemTray* tray = ash::Shell::GetInstance()->GetPrimarySystemTray();
 | 
|    tray->NotifyAccessibilityEvent(ui::AX_EVENT_HOVER, true);
 | 
|  
 | 
| -  EXPECT_EQ("Status tray,", monitor.GetNextUtterance());
 | 
| -  EXPECT_TRUE(MatchPattern(monitor.GetNextUtterance(), "time*,"));
 | 
| -  EXPECT_TRUE(MatchPattern(monitor.GetNextUtterance(), "Battery*,"));
 | 
| -  EXPECT_EQ("button", monitor.GetNextUtterance());
 | 
| +  EXPECT_EQ("Status tray,", speech_monitor_.GetNextUtterance());
 | 
| +  EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "time*,"));
 | 
| +  EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "Battery*,"));
 | 
| +  EXPECT_EQ("button", speech_monitor_.GetNextUtterance());
 | 
|  }
 | 
|  
 | 
|  //
 | 
| @@ -284,17 +358,16 @@
 | 
|  IN_PROC_BROWSER_TEST_F(GuestSpokenFeedbackTest, FocusToolbar) {
 | 
|    EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
 | 
|  
 | 
| -  SpeechMonitor monitor;
 | 
| -  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| -      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| -  EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
 | 
| +  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| +      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| +  EXPECT_TRUE(speech_monitor_.SkipChromeVoxEnabledMessage());
 | 
|    DisableEarcons();
 | 
|  
 | 
|    chrome::ExecuteCommand(browser(), IDC_FOCUS_TOOLBAR);
 | 
|    // Might be "Google Chrome Toolbar" or "Chromium Toolbar".
 | 
| -  EXPECT_TRUE(MatchPattern(monitor.GetNextUtterance(), "*oolbar*"));
 | 
| -  EXPECT_EQ("Reload,", monitor.GetNextUtterance());
 | 
| -  EXPECT_EQ("button", monitor.GetNextUtterance());
 | 
| +  EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(), "*oolbar*"));
 | 
| +  EXPECT_EQ("Reload,", speech_monitor_.GetNextUtterance());
 | 
| +  EXPECT_EQ("button", speech_monitor_.GetNextUtterance());
 | 
|  }
 | 
|  
 | 
|  //
 | 
| @@ -317,6 +390,8 @@
 | 
|          SetProfileForTest(ProfileHelper::GetSigninProfile());
 | 
|    }
 | 
|  
 | 
| +  SpeechMonitor speech_monitor_;
 | 
| +
 | 
|   private:
 | 
|    DISALLOW_COPY_AND_ASSIGN(OobeSpokenFeedbackTest);
 | 
|  };
 | 
| @@ -331,18 +406,18 @@
 | 
|    views::Widget* widget = web_ui_login_view->GetWidget();
 | 
|    gfx::NativeWindow window = widget->GetNativeWindow();
 | 
|  
 | 
| -  SpeechMonitor monitor;
 | 
| -  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| -      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| -  EXPECT_TRUE(monitor.SkipChromeVoxEnabledMessage());
 | 
| -
 | 
| -  EXPECT_EQ("Select your language:", monitor.GetNextUtterance());
 | 
| -  EXPECT_EQ("English ( United States)", monitor.GetNextUtterance());
 | 
| -  EXPECT_TRUE(MatchPattern(monitor.GetNextUtterance(), "Combo box * of *"));
 | 
| +  AccessibilityManager::Get()->EnableSpokenFeedback(
 | 
| +      true, ash::A11Y_NOTIFICATION_NONE);
 | 
| +  EXPECT_TRUE(speech_monitor_.SkipChromeVoxEnabledMessage());
 | 
| +
 | 
| +  EXPECT_EQ("Select your language:", speech_monitor_.GetNextUtterance());
 | 
| +  EXPECT_EQ("English ( United States)", speech_monitor_.GetNextUtterance());
 | 
| +  EXPECT_TRUE(MatchPattern(speech_monitor_.GetNextUtterance(),
 | 
| +                           "Combo box * of *"));
 | 
|    ASSERT_TRUE(
 | 
|        ui_test_utils::SendKeyPressToWindowSync(
 | 
|            window, ui::VKEY_TAB, false, false, false, false));
 | 
| -  EXPECT_EQ("Select your keyboard:", monitor.GetNextUtterance());
 | 
| +  EXPECT_EQ("Select your keyboard:", speech_monitor_.GetNextUtterance());
 | 
|  }
 | 
|  
 | 
|  }  // namespace chromeos
 | 
| 
 |