由於content scripts執行在Web頁面的上下文中,屬於Web頁面的組成部分,而不是Google Chrome擴充套件程式。但是content scripts又往往需要與Google Chrome擴充套件程式的其他部分通訊以共享資料。
這可以通過訊息傳遞實現,通過彼此互相的訊息的監聽與反饋進行通訊。一個訊息可以包含任何有效的JSON物件,如null,boolean,number,string,array,object。
1) 一次性請求與響應模式
對於一次性請求與響應模式,chrome.runtime.sendMessage(obj, function(response){})是從content scripts發生請求訊息給Google Chrome擴充套件程式頁面。
從Google Chrome擴充套件程式頁面傳送請求訊息給content scripts的時候,需要給出當前tab的ID。
1 chrome.tabs.query( 2 {active: true, currentWindow: true}, 3 function(tabs) { 4 chrome.tabs.sendMessage( 5 tabs[0].id, 6 {greeting: "hello"}, 7 function(response) { 8 console.log(response.farewell); 9 }); 10 });
監聽訊息時,需要註冊要監聽的訊息。
1 chrome.runtime.onMessage.addListener( 2 function(request, sender, sendResponse) { 3 console.log(sender.tab ? 4 "from a content script:" + sender.tab.url : 5 "from the extension"); 6 if (request.greeting == "hello")//判斷是否為要處理的訊息 7 sendResponse({farewell: "goodbye"}); 8 });
注意:如果為同一個訊息註冊了多個監聽器,則只有第一個監聽器能夠呼叫sendResponse()方法,其他的監聽器將被忽略。
2) 保持長期連線的模式
對於保持長期連線的模式,在content scripts與Chrome擴充套件程式頁面之間建立通道(可以為通道命名),可以處理多個訊息。在通道的兩端分別擁有一個chrome.runtime.Port物件,用以收發訊息。
在content scripts主動建立通道如下:
1 var port = chrome.runtime.connect({name: "yisheng"});//通道名稱 2 port.postMessage({joke: "Knock knock"});//傳送訊息 3 port.onMessage.addListener(function(msg) {//監聽訊息 4 if (msg.question == "Who's there?") 5 port.postMessage({answer: "yisheng"}); 6 else if (msg.question == "Madame who?") 7 port.postMessage({answer: "Madame... Bovary"}); 8 });
在Google Chrome擴充套件程式頁面主動建立通道如下:
1 chrome.tabs.query( 2 {active: true, currentWindow: true}, 3 function(tabs) { 4 var port = chrome.tabs.connect(//建立通道 5 tabs[0].id, 6 {name: "yisheng"}//通道名稱 7 ); 8 });
在content scripts或Google Chrome擴充套件程式頁面,監聽建立連線的請求如下:
1 chrome.runtime.onConnect.addListener(function(port) { 2 console.assert(port.name == "yisheng"); 3 port.onMessage.addListener(function(msg) { 4 if (msg.joke == "Knock knock") 5 port.postMessage({question: "Who's there?"}); 6 else if (msg.answer == "Madame") 7 port.postMessage({question: "Madame who?"}); 8 else if (msg.answer == "Madame... Bovary") 9 port.postMessage({question: "I don't get it."}); 10 }); 11 });
在content scripts或Google Chrome擴充套件程式頁面的任一端,呼叫chrome.runtime.Port.disconnect()則關閉連線,同時出發disconnect事件。這時,只有另一端監聽chrome.runtime.Port.onDisconnect事件,則可以知道連線關閉。
3) Google Chrome擴充套件程式之間訊息模式
還可以在不同的Google Chrome擴充套件程式之間傳送訊息,只要知道Google Chrome擴充套件程式的ID。這使得Google Chrome擴充套件程式可以釋出服務為其他擴充套件程式所用。
這種Google Chrome擴充套件程式之間的訊息也分為一次性請求與響應模式和保持長期連線的模式。
Google Chrome擴充套件程式監聽呼叫其服務的訊息如下:
1 //一次性請求與響應模式: 2 chrome.runtime.onMessageExternal.addListener( 3 function(request, sender, sendResponse) { 4 if (sender.id == blacklistedExtension)//黑名單 5 return; // don't allow this extension access 6 else if (request.getTargetData) 7 sendResponse({targetData: targetData}); 8 else if (request.activateLasers) { 9 var success = activateLasers(); 10 sendResponse({activateLasers: success}); 11 } 12 }); 13 14 //保持長期連線的模式: 15 chrome.runtime.onConnectExternal.addListener(function(port) { 16 port.onMessage.addListener(function(msg) { 17 // See other examples for sample onMessage handlers. 18 }); 19 });
傳送呼叫服務的訊息如下:
1 // The ID of the extension we want to talk to. 2 var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc"; 3 4 // Make a simple request: 5 chrome.runtime.sendMessage(laserExtensionId, {getTargetData: true}, 6 function(response) { 7 if (targetInRange(response.targetData)) 8 chrome.runtime.sendMessage(laserExtensionId, {activateLasers: true}); 9 }); 10 11 // Start a long-running conversation: 12 var port = chrome.runtime.connect(laserExtensionId); 13 port.postMessage(...);
4) Google Chrome擴充套件程式接收指定的Web頁面傳送的訊息
Google Chrome擴充套件程式可以與一些指定地點Web頁面直接收發訊息。
首先,在Google Chrome擴充套件程式的manifest.json檔案設定可以通訊的Web頁面範圍:
1 "externally_connectable": { 2 "matches": ["*://*.example.com/*"] 3 }
其次,在Google Chrome擴充套件程式中監聽Web頁面的訊息如下:
1 chrome.runtime.onMessageExternal.addListener( 2 function(request, sender, sendResponse) { 3 if (sender.url == blacklistedWebsite) 4 return; // don't allow this web page access 5 if (request.openUrlInEditor) 6 openUrl(request.openUrlInEditor); 7 });
最後,在指定的Web頁面中,傳送訊息如下:
1 // The ID of the extension we want to talk to. 2 var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc"; 3 4 // Make a simple request: 5 chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url}, 6 function(response) { 7 if (!response.success) 8 handleError(url); 9 });