What changes in Chrome Extension Manifest V3
Major change includes changes in almost every field of the Manifest file, permissions updates, API changes, and more.
▪A few months ago, I announced (a personally ambitious move) on Twitter that I started writing a book about WebExtensions. It was just about the same time I saw a talk about Chrome extensions and the world of tomorrow.
Being Chrome the browser that championed the Extensions concept, I got interested to know the changes behind their decision to roll out the update. How does it affect the ecosystem? What changes in real-terms? What do extension developers need to know?
That was when the idea of this post came into mind. This blog post is the result of personal research, mostly based on the publicly available Chrome’s Manifest V3 design document. All other resources are linked wherever they are mentioned.
While Manifest V3 is not finished at the moment of this writing, several fundamental changes are already available in Chrome Canary.
Motivations behind the Manifest V3 update
According to the design document (draft), the motivations for this update were divided in three core areas:
- "manifest_version": 2,
+ "manifest_version": 3,
- Security. Improve security guarantees against external attackers and malicious extensions. Increase the end-user trust in what they install.
- Privacy. Give users more control over what an extension can run/access. Encourage developers to use in-context permission requests and temporary permission grants, namely
activeTab.
- Performance. Reduce the number of resources consumed by an extension over its lifetime. Disallow long-running background processes.
Based on these three key points, some Manifest fields such as background scripts, content scripts, and host permissions were updated. This update also changed important/popular APIs such as webRequest,
declarativeNetRequest,
and the browserAction
/pageAction
APIs
What changes in Manifest V3?
- Changes in the background context. A service worker replaces the background script, end of long-lived/DOM-supported backgrounds.
- Changes in the Manifest host permission specification. New field for
host_permissions
, drop support for<all_urls>
,activeTab
-style host permissions. - Changes in the Manifest Content Security Policy. Split CSP per context, disallow
script-src
,worker-src
,object-src
, andstyle-src
with non-local values. - Changes in content scripts cross-origin capabilities. Content scripts will be allowed to execute cross-origin requests only where the host page is allowed.
- Deprecate NaCl/PNaCl. Extension authors should finish their native code to WebAssembly as NaCl/PNaCl (already deprecated) will stop working.
- Promise-based APIs. Instead of callbacks, authors can take advantage of Promises. The current callback version will still be supported.
- API changes Changes in
webRequest
, addition ofdeclarativeNetRequest
, merge ofbrowserAction
andpageAction
,chrome.favicon
namespace instead ofchrome://favicon
. Maybe more. - More restrictions for Web-Accessible resources. All resources to be loaded should be declared. Resources URL will be exposed using a unique identifier, instead of through their path.
- Dynamic Content Scripts. Support the ability to add/remove and enable/disable content scripts permissions dynamically.
Changes in the background context
In the extension context, “background” pages/scripts refer to the code that runs in the background process, invisible to the user, and allows extensions to execute (and listen) for code outside any tab or window.
With Manifest V2, you have two types of background processes: persistent pages (in theory, if you need to use the webRequest
API) and lazy (event) pages.
In Manifest V3, the only background option will be using a service worker.
"background": [{
- "scripts": ["background.js"]
+ "service_worker": ["background.js"]
}],
Since Service workers were inspired by background pages, we should not have any problems updating an extension using event pages for background processes. In their execution context, both can listen and terminate events when they are no longer needed.
Unlike background pages (which inherits from the Window
scope), The service workers’ scope is limited. It inherits its interface from WorkerGlobalScope, a child of EventTarget, so it has no means to access the DOM. Another change is for extensions that use the long-lived background to store a global state. Since service workers are event-based, there is no way to save a permanent state in long-lived backgrounds anymore.
If your extension falls into one of these cases, take a look at Migrate to Event-Driven Background Scripts. If the above situations do not apply to you, but still concerns, Chrome has a Service Worker migration guide to help you through the migration process.
Changes in the Manifest host permission specification
The host permission allows extensions to inject scripts on and intercept network requests from the host. In Manifest V2, extensions can request hosts by:
- Specificity, like,
https://cezaraugusto.com.
- Patterns, like
https://*.cezaraugusto.com.
- Special keys, like
<all_urls>.
+ "host_permissions": [
+ "*://*.twitter.com/*",
+ "*://*.instagram.com/*",
+ ],
"permissions": [
- "*://*.twitter.com/*",
- "*://*.instagram.com/*",
"webRequest",
"webRequestBlocking",
],
In Manifest V3, a new manifest key "host_permissions"
was added to host permissions and will be used only for API permissions. What is also new is that host permissions will require runtime approval by the use. This change plans to give users more control over permissions.
Exceptional cases in extensions that require broad permissions such as *://*/*
and <all_urls>
are rare, but often abused by developers. With Manifest V3, Chrome plans to prevent it by dropping support for <all_urls>
and start asking permissions at runtime, using an activeTab-style host permission by default, with extra options such as to always run on a specific site. In Manifest V3 public design document, using the chrome.permission
API is also under consideration.
activeTab
allows temporary access to an extension in the active tab after user invocation (such as clicking a browser action). If a user clicks an extension on a website, there is an implicit understanding that they are allowing the extension to see its contents.
It’s recommended that while developing your extension, try to target interactions around temporary host permissions (see activeTab
itself).
Changes on the Manifest Content Security Policy
With the Manifest V3 update, Chrome will disallow extensions from using remotely-hosted JavaScript, CSS, and WebAssembly code. Extensions will still be able to make server communication to request data, such as loading JSON, requesting media access, and remote API calls.
Chrome plans to make this change by changing how CSP works in the Manifest file (along with undisclosed policy changes). The content_security_policy
property is now split into three main categories:
- "content_security_policy": "font-src 'self' data:; script-src 'self';"
+ "content_security_policy": {
+ "extension_pages": "font-src 'self' data:; img-src 'self'",
+ "isolated_world": "script-src 'self'",
+ "sandbox": "worker-src: 'self'"
+ }
extension_pages
. Directives for the service worker and extension pages.isolated_world
. Used by content scripts to protects you against attacker’s attempts against your extension.sandbox
. Used for sandboxed pages.
Another change is with the directives script-src,
worker-src,
object-src
, and style-src
with that will be disallowed from using non-local values.
The official migration guide has a dedicated section about all the CSP field changes.
Changes in the content scripts cross-origin capabilities
Right now, extensions can make cross-origin requests via extension pages and content scripts. As long as Manifest’s host permissions are defined, extensions can make cross-origin requests to any domain.
In Manifest V3, will stop content scripts will stop having special request privileges by allowing exclusive access only through its background page, using extension messaging. Content scripts will only be allowed to make cross-origin requests that the host page is capable of doing.
If a cross-origin request needs to perform where there’s no permission, requests should be made from the background context and pass the response to a content script. See Changes to Cross-Origin Requests in Chrome Extension Content Scripts for proper guidance on how to execute cross-origin requests safely in an extension.
Deprecate NaCl/PNaCl
NaCl (Native Client) and PNaCI (Portable Native Client) allow developers to run native compiled C and C++ code as part of their extension.
PNaCl support was dropped everywhere already, except inside Chrome Apps and Extensions. Starting with Manifest V3, NaCl and PNaCl will no longer be supported. Instead of PNaCI, extension authors should use WebAssembly. There is a specific set of recommendations to help developers and authors through the migration process.
All APIs will be promise-based
The current callback version will still be supported. Providing a callback to an API method will prevent the promise from being returned. This backward compatibility allows developers to have more time migrating all the changes required in Manifest V3.
Worth noting that Firefox has been using a promise-based API for a while, and since Chromium represents all other major browsers, this change makes it easier for extension developers to create cross-browser extensions.
API changes
webRequest
allows extensions to intercept network requests to modify, redirect, or using its blocking version, block them. In this change, the blocking version will be limited, possibly making blocking options observational for most events.declarativeNetRequest
allows extensions to synchronously tell Chrome what to do with a request, rather than have Chrome forward the request to the extension. It will be created as the primary way to modify network requests.browserAction
andpageAction
allow extensions to create a toolbar icon. They will be merged into a singleaction
API. Since their difference is not well defined and both APIs have the same UI surface in the toolbar (pageAction
used to appear ephemerally inside the Omnibox).chrome://favicon
will move to a new API underchrome.favicon.
namespace. This API would be available with either new favicon permission, or with granted host permission for the requested favicon.chrome.capture
the namespace will allow extensions to capture the content of a user’s screen. The APIstabs.captureVisibleTab()
,tabCapture.capture()
,tabCapture.getMediaStreamId()
,pageCapture.saveAsMHTML()
, anddesktopCapture.chooseDesktopMedia()
will be moved under it.chrome.notifications
will be replaced by its native web counterpart, the Web Notifications API.- Update or remove APIs that returns
DOMWindow
orHTMLElement
since Service Workers runs on a different thread in the renderer without DOM access. - Deprecate APIs. Discontinue APIs described in this list.
- Unused, unpopular and limbo APIs are going to be removed too, such as
declarativeWebRequest
(obsolete withdeclarativeNetRequest
). - Miscellaneous API changes
i18n.getMessage
is considered to be changed, but the design document mentions the alternative for this method is TBD.
Note that the API changes section in Manifest V3 is not finished at the moment of this writing and thus prone to changes. If you are unsure about changes described here, use the linked material as the definitive reference.
More restrictions for Web-Accessible resources
Web-Accessible resources are resources used in the context of a web page. An extension that modifies the interface of a page must specify the modifying resources in the Manifest file under the web_accessible_resources
field.
In Manifest V3, resources restrictions will be stricter by requiring that any resource that will be loaded in an untrusted frame to be also specified.
{
"web_accessible_resources": [
"images/*.png"
]
}
Another change refers to the resources URL. Resources are identified as chrome-extension://<extension-id>/<resource-path>
. This schema allows websites to fingerprint extensions. According to the Manifest V3 design document, Chrome plans to improve this by (optionally) allowing resources to only be exposed through a unique identifier, rather than through their path.
Dynamic Content Scripts
Extensions will be able to dynamically add, remove, enable, and disable content scripts. This dynamic feature will allow extensions to add scripts only once they have such permission.
Conclusions
There are many changes. Moving background scripts to a Service Worker is a big move, both for the platform and for authors. Another high point is the API moving to be promise-based, making the development of WebExtensions similar to Firefox’s Add-On API. Considering there are no standards for Extensions, this is great for authors looking to ease the process of writing cross-platform extensions, considering that in theory, other Chromium-based browsers will not object in following changes that don’t affect the output (such as API promisification).
Still talking about the code standardization, my bet is that other browsers will follow most of the Manifest V3 changes, despite some divergences. See Firefox’s Manifest V3 FAQ and Opera, Brave, and Vivaldi’s opinions for more.
Call me an optimist, but I hope this update also gives traction to the browser extension community group.