Commit 8df286c2 authored by David Tseng's avatar David Tseng Committed by Commit Bot

Moves load progress tones from js to native

R=dmazzoni@chromium.org

Bug: 1046430
Change-Id: I134e5b7bfa2f38ea7143baad2f0f43f2ecc0dc18
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2149400
Commit-Queue: David Tseng <dtseng@chromium.org>
Reviewed-by: default avatarNancy Wang <nancylingwang@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#759912}
parent 3fc8ab94
......@@ -198,6 +198,74 @@ class AccessibilityPanelWidgetObserver : public views::WidgetObserver {
DISALLOW_COPY_AND_ASSIGN(AccessibilityPanelWidgetObserver);
};
// Responsible for deferring ChromeVox load until a text-to-speech voice is
// ready to be used. Plays progress tones while waiting.
class ChromeVoxDeferredLoader : public content::UtteranceEventDelegate,
public content::VoicesChangedDelegate {
public:
explicit ChromeVoxDeferredLoader(AccessibilityManager* manager)
: manager_(manager) {
Profile* profile = manager_->profile();
if (profile->HasOffTheRecordProfile())
profile = profile->GetOffTheRecordProfile();
std::vector<content::VoiceData> voices;
content::TtsController::GetInstance()->GetVoices(profile, &voices);
if (voices.empty())
content::TtsController::GetInstance()->AddVoicesChangedDelegate(this);
else
SendWarmupUtterance();
}
~ChromeVoxDeferredLoader() override {
content::TtsController::GetInstance()->RemoveVoicesChangedDelegate(this);
content::TtsController::GetInstance()->RemoveUtteranceEventDelegate(this);
manager_->UnloadChromeVox();
}
private:
// content::UtteranceEventDelegate:
void OnTtsEvent(content::TtsUtterance* utterance,
content::TtsEventType event_type,
int char_index,
int length,
const std::string& error_message) override {
utterance->SetEventDelegate(nullptr);
timer_.Stop();
manager_->LoadChromeVox();
}
// content::VoicesChangedDelegate:
void OnVoicesChanged() override {
Profile* profile = manager_->profile();
if (profile->HasOffTheRecordProfile())
profile = profile->GetOffTheRecordProfile();
std::vector<content::VoiceData> voices;
content::TtsController::GetInstance()->GetVoices(profile, &voices);
if (!voices.empty()) {
content::TtsController::GetInstance()->RemoveVoicesChangedDelegate(this);
SendWarmupUtterance();
}
}
void SendWarmupUtterance() {
Profile* profile = manager_->profile();
if (profile->HasOffTheRecordProfile())
profile = profile->GetOffTheRecordProfile();
std::unique_ptr<content::TtsUtterance> utterance =
content::TtsUtterance::Create(profile);
utterance->SetEventDelegate(this);
content::TtsController::GetInstance()->SpeakOrEnqueue(std::move(utterance));
timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(500), this,
&ChromeVoxDeferredLoader::OnTimer);
}
void OnTimer() { manager_->PlaySpokenFeedbackToggleCountdown(tick_count_++); }
AccessibilityManager* manager_;
int tick_count_ = 0;
base::RepeatingTimer timer_;
};
///////////////////////////////////////////////////////////////////////////////
// AccessibilityStatusEventDetails
......@@ -482,11 +550,10 @@ void AccessibilityManager::OnSpokenFeedbackChanged() {
NotifyAccessibilityStatusChanged(details);
if (enabled) {
chromevox_loader_->Load(
profile_, base::BindRepeating(&AccessibilityManager::PostLoadChromeVox,
weak_ptr_factory_.GetWeakPtr()));
chromevox_deferred_loader_ =
std::make_unique<ChromeVoxDeferredLoader>(this);
} else {
chromevox_loader_->Unload();
chromevox_deferred_loader_.reset();
}
UpdateBrailleImeState();
}
......@@ -1326,6 +1393,21 @@ void AccessibilityManager::OnShutdown(extensions::ExtensionRegistry* registry) {
extension_registry_observer_.Remove(registry);
}
void AccessibilityManager::LoadChromeVox() {
chromevox_loader_->Load(
profile_, base::BindRepeating(&AccessibilityManager::PostLoadChromeVox,
weak_ptr_factory_.GetWeakPtr()));
}
void AccessibilityManager::UnloadChromeVox() {
// In browser_tests unloading the ChromeVox extension can race with shutdown.
// http://crbug.com/801700
if (app_terminating_)
return;
chromevox_loader_->Unload();
}
void AccessibilityManager::PostLoadChromeVox() {
// In browser_tests loading the ChromeVox extension can race with shutdown.
// http://crbug.com/801700
......
......@@ -91,6 +91,7 @@ typedef AccessibilityStatusCallbackList::Subscription
AccessibilityStatusSubscription;
class AccessibilityPanelWidgetObserver;
class ChromeVoxDeferredLoader;
enum class PlaySoundOption {
// The sound is always played.
......@@ -362,6 +363,8 @@ class AccessibilityManager
~AccessibilityManager() override;
private:
void LoadChromeVox();
void UnloadChromeVox();
void PostLoadChromeVox();
void PostUnloadChromeVox();
void PostSwitchChromeVoxProfile();
......@@ -501,10 +504,14 @@ class AccessibilityManager
// Used to set the audio focus enforcement type for ChromeVox.
mojo::Remote<media_session::mojom::AudioFocusManager> audio_focus_manager_;
// Handles deferred ChromeVox load.
std::unique_ptr<ChromeVoxDeferredLoader> chromevox_deferred_loader_;
base::WeakPtrFactory<AccessibilityManager> weak_ptr_factory_{this};
friend class DictationTest;
friend class SwitchAccessTest;
friend class ChromeVoxDeferredLoader;
DISALLOW_COPY_AND_ASSIGN(AccessibilityManager);
};
......
......@@ -152,7 +152,15 @@ void LoggedInSpokenFeedbackTest::EnableChromeVox() {
ASSERT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
AccessibilityManager::Get()->EnableSpokenFeedback(true);
// AccessibilityManager sends a warmup utterance prior to actually loading
// ChromeVox.
sm_.ExpectSpeech("");
// The next utterance comes from ChromeVox signaling it is ready.
sm_.ExpectSpeechPattern("*");
// Injects js to disable earcons.
sm_.Call([this]() { DisableEarcons(); });
}
......
......@@ -16,17 +16,8 @@ GEN_INCLUDE(['../../testing/mock_feedback.js']);
ChromeVoxAnnotationTest = class extends ChromeVoxNextE2ETest {
/** @override */
testGenCppIncludes() {
super.testGenCppIncludes();
GEN(`
// The following includes are copy-pasted from chromevox_e2e_test_base.js.
#include "ash/accessibility/accessibility_delegate.h"
#include "ash/shell.h"
#include "base/bind.h"
#include "base/callback.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/common/extensions/extension_constants.h"
#include "extensions/common/extension_l10n_util.h"
// The following includes are necessary for this test file.
#include "base/command_line.h"
#include "ui/accessibility/accessibility_switches.h"
#include "ui/base/ui_base_switches.h"
......@@ -38,14 +29,8 @@ ChromeVoxAnnotationTest = class extends ChromeVoxNextE2ETest {
GEN(`
base::CommandLine::ForCurrentProcess()->AppendSwitch(
::switches::kEnableExperimentalAccessibilityChromeVoxAnnotations);
// Copy-pasted from chromevox_e2e_test_base.js.
auto allow = extension_l10n_util::AllowGzippedMessagesAllowedForTest();
base::Closure load_cb =
base::Bind(&chromeos::AccessibilityManager::EnableSpokenFeedback,
base::Unretained(chromeos::AccessibilityManager::Get()),
true);
WaitForExtension(extension_misc::kChromeVoxExtensionId, load_cb);
`);
super.testGenPreamble();
}
assertNumberOfAnnotationsForUrl(url, numAnnotations) {
......
......@@ -173,29 +173,6 @@ Background = class extends ChromeVoxState {
// Set the darkScreen state to false, since the display will be on whenever
// ChromeVox starts.
sessionStorage.setItem('darkScreen', 'false');
// A self-contained class to start and stop progress sounds before any
// speech has been generated on startup. This is important in cases where
// speech is severely delayed.
/** @implements {TtsCapturingEventListener} */
const ProgressPlayer = class {
constructor() {
ChromeVox.tts.addCapturingEventListener(this);
ChromeVox.earcons.playEarcon(Earcon.CHROMEVOX_LOADING);
}
/** @override */
onTtsStart() {
ChromeVox.earcons.playEarcon(Earcon.CHROMEVOX_LOADED);
ChromeVox.tts.removeCapturingEventListener(this);
}
/** @override */
onTtsEnd() {}
/** @override */
onTtsInterrupted() {}
};
new ProgressPlayer();
}
/**
......
......@@ -12,17 +12,8 @@ GEN_INCLUDE(['../testing/mock_feedback.js']);
ChromeVoxLocaleOutputHelperTest = class extends ChromeVoxNextE2ETest {
/** @override */
testGenCppIncludes() {
super.testGenCppIncludes();
GEN(`
// The following includes are copy-pasted from chromevox_e2e_test_base.js.
#include "ash/accessibility/accessibility_delegate.h"
#include "ash/shell.h"
#include "base/bind.h"
#include "base/callback.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/common/extensions/extension_constants.h"
#include "extensions/common/extension_l10n_util.h"
// The following includes are necessary for this test file.
#include "base/command_line.h"
#include "ui/accessibility/accessibility_switches.h"
#include "ui/base/ui_base_switches.h"
......@@ -37,15 +28,8 @@ ChromeVoxLocaleOutputHelperTest = class extends ChromeVoxNextE2ETest {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
::switches::kEnableExperimentalAccessibilityChromeVoxLanguageSwitching);
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(::switches::kLang, "en-US");
// Copy-pasted from chromevox_e2e_test_base.js.
auto allow = extension_l10n_util::AllowGzippedMessagesAllowedForTest();
base::Closure load_cb =
base::Bind(&chromeos::AccessibilityManager::EnableSpokenFeedback,
base::Unretained(chromeos::AccessibilityManager::Get()),
true);
WaitForExtension(extension_misc::kChromeVoxExtensionId, load_cb);
`);
super.testGenPreamble();
}
/** @override */
......@@ -617,4 +601,4 @@ TEST_F(
.expectSpeechWithLocale('pt', 'português: Portuguese');
mockFeedback.replay();
});
});
\ No newline at end of file
});
......@@ -23,6 +23,7 @@ ChromeVoxE2ETest = class extends testing.Test {
#include "base/bind.h"
#include "base/callback.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/browser/chromeos/accessibility/speech_monitor.h"
#include "chrome/common/extensions/extension_constants.h"
#include "extensions/common/extension_l10n_util.h"
`);
......@@ -31,6 +32,11 @@ ChromeVoxE2ETest = class extends testing.Test {
/** @override */
testGenPreamble() {
GEN(`
// SpeechMonitor swaps in a custom TtsPlatform to mock out events and
// voices. Do this for the current call stack to catch deferred load.
chromeos::SpeechMonitor speech_monitor;
auto allow = extension_l10n_util::AllowGzippedMessagesAllowedForTest();
base::Closure load_cb =
base::Bind(&chromeos::AccessibilityManager::EnableSpokenFeedback,
......
......@@ -2435,6 +2435,9 @@ IN_PROC_BROWSER_TEST_F(HotseatShelfAppBrowserTest, EnableChromeVox) {
ui::test::EventGenerator event_generator(controller->GetRootWindow());
auto* generator_ptr = &event_generator;
// AccessibilityManager sends an empty warmup utterance first.
speech_monitor.ExpectSpeech("");
// Wait for ChromeVox to start reading anything.
speech_monitor.ExpectSpeechPattern("*");
speech_monitor.Call([this]() {
......
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