Расширение 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, написанного в виде строки, как здесь.

Другие вопросы по тегам