- Revision
- 157735
- Author
- jer.no...@apple.com
- Date
- 2013-10-21 14:20:55 -0700 (Mon, 21 Oct 2013)
Log Message
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):
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (157734 => 157735)
--- trunk/Source/WebCore/ChangeLog 2013-10-21 21:20:35 UTC (rev 157734)
+++ trunk/Source/WebCore/ChangeLog 2013-10-21 21:20:55 UTC (rev 157735)
@@ -1,3 +1,49 @@
+2013-10-21 Jer Noble <jer.no...@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.lace...@openbossa.org>
MediaStreamTrack now tracks its own state
Modified: trunk/Source/WebCore/dom/Document.cpp (157734 => 157735)
--- trunk/Source/WebCore/dom/Document.cpp 2013-10-21 21:20:35 UTC (rev 157734)
+++ trunk/Source/WebCore/dom/Document.cpp 2013-10-21 21:20:55 UTC (rev 157735)
@@ -1528,6 +1528,23 @@
}
#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
Modified: trunk/Source/WebCore/dom/Document.h (157734 => 157735)
--- trunk/Source/WebCore/dom/Document.h 2013-10-21 21:20:35 UTC (rev 157734)
+++ trunk/Source/WebCore/dom/Document.h 2013-10-21 21:20:55 UTC (rev 157735)
@@ -417,6 +417,7 @@
virtual URL baseURI() const OVERRIDE;
#if ENABLE(PAGE_VISIBILITY_API)
+ void visibilityStateChanged();
String visibilityState() const;
bool hidden() const;
#endif
@@ -967,6 +968,11 @@
void captionPreferencesChanged();
#endif
+#if ENABLE(PAGE_VISIBILITY_API)
+ void registerForVisibilityStateChangedCallbacks(Element*);
+ void unregisterForVisibilityStateChangedCallbacks(Element*);
+#endif
+
void setShouldCreateRenderers(bool);
bool shouldCreateRenderers();
@@ -1439,6 +1445,10 @@
HashSet<Element*> m_captionPreferencesChangedElements;
#endif
+#if ENABLE(PAGE_VISIBILITY_API)
+ HashSet<Element*> m_visibilityStateCallbackElements;
+#endif
+
HashMap<StringImpl*, Element*, CaseFoldingHash> m_elementsByAccessKey;
bool m_accessKeyMapValid;
Modified: trunk/Source/WebCore/dom/Element.h (157734 => 157735)
--- trunk/Source/WebCore/dom/Element.h 2013-10-21 21:20:35 UTC (rev 157734)
+++ trunk/Source/WebCore/dom/Element.h 2013-10-21 21:20:55 UTC (rev 157735)
@@ -418,6 +418,11 @@
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
Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (157734 => 157735)
--- trunk/Source/WebCore/html/HTMLMediaElement.cpp 2013-10-21 21:20:35 UTC (rev 157734)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp 2013-10-21 21:20:55 UTC (rev 157735)
@@ -317,6 +317,9 @@
, 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)
@@ -342,6 +345,10 @@
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);
@@ -367,6 +374,11 @@
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) {
@@ -459,10 +471,8 @@
}
} 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;
@@ -3754,9 +3764,7 @@
if (m_playing)
invalidateCachedTime();
-#if PLATFORM(MAC)
- updateDisableSleep();
-#endif
+ updateSleepDisabling();
endProcessingMediaPlayerCallback();
}
@@ -4171,9 +4179,7 @@
configureTextTrackDisplay();
#endif
-#if PLATFORM(MAC)
- updateDisableSleep();
-#endif
+ updateSleepDisabling();
}
bool HTMLMediaElement::canSuspend() const
@@ -4207,9 +4213,7 @@
// 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)
@@ -4268,6 +4272,15 @@
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)
@@ -5025,17 +5038,24 @@
}
}
+void HTMLMediaElement::updateSleepDisabling()
+{
#if PLATFORM(MAC)
-void HTMLMediaElement::updateDisableSleep()
-{
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
Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (157734 => 157735)
--- trunk/Source/WebCore/html/HTMLMediaElement.h 2013-10-21 21:20:35 UTC (rev 157734)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h 2013-10-21 21:20:55 UTC (rev 157735)
@@ -458,6 +458,10 @@
virtual void mediaVolumeDidChange() OVERRIDE;
+#if ENABLE(PAGE_VISIBILITY_API)
+ virtual void visibilityStateChanged() OVERRIDE;
+#endif
+
virtual void updateDisplayState() { }
void setReadyState(MediaPlayer::ReadyState);
@@ -621,7 +625,7 @@
bool isAutoplaying() const { return m_autoplaying; }
#if PLATFORM(MAC)
- void updateDisableSleep();
+ void updateSleepDisabling();
bool shouldDisableSleep() const;
#endif
@@ -730,6 +734,9 @@
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;
Modified: trunk/Source/WebCore/page/Page.cpp (157734 => 157735)
--- trunk/Source/WebCore/page/Page.cpp 2013-10-21 21:20:35 UTC (rev 157734)
+++ trunk/Source/WebCore/page/Page.cpp 2013-10-21 21:20:55 UTC (rev 157735)
@@ -1244,7 +1244,7 @@
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