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 {
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(
bool recursive,
bool in_aria_labelled_by_traversal,
......
......@@ -54,6 +54,11 @@ class AccessibilityMediaControl : public AXLayoutObject {
AXDescriptionFrom&,
AXObjectVector* description_objects) const override;
bool OnNativeScrollToGlobalPointAction(const IntPoint&) const override;
bool OnNativeScrollToMakeVisibleAction() const override;
bool OnNativeScrollToMakeVisibleWithSubFocusAction(
const IntRect&) const override;
protected:
AccessibilityMediaControl(LayoutObject*, AXObjectCacheImpl&);
MediaControlElementType ControlType() const;
......
......@@ -12,6 +12,7 @@
#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_input_element.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
namespace blink {
......@@ -116,4 +117,15 @@ HTMLDivElement* MediaControlElementsHelper::CreateDivWithId(
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
......@@ -60,6 +60,10 @@ class MediaControlElementsHelper final {
// element ID.
static HTMLDivElement* CreateDivWithId(const WTF::AtomicString& id,
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
......
......@@ -68,6 +68,10 @@ void MediaControlPanelElement::MakeTransparent() {
StartTimer();
}
void MediaControlPanelElement::SetKeepDisplayedForAccessibility(bool value) {
keep_displayed_for_accessibility_ = value;
}
void MediaControlPanelElement::DefaultEventHandler(Event* event) {
// Suppress the media element activation behavior (toggle play/pause) when
// any part of the control panel is clicked.
......@@ -97,7 +101,7 @@ void MediaControlPanelElement::StopTimer() {
}
void MediaControlPanelElement::TransitionTimerFired(TimerBase*) {
if (!opaque_)
if (!opaque_ && !keep_displayed_for_accessibility_)
SetIsWanted(false);
StopTimer();
......
......@@ -25,6 +25,8 @@ class MediaControlPanelElement final : public MediaControlDivElement {
void MakeOpaque();
void MakeTransparent();
void SetKeepDisplayedForAccessibility(bool);
private:
void DefaultEventHandler(Event*) override;
bool KeepEventInNode(Event*) override;
......@@ -36,6 +38,7 @@ class MediaControlPanelElement final : public MediaControlDivElement {
bool is_displayed_ = false;
bool opaque_ = true;
bool keep_displayed_for_accessibility_ = false;
TaskRunnerTimer<MediaControlPanelElement> transition_timer_;
};
......
......@@ -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) {
HTMLDivElement::DefaultEventHandler(event);
......@@ -1295,15 +1306,17 @@ void MediaControlsImpl::DefaultEventHandler(Event* event) {
if ((event->type() == EventTypeNames::pointerover ||
event->type() == EventTypeNames::pointermove ||
event->type() == EventTypeNames::pointerout) &&
!is_touch_interaction_)
!is_touch_interaction_) {
HandlePointerEvent(event);
}
// 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)
// or when they seek either the timeline or volume sliders (input).
if (event->type() == EventTypeNames::focusin ||
event->type() == EventTypeNames::input)
event->type() == EventTypeNames::input) {
ResetHideMediaControlsTimer();
}
if (event->IsKeyboardEvent() &&
!IsSpatialNavigationEnabled(GetDocument().GetFrame())) {
......
......@@ -185,6 +185,11 @@ class MODULES_EXPORT MediaControlsImpl final : public HTMLDivElement,
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:
// MediaControlsMediaEventListener is a component that is listening to events
// and calling the appropriate callback on MediaControlsImpl. The object is
......
......@@ -138,7 +138,7 @@ bool IsElementVisible(Element& element) {
const CSSPropertyValueSet* inline_style = element.InlineStyle();
if (!inline_style)
return true;
return element.getAttribute("class") != "transparent";
if (inline_style->GetPropertyValue(CSSPropertyDisplay) == "none")
return false;
......@@ -1068,6 +1068,52 @@ TEST_F(MediaControlsImplTestWithMockScheduler, CursorHidesWhenControlsHide) {
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,
RemovingFromDocumentRemovesListenersAndCallbacks) {
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