Title: [276389] trunk
Revision
276389
Author
[email protected]
Date
2021-04-21 13:53:00 -0700 (Wed, 21 Apr 2021)

Log Message

GPUProcess launches unnecessarily when loading the amazon front page
https://bugs.webkit.org/show_bug.cgi?id=224843

Reviewed by Eric Carlson.

Source/WebCore:

Amazon.com was going media-related feature detection like so:
```
!!h.createElement("audio").canPlayType
!!h.createElement("video").canPlayType
```

Constructing an HTMLAudioElement / HTMLVideoElement would initialize a MediaSession
object, which would launch the GPUProcess. Running such code should really not require
launching the GPUProcess though.

To address this, I made the MediaSession initialization lazy. Instead of doing it when
constructing an HTMLMediaElement, we now do it as soon as we actually need a MediaSession
in the mediaSession() getter. This will at the very least happen in prepareForLoad() after
setting the 'src' attribute. However, in cases where the HTMLMediaElement is not used for
anyway meaningful (e.g no 'src' attribute is ever set), then we avoid launching the
GPUProcess.

I have verified on an iPad that visiting the amazon.com front page and searching for
something no longer launches the GPUProcess after this change. This changes also seems to
be a ~3.6% PLUM progression on iPhone and potentially higher on iPad.

* html/HTMLAudioElement.cpp:
(WebCore::HTMLAudioElement::create):
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::HTMLMediaElement):
(WebCore::HTMLMediaElement::initializeMediaSession):
(WebCore::HTMLMediaElement::~HTMLMediaElement):
(WebCore::HTMLMediaElement::registerWithDocument):
(WebCore::HTMLMediaElement::unregisterWithDocument):
(WebCore::HTMLMediaElement::prepareForDocumentSuspension):
(WebCore::HTMLMediaElement::resumeFromDocumentSuspension):
(WebCore::HTMLMediaElement::parseAttribute):
(WebCore::HTMLMediaElement::didFinishInsertingNode):
(WebCore::HTMLMediaElement::prepareForLoad):
(WebCore::HTMLMediaElement::selectMediaResource):
(WebCore::HTMLMediaElement::loadResource):
(WebCore::HTMLMediaElement::mediaLoadingFailed):
(WebCore::HTMLMediaElement::setReadyState):
(WebCore::HTMLMediaElement::seekWithTolerance):
(WebCore::HTMLMediaElement::play):
(WebCore::HTMLMediaElement::playInternal):
(WebCore::HTMLMediaElement::pause):
(WebCore::HTMLMediaElement::pauseInternal):
(WebCore::HTMLMediaElement::setVolume):
(WebCore::HTMLMediaElement::setMuted):
(WebCore::HTMLMediaElement::beginScrubbing):
(WebCore::HTMLMediaElement::mediaPlayerDidAddAudioTrack):
(WebCore::HTMLMediaElement::sourceWasAdded):
(WebCore::HTMLMediaElement::mediaPlayerTimeChanged):
(WebCore::HTMLMediaElement::addBehaviorRestrictionsOnEndIfNecessary):
(WebCore::HTMLMediaElement::seekToPlaybackPositionEndedTimerFired):
(WebCore::HTMLMediaElement::mediaEngineWasUpdated):
(WebCore::HTMLMediaElement::mediaPlayerCharacteristicChanged):
(WebCore::HTMLMediaElement::pausedForUserInteraction const):
(WebCore::HTMLMediaElement::updatePlayState):
(WebCore::HTMLMediaElement::checkForAudioAndVideo):
(WebCore::HTMLMediaElement::clearMediaPlayer):
(WebCore::HTMLMediaElement::stopWithoutDestroyingMediaPlayer):
(WebCore::HTMLMediaElement::stop):
(WebCore::HTMLMediaElement::suspend):
(WebCore::HTMLMediaElement::resume):
(WebCore::HTMLMediaElement::visibilityStateChanged):
(WebCore::HTMLMediaElement::webkitShowPlaybackTargetPicker):
(WebCore::HTMLMediaElement::wirelessRoutesAvailableDidChange):
(WebCore::HTMLMediaElement::setIsPlayingToWirelessTarget):
(WebCore::HTMLMediaElement::addEventListener):
(WebCore::HTMLMediaElement::removeEventListener):
(WebCore::HTMLMediaElement::enqueuePlaybackTargetAvailabilityChangedEvent):
(WebCore::HTMLMediaElement::remoteHasAvailabilityCallbacksChanged):
(WebCore::HTMLMediaElement::exitFullscreen):
(WebCore::HTMLMediaElement::shouldForceControlsDisplay const):
(WebCore::HTMLMediaElement::configureMediaControls):
(WebCore::HTMLMediaElement::createMediaPlayer):
(WebCore::HTMLMediaElement::mediaPlayerIsFullscreenPermitted const):
(WebCore::HTMLMediaElement::removeBehaviorRestrictionsAfterFirstUserGesture):
(WebCore::HTMLMediaElement::updateRateChangeRestrictions):
(WebCore::HTMLMediaElement::maximumSourceBufferSize const):
(WebCore::HTMLMediaElement::updateMediaState):
(WebCore::HTMLMediaElement::mediaState const):
(WebCore::HTMLMediaElement::purgeBufferedDataIfPossible):
(WebCore::HTMLMediaElement::allowsMediaDocumentInlinePlaybackChanged):
(WebCore::HTMLMediaElement::isVisibleInViewportChanged):
(WebCore::HTMLMediaElement::updateShouldAutoplay):
(WebCore::HTMLMediaElement::updateShouldPlay):
(WebCore::HTMLMediaElement::playbackControlsManagerBehaviorRestrictionsTimerFired):
(WebCore::HTMLMediaElement::setInActiveDocument):
(WebCore::HTMLMediaElement::mediaSession const):
* html/HTMLMediaElement.h:
* html/HTMLVideoElement.cpp:
(WebCore::HTMLVideoElement::create):

Tools:

Add API test coverage.

* TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm:
(TEST):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (276388 => 276389)


--- trunk/Source/WebCore/ChangeLog	2021-04-21 20:11:31 UTC (rev 276388)
+++ trunk/Source/WebCore/ChangeLog	2021-04-21 20:53:00 UTC (rev 276389)
@@ -1,3 +1,101 @@
+2021-04-21  Chris Dumez  <[email protected]>
+
+        GPUProcess launches unnecessarily when loading the amazon front page
+        https://bugs.webkit.org/show_bug.cgi?id=224843
+
+        Reviewed by Eric Carlson.
+
+        Amazon.com was going media-related feature detection like so:
+        ```
+        !!h.createElement("audio").canPlayType
+        !!h.createElement("video").canPlayType
+        ```
+
+        Constructing an HTMLAudioElement / HTMLVideoElement would initialize a MediaSession
+        object, which would launch the GPUProcess. Running such code should really not require
+        launching the GPUProcess though.
+
+        To address this, I made the MediaSession initialization lazy. Instead of doing it when
+        constructing an HTMLMediaElement, we now do it as soon as we actually need a MediaSession
+        in the mediaSession() getter. This will at the very least happen in prepareForLoad() after
+        setting the 'src' attribute. However, in cases where the HTMLMediaElement is not used for
+        anyway meaningful (e.g no 'src' attribute is ever set), then we avoid launching the
+        GPUProcess.
+
+        I have verified on an iPad that visiting the amazon.com front page and searching for
+        something no longer launches the GPUProcess after this change. This changes also seems to
+        be a ~3.6% PLUM progression on iPhone and potentially higher on iPad.
+
+        * html/HTMLAudioElement.cpp:
+        (WebCore::HTMLAudioElement::create):
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::HTMLMediaElement):
+        (WebCore::HTMLMediaElement::initializeMediaSession):
+        (WebCore::HTMLMediaElement::~HTMLMediaElement):
+        (WebCore::HTMLMediaElement::registerWithDocument):
+        (WebCore::HTMLMediaElement::unregisterWithDocument):
+        (WebCore::HTMLMediaElement::prepareForDocumentSuspension):
+        (WebCore::HTMLMediaElement::resumeFromDocumentSuspension):
+        (WebCore::HTMLMediaElement::parseAttribute):
+        (WebCore::HTMLMediaElement::didFinishInsertingNode):
+        (WebCore::HTMLMediaElement::prepareForLoad):
+        (WebCore::HTMLMediaElement::selectMediaResource):
+        (WebCore::HTMLMediaElement::loadResource):
+        (WebCore::HTMLMediaElement::mediaLoadingFailed):
+        (WebCore::HTMLMediaElement::setReadyState):
+        (WebCore::HTMLMediaElement::seekWithTolerance):
+        (WebCore::HTMLMediaElement::play):
+        (WebCore::HTMLMediaElement::playInternal):
+        (WebCore::HTMLMediaElement::pause):
+        (WebCore::HTMLMediaElement::pauseInternal):
+        (WebCore::HTMLMediaElement::setVolume):
+        (WebCore::HTMLMediaElement::setMuted):
+        (WebCore::HTMLMediaElement::beginScrubbing):
+        (WebCore::HTMLMediaElement::mediaPlayerDidAddAudioTrack):
+        (WebCore::HTMLMediaElement::sourceWasAdded):
+        (WebCore::HTMLMediaElement::mediaPlayerTimeChanged):
+        (WebCore::HTMLMediaElement::addBehaviorRestrictionsOnEndIfNecessary):
+        (WebCore::HTMLMediaElement::seekToPlaybackPositionEndedTimerFired):
+        (WebCore::HTMLMediaElement::mediaEngineWasUpdated):
+        (WebCore::HTMLMediaElement::mediaPlayerCharacteristicChanged):
+        (WebCore::HTMLMediaElement::pausedForUserInteraction const):
+        (WebCore::HTMLMediaElement::updatePlayState):
+        (WebCore::HTMLMediaElement::checkForAudioAndVideo):
+        (WebCore::HTMLMediaElement::clearMediaPlayer):
+        (WebCore::HTMLMediaElement::stopWithoutDestroyingMediaPlayer):
+        (WebCore::HTMLMediaElement::stop):
+        (WebCore::HTMLMediaElement::suspend):
+        (WebCore::HTMLMediaElement::resume):
+        (WebCore::HTMLMediaElement::visibilityStateChanged):
+        (WebCore::HTMLMediaElement::webkitShowPlaybackTargetPicker):
+        (WebCore::HTMLMediaElement::wirelessRoutesAvailableDidChange):
+        (WebCore::HTMLMediaElement::setIsPlayingToWirelessTarget):
+        (WebCore::HTMLMediaElement::addEventListener):
+        (WebCore::HTMLMediaElement::removeEventListener):
+        (WebCore::HTMLMediaElement::enqueuePlaybackTargetAvailabilityChangedEvent):
+        (WebCore::HTMLMediaElement::remoteHasAvailabilityCallbacksChanged):
+        (WebCore::HTMLMediaElement::exitFullscreen):
+        (WebCore::HTMLMediaElement::shouldForceControlsDisplay const):
+        (WebCore::HTMLMediaElement::configureMediaControls):
+        (WebCore::HTMLMediaElement::createMediaPlayer):
+        (WebCore::HTMLMediaElement::mediaPlayerIsFullscreenPermitted const):
+        (WebCore::HTMLMediaElement::removeBehaviorRestrictionsAfterFirstUserGesture):
+        (WebCore::HTMLMediaElement::updateRateChangeRestrictions):
+        (WebCore::HTMLMediaElement::maximumSourceBufferSize const):
+        (WebCore::HTMLMediaElement::updateMediaState):
+        (WebCore::HTMLMediaElement::mediaState const):
+        (WebCore::HTMLMediaElement::purgeBufferedDataIfPossible):
+        (WebCore::HTMLMediaElement::allowsMediaDocumentInlinePlaybackChanged):
+        (WebCore::HTMLMediaElement::isVisibleInViewportChanged):
+        (WebCore::HTMLMediaElement::updateShouldAutoplay):
+        (WebCore::HTMLMediaElement::updateShouldPlay):
+        (WebCore::HTMLMediaElement::playbackControlsManagerBehaviorRestrictionsTimerFired):
+        (WebCore::HTMLMediaElement::setInActiveDocument):
+        (WebCore::HTMLMediaElement::mediaSession const):
+        * html/HTMLMediaElement.h:
+        * html/HTMLVideoElement.cpp:
+        (WebCore::HTMLVideoElement::create):
+
 2021-04-21  Wenson Hsieh  <[email protected]>
 
         [iOS] Text selection in image overlays should not be limited to rectilinear quads

Modified: trunk/Source/WebCore/html/HTMLAudioElement.cpp (276388 => 276389)


--- trunk/Source/WebCore/html/HTMLAudioElement.cpp	2021-04-21 20:11:31 UTC (rev 276388)
+++ trunk/Source/WebCore/html/HTMLAudioElement.cpp	2021-04-21 20:53:00 UTC (rev 276389)
@@ -47,7 +47,6 @@
 Ref<HTMLAudioElement> HTMLAudioElement::create(const QualifiedName& tagName, Document& document, bool createdByParser)
 {
     auto element = adoptRef(*new HTMLAudioElement(tagName, document, createdByParser));
-    element->finishInitialization();
     element->suspendIfNeeded();
     return element;
 }

Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (276388 => 276389)


--- trunk/Source/WebCore/html/HTMLMediaElement.cpp	2021-04-21 20:11:31 UTC (rev 276388)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp	2021-04-21 20:53:00 UTC (rev 276389)
@@ -432,6 +432,8 @@
     , m_tracksAreReady(true)
     , m_haveVisibleTextTrack(false)
     , m_processingPreferenceChange(false)
