https://bugs.webkit.org/show_bug.cgi?id=123041
Reviewed by Darin Adler.
Use page visibility changes to suspend and resume the use of sleep assertions in
HTMLMediaElement.
Page will propogate the page visibility change notifications to its Documents, which
will further propogate those notifications to registered elements. Upon receiving
these notifications, HTMLMediaElement will release or take a DisplaySleepDisabler
token if necessary.
Also, rename HTMLMediaElement's updateDisableSleep() to updateSleepDisabling() and wrap
the implementation in a PLATFORM(MAC) guard rather than at each call site.
* dom/Document.cpp:
(WebCore::Document::registerForVisibilityStateCallbacks): Added registration method.
(WebCore::Document::unregisterForVisibilityStateCallbacks): Added unregistration method.
(WebCore::Document::visibilityStateChanged): Call all registered clients.
* dom/Document.h:
* dom/Element.h:
(WebCore::Element::visibilityStateChanged): Added default virtual method to be overridden
by subclasses.
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement): Register for the notification, and check the
current status of Document::hidden().
(WebCore::HTMLMediaElement::~HTMLMediaElement): Unregister for the notification.
(WebCore::HTMLMediaElement::visibilityStateChanged): Set m_displaySleepDisablingSuspended
and call updateSleepDisabling().
(WebCore::HTMLMediaElement::shouldDisableSleep): Add a check for m_displaySleepDisablingSuspended.
* html/HTMLMediaElement.h:
* page/Page.cpp:
(WebCore::Page::setVisibilityState): Pass to every child document.
Rename updateDisableSleep() -> updateSleepDisabling():
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement):
(WebCore::HTMLMediaElement::~HTMLMediaElement):
(WebCore::HTMLMediaElement::parseAttribute):
(WebCore::HTMLMediaElement::mediaPlayerRateChanged):
(WebCore::HTMLMediaElement::clearMediaPlayer):
(WebCore::HTMLMediaElement::stop):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@157735
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2013-10-21 Jer Noble <jer.noble@apple.com>
+
+ Limit use of display sleep assertion when <video> element is off-screen.
+ https://bugs.webkit.org/show_bug.cgi?id=123041
+
+ Reviewed by Darin Adler.
+
+ Use page visibility changes to suspend and resume the use of sleep assertions in
+ HTMLMediaElement.
+
+ Page will propogate the page visibility change notifications to its Documents, which
+ will further propogate those notifications to registered elements. Upon receiving
+ these notifications, HTMLMediaElement will release or take a DisplaySleepDisabler
+ token if necessary.
+
+ Also, rename HTMLMediaElement's updateDisableSleep() to updateSleepDisabling() and wrap
+ the implementation in a PLATFORM(MAC) guard rather than at each call site.
+
+ * dom/Document.cpp:
+ (WebCore::Document::registerForVisibilityStateCallbacks): Added registration method.
+ (WebCore::Document::unregisterForVisibilityStateCallbacks): Added unregistration method.
+ (WebCore::Document::visibilityStateChanged): Call all registered clients.
+ * dom/Document.h:
+ * dom/Element.h:
+ (WebCore::Element::visibilityStateChanged): Added default virtual method to be overridden
+ by subclasses.
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::HTMLMediaElement): Register for the notification, and check the
+ current status of Document::hidden().
+ (WebCore::HTMLMediaElement::~HTMLMediaElement): Unregister for the notification.
+ (WebCore::HTMLMediaElement::visibilityStateChanged): Set m_displaySleepDisablingSuspended
+ and call updateSleepDisabling().
+ (WebCore::HTMLMediaElement::shouldDisableSleep): Add a check for m_displaySleepDisablingSuspended.
+ * html/HTMLMediaElement.h:
+ * page/Page.cpp:
+ (WebCore::Page::setVisibilityState): Pass to every child document.
+
+ Rename updateDisableSleep() -> updateSleepDisabling():
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::HTMLMediaElement):
+ (WebCore::HTMLMediaElement::~HTMLMediaElement):
+ (WebCore::HTMLMediaElement::parseAttribute):
+ (WebCore::HTMLMediaElement::mediaPlayerRateChanged):
+ (WebCore::HTMLMediaElement::clearMediaPlayer):
+ (WebCore::HTMLMediaElement::stop):
+
2013-10-21 Thiago de Barros Lacerda <thiago.lacerda@openbossa.org>
MediaStreamTrack now tracks its own state
}
#if ENABLE(PAGE_VISIBILITY_API)
+void Document::registerForVisibilityStateChangedCallbacks(Element* element)
+{
+ m_visibilityStateCallbackElements.add(element);
+}
+
+void Document::unregisterForVisibilityStateChangedCallbacks(Element* element)
+{
+ m_visibilityStateCallbackElements.remove(element);
+}
+
+void Document::visibilityStateChanged()
+{
+ dispatchEvent(Event::create(eventNames().visibilitychangeEvent, false, false));
+ for (auto it = m_visibilityStateCallbackElements.begin(); it != m_visibilityStateCallbackElements.end(); ++it)
+ (*it)->visibilityStateChanged();
+}
+
PageVisibilityState Document::pageVisibilityState() const
{
// The visibility of the document is inherited from the visibility of the
virtual URL baseURI() const OVERRIDE;
#if ENABLE(PAGE_VISIBILITY_API)
+ void visibilityStateChanged();
String visibilityState() const;
bool hidden() const;
#endif
void captionPreferencesChanged();
#endif
+#if ENABLE(PAGE_VISIBILITY_API)
+ void registerForVisibilityStateChangedCallbacks(Element*);
+ void unregisterForVisibilityStateChangedCallbacks(Element*);
+#endif
+
void setShouldCreateRenderers(bool);
bool shouldCreateRenderers();
HashSet<Element*> m_captionPreferencesChangedElements;
#endif
+#if ENABLE(PAGE_VISIBILITY_API)
+ HashSet<Element*> m_visibilityStateCallbackElements;
+#endif
+
HashMap<StringImpl*, Element*, CaseFoldingHash> m_elementsByAccessKey;
bool m_accessKeyMapValid;
virtual void didBecomeFullscreenElement() { }
virtual void willStopBeingFullscreenElement() { }
+#if ENABLE(PAGE_VISIBILITY_API)
+ // Use Document::registerForVisibilityStateChangedCallbacks() to subscribe to this.
+ virtual void visibilityStateChanged() { }
+#endif
+
#if ENABLE(VIDEO_TRACK)
virtual void captionPreferencesChanged() { }
#endif
, m_completelyLoaded(false)
, m_havePreparedToPlay(false)
, m_parsingInProgress(createdByParser)
+#if ENABLE(PAGE_VISIBILITY_API)
+ , m_isDisplaySleepDisablingSuspended(document.hidden())
+#endif
#if ENABLE(VIDEO_TRACK)
, m_tracksAreReady(true)
, m_haveVisibleTextTrack(false)
document.registerForMediaVolumeCallbacks(this);
document.registerForPrivateBrowsingStateChangedCallbacks(this);
+#if ENABLE(PAGE_VISIBILITY_API)
+ document.registerForVisibilityStateChangedCallbacks(this);
+#endif
+
if (document.settings() && document.settings()->mediaPlaybackRequiresUserGesture()) {
addBehaviorRestriction(RequireUserGestureForRateChangeRestriction);
addBehaviorRestriction(RequireUserGestureForLoadRestriction);
setShouldDelayLoadEvent(false);
document().unregisterForMediaVolumeCallbacks(this);
document().unregisterForPrivateBrowsingStateChangedCallbacks(this);
+
+#if ENABLE(PAGE_VISIBILITY_API)
+ document().unregisterForVisibilityStateChangedCallbacks(this);
+#endif
+
#if ENABLE(VIDEO_TRACK)
document().unregisterForCaptionPreferencesChangedCallbacks(this);
if (m_audioTracks) {
}
} else if (name == controlsAttr)
configureMediaControls();
-#if PLATFORM(MAC)
else if (name == loopAttr)
- updateDisableSleep();
-#endif
+ updateSleepDisabling();
else if (name == preloadAttr) {
if (equalIgnoringCase(value, "none"))
m_preload = MediaPlayer::None;
if (m_playing)
invalidateCachedTime();
-#if PLATFORM(MAC)
- updateDisableSleep();
-#endif
+ updateSleepDisabling();
endProcessingMediaPlayerCallback();
}
configureTextTrackDisplay();
#endif
-#if PLATFORM(MAC)
- updateDisableSleep();
-#endif
+ updateSleepDisabling();
}
bool HTMLMediaElement::canSuspend() const
// if the media was not fully loaded. This handles all other cases.
m_player.clear();
-#if PLATFORM(MAC)
- updateDisableSleep();
-#endif
+ updateSleepDisabling();
}
void HTMLMediaElement::suspend(ReasonForSuspension why)
updateVolume();
}
+#if ENABLE(PAGE_VISIBILITY_API)
+void HTMLMediaElement::visibilityStateChanged()
+{
+ LOG(Media, "HTMLMediaElement::visibilityStateChanged");
+ m_isDisplaySleepDisablingSuspended = document().hidden();
+ updateSleepDisabling();
+}
+#endif
+
void HTMLMediaElement::defaultEventHandler(Event* event)
{
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
}
}
-#if PLATFORM(MAC)
-void HTMLMediaElement::updateDisableSleep()
+void HTMLMediaElement::updateSleepDisabling()
{
+#if PLATFORM(MAC)
if (!shouldDisableSleep() && m_sleepDisabler)
m_sleepDisabler = nullptr;
else if (shouldDisableSleep() && !m_sleepDisabler)
m_sleepDisabler = DisplaySleepDisabler::create("com.apple.WebCore: HTMLMediaElement playback");
+#endif
}
+#if PLATFORM(MAC)
bool HTMLMediaElement::shouldDisableSleep() const
{
+#if ENABLE(PAGE_VISIBILITY_API)
+ if (m_isDisplaySleepDisablingSuspended)
+ return false;
+#endif
+
return m_player && !m_player->paused() && hasVideo() && hasAudio() && !loop();
}
#endif
virtual void mediaVolumeDidChange() OVERRIDE;
+#if ENABLE(PAGE_VISIBILITY_API)
+ virtual void visibilityStateChanged() OVERRIDE;
+#endif
+
virtual void updateDisplayState() { }
void setReadyState(MediaPlayer::ReadyState);
bool isAutoplaying() const { return m_autoplaying; }
#if PLATFORM(MAC)
- void updateDisableSleep();
+ void updateSleepDisabling();
bool shouldDisableSleep() const;
#endif
bool m_completelyLoaded : 1;
bool m_havePreparedToPlay : 1;
bool m_parsingInProgress : 1;
+#if ENABLE(PAGE_VISIBILITY_API)
+ bool m_isDisplaySleepDisablingSuspended : 1;
+#endif
#if ENABLE(VIDEO_TRACK)
bool m_tracksAreReady : 1;
documents.append(*frame->document());
for (size_t i = 0, size = documents.size(); i < size; ++i)
- documents[i]->dispatchEvent(Event::create(eventNames().visibilitychangeEvent, false, false));
+ documents[i]->visibilityStateChanged();
}
#endif