在框架层次结构中识别真正的主动元素



我正在寻找一种以更新其值的目标的重点输入的方法。

我有一个内容脚本,可以接收该值并检查ActiveEllement是否为<input>

挑战是当主文档的Activelement是iFrame时。我可以在清单中设置all_frames: true,它将找到任何活动的<input>,但我只想设置Active Iframe的ActiveEllement的值。

目前,我正在通过让儿童内容脚本blur()除当前一个(将处理程序附加到focusin),但是不修改文档状态的解决方案将是更好的IMHO。p>是否只能将消息仅发送到主文档,并且如果此操作是一个iframe,请获取frameId(然后重试)?

我不控制网页。

注入一个新的内容脚本,该脚本检查完整的帧层次结构,包括跨域帧。

主要内容脚本如果需要,请询问背景/事件页面:

if (document.activeElement.matches('input') && window == parent) {
    console.log('Input', document.activeElement);
    document.activeElement.value += ' gotcha!';
} else {
    chrome.runtime.sendMessage({action: 'modifyInput'});
}

背景/事件页脚本在所有帧中执行其他内容脚本:

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse)) {
    if (msg.action == 'modifyInput') {
        chrome.tabs.executeScript(sender.tab && sender.tab.id, {
            file: 'modify-input.js',
            allFrames: true,
            matchAboutBlank: true,
            runAt: 'document_end',
        });
    }
});

modify-input.js ,IIFE用于确保垃圾收集删除注入的东西。

;(function() {
if (isInputActive()) {
    if (window == parent) {
        foundTheInput();
    } else {
        askParent();
    }
} else if (isFrameActive()) {
    window.addEventListener('message', function onMessage(e) {
        if (!e.data || e.data.id != chrome.runtime.id)
            return;
        switch (e.data.action) {
        // request from a child frame
        case 'checkme':
            if (window == parent) {
                confirmChild(e.source);
                window.removeEventListener('message', onMessage);
            } else {
                askParent();
            }
            break;
        // response from a parent
        case 'confirmed':
            window.removeEventListener('message', onMessage);
            if (isInputActive()) {
                foundTheInput();
            } else if (isFrameActive()) {
                confirmChild(e.source);
            }
            break;
        }
    });
}
function isInputActive() {
    return document.activeElement.matches('input');
}
function isFrameActive() {
    return document.activeElement.matches('frame, iframe');
}
function askParent() {
    parent.postMessage({id: chrome.runtime.id, action: 'checkme'}, '*');
}
function confirmChild(childWindow) {
    console.log('Frame', document.activeElement);
    childWindow.postMessage({id: chrome.runtime.id, action: 'confirmed': true}, '*');
}
function foundTheInput() {
    console.log('Input', document.activeElement);
    document.activeElement.value += ' gotcha!';
}
})();

我没有测试过,但以前确实使用过类似的代码。

最新更新