Early next year, Firefox will release Mozilla’s Manifest V3 (MV3). Therefore, it’s an ideal time to consider migrating your Manifest V2 extensions. One of our goals throughout our approach to MV3 has been to gradually release new WebExtensions features that enable you to begin implementing APIs that are compatible with MV3. To this end, we recently released some exciting new features you should know about…
MV3 changes you can make to your extension right now
In Firefox MV3, we’re providing Event Pages as the background script. Event Pages retain several important features, including access to DOM and WebAPIs that are not available with the new service worker backgrounds used in Google Chrome.
We enabled Event Pages for MV2 (aka non-persistent background pages that can be closed and respawned based on browser events) in Firefox 106. This update is a major step toward MV3 because all extensions must adopt Event Pages in MV3. But you can make this change today and use new Event Pages benefits such as:
- Resiliency against unexpected system crashes. Now we can restart a corrupted background page without hindering the user.
- No need for an extension reboot to reset a background page.
- Save on memory resources by putting idle background pages to sleep.
How do I implement Event Pages?
Now that your background script is non-persistent, you need to tell Firefox when to wake up the page if it’s suspended. There are two methods available:
- Use an event listener like `browser.tabs.onCreated` in your background script. Event listeners must be added at the top level execution of your script. This way, if your background is sleeping Firefox knows to wake the script whenever a new tab is spawned. This works with nearly all events in the WebExtensions API. Here’s more info on adding listeners. (Note that Firefox recognizes arguments passed to addListener and does not create multiple listeners for the same set of arguments.)
- Use `browser.runtime.getBackgroundPage` if you need a background page to run processes unrelated to events. For instance, you may need a background script to run a process while the user is involved with a browser action or side panel. Use this API anytime you need direct access to a background page that may be suspended or closed. Here’s more info on background script functions.
- Menu items created by an event page are available after they’re registered — even if the event page is terminated. The event page respawns as necessary to menu events.
- Registered scripts can be injected into matching web pages without the need for a running Event Page.
You can take another big step toward MV3 by switching to the new Scripting API. This API consolidates several scripting related APIs — contentScripts.register(), tabs.insertCSS(), tabs.removeCSS(), and tabs.executeScript() — and adds capabilities to register, update, and unregister content scripts at runtime.
Also, arbitrary strings can no longer be executed because the code parameter has been removed. So you’ll need to move any arbitrary strings executed as scripts into files contained within the extension, or to the func property used with, if necessary, the args parameter.
This API requires the scripting permission.
Preparing for MV3 restrictions
MV3 will impose enhanced restrictions on several features. Most of these restrictions are outlined in the MV3 migration guide. By following the steps detailed in the guide, there are some ways you can begin modifying your MV2 extension to make it comply more closely with MV3 requirements. A few noteworthy areas include…
Conform to MV3’s Content Security Policy
Mozilla’s long-standing add-on policies prohibit remote code execution. In keeping with these policies, the content_security_policy field no longer supports sources permitting remote code in script-related directives, such as script-src or `’unsafe-eval’`. The only permitted values for the `script-src` directive is `’self’` and `’wasm-unsafe-eval’`. `’wasm-unsafe-eval’` must be specified in the CSP if an extension wants to use WebAssembly. In MV3, content scripts are subject to the same CSP as other parts of the extension.
Historically, a custom extension CSP required object-src to be specified. This is not required in MV3 and was removed from MV2 in Firefox 106 (see object-src in content_security_policy on MDN). This change makes it easier for extensions to customize the CSP with minimal boilerplate.
The Content Security Policy (CSP) is more restrictive in MV3. If you are using a custom CSP in your MV2 add-on, you can validate the CSP by temporarily running it as an MV3 extension. See the MV3 migration guide for details.
Upgrade insecure requests – https by default
When communicating with external servers, extensions will use https by default. Extensions should replace the “http:” and ”ws:” schemes in their source code with secure alternatives, “https:” and ”wss:”. The default MV3 CSP includes the upgrade-secure-requests directive, to enforce the use of secure schemes even if an insecure scheme was used.
Extensions can opt out of this https requirement by overriding the content_security_policy and omitting the upgrade-secure-requests, provided that no user data is transmitted insecurely through the extension.
All MV3 permissions, including host permissions, are opt-in for users. This necessitated a significant Firefox design change — the introduction of the extensions button — so users can easily grant or deny website specific permissions at any time (the button is enabled on Firefox Nightly for early testing and feedback).
Therefore, you must ensure your extension has permission whenever it accesses APIs covered by a permission, accesses a tab, or uses Fetch API. MV2 already has APIs that enables you to check for permissions and watch for changes in permission. When necessary, you can get the current permission status. However, rather than always checking, use the permissions.onAdded and permissions.onRemoved event APIs to watch for changes.
Update content scripts
While content scripts continue to have access to the same extension APIs in MV3 as in MV2, most of the special exceptions and extension specific capabilities have been removed from the web platform APIs (DOM APIs). In particular, the extension’s host permissions no longer apply to Fetch and XMLHttpRequest.
CSP for content scripts
With MV2 no CSP is applied to content scripts. In MV3, content scripts are subjected to the same CSP as other parts of the extension (see CSP for content scripts on MDN). Notably, this means that remote code cannot be executed from the content script. Some existing uses can be replaced with functionality from the Scripting API such as func and args (see the “Scripting” section above), which is available to MV2 extensions.
XHR and Fetch
With MV2 you also have access to some APIs, such as XMLHttpRequest and Fetch, from both extension and web page contexts. This allows for cross origin requests in a way that is not available in MV3. In MV3, XHR and Fetch operate as if the web page itself was using them, and are subject to cross origin controls.
Content scripts can continue using XHR and Fetch by first making requests to background scripts. A background script can then use Fetch to get the data and return the necessary information to the content script. To avoid privacy issues, set the “credentials” option to “omit” and cache option to “no-cache”. In the future, we may offer an API to support the make-request-on-behalf-of-a-document-in-a-tab use case.
Will Chrome MV3 extensions work in Firefox MV2?
The release of MV3 in Firefox is distinct from Chrome. Add-ons intended to work across different browsers will, in most cases, require some level of adjustment to be compatible in both Firefox and Chrome. That said, we are committed to a high level of compatibility. We will be providing additional APIs and features in the near future. If you’ve converted your Chrome extension to Google’s MV3, you may be able to consolidate some of those changes into your Firefox MV2 extension. Here are a few areas to investigate:
- Service Workers are not yet available in Firefox; however many scripts may work interchangeably between Service Workers and Event Pages, depending on functionality. To get things working, you may need to remove service worker specific APIs. See Service Worker Global Scope for more information.
- DNR is not yet available in Firefox. Firefox retains WebRequest blocking in MV3, which can be used in place of DNR. When DNR is available, simple request modifications can be moved over to DNR.
- The storage.session API is not yet available in Firefox. You can use other storage mechanisms in the meantime.
Hopefully, we’ve provided helpful information so you can use the new MV2 features to start your migration to MV3. As always, we appreciate your feedback and welcome questions. Here are the ways to get in touch: