Почему не работает browser api
manifest.json
{
"manifest_version": 3,
"name": "name",
"version": "1.0",
"description": "description",
"icons": {
"128": "128.png"
},
"action": {
"default_popup": "index.html"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["index.js"],
"css": ["index.css"],
"run_at": "document_start"
}
],
"background": {
"service_worker": "background.js"
},
"permissions": ["tabs", "storage", "webRequest", "<all_urls>", "scripting", "storage"]
}
content.js
browser.runtime.sendMessage({
name: 'Denis',
});
background.js
browser.runtime.onMessage.addListener(function (message) {
console.log(message);
});
Делаю cntl+c -> cntl+v отсюда - все ровно не работает... Я не знаю что делать уже и как это заставить работать, но browser.runtime.onMessage просто не обрабатывает запрос
Ответы (1 шт):
В данном случае происходит ошибка действия от обратного.
Чтобы отправить данные в расширение нам нужно слушать событие на прием данных в файле content.js (index.js в моем случае), а не отправлять их. Чтобы получить данные в расширении, нам нужно отправить данные на целевую страницу, а не слушать их прием.
Логично было представить это иначе. Нам нужно отправить данные с целевой страницы в расширение - отправляем данные с целевой страницы в расширение:
chrome.runtime.sendMessage()
Расширение со своей стороны их прослушивает и получает результат:
chrome.runtime.onMessage.addListener()
Проблема в том, что все происходит в точности наоборот, и хотя в документации написано:
На принимающей стороне необходимо настроить прослушиватель событий runtime.onMessage для обработки сообщения. Это выглядит так же из сценария содержимого или страницы расширения.
из-за этой путаницы начинаешь теряться, где тут принимающая сторона...
Для начала удалим все дополнения в поле permissions файла manifest.json, так как в данных примерах они не понадобятся (они были добавлены от отчаяния) и переименуем index.js в content.js (так будет информативнее):
{
"manifest_version": 3,
"name": "Name",
"version": "1.0",
"description": "Description",
"icons": {
"128": "128.png"
},
"action": {
"default_popup": "page.html"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"],
"css": ["index.css"],
"run_at": "document_start"
}
],
"background": {
"service_worker": "background.js"
},
"permissions": []
}
Допустим, мы хотим прокинуть выбранный на странице текст в файл расширения. Нам нужно воспользоваться не chrome.runtime.sendMessage в файле content.js, который внедрен на целевую страницу и получает данные DOM, а chrome.runtime.onMessage, то есть слушать события:
content.js:
// получаем текст элемента и сохраняем его в локальном хранилище:
document.addEventListener('click', ({ target }) => {
localStorage.setItem('content', JSON.stringify(target?.textContent));
})
// слушаем ответ от расширения
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log(request, sender, sendResponse);
// request - ответ от сервера
// sender - id расширения и origin
// после того как получен ответ от расширения отправляем данные уже
// непосредственно ему самому
sendResponse(JSON.stringify({ content: localStorage.getItem('content') }));
});
background.js
// отправка данных текущей вкладке
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
console.log(document); // этот документ будет ссылаться на DOM вашего расширения, то есть файла html назначенного как action: { default_popup: page.html }
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
// response - это наш sendResponse(JSON.stringify({ content: localStorage.getItem('content') })); с предыдущего шага. Изменяем контент в DOM расширения
document.body.textContent = response;
// а {greeting: "hello"} - это наш request (ответ от сервера) с предыдущего шага
});
});
Не забудьте подключить файл background.js в ваш html файд расширения используя обычный тег script.
В моем случае нужно нажать на иконку расширения и скрипт background.js инициирует событие sendMessage и отправит данные с расширения на целевую страницу, где content.js будет это событие слушать и пересылать данные обратно расширению. Не наоборот, как могло показаться.
И наоборот, если нам нужно получить данные с расширения, мы должны не слушать их на целевой странице, а отправлять:
content.js:
chrome.runtime.sendMessage('Data for extension', function (msg) {
console.log(msg); // data from extension
});
В расширении мы их слушаем
background.js:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log(request, sender, sendResponse);
sendResponse(`From backend: ${request}`); // это будет отправлено на целевую страницу
});
Имейте в виду в chrome.runtime.onMessage.addListener файла background.js последнего примера не будет ни window, ни document. При попытке обратиться к ним вы получите: Error in event handler: ReferenceError: window is not defined. У расширения своя консоль. Нужно кликнуть по иконке и на всплывающем окне нажать ПКМ - исследовать. Все данные, которые приходят или логинятся в расширении будут видны там.
Ненавижу это API. Надеюсь я смог кому то помочь этим постом.