Tutorial: Migrate to Manifest V2
Manifest version 1 was deprecated in Chrome 18, and support will be phased out according to the manifest version 1 support schedule. The changes from version 1 to version 2 fall under two broad categories: API changes and Security changes.
This document provides checklists for migrating your Chrome extensions from manifest version 1 to version 2, followed by more detailed summaries of what these changes mean and why they were made.
API changes checklist
- Are you using the
browser_actions
property or thechrome.browserActions
API? - Replace
browser_actions
with the singularbrowser_action
property. - Replace
chrome.browserActions
withchrome.browserAction
. - Replace the
icons
property withdefault_icon
. - Replace the
name
property withdefault_title
. - Replace the
popup
property withdefault_popup
(and it now must be a string). - Are you using the
page_actions
property or thechrome.pageActions
API? - Replace
page_actions
withpage_action
. - Replace
chrome.pageActions
withchrome.pageAction
. - Replace the
icons
property withdefault_icon
. - Replace the
name
property withdefault_title
. - Replace the
popup
property withdefault_popup
(and it now must be a string). - Are you using the
chrome.self
property? - Replace with
chrome.extension
. - Are you using the
Port.tab
property? - Replace with
Port.sender
. - Are you using the
chrome.extension.getTabContentses()
or thechrome.extension.getExtensionTabs()
APIs? - Replace with
chrome.extension.getViews( { "type" : "tab" } )
. - Does your extension use a background page?
- Replace the
background_page
property with abackground
property. - Add a
scripts
orpage
property that contains the code for the page. - Add a
persistent
property and set it tofalse
to convert your background page to an event page
Security changes checklist
- Are you using inline script blocks in HTML pages?
- Remove JS code contained within <script> tags and place it within an external JS file.
- Are you using inline event handlers (like onclick, etc)?
- Remove them from the HTML code,
move them into an external JS file and
use
addEventListener()
instead. - Does your extension inject content scripts into Web pages that need to access resources (like images and scripts) that are contained in the extension’s package?
- Define the web_accessible_resources property and list the resources (and optionally a separate Content Security Policy for those resources).
- Does your extension embed external Web pages?
- Define the sandbox property.
- Is your code or library using
eval()
, newFunction()
,innerHTML
,setTimeout()
, or otherwise passing strings of JS code that are dynamically evaluated? - Use
JSON.parse()
if you’re parsing JSON code into an object. - Use a CSP-friendly library, for example, AngularJS.
- Create a sandbox entry in your manifest and
run the affected code in the sandbox,
using
postMessage()
to communicate with the sandboxed page. - Are you loading external code, such as jQuery or Google Analytics?
- Consider downloading the library and packaging it in your extension, then loading it from the local package.
- Whitelist the HTTPS domain that serves the resource in the "content_security_policy" part of your manifest.
Summary of API changes
Manifest version 2 introduces a few changes to the browser action and page action APIs, and replaces a few old APIs with newer ones.
Changes to browser actions
The browser actions API introduces some naming changes:
- The
browser_actions
andchrome.browserActions
properties have been replaced with their singular counterpartsbrowser_action
andchrome.browserAction
. - Under the old
browser_actions
property, there wereicons
,name
, andpopup
properties. These have been replaced with: default_icon
for the browser action badge icondefault_name
for the text that appears in the tooltip when you hover over the badgedefault_popup
for the HTML page that represents the UI for the browser action (and this must now be a string, it cannot be an object)
Changes to page actions
Similar to the changes for browser actions, the page actions API has also changed:
- The
page_actions
andchrome.pageActions
properties have been replaced with their singular counterpartspage_action
andchrome.pageAction
. - Under the old
page_actions
property, there wereicons
,name
, andpopup
properties. These have been replaced with: default_icon
for the page action badge icondefault_name
for the text that appears in the tooltip when you hover over the badgedefault_popup
for the HTML page that represents the UI for the page action (and this must now be a string, it cannot be an object)
Removed and changed APIs
A few extension APIs have been removed and replaced with new counterparts:
- The
background_page
property has been replaced by background. - The
chrome.self
property has been removed, usechrome.extension
. - The
Port.tab
property has been replaced withPort.sender
. - The
chrome.extension.getTabContentses()
and thechrome.extension.getExtensionTabs()
APIs have been replaced bychrome.extension.getViews( { "type" : "tab" } )
.
Summary of security changes
There are a number of security-related changes that accompany the move from manifest version 1 to version 2. Many of these changes stem from Chrome’s adoption of Content Security Policy; you should read more about this policy to understand its implications.
Inline scripts and event handlers disallowed
Due to the use of Content Security Policy, you can no longer use <script> tags that are inline with the HTML content. These must be moved to external JS files. In addition, inline event handlers are also not supported. For example, suppose you had the following code in your extension:
<html> <head> <script> function myFunc() { ... } </script> </head> </html>
This code would cause an error at runtime.
To fix this, move <script> tag contents to external files
and reference them with a src=’path_to_file.js’
attribute.
Similarly, inline event handlers, which are a common occurrence and convenience feature used by many Web developers, will not execute. For example, consider common instances such as:
<body onload="initialize()"> <button onclick="handleClick()" id="button1">
These will not work in manifest V2 extensions.
Remove the inline event handlers,
place them in your external JS file and use addEventListener()
to register event handlers for them instead.
For example, in your JS code, use:
window.addEventListener("load", initialize); ... document.getElementById("button1").addEventListener("click",handleClick);
This is a much cleaner way of separating your extension’s behavior from its user interface markup.
Embedding content
There are some scenarios where your extension might embed content that can be used externally or come from an external source.
Extension content in web pages:
If your extension embeds resources (like images, script, CSS styles, etc)
that are used in content scripts that are injected into web pages,
you need to use the
web_accessible_resources property
to whitelist these resources so that external Web pages can use them:
{ ... "web_accessible_resources": [ "images/image1.png", "script/myscript.js" ], ... }
Embedding external content:
The Content Security Policy only allows local script
and objects to loaded from your package,
which prevents external attackers from introducing unknown code to your extension.
However, there are times when you want to load externally served resources,
such as jQuery or Google Analytics code.
There are two ways to do this:
- Download the relevant library locally (like jQuery) and package it with your extension.
- You can relax the CSP in a limited way by whitelisting HTTPS origins
in the “content_security_policy” section of your manifest.
To include a library like Google Analytics, this is the approach to take:
{ ..., "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'", ... }
Using dynamic script evaluation
Perhaps one of the biggest changes in the new manifest v2 scheme is
that extensions can no longer use dynamic script evaluation techniques like
eval()
or new Function()
,
or pass strings of JS code to functions
that will cause an eval()
to be used,
like setTimeout()
.
In addition, certain commonly used JavaScript libraries,
such as Google Maps and certain templating libraries,
are known to use some of these techniques.
Chrome provides a sandbox for pages to run in their own origin,
which are denied access to chrome.* APIs.
In order to use eval()
and the like under the new Content Security Policy:
- Create a sandbox entry in your manifest file.
- In the sandbox entry, list the pages you want to run in the sandbox.
- Use message passing via
postMessage()
to communicate with the sandboxed page.
For more details on how to do this, see the Sandboxing Eval documentation.
Further reading
The changes in manifest version 2 are designed to guide developers toward building more secure and robustly-architected extensions and apps. To see a complete list of changes from manifest version 1 to version 2, see the manifest file documentation. For more information about using sandboxing to isolate unsafe code, read the sandboxing eval article. You can learn more about Content Security Policy by visiting our extensions-related tutorial and a good introduction on HTML5Rocks.