Open Bug 2067534 Opened 20 days ago Updated 10 days ago

MediaController never Activates (no SMTC) for a navigator.mediaSession page that plays audio only via Web Audio API, no HTMLMediaElement

Categories

(Core :: Audio/Video: Playback, defect, P3)

Firefox 154
defect

Tracking

()

ASSIGNED

People

(Reporter: canko, Assigned: canko)

References

Details

Attachments

(2 files)

Steps to reproduce:

  1. Enable MOZ_LOG via about:logging with module MediaControl:5.
  2. Load a page that calls navigator.mediaSession.metadata = new MediaMetadata(...), sets playbackState = "playing", and registers play/pause/etc. action handlers — but plays its audio purely through the Web Audio API (AudioContext + AudioBufferSourceNode/OscillatorNode), with no <audio>/<video> element anywhere in the page.
  3. Observe the log and the Windows SMTC widget.

Expected result: MediaController activates, WindowSMTCProvider opens, and the OS-level SMTC widget shows and responds to input — exactly as it does when audio plays through a real media element.

Actual result: The MediaController stays deactivated indefinitely. Every metadatachange event is dropped with Dropping event 'metadatachange' on a deactivated controller, even though MediaStatusManager, AudioFocusManager, and AudioSessionManager all correctly track metadata, grant audio focus, and select the session as active. Activate / Set controller as main controller / WindowSMTCProvider, Opening Source never appear in the log. No SMTC widget appears; hardware/OS media keys do nothing.

Root cause (from internal MediaControl:5 logging, both cases attached below): Controller activation is gated on MediaStatusManager::UpdateMediaPlaybackState reaching eStarted/ePlayed, which are internal HTMLMediaElement playback-lifecycle events. A page using only the Web Audio API never generates them, so the controller never calls Activate(), regardless of how complete and correct the navigator.mediaSession JS-facing state is. This appears to be a real gap in Firefox's implementation — per web.dev's Media Session documentation, Chrome decoupled its Media Session integration from requiring a media element years ago; Firefox's MediaController does not appear to have made the same change.

Reproduced on: soundcloud.com, which has two internal playback code paths sharing the same navigator.mediaSession registration logic: one calls native HTMLMediaElement.play() on a real (but DOM-detached) <audio> element backed by a MediaSource Extensions blob: URL; the other plays exclusively through the Web Audio API (AudioBufferSourceNode) with no media element involved at all, confirmed via document.querySelectorAll('audio,video').length === 0 including recursively through shadow roots and iframes. Only the first path generates eStarted/ePlayed and lets the controller activate — the same site produces working SMTC controls or none at all purely depending on which internal path handles a given playback session. Independently confirmed on a minimal standalone testcase with no SoundCloud involvement, using only the Web Audio API with no media element (attached or detached) anywhere: https://claude.ai/code/artifact/1345540b-41a5-45f9-b8ac-2f2e4ea669d2.

A page can register a fully-configured navigator.mediaSession (metadata,
declared playback state, action handlers) while producing its audio
purely through the Web Audio API, with no HTMLMediaElement anywhere in
the document. Previously the tab's active media session was only ever
derived from the browsing context that owned a controllable audible
source (i.e. an HTMLMediaElement), so such a page's Media Session was
never exposed, and MediaController::ShouldActivateController() -- which
itself only looked at HTMLMediaElement playback-lifecycle events -- never
activated the controller. As a result, no OS-level media-key integration
(SMTC on Windows, MPRIS on Linux) was ever set up for these pages, even
though the page had done everything the Media Session spec asks of it.

MediaStatusManager::UpdateActiveMediaSessionContext() now falls back to
any browsing context that has a registered Media Session and is audible
through any means, including uncontrollable sources such as the Web Audio
API, when no controllable-audible context qualifies. MediaController also
reacts to a declared-playback-state change (not only playback/audible
changes), so activation is re-checked regardless of the order in which
these signals arrive, and ShouldActivateController() now also activates
when the active session declares itself playing while the tab is audible.

Assignee: nobody → cankomusdogan
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true

The severity field is not set for this bug.
:jimm, could you have a look please?

For more information, please visit BugBot documentation.

Flags: needinfo?(jmathies)
Severity: -- → S3
Flags: needinfo?(jmathies)
Priority: -- → P3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: