Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

Chrome-Inkompatibilitäten

Die WebExtension-APIs zielen darauf ab, Kompatibilität über alle Hauptbrowser hinweg bereitzustellen, damit Erweiterungen in jedem Browser mit minimalen Änderungen ausgeführt werden können.

Es gibt jedoch erhebliche Unterschiede zwischen Chrome (und auf Chromium basierenden Browsern), Firefox und Safari. Im Besonderen:

  • Die Unterstützung für WebExtension-APIs unterscheidet sich je nach Browser. Details finden Sie unter Browserunterstützung für JavaScript-APIs.

  • Die Unterstützung für manifest.json Schlüssel unterscheidet sich je nach Browser. Details finden Sie im Abschnitt "Browser-Kompatibilität" auf der Seite manifest.json.

  • Namensraum der Erweiterungs-API:

    • In Firefox und Safari: Auf Erweiterungs-APIs wird unter dem Namensraum browser zugegriffen. Der Namensraum chrome wird ebenfalls für die Kompatibilität mit Chrome unterstützt.
    • In Chrome: Auf Erweiterungs-APIs wird unter dem Namensraum chrome zugegriffen. (siehe Chrome Bug 798169)
  • Asynchrone APIs:

    • In Firefox und Safari: Asynchrone APIs werden mit Promises implementiert.
    • In Chrome: In Manifest V2 werden asynchrone APIs mit Rückruffunktionen implementiert. In Manifest V3 wird die Unterstützung für Promises bei den meisten geeigneten Methoden bereitgestellt. (siehe Chrome Bug 328932) Rückruffunktionen werden in Manifest V3 für die Abwärtskompatibilität unterstützt.

Der Rest dieser Seite beschreibt diese und andere Inkompatibilitäten im Detail.

JavaScript-APIs

chrome.* und browser.* Namensraum

  • In Firefox und Safari: Die APIs werden mit dem Namensraum browser aufgerufen.

    js
    browser.browserAction.setIcon({ path: "path/to/icon.png" });
    
  • In Chrome: Die APIs werden mit dem Namensraum chrome aufgerufen.

    js
    chrome.browserAction.setIcon({ path: "path/to/icon.png" });
    

Rückrufe und Promises

  • In Firefox und Safari (alle Versionen) und Chrome (ab Manifest Version 3): Asynchrone APIs verwenden Promises, um Werte zurückzugeben.

    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 verwenden asynchrone APIs Rückruffunktionen, um Werte zurückzugeben, und runtime.lastError, um Fehler zu kommunizieren. In Manifest V3 werden Rückruffunktionen für die Abwärtskompatibilität unterstützt, zusammen mit der Unterstützung für Promises bei den meisten geeigneten Methoden.

    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 unterstützt sowohl chrome- als auch browser-Namensräume

Als Unterstützung für das Portieren unterstützt die Firefox-Implementierung von WebExtensions chrome mit Rückruffunktionen und browser mit Promises. Das bedeutet, dass viele Chrome-Erweiterungen in Firefox ohne Änderungen funktionieren.

Hinweis: Der Namensraum browser wird von Firefox und Safari unterstützt. Chrome bietet den browser-Namensraum nicht an, bis Chrome Bug 798169 behoben ist.

Wenn Sie sich entscheiden, Ihre Erweiterung so zu schreiben, dass sie browser und Promises verwendet, stellt Firefox ein Polyfill bereit, das sie in Chrome ausführen soll: https://github.com/mozilla/webextension-polyfill.

Teilweise unterstützte APIs

Die Seite Browserunterstützung für JavaScript-APIs enthält Kompatibilitätstabellen für alle APIs, die in Firefox in irgendeiner Form unterstützt werden. Wo es Einschränkungen bei der Unterstützung einer API-Methode, eines Eigenschafts, eines Typs oder eines Ereignisses gibt, wird dies in diesen Tabellen mit einem Sternchen "*" angegeben. Das Auswählen des Sternchens erweitert die Tabelle, um eine Erläuterung der Einschränkung anzuzeigen.

Die Tabellen werden aus Kompatibilitätsdaten generiert, die als JSON-Dateien in GitHub gespeichert sind.

Der Rest dieses Abschnitts beschreibt die Hauptkompatibilitätsprobleme, die Sie bei der Entwicklung einer plattformübergreifenden Erweiterung berücksichtigen müssen. Vergessen Sie auch nicht, die Browser-Kompatibilitätstabellen zu überprüfen, da diese möglicherweise zusätzliche Kompatibilitätsinformationen enthalten.

Notifications API

Für notifications.create() mit type "basic":

  • In Firefox: iconUrl ist optional.
  • In Chrome: iconUrl ist 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 schnell hintereinander aufrufen:

  • In Firefox: Die Benachrichtigungen werden möglicherweise nicht angezeigt. Das Warten auf nachfolgende 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 nicht kompatibel.

Firefox und Chrome bieten inkompatible APIs für die Arbeit mit einer Sidebar.

  • In Firefox (und Opera): Eine Sidebar wird mit dem Manifest-Schlüssel sidebar_action angegeben und mit der API sidebarAction manipuliert.
  • In Chrome: Eine anfängliche Sidebar kann mit dem Manifest-Schlüssel side_panel spezifiziert werden. Die sidePanel API ermöglicht es dann, Panels zu manipulieren.

Tabs API

Beim Verwenden von tabs.executeScript() oder tabs.insertCSS():

  • 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 Stamm der Erweiterung, so:

/path/to/script.js

Beim Aufrufen von tabs.remove():

  • In Firefox: Das Promise von tabs.remove() wird nach dem beforeunload-Ereignis 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 Schema http: oder https: verwendet.

    • Die Berechtigung activeTab erlaubt es nicht, Netzwerkanforderungen im aktuellen Tab abzufangen. (Siehe Bug 1617479)

    • Ereignisse werden nicht für Systemanfragen ausgelöst (zum Beispiel bei Erweiterungsupgrades oder Suchvorschlägen in der Suchleiste).

    • Wenn eine Erweiterung eine öffentliche (z. B. HTTPS) URL zu einer Erweiterungsseite umleiten möchte, muss die Datei manifest.json der Erweiterung einen Schlüssel web_accessible_resources mit der URL der Erweiterungsseite enthalten.

      Hinweis: Jede Website kann einen Link zu dieser URL herstellen oder zu dieser URL umleiten, und Erweiterungen sollten jede Eingabe (z. B. POST-Daten) so behandeln, als ob sie von einer nicht vertrauenswürdigen Quelle stammt, wie es normale Webseiten tun sollten.

    • Einige der browser.webRequest.* APIs ermöglichen das Zurückgeben von Promises, die webRequest.BlockingResponse asynchron auflösen.

  • In Chrome: Nur webRequest.onAuthRequired unterstützt asynchrone webRequest.BlockingResponse, indem 'asyncBlocking' über einen Rückruf anstelle eines Promise bereitgestellt wird.

Windows API

  • In Firefox: onFocusChanged der API windows wird bei einer Fokusänderung mehrfach ausgelöst.

Nicht unterstützte APIs

DeclarativeContent API

Verschiedene Inkompatibilitäten

URLs in CSS

  • In Firefox: URLs in injizierten CSS-Dateien werden relativ zur CSS-Datei aufgelöst.
  • In Chrome: URLs in injizierten CSS-Dateien werden relativ zur Seite, in die sie eingespeist werden, aufgelöst.

Unterstützung für Dialoge in Hintergrundseiten

web_accessible_resources

  • In Firefox: Ressourcen werden einer zufälligen UUID zugeordnet, die sich bei jeder Instanz von Firefox ändert: moz-extension://«random-UUID»/«path». Diese Zufälligkeit kann Sie daran hindern, Dinge zu tun, wie z. B. die URL Ihrer Erweiterung zur CSP-Richtlinie einer anderen Domäne hinzuzufügen.
  • In Chrome: Wenn eine Ressource in web_accessible_resources aufgeführt ist, ist sie als chrome-extension://«your-extension-id»/«path» zugänglich. Die Erweiterungs-ID ist für eine Erweiterung fixiert.

Manifest "key" Eigenschaft

  • In Firefox: Da Firefox zufällige UUIDs für web_accessible_resources verwendet, wird diese Eigenschaft nicht unterstützt. Firefox-Erweiterungen können ihre Erweiterungs-ID über den browser_specific_settings.gecko.id Manifest-Schlüssel festlegen (siehe browser_specific_settings.gecko).
  • In Chrome: Beim Arbeiten mit einer ungepackten Erweiterung kann das Manifest eine "key" Eigenschaft enthalten, um die Erweiterungs-ID auf verschiedenen Maschinen zu fixieren. Dies ist hauptsächlich nützlich, wenn mit web_accessible_resources gearbeitet wird.

HTTP(S)-Anfragen von Content Scripts

  • In Firefox: Wenn ein Content Script eine HTTP(S)-Anfrage stellt, muss eine absolute URL angegeben werden.
  • In Chrome: Wenn ein Content Script eine Anfrage stellt (zum Beispiel unter Verwendung von fetch()) zu einer relativen URL (wie /api), wird sie an https://example.com/api gesendet.

Umgebung von Content Scripts

  • In Firefox: Der globale Scope der Content Script Umgebung ist nicht strikt gleich window (Firefox Bug 1208775). Genauer gesagt setzt sich der globale Scope (globalThis) aus den üblichen Standard-JavaScript-Funktionen sowie window als Prototyp des globalen Scopes zusammen. Die meisten DOM-APIs werden über window von der Seite geerbt, durch Xray Vision, um das Content Script vor Modifikationen der Webseite zu schützen. Ein Content Script kann entweder JavaScript-Objekte aus seinem globalen Scope oder Xray-umwickelte Versionen von der Webseite treffen.
  • In Chrome: Der globale Scope ist window, und die verfügbaren DOM-APIs sind im Allgemeinen unabhängig von der Webseite (abgesehen vom gemeinsamen DOM). Content-Skripte können nicht direkt auf JavaScript-Objekte der Webseite zugreifen.

Seitenereignishandler von Content Scripts

  • In Firefox: Es wird kein separates Ereignishandling pro Welt gepflegt. Das bedeutet, dass das zuletzt angeforderte Content Script element.onclick = xxx die Seitenereignishandler oder die von anderen Erweiterungen überschreibt.
  • In Chrome: Es wird ein separates Ereignishandling pro Welt gepflegt, sodass Chrome Ereignishandler für eine Seite und jede anfordernde Erweiterung pflegt.

Um diese Inkonsistenz zu umgehen, verwenden Sie addEventListener(), um Ereignis-Listener zu registrieren. Weitere Informationen finden Sie bei Firefox Bug 1965975.

Ausführen von Code in einer Webseite aus einem Content Script

  • In Firefox: eval führt Code im Kontext des Content Scripts aus, und window.eval führt Code im Kontext der Seite aus. Siehe Verwendung von eval in Content Scripts.
  • In Chrome: eval und window.eval führen immer Code im Kontext des Content Scripts aus, nicht im Kontext der Seite.

Freigabe von Variablen zwischen Content Scripts

  • In Firefox: Sie können keine Variablen zwischen Content Scripts freigeben, indem Sie sie einem Script zu this.{variableName} zuweisen und dann versuchen, sie mit window.{variableName} in einem anderen Script aufzurufen. Dies ist eine Einschränkung der Sandbox-Umgebung in Firefox. Diese Einschränkung könnte entfernt werden; siehe Firefox Bug 1208775.

