Chrome incompatibilities

Sie lesen die englische Version dieses Inhalts, da für dieses Gebietsschema noch keine Übersetzung vorhanden ist. Helfen Sie uns, diesen Artikel zu übersetzen!

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.

However, there are significant differences between Chrome, Firefox, and Edge. In particular:

  • Support for JavaScript APIs differs across browsers. See Browser support for JavaScript APIs for more details.

  • Support for manifest.json keys differs across browsers. See the "Browser compatibility" section in the manifest.json page for more details.

  • Javascript APIs:

    In Chrome
    JavaScript APIs are accessed under the chrome namespace. (cf. Chrome bug 798169)
    In Firefox and Edge
    They are accessed under the browser namespace.
  • Asynchronous APIs:

    In Chrome and Edge
    Asynchronous APIs are implemented using callbacks. (cf. Chrome bug 328932)
    In Firefox
    Asynchronous APIs are implemented using promises.

The rest of this page summarizes these and other incompatibilities.

JavaScript APIs

Callbacks and the chrome.* namespace

In Chrome
Extensions access privileged JavaScript APIs using the chrome namespace.
chrome.browserAction.setIcon({path: "path/to/icon.png"});
In Firefox (via the WebExtension API)
The equivalent APIs are accessed using the browser namespace.
browser.browserAction.setIcon({path: "path/to/icon.png"});

Many of the APIs are asynchronous.

In Chrome
Asynchronous APIs use callbacks to return values, and runtime.lastError to communicate errors.
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
);
In Firefox (via the WebExtension API)
Asynchronous APIs use promises to return values instead.
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);

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.

Note: However, this is not part of the WebExtensions standard. and may not be supported by all compliant browsers.

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: https://github.com/mozilla/webextension-polyfill.

Partially supported APIs

The page 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.

These tables are generated from compatibility data stored as JSON files in GitHub.

The rest of this section describes compatibility issues that are not already captured in the tables.

notifications

  • For notifications.create(), with type "basic":

    In Firefox
    iconUrl is optional.
    In Chrome
    iconUrl is required.
  • When the user clicks on a notification:

    In Firefox
    The notification is cleared immediately.
    In Chrome
    This is not the case.
  • If you call notifications.create() more than once in rapid succession:

    • 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.

proxy

Firefox's Proxy API followed a completely different design from Chrome's Proxy API.

In Chrome
An extension can register a PAC file, but can also define explicit proxying rules.
In Firefox
The proxy API only supports the PAC file approach (since this is also possible using extended PAC files).
Note: Because this API is incompatible with Chrome's proxy API, the Firefox proxy API is only available through the browser namespace.

tabs

  • 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.

    To work cross-browser, you can specify the path as an absolute URL, starting at the extension's root, like this:

    /path/to/script.js
    
  • When :

    In Firefox
    Querying tabs by URL with tabs.query() requires the "tabs" permission.
    In Chrome
    querying tabs by URL with tabs.query() It's possible without the "tabs" permission, but will limit results to tabs whose URLs match host permissions.
  • When calling tabs.remove():

    In Firefox
    The tabs.remove() promise is fulfilled after the beforeunload event.
    In Chrome
    The callback does not wait for beforeunload.

webRequest

In Firefox
  • Requests can be redirected only if their original URL uses the http: or https: scheme.
  • Events are not fired for system requests (for example, extension upgrades or searchbar suggestions).
  • If an extension wants to redirect a public (e.g., HTTPS) URL to an extension page, the extension's manifest.json file must contain a 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.

  • When using browser.webRequest.*:

    In Firefox (starting from Firefox 52)
    Some of the browser.webRequest.* APIs allow returning Promises that resolves webRequest.BlockingResponse asynchronously.
    In Chrome
    Only webRequest.onAuthRequired supports asynchronous webRequest.BlockingResponse via supplying 'asyncBlocking'.

windows

In Firefox
onFocusChanged will trigger multiple times for a given focus change.

Unsupported APIs

declarativeContent

In Firefox
Chrome's declarativeContent API has not yet been implemented in Firefox.
In addition, Firefox will not be supporting 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 Chrome
URLs in injected CSS files are resolved relative to the page they are injected into.

Additional incompatibilities

In Firefox
Background pages do not support using alert(), confirm(), or prompt().

web_accessible_resources

In Chrome
When a resource is listed in web_accessible_resources, it is accessible as chrome-extension://«your-extension-id»/«path/to/resource». The extension ID is fixed for a given extension.
In Firefox
Resources are assigned a random UUID that changes for every instance of Firefox: moz-extension://«random-UUID»/«path/to/resource». This randomness can prevent you from doing a few things, such as add your specific extension's URL to another domain's CSP policy.

Manifest "key" property

In Chrome
When working with an unpacked extension, the manifest may include a "key" property to pin the extension ID across different machines. This is mainly useful when working with web_accessible_resources.
In Firefox
Since Firefox uses random UUIDs for web_accessible_resources, this property is unsupported.

Content script requests happen in the context of extension, not content page

In Chrome
When a contest script makes a request (for example, using fetch()) to a relative URL (like /api), it will be sent to https://example.com/api.
In Firefox
When a contest script makes a request, you must provide absolute URLs.

manifest.json keys

The main 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.

These tables are generated from compatibility data stored as JSON files in GitHub.

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». This enables the app to identify the extension.
On Windows

Chrome passes two arguments:

  1. The origin of the extension
  2. A handle to the Chrome native window that started the app

allowed_extensions

In Firefox
The manifest key is called allowed_extensions.
In Chrome
The manifest key is called allowed_origins instead.

App manifest location

In Chrome
The app manifest is expected in a different place. See Native messaging host location in the Chrome docs.