Closed Bug 1514093 Opened 2 years ago Closed 2 years ago

AccessibleHandler: IAccessible::get_accSelection fails with 0x800706f7: The stub received bad data.


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




Tracking Status
firefox66 --- fixed


(Reporter: Jamie, Assigned: Jamie)



(2 files)

Calling IAccessible::get_accSelection in-process with AccessibleHandler enabled returns 0x800706f7 (The stub received bad data). I have no idea why yet. With the handler disabled, it behaves as expected; i.e. it returns a VT_UNKNOWN which can be QIed to IEnumVARIANT. This is breaking new functionality for NVDA (not yet landed) which renders the selected item in browse mode for list boxes and trees.
Is this broken for listboxes *and* trees? I se in AccessibleWrap::get_accSelection that we have a special case for selects (which in this case means select @size>1), but not for trees.
I tested and it's broken for both. However, that isn't actually a special case. IsSelect() will return true for trees as well because ARIAMap specifies the eSelect type for role tree (and IsSelect calls HasGenericType, which also checks ARIAMap).
Test cases:

HTML select, selected item should be "b":
data:text/html,<select size="2"><option>a</option><option selected>b</option></select>

ARIA tree, selected item should be "b":
data:text/html,<div role="tree"><div role="treeitem">a</div><div role="treeitem" aria-selected="true" tabindex="0">b</div></div>
Aaron, do you have any idea why VT_UNKNOWN in a VARIANT out param breaks when the handler is in play? A generic IUnknown really should work. Even so, I changed a11y::HandlerProvider::GetEffectiveOutParamIid to return IID_IEnumVARIANT for IAccessible::get_accSelection (and verified that it hits that code path), but I still get this error. If I change the calling code to return  a single accessible as a VT_DISPATCH instead (just a test; that isn't practical for multiple selection), everything behaves as it should. If I return a single accessible with VT_UNKNOWN, it breaks. The fact that this only breaks with the handler suggests this is not MainThreadHandoff, but something specific to the HandlerProvider stuff. I can't fathom it beyond that, though, as the HandlerProvider shouldn't try to do anything unless the iid is IDispatch or IAccessible*.
Flags: needinfo?(aklotz)
We only use the handler for specific interfaces such as IAccessible* and IAccessibleHyperlink.
For interfaces which don't use the handler, we currently write an empty payload, but this still adds bytes to the stream.
This seems to break marshaling such an interface in a VT_UNKNOWN in a VARIANT.
To fix this, just don't write any payload at all when we aren't using the handler for the target interface.
Our accSelection implementation always returns an IUnknown which clients QI to IEnumVARIANT.
Marshaling as IUnknown works fine in this case, but it's more efficient and correct to marshal the correct interface.
Also, without this, we'd hit an assertion.

Depends on D16662

Figured it out.

Flags: needinfo?(aklotz)
Pushed by
part 1: A11y HandlerProvider: Don't write any payload at all (even an empty one) if the handler isn't used for the target interface. r=aklotz
part 2: Marshal the result from IAccessible::get_accSelection as IEnumVARIANT. r=MarcoZ
Closed: 2 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla66
You need to log in before you can comment on or make changes to this bug.