Migrating to Manifest V3

This is a living document. It will receive regular updates from Chromium contributors as implementation work on manifest version 3 (MV3) progresses.

Legend

Term Description
NYI Not Yet Implemented – Work has either not yet begun or is not substantial enough for the feature to be considered ready for experimentation.
In Preview The implementation has progressed far enough that the team is looking for developer feedback. The feature may continue to evolve during this stage.
Stable The feature is complete. The API should be considered stable and safe to implement against.
TBD To Be Determined — Has not yet been scheduled.
MV# Manifest Version <Number>— Indicates that the associated item applies to either the current (MV2) or future (MV3) version of the Chrome Extension platform.

Timeline

The following timeline provides a very rough estimate. Dates associated with the below milestones represent the earliest expected point at which the milestone may land and are subject to change.

Milestone (Estimated) Release Date
MV3 Preview/Alpha October 31st, 2019
MV3 Stable Release 2020
MV2 End of Life TBD

We have not decided on a final end of life date for MV2. We will continue evaluating necessary features in Manifest V3 and we don't have a firm timeline as dates are heavily dependent on implementation progress and implementation based on developer feedback.

Release Channels

MV3 is in active development. Developers that wish to experiment with the latest extension platform changes should install Chrome Canary. For additional information, see the Chromium project's documentation on Chrome Release Channels and Release Process.

API Checklist

  • Do you have host permissions in your permissions or optional_permissions arrays in manifest.json?
    • Move host permissions into the host_permissions field in manifest.json.
  • Are you using background pages?
    • Replace background.page or background.scripts with background.service_worker in manifest.json. Note that the service_worker field takes a string, not an array of strings.
    • Remove background.persistent from manifest.json.
    • Update background scripts to adapt to the service worker execution context.
  • Are you using the browser_action or page_action property in manifest.json?
    • Replace with action.
  • Are you using the chrome.browserAction or chrome.pageAction JavaScript API?
    • Migrate to chrome.action.
  • Are you currently using the blocking version of chrome.webRequest in a consumer-facing extension? (Does not apply to extensions only distributed using ExtensionInstallForcelist)?
    • Migrate request modification logic to chrome.declarativeNetRequest rules.
    • Replace the webRequestBlocking permission with declarativeNetRequest.
    • Remove the webRequest permissions if you no longer need to observe network requests.
    • Remove unnecessary host permissions; blocking a request or upgrading a request's protocol doesn't require host permissions with declarativeNetRequest.
  • Are you currently using chrome.tabs.executeScript({code: '...'}), eval(), or new Function() in background contexts or content scripts?
    • Move all external code (JS, Wasm, CSS) into your extension bundle.
    • Update script and style references to load resources from the extension bundle.
    • Use chrome.runtime.getURL() to build resource URLs at runtime.
  • Are you currently using chrome.runtime.getBackgroundPage(), chrome.extension.getBackgroundPage(), chrome.extension.getExtensionTabs(), or chrome.extension.getViews()?
    • Migrate to passing messages between other contexts and the background service worker.

Security Checklist

  • Are you making CORS requests in content scripts?
    • Move these requests to the background service worker.
  • Are you using a custom content_security_policy in manifest.json?
    • Replace content_security_policy with content_security_policy.extension_pages, content_security_policy.isolated_world (NYI), or content_security_policy.sandbox as appropriate.
    • Remove references to external domains in script-src, worker-src, object-src, and style-src directives if present.

API Changes

Background Service Workers (In Preview)

Background service workers are available to MV3 extensions in Canary as of October 31, 2019. Once this feature stabilizes, it will be available to MV2 extensions in Stable.

  • The background field remains in manifest.json
  • background.page, background.scripts, and background.persistent fields in manifest.json are not supported in MV3.
  • background.service_worker has been added. It takes a string specifying the relative path of the extension's root service worker. Additional scoped service workers can be registered from the root service worker, but they will not have access to Chrome APIs and cannot be registered for the root ('/') scope.
  • Additional guidance on migrating to service workers can be found in Migrating from Background Pages to Service Workers.

Extension Actions (In Preview)

The page action and browser action APIs have been consolidated into a single API called action. Once this feature stabilizes, it will be available to MV2 extensions in Stable.

  • page_action and browser_action fields in manifest.json have been replaced with the action property.
  • chrome.browserAction and chrome.pageAction APIs have been replaced by the chrome.action API.
  • chrome.action should behave the same as chrome.browserAction. This API is subject to change.

Removals

  • chrome.runtime.getBackgroundPage(), chrome.extension.getBackgroundPage(), chrome.extension.getExtensionTabs(), and chrome.extension.getViews() are not exposed in service workers.
    • Due to the asynchronous design of workers, we currently do not plan on exposing any API that allows synchronous DOM access to other pages.

Promise-based APIs (NYI)

NOTE: This feature is still in early development.

Security Changes

Cross Origin Requests in Content Scripts (MV2-3)

Note: This change took place in MV2 around the same time as early MV3 work. It is included here for the sake of completeness.

Content scripts now have similar privileges to the host page they're injected into. Consequently, fetches initiated by a content scripts share the page's origin and content scripts can only execute cross-origin requests that the host page could make. In order to perform a cross-origin request to a resource the page is not allowed to access, extension authors should adapt by executing the request from their background context and passing the response to a content script. See Changes to Cross-Origin Requests in Chrome Extension Content Scripts for additional guidance on how to safely execute cross-origin requests in an extension.

Extension Content Security Policy (NYI)

The way Chrome handles content security policy (CSP) customization is changing slightly in MV3. In MV2, Chrome enforced a default CSP and developers could override it by providing a custom content_security_policy in their manifest.json. In MV3, developers provide CSP overrides for specific execution environments rather than a single override. Additionally, Chrome now disallows specific directives in CSP overrides in order to prevent the extension from loading code that isn't distributed in its bundle.

  • content_security_policy in manifest.json will take an object rather than a string. Properties of this object define CSPs for various environments.
  • MV3 extensions that specify a content_security_policy string will throw an error on load.
  • content_security_policy.extension_pages is a string that defines the CSP for the extension's service worker(s), popup, extension pages, etc.
  • content_security_policy.isolated_world is a string that defines the CSP used by content scripts. This can be used to protect against attackers that attempt to gain privileged access to your extension's content scripts. (NYI)
  • content_security_policy.sandbox is a string that defines the CSP for sandboxed pages. Note that sandbox pages can still use remotely hosted code. See also Using eval in Chrome Extensions. Safely.
  • Developers can no longer use CSP directives that enable remotely hosted code (code that is not bundled with the extension). Manifests that include such directives will error at parse time.
    • script-src, worker-src, object-src, and style-src with non-local values are disallowed.

Known Issues

  • chrome.action.setIcon(), chrome.browserAction.setIcon(), and chrome.pageAction.setIcon() do not currently accept a path property in service workers (1015136).
    • The following APIs are not currently exposed in service workers
    • chrome.enterprise.platformKeys
    • chrome.fileBrowserHandler
    • chrome.fileSystem
    • chrome.fileSystemProvider
    • chrome.i18n, except getAcceptLanguages()
    • chrome.login
    • chrome.tabCapture
    • chrome.pageCapture
    • chrome.printerProvider
    • chrome.platformKeys
    • chrome.system.display
  • The following APIs are exposed but do not function as expected
    • chrome.tabs.captureVisibleTab() will error