Skip to content

MEDIA_ERR_ABORTED after restore page with media from bfcache - #1721

Open
pgorszkowski-igalia wants to merge 1 commit into
wpe-2.38from
pgorszkowski/2.38/MEDIA_ERR_ABORTED-after-restore-page-with-media-from-bfcache
Open

MEDIA_ERR_ABORTED after restore page with media from bfcache#1721
pgorszkowski-igalia wants to merge 1 commit into
wpe-2.38from
pgorszkowski/2.38/MEDIA_ERR_ABORTED-after-restore-page-with-media-from-bfcache

Conversation

@pgorszkowski-igalia

@pgorszkowski-igalia pgorszkowski-igalia commented Aug 24, 2026

Copy link
Copy Markdown

https://bugs.webkit.org/show_bug.cgi?id=319665

Reviewed by Alicia Boya Garcia and Nikolas Zimmermann.

This bundles three related fixes uncovered while restoring pages containing a media element (e.g.: "video") from the back/forward cache:

  1. HTMLMediaElement::suspend() destroyed the media player on entering the cache (via stopWithoutDestroyingMediaPlayer() -> userCancelledLoad()), so a restored page reported video.error.code == MEDIA_ERR_ABORTED. userCancelledLoad() now takes a destroyMediaPlayer flag, false for the BackForwardCache suspension path, so it early-returns instead of tearing the player down.

  2. A

  3. A

Also fixes a related macOS-only assert crash (ASSERTION FAILED: m_mediaSessions.contains(identifier) in MediaUsageManagerCocoa:: updateMediaUsage): the UI process unconditionally clears its usage-tracking map on every navigation commit, including a back/forward cache restore, but MediaElementSession kept believing it had already added its session across the whole suspend/resume cycle. mediaUsageManagerSessionWillBeSuspended() resets that flag on suspend so the next update re-adds the session first.

A LayoutTest for the playing-before-caching scenario (fix #2): it plays a video, waits for the playing event, navigates away and back via history.back(), and asserts the video is still not paused and currentTime has advanced after restore.

Added a LayoutTest based on media/restore-from-page-cache.html for a video that was paused before entering the cache, as a real pixel/screenshot comparison to catch the blank-frame regression from fix #3.

Tests: media/restore-from-page-cache-paused.html
media/restore-from-page-cache-playing.html

  • LayoutTests/media/restore-from-page-cache-paused-expected.png: Added.
  • LayoutTests/media/restore-from-page-cache-paused-expected.txt: Added.
  • LayoutTests/media/restore-from-page-cache-paused.html: Added.
  • LayoutTests/media/restore-from-page-cache-playing-expected.txt: Added.
  • LayoutTests/media/restore-from-page-cache-playing.html: Added.
  • LayoutTests/platform/ios/TestExpectations:
  • Source/WebCore/html/HTMLMediaElement.cpp: (WebCore::HTMLMediaElement::userCancelledLoad):
    (WebCore::HTMLMediaElement::stopWithoutDestroyingMediaPlayer): (WebCore::HTMLMediaElement::suspend):
    (WebCore::HTMLMediaElement::mayResumePlayback):
  • Source/WebCore/html/HTMLMediaElement.h:
  • Source/WebCore/html/MediaElementSession.cpp: (WebCore::MediaElementSession::mediaUsageManagerSessionWillBeSuspended):
  • Source/WebCore/html/MediaElementSession.h:
  • Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: (WebCore::MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer): (WebCore::MediaPlayerPrivateGStreamer::pushTextureToCompositor): (WebCore::MediaPlayerPrivateGStreamer::triggerRepaint):
  • Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h:
  • Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedPlatformLayerBufferProxy.cpp: (WebCore::CoordinatedPlatformLayerBufferProxy::CoordinatedPlatformLayerBufferProxy): (WebCore::CoordinatedPlatformLayerBufferProxy::create): (WebCore::CoordinatedPlatformLayerBufferProxy::setTargetLayer):
  • Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedPlatformLayerBufferProxy.h:

Canonical link: https://commits.webkit.org/319472@main
3d22762

Build-Tests Layout-Tests
✅ 🛠 wpe-238-amd64-build ✅ 🧪 wpe-238-amd64-layout
✅ 🛠 wpe-238-arm32-build ✅ 🧪 wpe-238-arm32-layout

https://bugs.webkit.org/show_bug.cgi?id=319665

Reviewed by Alicia Boya Garcia and Nikolas Zimmermann.

This bundles three related fixes uncovered while restoring pages containing
a media element (e.g.: "video") from the back/forward cache:

1. HTMLMediaElement::suspend() destroyed the media player on entering the
   cache (via stopWithoutDestroyingMediaPlayer() -> userCancelledLoad()),
   so a restored page reported video.error.code == MEDIA_ERR_ABORTED.
   userCancelledLoad() now takes a destroyMediaPlayer flag, false for the
   BackForwardCache suspension path, so it early-returns instead of tearing
   the player down.

2. A <video> that was playing before being cached did not resume playing
   after restore. HTMLMediaElement::resume() schedules an updatePlayState()
   task while the media session is still interrupted. mayResumePlayback()
   now also retries updatePlayState() when the element isn't paused.

3. A <video> that was paused before being cached showed a blank/white
   frame instead of its last decoded frame after restore. Restoring a page
   rebuilds the render tree, so CoordinatedPlatformLayerBufferProxy gets
   attached to a brand new CoordinatedPlatformLayer with no buffer of its
   own, and a paused GStreamer pipeline has no new sample to push. The
   proxy now invokes a layer-attached callback whenever a new non-null
   layer is attached, which MediaPlayerPrivateGStreamer uses to re-deliver
   its current sample so the new layer isn't left blank.

Also fixes a related macOS-only assert crash (ASSERTION FAILED:
m_mediaSessions.contains(identifier) in MediaUsageManagerCocoa::
updateMediaUsage): the UI process unconditionally clears its usage-tracking
map on every navigation commit, including a back/forward cache restore, but
MediaElementSession kept believing it had already added its session across
the whole suspend/resume cycle. mediaUsageManagerSessionWillBeSuspended()
resets that flag on suspend so the next update re-adds the session first.

A LayoutTest for the playing-before-caching scenario (fix #2):
it plays a video, waits for the playing event, navigates away and
back via history.back(), and asserts the video is still not paused and
currentTime has advanced after restore.

Added a LayoutTest based on media/restore-from-page-cache.html for a video
that was paused before entering the cache, as a real pixel/screenshot
comparison to catch the blank-frame regression from fix #3.

Tests: media/restore-from-page-cache-paused.html
       media/restore-from-page-cache-playing.html
* LayoutTests/media/restore-from-page-cache-paused-expected.png: Added.
* LayoutTests/media/restore-from-page-cache-paused-expected.txt: Added.
* LayoutTests/media/restore-from-page-cache-paused.html: Added.
* LayoutTests/media/restore-from-page-cache-playing-expected.txt: Added.
* LayoutTests/media/restore-from-page-cache-playing.html: Added.
* LayoutTests/platform/ios/TestExpectations:
* Source/WebCore/html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::userCancelledLoad):
(WebCore::HTMLMediaElement::stopWithoutDestroyingMediaPlayer):
(WebCore::HTMLMediaElement::suspend):
(WebCore::HTMLMediaElement::mayResumePlayback):
* Source/WebCore/html/HTMLMediaElement.h:
* Source/WebCore/html/MediaElementSession.cpp:
(WebCore::MediaElementSession::mediaUsageManagerSessionWillBeSuspended):
* Source/WebCore/html/MediaElementSession.h:
* Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
(WebCore::MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer):
(WebCore::MediaPlayerPrivateGStreamer::pushTextureToCompositor):
(WebCore::MediaPlayerPrivateGStreamer::triggerRepaint):
* Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h:
* Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedPlatformLayerBufferProxy.cpp:
(WebCore::CoordinatedPlatformLayerBufferProxy::CoordinatedPlatformLayerBufferProxy):
(WebCore::CoordinatedPlatformLayerBufferProxy::create):
(WebCore::CoordinatedPlatformLayerBufferProxy::setTargetLayer):
* Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedPlatformLayerBufferProxy.h:

Canonical link: https://commits.webkit.org/319472@main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

1 participant