summaryrefslogtreecommitdiff
path: root/chromium/ui/accessibility
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-03-08 10:28:10 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-03-20 13:40:30 +0000
commite733310db58160074f574c429d48f8308c0afe17 (patch)
treef8aef4b7e62a69928dbcf880620eece20f98c6df /chromium/ui/accessibility
parent2f583e4aec1ae3a86fa047829c96b310dc12ecdf (diff)
downloadqtwebengine-chromium-e733310db58160074f574c429d48f8308c0afe17.tar.gz
BASELINE: Update Chromium to 56.0.2924.122
Change-Id: I4e04de8f47e47e501c46ed934c76a431c6337ced Reviewed-by: Michael Brüning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/ui/accessibility')
-rw-r--r--chromium/ui/accessibility/BUILD.gn11
-rw-r--r--chromium/ui/accessibility/ax_action_data.cc59
-rw-r--r--chromium/ui/accessibility/ax_action_data.h60
-rw-r--r--chromium/ui/accessibility/ax_enums.idl61
-rw-r--r--chromium/ui/accessibility/ax_node.h4
-rw-r--r--chromium/ui/accessibility/ax_node_data.cc38
-rw-r--r--chromium/ui/accessibility/ax_node_data.h9
-rw-r--r--chromium/ui/accessibility/ax_node_position.cc79
-rw-r--r--chromium/ui/accessibility/ax_node_position.h40
-rw-r--r--chromium/ui/accessibility/ax_node_position_unittest.cc564
-rw-r--r--chromium/ui/accessibility/ax_position.h390
-rw-r--r--chromium/ui/accessibility/ax_tree_combiner.cc20
-rw-r--r--chromium/ui/accessibility/ax_tree_combiner.h5
-rw-r--r--chromium/ui/accessibility/ax_tree_combiner_unittest.cc51
-rw-r--r--chromium/ui/accessibility/ax_view_state.cc32
-rw-r--r--chromium/ui/accessibility/ax_view_state.h91
-rw-r--r--chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_bn.xtb2
-rw-r--r--chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_da.xtb2
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_delegate.h14
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_mac.mm41
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_win.cc11
-rw-r--r--chromium/ui/accessibility/platform/test_ax_node_wrapper.cc7
-rw-r--r--chromium/ui/accessibility/platform/test_ax_node_wrapper.h4
23 files changed, 1364 insertions, 231 deletions
diff --git a/chromium/ui/accessibility/BUILD.gn b/chromium/ui/accessibility/BUILD.gn
index f1c43b74475..e40911efb0e 100644
--- a/chromium/ui/accessibility/BUILD.gn
+++ b/chromium/ui/accessibility/BUILD.gn
@@ -5,19 +5,25 @@
import("//build/config/linux/pkg_config.gni")
import("//build/config/features.gni")
import("//build/config/ui.gni")
-import("//build/json_schema_api.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("//testing/test.gni")
+import("//tools/json_schema_compiler/json_schema_api.gni")
+
if (is_android) {
import("//build/config/android/rules.gni")
}
component("accessibility") {
sources = [
+ "ax_action_data.cc",
+ "ax_action_data.h",
"ax_node.cc",
"ax_node.h",
"ax_node_data.cc",
"ax_node_data.h",
+ "ax_node_position.cc",
+ "ax_node_position.h",
+ "ax_position.h",
"ax_relative_bounds.cc",
"ax_relative_bounds.h",
"ax_serializable_tree.cc",
@@ -34,8 +40,6 @@ component("accessibility") {
"ax_tree_serializer.h",
"ax_tree_source.h",
"ax_tree_update.h",
- "ax_view_state.cc",
- "ax_view_state.h",
"platform/ax_platform_node.cc",
"platform/ax_platform_node.h",
"platform/ax_platform_node_base.cc",
@@ -120,6 +124,7 @@ static_library("test_support") {
test("accessibility_unittests") {
sources = [
"ax_generated_tree_unittest.cc",
+ "ax_node_position_unittest.cc",
"ax_text_utils_unittest.cc",
"ax_tree_combiner_unittest.cc",
"ax_tree_serializer_unittest.cc",
diff --git a/chromium/ui/accessibility/ax_action_data.cc b/chromium/ui/accessibility/ax_action_data.cc
new file mode 100644
index 00000000000..8b9dbbef3c6
--- /dev/null
+++ b/chromium/ui/accessibility/ax_action_data.cc
@@ -0,0 +1,59 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/ax_action_data.h"
+
+#include <set>
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+
+using base::IntToString;
+
+namespace ui {
+
+AXActionData::AXActionData()
+ : action(AX_ACTION_NONE),
+ target_node_id(-1),
+ flags(0),
+ anchor_node_id(-1),
+ anchor_offset(-1),
+ focus_node_id(-1),
+ focus_offset(-1) {
+}
+
+AXActionData::AXActionData(const AXActionData& other) = default;
+
+AXActionData::~AXActionData() {
+}
+
+// Note that this includes an initial space character if nonempty, but
+// that works fine because this is normally printed by AXAction::ToString.
+std::string AXActionData::ToString() const {
+ std::string result = ui::ToString(action);
+
+ if (target_node_id != -1)
+ result += " target_node_id=" + IntToString(target_node_id);
+
+ if (flags & (1 << ui::AX_ACTION_FLAGS_REQUEST_IMAGES))
+ result += " flag_request_images";
+
+ if (flags & (1 << ui::AX_ACTION_FLAGS_REQUEST_INLINE_TEXT_BOXES))
+ result += " flag_request_inline_text_boxes";
+
+ if (anchor_node_id != -1) {
+ result += " anchor_node_id=" + IntToString(anchor_node_id);
+ result += " anchor_offset=" + IntToString(anchor_offset);
+ }
+ if (focus_node_id != -1) {
+ result += " focus_node_id=" + IntToString(focus_node_id);
+ result += " focus_offset=" + IntToString(focus_offset);
+ }
+
+ return result;
+}
+
+} // namespace ui
diff --git a/chromium/ui/accessibility/ax_action_data.h b/chromium/ui/accessibility/ax_action_data.h
new file mode 100644
index 00000000000..4c0af535749
--- /dev/null
+++ b/chromium/ui/accessibility/ax_action_data.h
@@ -0,0 +1,60 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ACCESSIBILITY_AX_ACTION_DATA_H_
+#define UI_ACCESSIBILITY_AX_ACTION_DATA_H_
+
+#include "base/strings/string16.h"
+#include "ui/accessibility/ax_enums.h"
+#include "ui/accessibility/ax_export.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace ui {
+
+// A compact representation of an accessibility action and the arguments
+// associated with that action.
+struct AX_EXPORT AXActionData {
+ AXActionData();
+ AXActionData(const AXActionData& other);
+ virtual ~AXActionData();
+
+ // Return a string representation of this data, for debugging.
+ virtual std::string ToString() const;
+
+ // This is a simple serializable struct. All member variables should be
+ // public and copyable.
+
+ // See the AXAction enums in ax_enums.idl for explanations of which
+ // parameters apply.
+
+ // The action to take.
+ AXAction action;
+
+ // The ID of the node that this action should be performed on.
+ int target_node_id;
+
+ // Use enums from AXActionFlags
+ int flags;
+
+ // For an action that creates a selection, the selection anchor and focus
+ // (see ax_tree_data.h for definitions).
+ int anchor_node_id;
+ int anchor_offset;
+
+ int focus_node_id;
+ int focus_offset;
+
+ // The target rect for the action.
+ gfx::Rect target_rect;
+
+ // The target point for the action.
+ gfx::Point target_point;
+
+ // The new value for a node, for the SET_VALUE action.
+ base::string16 value;
+};
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_AX_ACTION_DATA_H_
diff --git a/chromium/ui/accessibility/ax_enums.idl b/chromium/ui/accessibility/ax_enums.idl
index 89d38422786..e9e59fc99e0 100644
--- a/chromium/ui/accessibility/ax_enums.idl
+++ b/chromium/ui/accessibility/ax_enums.idl
@@ -7,7 +7,7 @@
// until the Chromium and Blink trees are merged.
[camel_case_enum_to_string=true] namespace ui {
- // For new entries to the following three enums, also add to
+ // For new entries to the following four enums, also add to
// chrome/common/extensions/api/automation.idl. This is enforced
// by a PRESUBMIT check.
//
@@ -210,6 +210,7 @@
expanded,
focusable,
haspopup,
+ // Grows horizontally, e.g. most toolbars and separators.
horizontal,
hovered,
invisible,
@@ -224,10 +225,61 @@
richly_editable,
selectable,
selected,
+ // Grows vertically, e.g. menu or combo box.
vertical,
visited
};
+ // An action to be taken on an accessibility node.
+ enum AXAction {
+ // Decrement a slider or range control by one step value.
+ decrement,
+
+ // Do the default action for an object, typically this means "click".
+ do_default,
+
+ // Given a point, find the object it corresponds to and fire a
+ // HOVER event on it in response.
+ hit_test,
+
+ // Increment a slider or range control by one step value.
+ increment,
+
+ // Delete any selected text in the control's text value and
+ // insert |AXActionData::value| in its place, like when typing or pasting.
+ replace_selected_text,
+
+ // Scroll any scrollable containers to make the target object visible
+ // on the screen. Optionally pass a subfocus rect in
+ // AXActionData.target_rect.
+ scroll_to_make_visible,
+
+ // Scroll the given object to a specified point on the screen in
+ // global screen coordinates. Pass a point in AXActionData.target_point.
+ scroll_to_point,
+
+ set_accessibility_focus,
+ set_focus,
+ set_scroll_offset,
+ set_selection,
+
+ // Don't focus this node, but set it as the sequential focus navigation
+ // starting point, so that pressing Tab moves to the next element
+ // following this one, for example.
+ set_sequential_focus_navigation_starting_point,
+
+ // Replace the value of the control with AXActionData::value and
+ // reset the selection, if applicable.
+ set_value,
+
+ show_context_menu
+ };
+
+ enum AXActionFlags {
+ request_images,
+ request_inline_text_boxes
+ };
+
// A change to the accessibility tree.
enum AXMutation {
node_created,
@@ -391,6 +443,11 @@
flowto_ids,
labelledby_ids,
+ // For static text. Character indices where line breaks occur. Note that
+ // this attribute is only available on Chrome OS and will be deprecated
+ // soon.
+ line_breaks,
+
// For static text. These int lists must be the same size; they represent
// the start and end character offset of each marker. Examples of markers
// include spelling and grammar errors, and find-in-page matches.
@@ -414,7 +471,7 @@
// within the object's bounds, the second offset is the right coordinate
// of the second character, and so on.
character_offsets,
-
+
// Used for caching. Do not read directly. Use
// |AXNode::GetOrComputeLineStartOffsets|
// For all text fields and content editable roots: A list of the start
diff --git a/chromium/ui/accessibility/ax_node.h b/chromium/ui/accessibility/ax_node.h
index 12eb1b88db0..195d6f3cc5e 100644
--- a/chromium/ui/accessibility/ax_node.h
+++ b/chromium/ui/accessibility/ax_node.h
@@ -11,10 +11,6 @@
#include "ui/accessibility/ax_node_data.h"
-namespace gfx {
-class Rect;
-}
-
namespace ui {
// One node in an AXTree.
diff --git a/chromium/ui/accessibility/ax_node_data.cc b/chromium/ui/accessibility/ax_node_data.cc
index 06c55e923b2..316ac433c09 100644
--- a/chromium/ui/accessibility/ax_node_data.cc
+++ b/chromium/ui/accessibility/ax_node_data.cc
@@ -287,13 +287,48 @@ void AXNodeData::AddIntListAttribute(AXIntListAttribute attribute,
}
void AXNodeData::SetName(const std::string& name) {
+ for (size_t i = 0; i < string_attributes.size(); ++i) {
+ if (string_attributes[i].first == AX_ATTR_NAME) {
+ string_attributes[i].second = name;
+ return;
+ }
+ }
+
string_attributes.push_back(std::make_pair(AX_ATTR_NAME, name));
}
+void AXNodeData::SetName(const base::string16& name) {
+ SetName(base::UTF16ToUTF8(name));
+}
+
void AXNodeData::SetValue(const std::string& value) {
+ for (size_t i = 0; i < string_attributes.size(); ++i) {
+ if (string_attributes[i].first == AX_ATTR_VALUE) {
+ string_attributes[i].second = value;
+ return;
+ }
+ }
+
string_attributes.push_back(std::make_pair(AX_ATTR_VALUE, value));
}
+void AXNodeData::SetValue(const base::string16& value) {
+ SetValue(base::UTF16ToUTF8(value));
+}
+
+// static
+bool AXNodeData::IsFlagSet(uint32_t state, ui::AXState state_flag) {
+ return 0 != (state & (1 << state_flag));
+}
+
+void AXNodeData::AddStateFlag(ui::AXState state_flag) {
+ state |= (1 << state_flag);
+}
+
+bool AXNodeData::HasStateFlag(ui::AXState state_flag) const {
+ return IsFlagSet(state, state_flag);
+}
+
std::string AXNodeData::ToString() const {
std::string result;
@@ -692,6 +727,9 @@ std::string AXNodeData::ToString() const {
case AX_ATTR_LABELLEDBY_IDS:
result += " labelledby_ids=" + IntVectorToString(values);
break;
+ case AX_ATTR_LINE_BREAKS:
+ result += " line_breaks=" + IntVectorToString(values);
+ break;
case AX_ATTR_MARKER_TYPES: {
std::string types_str;
for (size_t i = 0; i < values.size(); ++i) {
diff --git a/chromium/ui/accessibility/ax_node_data.h b/chromium/ui/accessibility/ax_node_data.h
index 3fbaaa5bd41..acd5ec54c47 100644
--- a/chromium/ui/accessibility/ax_node_data.h
+++ b/chromium/ui/accessibility/ax_node_data.h
@@ -93,8 +93,17 @@ struct AX_EXPORT AXNodeData {
// Convenience functions, mainly for writing unit tests.
// Equivalent to AddStringAttribute(ATTR_NAME, name).
void SetName(const std::string& name);
+ void SetName(const base::string16& name);
// Equivalent to AddStringAttribute(ATTR_VALUE, value).
void SetValue(const std::string& value);
+ void SetValue(const base::string16& value);
+
+ // Helper to check whether |state_flag| is set in the given |state|.
+ static bool IsFlagSet(uint32_t state, ui::AXState state_flag);
+
+ // Set or check bits in |state_|.
+ void AddStateFlag(ui::AXState state_flag);
+ bool HasStateFlag(ui::AXState state_flag) const;
// Return a string representation of this data, for debugging.
virtual std::string ToString() const;
diff --git a/chromium/ui/accessibility/ax_node_position.cc b/chromium/ui/accessibility/ax_node_position.cc
new file mode 100644
index 00000000000..4b91f29b3a1
--- /dev/null
+++ b/chromium/ui/accessibility/ax_node_position.cc
@@ -0,0 +1,79 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/ax_node_position.h"
+
+#include "base/strings/string16.h"
+#include "ui/accessibility/ax_enums.h"
+
+namespace ui {
+
+AXTree* AXNodePosition::tree_ = nullptr;
+
+AXNodePosition::AXNodePosition() {}
+
+AXNodePosition::~AXNodePosition() {}
+
+void AXNodePosition::AnchorChild(int child_index,
+ int* tree_id,
+ int32_t* child_id) const {
+ DCHECK(tree_id);
+ DCHECK(child_id);
+
+ if (!GetAnchor() || child_index < 0 || child_index >= AnchorChildCount()) {
+ *tree_id = AXPosition::INVALID_TREE_ID;
+ *child_id = AXPosition::INVALID_ANCHOR_ID;
+ return;
+ }
+
+ AXNode* child = GetAnchor()->ChildAtIndex(child_index);
+ DCHECK(child);
+ *tree_id = this->tree_id();
+ *child_id = child->id();
+}
+
+int AXNodePosition::AnchorChildCount() const {
+ return GetAnchor() ? GetAnchor()->child_count() : 0;
+}
+
+int AXNodePosition::AnchorIndexInParent() const {
+ return GetAnchor() ? GetAnchor()->index_in_parent()
+ : AXPosition::INVALID_INDEX;
+}
+
+void AXNodePosition::AnchorParent(int* tree_id, int32_t* parent_id) const {
+ DCHECK(tree_id);
+ DCHECK(parent_id);
+
+ if (!GetAnchor() || !GetAnchor()->parent()) {
+ *tree_id = AXPosition::INVALID_TREE_ID;
+ *parent_id = AXPosition::INVALID_ANCHOR_ID;
+ return;
+ }
+
+ AXNode* parent = GetAnchor()->parent();
+ *tree_id = this->tree_id();
+ *parent_id = parent->id();
+}
+
+AXNode* AXNodePosition::GetNodeInTree(int tree_id, int32_t node_id) const {
+ if (!tree_ || node_id == AXPosition::INVALID_ANCHOR_ID)
+ return nullptr;
+ return AXNodePosition::tree_->GetFromId(node_id);
+}
+
+int AXNodePosition::MaxTextOffset() const {
+ if (IsTextPosition()) {
+ DCHECK(GetAnchor());
+ base::string16 name =
+ GetAnchor()->data().GetString16Attribute(AX_ATTR_NAME);
+ return static_cast<int>(name.length());
+ } else if (IsTreePosition()) {
+ return 0;
+ }
+
+ return AXPosition::INVALID_INDEX;
+}
+
+} // namespace ui
diff --git a/chromium/ui/accessibility/ax_node_position.h b/chromium/ui/accessibility/ax_node_position.h
new file mode 100644
index 00000000000..40b1a584499
--- /dev/null
+++ b/chromium/ui/accessibility/ax_node_position.h
@@ -0,0 +1,40 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ACCESSIBILITY_AX_NODE_POSITION_H_
+#define UI_ACCESSIBILITY_AX_NODE_POSITION_H_
+
+#include <stdint.h>
+
+#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_node.h"
+#include "ui/accessibility/ax_position.h"
+#include "ui/accessibility/ax_tree.h"
+
+namespace ui {
+
+class AX_EXPORT AXNodePosition : public AXPosition<AXNodePosition, AXNode> {
+ public:
+ AXNodePosition();
+ ~AXNodePosition() override;
+
+ static void SetTreeForTesting(AXTree* tree) { tree_ = tree; }
+
+ protected:
+ void AnchorChild(int child_index,
+ int* tree_id,
+ int32_t* child_id) const override;
+ int AnchorChildCount() const override;
+ int AnchorIndexInParent() const override;
+ void AnchorParent(int* tree_id, int32_t* parent_id) const override;
+ AXNode* GetNodeInTree(int tree_id, int32_t node_id) const override;
+ int MaxTextOffset() const override;
+
+ private:
+ static AXTree* tree_;
+};
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_AX_NODE_POSITION_H_
diff --git a/chromium/ui/accessibility/ax_node_position_unittest.cc b/chromium/ui/accessibility/ax_node_position_unittest.cc
new file mode 100644
index 00000000000..37c8ffabc74
--- /dev/null
+++ b/chromium/ui/accessibility/ax_node_position_unittest.cc
@@ -0,0 +1,564 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/ax_enums.h"
+#include "ui/accessibility/ax_node.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/accessibility/ax_node_position.h"
+#include "ui/accessibility/ax_serializable_tree.h"
+#include "ui/accessibility/ax_tree_serializer.h"
+#include "ui/accessibility/ax_tree_update.h"
+
+namespace ui {
+
+using TestPositionType = AXPosition<AXNodePosition, AXNode>;
+
+namespace {
+
+class AXPositionTest : public testing::Test {
+ public:
+ const char* TEXT_VALUE = "Line 1\nLine 2";
+
+ AXPositionTest();
+ ~AXPositionTest() override;
+
+ protected:
+ void SetUp() override;
+ void TearDown() override;
+
+ AXNodeData root_;
+ AXNodeData button_;
+ AXNodeData check_box_;
+ AXNodeData text_field_;
+ AXNodeData static_text1_;
+ AXNodeData line_break_;
+ AXNodeData static_text2_;
+ AXNodeData inline_box1_;
+ AXNodeData inline_box2_;
+
+ AXTree tree_;
+ DISALLOW_COPY_AND_ASSIGN(AXPositionTest);
+};
+
+AXPositionTest::AXPositionTest() {}
+
+AXPositionTest::~AXPositionTest() {}
+
+void AXPositionTest::SetUp() {
+ std::vector<int32_t> line_start_offsets{0, 6};
+ std::vector<int32_t> word_starts{0, 5};
+ std::vector<int32_t> word_ends{3, 6};
+
+ root_.id = 1;
+ button_.id = 2;
+ check_box_.id = 3;
+ text_field_.id = 4;
+ static_text1_.id = 5;
+ inline_box1_.id = 6;
+ line_break_.id = 7;
+ static_text2_.id = 8;
+ inline_box2_.id = 9;
+
+ root_.role = AX_ROLE_DIALOG;
+ root_.state = 1 << AX_STATE_FOCUSABLE;
+ root_.location = gfx::RectF(0, 0, 800, 600);
+
+ button_.role = AX_ROLE_BUTTON;
+ button_.state = 1 << AX_STATE_HASPOPUP;
+ button_.SetName("Sample button_");
+ button_.location = gfx::RectF(20, 20, 200, 30);
+ root_.child_ids.push_back(button_.id);
+
+ check_box_.role = AX_ROLE_CHECK_BOX;
+ check_box_.state = 1 << AX_STATE_CHECKED;
+ check_box_.SetName("Sample check box");
+ check_box_.location = gfx::RectF(20, 50, 200, 30);
+ root_.child_ids.push_back(check_box_.id);
+
+ text_field_.role = AX_ROLE_TEXT_FIELD;
+ text_field_.state = 1 << AX_STATE_EDITABLE;
+ text_field_.SetValue(TEXT_VALUE);
+ text_field_.AddIntListAttribute(AX_ATTR_CACHED_LINE_STARTS,
+ line_start_offsets);
+ text_field_.child_ids.push_back(static_text1_.id);
+ text_field_.child_ids.push_back(line_break_.id);
+ text_field_.child_ids.push_back(static_text2_.id);
+ root_.child_ids.push_back(text_field_.id);
+
+ static_text1_.role = AX_ROLE_STATIC_TEXT;
+ static_text1_.state = 1 << AX_STATE_EDITABLE;
+ static_text1_.SetName("Line 1");
+ static_text1_.child_ids.push_back(inline_box1_.id);
+
+ inline_box1_.role = AX_ROLE_INLINE_TEXT_BOX;
+ inline_box1_.state = 1 << AX_STATE_EDITABLE;
+ inline_box1_.SetName("Line 1");
+ inline_box1_.AddIntListAttribute(AX_ATTR_WORD_STARTS, word_starts);
+ inline_box1_.AddIntListAttribute(AX_ATTR_WORD_ENDS, word_ends);
+
+ line_break_.role = AX_ROLE_LINE_BREAK;
+ line_break_.state = 1 << AX_STATE_EDITABLE;
+ line_break_.SetName("\n");
+
+ static_text2_.role = AX_ROLE_STATIC_TEXT;
+ static_text2_.state = 1 << AX_STATE_EDITABLE;
+ static_text2_.SetName("Line 2");
+ static_text2_.child_ids.push_back(inline_box2_.id);
+
+ inline_box2_.role = AX_ROLE_INLINE_TEXT_BOX;
+ inline_box2_.state = 1 << AX_STATE_EDITABLE;
+ inline_box2_.SetName("Line 2");
+ inline_box2_.AddIntListAttribute(AX_ATTR_WORD_STARTS, word_starts);
+ inline_box2_.AddIntListAttribute(AX_ATTR_WORD_ENDS, word_ends);
+
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.push_back(root_);
+ initial_state.nodes.push_back(button_);
+ initial_state.nodes.push_back(check_box_);
+ initial_state.nodes.push_back(text_field_);
+ initial_state.nodes.push_back(static_text1_);
+ initial_state.nodes.push_back(inline_box1_);
+ initial_state.nodes.push_back(line_break_);
+ initial_state.nodes.push_back(static_text2_);
+ initial_state.nodes.push_back(inline_box2_);
+ initial_state.has_tree_data = true;
+ initial_state.tree_data.tree_id = 0;
+ initial_state.tree_data.title = "Dialog title";
+ AXSerializableTree src_tree(initial_state);
+
+ std::unique_ptr<AXTreeSource<const AXNode*, AXNodeData, AXTreeData>>
+ tree_source(src_tree.CreateTreeSource());
+ AXTreeSerializer<const AXNode*, AXNodeData, AXTreeData> serializer(
+ tree_source.get());
+ AXTreeUpdate update;
+ serializer.SerializeChanges(src_tree.root(), &update);
+ ASSERT_TRUE(tree_.Unserialize(update));
+ AXNodePosition::SetTreeForTesting(&tree_);
+}
+
+void AXPositionTest::TearDown() {
+ AXNodePosition::SetTreeForTesting(nullptr);
+}
+
+} // namespace
+
+TEST_F(AXPositionTest, AtStartOfAnchorWithNullPosition) {
+ std::unique_ptr<TestPositionType> null_position(
+ AXNodePosition::CreateNullPosition());
+ ASSERT_NE(nullptr, null_position);
+ EXPECT_FALSE(null_position->AtStartOfAnchor());
+}
+
+TEST_F(AXPositionTest, AtStartOfAnchorWithTreePosition) {
+ std::unique_ptr<TestPositionType> tree_position(
+ AXNodePosition::CreateTreePosition(tree_.data().tree_id, root_.id,
+ 0 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ EXPECT_TRUE(tree_position->AtStartOfAnchor());
+
+ tree_position.reset(AXNodePosition::CreateTreePosition(
+ tree_.data().tree_id, root_.id, 1 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ EXPECT_FALSE(tree_position->AtStartOfAnchor());
+
+ tree_position.reset(AXNodePosition::CreateTreePosition(
+ tree_.data().tree_id, root_.id, 3 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ EXPECT_FALSE(tree_position->AtStartOfAnchor());
+}
+
+TEST_F(AXPositionTest, AtStartOfAnchorWithTextPosition) {
+ std::unique_ptr<TestPositionType> text_position(
+ AXNodePosition::CreateTextPosition(tree_.data().tree_id, inline_box1_.id,
+ 0 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ EXPECT_TRUE(text_position->AtStartOfAnchor());
+ text_position.reset(AXNodePosition::CreateTextPosition(
+ tree_.data().tree_id, inline_box1_.id, 1 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ EXPECT_FALSE(text_position->AtStartOfAnchor());
+
+ text_position.reset(AXNodePosition::CreateTextPosition(
+ tree_.data().tree_id, inline_box1_.id, 6 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ EXPECT_FALSE(text_position->AtStartOfAnchor());
+}
+
+TEST_F(AXPositionTest, AtEndOfAnchorWithNullPosition) {
+ std::unique_ptr<TestPositionType> null_position(
+ AXNodePosition::CreateNullPosition());
+ ASSERT_NE(nullptr, null_position);
+ EXPECT_FALSE(null_position->AtEndOfAnchor());
+}
+
+TEST_F(AXPositionTest, AtEndOfAnchorWithTreePosition) {
+ std::unique_ptr<TestPositionType> tree_position(
+ AXNodePosition::CreateTreePosition(tree_.data().tree_id, root_.id,
+ 3 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ EXPECT_TRUE(tree_position->AtEndOfAnchor());
+
+ tree_position.reset(AXNodePosition::CreateTreePosition(
+ tree_.data().tree_id, root_.id, 2 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ EXPECT_FALSE(tree_position->AtEndOfAnchor());
+
+ tree_position.reset(AXNodePosition::CreateTreePosition(
+ tree_.data().tree_id, root_.id, 0 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ EXPECT_FALSE(tree_position->AtEndOfAnchor());
+}
+
+TEST_F(AXPositionTest, AtEndOfAnchorWithTextPosition) {
+ std::unique_ptr<TestPositionType> text_position(
+ AXNodePosition::CreateTextPosition(tree_.data().tree_id, inline_box1_.id,
+ 6 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ EXPECT_TRUE(text_position->AtEndOfAnchor());
+
+ text_position.reset(AXNodePosition::CreateTextPosition(
+ tree_.data().tree_id, inline_box1_.id, 5 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ EXPECT_FALSE(text_position->AtEndOfAnchor());
+
+ text_position.reset(AXNodePosition::CreateTextPosition(
+ tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ EXPECT_FALSE(text_position->AtEndOfAnchor());
+}
+
+TEST_F(AXPositionTest, CreatePositionAtStartOfAnchorWithNullPosition) {
+ std::unique_ptr<TestPositionType> null_position(
+ AXNodePosition::CreateNullPosition());
+ ASSERT_NE(nullptr, null_position);
+ std::unique_ptr<TestPositionType> test_position(
+ null_position->CreatePositionAtStartOfAnchor());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsNullPosition());
+}
+
+TEST_F(AXPositionTest, CreatePositionAtStartOfAnchorWithTreePosition) {
+ std::unique_ptr<TestPositionType> tree_position(
+ AXNodePosition::CreateTreePosition(tree_.data().tree_id, root_.id,
+ 0 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ std::unique_ptr<TestPositionType> test_position(
+ tree_position->CreatePositionAtStartOfAnchor());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTreePosition());
+ EXPECT_EQ(root_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->child_index());
+
+ tree_position.reset(AXNodePosition::CreateTreePosition(
+ tree_.data().tree_id, root_.id, 1 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ test_position.reset(tree_position->CreatePositionAtStartOfAnchor());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTreePosition());
+ EXPECT_EQ(root_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->child_index());
+}
+
+TEST_F(AXPositionTest, CreatePositionAtStartOfAnchorWithTextPosition) {
+ std::unique_ptr<TestPositionType> text_position(
+ AXNodePosition::CreateTextPosition(tree_.data().tree_id, inline_box1_.id,
+ 0 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ std::unique_ptr<TestPositionType> test_position(
+ text_position->CreatePositionAtStartOfAnchor());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->text_offset());
+
+ text_position.reset(AXNodePosition::CreateTextPosition(
+ tree_.data().tree_id, inline_box1_.id, 1 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ test_position.reset(text_position->CreatePositionAtStartOfAnchor());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->text_offset());
+}
+
+TEST_F(AXPositionTest, CreatePositionAtEndOfAnchorWithNullPosition) {
+ std::unique_ptr<TestPositionType> null_position(
+ AXNodePosition::CreateNullPosition());
+ ASSERT_NE(nullptr, null_position);
+ std::unique_ptr<TestPositionType> test_position(
+ null_position->CreatePositionAtEndOfAnchor());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsNullPosition());
+}
+
+TEST_F(AXPositionTest, CreatePositionAtEndOfAnchorWithTreePosition) {
+ std::unique_ptr<TestPositionType> tree_position(
+ AXNodePosition::CreateTreePosition(tree_.data().tree_id, root_.id,
+ 3 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ std::unique_ptr<TestPositionType> test_position(
+ tree_position->CreatePositionAtEndOfAnchor());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTreePosition());
+ EXPECT_EQ(root_.id, test_position->anchor_id());
+ EXPECT_EQ(3, test_position->child_index());
+
+ tree_position.reset(AXNodePosition::CreateTreePosition(
+ tree_.data().tree_id, root_.id, 1 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ test_position.reset(tree_position->CreatePositionAtEndOfAnchor());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTreePosition());
+ EXPECT_EQ(root_.id, test_position->anchor_id());
+ EXPECT_EQ(3, test_position->child_index());
+}
+
+TEST_F(AXPositionTest, CreatePositionAtEndOfAnchorWithTextPosition) {
+ std::unique_ptr<TestPositionType> text_position(
+ AXNodePosition::CreateTextPosition(tree_.data().tree_id, inline_box1_.id,
+ 6 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ std::unique_ptr<TestPositionType> test_position(
+ text_position->CreatePositionAtEndOfAnchor());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
+ EXPECT_EQ(6, test_position->text_offset());
+
+ text_position.reset(AXNodePosition::CreateTextPosition(
+ tree_.data().tree_id, inline_box1_.id, 5 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ test_position.reset(text_position->CreatePositionAtEndOfAnchor());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
+ EXPECT_EQ(6, test_position->text_offset());
+}
+
+TEST_F(AXPositionTest, CreateChildPositionAtWithNullPosition) {
+ std::unique_ptr<TestPositionType> null_position(
+ AXNodePosition::CreateNullPosition());
+ ASSERT_NE(nullptr, null_position);
+ std::unique_ptr<TestPositionType> test_position(
+ null_position->CreateChildPositionAt(0));
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsNullPosition());
+}
+
+TEST_F(AXPositionTest, CreateChildPositionAtWithTreePosition) {
+ std::unique_ptr<TestPositionType> tree_position(
+ AXNodePosition::CreateTreePosition(tree_.data().tree_id, root_.id,
+ 2 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ std::unique_ptr<TestPositionType> test_position(
+ tree_position->CreateChildPositionAt(1));
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTreePosition());
+ EXPECT_EQ(check_box_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->child_index());
+
+ tree_position.reset(AXNodePosition::CreateTreePosition(
+ tree_.data().tree_id, button_.id, 0 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ test_position.reset(tree_position->CreateChildPositionAt(0));
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsNullPosition());
+}
+
+TEST_F(AXPositionTest, CreateChildPositionAtWithTextPosition) {
+ std::unique_ptr<TestPositionType> text_position(
+ AXNodePosition::CreateTextPosition(tree_.data().tree_id, static_text1_.id,
+ 5 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ std::unique_ptr<TestPositionType> test_position(
+ text_position->CreateChildPositionAt(0));
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->text_offset());
+
+ text_position.reset(AXNodePosition::CreateTextPosition(
+ tree_.data().tree_id, static_text2_.id, 4 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ test_position.reset(text_position->CreateChildPositionAt(1));
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsNullPosition());
+}
+
+TEST_F(AXPositionTest, CreateParentPositionWithNullPosition) {
+ std::unique_ptr<TestPositionType> null_position(
+ AXNodePosition::CreateNullPosition());
+ ASSERT_NE(nullptr, null_position);
+ std::unique_ptr<TestPositionType> test_position(
+ null_position->CreateParentPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsNullPosition());
+}
+
+TEST_F(AXPositionTest, CreateParentPositionWithTreePosition) {
+ std::unique_ptr<TestPositionType> tree_position(
+ AXNodePosition::CreateTreePosition(tree_.data().tree_id, check_box_.id,
+ 0 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ std::unique_ptr<TestPositionType> test_position(
+ tree_position->CreateParentPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTreePosition());
+ EXPECT_EQ(root_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->child_index());
+
+ tree_position.reset(AXNodePosition::CreateTreePosition(
+ tree_.data().tree_id, root_.id, 1 /* child_index */));
+ ASSERT_NE(nullptr, tree_position);
+ test_position.reset(tree_position->CreateParentPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsNullPosition());
+}
+
+TEST_F(AXPositionTest, CreateParentPositionWithTextPosition) {
+ std::unique_ptr<TestPositionType> text_position(
+ AXNodePosition::CreateTextPosition(tree_.data().tree_id, inline_box1_.id,
+ 5 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ std::unique_ptr<TestPositionType> test_position(
+ text_position->CreateParentPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(static_text1_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->text_offset());
+}
+
+TEST_F(AXPositionTest, CreateNextCharacterPositionWithNullPosition) {
+ std::unique_ptr<TestPositionType> null_position(
+ AXNodePosition::CreateNullPosition());
+ ASSERT_NE(nullptr, null_position);
+ std::unique_ptr<TestPositionType> test_position(
+ null_position->CreateNextCharacterPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsNullPosition());
+}
+
+TEST_F(AXPositionTest, CreateNextCharacterPositionWithTextPosition) {
+ std::unique_ptr<TestPositionType> text_position(
+ AXNodePosition::CreateTextPosition(tree_.data().tree_id, inline_box1_.id,
+ 4 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ std::unique_ptr<TestPositionType> test_position(
+ text_position->CreateNextCharacterPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
+ EXPECT_EQ(5, test_position->text_offset());
+
+ text_position.reset(AXNodePosition::CreateTextPosition(
+ tree_.data().tree_id, inline_box1_.id, 5 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ test_position.reset(text_position->CreateNextCharacterPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(line_break_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->text_offset());
+
+ test_position.reset(test_position->CreateNextCharacterPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->text_offset());
+
+ test_position.reset(test_position->CreateNextCharacterPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
+ EXPECT_EQ(1, test_position->text_offset());
+
+ text_position.reset(AXNodePosition::CreateTextPosition(
+ tree_.data().tree_id, check_box_.id, 15 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ test_position.reset(text_position->CreateNextCharacterPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->text_offset());
+}
+
+TEST_F(AXPositionTest, CreatePreviousCharacterPositionWithNullPosition) {
+ std::unique_ptr<TestPositionType> null_position(
+ AXNodePosition::CreateNullPosition());
+ ASSERT_NE(nullptr, null_position);
+ std::unique_ptr<TestPositionType> test_position(
+ null_position->CreatePreviousCharacterPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsNullPosition());
+}
+
+TEST_F(AXPositionTest, CreatePreviousCharacterPositionWithTextPosition) {
+ std::unique_ptr<TestPositionType> text_position(
+ AXNodePosition::CreateTextPosition(tree_.data().tree_id, inline_box2_.id,
+ 5 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ std::unique_ptr<TestPositionType> test_position(
+ text_position->CreatePreviousCharacterPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
+ EXPECT_EQ(4, test_position->text_offset());
+
+ text_position.reset(AXNodePosition::CreateTextPosition(
+ tree_.data().tree_id, inline_box2_.id, 0 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ test_position.reset(text_position->CreatePreviousCharacterPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(line_break_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->text_offset());
+
+ test_position.reset(test_position->CreatePreviousCharacterPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
+ EXPECT_EQ(5, test_position->text_offset());
+
+ test_position.reset(test_position->CreatePreviousCharacterPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
+ EXPECT_EQ(4, test_position->text_offset());
+
+ text_position.reset(AXNodePosition::CreateTextPosition(
+ tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM));
+ ASSERT_NE(nullptr, text_position);
+ test_position.reset(text_position->CreatePreviousCharacterPosition());
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(check_box_.id, test_position->anchor_id());
+ EXPECT_EQ(15, test_position->text_offset());
+}
+
+} // namespace ui
diff --git a/chromium/ui/accessibility/ax_position.h b/chromium/ui/accessibility/ax_position.h
new file mode 100644
index 00000000000..831d5018d8c
--- /dev/null
+++ b/chromium/ui/accessibility/ax_position.h
@@ -0,0 +1,390 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ACCESSIBILITY_AX_POSITION_H_
+#define UI_ACCESSIBILITY_AX_POSITION_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+namespace ui {
+
+// Defines the type of position in the accessibility tree.
+// A tree position is used when referring to a specific child of a node in the
+// accessibility tree.
+// A text position is used when referring to a specific character of text inside
+// a particular node.
+// A null position is used to signify that the provided data is invalid or that
+// a boundary has been reached.
+enum class AXPositionKind { NullPosition, TreePosition, TextPosition };
+
+// A position in the |AXTree|.
+// It could either indicate a non-textual node in the accessibility tree, or a
+// text node and a character offset.
+// A text node has either a role of static_text, inline_text_box or line_break.
+//
+// This class template uses static polymorphism in order to allow sub-classes to
+// be created from the base class without the base class knowing the type of the
+// sub-class in advance.
+// The template argument |AXPositionType| should always be set to the type of
+// any class that inherits from this template, making this a
+// "curiously recursive template".
+template <class AXPositionType, class AXNodeType>
+class AXPosition {
+ public:
+ static int INVALID_TREE_ID;
+ static int INVALID_ANCHOR_ID;
+ static int INVALID_INDEX;
+ static int INVALID_OFFSET;
+
+ AXPosition() {}
+ virtual ~AXPosition() {}
+
+ static AXPosition<AXPositionType, AXNodeType>* CreateNullPosition() {
+ auto new_position = static_cast<AXPosition<AXPositionType, AXNodeType>*>(
+ new AXPositionType());
+ DCHECK(new_position);
+ new_position->Initialize(AXPositionKind::NullPosition, INVALID_TREE_ID,
+ INVALID_ANCHOR_ID, INVALID_INDEX, INVALID_OFFSET,
+ AX_TEXT_AFFINITY_UPSTREAM);
+ return new_position;
+ }
+
+ static AXPosition<AXPositionType, AXNodeType>*
+ CreateTreePosition(int tree_id, int32_t anchor_id, int child_index) {
+ auto new_position = static_cast<AXPosition<AXPositionType, AXNodeType>*>(
+ new AXPositionType());
+ DCHECK(new_position);
+ new_position->Initialize(AXPositionKind::TreePosition, tree_id, anchor_id,
+ child_index, INVALID_OFFSET,
+ AX_TEXT_AFFINITY_UPSTREAM);
+ return new_position;
+ }
+
+ static AXPosition<AXPositionType, AXNodeType>* CreateTextPosition(
+ int tree_id,
+ int32_t anchor_id,
+ int text_offset,
+ AXTextAffinity affinity) {
+ auto new_position = static_cast<AXPosition<AXPositionType, AXNodeType>*>(
+ new AXPositionType());
+ DCHECK(new_position);
+ new_position->Initialize(AXPositionKind::TextPosition, tree_id, anchor_id,
+ INVALID_INDEX, text_offset, affinity);
+ return new_position;
+ }
+
+ int tree_id() const { return tree_id_; }
+ int32_t anchor_id() const { return anchor_id_; }
+
+ AXNodeType* GetAnchor() const {
+ if (tree_id_ == INVALID_TREE_ID || anchor_id_ == INVALID_ANCHOR_ID)
+ return nullptr;
+ DCHECK_GE(tree_id_, 0);
+ DCHECK_GE(anchor_id_, 0);
+ return GetNodeInTree(tree_id_, anchor_id_);
+ }
+
+ AXPositionKind kind() const { return kind_; }
+ int child_index() const { return child_index_; }
+ int text_offset() const { return text_offset_; }
+ AXTextAffinity affinity() const { return affinity_; }
+
+ bool IsNullPosition() const {
+ return kind_ == AXPositionKind::NullPosition || !GetAnchor();
+ }
+ bool IsTreePosition() const {
+ return GetAnchor() && kind_ == AXPositionKind::TreePosition;
+ }
+ bool IsTextPosition() const {
+ return GetAnchor() && kind_ == AXPositionKind::TextPosition;
+ }
+
+ bool AtStartOfAnchor() const {
+ if (!GetAnchor())
+ return false;
+
+ switch (kind_) {
+ case AXPositionKind::NullPosition:
+ return false;
+ case AXPositionKind::TreePosition:
+ return child_index_ == 0;
+ case AXPositionKind::TextPosition:
+ return text_offset_ == 0;
+ }
+
+ return false;
+ }
+
+ bool AtEndOfAnchor() const {
+ if (!GetAnchor())
+ return false;
+
+ switch (kind_) {
+ case AXPositionKind::NullPosition:
+ return false;
+ case AXPositionKind::TreePosition:
+ return child_index_ == AnchorChildCount();
+ case AXPositionKind::TextPosition:
+ return text_offset_ == MaxTextOffset();
+ }
+
+ return false;
+ }
+
+ AXPosition<AXPositionType, AXNodeType>* CreatePositionAtStartOfAnchor()
+ const {
+ switch (kind_) {
+ case AXPositionKind::NullPosition:
+ return CreateNullPosition();
+ case AXPositionKind::TreePosition:
+ return CreateTreePosition(tree_id_, anchor_id_, 0 /* child_index */);
+ case AXPositionKind::TextPosition:
+ return CreateTextPosition(tree_id_, anchor_id_, 0 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM);
+ }
+ return CreateNullPosition();
+ }
+
+ AXPosition<AXPositionType, AXNodeType>* CreatePositionAtEndOfAnchor() const {
+ switch (kind_) {
+ case AXPositionKind::NullPosition:
+ return CreateNullPosition();
+ case AXPositionKind::TreePosition:
+ return CreateTreePosition(tree_id_, anchor_id_, AnchorChildCount());
+ case AXPositionKind::TextPosition:
+ return CreateTextPosition(tree_id_, anchor_id_, MaxTextOffset(),
+ AX_TEXT_AFFINITY_UPSTREAM);
+ }
+ return CreateNullPosition();
+ }
+
+ AXPosition<AXPositionType, AXNodeType>* CreateChildPositionAt(
+ int child_index) const {
+ if (IsNullPosition())
+ return CreateNullPosition();
+
+ if (child_index < 0 || child_index >= AnchorChildCount())
+ return CreateNullPosition();
+
+ int tree_id = INVALID_TREE_ID;
+ int32_t child_id = INVALID_ANCHOR_ID;
+ AnchorChild(child_index, &tree_id, &child_id);
+ DCHECK_NE(tree_id, INVALID_TREE_ID);
+ DCHECK_NE(child_id, INVALID_ANCHOR_ID);
+ switch (kind_) {
+ case AXPositionKind::NullPosition:
+ NOTREACHED();
+ return CreateNullPosition();
+ case AXPositionKind::TreePosition:
+ return CreateTreePosition(tree_id, child_id, 0 /* child_index */);
+ case AXPositionKind::TextPosition:
+ return CreateTextPosition(tree_id, child_id, 0 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM);
+ }
+
+ return CreateNullPosition();
+ }
+
+ AXPosition<AXPositionType, AXNodeType>* CreateParentPosition() const {
+ if (IsNullPosition())
+ return CreateNullPosition();
+
+ int tree_id = INVALID_TREE_ID;
+ int32_t parent_id = INVALID_ANCHOR_ID;
+ AnchorParent(&tree_id, &parent_id);
+ if (tree_id == INVALID_TREE_ID || parent_id == INVALID_ANCHOR_ID)
+ return CreateNullPosition();
+
+ DCHECK_GE(tree_id, 0);
+ DCHECK_GE(parent_id, 0);
+ switch (kind_) {
+ case AXPositionKind::NullPosition:
+ NOTREACHED();
+ return CreateNullPosition();
+ case AXPositionKind::TreePosition:
+ return CreateTreePosition(tree_id, parent_id, 0 /* child_index */);
+ case AXPositionKind::TextPosition:
+ return CreateTextPosition(tree_id, parent_id, 0 /* text_offset */,
+ AX_TEXT_AFFINITY_UPSTREAM);
+ }
+
+ return CreateNullPosition();
+ }
+
+ // The following methods work across anchors.
+
+ // TODO(nektar): Not yet implemented for tree positions.
+ AXPosition<AXPositionType, AXNodeType>* CreateNextCharacterPosition() const {
+ if (IsNullPosition())
+ return CreateNullPosition();
+
+ if (text_offset_ + 1 < MaxTextOffset()) {
+ return CreateTextPosition(tree_id_, anchor_id_, text_offset_ + 1,
+ AX_TEXT_AFFINITY_UPSTREAM);
+ }
+
+ std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> next_leaf(
+ CreateNextAnchorPosition());
+ while (next_leaf && !next_leaf->IsNullPosition() &&
+ next_leaf->AnchorChildCount()) {
+ next_leaf.reset(next_leaf->CreateNextAnchorPosition());
+ }
+
+ DCHECK(next_leaf);
+ return next_leaf.release();
+ }
+
+ // TODO(nektar): Not yet implemented for tree positions.
+ AXPosition<AXPositionType, AXNodeType>* CreatePreviousCharacterPosition()
+ const {
+ if (IsNullPosition())
+ return CreateNullPosition();
+
+ if (text_offset_ > 0) {
+ return CreateTextPosition(tree_id_, anchor_id_, text_offset_ - 1,
+ AX_TEXT_AFFINITY_UPSTREAM);
+ }
+
+ std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> previous_leaf(
+ CreatePreviousAnchorPosition());
+ while (previous_leaf && !previous_leaf->IsNullPosition() &&
+ previous_leaf->AnchorChildCount()) {
+ previous_leaf.reset(previous_leaf->CreatePreviousAnchorPosition());
+ }
+
+ DCHECK(previous_leaf);
+ previous_leaf.reset(previous_leaf->CreatePositionAtEndOfAnchor());
+ if (!previous_leaf->AtStartOfAnchor())
+ --previous_leaf->text_offset_;
+ return previous_leaf.release();
+ }
+
+ // TODO(nektar): Add word, line and paragraph navigation methods.
+
+ protected:
+ virtual void Initialize(AXPositionKind kind,
+ int tree_id,
+ int32_t anchor_id,
+ int child_index,
+ int text_offset,
+ AXTextAffinity affinity) {
+ kind_ = kind;
+ tree_id_ = tree_id;
+ anchor_id_ = anchor_id;
+ child_index_ = child_index;
+ text_offset_ = text_offset;
+ affinity_ = affinity;
+
+ if (!GetAnchor() ||
+ (child_index_ != INVALID_INDEX &&
+ (child_index_ < 0 || child_index_ > AnchorChildCount())) ||
+ (text_offset_ != INVALID_OFFSET &&
+ (text_offset_ < 0 || text_offset_ > MaxTextOffset()))) {
+ // reset to the null position.
+ kind_ = AXPositionKind::NullPosition;
+ tree_id_ = INVALID_TREE_ID;
+ anchor_id_ = INVALID_ANCHOR_ID;
+ child_index_ = INVALID_INDEX;
+ text_offset_ = INVALID_OFFSET;
+ affinity_ = AX_TEXT_AFFINITY_UPSTREAM;
+ }
+ }
+
+ // Uses depth-first pre-order traversal.
+ virtual AXPosition<AXPositionType, AXNodeType>* CreateNextAnchorPosition()
+ const {
+ if (IsNullPosition())
+ return CreateNullPosition();
+
+ if (AnchorChildCount())
+ return CreateChildPositionAt(0);
+
+ std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> current_position(
+ CreateTreePosition(tree_id_, anchor_id_, child_index_));
+ std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> parent_position(
+ CreateParentPosition());
+ while (parent_position && !parent_position->IsNullPosition()) {
+ // Get the next sibling if it exists, otherwise move up to the parent's
+ // next sibling.
+ int index_in_parent = current_position->AnchorIndexInParent();
+ if (index_in_parent < parent_position->AnchorChildCount() - 1) {
+ AXPosition<AXPositionType, AXNodeType>* next_sibling =
+ parent_position->CreateChildPositionAt(index_in_parent + 1);
+ DCHECK(next_sibling && !next_sibling->IsNullPosition());
+ return next_sibling;
+ }
+
+ current_position = std::move(parent_position);
+ parent_position.reset(current_position->CreateParentPosition());
+ }
+
+ return CreateNullPosition();
+ }
+
+ // Uses depth-first pre-order traversal.
+ virtual AXPosition<AXPositionType, AXNodeType>* CreatePreviousAnchorPosition()
+ const {
+ if (IsNullPosition())
+ return CreateNullPosition();
+
+ std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> parent_position(
+ CreateParentPosition());
+ if (!parent_position || parent_position->IsNullPosition())
+ return CreateNullPosition();
+
+ // Get the previous sibling's deepest first child if a previous sibling
+ // exists, otherwise move up to the parent.
+ int index_in_parent = AnchorIndexInParent();
+ if (index_in_parent <= 0)
+ return parent_position.release();
+
+ std::unique_ptr<AXPosition<AXPositionType, AXNodeType>> leaf(
+ parent_position->CreateChildPositionAt(index_in_parent - 1));
+ while (leaf && !leaf->IsNullPosition() && leaf->AnchorChildCount())
+ leaf.reset(leaf->CreateChildPositionAt(0));
+
+ return leaf.release();
+ }
+
+ // Abstract methods.
+ virtual void AnchorChild(int child_index,
+ int* tree_id,
+ int32_t* child_id) const = 0;
+ virtual int AnchorChildCount() const = 0;
+ virtual int AnchorIndexInParent() const = 0;
+ virtual void AnchorParent(int* tree_id, int32_t* parent_id) const = 0;
+ virtual AXNodeType* GetNodeInTree(int tree_id, int32_t node_id) const = 0;
+ // Returns the length of the text that is present inside the anchor node,
+ // including any text found on descendant nodes.
+ virtual int MaxTextOffset() const = 0;
+
+ private:
+ AXPositionKind kind_;
+ int tree_id_;
+ int32_t anchor_id_;
+
+ // For text positions, |child_index_| is initially set to |-1| and only
+ // computed on demand. The same with tree positions and |text_offset_|.
+ int child_index_;
+ int text_offset_;
+
+ // TODO(nektar): Get rid of affinity and make Blink handle affinity
+ // internally since inline text objects don't span lines.
+ ui::AXTextAffinity affinity_;
+};
+
+template <class AXPositionType, class AXNodeType>
+int AXPosition<AXPositionType, AXNodeType>::INVALID_TREE_ID = -1;
+template <class AXPositionType, class AXNodeType>
+int32_t AXPosition<AXPositionType, AXNodeType>::INVALID_ANCHOR_ID = -1;
+template <class AXPositionType, class AXNodeType>
+int AXPosition<AXPositionType, AXNodeType>::INVALID_INDEX = -1;
+template <class AXPositionType, class AXNodeType>
+int AXPosition<AXPositionType, AXNodeType>::INVALID_OFFSET = -1;
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_AX_POSITION_H_
diff --git a/chromium/ui/accessibility/ax_tree_combiner.cc b/chromium/ui/accessibility/ax_tree_combiner.cc
index 736cc583a15..b983e995519 100644
--- a/chromium/ui/accessibility/ax_tree_combiner.cc
+++ b/chromium/ui/accessibility/ax_tree_combiner.cc
@@ -82,6 +82,7 @@ bool IsNodeIdIntListAttribute(AXIntListAttribute attr) {
// add a new attribute without explicitly considering whether it's
// a node id attribute or not.
case AX_INT_LIST_ATTRIBUTE_NONE:
+ case AX_ATTR_LINE_BREAKS:
case AX_ATTR_MARKER_TYPES:
case AX_ATTR_MARKER_STARTS:
case AX_ATTR_MARKER_ENDS:
@@ -167,12 +168,6 @@ int32_t AXTreeCombiner::MapId(int32_t tree_id, int32_t node_id) {
}
void AXTreeCombiner::ProcessTree(const AXTreeUpdate* tree) {
- // The root of each tree may contain a transform that needs to apply
- // to all of its descendants.
- gfx::Transform old_transform = transform_;
- if (!tree->nodes.empty() && tree->nodes[0].transform)
- transform_.ConcatTransform(*tree->nodes[0].transform);
-
int32_t tree_id = tree->tree_data.tree_id;
for (size_t i = 0; i < tree->nodes.size(); ++i) {
AXNodeData node = tree->nodes[i];
@@ -185,9 +180,9 @@ void AXTreeCombiner::ProcessTree(const AXTreeUpdate* tree) {
for (size_t j = 0; j < node.child_ids.size(); ++j)
node.child_ids[j] = MapId(tree_id, node.child_ids[j]);
- // Reset the offset container ID because we make all bounding boxes
- // absolute.
- node.offset_container_id = -1;
+ // Map the container id.
+ if (node.offset_container_id > 0)
+ node.offset_container_id = MapId(tree_id, node.offset_container_id);
// Map other int attributes that refer to node IDs, and remove the
// AX_ATTR_CHILD_TREE_ID attribute.
@@ -210,10 +205,6 @@ void AXTreeCombiner::ProcessTree(const AXTreeUpdate* tree) {
}
}
- // Apply the transformation to the object's bounds to put it in
- // the coordinate space of the root frame.
- transform_.TransformRect(&node.location);
-
// See if this node has a child tree. As a sanity check make sure the
// child tree lists this tree as its parent tree id.
const AXTreeUpdate* child_tree = nullptr;
@@ -236,9 +227,6 @@ void AXTreeCombiner::ProcessTree(const AXTreeUpdate* tree) {
if (child_tree)
ProcessTree(child_tree);
}
-
- // Reset the transform.
- transform_ = old_transform;
}
} // namespace ui
diff --git a/chromium/ui/accessibility/ax_tree_combiner.h b/chromium/ui/accessibility/ax_tree_combiner.h
index 37b9fa56879..ce8fbc792d5 100644
--- a/chromium/ui/accessibility/ax_tree_combiner.h
+++ b/chromium/ui/accessibility/ax_tree_combiner.h
@@ -9,7 +9,6 @@
#include "ui/accessibility/ax_export.h"
#include "ui/accessibility/ax_tree_update.h"
-#include "ui/gfx/transform.h"
namespace ui {
@@ -19,8 +18,7 @@ namespace ui {
//
// Since node IDs are relative to each ID, it has to renumber all of the IDs
// and update all of the attributes that reference IDs of other nodes to
-// ensure they point to the right node. It also applies transformations to
-// local bounding rectangles to make them global.
+// ensure they point to the right node.
//
// It also makes sure the final combined tree points to the correct focused
// node across all of the trees based on the focused tree ID of the root tree.
@@ -45,7 +43,6 @@ class AX_EXPORT AXTreeCombiner {
std::map<int32_t, const AXTreeUpdate*> tree_id_map_;
std::map<std::pair<int32_t, int32_t>, int32_t> tree_id_node_id_map_;
AXTreeUpdate combined_;
- gfx::Transform transform_;
};
diff --git a/chromium/ui/accessibility/ax_tree_combiner_unittest.cc b/chromium/ui/accessibility/ax_tree_combiner_unittest.cc
index 49fbccc988f..b80771d3bf0 100644
--- a/chromium/ui/accessibility/ax_tree_combiner_unittest.cc
+++ b/chromium/ui/accessibility/ax_tree_combiner_unittest.cc
@@ -149,57 +149,6 @@ TEST(CombineAXTreesTest, MapAllIdAttributes) {
AX_ATTR_UNIQUE_CELL_IDS)[0]);
}
-TEST(CombineAXTreesTest, Coordinates) {
- AXTreeUpdate parent_tree;
- parent_tree.has_tree_data = true;
- parent_tree.tree_data.tree_id = 1;
- parent_tree.root_id = 1;
- parent_tree.nodes.resize(3);
- parent_tree.nodes[0].id = 1;
- parent_tree.nodes[0].child_ids.push_back(2);
- parent_tree.nodes[0].child_ids.push_back(3);
- parent_tree.nodes[1].id = 2;
- parent_tree.nodes[1].role = AX_ROLE_BUTTON;
- parent_tree.nodes[1].location = gfx::RectF(50, 10, 200, 100);
- parent_tree.nodes[2].id = 3;
- parent_tree.nodes[2].role = AX_ROLE_IFRAME;
- parent_tree.nodes[2].AddIntAttribute(AX_ATTR_CHILD_TREE_ID, 2);
-
- AXTreeUpdate child_tree;
- child_tree.has_tree_data = true;
- child_tree.tree_data.parent_tree_id = 1;
- child_tree.tree_data.tree_id = 2;
- child_tree.root_id = 1;
- child_tree.nodes.resize(2);
- child_tree.nodes[0].id = 1;
- child_tree.nodes[0].child_ids.push_back(2);
-
- child_tree.nodes[0].transform.reset(new gfx::Transform());
- child_tree.nodes[0].transform->Translate(0, 300);
- child_tree.nodes[0].transform->Scale(2.0, 2.0);
-
- child_tree.nodes[1].id = 2;
- child_tree.nodes[1].role = AX_ROLE_BUTTON;
- child_tree.nodes[1].location = gfx::RectF(50, 10, 200, 100);
-
- AXTreeCombiner combiner;
- combiner.AddTree(parent_tree, true);
- combiner.AddTree(child_tree, false);
- combiner.Combine();
-
- const AXTreeUpdate& combined = combiner.combined();
-
- ASSERT_EQ(5U, combined.nodes.size());
- EXPECT_EQ(50, combined.nodes[1].location.x());
- EXPECT_EQ(10, combined.nodes[1].location.y());
- EXPECT_EQ(200, combined.nodes[1].location.width());
- EXPECT_EQ(100, combined.nodes[1].location.height());
- EXPECT_EQ(100, combined.nodes[4].location.x());
- EXPECT_EQ(320, combined.nodes[4].location.y());
- EXPECT_EQ(400, combined.nodes[4].location.width());
- EXPECT_EQ(200, combined.nodes[4].location.height());
-}
-
TEST(CombineAXTreesTest, FocusedTree) {
AXTreeUpdate parent_tree;
parent_tree.has_tree_data = true;
diff --git a/chromium/ui/accessibility/ax_view_state.cc b/chromium/ui/accessibility/ax_view_state.cc
deleted file mode 100644
index fe101a500c6..00000000000
--- a/chromium/ui/accessibility/ax_view_state.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/accessibility/ax_view_state.h"
-
-namespace ui {
-
-AXViewState::AXViewState()
- : role(AX_ROLE_CLIENT),
- selection_start(-1),
- selection_end(-1),
- index(-1),
- count(-1),
- state_(0) { }
-
-AXViewState::~AXViewState() { }
-
-// static
-bool AXViewState::IsFlagSet(uint32_t state, ui::AXState state_flag) {
- return 0 != (state & (1 << state_flag));
-}
-
-void AXViewState::AddStateFlag(ui::AXState state_flag) {
- state_ |= (1 << state_flag);
-}
-
-bool AXViewState::HasStateFlag(ui::AXState state_flag) const {
- return IsFlagSet(state_, state_flag);
-}
-
-} // namespace ui
diff --git a/chromium/ui/accessibility/ax_view_state.h b/chromium/ui/accessibility/ax_view_state.h
deleted file mode 100644
index a20a65d6e7d..00000000000
--- a/chromium/ui/accessibility/ax_view_state.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_ACCESSIBILITY_AX_VIEW_STATE_H_
-#define UI_ACCESSIBILITY_AX_VIEW_STATE_H_
-
-#include <stdint.h>
-
-#include "base/callback.h"
-#include "base/strings/string16.h"
-#include "ui/accessibility/ax_enums.h"
-#include "ui/accessibility/ax_export.h"
-
-namespace ui {
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// AXViewState
-//
-// A cross-platform struct for storing the core accessibility information
-// that should be provided about any UI view to assistive technology (AT).
-//
-////////////////////////////////////////////////////////////////////////////////
-struct AX_EXPORT AXViewState {
- public:
- AXViewState();
- ~AXViewState();
-
- // Helper to check whether |state_flag| is set in the given |state|.
- static bool IsFlagSet(uint32_t state, ui::AXState state_flag);
-
- // Set or check bits in |state_|.
- void AddStateFlag(ui::AXState state_flag);
- bool HasStateFlag(ui::AXState state_flag) const;
-
- // The view's state, a bitmask containing fields such as checked
- // (for a checkbox) and protected (for a password text box). This "state"
- // should not be confused with the class's name.
- uint32_t state() { return state_; }
-
- // The view's role, like button or list box.
- AXRole role;
-
- // The view's name / label.
- base::string16 name;
-
- // The view's value, for example the text content.
- base::string16 value;
-
- // The name of the default action if the user clicks on this view.
- base::string16 default_action;
-
- // The keyboard shortcut to activate this view, if any.
- base::string16 keyboard_shortcut;
-
- // The view's placeholder value, used only for views with editable text.
- base::string16 placeholder;
-
- // The view's help text/description, set to the view's tooltip text (if any).
- base::string16 description;
-
- // The selection start and end. Only applies to views with text content,
- // such as a text box or combo box; start and end should be -1 otherwise.
- int selection_start;
- int selection_end;
-
- // The selected item's index and the count of the number of items.
- // Only applies to views with multiple choices like a listbox; both
- // index and count should be -1 otherwise.
- int index;
- int count;
-
- // An optional callback that can be used by accessibility clients to
- // set the string value of this view. This only applies to roles where
- // setting the value makes sense, like a text box. Not often used by
- // screen readers, but often used by automation software to script
- // things like logging into portals or filling forms.
- //
- // This callback is only valid for the lifetime of the view, and should
- // be a safe no-op if the view is deleted. Typically, accessible views
- // should use a WeakPtr when binding the callback.
- base::Callback<void(const base::string16&)> set_value_callback;
-
- private:
- uint32_t state_;
-};
-
-} // namespace ui
-
-#endif // UI_ACCESSIBILITY_AX_VIEW_STATE_H_
diff --git a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_bn.xtb b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_bn.xtb
index c7c1bc0f4e3..04b981db1a0 100644
--- a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_bn.xtb
+++ b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_bn.xtb
@@ -18,7 +18,7 @@
<translation id="2648340354586434750">শব্দগুলির দ্বারা সরাতে &lt;span class='key'&gt;বিকল্প&lt;/span&gt; টিপে ধরে রাখুন৷</translation>
<translation id="2795227192542594043">এই এক্সটেনশানটি আপনাকে ওয়েব পৃষ্ঠাটির উপর একটি চলনশীল কার্সার দেয়, আপনাকে কীবোর্ড দিয়ে পাঠ্য নির্বাচন করতে দেয়৷</translation>
<translation id="2808027189040546825">পদক্ষেপ ১: ক্ষীণতম তারকা সহ সারিটি নির্বাচন করুন:</translation>
-<translation id="2965611304828530558">&lt;p&gt;যখন আপনি কোনো লিঙ্ক অ্যাক্সেস করেন বা নিয়ন্ত্রণ করেন, তখন এটি স্বয়ংক্রিয়ভাবে ফোকাস করবে৷ কোনো লিঙ্ক বা বোতামে ক্লিক করতে &lt;span class='key'&gt;Enter&lt;/span&gt; টিপুন৷ &lt;/p&gt; &lt;p&gt; যখন কোনো ফোকাস করা নিয়ন্ত্রণ (কোনো পাঠ্য বক্স বা তালিকা বক্স) নির্দেশক তীরচিহ্নগুলি ক্যাপচার করে, তখন ক্যারেট ব্রাউজিং করা চালিয়ে যেতে বাম বা ডান তীর অনুসরণ করে &lt;span class='key'&gt;Esc&lt;/span&gt; টিপুন৷ &lt;/p&gt; &lt;p&gt; অন্যথা, পরবর্তী ফোকাসযোগ্য নিয়ন্ত্রণে সরে যেতে &lt;span class='key'&gt;Tab&lt;/span&gt; টিপুন৷ &lt;/p&gt;</translation>
+<translation id="2965611304828530558">&lt;p&gt;যখন আপনি কোনো লিঙ্ক অ্যাক্সেস করেন বা নিয়ন্ত্রণ করেন, তখন এটি স্বয়ংক্রিয়ভাবে ফোকাস করবে৷ কোনো লিঙ্ক বা বোতামে ক্লিক করতে &lt;span class='key'&gt;Enter&lt;/span&gt; টিপুন৷ &lt;/p&gt; &lt;p&gt; যখন কোনো ফোকাস করা নিয়ন্ত্রণ (কোনো পাঠ্য বক্স বা তালিকা বক্স) নির্দেশক তীরচিহ্নগুলি ক্যাপচার করে, তখন ক্যারেট ব্রাউজিং করা চালিয়ে যেতে বাঁ বা ডান তীর অনুসরণ করে &lt;span class='key'&gt;Esc&lt;/span&gt; টিপুন৷ &lt;/p&gt; &lt;p&gt; অন্যথা, পরবর্তী ফোকাসযোগ্য নিয়ন্ত্রণে সরে যেতে &lt;span class='key'&gt;Tab&lt;/span&gt; টিপুন৷ &lt;/p&gt;</translation>
<translation id="3252573918265662711">সেটআপ</translation>
<translation id="3410969471888629217">সাইট কাস্টমাইজেশনগুলি মুছুন</translation>
<translation id="3435896845095436175">সক্ষম করুন</translation>
diff --git a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_da.xtb b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_da.xtb
index db92820b5f7..c22efe89c8e 100644
--- a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_da.xtb
+++ b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_da.xtb
@@ -21,7 +21,7 @@
<translation id="2965611304828530558">&lt;p&gt;Når du når til et link eller et kontrolelement, fremhæves det automatisk. Tryk på &lt;span class='key'&gt;Enter&lt;/span&gt; for at klikke på et link eller en knap. &lt;/p&gt; &lt;p&gt; Når et fremhævet kontrolelement (som f.eks. et tekstfelt eller et listefelt) griber piletaster, skal du trykke på &lt;span class='key'&gt;Esc&lt;/span&gt; efterfulgt af venstre eller højre pil for at fortsætte tastebrowsing. &lt;/p&gt; &lt;p&gt; Alternativt kan du også trykke på &lt;span class='key'&gt;Tab&lt;/span&gt; for at gå til det næste kontrolelement, der kan fremhæves. &lt;/p&gt;</translation>
<translation id="3252573918265662711">Konfiguration</translation>
<translation id="3410969471888629217">Glem websitets tilpasninger</translation>
-<translation id="3435896845095436175">Aktiver</translation>
+<translation id="3435896845095436175">Aktivér</translation>
<translation id="3622586652998721735">Vælg som standardtema</translation>
<translation id="3812541808639806898">Visningsprogram for billeder og "Alt"-tekst</translation>
<translation id="381767806621926835">Højreklik på indhold med en "longdesc"- eller "Aria-describedat"-attribut for at få adgang den lange version af beskrivelsen.</translation>
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_delegate.h b/chromium/ui/accessibility/platform/ax_platform_node_delegate.h
index 1e27f3f00a0..8569e7ff52d 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_delegate.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_delegate.h
@@ -85,10 +85,18 @@ class AX_EXPORT AXPlatformNodeDelegate {
virtual void DoDefaultAction() = 0;
// Change the value of a control, such as the text content of a text field.
- virtual bool SetStringValue(const base::string16& new_value) = 0;
-
- // Whether the string value is settable.
+ // If |clear_first| is true, this replaces all text with the |new_value|.
+ // Otherwise this inserts |new_value| at the cursor position, replacing any
+ // selected text. The cursor is placed at the end of |new_value|.
+ virtual bool SetStringValue(const base::string16& new_value,
+ bool clear_first) = 0;
+
+ // Whether SetStringValue() is callable, i.e. if the string value is not read
+ // only and if the callback exists.
virtual bool CanSetStringValue() = 0;
+
+ // Focus or unfocus a View, checking if the View is focusable first.
+ virtual bool SetFocused(bool focused) = 0;
};
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_mac.mm b/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
index be9eb9e3679..a30b42007f0 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
+++ b/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -10,7 +10,6 @@
#include "base/macros.h"
#include "base/strings/sys_string_conversions.h"
#include "ui/accessibility/ax_node_data.h"
-#include "ui/accessibility/ax_view_state.h"
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
#import "ui/gfx/mac/coordinate_conversion.h"
@@ -378,16 +377,13 @@ void NotifyMacEvent(AXPlatformNodeCocoa* target, ui::AXEvent event_type) {
return NO;
}
- if ([attributeName isEqualToString:NSAccessibilityValueAttribute])
+ if ([attributeName isEqualToString:NSAccessibilityValueAttribute] ||
+ [attributeName isEqualToString:NSAccessibilitySelectedTextAttribute])
return node_->GetDelegate()->CanSetStringValue();
- // TODO(patricialor): Implement and merge with conditional for value above.
- if ([attributeName isEqualToString:NSAccessibilitySelectedTextAttribute])
- return NO;
if ([attributeName isEqualToString:NSAccessibilityFocusedAttribute]) {
- if (ui::AXViewState::IsFlagSet(node_->GetData().state,
- ui::AX_STATE_FOCUSABLE))
- return NO;
+ return ui::AXNodeData::IsFlagSet(node_->GetData().state,
+ ui::AX_STATE_FOCUSABLE);
}
// TODO(patricialor): Add callbacks for updating the above attributes except
@@ -396,9 +392,20 @@ void NotifyMacEvent(AXPlatformNodeCocoa* target, ui::AXEvent event_type) {
}
- (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute {
- if ([attribute isEqualToString:NSAccessibilityValueAttribute] &&
- [value isKindOfClass:[NSString class]])
- node_->GetDelegate()->SetStringValue(base::SysNSStringToUTF16(value));
+ if ([value isKindOfClass:[NSString class]]) {
+ if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
+ node_->GetDelegate()->SetStringValue(base::SysNSStringToUTF16(value),
+ true);
+ } else if ([attribute
+ isEqualToString:NSAccessibilitySelectedTextAttribute]) {
+ node_->GetDelegate()->SetStringValue(base::SysNSStringToUTF16(value),
+ false);
+ }
+ } else if ([value isKindOfClass:[NSNumber class]]) {
+ if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
+ node_->GetDelegate()->SetFocused([value boolValue]);
+ }
+ }
// TODO(patricialor): Plumb through all the other writable attributes as
// specified in accessibilityIsAttributeSettable.
@@ -443,8 +450,8 @@ void NotifyMacEvent(AXPlatformNodeCocoa* target, ui::AXEvent event_type) {
ui::AXRole role = node_->GetData().role;
switch (role) {
case ui::AX_ROLE_TEXT_FIELD:
- if (ui::AXViewState::IsFlagSet(node_->GetData().state,
- ui::AX_STATE_PROTECTED))
+ if (ui::AXNodeData::IsFlagSet(node_->GetData().state,
+ ui::AX_STATE_PROTECTED))
return NSAccessibilitySecureTextFieldSubrole;
break;
default:
@@ -471,13 +478,13 @@ void NotifyMacEvent(AXPlatformNodeCocoa* target, ui::AXEvent event_type) {
- (NSValue*)AXEnabled {
return [NSNumber
- numberWithBool:!ui::AXViewState::IsFlagSet(node_->GetData().state,
- ui::AX_STATE_DISABLED)];
+ numberWithBool:!ui::AXNodeData::IsFlagSet(node_->GetData().state,
+ ui::AX_STATE_DISABLED)];
}
- (NSValue*)AXFocused {
- if (ui::AXViewState::IsFlagSet(node_->GetData().state,
- ui::AX_STATE_FOCUSABLE))
+ if (ui::AXNodeData::IsFlagSet(node_->GetData().state,
+ ui::AX_STATE_FOCUSABLE))
return [NSNumber numberWithBool:(node_->GetDelegate()->GetFocus() ==
node_->GetNativeViewAccessible())];
return [NSNumber numberWithBool:NO];
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win.cc b/chromium/ui/accessibility/platform/ax_platform_node_win.cc
index 814f383c19f..da6501c40c1 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_win.cc
@@ -454,7 +454,7 @@ STDMETHODIMP AXPlatformNodeWin::get_accValue(VARIANT var_id, BSTR* value) {
STDMETHODIMP AXPlatformNodeWin::put_accValue(VARIANT var_id,
BSTR new_value) {
COM_OBJECT_VALIDATE_VAR_ID(var_id);
- if (delegate_->SetStringValue(new_value))
+ if (delegate_->SetStringValue(new_value, true))
return S_OK;
return E_FAIL;
}
@@ -511,6 +511,8 @@ STDMETHODIMP AXPlatformNodeWin::get_states(AccessibleStates* states) {
*states = IA2_STATE_OPAQUE;
if (GetData().state & (1 << ui::AX_STATE_EDITABLE))
*states |= IA2_STATE_EDITABLE;
+ if (GetData().state & (1 << ui::AX_STATE_VERTICAL))
+ *states |= IA2_STATE_VERTICAL;
return S_OK;
}
@@ -897,9 +899,10 @@ STDMETHODIMP AXPlatformNodeWin::QueryService(
COM_OBJECT_VALIDATE_1_ARG(object);
if (riid == IID_IAccessible2) {
- FOR_EACH_OBSERVER(IAccessible2UsageObserver,
- GetIAccessible2UsageObserverList(),
- OnIAccessible2Used());
+ for (IAccessible2UsageObserver& observer :
+ GetIAccessible2UsageObserverList()) {
+ observer.OnIAccessible2Used();
+ }
}
if (guidService == IID_IAccessible ||
diff --git a/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc b/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc
index c639e0879bf..7388fd35758 100644
--- a/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc
+++ b/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -119,7 +119,8 @@ TestAXNodeWrapper::GetTargetForNativeAccessibilityEvent() {
void TestAXNodeWrapper::DoDefaultAction() {
}
-bool TestAXNodeWrapper::SetStringValue(const base::string16& new_value) {
+bool TestAXNodeWrapper::SetStringValue(const base::string16& new_value,
+ bool clear_first) {
return false;
}
@@ -127,6 +128,10 @@ bool TestAXNodeWrapper::CanSetStringValue() {
return false;
}
+bool TestAXNodeWrapper::SetFocused(bool focused) {
+ return false;
+}
+
TestAXNodeWrapper::TestAXNodeWrapper(AXTree* tree, AXNode* node)
: tree_(tree),
node_(node),
diff --git a/chromium/ui/accessibility/platform/test_ax_node_wrapper.h b/chromium/ui/accessibility/platform/test_ax_node_wrapper.h
index fdc2baa5abf..a52dd53707d 100644
--- a/chromium/ui/accessibility/platform/test_ax_node_wrapper.h
+++ b/chromium/ui/accessibility/platform/test_ax_node_wrapper.h
@@ -39,8 +39,10 @@ class TestAXNodeWrapper : public AXPlatformNodeDelegate {
gfx::NativeViewAccessible GetFocus() override;
gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
void DoDefaultAction() override;
- bool SetStringValue(const base::string16& new_value) override;
+ bool SetStringValue(const base::string16& new_value,
+ bool clear_first) override;
bool CanSetStringValue() override;
+ bool SetFocused(bool focused) override;
private:
TestAXNodeWrapper(AXTree* tree, AXNode* node);