runtime.Port

Ein Port-Objekt repräsentiert ein Ende einer Verbindung zwischen zwei spezifischen Kontexten, die zum Austausch von Nachrichten verwendet werden kann.

Eine Seite initiiert die Verbindung, indem sie eine connect()-API verwendet. Dies gibt ein Port-Objekt zurück. Die andere Seite hört auf Verbindungsversuche mit einem onConnect-Listener. Dieser wird ein entsprechendes Port-Objekt übergeben.

Sobald beide Seiten Port-Objekte haben, können sie Nachrichten mit Port.postMessage() und Port.onMessage austauschen. Wenn sie fertig sind, kann entweder das eine oder das andere Ende die Verbindung mit Port.disconnect() trennen, was ein Port.onDisconnect-Ereignis am anderen Ende auslöst, das es dem anderen Ende ermöglicht, notwendige Aufräumarbeiten durchzuführen.

Ein Port kann auch als Reaktion auf verschiedene Ereignisse getrennt werden. Siehe Lebenszyklus.

Dieses Muster kann verwendet werden, um zu kommunizieren zwischen:

Sie müssen unterschiedliche Verbindungs-APIs für unterschiedliche Arten von Verbindungen verwenden, wie in der folgenden Tabelle beschrieben.

Verbindungstyp Verbindungsversuch initiieren Verbindungsversuch handhaben
Hintergrundskript zu Inhaltsskript tabs.connect() runtime.onConnect
Inhaltsskript zu Hintergrundskript runtime.connect() runtime.onConnect
Erweiterung zu nativer Anwendung runtime.connectNative() Nicht anwendbar (siehe Native Messaging).
Erweiterung zu Erweiterung runtime.connect() runtime.onConnectExternal

Typ

Werte dieses Typs sind Objekte. Sie enthalten die folgenden Eigenschaften:

name

string. Der Name des Ports, definiert im runtime.connect()- oder tabs.connect()-Aufruf, der ihn erstellt hat. Wenn dieser Port mit einer nativen Anwendung verbunden ist, ist der Name der Name der nativen Anwendung.

disconnect

function. Trennt einen Port. Beide Enden können dies aufrufen, wenn sie den Port nicht mehr benötigen. Es wird onDisconnect am anderen Ende auslösen. Dies ist nützlich, wenn das andere Ende einen Status im Zusammenhang mit diesem Port verwaltet, der bei der Trennung bereinigt werden kann. Wenn dieser Port mit einer nativen Anwendung verbunden ist, wird diese Funktion die native Anwendung schließen.

error

object. Wenn der Port aufgrund eines Fehlers getrennt wurde, wird dies auf ein Objekt mit einer Zeichenketteneigenschaft message gesetzt, die Ihnen weitere Informationen über den Fehler gibt. Siehe onDisconnect.

onDisconnect

object. Dies enthält die addListener()- und removeListener()-Funktionen, die allen Ereignissen für Erweiterungen gemeinsam sind, die mit WebExtension-APIs erstellt wurden. Listener-Funktionen werden aufgerufen, wenn das andere Ende Port.disconnect() aufgerufen hat. Dieses Ereignis wird nur einmal für jeden Port ausgelöst. Der Listener-Funktion wird das Port-Objekt übergeben. Wenn der Port aufgrund eines Fehlers getrennt wurde, wird das Port-Argument eine error-Eigenschaft enthalten, die weitere Informationen über den Fehler gibt:

js
port.onDisconnect.addListener((p) => {
  if (p.error) {
    console.log(`Disconnected due to an error: ${p.error.message}`);
  }
});

Beachten Sie, dass in Google Chrome port.error nicht unterstützt wird: Verwenden Sie stattdessen runtime.lastError, um die Fehlermeldung zu erhalten.

onMessage

object. Dies enthält die addListener()- und removeListener()-Funktionen, die allen Ereignissen für Erweiterungen gemeinsam sind, die mit WebExtension-APIs erstellt wurden. Listener-Funktionen werden aufgerufen, wenn das andere Ende diesem Port eine Nachricht gesendet hat. Dem Listener wird der Wert übergeben, den das andere Ende gesendet hat.

postMessage

function. Sendet eine Nachricht an das andere Ende. Dies nimmt ein Argument, das ein serialisierbarer Wert ist (siehe Datenklonungsalgorithmus), der die Nachricht repräsentiert, die gesendet werden soll. Sie wird an jedes Script zugestellt, das auf das onMessage-Ereignis des Ports hört, oder an die native Anwendung, wenn dieser Port mit einer nativen Anwendung verbunden ist.

sender Optional

