Commit 7565b09d authored by Aaron Leventhal's avatar Aaron Leventhal Committed by Commit Bot

Useful result for IAText get_characterExtents() in empty textfield

Products like ZoomText use get_characterExtents with the special IA2_TEXT_OFFSET_CARET to get the
bounds of the character with the caret. Sometimes this results in getting the bounds for the
null character at the end of an editable textfield's text. In this case, get_characterExtents()
should return what the caret bounds would be if placed there.

In order to make this work, we can use the bounds of the anonymous inner editor element within
a textfield, and collapse it to the width of the caret. Normally this is exposed, but in the
case of an empty textfield, we were ignoring it.

This CL also adds a lot more tests for different kinds of empty fields. The plan is to move
the character extents implementation into the ui/accessibility code so that the automation
API support can leverage it.

Bug: 869985

Change-Id: I907a9df834f88aa9bf536e4dbbc9432e33d31202
Reviewed-on: https://chromium-review.googlesource.com/c/1255203
Commit-Queue: Aaron Leventhal <aleventhal@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596513}
parent 09998805
......@@ -78,6 +78,12 @@ class AccessibilityWinBrowserTest : public ContentBrowserTest {
Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
void SetUpSingleCharInputField(
Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
void SetUpSingleCharInputFieldWithPlaceholder(
Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
void SetUpSingleCharTextarea(
Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
void SetUpSingleCharContenteditable(
Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
void SetUpSingleCharRtlInputField(
Microsoft::WRL::ComPtr<IAccessibleText>* input_text);
void SetUpTextareaField(
......@@ -206,6 +212,8 @@ void AccessibilityWinBrowserTest::SetUpScrollableInputField(
}
// Loads a page with an input text field and places a single character in it.
// Also tests with padding, in order to ensure character extent of empty field
// does not erroneously include padding.
void AccessibilityWinBrowserTest::SetUpSingleCharInputField(
Microsoft::WRL::ComPtr<IAccessibleText>* input_text) {
ASSERT_NE(nullptr, input_text);
......@@ -214,7 +222,37 @@ void AccessibilityWinBrowserTest::SetUpSingleCharInputField(
<html>
<body>
<form>
<input type="text" id="textField" name="name" value="x">
<input type="text" value="x" style="padding:3px">
</form>
</body>
</html>)HTML"));
SetUpInputFieldHelper(input_text);
}
void AccessibilityWinBrowserTest::SetUpSingleCharInputFieldWithPlaceholder(
Microsoft::WRL::ComPtr<IAccessibleText>* input_text) {
ASSERT_NE(nullptr, input_text);
LoadInitialAccessibilityTreeFromHtml(std::string(
R"HTML(<!DOCTYPE html>
<html>
<body>
<form>
<input type="text" value="x" placeholder="placeholder">
</form>
</body>
</html>)HTML"));
SetUpInputFieldHelper(input_text);
}
void AccessibilityWinBrowserTest::SetUpSingleCharTextarea(
Microsoft::WRL::ComPtr<IAccessibleText>* input_text) {
ASSERT_NE(nullptr, input_text);
LoadInitialAccessibilityTreeFromHtml(std::string(
R"HTML(<!DOCTYPE html>
<html>
<body>
<form>
<textarea rows="3" cols="10">x</textarea>
</form>
</body>
</html>)HTML"));
......@@ -274,12 +312,13 @@ void AccessibilityWinBrowserTest::SetUpInputFieldHelper(
ax::mojom::Event::kTextSelectionChanged);
std::wstring caret_offset = base::UTF16ToWide(
base::IntToString16(static_cast<int>(kContentsLength - 1)));
ExecuteScript(std::wstring(L"let textField = document.querySelector('input');"
L"textField.focus();"
L"textField.setSelectionRange(") +
caret_offset + L"," + caret_offset +
L");"
L"textField.scrollLeft = 1000;");
ExecuteScript(
std::wstring(L"let textField = document.querySelector('input,textarea');"
L"textField.focus();"
L"textField.setSelectionRange(") +
caret_offset + L"," + caret_offset +
L");"
L"textField.scrollLeft = 1000;");
waiter.WaitForNotification();
}
......@@ -1433,10 +1472,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
}
}
// TODO(accessibility) Support bounds in an empty text field where there are
// no child inline text objects, such that the following test passes.
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
DISABLED_TestCharacterExtentsInEmptyInputField) {
TestCharacterExtentsInEmptyInputField) {
Microsoft::WRL::ComPtr<IAccessibleText> input_text;
SetUpSingleCharInputField(&input_text);
......@@ -1453,6 +1490,60 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
EXPECT_LT(1, prev_width);
EXPECT_LT(1, prev_height);
base::win::ScopedBstr text0;
ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text0.Receive()));
// Delete the character in the input field.
AccessibilityNotificationWaiter waiter(
shell()->web_contents(), ui::kAXModeComplete,
ax::mojom::Event::kTextSelectionChanged);
ExecuteScript(std::wstring(L"document.querySelector('input').value='';"));
waiter.WaitForNotification();
ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
ASSERT_EQ(0, n_characters);
LONG caret_offset;
ASSERT_HRESULT_SUCCEEDED(input_text->get_caretOffset(&caret_offset));
ASSERT_EQ(0, caret_offset);
base::win::ScopedBstr text;
ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text.Receive()));
// Now that input is completely empty, the position of the caret should be
// returned for character 0. The x,y position and height should be the same as
// it was as when there was single character, but the width should now be 1.
LONG x, y, width, height;
for (int offset = IA2_TEXT_OFFSET_CARET; offset <= 0; ++offset) {
EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
offset, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height));
EXPECT_EQ(prev_x, x);
EXPECT_EQ(prev_y, y);
EXPECT_EQ(1, width);
EXPECT_EQ(prev_height, height);
}
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
TestCharacterExtentsInEmptyInputFieldWithPlaceholder) {
Microsoft::WRL::ComPtr<IAccessibleText> input_text;
SetUpSingleCharInputFieldWithPlaceholder(&input_text);
LONG n_characters;
ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
ASSERT_EQ(1, n_characters);
// Get the rect for the only character.
LONG prev_x, prev_y, prev_width, prev_height;
EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
0, IA2_COORDTYPE_SCREEN_RELATIVE, &prev_x, &prev_y, &prev_width,
&prev_height));
EXPECT_LT(1, prev_width);
EXPECT_LT(1, prev_height);
base::win::ScopedBstr text0;
ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text0.Receive()));
// Delete the character in the input field.
AccessibilityNotificationWaiter waiter(
shell()->web_contents(), ui::kAXModeComplete,
......@@ -1466,6 +1557,117 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
ASSERT_HRESULT_SUCCEEDED(input_text->get_caretOffset(&caret_offset));
ASSERT_EQ(0, caret_offset);
base::win::ScopedBstr text;
ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text.Receive()));
// Now that input is completely empty, the position of the caret should be
// returned for character 0. The x,y position and height should be the same as
// it was as when there was single character, but the width should now be 1.
LONG x, y, width, height;
for (int offset = IA2_TEXT_OFFSET_CARET; offset <= 0; ++offset) {
EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
offset, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height));
EXPECT_EQ(prev_x, x);
EXPECT_EQ(prev_y, y);
EXPECT_EQ(1, width);
EXPECT_EQ(prev_height, height);
}
}
// TODO(accessibility) empty contenteditable gets height of entire
// contenteditable instead of just 1 line. May be able to use the following
// in Blink to get the height of a line -- it's at least close:
// layout_object->Style()->GetFont().PrimaryFont()->GetFontMetrics().Height()
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
DISABLED_TestCharacterExtentsInEmptyContenteditable) {
Microsoft::WRL::ComPtr<IAccessibleText> input_text;
SetUpSampleParagraphInScrollableEditable(&input_text);
LONG n_characters;
ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
ASSERT_LT(0, n_characters);
// Get the rect for the only character.
LONG prev_x, prev_y, prev_width, prev_height;
EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
0, IA2_COORDTYPE_SCREEN_RELATIVE, &prev_x, &prev_y, &prev_width,
&prev_height));
EXPECT_LT(1, prev_width);
EXPECT_LT(1, prev_height);
base::win::ScopedBstr text0;
ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text0.Receive()));
// Delete the character in the input field.
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kChildrenChanged);
ExecuteScript(std::wstring(
L"document.querySelector('[contenteditable]').innerText='';"));
waiter.WaitForNotification();
ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
ASSERT_EQ(0, n_characters);
LONG caret_offset;
ASSERT_HRESULT_SUCCEEDED(input_text->get_caretOffset(&caret_offset));
ASSERT_EQ(0, caret_offset);
base::win::ScopedBstr text;
ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text.Receive()));
// Now that input is completely empty, the position of the caret should be
// returned for character 0. The x,y position and height should be the same as
// it was as when there was single character, but the width should now be 1.
LONG x, y, width, height;
for (int offset = IA2_TEXT_OFFSET_CARET; offset <= 0; ++offset) {
EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
offset, IA2_COORDTYPE_SCREEN_RELATIVE, &x, &y, &width, &height));
EXPECT_EQ(prev_x, x);
EXPECT_EQ(prev_y, y);
EXPECT_EQ(1, width);
EXPECT_EQ(prev_height, height);
}
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
TestCharacterExtentsInEmptyTextarea) {
Microsoft::WRL::ComPtr<IAccessibleText> input_text;
SetUpSingleCharTextarea(&input_text);
LONG n_characters;
ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
ASSERT_EQ(1, n_characters);
// Get the rect for the only character.
LONG prev_x, prev_y, prev_width, prev_height;
EXPECT_HRESULT_SUCCEEDED(input_text->get_characterExtents(
0, IA2_COORDTYPE_SCREEN_RELATIVE, &prev_x, &prev_y, &prev_width,
&prev_height));
EXPECT_LT(1, prev_width);
EXPECT_LT(1, prev_height);
base::win::ScopedBstr text0;
ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text0.Receive()));
// Delete the character in the input field.
AccessibilityNotificationWaiter waiter(
shell()->web_contents(), ui::kAXModeComplete,
ax::mojom::Event::kTextSelectionChanged);
ExecuteScript(
std::wstring(L"document.querySelector('textarea').innerText='';"));
waiter.WaitForNotification();
ASSERT_HRESULT_SUCCEEDED(input_text->get_nCharacters(&n_characters));
ASSERT_EQ(0, n_characters);
LONG caret_offset;
ASSERT_HRESULT_SUCCEEDED(input_text->get_caretOffset(&caret_offset));
ASSERT_EQ(0, caret_offset);
base::win::ScopedBstr text;
ASSERT_HRESULT_SUCCEEDED(input_text->get_text(0, -1, text.Receive()));
// Now that input is completely empty, the position of the caret should be
// returned for character 0. The x,y position and height should be the same as
// it was as when there was single character, but the width should now be 1.
......@@ -1480,10 +1682,8 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
}
}
// TODO(accessibility) Support bounds in an empty text field where there are
// no child inline text objects, such that the following test passes.
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
DISABLED_TestCharacterExtentsInEmptyRtlInputField) {
TestCharacterExtentsInEmptyRtlInputField) {
Microsoft::WRL::ComPtr<IAccessibleText> input_text;
SetUpSingleCharRtlInputField(&input_text);
......
......@@ -511,9 +511,8 @@ gfx::Rect BrowserAccessibility::GetPageBoundsPastEndOfText() const {
if (bounds.width() == 0 && bounds.height() == 0)
return bounds; // Inline text boxes info not yet available.
} else {
// TODO(accessibility) Support bounds in an empty text field where there are
// no child inline text objects.
return bounds;
// Compute bounds of where caret would be, based on bounds of object.
bounds = GetPageBoundsRect();
}
// Step 2: correct for the thickness of the caret.
......
......@@ -8,3 +8,4 @@ rootWebArea
++++staticText name='Complex button '
++++++inlineTextBox name='Complex button '
++++textField
++++++genericContainer
\ No newline at end of file
......@@ -7,5 +7,6 @@ rootWebArea
++++staticText name='Complex '
++++++inlineTextBox name='Complex '
++++textField
++++++genericContainer
++++staticText name=' checkbox'
++++++inlineTextBox name=' checkbox'
++++++inlineTextBox name=' checkbox'
\ No newline at end of file
......@@ -3,6 +3,7 @@ rootWebArea
++++staticText name='State'
++++++inlineTextBox name='State'
++textFieldWithComboBox autoComplete='list' name='State' activedescendantId=listBoxOption restriction=readOnly haspopup=listbox
++++genericContainer
++listBox
++++listBoxOption name='Alabama' selected=false
++++listBoxOption name='Alaska' selected=true
++++listBoxOption name='Alaska' selected=true
\ No newline at end of file
rootWebArea
++textField description='Your username should be your email id' descriptionFrom=relatedElement describedbyIds=tooltip
++++genericContainer
++tooltip name='Your username should be your email id'
++++staticText name='Your username should be your email id'
++++++inlineTextBox name='Your username should be your email id'
++textField description='mmddyy' descriptionFrom=relatedElement describedbyIds=null
++++genericContainer
\ No newline at end of file
rootWebArea
++genericContainer
++++textField detailsId=paragraph
++++++genericContainer
++paragraph
++++staticText name='Details'
++++++inlineTextBox name='Details'
......@@ -14,4 +15,4 @@ rootWebArea
++++++inlineTextBox name=' has details'
++group
++++staticText name='Text details'
++++++inlineTextBox name='Text details'
++++++inlineTextBox name='Text details'
\ No newline at end of file
rootWebArea
++genericContainer
++++textField
++++++genericContainer
++++textField restriction=disabled
++++++genericContainer
++++textField
++++++genericContainer
++genericContainer restriction=disabled
++++textField restriction=disabled
++++++genericContainer
++++textField restriction=disabled
++++++genericContainer
++++textField
++++++genericContainer
++genericContainer
++++textField
++++++genericContainer
++++textField restriction=disabled
++++++genericContainer
++++textField
++++++genericContainer
\ No newline at end of file
rootWebArea
++genericContainer
++++textField errormessageId=paragraph invalidState=true
++++++genericContainer
++paragraph
++++staticText name='Error'
++++++inlineTextBox name='Error'
\ No newline at end of file
rootWebArea
++textField name='h2'
++++genericContainer
++heading name='h2' hierarchicalLevel=2
++++staticText name='h2'
++++++inlineTextBox name='h2'
\ No newline at end of file
......@@ -6,5 +6,6 @@ rootWebArea
++++++staticText name='Complex '
++++++++inlineTextBox name='Complex '
++++++textField
++++++++genericContainer
++++++staticText name=' menuitem'
++++++++inlineTextBox name=' menuitem'
++++++++inlineTextBox name=' menuitem'
\ No newline at end of file
......@@ -19,6 +19,7 @@ rootWebArea
++textField name='Readonly-true contenteditable textbox' restriction=readOnly
++checkBox name='Readonly checkbox' restriction=readOnly
++textFieldWithComboBox name='Readonly combobox' restriction=readOnly haspopup=listbox
++++genericContainer
++listBox name='Readonly listbox' restriction=readOnly
++radioGroup name='Readonly radiogroup' restriction=readOnly
++slider horizontal name='Readonly slider' restriction=readOnly
......@@ -26,4 +27,4 @@ rootWebArea
++menuItemCheckBox name='Readonly menuitemcheckbox' restriction=readOnly
++menuItemRadio name='Readonly menuitemradio' restriction=readOnly
++searchBox name='Readonly searchbox' restriction=readOnly
++switch name='Readonly switch' restriction=readOnly
++switch name='Readonly switch' restriction=readOnly
\ No newline at end of file
rootWebArea
++textField description='Your username should be your email id' descriptionFrom=relatedElement
++++genericContainer
++tooltip name='Your username should be your email id'
++++staticText name='Your username should be your email id'
++++++inlineTextBox name='Your username should be your email id'
\ No newline at end of file
......@@ -4,11 +4,13 @@ rootWebArea
++++++inlineTextBox name='State'
++comboBoxGrouping name='State' haspopup=listbox
++++textField activedescendantId=listBoxOption controlsIds=listBox
++++++genericContainer
++listBox
++++listBoxOption name='Alabama' selected=false
++++listBoxOption name='Alaska' selected=true
++comboBoxGrouping name='State' haspopup=listbox
++++textField activedescendantId=listBoxOption controlsIds=listBox
++++++genericContainer
++listBox
++++listBoxOption name='Alabama' selected=false
++++listBoxOption name='Alaska' selected=false
++++listBoxOption name='Alaska' selected=false
\ No newline at end of file
rootWebArea
++textField name='aria-placeholder1'
++++genericContainer
++textField name='placeholder2'
++++genericContainer
++textField name='aria-label3' placeholder='placeholder3'
++++genericContainer
++textField name='aria-label4' placeholder='aria-placeholder4'
++++genericContainer
++textField description='aria-description5' name='aria-label5' placeholder='placeholder5' descriptionFrom=relatedElement
++++genericContainer
++genericContainer
++++staticText name='aria-description5'
++++++inlineTextBox name='aria-description5'
++textField description='title6' name='aria-placeholder6' descriptionFrom=attribute
\ No newline at end of file
++textField description='title6' name='aria-placeholder6' descriptionFrom=attribute
++++genericContainer
\ No newline at end of file
......@@ -10,8 +10,11 @@ rootWebArea name='Action verbs'
++++staticText name='Link' defaultActionVerb=clickAncestor
++++++inlineTextBox name='Link'
++textField defaultActionVerb=activate
++++genericContainer
++searchBox defaultActionVerb=activate
++++genericContainer
++textField multiline defaultActionVerb=activate
++++genericContainer
++textField defaultActionVerb=activate
++checkBox defaultActionVerb=check checkedState=false
++checkBox defaultActionVerb=uncheck checkedState=true
......@@ -34,4 +37,4 @@ rootWebArea name='Action verbs'
++menu
++++menuItem name='Menu item 1' defaultActionVerb=select
++++menuItemCheckBox name='Menu item 2' defaultActionVerb=uncheck checkedState=true
++++menuItemRadio name='Menu item 3' defaultActionVerb=check checkedState=false
++++menuItemRadio name='Menu item 3' defaultActionVerb=check checkedState=false
\ No newline at end of file
......@@ -4,3 +4,4 @@ rootWebArea focusable
++++++staticText name='Choose a pokemon '
++++++++inlineTextBox name='Choose a pokemon '
++++++textFieldWithComboBox editable focusable autoComplete='list' name='Choose a pokemon' haspopup=listbox
++++++++genericContainer
\ No newline at end of file
......@@ -2,9 +2,11 @@ rootWebArea
++genericContainer
++++spinButton value='1' valueForRange=1.00
++++++genericContainer
++++++++staticText name='1'
++++++++++inlineTextBox name='1'
++++++++genericContainer
++++++++++staticText name='1'
++++++++++++inlineTextBox name='1'
++++spinButton value='6' valueForRange=6.00 minValueForRange=5.00 maxValueForRange=10.00
++++++genericContainer
++++++++staticText name='6'
++++++++++inlineTextBox name='6'
++++++++genericContainer
++++++++++staticText name='6'
++++++++++++inlineTextBox name='6'
\ No newline at end of file
rootWebArea
++genericContainer
++++textField
++++++genericContainer
++++button name='Reset'
\ No newline at end of file
rootWebArea
++form
++++textField
++++++genericContainer
++++button name='Submit'
\ No newline at end of file
rootWebArea
++genericContainer
++++textFieldWithComboBox autoComplete='list' haspopup=listbox
++++++genericContainer
\ No newline at end of file
rootWebArea
++textField name='Title0'
++++genericContainer
++textField description='Title1' name='Label1' descriptionFrom=attribute
++++genericContainer
++textField description='Title2' name='AriaLabel2' descriptionFrom=attribute
++++genericContainer
++textField description='Title3' name='LabelledBy3' descriptionFrom=attribute
++++genericContainer
++textField name='Placeholder4'
++++genericContainer
++textField name='ARIA Placeholder4a'
++++genericContainer
++textField name='Placeholder4b'
++++genericContainer
++textField description='Title5' name='Placeholder5' descriptionFrom=attribute
++++genericContainer
++textField description='DescribedBy6' name='LabelledBy6' descriptionFrom=relatedElement
\ No newline at end of file
++textField description='DescribedBy6' name='LabelledBy6' descriptionFrom=relatedElement
++++genericContainer
\ No newline at end of file
......@@ -4,6 +4,7 @@ rootWebArea focusable
++++++staticText name='l1'
++++++++inlineTextBox name='l1'
++++textField focusable name='l1'
++++++genericContainer
++++labelText
++++++staticText name='l2'
++++++++inlineTextBox name='l2'
......@@ -12,6 +13,7 @@ rootWebArea focusable
++++++++staticText name='value'
++++++++++inlineTextBox name='value'
++++textField focusable name='l2'
++++++genericContainer
++++textField focusable name='l2' value='value *'
++++++genericContainer
++++++++staticText name='value *'
......@@ -21,11 +23,13 @@ rootWebArea focusable
++++++++inlineTextBox name='Email'
++++genericContainer
++++textField focusable name='Email'
++++++genericContainer
++++textField focusable name='Email' value='value'
++++++genericContainer
++++++++staticText name='value'
++++++++++inlineTextBox name='value'
++++textField focusable multiline name='l5'
++++++genericContainer
++++textField focusable multiline name='l6' value='Value'
++++++genericContainer
++++++++staticText name='Value'
......@@ -33,4 +37,4 @@ rootWebArea focusable
++++textField focusable description='Description' name='Name' value='value' descriptionFrom=attribute
++++++genericContainer
++++++++staticText name='value'
++++++++++inlineTextBox name='value'
++++++++++inlineTextBox name='value'
\ No newline at end of file
rootWebArea
++genericContainer
++++textField name='oranges'
++++++genericContainer
++++textField name='bananas'
++++++genericContainer
\ No newline at end of file
......@@ -7,7 +7,9 @@ rootWebArea
++++++staticText name='Browser: '
++++++++inlineTextBox name='Browser: '
++++++textField
++++++++genericContainer
++++++staticText name=' Rendering Engine: '
++++++++inlineTextBox name=' '
++++++++inlineTextBox name='Rendering Engine: '
++++++textField
\ No newline at end of file
++++++textField
++++++++genericContainer
\ No newline at end of file
......@@ -64,9 +64,11 @@ test(function(t)
var axContainer3 = accessibilityController.accessibleElementById("container3");
assert_equals(axContainer3.childrenCount, 2);
assert_equals(axContainer3.childAtIndex(0).role, "AXRole: AXTextField");
assert_equals(axContainer3.childAtIndex(0).childrenCount, 0);
// An input element naturally gets 1 child that corresponds to the anonymous
// inner editor element.
assert_equals(axContainer3.childAtIndex(0).childrenCount, 1);
assert_equals(axContainer3.childAtIndex(1).role, "AXRole: AXMenu");
}, "Aria-owns doesn't create children of an input element.");
}, "Aria-owns doesn't create extra children of an input element.");
</script>
<div class="container" id="container4" role="group" aria-label="Container">
......
......@@ -4,7 +4,7 @@ This tests a crashing scenario where an element with a role attribute is a child
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS input.childrenCount is 0
PASS input.childrenCount is 1
PASS successfullyParsed is true
TEST COMPLETE
......
......@@ -20,7 +20,7 @@
// This line should not crash.
var input = accessibilityController.focusedElement;
shouldBe("input.childrenCount", "0");
shouldBe("input.childrenCount", "1");
}
</script>
......
......@@ -629,6 +629,30 @@ static bool HasLineBox(const LayoutBlockFlow& block_flow) {
return false;
}
// Is this the anonymous placeholder for a text control?
bool AXLayoutObject::IsPlaceholder() const {
AXObject* parent_object = ParentObject();
if (!parent_object)
return false;
LayoutObject* parent_layout_object = parent_object->GetLayoutObject();
if (!parent_layout_object || !parent_layout_object->IsTextControl())
return false;
LayoutTextControl* layout_text_control =
ToLayoutTextControl(parent_layout_object);
DCHECK(layout_text_control);
TextControlElement* text_control_element =
layout_text_control->GetTextControlElement();
if (!text_control_element)
return false;
HTMLElement* placeholder_element = text_control_element->PlaceholderElement();
return GetElement() == static_cast<Element*>(placeholder_element);
}
bool AXLayoutObject::ComputeAccessibilityIsIgnored(
IgnoredReasons* ignored_reasons) const {
#if DCHECK_IS_ON()
......@@ -687,8 +711,18 @@ bool AXLayoutObject::ComputeAccessibilityIsIgnored(
// Make sure renderers with layers stay in the tree.
if (GetLayoutObject() && GetLayoutObject()->HasLayer() && GetNode() &&
GetNode()->hasChildren())
GetNode()->hasChildren()) {
if (IsPlaceholder()) {
// Placeholder is already exposed via AX attributes, do not expose as
// child of text input. Therefore, if there is a child of a text input,
// it will contain the value.
if (ignored_reasons)
ignored_reasons->push_back(IgnoredReason(kAXPresentational));
return true;
}
return false;
}
// Find out if this element is inside of a label element. If so, it may be
// ignored because it's the label for a checkbox or radio button.
......@@ -871,6 +905,14 @@ bool AXLayoutObject::ComputeAccessibilityIsIgnored(
if (layout_object_->IsPositioned())
return false;
// Inner editor element of editable area with empty text provides bounds
// used to compute the character extent for index 0. This is the same as
// what the caret's bounds would be if the editable area is focused.
if (ParentObject() && ParentObject()->GetLayoutObject() &&
ParentObject()->GetLayoutObject()->IsTextControl()) {
return false;
}
// Ignore layout objects that are block flows with inline children. These
// are usually dummy layout objects that pad out the tree, but there are
// some exceptions below.
......
......@@ -236,6 +236,7 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
bool CanIgnoreTextAsEmpty() const;
bool CanIgnoreSpaceNextTo(LayoutObject*, bool is_after) const;
bool HasAriaCellRole(Element*) const;
bool IsPlaceholder() const;
bool is_autofill_available_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment