Chrome-Inkompatibilitäten
Die WebExtension-APIs zielen darauf ab, Kompatibilität in allen wichtigen Browsern bereitzustellen, sodass Erweiterungen in jedem Browser mit minimalen Änderungen laufen sollten.
Es gibt jedoch signifikante Unterschiede zwischen Chrome (und Chromium-basierten Browsern), Firefox und Safari. Insbesondere:
-
Die Unterstützung für WebExtension-APIs variiert zwischen den Browsern. Details finden Sie unter Browser-Unterstützung für JavaScript-APIs.
-
Die Unterstützung für
manifest.json-Keys variiert ebenfalls. Weitere Details finden Sie im Abschnitt "Browser-Kompatibilität" auf dermanifest.jsonSeite. -
Erweiterungs-API-Namespace:
- In Firefox und Safari: Erweiterungs-APIs werden über den
browserNamespace aufgerufen. DerchromeNamespace wird ebenfalls zur Kompatibilität mit Chrome unterstützt. - In Chrome: Erweiterungs-APIs werden über den
chromeNamespace aufgerufen. (siehe Chrome bug 798169)
- In Firefox und Safari: Erweiterungs-APIs werden über den
-
Asynchrone APIs:
- In Firefox und Safari: Asynchrone APIs werden mit Versprechen implementiert.
- In Chrome: In Manifest V2 werden asynchrone APIs mit Rückrufen implementiert. In Manifest V3 wird die Unterstützung von Versprechen für die meisten geeigneten Methoden geboten. (siehe Chrome bug 328932) Rückrufe werden in Manifest V3 aus Gründen der Rückwärtskompatibilität unterstützt.
Der Rest dieser Seite beschreibt diese und andere Inkompatibilitäten im Detail.
JavaScript-APIs
>chrome.* und browser.* Namespace
-
In Firefox und Safari: Die APIs werden über den
browserNamespace aufgerufen.jsbrowser.browserAction.setIcon({ path: "path/to/icon.png" }); -
In Chrome: Die APIs werden über den
chromeNamespace aufgerufen.jschrome.browserAction.setIcon({ path: "path/to/icon.png" });
Rückrufe und Versprechen
-
In Firefox und Safari (alle Versionen) und Chrome (ab Manifest Version 3): Asynchrone APIs verwenden Versprechen, um Werte zurückzugeben.
jsfunction 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 verwenden asynchrone APIs Rückrufe, um Werte zurückzugeben und
runtime.lastErrorzur Fehlerkommunikation. In Manifest V3 werden Rückrufe aus Gründen der Rückwärtskompatibilität unterstützt, zusammen mit der Unterstützung von Versprechen bei den meisten geeigneten Methoden.jsfunction 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 unterstützt sowohl die chrome als auch die browser Namensräume
Als Portierhilfe unterstützt die Firefox-Implementierung von WebExtensions chrome unter Verwendung von Rückrufen und browser unter Verwendung von Versprechen. Das bedeutet, dass viele Chrome-Erweiterungen in Firefox ohne Änderungen funktionieren.
Hinweis:
Der browser Namespace wird von Firefox und Safari unterstützt. Chrome bietet den browser Namespace nicht an, bis Chrome bug 798169 gelöst ist.
Wenn Sie sich entscheiden, Ihre Erweiterung so zu schreiben, dass sie browser und Versprechen verwendet, bietet Firefox ein Polyfill, das es ermöglichen sollte, sie in Chrome auszuführen: https://github.com/mozilla/webextension-polyfill.
Teilweise unterstützte APIs
Die Seite Browser-Unterstützung für JavaScript-APIs enthält Kompatibilitätstabellen für alle APIs, die in Firefox irgendeine Unterstützung haben. Wo es Hinweise bezüglich der Unterstützung einer API-Methode, Eigenschaft, Typ oder Ereignis gibt, wird dies in diesen Tabellen mit einem Sternchen "*" angezeigt. Durch Auswahl des Sternchens wird die Tabelle erweitert, um eine Notiz zu erklären, die den Hinweis erklärt.
Die Tabellen werden aus Kompatibilitätsdaten generiert, die als JSON-Dateien auf GitHub gespeichert sind.
Im Folgenden werden die Hauptkompatibilitätsprobleme beschrieben, die Sie berücksichtigen müssen, wenn Sie eine plattformübergreifende Erweiterung erstellen. Denken Sie auch daran, die Browser-Kompatibilitätstabellen zu prüfen, da sie zusätzliche Kompatibilitätsinformationen enthalten können.
Benachrichtigungs-API
Für notifications.create(), mit type "basic":
- In Firefox:
iconUrlist optional. - In Chrome:
iconUrlist erforderlich.
Wenn der Benutzer auf eine Benachrichtigung klickt:
- In Firefox: Die Benachrichtigung wird sofort gelöscht.
- In Chrome: Dies ist nicht der Fall.
Wenn Sie notifications.create() mehrmals in schneller Folge aufrufen:
- In Firefox: Die Benachrichtigungen werden möglicherweise nicht angezeigt. Das Warten auf die nachfolgenden Aufrufe innerhalb der
notifications.create()Rückruffunktion ist keine ausreichende Verzögerung, um dies zu verhindern.
Proxy-API
Firefox und Chrome enthalten eine Proxy-API. Das Design dieser beiden APIs ist jedoch inkompatibel.
- In Firefox: Proxies werden mit der Eigenschaft proxy.settings oder proxy.onRequest dynamisch ProxyInfo gesetzt. Weitere Informationen zur API finden Sie unter proxy.
- In Chrome: Proxy-Einstellungen werden in einem
proxy.ProxyConfigObjekt definiert. Abhängig von Chromes Proxyeinstellungen können die Einstellungenproxy.ProxyRulesoder einproxy.PacScriptenthalten. Proxies werden mit der Eigenschaft proxy.settings gesetzt. Weitere Informationen zur API finden Sie unter chrome.proxy.
Sidebar-API
Firefox und Chrome bieten inkompatible APIs für die Arbeit mit einer Sidebar.
- In Firefox (und Opera): Eine Sidebar wird mit dem
sidebar_actionManifest-Key spezifiziert und mit der APIsidebarActionbearbeitet. - In Chrome: Eine initiale Sidebar kann mit dem Manifest-Key
side_panelspezifiziert werden. DiesidePanelAPI ermöglicht es dann, Panels zu bearbeiten.
Tabs-API
Wenn Sie tabs.executeScript() oder tabs.insertCSS() verwenden:
- In Firefox: Relative URLs werden relativ zur aktuellen Seiten-URL aufgelöst.
- In Chrome: Relative URLs werden relativ zur Basis-URL der Erweiterung aufgelöst.
Um plattformübergreifend zu arbeiten, können Sie den Pfad als absolute URL angeben, beginnend am Root der Erweiterung, wie folgt:
/path/to/script.js
Beim Aufruf von tabs.remove():
- In Firefox: Das
tabs.remove()Versprechen wird nach dembeforeunloadEreignis erfüllt. - In Chrome: Der Rückruf wartet nicht auf
beforeunload.
WebRequest-API
-
In Firefox:
-
Anfragen können nur umgeleitet werden, wenn ihre ursprüngliche URL das
http:oderhttps:Schema verwendet. -
Die
activeTabBerechtigung erlaubt es nicht, Netzwerk-Anfragen im aktuellen Tab abzufangen. (Siehe Bug 1617479) -
Ereignisse werden nicht für Systemanfragen ausgelöst (z. B. Erweiterungs-Updates oder Suchleisten-Vorschläge).
- Ab Firefox 57: Firefox macht eine Ausnahme für Erweiterungen, die
webRequest.onAuthRequiredzum Proxy-Authentifizierung abfangen müssen. Siehe die Dokumentation zuwebRequest.onAuthRequired.
- Ab Firefox 57: Firefox macht eine Ausnahme für Erweiterungen, die
-
Wenn eine Erweiterung eine öffentliche (z. B. HTTPS) URL auf eine Erweiterungsseite umleiten möchte, muss die
manifest.json-Datei der Erweiterung einenweb_accessible_resourcesKey mit der URL der Erweiterungsseite enthalten.Hinweis: Jede Website kann zu dieser URL verlinken oder umleiten, und Erweiterungen sollten alle Eingaben (z. B. POST-Daten) so behandeln, als kämen sie von einer nicht vertrauenswürdigen Quelle, wie es bei einer normalen Webseite der Fall wäre.
-
Einige der
browser.webRequest.*APIs erlauben es, Versprechen zurückzugeben, diewebRequest.BlockingResponseasynchron auflösen.
-
-
In Chrome: Nur
webRequest.onAuthRequiredunterstützt asynchronewebRequest.BlockingResponsedurch die Bereitstellung von'asyncBlocking', über einen Rückruf statt eines Versprechens.
Windows-API
- In Firefox:
onFocusChangedderwindowsAPI wird mehrmals für eine Fokussänderung ausgelöst.
Nicht unterstützte APIs
Debugger-API
- In Firefox: Die debugger API von Chrome ist nicht implementiert.
DeclarativeContent-API
- In Firefox: Die declarativeContent API von Chrome ist nicht implementiert. Außerdem wird Firefox die
declarativeContent.RequestContentScriptAPI nicht unterstützen (die selten verwendet und in stabilen Versionen von Chrome nicht verfügbar ist).
Verschiedene Inkompatibilitäten
URLs in CSS
- In Firefox: URLs in eingefügten CSS-Dateien werden relativ zur CSS-Datei aufgelöst.
- In Chrome: URLs in eingefügten CSS-Dateien werden relativ zur Seite, in die sie eingefügt werden, aufgelöst.
Unterstützung für Dialoge auf Hintergrundseiten
web_accessible_resources
- In Firefox: Ressourcen werden einem zufälligen UUID zugewiesen, das für jede Instanz von Firefox ändert:
moz-extension://«random-UUID»/«path». Diese Zufälligkeit kann verhindern, dass Sie Dinge tun, wie zum Beispiel die URL Ihrer Erweiterung zur CSP-Richtlinie eines anderen Domain hinzuzufügen. - In Chrome: Wenn eine Ressource in
web_accessible_resourcesaufgeführt ist, ist sie zugänglich alschrome-extension://«your-extension-id»/«path». Die Erweiterungs-ID ist für eine Erweiterung festgelegt.
Manifest "key" Eigenschaft
- In Firefox: Da Firefox zufällige UUIDs für
web_accessible_resourcesverwendet, wird diese Eigenschaft nicht unterstützt. Firefox-Erweiterungen können ihre Erweiterungs-ID über denbrowser_specific_settings.gecko.idManifest-Key fixieren (siehe browser_specific_settings.gecko). - In Chrome: Beim Arbeiten mit einer entpackten Erweiterung kann das Manifest eine
"key"Eigenschaft enthalten, um die Erweiterungs-ID über verschiedene Maschinen hinweg zu fixieren. Dies ist hauptsächlich nützlich, wenn mitweb_accessible_resourcesgearbeitet wird.
HTTP(S)-Anfragen durch Inhalts-Skript
- In Firefox: Wenn ein Inhalts-Skript eine HTTP(S)-Anfrage macht, müssen Sie absolute URLs bereitstellen.
- In Chrome: Wenn ein Inhalts-Skript eine Anfrage macht (zum Beispiel mittels
fetch()) an eine relative URL (wie/api), wird sie anhttps://example.com/apigesendet.
Inhalts-Skriptumgebung
- In Firefox: Der globale Geltungsbereich der Inhalts-Skriptumgebung ist nicht streng gleich
window(Firefox bug 1208775). Genauer gesagt, der globale Geltungsbereich (globalThis) besteht aus standardmäßigen JavaScript-Funktionen wie üblich, pluswindowals Prototyp des globalen Geltungsbereichs. Die meisten DOM-APIs werden von der Seite durchwindowvererbt, durch Xray vision, um das Inhalts-Skript vor Modifikationen durch die Webseite zu schützen. Ein Inhalts-Skript kann JavaScript-Objekte aus seinem globalen Geltungsbereich oder Xray-umhüllte Versionen von der Webseite antreffen. - In Chrome: Der globale Geltungsbereich ist
window, und die verfügbaren DOM-APIs sind im Allgemeinen unabhängig von der Webseite (abgesehen von der gemeinsamen Nutzung des zugrunde liegenden DOMs). Inhalts-Skripte können nicht direkt auf JavaScript-Objekte von der Webseite zugreifen.
Inhalts-Skript-Seitenereignis-Handler
- In Firefox: separate Ereignis-Handler werden nicht pro Welt gepflegt. Das bedeutet, dass das jüngste Inhalts-Skript, das
element.onclick = xxxanfordert, die Ereignis-Handler der Seite oder anderer Erweiterungen überschreibt. - In Chrome: separate Ereignis-Handler werden pro Welt gepflegt, sodass Chrome Ereignis-Handler für eine Seite und jede anfordernde Erweiterung verwaltet.
Um diese Inkonsistenz zu umgehen, verwenden Sie addEventListener(), um Ereignis-Listener zu registrieren. Siehe Firefox bug 1965975 für weitere Informationen.
Ausführung von Code in einer Webseite aus Inhalts-Skript
- In Firefox:
evalführt Code im Kontext des Inhalts-Skripts aus undwindow.evalführt Code im Kontext der Seite aus. Siehe Verwendung vonevalin Inhalts-Skripten. - In Chrome:
evalundwindow.evalführen immer Code im Kontext des Inhalts-Skripts, nicht im Kontext der Seite aus.
Variablen zwischen Inhalts-Skripten teilen
- In Firefox: Sie können keine Variablen zwischen Inhalts-Skripten teilen, indem Sie sie zu
this.{variableName}in einem Skript zuweisen und dann versuchen, sie mitwindow.{variableName}in einem anderen abzurufen. Dieser ist eine Einschränkung der Sandbox-Umgebung in Firefox. Diese Einschränkung könnte entfernt werden; siehe Firefox bug 1208775.
Inhalts-Skript Lebenszyklus während der Navigation
-
In Firefox: Inhalts-Skripte bleiben in einer Webseite nach der Navigation bestehen. Die Eigenschaften des Fensterobjekts werden jedoch gelöscht. Zum Beispiel, wenn ein Inhalts-Skript
window.prop1 = "prop"setzt und der Benutzer dann navigiert und zur Seite zurückkehrt, istwindow.prop1undefiniert. Dieses Problem wird in Firefox bug 1525400 verfolgt.Um das Verhalten von Chrome zu imitieren, hören Sie auf die pageshow- und pagehide-Ereignisse. Simulieren Sie dann das Einfügen oder die Zerstörung des Inhalts-Skripts.
-
In Chrome: Inhalts-Skripte werden zerstört, wenn der Benutzer von einer Webseite weg navigiert. Wenn der Benutzer die Zurück-Taste klickt, um über die Historie zur Seite zurückzukehren, wird das Inhalts-Skript erneut in die Webseite eingefügt.
"pro-Tab" Zoom-Verhalten
- In Firefox: Der Zoom-Level bleibt bei Lade- und Navigationsvorgängen innerhalb des Tabs erhalten.
- In Chrome: Zoom-Änderungen werden beim Navigieren zurückgesetzt; das Navigieren eines Tabs lädt Seiten immer mit ihren pro-Herkunft-Zoomfaktoren.
Siehe tabs.ZoomSettingsScope.
manifest.json Keys
Die Hauptseite manifest.json enthält eine Tabelle, die die Browser-Unterstützung für manifest.json-Keys beschreibt. Wo es Hinweise zur Unterstützung einer bestimmten Eigenschaft gibt, wird dies in der Tabelle mit einem Sternchen "*" angezeigt. Durch Auswahl des Sternchens wird die Tabelle erweitert, um eine Notiz zu erklären, die den Hinweis erklärt.
Die Tabellen werden aus Kompatibilitätsdaten generiert, die als JSON-Dateien auf GitHub gespeichert sind.
Native Messaging
>Argumente für verbindungsbasiertes Messaging
Auf Linux und Mac: Chrome übergibt der nativen App ein Argument, nämlich die Herkunft der Erweiterung, die sie gestartet hat, in Form von chrome-extension://«extensionID/» (nachgestellter Schrägstrich erforderlich). Dies ermöglicht es der App, die Erweiterung zu identifizieren.
Auf Windows: Chrome übergibt zwei Argumente:
- Die Herkunft der Erweiterung
- Ein Handle zum nativen Chrome-Fenster, das die App gestartet hat
allowed_extensions
- In Firefox: Der Manifest-Key heißt
allowed_extensions. - In Chrome: Der Manifest-Key heißt
allowed_origins.
Speicherort des App-Manifests
- In Chrome: Das App-Manifest wird an einem anderen Ort erwartet. Siehe Native messaging host location in der Chrome-Dokumentation.
App-Bestand
- In Firefox: Wenn eine native Messaging-Verbindung geschlossen wird, beendet Firefox die Subprozesse, wenn sie nicht unterbrochen werden. Auf Windows platziert der Browser den Prozess der nativen Anwendung in ein Job-Objekt und beendet den Job. Wenn die native Anwendung andere Prozesse startet und möchte, dass sie nach dem Beenden der nativen Anwendung geöffnet bleiben, muss die native Anwendung
CreateProcessanstelle vonShellExecuteverwenden, um den zusätzlichen Prozess mit demCREATE_BREAKAWAY_FROM_JOBFlag zu starten.
Daten-Klon-Algorithmus
Einige Erweiterungs-APIs erlauben es einer Erweiterung, Daten von einem Teil der Erweiterung zu einem anderen zu senden, wie runtime.sendMessage(), tabs.sendMessage(), runtime.onMessage, die postMessage() Methode von runtime.port, und tabs.executeScript().
- In Firefox: Der Structured clone algorithm wird verwendet.
- In Chrome: Der JSON serialization algorithm wird verwendet. Er könnte in Zukunft zum strukturellen Klonen wechseln (Issue 248548).
Der Structured clone algorithm unterstützt mehr Typen als der JSON serialization algorithm. Eine bemerkenswerte Ausnahme sind (DOM-)Objekte mit einer toJSON Methode. DOM-Objekte sind weder klonbar noch JSON-serialisierbar standardmäßig, aber mit einer toJSON() Methode können diese JSON-serialisiert werden (aber immer noch nicht mit dem strukturellen Klonalgorithmus geklont werden). Beispiele für JSON-serialisierbare Objekte, die nicht strukturell klonbar sind, sind Instanzen von URL und PerformanceEntry.
Erweiterungen, die sich auf die toJSON() Methode des JSON serialization algorithm verlassen, können JSON.stringify() gefolgt von JSON.parse() verwenden, um sicherzustellen, dass eine Nachricht ausgetauscht werden kann, da ein geparster JSON-Wert immer strukturell klonbar ist.