Commit 23c5921b authored by Johann Koenig's avatar Johann Koenig Committed by Commit Bot

Revert "Remove the blocking apis in SpeechMonitor"

This reverts commit 4e3c8ff8.

Reason for revert: ChromeOS bot failures

Bug: chromium:1065746

Original change's description:
> Remove the blocking apis in SpeechMonitor
> 
> - convert all callers to use the async api
> - some misc cleanup in SpokenFeedbackBrowserTest
> 
> Run these against debug and release; use both 5 and 10 parallel jobs which should load the tests enough to catch flakes.
> 
> Test: browser_tests against all relevant suites (SelectToSpeak*, Spoken*, and *.EnableChromeVox).
> Change-Id: I1b425b8640433b7608d84aa67f1cf5900ce26638
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2124701
> Reviewed-by: Nancy Wang <nancylingwang@chromium.org>
> Reviewed-by: Dominic Mazzoni <dmazzoni@chromium.org>
> Commit-Queue: David Tseng <dtseng@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#754319}

TBR=dmazzoni@chromium.org,dtseng@chromium.org,nancylingwang@chromium.org,nancylingwang@google.com

# Not skipping CQ checks because original CL landed > 1 day ago.

Change-Id: I121b1d503547f3fc54597527ecbdb95ee65b9511
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2126328Reviewed-by: default avatarJohann Koenig <johannkoenig@google.com>
Commit-Queue: Johann Koenig <johannkoenig@google.com>
Cr-Commit-Position: refs/heads/master@{#754374}
parent dfa4a7a6
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/strings/pattern.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/browser/chromeos/accessibility/speech_monitor.h" #include "chrome/browser/chromeos/accessibility/speech_monitor.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
...@@ -73,7 +74,7 @@ class SelectToSpeakTest : public InProcessBrowserTest { ...@@ -73,7 +74,7 @@ class SelectToSpeakTest : public InProcessBrowserTest {
ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
} }
SpeechMonitor sm_; SpeechMonitor speech_monitor_;
std::unique_ptr<ui::test::EventGenerator> generator_; std::unique_ptr<ui::test::EventGenerator> generator_;
gfx::Rect GetWebContentsBounds() const { gfx::Rect GetWebContentsBounds() const {
...@@ -139,8 +140,8 @@ class SelectToSpeakTest : public InProcessBrowserTest { ...@@ -139,8 +140,8 @@ class SelectToSpeakTest : public InProcessBrowserTest {
return browser()->tab_strip_model()->GetActiveWebContents(); return browser()->tab_strip_model()->GetActiveWebContents();
} }
void ExecuteJavaScriptAsync(const std::string& script) { void ExecuteJavaScriptInForeground(const std::string& script) {
content::ExecuteScriptAsync(GetWebContents(), script); CHECK(content::ExecuteScript(GetWebContents(), script));
} }
private: private:
...@@ -175,8 +176,8 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SpeakStatusTray) { ...@@ -175,8 +176,8 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SpeakStatusTray) {
generator_->ReleaseLeftButton(); generator_->ReleaseLeftButton();
generator_->ReleaseKey(ui::VKEY_LWIN, 0 /* flags */); generator_->ReleaseKey(ui::VKEY_LWIN, 0 /* flags */);
sm_.ExpectSpeechPattern("Status tray*"); EXPECT_TRUE(
sm_.Replay(); base::MatchPattern(speech_monitor_.GetNextUtterance(), "Status tray*"));
} }
IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, ActivatesWithTapOnSelectToSpeakTray) { IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, ActivatesWithTapOnSelectToSpeakTray) {
...@@ -198,8 +199,8 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, ActivatesWithTapOnSelectToSpeakTray) { ...@@ -198,8 +199,8 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, ActivatesWithTapOnSelectToSpeakTray) {
bounds.y() + bounds.height()); bounds.y() + bounds.height());
generator_->ReleaseLeftButton(); generator_->ReleaseLeftButton();
sm_.ExpectSpeechPattern("This is some text*"); EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(),
sm_.Replay(); "This is some text*"));
} }
IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SelectToSpeakTrayNotSpoken) { IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SelectToSpeakTrayNotSpoken) {
...@@ -217,9 +218,8 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SelectToSpeakTrayNotSpoken) { ...@@ -217,9 +218,8 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SelectToSpeakTrayNotSpoken) {
// The next should be the first thing spoken -- the tray was not spoken. // The next should be the first thing spoken -- the tray was not spoken.
ActivateSelectToSpeakInWindowBounds( ActivateSelectToSpeakInWindowBounds(
"data:text/html;charset=utf-8,<p>This is some text</p>"); "data:text/html;charset=utf-8,<p>This is some text</p>");
EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(),
sm_.ExpectSpeechPattern("This is some text*"); "This is some text*"));
sm_.Replay();
} }
IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossInlineUrl) { IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossInlineUrl) {
...@@ -230,8 +230,9 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossInlineUrl) { ...@@ -230,8 +230,9 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossInlineUrl) {
// Should combine nodes in a paragraph into one utterance. // Should combine nodes in a paragraph into one utterance.
// Includes some wildcards between words because there may be extra // Includes some wildcards between words because there may be extra
// spaces. Spaces are not pronounced, so extra spaces do not impact output. // spaces. Spaces are not pronounced, so extra spaces do not impact output.
sm_.ExpectSpeechPattern("This is some text*with a node*in the middle*"); EXPECT_TRUE(
sm_.Replay(); base::MatchPattern(speech_monitor_.GetNextUtterance(),
"This is some text*with a node*in the middle*"));
} }
IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossMultipleLines) { IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossMultipleLines) {
...@@ -244,8 +245,9 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossMultipleLines) { ...@@ -244,8 +245,9 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossMultipleLines) {
// spaces, for example at line wraps. Extra wildcards included to // spaces, for example at line wraps. Extra wildcards included to
// reduce flakyness in case wrapping is not consistent. // reduce flakyness in case wrapping is not consistent.
// Spaces are not pronounced, so extra spaces do not impact output. // Spaces are not pronounced, so extra spaces do not impact output.
sm_.ExpectSpeechPattern("This is some*text*with*a*node*in*the*middle*"); EXPECT_TRUE(
sm_.Replay(); base::MatchPattern(speech_monitor_.GetNextUtterance(),
"This is some*text*with*a*node*in*the*middle*"));
} }
IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossFormattedText) { IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossFormattedText) {
...@@ -257,8 +259,9 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossFormattedText) { ...@@ -257,8 +259,9 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossFormattedText) {
// Should combine nodes in a paragraph into one utterance. // Should combine nodes in a paragraph into one utterance.
// Includes some wildcards between words because there may be extra // Includes some wildcards between words because there may be extra
// spaces. Spaces are not pronounced, so extra spaces do not impact output. // spaces. Spaces are not pronounced, so extra spaces do not impact output.
sm_.ExpectSpeechPattern("This is some text*with a node*in the middle*"); EXPECT_TRUE(
sm_.Replay(); base::MatchPattern(speech_monitor_.GetNextUtterance(),
"This is some text*with a node*in the middle*"));
} }
IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, IN_PROC_BROWSER_TEST_F(SelectToSpeakTest,
...@@ -266,9 +269,8 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, ...@@ -266,9 +269,8 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest,
// Bold or formatted text // Bold or formatted text
ActivateSelectToSpeakInWindowBounds( ActivateSelectToSpeakInWindowBounds(
"data:text/html;charset=utf-8,<canvas>This is some text</canvas>"); "data:text/html;charset=utf-8,<canvas>This is some text</canvas>");
EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(),
sm_.ExpectSpeechPattern("This is some text*"); "This is some text*"));
sm_.Replay();
} }
IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, BreaksAtParagraphBounds) { IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, BreaksAtParagraphBounds) {
...@@ -277,9 +279,10 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, BreaksAtParagraphBounds) { ...@@ -277,9 +279,10 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, BreaksAtParagraphBounds) {
"<p>Second paragraph</p></div>"); "<p>Second paragraph</p></div>");
// Should keep each paragraph as its own utterance. // Should keep each paragraph as its own utterance.
sm_.ExpectSpeechPattern("First paragraph*"); EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(),
sm_.ExpectSpeechPattern("Second paragraph*"); "First paragraph*"));
sm_.Replay(); EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(),
"Second paragraph*"));
} }
IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, LanguageBoundsIgnoredByDefault) { IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, LanguageBoundsIgnoredByDefault) {
...@@ -290,8 +293,9 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, LanguageBoundsIgnoredByDefault) { ...@@ -290,8 +293,9 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, LanguageBoundsIgnoredByDefault) {
"<span lang='en-US'>The first paragraph</span>" "<span lang='en-US'>The first paragraph</span>"
"<span lang='fr-FR'>la deuxième paragraphe</span></div>"); "<span lang='fr-FR'>la deuxième paragraphe</span></div>");
sm_.ExpectSpeechPattern("The first paragraph* la deuxième paragraphe*"); EXPECT_TRUE(
sm_.Replay(); base::MatchPattern(speech_monitor_.GetNextUtterance(),
"The first paragraph* la deuxième paragraphe*"));
} }
IN_PROC_BROWSER_TEST_F(SelectToSpeakTestWithLanguageDetection, IN_PROC_BROWSER_TEST_F(SelectToSpeakTestWithLanguageDetection,
...@@ -301,9 +305,15 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTestWithLanguageDetection, ...@@ -301,9 +305,15 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTestWithLanguageDetection,
"<span lang='en-US'>The first paragraph</span>" "<span lang='en-US'>The first paragraph</span>"
"<span lang='fr-FR'>la deuxième paragraphe</span></div>"); "<span lang='fr-FR'>la deuxième paragraphe</span></div>");
sm_.ExpectSpeechPatternWithLocale("The first paragraph*", "en-US"); SpeechMonitorUtterance result1 =
sm_.ExpectSpeechPatternWithLocale("la deuxième paragraphe*", "fr-FR"); speech_monitor_.GetNextUtteranceWithLanguage();
sm_.Replay(); EXPECT_TRUE(base::MatchPattern(result1.text, "The first paragraph*"));
EXPECT_EQ("en-US", result1.lang);
SpeechMonitorUtterance result2 =
speech_monitor_.GetNextUtteranceWithLanguage();
EXPECT_TRUE(base::MatchPattern(result2.text, "la deuxième paragraphe*"));
EXPECT_EQ("fr-FR", result2.lang);
} }
// Flaky test. https://crbug.com/950049 // Flaky test. https://crbug.com/950049
...@@ -389,16 +399,15 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, ContinuesReadingDuringResize) { ...@@ -389,16 +399,15 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, ContinuesReadingDuringResize) {
"<p>Second paragraph is longer than 300 pixels and will wrap when " "<p>Second paragraph is longer than 300 pixels and will wrap when "
"resized</p></div>"); "resized</p></div>");
sm_.ExpectSpeechPattern("First paragraph*"); EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(),
"First paragraph*"));
// Resize before second is spoken. If resizing caused errors finding the // Resize before second is spoken. If resizing caused errors finding the
// inlineTextBoxes in the node, speech would be stopped early. // inlineTextBoxes in the node, speech would be stopped early.
sm_.Call([this]() { ExecuteJavaScriptInForeground(
ExecuteJavaScriptAsync( "document.getElementById('resize').style.width='100px'");
"document.getElementById('resize').style.width='100px'"); EXPECT_TRUE(
}); base::MatchPattern(speech_monitor_.GetNextUtterance(), "*when*resized*"));
sm_.ExpectSpeechPattern("*when*resized*");
sm_.Replay();
} }
IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, WorksWithStickyKeys) { IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, WorksWithStickyKeys) {
...@@ -420,12 +429,11 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, WorksWithStickyKeys) { ...@@ -420,12 +429,11 @@ IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, WorksWithStickyKeys) {
bounds.y() + bounds.height()); bounds.y() + bounds.height());
generator_->ReleaseLeftButton(); generator_->ReleaseLeftButton();
sm_.ExpectSpeechPattern("This is some text*"); EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(),
"This is some text*"));
// Reset state. // Reset state.
sm_.Call([]() { AccessibilityManager::Get()->EnableStickyKeys(false); }); AccessibilityManager::Get()->EnableStickyKeys(false);
sm_.Replay();
} }
} // namespace chromeos } // namespace chromeos
...@@ -12,9 +12,12 @@ ...@@ -12,9 +12,12 @@
namespace chromeos { namespace chromeos {
namespace { namespace {
const char kChromeVoxEnabledMessage[] = "ChromeVox spoken feedback is ready";
const char kChromeVoxAlertMessage[] = "Alert";
const char kChromeVoxUpdate1[] = "chrome vox Updated Press chrome vox o,";
const char kChromeVoxUpdate2[] = "n to learn more about chrome vox Next.";
constexpr int kPrintExpectationDelayMs = 3000; constexpr int kPrintExpectationDelayMs = 3000;
} // namespace } // namespace
SpeechMonitor::SpeechMonitor() { SpeechMonitor::SpeechMonitor() {
...@@ -28,6 +31,52 @@ SpeechMonitor::~SpeechMonitor() { ...@@ -28,6 +31,52 @@ SpeechMonitor::~SpeechMonitor() {
CHECK(replay_called_) << "Expectation was made, but Replay() not called."; CHECK(replay_called_) << "Expectation was made, but Replay() not called.";
} }
std::string SpeechMonitor::GetNextUtterance() {
return GetNextUtteranceWithLanguage().text;
}
SpeechMonitorUtterance SpeechMonitor::GetNextUtteranceWithLanguage() {
if (utterance_queue_.empty()) {
loop_runner_ = new content::MessageLoopRunner();
loop_runner_->Run();
loop_runner_.reset();
}
SpeechMonitorUtterance result = utterance_queue_.front();
utterance_queue_.pop_front();
return result;
}
bool SpeechMonitor::SkipChromeVoxEnabledMessage() {
return SkipChromeVoxMessage(kChromeVoxEnabledMessage);
}
bool SpeechMonitor::DidStop() {
return did_stop_;
}
void SpeechMonitor::BlockUntilStop() {
if (!did_stop_) {
loop_runner_ = new content::MessageLoopRunner();
loop_runner_->Run();
loop_runner_.reset();
}
}
bool SpeechMonitor::SkipChromeVoxMessage(const std::string& message) {
while (true) {
if (utterance_queue_.empty()) {
loop_runner_ = new content::MessageLoopRunner();
loop_runner_->Run();
loop_runner_.reset();
}
SpeechMonitorUtterance result = utterance_queue_.front();
utterance_queue_.pop_front();
if (result.text == message)
return true;
}
return false;
}
bool SpeechMonitor::PlatformImplAvailable() { bool SpeechMonitor::PlatformImplAvailable() {
return true; return true;
} }
...@@ -46,6 +95,7 @@ void SpeechMonitor::Speak(int utterance_id, ...@@ -46,6 +95,7 @@ void SpeechMonitor::Speak(int utterance_id,
} }
bool SpeechMonitor::StopSpeaking() { bool SpeechMonitor::StopSpeaking() {
did_stop_ = true;
return true; return true;
} }
...@@ -64,8 +114,21 @@ void SpeechMonitor::GetVoices(std::vector<content::VoiceData>* out_voices) { ...@@ -64,8 +114,21 @@ void SpeechMonitor::GetVoices(std::vector<content::VoiceData>* out_voices) {
void SpeechMonitor::WillSpeakUtteranceWithVoice( void SpeechMonitor::WillSpeakUtteranceWithVoice(
content::TtsUtterance* utterance, content::TtsUtterance* utterance,
const content::VoiceData& voice_data) { const content::VoiceData& voice_data) {
// Blacklist some phrases.
// Filter out empty utterances which can be used to trigger a start event from
// tts as an earcon sync.
if (utterance->GetText() == "" ||
utterance->GetText() == kChromeVoxAlertMessage ||
utterance->GetText() == kChromeVoxUpdate1 ||
utterance->GetText() == kChromeVoxUpdate2)
return;
VLOG(0) << "Speaking " << utterance->GetText();
utterance_queue_.emplace_back(utterance->GetText(), utterance->GetLang()); utterance_queue_.emplace_back(utterance->GetText(), utterance->GetLang());
delay_for_last_utterance_ms_ = CalculateUtteranceDelayMS(); delay_for_last_utterance_ms_ = CalculateUtteranceDelayMS();
if (loop_runner_.get())
loop_runner_->Quit();
MaybeContinueReplay(); MaybeContinueReplay();
} }
...@@ -120,19 +183,11 @@ void SpeechMonitor::ExpectSpeech(const std::string& text, ...@@ -120,19 +183,11 @@ void SpeechMonitor::ExpectSpeech(const std::string& text,
void SpeechMonitor::ExpectSpeechPattern(const std::string& pattern, void SpeechMonitor::ExpectSpeechPattern(const std::string& pattern,
const base::Location& location) { const base::Location& location) {
ExpectSpeechPatternWithLocale(pattern, "", location);
}
void SpeechMonitor::ExpectSpeechPatternWithLocale(
const std::string& pattern,
const std::string& locale,
const base::Location& location) {
CHECK(!replay_loop_runner_.get()); CHECK(!replay_loop_runner_.get());
replay_queue_.push_back({[this, pattern, locale]() { replay_queue_.push_back({[this, pattern]() {
for (auto it = utterance_queue_.begin(); for (auto it = utterance_queue_.begin();
it != utterance_queue_.end(); it++) { it != utterance_queue_.end(); it++) {
if (base::MatchPattern(it->text, pattern) && if (base::MatchPattern(it->text, pattern)) {
(locale.empty() || it->lang == locale)) {
// Erase all utterances that came before the // Erase all utterances that came before the
// match as well as the match itself. // match as well as the match itself.
utterance_queue_.erase( utterance_queue_.erase(
......
...@@ -25,13 +25,35 @@ struct SpeechMonitorUtterance { ...@@ -25,13 +25,35 @@ struct SpeechMonitorUtterance {
}; };
// For testing purpose installs itself as the platform speech synthesis engine, // For testing purpose installs itself as the platform speech synthesis engine,
// allowing it to intercept all speech calls. Provides an api to make // allowing it to intercept all speech calls, and then provides a method to
// asynchronous function calls and expectations about resulting speech. // block until the next utterance is spoken.
class SpeechMonitor : public content::TtsPlatform { class SpeechMonitor : public content::TtsPlatform {
public: public:
SpeechMonitor(); SpeechMonitor();
virtual ~SpeechMonitor(); virtual ~SpeechMonitor();
// Blocing api.
// Use the following apis to write a synchronous test e.g.
// DoSomething();
// EXPECT_EQ("foo", speech_monitor_.GetNextUtterance());
// Blocks until the next utterance is spoken, and returns its text.
std::string GetNextUtterance();
// Blocks until the next utterance is spoken, and returns its text.
SpeechMonitorUtterance GetNextUtteranceWithLanguage();
// Wait for next utterance and return true if next utterance is ChromeVox
// enabled message.
bool SkipChromeVoxEnabledMessage();
bool SkipChromeVoxMessage(const std::string& message);
// Returns true if StopSpeaking() was called on TtsController.
bool DidStop();
// Blocks until StopSpeaking() is called on TtsController.
void BlockUntilStop();
// Non-blocking api.
// Use these apis if you want to write an async test e.g. // Use these apis if you want to write an async test e.g.
// sm_.ExpectSpeech("foo"); // sm_.ExpectSpeech("foo");
// sm_.Call([this]() { DoSomething(); }) // sm_.Call([this]() { DoSomething(); })
...@@ -45,10 +67,6 @@ class SpeechMonitor : public content::TtsPlatform { ...@@ -45,10 +67,6 @@ class SpeechMonitor : public content::TtsPlatform {
const base::Location& location = FROM_HERE); const base::Location& location = FROM_HERE);
void ExpectSpeechPattern(const std::string& pattern, void ExpectSpeechPattern(const std::string& pattern,
const base::Location& location = FROM_HERE); const base::Location& location = FROM_HERE);
void ExpectSpeechPatternWithLocale(
const std::string& pattern,
const std::string& locale,
const base::Location& location = FROM_HERE);
void ExpectNextSpeechIsNot(const std::string& text, void ExpectNextSpeechIsNot(const std::string& text,
const base::Location& location = FROM_HERE); const base::Location& location = FROM_HERE);
void ExpectNextSpeechIsNotPattern(const std::string& pattern, void ExpectNextSpeechIsNotPattern(const std::string& pattern,
...@@ -93,17 +111,17 @@ class SpeechMonitor : public content::TtsPlatform { ...@@ -93,17 +111,17 @@ class SpeechMonitor : public content::TtsPlatform {
void MaybeContinueReplay(); void MaybeContinueReplay();
void MaybePrintExpectations(); void MaybePrintExpectations();
scoped_refptr<content::MessageLoopRunner> loop_runner_;
// Our list of utterances and specified language. // Our list of utterances and specified language.
base::circular_deque<SpeechMonitorUtterance> utterance_queue_; base::circular_deque<SpeechMonitorUtterance> utterance_queue_;
bool did_stop_ = false;
std::string error_; std::string error_;
// Delayed utterances.
// Calculates the milliseconds elapsed since the last call to Speak(). // Calculates the milliseconds elapsed since the last call to Speak().
double CalculateUtteranceDelayMS(); double CalculateUtteranceDelayMS();
// Stores the milliseconds elapsed since the last call to Speak(). // Stores the milliseconds elapsed since the last call to Speak().
double delay_for_last_utterance_ms_; double delay_for_last_utterance_ms_;
// Stores the last time Speak() was called. // Stores the last time Speak() was called.
std::chrono::steady_clock::time_point time_of_last_utterance_; std::chrono::steady_clock::time_point time_of_last_utterance_;
......
...@@ -8,12 +8,15 @@ ...@@ -8,12 +8,15 @@
#include "ash/app_list/test/test_search_result.h" #include "ash/app_list/test/test_search_result.h"
#include "ash/app_list/views/app_list_view.h" #include "ash/app_list/views/app_list_view.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "base/strings/pattern.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.h" #include "chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/app_list/app_list_client_impl.h" #include "chrome/browser/ui/app_list/app_list_client_impl.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "chromeos/constants/chromeos_switches.h" #include "chromeos/constants/chromeos_switches.h"
#include "components/account_id/account_id.h"
#include "components/user_manager/user_names.h" #include "components/user_manager/user_names.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
...@@ -101,8 +104,8 @@ INSTANTIATE_TEST_SUITE_P(TestAsNormalAndGuestUser, ...@@ -101,8 +104,8 @@ INSTANTIATE_TEST_SUITE_P(TestAsNormalAndGuestUser,
IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest, LauncherStateTransition) { IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest, LauncherStateTransition) {
EnableChromeVox(); EnableChromeVox();
sm_.Call( EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF));
[this]() { EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); });
sm_.ExpectSpeechPattern("Launcher"); sm_.ExpectSpeechPattern("Launcher");
sm_.ExpectSpeech("Button"); sm_.ExpectSpeech("Button");
sm_.ExpectSpeech("Shelf"); sm_.ExpectSpeech("Shelf");
...@@ -135,8 +138,8 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest, ...@@ -135,8 +138,8 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest,
DisabledFullscreenExpandButton) { DisabledFullscreenExpandButton) {
EnableChromeVox(); EnableChromeVox();
sm_.Call( EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF));
[this]() { EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); });
sm_.ExpectSpeech("Shelf"); sm_.ExpectSpeech("Shelf");
// Press space on the launcher button in shelf, this opens peeking launcher. // Press space on the launcher button in shelf, this opens peeking launcher.
...@@ -172,8 +175,8 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest, ...@@ -172,8 +175,8 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest,
EnableChromeVox(); EnableChromeVox();
sm_.Call( EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF));
[this]() { EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); });
sm_.ExpectSpeech("Press Search plus Space to activate"); sm_.ExpectSpeech("Press Search plus Space to activate");
// Press space on the launcher button in shelf, this opens peeking // Press space on the launcher button in shelf, this opens peeking
// launcher. // launcher.
...@@ -209,8 +212,8 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest, ...@@ -209,8 +212,8 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest,
EnableChromeVox(); EnableChromeVox();
sm_.Call( EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF));
[this]() { EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); });
sm_.ExpectSpeech("Press Search plus Space to activate"); sm_.ExpectSpeech("Press Search plus Space to activate");
// Press space on the launcher button in shelf, this opens peeking // Press space on the launcher button in shelf, this opens peeking
// launcher. // launcher.
...@@ -254,12 +257,10 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest, ...@@ -254,12 +257,10 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest,
IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest, NavigateAppLauncher) { IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest, NavigateAppLauncher) {
EnableChromeVox(); EnableChromeVox();
sm_.Call([this]() { // Add one app to the applist.
// Add one app to the applist. PopulateApps(1);
PopulateApps(1);
EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF));
});
// Wait for it to say "Launcher", "Button", "Shelf", "Tool bar". // Wait for it to say "Launcher", "Button", "Shelf", "Tool bar".
sm_.ExpectSpeechPattern("Launcher"); sm_.ExpectSpeechPattern("Launcher");
......
...@@ -2333,46 +2333,48 @@ IN_PROC_BROWSER_TEST_F(HotseatShelfAppBrowserTest, EnableChromeVox) { ...@@ -2333,46 +2333,48 @@ IN_PROC_BROWSER_TEST_F(HotseatShelfAppBrowserTest, EnableChromeVox) {
chromeos::SpeechMonitor speech_monitor; chromeos::SpeechMonitor speech_monitor;
// Enable ChromeVox. // Enable ChromeVox.
{
ASSERT_FALSE( ASSERT_FALSE(
chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
chromeos::AccessibilityManager::Get()->EnableSpokenFeedback(true); chromeos::AccessibilityManager::Get()->EnableSpokenFeedback(true);
EXPECT_TRUE(speech_monitor.SkipChromeVoxEnabledMessage());
// Disable earcons (https://crbug.com/396507).
const std::string script("ChromeVox.earcons.playEarcon = function() {};");
extensions::ExtensionHost* host =
extensions::ProcessManager::Get(browser()->profile())
->GetBackgroundHostForExtension(
extension_misc::kChromeVoxExtensionId);
ASSERT_TRUE(content::ExecuteScript(host->host_contents(), script));
}
ash::RootWindowController* controller = ash::RootWindowController* controller =
ash::Shell::GetRootWindowControllerWithDisplayId( ash::Shell::GetRootWindowControllerWithDisplayId(
display::Screen::GetScreen()->GetPrimaryDisplay().id()); display::Screen::GetScreen()->GetPrimaryDisplay().id());
// Gesture tap at the home button.
views::View* home_button = ash::ShelfTestApi().GetHomeButton(); views::View* home_button = ash::ShelfTestApi().GetHomeButton();
ui::test::EventGenerator event_generator(controller->GetRootWindow()); ui::test::EventGenerator event_generator(controller->GetRootWindow());
auto* generator_ptr = &event_generator; event_generator.GestureTapAt(home_button->GetBoundsInScreen().CenterPoint());
// Wait for ChromeVox to start reading anything. ASSERT_EQ("Launcher", speech_monitor.GetNextUtterance());
speech_monitor.ExpectSpeechPattern("*"); ASSERT_EQ("Button", speech_monitor.GetNextUtterance());
speech_monitor.Call([generator_ptr, home_button]() { ASSERT_EQ("Shelf", speech_monitor.GetNextUtterance());
// Gesture tap at the home button. ASSERT_EQ("Tool bar", speech_monitor.GetNextUtterance());
generator_ptr->GestureTapAt(home_button->GetBoundsInScreen().CenterPoint()); ASSERT_EQ(", window", speech_monitor.GetNextUtterance());
});
speech_monitor.ExpectSpeech("Launcher"); // Hotseat is expected to be extended if spoken feedback is enabled.
speech_monitor.ExpectSpeech("Button"); ASSERT_EQ(ash::HotseatState::kExtended,
speech_monitor.ExpectSpeech("Shelf"); controller->shelf()->shelf_layout_manager()->hotseat_state());
speech_monitor.ExpectSpeech("Tool bar");
speech_monitor.ExpectSpeech(", window"); // Press the search + right. Expects that the browser icon receives the
// accessibility focus and the hotseat remains in kExtended state.
speech_monitor.Call([controller]() { event_generator.PressKey(ui::VKEY_RIGHT, ui::EF_COMMAND_DOWN);
// Hotseat is expected to be extended if spoken feedback is enabled.
ASSERT_EQ(ash::HotseatState::kExtended,
controller->shelf()->shelf_layout_manager()->hotseat_state());
});
speech_monitor.Call([generator_ptr]() {
// Press the search + right. Expects that the browser icon receives the
// accessibility focus and the hotseat remains in kExtended state.
generator_ptr->PressKey(ui::VKEY_RIGHT, ui::EF_COMMAND_DOWN);
});
const int browser_index = const int browser_index =
ash::ShelfModel::Get()->GetItemIndexForType(ash::TYPE_BROWSER_SHORTCUT); ash::ShelfModel::Get()->GetItemIndexForType(ash::TYPE_BROWSER_SHORTCUT);
speech_monitor.ExpectSpeech( EXPECT_EQ(
base::UTF16ToASCII(ash::ShelfModel::Get()->items()[browser_index].title)); base::UTF16ToASCII(ash::ShelfModel::Get()->items()[browser_index].title),
speech_monitor.Replay(); speech_monitor.GetNextUtterance());
EXPECT_EQ(ash::HotseatState::kExtended, EXPECT_EQ(ash::HotseatState::kExtended,
controller->shelf()->shelf_layout_manager()->hotseat_state()); controller->shelf()->shelf_layout_manager()->hotseat_state());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment