我正在对 Chrome 扩展进行一些更新,重新定义 navigator.userAgent, 我在用 MutationObserver 替换 DOMNodeInserted 时遇到了这种行为..
这个问题是通用的,不需要通过 Chrome 扩展进行测试。
解释此行为的最佳方法是导航至: https://webbrowsertools.com/useragent/
然后...使用控制台运行以下 javacript 代码,并检查 iframe> navigator.userAgent 的响应:
DOMNodeInserted 工作正常,iframe > navigator.userAgent 已切换:
document.addEventListener('DOMNodeInserted', function(event)
{
if (event.target.tagName == 'IFRAME')
for (var i=0; i<window.frames.length; i++)
try { Object.defineProperty(window.frames[i].navigator, 'userAgent', {value:'TEST'}); } catch(e) {}
});
MutationObserver 不起作用,iframe > navigator.userAgent 未切换:
var observer = new MutationObserver(function(mutations)
{
for (var mutation of mutations)
for (var item of mutation.addedNodes)
if (item.tagName == 'IFRAME')
for (var i=0; i<window.frames.length; i++)
try { Object.defineProperty(window.frames[i].navigator, 'userAgent', {value:'TEST'}); } catch(e) {}
});
observer.observe(document, { childList:true, subtree:true });
请原谅通过 window.frames 进行的粗略迭代,而不是实际的 event.target
我相信这与 MutationObserver 太慢有关,但我不知道如何解决这个问题?!
我无法重现您的行为,所以代码片段抱怨 CORS iframe,所以这里是一个 JSFiddle
这是代码
const daFrame = document.createElement("iframe"),
body = document.body,
obs = new MutationObserver(function(muts){
muts.forEach(mut => {
if(mut.type !== "childList"){return}
mut.addedNodes.forEach(n => {
if(!(n instanceof HTMLIFrameElement)){return}
Object.defineProperty(
n.contentWindow.navigator,
"userAgent",
{value: "whateva"}
)
})
})
});
obs.observe(document.body, {childList: true, subtree: true});
setTimeout(() => document.body.appendChild(daFrame), 0);
setTimeout(() => console.log(`userAgent =`, window.frames[0].navigator.userAgent), 3000);
我使用
setTimeout
引入延迟来启动 MutationObserver
,以防 DOM 节点(在本例中为 iframe)可能在观察者启动之前插入。
如果您不想使用 setTimeout,您还可以将
Promise
推送到外部数组并解析这些推送的承诺。但这不是这个问题的主题。