I am writing a browser extension that needs to attach handlers to the keyup and keydown events on all pages. I can get it working pretty well with the following content script code.
document.addEventListener("keydown",keyDown, true);
document.addEventListener("keyup", keyUp, true);
I can’t get this to work in Gmail though. Specifically I can’t get it to work when composing the body of an new email. It will work everywhere else I have tested. I think the problem is because Gmail is calling stopPropagation on all keyboard events but it is difficult to debug their minimized code. I thought that setting the 3rd parameter to true would cause the event to be captured during the CAPTURE_PHASE but this isn’t working.
How can I capture keyup and keydown events while composing a new body in Gmail with a Google Chrome content script?
Edit:
I’ve ensured that my content scripts are being injected into all iframes of the DOM by adding "all_frames": true, to my manifest. I have even tried using the following code:
document.addEventListener("DOMNodeInserted", function (event) {
if(event.type === "DOMNodeInserted") {
if(event.srcElement.nodeName === "IFRAME") {
console.log(event.srcElement.nodeName + " iframe detected");
event.srcElement.addEventListener("keydown", function(kevent) {
document.dispatchEvent(kevent);
}, true);
event.srcElement.addEventListener("keyup", function(kevent) {
document.dispatchEvent(kevent);
}, true);
}
}
},true);
This still doesn’t fix the issue with Gmail.
Your code doesn’t work because
event.srcElementrefers to the<iframe>element, not its content. To access its content document, you have to wait for the frame to be loaded (onloador polling), then useframe.contentDocumentto access the frame.Starting from Chrome 37.0.1995.0, you can also use the
match_about_blank(with all_frames) to insert a content script in theabout:blankframe that captures the event and sends it to the parent content script.Here is an example of an implementation for the original idea (using polling):
The relevant parts of
manifest.json:contentscript.jsNote that I used polling instead of DOM mutation events, because the latter heavily reduces performance.