Chromium Code Reviews| Index: content/browser/accessibility/browser_accessibility_win.cc |
| diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc |
| index 285f99d9c9f9031f0a3aaea0224a02807ab67cc8..9c7d955f0f09c8319857d1467abe1648eb61867f 100644 |
| --- a/content/browser/accessibility/browser_accessibility_win.cc |
| +++ b/content/browser/accessibility/browser_accessibility_win.cc |
| @@ -4,6 +4,7 @@ |
| #include "content/browser/accessibility/browser_accessibility_win.h" |
| +#include <algorithm> |
| #include <UIAutomationClient.h> |
| #include <UIAutomationCoreApi.h> |
| @@ -2001,19 +2002,18 @@ STDMETHODIMP BrowserAccessibilityWin::get_caretOffset(LONG* offset) { |
| if (!offset) |
| return E_INVALIDARG; |
| - // IA2 spec says that caret offset should be -1 if the object is not focused. |
| - if (manager()->GetFocus(this) != this) { |
| + // IA2 spec says that caret offset should be -1 if the caret is not active |
| + // on this object. |
| + if (!manager()->GetFocus(this)) { |
| *offset = -1; |
| return S_FALSE; |
| } |
| + |
| + int selection_start = GetSelectionStart(); |
|
dmazzoni
2015/06/22 19:23:21
nit: indentation
|
| - *offset = 0; |
| - if (IsEditableText()) { |
| - int sel_start = 0; |
| - if (GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, |
| - &sel_start)) |
| - *offset = sel_start; |
| - } |
| + *offset = selection_start; |
| + if (selection_start < 0) |
| + return S_FALSE; |
| return S_OK; |
| } |
| @@ -2063,15 +2063,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_nSelections(LONG* n_selections) { |
| return E_INVALIDARG; |
| *n_selections = 0; |
| - if (IsEditableText()) { |
| - int sel_start = 0; |
| - int sel_end = 0; |
| - if (GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, |
| - &sel_start) && |
| - GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &sel_end) && |
| - sel_start != sel_end) |
| - *n_selections = 1; |
| - } |
| + int selection_start = GetSelectionStart(); |
| + int selection_end = GetSelectionEnd(); |
| + if (selection_start >= 0 && selection_end >= 0 && |
| + selection_start != selection_end) |
| + *n_selections = 1; |
| return S_OK; |
| } |
| @@ -2091,15 +2087,11 @@ STDMETHODIMP BrowserAccessibilityWin::get_selection(LONG selection_index, |
| *start_offset = 0; |
| *end_offset = 0; |
| - if (IsEditableText()) { |
| - int sel_start = 0; |
| - int sel_end = 0; |
| - if (GetIntAttribute( |
| - ui::AX_ATTR_TEXT_SEL_START, &sel_start) && |
| - GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &sel_end)) { |
| - *start_offset = sel_start; |
| - *end_offset = sel_end; |
| - } |
| + int selection_start = GetSelectionStart(); |
| + int selection_end = GetSelectionEnd(); |
| + if (selection_start >= 0 && selection_end >= 0) |
| + *start_offset = sel_start; |
| + *end_offset = sel_end; |
| } |
| return S_OK; |
| @@ -3650,6 +3642,114 @@ void BrowserAccessibilityWin::IntAttributeToIA2( |
| } |
| } |
| +int32 BrowserAccessibilityWin::GetHyperlinkIndexFromChild( |
| + const BrowserAccessibilityWin& child) const { |
| + auto& iterator = std::find( |
| + hyperlinks().begin(), hyperlinks().end(), child.GetId()); |
| + if (iterator == hyperlinks().end()) |
| + return -1; |
| + |
| + return static_cast<int32>(iterator - hyperlinks().begin()); |
| +} |
| + |
| +int32 BrowserAccessibilityWin::GetHypertextOffsetFromHyperlinkIndex( |
| + int32 hyperlink_index) const { |
| + auto& offsets_map = hyperlink_offset_to_index(); |
| + for (size_t i = 0; i < hyperlink_offset_to_index().size(); ++i) |
| + if (offsets_map[i].second == hyperlink_index) |
| + return offsets_map[i].first; |
| + |
| + return -1; |
| +} |
| + |
| +int32 BrowserAccessibilityWin::GetSelectionStart() const { |
| + int32 selection_start; |
| + if (!GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, &selection_start)) |
|
dmazzoni
2015/06/22 19:23:21
Did you mean this to be negated?
|
| + return selection_start; |
| + |
| + BrowserAccessibility* root = manager()->GetRoot(); |
| + int32 focus_id; |
| + if (!root || !GetIntAttribute(ui::AX_ATTR_OBJ_SEL_START, &focus_id)) |
|
dmazzoni
2015/06/22 19:23:21
Did you mean to call GetIntAttribute on root?
|
| + return -1; |
| + |
| + BrowserAccessibilityWin* focus_object = manager()->GetFromID( |
| + focus_id)->ToBrowserAccessibilityWin(); |
| + if (!focus_object) |
| + return -1; |
| + |
| + if (focus_object == this) { |
| + int focus_offset; |
| + if (!GetIntAttribute(ui::AX_ATTR_SEL_TEXT_START, &focus_offset)) |
| + return -1; |
| + |
| + return focus_offset; |
| + } |
| + |
| + auto focus_parent = focus_object->GetParent(); |
|
dmazzoni
2015/06/22 19:23:21
Stick this part of the code in a helper function t
|
| + while (parent_object && parent_object != this) { |
| + focus_object = parent_object; |
| + parent_object = focus_object->GetParent(); |
| + } |
| + if (!parent_object) |
| + return -1; |
| + |
| + int32 hyperlink_index = parent_object->GetHyperlinkIndexFromChild( |
| + focus_object); |
| + if (hyperlink_index < 0) |
| + return -1; |
| + |
| + hypertext_offset = parent_object->GetHypertextOffsetFromHyperlinkIndex( |
| + hyperlink_index); |
| + if (hypertext_offset < 0) |
| + return -1; |
| + |
| + return hypertext_offset; |
| +} |
| + |
| +int32 BrowserAccessibilityWin::GetSelectionEnd() const { |
| + int selection_end; |
| + if (!GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &selection_end)) |
| + return selection_end; |
| + |
| + BrowserAccessibility* root = manager()->GetRoot(); |
| + int32 anchor_id; |
| + if (!root || !GetIntAttribute(ui::AX_ATTR_OBJ_SEL_END, &anchor_id)) |
| + return -1; |
| + |
| + BrowserAccessibilityWin* anchor_object = manager()->GetFromID( |
| + anchor_id)->ToBrowserAccessibilityWin(); |
| + if (!anchor_object) |
| + return -1; |
| + |
| + if (anchor_object == this) { |
| + int anchor_offset; |
| + if (!GetIntAttribute(ui::AX_ATTR_SEL_TEXT_END, &anchor_offset)) |
| + return -1; |
| + |
| + return anchor_offset; |
| + } |
| + |
| + auto anchor_parent = anchor_object->GetParent(); |
| + while (parent_object && parent_object != this) { |
| + anchor_object = parent_object; |
| + parent_object = anchor_object->GetParent(); |
| + } |
| + if (!parent_object) |
| + return -1; |
| + |
| + int32 hyperlink_index = parent_object->GetHyperlinkIndexFromChild( |
| + anchor_object); |
| + if (hyperlink_index < 0) |
| + return -1; |
| + |
| + int32 hypertext_offset = parent_object->GetHypertextOffsetFromHyperlinkIndex( |
| + hyperlink_index); |
| + if (hypertext_offset < 0) |
| + return -1; |
| + |
| + return hypertext_offset; |
| +} |
| + |
| base::string16 BrowserAccessibilityWin::GetNameRecursive() const { |
| if (!name().empty()) { |
| return name(); |