Anatomy of an extension - Mozilla

Anatomy of an extension
=======================

An extension consists of a collection of files, packaged for distribution and installation. In this article, we will quickly go through the files that might be present in an extension.

manifest.json
-------------

This is the only file that must be present in every extension. It contains basic metadata such as its name, version, and the permissions it requires. It also provides pointers to other files in the extension.

The manifest can also contain pointers to several other types of files:

Background scripts

Scripts that respond to browser events.

Icons

For the extension and any buttons it might define.

Sidebars, popups, and options pages

HTML documents that provide content for various user interface components.

Content scripts

JavaScript included with your extension, that you will inject into web pages.

Web-accessible resources

Make packaged content accessible to web pages and content scripts.

![The components of a web extension. The manifest.JSON must be present in all extensions. It provides pointers to background pages, content scripts, browser actions, page actions, options pages, and web accessible resources. Background pages consist of HTML and JS. Content scripts consist of JS and CSS. The user clicks on an icon to trigger browser actions and page actions and the resulting pop-up consists of HTML, CSS, and JS. Options pages consist of HTML, CSS, and JS.](/en-US/docs/Mozilla/Add-ons/WebExtensions/Anatomy_of_a_WebExtension/webextension-anatomy.png)

See the `manifest.json` reference page for all the details.

Along with those already listed in the manifest, an extension may also include additional Extension pages and supporting files.

Background scripts
------------------

Extensions often need to respond to events that occur in the browser independently of the lifetime of any particular web page or browser window. That is what background scripts are for.

Background scripts can be persistent or non-persistent. Persistent background scripts load as soon as the extension loads and stay loaded until the extension is disabled or uninstalled. This background script behavior is only available in Manifest V2. Non-persistent background scripts load when needed to respond to an event and unload when they become idle. This background script behavior is an option in Manifest V2 and the only background script behavior available in Manifest V3.

You can use any of the WebExtension APIs in the script, if you have requested the necessary permissions.

See the background scripts article to learn more.

Sidebars, popups, and options pages
-----------------------------------

Your extension can include various user interface components whose content is defined using an HTML document:

Sidebar

A pane that is displayed at the left-hand side of the browser window, next to the web page.

Popup

A dialog that you can display when the user clicks on a toolbar button or address bar button

Options

A page that's shown when the user accesses your add-on's preferences in the browser's native add-ons manager.

For each of these components, you create an HTML file and point to it using a specific property in `manifest.json`. The HTML file can include CSS and JavaScript files, just like a normal web page.

All of these are a type of Extension pages. Unlike a normal web page, your JavaScript can use all the same privileged WebExtension APIs as your background script.

Extension pages
---------------

You can also include HTML documents in your extension which are not attached to some predefined user interface component. Unlike the documents you might provide for sidebars, popups, or options pages, these don't have an entry in `manifest.json`. However, they do also get access to all the same privileged WebExtension APIs as your background script.

You'd typically load a page like this using `windows.create()` or `tabs.create()`.

See Extension pages to learn more.

Content scripts
---------------

Use content scripts to access and manipulate web pages. Content scripts are loaded into web pages and run in the context of that particular page.

Content scripts are extension-provided scripts which run in the context of a web page; this differs from scripts which are loaded by the page itself, including those which are provided in `<script>` elements within the page.

Content scripts can see and manipulate the page's DOM, just like normal scripts loaded by the page.

Unlike normal page scripts, content scripts can:

* Make cross-domain XHR requests.
* Use a small subset of the WebExtension APIs.
* Exchange messages with their background scripts and can in this way indirectly access all the WebExtension APIs.

Content scripts cannot directly access normal page scripts but can exchange messages with them using the standard `window.postMessage()` API.

Usually, when we talk about content scripts, we are referring to JavaScript, but you can inject CSS into web pages using the same mechanism.

See the content scripts article to learn more.

Web accessible resources
------------------------

Web accessible resources are resources—such as images, HTML, CSS, and JavaScript—that you include in the extension and want to make accessible to content scripts and page scripts. Resources which are made web-accessible can be referenced by page scripts and content scripts using a special URI scheme.

For example, if a content script wants to insert some images into web pages, you could include them in the extension and make them web accessible. Then the content script could create and append `img` tags which reference the images via the `src` attribute.

To learn more, see the documentation for the `"web_accessible_resources"` `manifest.json` key.


JavaScript APIs - Mozilla

JavaScript APIs
===============

JavaScript APIs for WebExtensions can be used inside the extension's background scripts and in any other documents bundled with the extension, including browser action or page action popups, sidebars, options pages, or new tab pages. A few of these APIs can also be accessed by an extension's content scripts. (See the list in the content script guide.)

To use the more powerful APIs, you need to request permission in your extension's `manifest.json`.

You can access the APIs using the `browser` namespace:

```js
function logTabs(tabs) {
  console.log(tabs);
}

browser.tabs.query({ currentWindow: true }, logTabs);
```

Many of the APIs are asynchronous, returning a `Promise`:

```js
function logCookie(c) {
  console.log(c);
}

function logError(e) {
  console.error(e);
}

let setCookie = browser.cookies.set({ url: "https://developer.mozilla.org/" });
setCookie.then(logCookie, logError);
```

Browser API differences
-----------------------

Note that this is different from Google Chrome's extension system, which uses the `chrome` namespace instead of `browser`, and which uses callbacks instead of promises for asynchronous functions. As a porting aid, the Firefox implementation of WebExtensions APIs supports `chrome` and callbacks as well as `browser` and promises. Mozilla has also written a polyfill which enables code that uses `browser` and promises to work unchanged in Chrome: https://github.com/mozilla/webextension-polyfill.

Firefox also implements these APIs under the `chrome` namespace using callbacks. This allows code written for Chrome to run largely unchanged in Firefox for the APIs documented here.

Microsoft Edge uses the `browser` namespace, but doesn't yet support promise-based asynchronous APIs. In Edge, for the time being, asynchronous APIs must use callbacks.

Not all browsers support all the APIs: for the details, see Browser support for JavaScript APIs and Chrome incompatibilities.

Examples
--------

Throughout the JavaScript API listings, short code examples illustrate how the API is used. You can experiment with most of these examples using the console in the Toolbox. However, you need Toolbox running in the context of a web extension. To do this, open `about:debugging` then **This Firefox**, click **Inspect** against any installed or temporary extension, and open **Console**. You can then paste and run the example code in the console.

For example, here is the first code example on this page running in the Toolbox console in Firefox Developer Edition:

![Illustration of a snippet of web extension code run from the console in the Toolbox](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/javascript_exercised_in_console.jpg)

JavaScript API listing
----------------------

See below for a complete list of JavaScript APIs:

actionAdds a button to the browser's toolbar.

alarmsSchedule code to run at a specific time in the future. This is like `setTimeout()` and `setInterval()`, except that those functions don't work with background pages that are loaded on demand.

bookmarksThe WebExtensions `bookmarks` API lets an extension interact with and manipulate the browser's bookmarking system. You can use it to bookmark pages, retrieve existing bookmarks, and edit, remove, and organize bookmarks.

browserActionAdds a button to the browser's toolbar.

browserSettingsEnables an extension to modify certain global browser settings. Each property of this API is a `types.BrowserSetting` object, providing the ability to modify a particular setting.

browsingDataEnables extensions to clear the data that is accumulated while the user is browsing.

captivePortalDetermine the captive portal state of the user's connection. A captive portal is a web page displayed when a user first connects to a Wi-Fi network. The user provides information or acts on the captive portal web page to gain broader access to network resources, such as accepting terms and conditions or making a payment.

clipboardThe WebExtension `clipboard` API (which is different from the standard Clipboard API) enables an extension to copy items to the system clipboard. Currently the WebExtension `clipboard` API only supports copying images, but it's intended to support copying text and HTML in the future.

commandsListen for the user executing commands that you have registered using the `commands` manifest.json key.

contentScriptsUse this API to register content scripts. Registering a content script instructs the browser to insert the given content scripts into pages that match the given URL patterns.

contextualIdentitiesWork with contextual identities: list, create, remove, and update contextual identities.

cookiesEnables extensions to get and set cookies, and be notified when they change.

declarativeNetRequestThis API enables extensions to specify conditions and actions that describe how network requests should be handled. These declarative rules enable the browser to evaluate and modify network requests without notifying extensions about individual network requests.

devtoolsEnables extensions to interact with the browser's Developer Tools. You use this API to create Developer Tools pages, interact with the window that is being inspected, inspect the page network usage.

dnsEnables an extension to resolve domain names.

domAccess special extension only DOM features.

downloadsEnables extensions to interact with the browser's download manager. You can use this API module to download files, cancel, pause, resume downloads, and show downloaded files in the file manager.

eventsCommon types used by APIs that dispatch events.

extensionUtilities related to your extension. Get URLs to resources packages with your extension. Get the `Window` object for your extension's pages. Get the values for various settings.

