11

我无法将外部 js 脚本加载和执行到我的 chrome 扩展程序中。看起来和这个问题一样,但我仍然不明白为什么它在我的情况下不起作用。

这个想法是我想在我的内容脚本中有一些默认函数来解析网页内容。对于某些特定的网页,我想加载和使用特定的解析器,所以我尝试为 wep 页面加载正确的 js 脚本,并且这个脚本应该扩展默认解析器的功能。

现在我尝试只从外部脚本执行代码,但有这样的错误:Unchecked runtime.lastError while running tabs.executeScript: No source code or file specified at Object.callback

这是我的manifest.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"});
});

我错了什么,我错过了什么吗?还是我应该使用另一种方法来解决问题?

4

3 回答 3

10

谷歌浏览器禁止像您尝试从外部来源运行脚本,并且会阻止甚至不发布您的扩展程序。所有脚本都必须在扩展中。但是有一个解决方案, 来自 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'"`,
于 2016-04-15T11:12:20.147 回答
5

根据这里的讨论:https ://groups.google.com/a/chromium.org/forum/#!topic/chromium-extensions/LIH7LGXeQHo ,

从外部源运行脚本可能会导致您的扩展程序未发布或被阻止。

只是提供另一种方法,您可以对内容脚本进行 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");
});
于 2016-04-15T11:17:34.063 回答
1

executeScript 的“文件”选项仅与嵌入在您的扩展程序中的文件有关。我知道,文档对此并不清楚,虽然它可能与 URL 一起使用,但听起来像是 hack,而不是功能。为了将来自外部源的脚本加载到您的活动页面中,您通常必须执行一个脚本,该脚本会在此处加载的文档的 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 的丑陋之处。

于 2016-04-20T12:55:07.703 回答