javascript Chrome 扩展:加载和执行外部脚本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28020878/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Chrome extension: load and execute external script
提问by jenush
I have trouble loading and executing external js-script into my chrome extension. Looks the same as this question, but I still cant't figure out why it doesn't work in my case.
我无法将外部 js 脚本加载和执行到我的 chrome 扩展程序中。看起来与这个问题相同,但我仍然无法弄清楚为什么它在我的情况下不起作用。
The idea is that I want to have in my content script some default function which should parse a web-page content. And for some specific web-pages I want to load and use specific parsers, so I try to load proper js-script for a wep-page, and this script shoud extend functionality of default parser.
这个想法是我想在我的内容脚本中包含一些应该解析网页内容的默认函数。对于一些特定的网页,我想加载和使用特定的解析器,所以我尝试为一个 web 页面加载适当的 js 脚本,并且这个脚本应该扩展默认解析器的功能。
By now I try only execute code from external script, but have such error: Unchecked runtime.lastError while running tabs.executeScript: No source code or file specified at Object.callback
现在我只尝试从外部脚本执行代码,但有这样的错误: Unchecked runtime.lastError while running tabs.executeScript: No source code or file specified at Object.callback
This is my manifest.json:
这是我的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
}
}
This is popup.html
这是popup.html
<!doctype html>
<html>
<head>
<title>Title</title>
<script src="popup.js"></script>
</head>
<body>
<ul>
<li>Some link</li>
</ul>
</body>
</html>
And in popup.jsi execute scrip like this:
在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"});
});
What am I dong wrong, did I miss something? Or should I use another approach to solve the issue?
我做错了什么,我错过了什么吗?或者我应该使用另一种方法来解决问题吗?
回答by Thomas Karachristos
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:
谷歌浏览器禁止像您尝试一样从外部来源运行脚本,并且会阻止甚至不发布您的扩展程序。所有脚本都必须在扩展中。但是有一个解决方案, 来自 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.
对通过 HTTP 加载的资源的限制仅适用于直接执行的资源。例如,您仍然可以自由地将 XMLHTTPRequest 连接到您喜欢的任何来源;默认策略不会以任何方式限制 connect-src 或任何其他 CSP 指令。
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:
如果您非常需要外部源,您可以执行 XML HTTP 请求并对内容使用 eval。这是谷歌文档的一部分代码:
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 jqueryor $http with angularjs. if you add eval in your code you must add in manifest.json this:
或者你可以使用一些库,$.get() 与 jquery或$http 与 angularjs。如果您在代码中添加 eval,则必须在 manifest.json 中添加以下内容:
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"`,
回答by Haibara Ai
As per the discussion here: https://groups.google.com/a/chromium.org/forum/#!topic/chromium-extensions/LIH7LGXeQHo,
根据此处的讨论:https://groups.google.com/a/chromium.org/forum/#!topic/chromium-extensions/LIH7LGXeQHo,
Running scripts from external sources may cause your extension to be unpublished or blocked.
从外部源运行脚本可能会导致您的扩展被取消发布或阻止。
Just providing another approach, you could make an ajax call to the content script then call chrome.tabs.executeScript
只是提供另一种方法,您可以对内容脚本进行 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");
});
回答by Siderite Zackwehdex
The 'file' option for executeScript only relates to filesembedded in your extension. I know, the documentationisn't clear on that and while it might work with URLs, it sounds like a hack, not a feature. In order to load scripts from external sources into your active page, you usually have to execute a script that creates a script tag inside the DOM of the loaded document there.
executeScript 的 'file' 选项仅与嵌入在扩展中的文件相关。我知道,文档对此并不清楚,虽然它可能适用于 URL,但听起来像是一个 hack,而不是一个功能。为了将来自外部源的脚本加载到您的活动页面中,您通常必须执行一个脚本,该脚本在那里加载的文档的 DOM 内创建一个脚本标记。
I feel I have answered parts of this question before here: Why is chrome.tabs.executeScript() necessary to change the current website DOM and how can I use jQuery to achieve the same effect?
我觉得我在这里之前已经回答了这个问题的一部分:为什么 chrome.tabs.executeScript() 需要更改当前网站的 DOM 以及如何使用 jQuery 来实现相同的效果?
To summarize:
总结一下:
1) in order to have access to web pages from the extension, you need to add permissionsfor it:
1)为了从扩展程序访问网页,您需要为其添加权限:
"permissions" : [
"tabs",
[...]
"http://*/*",
"https://*/*" ],
2) you need to execute some sort of code that creates the DOM script element that loads what you need:
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
});
Take a look at the remex
function in the link above, which I think solves a lot of the ugliness of javascript written as a string as here.
看看remex
上面链接中的函数,我认为它解决了很多像这里这样写成字符串的javascript的丑陋。