识别帧层次结构中的true activeElement

时间:2017-02-15 07:33:38

标签: google-chrome-extension firefox-addon firefox-webextensions

我正在寻找一种方法来获取任何页面的重点输入,目的是更新它的价值。

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

挑战在于主文档的activeElement是iframe。我可以在清单中设置all_frames: true,它会找到任何有效的<input>,但我只想设置活动iframe的activeElement的值。

目前我通过让子内容脚本blur()除了当前的所有activeElements(将处理程序附加到focusin)来解决这个问题,但解决方法是不修改文件状态会更好imho。

是否可以仅向主文档发送消息,如果这个主动元素是iframe,那么获取该frameId(并再试一次)?

我无法控制网页。

1 个答案:

答案 0 :(得分:0)

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

主要内容脚本会根据需要询问背景/事件页面:

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

background/event page脚本在所有框架中执行其他内容脚本:

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!';
}
})();

我没有对此进行测试,但之前使用并看过类似的代码。