Обмен сообщениями между веб страницей и расширением в браузере chrome
Расширения chrome (chrome extentions) могут взаимодействовать с веб страницами, для которых они загружаются. Для этой цели в модели программирования расширений используется специальное промежуточное звено - подгружаемый скрипт расширения (content script). Этот скрипт может взаимодействовать с элементами объектной модели документа (DOM) веб страницы, в которую он подгружен. То есть, можно вызвать из него метод document.getElementById и читать и менять свойства любого элемента. Но из этого скрипта нельзя вызывать методы сценариев, используемых на веб странице, и из javascript сценариев на веб странице нельзя вызывать методы в этом скрипте.
Для организации взаимодействия на уровне вызова процедур между веб страницей и скриптом используется междоменная модель обмена сообщениями html5. Сообщения посылаются с помощью метода window.postMessage(), а ловятся с помощью обработчика события message - window.addEventListener("message", function(event) {...}. Код работает одинаково на стороне веб страницы и скрипта.
Content script не имеет доступа к большинству API, доступных для основного кода расширения (Background script), ему доступно только несколько методов из подмножества chrome.extension.*, с помощью которых он может взаимодействовать с основным кодом в Background.js и передавать и получать данные из расширения.
В простейшем случае для вызова кода на стороне расширения из Content script используется вызов chrome.extension.sendMessage и обработчик на стороне расширения chrome.extension.onMessage.addListener. Для обратного взаимодействия на стороне расширения используется вызов метода chrome.tabs.sendMessage, а со стороны скрипта обработка не меняется - также используется обработчик chrome.extension.onMessage.addListener.
Ниже показан простейший код расширения, реализующего обмен данными между веб страницей и основным кодом расширения.
//file mainifest.json
{
"name": "Message exchange demo",
"version": "1.0",
"description": "Explain the data exchange between web page and extention.",
"background": { "scripts": ["background.js"] },
"permissions": [
"tabs"
],
"content_scripts": [
{
"matches": ["http://*/*"],
"js": ["myscript.js"]
}
],
"manifest_version": 2
}
//file myscript.js
alert("demo content script loaded");
window.addEventListener("message", function(event)
{
// We only accept messages from ourselves
if (event.source != window)
return;
if (event.data.type && (event.data.type == "FROM_PAGE"))
{
console.log("event from page content");
chrome.extension.sendMessage(
{greeting: "hello"}, function(response)
{
console.log(response.farewell);
});
}
}, false);
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse)
{
console.log("from the extension");
if (request.greeting == "all ok")
{
sendResponse({farewell: "greet!"});
window.postMessage({ type: "FROM_SCRIPT", text: "all ok"}, "*");
}
}
);
//file background.js
alert("demo ext start");
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse)
{
console.log("from a content script:" + sender.tab.url);
if (request.greeting == "hello")
{
sendmes("all ok")
sendResponse({farewell: "goodbye"});
}
});
function sendmes(mes)
{
chrome.tabs.getSelected(null, function(tab)
{
chrome.tabs.sendMessage(tab.id, {greeting: mes}, function(response)
{
console.log(response.farewell);
});
});
}
//test.htm - тестовая страница
<!DOCTYPE html>
<html lang=en>
<head>
<meta charset="utf-8">
<script type="text/javascript">
function postmes(mes)
{
window.postMessage({ type: "FROM_PAGE", text: mes}, "*");
}
window.addEventListener("message", function(event) {
// We only accept messages from ourselves
if (event.source != window)
return;
if (event.data.type && (event.data.type == "FROM_SCRIPT")) {
console.log("Page received: " + event.data.text);
}
}, false);
</script>
</head>
<body>
<form>
<input type ="button" onclick="postmes('mymes');" value="postmessage">
</form>
</body>
</html>
После загрузки расширения и нажатии на кнопку postmessage на тестовой странице мы получим в javascript консоли chrome, вызванной для демо страницы:
event from page content
goodbye
from the extension
Page received: all ok
Алексей Шечков, 2012.
Эту статью я опубликовал первоначально в песочнице habrahabr, где она стояла покуда я ее оттуда не снял :)
|