Repository navigation
A file is what its bytes are; Firefox's own player keeps the page's headers - #607
Merged
Merged
Conversation
…eaders
A hoster served a Matroska file as video/mp4 from an .mp4 URL. The page's own <video>
played it; FastStream took it for an MP4 by its type, mp4box stopped at the first bytes
("Invalid data found while parsing box of type '£B'"), and the player failed.
- MP4Player looks at the first range's first 8 bytes (ContainerSniff.startsLikeMp4: a
box's size, then four printable characters) and hands a file that cannot be an MP4 to
Firefox's own player (playDirectly), which reads files by their bytes.
- That server sends a request without the page's Referer to a decoy. DirectVideoPlayer set
its header rule once, and rules lived 5 s: the element's first request after that (the
Matroska index at the end, a seek) had no Referer, and the source was reloaded. Its rule
now lives 30 s and is renewed every 10 s while it has the source (SET_HEADERS'
lifetimeMs, capped at 60 s). A request's rule stays 5 s.
mislabelled-file.e2e.mjs fails on main (the mp4box error) and with the hand-over alone
(the request 12 s in had no Referer); it passes with both.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…jection) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Firefox may hold a hidden tab's timers back: with a 30 s rule renewed every 10 s, a renewal more than 20 s late left the element's next request without the page's headers. At 60 s a renewal may come 50 s late. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ct-headers # Conflicts: # tests/unit/typeChecked.test.mjs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong
A hoster served a Matroska file as
video/mp4, from a URL ending in.mp4. The page's own<video>played it: Firefox reads a file by its bytes. FastStream took it for an MP4 by its type, mp4box stopped at the first bytes (Invalid data found while parsing box of type '£B' at position 0), and FastStream's player failed where the page's had played.The same server answers a request without the page's Referer with a 302 to a decoy. Firefox's own player in FastStream (DIRECT) got the page's headers from a background rule that lived 5 s; the element asks for ranges whenever it needs them, so its first request after 5 s (a Matroska file's index at the end, a seek) went out without a Referer, and the client's recovery reloaded the source.
The fix (no site rule)
MP4Playerlooks at the first range's first 8 bytes (ContainerSniff.startsLikeMp4: a box's size, then four printable characters) and hands a file that cannot be an MP4 to Firefox's own player (playDirectly, the existing hand-over), one range in. Every MP4/QuickTime file starts with a box, so none leaves MP4Player.SET_HEADERSgets an optionallifetimeMs, capped at 60 s inRuleEntry): Firefox may hold a hidden tab's timers back, and a renewal up to 50 s late still comes in time. A request's rule stays 5 s. After the player is gone the rule lasts at most 60 s, limited to the extension's own requests to that URL in that tab.Tests
ext-specs/mislabelled-file.e2e.mjs(new): a Matroska film served asvideo/mp4from an.mp4URL, by a server that sends a request without the page's Referer to a decoy, at 400 KB/s. The player plays it in Firefox's own player, plays on after a seek 12 s in, and no request lacks the Referer.ContainerSniff.test.mjs(MP4/QuickTime starts vs. Matroska, WebM, Ogg, FLAC, ID3, WAV, FLV, MPEG-TS),NetRequestRuleManager.test.mjs(lifetime, cap, floor),DirectVideoPlayer.test.mjs(renewal, stop on destroy and on a new source, none without headers). The renewal and lifetime tests fail without the change.glm reviewed both halves. The 30 s → 60 s change came from it. Its other finding (the seek preview's MP4Player handing over) is harmless: the preview has its own event context, stops after one range, and the main player's hand-over replaces it (
resetPlayer).Notes in
docs/notes/player.md("A file is what its bytes are…"), including that the e2e web build is cross-origin isolated (COOP/COEP), so DIRECT there loads only files withCross-Origin-Resource-Policy.🤖 Generated with Claude Code