HyperTextAccessible::IsCaretAtEndOfLine returns true when it shouldn't
Categories
(Core :: Disability Access APIs, defect)
Tracking
()
People
(Reporter: Jamie, Assigned: Jamie)
References
(Blocks 2 open bugs, Regressed 1 open bug)
Details
Crash Data
Attachments
(2 files, 1 obsolete file)
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
RyanVM
:
approval-mozilla-beta-
RyanVM
:
approval-mozilla-release+
RyanVM
:
approval-mozilla-esr128+
|
Details | Review |
STR:
- Open this test case:
data:text/html,<div contenteditable>a<span>b
- Focus the editable text.
- Press right arrow.
- Open the NVDA Python console with NVDA+control+z.
- Enter this command:
nav.IAccessibleTextObject.textAtOffset(-2, 0)
- Note: -2 is caret. 0 is character.
- Expected: (1, 2, 'b')
- Actual: (1, 1, None)
Impact: This breaks caret exposure when moving the cursor forward to the start of a new node. This bug has existed for a long time, but it's more problematic now that we're implementing UIA text and now that NVDA will start using IA2_TEXT_OFFSET_CARET.
This occurs because HyperTextAccessible::IsCaretAtEndOfLine() returns true here, but it shouldn't; we're definitely not at the end of a line. That function assumes that CaretAssociationHint::Before always means that the caret is at the end of a line, which is a reasonable assumption given the code comments but doesn't seem to be true. It can also mean that the caret is positioned before the start of a node. This behaviour seems to be true going as far back as 2013 (bug 880159 when a11y first started using this), probably much further. We need to detect that case and return false. That's probably going to involve checking whether the previous character is on a different line if mOffset is 0. (If mOffset > 0, this is not a node boundary, so this case doesn't apply.)
Assignee | ||
Comment 1•8 months ago
|
||
Emilio, do you agree that this code comment looks wrong? The comment says:
Hint to tell if the selection is at the end of this line or beginning of next.
IN reality, the hint can also be Before
if the caret is moved forward to the start of a new node.
Is there some way (in addition to the caret association hint) to differentiate between this node crossing case and the end of wrapped line case?
Assignee | ||
Updated•8 months ago
|
Comment 2•8 months ago
|
||
Yeah I agree, that hint is not about lines necessarily, it's also about frames and nodes. To know whether the caret offset is at the beginning of the line you need to look at the caret position as well and confirm it's a line boundary, or something along those lines.
Assignee | ||
Comment 3•8 months ago
|
||
This nearly works, but for some reason, when you first focus a contentEditable, you get CaretAssociationHint::Before. I can't tell the difference between that case and the case that you're at the start of a node which wrapped onto a new line.
Comment 4•8 months ago
|
||
You get CaretAssociationHint::Before, with which caret position? Is the contenteditable node empty? Hard to say off-hand without that. I assume the behavior might be different with a <span contenteditable>
vs a <div contenteditable>
too?
Assignee | ||
Comment 5•8 months ago
|
||
The contentEditable is not empty. Caret position 0 in the first text node.
I think I can work around this by checking if this is the start of a block, but... this is definitely going to be ugly. :)
Assignee | ||
Comment 6•8 months ago
|
||
Previously, we assumed that CaretAssociationHint::Before always meant the caret was at the insertion point at the end of a line.
However, it can also mean that the caret is before the start of a node in the middle of a line.
To fix this, we need to check for line and paragraph boundaries.
See the code comments for details.
I moved this functionality completely out of HyperTextAccessible and into TextLeafPoint.
First, it was easiest to do these checks with private functions already available to TextLeafPoint.
Second, this ideally belongs in TextLeafPoint anyway; its existence in HyperTextAccessible was vestigial.
Assignee | ||
Updated•8 months ago
|
Comment 8•8 months ago
|
||
bugherder |
Assignee | ||
Comment 9•8 months ago
|
||
Previously, we assumed that CaretAssociationHint::Before always meant the caret was at the insertion point at the end of a line.
However, it can also mean that the caret is before the start of a node in the middle of a line.
To fix this, we need to check for line and paragraph boundaries.
See the code comments for details.
I moved this functionality completely out of HyperTextAccessible and into TextLeafPoint.
First, it was easiest to do these checks with private functions already available to TextLeafPoint.
Second, this ideally belongs in TextLeafPoint anyway; its existence in HyperTextAccessible was vestigial.
Original Revision: https://phabricator.services.mozilla.com/D215089
Updated•8 months ago
|
Updated•8 months ago
|
![]() |
||
Comment 10•8 months ago
|
||
This causes frequent accessibility crashes. The change will be backed out from the next Nightly which starts to build at 10pm UTC.
Comment 11•8 months ago
|
||
Backed out as requested for causing accessibility crashes related to selection
Backout link: https://hg.mozilla.org/mozilla-central/rev/48a7ce6fe0888f9be96810dcf74829c995f29764
Assignee | ||
Comment 12•8 months ago
|
||
Previously, we assumed that CaretAssociationHint::Before always meant the caret was at the insertion point at the end of a line.
However, it can also mean that the caret is before the start of a node in the middle of a line.
To fix this, we need to check for line and paragraph boundaries.
See the code comments for details.
Updated•8 months ago
|
Assignee | ||
Comment 13•8 months ago
•
|
||
The crash occurs when ToTextLeafPoint on the HyperTextAccessible with the caret offset returns an invalid point. I don't understand how that could happen, though. That should only happen if an invalid HyperText offset is provided, but the caret offset retrieved from HyperTextAccessible::CaretOffset should never be invalid. I've added an assertion to try to catch this with a graceful return for non-debug builds.
I did take a look at some crash dumps, but unfortunately, all of the variables I need for better diagnosis in the TextLeafPoint::GetCaret stack frame aren't included in any of the dumps.
Comment 14•8 months ago
|
||
Comment 15•8 months ago
|
||
bugherder |
Updated•8 months ago
|
Updated•8 months ago
|
Comment 16•8 months ago
|
||
Comment on attachment 9410374 [details]
Bug 1905021: Don't incorrectly treat the start of a node inside a contentEditable as the end of a line.
I'm going to sit on this request for now as we're in RC week and it only re-landed on Nightly today and it seems this could use some bake time. We can re-evaluate for the mid-cycle scheduled dot release.
Assignee | ||
Updated•8 months ago
|
Comment 17•8 months ago
|
||
release Uplift Approval Request
- User impact if declined: Some screen readers will fail to read when navigating by character in rich text editors in some cases.
- Code covered by automated testing: yes
- Fix verified in Nightly: yes
- Needs manual QE test: no
- Steps to reproduce for manual QE testing: NA
- Risk associated with taking this patch: low
- Explanation of risk level: Isolated to a single function with multiple error checks. Covered by automated tests. This is a simpler version of the patch that landed on central.
- String changes made/needed: none
- Is Android affected?: no
Assignee | ||
Comment 19•8 months ago
|
||
Yes, that was deliberate. It turns out that this bug goes back a long way, and recent fixes in the NVDA screen reader are likely to expose this bug such that it impacts users.
Updated•7 months ago
|
Comment 20•7 months ago
|
||
uplift |
Updated•7 months ago
|
Comment 21•7 months ago
|
||
Comment on attachment 9410374 [details]
Bug 1905021: Don't incorrectly treat the start of a node inside a contentEditable as the end of a line.
Approved for 128.1esr.
Updated•7 months ago
|
Updated•7 months ago
|
Comment 22•7 months ago
|
||
uplift |
Comment 23•7 months ago
|
||
This'll need a rebased patch for ESR115 if you wanted to uplift there also.
Assignee | ||
Comment 24•7 months ago
|
||
This might have been worthwhile if we could take the beta patch, but requiring yet another patch probably isn't worth it given the time we have left until ESR 115 is EOL. It also just occurred to me that if folks haven't updated to ESR 128 yet, they'll probably also be behind on NVDA updates, in which case this won't impact them.
Comment 25•7 months ago
|
||
Added to the 128.0.2 relnotes:
Fixed an issue causing some screen readers to fail to read when navigating by character in rich text editors.
Description
•