> [!WARNING]
> **Warning:** The Chrome Web Store no longer accepts Manifest V2 extensions. Follow the [Manifest V3 Migration guide](https://developer.chrome.com/docs/extensions/migrating) to convert your extension to Manifest V3.

## Summary

### What's changing?

Beginning in Chrome 70, users have the ability to restrict extension host access to a custom list of
sites, or to configure extensions to require a click to gain access to the current page.

### Which APIs are affected?

This change affects any APIs that are affected by the host permissions specified in your extension's
manifest, as well as content scripts. APIs that require host permissions include [webRequest](https://developer.chrome.com/docs/extensions/mv2/reference/webRequest),
[cookies](https://developer.chrome.com/docs/extensions/mv2/reference/cookies), [tabs.executeScript()](https://developer.chrome.com/docs/extensions/mv2/reference/tabs#method-executeScript) and [tabs.insertCSS()](https://developer.chrome.com/docs/extensions/mv2/reference/tabs#method-insertCSS), and performing cross-origin
requests, such as through an `XMLHTTPRequest` or the `fetch()` API.

## Restricting access

### How can the user restrict access?

Users can choose to allow your extension to run on click, on a specific set of sites, or on all
requested sites. These options are presented to users on the `chrome://extensions` page as well as
in the extension context menu.

![A screenshot of the context menu controls for runtime host permissions,
including options to run the extension on click, on a specific site, or on all sites.](https://developer.chrome.com/static/docs/extensions/mv2/runtime-host-permissions/image/a-screenshot-the-context-fa2133e9813b4.png)

### What happens if a user chooses to run my extension "on click"?

The extension essentially behaves as though it used the [activeTab](https://developer.chrome.com/docs/extensions/mv2/manifest/activeTab) permission. The extension is
granted temporary access to any host the user clicks the extension on, if that host was requested by
the extension (and isn't a restricted site, like chrome://settings). When set to run on click,
Chrome badges your extension with a circle and drop shadow (see below) to indicate that is
requesting access on a particular site.

![A screenshot of the badging Chrome adds to the extension icon in the toolbar](https://developer.chrome.com/static/docs/extensions/mv2/runtime-host-permissions/image/a-screenshot-the-badging-63a9e7033506c.png)

### What happens if a user chooses to run my extension on specific sites?

Your extension is allowed to run automatically on any sites the user has chosen, and can access the
site without further user action. On other sites that your extension requested, but the user did not
grant permission to, the behavior is the same as if the user had set the extension to run on click.

### What happens if a user chooses to run my extension on all sites?

The extension can automatically access any sites requested in the manifest.

## API behaviors

### Web request API

The extension can still intercept, modify, and block any requests from sites it has access to. For
sites the extension does not have access to, Chrome badges the extension to indicate that the
extension requests access to the page. The user can then grant access to the extension; Chrome then
prompts the user to refresh the page to allow your extension to intercept the network requests.

### Content scripts, tabs.executeScript(), tabs.insertCSS()

The extension can still inject scripts and style sheets automatically for any sites it has access
to. For sites the extension does not have access to, Chrome badges the extension to indicate that
the extension requests access to the page. The user can then grant access to the extension. If the
content script was set to inject at document_idle, the script will inject immediately. Otherwise,
Chrome prompts the user to refresh the page to allow your extension to inject scripts earlier in
page load (at document_start or document_end). The callbacks for the [tabs.executeScript()](https://developer.chrome.com/docs/extensions/mv2/reference/tabs#method-executeScript) and
[tabs.insertCSS()](https://developer.chrome.com/docs/extensions/mv2/reference/tabs#method-insertCSS) methods are only invoked if the user grants access to the site.

### Cookies and background page XHR

The extension can still read and modify any cookies from and perform a cross-origin XHR to sites it
has access to. Because there is no tab associated with an extension page accessing another origin's
cookies or XHRing to another host, Chrome does not badge the extension to indicate to the user that
the extension is requesting to access a site. Trying to access a cookie for another site or make a
cross-origin XHR will fail with an error as if the extension's manifest did not include the host
permission. For these cases, we encourage you to use optional permissions in order to allow the user
to grant runtime access to different sites.

The example below illustrates how this may work for the cookies API.

Before:

    {
      ...
      "permissions": ["cookies", "https://example.com"]
    }

    chrome.cookies.get({url: 'https://example.com', name: 'mycookie'},
                        function(cookie) {
                          // Use the cookie.
                        });

After:

    {
      ...
      "permissions": ["cookies"],
      "optional_permissions": ["https://example.com"]
    }

    // Note: permissions.request() requires a user gesture, so this
    // may only be done in response to a user action.
    chrome.permissions.request(
        {origins: ['https://example.com']},
        function(granted) {
          if (granted) {
            chrome.cookies.get({url: 'https://example.com', name: 'mycookie'},
                                function(cookie) {
                                  // Use the cookie.
                                });
          } else {
            // Handle grant failure
          }
        });

## Migration

### What are best practices to avoid being negatively impacted?

Extensions can use the [optional permissions](https://developer.chrome.com/docs/extensions/mv2/reference/permissions), [activeTab](https://developer.chrome.com/docs/extensions/mv2/manifest/activeTab), and [declarativeContent](https://developer.chrome.com/docs/extensions/mv2/reference/declarativeContent) APIs
to follow best practices. Optional permissions are granted at runtime, and allow the extension to
request specific access to a site. The [activeTab](https://developer.chrome.com/docs/extensions/mv2/manifest/activeTab) permission is not affected, and extensions
using it continue to work normally. The [declarativeContent](https://developer.chrome.com/docs/extensions/mv2/reference/declarativeContent) API is a substitute for many needs
to inject scripts into every page.

### What happens to my current users' settings?

This change will not immediately affect any current permissions granted to your extension. That is,
it will continue to operate as before unless the user takes action to restrict the sites it is
allowed to access. In future releases, Chrome will provide more controls to users to adjust
settings.

### How can I check if my extension has permission to run on a site?

You can use the [permissions.contains()](https://developer.chrome.com/docs/extensions/mv2/reference/permissions#method-contains) API in order to check whether your extension has been
granted access to a given origin.