在框架层次结构中识别真正的活动元素
Identify true activeElement in a frame hierarchy
我正在寻找一种方法来获取任何页面的重点输入,目的是更新它的值。
我有一个接收值并检查 activeElement 是否为 <input>
.
的内容脚本
挑战在于主文档的 activeElement 是 iframe。我可以在清单中设置 all_frames: true
,这将找到任何活动的 <input>
,但我只想设置活动 iframe 的 activeElement 的值。
目前我正在通过让子内容脚本 blur()
除了当前的所有 activeElements(将处理程序附加到 focusin
)来解决这个问题,但是一个不修改的解决方案恕我直言,文档状态会更好。
是否可以只向主文档发送消息,如果这个的 activeElement 是一个 iframe,获取那个 frameId(然后重试)?
我不控制网页。
注入一个新的内容脚本来检查框架的完整层次结构,包括 cross-domain 个框架。
主要内容脚本 询问 background/event 页面是否需要:
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!';
}
})();
我没有对此进行测试,但之前确实使用过并看到过类似的代码。
我正在寻找一种方法来获取任何页面的重点输入,目的是更新它的值。
我有一个接收值并检查 activeElement 是否为 <input>
.
挑战在于主文档的 activeElement 是 iframe。我可以在清单中设置 all_frames: true
,这将找到任何活动的 <input>
,但我只想设置活动 iframe 的 activeElement 的值。
目前我正在通过让子内容脚本 blur()
除了当前的所有 activeElements(将处理程序附加到 focusin
)来解决这个问题,但是一个不修改的解决方案恕我直言,文档状态会更好。
是否可以只向主文档发送消息,如果这个的 activeElement 是一个 iframe,获取那个 frameId(然后重试)?
我不控制网页。
注入一个新的内容脚本来检查框架的完整层次结构,包括 cross-domain 个框架。
主要内容脚本 询问 background/event 页面是否需要:
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!';
}
})();
我没有对此进行测试,但之前确实使用过并看到过类似的代码。