From f05843edf2c9daf0e405df51f210fac0fcfab4fb Mon Sep 17 00:00:00 2001 From: Oliver Dunk Date: Wed, 29 Jul 2026 14:25:38 +0000 Subject: [PATCH 1/4] Update Chrome incompatibilities page for `browser` namespace support Remove outdated information on `browser` namespace support and promise support. This page could do with a lot of additional work, but scoping this change as strictly as possible to reduce creep. Similarly, another article ("Cross-platform extension coding hurdles") could do with further updates but making only the minimum required changes and will update that further in a second PR. --- .../build_a_cross_browser_extension/index.md | 2 +- .../chrome_incompatibilities/index.md | 71 +++---------------- 2 files changed, 9 insertions(+), 64 deletions(-) diff --git a/files/en-us/mozilla/add-ons/webextensions/build_a_cross_browser_extension/index.md b/files/en-us/mozilla/add-ons/webextensions/build_a_cross_browser_extension/index.md index 45ef85cd8ec24ba..1890a6f5fa0ec92 100644 --- a/files/en-us/mozilla/add-ons/webextensions/build_a_cross_browser_extension/index.md +++ b/files/en-us/mozilla/add-ons/webextensions/build_a_cross_browser_extension/index.md @@ -40,7 +40,7 @@ Only in the most trivial extensions is namespace likely to be the only cross-pla 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](https://crbug.com/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](/en-US/docs/Mozilla/Add-ons/WebExtensions/Chrome_incompatibilities#callbacks_and_promises) for details. +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, for example using `browser.cookies.set({ url: "https://developer.mozilla.org/" }, logCookie)` instead of `browser.cookies.set({ url: "https://developer.mozilla.org/" }).then(logCookie)`; 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`](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage#sending_an_asynchronous_response_using_a_promise) or using [a callback](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage#sending_an_asynchronous_response_using_sendresponse). A `Promise` as the return value from an event handler is supported in Firefox and Safari, but not yet in Chrome. 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 5281c10bfe1af92..2112e8570a2c197 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 @@ -11,74 +11,11 @@ However, there are significant differences between Chrome (and Chromium-based br - 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 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 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/develop/migrate#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 details these and other incompatibilities. ## JavaScript APIs -### chrome.\* and 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:** The APIs are accessed using the `chrome` namespace. - - ```js - chrome.browserAction.setIcon({ path: "path/to/icon.png" }); - ``` - -### Callbacks and promises - -- **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) { - console.log(c); - } - - function logError(e) { - console.error(e); - } - - let setCookie = browser.cookies.set({ - url: "https://developer.mozilla.org/", - }); - setCookie.then(logCookie, logError); - ``` - -- **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/develop/migrate#promises) on most appropriate methods. - - ```js - function logCookie(c) { - if (chrome.runtime.lastError) { - console.error(chrome.runtime.lastError); - } else { - console.log(c); - } - } - - chrome.cookies.set({ url: "https://developer.mozilla.org/" }, logCookie); - ``` - -### Firefox supports both the chrome and browser namespaces - -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] -> 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, Firefox provides a polyfill that should enable it to run in Chrome: . - ### Partially supported APIs 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. @@ -270,3 +207,11 @@ 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")}}. 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. + +## Historical differences + +### chrome.\* and browser.\* namespace + +Prior to Chrome 148, Chrome only exposed APIs on the `chrome` namespace instead of `browser`. For example, `browser.browserAction.setIcon({ path: "path/to/icon.png" });` would instead be `chrome.browserAction.setIcon({ path: "path/to/icon.png" });`. + +For extensions that use the `devtools_page` manifest key, Chrome support for the `browser` namespace and promises was introduced in Chrome 152. From e1b881698a3c9905dd75616dd2f3ef4867189aec Mon Sep 17 00:00:00 2001 From: Oliver Dunk Date: Tue, 4 Aug 2026 16:29:28 +0000 Subject: [PATCH 2/4] Restore mention of callbacks and polyfill --- .../add-ons/webextensions/chrome_incompatibilities/index.md | 4 ++++ 1 file changed, 4 insertions(+) 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 2112e8570a2c197..a8242e05f11f68d 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 @@ -215,3 +215,7 @@ Extensions that rely on the `toJSON()` method of the JSON serialization algorith Prior to Chrome 148, Chrome only exposed APIs on the `chrome` namespace instead of `browser`. For example, `browser.browserAction.setIcon({ path: "path/to/icon.png" });` would instead be `chrome.browserAction.setIcon({ path: "path/to/icon.png" });`. For extensions that use the `devtools_page` manifest key, Chrome support for the `browser` namespace and promises was introduced in Chrome 152. + +Additionally, Chrome support for Promise-based return values from APIs was introduced starting in Manifest V3, with some APIs being supported later. Before, a call like `browser.cookies.set({ url: "https://developer.mozilla.org/" }).then(logCookie);` would instead use a callback like `browser.cookies.set({ url: "https://developer.mozilla.org/" }, logCookie);`. + +If you are targetting older browser versions, Firefox provides a polyfill that provides the `browser` namespace and promise support: . From d0317c901191324e59cd8f054c1c0009b3548df9 Mon Sep 17 00:00:00 2001 From: Oliver Dunk Date: Tue, 4 Aug 2026 20:19:33 +0100 Subject: [PATCH 3/4] Update files/en-us/mozilla/add-ons/webextensions/chrome_incompatibilities/index.md Co-authored-by: rebloor --- .../webextensions/chrome_incompatibilities/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 a8242e05f11f68d..e324934477171c6 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 @@ -212,10 +212,10 @@ Extensions that rely on the `toJSON()` method of the JSON serialization algorith ### chrome.\* and browser.\* namespace -Prior to Chrome 148, Chrome only exposed APIs on the `chrome` namespace instead of `browser`. For example, `browser.browserAction.setIcon({ path: "path/to/icon.png" });` would instead be `chrome.browserAction.setIcon({ path: "path/to/icon.png" });`. +Before Chrome 148, Chrome exposed APIs only under the `chrome` namespace rather than `browser`. For example, `browser.browserAction.setIcon({ path: "path/to/icon.png" });` would instead be `chrome.browserAction.setIcon({ path: "path/to/icon.png" });`. -For extensions that use the `devtools_page` manifest key, Chrome support for the `browser` namespace and promises was introduced in Chrome 152. +Chrome introduced support for promise-based return values from APIs in Manifest V3, with some APIs supported later. Before the introduction of promises, a call such as `browser.cookies.set({ url: "https://developer.mozilla.org/" }).then(logCookie);` would use a callback like this: `browser.cookies.set({ url: "https://developer.mozilla.org/" }, logCookie);`. -Additionally, Chrome support for Promise-based return values from APIs was introduced starting in Manifest V3, with some APIs being supported later. Before, a call like `browser.cookies.set({ url: "https://developer.mozilla.org/" }).then(logCookie);` would instead use a callback like `browser.cookies.set({ url: "https://developer.mozilla.org/" }, logCookie);`. +For extensions that use the `devtools_page` manifest key, Chrome support for the `browser` namespace and promises was introduced in Chrome 152. -If you are targetting older browser versions, Firefox provides a polyfill that provides the `browser` namespace and promise support: . +If you're targeting older Chrome browser versions, Firefox offers a polyfill that provides the `browser` namespace and promise support: . From 6c16b5467f2c1cd228493423e624eafa5f4edba5 Mon Sep 17 00:00:00 2001 From: Oliver Dunk Date: Wed, 5 Aug 2026 22:27:45 +0000 Subject: [PATCH 4/4] Address feedback --- .../webextensions/build_a_cross_browser_extension/index.md | 2 +- .../add-ons/webextensions/chrome_incompatibilities/index.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/files/en-us/mozilla/add-ons/webextensions/build_a_cross_browser_extension/index.md b/files/en-us/mozilla/add-ons/webextensions/build_a_cross_browser_extension/index.md index 1890a6f5fa0ec92..3a9da0d85b140d6 100644 --- a/files/en-us/mozilla/add-ons/webextensions/build_a_cross_browser_extension/index.md +++ b/files/en-us/mozilla/add-ons/webextensions/build_a_cross_browser_extension/index.md @@ -40,7 +40,7 @@ Only in the most trivial extensions is namespace likely to be the only cross-pla 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](https://crbug.com/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, for example using `browser.cookies.set({ url: "https://developer.mozilla.org/" }, logCookie)` instead of `browser.cookies.set({ url: "https://developer.mozilla.org/" }).then(logCookie)`; +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 the [Historical differences](/en-US/docs/Mozilla/Add-ons/WebExtensions/Chrome_incompatibilities#historical_differences) section of the Chrome incompatibilities page 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`](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage#sending_an_asynchronous_response_using_a_promise) or using [a callback](/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage#sending_an_asynchronous_response_using_sendresponse). A `Promise` as the return value from an event handler is supported in Firefox and Safari, but not yet in Chrome. 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 e324934477171c6..bf5601807735332 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 @@ -14,6 +14,8 @@ However, there are significant differences between Chrome (and Chromium-based br The rest of this page details these and other incompatibilities. +Support for the `browser` namespace and promises are no longer a source of incompatibility. See [Historical differences](#historical_differences). + ## JavaScript APIs ### Partially supported APIs