Chrome扩展Content Script提前注入JS遇双body标签问题求助
解决Chrome扩展Content Script在document_start注入脚本的DOM冲突与全局变量访问问题
我来帮你梳理下问题的核心,然后给出具体的解决方案:
问题根源
你在document_start阶段手动创建并替换document.body的操作,会和浏览器后续自动生成的页面原生body标签冲突,导致DOM结构异常。这种错误的DOM操作同时干扰了注入脚本的全局上下文,使得页面主代码无法访问你注入的变量。
解决方案
核心思路是完全放弃手动创建/替换body元素,而是直接在document_start阶段将脚本注入到已存在的文档根节点(<html>元素)中,或者用document.write更直接地插入脚本——这两种方式都能保证脚本在页面所有原生脚本之前执行,且运行在页面的全局上下文里。
1. 修改xhook.js代码,移除错误的DOM操作
以下是两种可行的修改方案:
方案一:使用document.write注入脚本(最直接)
document_start阶段使用document.write不会覆盖页面内容,而是作为页面初始HTML的一部分被解析,能确保脚本最早执行:
document.write(`<script type="text/javascript"> // Xhook library code - v1.4.9 // ... 这里放入完整的Xhook库代码 ... console.log('loading extension'); xhook.after(async function (request, response) { if (request.url.startsWith("https://example.com/")) { var urlParams = new URLSearchParams(window.location.search); try { const apiresponse = await fetch('https://example.com/robots.txt'); if (apiresponse.status === 200) { // 注意:这里需要await获取文本内容,否则response.text会是Promise对象 response.text = await apiresponse.text(); } else { console.log('File not found. Status Code: ' + apiresponse.status); } } catch (err) { console.error('Fetch failed:', err); } } }); xhook.enable(); <\/script>`);
方案二:创建script标签并插入到文档根节点
如果你更倾向于DOM操作的方式,可将脚本插入到<html>元素中(document_start阶段<html>已经存在):
var script_tag = document.createElement('script'); script_tag.type = 'text/javascript'; script_tag.textContent = ` // Xhook library code - v1.4.9 // ... 这里放入完整的Xhook库代码 ... console.log('loading extension'); xhook.after(async function (request, response) { if (request.url.startsWith("https://example.com/")) { var urlParams = new URLSearchParams(window.location.search); try { const apiresponse = await fetch('https://example.com/robots.txt'); if (apiresponse.status === 200) { response.text = await apiresponse.text(); } else { console.log('File not found. Status Code: ' + apiresponse.status); } } catch (err) { console.error('Fetch failed:', err); } } }); xhook.enable();`; // 插入到<html>元素中,确保脚本最早被执行 document.documentElement.appendChild(script_tag);
2. 额外修复:Xhook拦截中的异步问题
你的原代码里response.text = apiresponse.text();存在逻辑错误——apiresponse.text()返回的是Promise对象,直接赋值会导致response.text不是预期的文本内容。上面的代码用async/await修正了这个问题,确保能正确获取并设置响应文本。
为什么这样能解决问题?
- 移除手动创建
body的逻辑后,浏览器会正常生成页面原生的DOM结构,不会再出现重复body标签的问题。 - 脚本注入到文档根节点或使用
document.write,能保证脚本在页面所有原生脚本之前执行,且运行在页面的全局上下文,这样你注入的xhook等变量就能被主页面代码正常访问。
内容的提问来源于stack exchange,提问作者user9811991