+    , m_shouldAudioPlaybackRequireUserGesture(document.topDocument().audioPlaybackRequiresUserGesture() && !processingUserGestureForMedia())
+    , m_shouldVideoPlaybackRequireUserGesture(document.topDocument().videoPlaybackRequiresUserGesture() && !processingUserGestureForMedia())
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
     , m_remote(RemotePlayback::create(*this))
 #endif
@@ -449,8 +451,9 @@
     InspectorInstrumentation::addEventListenersToNode(*this);
 }
 
-void HTMLMediaElement::finishInitialization()
+void HTMLMediaElement::initializeMediaSession()
 {
+    ASSERT(!m_mediaSession);
     m_mediaSession = makeUnique<MediaElementSession>(*this);
 
     m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForFullscreen);
@@ -468,12 +471,7 @@
         m_mediaSession->addBehaviorRestriction(MediaElementSession::InvisibleAutoplayNotPermitted);
 
     if (document.ownerElement() || !document.isMediaDocument()) {
-        const auto& topDocument = document.topDocument();
-        const bool isProcessingUserGesture = processingUserGestureForMedia();
-        const bool shouldAudioPlaybackRequireUserGesture = topDocument.audioPlaybackRequiresUserGesture() && !isProcessingUserGesture;
-        const bool shouldVideoPlaybackRequireUserGesture = topDocument.videoPlaybackRequiresUserGesture() && !isProcessingUserGesture;
-
-        if (shouldVideoPlaybackRequireUserGesture) {
+        if (m_shouldVideoPlaybackRequireUserGesture) {
             m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForVideoRateChange);
             if (document.settings().requiresUserGestureToLoadVideo())
                 m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForLoad);
@@ -482,11 +480,11 @@
         if (page && page->isLowPowerModeEnabled())
             m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForVideoDueToLowPowerMode);
 
-        if (shouldAudioPlaybackRequireUserGesture)
+        if (m_shouldAudioPlaybackRequireUserGesture)
             m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForAudioRateChange);
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
-        if (shouldVideoPlaybackRequireUserGesture || shouldAudioPlaybackRequireUserGesture)
+        if (m_shouldVideoPlaybackRequireUserGesture || m_shouldAudioPlaybackRequireUserGesture)
             m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureToShowPlaybackTargetPicker);
 #endif
 
@@ -510,7 +508,7 @@
     AudioSession::sharedSession().addMutedStateObserver(this);
 #endif
 
-    mediaSession().clientWillBeginAutoplaying();
+    m_mediaSession->clientWillBeginAutoplaying();
 }
 
 HTMLMediaElement::~HTMLMediaElement()
@@ -539,7 +537,8 @@
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
     if (hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent) || m_remote->hasAvailabilityCallbacks()) {
         m_hasPlaybackTargetAvailabilityListeners = false;
-        m_mediaSession->setHasPlaybackTargetAvailabilityListeners(false);
+        if (m_mediaSession)
+            m_mediaSession->setHasPlaybackTargetAvailabilityListeners(false);
         updateMediaState();
     }
 #endif
@@ -623,7 +622,7 @@
 {
     document.registerMediaElement(*this);
 
-    m_mediaSession->registerWithDocument(document);
+    mediaSession().registerWithDocument(document);
 
     if (m_isWaitingUntilMediaCanStart)
         document.addMediaCanStartListener(*this);
@@ -644,7 +643,8 @@
 {
     document.unregisterMediaElement(*this);
 
-    m_mediaSession->unregisterWithDocument(document);
+    if (m_mediaSession)
+        m_mediaSession->unregisterWithDocument(document);
 
     if (m_isWaitingUntilMediaCanStart)
         document.removeMediaCanStartListener(*this);
@@ -680,12 +680,12 @@
 
 void HTMLMediaElement::prepareForDocumentSuspension()
 {
-    m_mediaSession->unregisterWithDocument(document());
+    mediaSession().unregisterWithDocument(document());
 }
 
 void HTMLMediaElement::resumeFromDocumentSuspension()
 {
-    m_mediaSession->registerWithDocument(document());
+    mediaSession().registerWithDocument(document());
     updateShouldAutoplay();
 }
 
@@ -738,7 +738,7 @@
 
         // The attribute must be ignored if the autoplay attribute is present
         if (!autoplay() && !m_havePreparedToPlay && m_player)
-            m_player->setPreload(m_mediaSession->effectivePreloadForElement());
+            m_player->setPreload(mediaSession().effectivePreloadForElement());
 
     } else if (name == mediagroupAttr)
         setMediaGroup(value);
@@ -800,7 +800,7 @@
     if (!m_explicitlyMuted) {
         m_explicitlyMuted = true;
         m_muted = hasAttributeWithoutSynchronization(mutedAttr);
-        m_mediaSession->canProduceAudioChanged();
+        mediaSession().canProduceAudioChanged();
     }
 
     configureMediaControls();
@@ -1206,7 +1206,7 @@
         // 9 - Invoke the media element's resource selection algorithm.
         // Note, unless the restriction on requiring user action has been removed,
         // do not begin downloading data.
-        if (m_mediaSession->dataLoadingPermitted())
+        if (mediaSession().dataLoadingPermitted())
             selectMediaResource();
     }
 
@@ -1257,7 +1257,7 @@
     if (m_resourceSelectionTaskQueue.hasPendingTasks())
         return;
 
