runtime.Port
A Port
object represents one end of a connection between two specific contexts, which can be used to exchange messages.
One side initiates the connection, using a connect()
API. This returns a Port
object. The other side listens for connection attempts using an onConnect
listener. This is passed a corresponding Port
object.
Once both sides have Port
objects, they can exchange messages using Port.postMessage()
and Port.onMessage
. When they are finished, either end can disconnect using Port.disconnect()
, which will generate a Port.onDisconnect
event at the other end, enabling the other end to do any cleanup required.
A Port
can also become disconnected in response to various events. See Lifecycle.
You can use this pattern to communicate between
- different parts of your extension (for example, between content scripts and background scripts)
- between your extension and a native application running on the user's computer.
- between your extension and a different extension
You need to use different connection APIs for different sorts of connections, as detailed in the table below.
连接类型 | 发起连接尝试 | 处理连接尝试 |
---|---|---|
后台脚本到内容脚本 | tabs.connect() |
runtime.onConnect |
内容脚本到后台脚本 | runtime.connect() |
runtime.onConnect |
扩展到原生应用程序 | runtime.connectNative() |
不适用(请参阅 原生消息传递)。 |
扩展到扩展 | runtime.connect() |
runtime.onConnectExternal |
类型
Values of this type are objects. They contain the following properties
name
-
string
. The port's name, defined in theruntime.connect()
ortabs.connect()
call that created it. If this port is connected to a native application, its name is the name of the native application. disconnect
-
function
. Disconnects a port. Either end can call this when they have finished with the port. It will causeonDisconnect
to be fired at the other end. This is useful if the other end is maintaining some state relating to this port, which can be cleaned up on disconnect. If this port is connected to a native application, this function will close the native application. error
-
object
. If the port was disconnected due to an error, this will be set to an object with a string propertymessage
, giving you more information about the error. SeeonDisconnect
. onDisconnect
-
object
. This contains theaddListener()
andremoveListener()
functions common to all events for extensions built using WebExtension APIs. Listener functions will be called when the other end has calledPort.disconnect()
. This event will only be fired once for each port. The listener function will be passed thePort
object. If the port was disconnected due to an error, then thePort
argument will contain anerror
property giving more information about the errorjsport.onDisconnect.addListener((p) => { if (p.error) { console.log(`Disconnected due to an error: ${p.error.message}`); } });
Note that in Google Chrome
port.error
is not supported: instead, useruntime.lastError
to get the error message. onMessage
-
object
. This contains theaddListener()
andremoveListener()
functions common to all events for extensions built using WebExtension APIs. Listener functions will be called when the other end has sent this port a message. The listener will be passed the value that the other end sent. postMessage
-
function
. Send a message to the other end. This takes one argument, which is a serializable value (see Data cloning algorithm) representing the message to send. It will be delivered to any script listening to the port'sonMessage
event, or to the native application if this port is connected to a native application. sender
可选-
runtime.MessageSender
. Contains information about the sender of the message. This property will only be present on ports passed toonConnect
/onConnectExternal
listeners.
生命周期
The lifecycle of a Port
is described in the Chrome docs.
There is, however, one important difference between Firefox and Chrome, stemming from the fact that the runtime.connect
and tabs.connect
APIs are broadcast channels. This means that there may be potentially more than one recipient, and this results in ambiguity when one of the contexts with a runtime.onConnect
call is closed. In Chrome, a port stays active as long as there is any other recipient. In Firefox, the port closes when any of the contexts unloads. In other words, the disconnection condition,
- All frames that received the port (via
runtime.onConnect
) have unloaded.
which holds in Chrome, is replaced by
- Any frame that received the port (via
runtime.onConnect
) has unloaded.
in Firefox (see bug 1465514).
浏览器兼容性
BCD 表格仅在浏览器中加载
示例
从内容脚本连接
此内容脚本
- 连接到后台脚本并存储
Port
到名为myPort
的变量中。 - 在
myPort
上监听消息并记录它们。 - 当用户点击文档时,使用
myPort
向后台脚本发送消息。
// 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!" });
});
相应的后台脚本
- 监听来自内容脚本的连接尝试。
- 当收到连接尝试时
- 将端口存储在一个名为
portFromCS
的变量中。 - 使用该端口向内容脚本发送消息。
- 开始监听接收到的端口消息,并记录它们。
- 将端口存储在一个名为
- 当用户点击扩展的浏览器操作时,使用
portFromCS
向内容脚本发送消息。
// 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!" });
});
多个内容脚本
如果您有多个内容脚本同时通信,您可能希望将每个连接存储在一个数组中。
// 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!" });
});
});
连接到原生应用程序
此示例连接到原生应用程序“ping_pong”并开始监听来自它的消息。它还会在用户点击浏览器操作图标时向原生应用程序发送消息。
/*
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");
});
注意: 此 API 基于 Chromium 的 chrome.runtime
API。 此文档源自 Chromium 代码中的 runtime.json
。