Chrome扩展程序:加载并执行外部脚本

时间:2015-01-19 08:54:47

标签: javascript google-chrome-extension external-script

我无法在我的Chrome扩展程序中加载和执行外部js-script。看起来与this question相同,但我仍然无法弄清楚为什么它不起作用。

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

到目前为止,我只尝试从外部脚本执行代码,但出现了这样的错误: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"});
});

我错了什么,我错过了什么吗?或者我应该使用其他方法来解决问题?

3 个答案:

答案 0 :(得分:7)

Running scripts from external sources like you try is forbidden by google chrome and will block or even not publish your extension. All scripts must be in the extension. But there is a solution, from google chrome doc:

The restriction against resources loaded over HTTP applies only to those resources which are directly executed. You're still free, for example, to make XMLHTTPRequest connections to any origin you like; the default policy doesn't restrict connect-src or any of the other CSP directives in any way.

If you need badly an external source, you can do a XML HTTP request and use the eval to the content. Here is a part of code from 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();

or you can use some library, $.get() with jquery or $http with angularjs. if you add eval in your code you must add in manifest.json this:

"content_security_policy":  "script-src 'self' 'unsafe-eval'; object-src 'self'"`,

答案 1 :(得分: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");
});

答案 2 :(得分:1)

executeScript的“文件”选项仅与扩展程序中嵌入的文件相关。我知道,the documentation并不清楚,虽然它可能适用于网址,但它听起来像是一个黑客,而不是一个功能。为了将来自外部源的脚本加载到活动页面,您通常必须执行一个脚本,在那里加载的文档的DOM中创建脚本标记。

我觉得我在此之前已回答了部分问题:Why is chrome.tabs.executeScript() necessary to change the current website DOM and how can I use jQuery to achieve the same effect?

总结:

1)为了能够从扩展程序访问网页,您需要为其添加permissions

"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编写为字符串的丑陋问题。