diff options
author | nektar <nektar@chromium.org> | 2015-09-17 18:24:49 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-09-18 01:25:36 +0000 |
commit | 76e1a77f80c13c745b9740f33f767aa965f2841e (patch) | |
tree | f1560b750d3f07aa10abf2b3b78378daeb6c5194 | |
parent | f3dafca437f7e35338f3fd959423289a4f3323a3 (diff) | |
download | chromium_src-76e1a77f80c13c745b9740f33f767aa965f2841e.zip chromium_src-76e1a77f80c13c745b9740f33f767aa965f2841e.tar.gz chromium_src-76e1a77f80c13c745b9740f33f767aa965f2841e.tar.bz2 |
Uses isEditable and isRichlyEditable to determine which attributes to expose on Mac and how to represent caret position and text selection on Windows.
BUG=516869
R=dmazzoni@chromium.org
Review URL: https://codereview.chromium.org/1308153012
Cr-Commit-Position: refs/heads/master@{#349575}
15 files changed, 66 insertions, 53 deletions
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/sanity_check.js b/chrome/test/data/extensions/api_test/automation/tests/tabs/sanity_check.js index c45bd6e..b0c8846 100644 --- a/chrome/test/data/extensions/api_test/automation/tests/tabs/sanity_check.js +++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/sanity_check.js @@ -40,7 +40,7 @@ var allTests = [ assertEq('Username', userNameInput.description); state = RemoveUntestedStates(userNameInput.state); - assertEq({enabled: true, focusable: true}, state); + assertEq({editable: true, enabled: true, focusable: true}, state); var cancelButton = contentChildren[2]; assertEq('Cancel', cancelButton.name); diff --git a/components/test_runner/web_ax_object_proxy.cc b/components/test_runner/web_ax_object_proxy.cc index 0926f31..38c6afd 100644 --- a/components/test_runner/web_ax_object_proxy.cc +++ b/components/test_runner/web_ax_object_proxy.cc @@ -508,6 +508,7 @@ WebAXObjectProxy::GetObjectTemplateBuilder(v8::Isolate* isolate) { &WebAXObjectProxy::SelectionEndLineNumber) .SetProperty("isEnabled", &WebAXObjectProxy::IsEnabled) .SetProperty("isRequired", &WebAXObjectProxy::IsRequired) + .SetProperty("isEditable", &WebAXObjectProxy::IsEditable) .SetProperty("isRichlyEditable", &WebAXObjectProxy::IsRichlyEditable) .SetProperty("isFocused", &WebAXObjectProxy::IsFocused) .SetProperty("isFocusable", &WebAXObjectProxy::IsFocusable) @@ -834,6 +835,11 @@ bool WebAXObjectProxy::IsRequired() { return accessibility_object_.isRequired(); } +bool WebAXObjectProxy::IsEditable() { + accessibility_object_.updateLayoutAndCheckValidity(); + return accessibility_object_.isEditable(); +} + bool WebAXObjectProxy::IsRichlyEditable() { accessibility_object_.updateLayoutAndCheckValidity(); return accessibility_object_.isRichlyEditable(); diff --git a/components/test_runner/web_ax_object_proxy.h b/components/test_runner/web_ax_object_proxy.h index 5b73df8..fc636a1 100644 --- a/components/test_runner/web_ax_object_proxy.h +++ b/components/test_runner/web_ax_object_proxy.h @@ -89,6 +89,7 @@ class WebAXObjectProxy : public gin::Wrappable<WebAXObjectProxy> { bool IsEnabled(); bool IsRequired(); + bool IsEditable(); bool IsRichlyEditable(); bool IsFocused(); bool IsFocusable(); diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc index 163ee4c..373ef0ed 100644 --- a/content/browser/accessibility/accessibility_win_browsertest.cc +++ b/content/browser/accessibility/accessibility_win_browsertest.cc @@ -871,7 +871,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, SupportsISimpleDOM) { LoadInitialAccessibilityTreeFromHtml( - "<body><input type='checkbox' /></body>"); + "<body><input type='checkbox'></body>"); // Get the IAccessible object for the document. base::win::ScopedComPtr<IAccessible> document_accessible( diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc index 93d8413..150d0f4 100644 --- a/content/browser/accessibility/browser_accessibility.cc +++ b/content/browser/accessibility/browser_accessibility.cc @@ -641,18 +641,7 @@ bool BrowserAccessibility::IsCellOrTableHeaderRole() const { } bool BrowserAccessibility::IsEditableText() const { - // These roles don't have readonly set, but they're not editable text. - if (GetRole() == ui::AX_ROLE_SCROLL_AREA || - GetRole() == ui::AX_ROLE_COLUMN || - GetRole() == ui::AX_ROLE_TABLE_HEADER_CONTAINER) { - return false; - } - - // Note: WebAXStateReadonly being false means it's either a text control, - // or contenteditable. We also check for the text field role to cover - // elements that have role=textbox set on it. - return (!HasState(ui::AX_STATE_READ_ONLY) || - GetRole() == ui::AX_ROLE_TEXT_FIELD); + return HasState(ui::AX_STATE_EDITABLE); } bool BrowserAccessibility::IsWebAreaForPresentationalIframe() const { diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm index 7afcb30..f59dde4 100644 --- a/content/browser/accessibility/browser_accessibility_cocoa.mm +++ b/content/browser/accessibility/browser_accessibility_cocoa.mm @@ -1562,8 +1562,7 @@ bool InitializeAccessibilityTreeSearch( NSAccessibilityCellForColumnAndRowParameterizedAttribute, nil]]; } - if ([[self role] isEqualToString:NSAccessibilityTextFieldRole] || - [[self role] isEqualToString:NSAccessibilityTextAreaRole]) { + if (browserAccessibility_->IsEditableText()) { [ret addObjectsFromArray:[NSArray arrayWithObjects: NSAccessibilityLineForIndexParameterizedAttribute, NSAccessibilityRangeForLineParameterizedAttribute, @@ -1699,15 +1698,6 @@ bool InitializeAccessibilityTreeSearch( @"AXLoaded", @"AXLoadingProgress", nil]]; - } else if ([role isEqualToString:NSAccessibilityTextFieldRole] || - [role isEqualToString:NSAccessibilityTextAreaRole]) { - [ret addObjectsFromArray:[NSArray arrayWithObjects: - NSAccessibilityInsertionPointLineNumberAttribute, - NSAccessibilityNumberOfCharactersAttribute, - NSAccessibilitySelectedTextAttribute, - NSAccessibilitySelectedTextRangeAttribute, - NSAccessibilityVisibleCharacterRangeAttribute, - nil]]; } else if ([role isEqualToString:NSAccessibilityTabGroupRole]) { [ret addObject:NSAccessibilityTabsAttribute]; } else if ([role isEqualToString:NSAccessibilityProgressIndicatorRole] || @@ -1752,6 +1742,17 @@ bool InitializeAccessibilityTreeSearch( nil]]; } + // Caret navigation and text selection attributes. + if (browserAccessibility_->IsEditableText()) { + [ret addObjectsFromArray:[NSArray arrayWithObjects: + NSAccessibilityInsertionPointLineNumberAttribute, + NSAccessibilityNumberOfCharactersAttribute, + NSAccessibilitySelectedTextAttribute, + NSAccessibilitySelectedTextRangeAttribute, + NSAccessibilityVisibleCharacterRangeAttribute, + nil]]; + } + // Add the url attribute only if it has a valid url. if ([self url] != nil) { [ret addObjectsFromArray:[NSArray arrayWithObjects: diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc index 76d15c7..74e7f11 100644 --- a/content/browser/accessibility/browser_accessibility_win.cc +++ b/content/browser/accessibility/browser_accessibility_win.cc @@ -2648,10 +2648,10 @@ STDMETHODIMP BrowserAccessibilityWin::get_nodeInfo( *num_children = PlatformChildCount(); *unique_id = unique_id_win_; - if (ia_role() == ROLE_SYSTEM_DOCUMENT) { + if (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA || + GetRole() == ui::AX_ROLE_WEB_AREA) { *node_type = NODETYPE_DOCUMENT; - } else if (ia_role() == ROLE_SYSTEM_TEXT && - ((ia2_state() & IA2_STATE_EDITABLE) == 0)) { + } else if (IsTextOnlyObject()) { *node_type = NODETYPE_TEXT; } else { *node_type = NODETYPE_ELEMENT; @@ -3753,7 +3753,8 @@ void BrowserAccessibilityWin::GetSelectionOffsets( int* selection_start, int* selection_end) const { DCHECK(selection_start && selection_end); - if (GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, selection_start) && + if (IsEditableText() && !HasState(ui::AX_STATE_RICHLY_EDITABLE) && + GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, selection_start) && GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, selection_end)) { return; } @@ -3767,8 +3768,11 @@ void BrowserAccessibilityWin::GetSelectionOffsets( std::swap(*selection_start, *selection_end); // IA2 Spec says that the end of the selection should be after the last - // embedded object character that is part of the selection. - ++(*selection_end); + // embedded object character that is part of the selection, if there is one. + if (hyperlink_offset_to_index().find(*selection_end) != + hyperlink_offset_to_index().end()) { + ++(*selection_end); + } } base::string16 BrowserAccessibilityWin::GetNameRecursive() const { @@ -4012,10 +4016,7 @@ void BrowserAccessibilityWin::InitRoleAndState() { ia_state |= STATE_SYSTEM_HOTTRACKED; } - // WebKit marks everything as readonly unless it's editable text, so if it's - // not readonly, mark it as editable now. The final computation of the - // READONLY state for MSAA is below, after the switch. - if (!HasState(ui::AX_STATE_READ_ONLY)) + if (IsEditableText()) ia2_state |= IA2_STATE_EDITABLE; if (GetBoolAttribute(ui::AX_ATTR_BUTTON_MIXED)) @@ -4427,7 +4428,6 @@ void BrowserAccessibilityWin::InitRoleAndState() { ia2_state |= IA2_STATE_MULTI_LINE; else ia2_state |= IA2_STATE_SINGLE_LINE; - ia2_state |= IA2_STATE_EDITABLE; ia2_state |= IA2_STATE_SELECTABLE_TEXT; break; case ui::AX_ROLE_TIME: diff --git a/content/browser/accessibility/browser_accessibility_win_unittest.cc b/content/browser/accessibility/browser_accessibility_win_unittest.cc index e37a0d8d..898e5dc 100644 --- a/content/browser/accessibility/browser_accessibility_win_unittest.cc +++ b/content/browser/accessibility/browser_accessibility_win_unittest.cc @@ -823,7 +823,8 @@ TEST_F(BrowserAccessibilityTest, TestCaretAndSelectionInSimpleFields) { ui::AXNodeData combo_box; combo_box.id = 2; combo_box.role = ui::AX_ROLE_COMBO_BOX; - combo_box.state = (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_FOCUSED); + combo_box.state = (1 << ui::AX_STATE_EDITABLE) | + (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_FOCUSED); combo_box.SetValue("Test1"); // Place the caret between 't' and 'e'. combo_box.AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, 1); @@ -832,7 +833,8 @@ TEST_F(BrowserAccessibilityTest, TestCaretAndSelectionInSimpleFields) { ui::AXNodeData text_field; text_field.id = 3; text_field.role = ui::AX_ROLE_TEXT_FIELD; - text_field.state = 1 << ui::AX_STATE_FOCUSABLE; + text_field.state = (1 << ui::AX_STATE_EDITABLE) | + (1 << ui::AX_STATE_FOCUSABLE); text_field.SetValue("Test2"); // Select the letter 'e'. text_field.AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, 1); @@ -925,23 +927,27 @@ TEST_F(BrowserAccessibilityTest, TestCaretInContentEditables) { ui::AXNodeData div_editable; div_editable.id = 2; div_editable.role = ui::AX_ROLE_DIV; - div_editable.state = (1 << ui::AX_STATE_FOCUSABLE); + div_editable.state = (1 << ui::AX_STATE_EDITABLE) | + (1 << ui::AX_STATE_FOCUSABLE); ui::AXNodeData text; text.id = 3; text.role = ui::AX_ROLE_STATIC_TEXT; + text.state = (1 << ui::AX_STATE_EDITABLE); text.SetName("Click "); ui::AXNodeData link; link.id = 4; link.role = ui::AX_ROLE_LINK; - link.state = (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_LINKED); + link.state = (1 << ui::AX_STATE_EDITABLE) | + (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_LINKED); link.SetName("here"); ui::AXNodeData link_text; link_text.id = 5; link_text.role = ui::AX_ROLE_STATIC_TEXT; - link_text.state = (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_LINKED); + link_text.state = (1 << ui::AX_STATE_EDITABLE) | + (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_LINKED); link_text.SetName("here"); // Place the caret between 'h' and 'e'. diff --git a/content/renderer/accessibility/blink_ax_enum_conversion.cc b/content/renderer/accessibility/blink_ax_enum_conversion.cc index a48994a..e5e7e0b 100644 --- a/content/renderer/accessibility/blink_ax_enum_conversion.cc +++ b/content/renderer/accessibility/blink_ax_enum_conversion.cc @@ -67,15 +67,21 @@ uint32 AXStateFromBlink(const blink::WebAXObject& o) { if (o.canSetSelectedAttribute()) state |= (1 << ui::AX_STATE_SELECTABLE); + if (o.isEditable()) + state |= (1 << ui::AX_STATE_EDITABLE); + + if (o.isEnabled()) + state |= (1 << ui::AX_STATE_ENABLED); + if (o.isSelected()) state |= (1 << ui::AX_STATE_SELECTED); + if (o.isRichlyEditable()) + state |= (1 << ui::AX_STATE_RICHLY_EDITABLE); + if (o.isVisited()) state |= (1 << ui::AX_STATE_VISITED); - if (o.isEnabled()) - state |= (1 << ui::AX_STATE_ENABLED); - if (o.orientation() == blink::WebAXOrientationVertical) state |= (1 << ui::AX_STATE_VERTICAL); else if (o.orientation() == blink::WebAXOrientationHorizontal) diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc index 7254ca2..d765d8e 100644 --- a/content/renderer/accessibility/blink_ax_tree_source.cc +++ b/content/renderer/accessibility/blink_ax_tree_source.cc @@ -392,7 +392,7 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src, dst->html_attributes.push_back(std::make_pair(name, value)); } - if (!src.isReadOnly() || dst->role == ui::AX_ROLE_TEXT_FIELD) { + if (src.isEditable()) { dst->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, src.selectionStart()); dst->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END, src.selectionEnd()); diff --git a/content/test/data/accessibility/aria/aria-searchbox-expected-win.txt b/content/test/data/accessibility/aria/aria-searchbox-expected-win.txt index 3d7831d..f35530d 100644 --- a/content/test/data/accessibility/aria/aria-searchbox-expected-win.txt +++ b/content/test/data/accessibility/aria/aria-searchbox-expected-win.txt @@ -1,3 +1,3 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE n_selections=0 -++ROLE_SYSTEM_TEXT FOCUSABLE xml-roles:searchbox n_selections=0 +++ROLE_SYSTEM_TEXT FOCUSABLE xml-roles:searchbox caret_offset=0 n_selections=0 ++++ROLE_SYSTEM_STATICTEXT name='ARIA role searchbox.' n_selections=0 diff --git a/content/test/data/accessibility/aria/aria-searchbox-with-selection-expected-win.txt b/content/test/data/accessibility/aria/aria-searchbox-with-selection-expected-win.txt index a6d1ac6..bf62da6 100644 --- a/content/test/data/accessibility/aria/aria-searchbox-with-selection-expected-win.txt +++ b/content/test/data/accessibility/aria/aria-searchbox-with-selection-expected-win.txt @@ -1,3 +1,3 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE caret_offset=0 n_selections=1 selection_start=0 selection_end=1 -++ROLE_SYSTEM_TEXT FOCUSABLE xml-roles:searchbox caret_offset=0 n_selections=1 selection_start=0 selection_end=21 -++++ROLE_SYSTEM_STATICTEXT name='ARIA role searchbox.' caret_offset=0 n_selections=1 selection_start=0 selection_end=21 +++ROLE_SYSTEM_TEXT FOCUSABLE xml-roles:searchbox caret_offset=0 n_selections=1 selection_start=0 selection_end=20 +++++ROLE_SYSTEM_STATICTEXT name='ARIA role searchbox.' caret_offset=0 n_selections=1 selection_start=0 selection_end=20 diff --git a/content/test/data/accessibility/html/contenteditable-descendants-expected-win.txt b/content/test/data/accessibility/html/contenteditable-descendants-expected-win.txt index f3b9d23..b83a1dd 100644 --- a/content/test/data/accessibility/html/contenteditable-descendants-expected-win.txt +++ b/content/test/data/accessibility/html/contenteditable-descendants-expected-win.txt @@ -13,8 +13,8 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0><obj1><obj2>' ++++++ROLE_SYSTEM_ROW IA2_STATE_EDITABLE ia2_hypertext='<obj0>' ++++++++ROLE_SYSTEM_CELL IA2_STATE_EDITABLE ia2_hypertext='Always expose editable tables as tables.' ++++++++++ROLE_SYSTEM_STATICTEXT name='Always expose editable tables as tables.' IA2_STATE_EDITABLE ia2_hypertext='Always expose editable tables as tables.' -++++++ROLE_SYSTEM_COLUMN IA2_STATE_EDITABLE -++++++IA2_ROLE_SECTION IA2_STATE_EDITABLE +++++++ROLE_SYSTEM_COLUMN +++++++IA2_ROLE_SECTION ++++ROLE_SYSTEM_LIST IA2_STATE_EDITABLE ia2_hypertext='<obj0>' ++++++ROLE_SYSTEM_LISTITEM name='Editable list item.' IA2_STATE_EDITABLE ia2_hypertext='<obj0>Editable list item.' ++++++++ROLE_SYSTEM_STATICTEXT name='1' ia2_hypertext='1' diff --git a/ui/accessibility/ax_enums.idl b/ui/accessibility/ax_enums.idl index af160e4..17608a0 100644 --- a/ui/accessibility/ax_enums.idl +++ b/ui/accessibility/ax_enums.idl @@ -191,14 +191,14 @@ }; // TODO(dmazzoni): switch content/ to use AX_STATE_DISABLED instead of - // !AX_STATE_ENABLED, and AX_STATE_EDITABLE instead of !AX_STATE_READONLY. + // !AX_STATE_ENABLED. enum AXState { busy, checked, collapsed, default, disabled, // ui/views only - editable, // ui/views only + editable, enabled, // content only expanded, focusable, @@ -216,6 +216,7 @@ protected, read_only, required, + richly_editable, selectable, selected, vertical, @@ -273,7 +274,6 @@ anchor_offset, focus_object_id, focus_offset, - // Deprecated. text_sel_start, text_sel_end, diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc index 7dd0dd7..262e192 100644 --- a/ui/accessibility/ax_node_data.cc +++ b/ui/accessibility/ax_node_data.cc @@ -264,6 +264,8 @@ std::string AXNodeData::ToString() const { result += " CHECKED"; if (state & (1 << AX_STATE_COLLAPSED)) result += " COLLAPSED"; + if (state & (1 << AX_STATE_EDITABLE)) + result += " EDITABLE"; if (state & (1 << AX_STATE_EXPANDED)) result += " EXPANDED"; if (state & (1 << AX_STATE_FOCUSABLE)) @@ -292,6 +294,8 @@ std::string AXNodeData::ToString() const { result += " READONLY"; if (state & (1 << AX_STATE_REQUIRED)) result += " REQUIRED"; + if (state & (1 << AX_STATE_RICHLY_EDITABLE)) + result += " RICHLY_EDITABLE"; if (state & (1 << AX_STATE_SELECTABLE)) result += " SELECTABLE"; if (state & (1 << AX_STATE_SELECTED)) |