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.srcElement
refers to the <iframe>
element, not its content. To access its content document, you have to wait for the frame to be loaded ( onload
or polling), then use frame.contentDocument
to 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 the about:blank
frame 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
:
"content_scripts": [{
"matches": ["*://mail.google.com/*"],
"js": ["contentscript.js"],
"run_at": "document_end"
}],
contentscript.js
function keyDown(e) {console.log(e.which);}; // Test
function keyUp(e) {console.log(e.keyCode);}; // Test
(function checkForNewIframe(doc) {
if (!doc) return; // document does not exist. Cya
// Note: It is important to use "true", to bind events to the capturing
// phase. If omitted or set to false, the event listener will be bound
// to the bubbling phase, where the event is not visible any more when
// Gmail calls event.stopPropagation().
// Calling addEventListener with the same arguments multiple times bind
// the listener only once, so we don't have to set a guard for that.
doc.addEventListener('keydown', keyDown, true);
doc.addEventListener('keyup', keyUp, true);
doc.hasSeenDocument = true;
for (var i = 0, contentDocument; i<frames.length; i++) {
try {
contentDocument = iframes[i].document;
} catch (e) {
continue; // Same-origin policy violation?
}
if (contentDocument && !contentDocument.hasSeenDocument) {
// Add poller to the new iframe
checkForNewIframe(iframes[i].contentDocument);
}
}
setTimeout(checkForNewIframe, 250, doc; // <-- delay of 1/4 second
})(document); // Initiate recursive function for the document.
Note that I used polling instead of DOM mutation events, because the latter heavily reduces performance .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.