Commit a5af34fb authored by Becca Hughes's avatar Becca Hughes Committed by Commit Bot

Media Controls: Create panel listener on demand

Create the 'transitionend' event listener on the panel on demand instead
of leaving it around when we do not need it.

BUG=832771

Change-Id: If722535b63052a0fc6383a7b1fbcc158a8fb284c
Reviewed-on: https://chromium-review.googlesource.com/1022317
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Cr-Commit-Position: refs/heads/master@{#552769}
parent e58978d9
......@@ -33,14 +33,24 @@ class MediaControlPanelElement::TransitionEventListener final
element_(element) {
DCHECK(callback_);
DCHECK(element_);
}
void Attach() {
DCHECK(!attached_);
attached_ = true;
element->addEventListener(EventTypeNames::transitionend, this, false);
element_->addEventListener(EventTypeNames::transitionend, this, false);
}
void Detach() {
DCHECK(attached_);
attached_ = false;
element_->removeEventListener(EventTypeNames::transitionend, this, false);
}
bool IsAttached() const { return attached_; }
bool operator==(const EventListener& other) const override {
return this == &other;
}
......@@ -60,6 +70,8 @@ class MediaControlPanelElement::TransitionEventListener final
NOTREACHED();
}
bool attached_ = false;
Callback callback_;
Member<Element> element_;
};
......@@ -67,11 +79,7 @@ class MediaControlPanelElement::TransitionEventListener final
MediaControlPanelElement::MediaControlPanelElement(
MediaControlsImpl& media_controls)
: MediaControlDivElement(media_controls, kMediaControlsPanel),
event_listener_(new MediaControlPanelElement::TransitionEventListener(
this,
WTF::BindRepeating(
&MediaControlPanelElement::HandleTransitionEndEvent,
WrapWeakPersistent(this)))) {
event_listener_(nullptr) {
SetShadowPseudoId(AtomicString("-webkit-media-controls-panel"));
}
......@@ -95,6 +103,9 @@ void MediaControlPanelElement::MakeOpaque() {
opaque_ = true;
if (is_displayed_) {
// Make sure we are listening for the 'transitionend' event.
EnsureTransitionEventListener();
SetIsWanted(true);
removeAttribute("class");
DidBecomeVisible();
......@@ -105,13 +116,16 @@ void MediaControlPanelElement::MakeTransparent() {
if (!opaque_)
return;
// Make sure we are listening for the 'transitionend' event.
EnsureTransitionEventListener();
setAttribute("class", kTransparentClassName);
opaque_ = false;
}
void MediaControlPanelElement::RemovedFrom(ContainerNode*) {
event_listener_->Detach();
DetachTransitionEventListener();
}
void MediaControlPanelElement::Trace(blink::Visitor* visitor) {
......@@ -123,6 +137,33 @@ void MediaControlPanelElement::SetKeepDisplayedForAccessibility(bool value) {
keep_displayed_for_accessibility_ = value;
}
bool MediaControlPanelElement::EventListenerIsAttachedForTest() const {
return event_listener_->IsAttached();
}
void MediaControlPanelElement::EnsureTransitionEventListener() {
// Create the event listener if it doesn't exist.
if (!event_listener_) {
event_listener_ = new MediaControlPanelElement::TransitionEventListener(
this,
WTF::BindRepeating(&MediaControlPanelElement::HandleTransitionEndEvent,
WrapWeakPersistent(this)));
}
// Attach the event listener if we are not attached.
if (!event_listener_->IsAttached())
event_listener_->Attach();
}
void MediaControlPanelElement::DetachTransitionEventListener() {
if (!event_listener_)
return;
// Detach the event listener if we are attached.
if (event_listener_->IsAttached())
event_listener_->Detach();
}
void MediaControlPanelElement::DefaultEventHandler(Event* event) {
// Suppress the media element activation behavior (toggle play/pause) when
// any part of the control panel is clicked.
......@@ -146,6 +187,10 @@ void MediaControlPanelElement::HandleTransitionEndEvent() {
// Hide the element in the DOM once we have finished the transition.
if (!opaque_ && !keep_displayed_for_accessibility_)
SetIsWanted(false);
// Now that we have received the 'transitionend' event we can dispose of
// the listener.
DetachTransitionEventListener();
}
} // namespace blink
......@@ -33,9 +33,17 @@ class MODULES_EXPORT MediaControlPanelElement final
virtual void Trace(blink::Visitor*);
protected:
friend class MediaControlPanelElementTest;
bool EventListenerIsAttachedForTest() const;
private:
class TransitionEventListener;
void EnsureTransitionEventListener();
void DetachTransitionEventListener();
void DefaultEventHandler(Event*) override;
bool KeepEventInNode(Event*) override;
......
......@@ -38,6 +38,16 @@ class MediaControlPanelElementTest : public PageTestBase {
void ExpectPanelIsNotDisplayed() { EXPECT_FALSE(GetPanel().IsWanted()); }
void EventListenerNotCreated() { EXPECT_FALSE(GetPanel().event_listener_); }
void EventListenerAttached() {
EXPECT_TRUE(GetPanel().EventListenerIsAttachedForTest());
}
void EventListenerDetached() {
EXPECT_FALSE(GetPanel().EventListenerIsAttachedForTest());
}
MediaControlPanelElement& GetPanel() { return *panel_element_.Get(); }
private:
......@@ -52,16 +62,31 @@ class MediaControlPanelElementTest : public PageTestBase {
};
TEST_F(MediaControlPanelElementTest, StateTransitions) {
// Make sure we are displayed (we are already opaque).
GetPanel().SetIsDisplayed(true);
GetPanel().MakeOpaque();
ExpectPanelIsDisplayed();
SimulateTransitionEnd();
// Ensure the event listener has not been created and make the panel
// transparent.
EventListenerNotCreated();
GetPanel().MakeTransparent();
// The event listener should now be attached so we should simulate the
// transition end and the panel will be hidden.
EventListenerAttached();
SimulateTransitionEnd();
ExpectPanelIsNotDisplayed();
// The event listener should be detached. We should now make the panel
// opaque again.
EventListenerDetached();
GetPanel().MakeOpaque();
// The event listener should now be attached so we should simulate the
// transition end event and the panel will be hidden.
EventListenerAttached();
SimulateTransitionEnd();
ExpectPanelIsDisplayed();
}
} // namespace blink
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