Расширение Chrome: загрузите и выполните внешний скрипт
У меня проблемы с загрузкой и выполнением внешнего js-скрипта в моем расширении chrome. Выглядит так же, как этот вопрос, но я до сих пор не могу понять, почему это не работает в моем случае.
Идея состоит в том, что я хочу, чтобы в моем скрипте контента была функция по умолчанию, которая должна анализировать контент веб-страницы. А для некоторых конкретных веб-страниц я хочу загрузить и использовать определенные парсеры, поэтому я пытаюсь загрузить соответствующий js-скрипт для wep-страницы, и этот скрипт должен расширить функциональность парсера по умолчанию.
К настоящему времени я пытаюсь только выполнить код из внешнего скрипта, но есть такая ошибка: Unchecked runtime.lastError while running tabs.executeScript: No source code or file specified at Object.callback
Это мой манифест.json:
{
"name": "Extension name",
"version": "1.2",
"description": "My chrome extension",
"browser_action": {
"default_popup": "popup.html",
},
"content_scripts": [{
"css": [
"style.css"
],
"js": [
"bower_components/jquery/dist/jquery.js",
"bower_components/bootstrap/dist/js/bootstrap.js",
"content.js"
],
"matches": ["*://*/*"]
}],
"web_accessible_resources": [
"frame.html",
"logo-48.png"
],
"icons": {
"16": "logo-16.png",
"48": "logo-48.png",
"128": "logo-128.png"
},
"permissions": [
"tabs",
"storage",
"http://*/",
"https://*/"
],
"manifest_version": 2
}
Это popup.html
<!doctype html>
<html>
<head>
<title>Title</title>
<script src="popup.js"></script>
</head>
<body>
<ul>
<li>Some link</li>
</ul>
</body>
</html>
И в popup.js я выполняю скрипт так:
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.executeScript(tabs[0].id, {file: "http://127.0.0.1:8000/static/plugin/somesite.js"});
});
Что я не прав, я что-то пропустил? Или я должен использовать другой подход для решения проблемы?
3 ответа
Запуск сценариев из внешних источников, как вы пытаетесь, запрещен Google Chrome и будет блокировать или даже не публиковать ваше расширение. Все скрипты должны быть в расширении. Но есть решение, от Google Chrome Doc:
Ограничение на ресурсы, загружаемые по HTTP, распространяется только на те ресурсы, которые выполняются напрямую. Например, вы по-прежнему можете устанавливать соединения XMLHTTPRequest с любым источником, который вам нравится; политика по умолчанию никоим образом не ограничивает connect-src или любые другие директивы CSP.
Если вам очень нужен внешний источник, вы можете выполнить XML-HTTP-запрос и использовать eval для содержимого. Вот часть кода из Google Doc:
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://127.0.0.1:8000/static/plugin/somesite.js", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// WARNING! Might be evaluating an evil script!
var resp = eval("(" + xhr.responseText + ")");
// Or this if it's work
chrome.tabs.executeScript(tabs[0].id, {code: xhr.responseText});
}
}
xhr.send();
или вы можете использовать некоторую библиотеку, $.get () с jquery или $ http с angularjs. если вы добавите eval в свой код, вы должны добавить в manifest.json это:
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"`,
Согласно обсуждению здесь: https://groups.google.com/a/chromium.org/forum/,
Запуск сценариев из внешних источников может привести к тому, что ваше расширение будет неопубликовано или заблокировано.
Просто предоставив другой подход, вы можете сделать ajax-вызов скрипта контента, а затем вызвать chrome.tabs.executeScript
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
$.get("http://127.0.0.1:8000/static/plugin/somesite.js", function(result) {
chrome.tabs.executeScript(tabs[0].id, {code: result});
}, "text");
});
Опция 'file' для executeScript относится только к файлам, встроенным в ваше расширение. Я знаю, что документация по этому вопросу не ясна, и хотя она может работать с URL-адресами, это звучит как хак, а не как функция. Чтобы загрузить сценарии из внешних источников на вашу активную страницу, вам обычно нужно выполнить сценарий, который создает тег сценария внутри DOM загруженного документа.
Я чувствую, что уже отвечал на некоторые части этого вопроса раньше: почему chrome.tabs.executeScript() необходим для изменения DOM текущего веб-сайта и как я могу использовать jQuery для достижения того же эффекта?
Подвести итоги:
1) для того, чтобы иметь доступ к веб-страницам из расширения, необходимо добавить разрешения для него:
"permissions" : [
"tabs",
[...]
"http://*/*",
"https://*/*" ],
2) вам нужно выполнить какой-то код, который создает элемент сценария DOM, который загружает то, что вам нужно:
chrome.tabs.executeScript(tab.id, {
code : 'var script=document.createElement(\'script\');' +
'script.onload=function() { /*do something in the page after the script was loaded*/ };' +
'script.src=\'http://127.0.0.1:8000/static/plugin/somesite.js\';' +
'document.body.appendChild(script);'
}, function (returnedValue) {
// do something in the extension context after the code was executed
});
Посмотрите на remex
Функция в ссылке выше, которая, я думаю, решает большую часть уродства JavaScript, написанного в виде строки, как здесь.