extensionTypesSome common types used in other WebExtension APIs.

findFinds text in a web page, and highlights matches.

historyUse the `history` API to interact with the browser history.

i18nFunctions to internationalize your extension. You can use these APIs to get localized strings from locale files packaged with your extension, find out the browser's current language, and find out the value of its Accept-Language header.

identityUse the identity API to get an OAuth2 authorization code or access token, which an extension can then use to access user data from a service that supports OAuth2 access (such as Google or Facebook).

idleFind out when the user's system is idle, locked, or active.

managementGet information about installed add-ons.

menusAdd items to the browser's menu system.

notificationsDisplay notifications to the user, using the underlying operating system's notification mechanism. Because this API uses the operating system's notification mechanism, the details of how notifications appear and behave may differ according to the operating system and the user's settings.

omniboxEnables extensions to implement customized behavior when the user types into the browser's address bar.

pageActionThe API to control address bar button.

permissionsEnables extensions to request extra permissions at runtime, after they have been installed.

pkcs11The `pkcs11` API enables an extension to enumerate PKCS #11 security modules and to make them accessible to the browser as sources of keys and certificates.

privacyAccess and modify various privacy-related browser settings.

proxyUse the proxy API to proxy web requests. You can use the `proxy.onRequest` event listener to intercept web requests, and return an object that describes whether and how to proxy them.

runtimeThis module provides information about your extension and the environment it's running in.

scriptingInserts JavaScript and CSS into websites. This API offers two approaches to inserting content:

searchUse the search API to retrieve the installed search engines and execute searches.

sessionsUse the sessions API to list, and restore, tabs and windows that have been closed while the browser has been running.

sidebarActionGets and sets properties of an extension's sidebar.

storageEnables extensions to store and retrieve data, and listen for changes to stored items.

tabsInteract with the browser's tab system.

themeEnables browser extensions to get details of the browser's theme and update the theme.

topSitesUse the topSites API to get an array containing pages that the user has visited frequently.

typesDefines the `BrowserSetting` type, which is used to represent a browser setting.

userScriptsUse this API to register user scripts, third-party scripts designed to manipulate webpages or provide new features. Registering a user script instructs the browser to attach the script to pages that match the URL patterns specified during registration.

webNavigationAdd event listeners for the various stages of a navigation. A navigation consists of a frame in the browser transitioning from one URL to another, usually (but not always) in response to a user action like clicking a link or entering a URL in the location bar.

webRequestAdd event listeners for the various stages of making an HTTP request, which includes websocket requests on `ws://` and `wss://`. The event listener receives detailed information about the request and can modify or cancel the request.

windowsInteract with browser windows. You can use this API to get information about open windows and to open, modify, and close windows. You can also listen for window open, close, and activate events.


Build a cross-browser extension - Mozilla

Build a cross-browser extension
===============================

The introduction of the browser extensions API created a uniform landscape for the development of browser extensions. However, there are differences in the API implementations and the scope of coverage among the browsers that use the extensions API (the major ones being Chrome, Edge, Firefox, Opera, and Safari).

Maximizing the reach of your browser extension means developing it for at least two browsers, possibly more. This article looks at the main challenges faced when creating a cross-browser extension and suggests how to address these challenges.

**Note:** The main browsers have adopted Manifest V3. This manifest version provides better compatibility between the browser extension environments, such as promises for handling asynchronous events. In addition to the information in this guide, refer to the Manifest V3 migration guides for Firefox and Chrome.

Cross-platform extension coding hurdles
---------------------------------------

You need to address the following areas when tackling a cross-platform extension:

* API namespace
* API asynchronous event handling
* API function coverage
* Content script execution contexts
* Background page versus extension service worker (in Manifest V3)
* Manifest keys
* Extension packaging
* Extension publishing
### API namespace

There are two API namespaces in use among the main browsers:

* `browser.*`, the proposed standard for the extensions API used by Firefox and Safari.
* `chrome.*` used by Chrome, Opera, and Edge.

Firefox also supports the `chrome.*` namespace for APIs that are compatible with Chrome, primarily to assist with porting. However, using the `browser.*` namespace is preferred. In addition to being the proposed standard, `browser.*` uses promises—a modern and convenient mechanism for handling asynchronous events.

Only in the most trivial extensions is namespace likely to be the only cross-platform issue to be addressed. Therefore, it's rarely, if ever, helpful to address this issue alone. The best approach is to address this with asynchronous event handling.

### API asynchronous event handling

With the introduction of Manifest V3, all the main browsers adopted the standard of returning *Promises* from asynchronous methods. Firefox and Safari have full support for Promises on all asynchronous APIs. Starting from Chrome 121, all asynchronous extension APIs support promises unless documented otherwise. The `devtools` API is the only API namespace without Promise support (Chromium bug 1510416).

In Manifest V2, Firefox and Safari support Promises for asynchronous methods. At the same time, Chrome methods invoke *callbacks*. For compatibility, all the main browsers support callbacks across all manifest versions. See Callbacks and Promises for details.

Some handlers of extension API events are expected to respond asynchronously through a `Promise` or callback function. For example, a handler of the `runtime.onMessage` event can send an asynchronous response using a `Promise` or using a callback. A `Promise` as the return value from an event handler is supported in Firefox and Safari, but not yet in Chrome.

Firefox also supports callbacks for the APIs that support the `chrome.*` namespace. However, using promises is recommended. Promises greatly simplifies asynchronous event handling, particularly where you need to chain events together. This means using a polyfill or similar so your extension uses the `browser.*` namespace in Firefox and Safari and `chrome.*` in Chrome, Opera, and Edge.

**Note:** If you're unfamiliar with the differences between these two methods, look at Getting to know asynchronous JavaScript: Callbacks, Promises and Async/Await or the MDN Using promises page.

#### The WebExtension browser API Polyfill

So, how do you take advantage of promises easily? The solution is to code for Firefox using promises and use the WebExtension browser API Polyfill to address Chrome, Opera, and Edge.

This polyfill addresses the API namespace and asynchronous event handling across Firefox, Chrome, Opera, and Edge.

To use the polyfill, install it into your development environment using npm or download it directly from GitHub releases.

Then, reference `browser-polyfill.js` in:

* `manifest.json` to make it available to background and content scripts.
* HTML documents, such as `browserAction` popups or tab pages.
* The `executeScript` call in dynamically-injected content scripts loaded by `tabs.executeScript`, where it hasn't been loaded using a `content_scripts` declaration in `manifest.json`.

So, for example, this `manifest.json` code makes the polyfill available to background scripts:

```json
{
  // …
  "background": {
    "scripts": ["browser-polyfill.js", "background.js"]
  }
}
```

Your goal is to ensure that the polyfill executes in your extension before any other scripts that expect the `browser.*` API namespace execute.

**Note:** For more details and information on using the polyfill with a module bundler, see the project's readme on GitHub.

There are other polyfill options. However, at the time of writing, none of the other options provide the coverage of the WebExtension browser API Polyfill. So, where you haven't targeted Firefox as your first choice, your options are to accept the limitations of alternative polyfills, port to Firefox and add cross-browser support, or develop your own polyfill.

### API function coverage

The differences in the API functions offered in each of the main browsers fall into three broad categories:

1. **Lack of support for an entire function.**
 For example, at the time of writing, Edge didn't support the `browserSettings` function.
2. **Variations in the support for features within a function.**
 For example, at the time of writing, Firefox doesn't support the notification function method `notifications.onButtonClicked`, while Firefox is the only browser that supports `notifications.onShown`.
3. **Proprietary functions, supporting browser-specific features.**
 For example, at the time of writing, containers was a Firefox-specific feature supported by the `contextualIdentities` function.

Details about the support for the extension APIs among the main browsers and Firefox for Android and Safari on iOS can be found on the Mozilla Developer Network Browser support for JavaScript APIs page. Browser compatibility information is also included with each function and its methods, types, and events in the Mozilla Developer Network JavaScript APIs reference pages.

#### Handling API differences

A simple approach to addressing API differences is to limit the functions used in your extension to functions that offer the same functionality across your range of targeted browsers. In practice, this approach is likely to be too restrictive for most extensions.

Instead, where there are differences among the APIs, you should either offer alternative implementations or fallback functionality. (Remember: you may also need to do this to allow for differences in API support between versions of the *same* browser.)

Using runtime checks on the availability of a function's features is the recommended approach to implementing alternative or fallback functionality. The benefit of performing a runtime check is that you don't need to update and redistribute the extension to take advantage of a function when it becomes available.

The following code enables you to perform a runtime check:

```js
if (typeof fn === "function") {
  // safe to use the function
}
```

### Content script execution contexts

Content scripts can access and modify the page's DOM, just as page scripts can. They can also see any changes made to the DOM by page scripts. However, content scripts get a "clean" view of the DOM.

Firefox and Chrome use fundamentally different approaches to handle this behavior: in Firefox it's called Xray vision, while Chrome uses isolated worlds. For more details, see Content script environment section of the Content scripts concept article.

However, Firefox provides some APIs that enable content scripts to access JavaScript objects created by page scripts and to expose their JavaScript objects to page scripts. See Sharing objects with page scripts for details.

There are also differences between the Content Security Policy (CSP) for content scripts.

### Background page and extension service worker

As part of its implementation of Manifest V3, Chrome replaced background pages with extension service workers. Firefox retains the use of background pages, while Safari supports background pages and service workers.

For more information, see the browser support section on the `"background"` manifest key page. This includes a simple example of how to implement a cross-browser script.

### Manifest keys

The differences in the `manifest.json` file keys supported by the main browsers fall broadly into three categories:

1. **Extension information attributes.**
 For example, at the time of writing, Firefox and Opera include the `developer` key for details about the developer of the extension.
2. **Extension features.**
 For example, at the time of writing, Chrome did not support the `browser_specific_settings` key.
3. **Key optionality.**
 At the time of writing, generally, only `"manifest_version"`, `"version"`, and `"name"` are mandatory keys.

Browser compatibility information is included with each key in the Mozilla Developer Network `manifest.json` key reference pages.

As `manifest.json` files tend to change little—except for release numbers, which may differ between the various browsers—creating and editing a static version for each browser is usually the simplest approach.

### Extension packaging

Packaging an extension for distribution through the browser extension stores is relatively straightforward. Firefox, Chrome, Edge, and Opera all use a simple zip format that requires the `manifest.json` file to be at the root of the zip package. Safari requires extensions to be packaged in a similar way to apps.

For details on packaging, refer to the guidance on the respective extension's developer portals.

### Extension publishing

Each of the major browsers maintains browser extension stores. Each store also reviews your extension to check for security vulnerabilities.

As a consequence, you need to approach adding and updating your extension for each store separately. In some cases, you can upload your extension using a utility.

This table summarizes the approach and features of each store:

| Browser | Registration fee | Upload utility | Pre-publication review process | Account two-factor authentication |
| --- | --- | --- | --- | --- |
| Chrome | Yes | Yes | Automatic, less than an hour | Yes |
| Edge | No | No | No SLA provided | Yes |
| Firefox | No | web-ext | Automatic, a few seconds.

 A manual review of the extension takes place after publication, which
 may result in the extension being suspended where issues that need
 fixing are found.
  | Yes |
| Opera | No | No | Manual, no SLA provided | No |
| Safari | Yes | No | Yes with, according to Apple, on average, 50% of apps reviewed in 24 hours and over 90% reviewed in 48 hours. | Yes |

### Other considerations

#### Version numbering

The Firefox, Chrome, and Edge stores require that each uploaded version has a different version number. This means you cannot revert to an earlier version number if you come across issues in a release.

Conclusion
----------

When approaching a cross-platform extension development, the differences between extension API implementations can be addressed by targeting Firefox and using the WebExtension browser API Polyfill.

The bulk of your cross-platform work is likely to focus on handling variations among the API features supported by the main browsers. You may also need to account for differences between the content script and background script implementations. Creating your `manifest.json` files should be relatively straightforward and something you can do manually. You then need to account for the variations in the processes for submitting to each extension store.

Following the advice in this article, you should be able to create an extension that works well on all of the four main browsers, enabling you to deliver your extension features to more people.


Background scripts - Mozilla

Background scripts
==================

Background scripts or a background page enable you to monitor and react to events in the browser, such as navigating to a new page, removing a bookmark, or closing a tab.

Background scripts or a page are:

* Persistent – loaded when the extension starts and unloaded when the extension is disabled or uninstalled.
* Non-persistent (which are also known as event pages) – loaded only when needed to respond to an event and unloaded when they become idle. However, a background page does not unload until all visible views and message ports are closed. Opening a view does not cause the background page to load but does prevent it from closing.

**Note:** In Firefox, if the extension process crashes:

* persistent background scripts running at the time of the crash are reloaded automatically.
* non-persistent background scripts (also known as "Event Pages") running at the time of the crash are not reloaded. However, they are restarted automatically when Firefox calls one of their WebExtensions API events listeners.
* extension pages loaded in tabs at the time of the crash are not automatically restored. A warning message in each tab informs the user the page has crashed and enables the user to close or restore the tab.

 ![Browser window displaying the user message indicating that a page has crashed with the options to close or restart the tab](/en-US/docs/Mozilla/Add-ons/WebExtensions/Background_scripts/your-tab-crashed-screenshot.png)
 You can test this condition by opening a new tab and navigating to `about:crashextensions`, which silently triggers a crash of the extension process.

In Manifest V2, background scripts or a page can be persistent or non-persistent. Non-persistent background scripts are recommended as they reduce the resource cost of your extension. In Manifest V3, only non-persistent background scripts or a page are supported.

If you have persistent background scripts or a page in Manifest V2 and want to prepare your extension for migration to Manifest V3, Convert to non-persistent provides advice on transitioning the scripts or page to the non-persistent model.

Background script environment
-----------------------------

### DOM APIs

Background scripts run in the context of a special page called a background page. This gives them a `window` global, along with all the standard DOM APIs provided by that object.

**Warning:** In Firefox, background pages do not support the use of `alert()`, `confirm()`, or `prompt()`.

### WebExtension APIs

Background scripts can use any WebExtension APIs, as long as their extension has the necessary permissions.

### Cross-origin access

Background scripts can make XHR requests to hosts they have host permissions for.

### Web content

Background scripts do not get direct access to web pages. However, they can load content scripts into web pages and communicate with these content scripts using a message-passing API.

### Content security policy

Background scripts are restricted from certain potentially dangerous operations, such as the use of `eval()`, through a Content Security Policy.

See Content Security Policy for more details.

Implementing background scripts
-------------------------------

This section describes how to implement a non-persistent background script.

### Specify the background scripts

In your extension, you include a background script or scripts, if you need them, using the `"background"` key in `manifest.json`. For Manifest V2 extensions, the `persistent` property must be `false` to create a non-persistent script. It can be omitted for Manifest V3 extensions or must be set to `false`, as script are always non-persistent in Manifest V3. Including `"type": "module"` loads the background scripts as ES modules.

```json
"background": {
  "scripts": ["background-script.js"],
  "persistent": false,
  "type": "module"
}
```

These scripts execute in the extension's background page, so they run in the same context, like scripts loaded into a web page.

However, if you need certain content in the background page, you can specify one. You then specify your script from the page rather than using the `"scripts"` property. Before the introduction of the `"type"` property to the `"background"` key, this was the only option to include ES modules. You specify a background page like this:

* manifest.json

```json
"background": {
  "page": "background-page.html",
  "persistent": false
}
```

* background-page.html

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <script type="module" src="background-script.js"></script>
  </head>
</html>
```

You cannot specify background scripts and a background page.

### Initialize the extension

Listen to `runtime.onInstalled` to initialize an extension on installation. Use this event to set a state or for one-time initialization.

For extensions with event pages, this is where stateful APIs, such as a context menu created using `menus.create`, should be used. This is because stateful APIs don't need to be run each time the event page reloads; they only need to run when the extension is installed.

```js
browser.runtime.onInstalled.addListener(() => {
  browser.contextMenus.create({
    id: "sampleContextMenu",
    title: "Sample Context Menu",
    contexts: ["selection"],
  });
});
```

### Add listeners

Structure background scripts around events the extension depends on. Defining relevant events enables background scripts to lie dormant until those events are fired and prevents the extension from missing essential triggers.

Listeners must be registered synchronously from the start of the page.

```js
browser.runtime.onInstalled.addListener(() => {
  browser.contextMenus.create({
    id: "sampleContextMenu",
    title: "Sample Context Menu",
    contexts: ["selection"],
  });
});

// This will run when a bookmark is created.
browser.bookmarks.onCreated.addListener(() => {
  // do something
});
```

Do not register listeners asynchronously, as they will not be properly triggered. So, rather than:

```js
window.onload = () => {
  // WARNING! This event is not persisted, and will not restart the event page.
  browser.bookmarks.onCreated.addListener(() => {
    // do something
  });
};
```

Do this:

```js
browser.tabs.onUpdated.addListener(() => {
  // This event is run in the top level scope of the event page, and will persist, allowing
  // it to restart the event page if necessary.
});
```

Extensions can remove listeners from their background scripts by calling `removeListener`, such as with `runtime.onMessage` `removeListener`. If all listeners for an event are removed, the browser no longer loads the extension's background script for that event.

```js
browser.runtime.onMessage.addListener(
  function messageListener(message, sender, sendResponse) {
    browser.runtime.onMessage.removeListener(messageListener);
  },
);
```

### Filter events

Use APIs that support event filters to restrict listeners to the cases the extension cares about. If an extension is listening for `tabs.onUpdated`, use the `webNavigation.onCompleted` event with filters instead, as the tabs API does not support filters.

```js
browser.webNavigation.onCompleted.addListener(
  () => {
    console.log("This is my favorite website!");
  },
  { url: [{ urlMatches: "https://www.mozilla.org/" }] },
);
```

### React to listeners

Listeners exist to trigger functionality once an event has fired. To react to an event, structure the desired reaction inside the listener event.

When responding to events in the context of a specific tab or frame, use the `tabId` and `frameId` from the event details instead of relying on the "current tab". Specifying the target ensures your extension does not invoke an extension API on the wrong target when the "current tab" changes while waking the event page.

For example, `runtime.onMessage` can respond to `runtime.sendMessage` calls as follows:

```js
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.data === "setAlarm") {
    browser.alarms.create({ delayInMinutes: 5 });
  } else if (message.data === "runLogic") {
    browser.scripting.executeScript({
      target: {
        tabId: sender.tab.id,
        frameIds: [sender.frameId],
      },
      files: ["logic.js"],
    });
  } else if (message.data === "changeColor") {
    browser.scripting.executeScript({
      target: {
        tabId: sender.tab.id,
        frameIds: [sender.frameId],
      },
      func: () => {
        document.body.style.backgroundColor = "orange";
      },
    });
  }
});
```

### Unload background scripts

Data should be persisted periodically to not lose important information if an extension crashes without receiving `runtime.onSuspend`. Use the storage API to assist with this.

```js
// Or storage.session if the variable does not need to persist pass browser shutdown.
browser.storage.local.set({ variable: variableInformation });
```

Message ports cannot prevent an event page from shutting down. If an extension uses message passing, the ports are closed when the event page idles. Listening to the `runtime.Port` `onDisconnect` lets you discover when open ports are closing, however the listener is under the same time constraints as `runtime.onSuspend`.

```js
browser.runtime.onConnect.addListener((port) => {
  port.onMessage.addListener((message) => {
    if (message === "hello") {
      let response = { greeting: "welcome!" };
      port.postMessage(response);
    } else if (message === "goodbye") {
      console.log("Disconnecting port from this end");
      port.disconnect();
    }
  });
  port.onDisconnect.addListener(() => {
    console.log("Port was disconnected from the other end");
  });
});
```

Background scripts unload after a few seconds of inactivity. However, if during the suspension of a background script another event wakes the background script, `runtime.onSuspendCanceled` is called and the background script continues running. If any cleanup is required, listen to `runtime.onSuspend`.

```js
browser.runtime.onSuspend.addListener(() => {
  console.log("Unloading.");
  browser.browserAction.setBadgeText({ text: "" });
});
```

However, persisting data should be preferred rather than relying on `runtime.onSuspend`. It doesn't allow for as much cleanup as may be needed and does not help in case of a crash.

Convert to non-persistent
-------------------------

If you've a persistent background script, this section provides instructions on converting it to the non-persistent model.

### Update your manifest.json file

In your extension's `manifest.json` file, change the persistent property of `"background"` key to `false` for your script or page.

```json
"background": {
  …,
  "persistent": false
}
```

### Move event listeners

Listeners must be at the top-level to activate the background script if an event is triggered. Registered listeners may need to be restructured to the synchronous pattern and moved to the top-level.

```js
browser.runtime.onStartup.addListener(() => {
  // run startup function
});
```

### Record state changes

Scripts now open and close as needed. So, do not rely on global variables.

```js
var count = 101;
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message === "count") {
    ++count;
    sendResponse(count);
  }
});
```

Instead, use the storage API to set and return states and values:

* Use `storage.session` for in-memory storage that is cleared when the extension or browser shuts down. By default, `storage.session` is only available to extension contexts and not to content scripts.
* Use `storage.local` for a larger storage area that persists across browser and extension restarts.

```js
browser.runtime.onMessage.addListener(async (message, sender) => {
  if (message === "count") {
    let items = await browser.storage.session.get({ myStoredCount: 101 });
    let count = items.myStoredCount;
    ++count;
    await browser.storage.session.set({ myStoredCount: count });
    return count;
  }
});
```

 The preceding example sends an asynchronous response using a promise, which is not supported in Chrome until Chrome bug 1185241 is resolved.
 A cross-browser alternative is to return true and use `sendResponse`.

```js
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message === "count") {
    browser.storage.session.get({ myStoredCount: 101 }).then(async (items) => {
      let count = items.myStoredCount;
      ++count;
      await browser.storage.session.set({ myStoredCount: count });
      sendResponse(count);
    });
    return true;
  }
});
```

### Change timers into alarms

DOM-based timers, such as `setTimeout()`, do not remain active after an event page has idled. Instead, use the `alarms` API if you need a timer to wake an event page.

```js
browser.alarms.create({ delayInMinutes: 3.0 });
```

Then add a listener.

```js
browser.alarms.onAlarm.addListener(() => {
  alert("Hello, world!");
});
```

### Update calls for background script functions

 Extensions commonly host their primary functionality in the background script. Some extensions access functions and variables defined in the background page through the `window` returned by `extension.getBackgroundPage`.
 The method returns `null` when:

* extension pages are isolated, such as extension pages in Private Browsing mode or container tabs.
* the background page is not running. This is uncommon with persistent background pages but very likely when using an Event Page, as an Event Page can be suspended.

**Note:** The recommended way to invoke functionality in the background script is to communicate with it through `runtime.sendMessage()` or `runtime.connect()`.
 The `getBackgroundPage()` methods discussed in this section cannot be used in a cross-browser extension, because Manifest Version 3 extensions in Chrome cannot use background or event pages.

 If your extension requires a reference to the `window` of the background page, use `runtime.getBackgroundPage` to ensure the event page is running.
 If the call is optional (that is, only needed if the event page is alive) then use `extension.getBackgroundPage`.

```js
document.getElementById("target").addEventListener("click", async () => {
  let backgroundPage = browser.extension.getBackgroundPage();
  // Warning: backgroundPage is likely null.
  backgroundPage.backgroundFunction();
});
```

```js
document.getElementById("target").addEventListener("click", async () => {
  // runtime.getBackgroundPage() wakes up the event page if it was not running.
  let backgroundPage = await browser.runtime.getBackgroundPage();
  backgroundPage.backgroundFunction();
});
```


protocol_handlers - Mozilla

protocol\_handlers
==================

|  |  |
| --- | --- |
| Type | `Array` |
| Mandatory | No |
| Manifest version | 2 or higher |
| Example |
```json
"protocol\_handlers": [
  {
    "protocol": "ircs",
    "name": "IRC Mozilla Extension",
    "uriTemplate": "https://irccloud.mozilla.com/#!/%s"
  }
]
```
 |

Use this key to register one or more web-based protocol handlers.

A protocol handler is an application that knows how to handle particular types of links: for example, a mail client is a protocol handler for "mailto:" links. When the user clicks a "mailto:" link, the browser opens the application selected as the handler for the "mailto:" protocol (or offers them a choice of handlers, depending on their settings).

**Note:** By default, extensions do not run in private browsing windows. As protocol handlers are part of the extension, they don't work in private browsing windows by default. Whether an extension can access private browsing windows and its protocol handlers become active is under user control. For details, see Extensions in Private Browsing. Your extension can check whether it can access private browsing windows using `extension.isAllowedIncognitoAccess`.

With this key, you can register a website as a handler for a particular protocol. The syntax and semantics of this key is very much like the `Navigator.registerProtocolHandler()` function, except that with `registerProtocolHandler()` a website can only register itself as a handler.

Each protocol handler has three properties, all mandatory:

`protocol`

A string defining the protocol. This must be either:

* one of the following: "bitcoin", "dat", "dweb", "ftp", "geo", "gopher", "im", "ipfs", "ipns", "irc", "ircs", "magnet", "mailto", "matrix", "mms", "news", "nntp", "sip", "sms", "smsto", "ssb", "ssh", "tel", "urn", "webcal", "wtai", "xmpp".
* a string consisting of a custom name prefixed with "web+" or "ext+". For example: "web+foo" or "ext+foo". The custom name must consist only of lower-case ASCII characters. It's recommended that extensions use the "ext+" form.

`name`

A string representing the name of the protocol handler. This will be displayed to the user when they are being asked if they want this handler to open the link.

`uriTemplate`

A string representing the URL of the handler. This string must include "%s" as a placeholder: this will be replaced with the escaped URL of the document to be handled. This URL might be a true URL, or it could be a phone number, email address, or so forth. This is a localizable property.

Example
-------

```json
"protocol\_handlers": [
  {
    "protocol": "magnet",
    "name": "Magnet Extension",
    "uriTemplate": "https://example.com/#!/%s"
  }
]
```

If the protocol is not in the allowed list then it has to start with 'ext+'

```json
"protocol\_handlers": [
  {
    "protocol": "ext+foo",
    "name": "Foo Extension",
    "uriTemplate": "https://example.com/#!/%s"
  }
]
```

Handlers can also be extension pages.

```json
"protocol\_handlers": [
  {
    "protocol": "magnet",
    "name": "Magnet Extension",
    "uriTemplate": "/example.xhtml#!/%s"
  }
]
```

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


options_page - Mozilla

options\_page
=============

|  |  |
| --- | --- |
| Type | `String` |
| Mandatory | No |
| Manifest version | 2 or higher |
| Example |
```json
"options\_page": "options/options.html"
```
 |

**Deprecated:** This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any time.

**Warning:** This manifest key has been deprecated. Use `options_ui` instead.

Use the `options_page` key to define an options page for your extension.

The options page contains settings for the extension. The user can access it from the browser's add-ons manager, and you can open it from within your extension using `runtime.openOptionsPage()`.

Unlike options pages specified using the newer `options_ui` key, options pages specified using the deprecated `options_page` key don't receive browser styles and always open in a normal browser tab.

Example
-------

```json
"options\_page": "options/options.html"
```

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `options_ui`
* Options pages


content_security_policy - Mozilla

content\_security\_policy
=========================

|  |  |
| --- | --- |
| Type | `String` |
| Mandatory | No |
| Manifest version | 2 or higher |
| Example | Manifest V2:

```json
"content\_security\_policy": "default-src 'self'"
```
Manifest V3:

```json
"content\_security\_policy": {
  "extension\_pages": "default-src 'self'"
}
```
 |

Extensions have a content security policy (CSP) applied to them by default. The default policy restricts the sources from which extensions can load code (such as <script> resources) and disallows potentially unsafe practices such as the use of `eval()`. See Default content security policy to learn more about the implications of this.

You can use the `"content_security_policy"` manifest key to loosen or tighten the default policy. This key is specified in the same way as the Content-Security-Policy HTTP header. See Using Content Security Policy for a general description of CSP syntax.

For example, you can use this key to:

* Restrict permitted sources for other types of content, such as images and stylesheets, using the appropriate policy directive.
* Allow the extension to take advantage of WebAssembly by including the `'wasm-unsafe-eval'` source in the `script-src` directive.
* Loosen the default `script-src` policies (Manifest V2 only):
    + Allow the extension to load scripts from outside its package by supplying their URL in the `script-src` directive.
    + Allow the extension to execute inline scripts by supplying the hash of the script in the `script-src` directive.
    + Allow the extension to use `eval()` and similar features by including `'unsafe-eval'` in the `script-src` directive.

There are restrictions on the policy you can specify with this manifest key:

* The `script-src` directive must include at least the `'self'` keyword and may only contain secure sources. The set of permitted secure sources differs between Manifest V2 and Manifest V3.
* The policy may include `default-src` alone (without `script-src`) if its sources meet the requirement for the `script-src` directive.
* The `object-src` keyword may be required, see object-src directive for details.
* Directives that reference code – `script-src`, `script-src-elem`, `worker-src`, and `default-src` (if used as a fallback) – share the same secure source requirement. There are no restrictions on CSP directives that cover non-script content, such as `img-src`.

 In Manifest V3, all CSP sources that refer to external or non-static content are forbidden. The only permitted values are `'none'`, `'self'`, and `'wasm-unsafe-eval'`.
 In Manifest V2, a source for a script directive is considered secure if it meets these criteria:

* Wildcard hosts are not permitted, such as `"script-src 'self' *"`.
* Remote sources must use `https:` schemes.
* Remote sources must not use wildcards for any domains in the public suffix list (so "\*.co.uk" and "\*.blogspot.com" are not allowed, although "\*.foo.blogspot.com" is permitted).
* All sources must specify a host.
* The only permitted schemes for sources are `blob:`, `filesystem:`, `moz-extension:`, `https:`, and `wss:`.
* The only permitted keywords are: `'none'`, `'self'`, `'unsafe-eval'`, and `'wasm-unsafe-eval'`.
object-src directive
--------------------

The ``object-src`` directive may be required in some browsers that support obsolete plugins and should be set to a secure source such as `'none'` if needed. This may be necessary for browsers up until 2022.

* In Firefox, `"object-src"` it optional from Firefox 106. In earlier versions, if `"object-src"` isn't specified, `"content_security_policy"` is ignored and the default CSP used.
* In Chrome, `"object-src"` is required. If it's missing or deemed insecure, the default (`"object-src 'self'"`) is used and a warning message logged.
* In Safari, there is no requirement for `"object-src"`.

See W3C WebExtensions Community Group issue 204, Remove object-src from the CSP, for more information.

Manifest V2 syntax
------------------

In Manifest V2, there is one content security policy specified against the key like this:

```json
"content\_security\_policy": "default-src 'self'"
```

Manifest V3 syntax
------------------

In Manifest V3, the `content_security_policy` key is an object that may have any of these properties, all optional:

| Name | Type | Description |
| --- | --- | --- |
| `extension_pages` | `String` | The content security policy used for extension pages. The `script-src` and `worker-src` directives may only have these values:
 * `'self'`
* `'none'`
* `'wasm-unsafe-eval'`
 |
| `sandbox` | `String` | The content security policy used for sandboxed extension pages. |

Examples
--------

### Valid examples

**Note:** Valid examples demonstrate the correct use of keys in CSP.
 However, extensions with 'unsafe-eval', remote script, blob, or remote sources in their CSP are not allowed for Firefox extensions per the add-on policies and due to significant security issues.

**Note:** Some examples include the ``object-src`` directive, which provides backward compatibility for older browser versions. See object-src directive for more details.

Require that all types of content should be packaged with the extension:

* Manifest V2

```json
"content\_security\_policy": "default-src 'self'"
```

* Manifest V3

```json
"content\_security\_policy": {
  "extension\_pages": "default-src 'self'"
}
```

Allow remote scripts from "https://example.com":

* Manifest V2

```json
"content\_security\_policy": "script-src 'self' https://example.com; object-src 'self'"
```

* Manifest V3 does not allow remote URLs in `script-src` of `extension_pages`.

Allow remote scripts from any subdomain of "jquery.com":

* Manifest V2

```json
"content\_security\_policy": "script-src 'self' https://\*.jquery.com; object-src 'self'"
```

* Manifest V3 does not allow remote URLs in `script-src` of `extension_pages`.

Allow `eval()` and friends:

* Manifest V2

```json
"content\_security\_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';"
```

* Manifest V3 does not allow `'unsafe-eval'` in `script-src`.

Allow the inline script: `"<script>alert('Hello, world.');</script>"`:

* Manifest V2

```json
"content\_security\_policy": "script-src 'self' 'sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng='; object-src 'self'"
```

* Manifest V3 does not allow CSP hashes in `script-src` of `extension_pages`.

Keep the rest of the policy, but also require that images should be packaged with the extension:

* Manifest V2

```json
"content\_security\_policy": "script-src 'self'; object-src 'self'; img-src 'self'"
```

* Manifest V3

```json
"content\_security\_policy": {
  "extension\_pages": "script-src 'self'; img-src 'self'"
}
```

Enable the use of WebAssembly:

* Manifest V2
 For backward compatibility, Manifest V2 extensions in Firefox can use WebAssembly without the use of `'wasm-unsafe-eval'`. However, this behavior isn't guaranteed. See Firefox bug 1770909. Extensions using WebAssembly are therefore encouraged to declare `'wasm-unsafe-eval'` in their CSP. See WebAssembly on the Content Security Policy page for more information.

```json
"content\_security\_policy": "script-src 'self' 'wasm-unsafe-eval'"
```

* Manifest V3

```json
"content\_security\_policy": {
  "extension\_pages": "script-src 'self' 'wasm-unsafe-eval'"
}
```

### Invalid examples

Policy that omits the `"object-src"` directive:

```json
"content\_security\_policy": "script-src 'self' https://\*.jquery.com;"
```

However, this is only invalid in browsers that support obsolete plugins. See object-src directive for more details..

Policy that omits the `"self"` keyword in the `"script-src"` directive:

```json
"content\_security\_policy": "script-src https://\*.jquery.com; object-src 'self'"
```

Scheme for a remote source is not `https`:

```json
"content\_security\_policy": "script-src 'self' http://code.jquery.com; object-src 'self'"
```

Wildcard is used with a generic domain:

```json
"content\_security\_policy": "script-src 'self' https://\*.blogspot.com; object-src 'self'"
```

Source specifies a scheme but no host:

```json
"content\_security\_policy": "script-src 'self' https:; object-src 'self'"
```

Directive includes the unsupported keyword `'unsafe-inline'`:

```json
"content\_security\_policy": "script-src 'self' 'unsafe-inline'; object-src 'self'"
```

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


author - Mozilla

author
======

|  |  |
| --- | --- |
| Type | `String` |
| Mandatory | No |
| Manifest version | 2 or higher |
| Example |
```json
"author": "Walt Whitman"
```
 |

The extension's author, intended for display in the browser's user interface. If the developer key is supplied and it contains the "name" property, it will override the author key. There's no way to specify multiple authors.

This is a localizable property.

Example
-------

```json
"author": "Walt Whitman"
```

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


chrome_url_overrides - Mozilla

chrome\_url\_overrides
======================

|  |  |
| --- | --- |
| Type | `Object` |
| Mandatory | No |
| Manifest version | 2 or higher |
| Example |
```json
  "chrome\_url\_overrides" : {
    "newtab": "my-new-tab.html"
  }
```
 |

Use the `chrome_url_overrides` key to provide a custom replacement for the documents loaded into various special pages usually provided by the browser itself.

Syntax
------

The `chrome_url_overrides` key is an object that may have the following properties:

| Name | Type | Description |
| --- | --- | --- |
| `bookmarks` | `String` | Provide a replacement for the page that shows the bookmarks. |
| `history` | `String` | Provide a replacement for the page that shows the browsing history. |
| `newtab` | `String` |
 Provide a replacement for the document that's shown in the "new tab"
 page. This is the page that's shown when the user has opened a new tab
 but has not loaded any document into it: for example, by using the
 `Ctrl`/`Command`+`T` keyboard shortcut.

 The replacement is given as a URL to an HTML file. The file must be
 bundled with the extension: you can't specify a remote URL here. You
 can specify it relative to the extension's root folder, like:
 "path/to/newtab.html".

 The document can load CSS and JavaScript, just like a normal web page.
 JavaScript running in the page gets access to the same
 privileged "browser.\*" APIs
 as the extension's background script.

 It's very good practice to include a
 <title> for the
 page, or the tab's title will be the "moz-extension://..." URL.

 A common use case is to let the user define a new tab page: to do
 this, provide a custom new tab page that navigates to the page the
 user defined.

 If two or more extensions both define custom new tab pages, then the
 last one to be installed or enabled gets to use its value.

To override the browser's homepage, use "chrome\_settings\_overrides" instead. |

All properties are localizable.

Example
-------

```json
"chrome\_url\_overrides" : {
  "newtab": "my-new-tab.html"
}
```

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


theme_experiment - Mozilla

theme\_experiment
=================

|  |  |
| --- | --- |
| Type | `Object` |
| Mandatory | No |
| Manifest version | 2 or higher |
| Example |
```json
"theme\_experiment": {
  "stylesheet": "style.css",
  "colors": {
    "popup\_affordance": "--arrowpanel-dimmed"
  },
  "images": {
    "theme\_toolbar": "--toolbar-bgimage"
  },
  "properties": {
    "toolbar\_image\_alignment":
    "--toolbar-bgalignment"
  }
}
```
 |

This key enables the definition of experimental `theme` key properties for the Firefox interface. These experiments are a precursor to proposing new theme features for inclusion in Firefox. Experimentation is done by:

* creating a stylesheet that defines mappings between internal CSS selectors for Firefox UI elements and arbitrary CSS variables. The CSS variables are then mapped in the `colors`, `images`, and `properties` objects to new `theme` key properties.
* (without a stylesheet) using `colors`, `images`, and `properties` to map internal Firefox CSS selectors, such as `--arrowpanel-dimmed` to new `theme` key properties. This option limits experimentation to UI components that are associated with an inbuilt CSS variable.

To discover the CSS selectors for Firefox UI elements or internal Firefox CSS variables use the browser toolbox.

**Note:** This key is only available for use in Firefox Developer Edition and Firefox Nightly channels and requires the `extensions.experiments.enabled` preference to be enabled. In Firefox 73 and earlier, the `extensions.legacy.enabled` had to be used instead.

**Warning:** This feature is experimental and could be subject to change.

Syntax
------

The theme\_experiment key is an object that takes the following properties:

| Name | Type | Description |
| --- | --- | --- |
| `stylesheet` | `String` | Optional

 Name of a stylesheet providing mapping of Firefox UI element CSS
 selectors to CSS variables.
  |
| `images` | `Object` | Optional

 Mappings of CSS variables (as defined in Firefox or by the stylesheet
 defined in `stylesheet`) to `images` property
 names for use in the
 `theme`
 key.
  |
| `colors` | `Object` | Optional

 Mappings of CSS variables (as defined in Firefox or by the stylesheet
 defined in `stylesheet`) to `colors` property
 names for use in the
 `theme`
 key.
  |
| `properties` | `Object` | Optional

 Mappings of CSS variables (as defined in Firefox or by the stylesheet
 defined in `stylesheet`) to
 `properties` property names for use in the
 `theme`
 key.
  |

Examples
--------

This example uses a stylesheet named `style.css` to provide the ability to set a color for the browser reload button in the `theme` key.

The stylesheet defines:

```css
#reload-button {
  fill: var(--reload-button-color);
}
```

where `#reload-button` is the Firefox internal CSS selector for the reload button and `--reload-button-color` is an arbitrary name.

