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 mit einem entsprechenden Port
-Objekt übergeben.
Sobald beide Seiten Port
-Objekte haben, können sie Nachrichten über Port.postMessage()
und Port.onMessage
austauschen. Wenn sie fertig sind, kann jede Seite die Verbindung mit Port.disconnect()
trennen, was ein Port.onDisconnect
-Ereignis am anderen Ende erzeugt und es dem anderen Ende ermöglicht, alle erforderlichen Aufräumarbeiten durchzuführen.
Ein Port
kann auch in Reaktion auf verschiedene Ereignisse getrennt werden. Siehe Lifecycle.
Sie können dieses Muster verwenden, um zwischen folgenden zu kommunizieren:
- verschiedene Teile Ihrer Erweiterung (z. B. zwischen Inhaltsskripten und Hintergrundskripten)
- zwischen Ihrer Erweiterung und einer nativen Anwendung, die auf dem Computer des Benutzers läuft.
- zwischen Ihrer Erweiterung und einer anderen Erweiterung
Für verschiedene Verbindungen müssen Sie unterschiedliche Verbindungs-APIs verwenden, wie in der Tabelle unten beschrieben.
Verbindungstyp | Verbindungsversuch initiieren | Verbindungsversuch behandeln |
---|---|---|
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 in demruntime.connect()
odertabs.connect()
Aufruf, der ihn erstellt hat. Wenn dieser Port mit einer nativen Anwendung verbunden ist, ist sein Name der Name der nativen Anwendung. disconnect
-
function
. Trennt einen Port. Jede Seite kann dies aufrufen, wenn sie mit dem Port fertig ist. Dies wirdonDisconnect
am anderen Ende auslösen. Dies ist nützlich, wenn das andere Ende einen Zustand in Bezug auf diesen Port verwaltet, der bei einer 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 String-Eigenschaftmessage
gesetzt, die Ihnen mehr Informationen über den Fehler gibt. SieheonDisconnect
. onDisconnect
-
object
. Dies enthält dieaddListener()
undremoveListener()
Funktionen, die allen Ereignissen für mit WebExtension APIs erstellte Erweiterungen gemeinsam sind. Listener-Funktionen werden aufgerufen, wenn das andere EndePort.disconnect()
aufgerufen hat. Dieses Ereignis wird nur einmal für jeden Port ausgelöst. Der Listener wird dasPort
-Objekt übergeben. Wenn der Port aufgrund eines Fehlers getrennt wurde, enthält dasPort
-Argument eineerror
-Eigenschaft, die weitere Informationen über den Fehler gibt:jsport.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: Stattdessen verwenden Sieruntime.lastError
, um die Fehlermeldung zu erhalten. onMessage
-
object
. Dies enthält dieaddListener()
undremoveListener()
Funktionen, die allen Ereignissen für mit WebExtension APIs erstellte Erweiterungen gemeinsam sind. Listener-Funktionen werden aufgerufen, wenn das andere Ende diesem Port eine Nachricht gesendet hat. Der Listener wird den Wert übergeben, den das andere Ende gesendet hat. postMessage
-
function
. Sendet eine Nachricht an das andere Ende. Dies erfordert ein Argument, welches einen serialisierbaren Wert darstellt (siehe Datenklon-Algorithmus) und die Nachricht repräsentiert, die gesendet werden soll. Sie wird an jedes Skript übermittelt, das auf dasonMessage
-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. Nur bei Ports vorhanden, die an dieruntime.onConnect
,runtime.onConnectExternal
, oderruntime.onUserScriptConnect
Listener übergeben werden.
Lebenszyklus
Der Lebenszyklus eines Port
ist in den Chrome-Dokumenten beschrieben.
Es gibt jedoch einen wichtigen Unterschied zwischen Firefox und Chrome, der darauf beruht, dass die runtime.connect
- und tabs.connect
-APIs Broadcast-Kanäle sind. Das bedeutet, dass es potenziell mehr als einen Empfänger geben kann, was zu Mehrdeutigkeiten führt, wenn einer der Kontexte mit einem runtime.onConnect
-Aufruf geschlossen wird. In Chrome bleibt ein Port so lange aktiv, wie es einen anderen Empfänger gibt. In Firefox wird der Port geschlossen, wenn einer der Kontexte entladen wird. Anders ausgedrückt, die Trennungsbedingung,
- Alle Frames, die den Port erhielten (über
runtime.onConnect
), sind entladen.
die in Chrome gilt, wird in Firefox durch
- Irgendein Frame, der den Port empfing (über
runtime.onConnect
), ist entladen.
ersetzt (siehe Bug 1465514).
Browser-Kompatibilität
Beispiele
Verbindung aus Inhaltsskripten aufbauen
Dieses Inhaltsskript:
- verbindet sich mit dem Hintergrundskript und speichert den
Port
in einer Variablen namensmyPort
. - wartet auf Nachrichten auf
myPort
und protokolliert sie. - sendet Nachrichten an das Hintergrundskript, unter Verwendung von
myPort
, wenn der Benutzer auf das Dokument klickt.
// 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:
-
wartet auf Verbindungsversuche des Inhaltsskripts.
-
wenn es einen Verbindungsversuch erhält:
- speichert den Port in einer Variablen namens
portFromCS
. - sendet dem Inhaltsskript eine Nachricht mittels des Ports.
- beginnt, Nachrichten zu empfangen, die auf dem Port empfangen werden, und protokolliert sie.
- speichert den Port in einer Variablen namens
-
sendet Nachrichten an das Inhaltsskript, unter Verwendung von
portFromCS
, wenn der Benutzer auf die Browseraktion der Erweiterung klickt.
// 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 vielleicht jede Verbindung in einem Array speichern.
// 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 aufbauen
Dieses Beispiel verbindet sich mit der nativen Anwendung "ping_pong" und beginnt, Nachrichten von ihr zu empfangen. Es sendet auch eine Nachricht an die native Anwendung, wenn der Benutzer auf ein Browseraktionssymbol klickt:
/*
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 der chrome.runtime
-API von Chromium. Diese Dokumentation stammt aus runtime.json
im Chromium-Code.