14 Jul 2026
Planet Mozilla
Mozilla GFX: HDR video in Firefox for Windows tech retrospective
HDR video is coming to Firefox for Windows users (and has been available for some time on macOS). This blog post explains how we developed the feature and gives a retrospective on the technical choices we made.
A primer on video playback for the web:
- Video file demux and decode: A video stream generally consists of parallel image and audio streams, along with captions, HDR scene metadata, and the like. "Container" formats like MP4 or MKV specify how these streams are combined, or multiplexed, into a single byte stream for transmission. On receipt, Firefox needs to divide that byte stream back into the individual media streams; this is de-multiplexing or "demuxing". Then Firefox must uncompress the data to get images, audio samples, and so on. Firefox's media team provides the demuxers, and pulls in appropriate codecs to decode them. We prefer using hardware video decoders if they work reasonably well. Video decompression usually produces roughly a YUV 4:2:0 image in NV12 for SDR or P010 for HDR. (If you visit about:support in Firefox, and search for Codec Support Information (or one of the codec names like AV1), you can see a whole feature matrix of support details for which codecs are hardware and software on your system.)
- Gecko displaylist building: Given a demultiplexed, uncompressed frame of video, Gecko displaylist building incorporates it into a video element in the displaylist being sent to WebRender. If the frame was decoded in hardware, it is generally represented by a texture in GPU memory. Or, if it was decoded in software, then it is represented by a memory mapping holding some raw pixel data in system memory shared with Firefox's media decoder process.
- WebRender: Given the video element in the displaylist, WebRender decides whether to promote it to a desktop compositor overlay, or whether it must instead be rendered using a pathway more like an ordinary HTML element. A compositor overlay is faster and uses less power; on Windows this uses DWM with the DirectComposition API, which manages a graph of visuals. But if complex CSS is involved (rounded corners, blur filters, or similar features), Firefox must use WebRender's ordinary rendering pathway. Currently the latter is not HDR capable, so Firefox favors the desktop compositor overlay for animated elements such as video and canvas.
As we began designing Firefox's HDR support, we had to lay out some assumptions and found many complications:
- Initially, we had hoped that on a modern system, BT2100 HDR videos could be displayed on Windows by simply sending them to DirectComposition.
- In theory, the Desktop Window Manager (DWM) honors the DXGISwapChain3::SetColorSpace1 method which should let us request either DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020 or DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_LEFT_P2020. The former refers to SMPTE 2084, more commonly called PQ, the Perceptual Quantizer function and the latter is ARIB-STD-B67 also known as HLG, the Hybrid Log Gamma function, most commonly used on HDR TV broadcasts.
- Unfortunately, this was a dead end. In testing with a mocked up compositor test app, calling SetColorSpace1 with this value seems to be ignored on P010 (at least in testing on AMD), so it incorrectly displays BT2100 PQ video as if it were BT709, which makes the video dull and muddy, since BT709 is a narrower gamut than BT2020, and the BT1886 transfer function used by BT709 is very different from PQ defined by BT2100. SetColorSpace1 may work on other vendors with P010, so it may be a valid optimization, but we were looking for a universal solution.
- For the future, Windows 11 23H2 has added a new interface called IDCompositionTexture which may serve our purposes better; from what we have been told, it is universally supported for all formats and color spaces. We haven't used it for video so far, but it's an interesting future direction.
- As noted above, HDR videos must use a desktop compositor overlay. HDR video uses the BT2100 PQ colorspace with an RGB10A2 format, while WebRender can only work with images in the sRGB colorspace (appropriate for standard-dynamic-range BT709 video).
- Until HDR came along, Gecko and WebRender only used desktop compositor overlays as a power/performance optimization. With HDR, overlays become a necessity as the pixel format and color space differ from classic sRGB.
- Fortunately, HDR videos tend to be shown without particularly fancy CSS rendering such as clip masks and rounded corners, which would require WebRender to perform further copies. Technically, DirectComposition does support all of those features, but Firefox doesn't use that functionality much.
- In the future, we expect to upgrade WebRender for HDR rendering, allowing us to deal with complex cases like clip masks or blur filters on video elements.
- We considered whether we could use VideoProcessorBlt, or whether we should write our own shader instead.
- In favor of VideoProcessorBlt:
- It uses less power on GPUs that have a video processor unit.
- We discovered in testing (using CheckVideoProcessorFormatConversion) that while many modern GPUs support one of the needed conversions (P010 PQ -> RGB10 PQ), few support the ones we need for HLG videos (P010 HLG -> RGB10 PQ).
- The 'video-dynamic-range' query used on the web is not fine-grained enough to be able to say "the web browser can display PQ video but not HLG video", so if we went with VideoProcessorBlt as a required feature, only about 20% of HDR desktop users would be able to use the feature.
- In the future, we could explore using VideoProcessorBlit to save power on hardware that supports the conversions we need. But other web browsers are not using this functionality, so there may be more issues we haven't found yet.
- In favor of writing our own shader with all of the features:
- This would work consistently on all vendors - nothing special here.
- This would look the same on all vendors, regardless of hardware capabilities. This is generally the aim of web standards.
- This would support anything we want it to. HDR tonemapping can be implemented. Video orientation can be implemented (for videos recorded on phones which may be rotated 90, 180 or 270 degrees). We can support any kind of YUV->RGB conversion with a color matrix (even weird legacy formats like GBR 4:2:0). We can support conversion between color primaries (e.g. BT2020->BT709). We can convert to linear color (for scRGB using RGBA16F) or any EOTF we want (notably BT2100 PQ with RGB10A2, for our use-case).
- In the end we went with the shader after a significant period of time experimenting with VideoProcessorBlt in our Nightly releases.
- In favor of VideoProcessorBlt:
- There is a very large amount of graphics code in Gecko and WebRender that needs to be upgraded for HDR.
- We decided that the most important code paths to upgrade first are the ones for regular video playback and DRM-protected video playback, and later canvas video import (Canvas2D, WebGL, WebGPU) which will require upgrading canvas for HDR first - another big project.
- We had to upgrade several dozen structs to carry the transfer function for video data, as previously all code assumed video used BT1886 EOTF.
- We hope we can avoid tone mapping HDR content when viewed on HDR displays.
- It's reasonable to expect that most displays going forward will be HDR displays (partly because of marketing momentum, partly because displays are made by a very finite set of manufacturers who are all making HDR display panels), and eventually tone mapping may become unnecessary on the web.
- For the short-term we will have to apply a tone mapping effect when HDR content is viewed on SDR displays, likely using 'Reinhard tonemapping' which refers to the widely available paper Photographic Tone Reproduction for Digital Images by Erik Reinhard et al, and configuring it for a fixed brightness ratio of 400 cd/m^2 -> 100 cd/m^2 when used on SDR displays, and see if that fits all HDR content on the web well enough for a good user experience - and if it does not, we will iterate based on feedback from users on Firefox Nightly.
- We are hoping that we will never have to apply tonemapping for HDR content on HDR displays, there are multiple factors in this decision:
- Varying the brightness limit would make it a significant fingerprinting vector if not handled very carefully if the script can inspect pixels or parameters related to that. There are ways to mitigate this but they are all awkward restrictions to impose, and queries would have to get a different answer than what the rendering is using.
- Phones and laptops with light sensors may vary the reference brightness in real time, and this changes the maximum displayable ratio (aka HDR headroom) every refresh, which is also a major battery drain if we keep redrawing all of the time.
- Documents composed of multiple images (a gallery or some form of art composition) would apply different tonemapping to each image if the brightest pixel in each image is different brightness). We'd have to do something about that to make it controllable via CSS.
- In general the detailed parts of an image are within a certain brightness band - see Debunking HDR for a detailed lecture on film grading and why you would not have significant difference in brightness between scene elements.
- User feedback so far has indicated that not applying tonemapping has given them a better viewing experience on some videos.
- WebRTC is implemented using a library, common to all web browsers, which has limited support for HDR.
- While we didn't prioritize this for an initial feature launch, we are looking at how to implement HDR support properly in libwebrtc. This is in the early assessment phase but we know this is wanted for a couple of use-cases, like video calls for meetings, or game streaming with friends watching.
In general, one of the biggest challenges in working on graphics code in a web browser is a lack of documentation for how to best use features like video playback and desktop compositing in the context of a web browser (e.g. multiple processes, sandboxing, shared memory, sharing external textures, etc). This parallels the rarity of graphics engineers with such experience. Building new features in this space requires a lot of research (and a lot of trial and error). The solution you end up with may not look at all like the one you initially imagined.
On behalf of the graphics team at Mozilla, I want to thank the people who use Firefox Nightly regularly and file bug reports when things aren't working the way they want. Comments on Experimental High Dynamic Range video playback on Windows in Firefox Nightly 148, Mozilla Connect, and Bugzilla bug reports have guided us to focus on the use-cases that matter to people using Firefox. When we succeed, it's a great feeling.
We're working on extending HDR support to photos, apps/games and general web content.
14 Jul 2026 4:15am GMT
13 Jul 2026
Planet Mozilla
The Rust Programming Language Blog: crates.io: development update
Another six months have passed since our last development update, and the crates.io team has been busy. Here's a summary of the most notable changes and improvements made to crates.io since then.
Source Code Viewer
Crate pages now have a "Code" tab that lets you browse the contents of published crate versions directly on crates.io. This shows you the exact files that cargo downloads when you add a crate as a dependency, which might differ from the linked repository. This makes it much easier to audit your dependencies, including files that never appear in the repository, like the normalized Cargo.toml files that cargo generates.

The viewer comes with a file tree sidebar with search functionality, syntax highlighting, and GitHub-style line selection, where clicking or dragging line numbers produces shareable #L10-L20 URLs.
Under the hood, the server now builds a zip file for every published version. Since the .crate files that cargo consumes are gzipped tarballs without random access support, a background job re-packs each of them into a seekable zip archive plus a JSON manifest describing the contained files. Both are served from our static CDN. The frontend then fetches only the manifest and loads each file on demand with an HTTP range request. Because of this architecture, browsing crate sources essentially adds no load on the crates.io API servers. Existing crate versions have been backfilled, so this works for old releases too.
The rendering library behind the code viewer is a diff renderer at heart, and that's no accident: a version-to-version diff viewer built on the same infrastructure is currently in the works. This will allow you to review exactly what changed between two published versions, right on crates.io. Stay tuned!
Untangling crates.io Accounts from GitHub
At the end of May, the crates.io team accepted RFC #3946. Crates.io accounts always have been tightly coupled to GitHub: signing in means "Log in with GitHub", and your crates.io identity is your GitHub username. The RFC changes that. It introduces usernames that are native to crates.io and independent of linked GitHub accounts, as a prerequisite for eventually supporting login via other identity providers.
The implementation of crates.io usernames has started, but there is still a lot left to do, most visibly the ability to change your crates.io username. After that is complete, there will be future RFCs and implementation for signing in with identity providers other than GitHub. Since all of this touches authentication and account security, we are deliberately taking it slow and rolling these changes out in small, carefully reviewed steps.
Advisories and Suggestions
In our January update we introduced the "Security" tab, which shows security advisories from the RustSec database. We have since taken this integration one step further: crates that RustSec has flagged as unmaintained now show a warning banner directly on their crate pages, linking to the corresponding advisory for details and possible alternatives. Thanks to Dirkjan Ochtman for implementing this feature!