In the `manifest.json` file, `--reload-button-color` is then mapped to the name to be used in the `colors` property of `theme`:

```json
"theme\_experiment": {
  "stylesheet": "style.css",
  "colors": {
    "reload\_button": "--reload-button-color"
  }
}
```

The argument `reload_button` is used in the same way as any other `theme` property:

```json
"theme": {
  "colors": {
    "reload\_button": "orange"
  }
}
```

This has the effect of making the reload icon orange.

![Outcome of a theme experiment, showing the reload button colored orange.](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/theme_experiment/theme_experiment.png)

This property can also be used in `browser.theme.update()`. `images` and `properties` work in a similar way to `colors`.

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


sidebar_action - Mozilla

sidebar\_action
===============

|  |  |
| --- | --- |
| Type | `Object` |
| Mandatory | No |
| Manifest version | 2 or higher |
| Example |
```json
"sidebar\_action": {
  "default\_icon": {
    "16": "button/geo-16.png",
    "32": "button/geo-32.png"
  },
  "default\_title": "My sidebar",
  "default\_panel": "sidebar/sidebar.html",
  "open\_at\_install":true
}
```
 |
|  |  |

A sidebar is a pane that is displayed at the left-hand side of the browser window, next to the web page. The browser provides a UI that enables the user to see the currently available sidebars and to select a sidebar to display.

The sidebar\_action key enables you to define the default properties for the sidebar. You can change these properties at runtime using the `sidebarAction` API.

Syntax
------

The `sidebar_action` key is an object that may have any of the properties listed below. The only mandatory property is `default_panel`.

| Name | Type | Description |
| --- | --- | --- |
| `browser\_style`Optional
Deprecated
 in Manifest V3. | `Boolean` | Optional, defaulting to:* `true` in Manifest V2 and prior to Firefox 115 in Manifest V3.
* `false` in Manifest V3 from Firefox 115.

Do not set `browser_style` to true: its not support in Manifest V3 from Firefox 118. See Manifest V3 migration for `browser_style`.

 In Firefox, the stylesheet can be seen at
 chrome://browser/content/extension.css or
 chrome://browser/content/extension-mac.css on macOS. When setting
 dimensions, be aware that this stylesheet sets
 `box-sizing: border-box` (see
 box-sizing).
  |
| `default_icon`Optional | `Object` or `String` |
 Use this to specify one or more icons for the sidebar. The icon is
 shown in the browser's UI for opening and closing sidebars.

Icons are specified as URLs relative to the manifest.json file itself.
You can specify a single icon file by supplying a string here:

```json
"default\_icon": "path/to/geo.svg"
```

 To specify multiple icons in different sizes, specify an object here.
 The name of each property is the icon's height in pixels, and must be
 convertible to an integer. The value is the URL. For example:

```json
    "default\_icon": {
      "16": "path/to/geo-16.png",
      "32": "path/to/geo-32.png"
    }
```

 See
 Choosing icon sizes
 for more guidance on this.

 This property is optional: if it is omitted, the sidebar doesn't get
 an icon.
  |
| `default_panel` | `String` | The path to an HTML file that specifies the sidebar's contents.

 The HTML file may include CSS and JavaScript files using
 `<link>`
 and
 `<script>`
 elements, just like a normal web page.

 Unlike a normal web page, JavaScript running in the panel can access
 all the
 WebExtension APIs
 (subject, of course, to the extension having the appropriate
 permissions).

This property is mandatory.

 This is a
 localizable property.
  |
| `default_title`Optional | `String` |
 Title for the sidebar. This is used in the browser UI for listing and
 opening sidebars, and is displayed at the top of the sidebar when it
 is open.

 This property is optional: if it is omitted, the sidebar's title is
 the extension's
 `name`.

 This is a
 localizable property.
  |
| `open_at_install`Optional | Boolean |
 Optional, defaulting to `true`. Determines whether the
 sidebar should open on install. The default behavior is to open the
 sidebar when installation is completed.
  |

Example
-------

```json
"sidebar\_action": {
  "default\_icon": "sidebar.svg",
  "default\_title": "My sidebar!",
  "default\_panel": "sidebar.html"
}
```

For a simple example of an extension that uses a sidebar, see annotate-page.

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `browser_action`
* `page_action`
* Browser styles


page_action - Mozilla

page\_action
============

|  |  |
| --- | --- |
| Type | `Object` |
| Mandatory | No |
| Manifest version | 2 or higher |
| Example |
```json
"page\_action": {
  "default\_icon": {
    "19": "button/geo-19.png",
    "38": "button/geo-38.png"
  },
  "default\_title": "Whereami?",
  "default\_popup": "popup/geo.html"
}
```
 |

A page action is an icon that your extension adds inside the browser's URL bar.

Your extension may optionally also supply an associated popup whose content is specified using HTML, CSS, and JavaScript.

If you supply a popup, then the popup is opened when the user clicks the icon, and your JavaScript running in the popup can handle the user's interaction with it. If you don't supply a popup, then a click event is dispatched to your extension's background scripts when the user clicks the icon.

You can also create and manipulate page actions programmatically using the `pageAction API`.

Page actions are like browser actions, except that they are associated with particular web pages rather than with the browser as a whole. If an action is only relevant on certain pages, then you should use a page action and display it only on relevant pages. If an action is relevant to all pages or to the browser itself, use a browser action.

While browser actions are displayed by default, page actions are hidden by default. They can be shown for a particular tab by calling `pageAction.show()`, passing in the tab's `id`. You can also change this default behavior using the `show_matches` property.

Syntax
------

The `page_action` key is an object that may have any of three properties, all optional:

| Name | Type | Description |
| --- | --- | --- |
| `browser\_style`Optional
Deprecated
 in Manifest V3. | `Boolean` | Optional. Defaults to `false`.

Do not set `browser_style` to true: its not support in Manifest V3 from Firefox 118. See Manifest V3 migration for `browser_style`.

 In Firefox, the stylesheet can be seen at
 `chrome://browser/content/extension.css` or
 `chrome://browser/content/extension-mac.css` on macOS.

 The
 latest-download
 example extension uses `browser_style` in its popup.
  |
| `default_icon` | `Object` or `String` | Use this to specify an icon for the action.

 It's recommended that you supply two icons here (19×19 pixels and
 38×38 pixels), and specify them in an object with properties named
 `"19"` and `"38"`, like this:

```json
    "default\_icon": {
      "19": "geo-19.png",
      "38": "geo-38.png"
    }
```

 If you do this, then the browser will pick the right size icon for the
 screen's pixel density.

You can just supply a string here:

```json
"default\_icon": "geo.png"
```

 If you do this, then the icon will be scaled to fit the toolbar, and
 may appear blurry.
  |
| `default_popup` | `String` | The path to an HTML file containing the specification of the popup.

 The HTML file may include CSS and JavaScript files using
 `<link>`
 and
 `<script>`
 elements, just like a normal web page. However, don't use
 `<script>`
 with embedded code, because you'll get a Content Violation Policy
 error. Instead,
 `<script>`
 must use the
 `src`
 attribute to load a separate script file.

 Unlike a normal web page, JavaScript running in the popup can access
 all the
 WebExtension APIs
 (subject, of course, to the extension having the appropriate
 permissions).

 This is a
 localizable property.
  |
| `default_title` | `String` |
 Tooltip for the icon, displayed when the user moves their mouse over
 it.

 This is a
 localizable property.
  |
| `hide_matches` | `Array` of `Match Pattern` except
 `<all_urls>` |
 Hide the page action by default for pages whose URLs match any of the
 given
 match patterns.

 Note that page actions are always hidden by default unless
 `show_matches` is given. Therefore, it only makes sense to
 include this property if `show_matches` is also given, and
 will override the patterns in `show_matches`.

For example, consider a value like:

```json
"page\_action": {
  "show\_matches": ["https://\*.mozilla.org/\*"],
  "hide\_matches": ["https://developer.mozilla.org/\*"]
}
```

 This shows the page action by default for all HTTPS URLs under the
 `"mozilla.org"` domain, except for pages under
 `"developer.mozilla.org"`.
  |
| `show_matches` | `Array` of `Match Pattern` |
 Show the page action by default for pages whose URLs match any of the
 given patterns.

See also `hide_matches`. |
| `pinned`
Deprecated
 | `Boolean` | Optional. Defaults to `true`.

 Controls whether or not the page action should appear in the location
 bar by default when the user installs the extension. This property is
 no longer supported since Firefox 89.
  |

Example
-------

```json
"page\_action": {
  "default\_icon": {
    "19": "button/geo-19.png",
    "38": "button/geo-38.png"
  }
}
```

A page action with just an icon, specified in 2 different sizes. The extension's background scripts can receive click events when the user clicks the icon using code like this:

```js
browser.pageAction.onClicked.addListener(handleClick);
```

```json
"page\_action": {
  "default\_icon": {
    "19": "button/geo-19.png",
    "38": "button/geo-38.png"
  },
  "default\_title": "Whereami?",
  "default\_popup": "popup/geo.html"
}
```

A page action with an icon, a title, and a popup. The popup will be shown when the user clicks the icon.

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `browser_action`
* `sidebar_action`
* Browser styles


devtools_page - Mozilla

devtools\_page
==============

|  |  |
| --- | --- |
| Type | `String` |
| Mandatory | No |
| Manifest version | 2 or higher |
| Example |
```json
"devtools\_page": "devtools/my-page.html"
```
 |

Use this key to enable your extension to extend the browser's built-in devtools.

This key is defined as a URL to an HTML file. The HTML file must be bundled with the extension, and the URL is relative to the extension's root.

The use of this manifest key triggers an install-time permission warning about devtools. To avoid an install-time permission warning, mark the feature as optional by listing the `"devtools"` permission in the `optional_permissions` manifest key.

See Extending the developer tools to learn more.

Example
-------

```json
"devtools\_page": "devtools/my-page.html"
```

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


chrome_settings_overrides - Mozilla

chrome\_settings\_overrides
===========================

|  |  |
| --- | --- |
| Type | `Object` |
| Mandatory | No |
| Manifest version | 2 or higher |
| Example |
```json
"chrome\_settings\_overrides" : {
  "homepage": "https://developer.mozilla.org/"
 },
```

 |

Use the `chrome_settings_overrides` key to override the browser's home page and add a new search engine.

Syntax
------

The `chrome_settings_overrides` key is an object that may have the following properties:

| Name | Type | Description |
| --- | --- | --- |
| `homepage` | `String` | Defines the page to be used as the browser's homepage.
The replacement is given as a URL. The URL may:* point to a file bundled with the extension, in which case it is
 given as a URL relative to the manifest.json file
* be a remote URL, such as "https://developer.mozilla.org/".

 If two or more extensions both set this value, then the setting from
 the most recently installed one will take precedence.

To override new tabs, use "chrome\_url\_overrides" instead.

 This is a
 localizable property.
  |
| `search_provider` | `Object` | Defines a search provider to add to the browser.

 The search provider has a name and a primary search URL. Alternative
 URLs may be provided, including URLs for more specialized searches
 like image search. In the URL you supply, use
 "`{searchTerms}`" to interpolate the search term into the
 URL, like:
 `https://www.discogs.com/search/?q={searchTerms}`. You can
 also provide POST parameters to be sent along with the search.

 The search provider will be presented to the user alongside the
 built-in providers. If you include the
 `is_default` property and set it to `true`, the
 new search provider will be the default option. By supplying the
 `keyword` property, you enable the user to select your
 search provider by typing the keyword into the search/address bar
 before the search term.

 This is an object with the properties listed below. All string
 properties are
 localizable.

`name`
String: The search engine's name, displayed to the user.
`search_url`
String: URL used by the search engine. This must be an HTTPS URL.
`is_default Optional`

 Boolean: True if the search engine should be the default choice. On
 Firefox, this is opt-in and the user will only be asked the first
 time the extension is installed. They will not be asked again if a
 search engine is added later.

`alternate_urls Optional`

 Array of String: An array of alternative URLs that can be used
 instead of `search_url`.

`encoding Optional`

 String: Encoding of the search term, specified as a
 standard character encoding name, such as "UTF-8".

`favicon_url Optional`

 String: URL pointing to an icon for the search engine. In Manifest V2,
 this must be an absolute HTTP or HTTPS URL. In Manifest V3, this must
 reference an icon provided in the extension as a path relative to the
 extension's root.

`image_url Optional`
String: URL used for image search.
`image_url_post_params Optional`
String: POST parameters to send to `image_url`.
`instant_url Optional`
String: URL used for instant search.
`instant_url_post_params Optional`
String: POST parameters to send to `instant_url`.
`keyword Optional`
String: Address bar keyword for the search engine.
`prepopulated_id Optional`
The ID of a built-in search engine to use.
`search_url_post_params Optional`
String: POST parameters to send to `search_url`.
`suggest_url Optional`
String: URL used for search suggestions. This must be an HTTPS URL.
`suggest_url_post_params Optional`
String: POST parameters to send to `suggest_url`.
 |

Example
-------

This example shows how to set a search provider.