runtime.MessageSender. Enthält Informationen über den Absender der Nachricht. Diese Eigenschaft ist nur bei Ports vorhanden, die an onConnect/onConnectExternal-Listener übergeben werden.

Lebenszyklus

Der Lebenszyklus eines Port wird in den Chrome-Dokumenten beschrieben.

Es gibt jedoch einen wesentlichen Unterschied zwischen Firefox und Chrome, der sich aus der Tatsache ergibt, dass die runtime.connect- und tabs.connect-APIs Broadcast-Kanäle sind. Das bedeutet, dass möglicherweise mehr als ein Empfänger vorhanden ist, was zu Unklarheiten führt, wenn einer der Kontexte mit einem runtime.onConnect-Aufruf geschlossen wird. In Chrome bleibt ein Port so lange aktiv, wie es noch einen anderen Empfänger gibt. In Firefox wird der Port geschlossen, wenn einer der Kontexte entladen wird. Mit anderen Worten, die Trennungsbedingung,

  • Alle Frames, die den Port (über runtime.onConnect) erhalten haben, sind entladen worden.

die in Chrome gilt, wird in Firefox ersetzt durch

  • Ein Frame, der den Port (über runtime.onConnect) erhalten hat, ist entladen worden.

siehe Bug 1465514.

Browser-Kompatibilität

BCD tables only load in the browser

Beispiele

Verbindung von Inhaltsskripten

Dieses Inhaltsskript:

  • stellt eine Verbindung zum Hintergrundskript her und speichert den Port in einer Variablen namens myPort.
  • hört auf Nachrichten auf myPort und protokolliert sie.
  • sendet Nachrichten an das Hintergrundskript, unter Verwendung von myPort, wenn der Benutzer auf das Dokument klickt.
js
// content-script.js

let myPort = browser.runtime.connect({ name: "port-from-cs" });
myPort.postMessage({ greeting: "hello from content script" });

myPort.onMessage.addListener((m) => {
  console.log("In content script, received message from background script: ");
  console.log(m.greeting);
});

document.body.addEventListener("click", () => {
  myPort.postMessage({ greeting: "they clicked the page!" });
});

Das entsprechende Hintergrundskript:

  • hört auf Verbindungsversuche vom Inhaltsskript.

  • wenn es einen Verbindungsversuch erhält:

    • speichert den Port in einer Variablen namens portFromCS.
    • sendet dem Inhaltsskript eine Nachricht mit dem Port.
    • beginnt, ankommende Nachrichten auf dem Port zu hören und protokolliert diese.
  • sendet Nachrichten an das Inhaltsskript, unter Verwendung von portFromCS, wenn der Benutzer auf die Browser-Aktion der Erweiterung klickt.

js
// background-script.js

let portFromCS;

function connected(p) {
  portFromCS = p;
  portFromCS.postMessage({ greeting: "hi there content script!" });
  portFromCS.onMessage.addListener((m) => {
    console.log("In background script, received message from content script");
    console.log(m.greeting);
  });
}

browser.runtime.onConnect.addListener(connected);

browser.browserAction.onClicked.addListener(() => {
  portFromCS.postMessage({ greeting: "they clicked the button!" });
});

Mehrere Inhaltsskripte

Wenn Sie mehrere Inhaltsskripte haben, die gleichzeitig kommunizieren, möchten Sie möglicherweise jede Verbindung in einem Array speichern.

js
// background-script.js

let ports = [];

function connected(p) {
  ports[p.sender.tab.id] = p;
  // …
}

browser.runtime.onConnect.addListener(connected);

browser.browserAction.onClicked.addListener(() => {
  ports.forEach((p) => {
    p.postMessage({ greeting: "they clicked the button!" });
  });
});

Verbindung zu nativen Anwendungen

Dieses Beispiel verbindet sich mit der nativen Anwendung "ping_pong" und beginnt, Nachrichten von ihr zu empfangen. Es sendet der nativen Anwendung auch eine Nachricht, wenn der Benutzer auf ein Browser-Aktionssymbol klickt:

js
/*
On startup, connect to the "ping_pong" app.
*/
let port = browser.runtime.connectNative("ping_pong");

/*
Listen for messages from the app.
*/
port.onMessage.addListener((response) => {
  console.log(`Received: ${response}`);
});

/*
On a click on the browser action, send the app a message.
*/
browser.browserAction.onClicked.addListener(() => {
  console.log("Sending:  ping");
  port.postMessage("ping");
});

Hinweis: Diese API basiert auf Chromiums chrome.runtime API. Diese Dokumentation stammt von runtime.json im Chromium-Code.