Lebenszyklus von Content Scripts während der Navigation

  • In Firefox: Content Scripts bleiben in einer Webseite erheblich weitereingebetteter nach dem Benutzer wegge navigiert hat. Die Eigenschaften des Fensterobjekts werden jedoch zerstört. Wenn ein Content Script zum Beispiel window.prop1 = "prop" einstellt und der Benutzer dann weg navigiert und zur Seite zurückkehrt, ist window.prop1 undefiniert. Dieses Problem wird im Firefox Bug 1525400 verfolgt.

    Um das Verhalten von Chrome zu simulieren, hören Sie auf die pageshow- und pagehide-Ereignisse. Simulieren Sie dann das Einfügen oder Zerstören des Content Scripts.

  • In Chrome: Content Scripts werden zerstört, wenn der Benutzer von einer Webseite navigiert. Wenn der Benutzer durch Klick auf die Zurück-Taste durch die Historie zur Seite zurückkehrt, wird das Content Script in die Webseite eingefügt.

"pro-Tab" Zoomverhalten

  • In Firefox: Der Zoomfaktor bleibt über das Seitenladen und die Navigation innerhalb des Tabs hinweg erhalten.
  • In Chrome: Zoomänderungen werden bei der Navigation zurückgesetzt; das Navigieren zu einer Seite lädt immer Seiten mit ihren Herkunfts-Zoomfaktoren.

Siehe tabs.ZoomSettingsScope.

manifest.json Schlüssel

Die Hauptseite manifest.json enthält eine Tabelle, die die Browserunterstützung für manifest.json Schlüssel beschreibt. Wo es Einschränkungen bei der Unterstützung eines bestimmten Schlüssels gibt, wird dies in der Tabelle mit einem Sternchen "*" angegeben. Das Auswählen des Sternchens erweitert die Tabelle, um eine Erläuterung der Einschränkung anzuzeigen.

Die Tabellen werden aus Kompatibilitätsdaten generiert, die als JSON-Dateien in GitHub gespeichert sind.

Native Messaging

Argumente für verbindungsbasierte Nachrichten

Auf Linux und Mac: Chrome übergibt ein Argument an die native App, welches der Ursprung der Erweiterung ist, die es gestartet hat, in der Form chrome-extension://«extensionID/» (einschließlich erforderlichem Schrägstrich). Dies ermöglicht der App, die Erweiterung zu identifizieren.

Auf Windows: Chrome übergibt zwei Argumente:

  1. Den Ursprung der Erweiterung
  2. Ein Handle zum nativen Chrome Fenster, das die App gestartet hat

allowed_extensions

  • In Firefox: Der Manifest-Schlüssel heißt allowed_extensions.
  • In Chrome: Der Manifest-Schlüssel heißt allowed_origins.

Speicherort des App-Manifests

App-Persistenz

  • In Firefox: Wenn eine Native Messaging-Verbindung geschlossen wird, beendet Firefox die Subprozesse, wenn diese sich nicht trennen. Auf Windows legt 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 diese geöffnet bleiben, nachdem die native Anwendung beendet ist, muss die native Anwendung CreateProcess anstelle von ShellExecute verwenden, um den zusätzlichen Prozess mit dem CREATE_BREAKAWAY_FROM_JOB-Flag zu starten.

Datenklon-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().

Der Strukturierte Klon-Algorithmus unterstützt mehr Typen als der JSON-Serialisierungsalgorithmus. Eine bemerkenswerte Ausnahme sind (DOM-)Objekte mit einer toJSON-Methode. DOM-Objekte sind standardmäßig weder klonbar noch JSON-serialisierbar, aber mit einer toJSON()-Methode können diese JSON-serialisiert werden (aber immer noch nicht mit dem strukturierten Klon-Algorithmus geklont werden). Beispiele für JSON-serialisierbare Objekte, die nicht strukuriert klonbar sind, umfassen Instanzen von URL und PerformanceEntry.

Erweiterungen, die auf die toJSON()-Methode des JSON-Serialisierungsalgorithmus angewiesen sind, 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.