HTMLMediaElement can hold onto display sleep assertion while process is suspended.
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Jul 2019 00:08:00 +0000 (00:08 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Jul 2019 00:08:00 +0000 (00:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=199471
<rdar://problem/52124320>

If the WebContent process is suspended before HTMLMediaElement gets a callback telling it
that the MediaPlayer has stopped playing, the SleepDisabler may stay set (and hold a display
or system sleep assertion) for the entire duration the process is suspended, causing excess
power drain.

Add a PlatformMediaSessionClient method (and an implementation in HTMLMediaElement) which will
be called during the preperation for process suspension, and in this callback, clear the
SleepDisabler token.

Reviewed by Eric Carlson.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::shouldDisableSleep const):
(WebCore::HTMLMediaElement::processIsSuspendedChanged):
* html/HTMLMediaElement.h:
* platform/audio/PlatformMediaSession.h:
(WebCore::PlatformMediaSessionClient::processIsSuspendedChanged):
* platform/audio/PlatformMediaSessionManager.cpp:
(WebCore::PlatformMediaSessionManager::processWillSuspend):
(WebCore::PlatformMediaSessionManager::processDidResume):
* platform/audio/PlatformMediaSessionManager.h:
(WebCore::PlatformMediaSessionManager::processIsSuspended const):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@247118 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/platform/audio/PlatformMediaSession.h
Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp
Source/WebCore/platform/audio/PlatformMediaSessionManager.h

index 502db28..3d24cc4 100644 (file)
@@ -1,3 +1,32 @@
+2019-07-03  Jer Noble  <jer.noble@apple.com>
+
+        HTMLMediaElement can hold onto display sleep assertion while process is suspended.
+        https://bugs.webkit.org/show_bug.cgi?id=199471
+        <rdar://problem/52124320>
+
+        If the WebContent process is suspended before HTMLMediaElement gets a callback telling it
+        that the MediaPlayer has stopped playing, the SleepDisabler may stay set (and hold a display
+        or system sleep assertion) for the entire duration the process is suspended, causing excess
+        power drain.
+
+        Add a PlatformMediaSessionClient method (and an implementation in HTMLMediaElement) which will
+        be called during the preperation for process suspension, and in this callback, clear the
+        SleepDisabler token.
+
+        Reviewed by Eric Carlson.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::shouldDisableSleep const):
+        (WebCore::HTMLMediaElement::processIsSuspendedChanged):
+        * html/HTMLMediaElement.h:
+        * platform/audio/PlatformMediaSession.h:
+        (WebCore::PlatformMediaSessionClient::processIsSuspendedChanged):
+        * platform/audio/PlatformMediaSessionManager.cpp:
+        (WebCore::PlatformMediaSessionManager::processWillSuspend):
+        (WebCore::PlatformMediaSessionManager::processDidResume):
+        * platform/audio/PlatformMediaSessionManager.h:
+        (WebCore::PlatformMediaSessionManager::processIsSuspended const):
+
 2019-07-03  Jonathan Bedard  <jbedard@apple.com>
 
         [Catalina] Enable WebKit build
index 24c687e..9916a3a 100644 (file)
@@ -6923,6 +6923,9 @@ HTMLMediaElement::SleepType HTMLMediaElement::shouldDisableSleep() const
         return SleepType::System;
 #endif
 
+    if (PlatformMediaSessionManager::sharedManager().processIsSuspended())
+        return SleepType::None;
+
     bool shouldBeAbleToSleep = !hasVideo() || !hasAudio();
 #if ENABLE(MEDIA_STREAM)
     // Remote media stream video tracks may have their corresponding audio tracks being played outside of the media element. Let's ensure to not IDLE the screen in that case.
@@ -7742,6 +7745,12 @@ bool HTMLMediaElement::processingUserGestureForMedia() const
 {
     return document().processingUserGestureForMedia();
 }
+
+void HTMLMediaElement::processIsSuspendedChanged()
+{
+    updateSleepDisabling();
+}
+
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
 
 void HTMLMediaElement::scheduleUpdateMediaState()
index 2f7047e..682e223 100644 (file)
@@ -894,6 +894,7 @@ private:
     bool canProduceAudio() const final;
     bool processingUserGestureForMedia() const final;
     bool hasMediaStreamSource() const final;
+    void processIsSuspendedChanged() final;
 
     void pageMutedStateDidChange() override;
 
index 9c35117..1d04187 100644 (file)
@@ -259,6 +259,8 @@ public:
 
     virtual bool hasMediaStreamSource() const { return false; }
 
+    virtual void processIsSuspendedChanged() { }
+
 protected:
     virtual ~PlatformMediaSessionClient() = default;
 };
index b42c214..6f99695 100644 (file)
@@ -368,6 +368,10 @@ void PlatformMediaSessionManager::processWillSuspend()
         return;
     m_processIsSuspended = true;
 
+    forEachSession([&] (auto& session) {
+        session.client().processIsSuspendedChanged();
+    });
+
 #if USE(AUDIO_SESSION)
     if (m_becameActive && shouldDeactivateAudioSession()) {
         AudioSession::sharedSession().tryToSetActive(false);
@@ -383,6 +387,10 @@ void PlatformMediaSessionManager::processDidResume()
         return;
     m_processIsSuspended = false;
 
+    forEachSession([&] (auto& session) {
+        session.client().processIsSuspendedChanged();
+    });
+
 #if USE(AUDIO_SESSION)
     if (!m_becameActive && activeAudioSessionRequired()) {
         m_becameActive = AudioSession::sharedSession().tryToSetActive(true);
index b9119e0..c327397 100644 (file)
@@ -134,6 +134,8 @@ public:
 
     void forEachMatchingSession(const Function<bool(const PlatformMediaSession&)>& predicate, const Function<void(PlatformMediaSession&)>& matchingCallback);
 
+    bool processIsSuspended() const { return m_processIsSuspended; }
+
 protected:
     friend class PlatformMediaSession;
     explicit PlatformMediaSessionManager();
@@ -147,8 +149,6 @@ protected:
 
     AudioHardwareListener* audioHardwareListener() { return m_audioHardwareListener.get(); }
 
-    bool processIsSuspended() const { return m_processIsSuspended; }
-
 #if !RELEASE_LOG_DISABLED
     const Logger& logger() const final { return m_logger; }
     const void* logIdentifier() const final { return nullptr; }