Closed Bug 854439 Opened 9 years ago Closed 9 years ago

nsIEventListenerInfo & nsIEventListenerService for JSD2

Categories

(Core :: DOM: Events, defect)

20 Branch
x86
Windows Vista
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla23

People

(Reporter: Honza, Assigned: bzbarsky)

References

Details

(Whiteboard: [firebug-p1])

Attachments

(1 file)

Firebug is using nsIEventListenerInfo & nsIEventListenerService interfaces to enumerate event listeners for a node.

However these interfaces are wired to JSD1

Check out getDebugObject() method: https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIEventListenerInfo

Since JSD1 has been replaced by JSD2, could we also have new interfaces for event listeners enumeration?

---

These interfaces have been implemented as part of Bug 448602.

There is also one reported requirement here:
Bug 524674 - nsIEventListenerService: tracking of dynamically added and removed event listeners

Honza
Whiteboard: [firebug-p1]
What similar facilities does jsd2 expose?

Afaik the basic design requirement here was to allow debugging a JS listener without actually handing out the object itself.  I don't quite understand why we have that last restriction, honestly...
In my opinion we should be able to get the script (and the uri and line number) without using getDebugObject() ... we need to be in privileged code in order to use these listeners anyhow so there are no security implications.
At the time ELS was added, calling random callbacks without pushing correct cx to stack was
too error/security prone. So the callback was handed only via getDebugObject.
Because of compartments it is still error prone in C++, but I guess
xpconnect handles the case for JS.
(In reply to Michael Ratcliffe [:miker] [:mratcliffe] from comment #2)
>  we need to be in privileged code
> in order to use these listeners anyhow so there are no security implications.
In the old days there were security implications. The callback might have been a function from content,
but if chrome would call it, it got chrome privileges. But as far as I know, that security prone
case is fixed.
Michael, if we just handed you the JS Function object (well, a cross-compartment SJOW around it, actually), would that be good enough?
If it is possible to get the uri and line number from that then yes, it would be perfect.
That's something to ask the JS debugger folks, presumably....
(In reply to Boris Zbarsky (:bz) from comment #7)
> That's something to ask the JS debugger folks, presumably....

As a first step, a JS Function object with a cross-compartment SJOW around it would be great.
We no longer hand out chrome privileges to code based on its caller; we use its compartment instead. So I don't think there's any reason nsIEventListenerInfo should avoid simply handing out the actual listener object.

Debugger can take a content object and produce a Debugger.Object instance referring to it. Then, if the referent is a function, D.Object can hand you a Debugger.Script instance referring to that function's script. Then, that script knows its URL and line number.

So if we had an imaginary nsIEventListenerInfo::getObject method, and the following variables:
- GDO, a Debugger.Object instance referring to a debuggee global object or window
- ELI, an nsIEventListenerInfo of interest
I think it would go like this:

var listener = ELI.getObject();
var listenerDO = GDO.makeDebuggeeValue(listener);
var scriptDS = listenerDO.script;
var url = scriptDS.url;
var startLine = scriptDS.startLine;

(It may seem odd that one works from GDO, but a Debugger.Object instance needs to know which compartment its referent is viewed from, since different compartments have different views of an object. The call 'viewerDO.makeDebuggeeValue(viewee)' returns a Debugger.Object instance that refers to viewee, as it would be seen by code in the compartment of the referent of viewerDO. So here, GDO specifies the compartment from which listener is being viewed. listenerDO.unwrap would return a DO referring to the listener from its own compartment, if you want that.)
(In reply to Jim Blandy :jimb from comment #9)
> We no longer hand out chrome privileges to code based on its caller; we use
> its compartment instead. So I don't think there's any reason
> nsIEventListenerInfo should avoid simply handing out the actual listener
> object.
Yep, that should perfectly work for Firebug.

Honza
Assignee: nobody → bzbarsky
Whiteboard: [firebug-p1] → [need review][firebug-p1]
Comment on attachment 732026 [details] [diff] [review]
Expose the underlying JS object of scripted event listeners on nsIEventListenerInfo.

Some test would be nice.
Attachment #732026 - Flags: review?(bugs) → review+
I added some tests to content/events/test/test_bug448602.html
https://hg.mozilla.org/integration/mozilla-inbound/rev/c3b41432afea
Flags: in-testsuite+
Whiteboard: [need review][firebug-p1] → [firebug-p1]
Target Milestone: --- → mozilla23
https://hg.mozilla.org/mozilla-central/rev/c3b41432afea
Status: NEW → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
I've noticed that (some?) system event listeners don't return a listenerObject. Is this by design or an omission?

For example, try running this scratchpad in a browser context on mozilla.org:
https://gist.github.com/past/5443573

Notice that the key events on the #id_email input don't get a listenerObject.
Is #id_email an input element or similar. Elements may have event listeners implemented in C++.
(In reply to Olli Pettay [:smaug] from comment #17)
> Is #id_email an input element or similar. Elements may have event listeners
> implemented in C++.

#id_email is indeed an input field of type 'email'. I guess my question is, can I expect that a missing listenerObject corresponds to a native event listener, or could it be one that is implemented in JS but not visible to my code due to security constraints?

My use case is displaying those listeners in the JS debugger, so in the latter case I would need to find some way to get to those listeners when debugging chrome JS.
Chrome/privileged JS should be able to access any JS listeners. So null listenerObject should indeed 
correspond to native listener.
You need to log in before you can comment on or make changes to this bug.