JS расширение в Chrome. При вызове нативного приложения с активной вкладки - в консоли отображается ошибка
JS расширение в Chrome.
При вызове нативного приложения с активной вкладки - в консоли отображается ошибка.
Uncaught TypeError: chrome.runtime.sendNativeMessage is not a function
at background.js:7:20
Я просто ручной тестировщик.
У нас есть скрипт на python (.exe) для получения сборок приложений.
При запуске из cmd
в первом аргументе скрипт ожидает ID тестовой задачи.
Но каждый раз запускать его из cmd
вручную не хочется.
Есть идея по кнопке получать ID задачи с активной страницы в браузере и передавать его в скрипт для получения сборок.
- Было создано маленькое JS расширение для браузера Chrome.
- А так же маленькое нативное приложение на python (.exe).
Которое принимает сообщение от расширения и в будущем будет вызывать скрипт для получения сборок - оно написано согласно dev.chrome ресурсу и работает корректно.
Если вызывать chrome.runtime.sendNativeMessage
из отладки страниц chrome://extensions/
моего приложения - сообщение нативным приложением принимается и ошибки нет.
Упрощённый пример кода (оставил только вызов chrome.runtime.sendNativeMessage
)
Манифест расширения
{
"name": "sample: GetDevApk",
"description": "Get apk from YouTrack",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html"
},
"permissions": [
"scripting",
"activeTab",
"nativeMessaging"
],
"background": {
"service_worker": "background.js",
"type": "module"
},
"content_scripts": [
{
"matches": ["https://youtrack.sample.ru/issue/*"],
"js": ["background.js"]
}
],
"author": "User3000"
}
background.js
let id_task = 'Example-111';
const app_name = 'ru.sample.n_app';
const message = {get_apk: id_task};
setTimeout(() => {
chrome.runtime.sendNativeMessage(
app_name,
message,
function (response) {
console.log('Response:', response);
},
);
}, 3500);
popup.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
chrome.runtime.sendNativeMessage(
app_name,
message,
function(response) {
sendResponse(response);
}
);
return true;
});
Манифест нативного приложения (на всякий случай)
{
"name": "ru.sample.n_app",
"description": "n_app for get_apk",
"path": "n_app.exe",
"type": "stdio",
"allowed_origins": [
"chrome-extension://loanjfflomlmjmmdjmcfmepeajaffpkk/"
]
}
Объявление app_name
и message
в popup.js
результата не изменяет.
Буду благодарен за любые подсказки.
Заранее спасибо!
Ответы (1 шт):
Удалось разобраться!
Нужно было больше времени уделить на изучение первоисточника "chrome.runtime", а не точечно искать информацию на различных ресурсах.
Плюс помог конкретный пример "Send data from a content script to the service worke" из того же первоисточника.
Так же, как итог, очень сильно помог разбор кода рабочего расширения от Microsoft: Single Sing On.
Если коротко, как я понял (может и не правильно), то:
background.js
не имеет доступа кdom
по умолчанию, но используется как сервис для прослушивания и обработки событий (service_worker)
-> он может взаимодействовать с нативными приложениями черезsendNativeMessage
и другими прописанными расширениями, выполнять некоторые действияcontent.js
(у меня былpopen.js
) для обработки контента на активной станице
-> он не может вызвать нативное приложение черезsendNativeMessage
- будет ошибкаis not a function
-> но он может послать сообщениеsendMessage
, которое сможет прослушатьbackground.js
используяonMessage.addListener
popup.js
нужен для обработки действий выполняемых внутри формы расширения (когда кликаем на него и открывается собственное меню или мини страничкаpopup.html
)
-> он может получить содержимое активной страницы и внести изменения, если это необходимо, но для этого нужно будет дописать небольшой обработчик
-> и событие будет происходить по нажатию на кнопку в расширении (которую нужно добавить, конечно), а не сразу по открытию вкладки
Так или иначе, все эти названия файлов - достаточно условны, вся соль в особенностях работы и тут уже решает то что именно указано в манифесте и документации.
С JS раньше не работал - по сути, первый проект, по этому простите - если задел чьи-то чувства! Готов к конструктивной критике и советам.
Всем спасибо!
Вот упрощённый рабочий пример с комментариями по коду.
манифест расширения
{
"name": "sample: GetDevApk",
"description": "Get apk from YouTrack",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"scripting",
"activeTab",
"nativeMessaging"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"all_frames": true,
"matches": ["https://youtrack.sample.ru/issue/*"],
"js": ["content.js"]
} ]
}
background.js
const app_name = 'ru.sample.n_app';
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse){
// request тут - это наше сообщение (id задачи)
// формируем сообщение для нативного приложения в формате json
let state = {get_apk: request};
// вызываем наше нативное приложение
// тут нет аргумента function(response) т.к. обработка ошибок пока не требуется
chrome.runtime.sendNativeMessage(app_name, state);
// отправляем ответ в content.js
sendResponse({get_apk: "Execute", status: "Success", id_task: request});
return true // говорим, что всё "ОК"
});
content.js
// задержка перед выполнением
setTimeout(() => {
// формируем сообщение для background.js
// слушатель со стороны background.js должен его получить
// и выполнить необходимое нам действие sendNativeMessage
chrome.runtime.sendMessage(
'Example-111', // наше сообщение (id задачи)
(response) => { // обработка ответа
console.log(response) // вывод ответа в консоль
return true // говорим, что всё "ОК"
}
);
}, 2500);