Related to this, some popular crates have been largely absorbed into the Rust standard library over the years, like lazy_static, which has been superseded by std::sync::LazyLock since Rust 1.80. Crate pages of such crates now show a friendly "You might not need this dependency" banner describing the standard library replacement, and superseded crates in dependency lists get a small light bulb icon with a similar hint.

The dataset behind this feature lives in the new rust-lang/std-replacement-data repository, together with a documented inclusion policy: standard library replacements only, every entry must cite the stable std, core, or alloc API and Rust version, and crate maintainers get a notice-and-comment window before an entry is added. New entries can be proposed upstream and can benefit other tools too.
Ferris
The most delightful change of this cycle: the Ferris on our error pages now follows your mouse cursor with its eyes:

Getting a 404 error on crates.io is now slightly less sad.
Svelte Frontend Migration Completed
In our January update, we announced that we were experimenting with porting the crates.io frontend from Ember.js to Svelte. This experiment has concluded successfully: the new frontend reached feature parity, went through a public testing phase in April, became the default at the beginning of May, and the Ember.js app has been removed from our repository.
We designed this change to be invisible for our users, since the new frontend is a 1:1 port of the previous design and functionality. For the team and our contributors, however, it is a big deal: the frontend is now built on a more modern framework, which should make it easier for new contributors to get started. It also allows us to iterate faster, as the source code viewer above demonstrates.
We want to thank the Ember.js team for a framework that served crates.io well for many years, and the Svelte team for making the transition so enjoyable.
Miscellaneous
These were some of the more visible changes to crates.io over the past six months, but a lot has happened "under the hood" as well:
-
Search performance: Relevance-sorted search queries previously ranked every crate matching the query, which could take 1-2 seconds for short or common search terms. Ranking is now bounded to the 1,000 matching crates with the highest recent download counts.
-
Reverse dependencies performance: The reverse dependencies endpoint no longer recomputes the full dependent set on every request. It is now served from a precomputed table kept in sync by database triggers, turning an expensive join into a bounded index scan and greatly reducing the chance of getting a timeout error.
-
New ARCHITECTURE.md: If you've ever wondered how crates.io actually works, our
ARCHITECTURE.mddocument got a complete rewrite. It is now organized around the high-level systems that make up crates.io and how they fit together, and includes walkthroughs of what happens when you runcargo publish, why a typical crate download never touches our API servers, and how download counts are derived from CDN access logs. -
Definition lists: READMEs now render Markdown definition lists, a widely used Markdown extension. Our markdown renderer comrak already supported them, the extension just wasn't enabled yet. Thanks to @mistaste for this contribution!
-
CDN cache tags: Files uploaded to our static CDN now carry cache-tag metadata, allowing us to invalidate all cached files of a crate or a specific release in a single operation, instead of issuing one invalidation per file URL.
-
Caching improvements: We removed a global
Vary: Cookieresponse header that was preventing our CDNs from caching public API responses and frontend assets effectively. Per-user responses now useCache-Control: no-storeinstead, resulting in better cache hit rates at the CDN edge. -
Accessibility: We have made crates.io friendlier to screen readers: decorative icons are now hidden from the accessibility tree, heading hierarchies have been fixed, and lists are marked up as proper lists. ARIA snapshot tests now ensure that regressions can't slip in unnoticed. We plan to continue to improve crates.io accessibility over the coming months.
-
Git index performance: The background worker's local clone of the git index is now a bare and shallow repository, eliminating roughly 250,000 checked-out files and the full commit history from its disk, improving its performance as we see increased rates of crate publication. The periodic index squashing now goes through the GitHub API instead of generating large git packs locally, which had previously caused out-of-memory failures on the production worker.
Feedback
We hope you enjoyed this update on the development of crates.io. If you have any feedback or questions, please let us know on Zulip or GitHub. We are always happy to hear from you and are looking forward to your feedback!
13 Jul 2026 12:00am GMT
12 Jul 2026
Planet Mozilla
Firefox Application Security Team: Firefox Security & Privacy Newsletter 2026 Q2
Welcome to the Q2 2026 edition of the Firefox Security & Privacy Newsletter.
Security and privacy are core principles of Mozilla's Manifesto and remain at the heart of Firefox's development. In this edition, we highlight some of the key security and privacy initiatives from Q2 2026, grouped into the following areas:
- Firefox Product Security & Privacy, new security and privacy features, protections, and integrations in Firefox
- Core Security, platform security improvements, hardening efforts, and foundational enhancements
- Community Engagement, highlights from our security research community and bug bounty program
- Web Security & Standards, progress on web technologies and standards that help websites better protect users from online threats
Preface
Note: Some of the bugs linked below might not be accessible to the general public and restricted to specific work groups. We de-restrict fixed security bugs after a grace-period, until the majority of our user population have received Firefox updates. If a link does not work for you, please accept this as a precaution for the safety of all Firefox users.
Firefox Product Security & Privacy
Private Access Control Tokens (PACT): PACT is a cross-industry initiative designed to tackle one of the web's most urgent challenges: enabling websites to reliably distinguish legitimate users and authorized automated agents from abusive traffic without compromising user privacy. To introduce the initiative, we published a technical deep dive on Mozilla Hacks alongside a companion Mozilla blog post that explains the vision, motivation, and privacy-preserving design behind PACT.
Qualified Website Authentication Certificates (QWACs): Firefox is prepared to meet upcoming eIDAS requirements under the EU Digital Identity Framework. Qualified Website Authentication Certificates (QWACs), as required by the framework, are supported in Firefox 153 (Bug 2043399) onwards.
Hardening Firefox with Claude Mythos: In a blogpost we shared how our AI-assisted security testing pipeline, powered by Claude Mythos, uncovered and helped remediate hundreds of previously hidden vulnerabilities in Firefox, significantly strengthening the browser's security while demonstrating the transformative potential of AI to enhance defensive cybersecurity.
Visual Indications for Geolocation Access: In light of some web pages using geolocation for activities that are not related to their maps functionality, Firefox now displays a real-time visual indicator whenever a web page is accessing the user's geolocation. Starting with Firefox 153, the address bar now provides a real-time visual indicator the moment a website begins accessing a user's location, providing users with immediate awareness and greater transparency into when and how their geolocation data is being used.
Improving Website Compatibility in Private Browsing: Starting with Firefox 152, Private Browsing Mode now offers users the option to temporarily lower tracking protections for the current tab when stricter tracker blocking could be causing a website to malfunction. Previously, this may have resulted in users turning off privacy protections completely to continue using visited web page. With our new feature, users can quickly restore site functionality of the current tab, preserving users' overall privacy settings.
Instant fresh start through new Fire Button: Firefox 151 introduced the new Fire Button for Private Browsing, giving users an instant fresh start with a single click. Instead of closing and reopening a Private Window, users can immediately clear all browsing data and continue browsing in a clean session, making Private Browsing faster, more convenient, and just as private.
Advanced Anti-Fingerprinting Protections: Firefox 151 expands our default anti-fingerprinting defenses by ensuring the Available Screen Resolution, Touch Points, and Canvas APIs will provide uniform results for all of our users while also maintaining performance and compatibility. On macOS, for example, these enhancements are expected to reduce the share of users identified as unique by more than 20%, making it significantly harder for websites to uniquely identify and track users using obscure fingerprinting.
Local Network Access Protections: Firefox now requires user permission before websites can access apps and services on a user's local network or device, helping prevent unauthorized access and sneaky tracking attempts. The LNA feature is rolling out gradually, starting with Firefox Desktop 151 through 153. Android support will follow in upcoming releases.
Core Security
Firefox CA Root Program: We published Root Store Policy v3.1, introducing stricter transparency, documentation, and audit requirements for public CAs to strengthen trust in the Web PKI.
WebAuthn Related Origin Requests: This feature allows seamless passkey sign-ins across related domains e.g., the same provider using multiple top-level domains. In contrast to other browsers, Firefox UI provides transparency and choice so users are aware and can control when websites request for passkeys from other, related sites.
Community Engagement
Hosting Events: We organized and hosted multiple web tech meet-ups in the Mozilla Berlin office, bringing together the developer community to explore the latest advances in web technology, privacy, and security. If you're in the area, we'd love to have you join us at a future event.
Community Shares: Firefox tracking protection was presented at the SnooSec conference held in the Reddit NYC office. We also had a presentation about existing and upcoming protections against web tracking at the Chemnitz Linux Days conference, and a talk about the latest browser-based XSS protections at OWASP AppSec '26 in Vienna.
Web Security & Standards
Web Application Integrity, Consistency and Transparency (WAICT): We are working on WAICT, a new proposal to bring stronger integrity and transparency guarantees to web applications, helping make the web a more trustworthy platform for security-sensitive applications such as end-to-end encrypted messaging. We shared our technical vision in a Mozilla Hacks blog post, including a prototype implementation in Firefox Nightly that works with our WAICT Demo and a draft specification.
Sanitizer API: We are advancing the Sanitizer API to make robust protection against cross-site scripting (XSS) vulnerabilities more accessible. By exploring an implicit sanitizer policy that integrates with Trusted Types, we aim to prevent an entire class of XSS attacks with no application code changes, making secure-by-default web applications easier to build and deploy.
Looking Ahead
Firefox users will receive these security and privacy improvements automatically. If you're not already a user, we recommend you give it a try. Firefox helps you shape a more personal internet that puts you back in control - all while supporting the non-profit Mozilla in its mission to keep the web open, safe, and accessible for everyone.
Thank you to everyone who contributes to making Firefox and the web more secure and privacy-focused. You can have an impact too, just by reporting bugs, conducting research, contributing code, or providing feedback.
We look forward to sharing more updates in the Q3 2026 edition.
- The Firefox Security & Privacy Teams
12 Jul 2026 11:00pm GMT