Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 041d3443858bb3cfa03f843a2fcd998ccbda223a
https://github.com/WebKit/WebKit/commit/041d3443858bb3cfa03f843a2fcd998ccbda223a
Author: Eric Carlson <[email protected]>
Date: 2026-08-20 (Thu, 20 Aug 2026)
Changed paths:
A
LayoutTests/http/tests/site-isolation/now-playing-elected-across-frames-expected.txt
A
LayoutTests/http/tests/site-isolation/now-playing-elected-across-frames.html
A
LayoutTests/http/tests/site-isolation/now-playing-reelects-on-resize-expected.txt
A LayoutTests/http/tests/site-isolation/now-playing-reelects-on-resize.html
A LayoutTests/http/tests/site-isolation/resources/now-playing-frame.html
M Source/WebCore/html/MediaElementSession.cpp
M Source/WebCore/html/MediaElementSession.h
M Source/WebCore/platform/MediaStrategy.cpp
M Source/WebCore/platform/MediaStrategy.h
M Source/WebCore/platform/NowPlayingManager.cpp
M Source/WebCore/platform/NowPlayingManager.h
M Source/WebCore/platform/audio/NowPlayingInfo.h
M Source/WebCore/platform/audio/PlatformMediaSessionInterface.cpp
M Source/WebCore/platform/audio/PlatformMediaSessionInterface.h
M Source/WebCore/platform/audio/cocoa/MediaSessionManagerCocoa.h
M Source/WebCore/platform/audio/cocoa/MediaSessionManagerCocoa.mm
M Source/WebCore/platform/audio/glib/MediaSessionManagerGLib.cpp
M Source/WebCore/testing/Internals.cpp
M Source/WebCore/testing/Internals.h
M Source/WebCore/testing/Internals.idl
M Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp
M Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h
M Source/WebKit/GPUProcess/GPUConnectionToWebProcess.messages.in
M Source/WebKit/GPUProcess/GPUProcess.cpp
M Source/WebKit/GPUProcess/GPUProcess.h
M Source/WebKit/Scripts/webkit/messages.py
M Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in
M Source/WebKit/WebProcess/GPU/media/WebMediaStrategy.cpp
M Source/WebKit/WebProcess/GPU/media/WebMediaStrategy.h
Log Message:
-----------
[Site Isolation] Elect the NowPlaying session in the GPU process
https://bugs.webkit.org/show_bug.cgi?id=321966
rdar://171748880
Reviewed by Jean-Yves Avenard.
There is exactly one system NowPlaying session per app, but the GPU process's
NowPlayingManager holds a single client slot: whichever web process pushes its
NowPlaying info last becomes NowPlaying and receives remote-control commands.
When a page has more than one element eligible to be the NowPlaying session,
WebKit chooses the best candidate based on the session's characteristics: size,
whether or not it is playing, has audio, etc. With site isolation a top-level
page's cross-origin subframes run in separate processes so the selection logic
can't run in the web process or an audible subframe could take over NowPlaying
and its remote commands from a "more eligible" session in the same page but
running in another process.
Each web process already chooses its own best NowPlaying session in
MediaSessionManagerCocoa::updateNowPlayingInfo and sends it to the GPU process.
This
change updates the GPU process so it doesn't just choose the most recent
session pushed
to it, but instead chooses the most eligible session from the per-page winners:
- A page's candidate and its NowPlaying info are reported separately.
SetNowPlayingCandidateState carries the winning session's page and session
identifiers
plus the comparator inputs the election reads (presentationType,
isLargeEnoughForMainContent, isPlaying, and the most-recent user-interaction
time as a
WallTime, since MonotonicTime is not comparable across processes); the GPU
process
updates that page's candidate and re-runs the election.
SetNowPlayingInfoForPage
carries the NowPlayingInfo and page identifier; the GPU process updates that
page's
info and, when the page owns NowPlaying, pushes it straight to
NowPlayingManager
without re-electing. ClearNowPlayingInfoForPage withdraws a page's candidate.
Candidacy
is reported whenever it changes, independent of the info-update throttling,
so resizing
a paused video (which changes its eligibility but not its info) still re-runs
the
election.
- GPUConnectionToWebProcess keeps its process's per-page candidates; on any
change
GPUProcess::recomputeNowPlayingOwner picks the single winner using the same
tiered
order as PlatformMediaSessionManager::bestEligibleSessionForRemoteControls and
HTMLMediaElement::selectBestMediaSession, preferring the current owner when
candidates
are otherwise equal so the choice is stable.
- The candidates are keyed by { process, page } so a process hosting several
pages is
handled correctly.
- The GPU process enables arbitration itself from shared preferences
(remoteMediaSessionManagerEnabled || siteIsolationEnabled); the flag is
process-wide
and sticky so a non-isolated process cannot take the panel from the election.
Without
it, each process self-designates on push, preserving the existing behavior.
For test observability, internals.elementIsActiveNowPlayingSessionInGPUProcess
asks
the GPU process whether a given element's session is the elected system owner,
so
a test can assert the session chosen by the GPU process rather than a value the
content
process set itself.
Cross-process playback interruption is unchanged; the layout tests exercise it
together
with the NowPlaying takeover, and the re-election when a paused candidate is
resized.
Tests: http/tests/site-isolation/now-playing-elected-across-frames.html
http/tests/site-isolation/now-playing-reelects-on-resize.html
*
LayoutTests/http/tests/site-isolation/now-playing-elected-across-frames-expected.txt:
Added.
* LayoutTests/http/tests/site-isolation/now-playing-elected-across-frames.html:
Added.
*
LayoutTests/http/tests/site-isolation/now-playing-reelects-on-resize-expected.txt:
Added.
* LayoutTests/http/tests/site-isolation/now-playing-reelects-on-resize.html:
Added.
* LayoutTests/http/tests/site-isolation/resources/now-playing-frame.html: Added.
* Source/WebCore/html/MediaElementSession.cpp:
(WebCore::isElementLargeEnoughForMainContent):
* Source/WebCore/html/MediaElementSession.h:
* Source/WebCore/platform/MediaStrategy.cpp:
(WebCore::MediaStrategy::isActiveNowPlayingSessionInGPUProcessForTesting):
* Source/WebCore/platform/MediaStrategy.h:
* Source/WebCore/platform/NowPlayingManager.cpp:
(WebCore::NowPlayingManager::clearNowPlayingInfoForPage):
(WebCore::NowPlayingManager::clearNowPlayingInfoPrivate):
(WebCore::NowPlayingManager::setNowPlayingInfo):
(WebCore::NowPlayingManager::updateNowPlayingCandidateState):
(WebCore::NowPlayingManager::setNowPlayingInfoPrivate):
* Source/WebCore/platform/NowPlayingManager.h:
* Source/WebCore/platform/audio/NowPlayingInfo.h:
* Source/WebCore/platform/audio/PlatformMediaSessionInterface.cpp:
(WebCore::PlatformMediaSessionInterface::isLargeEnoughForMainContent const):
(WebCore::PlatformMediaSessionInterface::mostRecentUserInteractionTime const):
* Source/WebCore/platform/audio/PlatformMediaSessionInterface.h:
* Source/WebCore/platform/audio/cocoa/MediaSessionManagerCocoa.h:
* Source/WebCore/platform/audio/cocoa/MediaSessionManagerCocoa.mm:
(WebCore::MediaSessionManagerCocoa::updateNowPlayingInfo):
* Source/WebCore/platform/audio/glib/MediaSessionManagerGLib.cpp:
(WebCore::MediaSessionManagerGLib::updateNowPlayingInfo):
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::elementIsActiveNowPlayingSessionInGPUProcess):
* Source/WebCore/testing/Internals.h:
* Source/WebCore/testing/Internals.idl:
* Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp:
(WebKit::GPUConnectionToWebProcess::clearNowPlayingInfoForPage):
(WebKit::GPUConnectionToWebProcess::setNowPlayingCandidateState):
(WebKit::GPUConnectionToWebProcess::setNowPlayingInfoForPage):
(WebKit::GPUConnectionToWebProcess::becomeNowPlayingOwner):
(WebKit::GPUConnectionToWebProcess::resignNowPlayingOwner):
(WebKit::GPUConnectionToWebProcess::isActiveNowPlayingSessionForTesting):
* Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h:
* Source/WebKit/GPUProcess/GPUConnectionToWebProcess.messages.in:
* Source/WebKit/GPUProcess/GPUProcess.cpp:
(WebKit::GPUProcess::createGPUConnectionToWebProcess):
(WebKit::GPUProcess::updateNowPlayingArbiterActive):
(WebKit::GPUProcess::sharedPreferencesForWebProcessDidChange):
(WebKit::GPUProcess::removeGPUConnectionToWebProcess):
(WebKit::GPUProcess::recomputeNowPlayingOwner):
* Source/WebKit/GPUProcess/GPUProcess.h:
* Source/WebKit/Scripts/webkit/messages.py:
* Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in:
* Source/WebKit/WebProcess/GPU/media/WebMediaStrategy.cpp:
(WebKit::WebMediaStrategy::createNowPlayingManager):
(WebKit::WebMediaStrategy::isActiveNowPlayingSessionInGPUProcessForTesting):
* Source/WebKit/WebProcess/GPU/media/WebMediaStrategy.h:
Canonical link: https://commits.webkit.org/319542@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications