Closed Bug 1473234 Opened Last year Closed 8 months ago

Collapsed <select size="1"> in iframes don't fire value change events

Categories

(Core :: Disability Access APIs, defect, P2)

All
Windows
defect

Tracking

()

RESOLVED FIXED
mozilla68
Tracking Status
firefox-esr60 --- wontfix
firefox66 --- wontfix
firefox67 --- wontfix
firefox68 --- fixed

People

(Reporter: Jamie, Assigned: Jamie)

References

Details

(Keywords: regression)

Attachments

(1 file)

STR (with the NVDA screen reader):
1. Open this URL:
data:text/html,<iframe src="data:text/html,<select size='1'><option>a</option><option>b</option>">
2. Tab to the combo box.
3. Press down arrow.
Expected: NVDA should report "b"
Actual: NVDA reports nothing.

This works outside of an iframe, but fails with the iframe.

This broke in Firefox 57 due to e10s.

Originally reported in an NVDA issue: https://github.com/nvaccess/nvda/issues/7819

Also broken with shadow DOM. Same STR. Test case:
data:text/html,<div id="host"></div><script>let shadow = host.attachShadow({mode: "open"}); shadow.innerHTML = '<select><option>a</option><option>b</option></select>';</script>

We listen for DOM events on RootAccessible. Perhaps iframe and shadow DOM events don't bubble up that far?

Smaug, is there some way we can globally listen such that we catch specific DOM events from iframes/shadow DOM, or is the only way to add an event listener on each document/shadow root?

Flags: needinfo?(bugs)

RootAccessible isn't any event target. Where are the listeners added?
window's chrome event handler or basically https://searchfox.org/mozilla-central/rev/dc0adc07db3df9431a0876156f50c65d580010cb/dom/base/nsPIDOMWindow.h#351 would be such place which would capture events also from iframes.

Flags: needinfo?(bugs)

(In reply to Olli Pettay [:smaug] from comment #3)

RootAccessible isn't any event target. Where are the listeners added?

In RootAccessible::AddEventListeners:
https://searchfox.org/mozilla-central/source/accessible/generic/RootAccessible.cpp#159

window's chrome event handler or basically https://searchfox.org/mozilla-central/rev/dc0adc07db3df9431a0876156f50c65d580010cb/dom/base/nsPIDOMWindow.h#351 would be such place which would capture events also from iframes.

Thanks! Tweaking RootAccessible::AddEventListeners to register with nsPIDOMWindowInner::GetChromeEventHandler fixes this for iframes. However, it doesn't fix it for shadow DOM; see example in comment 1. Is there some way we can get events from within shadow DOM as well? (I can see why this would normally not be something you'd want to do, but a11y needs these events.)

Flags: needinfo?(bugs)

It should fix for shadow DOM too, because event non-composed events propagate to window's parent
https://searchfox.org/mozilla-central/rev/dc0adc07db3df9431a0876156f50c65d580010cb/dom/base/ShadowRoot.cpp#461-470
GetParentTarget usage there.

Flags: needinfo?(bugs)

(In reply to Olli Pettay [:smaug] from comment #5)

It should fix for shadow DOM too, because event non-composed events propagate to window's parent

You're right; we do get the event. However, when we get the event, we can't process it straight away; we hold on to the Event and schedule it for a future refresh driver tick. It seems that for shadow DOM ValueChange events from select elements, event->GetOriginalTarget() succeeds when we get the event, but it returns null when we process it later in the future fresh driver tick. (In contrast, this doesn't happen for these events outside of shadow DOM.)

I made a change to hold onto the target node as well and this seems to work. However, a few questions:

  1. Why is this different for shadow DOM?
  2. Is this expected?
  3. Normally, GetOriginalTarget returning null in this way indicates to us that the node died before we could process the event, so we just ignore it. I guess now the node can't die where it might have previously, but that does potentially change the life-cycle a bit here. Could holding onto the node like this cause any problems you can think of if the node would otherwise have died?
  4. Is there anyone else I can ask questions like these in future? I realise you probably get a whole stack of NIs. :)
Flags: needinfo?(bugs)

Yes, event's targets get cleared when dealing with shadow DOM.
This is per spec and it is about not revealing shadow DOM to light DOM, if someone keeps a pointer to the event after dispatch, just like what you do.

If you keep event object (dispatched to light DOM) alive, its original target doesn't magically disappear.

(My ni? queue is long and I should clear it :) Happy to answer to questions, and if I'm slow with answering, just ping on IRC)

Flags: needinfo?(bugs)
Assignee: nobody → jteh
Status: NEW → ASSIGNED
Depends on: 1530931
  1. Register with the root document window's parent target, since this receives events for iframes and shadow DOM.
  2. Hold onto the target node when scheduling processing of the DOM event, as GetOriginalTarget returns null when we process shadow DOM events async.

Depends on D21349

Pushed by jteh@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/54057e1121b5
make a11y listen to DOM events from iframes and shadow DOM. r=eeejay
Pushed by jteh@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/5697e0aa6e26
make a11y listen to DOM events from iframes and shadow DOM. r=eeejay
Status: ASSIGNED → RESOLVED
Closed: 8 months ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla68
Flags: needinfo?(jteh)
You need to log in before you can comment on or make changes to this bug.