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 mithilfe der connect()
-API. Dies gibt ein Port
-Objekt zurück. Die andere Seite horcht auf Verbindungsversuche mit einem onConnect
-Listener. Diesem wird ein entsprechendes Port
-Objekt übergeben.
Sobald beide Seiten über Port
-Objekte verfügen, können sie Nachrichten mit Port.postMessage()
und Port.onMessage
austauschen. Wenn sie fertig sind, kann jede Seite die Verbindung mit Port.disconnect()
trennen, was ein Port.onDisconnect
-Ereignis auf der anderen Seite auslöst, so dass die andere Seite alle erforderlichen Aufräumarbeiten durchführen kann.
Ein Port
kann auch infolge verschiedener Ereignisse getrennt werden. Siehe Lebenszyklus.
Dieses Muster kann zur Kommunikation zwischen:
- verschiedenen Teilen Ihrer Erweiterung verwendet werden (zum Beispiel zwischen Inhaltsskripten und Hintergrundskripten)
- zwischen Ihrer Erweiterung und einer auf dem Computer des Nutzers laufenden nativen Anwendung.
- zwischen Ihrer Erweiterung und einer anderen Erweiterung
Sie müssen unterschiedliche Verbindungsschnittstellen-APIs für verschiedene Arten von Verbindungen verwenden, wie in der folgenden Tabelle beschrieben.
Verbindungstyp | Verbindungsversuch initiieren | Verbindungsversuch verarbeiten |
---|---|---|
Hintergrundskript zu Inhaltsskript | tabs.connect() |
runtime.onConnect |
Inhaltsskript zu Hintergrundskript | runtime.connect() |
runtime.onConnect |
Erweiterung zu nativer Anwendung | runtime.connectNative() |
Nicht zutreffend (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 Aufruf vonruntime.connect()
odertabs.connect()
, 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. Dadurch wirdonDisconnect
auf der anderen Seite ausgelöst. Dies ist nützlich, wenn die andere Seite einen Zustand in Bezug auf diesen Port aufrechterhält, der beim Trennen der Verbindung 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, das weitere Informationen über den Fehler gibt. SieheonDisconnect
. onDisconnect
-
object
. Dies enthält die FunktionenaddListener()
undremoveListener()
, die allen Ereignissen für Erweiterungen, die die WebExtension-APIs verwenden, gemeinsam sind. Listener-Funktionen werden aufgerufen, wenn die andere SeitePort.disconnect()
aufgerufen hat. Dieses Ereignis wird nur einmal für jeden Port ausgelöst. Der Listener-Funktion 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 die FunktionenaddListener()
undremoveListener()
, die allen Ereignissen für Erweiterungen, die die WebExtension-APIs verwenden, gemeinsam sind. Listener-Funktionen werden aufgerufen, wenn die andere Seite diesem Port eine Nachricht gesendet hat. Der Listener wird der Wert übergeben, den die andere Seite gesendet hat. postMessage
-
function
. Sendet eine Nachricht an die andere Seite. Dies nimmt ein Argument, das einen serialisierbaren Wert darstellt (siehe Datenduplizierungs-Algorithmus), der die zu sendende Nachricht repräsentiert. Es 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 vorhanden bei Ports, die den
,runtime.onConnect
runtime.onConnectExternal
oder `runtime.onUserScriptConnect
-Listenern übergeben werden.
Lebenszyklus
Der Lebenszyklus eines Port
ist in den Chrome-Dokumenten beschrieben.
Es gibt jedoch einen wichtigen Unterschied zwischen Firefox und Chrome, der sich daraus ergibt, dass die runtime.connect
- und tabs.connect
-APIs als Broadcast-Kanäle fungieren. Dies bedeutet, dass es möglicherweise mehr als einen Empfänger gibt, was zu Mehrdeutigkeiten führt, wenn einer der Kontexte mit einem runtime.onConnect
-Aufruf geschlossen wird. In Chrome bleibt ein Port aktiv, solange es einen anderen Empfänger gibt. In Firefox wird der Port geschlossen, wenn einer der Kontexte entladen wird. Mit anderen Worten, die Bedingung zum Trennen der Verbindung,
- Alle Frames, die den Port (über
runtime.onConnect
) empfangen haben, wurden entladen.
was in Chrome gilt, wird durch
- Irgendein Frame, das den Port (über
runtime.onConnect
) empfangen hat, wurde entladen.
in Firefox ersetzt (siehe Fehler 1465514).
Beispiele
Verbindung von Inhaltsskripten
Dieses Inhaltsskript:
- verbindet sich mit dem Hintergrundskript und speichert den
Port
in einer Variablen namensmyPort
. - hört auf Nachrichten auf
myPort
und protokolliert sie. - sendet Nachrichten an das Hintergrundskript, indem es
myPort
verwendet, wenn der Nutzer 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:
-
horcht auf Verbindungsversuche vom Inhaltsskript.
-
wenn es einen Verbindungsversuch erhält:
- speichert es den Port in einer Variablen namens
portFromCS
. - sendet es dem Inhaltsskript eine Nachricht über den Port.
- beginnt es, auf empfangene Nachrichten über den Port zu hören und protokolliert sie.
- speichert es den Port in einer Variablen namens
-
sendet Nachrichten an das Inhaltsskript, indem es
portFromCS
verwendet, wenn der Nutzer 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 gleichzeitig mehrere Inhaltsskripte haben, die kommunizieren, möchten Sie möglicherweise 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
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 Nutzer ein Browseraktions-Icon 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");
});
Browser-Kompatibilität
Hinweis:
Diese API basiert auf Chromium's chrome.runtime
API. Diese Dokumentation stammt aus runtime.json
im Chromium-Code.