How to find out what event listener types attached to specific HTML element in Chrome extension?
-
29-10-2019 - |
题
I'm posting this question here, since I can't get it posted on the official Chromium extension forums (or there's a terrific delay until it's being moderated). I have to check in Chromium extension whether there's a listener of a specific event type attached to an arbitrary HTML element. In Firefox I could use the following service to get this information:
var listenerService = Components.classes["@mozilla.org/eventlistenerservice;1"]
.getService(Components.interfaces.nsIEventListenerService);
var infos = listenerService.getListenerInfoFor(element, {});
var types = [];
for ( var i = 0; i < infos.length; ++i) {
var info = infos[i].QueryInterface(Components.interfaces.nsIEventListenerInfo);
types.push(info.type);
}
As I see in Chromium there's no similar API. Therefore I've tried the following technique (which was suggested here):
I've created script events_spy.js
:
(function(original) {
Element.prototype.addEventListener = function(type, listener, useCapture) {
if (typeof (this._handlerTypes) == 'undefined') {
this._handlerTypes = {};
}
this._handlerTypes[type] = true;
return original.apply(this, arguments);
}
})(Element.prototype.addEventListener);
(function(original) {
Element.prototype.removeEventListener = function(type, listener,useCapture) {
if (typeof (this._handlerTypes) != 'undefined') {
delete this._handlerTypes[type];
}
return original.apply(this, arguments);
}
})(Element.prototype.removeEventListener);
I declare this script in manifest.json
as follows:
"content_scripts" : [{
"matches" : [ "http://*/*", "https://*/*" ],
"js" : [ "content/events_spy.js" ],
"run_at" : "document_start",
"all_frames" : true
},
...
]
Then, I test my extension on the following HTML page:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<a id="test" href="#">Click here</a>
<script type="application/javascript">
document.getElementById("test").addEventListener("click", function()
{ alert("clicked"); }, false);
</script>
</body>
</html>
Unfortunately, this doesn't work - I can't see that debugger stops
inside of my custom addEventListener()
function. What am I doing wrong?
Thanks!
EDIT: Final (dirty) solution, thanks to @kdzwinel
var injectedJS = "\
(function(original) { \
Element.prototype.addEventListener = function(type, listener, useCapture) { \
var attr = this.getAttribute('_handlerTypes'); \
var types = attr ? attr.split(',') : []; \
var found = false; \
for (var i = 0; i < types.length; ++i) { \
if (types[i] == type) { \
found = true; \
break; \
} \
} \
if (!found) { \
types.push(type); \
} \
this.setAttribute('_handlerTypes', types.join(',')); \
return original.apply(this, arguments); \
} \
})(Element.prototype.addEventListener); \
\
(function(original) { \
Element.prototype.removeEventListener = function(type, listener, useCapture) { \
var attr = this.getAttribute('_handlerTypes'); \
var types = attr ? attr.split(',') : []; \
var removed = false; \
for (var i = 0; i < types.length; ++i) { \
if (types[i] == type) { \
types.splice(i, 1); \
removed = true; \
break; \
} \
} \
if (removed) { \
this.setAttribute('_handlerTypes', types.join(',')); \
} \
return original.apply(this, arguments); \
} \
})(Element.prototype.removeEventListener); \
";
var script = document.createElement("script");
script.type = "text/javascript";
script.appendChild(document.createTextNode(injectedJS));
document.documentElement.appendChild(script);
Every HTML element that has an attached event listeners will have a special attribute "_handlerTypes", which contains comma separated list of events. And this attribute is accessible from Chrome extension's content script!
没有正确的解决方案