```json
"chrome\_settings\_overrides": {
  "search\_provider": {
    "name": "Discogs",
    "search\_url": "https://www.discogs.com/search/?q={searchTerms}",
    "keyword": "disc",
    "favicon\_url": "https://www.discogs.com/favicon.ico"
  }
}
```

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


permissions - Mozilla

permissions
===========

|  |  |
| --- | --- |
| Type | `Array` |
| Mandatory | No |
| Manifest version | 2 or higher |
| Example |
```json
"permissions": [
  "webRequest"
]
```
 |

Use the `permissions` key to request special powers for your extension. This key is an array of strings, and each string is a request for a permission.

If you request permissions using this key, then the browser may inform the user at install time that the extension is requesting certain privileges, and ask them to confirm that they are happy to grant these privileges. The browser may also allow the user to inspect an extension's privileges after installation. As the request to grant privileges may impact on users' willingness to install your extension, requesting privileges is worth careful consideration. For example, you want to avoid requesting unnecessary permissions and may want to provide information about why you are requesting permissions in your extension's store description. More information on the issues you should consider is provided in the article Request the right permissions.

For information on how to test and preview permission requests, see Test permission requests on the Extension Workshop site.

The key can contain three kinds of permissions:

* host permissions (Manifest V2 only, host permissions are specified in the `host_permissions` manifest key for Manifest V3 or higher.)
* API permissions
* the `activeTab` permission
Host permissions
----------------

**Note:** When using Manifest V3 or higher, host permissions must be specified in the `host_permissions` manifest key.

Host permissions are specified as match patterns, and each pattern identifies a group of URLs for which the extension is requesting extra privileges. For example, a host permission could be `"*://developer.mozilla.org/*"`.

The extra privileges include:

* XMLHttpRequest and fetch access to those origins without cross-origin restrictions (even for requests made from content scripts)
* the ability to read tab-specific metadata without the "tabs" permission, such as the `url`, `title`, and `favIconUrl` properties of `tabs.Tab` objects
* the ability to inject content scripts and styles programmatically into pages served from those origins.
* the ability to receive events from the `webrequest` API for these hosts
* the ability to access cookies for that host using the `cookies` API, as long as the `"cookies"` API permission is also included.
* bypassing tracking protection for extension pages where a host is specified as a full domain or with wildcards. Content scripts, however, can only bypass tracking protection for hosts specified with a full domain.

In Firefox, from version 56 onwards, extensions automatically get host permissions for their own origin, which is of the form:

```url
moz-extension://60a20a9b-1ad4-af49-9b6c-c64c98c37920/
```

where `60a20a9b-1ad4-af49-9b6c-c64c98c37920` is the extension's internal ID. The extension can get this URL programmatically by calling `extension.getURL()`:

```js
browser.extension.getURL("");
// moz-extension://60a20a9b-1ad4-af49-9b6c-c64c98c37920/
```

API permissions
---------------

API permissions are specified as keywords, and each keyword names a WebExtension API that the extension would like to use.

These permissions are available in Manifest V2 and above unless otherwise noted:

* `activeTab`
* `alarms`
* `background`
* `bookmarks`
* `browserSettings`
* `browsingData`
* `captivePortal`
* `clipboardRead`
* `clipboardWrite`
* `contentSettings`
* `contextMenus`
* `contextualIdentities`
* `cookies`
* `debugger`
* `declarativeNetRequest`
* `declarativeNetRequestFeedback`
* `declarativeNetRequestWithHostAccess`
* `devtools` (This permission is granted implicitly when the `devtools_page` manifest key is present.)
* `dns`
* `downloads`
* `downloads.open`
* `find`
* `geolocation`
* `history`
* `identity`
* `idle`
* `management`
* `menus`
* `menus.overrideContext`
* `nativeMessaging`
* `notifications`
* `pageCapture`
* `pkcs11`
* `privacy`
* `proxy`
* `scripting`
* `search`
* `sessions`
* `storage`
* `tabHide`
* `tabs`
* `theme`
* `topSites`
* `unlimitedStorage`
* `webNavigation`
* `webRequest`
* `webRequestAuthProvider` (Manifest V3 and above)
* `webRequestBlocking`
* `webRequestFilterResponse`
* `webRequestFilterResponse.serviceWorkerScript`

In most cases the permission just grants access to the API, with the following exceptions:

* `tabs` gives you access to `privileged parts of the `tabs` API` without the need for host permissions: `Tab.url`, `Tab.title`, and `Tab.faviconUrl`.
    + In Firefox 85 and earlier, you also need `tabs` if you want to include `url` in the `queryInfo` parameter to `tabs.query()`. The rest of the `tabs` API can be used without requesting any permission.
    + As of Firefox 86 and Chrome 50, matching host permissions can also be used instead of the "tabs" permission.
* `webRequestBlocking` enables you to use the `"blocking"` argument, so you can `modify and cancel requests`.
* `downloads.open` lets you use the `downloads.open()` API.
* `tabHide` lets you use the `tabs.hide()` API.
activeTab permission
--------------------

This permission is specified as `"activeTab"`. If an extension has the `activeTab` permission, then when the user interacts with the extension, the extension is granted extra privileges for the active tab only.

"User interaction" includes:

* the user clicks the extension's browser action or page action
* the user selects its context menu item
* the user activates a keyboard shortcut defined by the extension

The extra privileges are:

* The ability to inject JavaScript or CSS into the tab programmatically (see Loading content scripts).
* Access to the privileged parts of the tabs API for the current tab: `Tab.url`, `Tab.title`, and `Tab.faviconUrl`.

The intention of this permission is to enable extensions to fulfill a common use case, without having to give them very powerful permissions. Many extensions want to "do something to the current page when the user asks".

For example, consider an extension that wants to run a script in the current page when the user clicks a browser action. If the `activeTab` permission did not exist, the extension would need to ask for the host permission `<all_urls>`. But this gives the extension more power than it needs: it could now execute scripts in *any tab*, *any time* it likes, instead of just the active tab and only in response to a user action.

**Note:** You can only get access to the tab/data that was there, when the user interaction occurred (e.g. the click). When the active tab navigates away (e.g., due to finishing loading or some other event), the permission does not grant you access to the tab anymore.

The `activeTab` permission enables scripting access to the top level tab's page and same origin frames. Running scripts or modifying styles inside cross-origin frames may require additional host permissions. Of course, restrictions and limitations related to particular sites and URI schemes are applied as well.

Usually the tab that's granted `activeTab` is just the currently active tab, except in one case. The `menus` API enables an extension to create a menu item which is shown if the user context-clicks on a tab (that is, on the element in the tabstrip that enables the user to switch from one tab to another).

If the user clicks such an item, then the `activeTab` permission is granted for the tab the user clicked, even if it's not the currently active tab (as of Firefox 63, Firefox bug 1446956).

Clipboard access
----------------

There are two permissions which enables the extension to interact with the clipboard:

`clipboardWrite`

Write to the clipboard using `Clipboard.write()`, `Clipboard.writeText()`, `document.execCommand("copy")` or `document.execCommand("cut")`

`clipboardRead`

Read from the clipboard using `Clipboard.read()`, `Clipboard.readText()` or `document.execCommand("paste")`

See Interact with the clipboard for more details.

Unlimited storage
-----------------

The `unlimitedStorage` permission:

* Enables extensions to exceed any quota imposed by the `storage.local` API
* In Firefox, enables extensions to create a "persistent" IndexedDB database without the browser prompting the user for permission at the time the database is created.
Example
-------

```json
 "permissions": ["\*://developer.mozilla.org/\*"]
```

In Manifest V2 only, request privileged access to pages under `developer.mozilla.org`.

```json
  "permissions": ["tabs"]
```

Request access to the privileged pieces of the `tabs` API.

```json
  "permissions": ["\*://developer.mozilla.org/\*", "tabs"]
```

In Manifest V2 only, request both of the above permissions.

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


storage - Mozilla

storage
=======

|  |  |
| --- | --- |
| Type | `Object` |
| Mandatory | No |
| Manifest version | 2 or higher |
| Example |
```json
"storage": {
  "managed\_schema": "schema.json"
}
```
 |

Use the `storage` key to specify the name of the schema file that defines the structure of data in managed storage.

Managed data declares the enterprise policies supported by the app. Policies are analogous to options but are configured by a system administrator instead of the user, enabling the app to be configured for all users of an organization.

After declaring the policies, they are read from the `storage.managed` API. However, if a policy value does not conform to the schema, then it is not published by the `storage.managed` API. It's up to the app to enforce the policies configured by the administrator.

**Note:** Firefox does not define a schema for managed storage, see `storage.managed` for more details.

The `storage` key is an object that has the following required property:

|  |  |
| --- | --- |
| `managed_schema` |
 A `String` specifying the full path of the file within the
 extension that defines the schema of the manage storage.
  |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

**Note:**

This page includes details from the Chrome developer website page Manifest for storage areas included here under the Creative Commons Attribution 3.0 United States License.