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 7f77ad28ac986eb41b4a5fc0886265c3121ad474..74e7f11e9007eb663a1439485e688d45cbe89219 100644 |
--- a/content/browser/accessibility/browser_accessibility_win.cc |
+++ b/content/browser/accessibility/browser_accessibility_win.cc |
@@ -205,11 +205,6 @@ |
HRESULT hr = CComObject<BrowserAccessibilityWin>::CreateInstance(&instance); |
DCHECK(SUCCEEDED(hr)); |
return instance->NewReference(); |
-} |
- |
-const BrowserAccessibilityWin* BrowserAccessibility::ToBrowserAccessibilityWin() |
- const { |
- return static_cast<const BrowserAccessibilityWin*>(this); |
} |
BrowserAccessibilityWin* BrowserAccessibility::ToBrowserAccessibilityWin() { |
@@ -2015,9 +2010,8 @@ |
int selection_start, selection_end; |
GetSelectionOffsets(&selection_start, &selection_end); |
- // The caret is always at the end of the selection, if a selection exists. |
- *offset = selection_end; |
- if (*offset < 0) |
+ *offset = selection_start; |
+ if (selection_start < 0) |
return S_FALSE; |
return S_OK; |
@@ -2071,9 +2065,8 @@ |
int selection_start, selection_end; |
GetSelectionOffsets(&selection_start, &selection_end); |
if (selection_start >= 0 && selection_end >= 0 && |
- selection_start != selection_end) { |
+ selection_start != selection_end) |
*n_selections = 1; |
- } |
return S_OK; |
} |
@@ -2096,13 +2089,6 @@ |
int selection_start, selection_end; |
GetSelectionOffsets(&selection_start, &selection_end); |
if (selection_start >= 0 && selection_end >= 0) { |
- // We should ignore the direction of the selection when exposing start and |
- // end offsets. According to the IA2 Spec the end offset is always increased |
- // by one past the end of the selection. This wouldn't make sense if |
- // end < start. |
- if (selection_end < selection_start) |
- std::swap(selection_start, selection_end); |
- |
*start_offset = selection_start; |
*end_offset = selection_end; |
} |
@@ -3662,9 +3648,6 @@ |
int32 BrowserAccessibilityWin::GetHyperlinkIndexFromChild( |
const BrowserAccessibilityWin& child) const { |
- if (hyperlinks().empty()) |
- return -1; |
- |
auto iterator = std::find( |
hyperlinks().begin(), hyperlinks().end(), child.GetId()); |
if (iterator == hyperlinks().end()) |
@@ -3675,7 +3658,8 @@ |
int32 BrowserAccessibilityWin::GetHypertextOffsetFromHyperlinkIndex( |
int32 hyperlink_index) const { |
- for (auto& offset_index : hyperlink_offset_to_index()) { |
+ auto& offsets_map = hyperlink_offset_to_index(); |
+ for (auto& offset_index : offsets_map) { |
if (offset_index.second == hyperlink_index) |
return offset_index.first; |
} |
@@ -3706,84 +3690,6 @@ |
return parent_object->GetHypertextOffsetFromChild(*current_object); |
} |
-int BrowserAccessibilityWin::GetHypertextOffsetFromEndpoint( |
- const BrowserAccessibilityWin& endpoint_object, |
- int endpoint_offset) const { |
- // There are three cases: |
- // 1. Either the selection endpoint is inside this object or is an ancestor of |
- // of this object. endpoint_offset should be returned. |
- // 2. The selection endpoint is a pure descendant of this object. The offset |
- // of the embedded object character corresponding to the subtree in which |
- // the endpoint is located should be returned. |
- // 3. The selection endpoint is in a completely different part of the tree. |
- // Either 0 or text_length should be returned depending on the direction that |
- // one needs to travel to find the endpoint. |
- |
- // Case 1. |
- // |
- // IsDescendantOf includes the case when endpoint_object == this. |
- if (IsDescendantOf(&endpoint_object) || |
- // Handle the case when the endpoint is a direct text-only child. |
- // The selection offset should still be valid on the parent. |
- (endpoint_object.IsTextOnlyObject() && |
- endpoint_object.GetParent() == this)) { |
- return endpoint_offset; |
- } |
- |
- const BrowserAccessibility* common_parent = this; |
- while (common_parent && !endpoint_object.IsDescendantOf(common_parent)) { |
- common_parent = common_parent->GetParent(); |
- } |
- if (!common_parent) |
- return -1; |
- |
- auto common_parent_win = common_parent->ToBrowserAccessibilityWin(); |
- // Text only objects must have a parent. |
- DCHECK(!IsTextOnlyObject() || GetParent()); |
- DCHECK(!endpoint_object.IsTextOnlyObject() || endpoint_object.GetParent()); |
- // Text only objects that are direct descendants should behave as if they |
- // are part of their parent when computing hyperlink offsets. |
- const BrowserAccessibilityWin* nearest_non_text_ancestor = |
- IsTextOnlyObject() ? GetParent()->ToBrowserAccessibilityWin() : this; |
- const BrowserAccessibilityWin& nearest_non_text_endpoint = |
- endpoint_object.IsTextOnlyObject() |
- ? *(endpoint_object.GetParent()->ToBrowserAccessibilityWin()) |
- : endpoint_object; |
- |
- // Case 2. |
- // |
- // We already checked in case 1 if our endpoint is inside this object. |
- // We can safely assume that it is a descendant or in a completely different |
- // part of the tree. |
- if (common_parent_win == nearest_non_text_ancestor) { |
- return nearest_non_text_ancestor->GetHypertextOffsetFromDescendant( |
- nearest_non_text_endpoint); |
- } |
- |
- // Case 3. |
- // |
- // We can safely assume that the endpoint is in another part of the tree or |
- // at common parent, and that this object is a descendant of common parent. |
- int current_offset = |
- static_cast<int>(common_parent_win->GetHypertextOffsetFromDescendant( |
- *nearest_non_text_ancestor)); |
- DCHECK_GE(current_offset, 0); |
- if (common_parent_win != &nearest_non_text_endpoint) { |
- endpoint_offset = |
- static_cast<int>(common_parent_win->GetHypertextOffsetFromDescendant( |
- nearest_non_text_endpoint)); |
- DCHECK_GE(endpoint_offset, 0); |
- } |
- |
- if (endpoint_offset < current_offset) |
- return 0; |
- if (endpoint_offset > current_offset) |
- return TextForIAccessibleText().length(); |
- |
- NOTREACHED(); |
- return -1; |
-} |
- |
int BrowserAccessibilityWin::GetSelectionAnchor() const { |
BrowserAccessibility* root = manager()->GetRoot(); |
int32 anchor_id; |
@@ -3795,11 +3701,23 @@ |
if (!anchor_object) |
return -1; |
- int anchor_offset; |
- if (!root->GetIntAttribute(ui::AX_ATTR_ANCHOR_OFFSET, &anchor_offset)) |
- return -1; |
- |
- return GetHypertextOffsetFromEndpoint(*anchor_object, anchor_offset); |
+ // Includes the case when anchor_object == this. |
+ if (IsDescendantOf(anchor_object) || |
+ // Text only objects that are direct descendants should behave as if they |
+ // are part of this object when computing hypertext. |
+ (anchor_object->GetParent() == this && |
+ anchor_object->IsTextOnlyObject())) { |
+ int anchor_offset; |
+ if (!root->GetIntAttribute(ui::AX_ATTR_ANCHOR_OFFSET, &anchor_offset)) |
+ return -1; |
+ |
+ return anchor_offset; |
+ } |
+ |
+ if (anchor_object->IsDescendantOf(this)) |
+ return GetHypertextOffsetFromDescendant(*anchor_object); |
+ |
+ return -1; |
} |
int BrowserAccessibilityWin::GetSelectionFocus() const { |
@@ -3813,11 +3731,22 @@ |
if (!focus_object) |
return -1; |
- int focus_offset; |
- if (!root->GetIntAttribute(ui::AX_ATTR_FOCUS_OFFSET, &focus_offset)) |
- return -1; |
- |
- return GetHypertextOffsetFromEndpoint(*focus_object, focus_offset); |
+ // Includes the case when focus_object == this. |
+ if (IsDescendantOf(focus_object) || |
+ // Text only objects that are direct descendants should behave as if they |
+ // are part of this object when computing hypertext. |
+ (focus_object->GetParent() == this && focus_object->IsTextOnlyObject())) { |
+ int focus_offset; |
+ if (!root->GetIntAttribute(ui::AX_ATTR_FOCUS_OFFSET, &focus_offset)) |
+ return -1; |
+ |
+ return focus_offset; |
+ } |
+ |
+ if (focus_object->IsDescendantOf(this)) |
+ return GetHypertextOffsetFromDescendant(*focus_object); |
+ |
+ return -1; |
} |
void BrowserAccessibilityWin::GetSelectionOffsets( |
@@ -3835,56 +3764,15 @@ |
if (*selection_start < 0 || *selection_end < 0) |
return; |
- // If the selection is collapsed or if it only spans one character, return the |
- // selection offsets only if the caret is active on this object or any of its |
- // children. |
- // The focus object indicates the caret position. |
- if (*selection_start == *selection_end) { |
- BrowserAccessibility* root = manager()->GetRoot(); |
- int32 focus_id; |
- if (!root || !root->GetIntAttribute(ui::AX_ATTR_FOCUS_OBJECT_ID, &focus_id)) |
- return; |
- |
- BrowserAccessibilityWin* focus_object = |
- manager()->GetFromID(focus_id)->ToBrowserAccessibilityWin(); |
- if (!focus_object) |
- return; |
- |
- if (!focus_object->IsDescendantOf(this) && |
- !(IsTextOnlyObject() && GetParent() == focus_object)) { |
- *selection_start = -1; |
- *selection_end = -1; |
- return; |
- } |
- } |
- |
- // The IA2 Spec says that if the largest of the two offsets falls on an |
- // embedded object character and if there is a selection in that embedded |
- // object, it should be incremented by one so that it points after the |
- // embedded object character. |
- // This is a signal to AT software that the embedded object is also part of |
- // the selection. |
- int* largest_offset = |
- (*selection_start <= *selection_end) ? selection_end : selection_start; |
- auto current_object = const_cast<BrowserAccessibilityWin*>(this); |
- LONG hyperlink_index; |
- HRESULT hr = |
- current_object->get_hyperlinkIndex(*largest_offset, &hyperlink_index); |
- if (hr != S_OK) |
- return; |
- |
- DCHECK_GE(hyperlink_index, 0); |
- base::win::ScopedComPtr<IAccessibleHyperlink> hyperlink; |
- hr = current_object->get_hyperlink(hyperlink_index, hyperlink.Receive()); |
- DCHECK(SUCCEEDED(hr)); |
- base::win::ScopedComPtr<IAccessibleText> hyperlink_text; |
- hr = hyperlink.QueryInterface(hyperlink_text.Receive()); |
- DCHECK(SUCCEEDED(hr)); |
- LONG n_selections = 0; |
- hr = hyperlink_text->get_nSelections(&n_selections); |
- DCHECK(SUCCEEDED(hr)); |
- if (n_selections > 0) |
- ++(*largest_offset); |
+ if (*selection_end < *selection_start) |
+ 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, if there is one. |
+ if (hyperlink_offset_to_index().find(*selection_end) != |
+ hyperlink_offset_to_index().end()) { |
+ ++(*selection_end); |
+ } |
} |
base::string16 BrowserAccessibilityWin::GetNameRecursive() const { |
@@ -3911,7 +3799,7 @@ |
return value; |
} |
-base::string16 BrowserAccessibilityWin::TextForIAccessibleText() const { |
+base::string16 BrowserAccessibilityWin::TextForIAccessibleText() { |
switch (GetRole()) { |
case ui::AX_ROLE_TEXT_FIELD: |
case ui::AX_ROLE_MENU_LIST_OPTION: |