diff --git a/files/en-us/mozilla/add-ons/webextensions/chrome_incompatibilities/index.md b/files/en-us/mozilla/add-ons/webextensions/chrome_incompatibilities/index.md index 81813ba53a2d270..083171ecd33f007 100644 --- a/files/en-us/mozilla/add-ons/webextensions/chrome_incompatibilities/index.md +++ b/files/en-us/mozilla/add-ons/webextensions/chrome_incompatibilities/index.md @@ -6,35 +6,35 @@ page-type: guide {{AddonSidebar}} -Extensions built with WebExtension APIs are designed to be compatible with Chrome and Opera extensions. As far as possible, extensions written for those browsers should run on Firefox with minimal changes. +The WebExtension APIs aim to provide compatibility across all the main browsers, so extensions should run on any browser with minimal changes. -However, there are significant differences between Chrome, Firefox, and Edge. In particular: +However, there are significant differences between Chrome (and Chromium-based browsers), Firefox, and Safari. In particular: -- Support for JavaScript APIs differs across browsers. See [Browser support for JavaScript APIs](/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs) for more details. -- Support for `manifest.json` keys differs across browsers. See the ["Browser compatibility" section](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json#browser_compatibility) in the [`manifest.json`](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json) page for more details. -- JavaScript APIs: +- Support for WebExtension APIs differs across browsers. See [Browser support for JavaScript APIs](/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs) for details. +- Support for `manifest.json` keys differs across browsers. See the ["Browser compatibility" section](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json#browser_compatibility) on the [`manifest.json`](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json) page for more details. +- Extension API namespace: - - **In Firefox:** JavaScript APIs are accessed under the `browser` namespace. - - **In Chrome and Edge:** JavaScript APIs are accessed under the `chrome` namespace. (cf. [Chrome bug 798169](https://crbug.com/798169)) + - **In Firefox and Safari:** Extension APIs are accessed under the `browser` namespace. The `chrome` namespace is also supported for compatibility with Chrome. + - **In Chrome:** Extension APIs are accessed under the `chrome` namespace. (cf. [Chrome bug 798169](https://crbug.com/798169)) - Asynchronous APIs: - - **In Firefox:** Asynchronous APIs are implemented using promises. - - **In Chrome and Edge:** Asynchronous APIs are implemented using callbacks. (cf. [Chrome bug 328932](https://crbug.com/328932)) + - **In Firefox and Safari:** Asynchronous APIs are implemented using promises. + - **In Chrome:** In Manifest V2, asynchronous APIs are implemented using callbacks. In Manifest V3, support is provided for [promises](https://developer.chrome.com/docs/extensions/mv3/intro/mv3-overview/#promises) on most appropriate methods. (cf. [Chrome bug 328932](https://crbug.com/328932)) Callbacks are supported in Manifest V3 for backward compatibility. -The rest of this page summarizes these and other incompatibilities. +The rest of this page details these and other incompatibilities. ## JavaScript APIs ### chrome.\* and browser.\* namespace -- **In Firefox:** The equivalent APIs are accessed using the `browser` namespace. +- **In Firefox and Safari:** The APIs are accessed using the `browser` namespace. ```js browser.browserAction.setIcon({ path: "path/to/icon.png" }); ``` -- **In Chrome:** Extensions access privileged JavaScript APIs using the `chrome` namespace. +- **In Chrome:** The APIs are accessed using the `chrome` namespace. ```js chrome.browserAction.setIcon({ path: "path/to/icon.png" }); @@ -42,7 +42,7 @@ The rest of this page summarizes these and other incompatibilities. ### Callbacks and promises -- **In Firefox:** Asynchronous APIs use [promises](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) to return values instead. +- **In Firefox and Safari (all versions), and Chrome (starting from Manifest Version 3):** Asynchronous APIs use [promises](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) to return values. ```js function logCookie(c) { @@ -59,7 +59,7 @@ The rest of this page summarizes these and other incompatibilities. setCookie.then(logCookie, logError); ``` -- **In Chrome:** Asynchronous APIs use callbacks to return values, and {{WebExtAPIRef("runtime.lastError")}} to communicate errors. +- **In Chrome:** In Manifest V2, asynchronous APIs use callbacks to return values and {{WebExtAPIRef("runtime.lastError")}} to communicate errors. In Manifest V3, callbacks are supported for backward compatibility, along with support for [promises](https://developer.chrome.com/docs/extensions/mv3/intro/mv3-overview/#promises) on most appropriate methods. ```js function logCookie(c) { @@ -75,19 +75,19 @@ The rest of this page summarizes these and other incompatibilities. ### Firefox supports both the chrome and browser namespaces -As a porting aid, the Firefox implementation of WebExtensions supports `chrome`, using callbacks, as well as `browser`, using promises. This means that many Chrome extensions will just work in Firefox without any changes. +As a porting aid, the Firefox implementation of WebExtensions supports `chrome` using callbacks and `browser` using promises. This means that many Chrome extensions work in Firefox without changes. -> **Note:** However, this is _not_ part of the WebExtensions standard and may not be supported by all compliant browsers. +> **Note:** The `browser` namespace is supported by Firefox and Safari. Chrome does not offer the `browser` namespace, until [Chrome bug 798169](https://crbug.com/798169) is resolved. -If you choose to write your extension to use `browser` and promises, then Firefox also provides a polyfill that will enable it to run in Chrome: . +If you choose to write your extension to use `browser` and promises, Firefox provides a polyfill that should enable it to run in Chrome: . ### Partially supported APIs -The page [Browser support for JavaScript APIs](/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs) includes compatibility tables for all APIs that have any support in Firefox. Where there are caveats around support for a given API item, this is indicated in these tables with an asterisk "\*" and in the reference page for the API item, the caveats are explained. +The [Browser support for JavaScript APIs](/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs) page includes compatibility tables for all APIs that have any support in Firefox. Where there are caveats regarding support for an API method, property, type, or event, this is indicated in these tables with an asterisk "\*". Selecting the asterisk expands the table to display a note explaining the caveat. -These tables are generated from compatibility data stored as [JSON files in GitHub](https://github.com/mdn/browser-compat-data). +The tables are generated from compatibility data stored as [JSON files in GitHub](https://github.com/mdn/browser-compat-data). -The rest of this section describes compatibility issues that are not already captured in the tables. +The rest of this section describes the main compatibility issues you may need to consider when building a cross-browser extension. Also, remember to check the browser compatibility tables, as they may contain additional compatibility information. #### Notifications API @@ -103,7 +103,7 @@ When the user clicks on a notification: If you call `notifications.create()` more than once in rapid succession: -- **In Firefox**: In Firefox, the notifications may not display at all. Waiting to make subsequent calls until within the `chrome.notifications.create()` callback function is not a sufficient delay to prevent this. +- **In Firefox**: The notifications may not display. Waiting to make subsequent calls within the `notifications.create()` callback function is not a sufficient delay to prevent this. #### Proxy API @@ -119,7 +119,7 @@ Firefox and Chrome include a Proxy API. However, the design of these two APIs is When using `tabs.executeScript()` or `tabs.insertCSS()`: - **In Firefox**: Relative URLs passed are resolved relative to the current page URL. -- **In Chrome**: These URLs are resolved relative to the extension's base URL. +- **In Chrome**: Relative URLs are resolved relative to the extension's base URL. To work cross-browser, you can specify the path as an absolute URL, starting at the extension's root, like this: @@ -127,11 +127,6 @@ To work cross-browser, you can specify the path as an absolute URL, starting at /path/to/script.js ``` -When querying tabs by URL `tabs.query()`: - -- **In Firefox**: Extensions must have the `"tabs"` permission. -- **In Chrome**: Extensions do not need the `"tabs"` permission, but only tabs whose URLs match the extension's host permissions will be included in the results. - When calling `tabs.remove()`: - **In Firefox**: The `tabs.remove()` promise is fulfilled after the `beforeunload` event. @@ -142,95 +137,95 @@ When calling `tabs.remove()`: - **In Firefox:** - Requests can be redirected only if their original URL uses the `http:` or `https:` scheme. - - The `activeTab` permission does not allow intercepting network requests in the current tab. (See [bug 1617479](https://bugzil.la/1617479)) + - The `activeTab` permission does not allow for intercepting network requests in the current tab. (See [bug 1617479](https://bugzil.la/1617479)) - Events are not fired for system requests (for example, extension upgrades or search bar suggestions). - **From Firefox 57 onwards:** Firefox makes an exception for extensions that need to intercept {{WebExtAPIRef("webRequest.onAuthRequired")}} for proxy authorization. See the documentation for {{WebExtAPIRef("webRequest.onAuthRequired")}}. - If an extension wants to redirect a public (e.g., HTTPS) URL to an [extension page](/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Extension_pages), the extension's `manifest.json` file must contain a [`web_accessible_resources`](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/web_accessible_resources) key with the URL of the extension page. - - > **Note:** _Any_ website may then link or redirect to that URL, and extensions should treat any input (POST data, for example) as if it came from an untrusted source, just as a normal web page should. + - > **Note:** _Any_ website may link or redirect to that URL, and extensions should treat any input (POST data, for example) as if it came from an untrusted source, as a normal web page should. - - Some of the `browser.webRequest.*` APIs allow returning Promises that resolves `webRequest.BlockingResponse` asynchronously. + - Some of the `browser.webRequest.*` APIs allow for returning Promises that resolves `webRequest.BlockingResponse` asynchronously. -- **In Chrome:** Only `webRequest.onAuthRequired` supports asynchronous `webRequest.BlockingResponse` via supplying `'asyncBlocking'`. +- **In Chrome:** Only `webRequest.onAuthRequired` supports asynchronous `webRequest.BlockingResponse` by supplying `'asyncBlocking'`, through a callback instead of a Promise. #### Windows API -- **In Firefox:** `onFocusChanged` of the {{WebExtAPIRef("windows")}} API, will trigger multiple times for a given focus change. +- **In Firefox:** `onFocusChanged` of the {{WebExtAPIRef("windows")}} API triggers multiple times for a focus change. ### Unsupported APIs #### DeclarativeContent API -- **In Firefox:** Chrome's [declarativeContent](https://developer.chrome.com/docs/extensions/reference/declarativeContent/) API [has not yet been implemented](https://bugzil.la/1435864). In addition, Firefox [will not be supporting](https://bugzil.la/1323433#c16) the `declarativeContent.RequestContentScript` API (which is rarely used, and is unavailable in stable releases of Chrome). +- **In Firefox:** Chrome's [declarativeContent](https://developer.chrome.com/docs/extensions/reference/declarativeContent/) API [is not implemented](https://bugzil.la/1435864). In addition, Firefox [will not support](https://bugzil.la/1323433#c16) the `declarativeContent.RequestContentScript` API (which is rarely used and is unavailable in stable releases of Chrome). ### Miscellaneous incompatibilities #### URLs in CSS -- **In Firefox:** URLs in injected CSS files are resolved relative to _the CSS file itself_. +- **In Firefox:** URLs in injected CSS files are resolved relative to _the CSS file_. - **In Chrome:** URLs in injected CSS files are resolved relative to _the page they are injected into_. #### Support for dialogs in background pages -- **In Firefox:** [`alert()`](/en-US/docs/Web/API/Window/alert), [`confirm()`](/en-US/docs/Web/API/Window/confirm), and [`prompt()`](/en-US/docs/Web/API/Window/prompt) are not supported in background pages: +- **In Firefox:** [`alert()`](/en-US/docs/Web/API/Window/alert), [`confirm()`](/en-US/docs/Web/API/Window/confirm), and [`prompt()`](/en-US/docs/Web/API/Window/prompt) are not supported in background pages. #### web_accessible_resources -- **In Firefox:** Resources are assigned a random {{Glossary("UUID")}} that changes for every instance of Firefox: `moz-extension://«random-UUID»/«path»`. This randomness can prevent you from doing a few things, such as add your specific extension's URL to another domain's CSP policy. -- **In Chrome:** When a resource is listed in `web_accessible_resources`, it is accessible as `chrome-extension://«your-extension-id»/«path»`. The extension ID is fixed for a given extension. +- **In Firefox:** Resources are assigned a random {{Glossary("UUID")}} that changes for every instance of Firefox: `moz-extension://«random-UUID»/«path»`. This randomness can prevent you from doing things, such as adding your extension's URL to another domain's CSP policy. +- **In Chrome:** When a resource is listed in `web_accessible_resources`, it is accessible as `chrome-extension://«your-extension-id»/«path»`. The extension ID is fixed for an extension. #### Manifest "key" property -- **In Firefox:** Since Firefox uses random UUIDs for `web_accessible_resources`, this property is unsupported. +- **In Firefox:** As Firefox uses random UUIDs for `web_accessible_resources`, this property is unsupported. Firefox extensions can fix their extension ID through the `browser_specific_settings.gecko.id` manifest key (see [browser_specific_settings.gecko](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_specific_settings#firefox_gecko_properties)). - **In Chrome:** When working with an unpacked extension, the manifest may include a [`"key"` property](https://developer.chrome.com/docs/extensions/mv3/manifest/key/) to pin the extension ID across different machines. This is mainly useful when working with `web_accessible_resources`. #### Content script HTTP(S) requests - **In Firefox:** When a content script makes an HTTP(S) request, you _must_ provide absolute URLs. -- **In Chrome:** When a content script makes a request (for example, using [`fetch()`](/en-US/docs/Web/API/Fetch_API/Using_Fetch)) to a relative URL (like `/api`), it will be sent to `https://example.com/api`. +- **In Chrome:** When a content script makes a request (for example, using [`fetch()`](/en-US/docs/Web/API/Fetch_API/Using_Fetch)) to a relative URL (like `/api`), it is sent to `https://example.com/api`. #### Content script environment -- **In Firefox:** The global scope of the [content script environment](/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#content_script_environment) is not strictly equal to `window` ([Firefox bug 1208775](https://bugzil.la/1208775)). More specifically, the global scope (`globalThis`) is composed of standard JavaScript features as usual, plus `window` as the prototype of the global scope. Most DOM APIs are inherit from the page through `window`, through [Xray vision](/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts#xray_vision_in_firefox) to shield the content script from modifications by the web page. Content scripts may encounter JavaScript objects from its own global scope or Xray-wrapped versions from the web page. -- **In Chrome:** The global scope is `window` and the available DOM APIs are generally independent of the web page (other than sharing the underlying DOM). Content scripts cannot directly access JavaScript objects from the web page. +- **In Firefox:** The global scope of the [content script environment](/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#content_script_environment) is not strictly equal to `window` ([Firefox bug 1208775](https://bugzil.la/1208775)). More specifically, the global scope (`globalThis`) is composed of standard JavaScript features as usual, plus `window` as the prototype of the global scope. Most DOM APIs are inherited from the page through `window`, through [Xray vision](/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts#xray_vision_in_firefox) to shield the content script from modifications by the web page. A content script may encounter JavaScript objects from its global scope or Xray-wrapped versions from the web page. +- **In Chrome:** The global scope is `window`, and the available DOM APIs are generally independent of the web page (other than sharing the underlying DOM). Content scripts cannot directly access JavaScript objects from the web page. -#### Executing code in web page from content script +#### Executing code in a web page from content script -- **In Firefox:** {{jsxref("Global_Objects/eval", "eval")}} runs code in the context of the content script, and `window.eval` runs code in the context of the page. See [Using `eval` in content scripts](/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#using_eval_in_content_scripts). +- **In Firefox:** {{jsxref("Global_Objects/eval", "eval")}} runs code in the context of the content script and `window.eval` runs code in the context of the page. See [Using `eval` in content scripts](/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#using_eval_in_content_scripts). - **In Chrome:** {{jsxref("Global_Objects/eval", "eval")}} and `window.eval` always runs code in the context of the content script, not in the context of the page. #### Sharing variables between content scripts -- **In Firefox:** You cannot share variables between content scripts by assigning them to `this.{variableName}` in one script and then attempting to access them using `window.{variableName}` in another. This is a limitation created by the sandbox environment in Firefox. This limitation may be removed, see [Firefox bug 1208775](https://bugzil.la/1208775). +- **In Firefox:** You cannot share variables between content scripts by assigning them to `this.{variableName}` in one script and then attempting to access them using `window.{variableName}` in another. This is a limitation created by the sandbox environment in Firefox. This limitation may be removed; see [Firefox bug 1208775](https://bugzil.la/1208775). #### Content script lifecycle during navigation -- **In Firefox:** Content scripts remain injected in a web page after the user has navigated away, however, window object properties are destroyed. For example, if a content script sets `window.prop1 = "prop"` and the user then navigates away and returns to the page `window.prop1` is undefined. This issue is tracked in [Firefox bug 1525400](https://bugzil.la/1525400). +- **In Firefox:** Content scripts remain injected in a web page after the user has navigated away. However, window object properties are destroyed. For example, if a content script sets `window.prop1 = "prop"` and the user then navigates away and returns to the page `window.prop1` is undefined. This issue is tracked in [Firefox bug 1525400](https://bugzil.la/1525400). To mimic the behavior of Chrome, listen for the [pageshow](/en-US/docs/Web/API/Window/pageshow_event) and [pagehide](/en-US/docs/Web/API/Window/pagehide_event) events. Then simulate the injection or destruction of the content script. -- **In Chrome:** Content scripts are destroyed when the user navigates away from a web page. If the user then returns to the page through history, by clicking the back button, the content script is injected into the web page again. +- **In Chrome:** Content scripts are destroyed when the user navigates away from a web page. If the user clicks the back button to return to the page through history, the content script is injected into the web page. #### "per-tab" zoom behavior - **In Firefox:** The zoom level persists across page loads and navigation within the tab. -- **In Chrome:** Zoom changes are reset on navigation; navigating a tab will always load pages with their per-origin zoom factors. +- **In Chrome:** Zoom changes are reset on navigation; navigating a tab always loads pages with their per-origin zoom factors. See {{WebExtAPIRef("tabs.ZoomSettingsScope")}}. ## manifest.json keys -The main [`manifest.json`](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json) page includes a table describing browser support for `manifest.json` keys. Where there are caveats around support for a given key, this is indicated in the table with an asterisk "\*" and in the reference page for the key, the caveats are explained. +The main [`manifest.json`](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json) page includes a table describing browser support for `manifest.json` keys. Where there are caveats around support for a given key, this is indicated in the table with an asterisk "\*". Selecting the asterisk expands the table to display a note explaining the caveat. -These tables are generated from compatibility data stored as [JSON files in GitHub](https://github.com/mdn/browser-compat-data). +The tables are generated from compatibility data stored as [JSON files in GitHub](https://github.com/mdn/browser-compat-data). ## Native messaging ### Connection-based messaging arguments -**On Linux and Mac:** Chrome passes one argument to the native app, which is the origin of the extension that started it, in the form: `chrome-extension://«extensionID/»` (trailing slash required). This enables the app to identify the extension. +**On Linux and Mac:** Chrome passes one argument to the native app, which is the origin of the extension that started it, in the form of `chrome-extension://«extensionID/»` (trailing slash required). This enables the app to identify the extension. **On Windows:** Chrome passes two arguments: @@ -240,7 +235,7 @@ These tables are generated from compatibility data stored as [JSON files in GitH ### allowed_extensions - **In Firefox:** The manifest key is called `allowed_extensions`. -- **In Chrome:** The manifest key is called `allowed_origins` instead. +- **In Chrome:** The manifest key is called `allowed_origins`. ### App manifest location @@ -259,4 +254,4 @@ Some extension APIs allow an extension to send data from one part of the extensi The Structured clone algorithm supports more types than the JSON serialization algorithm. A notable exception are (DOM) objects with a `toJSON` method. DOM objects are not cloneable nor JSON-serializable by default, but with a `toJSON()` method, these can be JSON-serialized (but still not cloned with the structured cloning algorithm). Examples of JSON-serializable objects that are not structured cloneable include instances of {{domxref("URL")}} and {{domxref("PerformanceEntry")}}. -Extension that rely on the `toJSON()` method of the JSON serialization algorithm can use {{jsxref("JSON.stringify()")}} followed by {{jsxref("JSON.parse()")}} to ensure that a message can be exchanged, because a parsed JSON value is always structurally cloneable. +Extensions that rely on the `toJSON()` method of the JSON serialization algorithm can use {{jsxref("JSON.stringify()")}} followed by {{jsxref("JSON.parse()")}} to ensure that a message can be exchanged because a parsed JSON value is always structurally cloneable. diff --git a/files/en-us/mozilla/add-ons/webextensions/differences_between_api_implementations/index.md b/files/en-us/mozilla/add-ons/webextensions/differences_between_api_implementations/index.md index d918a0d6ca8b669..b7b30e80f6e2123 100644 --- a/files/en-us/mozilla/add-ons/webextensions/differences_between_api_implementations/index.md +++ b/files/en-us/mozilla/add-ons/webextensions/differences_between_api_implementations/index.md @@ -6,43 +6,43 @@ page-type: guide {{AddonSidebar}} -The browser extensions API is still an [emerging standard](https://browserext.github.io/browserext/). As a result, while it is supported by most major browsers including Firefox, Chrome, Edge, and Opera, there are differences between the various implementations. This means that some changes may be necessary to implement your extension for multiple browsers. +The browser extensions API is an [emerging standard](https://browserext.github.io/browserext/). As a result, while it is supported by most major browsers – including Firefox, Chrome, Edge, and Opera – there are differences between the various implementations. This means some changes may be necessary to implement your extension for multiple browsers. -Among the various browsers supporting the extensions API, Firefox is the most compliant with the emerging standard, and is, therefore, your best place to start when developing browser extensions. +Among the various browsers supporting the extensions API, Firefox is the most compliant with the emerging standard and, therefore, is your best place to start when developing browser extensions. -The differences between browsers' extensions API implementations fall into four areas: namespace, asynchronous event handling, API coverage, and manifest keys. +The differences between browsers' API implementations fall into four areas: namespace, asynchronous event handling, API coverage, and manifest keys. ## Namespace -You reference all extensions API functions using a namespace, for example, `browser.alarms.create({delayInMinutes});` would create an alarm in Firefox that goes off after the time specified in `delayInMinutes`. +You reference all extensions API functions using a namespace. For example, `browser.alarms.create({delayInMinutes});` creates an alarm in Firefox that goes off after the time specified in `delayInMinutes`. There are two API namespaces in use: -- `chrome` used in Chrome, Edge and Opera. -- `browser` used in Firefox. +- `chrome` used in Chrome, Edge, and Opera. +- `browser` used in Firefox and Safari. ## Asynchronous event handling -JavaScript provides several ways in which to handle asynchronous events. The proposed extensions API standard is to use promises. The promises approach provides significant advantages when dealing with chained asynchronous event calls. +JavaScript provides several ways to handle asynchronous events. The proposed extensions API standard is to use promises. The promises approach offers significant advantages when dealing with chained asynchronous event calls. -If you are unfamiliar with how JavaScript can handle asynchronous events or promises, take a look at [Getting to know asynchronous JavaScript: Callbacks, Promises and Async/Await](https://medium.com/codebuddies/getting-to-know-asynchronous-javascript-callbacks-promises-and-async-await-17e0673281ee) or the MDN [Using promises](/en-US/docs/Web/JavaScript/Guide/Using_promises) page. +Firefox and Safari implement promises for the extensions API. All other browsers use callbacks. In Manifest V3, Chrome, Edge, and Opera provided for [promises](https://developer.chrome.com/docs/extensions/mv3/intro/mv3-overview/#promises) on most appropriate methods. (cf. [Chrome bug 328932](https://crbug.com/328932)) -Firefox is the only major browser that has implemented promises for the extensions API. All other browsers use callbacks. +If you are unfamiliar with how JavaScript can handle asynchronous events or promises, look at [Getting to know asynchronous JavaScript: Callbacks, Promises and Async/Await](https://medium.com/codebuddies/getting-to-know-asynchronous-javascript-callbacks-promises-and-async-await-17e0673281ee) or the MDN [Using promises](/en-US/docs/Web/JavaScript/Guide/Using_promises) page. ## API coverage The differences in the extensions API function implementations among the browsers fall into three broad categories: -- Lack of support for an entire function. For example, at the time of writing, Edge doesn't provide support for the [`privacy`](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/privacy) function. +- Lack of support for an entire function. - Variations in the support for features within a function. For example, at the time of writing, Firefox doesn't support the [`notification`](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/notifications) function method [`onButtonClicked`](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/notifications/onButtonClicked), while Firefox is the only browser that supports [`onShown`](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/notifications/onShown). -- Proprietary functions, supporting browser-specific features. For example, at the time of writing, containers is a Firefox-specific feature supported by the [`contextualIdentities`](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/contextualIdentities) function. +- Proprietary functions supporting browser-specific features. For example, at the time of writing, containers is a Firefox-specific feature supported by the [`contextualIdentities`](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/contextualIdentities) function. ## Manifest keys The differences in the supported [`manifest.json` keys](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json) among the browsers fall broadly into two categories: -- Extension information attributes. For example, at the time of writing, Firefox and Opera include the [`developer`](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/developer) key enabling the addition of details about the developer of the extension, as well as the author, to be recorded. -- Extension features. For example, at the time of writing, Edge did not support the [`commands`](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/commands) key (which enables shortcut keys to be defined for an extension). +- Extension information attributes. For example, at the time of writing, Firefox and Opera include the [`developer`](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/developer) key (in addition to the [`author`](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/author) key) to record details about the extension developer. +- Extension features. For example, at the time of writing, only Firefox supports the [`protocol_handlers`](/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/protocol_handlers) key (which registers web-based protocol handlers, applications that know how to handle particular types of links). ## More information