runtime.Port
Ein Port
-Objekt repräsentiert ein Ende einer Verbindung zwischen zwei bestimmten Kontexten, die zum Austausch von Nachrichten verwendet werden können.
Eine Seite initiiert die Verbindung durch die Verwendung einer connect()
-API. Dies gibt ein Port
-Objekt zurück. Die andere Seite hört nach Verbindungsversuchen mit einem onConnect
-Listener. Dieser wird mit einem entsprechenden Port
-Objekt übergeben.
Sobald beide Seiten Port
-Objekte haben, können sie Nachrichten mithilfe von Port.postMessage()
und Port.onMessage
austauschen. Wenn sie fertig sind, kann jede Seite die Verbindung mit Port.disconnect()
trennen, was auf der anderen Seite ein Port.onDisconnect
-Ereignis erzeugt, das es der anderen Seite ermöglicht, alle erforderlichen Aufräumarbeiten durchzuführen.
Ein Port
kann auch in Reaktion auf verschiedene Ereignisse getrennt werden. Siehe Lebenszyklus.
Sie können dieses Muster verwenden, um zwischen Folgendem zu kommunizieren:
- Verschiedene Teile Ihrer Erweiterung (zum Beispiel zwischen Content Scripts und Background Scripts)
- Zwischen Ihrer Erweiterung und einer nativ auf dem Computer des Benutzers laufenden Anwendung.
- Zwischen Ihrer Erweiterung und einer anderen Erweiterung
Verschiedene Verbindungs-APIs müssen für verschiedene Verbindungstypen verwendet werden, wie in der folgenden Tabelle beschrieben.
Verbindungstyp | Verbindungsversuch initiieren | Verbindungsversuch bearbeiten |
---|---|---|
Background Script zu Content Script | tabs.connect() |
runtime.onConnect |
Content Script zu Background Script | 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 imruntime.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 sind. Es wird bewirken, dassonDisconnect
auf der anderen Seite ausgelöst wird. Dies ist nützlich, wenn die andere Seite einen Status in Bezug auf diesen Port aufrechterhält, der beim Trennen bereinigt werden kann. Wenn dieser Port mit einer nativen Anwendung verbunden ist, schließt diese Funktion die native Anwendung. error
-
object
. Wenn der Port aufgrund eines Fehlers getrennt wurde, wird dies auf ein Objekt mit einer Zeichenfolgeigenschaftmessage
gesetzt, die Ihnen mehr Informationen über den Fehler gibt. SieheonDisconnect
. onDisconnect
-
object
. Dies enthält dieaddListener()
- undremoveListener()
-Funktionen, die allen Ereignissen gemein sind, die mit den WebExtension-APIs erstellt wurden. 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 mit weiteren Informationen zum Fehler: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: Verwenden Sie stattdessenruntime.lastError
, um die Fehlermeldung zu erhalten. onMessage
-
object
. Dies enthält dieaddListener()
- undremoveListener()
-Funktionen, die allen Ereignissen gemein sind, die mit den WebExtension-APIs erstellt wurden. Listener-Funktionen werden aufgerufen, wenn die andere Seite diesem Port eine Nachricht gesendet hat. Dem Listener wird der Wert übergeben, den die andere Seite gesendet hat. postMessage
-
function
. Sendet eine Nachricht an die andere Seite. Dies nimmt ein Argument an, das ein serialisierbarer Wert ist (siehe Datenklon-Algorithmus), der die zu sendende Nachricht darstellt. Es wird an jedes Skript geliefert, 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 auf Ports vorhanden, die an dieruntime.onConnect
,runtime.onConnectExternal
, oderruntime.onUserScriptConnect
-Listener übergeben werden.
Lebenszyklus
Der Lebenszyklus eines Port
wird in den Chrome-Dokumenten beschrieben.
Es gibt jedoch einen wichtigen Unterschied zwischen Firefox und Chrome, der daraus resultiert, dass die runtime.connect
- und tabs.connect
-APIs als Broadcast-Kanäle fungieren. Dies 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 aktiv, solange es noch einen anderen Empfänger gibt. In Firefox schließt sich der Port, wenn einer der Kontexte entladen wird. Mit anderen Worten, die Bedingung für die Trennung,
- Alle Frames, die den Port empfangen haben (über
runtime.onConnect
), sind entladen worden.
die in Chrome gilt, wird ersetzt durch
- Ein beliebiger Frame, der den Port empfangen hat (über
runtime.onConnect
), ist entladen worden.
in Firefox (siehe Fehler 1465514).
Browser-Kompatibilität
Beispiele
Verbindung von Content Scripts
Dieses Content Script:
- verbindet sich mit dem Background Script und speichert den
Port
in einer Variablen namensmyPort
. - hört auf Nachrichten auf
myPort
und protokolliert sie. - sendet Nachrichten an das Background Script, indem es
myPort
verwendet, 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 Background Script:
-
hört auf Verbindungsversuche des Content Scripts.
-
wenn es einen Verbindungsversuch erhält:
- speichert den Port in einer Variablen namens
portFromCS
. - sendet dem Content Script eine Nachricht mit dem Port.
- beginnt, auf Nachrichten zu hören, die über den Port empfangen werden, und protokolliert sie.
- speichert den Port in einer Variablen namens
-
sendet Nachrichten an das Content Script, indem es
portFromCS
verwendet, wenn der Benutzer auf die Browser-Aktion 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 Content Scripts
Wenn Sie mehrere Content Scripts haben, die gleichzeitig 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, auf Nachrichten von dieser zu hören. Es sendet der nativen Anwendung auch eine Nachricht, wenn der Benutzer auf ein Browser-Aktionssymbol 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 Chromium's chrome.runtime
API. Diese Dokumentation ist abgeleitet von runtime.json
im Chromium-Code.