如何将参数传递给使用以下内容注入的内容脚本文件中的 JavaScript:
chrome.tabs.executeScript(tab.id, {file: "content.js"});
原文由 user1365732 发布,翻译遵循 CC BY-SA 4.0 许可协议
如何将参数传递给使用以下内容注入的内容脚本文件中的 JavaScript:
chrome.tabs.executeScript(tab.id, {file: "content.js"});
原文由 user1365732 发布,翻译遵循 CC BY-SA 4.0 许可协议
有五种通用方法可以将数据传递给注入了 tabs.executeScript()
( MDN )的内容脚本:
chrome.storage.local
( MDN )传递数据(在注入脚本之前设置)。document_start
注入的 manifest.json 内容脚本,而不需要内容脚本执行异步请求。chrome.storage.onChanged
( MDN )来侦听后台脚本以使用 chrome.storage.local.set()
( MDN )设置一个值。chrome.storage.local
(在执行脚本之前设置)使用此方法可以维护您正在使用的执行范例,即注入执行功能然后退出的脚本。它也没有使用动态值构建执行代码的潜在安全问题,这是在下面的第二个选项中完成的。
chrome.storage.local.set()
( MDN )存储数据。chrome.storage.local.set()
的回调中,调用 tabs.executeScript()
( MDN ) 。 var updateTextTo = document.getElementById('comments').value;
chrome.storage.local.set({
updateTextTo: updateTextTo
}, function () {
chrome.tabs.executeScript({
file: "content_script3.js"
});
});
chrome.storage.local.get()
( MDN )中读取数据。storage.local
中的数据无效(例如删除密钥: chrome.storage.local.remove()
( MDN ) )。 chrome.storage.local.get('updateTextTo', function (items) {
assignTextToTextareas(items.updateTextTo);
chrome.storage.local.remove('updateTextTo');
});
function assignTextToTextareas(newText){
if (typeof newText === 'string') {
Array.from(document.querySelectorAll('textarea.comments')).forEach(el => {
el.value = newText;
});
}
}
请参阅:注释 1 和 2。
在执行脚本之前,您可以注入一些代码,在内容脚本上下文中设置一个变量,然后您的主脚本可以使用该变量:
以下使用 "'" + JSON.stringify().replace(/\\/g,'\\\\').replace(/'/g,"\\'") + "'"
将数据编码为文本,当将其解释为代码时,这将是正确的 JSON,然后再将其放入 code
字符串。 .replace()
方法需要 A) 在用作代码时将文本正确解释为字符串,以及 B) 引用数据中存在的任何 '
。然后它使用 JSON.parse()
将数据返回到内容脚本中的字符串。虽然这种编码不是严格要求的,但这是一个好主意,因为您不知道要发送到内容脚本的值的内容。这个值很容易成为破坏您正在注入的代码的东西(即用户可能正在使用 '
和/或 "
在他们输入的文本中)。如果您不以某种方式转义该值,则存在安全漏洞,可能导致执行任意代码。
chrome.tabs.executeScript()
( MDN )的回调中,调用 tabs.executeScript()
以注入您的脚本(注意: tabs.executeScript()
将执行脚本的调用顺序 tabs.executeScript()
,只要它们具有相同的值 runAt
。因此,等待小 code
的回调并不是严格要求的)。 var updateTextTo = document.getElementById('comments').value;
chrome.tabs.executeScript({
code: "var newText = JSON.parse('" + encodeToPassToContentScript(updateTextTo) + "');"
}, function () {
chrome.tabs.executeScript({
file: "content_script3.js"
});
});
function encodeToPassToContentScript(obj){
//Encodes into JSON and quotes \ characters so they will not break
// when re-interpreted as a string literal. Failing to do so could
// result in the injection of arbitrary code and/or JSON.parse() failing.
return JSON.stringify(obj).replace(/\\/g,'\\\\').replace(/'/g,"\\'")
}
if (typeof newText === 'string') {
Array.from(document.querySelectorAll('textarea.comments')).forEach(el => {
el.value = newText;
});
}
请参阅:注释 1、2 和 3。
这需要您的内容脚本代码为弹出窗口或后台脚本(如果与 UI 的交互导致弹出窗口关闭)发送的消息安装侦听器。它有点复杂。
tabs.query()
( MDN )确定活动选项卡。tabs.executeScript()
( MDN )tabs.executeScript()
的回调中,使用 tabs.sendMessage()
( MDN ) (需要了解 tabId
),将数据作为消息发送。 var updateTextTo = document.getElementById('comments').value;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.executeScript(tabs[0].id, {
file: "content_script3.js"
}, function(){
chrome.tabs.sendMessage(tabs[0].id,{
updateTextTo: updateTextTo
});
});
});
chrome.runtime.onMessage.addListener()
( MDN )添加监听器。runtime.onMessage
监听器#3.2 是可选的。您可以让您的代码保持活动状态以等待另一条消息,但这会将您正在使用的范例更改为您加载代码并保持驻留以等待消息启动操作的范例。
chrome.runtime.onMessage.addListener(assignTextToTextareas);
function assignTextToTextareas(message){
newText = message.updateTextTo;
if (typeof newText === 'string') {
Array.from(document.querySelectorAll('textarea.comments')).forEach(el => {
el.value = newText;
});
}
chrome.runtime.onMessage.removeListener(assignTextToTextareas); //optional
}
请参阅:注释 1 和 2。
注意 1:使用 Array.from()
没问题,如果你没有多次这样做并且使用的 浏览器版本有它(Chrome >= 版本 45,Firefox >= 32)。在 Chrome 和 Firefox 中, Array.from()
比其他从 NodeList 获取数组的方法慢。为了更快、更兼容地转换为数组,您可以使用 asArray()
此答案 中的代码。该答案中提供的 asArray()
的第二个版本也更强大。
注意 2:如果您愿意 将代码限制为 Chrome version >= 51 或 Firefox version >= 50 ,Chrome 有一个 forEach()
从 v51 开始的 NodeLists 方法。因此,您不需要转换为数组。显然,如果您使用不同类型的循环,则不需要转换为数组。
注意 3:虽然我以前在自己的代码中使用过这种方法(注入带有变量值的脚本),但我被提醒在阅读 此答案 时应该将其包含在这里。
原文由 Makyen 发布,翻译遵循 CC BY-SA 3.0 许可协议
13 回答13k 阅读
7 回答2.2k 阅读
3 回答1.3k 阅读✓ 已解决
6 回答1.3k 阅读✓ 已解决
2 回答1.4k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
6 回答1.1k 阅读
没有“将参数传递给文件”这样的事情。
您 可以 做的是在执行文件 之前 插入内容脚本,或者在插入文件 之后 发送消息。我将在下面展示这些不同方法的示例。
JS文件执行前设置参数
如果要在插入文件之前定义一些变量,只需嵌套
chrome.tabs.executeScript
调用:如果您的变量不是那么简单,那么我建议使用
JSON.stringify
将对象转换为字符串:使用前面的方法,可以通过以下方式在
content.js
中使用变量:执行js文件后设置参数
JS文件后可以使用前面的方法设置参数。您可以使用 消息传递 API 来传递参数,而不是直接在全局范围内定义变量:
在内容脚本 (
content.js
) 中,您可以使用chrome.runtime.onMessage
事件侦听这些消息,并处理消息: