How to find out what event listener types attached to specific HTML element in Chrome extension?

StackOverflow https://stackoverflow.com/questions/8915461

  •  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!

没有正确的解决方案

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top