Commit 8608426e authored by Alex Keng's avatar Alex Keng Committed by Commit Bot

video: suppress Aria update when timeline slider is focused

This CL addresses the issue where when the timeline slider is focused
while the media is playing, Narrator will announce 'Elapsed time,
Elapsed time, ..." repeatedly. (NVDA will repeat the whole sentence
which is also not ideal)

With this change, the behavior is now changed to announce the
current/elapsed time only once when the slider gets focused.

Note
1. only Aria updates triggered by the timer are suppressed, so
user interactions that would move timeline slider, ex mouse clicks,
left/right keys etc, would still trigger current/elapsed time utterance.

2. we can't use aria-live:off to suppress aria since according to
the spec [1], aria-live:off doesn't apply to areas that are being focused.

[1] https://www.w3.org/TR/wai-aria-1.1/#aria-live

Bug: 1054885
Change-Id: I5519793a3d53f1982733f49fd4db882326f5c2f9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2067381
Commit-Queue: Alex Keng <shihken@microsoft.com>
Reviewed-by: default avatarTommy Steimel <steimel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#744920}
parent 23d275b6
...@@ -65,8 +65,7 @@ bool MediaControlTimelineElement::WillRespondToMouseClickEvents() { ...@@ -65,8 +65,7 @@ bool MediaControlTimelineElement::WillRespondToMouseClickEvents() {
return isConnected() && GetDocument().IsActive(); return isConnected() && GetDocument().IsActive();
} }
void MediaControlTimelineElement::SetPosition(double current_time) { void MediaControlTimelineElement::UpdateAria() {
setValue(String::Number(current_time));
String aria_label = String aria_label =
GetLocale().QueryString(IsA<HTMLVideoElement>(MediaElement()) GetLocale().QueryString(IsA<HTMLVideoElement>(MediaElement())
? IDS_AX_MEDIA_VIDEO_SLIDER_HELP ? IDS_AX_MEDIA_VIDEO_SLIDER_HELP
...@@ -79,6 +78,15 @@ void MediaControlTimelineElement::SetPosition(double current_time) { ...@@ -79,6 +78,15 @@ void MediaControlTimelineElement::SetPosition(double current_time) {
AtomicString(GetLocale().QueryString( AtomicString(GetLocale().QueryString(
IDS_AX_MEDIA_CURRENT_TIME_DISPLAY, IDS_AX_MEDIA_CURRENT_TIME_DISPLAY,
GetMediaControls().CurrentTimeDisplay().textContent(true)))); GetMediaControls().CurrentTimeDisplay().textContent(true))));
}
void MediaControlTimelineElement::SetPosition(double current_time,
bool suppress_aria) {
setValue(String::Number(current_time));
if (!suppress_aria)
UpdateAria();
RenderBarSegments(); RenderBarSegments();
} }
...@@ -113,14 +121,15 @@ void MediaControlTimelineElement::DefaultEventHandler(Event& event) { ...@@ -113,14 +121,15 @@ void MediaControlTimelineElement::DefaultEventHandler(Event& event) {
metrics_.RecordEndGesture(TrackWidth(), MediaElement().duration()); metrics_.RecordEndGesture(TrackWidth(), MediaElement().duration());
} }
if (event.type() == event_type_names::kKeydown) { if (event.type() == event_type_names::kFocus)
UpdateAria();
if (event.type() == event_type_names::kKeydown)
metrics_.StartKey(); metrics_.StartKey();
}
auto* keyboard_event = DynamicTo<KeyboardEvent>(event); auto* keyboard_event = DynamicTo<KeyboardEvent>(event);
if (event.type() == event_type_names::kKeyup && keyboard_event) { if (event.type() == event_type_names::kKeyup && keyboard_event)
metrics_.RecordEndKey(TrackWidth(), keyboard_event->keyCode()); metrics_.RecordEndKey(TrackWidth(), keyboard_event->keyCode());
}
MediaControlInputElement::DefaultEventHandler(event); MediaControlInputElement::DefaultEventHandler(event);
......
...@@ -24,7 +24,7 @@ class MediaControlTimelineElement : public MediaControlSliderElement { ...@@ -24,7 +24,7 @@ class MediaControlTimelineElement : public MediaControlSliderElement {
// FIXME: An "earliest possible position" will be needed once that concept // FIXME: An "earliest possible position" will be needed once that concept
// is supported by HTMLMediaElement, see https://crbug.com/137275 // is supported by HTMLMediaElement, see https://crbug.com/137275
void SetPosition(double); void SetPosition(double, bool suppress_aria = false);
void SetDuration(double); void SetDuration(double);
void OnMediaKeyboardEvent(Event* event) { DefaultEventHandler(*event); } void OnMediaKeyboardEvent(Event* event) { DefaultEventHandler(*event); }
...@@ -51,6 +51,8 @@ class MediaControlTimelineElement : public MediaControlSliderElement { ...@@ -51,6 +51,8 @@ class MediaControlTimelineElement : public MediaControlSliderElement {
bool BeginScrubbingEvent(Event&); bool BeginScrubbingEvent(Event&);
bool EndScrubbingEvent(Event&); bool EndScrubbingEvent(Event&);
void UpdateAria();
MediaControlTimelineMetrics metrics_; MediaControlTimelineMetrics metrics_;
bool is_touching_ = false; bool is_touching_ = false;
......
...@@ -875,8 +875,8 @@ void MediaControlsImpl::Reset() { ...@@ -875,8 +875,8 @@ void MediaControlsImpl::Reset() {
OnControlsListUpdated(); OnControlsListUpdated();
} }
void MediaControlsImpl::UpdateTimeIndicators() { void MediaControlsImpl::UpdateTimeIndicators(bool suppress_aria) {
timeline_->SetPosition(MediaElement().currentTime()); timeline_->SetPosition(MediaElement().currentTime(), suppress_aria);
UpdateCurrentTimeDisplay(); UpdateCurrentTimeDisplay();
} }
...@@ -1743,7 +1743,7 @@ void MediaControlsImpl::OnFocusIn() { ...@@ -1743,7 +1743,7 @@ void MediaControlsImpl::OnFocusIn() {
} }
void MediaControlsImpl::OnTimeUpdate() { void MediaControlsImpl::OnTimeUpdate() {
UpdateTimeIndicators(); UpdateTimeIndicators(true /* suppress_aria */);
// 'timeupdate' might be called in a paused state. The controls should not // 'timeupdate' might be called in a paused state. The controls should not
// become transparent in that case. // become transparent in that case.
......
...@@ -280,7 +280,7 @@ class MODULES_EXPORT MediaControlsImpl final : public HTMLDivElement, ...@@ -280,7 +280,7 @@ class MODULES_EXPORT MediaControlsImpl final : public HTMLDivElement,
void ElementSizeChangedTimerFired(TimerBase*); void ElementSizeChangedTimerFired(TimerBase*);
// Update any visible indicators of the current time. // Update any visible indicators of the current time.
void UpdateTimeIndicators(); void UpdateTimeIndicators(bool suppress_aria = false);
// Hide elements that don't fit, and show those things that we want which // Hide elements that don't fit, and show those things that we want which
// do fit. This requires that m_effectiveWidth and m_effectiveHeight are // do fit. This requires that m_effectiveWidth and m_effectiveHeight are
......
...@@ -25,10 +25,10 @@ async_test(t => { ...@@ -25,10 +25,10 @@ async_test(t => {
assert_equals(timeline_element.getAttribute('aria-valuetext'), 'elapsed time: 0:00'); assert_equals(timeline_element.getAttribute('aria-valuetext'), 'elapsed time: 0:00');
video.onseeked = t.step_func(_ => { video.onseeked = t.step_func(_ => {
// Check to see that we update the elasped time properly upon seeking. // Check to see that we don't update Aria during the playback.
assert_equals(timeline_element.getAttribute('aria-label'), assert_equals(timeline_element.getAttribute('aria-label'),
'video time scrubber 0:01 / 0:06'); 'video time scrubber 0:00 / 0:06');
assert_equals(timeline_element.getAttribute('aria-valuetext'), 'elapsed time: 0:01'); assert_equals(timeline_element.getAttribute('aria-valuetext'), 'elapsed time: 0:00');
// To make sure all the tests run before t.step_func_done, we load audio after we test video. // To make sure all the tests run before t.step_func_done, we load audio after we test video.
audio.load(); audio.load();
...@@ -49,8 +49,8 @@ async_test(t => { ...@@ -49,8 +49,8 @@ async_test(t => {
audio.onseeked = t.step_func_done(_ => { audio.onseeked = t.step_func_done(_ => {
assert_equals(timeline_element.getAttribute('aria-label'), assert_equals(timeline_element.getAttribute('aria-label'),
'audio time scrubber 0:01 / 0:07'); 'audio time scrubber 0:00 / 0:07');
assert_equals(timeline_element.getAttribute('aria-valuetext'), 'elapsed time: 0:01'); assert_equals(timeline_element.getAttribute('aria-valuetext'), 'elapsed time: 0:00');
}); });
audio.currentTime = 1; audio.currentTime = 1;
......
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