沙盒页面
沙盒页面是具有不同 CSP 限制的特殊扩展页面。例如,可以在沙盒页面中 eval
任意代码。使用沙盒页面可以在比普通扩展页面具有更多权限的安全上下文中动态运行代码。
沙盒页面可以挂载类似于 CSUI 的 UI 组件或执行简单脚本。以下示例展示了从沙盒页面 eval
任意代码并通过消息传递将结果返回给调用者的能力。
首先,我们需要添加一个沙盒页面:
- 在源目录(项目根目录或
src
)中创建一个sandbox.ts
文件或sandboxes/<name>.ts
文件。 - 导出以下脚本:
sandbox.ts
export const life = 42
window.addEventListener("message", async function (event) {
const source = event.source as {
window: WindowProxy
}
source.window.postMessage(eval(event.data), event.origin)
})
上述脚本监听来自窗口范围的 message
事件,并通过数据属性评估调用者发送的代码。沙盒页面现在可以在扩展包中的 sandbox.html
或 sandboxes/<name>.html
下使用。要向此页面发送消息,我们需要将其挂载在 iframe 中,并调用 postMessage API。让我们在 popup.tsx
扩展页面 中实现:
popup.tsx
import { useEffect, useRef, useState } from "react"
function IndexPopup() {
const iframeRef = useRef<HTMLIFrameElement>(null)
useEffect(() => {
window.addEventListener("message", (event) => {
console.log("EVAL 输出: " + event.data)
})
}, [])
return (
<div
style={{
display: "flex",
flexDirection: "column",
padding: 16
}}>
<button
onClick={() => {
iframeRef.current.contentWindow.postMessage("10 + 20", "*")
}}>
触发 iframe eval
</button>
<iframe src="sandbox.html" ref={iframeRef} style={{ display: "none" }} />
</div>
)
}
export default IndexPopup
当用户点击 触发 iframe eval
时,他们将看到在沙盒页面中执行 eval
的结果。
更多信息请参阅 rfc-263 (opens in a new tab)。