- Mar 29, 2018
- 7,577
It's been over two years since our initial response to Google's Manifest V3 proposal. Manifest V3 is the latest set of changes to the Chrome browser’s rules for browser extensions. Each extensions manifest version update introduces backwards-incompatible changes to ostensibly move the platform forward. In 2018, Manifest V3 was framed as a proposal, with Google repeatedly claiming to be listening to feedback. Let's check in to see where we stand as 2021 wraps up. Since announcing Manifest V3 in 2018, Google has launched Manifest V3 in Chrome, started accepting Manifest V3 extensions in the Chrome Web Store, co-announced joining the W3C WebExtensions Community Group (formed in collaboration with Apple, Microsoft and Mozilla), and, most recently, laid out a timeline for Manifest V2 deprecation. New Manifest V2 extensions will no longer be accepted as of January 2022, and Manifest V2 will no longer function as of January 2023.
According to Google, Manifest V3 will improve privacy, security, and performance. We fundamentally disagree. The changes in Manifest V3 won’t stop malicious extensions, but will hurt innovation, reduce extension capabilities, and harm real world performance. Google is right to ban remotely hosted code (with some exceptions for things like user scripts), but this is a policy change that didn’t need to be bundled with the rest of Manifest V3.
Community response to Manifest V3, whether in the Chromium extensions Google group or the W3C WebExtensions Community Group, has been largely negative. Developers are concerned about Manifest V3 breaking their extensions, confused by the poor documentation, and frustrated by the uncertainty around missing functionality coupled with the Manifest V2 end-of-life deadline. Google has been selectively responsive, filling in some egregious gaps in functionality and increasing their arbitrary limits on declarative blocking rules. However, there are no signs of Google altering course on the most painful parts of Manifest V3. Something similar happened when Chrome announced adding a “puzzle piece” icon to the Chrome toolbar. All extension icons were to be hidden inside the puzzle piece menu (“unpinned”) by default. Despite universally negative feedback, Google went ahead with hiding extensions by default. The Chrome puzzle piece experience continues to confuse users to this day.
The World Wide Web Consortium’s (W3C) WebExtensions Community Group is a welcome development, but it won't address the power imbalance created by Chrome’s overwhelming market share: over two-thirds of all users globally use Chrome as their browser. This supermajority of web users is not likely to migrate away because of a technical squabble about extension APIs. No matter what Google decides to do, extension developers will have to work around it—or lose most of their users. And since developers are unlikely to want to maintain separate codebases for different browsers, other browsers will be heavily incentivized to adopt whatever set of extension APIs that Google ends up implementing.
Instead of working in true collaboration on the next iteration of browser extensions, Google expects Manifest V3 to be treated as a foregone conclusion. Participation in the WebExtensions group gives Google the veneer of collaboration even as it continues to do what it was going to do anyway. In short, Google enters the room as an 800-pound gorilla unwilling to listen or meaningfully work with the community.
Forcing all extensions to be rewritten for Google’s requirements without corresponding benefits to users is a fundamentally user-hostile move by Google. Manifest V3 violates the "user-centered", "compatibility", "performance" and "maintainability" design principles of the WebExtensions group charter. While Google's response to community feedback has been tweaks and fixes around the margins, we have been paying attention to what developers are saying. The shortcomings of Manifest V3 have come into focus.
Requiring service workers for extensions is harmful
Most browser extensions are built around a background page, a place where all sorts of work happens out of sight as the user browses. With today’s Manifest V2, extensions in Chrome have the choice to opt into using an ephemeral “event”-based background page, or to use a persistent background page. Ephemeral pages get shut down and restarted repeatedly, whenever Chrome decides to do so. Persistent pages continue running as long as the browser is open. In addition to extension APIs, both kinds of extension background pages have access to the standard set of website APIs.
Manifest V3 removes the choice, instead requiring all extensions to be based on “service workers.” Service workers are ephemeral, event-based, and do not have access to the standard set of website APIs. Along with removing the “blocking webRequest” mechanism, which we talk about below, rebasing all extensions on service workers is one of the most damaging changes in Manifest V3.
Service workers are JavaScript scripts that run in the background, independent of the website that launched them. Service workers are meant to enable websites to perform previously hard or impossible tasks that optimize website performance or provide offline functionality. For example, the first time you visit twitter.com, the website installs a service worker in your browser. The service worker will stay installed, and may continue to perform tasks, even if you lose network connectivity or navigate away from twitter.com. Service workers give websites superpowers, giving web apps functionality that is otherwise difficult or impossible. But service workers don’t have the same freedom to execute code that websites do, and there are limits to how long service workers live. Each service worker listens for messages from its website, performs its tasks, and shuts down shortly after. This makes sense, as the website is the main actor that calls upon its service worker for help. But this model doesn’t translate well to browser extensions.
Service workers were designed to work with websites, and they are a standardized part of the Web Platform. But there is no equivalent service worker standard for WebExtensions. Since extensions enhance the browser, applying the same execution limits from website service workers makes no sense, and yet this is exactly what Google has done.
Websites and their service workers are developed by the same teams, and are meant to work in tandem. But browsers and browser extensions are built by different teams with different goals. Extensions are supposed to add new functionality that browser developers didn’t think of or intentionally left out. Sometimes, extensions do things that explicitly act against the intentions of the browser developers, such as when tracker blockers restrict the information flowing out of Chrome. Chrome continues to be the only major browser without meaningful built-in tracking protection. Web extensions need more freedom to operate on their own, which means first-class access to browser APIs and persistent memory.
Take a look at the long list of known use cases harmed by requiring service workers. Seamlessly playing audio, parsing HTML, requesting geolocation, communicating via WebRTC data channels, and the ability to start a separate service worker are all broken under the new paradigm. Under Manifest V2, extensions are treated like first-class applications with their own persistent execution environment. But under V3, they are treated like accessories, given limited privileges and only allowed to execute reactively.
As per feedback from Mozilla engineers, one legitimate benefit of service workers may be getting extensions to gracefully handle early termination on Android. But there are ways of achieving this goal that don’t involve this degree of harm. And if one of Google's aims for Manifest V3 is to help bring extensions to Chrome on Android, Google failed to communicate this information. How can browsers and extensions developers collaborate on moving extensions forward when it appears that Google is unwilling to share all of the reasons behind Manifest V3?
declarativeNetRequest alone is inadequate
Besides proposing to move extensions to an ill-fitting service worker foundation, Google’s Manifest V3 is changing the way that content-blocking extensions can function. Extensions based on Manifest V2 use webRequest, a flexible API that lets extensions intercept and block or otherwise modify HTTP requests and responses. Manifest V3 drops the blocking and modification capabilities of webRequest in favor of the new declarativeNetRequest API. The interception-only or “observational” webRequest API—which allows extensions to monitor, though not modify, requests—will supposedly remain in Manifest V3, although the API is broken in Manifest V3 at this time, with the relevant bug report open for over two years.
As the name suggests, the new declarativeNetRequest API is declarative. Today, extensions can intercept every request that a web page makes, and decide what to do with each one on the fly. But a declarative API requires developers to define what their extension will do with specific requests ahead of time, choosing from a limited set of rules implemented by the browser. Gone is the ability to run sophisticated functions that decide what to do with each individual request. If your extension needs to process requests in a way that isn’t covered by the existing rules, you just can’t do it.
From this follows the main problem with requiring a declarative API for blocking. Advertising technology evolves rapidly, and privacy extension developers need to be able to change their approaches to it over time. To make matters worse, extension developers can't depend on Google browser engineers to react in any timely manner or at all. Google abandoned extension API development for years before Manifest V3. For example, while extensions have had the ability to “uncloak” CNAME domains in Firefox for over three years now, Chrome still lacks support for CNAME uncloaking. And while this support may come at some point in the future as part of declarativeNetRequest, many years behind Firefox, what about uncloaking CNAMEs elsewhere, such as in observational webRequest?
As we wrote in 2019, “For developers of ad- and tracker-blocking extensions, flexible APIs aren’t just nice to have, they are a requirement. When particular privacy protections gain popularity, ads and trackers evolve to evade them. As a result, the blocking extensions need to evolve too, or risk becoming irrelevant. [...] If Google decides that privacy extensions can only work in one specific way, it will be permanently tipping the scales in favor of ads and trackers.” We have many questions about how the declarative API will interact with other Google projects. Will Google’s Privacy Sandbox technologies be exposed to declarativeNetRequest? If declarativeNetRequest works exclusively on the basis of URL pattern matching, how will extensions block subresources that lack meaningful URLs, facilitated by another Google effort called WebBundles? As more tracking moves to the server, will Manifest V3 extensions be able to keep up? Is Manifest V3 a step down a path where the Google parts of the Web become unblockable by extensions?
We reject declarativeNetRequest as a replacement for blocking webRequest. Instead, Google should let developers choose to use either API. Making both APIs available can still fulfill Google’s stated goals of making extensions safer and more performant. Google could use Chrome Web Store to guide extensions that don’t actually need blocking webRequest towards the declarative API. Google could also provide extension developer tools that would automatically analyze your extension for potential improvements, like the audit tools provided to promote best practices to website developers. In addition, extensions that use webRequest should get flagged for additional review; this should be clearly communicated to extension developers.
Google’s performance claims
Google has claimed that part of the reason for its Manifest V3 restrictions is to improve performance. If extensions are allowed to have persistent background pages, the argument goes, then those pages will sit idle and waste memory. In addition, Google claims webRequest is an inefficient API because of how it traverses browser internals and extension code, and because it makes it possible for poorly implemented extensions to slow down Chrome. Google has provided no evidence to back these claims. In fact, many of the most popular extensions drastically speed up regular browsing by blocking resource-hogging ads and trackers. On the other hand, the restraints imposed by Manifest V3 will cause broken functionality and degraded performance for common extension tasks.
While a persistent extension background page will continue to use memory as long as your browser is open, try opening Chrome’s Task Manager sometime. Then compare the memory consumed by each and every website you have open to the memory consumed by your (presumably far fewer) extensions. Then, if you are a user of privacy or ad blocking extensions, try disabling them and reloading your websites. This exercise should quickly put the lie to Google’s claims. The memory consumed by your various open websites—especially without the help of privacy and security extensions to block memory-intensive trackers and advertisers—should dwarf the memory consumed by the extensions themselves.
Furthermore, repeatedly starting up and tearing down service worker-based extensions will lead to greater CPU load. For example, an extension using tabs, webNavigation, or observational webRequest APIs will get constantly invoked during browsing until either the user stops browsing or the five-minute time limit is reached. When the user resumes browsing, the service worker will have to get restarted immediately. Imagine how many times such an extension will get restarted during a typical day, and to what end? Any extension that depends on relatively expensive one-time processing on startup (for example, machine learning models or WebAssembly) is an especially poor fit for service workers’ ephemeral nature.
Beyond harming performance, arbitrarily shutting down extension service workers will break functionality. The user may be in the middle of interacting with extension-provided functionality on some web page when the extension's service worker gets shut down. After a service worker restart, the extension may have stale or missing configuration data and won't work properly without the user knowing to reload the page. The additional delay caused by service worker startup will break use cases that depend on speedy messaging between the web page and the extension. For example, an extension that dynamically modifies the right-click menu based on the type of clicked element is no longer able to communicate within itself in time to modify the menu before it opens.
Regressions and bugs
On top of everything else, Google’s rollout of Manifest V3 has been rushed and buggy. While you will no longer be able to upload new Manifest V2 extensions to the Chrome Web Store as of January 2022 (next month!), entire classes of existing extensions are completely broken in Manifest V3. As previously mentioned, observational webRequest is still broken, and so is native messaging. Manipulating web pages in the background, WebSockets, user script extensions, WebAssembly: all broken. Injecting scripts into page contexts before anything else happens (document_start “main world” injection) is also broken. This is critical functionality for privacy and security extensions. Extension developers have to resort to ugly hacks to accomplish this injection with configuration parameters, but they are all broken in Manifest V3, and the promised Manifest V3 replacement is still not available. Meanwhile, early adopters of Manifest V3 are running into bugs that cause their extensions to stop working when new extension versions are released. Even something as basic as internationalization is broken inside service workers.
Mozilla’s disappointing response
Mozilla, apparently forced to follow in Google's wake for compatibility reasons, announced it will also be requiring extensions to switch to service workers. While Mozilla will continue to support the blocking capabilities of webRequest, in addition to implementing declarativeNetRequest, it was framed as a temporary reprieve “until there’s a better solution which covers all use cases we consider important.” Recently, in a belated sign of community feedback finally having some effect, a Mozilla engineer proposed a compromise in the form of “limited event pages”. Limited event pages would lessen the pain of Manifest V3 by restoring the standard set of website APIs to extension background pages. An Apple representative expressed support on the part of Safari. Google said no. Instead of following Google into Manifest V3, Mozilla should be fighting tooth and nail against Google’s proposal. It should be absolutely clear that Google acts alone despite overwhelmingly negative community feedback. A proposal cannot become a standard when everyone else stands in opposition. Mozilla’s behavior is obscuring Google’s betrayal of the extensions ecosystem. Moreover, it gives a false sense of competition and consensus when in reality this is one of the prime examples of Google’s market dominance and anti-competitive behavior.
Conclusion
What is the future of extensions? As we explained in our 2019 response, removing blocking webRequest won’t stop abusive extensions, but will harm privacy and security extensions. If Manifest V3 is merely a step on the way towards a more "safe" (i.e., limited) extensions experience, what will Manifest V4 look like? If the answer is fewer, less-powerful APIs in service of “safety”, users will ultimately suffer. The universe of possible extensions will be limited to what Google explicitly chooses to allow, and creative developers will find they lack the tools to innovate. Meanwhile, extensions that defend user privacy and safety against various threats on the Web will be stuck in the past, unable to adapt as the threats evolve.
Google’s Manifest V3 Still Hurts Privacy, Security, and InnovationThe WebExtensions standard is what we all make it to be. If we are to take the WebExtensions Community Group at face value, we should be making extensions more capable together. We should indeed be making it easier to write secure, performant, privacy-respecting extensions, but not at the cost of losing powerful privacy-preserving functionality. We should make it easier to detect abuse, but not at the cost of losing the ability to innovate. We shouldn't rely on browser developers to think of all the needs of the diverse Web, and we don't have to: that's the beauty of extensions.
The next extensions manifest version update should be opening doors to empower all of us, unconstrained by whether you can convince a few browser engineers of the validity of your needs. Google needs to cancel moving to service workers, restore blocking webRequest, and halt Manifest V2 deprecation until all regressions in functionality are addressed. Anything short of that is at best an insincere acknowledgment of developers' shared concerns, and at worst outright hostility to the extensions community at large.
Last edited: