Добрый день!
Уже несколько суток бьюсь с задачей перевести расширение с манифеста2 на манифест3 для Хрома.
Суть в следующем: в настоящее время расширение открывается в iframe внутри любой вкладки браузера и выполняется внешний скрипт, который загружает данные в расширение.
Манифест2
{
"manifest_version": 2,
"name": "__MSG_extension_name__",
"short_name": "__MSG_extension_short_name__",
"version": "1.4.1",
"default_locale": "ru",
"description":"__MSG_extension_description__",
"icons":{
"128":"img/icons/128.png",
"16":"img/icons/16.png",
"48":"img/icons/48.png"
},
"background": {
"scripts": [
"background.js"
]
},
"permissions": [
"http://*/*",
"https://*/*",
"\u003Call_urls\u003E"
],
"browser_action": {
"default_title": "My widget",
"default_icon": "img/icons/128.png"
}
}
background.js
var SSChromePanelTab = function (id) {
var t = this;
t.id = id;
t.init();
};
/**
* Скрипт показывающий/скрывающий панельку
*/
SSChromePanelTab.prototype.executeToggleScript = function () {
chrome.tabs.executeScript(this.id, {file: "functions/toggle.js"});
};
/**
* Инициализация виджета во вкладке
*/
SSChromePanelTab.prototype.init = function () {
var t = this;
t.executeToggleScript();
};
/**
* Инспектор, следящий за всеми объектами вкладок
*
* @constructor
*/
var SSChromePanelInspector = function () {
var i = this;
i.tabs = {};
};
/**
* Функция-обработчик клика по кнопке расширения
*
* @param tab_id
*/
SSChromePanelInspector.prototype.toggle = function (tab_id) {
var i = this;
if (typeof i.tabs[tab_id] === 'undefined') {
i.tabs[tab_id] = new SSChromePanelTab(tab_id);
} else {
i.tabs[tab_id].executeToggleScript();
}
};
// Инициализируем инспектор панелей
var sschromepanelinspector = new SSChromePanelInspector();
// Инициализируем обработчик клика по кнопке расширения
chrome.browserAction.onClicked.addListener(function (tab) {
sschromepanelinspector.toggle(tab.id);
});
chrome.tabs.onUpdated.addListener( function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
chrome.tabs.executeScript(tabId, {file: "functions/auto_init.js"});
}
});
toggle.js файл
var loaded = document.getElementById('sswidget-loaded');
function getIsSSWidgetDestryed() {
var from_storage = localStorage.getItem('sswidget');
if (from_storage) {
var data = JSON.parse(from_storage);
return data.destroyed;
}
return false;
}
if (!loaded) {
var elt = document.createElement("script");
elt.innerHTML = "window['SSWidgetInstance'] = 'sswidget';";
document.head.appendChild(elt);
(function (d, w) {
var n = d.getElementsByTagName("script")[0],
s = d.createElement("script"),
f = function () {
n.parentNode.insertBefore(s, n);
};
s.type = "text/javascript";
s.async = true;
s.src = "//mysite.ru/widget.js";
if (w.opera == "[object Opera]") {
d.addEventListener("DOMContentLoaded", f, false);
} else {
f();
}
})(document, window);
} else if (getIsSSWidgetDestryed()) {
var elt = document.createElement("script");
elt.innerHTML = "window['sswidget'].init()";
document.head.appendChild(elt);
} else {
var elt = document.createElement("script");
elt.innerHTML = "window['sswidget'].destroy()";
document.head.appendChild(elt);
}
auto_init.js
function getIsSSWidgetEnabled() {
var from_storage = localStorage.getItem('sswidget');
if (from_storage) {
var data = JSON.parse(from_storage);
return !data.destroyed;
}
return false;
}
var loaded = document.getElementById('sswidget-loaded');
if (!loaded && getIsSSWidgetEnabled()) {
console.log('auto init!');
var elt = document.createElement("script");
elt.innerHTML = "window['SSWidgetInstance'] = 'sswidget';";
document.head.appendChild(elt);
(function (d, w) {
var n = d.getElementsByTagName("script")[0],
s = d.createElement("script"),
f = function () {
n.parentNode.insertBefore(s, n);
};
s.type = "text/javascript";
s.async = true;
s.src = "//mysite.ru/widget.js";
if (w.opera == "[object Opera]") {
d.addEventListener("DOMContentLoaded", f, false);
} else {
f();
}
})(document, window);
}
Я переделываю уже на разный манер данный виджет для 3 манифеста, но не могу нащупать путь, как мне подгрузить внешний скрипт src = "//mysite.ru/widget.js" и везде натыкаюсь на CSP. Последний вариант такой:
Манифест3
{
"manifest_version": 3,
"name": "Action API Demo",
"short_name": "__Action API Demo__",
"version": "1.4.8",
"description": "Uses the Action API to change the badge text, icon, hover text, or popup page.",
"icons": {
"32": "icons/32.png",
"72": "icons/72.png",
"128": "icons/128.png",
"512": "icons/512.png"
},
"content_scripts": [
{
"matches": ["<all_urls>",
"http://*/*",
"https://*/*"],
"js": ["content.js"]
}
],
"background": {
"service_worker": "background.js",
"action": {}
},
"permissions": [
"tabs", "activeTab", "scripting"
],
"host_permissions": [
"<all_urls>",
"http://*/*",
"https://*/*"
],
"action": {
"default_title": "Default Title"
}
}
Сервис-вокер:
// Инициализируем обработчик клика по кнопке расширения
/**
* Обработчик нажатия на действие расширения
*/
chrome.action.onClicked.addListener(tab => {
chrome.scripting.executeScript({
target: {tabId: tab.id},
files: ['content.js']
}, () => {
if (chrome.runtime.lastError) {
console.error("Ошибка при выполнении скрипта:", chrome.runtime.lastError.message);
} else {
console.log("Скрипт content.js успешно выполнен на вкладке с ID:", tab.id);
// Добавляем небольшую задержку перед отправкой сообщения
setTimeout(() => {
sendMessageToContentScript(tab.id);
}, 100); // Установите время задержки по вашему усмотрению
}
});
});
function sendMessageToContentScript(tabId) {
chrome.tabs.sendMessage(tabId, {action: "toggle", tabId: tabId}, response => {
if (chrome.runtime.lastError) {
console.error("Ошибка при отправке сообщения:", chrome.runtime.lastError.message);
} else {
console.log("Сообщение успешно отправлено на вкладку с ID:", tabId);
}
});
}
Контентный скрипт:
/**
* Объект-обертка для функций вкладки
* @param id
* @constructor
*/
class SSChromePanelTab {
constructor(id) {
this.id = id;
this.init();
}
executeToggleScript() {
console.log('executeToggleScript');
var loaded = document.getElementById('sswidget-loaded');
function getIsSSWidgetDestryed() {
var from_storage = localStorage.getItem('sswidget');
if (from_storage) {
var data = JSON.parse(from_storage);
return data.destroyed;
}
return false;
}
if (!loaded) {
// Устанавливаем переменную окружения для виджета
window['SSWidgetInstance'] = 'sswidget';
// Создаем элемент <script> для загрузки внешнего скрипта
var script = document.createElement('script');
script.src = 'https://mysite.ru/widget.js';
script.async = true; // Устанавливаем асинхронную загрузку
document.head.appendChild(script);
} else if (getIsSSWidgetDestryed()) {
var elt = document.createElement("script");
elt.innerHTML = "window['sswidget'].init()";
document.head.appendChild(elt);
} else {
var elt = document.createElement("script");
elt.innerHTML = "window['sswidget'].destroy()";
document.head.appendChild(elt);
}
}
init() {
this.executeToggleScript();
}
}
/**
* Инспектор, следящий за всеми объектами вкладок
*/
class SSChromePanelInspector {
constructor() {
this.tabs = {};
}
toggle(tab_id) {
console.log('toggle');
if (typeof this.tabs[tab_id] === 'undefined') {
this.tabs[tab_id] = new SSChromePanelTab(tab_id);
} else {
this.tabs[tab_id].executeToggleScript();
}
}
}
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "toggle") {
console.log('Content script received toggle action for tab ID:', message.tabId);
const ssChromePanelInspector = new SSChromePanelInspector();
ssChromePanelInspector.toggle(message.tabId);
}
});
И на строке контентного скрипта document.head.appendChild(script); получаю ошибку в консоли Refused to load the script '
https://mysite.ru/widget.js' because it violates the following Content Security Policy directive: "script-src 'self' 'wasm-unsafe-eval'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
Пробовала создать расширение-песочницу - там открывается отдельная страница html и пропадает смысл приложения, тк оно позиционируется как помощник на любой вкладке. С popup не получилось, возможно, Вы мне посоветуете, как переделать код, для открытия расширения в popup...
Подскажите, пожалуйста, как мне вывести в iframe расширение в текущих условиях манифеста3?