如何在瀏覽器擴展中使用 eval 函數

思路是把 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 函數。

在模板引擎比如 NunjucksHandlebars 中,通常會使用到 eval 等類似比較“危險”的函數,遇到無法在瀏覽器擴展中使用這些庫時可以類似解決。

參考:Using eval in Chrome extensions - Chrome Developersjavascript - JS templating in google chrome extension(manifest v2) - Stack Overflow

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章