-    if (!m_mediaSession->pageAllowsDataLoading()) {
+    if (!mediaSession().pageAllowsDataLoading()) {
         ALWAYS_LOG(LOGIDENTIFIER, "not allowed to load in background, waiting");
         setShouldDelayLoadEvent(false);
         if (m_isWaitingUntilMediaCanStart)
@@ -1270,7 +1270,7 @@
     // Once the page has allowed an element to load media, it is free to load at will. This allows a
     // playlist that starts in a foreground tab to continue automatically if the tab is subsequently
     // put into the background.
-    m_mediaSession->removeBehaviorRestriction(MediaElementSession::RequirePageConsentToLoadMedia);
+    mediaSession().removeBehaviorRestriction(MediaElementSession::RequirePageConsentToLoadMedia);
 
     auto logSiteIdentifier = LOGIDENTIFIER;
     UNUSED_PARAM(logSiteIdentifier);
@@ -1495,7 +1495,7 @@
     m_player->setPrivateBrowsingMode(privateMode);
 
     if (!autoplay() && !m_havePreparedToPlay)
-        m_player->setPreload(m_mediaSession->effectivePreloadForElement());
+        m_player->setPreload(mediaSession().effectivePreloadForElement());
     m_player->setPreservesPitch(m_webkitPreservesPitch);
     m_player->setPitchCorrectionAlgorithm(document().settings().pitchCorrectionAlgorithm());
 
@@ -1502,7 +1502,7 @@
     if (!m_explicitlyMuted) {
         m_explicitlyMuted = true;
         m_muted = hasAttributeWithoutSynchronization(mutedAttr);
-        m_mediaSession->canProduceAudioChanged();
+        mediaSession().canProduceAudioChanged();
     }
 
     updateVolume();
@@ -2223,7 +2223,7 @@
 
     logMediaLoadRequest(document().page(), String(), convertEnumerationToString(error), false);
 
-    m_mediaSession->clientCharacteristicsChanged();
+    mediaSession().clientCharacteristicsChanged();
 }
 
 void HTMLMediaElement::setNetworkState(MediaPlayer::NetworkState state)
@@ -2416,7 +2416,7 @@
         scheduleUpdateMediaState();
 #endif
 
-        m_mediaSession->clientCharacteristicsChanged();
+        mediaSession().clientCharacteristicsChanged();
     }
 
     if (m_readyState >= HAVE_CURRENT_DATA && oldState < HAVE_CURRENT_DATA) {
@@ -2456,7 +2456,7 @@
 
     // If we transition to the Future Data state and we're about to begin playing, ensure playback is actually permitted first,
     // honoring any playback denial reasons such as the requirement of a user gesture.
-    if (m_readyState == HAVE_FUTURE_DATA && oldState < HAVE_FUTURE_DATA && potentiallyPlaying() && !m_mediaSession->playbackStateChangePermitted(MediaPlaybackState::Playing)) {
+    if (m_readyState == HAVE_FUTURE_DATA && oldState < HAVE_FUTURE_DATA && potentiallyPlaying() && !mediaSession().playbackStateChangePermitted(MediaPlaybackState::Playing)) {
         auto canTransition = canTransitionFromAutoplayToPlay();
         if (canTransition && canTransition.value() == MediaPlaybackDenialReason::UserGestureRequired)
             ALWAYS_LOG(LOGIDENTIFIER, "Autoplay blocked, user gesture required");
@@ -2976,7 +2976,7 @@
         seekTask();
 
     if (processingUserGestureForMedia())
-        m_mediaSession->removeBehaviorRestriction(MediaElementSession::RequireUserGestureToControlControlsManager);
+        mediaSession().removeBehaviorRestriction(MediaElementSession::RequireUserGestureToControlControlsManager);
 }
 
 void HTMLMediaElement::seekTask()
@@ -3445,7 +3445,7 @@
 {
     ALWAYS_LOG(LOGIDENTIFIER);
 
-    auto success = m_mediaSession->playbackStateChangePermitted(MediaPlaybackState::Playing);
+    auto success = mediaSession().playbackStateChangePermitted(MediaPlaybackState::Playing);
     if (!success) {
         if (success.value() == MediaPlaybackDenialReason::UserGestureRequired)
             setAutoplayEventPlaybackState(AutoplayEventPlaybackState::PreventedAutoplay);
@@ -3471,7 +3471,7 @@
 {
     ALWAYS_LOG(LOGIDENTIFIER);
 
-    auto success = m_mediaSession->playbackStateChangePermitted(MediaPlaybackState::Playing);
+    auto success = mediaSession().playbackStateChangePermitted(MediaPlaybackState::Playing);
     if (!success) {
         ERROR_LOG(LOGIDENTIFIER, "playback not permitted: ", success.value());
         if (success.value() == MediaPlaybackDenialReason::UserGestureRequired)
@@ -3498,7 +3498,7 @@
         return;
     }
 
-    if (!m_mediaSession->clientWillBeginPlayback()) {
+    if (!mediaSession().clientWillBeginPlayback()) {
         ALWAYS_LOG(LOGIDENTIFIER, "returning because of interruption");
         return;
     }
@@ -3552,7 +3552,7 @@
     if (m_waitingToEnterFullscreen)
         m_waitingToEnterFullscreen = false;
 
-    if (!m_mediaSession->playbackStateChangePermitted(MediaPlaybackState::Paused))
+    if (!mediaSession().playbackStateChangePermitted(MediaPlaybackState::Paused))
         return;
 
     if (processingUserGestureForMedia())
@@ -3575,7 +3575,7 @@
         return;
     }
 
-    if (!m_mediaSession->clientWillPausePlayback()) {
+    if (!mediaSession().clientWillPausePlayback()) {
         ALWAYS_LOG(LOGIDENTIFIER, "returning because of interruption");
         return;
     }
@@ -3584,7 +3584,7 @@
     if (!m_player || m_networkState == NETWORK_EMPTY) {
         // Unless the restriction on media requiring user action has been lifted
         // don't trigger loading if a script calls pause().
-        if (!m_mediaSession->playbackStateChangePermitted(MediaPlaybackState::Playing))
+        if (!mediaSession().playbackStateChangePermitted(MediaPlaybackState::Playing))
             return;
         selectMediaResource();
     }
@@ -3673,7 +3673,7 @@
     updateVolume();
     scheduleEvent(eventNames().volumechangeEvent);
 
-    if (isPlaying() && !m_mediaSession->playbackStateChangePermitted(MediaPlaybackState::Playing)) {
+    if (isPlaying() && !mediaSession().playbackStateChangePermitted(MediaPlaybackState::Playing)) {
         scheduleRejectPendingPlayPromises(DOMException::create(NotAllowedError));
         pauseInternal();
         setAutoplayEventPlaybackState(AutoplayEventPlaybackState::PreventedAutoplay);
@@ -3732,7 +3732,7 @@
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
         scheduleUpdateMediaState();
 #endif
-        m_mediaSession->canProduceAudioChanged();
+        mediaSession().canProduceAudioChanged();
         updateSleepDisabling();
     }
 
@@ -3787,7 +3787,7 @@
         }
     }
 
-    m_mediaSession->removeBehaviorRestriction(MediaElementSession::RequireUserGestureToControlControlsManager);
+    mediaSession().removeBehaviorRestriction(MediaElementSession::RequireUserGestureToControlControlsManager);
 }
 
 void HTMLMediaElement::endScrubbing()
@@ -3941,7 +3941,7 @@
 
 void HTMLMediaElement::mediaPlayerDidAddAudioTrack(AudioTrackPrivate& track)
 {
-    if (isPlaying() && !m_mediaSession->playbackStateChangePermitted(MediaPlaybackState::Playing)) {
+    if (isPlaying() && !mediaSession().playbackStateChangePermitted(MediaPlaybackState::Playing)) {
         scheduleRejectPendingPlayPromises(DOMException::create(NotAllowedError));
         pauseInternal();
         setAutoplayEventPlaybackState(AutoplayEventPlaybackState::PreventedAutoplay);
@@ -4685,7 +4685,7 @@
     if (m_networkState == NETWORK_EMPTY) {
         m_nextChildNodeToConsider = &source;
 #if PLATFORM(IOS_FAMILY)
-        if (m_mediaSession->dataLoadingPermitted())
+        if (mediaSession().dataLoadingPermitted())
 #endif
             selectMediaResource();
         return;
@@ -4783,7 +4783,7 @@
                 // changes paused to true and fires a simple event named pause at the media element.
                 m_paused = true;
                 scheduleEvent(eventNames().pauseEvent);
-                m_mediaSession->clientWillPausePlayback();
+                mediaSession().clientWillPausePlayback();
             }
             // Queue a task to fire a simple event named ended at the media element.
             if (!m_sentEndEvent) {
@@ -4832,7 +4832,7 @@
     if (isFullscreen())
         return;
 
-    m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureToControlControlsManager);
+    mediaSession().addBehaviorRestriction(MediaElementSession::RequireUserGestureToControlControlsManager);
     m_playbackControlsManagerBehaviorRestrictionsTimer.stop();
     m_playbackControlsManagerBehaviorRestrictionsTimer.startOneShot(hideMediaControlsAfterEndedDelay);
 }
@@ -4862,7 +4862,7 @@
     if (!m_isScrubbingRemotely)
         return;
 
-    PlatformMediaSessionManager::sharedManager().sessionDidEndRemoteScrubbing(*m_mediaSession);
+    PlatformMediaSessionManager::sharedManager().sessionDidEndRemoteScrubbing(mediaSession());
     m_isScrubbingRemotely = false;
     m_seekToPlaybackPositionEndedTimer.stop();
 #endif
@@ -5040,7 +5040,7 @@
     updateRenderer();
     endProcessingMediaPlayerCallback();
 
-    m_mediaSession->mediaEngineUpdated();
+    mediaSession().mediaEngineUpdated();
 
 #if ENABLE(ENCRYPTED_MEDIA)
     if (m_player && m_mediaKeys)
@@ -5122,7 +5122,7 @@
 
     updateRenderer();
 
-    if (!paused() && !m_mediaSession->playbackStateChangePermitted(MediaPlaybackState::Playing)) {
+    if (!paused() && !mediaSession().playbackStateChangePermitted(MediaPlaybackState::Playing)) {
         scheduleRejectPendingPlayPromises(DOMException::create(NotAllowedError));
         pauseInternal();
         setAutoplayEventPlaybackState(AutoplayEventPlaybackState::PreventedAutoplay);
@@ -5267,7 +5267,7 @@
 
 bool HTMLMediaElement::pausedForUserInteraction() const
 {
-    if (m_mediaSession->state() == PlatformMediaSession::Interrupted)
+    if (mediaSession().state() == PlatformMediaSession::Interrupted)
         return true;
 
     return false;
@@ -5338,7 +5338,7 @@
 
     ALWAYS_LOG(LOGIDENTIFIER, "shouldBePlaying = ", shouldBePlaying, ", playerPaused = ", playerPaused);
 
-    if (shouldBePlaying && playerPaused && m_mediaSession->requiresFullscreenForVideoPlayback() && (m_waitingToEnterFullscreen || !isFullscreen())) {
+    if (shouldBePlaying && playerPaused && mediaSession().requiresFullscreenForVideoPlayback() && (m_waitingToEnterFullscreen || !isFullscreen())) {
         if (!m_waitingToEnterFullscreen)
             enterFullscreen();
 
@@ -5354,7 +5354,7 @@
         invalidateCachedTime();
 
         if (playerPaused) {
-            m_mediaSession->clientWillBeginPlayback();
+            mediaSession().clientWillBeginPlayback();
 
             // Set rate, muted and volume before calling play in case they were set before the media engine was set up.
             // The media engine should just stash the rate, muted and volume values since it isn't already playing.
@@ -5401,7 +5401,7 @@
 {
     m_hasEverHadAudio |= hasAudio();
     m_hasEverHadVideo |= hasVideo();
-    m_mediaSession->canProduceAudioChanged();
+    mediaSession().canProduceAudioChanged();
 }
 
 void HTMLMediaElement::setPlaying(bool playing)
@@ -5528,7 +5528,8 @@
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
     if (hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent) || m_remote->hasAvailabilityCallbacks()) {
         m_hasPlaybackTargetAvailabilityListeners = false;
-        m_mediaSession->setHasPlaybackTargetAvailabilityListeners(false);
+        if (m_mediaSession)
+            m_mediaSession->setHasPlaybackTargetAvailabilityListeners(false);
 
         // Send an availability event in case scripts want to hide the picker when the element
         // doesn't support playback to a target.
@@ -5559,8 +5560,10 @@
     if (m_textTracks)
         configureTextTrackDisplay();
 
-    m_mediaSession->clientCharacteristicsChanged();
-    m_mediaSession->canProduceAudioChanged();
+    if (m_mediaSession) {
+        m_mediaSession->clientCharacteristicsChanged();
+        m_mediaSession->canProduceAudioChanged();
+    }
 
     m_resourceSelectionTaskQueue.cancelAllTasks();
 
@@ -5587,7 +5590,8 @@
     // Stop the playback without generating events
     setPlaying(false);
     pauseAndUpdatePlayStateImmediately();
-    m_mediaSession->clientWillBeDOMSuspended();
+    if (m_mediaSession)
+        m_mediaSession->clientWillBeDOMSuspended();
 
     setAutoplayEventPlaybackState(AutoplayEventPlaybackState::None);
 
@@ -5647,7 +5651,8 @@
     // loaded and calling it again won't cause any problems.
     clearMediaPlayer();
 
-    m_mediaSession->stopSession();
+    if (m_mediaSession)
+        m_mediaSession->stopSession();
 }
 
 void HTMLMediaElement::suspend(ReasonForSuspension reason)
@@ -5661,7 +5666,8 @@
     case ReasonForSuspension::BackForwardCache:
         stopWithoutDestroyingMediaPlayer();
         setBufferingPolicy(BufferingPolicy::MakeResourcesPurgeable);
-        m_mediaSession->addBehaviorRestriction(MediaElementSession::RequirePageConsentToResumeMedia);
+        if (m_mediaSession)
+            m_mediaSession->addBehaviorRestriction(MediaElementSession::RequirePageConsentToResumeMedia);
         break;
     case ReasonForSuspension::PageWillBeSuspended:
     case ReasonForSuspension::_javascript_DebuggerPaused:
@@ -5677,13 +5683,15 @@
 
     setInActiveDocument(true);
 
-    if (!m_mediaSession->pageAllowsPlaybackAfterResuming())
+    if (m_mediaSession && !m_mediaSession->pageAllowsPlaybackAfterResuming())
         document().addMediaCanStartListener(*this);
     else
         setPausedInternal(false);
 
-    m_mediaSession->removeBehaviorRestriction(MediaElementSession::RequirePageConsentToResumeMedia);
-    m_mediaSession->updateBufferingPolicy();
+    if (m_mediaSession) {
+        m_mediaSession->removeBehaviorRestriction(MediaElementSession::RequirePageConsentToResumeMedia);
+        m_mediaSession->updateBufferingPolicy();
+    }
 
     if (m_error && m_error->code() == MediaError::MEDIA_ERR_ABORTED && !m_resumeTaskQueue.hasPendingTask()) {
         // Restart the load if it was aborted in the middle by moving the document to the back/forward cache.
@@ -5724,7 +5732,7 @@
     ALWAYS_LOG(LOGIDENTIFIER, "visible = ", !m_elementIsHidden);
 
     updateSleepDisabling();
-    m_mediaSession->visibilityChanged();
+    mediaSession().visibilityChanged();
     if (m_player)
         m_player->setVisible(!m_elementIsHidden);
 
@@ -5732,10 +5740,10 @@
     if (!isPlayingAudio) {
         if (m_elementIsHidden) {
             ALWAYS_LOG(LOGIDENTIFIER, "Suspending playback after going to the background");
-            m_mediaSession->beginInterruption(PlatformMediaSession::EnteringBackground);
+            mediaSession().beginInterruption(PlatformMediaSession::EnteringBackground);
         } else {
             ALWAYS_LOG(LOGIDENTIFIER, "Resuming playback after entering foreground");
-            m_mediaSession->endInterruption(PlatformMediaSession::MayResumePlaying);
+            mediaSession().endInterruption(PlatformMediaSession::MayResumePlaying);
         }
     }
 }
@@ -5768,12 +5776,12 @@
     ALWAYS_LOG(LOGIDENTIFIER);
     if (processingUserGestureForMedia())
         removeBehaviorRestrictionsAfterFirstUserGesture();
-    m_mediaSession->showPlaybackTargetPicker();
+    mediaSession().showPlaybackTargetPicker();
 }
 
 void HTMLMediaElement::wirelessRoutesAvailableDidChange()
 {
-    bool hasTargets = m_mediaSession->hasWirelessPlaybackTargets();
+    bool hasTargets = mediaSession().hasWirelessPlaybackTargets();
     m_remote->availabilityChanged(hasTargets);
 
     enqueuePlaybackTargetAvailabilityChangedEvent();
@@ -5797,8 +5805,8 @@
         m_remote->isPlayingToRemoteTargetChanged(m_isPlayingToWirelessTarget);
         ALWAYS_LOG(logSiteIdentifier, m_isPlayingToWirelessTarget);
         configureMediaControls();
-        m_mediaSession->isPlayingToWirelessPlaybackTargetChanged(m_isPlayingToWirelessTarget);
-        m_mediaSession->canProduceAudioChanged();
+        mediaSession().isPlayingToWirelessPlaybackTargetChanged(m_isPlayingToWirelessTarget);
+        mediaSession().canProduceAudioChanged();
         scheduleUpdateMediaState();
         updateSleepDisabling();
 
@@ -5846,7 +5854,7 @@
 
     if (isFirstAvailabilityChangedListener) {
         m_hasPlaybackTargetAvailabilityListeners = true;
-        m_mediaSession->setHasPlaybackTargetAvailabilityListeners(true);
+        mediaSession().setHasPlaybackTargetAvailabilityListeners(true);
     }
 
     ALWAYS_LOG(LOGIDENTIFIER, "'webkitplaybacktargetavailabilitychanged'");
@@ -5872,7 +5880,7 @@
     ALWAYS_LOG(LOGIDENTIFIER, "removed last listener = ", didRemoveLastAvailabilityChangedListener);
     if (didRemoveLastAvailabilityChangedListener) {
         m_hasPlaybackTargetAvailabilityListeners = false;
-        m_mediaSession->setHasPlaybackTargetAvailabilityListeners(false);
+        mediaSession().setHasPlaybackTargetAvailabilityListeners(false);
         scheduleUpdateMediaState();
     }
 
@@ -5881,7 +5889,7 @@
 
 void HTMLMediaElement::enqueuePlaybackTargetAvailabilityChangedEvent()
 {
-    bool hasTargets = m_mediaSession->hasWirelessPlaybackTargets();
+    bool hasTargets = mediaSession().hasWirelessPlaybackTargets();
     ALWAYS_LOG(LOGIDENTIFIER, "hasTargets = ", hasTargets);
     auto event = WebKitPlaybackTargetAvailabilityEvent::create(eventNames().webkitplaybacktargetavailabilitychangedEvent, hasTargets);
     event->setTarget(this);
@@ -5920,7 +5928,7 @@
 
     ALWAYS_LOG(LOGIDENTIFIER, "hasListeners: ", hasListeners);
     m_hasPlaybackTargetAvailabilityListeners = hasListeners;
-    m_mediaSession->setHasPlaybackTargetAvailabilityListeners(hasListeners);
+    mediaSession().setHasPlaybackTargetAvailabilityListeners(hasListeners);
     scheduleUpdateMediaState();
 }
 #endif // ENABLE(WIRELESS_PLAYBACK_TARGET)
@@ -6071,7 +6079,7 @@
     if (!document().page() || !is<HTMLVideoElement>(*this))
         return;
 
-    if (!paused() && m_mediaSession->requiresFullscreenForVideoPlayback()) {
+    if (!paused() && mediaSession().requiresFullscreenForVideoPlayback()) {
         if (!document().settings().allowsInlineMediaPlaybackAfterFullscreen() || isVideoTooSmallForInlinePlayback())
             pauseInternal();
         else {
@@ -6506,7 +6514,7 @@
 bool HTMLMediaElement::shouldForceControlsDisplay() const
 {
     // Always create controls for autoplay video that requires user gesture due to being in low power mode.
-    return isVideo() && autoplay() && m_mediaSession->hasBehaviorRestriction(MediaElementSession::RequireUserGestureForVideoDueToLowPowerMode);
+    return isVideo() && autoplay() && mediaSession().hasBehaviorRestriction(MediaElementSession::RequireUserGestureForVideoDueToLowPowerMode);
 }
 
 void HTMLMediaElement::configureMediaControls()
@@ -6514,7 +6522,7 @@
     bool requireControls = controls();
 
     // Always create controls for video when fullscreen playback is required.
-    if (isVideo() && m_mediaSession->requiresFullscreenForVideoPlayback())
+    if (isVideo() && mediaSession().requiresFullscreenForVideoPlayback())
         requireControls = true;
 
     if (shouldForceControlsDisplay())
@@ -6635,7 +6643,7 @@
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
     if (hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent) || m_remote->hasAvailabilityCallbacks()) {
         m_hasPlaybackTargetAvailabilityListeners = true;
-        m_mediaSession->setHasPlaybackTargetAvailabilityListeners(true);
+        mediaSession().setHasPlaybackTargetAvailabilityListeners(true);
         enqueuePlaybackTargetAvailabilityChangedEvent(); // Ensure the event listener gets at least one event.
     }
 #endif
@@ -6949,7 +6957,7 @@
 
 bool HTMLMediaElement::mediaPlayerIsFullscreenPermitted() const
 {
-    return m_mediaSession->fullscreenPermitted();
+    return mediaSession().fullscreenPermitted();
 }
 
 bool HTMLMediaElement::mediaPlayerIsVideo() const
@@ -7157,7 +7165,7 @@
 
     m_removedBehaviorRestrictionsAfterFirstUserGesture = true;
 
-    m_mediaSession->removeBehaviorRestriction(restrictionsToRemove);
+    mediaSession().removeBehaviorRestriction(restrictionsToRemove);
     document().topDocument().noteUserInteractionWithMediaElement();
 }
 
@@ -7169,14 +7177,14 @@
 
     const auto& topDocument = document.topDocument();
     if (topDocument.videoPlaybackRequiresUserGesture())
-        m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForVideoRateChange);
+        mediaSession().addBehaviorRestriction(MediaElementSession::RequireUserGestureForVideoRateChange);
     else
-        m_mediaSession->removeBehaviorRestriction(MediaElementSession::RequireUserGestureForVideoRateChange);
+        mediaSession().removeBehaviorRestriction(MediaElementSession::RequireUserGestureForVideoRateChange);
 
     if (topDocument.audioPlaybackRequiresUserGesture())
-        m_mediaSession->addBehaviorRestriction(MediaElementSession::RequireUserGestureForAudioRateChange);
+        mediaSession().addBehaviorRestriction(MediaElementSession::RequireUserGestureForAudioRateChange);
     else
-        m_mediaSession->removeBehaviorRestriction(MediaElementSession::RequireUserGestureForAudioRateChange);
+        mediaSession().removeBehaviorRestriction(MediaElementSession::RequireUserGestureForAudioRateChange);
 }
 
 RefPtr<VideoPlaybackQuality> HTMLMediaElement::getVideoPlaybackQuality()
@@ -7541,7 +7549,7 @@
 #if ENABLE(MEDIA_SOURCE)
 size_t HTMLMediaElement::maximumSourceBufferSize(const SourceBuffer& buffer) const
 {
-    return m_mediaSession->maximumMediaSourceBufferSize(buffer);
+    return mediaSession().maximumMediaSourceBufferSize(buffer);
 }
 #endif
 
@@ -7749,7 +7757,7 @@
         return;
 
     m_mediaState = state;
-    m_mediaSession->mediaStateDidChange(m_mediaState);
+    mediaSession().mediaStateDidChange(m_mediaState);
 
     document().updateIsPlayingMedia();
 }
@@ -7767,11 +7775,11 @@
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
     if (m_hasPlaybackTargetAvailabilityListeners) {
         state |= HasPlaybackTargetAvailabilityListener;
-        if (!m_mediaSession->wirelessVideoPlaybackDisabled())
+        if (!mediaSession().wirelessVideoPlaybackDisabled())
             state |= RequiresPlaybackTargetMonitoring;
     }
 
-    bool requireUserGesture = m_mediaSession->hasBehaviorRestriction(MediaElementSession::RequireUserGestureToAutoplayToExternalDevice);
+    bool requireUserGesture = mediaSession().hasBehaviorRestriction(MediaElementSession::RequireUserGestureToAutoplayToExternalDevice);
     if (m_readyState >= HAVE_METADATA && !requireUserGesture && !m_failedToPlayToWirelessTarget)
         state |= ExternalDeviceAutoPlayCandidate;
 
@@ -7905,7 +7913,7 @@
 {
     ALWAYS_LOG(LOGIDENTIFIER);
 
-    if (!MemoryPressureHandler::singleton().isUnderMemoryPressure() && m_mediaSession->preferredBufferingPolicy() == BufferingPolicy::Default)
+    if (!MemoryPressureHandler::singleton().isUnderMemoryPressure() && mediaSession().preferredBufferingPolicy() == BufferingPolicy::Default)
         return;
 
     if (isPlayingToExternalTarget()) {
@@ -7926,7 +7934,7 @@
 
 void HTMLMediaElement::allowsMediaDocumentInlinePlaybackChanged()
 {
-    if (potentiallyPlaying() && m_mediaSession->requiresFullscreenForVideoPlayback() && !isFullscreen())
+    if (potentiallyPlaying() && mediaSession().requiresFullscreenForVideoPlayback() && !isFullscreen())
         enterFullscreen();
 }
 
@@ -7944,7 +7952,7 @@
 void HTMLMediaElement::isVisibleInViewportChanged()
 {
     m_visibilityChangeTaskQueue.enqueueTask([this] {
-        m_mediaSession->isVisibleInViewportChanged();
+        mediaSession().isVisibleInViewportChanged();
         updateShouldAutoplay();
         schedulePlaybackControlsManagerUpdate();
     });
@@ -7955,22 +7963,22 @@
     if (!autoplay())
         return;
 
-    if (!m_mediaSession->hasBehaviorRestriction(MediaElementSession::InvisibleAutoplayNotPermitted))
+    if (!mediaSession().hasBehaviorRestriction(MediaElementSession::InvisibleAutoplayNotPermitted))
         return;
 
     bool canAutoplay = mediaSession().autoplayPermitted();
     if (canAutoplay
-        && m_mediaSession->state() == PlatformMediaSession::Interrupted
-        && m_mediaSession->interruptionType() == PlatformMediaSession::InvisibleAutoplay)
-        m_mediaSession->endInterruption(PlatformMediaSession::MayResumePlaying);
+        && mediaSession().state() == PlatformMediaSession::Interrupted
+        && mediaSession().interruptionType() == PlatformMediaSession::InvisibleAutoplay)
+        mediaSession().endInterruption(PlatformMediaSession::MayResumePlaying);
     else if (!canAutoplay
-        && m_mediaSession->state() != PlatformMediaSession::Interrupted)
-        m_mediaSession->beginInterruption(PlatformMediaSession::InvisibleAutoplay);
+        && mediaSession().state() != PlatformMediaSession::Interrupted)
+        mediaSession().beginInterruption(PlatformMediaSession::InvisibleAutoplay);
 }
 
 void HTMLMediaElement::updateShouldPlay()
 {
-    if (!paused() && !m_mediaSession->playbackStateChangePermitted(MediaPlaybackState::Playing)) {
+    if (!paused() && !mediaSession().playbackStateChangePermitted(MediaPlaybackState::Playing)) {
         scheduleRejectPendingPlayPromises(DOMException::create(NotAllowedError));
         pauseInternal();
         setAutoplayEventPlaybackState(AutoplayEventPlaybackState::PreventedAutoplay);
@@ -8003,16 +8011,16 @@
     if (m_playbackControlsManagerBehaviorRestrictionsQueue.hasPendingTask())
         return;
 
-    if (!m_mediaSession->hasBehaviorRestriction(MediaElementSession::RequireUserGestureToControlControlsManager))
+    if (!mediaSession().hasBehaviorRestriction(MediaElementSession::RequireUserGestureToControlControlsManager))
         return;
 
     RefPtr<HTMLMediaElement> protectedThis(this);
     m_playbackControlsManagerBehaviorRestrictionsQueue.scheduleTask([protectedThis] () {
-        MediaElementSession* mediaElementSession = protectedThis->m_mediaSession.get();
-        if (protectedThis->isPlaying() || mediaElementSession->state() == PlatformMediaSession::Autoplaying || mediaElementSession->state() == PlatformMediaSession::Playing)
+        auto& mediaElementSession = protectedThis->mediaSession();
+        if (protectedThis->isPlaying() || mediaElementSession.state() == PlatformMediaSession::Autoplaying || mediaElementSession.state() == PlatformMediaSession::Playing)
             return;
 
-        mediaElementSession->addBehaviorRestriction(MediaElementSession::RequirePlaybackToControlControlsManager);
+        mediaElementSession.addBehaviorRestriction(MediaElementSession::RequirePlaybackToControlControlsManager);
         protectedThis->schedulePlaybackControlsManagerUpdate();
     });
 }
@@ -8079,7 +8087,8 @@
         return;
 
     m_inActiveDocument = inActiveDocument;
-    m_mediaSession->inActiveDocumentChanged();
+    if (m_mediaSession)
+        m_mediaSession->inActiveDocumentChanged();
 }
 
 HTMLMediaElementEnums::BufferingPolicy HTMLMediaElement::bufferingPolicy() const
@@ -8129,6 +8138,13 @@
     invalidateStyleAndLayerComposition();
 }
 
+MediaElementSession& HTMLMediaElement::mediaSession() const
+{
+    if (!m_mediaSession)
+        const_cast<HTMLMediaElement&>(*this).initializeMediaSession();
+    return *m_mediaSession;
 }
 
+}
+
 #endif

Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (276388 => 276389)


--- trunk/Source/WebCore/html/HTMLMediaElement.h	2021-04-21 20:11:31 UTC (rev 276388)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h	2021-04-21 20:53:00 UTC (rev 276389)
@@ -490,7 +490,7 @@
     RefPtr<VideoPlaybackQuality> getVideoPlaybackQuality();
 
     MediaPlayer::Preload preloadValue() const { return m_preload; }
-    MediaElementSession& mediaSession() const { return *m_mediaSession; }
+    WEBCORE_EXPORT MediaElementSession& mediaSession() const;
 
     void pageScaleFactorChanged();
     void userInterfaceLayoutDirectionChanged();
@@ -578,7 +578,6 @@
 
 protected:
     HTMLMediaElement(const QualifiedName&, Document&, bool createdByParser);
-    virtual void finishInitialization();
     virtual ~HTMLMediaElement();
 
     void parseAttribute(const QualifiedName&, const AtomString&) override;
@@ -891,6 +890,8 @@
     void registerWithDocument(Document&);
     void unregisterWithDocument(Document&);
 
+    void initializeMediaSession();
+
     void updateCaptionContainer();
     void ensureMediaControlsShadowRoot();
 
@@ -1105,6 +1106,8 @@
     bool m_tracksAreReady : 1;
     bool m_haveVisibleTextTrack : 1;
     bool m_processingPreferenceChange : 1;
+    bool m_shouldAudioPlaybackRequireUserGesture : 1;
+    bool m_shouldVideoPlaybackRequireUserGesture : 1;
 
     AutoplayEventPlaybackState m_autoplayEventPlaybackState { AutoplayEventPlaybackState::None };
 

Modified: trunk/Source/WebCore/html/HTMLVideoElement.cpp (276388 => 276389)


--- trunk/Source/WebCore/html/HTMLVideoElement.cpp	2021-04-21 20:11:31 UTC (rev 276388)
+++ trunk/Source/WebCore/html/HTMLVideoElement.cpp	2021-04-21 20:53:00 UTC (rev 276389)
@@ -79,7 +79,6 @@
     HTMLVideoElementPictureInPicture::providePictureInPictureTo(videoElement);
 #endif
 
-    videoElement->finishInitialization();
     videoElement->suspendIfNeeded();
     return videoElement;
 }

Modified: trunk/Tools/ChangeLog (276388 => 276389)


--- trunk/Tools/ChangeLog	2021-04-21 20:11:31 UTC (rev 276388)
+++ trunk/Tools/ChangeLog	2021-04-21 20:53:00 UTC (rev 276389)
@@ -1,3 +1,15 @@
+2021-04-21  Chris Dumez  <[email protected]>
+
+        GPUProcess launches unnecessarily when loading the amazon front page
+        https://bugs.webkit.org/show_bug.cgi?id=224843
+
+        Reviewed by Eric Carlson.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm:
+        (TEST):
+
 2021-04-21  Sam Sneddon  <[email protected]>
 
         Always pass --no-abbrev-commit to git-log/show

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm (276388 => 276389)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm	2021-04-21 20:11:31 UTC (rev 276388)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm	2021-04-21 20:53:00 UTC (rev 276389)
@@ -249,6 +249,39 @@
     EXPECT_EQ([configuration.get().processPool _gpuProcessIdentifier], 0);
 }
 
+TEST(GPUProcess, OnlyLaunchesGPUProcessWhenNecessaryMediaFeatureDetection)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    WKPreferencesSetBoolValueForKeyForTesting((__bridge WKPreferencesRef)[configuration preferences], true, WKStringCreateWithUTF8CString("UseGPUProcessForMediaEnabled"));
+    WKPreferencesSetBoolValueForKeyForTesting((__bridge WKPreferencesRef)[configuration preferences], true, WKStringCreateWithUTF8CString("CaptureVideoInGPUProcessEnabled"));
+    WKPreferencesSetBoolValueForKeyForTesting((__bridge WKPreferencesRef)[configuration preferences], true, WKStringCreateWithUTF8CString("UseGPUProcessForCanvasRenderingEnabled"));
+    WKPreferencesSetBoolValueForKeyForTesting((__bridge WKPreferencesRef)[configuration preferences], false, WKStringCreateWithUTF8CString("UseGPUProcessForDOMRenderingEnabled"));
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:configuration.get()]);
+    [webView synchronouslyLoadTestPageNamed:@"simple"];
+
+    __block bool done = false;
+    [webView evaluateJavaScript:@"!!document.createElement('audio').canPlayType" completionHandler:^(id result, NSError *error) {
+        EXPECT_TRUE(!error);
+        EXPECT_TRUE([result boolValue]);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    done = false;
+    [webView evaluateJavaScript:@"!!document.createElement('video').canPlayType" completionHandler:^(id result, NSError *error) {
+        EXPECT_TRUE(!error);
+        EXPECT_TRUE([result boolValue]);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    TestWebKitAPI::Util::spinRunLoop(10);
+
+    // This should not have launched a GPUProcess.
+    EXPECT_EQ([configuration.get().processPool _gpuProcessIdentifier], 0);
+}
+
 TEST(GPUProcess, CrashWhilePlayingVideo)
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to