Commit c32bb934 authored by Mounir Lamouri's avatar Mounir Lamouri Committed by Commit Bot

Reland "Media Controls: allow navigation with accessibility tools."

This is a reland of a5439425

The CL failed after CQ because another CL that landed a couple of
commits prior broke some assumptions made in the unit tests.

Original change's description:
> Media Controls: allow navigation with accessibility tools.
>
> The media controls auto-hide mechanism breaks accessibility tools. This
> prevents the controls from fully hiding when navigated with
> accessibility tools. Instead of marking themselves as `display:none;`,
> this only mark the controls as hidden and will show them again if the
> user navigates trough them again. Similar to using a mouse.
>
> Bug: 667833
> Change-Id: I7c2dbfd4b047e2955f6ffa9fb1a5f3bbe37878fd
> Reviewed-on: https://chromium-review.googlesource.com/999637
> Reviewed-by: Tommy Steimel <steimel@chromium.org>
> Reviewed-by: Dominic Mazzoni <dmazzoni@chromium.org>
> Commit-Queue: Mounir Lamouri <mlamouri@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#549774}

TBR=dmazzoni@chromium.org, pfeldman@chromium.org

Bug: 667833
Change-Id: I03bbe4858d456a9131b257ca709f7d8728e712f7
Reviewed-on: https://chromium-review.googlesource.com/1007075Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: Mounir Lamouri <mlamouri@chromium.org>
Cr-Commit-Position: refs/heads/master@{#550096}
parent 2f18ba79
...@@ -105,6 +105,23 @@ MediaControlElementType AccessibilityMediaControl::ControlType() const { ...@@ -105,6 +105,23 @@ MediaControlElementType AccessibilityMediaControl::ControlType() const {
GetLayoutObject()->GetNode()); GetLayoutObject()->GetNode());
} }
bool AccessibilityMediaControl::OnNativeScrollToGlobalPointAction(
const IntPoint& point) const {
MediaControlElementsHelper::NotifyMediaControlAccessibleFocus(GetElement());
return AXLayoutObject::OnNativeScrollToGlobalPointAction(point);
}
bool AccessibilityMediaControl::OnNativeScrollToMakeVisibleAction() const {
MediaControlElementsHelper::NotifyMediaControlAccessibleFocus(GetElement());
return AXLayoutObject::OnNativeScrollToMakeVisibleAction();
}
bool AccessibilityMediaControl::OnNativeScrollToMakeVisibleWithSubFocusAction(
const IntRect& rect) const {
MediaControlElementsHelper::NotifyMediaControlAccessibleFocus(GetElement());
return AXLayoutObject::OnNativeScrollToMakeVisibleWithSubFocusAction(rect);
}
String AccessibilityMediaControl::TextAlternative( String AccessibilityMediaControl::TextAlternative(
bool recursive, bool recursive,
bool in_aria_labelled_by_traversal, bool in_aria_labelled_by_traversal,
......
...@@ -54,6 +54,11 @@ class AccessibilityMediaControl : public AXLayoutObject { ...@@ -54,6 +54,11 @@ class AccessibilityMediaControl : public AXLayoutObject {
AXDescriptionFrom&, AXDescriptionFrom&,
AXObjectVector* description_objects) const override; AXObjectVector* description_objects) const override;
bool OnNativeScrollToGlobalPointAction(const IntPoint&) const override;
bool OnNativeScrollToMakeVisibleAction() const override;
bool OnNativeScrollToMakeVisibleWithSubFocusAction(
const IntRect&) const override;
protected: protected:
AccessibilityMediaControl(LayoutObject*, AXObjectCacheImpl&); AccessibilityMediaControl(LayoutObject*, AXObjectCacheImpl&);
MediaControlElementType ControlType() const; MediaControlElementType ControlType() const;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_div_element.h" #include "third_party/blink/renderer/modules/media_controls/elements/media_control_div_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.h" #include "third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
namespace blink { namespace blink {
...@@ -116,4 +117,15 @@ HTMLDivElement* MediaControlElementsHelper::CreateDivWithId( ...@@ -116,4 +117,15 @@ HTMLDivElement* MediaControlElementsHelper::CreateDivWithId(
return element; return element;
} }
// static
void MediaControlElementsHelper::NotifyMediaControlAccessibleFocus(
Element* element) {
const HTMLMediaElement* media_element = ToParentMediaElement(element);
if (!media_element || !media_element->GetMediaControls())
return;
static_cast<MediaControlsImpl*>(media_element->GetMediaControls())
->OnAccessibleFocus();
}
} // namespace blink } // namespace blink
...@@ -60,6 +60,10 @@ class MediaControlElementsHelper final { ...@@ -60,6 +60,10 @@ class MediaControlElementsHelper final {
// element ID. // element ID.
static HTMLDivElement* CreateDivWithId(const WTF::AtomicString& id, static HTMLDivElement* CreateDivWithId(const WTF::AtomicString& id,
ContainerNode* parent); ContainerNode* parent);
// Utility function that notifies the media controls in which the element is
// that it was focused by an accessibility tool.
static void NotifyMediaControlAccessibleFocus(Element*);
}; };
} // namespace blink } // namespace blink
......
...@@ -68,6 +68,10 @@ void MediaControlPanelElement::MakeTransparent() { ...@@ -68,6 +68,10 @@ void MediaControlPanelElement::MakeTransparent() {
StartTimer(); StartTimer();
} }
void MediaControlPanelElement::SetKeepDisplayedForAccessibility(bool value) {
keep_displayed_for_accessibility_ = value;
}
void MediaControlPanelElement::DefaultEventHandler(Event* event) { void MediaControlPanelElement::DefaultEventHandler(Event* event) {
// Suppress the media element activation behavior (toggle play/pause) when // Suppress the media element activation behavior (toggle play/pause) when
// any part of the control panel is clicked. // any part of the control panel is clicked.
...@@ -97,7 +101,7 @@ void MediaControlPanelElement::StopTimer() { ...@@ -97,7 +101,7 @@ void MediaControlPanelElement::StopTimer() {
} }
void MediaControlPanelElement::TransitionTimerFired(TimerBase*) { void MediaControlPanelElement::TransitionTimerFired(TimerBase*) {
if (!opaque_) if (!opaque_ && !keep_displayed_for_accessibility_)
SetIsWanted(false); SetIsWanted(false);
StopTimer(); StopTimer();
......
...@@ -25,6 +25,8 @@ class MediaControlPanelElement final : public MediaControlDivElement { ...@@ -25,6 +25,8 @@ class MediaControlPanelElement final : public MediaControlDivElement {
void MakeOpaque(); void MakeOpaque();
void MakeTransparent(); void MakeTransparent();
void SetKeepDisplayedForAccessibility(bool);
private: private:
void DefaultEventHandler(Event*) override; void DefaultEventHandler(Event*) override;
bool KeepEventInNode(Event*) override; bool KeepEventInNode(Event*) override;
...@@ -36,6 +38,7 @@ class MediaControlPanelElement final : public MediaControlDivElement { ...@@ -36,6 +38,7 @@ class MediaControlPanelElement final : public MediaControlDivElement {
bool is_displayed_ = false; bool is_displayed_ = false;
bool opaque_ = true; bool opaque_ = true;
bool keep_displayed_for_accessibility_ = false;
TaskRunnerTimer<MediaControlPanelElement> transition_timer_; TaskRunnerTimer<MediaControlPanelElement> transition_timer_;
}; };
......
...@@ -1267,6 +1267,17 @@ void MediaControlsImpl::MaybeToggleControlsFromTap() { ...@@ -1267,6 +1267,17 @@ void MediaControlsImpl::MaybeToggleControlsFromTap() {
} }
} }
void MediaControlsImpl::OnAccessibleFocus() {
panel_->SetKeepDisplayedForAccessibility(true);
if (!MediaElement().ShouldShowControls())
return;
keep_showing_until_timer_fires_ = true;
StartHideMediaControlsTimer();
MaybeShow();
}
void MediaControlsImpl::DefaultEventHandler(Event* event) { void MediaControlsImpl::DefaultEventHandler(Event* event) {
HTMLDivElement::DefaultEventHandler(event); HTMLDivElement::DefaultEventHandler(event);
...@@ -1295,15 +1306,17 @@ void MediaControlsImpl::DefaultEventHandler(Event* event) { ...@@ -1295,15 +1306,17 @@ void MediaControlsImpl::DefaultEventHandler(Event* event) {
if ((event->type() == EventTypeNames::pointerover || if ((event->type() == EventTypeNames::pointerover ||
event->type() == EventTypeNames::pointermove || event->type() == EventTypeNames::pointermove ||
event->type() == EventTypeNames::pointerout) && event->type() == EventTypeNames::pointerout) &&
!is_touch_interaction_) !is_touch_interaction_) {
HandlePointerEvent(event); HandlePointerEvent(event);
}
// If the user is interacting with the controls via the keyboard, don't hide // If the user is interacting with the controls via the keyboard, don't hide
// the controls. This will fire when the user tabs between controls (focusin) // the controls. This will fire when the user tabs between controls (focusin)
// or when they seek either the timeline or volume sliders (input). // or when they seek either the timeline or volume sliders (input).
if (event->type() == EventTypeNames::focusin || if (event->type() == EventTypeNames::focusin ||
event->type() == EventTypeNames::input) event->type() == EventTypeNames::input) {
ResetHideMediaControlsTimer(); ResetHideMediaControlsTimer();
}
if (event->IsKeyboardEvent() && if (event->IsKeyboardEvent() &&
!IsSpatialNavigationEnabled(GetDocument().GetFrame())) { !IsSpatialNavigationEnabled(GetDocument().GetFrame())) {
......
...@@ -185,6 +185,11 @@ class MODULES_EXPORT MediaControlsImpl final : public HTMLDivElement, ...@@ -185,6 +185,11 @@ class MODULES_EXPORT MediaControlsImpl final : public HTMLDivElement,
void MaybeToggleControlsFromTap(); void MaybeToggleControlsFromTap();
// Called by accessibility code to notify that the controls was focused by an
// accessibility tool. This is meant to be replaced by AOM when the event will
// be exposed to the platform.
void OnAccessibleFocus();
private: private:
// MediaControlsMediaEventListener is a component that is listening to events // MediaControlsMediaEventListener is a component that is listening to events
// and calling the appropriate callback on MediaControlsImpl. The object is // and calling the appropriate callback on MediaControlsImpl. The object is
......
...@@ -138,7 +138,7 @@ bool IsElementVisible(Element& element) { ...@@ -138,7 +138,7 @@ bool IsElementVisible(Element& element) {
const CSSPropertyValueSet* inline_style = element.InlineStyle(); const CSSPropertyValueSet* inline_style = element.InlineStyle();
if (!inline_style) if (!inline_style)
return true; return element.getAttribute("class") != "transparent";
if (inline_style->GetPropertyValue(CSSPropertyDisplay) == "none") if (inline_style->GetPropertyValue(CSSPropertyDisplay) == "none")
return false; return false;
...@@ -1068,6 +1068,52 @@ TEST_F(MediaControlsImplTestWithMockScheduler, CursorHidesWhenControlsHide) { ...@@ -1068,6 +1068,52 @@ TEST_F(MediaControlsImplTestWithMockScheduler, CursorHidesWhenControlsHide) {
EXPECT_TRUE(IsCursorHidden()); EXPECT_TRUE(IsCursorHidden());
} }
TEST_F(MediaControlsImplTestWithMockScheduler, AccessibleFocusShowsControls) {
EnsureSizing();
Element* panel = MediaControls().PanelElement();
MediaControls().MediaElement().SetSrc("http://example.com");
MediaControls().MediaElement().Play();
platform_->RunForPeriodSeconds(2);
EXPECT_TRUE(IsElementVisible(*panel));
MediaControls().OnAccessibleFocus();
platform_->RunForPeriodSeconds(2);
EXPECT_TRUE(IsElementVisible(*panel));
platform_->RunForPeriodSeconds(2);
EXPECT_FALSE(IsElementVisible(*panel));
MediaControls().OnAccessibleFocus();
platform_->RunForPeriodSeconds(2);
EXPECT_TRUE(IsElementVisible(*panel));
}
TEST_F(MediaControlsImplTestWithMockScheduler,
AccessibleFocusKeepsControlsHiddenButDisplayed) {
EnsureSizing();
Element* panel = MediaControls().PanelElement();
MediaControls().MediaElement().SetSrc("http://example.com");
MediaControls().MediaElement().Play();
platform_->RunForPeriodSeconds(2);
EXPECT_TRUE(IsElementVisible(*panel));
MediaControls().OnAccessibleFocus();
platform_->RunForPeriodSeconds(4);
EXPECT_FALSE(IsElementVisible(*panel));
// Display is none but can't be checked via InlineStyle. Adding checks of this
// to make sure that any one changing this assumption will have to update this
// test.
EXPECT_FALSE(panel->InlineStyle());
EXPECT_NE(EDisplay::kNone, panel->EnsureComputedStyle()->Display());
}
TEST_F(MediaControlsImplTest, TEST_F(MediaControlsImplTest,
RemovingFromDocumentRemovesListenersAndCallbacks) { RemovingFromDocumentRemovesListenersAndCallbacks) {
auto page_holder = DummyPageHolder::Create(); auto page_holder = DummyPageHolder::Create();
......
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