思路是把 iframe 作为沙箱环境,让 eval 在 iframe 中执行。
以 Chrome Manifest V2 为例。V3 可参考 Using eval in Chrome extensions - Chrome Developers。
1. 在 manifest 文件中列出沙箱 html
{
...,
"sandbox": {
"pages": ["sandbox.html"]
},
...
}
2. 加载沙箱 html
比如在 Manifest V2 中,可以将其放在背景页中(Manifest V3 取消了背景页):
<!-- background.html -->
<body>
<iframe id="theFrame" src="sandbox.html" style="display: none"></iframe>
</body>
3. 在沙箱 html 中执行 eval 等特殊操作
<!DOCTYPE html>
<html>
<body>
<script>
// 接收消息
window.addEventListener('message', async function (event) {
const message = event.data
let result = ''
if (message) {
switch (message.command) {
// 根据所收到消息的 command 值决定执行流程
case 'eval':
try {
result = eval(message.expression)
console.log(result)
} catch (error) {
event.source?.postMessage({ error, command: message.command }, event.origin)
return;
}
break
}
}
// 传回消息给消息发起方
event.source?.postMessage({ result, command: message.command }, event.origin)
});
</script>
</body>
</html>
4. 传递消息给沙箱 html
因为 sandbox 放在了 background.html 中,所以在 background.html 的 js 脚本中添加如下内容:
// 发送 eval 消息到 iframe
function sandboxEval(expression) {
const iframe = document.getElementById('theFrame')
const message = {
command: 'eval',
expression
};
iframe?.contentWindow?.postMessage(message, '*')
}
// 接收消息
window.addEventListener('message', function(event){
const message = event.data
if (message) {
switch (message.command) {
// 接收来自 iframe 的 eval 结果
case 'eval':
if (message.error) {
console.error(message.error)
} else {
console.log(message.result)
}
break
}
}
})
// 调用函数进行测试
sandboxEval('1 + 1')
这样就间接实现了调用 eval 函数。
在模板引擎比如 Nunjucks、Handlebars 中,通常会使用到 eval 等类似比较“危险”的函数,遇到无法在浏览器扩展中使用这些库时可以类似解决。
标签:浏览器,函数,iframe,html,command,eval,message,event From: https://www.cnblogs.com/Higurashi-kagome/p/17612718.html参考:Using eval in Chrome extensions - Chrome Developers、javascript - JS templating in google chrome extension(manifest v2) - Stack Overflow