由於內容指令碼是在網頁環境中執行,而不是擴充功能,因此通常需要一些程式碼。 可讓您與擴充功能的其他部分通訊舉例來說,RSS 閱讀器擴充功能可能會使用 內容指令碼,偵測網頁上是否有 RSS 動態消息,然後通知背景網頁 即可顯示該網頁的網頁動作圖示。
擴充功能及其內容指令碼之間的通訊方式,是透過訊息傳送功能運作。兩者皆可 對方可以聆聽對方傳送的訊息,並在同一管道回覆。訊息可以 包含任何有效的 JSON 物件 (空值、布林值、數字、字串、陣列或物件)。做法很簡單 適用於一次性要求的 API 和更複雜的 API,可讓您使用長效型 API 連線,透過共用情境交換多則訊息。您也可以 如果您知道這個擴充功能的 ID,請參閱跨擴充功能 訊息」一節。
簡單的一次性要求
如果您只需要將一則訊息傳送至擴充功能的其他部分 (並且視需要 回應),您應使用簡化的 runtime.sendMessage 或 tabs.sendMessage。 這可讓您從內容指令碼將一次性的 JSON 序列化訊息傳送至擴充功能 (或從延伸) 。可選用的回呼參數可讓您處理來自 如果有的話。
從內容指令碼傳送要求看起來會像這樣:
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
從擴充功能傳送要求到內容指令碼看起來非常相似,但您必須 指定要傳送至哪個分頁。這個範例示範如何傳送訊息至內容指令碼 就在所選分頁中
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
在接收端,您需要設定 runtime.onMessage 事件監聽器來處理 撰寫新的電子郵件訊息這和內容指令碼或擴充功能網頁看起來相同。
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
}
);
在上述範例中,系統已同步呼叫 sendResponse
。如果想以非同步方式
sendResponse
,將 return true;
新增至 onMessage
事件處理常式。
true
表示將以非同步方式回應時,sendResponse
回呼才有效。如果沒有處理常式傳回 true,或者 sendResponse
回呼是垃圾收集,則系統會自動叫用 sendMessage
函式的回呼。長期連線
聊天室的持續時間比單一要求和回應長,有時候有幫助。 在這個情況下,您可以從內容指令碼開啟一個長效頻道,然後開啟擴充功能頁面 或分別使用 runtime.connect 或 tabs.connect。管道可以 選擇性名稱,方便您區分不同類型的連線。
其中一個用途可能是自動填寫表單額外資訊。內容指令碼可以開啟頻道 取得特定登入資訊的擴充功能頁面,並針對每個輸入內容將訊息傳送至擴充功能 元素,要求表單資料填寫。共用連線可讓擴充功能 保持共用狀態連結內容指令碼中的數則訊息。
建立連線時,每個端點都會獲得一個 runtime.Port 物件,用於 透過該連線收發訊息
以下說明如何透過內容指令碼開啟頻道,以及傳送及監聽訊息:
var port = chrome.runtime.connect({name: "knockknock"});
port.postMessage({joke: "Knock knock"});
port.onMessage.addListener(function(msg) {
if (msg.question == "Who's there?")
port.postMessage({answer: "Madame"});
else if (msg.question == "Madame who?")
port.postMessage({answer: "Madame... Bovary"});
});
從擴充功能傳送要求到內容指令碼看起來非常相似,但您必須 指定要連結的分頁。只要將上述呼叫取代為 tabs.connect.
為了處理連入連線,您必須設定 runtime.onConnect 事件 接聽程式。這在內容指令碼或擴充功能網頁中看起來相同。如果網站的其他部分 擴充功能呼叫「connect()」、引發此事件,以及您可以下載的 runtime.Port 物件 用於透過該連線收發訊息。以下是回應內容 連入連線:
chrome.runtime.onConnect.addListener(function(port) {
console.assert(port.name == "knockknock");
port.onMessage.addListener(function(msg) {
if (msg.joke == "Knock knock")
port.postMessage({question: "Who's there?"});
else if (msg.answer == "Madame")
port.postMessage({question: "Madame who?"});
else if (msg.answer == "Madame... Bovary")
port.postMessage({question: "I don't get it."});
});
});
通訊埠生命週期
連接埠是專用於擴充功能各部分之間的雙向通訊方式, 畫面最小化成一個 (頂層) 頁框。 呼叫 tabs.connect、runtime.connect 或 runtime.connectNative、Port 時 即可透過這個通訊埠,立即透過該通訊埠傳送訊息至另一端, postMessage。
如果分頁中有多個影格,呼叫 tabs.connect 即可多次叫用 runtime.onConnect 事件 (分頁中每個影格一次)。同樣地, 如果使用 runtime.connect,可能會多次觸發 onConnect 事件 (每 擷取頁框)。
您可能會想瞭解連線關閉的時間,例如為了維護 狀態。為此,您可以監聽 runtime.Port.onDisconnect 事件。這個 事件就會引發事件。這會發生在 下列情況:
- 另一端沒有 runtime.onConnect 的事件監聽器。
- 含有通訊埠的分頁已卸載 (例如,分頁是否正在瀏覽)。
- 呼叫
connect
的影格已卸載。 - 所有接收通訊埠 (透過 runtime.onConnect) 的影格均已卸載。
- 由另一端呼叫 runtime.Port.disconnect。請注意,如果
connect
呼叫結果 且該通訊埠在其中一個通訊埠上呼叫disconnect()
,然後onDisconnect
事件只會在傳送者的通訊埠上觸發,在其他通訊埠上則不會。
跨額外資訊訊息功能
除了在擴充功能中的不同元件之間傳送訊息之外,您還可以使用 訊息 API,以便與其他擴充功能通訊。這樣您就能向其他使用者公開 也能使用額外資訊
監聽傳入的要求和連線與內部案例類似,差別在於可以使用 runtime.onMessageExternal 或 runtime.onConnectExternal 方法。這裡舉例說明 每個:
// For simple requests:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.id == blocklistedExtension)
return; // don't allow this extension access
else if (request.getTargetData)
sendResponse({targetData: targetData});
else if (request.activateLasers) {
var success = activateLasers();
sendResponse({activateLasers: success});
}
});
// For long-lived connections:
chrome.runtime.onConnectExternal.addListener(function(port) {
port.onMessage.addListener(function(msg) {
// See other examples for sample onMessage handlers.
});
});
同樣地,傳送訊息到其他擴充功能就如同在您的額外資訊中傳送。 唯一的差別在於,您必須傳遞要通訊的擴充功能 ID。例如:
// The ID of the extension we want to talk to.
var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
// Make a simple request:
chrome.runtime.sendMessage(laserExtensionId, {getTargetData: true},
function(response) {
if (targetInRange(response.targetData))
chrome.runtime.sendMessage(laserExtensionId, {activateLasers: true});
}
);
// Start a long-running conversation:
var port = chrome.runtime.connect(laserExtensionId);
port.postMessage(...);
從網頁傳送訊息
如同跨擴充功能傳訊,您的應用程式或擴充功能可以接收及回覆 。如要使用這項功能,您必須先在 manifest.json 中指定 可讓您進行通訊的網站。例如:
"externally_connectable": {
"matches": ["*://*.example.com/*"]
}
如此一來,凡是與指定網址模式相符的網頁,都能看到訊息 API。網址 模式至少須包含一個第二層網域,也就是主機名稱模式,例如「*」、「 「*.com」、「*.co.uk」和「*.appspot.com」。只要在網頁上使用 runtime.sendMessage 或 runtime.connect API 可讓您傳送訊息至特定應用程式或 。例如:
// The ID of the extension we want to talk to.
var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
// Make a simple request:
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
function(response) {
if (!response.success)
handleError(url);
});
你可以透過應用程式或擴充功能,聆聽來自網頁的訊息 runtime.onMessageExternal 或 runtime.onConnectExternalAPI,與 跨擴充功能類似 訊息只有網頁可以啟動連線。範例如下:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.url == blocklistedWebsite)
return; // don't allow this web page access
if (request.openUrlInEditor)
openUrl(request.openUrlInEditor);
});
內建訊息傳遞功能
凡是已註冊註冊為裝置的原生應用程式,都可以交換訊息和應用程式 內建訊息傳遞主機。如要進一步瞭解這項功能,請參閱原生訊息傳遞。
安全性考量
內容指令碼較不可靠
內容指令碼不可靠,比擴充功能背景網頁更可靠 (例如惡意網路) 網頁可能會破壞內容指令碼執行的轉譯器程序)。假設 內容指令碼中的訊息可能是由攻擊者製作,因此請務必驗證並驗證 處理所有輸入內容。假設傳送到內容指令碼的任何資料都可能流向網頁。 限制內容從內容收到的訊息可觸發的權限動作範圍 指令碼
跨網站指令碼攻擊
收到內容指令碼或其他擴充功能傳來的訊息時,請務必謹慎處理指令碼 不會因此落於跨網站指令碼攻擊的情況下遭受受害者。這項建議適用於 擴充功能背景頁面以及在其他網路來源內執行的內容指令碼。 具體來說,請避免使用危險的 API,例如下列 API:
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
// WARNING! Might be evaluating an evil script!
var resp = eval("(" + response.farewell + ")");
});
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
// WARNING! Might be injecting a malicious script!
document.getElementById("resp").innerHTML = response.farewell;
});
請改為使用不會執行指令碼的更安全的 API:
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
// JSON.parse does not evaluate the attacker's scripts.
var resp = JSON.parse(response.farewell);
});
chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
// innerText does not let the attacker inject HTML elements.
document.getElementById("resp").innerText = response.farewell;
});
範例
您可以在 examples/api/訊息 aging 中找到透過訊息溝通的簡單範例。 目錄。內建訊息功能範例示範 Chrome 應用程式如何與 原生應用程式如需更多範例及瞭解如何查看原始碼,請參閱範例。