summaryrefslogtreecommitdiff
path: root/chromium/content/browser/accessibility
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-29 10:46:47 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-11-02 12:02:10 +0000
commit99677208ff3b216fdfec551fbe548da5520cd6fb (patch)
tree476a4865c10320249360e859d8fdd3e01833b03a /chromium/content/browser/accessibility
parentc30a6232df03e1efbd9f3b226777b07e087a1122 (diff)
downloadqtwebengine-chromium-99677208ff3b216fdfec551fbe548da5520cd6fb.tar.gz
BASELINE: Update Chromium to 86.0.4240.124
Change-Id: Ide0ff151e94cd665ae6521a446995d34a9d1d644 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/content/browser/accessibility')
-rw-r--r--chromium/content/browser/accessibility/accessibility_action_browsertest.cc45
-rw-r--r--chromium/content/browser/accessibility/accessibility_auralinux_browsertest.cc2
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder.cc2
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder.h3
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc4
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder_win.cc26
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc50
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc7
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_base.cc121
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_base.h31
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_base_unittest.cc40
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc9
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_blink.h1
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm321
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_mac_browsertest.mm56
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc4
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.h1
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_utils_mac.h97
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_utils_mac.mm298
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc51
-rw-r--r--chromium/content/browser/accessibility/accessibility_win_browsertest.cc280
-rw-r--r--chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc10
-rw-r--r--chromium/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc80
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.cc59
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.h13
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.cc76
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.h10
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc108
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.h18
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.mm35
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm37
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_com_win.cc11
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.cc12
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.h4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.cc4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc66
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.h8
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm97
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc18
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.cc239
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.h44
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_position.cc4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.cc11
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.h9
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl_android.cc2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_unittest.cc14
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc92
-rw-r--r--chromium/content/browser/accessibility/captioning_controller.cc8
-rw-r--r--chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc151
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc18
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc94
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc103
-rw-r--r--chromium/content/browser/accessibility/hit_testing_browsertest.cc15
-rw-r--r--chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc1
-rw-r--r--chromium/content/browser/accessibility/web_contents_accessibility_android.cc34
58 files changed, 2057 insertions, 903 deletions
diff --git a/chromium/content/browser/accessibility/accessibility_action_browsertest.cc b/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
index efe6f4683be..5600f91336e 100644
--- a/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_action_browsertest.cc
@@ -19,6 +19,7 @@
#include "content/shell/browser/shell.h"
#include "net/base/data_url.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/accessibility_switches.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/gfx/codec/png_codec.h"
#include "url/gurl.h"
@@ -877,4 +878,48 @@ IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest, ClickSVG) {
#endif // !defined(OS_ANDROID)
}
+// This test ony makes sense on platforms where the popup menu is implemented
+// internally as an HTML page in a popup, not where it's a native popup.
+#if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(USE_ATK)
+IN_PROC_BROWSER_TEST_F(AccessibilityActionBrowserTest,
+ OpenSelectPopupWithNoAXMenuList) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ ::switches::kDisableAXMenuList);
+
+ LoadInitialAccessibilityTreeFromHtml(R"HTML(
+ <head><title>No AXMenuList</title></head>
+ <body>
+ <select>
+ <option selected>One</option>
+ <option>Two</option>
+ <option>Three</option>
+ </select>
+ </body>
+ )HTML");
+
+ BrowserAccessibility* target = FindNode(ax::mojom::Role::kPopUpButton, "One");
+ ASSERT_NE(nullptr, target);
+
+ EXPECT_EQ(0U, target->PlatformChildCount());
+ EXPECT_EQ(nullptr, FindNode(ax::mojom::Role::kListBox, ""));
+
+ // Call DoDefaultAction.
+ AccessibilityNotificationWaiter waiter2(
+ shell()->web_contents(), ui::kAXModeComplete, ax::mojom::Event::kClicked);
+ GetManager()->DoDefaultAction(*target);
+ waiter2.WaitForNotification();
+
+ WaitForAccessibilityTreeToContainNodeWithName(shell()->web_contents(),
+ "Three");
+
+ ASSERT_EQ(1U, target->PlatformChildCount());
+ BrowserAccessibility* popup_web_area = target->PlatformGetChild(0);
+ EXPECT_EQ(ax::mojom::Role::kRootWebArea, popup_web_area->GetRole());
+
+ BrowserAccessibility* listbox = FindNode(ax::mojom::Role::kListBox, "");
+ ASSERT_TRUE(listbox);
+ EXPECT_EQ(3U, listbox->PlatformChildCount());
+}
+#endif // defined(OS_WIN) || defined(OS_CHROMEOS) || defined(USE_ATK)
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_auralinux_browsertest.cc b/chromium/content/browser/accessibility/accessibility_auralinux_browsertest.cc
index 71a757df88e..657d4b4f218 100644
--- a/chromium/content/browser/accessibility/accessibility_auralinux_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_auralinux_browsertest.cc
@@ -1123,7 +1123,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityAuraLinuxBrowserTest,
}
#endif // defined(ATK_CHECK_VERSION) && ATK_CHECK_VERSION(2, 32, 0)
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
// Flaky on crbug.com/1026149
#define MAYBE_TestSetSelection DISABLED_TestSetSelection
#else
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder.cc b/chromium/content/browser/accessibility/accessibility_event_recorder.cc
index 555251c9218..1a636008c9e 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder.cc
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder.cc
@@ -16,7 +16,7 @@ AccessibilityEventRecorder::AccessibilityEventRecorder(
AccessibilityEventRecorder::~AccessibilityEventRecorder() = default;
-#if !defined(OS_WIN) && !defined(OS_MACOSX) && !BUILDFLAG(USE_ATK)
+#if !defined(OS_WIN) && !defined(OS_MAC) && !BUILDFLAG(USE_ATK)
// static
std::unique_ptr<AccessibilityEventRecorder> AccessibilityEventRecorder::Create(
BrowserAccessibilityManager* manager,
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder.h b/chromium/content/browser/accessibility/accessibility_event_recorder.h
index 6a9adf70381..dfed6174acf 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder.h
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder.h
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/macros.h"
#include "base/process/process_handle.h"
@@ -68,6 +69,8 @@ class CONTENT_EXPORT AccessibilityEventRecorder {
callback_ = std::move(callback);
}
+ void StopListeningToEvents() { callback_ = base::NullCallback(); }
+
// Called to ensure the event recorder has finished recording async events.
virtual void FlushAsyncEvents() {}
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc b/chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
index ceca7d9f66b..bfe6f5a3c73 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
@@ -166,7 +166,10 @@ void AccessibilityEventRecorderAuraLinux::AddATKEventListeners() {
AddATKEventListener("ATK:AtkText:text-remove");
AddATKEventListener("ATK:AtkText:text-selection-changed");
AddATKEventListener("ATK:AtkText:text-caret-moved");
+ AddATKEventListener("ATK:AtkText:text-attributes-changed");
AddATKEventListener("ATK:AtkSelection:selection-changed");
+ AddATKEventListener("ATK:AtkTable:column-reordered");
+ AddATKEventListener("ATK:AtkTable:row-reordered");
}
void AccessibilityEventRecorderAuraLinux::RemoveATKEventListeners() {
@@ -326,6 +329,7 @@ const char* const kEventNames[] = {
"object:row-reordered",
"object:selection-changed",
"object:state-changed",
+ "object:text-attributes-changed",
"object:text-caret-moved",
"object:text-changed",
"object:text-selection-changed",
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc b/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
index 73c7d6214ca..7d8ee27f05b 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
@@ -41,7 +41,7 @@ std::string RoleVariantToString(const base::win::ScopedVariant& role) {
HRESULT QueryIAccessible2(IAccessible* accessible, IAccessible2** accessible2) {
Microsoft::WRL::ComPtr<IServiceProvider> service_provider;
- HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+ HRESULT hr = accessible->QueryInterface(IID_PPV_ARGS(&service_provider));
return SUCCEEDED(hr)
? service_provider->QueryService(IID_IAccessible2, accessible2)
: hr;
@@ -50,7 +50,7 @@ HRESULT QueryIAccessible2(IAccessible* accessible, IAccessible2** accessible2) {
HRESULT QueryIAccessibleText(IAccessible* accessible,
IAccessibleText** accessible_text) {
Microsoft::WRL::ComPtr<IServiceProvider> service_provider;
- HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+ HRESULT hr = accessible->QueryInterface(IID_PPV_ARGS(&service_provider));
return SUCCEEDED(hr) ? service_provider->QueryService(IID_IAccessibleText,
accessible_text)
: hr;
@@ -199,8 +199,7 @@ void AccessibilityEventRecorderWin::OnWinEventHook(HWINEVENTHOOK handle,
DWORD event_time) {
Microsoft::WRL::ComPtr<IAccessible> browser_accessible;
HRESULT hr = AccessibleObjectFromWindowWrapper(
- hwnd, obj_id, IID_IAccessible,
- reinterpret_cast<void**>(browser_accessible.GetAddressOf()));
+ hwnd, obj_id, IID_PPV_ARGS(&browser_accessible));
if (FAILED(hr)) {
// Note: our event hook will pick up some superfluous events we
// don't care about, so it's safe to just ignore these failures.
@@ -211,8 +210,7 @@ void AccessibilityEventRecorderWin::OnWinEventHook(HWINEVENTHOOK handle,
base::win::ScopedVariant childid_variant(child_id);
Microsoft::WRL::ComPtr<IDispatch> dispatch;
- hr = browser_accessible->get_accChild(childid_variant,
- dispatch.GetAddressOf());
+ hr = browser_accessible->get_accChild(childid_variant, &dispatch);
if (hr != S_OK || !dispatch) {
VLOG(1) << "Ignoring result " << hr << " and result " << dispatch.Get()
<< " from get_accChild";
@@ -220,7 +218,7 @@ void AccessibilityEventRecorderWin::OnWinEventHook(HWINEVENTHOOK handle,
}
Microsoft::WRL::ComPtr<IAccessible> iaccessible;
- hr = dispatch.CopyTo(iaccessible.GetAddressOf());
+ hr = dispatch.As(&iaccessible);
if (FAILED(hr)) {
VLOG(1) << "Ignoring result " << hr << " from QueryInterface";
return;
@@ -257,13 +255,13 @@ void AccessibilityEventRecorderWin::OnWinEventHook(HWINEVENTHOOK handle,
return;
Microsoft::WRL::ComPtr<IServiceProvider> service_provider;
- hr = iaccessible->QueryInterface(service_provider.GetAddressOf());
+ hr = iaccessible->QueryInterface(IID_PPV_ARGS(&service_provider));
if (FAILED(hr))
return;
Microsoft::WRL::ComPtr<IAccessible> content_document;
hr = service_provider->QueryService(GUID_IAccessibleContentDocument,
- content_document.GetAddressOf());
+ IID_PPV_ARGS(&content_document));
if (FAILED(hr))
return;
}
@@ -291,7 +289,7 @@ void AccessibilityEventRecorderWin::OnWinEventHook(HWINEVENTHOOK handle,
AccessibleStates ia2_state = 0;
Microsoft::WRL::ComPtr<IAccessible2> iaccessible2;
- hr = QueryIAccessible2(iaccessible.Get(), iaccessible2.GetAddressOf());
+ hr = QueryIAccessible2(iaccessible.Get(), &iaccessible2);
bool has_ia2 = SUCCEEDED(hr) && iaccessible2;
base::string16 html_tag;
@@ -306,13 +304,13 @@ void AccessibilityEventRecorderWin::OnWinEventHook(HWINEVENTHOOK handle,
base::string16(attributes_bstr.Get(), attributes_bstr.Length()),
base::string16(1, ';'), base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
for (base::string16& attr : ia2_attributes) {
- if (base::StringPiece16(attr).starts_with(L"class:"))
+ if (base::StartsWith(attr, L"class:"))
obj_class = attr.substr(6); // HTML or view class
- if (base::StringPiece16(attr).starts_with(L"id:")) {
+ if (base::StartsWith(attr, L"id:")) {
html_id = base::string16(L"#");
html_id += attr.substr(3);
}
- if (base::StringPiece16(attr).starts_with(L"tag:")) {
+ if (base::StartsWith(attr, L"tag:")) {
html_tag = attr.substr(4);
}
}
@@ -367,7 +365,7 @@ void AccessibilityEventRecorderWin::OnWinEventHook(HWINEVENTHOOK handle,
// For TEXT_REMOVED and TEXT_INSERTED events, query the text that was
// inserted or removed and include that in the log.
Microsoft::WRL::ComPtr<IAccessibleText> accessible_text;
- hr = QueryIAccessibleText(iaccessible.Get(), accessible_text.GetAddressOf());
+ hr = QueryIAccessibleText(iaccessible.Get(), &accessible_text);
if (SUCCEEDED(hr)) {
if (event == IA2_EVENT_TEXT_REMOVED) {
IA2TextSegment old_text;
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
index afeb78a3c21..67b75709615 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
@@ -22,24 +22,39 @@ using base::StringPrintf;
namespace content {
namespace {
-
+// clang-format off
const char* const BOOL_ATTRIBUTES[] = {
- "checkable", "checked",
- "clickable", "collection",
- "collection_item", "content_invalid",
- "disabled", "dismissable",
- "editable_text", "focusable",
- "focused", "has_character_locations",
- "has_image", "has_non_empty_value",
- "heading", "hierarchical",
- "invisible", "link",
- "multiline", "password",
- "range", "scrollable",
- "selected", "interesting"};
+ "checkable",
+ "checked",
+ "clickable",
+ "collection",
+ "collection_item",
+ "content_invalid",
+ "disabled",
+ "dismissable",
+ "editable_text",
+ "focusable",
+ "focused",
+ "has_character_locations",
+ "has_image",
+ "has_non_empty_value",
+ "heading",
+ "hierarchical",
+ "invisible",
+ "link",
+ "multiline",
+ "multiselectable",
+ "password",
+ "range",
+ "scrollable",
+ "selected",
+ "interesting"
+};
const char* const STRING_ATTRIBUTES[] = {
"name",
"hint",
+ "state_description",
};
const char* const INT_ATTRIBUTES[] = {
@@ -59,7 +74,7 @@ const char* const INT_ATTRIBUTES[] = {
"text_change_added_count",
"text_change_removed_count",
};
-
+// clang-format on
} // namespace
class AccessibilityTreeFormatterAndroid
@@ -89,6 +104,7 @@ class AccessibilityTreeFormatterAndroid
const std::string GetAllowString() override;
const std::string GetDenyString() override;
const std::string GetDenyNodeString() override;
+ const std::string GetRunUntilEventString() override;
void RecursiveBuildAccessibilityTree(const BrowserAccessibility& node,
base::DictionaryValue* dict) const;
@@ -210,6 +226,7 @@ void AccessibilityTreeFormatterAndroid::AddProperties(
dict->SetBoolean("invisible", !android_node->IsVisibleToUser());
dict->SetBoolean("link", android_node->IsLink());
dict->SetBoolean("multiline", android_node->IsMultiLine());
+ dict->SetBoolean("multiselectable", android_node->IsMultiselectable());
dict->SetBoolean("range", android_node->IsRangeType());
dict->SetBoolean("password", android_node->IsPasswordField());
dict->SetBoolean("scrollable", android_node->IsScrollable());
@@ -220,6 +237,7 @@ void AccessibilityTreeFormatterAndroid::AddProperties(
dict->SetString("name", android_node->GetInnerText());
dict->SetString("hint", android_node->GetHint());
dict->SetString("role_description", android_node->GetRoleDescription());
+ dict->SetString("state_description", android_node->GetStateDescription());
// Int attributes.
dict->SetInteger("item_index", android_node->GetItemIndex());
@@ -324,4 +342,8 @@ const std::string AccessibilityTreeFormatterAndroid::GetDenyNodeString() {
return "@ANDROID-DENY-NODE:";
}
+const std::string AccessibilityTreeFormatterAndroid::GetRunUntilEventString() {
+ return "@ANDROID-RUN-UNTIL-EVENT:";
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
index b09bf27719f..91f6ff6b7d9 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
@@ -36,6 +36,7 @@ class AccessibilityTreeFormatterAuraLinux
const std::string GetAllowString() override;
const std::string GetDenyString() override;
const std::string GetDenyNodeString() override;
+ const std::string GetRunUntilEventString() override;
base::string16 ProcessTreeForOutput(
const base::DictionaryValue& node,
@@ -603,6 +604,7 @@ const char* const ATK_OBJECT_ATTRIBUTES[] = {
"src",
"table-cell-index",
"tag",
+ "text-align",
"text-input-type",
"valuemin",
"valuemax",
@@ -746,4 +748,9 @@ const std::string AccessibilityTreeFormatterAuraLinux::GetDenyNodeString() {
return "@AURALINUX-DENY-NODE:";
}
+const std::string
+AccessibilityTreeFormatterAuraLinux::GetRunUntilEventString() {
+ return "@AURALINUX-RUN-UNTIL-EVENT:";
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_base.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_base.cc
index 706b036cab9..7b1f9188212 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_base.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_base.cc
@@ -43,18 +43,23 @@ PropertyNode PropertyNode::FromPropertyFilter(
// Property invocation: property_str expected format is
// prop_name or prop_name(arg1, ... argN).
PropertyNode root;
- Parse(&root, filter.property_str.begin(), filter.property_str.end());
+ const std::string& property_str = filter.property_str;
+ Parse(&root, property_str.begin(), property_str.end());
PropertyNode* node = &root.parameters[0];
- node->original_property = filter.property_str;
+
+ // Expel a trailing wildcard if any.
+ node->original_property =
+ property_str.substr(0, property_str.find_last_of('*'));
// Line indexes filter: filter_str expected format is
// :line_num_1, ... :line_num_N, a comma separated list of line indexes
// the property should be queried for. For example, ":1,:5,:7" indicates that
// the property should called for objects placed on 1, 5 and 7 lines only.
- if (!filter.filter_str.empty()) {
+ const std::string& filter_str = filter.filter_str;
+ if (!filter_str.empty()) {
node->line_indexes =
- base::SplitString(filter.filter_str, base::string16(1, ','),
+ base::SplitString(filter_str, std::string(1, ','),
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
}
@@ -83,12 +88,19 @@ PropertyNode::operator bool() const {
return !name_or_value.empty();
}
+bool PropertyNode::IsMatching(const std::string& pattern) const {
+ // Looking for exact property match. Expel a trailing whildcard from
+ // the property filter to handle filters like AXRole*.
+ return name_or_value.compare(0, name_or_value.find_last_of('*'), pattern) ==
+ 0;
+}
+
bool PropertyNode::IsArray() const {
- return name_or_value == base::ASCIIToUTF16("[]");
+ return name_or_value == "[]";
}
bool PropertyNode::IsDict() const {
- return name_or_value == base::ASCIIToUTF16("{}");
+ return name_or_value == "{}";
}
base::Optional<int> PropertyNode::AsInt() const {
@@ -99,9 +111,19 @@ base::Optional<int> PropertyNode::AsInt() const {
return value;
}
-base::Optional<base::string16> PropertyNode::FindKey(const char* refkey) const {
+const PropertyNode* PropertyNode::FindKey(const char* refkey) const {
for (const auto& param : parameters) {
- if (param.key == base::ASCIIToUTF16(refkey)) {
+ if (param.key == refkey) {
+ return &param;
+ }
+ }
+ return nullptr;
+}
+
+base::Optional<std::string> PropertyNode::FindStringKey(
+ const char* refkey) const {
+ for (const auto& param : parameters) {
+ if (param.key == refkey) {
return param.name_or_value;
}
}
@@ -110,7 +132,7 @@ base::Optional<base::string16> PropertyNode::FindKey(const char* refkey) const {
base::Optional<int> PropertyNode::FindIntKey(const char* refkey) const {
for (const auto& param : parameters) {
- if (param.key == base::ASCIIToUTF16(refkey)) {
+ if (param.key == refkey) {
return param.AsInt();
}
}
@@ -123,16 +145,16 @@ std::string PropertyNode::ToString() const {
if (!out.empty()) {
out += ',';
}
- out += base::UTF16ToUTF8(index);
+ out += index;
}
if (!out.empty()) {
out += ';';
}
if (!key.empty()) {
- out += base::UTF16ToUTF8(key) + ": ";
+ out += key + ": ";
}
- out += base::UTF16ToUTF8(name_or_value);
+ out += name_or_value;
if (parameters.size()) {
out += '(';
for (size_t i = 0; i < parameters.size(); i++) {
@@ -149,7 +171,7 @@ std::string PropertyNode::ToString() const {
// private
PropertyNode::PropertyNode(PropertyNode::iterator key_begin,
PropertyNode::iterator key_end,
- const base::string16& name_or_value)
+ const std::string& name_or_value)
: key(key_begin, key_end), name_or_value(name_or_value) {}
PropertyNode::PropertyNode(PropertyNode::iterator begin,
PropertyNode::iterator end)
@@ -179,8 +201,7 @@ PropertyNode::iterator PropertyNode::Parse(PropertyNode* node,
// Subnode begins: a special case for arrays, which have [arg1, ..., argN]
// form.
if (*iter == '[') {
- node->parameters.push_back(
- PropertyNode(key_begin, key_end, base::UTF8ToUTF16("[]")));
+ node->parameters.push_back(PropertyNode(key_begin, key_end, "[]"));
key_begin = key_end = end;
begin = iter = Parse(&node->parameters.back(), ++iter, end);
continue;
@@ -189,8 +210,7 @@ PropertyNode::iterator PropertyNode::Parse(PropertyNode* node,
// Subnode begins: a special case for dictionaries of {key1: value1, ...,
// key2: value2} form.
if (*iter == '{') {
- node->parameters.push_back(
- PropertyNode(key_begin, key_end, base::UTF8ToUTF16("{}")));
+ node->parameters.push_back(PropertyNode(key_begin, key_end, "{}"));
key_begin = key_end = end;
begin = iter = Parse(&node->parameters.back(), ++iter, end);
continue;
@@ -249,7 +269,7 @@ AccessibilityTreeFormatter::PropertyFilter::PropertyFilter(
const PropertyFilter&) = default;
AccessibilityTreeFormatter::PropertyFilter::PropertyFilter(
- const base::string16& str,
+ const std::string& str,
Type type)
: match_str(str), type(type) {
size_t index = str.find(';');
@@ -291,17 +311,26 @@ base::string16 AccessibilityTreeFormatterBase::DumpAccessibilityTreeFromManager(
bool AccessibilityTreeFormatter::MatchesPropertyFilters(
const std::vector<PropertyFilter>& property_filters,
- const base::string16& text,
+ const std::string& text,
bool default_result) {
bool allow = default_result;
for (const auto& filter : property_filters) {
- if (base::MatchPattern(text, filter.match_str)) {
+ // Either
+ // 1) the line matches a filter pattern, for example, AXSubrole=* filter
+ // will match AXSubrole=AXTerm line or
+ // 2) a property on the line is exactly equal to the filter pattern, for
+ // example, AXSubrole filter will match AXSubrole=AXTerm line.
+ if (base::MatchPattern(text, filter.match_str) ||
+ (filter.match_str.length() > 0 &&
+ filter.match_str.find('=') == std::string::npos &&
+ filter.match_str[filter.match_str.length() - 1] != '*' &&
+ base::MatchPattern(text, filter.match_str + "=*"))) {
switch (filter.type) {
case PropertyFilter::ALLOW_EMPTY:
allow = true;
break;
case PropertyFilter::ALLOW:
- allow = (!base::MatchPattern(text, base::UTF8ToUTF16("*=''")));
+ allow = (!base::MatchPattern(text, "*=''"));
break;
case PropertyFilter::DENY:
allow = false;
@@ -419,14 +448,14 @@ AccessibilityTreeFormatterBase::GetVersionSpecificExpectedFileSuffix() {
return FILE_PATH_LITERAL("");
}
-PropertyNode AccessibilityTreeFormatterBase::GetMatchingPropertyNode(
- const base::string16& line_index,
- const base::string16& property_name) {
- // Find the first allow-filter matching the line index and the property name.
+std::vector<PropertyNode>
+AccessibilityTreeFormatterBase::PropertyFilterNodesFor(
+ const std::string& line_index) const {
+ std::vector<PropertyNode> list;
for (const auto& filter : property_filters_) {
PropertyNode property_node = PropertyNode::FromPropertyFilter(filter);
- // Skip if the line index filter doesn't matched (if specified).
+ // Filter out if doesn't match line index (if specified).
if (!property_node.line_indexes.empty() &&
std::find(property_node.line_indexes.begin(),
property_node.line_indexes.end(),
@@ -434,27 +463,31 @@ PropertyNode AccessibilityTreeFormatterBase::GetMatchingPropertyNode(
continue;
}
- // The filter should be either an exact property match or a wildcard
- // matching to support filter collections like AXRole* which matches
- // AXRoleDescription.
- if (property_name == property_node.name_or_value ||
- base::MatchPattern(property_name, property_node.name_or_value)) {
- switch (filter.type) {
- case PropertyFilter::ALLOW_EMPTY:
- case PropertyFilter::ALLOW:
- return property_node;
- case PropertyFilter::DENY:
- break;
- default:
- break;
- }
+ switch (filter.type) {
+ case PropertyFilter::ALLOW_EMPTY:
+ case PropertyFilter::ALLOW:
+ list.push_back(std::move(property_node));
+ break;
+ case PropertyFilter::DENY:
+ break;
+ default:
+ break;
}
}
- return PropertyNode();
+ return list;
+}
+
+bool AccessibilityTreeFormatterBase::HasMatchAllPropertyFilter() const {
+ for (const auto& filter : property_filters_) {
+ if (filter.type == PropertyFilter::ALLOW && filter.match_str == "*") {
+ return true;
+ }
+ }
+ return false;
}
bool AccessibilityTreeFormatterBase::MatchesPropertyFilters(
- const base::string16& text,
+ const std::string& text,
bool default_result) const {
return AccessibilityTreeFormatter::MatchesPropertyFilters(
property_filters_, text, default_result);
@@ -507,7 +540,7 @@ bool AccessibilityTreeFormatterBase::WriteAttribute(bool include_by_default,
base::string16* line) {
if (attr.empty())
return false;
- if (!MatchesPropertyFilters(attr, include_by_default))
+ if (!MatchesPropertyFilters(base::UTF16ToUTF8(attr), include_by_default))
return false;
if (!line->empty())
*line += base::ASCIIToUTF16(" ");
@@ -519,7 +552,7 @@ void AccessibilityTreeFormatterBase::AddPropertyFilter(
std::vector<PropertyFilter>* property_filters,
std::string filter,
PropertyFilter::Type type) {
- property_filters->push_back(PropertyFilter(base::ASCIIToUTF16(filter), type));
+ property_filters->push_back(PropertyFilter(filter, type));
}
void AccessibilityTreeFormatterBase::AddDefaultFilters(
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_base.h b/chromium/content/browser/accessibility/accessibility_tree_formatter_base.h
index 13ebfad47d3..20f52d52c39 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_base.h
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_base.h
@@ -48,10 +48,10 @@ class CONTENT_EXPORT PropertyNode final {
explicit operator bool() const;
// Key name in case of { key: value } dictionary.
- base::string16 key;
+ std::string key;
// Value or a property name, for example 3 or AXLineForIndex
- base::string16 name_or_value;
+ std::string name_or_value;
// Parameters if it's a property, for example, it is a vector of a single
// value 3 in case of AXLineForIndex(3)
@@ -59,27 +59,30 @@ class CONTENT_EXPORT PropertyNode final {
// Used to store the origianl unparsed property including invocation
// parameters if any.
- base::string16 original_property;
+ std::string original_property;
// The list of line indexes of accessible objects the property is allowed to
// be called for.
- std::vector<base::string16> line_indexes;
+ std::vector<std::string> line_indexes;
+
+ bool IsMatching(const std::string& pattern) const;
// Argument conversion methods.
bool IsArray() const;
bool IsDict() const;
base::Optional<int> AsInt() const;
- base::Optional<base::string16> FindKey(const char* refkey) const;
+ const PropertyNode* FindKey(const char* refkey) const;
+ base::Optional<std::string> FindStringKey(const char* refkey) const;
base::Optional<int> FindIntKey(const char* key) const;
std::string ToString() const;
private:
- using iterator = base::string16::const_iterator;
+ using iterator = std::string::const_iterator;
explicit PropertyNode(iterator key_begin,
iterator key_end,
- const base::string16&);
+ const std::string&);
PropertyNode(iterator begin, iterator end);
PropertyNode(iterator key_begin,
iterator key_end,
@@ -150,11 +153,13 @@ class CONTENT_EXPORT AccessibilityTreeFormatterBase
// Overridden by platform subclasses.
//
- // Returns a property node struct built for a matching property filter,
- // which includes a property name and invocation parameters if any.
- // If no matching property filter, then empty property node is returned.
- PropertyNode GetMatchingPropertyNode(const base::string16& line_index,
- const base::string16& property_name);
+ // Returns property nodes complying to the line index filter for all
+ // allow/allow_empty property filters.
+ std::vector<PropertyNode> PropertyFilterNodesFor(
+ const std::string& line_index) const;
+
+ // Return true if match-all filter is present.
+ bool HasMatchAllPropertyFilter() const;
// Process accessibility tree with filters for output.
// Given a dictionary that contains a platform-specific dictionary
@@ -205,7 +210,7 @@ class CONTENT_EXPORT AccessibilityTreeFormatterBase
base::string16* contents,
int depth = 0);
- bool MatchesPropertyFilters(const base::string16& text,
+ bool MatchesPropertyFilters(const std::string& text,
bool default_result) const;
bool MatchesNodeFilters(const base::DictionaryValue& dict) const;
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_base_unittest.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_base_unittest.cc
index a2d5fdfb547..fb5712420f4 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_base_unittest.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_base_unittest.cc
@@ -32,8 +32,7 @@ class AccessibilityTreeFormatterBaseTest : public testing::Test {
PropertyNode Parse(const char* input) {
AccessibilityTreeFormatter::PropertyFilter filter(
- base::UTF8ToUTF16(input),
- AccessibilityTreeFormatter::PropertyFilter::ALLOW);
+ input, AccessibilityTreeFormatter::PropertyFilter::ALLOW);
return PropertyNode::FromPropertyFilter(filter);
}
@@ -70,6 +69,10 @@ TEST_F(AccessibilityTreeFormatterBaseTest, ParseProperty) {
ParseAndCheck("Text({dict: [1, 2]})", "Text({}(dict: [](1, 2)))");
ParseAndCheck("Text({dict: ValueFor(1)})", "Text({}(dict: ValueFor(1)))");
+ // Nested arguments
+ ParseAndCheck("AXIndexForTextMarker(AXTextMarkerForIndex(0))",
+ "AXIndexForTextMarker(AXTextMarkerForIndex(0))");
+
// Line indexes filter.
ParseAndCheck(":3,:5;AXDOMClassList", ":3,:5;AXDOMClassList");
@@ -84,17 +87,38 @@ TEST_F(AccessibilityTreeFormatterBaseTest, ParseProperty) {
EXPECT_EQ(GetArgumentNode("ChildAt(3)").IsDict(), false);
EXPECT_EQ(GetArgumentNode("ChildAt(3)").IsArray(), false);
EXPECT_EQ(GetArgumentNode("ChildAt(3)").AsInt(), 3);
- EXPECT_EQ(GetArgumentNode("Text({start: :1, dir: forward})").FindKey("start"),
- base::ASCIIToUTF16(":1"));
- EXPECT_EQ(GetArgumentNode("Text({start: :1, dir: forward})").FindKey("dir"),
- base::ASCIIToUTF16("forward"));
+
+ // Dict: FindStringKey
EXPECT_EQ(
- GetArgumentNode("Text({start: :1, dir: forward})").FindKey("notexists"),
- base::nullopt);
+ GetArgumentNode("Text({start: :1, dir: forward})").FindStringKey("start"),
+ ":1");
+ EXPECT_EQ(
+ GetArgumentNode("Text({start: :1, dir: forward})").FindStringKey("dir"),
+ "forward");
+ EXPECT_EQ(GetArgumentNode("Text({start: :1, dir: forward})")
+ .FindStringKey("notexists"),
+ base::nullopt);
+
+ // Dict: FindIntKey
EXPECT_EQ(GetArgumentNode("Text({loc: 3, len: 2})").FindIntKey("loc"), 3);
EXPECT_EQ(GetArgumentNode("Text({loc: 3, len: 2})").FindIntKey("len"), 2);
EXPECT_EQ(GetArgumentNode("Text({loc: 3, len: 2})").FindIntKey("notexists"),
base::nullopt);
+
+ // Dict: FindKey
+ EXPECT_EQ(GetArgumentNode("Text({anchor: {:1, 0, up}})")
+ .FindKey("anchor")
+ ->ToString(),
+ "anchor: {}(:1, 0, up)");
+
+ EXPECT_EQ(GetArgumentNode("Text({anchor: {:1, 0, up}})").FindKey("focus"),
+ nullptr);
+
+ EXPECT_EQ(GetArgumentNode("AXStringForTextMarkerRange({anchor: {:2, 1, "
+ "down}, focus: {:2, 2, down}})")
+ .FindKey("anchor")
+ ->ToString(),
+ "anchor: {}(:2, 1, down)");
}
} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
index abc989bacd5..2f5be04faf4 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -89,12 +89,14 @@ std::string IntAttrToString(const BrowserAccessibility& node,
return ui::ToString(static_cast<ax::mojom::Restriction>(value));
case ax::mojom::IntAttribute::kSortDirection:
return ui::ToString(static_cast<ax::mojom::SortDirection>(value));
+ case ax::mojom::IntAttribute::kTextAlign:
+ return ui::ToString(static_cast<ax::mojom::TextAlign>(value));
case ax::mojom::IntAttribute::kTextOverlineStyle:
case ax::mojom::IntAttribute::kTextStrikethroughStyle:
case ax::mojom::IntAttribute::kTextUnderlineStyle:
return ui::ToString(static_cast<ax::mojom::TextDecorationStyle>(value));
case ax::mojom::IntAttribute::kTextDirection:
- return ui::ToString(static_cast<ax::mojom::TextDirection>(value));
+ return ui::ToString(static_cast<ax::mojom::WritingDirection>(value));
case ax::mojom::IntAttribute::kTextPosition:
return ui::ToString(static_cast<ax::mojom::TextPosition>(value));
case ax::mojom::IntAttribute::kImageAnnotationStatus:
@@ -164,7 +166,6 @@ void AccessibilityTreeFormatterBlink::AddDefaultFilters(
// Too flaky: hovered, offscreen
// States
AddPropertyFilter(property_filters, "collapsed");
- AddPropertyFilter(property_filters, "haspopup");
AddPropertyFilter(property_filters, "invisible");
AddPropertyFilter(property_filters, "multiline");
AddPropertyFilter(property_filters, "protected");
@@ -631,4 +632,8 @@ const std::string AccessibilityTreeFormatterBlink::GetDenyNodeString() {
return "@BLINK-DENY-NODE:";
}
+const std::string AccessibilityTreeFormatterBlink::GetRunUntilEventString() {
+ return "@BLINK-RUN-UNTIL-EVENT:";
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.h b/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.h
index 29f82dfd6af..440ced2e774 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.h
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.h
@@ -42,6 +42,7 @@ class CONTENT_EXPORT AccessibilityTreeFormatterBlink
const std::string GetAllowString() override;
const std::string GetDenyString() override;
const std::string GetDenyNodeString() override;
+ const std::string GetRunUntilEventString() override;
void RecursiveBuildAccessibilityTree(const BrowserAccessibility& node,
base::DictionaryValue* dict) const;
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index bc23c9cea29..f60a93dd95c 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -4,17 +4,14 @@
#include "content/browser/accessibility/accessibility_tree_formatter_base.h"
-#import <Cocoa/Cocoa.h>
-
#include "base/files/file_path.h"
-#include "base/json/json_writer.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/browser/accessibility/accessibility_tree_formatter_blink.h"
-#include "content/browser/accessibility/browser_accessibility_cocoa.h"
+#include "content/browser/accessibility/accessibility_tree_formatter_utils_mac.h"
#include "content/browser/accessibility/browser_accessibility_mac.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
@@ -26,7 +23,11 @@
using base::StringPrintf;
using base::SysNSStringToUTF8;
using base::SysNSStringToUTF16;
+using base::SysUTF16ToNSString;
using std::string;
+using content::a11y::LineIndexesMap;
+using content::a11y::OptionalNSObject;
+using content::a11y::AttributeInvoker;
namespace content {
@@ -46,34 +47,6 @@ const char kConstValuePrefix[] = "_const_";
const char kNULLValue[] = "_const_NULL";
const char kFailedToParseArgsError[] = "_const_ERROR:FAILED_TO_PARSE_ARGS";
-#define INT_FAIL(propnode, msg) \
- LOG(ERROR) << "Failed to parse " << propnode.original_property \
- << " to Int: " << msg; \
- return nil;
-
-#define INTARRAY_FAIL(propnode, msg) \
- LOG(ERROR) << "Failed to parse " << propnode.original_property \
- << " to IntArray: " << msg; \
- return nil;
-
-#define NSRANGE_FAIL(propnode, msg) \
- LOG(ERROR) << "Failed to parse " << propnode.original_property \
- << " to NSRange: " << msg; \
- return nil;
-
-#define UIELEMENT_FAIL(propnode, msg) \
- LOG(ERROR) << "Failed to parse " << propnode.original_property \
- << " to UIElement: " << msg; \
- return nil;
-
-#define TEXTMARKER_FAIL(propnode, msg) \
- LOG(ERROR) << "Failed to parse " << propnode.original_property \
- << " to AXTextMarker: " << msg \
- << ". Expected format: {anchor, offset, affinity}, where anchor " \
- "is :line_num, offset is integer, affinity is either down, " \
- "up or none"; \
- return nil;
-
} // namespace
class AccessibilityTreeFormatterMac : public AccessibilityTreeFormatterBase {
@@ -95,57 +68,26 @@ class AccessibilityTreeFormatterMac : public AccessibilityTreeFormatterBase {
const base::StringPiece& pattern) override;
private:
- using LineIndexesMap =
- std::map<const gfx::NativeViewAccessible, base::string16>;
-
void RecursiveBuildAccessibilityTree(const BrowserAccessibilityCocoa* node,
const LineIndexesMap& line_indexes_map,
base::DictionaryValue* dict);
- void RecursiveBuildLineIndexesMap(const BrowserAccessibilityCocoa* node,
- LineIndexesMap* line_indexes_map,
- int* counter);
base::FilePath::StringType GetExpectedFileSuffix() override;
const std::string GetAllowEmptyString() override;
const std::string GetAllowString() override;
const std::string GetDenyString() override;
const std::string GetDenyNodeString() override;
+ const std::string GetRunUntilEventString() override;
void AddProperties(const BrowserAccessibilityCocoa* node,
const LineIndexesMap& line_indexes_map,
base::Value* dict);
- // Helper class used to compute a parameter for a parameterized attribute
- // call. Can be either id or error. Similar to base::Optional, but allows nil
- // id as a valid value.
- class IdOrError {
- public:
- IdOrError() : value(nil), error(false) {}
-
- IdOrError& operator=(id other_value) {
- error = !other_value;
- value = other_value;
- return *this;
- }
-
- bool IsError() const { return error; }
- bool IsNotNil() const { return !!value; }
- constexpr const id& operator*() const& { return value; }
-
- private:
- id value;
- bool error;
- };
-
- IdOrError ParamByPropertyNode(const PropertyNode&,
- const LineIndexesMap&) const;
- NSNumber* PropertyNodeToInt(const PropertyNode&) const;
- NSArray* PropertyNodeToIntArray(const PropertyNode&) const;
- NSValue* PropertyNodeToRange(const PropertyNode&) const;
- gfx::NativeViewAccessible PropertyNodeToUIElement(
- const PropertyNode&,
- const LineIndexesMap&) const;
- id PropertyNodeToTextMarker(const PropertyNode&, const LineIndexesMap&) const;
+ // Invokes an attributes by a property node.
+ OptionalNSObject InvokeAttributeFor(
+ const BrowserAccessibilityCocoa* cocoa_node,
+ const PropertyNode& property_node,
+ const LineIndexesMap& line_indexes_map) const;
base::Value PopulateSize(const BrowserAccessibilityCocoa*) const;
base::Value PopulatePosition(const BrowserAccessibilityCocoa*) const;
@@ -159,9 +101,6 @@ class AccessibilityTreeFormatterMac : public AccessibilityTreeFormatterBase {
const LineIndexesMap& line_indexes_map) const;
std::string NodeToLineIndex(id, const LineIndexesMap&) const;
- gfx::NativeViewAccessible LineIndexToNode(
- const base::string16 line_index,
- const LineIndexesMap& line_indexes_map) const;
base::string16 ProcessTreeForOutput(
const base::DictionaryValue& node,
@@ -212,9 +151,7 @@ AccessibilityTreeFormatterMac::BuildAccessibilityTree(
BrowserAccessibilityCocoa* cocoa_root = ToBrowserAccessibilityCocoa(root);
- int counter = 0;
- LineIndexesMap line_indexes_map;
- RecursiveBuildLineIndexesMap(cocoa_root, &line_indexes_map, &counter);
+ LineIndexesMap line_indexes_map(cocoa_root);
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
RecursiveBuildAccessibilityTree(cocoa_root, line_indexes_map, dict.get());
@@ -259,18 +196,6 @@ void AccessibilityTreeFormatterMac::RecursiveBuildAccessibilityTree(
dict->Set(kChildrenDictAttr, std::move(children));
}
-void AccessibilityTreeFormatterMac::RecursiveBuildLineIndexesMap(
- const BrowserAccessibilityCocoa* cocoa_node,
- LineIndexesMap* line_indexes_map,
- int* counter) {
- const base::string16 line_index =
- base::string16(1, ':') + base::NumberToString16(++(*counter));
- line_indexes_map->insert({cocoa_node, line_index});
- for (BrowserAccessibilityCocoa* cocoa_child in [cocoa_node children]) {
- RecursiveBuildLineIndexesMap(cocoa_child, line_indexes_map, counter);
- }
-}
-
void AccessibilityTreeFormatterMac::AddProperties(
const BrowserAccessibilityCocoa* cocoa_node,
const LineIndexesMap& line_indexes_map,
@@ -279,42 +204,32 @@ void AccessibilityTreeFormatterMac::AddProperties(
BrowserAccessibility* node = [cocoa_node owner];
dict->SetKey("id", base::Value(base::NumberToString16(node->GetId())));
- base::string16 line_index = base::ASCIIToUTF16("-1");
- if (line_indexes_map.find(cocoa_node) != line_indexes_map.end()) {
- line_index = line_indexes_map.at(cocoa_node);
- }
-
- // Attributes
- for (NSString* supportedAttribute in
- [cocoa_node accessibilityAttributeNames]) {
- if (GetMatchingPropertyNode(line_index,
- SysNSStringToUTF16(supportedAttribute))) {
- id value = [cocoa_node accessibilityAttributeValue:supportedAttribute];
- if (value != nil) {
- dict->SetPath(SysNSStringToUTF8(supportedAttribute),
- PopulateObject(value, line_indexes_map));
- }
+ // Dump all attributes if match-all filter is specified.
+ if (HasMatchAllPropertyFilter()) {
+ for (NSString* attribute : [cocoa_node accessibilityAttributeNames]) {
+ dict->SetPath(
+ SysNSStringToUTF8(attribute),
+ PopulateObject([cocoa_node accessibilityAttributeValue:attribute],
+ line_indexes_map));
}
+ return;
}
- // Parameterized attributes
- for (NSString* supportedAttribute in
- [cocoa_node accessibilityParameterizedAttributeNames]) {
- auto propnode = GetMatchingPropertyNode(
- line_index, SysNSStringToUTF16(supportedAttribute));
- IdOrError param = ParamByPropertyNode(propnode, line_indexes_map);
- if (param.IsError()) {
- dict->SetPath(base::UTF16ToUTF8(propnode.original_property),
- base::Value(kFailedToParseArgsError));
+ // Otherwise dump attributes matching allow filters only.
+ std::string line_index = line_indexes_map.IndexBy(cocoa_node);
+ for (const PropertyNode& property_node : PropertyFilterNodesFor(line_index)) {
+ AttributeInvoker invoker(cocoa_node, line_indexes_map);
+ OptionalNSObject value = invoker.Invoke(property_node);
+ if (value.IsNotApplicable()) {
continue;
}
-
- if (param.IsNotNil()) {
- id value = [cocoa_node accessibilityAttributeValue:supportedAttribute
- forParameter:*param];
- dict->SetPath(base::UTF16ToUTF8(propnode.original_property),
- PopulateObject(value, line_indexes_map));
+ if (value.IsError()) {
+ dict->SetPath(property_node.original_property,
+ base::Value(kFailedToParseArgsError));
+ continue;
}
+ dict->SetPath(property_node.original_property,
+ PopulateObject(*value, line_indexes_map));
}
// Position and size
@@ -322,151 +237,6 @@ void AccessibilityTreeFormatterMac::AddProperties(
dict->SetPath(kSizeDictAttr, PopulateSize(cocoa_node));
}
-AccessibilityTreeFormatterMac::IdOrError
-AccessibilityTreeFormatterMac::ParamByPropertyNode(
- const PropertyNode& property_node,
- const LineIndexesMap& line_indexes_map) const {
- IdOrError param;
- std::string property_name = base::UTF16ToASCII(property_node.name_or_value);
-
- if (property_name == "AXLineForIndex") { // Int
- param = PropertyNodeToInt(property_node);
- } else if (property_name == "AXCellForColumnAndRow") { // IntArray
- param = PropertyNodeToIntArray(property_node);
- } else if (property_name == "AXStringForRange") { // NSRange
- param = PropertyNodeToRange(property_node);
- } else if (property_name == "AXIndexForChildUIElement") { // UIElement
- param = PropertyNodeToUIElement(property_node, line_indexes_map);
- } else if (property_name == "AXIndexForTextMarker") { // TextMarker
- param = PropertyNodeToTextMarker(property_node, line_indexes_map);
- }
-
- return param;
-}
-
-// NSNumber. Format: integer.
-NSNumber* AccessibilityTreeFormatterMac::PropertyNodeToInt(
- const PropertyNode& propnode) const {
- if (propnode.parameters.size() != 1) {
- INT_FAIL(propnode, "single argument is expected")
- }
-
- const auto& intnode = propnode.parameters[0];
- base::Optional<int> param = intnode.AsInt();
- if (!param) {
- INT_FAIL(propnode, "not a number")
- }
- return [NSNumber numberWithInt:*param];
-}
-
-// NSArray of two NSNumber. Format: [integer, integer].
-NSArray* AccessibilityTreeFormatterMac::PropertyNodeToIntArray(
- const PropertyNode& propnode) const {
- if (propnode.parameters.size() != 1) {
- INTARRAY_FAIL(propnode, "single argument is expected")
- }
-
- const auto& arraynode = propnode.parameters[0];
- if (arraynode.name_or_value != base::ASCIIToUTF16("[]")) {
- INTARRAY_FAIL(propnode, "not array")
- }
-
- NSMutableArray* array =
- [[NSMutableArray alloc] initWithCapacity:arraynode.parameters.size()];
- for (const auto& paramnode : arraynode.parameters) {
- base::Optional<int> param = paramnode.AsInt();
- if (!param) {
- INTARRAY_FAIL(propnode, paramnode.name_or_value +
- base::UTF8ToUTF16(" is not a number"))
- }
- [array addObject:@(*param)];
- }
- return array;
-}
-
-// NSRange. Format: {loc: integer, len: integer}.
-NSValue* AccessibilityTreeFormatterMac::PropertyNodeToRange(
- const PropertyNode& propnode) const {
- if (propnode.parameters.size() != 1) {
- NSRANGE_FAIL(propnode, "single argument is expected")
- }
-
- const auto& dictnode = propnode.parameters[0];
- if (!dictnode.IsDict()) {
- NSRANGE_FAIL(propnode, "dictionary is expected")
- }
-
- base::Optional<int> loc = dictnode.FindIntKey("loc");
- if (!loc) {
- NSRANGE_FAIL(propnode, "no loc or loc is not a number")
- }
-
- base::Optional<int> len = dictnode.FindIntKey("len");
- if (!len) {
- NSRANGE_FAIL(propnode, "no len or len is not a number")
- }
-
- return [NSValue valueWithRange:NSMakeRange(*loc, *len)];
-}
-
-// UIElement. Format: :line_num.
-gfx::NativeViewAccessible
-AccessibilityTreeFormatterMac::PropertyNodeToUIElement(
- const PropertyNode& propnode,
- const LineIndexesMap& line_indexes_map) const {
- if (propnode.parameters.size() != 1) {
- UIELEMENT_FAIL(propnode, "single argument is expected")
- }
-
- gfx::NativeViewAccessible uielement =
- LineIndexToNode(propnode.parameters[0].name_or_value, line_indexes_map);
- if (!uielement) {
- UIELEMENT_FAIL(propnode, "no corresponding UIElement was found in the tree")
- }
- return uielement;
-}
-
-id AccessibilityTreeFormatterMac::PropertyNodeToTextMarker(
- const PropertyNode& propnode,
- const LineIndexesMap& line_indexes_map) const {
- if (propnode.parameters.size() != 1) {
- TEXTMARKER_FAIL(propnode, "single argument is expected")
- }
-
- const auto& tmnode = propnode.parameters[0];
- if (!tmnode.IsDict()) {
- TEXTMARKER_FAIL(propnode, "dictionary is expected")
- }
- if (tmnode.parameters.size() != 3) {
- TEXTMARKER_FAIL(propnode, "wrong number of dictionary elements")
- }
-
- BrowserAccessibilityCocoa* anchor_cocoa =
- LineIndexToNode(tmnode.parameters[0].name_or_value, line_indexes_map);
- if (!anchor_cocoa) {
- TEXTMARKER_FAIL(propnode, "1st argument: wrong anchor")
- }
-
- base::Optional<int> offset = tmnode.parameters[1].AsInt();
- if (!offset) {
- TEXTMARKER_FAIL(propnode, "2nd argument: wrong offset")
- }
-
- ax::mojom::TextAffinity affinity;
- const base::string16& affinity_str = tmnode.parameters[2].name_or_value;
- if (affinity_str == base::UTF8ToUTF16("none")) {
- affinity = ax::mojom::TextAffinity::kNone;
- } else if (affinity_str == base::UTF8ToUTF16("down")) {
- affinity = ax::mojom::TextAffinity::kDownstream;
- } else if (affinity_str == base::UTF8ToUTF16("up")) {
- affinity = ax::mojom::TextAffinity::kUpstream;
- } else {
- TEXTMARKER_FAIL(propnode, "3rd argument: wrong affinity")
- }
-
- return content::AXTextMarkerFrom(anchor_cocoa, *offset, affinity);
-}
-
base::Value AccessibilityTreeFormatterMac::PopulateSize(
const BrowserAccessibilityCocoa* cocoa_node) const {
base::Value size(base::Value::Type::DICTIONARY);
@@ -483,8 +253,8 @@ base::Value AccessibilityTreeFormatterMac::PopulatePosition(
DCHECK(root_manager);
// The NSAccessibility position of an object is in global coordinates and
- // based on the lower-left corner of the object. To make this easier and less
- // confusing, convert it to local window coordinates using the top-left
+ // based on the lower-left corner of the object. To make this easier and
+ // less confusing, convert it to local window coordinates using the top-left
// corner when dumping the position.
BrowserAccessibility* root = root_manager->GetRoot();
BrowserAccessibilityCocoa* cocoa_root = ToBrowserAccessibilityCocoa(root);
@@ -617,24 +387,7 @@ base::Value AccessibilityTreeFormatterMac::PopulateArray(
std::string AccessibilityTreeFormatterMac::NodeToLineIndex(
id cocoa_node,
const LineIndexesMap& line_indexes_map) const {
- std::string line_index = ":unknown";
- auto index_iterator = line_indexes_map.find(cocoa_node);
- if (index_iterator != line_indexes_map.end()) {
- line_index = base::UTF16ToUTF8(index_iterator->second);
- }
- return kConstValuePrefix + line_index;
-}
-
-gfx::NativeViewAccessible AccessibilityTreeFormatterMac::LineIndexToNode(
- const base::string16 line_index,
- const LineIndexesMap& line_indexes_map) const {
- for (std::pair<const gfx::NativeViewAccessible, base::string16> item :
- line_indexes_map) {
- if (item.second == line_index) {
- return item.first;
- }
- }
- return nil;
+ return kConstValuePrefix + line_indexes_map.IndexBy(cocoa_node);
}
base::string16 AccessibilityTreeFormatterMac::ProcessTreeForOutput(
@@ -771,6 +524,10 @@ const string AccessibilityTreeFormatterMac::GetDenyNodeString() {
return "@MAC-DENY-NODE:";
}
+const std::string AccessibilityTreeFormatterMac::GetRunUntilEventString() {
+ return "@MAC-RUN-UNTIL-EVENT:";
+}
+
} // namespace content
#pragma clang diagnostic pop
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac_browsertest.mm b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac_browsertest.mm
index 5f6db82d33d..e936844370d 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac_browsertest.mm
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac_browsertest.mm
@@ -67,8 +67,7 @@ void AccessibilityTreeFormatterMacBrowserTest::TestAndCheck(
for (const char* filter : filters) {
property_filters.push_back(AccessibilityTreeFormatter::PropertyFilter(
- base::UTF8ToUTF16(filter),
- AccessibilityTreeFormatter::PropertyFilter::ALLOW_EMPTY));
+ filter, AccessibilityTreeFormatter::PropertyFilter::ALLOW_EMPTY));
}
formatter->AddDefaultFilters(&property_filters);
@@ -122,7 +121,18 @@ IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
}
IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
- LineIndexFilter) {
+ Filters_NoWildcardProperty) {
+ TestAndCheck(R"~~(data:text/html,
+ <input class='classolasso'>)~~",
+ {"AXDOMClassList"},
+ R"~~(AXWebArea AXDOMClassList=[]
+++AXGroup AXDOMClassList=[]
+++++AXTextField AXDOMClassList=['classolasso']
+)~~");
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
+ Filters_LineIndex) {
TestAndCheck(R"~~(data:text/html,
<input class='input_at_3rd_line'>
<input class='input_at_4th_line'>
@@ -154,7 +164,7 @@ IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
</script>)~~",
{":3;AXSelectedTextMarkerRange=*"}, R"~~(AXWebArea
++AXGroup
-++++AXStaticText AXSelectedTextMarkerRange={anchor: {:3, 0, down}, focus: {:2, -1, down}} AXValue='Paragraph'
+++++AXStaticText AXSelectedTextMarkerRange={anchor: {:2, -1, down}, focus: {:3, 0, down}} AXValue='Paragraph'
)~~");
}
@@ -290,4 +300,42 @@ IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
)~~");
}
+IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
+ ParameterizedAttributes_TextMarkerRange) {
+ TestAndCheck(R"~~(data:text/html,
+ <p>Text</p>)~~",
+ {":2;AXStringForTextMarkerRange({anchor: {:2, 1, down}, focus: "
+ "{:2, 3, down}})=*"},
+ R"~~(AXWebArea
+++AXGroup AXStringForTextMarkerRange({anchor: {:2, 1, down}, focus: {:2, 3, down}})='ex'
+++++AXStaticText AXValue='Text'
+)~~");
+}
+
+IN_PROC_BROWSER_TEST_F(
+ AccessibilityTreeFormatterMacBrowserTest,
+ ParameterizedAttributes_TextMarkerRange_WrongParameters) {
+ TestWrongParameters(
+ R"~~(data:text/html,
+ <p>Text</p>)~~",
+ {"1, 2", "2", "{focus: {:2, 1, down}}", "{anchor: {:2, 1, down}}",
+ "{anchor: {2, 1, down}, focus: {2, 1, down}}"},
+ ":1;AXStringForTextMarkerRange(Argument)=*",
+ R"~~(AXWebArea AXStringForTextMarkerRange(Argument)=ERROR:FAILED_TO_PARSE_ARGS
+++AXGroup
+++++AXStaticText AXValue='Text'
+)~~");
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityTreeFormatterMacBrowserTest,
+ NestedCalls_Attributes) {
+ TestAndCheck(R"~~(data:text/html,
+ <p>Text</p>)~~",
+ {":1;AXIndexForTextMarker(AXTextMarkerForIndex(0))"},
+ R"~~(AXWebArea AXIndexForTextMarker(AXTextMarkerForIndex(0))=0
+++AXGroup
+++++AXStaticText AXValue='Text'
+)~~");
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
index b7181143268..b751a10e81f 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
@@ -1200,4 +1200,8 @@ const std::string AccessibilityTreeFormatterUia::GetDenyNodeString() {
return "@UIA-WIN-DENY-NODE:";
}
+const std::string AccessibilityTreeFormatterUia::GetRunUntilEventString() {
+ return "@UIA-WIN-RUN-UNTIL-EVENT:";
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.h b/chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.h
index 45fbaaa46a9..86c85f29731 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.h
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_uia_win.h
@@ -100,6 +100,7 @@ class AccessibilityTreeFormatterUia : public AccessibilityTreeFormatterBase {
const std::string GetAllowString() override;
const std::string GetDenyString() override;
const std::string GetDenyNodeString() override;
+ const std::string GetRunUntilEventString() override;
base::string16 ProcessTreeForOutput(
const base::DictionaryValue& node,
base::DictionaryValue* filtered_result = nullptr) override;
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_mac.h b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_mac.h
new file mode 100644
index 00000000000..5dd04e900cf
--- /dev/null
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_mac.h
@@ -0,0 +1,97 @@
+// Copyright 2020 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 CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_TREE_FORMATTER_UTILS_MAC_H_
+#define CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_TREE_FORMATTER_UTILS_MAC_H_
+
+#include "content/browser/accessibility/accessibility_tree_formatter_base.h"
+#include "content/browser/accessibility/browser_accessibility_cocoa.h"
+
+namespace content {
+namespace a11y {
+
+/**
+ * Converts cocoa node object to a line index in the formatted accessibility
+ * tree, the node is placed at, and vice versa.
+ */
+class LineIndexesMap {
+ public:
+ LineIndexesMap(const BrowserAccessibilityCocoa* cocoa_node);
+ ~LineIndexesMap();
+
+ std::string IndexBy(const BrowserAccessibilityCocoa* cocoa_node) const;
+ gfx::NativeViewAccessible NodeBy(const std::string& index) const;
+
+ private:
+ void Build(const BrowserAccessibilityCocoa* cocoa_node, int* counter);
+
+ std::map<const gfx::NativeViewAccessible, std::string> map;
+};
+
+// Implements stateful id values. Can be either id or be in
+// error or not applciable state. Similar to base::Optional, but tri-state
+// allowing nullable values.
+class OptionalNSObject final {
+ public:
+ enum { ID, ERROR, NOT_APPLICABLE };
+
+ static OptionalNSObject Error() { return OptionalNSObject(ERROR); }
+ static OptionalNSObject NotApplicable() {
+ return OptionalNSObject(NOT_APPLICABLE);
+ }
+ static OptionalNSObject NotNilOrError(id other_value) {
+ return OptionalNSObject(other_value, other_value ? ID : ERROR);
+ }
+ static OptionalNSObject NotNullOrNotApplicable(id other_value) {
+ return OptionalNSObject(other_value, other_value ? ID : NOT_APPLICABLE);
+ }
+
+ OptionalNSObject(int flag) : value(nil), flag(flag) {}
+ OptionalNSObject(id value, int flag = ID) : value(value), flag(flag) {}
+
+ bool IsNotApplicable() const { return flag == NOT_APPLICABLE; }
+ bool IsError() const { return flag == ERROR; }
+ bool IsNotNil() const { return value != nil; }
+ constexpr const id& operator*() const& { return value; }
+
+ private:
+ id value;
+ int flag;
+};
+
+// Invokes attributes matching the given property filter.
+class AttributeInvoker final {
+ public:
+ AttributeInvoker(const BrowserAccessibilityCocoa* cocoa_node,
+ const LineIndexesMap& line_indexes_map);
+
+ // Invokes an attribute matching to a property filter.
+ OptionalNSObject Invoke(const PropertyNode& property_node) const;
+
+ private:
+ // Returns a parameterized attribute parameter by a property node.
+ OptionalNSObject ParamByPropertyNode(const PropertyNode&) const;
+
+ NSNumber* PropertyNodeToInt(const PropertyNode&) const;
+ NSArray* PropertyNodeToIntArray(const PropertyNode&) const;
+ NSValue* PropertyNodeToRange(const PropertyNode&) const;
+ gfx::NativeViewAccessible PropertyNodeToUIElement(const PropertyNode&) const;
+
+ id DictNodeToTextMarker(const PropertyNode&) const;
+ id PropertyNodeToTextMarker(const PropertyNode&) const;
+ id PropertyNodeToTextMarkerRange(const PropertyNode&) const;
+
+ gfx::NativeViewAccessible LineIndexToNode(
+ const base::string16 line_index) const;
+
+ const BrowserAccessibilityCocoa* cocoa_node;
+ const LineIndexesMap& line_indexes_map;
+ const NSArray* attributes;
+ const NSArray* parameterized_attributes;
+};
+
+} // namespace a11y
+} // namespace content
+
+#endif
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_mac.mm b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_mac.mm
new file mode 100644
index 00000000000..71126d0224f
--- /dev/null
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_mac.mm
@@ -0,0 +1,298 @@
+// Copyright 2020 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 "content/browser/accessibility/accessibility_tree_formatter_utils_mac.h"
+
+#include "base/strings/sys_string_conversions.h"
+
+// error: 'accessibilityAttributeNames' is deprecated: first deprecated in
+// macOS 10.10 - Use the NSAccessibility protocol methods instead (see
+// NSAccessibilityProtocols.h
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+
+using base::SysNSStringToUTF8;
+
+namespace content {
+namespace a11y {
+
+namespace {
+
+#define INT_FAIL(property_node, msg) \
+ LOG(ERROR) << "Failed to parse " << property_node.name_or_value \
+ << " to Int: " << msg; \
+ return nil;
+
+#define INTARRAY_FAIL(property_node, msg) \
+ LOG(ERROR) << "Failed to parse " << property_node.name_or_value \
+ << " to IntArray: " << msg; \
+ return nil;
+
+#define NSRANGE_FAIL(property_node, msg) \
+ LOG(ERROR) << "Failed to parse " << property_node.name_or_value \
+ << " to NSRange: " << msg; \
+ return nil;
+
+#define UIELEMENT_FAIL(property_node, msg) \
+ LOG(ERROR) << "Failed to parse " << property_node.name_or_value \
+ << " to UIElement: " << msg; \
+ return nil;
+
+#define TEXTMARKER_FAIL(property_node, msg) \
+ LOG(ERROR) << "Failed to parse " << property_node.name_or_value \
+ << " to AXTextMarker: " << msg \
+ << ". Expected format: {anchor, offset, affinity}, where anchor " \
+ "is :line_num, offset is integer, affinity is either down, " \
+ "up or none"; \
+ return nil;
+
+} // namespace
+
+LineIndexesMap::LineIndexesMap(const BrowserAccessibilityCocoa* cocoa_node) {
+ int counter = 0;
+ Build(cocoa_node, &counter);
+}
+
+LineIndexesMap::~LineIndexesMap() {}
+
+std::string LineIndexesMap::IndexBy(
+ const BrowserAccessibilityCocoa* cocoa_node) const {
+ std::string line_index = ":unknown";
+ if (map.find(cocoa_node) != map.end()) {
+ line_index = map.at(cocoa_node);
+ }
+ return line_index;
+}
+
+gfx::NativeViewAccessible LineIndexesMap::NodeBy(
+ const std::string& line_index) const {
+ for (std::pair<const gfx::NativeViewAccessible, std::string> item : map) {
+ if (item.second == line_index) {
+ return item.first;
+ }
+ }
+ return nil;
+}
+
+void LineIndexesMap::Build(const BrowserAccessibilityCocoa* cocoa_node,
+ int* counter) {
+ const std::string line_index =
+ std::string(1, ':') + base::NumberToString(++(*counter));
+ map.insert({cocoa_node, line_index});
+ for (BrowserAccessibilityCocoa* cocoa_child in [cocoa_node children]) {
+ Build(cocoa_child, counter);
+ }
+}
+
+// AttributeInvoker
+
+AttributeInvoker::AttributeInvoker(const BrowserAccessibilityCocoa* cocoa_node,
+ const LineIndexesMap& line_indexes_map)
+ : cocoa_node(cocoa_node), line_indexes_map(line_indexes_map) {
+ attributes = [cocoa_node accessibilityAttributeNames];
+ parameterized_attributes =
+ [cocoa_node accessibilityParameterizedAttributeNames];
+}
+
+OptionalNSObject AttributeInvoker::Invoke(
+ const PropertyNode& property_node) const {
+ // Attributes
+ for (NSString* attribute : attributes) {
+ if (property_node.IsMatching(SysNSStringToUTF8(attribute))) {
+ return OptionalNSObject::NotNullOrNotApplicable(
+ [cocoa_node accessibilityAttributeValue:attribute]);
+ }
+ }
+
+ // Parameterized attributes
+ for (NSString* attribute : parameterized_attributes) {
+ if (property_node.IsMatching(SysNSStringToUTF8(attribute))) {
+ OptionalNSObject param = ParamByPropertyNode(property_node);
+ if (param.IsNotNil()) {
+ return OptionalNSObject([cocoa_node
+ accessibilityAttributeValue:attribute
+ forParameter:*param]);
+ }
+ return param;
+ }
+ }
+
+ return OptionalNSObject::NotApplicable();
+}
+
+OptionalNSObject AttributeInvoker::ParamByPropertyNode(
+ const PropertyNode& property_node) const {
+ // NSAccessibility attributes always take a single parameter.
+ if (property_node.parameters.size() != 1) {
+ LOG(ERROR) << "Failed to parse " << property_node.original_property
+ << ": single parameter is expected";
+ return OptionalNSObject::Error();
+ }
+
+ // Nested attribute case: attempt to invoke an attribute for an argument node.
+ const PropertyNode& arg_node = property_node.parameters[0];
+ OptionalNSObject subvalue = Invoke(arg_node);
+ if (!subvalue.IsNotApplicable()) {
+ return subvalue;
+ }
+
+ // Otherwise parse argument node value.
+ const std::string& property_name = property_node.name_or_value;
+ if (property_name == "AXLineForIndex" ||
+ property_name == "AXTextMarkerForIndex") { // Int
+ return OptionalNSObject::NotNilOrError(PropertyNodeToInt(arg_node));
+ }
+ if (property_name == "AXCellForColumnAndRow") { // IntArray
+ return OptionalNSObject::NotNilOrError(PropertyNodeToIntArray(arg_node));
+ }
+ if (property_name == "AXStringForRange") { // NSRange
+ return OptionalNSObject::NotNilOrError(PropertyNodeToRange(arg_node));
+ }
+ if (property_name == "AXIndexForChildUIElement") { // UIElement
+ return OptionalNSObject::NotNilOrError(PropertyNodeToUIElement(arg_node));
+ }
+ if (property_name == "AXIndexForTextMarker") { // TextMarker
+ return OptionalNSObject::NotNilOrError(PropertyNodeToTextMarker(arg_node));
+ }
+ if (property_name == "AXStringForTextMarkerRange") { // TextMarkerRange
+ return OptionalNSObject::NotNilOrError(
+ PropertyNodeToTextMarkerRange(arg_node));
+ }
+
+ return OptionalNSObject::NotApplicable();
+}
+
+// NSNumber. Format: integer.
+NSNumber* AttributeInvoker::PropertyNodeToInt(
+ const PropertyNode& intnode) const {
+ base::Optional<int> param = intnode.AsInt();
+ if (!param) {
+ INT_FAIL(intnode, "not a number")
+ }
+ return [NSNumber numberWithInt:*param];
+}
+
+// NSArray of two NSNumber. Format: [integer, integer].
+NSArray* AttributeInvoker::PropertyNodeToIntArray(
+ const PropertyNode& arraynode) const {
+ if (arraynode.name_or_value != "[]") {
+ INTARRAY_FAIL(arraynode, "not array")
+ }
+
+ NSMutableArray* array =
+ [[NSMutableArray alloc] initWithCapacity:arraynode.parameters.size()];
+ for (const auto& paramnode : arraynode.parameters) {
+ base::Optional<int> param = paramnode.AsInt();
+ if (!param) {
+ INTARRAY_FAIL(arraynode, paramnode.name_or_value + " is not a number")
+ }
+ [array addObject:@(*param)];
+ }
+ return array;
+}
+
+// NSRange. Format: {loc: integer, len: integer}.
+NSValue* AttributeInvoker::PropertyNodeToRange(
+ const PropertyNode& dictnode) const {
+ if (!dictnode.IsDict()) {
+ NSRANGE_FAIL(dictnode, "dictionary is expected")
+ }
+
+ base::Optional<int> loc = dictnode.FindIntKey("loc");
+ if (!loc) {
+ NSRANGE_FAIL(dictnode, "no loc or loc is not a number")
+ }
+
+ base::Optional<int> len = dictnode.FindIntKey("len");
+ if (!len) {
+ NSRANGE_FAIL(dictnode, "no len or len is not a number")
+ }
+
+ return [NSValue valueWithRange:NSMakeRange(*loc, *len)];
+}
+
+// UIElement. Format: :line_num.
+gfx::NativeViewAccessible AttributeInvoker::PropertyNodeToUIElement(
+ const PropertyNode& uielement_node) const {
+ gfx::NativeViewAccessible uielement =
+ line_indexes_map.NodeBy(uielement_node.name_or_value);
+ if (!uielement) {
+ UIELEMENT_FAIL(uielement_node,
+ "no corresponding UIElement was found in the tree")
+ }
+ return uielement;
+}
+
+id AttributeInvoker::DictNodeToTextMarker(const PropertyNode& dictnode) const {
+ if (!dictnode.IsDict()) {
+ TEXTMARKER_FAIL(dictnode, "dictionary is expected")
+ }
+ if (dictnode.parameters.size() != 3) {
+ TEXTMARKER_FAIL(dictnode, "wrong number of dictionary elements")
+ }
+
+ BrowserAccessibilityCocoa* anchor_cocoa =
+ line_indexes_map.NodeBy(dictnode.parameters[0].name_or_value);
+ if (!anchor_cocoa) {
+ TEXTMARKER_FAIL(dictnode, "1st argument: wrong anchor")
+ }
+
+ base::Optional<int> offset = dictnode.parameters[1].AsInt();
+ if (!offset) {
+ TEXTMARKER_FAIL(dictnode, "2nd argument: wrong offset")
+ }
+
+ ax::mojom::TextAffinity affinity;
+ const std::string& affinity_str = dictnode.parameters[2].name_or_value;
+ if (affinity_str == "none") {
+ affinity = ax::mojom::TextAffinity::kNone;
+ } else if (affinity_str == "down") {
+ affinity = ax::mojom::TextAffinity::kDownstream;
+ } else if (affinity_str == "up") {
+ affinity = ax::mojom::TextAffinity::kUpstream;
+ } else {
+ TEXTMARKER_FAIL(dictnode, "3rd argument: wrong affinity")
+ }
+
+ return content::AXTextMarkerFrom(anchor_cocoa, *offset, affinity);
+}
+
+id AttributeInvoker::PropertyNodeToTextMarker(
+ const PropertyNode& dictnode) const {
+ return DictNodeToTextMarker(dictnode);
+}
+
+id AttributeInvoker::PropertyNodeToTextMarkerRange(
+ const PropertyNode& rangenode) const {
+ if (!rangenode.IsDict()) {
+ TEXTMARKER_FAIL(rangenode, "dictionary is expected")
+ }
+
+ const PropertyNode* anchornode = rangenode.FindKey("anchor");
+ if (!anchornode) {
+ TEXTMARKER_FAIL(rangenode, "no anchor")
+ }
+
+ id anchor_textmarker = DictNodeToTextMarker(*anchornode);
+ if (!anchor_textmarker) {
+ TEXTMARKER_FAIL(rangenode, "failed to parse anchor")
+ }
+
+ const PropertyNode* focusnode = rangenode.FindKey("focus");
+ if (!focusnode) {
+ TEXTMARKER_FAIL(rangenode, "no focus")
+ }
+
+ id focus_textmarker = DictNodeToTextMarker(*focusnode);
+ if (!focus_textmarker) {
+ TEXTMARKER_FAIL(rangenode, "failed to parse focus")
+ }
+
+ return content::AXTextMarkerRangeFrom(anchor_textmarker, focus_textmarker);
+}
+
+} // namespace a11y
+} // namespace content
+
+#pragma clang diagnostic pop
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
index 6b8e3a375b1..f4f137e8498 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -71,6 +71,7 @@ class AccessibilityTreeFormatterWin : public AccessibilityTreeFormatterBase {
const std::string GetAllowString() override;
const std::string GetDenyString() override;
const std::string GetDenyNodeString() override;
+ const std::string GetRunUntilEventString() override;
void AddProperties(const Microsoft::WRL::ComPtr<IAccessible>,
base::DictionaryValue* dict,
LONG root_x,
@@ -184,7 +185,7 @@ static HRESULT QuerySimpleDOMNode(IAccessible* accessible,
// IA2 Spec dictates that IServiceProvider should be used instead of
// QueryInterface when retrieving IAccessible2.
Microsoft::WRL::ComPtr<IServiceProvider> service_provider;
- HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+ HRESULT hr = accessible->QueryInterface(IID_PPV_ARGS(&service_provider));
if (FAILED(hr))
return hr;
return service_provider->QueryService(IID_ISimpleDOMNode, simple_dom_node);
@@ -195,7 +196,7 @@ static HRESULT QueryIAccessible2(IAccessible* accessible,
// IA2 Spec dictates that IServiceProvider should be used instead of
// QueryInterface when retrieving IAccessible2.
Microsoft::WRL::ComPtr<IServiceProvider> service_provider;
- HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+ HRESULT hr = accessible->QueryInterface(IID_PPV_ARGS(&service_provider));
if (FAILED(hr))
return hr;
return service_provider->QueryService(IID_IAccessible2, accessible2);
@@ -206,7 +207,7 @@ static HRESULT QueryIAccessibleAction(IAccessible* accessible,
// IA2 Spec dictates that IServiceProvider should be used instead of
// QueryInterface when retrieving alternate interfaces.
Microsoft::WRL::ComPtr<IServiceProvider> service_provider;
- HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+ HRESULT hr = accessible->QueryInterface(IID_PPV_ARGS(&service_provider));
if (FAILED(hr))
return hr;
@@ -220,7 +221,7 @@ static HRESULT QueryIAccessibleHypertext(
// IA2 Spec dictates that IServiceProvider should be used instead of
// QueryInterface when retrieving alternate interfaces.
Microsoft::WRL::ComPtr<IServiceProvider> service_provider;
- HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+ HRESULT hr = accessible->QueryInterface(IID_PPV_ARGS(&service_provider));
if (FAILED(hr))
return hr;
return service_provider->QueryService(IID_IAccessibleHypertext,
@@ -232,7 +233,7 @@ static HRESULT QueryIAccessibleTable(IAccessible* accessible,
// IA2 Spec dictates that IServiceProvider should be used instead of
// QueryInterface when retrieving alternate interfaces.
Microsoft::WRL::ComPtr<IServiceProvider> service_provider;
- HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+ HRESULT hr = accessible->QueryInterface(IID_PPV_ARGS(&service_provider));
if (FAILED(hr))
return hr;
return service_provider->QueryService(IID_IAccessibleTable, accessibleTable);
@@ -244,7 +245,7 @@ static HRESULT QueryIAccessibleTableCell(
// IA2 Spec dictates that IServiceProvider should be used instead of
// QueryInterface when retrieving alternate interfaces.
Microsoft::WRL::ComPtr<IServiceProvider> service_provider;
- HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+ HRESULT hr = accessible->QueryInterface(IID_PPV_ARGS(&service_provider));
if (FAILED(hr))
return hr;
return service_provider->QueryService(IID_IAccessibleTableCell,
@@ -256,7 +257,7 @@ static HRESULT QueryIAccessibleText(IAccessible* accessible,
// IA2 Spec dictates that IServiceProvider should be used instead of
// QueryInterface when retrieving alternate interfaces.
Microsoft::WRL::ComPtr<IServiceProvider> service_provider;
- HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+ HRESULT hr = accessible->QueryInterface(IID_PPV_ARGS(&service_provider));
if (FAILED(hr))
return hr;
return service_provider->QueryService(IID_IAccessibleText, accessibleText);
@@ -267,7 +268,7 @@ static HRESULT QueryIAccessibleValue(IAccessible* accessible,
// IA2 Spec dictates that IServiceProvider should be used instead of
// QueryInterface when retrieving alternate interfaces.
Microsoft::WRL::ComPtr<IServiceProvider> service_provider;
- HRESULT hr = accessible->QueryInterface(service_provider.GetAddressOf());
+ HRESULT hr = accessible->QueryInterface(IID_PPV_ARGS(&service_provider));
if (FAILED(hr))
return hr;
return service_provider->QueryService(IID_IAccessibleValue, accessibleValue);
@@ -372,7 +373,7 @@ void AccessibilityTreeFormatterWin::RecursiveBuildAccessibilityTree(
if (child_variant.type() == VT_DISPATCH) {
dispatch = V_DISPATCH(child_variant.ptr());
} else if (child_variant.type() == VT_I4) {
- hr = node->get_accChild(child_variant, dispatch.GetAddressOf());
+ hr = node->get_accChild(child_variant, &dispatch);
if (FAILED(hr)) {
child_dict->SetString("error",
base::ASCIIToUTF16("[Error retrieving child]"));
@@ -496,12 +497,11 @@ void AccessibilityTreeFormatterWin::AddMSAAProperties(
temp_bstr.Reset();
Microsoft::WRL::ComPtr<IDispatch> parent_dispatch;
- if (SUCCEEDED(node->get_accParent(parent_dispatch.GetAddressOf()))) {
+ if (SUCCEEDED(node->get_accParent(&parent_dispatch))) {
Microsoft::WRL::ComPtr<IAccessible> parent_accessible;
if (!parent_dispatch) {
dict->SetString("parent", "[null]");
- } else if (SUCCEEDED(
- parent_dispatch.CopyTo(parent_accessible.GetAddressOf()))) {
+ } else if (SUCCEEDED(parent_dispatch.As(&parent_accessible))) {
base::win::ScopedVariant parent_ia_role_variant;
if (SUCCEEDED(parent_accessible->get_accRole(
variant_self, parent_ia_role_variant.Receive())))
@@ -587,7 +587,7 @@ void AccessibilityTreeFormatterWin::AddSimpleDOMNodeProperties(
base::DictionaryValue* dict) {
Microsoft::WRL::ComPtr<ISimpleDOMNode> simple_dom_node;
- if (S_OK != QuerySimpleDOMNode(node.Get(), simple_dom_node.GetAddressOf()))
+ if (S_OK != QuerySimpleDOMNode(node.Get(), &simple_dom_node))
return; // No IA2Value, we are finished with this node.
base::win::ScopedBstr temp_bstr;
@@ -603,7 +603,7 @@ bool AccessibilityTreeFormatterWin::AddIA2Properties(
const Microsoft::WRL::ComPtr<IAccessible> node,
base::DictionaryValue* dict) {
Microsoft::WRL::ComPtr<IAccessible2> ia2;
- if (S_OK != QueryIAccessible2(node.Get(), ia2.GetAddressOf()))
+ if (S_OK != QueryIAccessible2(node.Get(), &ia2))
return false; // No IA2, we are finished with this node.
LONG ia2_role = 0;
@@ -671,7 +671,7 @@ void AccessibilityTreeFormatterWin::AddIA2ActionProperties(
const Microsoft::WRL::ComPtr<IAccessible> node,
base::DictionaryValue* dict) {
Microsoft::WRL::ComPtr<IAccessibleAction> ia2action;
- if (S_OK != QueryIAccessibleAction(node.Get(), ia2action.GetAddressOf()))
+ if (S_OK != QueryIAccessibleAction(node.Get(), &ia2action))
return; // No IA2Value, we are finished with this node.
base::win::ScopedBstr temp_bstr;
@@ -688,7 +688,7 @@ void AccessibilityTreeFormatterWin::AddIA2HypertextProperties(
Microsoft::WRL::ComPtr<IAccessible> node,
base::DictionaryValue* dict) {
Microsoft::WRL::ComPtr<IAccessibleHypertext> ia2hyper;
- if (S_OK != QueryIAccessibleHypertext(node.Get(), ia2hyper.GetAddressOf()))
+ if (S_OK != QueryIAccessibleHypertext(node.Get(), &ia2hyper))
return; // No IA2, we are finished with this node
base::win::ScopedBstr text_bstr;
@@ -725,11 +725,10 @@ void AccessibilityTreeFormatterWin::AddIA2HypertextProperties(
if (hr == S_OK) {
DCHECK_GE(index_of_embed, 0);
Microsoft::WRL::ComPtr<IAccessibleHyperlink> embedded_object;
- hr = ia2hyper->get_hyperlink(index_of_embed,
- embedded_object.GetAddressOf());
+ hr = ia2hyper->get_hyperlink(index_of_embed, &embedded_object);
DCHECK(SUCCEEDED(hr));
Microsoft::WRL::ComPtr<IAccessible2> ax_embed;
- hr = embedded_object.CopyTo(ax_embed.GetAddressOf());
+ hr = embedded_object.As(&ax_embed);
DCHECK(SUCCEEDED(hr));
hr = ax_embed->get_indexInParent(&child_index);
DCHECK(SUCCEEDED(hr));
@@ -757,7 +756,7 @@ void AccessibilityTreeFormatterWin::AddIA2TableProperties(
const Microsoft::WRL::ComPtr<IAccessible> node,
base::DictionaryValue* dict) {
Microsoft::WRL::ComPtr<IAccessibleTable> ia2table;
- if (S_OK != QueryIAccessibleTable(node.Get(), ia2table.GetAddressOf()))
+ if (S_OK != QueryIAccessibleTable(node.Get(), &ia2table))
return; // No IA2Text, we are finished with this node.
LONG table_rows;
@@ -780,7 +779,7 @@ static base::string16 ProcessAccessiblesArray(IUnknown** accessibles,
related_accessibles_string += index > 0 ? L"," : L"<";
Microsoft::WRL::ComPtr<IUnknown> unknown = accessibles[index];
Microsoft::WRL::ComPtr<IAccessible> accessible;
- if (SUCCEEDED(unknown.CopyTo(accessible.GetAddressOf()))) {
+ if (SUCCEEDED(unknown.As(&accessible))) {
base::win::ScopedBstr temp_bstr;
if (S_OK == accessible->get_accName(variant_self, temp_bstr.Receive()))
related_accessibles_string += temp_bstr.Get();
@@ -796,7 +795,7 @@ void AccessibilityTreeFormatterWin::AddIA2TableCellProperties(
const Microsoft::WRL::ComPtr<IAccessible> node,
base::DictionaryValue* dict) {
Microsoft::WRL::ComPtr<IAccessibleTableCell> ia2cell;
- if (S_OK != QueryIAccessibleTableCell(node.Get(), ia2cell.GetAddressOf()))
+ if (S_OK != QueryIAccessibleTableCell(node.Get(), &ia2cell))
return; // No IA2Text, we are finished with this node.
LONG n_row_header_cells;
@@ -826,7 +825,7 @@ void AccessibilityTreeFormatterWin::AddIA2TextProperties(
const Microsoft::WRL::ComPtr<IAccessible> node,
base::DictionaryValue* dict) {
Microsoft::WRL::ComPtr<IAccessibleText> ia2text;
- if (S_OK != QueryIAccessibleText(node.Get(), ia2text.GetAddressOf()))
+ if (S_OK != QueryIAccessibleText(node.Get(), &ia2text))
return; // No IA2Text, we are finished with this node.
LONG n_characters;
@@ -892,7 +891,7 @@ void AccessibilityTreeFormatterWin::AddIA2ValueProperties(
const Microsoft::WRL::ComPtr<IAccessible> node,
base::DictionaryValue* dict) {
Microsoft::WRL::ComPtr<IAccessibleValue> ia2value;
- if (S_OK != QueryIAccessibleValue(node.Get(), ia2value.GetAddressOf()))
+ if (S_OK != QueryIAccessibleValue(node.Get(), &ia2value))
return; // No IA2Value, we are finished with this node.
base::win::ScopedVariant current_value;
@@ -1038,4 +1037,8 @@ const std::string AccessibilityTreeFormatterWin::GetDenyNodeString() {
return "@WIN-DENY-NODE:";
}
+const std::string AccessibilityTreeFormatterWin::GetRunUntilEventString() {
+ return "@WIN-RUN-UNTIL-EVENT:";
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
index 1c33a05fbef..0520950e461 100644
--- a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -145,7 +145,7 @@ base::string16 AccessibilityWinBrowserTest::PrintAXTree() const {
DCHECK(formatter);
formatter->set_show_ids(true);
formatter->SetPropertyFilters({AccessibilityTreeFormatter::PropertyFilter(
- L"*", AccessibilityTreeFormatter::PropertyFilter::ALLOW)});
+ "*", AccessibilityTreeFormatter::PropertyFilter::ALLOW)});
base::string16 str;
formatter->FormatAccessibilityTreeForTesting(
@@ -2697,19 +2697,16 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestSetSelectionRanges) {
ranges = nullptr;
n_ranges = 0;
- // For native plain text fields, e.g. input and textarea, anchor and active
- // offsets are always swapped to be in ascending order by the renderer. The
- // selection's directionality is lost.
hr = ax_input->get_selectionRanges(&ranges, &n_ranges);
EXPECT_EQ(S_OK, hr);
EXPECT_EQ(1, n_ranges);
ASSERT_NE(nullptr, ranges);
ASSERT_NE(nullptr, ranges[0].anchor);
EXPECT_EQ(ax_input.Get(), ranges[0].anchor);
- EXPECT_EQ(1, ranges[0].anchorOffset);
+ EXPECT_EQ(contents_string_length, ranges[0].anchorOffset);
ASSERT_NE(nullptr, ranges[0].active);
EXPECT_EQ(ax_input.Get(), ranges[0].active);
- EXPECT_EQ(contents_string_length, ranges[0].activeOffset);
+ EXPECT_EQ(1, ranges[0].activeOffset);
ranges[0].anchor->Release();
ranges[0].active->Release();
@@ -2717,6 +2714,94 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestSetSelectionRanges) {
ranges = nullptr;
}
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+ TestSetSelectionRangesIFrame) {
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLoadComplete);
+ GURL url(
+ "data:text/html,"
+ "<!doctype html><html><body>"
+ "Text before iframe"
+ "<iframe src='data:text/html,"
+ "<!doctype html><html><body>"
+ "<button>Text in iframe</button></body></html>"
+ "'></iframe>"
+ "<button>Text after iframe</button>"
+ "</body></html>");
+ ASSERT_TRUE(NavigateToURL(shell(), url));
+ waiter.WaitForNotification();
+ WaitForAccessibilityTreeToContainNodeWithName(shell()->web_contents(),
+ "Text in iframe");
+
+ Microsoft::WRL::ComPtr<IAccessible> document(GetRendererAccessible());
+ std::vector<base::win::ScopedVariant> document_children =
+ GetAllAccessibleChildren(document.Get());
+ ASSERT_EQ(1u, document_children.size());
+ Microsoft::WRL::ComPtr<IAccessible2> body_iaccessible2;
+ ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2(
+ GetAccessibleFromVariant(document.Get(), document_children[0].AsInput())
+ .Get(),
+ &body_iaccessible2));
+
+ std::vector<base::win::ScopedVariant> body_children =
+ GetAllAccessibleChildren(body_iaccessible2.Get());
+ ASSERT_EQ(3u, body_children.size());
+
+ Microsoft::WRL::ComPtr<IAccessible2> iframe;
+ ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2(
+ GetAccessibleFromVariant(document.Get(), body_children[1].AsInput())
+ .Get(),
+ &iframe));
+
+ std::vector<base::win::ScopedVariant> iframe_children =
+ GetAllAccessibleChildren(iframe.Get());
+ ASSERT_EQ(1u, iframe_children.size());
+
+ Microsoft::WRL::ComPtr<IAccessible2> iframe_body;
+ ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2(
+ GetAccessibleFromVariant(document.Get(), iframe_children[0].AsInput())
+ .Get(),
+ &iframe_body));
+
+ std::vector<base::win::ScopedVariant> iframe_body_children =
+ GetAllAccessibleChildren(iframe_body.Get());
+ ASSERT_EQ(1u, iframe_body_children.size());
+
+ Microsoft::WRL::ComPtr<IAccessible2> text_in_iframe;
+ ASSERT_HRESULT_SUCCEEDED(
+ QueryIAccessible2(GetAccessibleFromVariant(
+ document.Get(), iframe_body_children[0].AsInput())
+ .Get(),
+ &text_in_iframe));
+
+ Microsoft::WRL::ComPtr<IAccessible2> text_after_iframe;
+ ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2(
+ GetAccessibleFromVariant(document.Get(), body_children[2].AsInput())
+ .Get(),
+ &text_after_iframe));
+
+ Microsoft::WRL::ComPtr<IAccessible2_4> text_after_iframe_iaccessible2_4;
+ ASSERT_HRESULT_SUCCEEDED(
+ text_after_iframe.As(&text_after_iframe_iaccessible2_4));
+
+ LONG n_ranges = 1;
+ IA2Range* ranges =
+ reinterpret_cast<IA2Range*>(CoTaskMemAlloc(sizeof(IA2Range)));
+ ranges[0].anchor = text_in_iframe.Get();
+ ranges[0].anchorOffset = 0;
+ ranges[0].active = text_after_iframe.Get();
+ ranges[0].activeOffset = 2;
+
+ // This is expected to fail because the anchor and focus nodes are in
+ // different trees, which Blink doesn't support.
+ EXPECT_HRESULT_FAILED(
+ text_after_iframe_iaccessible2_4->setSelectionRanges(n_ranges, ranges));
+
+ CoTaskMemFree(ranges);
+ ranges = nullptr;
+}
+
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestMultiLineSetSelection) {
Microsoft::WRL::ComPtr<IAccessibleText> textarea_text;
SetUpTextareaField(&textarea_text);
@@ -2816,19 +2901,16 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
ranges = nullptr;
n_ranges = 0;
- // For native plain text fields, e.g. input and textarea, anchor and active
- // offsets are always swapped to be in ascending order by the renderer. The
- // selection's directionality is lost.
hr = ax_textarea->get_selectionRanges(&ranges, &n_ranges);
EXPECT_EQ(S_OK, hr);
EXPECT_EQ(1, n_ranges);
ASSERT_NE(nullptr, ranges);
ASSERT_NE(nullptr, ranges[0].anchor);
EXPECT_EQ(ax_textarea.Get(), ranges[0].anchor);
- EXPECT_EQ(0, ranges[0].anchorOffset);
+ EXPECT_EQ(contents_string_length - 1, ranges[0].anchorOffset);
ASSERT_NE(nullptr, ranges[0].active);
EXPECT_EQ(ax_textarea.Get(), ranges[0].active);
- EXPECT_EQ(contents_string_length - 1, ranges[0].activeOffset);
+ EXPECT_EQ(0, ranges[0].activeOffset);
ranges[0].anchor->Release();
ranges[0].active->Release();
@@ -3684,57 +3766,62 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
Microsoft::WRL::ComPtr<IAccessibleText> input_text;
SetUpInputField(&input_text);
- // Trailing punctuation should be included as part of the previous word.
- CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_WORD, 0, 4, L"Moz/");
- CheckTextAtOffset(input_text, 2, IA2_TEXT_BOUNDARY_WORD, 0, 4, L"Moz/");
+ // Trailing punctuation should not be included as part of the previous word.
+ CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_WORD, 0, 3, L"Moz");
+ CheckTextAtOffset(input_text, 2, IA2_TEXT_BOUNDARY_WORD, 0, 3, L"Moz");
// If the offset is at the punctuation, it should return
- // the previous word.
- CheckTextAtOffset(input_text, 3, IA2_TEXT_BOUNDARY_WORD, 0, 4, L"Moz/");
+ // the punctuation as a word.
+ CheckTextAtOffset(input_text, 3, IA2_TEXT_BOUNDARY_WORD, 3, 4, L"/");
// Numbers with a decimal point ("." for U.S), should be treated as one word.
- // Also, trailing punctuation that occurs after empty space should be part of
- // the word. ("5.0 (" and not "5.0 ".)
- CheckTextAtOffset(input_text, 4, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
- CheckTextAtOffset(input_text, 5, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
- CheckTextAtOffset(input_text, 6, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
- CheckTextAtOffset(input_text, 7, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
+ // Also, trailing punctuation that occurs after empty space should not be part
+ // of the word. ("5.0 " and not "5.0 (".)
+ CheckTextAtOffset(input_text, 4, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
+ CheckTextAtOffset(input_text, 5, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
+ CheckTextAtOffset(input_text, 6, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
+ CheckTextAtOffset(input_text, 7, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
// Leading punctuation should not be included with the word after it.
- CheckTextAtOffset(input_text, 8, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
+ CheckTextAtOffset(input_text, 8, IA2_TEXT_BOUNDARY_WORD, 8, 9, L"(");
CheckTextAtOffset(input_text, 11, IA2_TEXT_BOUNDARY_WORD, 9, 12, L"ST ");
// Numbers separated from letters with trailing punctuation should
- // be split into two words. Same for abreviations like "i.e.".
- CheckTextAtOffset(input_text, 12, IA2_TEXT_BOUNDARY_WORD, 12, 14, L"6.");
- CheckTextAtOffset(input_text, 15, IA2_TEXT_BOUNDARY_WORD, 14, 17, L"x; ");
+ // be split into multiple words. Same for abbreviations like "i.e.".
+ CheckTextAtOffset(input_text, 12, IA2_TEXT_BOUNDARY_WORD, 12, 13, L"6");
+ CheckTextAtOffset(input_text, 13, IA2_TEXT_BOUNDARY_WORD, 13, 14, L".");
+ CheckTextAtOffset(input_text, 14, IA2_TEXT_BOUNDARY_WORD, 14, 15, L"x");
+ CheckTextAtOffset(input_text, 15, IA2_TEXT_BOUNDARY_WORD, 15, 17, L"; ");
// Words with numbers should be treated like ordinary words.
- CheckTextAtOffset(input_text, 17, IA2_TEXT_BOUNDARY_WORD, 17, 24, L"WWW33) ");
- CheckTextAtOffset(input_text, 23, IA2_TEXT_BOUNDARY_WORD, 17, 24, L"WWW33) ");
+ CheckTextAtOffset(input_text, 17, IA2_TEXT_BOUNDARY_WORD, 17, 22, L"WWW33");
+ CheckTextAtOffset(input_text, 23, IA2_TEXT_BOUNDARY_WORD, 22, 24, L") ");
// Multiple trailing empty spaces should be part of the word preceding it.
- CheckTextAtOffset(input_text, 28, IA2_TEXT_BOUNDARY_WORD, 24, 33,
- L"WebKit \"");
- CheckTextAtOffset(input_text, 31, IA2_TEXT_BOUNDARY_WORD, 24, 33,
- L"WebKit \"");
- CheckTextAtOffset(input_text, 32, IA2_TEXT_BOUNDARY_WORD, 24, 33,
- L"WebKit \"");
-
- // Leading punctuation such as quotation marks should not be part of the word.
- CheckTextAtOffset(input_text, 33, IA2_TEXT_BOUNDARY_WORD, 33, 40, L"KHTML, ");
- CheckTextAtOffset(input_text, 38, IA2_TEXT_BOUNDARY_WORD, 33, 40, L"KHTML, ");
-
- // Trailing final punctuation should be part of the last word.
+ CheckTextAtOffset(input_text, 28, IA2_TEXT_BOUNDARY_WORD, 24, 32,
+ L"WebKit ");
+ CheckTextAtOffset(input_text, 31, IA2_TEXT_BOUNDARY_WORD, 24, 32,
+ L"WebKit ");
+ CheckTextAtOffset(input_text, 32, IA2_TEXT_BOUNDARY_WORD, 32, 33, L"\"");
+
+ // Leading and trailing punctuation such as quotation marks should not be part
+ // of the word.
+ CheckTextAtOffset(input_text, 33, IA2_TEXT_BOUNDARY_WORD, 33, 38, L"KHTML");
+ CheckTextAtOffset(input_text, 38, IA2_TEXT_BOUNDARY_WORD, 38, 40, L", ");
+ CheckTextAtOffset(input_text, 39, IA2_TEXT_BOUNDARY_WORD, 38, 40, L", ");
+
+ // Trailing final punctuation should not be part of the last word.
int contents_string_length = int{InputContentsString().size()};
- CheckTextAtOffset(input_text, 41, IA2_TEXT_BOUNDARY_WORD, 40,
- contents_string_length, L"like\".");
- CheckTextAtOffset(input_text, 45, IA2_TEXT_BOUNDARY_WORD, 40,
- contents_string_length, L"like\".");
+ CheckTextAtOffset(input_text, 40, IA2_TEXT_BOUNDARY_WORD, 40, 44, L"like");
+ CheckTextAtOffset(input_text, 41, IA2_TEXT_BOUNDARY_WORD, 40, 44, L"like");
+ CheckTextAtOffset(input_text, 44, IA2_TEXT_BOUNDARY_WORD, 44,
+ contents_string_length, L"\".");
+ CheckTextAtOffset(input_text, 45, IA2_TEXT_BOUNDARY_WORD, 44,
+ contents_string_length, L"\".");
// Test special offsets.
CheckTextAtOffset(input_text, IA2_TEXT_OFFSET_CARET, IA2_TEXT_BOUNDARY_WORD,
- 40, contents_string_length, L"like\".");
+ 44, contents_string_length, L"\".");
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
@@ -3742,62 +3829,64 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
Microsoft::WRL::ComPtr<IAccessibleText> textarea_text;
SetUpTextareaField(&textarea_text);
- // Trailing punctuation should be included as part of the previous word.
- CheckTextAtOffset(textarea_text, 0, IA2_TEXT_BOUNDARY_WORD, 0, 4, L"Moz/");
- CheckTextAtOffset(textarea_text, 2, IA2_TEXT_BOUNDARY_WORD, 0, 4, L"Moz/");
+ // Trailing punctuation should not be included as part of the previous word.
+ CheckTextAtOffset(textarea_text, 0, IA2_TEXT_BOUNDARY_WORD, 0, 3, L"Moz");
+ CheckTextAtOffset(textarea_text, 2, IA2_TEXT_BOUNDARY_WORD, 0, 3, L"Moz");
// If the offset is at the punctuation, it should return
- // the previous word.
- CheckTextAtOffset(textarea_text, 3, IA2_TEXT_BOUNDARY_WORD, 0, 4, L"Moz/");
+ // the punctuation as a word.
+ CheckTextAtOffset(textarea_text, 3, IA2_TEXT_BOUNDARY_WORD, 3, 4, L"/");
// Numbers with a decimal point ("." for U.S), should be treated as one word.
- // Also, trailing punctuation that occurs after empty space should be part of
- // the word. ("5.0 (" and not "5.0 ".)
- CheckTextAtOffset(textarea_text, 4, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
- CheckTextAtOffset(textarea_text, 5, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
- CheckTextAtOffset(textarea_text, 6, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
- CheckTextAtOffset(textarea_text, 7, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
+ // Also, trailing punctuation that occurs after empty space should not be part
+ // of the word. ("5.0 " and not "5.0 (".)
+ CheckTextAtOffset(textarea_text, 4, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
+ CheckTextAtOffset(textarea_text, 5, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
+ CheckTextAtOffset(textarea_text, 6, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
+ CheckTextAtOffset(textarea_text, 7, IA2_TEXT_BOUNDARY_WORD, 4, 8, L"5.0 ");
// Leading punctuation should not be included with the word after it.
- CheckTextAtOffset(textarea_text, 8, IA2_TEXT_BOUNDARY_WORD, 4, 9, L"5.0 (");
+ CheckTextAtOffset(textarea_text, 8, IA2_TEXT_BOUNDARY_WORD, 8, 9, L"(");
CheckTextAtOffset(textarea_text, 11, IA2_TEXT_BOUNDARY_WORD, 9, 12, L"ST ");
// Numbers separated from letters with trailing punctuation should
- // be split into two words. Same for abreviations like "i.e.".
- CheckTextAtOffset(textarea_text, 12, IA2_TEXT_BOUNDARY_WORD, 12, 14, L"6.");
- CheckTextAtOffset(textarea_text, 15, IA2_TEXT_BOUNDARY_WORD, 14, 17, L"x; ");
+ // be split into multiple words. Same for abbreviations like "i.e.".
+ CheckTextAtOffset(textarea_text, 12, IA2_TEXT_BOUNDARY_WORD, 12, 13, L"6");
+ CheckTextAtOffset(textarea_text, 13, IA2_TEXT_BOUNDARY_WORD, 13, 14, L".");
+ CheckTextAtOffset(textarea_text, 14, IA2_TEXT_BOUNDARY_WORD, 14, 15, L"x");
+ CheckTextAtOffset(textarea_text, 15, IA2_TEXT_BOUNDARY_WORD, 15, 17, L"; ");
// Words with numbers should be treated like ordinary words.
- CheckTextAtOffset(textarea_text, 17, IA2_TEXT_BOUNDARY_WORD, 17, 24,
- L"WWW33)\n");
- CheckTextAtOffset(textarea_text, 23, IA2_TEXT_BOUNDARY_WORD, 17, 24,
- L"WWW33)\n");
+ CheckTextAtOffset(textarea_text, 17, IA2_TEXT_BOUNDARY_WORD, 17, 22,
+ L"WWW33");
+ CheckTextAtOffset(textarea_text, 23, IA2_TEXT_BOUNDARY_WORD, 22, 24, L")\n");
// Multiple trailing empty spaces should be part of the word preceding it.
- CheckTextAtOffset(textarea_text, 28, IA2_TEXT_BOUNDARY_WORD, 24, 33,
- L"WebKit \n\"");
- CheckTextAtOffset(textarea_text, 31, IA2_TEXT_BOUNDARY_WORD, 24, 33,
- L"WebKit \n\"");
- CheckTextAtOffset(textarea_text, 32, IA2_TEXT_BOUNDARY_WORD, 24, 33,
- L"WebKit \n\"");
-
- // Leading punctuation such as quotation marks should not be part of the word.
- CheckTextAtOffset(textarea_text, 33, IA2_TEXT_BOUNDARY_WORD, 33, 40,
- L"KHTML, ");
- CheckTextAtOffset(textarea_text, 38, IA2_TEXT_BOUNDARY_WORD, 33, 40,
- L"KHTML, ");
-
- // Trailing final punctuation should be part of the last word.
+ CheckTextAtOffset(textarea_text, 28, IA2_TEXT_BOUNDARY_WORD, 24, 32,
+ L"WebKit \n");
+ CheckTextAtOffset(textarea_text, 31, IA2_TEXT_BOUNDARY_WORD, 24, 32,
+ L"WebKit \n");
+ CheckTextAtOffset(textarea_text, 32, IA2_TEXT_BOUNDARY_WORD, 32, 33, L"\"");
+
+ // Leading and trailing punctuation such as quotation marks should not be part
+ // of the word.
+ CheckTextAtOffset(textarea_text, 33, IA2_TEXT_BOUNDARY_WORD, 33, 38,
+ L"KHTML");
+ CheckTextAtOffset(textarea_text, 38, IA2_TEXT_BOUNDARY_WORD, 38, 40, L", ");
+ CheckTextAtOffset(textarea_text, 39, IA2_TEXT_BOUNDARY_WORD, 38, 40, L", ");
+
+ // Trailing final punctuation should not be part of the last word.
int contents_string_length = int{InputContentsString().size()};
- CheckTextAtOffset(textarea_text, 41, IA2_TEXT_BOUNDARY_WORD, 40,
- contents_string_length, L"like\".");
- CheckTextAtOffset(textarea_text, 45, IA2_TEXT_BOUNDARY_WORD, 40,
- contents_string_length, L"like\".");
+ CheckTextAtOffset(textarea_text, 40, IA2_TEXT_BOUNDARY_WORD, 40, 44, L"like");
+ CheckTextAtOffset(textarea_text, 41, IA2_TEXT_BOUNDARY_WORD, 40, 44, L"like");
+ CheckTextAtOffset(textarea_text, 44, IA2_TEXT_BOUNDARY_WORD, 44,
+ contents_string_length, L"\".");
+ CheckTextAtOffset(textarea_text, 45, IA2_TEXT_BOUNDARY_WORD, 44,
+ contents_string_length, L"\".");
// Test special offsets.
CheckTextAtOffset(textarea_text, IA2_TEXT_OFFSET_CARET,
- IA2_TEXT_BOUNDARY_WORD, 40, contents_string_length,
- L"like\".");
+ IA2_TEXT_BOUNDARY_WORD, 44, contents_string_length, L"\".");
}
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
@@ -3806,23 +3895,12 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
SetUpSampleParagraph(&paragraph_text);
base::string16 embedded_character(
1, BrowserAccessibilityComWin::kEmbeddedCharacter);
- std::vector<std::wstring> words;
- words.push_back(L"Game ");
- words.push_back(L"theory ");
- words.push_back(L"is \"");
- words.push_back(L"the ");
- words.push_back(L"study ");
- words.push_back(L"of ");
- words.push_back(embedded_character);
- words.push_back(L"of ");
- words.push_back(L"conflict ");
- words.push_back(L"and\n");
- words.push_back(L"cooperation ");
- words.push_back(L"between ");
- words.push_back(L"intelligent ");
- words.push_back(L"rational ");
- words.push_back(L"decision-");
- words.push_back(L"makers.\"");
+ std::vector<std::wstring> words = {
+ L"Game ", L"theory ", L"is ", L"\"",
+ L"the ", L"study ", L"of ", embedded_character,
+ L"of ", L"conflict ", L"and\n", L"cooperation ",
+ L"between ", L"intelligent ", L"rational ", L"decision",
+ L"-", L"makers", L".\""};
// Try to retrieve one word after another.
LONG word_start_offset = 0;
diff --git a/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc b/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
index 196d21f1e80..5d8fd52a23f 100644
--- a/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
+++ b/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
@@ -160,10 +160,10 @@ IN_PROC_BROWSER_TEST_F(AndroidGranularityMovementBrowserTest,
BrowserAccessibility* button = button_container->PlatformGetChild(0);
ASSERT_EQ(0U, button->PlatformChildCount());
- ASSERT_EQ(base::ASCIIToUTF16("'O', 'n', 'e', ',', ' ', 't', 'w', 'o', "
+ EXPECT_EQ(base::ASCIIToUTF16("'O', 'n', 'e', ',', ' ', 't', 'w', 'o', "
"',', ' ', 't', 'h', 'r', 'e', 'e', '!'"),
TraverseNodeAtGranularity(para, GRANULARITY_CHARACTER));
- ASSERT_EQ(
+ EXPECT_EQ(
base::ASCIIToUTF16("'S', 'e', 'v', 'e', 'n', ',', ' ', 'e', 'i', 'g', "
"'h', 't', ',', ' ', 'n', 'i', 'n', 'e', '!'"),
TraverseNodeAtGranularity(button, GRANULARITY_CHARACTER));
@@ -187,9 +187,9 @@ IN_PROC_BROWSER_TEST_F(AndroidGranularityMovementBrowserTest, NavigateByWords) {
BrowserAccessibility* button = button_container->PlatformGetChild(0);
ASSERT_EQ(0U, button->PlatformChildCount());
- ASSERT_EQ(base::ASCIIToUTF16("'One', 'two', 'three'"),
+ EXPECT_EQ(base::ASCIIToUTF16("'One', ',', 'two', ',', 'three', '!'"),
TraverseNodeAtGranularity(para, GRANULARITY_WORD));
- ASSERT_EQ(base::ASCIIToUTF16("'Seven', 'eight', 'nine'"),
+ EXPECT_EQ(base::ASCIIToUTF16("'Seven', 'eight', 'nine'"),
TraverseNodeAtGranularity(button, GRANULARITY_WORD));
}
@@ -204,7 +204,7 @@ IN_PROC_BROWSER_TEST_F(AndroidGranularityMovementBrowserTest, NavigateByLine) {
BrowserAccessibility* pre = root->PlatformGetChild(0);
ASSERT_EQ(0U, pre->PlatformChildCount());
- ASSERT_EQ(base::ASCIIToUTF16("'One,', 'two,', 'three!'"),
+ EXPECT_EQ(base::ASCIIToUTF16("'One,', 'two,', 'three!'"),
TraverseNodeAtGranularity(pre, GRANULARITY_LINE));
}
diff --git a/chromium/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc b/chromium/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
index 164a92b2a15..f24424ba53c 100644
--- a/chromium/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
+++ b/chromium/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
@@ -2237,30 +2237,30 @@ IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
EntireMarkupSuccessiveMoveByWord) {
- AssertMoveByUnitForMarkup(TextUnit_Word, "this is a test.",
- {L"this ", L"is ", L"a ", L"test."});
+ AssertMoveByUnitForMarkup(TextUnit_Word, "This is a test.",
+ {L"This ", L"is ", L"a ", L"test", L"."});
AssertMoveByUnitForMarkup(TextUnit_Word,
- " this is a test. ",
- {L"this ", L"is ", L"a ", L"test."});
+ " This is a test. ",
+ {L"This ", L"is ", L"a ", L"test", L"."});
AssertMoveByUnitForMarkup(
TextUnit_Word, "It said: to be continued...",
- {L"It ", L"said: ", L"to ", L"be ", L"continued..."});
+ {L"It ", L"said", L": ", L"to ", L"be ", L"continued", L"..."});
AssertMoveByUnitForMarkup(TextUnit_Word,
- "a <a>link with multiple words</a> and text after.",
- {L"a ", L"link ", L"with ", L"multiple ", L"words",
- L"and ", L"text ", L"after."});
+ "A <a>link with multiple words</a> and text after.",
+ {L"A ", L"link ", L"with ", L"multiple ", L"words",
+ L"and ", L"text ", L"after", L"."});
AssertMoveByUnitForMarkup(TextUnit_Word,
- "a <span aria-hidden='true'>span with ignored "
+ "A <span aria-hidden='true'>span with ignored "
"text</span> and text after.",
- {L"a ", L"and ", L"text ", L"after."});
+ {L"A ", L"and ", L"text ", L"after", L"."});
AssertMoveByUnitForMarkup(
TextUnit_Word, "<ol><li>item one</li><li>item two</li></ol>",
- {L"1. ", L"item ", L"one", L"2. ", L"item ", L"two"});
+ {L"1", L". ", L"item ", L"one", L"2", L". ", L"item ", L"two"});
// The following test should be enabled when crbug.com/1028830 is fixed.
// AssertMoveByUnitForMarkup(TextUnit_Word,
@@ -2488,4 +2488,62 @@ IN_PROC_BROWSER_TEST_F(
AssertMoveByUnitForMarkup(TextUnit_Format, html_markup, format_units);
}
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextRangeProviderWinBrowserTest,
+ IframeSelect) {
+ LoadInitialAccessibilityTreeFromHtmlFilePath(
+ "/accessibility/html/iframe-cross-process.html");
+
+ WaitForAccessibilityTreeToContainNodeWithName(shell()->web_contents(),
+ "Text in iframe");
+
+ auto* node = FindNode(ax::mojom::Role::kStaticText, "Text in iframe");
+ ASSERT_NE(nullptr, node);
+
+ ComPtr<ITextRangeProvider> text_range_provider;
+ GetTextRangeProviderFromTextNode(*node, &text_range_provider);
+ ASSERT_NE(nullptr, text_range_provider.Get());
+ EXPECT_UIA_TEXTRANGE_EQ(text_range_provider, L"Text in iframe");
+
+ // First select text entirely in the iframe. To prevent test timeouts, only
+ // validate the next selection, which spans outside of the iframe.
+ EXPECT_HRESULT_SUCCEEDED(text_range_provider->Select());
+
+ // Move the endpoint so it spans outside of the text range and ensure
+ // selection still works.
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Document,
+ /*count*/ 1,
+ /*expected_text*/ L"Text in iframe\nAfter frame",
+ /*expected_count*/ 1);
+
+ // Validiate this selection with a waiter.
+ AccessibilityNotificationWaiter waiter(
+ shell()->web_contents(), ui::kAXModeComplete,
+ ax::mojom::Event::kDocumentSelectionChanged);
+ EXPECT_HRESULT_SUCCEEDED(text_range_provider->Select());
+
+ waiter.WaitForNotification();
+ ui::AXTree::Selection selection = node->GetUnignoredSelection();
+ EXPECT_EQ(selection.anchor_object_id, node->GetId());
+ EXPECT_EQ(selection.anchor_offset, 0);
+ EXPECT_EQ(selection.focus_object_id, node->GetId());
+ EXPECT_EQ(selection.focus_offset, 14);
+
+ // Now move the start position to outside of the iframe and select.
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Document,
+ /*count*/ -1,
+ /*expected_text*/ L"Before frame\nText in iframe\nAfter frame",
+ /*expected_count*/ -1);
+ EXPECT_HRESULT_SUCCEEDED(text_range_provider->Select());
+
+ // Now move the end position so it's inside of the iframe.
+ EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT(
+ text_range_provider, TextPatternRangeEndpoint_End, TextUnit_Character,
+ /*count*/ -12,
+ /*expected_text*/ L"Before frame\nText in ifram",
+ /*expected_count*/ -12);
+ EXPECT_HRESULT_SUCCEEDED(text_range_provider->Select());
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility.cc b/chromium/content/browser/accessibility/browser_accessibility.cc
index a84e5a94575..013b4fb4640 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility.cc
@@ -112,10 +112,6 @@ bool BrowserAccessibility::PlatformIsLeaf() const {
return IsLeaf();
}
-bool BrowserAccessibility::PlatformIsLeafIncludingIgnored() const {
- return node()->IsLeafIncludingIgnored();
-}
-
bool BrowserAccessibility::CanFireEvents() const {
// Allow events unless this object would be trimmed away.
return !IsChildOfLeaf();
@@ -207,10 +203,6 @@ bool BrowserAccessibility::IsIgnored() const {
return node()->IsIgnored();
}
-bool BrowserAccessibility::IsTextOnlyObject() const {
- return node()->IsText();
-}
-
bool BrowserAccessibility::IsLineBreakObject() const {
return node()->IsLineBreak();
}
@@ -556,11 +548,11 @@ gfx::Rect BrowserAccessibility::GetRootFrameHypertextRangeBoundsRect(
// Child objects are of length one, since they are represented by a single
// embedded object character. The exception is text-only objects.
int child_length_in_parent = 1;
- if (child->IsTextOnlyObject())
+ if (child->IsText())
child_length_in_parent = static_cast<int>(child->GetHypertext().size());
if (start < child_length_in_parent) {
gfx::Rect child_rect;
- if (child->IsTextOnlyObject()) {
+ if (child->IsText()) {
child_rect = child->GetRootFrameHypertextRangeBoundsRect(
start, len, clipping_behavior, offscreen_result);
} else {
@@ -668,25 +660,25 @@ gfx::Rect BrowserAccessibility::GetRootFrameHypertextBoundsPastEndOfText(
}
// Step 2: correct for the thickness of the caret.
- auto text_direction = static_cast<ax::mojom::TextDirection>(
+ auto text_direction = static_cast<ax::mojom::WritingDirection>(
GetIntAttribute(ax::mojom::IntAttribute::kTextDirection));
constexpr int kCaretThickness = 1;
switch (text_direction) {
- case ax::mojom::TextDirection::kNone:
- case ax::mojom::TextDirection::kLtr: {
+ case ax::mojom::WritingDirection::kNone:
+ case ax::mojom::WritingDirection::kLtr: {
bounds.set_width(kCaretThickness);
break;
}
- case ax::mojom::TextDirection::kRtl: {
+ case ax::mojom::WritingDirection::kRtl: {
bounds.set_x(bounds.right() - kCaretThickness);
bounds.set_width(kCaretThickness);
break;
}
- case ax::mojom::TextDirection::kTtb: {
+ case ax::mojom::WritingDirection::kTtb: {
bounds.set_height(kCaretThickness);
break;
}
- case ax::mojom::TextDirection::kBtt: {
+ case ax::mojom::WritingDirection::kBtt: {
bounds.set_y(bounds.bottom() - kCaretThickness);
bounds.set_height(kCaretThickness);
break;
@@ -795,25 +787,25 @@ gfx::RectF BrowserAccessibility::GetInlineTextRect(const int start_offset,
const int location_height = location.height();
gfx::RectF bounds;
- switch (static_cast<ax::mojom::TextDirection>(
+ switch (static_cast<ax::mojom::WritingDirection>(
GetIntAttribute(ax::mojom::IntAttribute::kTextDirection))) {
- case ax::mojom::TextDirection::kNone:
- case ax::mojom::TextDirection::kLtr:
+ case ax::mojom::WritingDirection::kNone:
+ case ax::mojom::WritingDirection::kLtr:
bounds =
gfx::RectF(start_pixel_offset, 0,
end_pixel_offset - start_pixel_offset, location_height);
break;
- case ax::mojom::TextDirection::kRtl: {
+ case ax::mojom::WritingDirection::kRtl: {
const int left = max_pixel_offset - end_pixel_offset;
const int right = max_pixel_offset - start_pixel_offset;
bounds = gfx::RectF(left, 0, right - left, location_height);
break;
}
- case ax::mojom::TextDirection::kTtb:
+ case ax::mojom::WritingDirection::kTtb:
bounds = gfx::RectF(0, start_pixel_offset, location_width,
end_pixel_offset - start_pixel_offset);
break;
- case ax::mojom::TextDirection::kBtt: {
+ case ax::mojom::WritingDirection::kBtt: {
const int top = max_pixel_offset - end_pixel_offset;
const int bottom = max_pixel_offset - start_pixel_offset;
bounds = gfx::RectF(0, top, location_width, bottom - top);
@@ -1228,6 +1220,10 @@ bool BrowserAccessibility::IsMinimized() const {
return false;
}
+bool BrowserAccessibility::IsText() const {
+ return node()->IsText();
+}
+
bool BrowserAccessibility::IsWebContent() const {
return true;
}
@@ -1500,6 +1496,10 @@ gfx::NativeViewAccessible BrowserAccessibility::ChildAtIndex(int index) {
return child->GetNativeViewAccessible();
}
+bool BrowserAccessibility::HasModalDialog() const {
+ return false;
+}
+
gfx::NativeViewAccessible BrowserAccessibility::GetFirstChild() {
BrowserAccessibility* child = PlatformGetFirstChild();
if (!child)
@@ -1549,12 +1549,17 @@ bool BrowserAccessibility::IsLeaf() const {
// children. The only exception to enforce leafiness is when the button has
// a single text child and to prevent screen readers from double speak.
if (GetRole() == ax::mojom::Role::kButton) {
- return InternalChildCount() == 1 &&
- InternalGetFirstChild()->IsTextOnlyObject();
+ uint32_t child_count = InternalChildCount();
+ return !child_count ||
+ (child_count == 1 && InternalGetFirstChild()->IsText());
}
return node()->IsLeaf();
}
+bool BrowserAccessibility::IsToplevelBrowserWindow() {
+ return false;
+}
+
bool BrowserAccessibility::IsChildOfPlainTextField() const {
ui::AXNode* textfield_node = node()->GetTextFieldAncestor();
return textfield_node && textfield_node->data().IsPlainTextField();
@@ -2163,7 +2168,7 @@ std::string BrowserAccessibility::GetInheritedFontFamilyName() const {
ui::TextAttributeMap BrowserAccessibility::GetSpellingAndGrammarAttributes()
const {
ui::TextAttributeMap spelling_attributes;
- if (IsTextOnlyObject()) {
+ if (IsText()) {
const std::vector<int32_t>& marker_types =
GetIntListAttribute(ax::mojom::IntListAttribute::kMarkerTypes);
const std::vector<int>& marker_starts =
@@ -2263,6 +2268,8 @@ ui::TextAttributeMap BrowserAccessibility::ComputeTextAttributeMap(
return attributes_map;
}
+ DCHECK(PlatformChildCount());
+
int start_offset = 0;
for (BrowserAccessibility::PlatformChildIterator it = PlatformChildrenBegin();
it != PlatformChildrenEnd(); ++it) {
@@ -2286,7 +2293,7 @@ ui::TextAttributeMap BrowserAccessibility::ComputeTextAttributeMap(
}
}
- if (child->IsTextOnlyObject()) {
+ if (child->IsText()) {
const ui::TextAttributeMap spelling_attributes =
child->GetSpellingAndGrammarAttributes();
MergeSpellingAndGrammarIntoTextAttributes(spelling_attributes,
diff --git a/chromium/content/browser/accessibility/browser_accessibility.h b/chromium/content/browser/accessibility/browser_accessibility.h
index df1b7977798..16c7908f65c 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.h
+++ b/chromium/content/browser/accessibility/browser_accessibility.h
@@ -41,7 +41,7 @@
#define PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL 1
#endif
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
#define PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL 1
#endif
@@ -53,7 +53,7 @@
#define PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL 1
#endif
-#if defined(OS_MACOSX) && __OBJC__
+#if defined(OS_MAC) && __OBJC__
@class BrowserAccessibilityCocoa;
#endif
@@ -111,17 +111,11 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
bool IsIgnored() const;
- // Returns true if this object is used only for representing text.
- bool IsTextOnlyObject() const;
-
bool IsLineBreakObject() const;
// See AXNode::IsLeaf().
bool PlatformIsLeaf() const;
- // See AXNode::IsLeafIncludingIgnored().
- bool PlatformIsLeafIncludingIgnored() const;
-
// Returns true if this object can fire events.
virtual bool CanFireEvents() const;
@@ -439,6 +433,7 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
gfx::NativeViewAccessible GetParent() override;
int GetChildCount() const override;
gfx::NativeViewAccessible ChildAtIndex(int index) override;
+ bool HasModalDialog() const override;
gfx::NativeViewAccessible GetFirstChild() override;
gfx::NativeViewAccessible GetLastChild() override;
gfx::NativeViewAccessible GetNextSibling() override;
@@ -447,6 +442,7 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
bool IsChildOfLeaf() const override;
bool IsChildOfPlainTextField() const override;
bool IsLeaf() const override;
+ bool IsToplevelBrowserWindow() override;
gfx::NativeViewAccessible GetClosestPlatformObject() const override;
std::unique_ptr<ChildIterator> ChildrenBegin() override;
@@ -538,6 +534,7 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
bool ShouldIgnoreHoveredStateForTesting() override;
bool IsOffscreen() const override;
bool IsMinimized() const override;
+ bool IsText() const override;
bool IsWebContent() const override;
bool HasVisibleCaretOrSelection() const override;
ui::AXPlatformNode* GetTargetNodeForRelation(
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.cc b/chromium/content/browser/accessibility/browser_accessibility_android.cc
index c219569e5e4..2aae62b5648 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.cc
@@ -55,8 +55,6 @@ enum { ANDROID_VIEW_ACCESSIBILITY_RANGE_TYPE_FLOAT = 1 };
namespace content {
-const float kContentInvalidTimeoutMillisecs = 6000.0;
-
// static
BrowserAccessibility* BrowserAccessibility::Create() {
return new BrowserAccessibilityAndroid();
@@ -176,20 +174,6 @@ bool BrowserAccessibilityAndroid::IsCollectionItem() const {
}
bool BrowserAccessibilityAndroid::IsContentInvalid() const {
- if (IsFocused()) {
- // When a node has focus, only report that it's invalid for a short period
- // of time. Otherwise it's annoying to hear the invalid message every time
- // a character is entered.
- if (content_invalid_timer_.Elapsed().InMillisecondsF() <
- kContentInvalidTimeoutMillisecs) {
- bool invalid_state =
- HasIntAttribute(ax::mojom::IntAttribute::kInvalidState) &&
- GetData().GetInvalidState() != ax::mojom::InvalidState::kFalse;
- if (invalid_state)
- return true;
- }
- return false;
- }
return HasIntAttribute(ax::mojom::IntAttribute::kInvalidState) &&
GetData().GetInvalidState() != ax::mojom::InvalidState::kFalse;
}
@@ -269,6 +253,10 @@ bool BrowserAccessibilityAndroid::IsMultiLine() const {
return HasState(ax::mojom::State::kMultiline);
}
+bool BrowserAccessibilityAndroid::IsMultiselectable() const {
+ return HasState(ax::mojom::State::kMultiselectable);
+}
+
bool BrowserAccessibilityAndroid::IsRangeType() const {
return (GetRole() == ax::mojom::Role::kProgressIndicator ||
GetRole() == ax::mojom::Role::kMeter ||
@@ -378,7 +366,7 @@ BrowserAccessibilityAndroid::GetSoleInterestingNodeFromSubtree() const {
}
bool BrowserAccessibilityAndroid::AreInlineTextBoxesLoaded() const {
- if (GetRole() == ax::mojom::Role::kStaticText)
+ if (IsText())
return InternalChildCount() > 0;
// Return false if any descendant needs to load inline text boxes.
@@ -550,6 +538,47 @@ base::string16 BrowserAccessibilityAndroid::GetHint() const {
return base::JoinString(strings, base::ASCIIToUTF16(" "));
}
+base::string16 BrowserAccessibilityAndroid::GetStateDescription() const {
+ // For multiselectable state, generate a state description
+ if (IsMultiselectable())
+ return GetMultiselectableStateDescription();
+
+ // Otherwise we will not use state description
+ return base::string16();
+}
+
+base::string16 BrowserAccessibilityAndroid::GetMultiselectableStateDescription()
+ const {
+ content::ContentClient* content_client = content::GetContentClient();
+
+ // Count the number of children and selected children.
+ int child_count = 0;
+ int selected_count = 0;
+ for (PlatformChildIterator it = PlatformChildrenBegin();
+ it != PlatformChildrenEnd(); ++it) {
+ child_count++;
+ BrowserAccessibilityAndroid* child =
+ static_cast<BrowserAccessibilityAndroid*>(it.get());
+ if (child->IsSelected())
+ selected_count++;
+ }
+
+ // If none are selected, return special case.
+ if (!selected_count)
+ return content_client->GetLocalizedString(
+ IDS_AX_MULTISELECTABLE_STATE_DESCRIPTION_NONE);
+
+ // Generate a state description of the form: "multiselectable, x of y
+ // selected.".
+ std::vector<base::string16> values;
+ values.push_back(base::NumberToString16(selected_count));
+ values.push_back(base::NumberToString16(child_count));
+ return base::ReplaceStringPlaceholders(
+ content_client->GetLocalizedString(
+ IDS_AX_MULTISELECTABLE_STATE_DESCRIPTION),
+ values, nullptr);
+}
+
std::string BrowserAccessibilityAndroid::GetRoleString() const {
return ui::ToString(GetRole());
}
@@ -964,8 +993,6 @@ base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
message_id = IDS_AX_ROLE_MENU_BAR;
break;
case ax::mojom::Role::kMenuButton:
- message_id = IDS_AX_ROLE_MENU_BUTTON;
- break;
case ax::mojom::Role::kMenuItem:
message_id = IDS_AX_ROLE_MENU_ITEM;
break;
@@ -1724,7 +1751,7 @@ void BrowserAccessibilityAndroid::GetSuggestions(
BrowserAccessibility* node = InternalGetFirstChild();
int start_offset = 0;
while (node && node != this) {
- if (node->IsTextOnlyObject()) {
+ if (node->IsText()) {
const std::vector<int32_t>& marker_types =
node->GetData().GetIntListAttribute(
ax::mojom::IntListAttribute::kMarkerTypes);
@@ -1801,7 +1828,7 @@ bool BrowserAccessibilityAndroid::HasOnlyTextChildren() const {
// This is called from IsLeaf, so don't call PlatformChildCount
// from within this!
for (auto it = InternalChildrenBegin(); it != InternalChildrenEnd(); ++it) {
- if (!it->IsTextOnlyObject())
+ if (!it->IsText())
return false;
}
return true;
@@ -1812,8 +1839,7 @@ bool BrowserAccessibilityAndroid::HasOnlyTextAndImageChildren() const {
// from within this!
for (auto it = InternalChildrenBegin(); it != InternalChildrenEnd(); ++it) {
BrowserAccessibility* child = it.get();
- if (child->GetRole() != ax::mojom::Role::kStaticText &&
- !ui::IsImageOrVideo(child->GetRole())) {
+ if (!child->IsText() && !ui::IsImageOrVideo(child->GetRole())) {
return false;
}
}
@@ -1908,8 +1934,4 @@ base::string16 BrowserAccessibilityAndroid::GetContentInvalidErrorMessage()
return base::string16();
}
-void BrowserAccessibilityAndroid::ResetContentInvalidTimer() {
- content_invalid_timer_ = base::ElapsedTimer();
-}
-
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.h b/chromium/content/browser/accessibility/browser_accessibility_android.h
index ee55916ca43..ff453ec1d48 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.h
@@ -13,7 +13,6 @@
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
-#include "base/timer/elapsed_timer.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "ui/accessibility/platform/ax_platform_node.h"
@@ -46,6 +45,7 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
bool IsHierarchical() const;
bool IsLink() const;
bool IsMultiLine() const;
+ bool IsMultiselectable() const;
bool IsRangeType() const;
bool IsScrollable() const;
bool IsSelected() const;
@@ -89,6 +89,9 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
base::string16 GetContentInvalidErrorMessage() const;
+ base::string16 GetStateDescription() const;
+ base::string16 GetMultiselectableStateDescription() const;
+
base::string16 GetRoleDescription() const;
int GetItemIndex() const;
@@ -162,11 +165,6 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
void GetSuggestions(std::vector<int>* suggestion_starts,
std::vector<int>* suggestion_ends) const;
- // Used to keep track of when to stop reporting content_invalid.
- // Timer only applies if node has focus.
- void ResetContentInvalidTimer();
- base::ElapsedTimer content_invalid_timer_ = base::ElapsedTimer();
-
private:
// This gives BrowserAccessibility::Create access to the class constructor.
friend class BrowserAccessibility;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc
index e3f0043c295..74fbe552feb 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_auralinux_unittest.cc
@@ -305,6 +305,59 @@ TEST_F(BrowserAccessibilityAuraLinuxTest, TestComplexHypertext) {
manager.reset();
}
+TEST_F(BrowserAccessibilityAuraLinuxTest, TestTextAttributesInButtons) {
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ax::mojom::Role::kRootWebArea;
+ root.AddState(ax::mojom::State::kFocusable);
+
+ ui::AXNodeData button;
+ button.id = 2;
+ button.role = ax::mojom::Role::kButton;
+ button.AddStringAttribute(ax::mojom::StringAttribute::kFontFamily, "Times");
+ root.child_ids.push_back(button.id);
+
+ ui::AXNodeData text;
+ text.id = 3;
+ text.role = ax::mojom::Role::kStaticText;
+ text.SetName("OK");
+ button.child_ids.push_back(text.id);
+
+ ui::AXNodeData empty_button;
+ empty_button.id = 4;
+ empty_button.role = ax::mojom::Role::kButton;
+ empty_button.AddStringAttribute(ax::mojom::StringAttribute::kFontFamily,
+ "Times");
+ root.child_ids.push_back(empty_button.id);
+
+ ui::AXTreeUpdate update = MakeAXTreeUpdate(root, button, text, empty_button);
+ std::unique_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(
+ update, test_browser_accessibility_delegate_.get()));
+
+ BrowserAccessibilityAuraLinux* ax_root =
+ ToBrowserAccessibilityAuraLinux(manager->GetRoot());
+
+ BrowserAccessibilityAuraLinux* ax_button =
+ ToBrowserAccessibilityAuraLinux(ax_root->PlatformGetChild(0));
+ AtkObject* atk_button = ax_button->GetNode()->GetNativeViewAccessible();
+
+ int start_offset, end_offset;
+ AtkAttributeSet* attributes = atk_text_get_run_attributes(
+ ATK_TEXT(atk_button), 0, &start_offset, &end_offset);
+ ASSERT_EQ(1U, g_slist_length(attributes));
+ atk_attribute_set_free(attributes);
+
+ BrowserAccessibilityAuraLinux* ax_empty_button =
+ ToBrowserAccessibilityAuraLinux(ax_root->PlatformGetChild(1));
+ AtkObject* atk_empty_button =
+ ax_empty_button->GetNode()->GetNativeViewAccessible();
+ attributes = atk_text_get_run_attributes(ATK_TEXT(atk_empty_button), 0,
+ &start_offset, &end_offset);
+ ASSERT_EQ(1U, g_slist_length(attributes));
+ atk_attribute_set_free(attributes);
+}
+
TEST_F(BrowserAccessibilityAuraLinuxTest,
TestTextAttributesInContentEditables) {
auto has_attribute = [](AtkAttributeSet* attributes,
@@ -763,4 +816,59 @@ TEST_F(BrowserAccessibilityAuraLinuxTest, TextAtkStaticTextChange) {
EXPECT_STREQ(base::UTF16ToUTF8(div_node->GetHypertext()).c_str(), "Text2");
}
+TEST_F(BrowserAccessibilityAuraLinuxTest, TestAtkTextGetOffesetAtPoint) {
+ ui::AXNodeData static_text1;
+ static_text1.id = 1;
+ static_text1.role = ax::mojom::Role::kStaticText;
+ static_text1.SetName("Hello");
+ static_text1.child_ids = {2};
+
+ ui::AXNodeData inline_box1;
+ inline_box1.id = 2;
+ inline_box1.role = ax::mojom::Role::kInlineTextBox;
+ inline_box1.SetName("Hello");
+ inline_box1.relative_bounds.bounds = gfx::RectF(0, 50, 25, 30);
+ std::vector<int32_t> character_offsets1;
+ // The width of each character is 5px.
+ character_offsets1.push_back(5);
+ character_offsets1.push_back(10);
+ character_offsets1.push_back(15);
+ character_offsets1.push_back(20);
+ character_offsets1.push_back(25);
+ inline_box1.AddIntListAttribute(
+ ax::mojom::IntListAttribute::kCharacterOffsets, character_offsets1);
+ inline_box1.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
+ std::vector<int32_t>{0});
+ inline_box1.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
+ std::vector<int32_t>{5});
+
+ std::unique_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(
+ MakeAXTreeUpdate(static_text1, inline_box1),
+ test_browser_accessibility_delegate_.get()));
+
+ ASSERT_NE(nullptr, manager->GetRoot());
+ BrowserAccessibilityAuraLinux* ax_root =
+ ToBrowserAccessibilityAuraLinux(manager->GetRoot());
+ ASSERT_NE(nullptr, ax_root);
+
+ AtkObject* root_atk_object = ax_root->GetNode()->GetNativeViewAccessible();
+ g_object_ref(root_atk_object);
+ AtkText* atk_text = ATK_TEXT(root_atk_object);
+ ASSERT_TRUE(ATK_IS_TEXT(atk_text));
+
+ int x, y, width, height;
+ char* text = atk_text_get_text(atk_text, 0, -1);
+ int root_text_length = g_utf8_strlen(text, -1);
+ g_free(text);
+ for (int offset = 0; offset < root_text_length; offset++) {
+ atk_text_get_character_extents(atk_text, offset, &x, &y, &width, &height,
+ ATK_XY_SCREEN);
+ int result = atk_text_get_offset_at_point(atk_text, x, y, ATK_XY_SCREEN);
+ ASSERT_EQ(offset, result);
+ }
+ g_object_unref(root_atk_object);
+ manager.reset();
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
index 947a5482780..cb253906ddd 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -12,20 +12,25 @@
#include "base/strings/string16.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/common/content_export.h"
namespace content {
// Used to store changes in edit fields, required by VoiceOver in order to
// support character echo and other announcements during editing.
-struct AXTextEdit {
- AXTextEdit() = default;
- AXTextEdit(base::string16 inserted_text, base::string16 deleted_text)
- : inserted_text(inserted_text), deleted_text(deleted_text) {}
+struct CONTENT_EXPORT AXTextEdit {
+ AXTextEdit();
+ AXTextEdit(base::string16 inserted_text,
+ base::string16 deleted_text,
+ id edit_text_marker);
+ AXTextEdit(const AXTextEdit& other);
+ ~AXTextEdit();
bool IsEmpty() const { return inserted_text.empty() && deleted_text.empty(); }
base::string16 inserted_text;
base::string16 deleted_text;
+ base::scoped_nsprotocol<id> edit_text_marker;
};
// Returns true if the given object is AXTextMarker object.
@@ -35,7 +40,7 @@ bool IsAXTextMarker(id);
bool IsAXTextMarkerRange(id);
// Returns browser accessibility position for the given AXTextMarker.
-BrowserAccessibilityPosition::AXPositionInstance AXTextMarkerToPosition(id);
+CONTENT_EXPORT BrowserAccessibilityPosition::AXPositionInstance AXTextMarkerToPosition(id);
// Returns browser accessibility range for the given AXTextMarkerRange.
BrowserAccessibilityPosition::AXRangeType AXTextMarkerRangeToRange(id);
@@ -45,6 +50,9 @@ id AXTextMarkerFrom(const BrowserAccessibilityCocoa* anchor,
int offset,
ax::mojom::TextAffinity affinity);
+// Returns AXTextMarkerRange for the given browser accessibility positions.
+id AXTextMarkerRangeFrom(id anchor_textmarker, id focus_textmarker);
+
} // namespace content
// BrowserAccessibilityCocoa is a cocoa wrapper around the BrowserAccessibility
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
index 8e2592948d6..d203e3a6a80 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -564,7 +564,7 @@ AccessibilityMatchPredicate PredicateForSearchKey(NSString* searchKey) {
};
} else if ([searchKey isEqualToString:@"AXStaticTextSearchKey"]) {
return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return current->IsTextOnlyObject();
+ return current->IsText();
};
} else if ([searchKey isEqualToString:@"AXStyleChangeSearchKey"]) {
// TODO(dmazzoni): implement this.
@@ -707,6 +707,20 @@ bool IsSelectedStateRelevant(BrowserAccessibility* item) {
} // namespace
+namespace content {
+
+AXTextEdit::AXTextEdit() = default;
+AXTextEdit::AXTextEdit(base::string16 inserted_text,
+ base::string16 deleted_text,
+ id edit_text_marker)
+ : inserted_text(inserted_text),
+ deleted_text(deleted_text),
+ edit_text_marker(edit_text_marker, base::scoped_policy::RETAIN) {}
+AXTextEdit::AXTextEdit(const AXTextEdit& other) = default;
+AXTextEdit::~AXTextEdit() = default;
+
+} // namespace content
+
#if defined(MAC_OS_X_VERSION_10_12) && \
(MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12)
#warning NSAccessibilityRequiredAttributeChrome \
@@ -765,6 +779,12 @@ id content::AXTextMarkerFrom(const BrowserAccessibilityCocoa* anchor,
return CreateTextMarker(std::move(position));
}
+id content::AXTextMarkerRangeFrom(id anchor_textmarker, id focus_textmarker) {
+ AXTextMarkerRangeRef cf_marker_range = AXTextMarkerRangeCreate(
+ kCFAllocatorDefault, anchor_textmarker, focus_textmarker);
+ return [static_cast<id>(cf_marker_range) autorelease];
+}
+
@implementation BrowserAccessibilityCocoa
+ (void)initialize {
@@ -1871,10 +1891,11 @@ id content::AXTextMarkerFrom(const BrowserAccessibilityCocoa* anchor,
if (size_t{sel_start} == newValue.length() &&
size_t{sel_end} == newValue.length()) {
// Don't include oldValue as it would be announced -- very confusing.
- return content::AXTextEdit(newValue, base::string16());
+ return content::AXTextEdit(newValue, base::string16(), nil);
}
}
- return content::AXTextEdit(insertedText, deletedText);
+ return content::AXTextEdit(insertedText, deletedText,
+ CreateTextMarker(_owner->CreatePositionAt(i)));
}
- (BOOL)instanceActive {
@@ -2244,7 +2265,9 @@ id content::AXTextMarkerFrom(const BrowserAccessibilityCocoa* anchor,
- (id)selectedTextMarkerRange {
if (![self instanceActive])
return nil;
- return CreateTextMarkerRange(GetSelectedRange(*_owner));
+ // Voiceover expects this range to be backwards in order to read the selected
+ // words correctly.
+ return CreateTextMarkerRange(GetSelectedRange(*_owner).AsBackwardRange());
}
- (NSValue*)size {
@@ -2607,7 +2630,7 @@ id content::AXTextMarkerFrom(const BrowserAccessibilityCocoa* anchor,
NSMutableAttributedString* attributedInnerText =
[[[NSMutableAttributedString alloc]
initWithString:base::SysUTF16ToNSString(innerText)] autorelease];
- if (!_owner->IsTextOnlyObject()) {
+ if (!_owner->IsText()) {
AXPlatformRange ax_range(_owner->CreatePositionAt(0),
_owner->CreatePositionAt(int{innerText.length()}));
AddMisspelledTextAttributes(ax_range, attributedInnerText);
@@ -3033,7 +3056,7 @@ id content::AXTextMarkerFrom(const BrowserAccessibilityCocoa* anchor,
if ([attribute isEqualToString:
NSAccessibilityBoundsForRangeParameterizedAttribute]) {
- if ([self internalRole] != ax::mojom::Role::kStaticText)
+ if (!_owner->IsText())
return nil;
NSRange range = [(NSValue*)parameter rangeValue];
gfx::Rect rect = _owner->GetUnclippedScreenInnerTextRangeBoundsRect(
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm
index 4148e32e718..48f8d9dbbe3 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa_browsertest.mm
@@ -63,6 +63,43 @@ class BrowserAccessibilityCocoaBrowserTest : public ContentBrowserTest {
} // namespace
IN_PROC_BROWSER_TEST_F(BrowserAccessibilityCocoaBrowserTest,
+ AXTextMarkerForTextEdit) {
+ EXPECT_TRUE(NavigateToURL(shell(), GURL(url::kAboutBlankURL)));
+
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLoadComplete);
+ GURL url(R"HTML(data:text/html,
+ <input />)HTML");
+
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ waiter.WaitForNotification();
+
+ BrowserAccessibility* text_field = FindNode(ax::mojom::Role::kTextField);
+ ASSERT_NE(nullptr, text_field);
+ EXPECT_TRUE(content::ExecuteScript(
+ shell()->web_contents(), "document.querySelector('input').focus()"));
+
+ content::SimulateKeyPress(shell()->web_contents(),
+ ui::DomKey::FromCharacter('B'), ui::DomCode::US_B,
+ ui::VKEY_B, false, false, false, false);
+
+ base::scoped_nsobject<BrowserAccessibilityCocoa> cocoa_text_field(
+ [ToBrowserAccessibilityCocoa(text_field) retain]);
+ AccessibilityNotificationWaiter value_waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kValueChanged);
+ value_waiter.WaitForNotification();
+ AXTextEdit text_edit = [cocoa_text_field computeTextEdit];
+ EXPECT_NE(text_edit.edit_text_marker, nil);
+
+ EXPECT_EQ(
+ content::AXTextMarkerToPosition(text_edit.edit_text_marker)->ToString(),
+ "TextPosition anchor_id=5 text_offset=1 affinity=downstream "
+ "annotated_text=B<>");
+}
+
+IN_PROC_BROWSER_TEST_F(BrowserAccessibilityCocoaBrowserTest,
AXCellForColumnAndRow) {
EXPECT_TRUE(NavigateToURL(shell(), GURL(url::kAboutBlankURL)));
diff --git a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
index a8a043f82b4..ce8fb53107b 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -897,7 +897,7 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_nodeInfo(
if (owner()->IsDocument()) {
*node_type = NODETYPE_DOCUMENT;
- } else if (owner()->IsTextOnlyObject()) {
+ } else if (owner()->IsText()) {
*node_type = NODETYPE_TEXT;
} else {
*node_type = NODETYPE_ELEMENT;
@@ -1447,7 +1447,6 @@ void BrowserAccessibilityComWin::UpdateStep2ComputeHypertext() {
}
void BrowserAccessibilityComWin::UpdateStep3FireEvents() {
- int32_t state = MSAAState();
const bool ignored = owner()->IsIgnored();
// Suppress all of these events when the node is ignored, or when the ignored
@@ -1462,14 +1461,6 @@ void BrowserAccessibilityComWin::UpdateStep3FireEvents() {
if (description() != old_win_attributes_->description)
FireNativeEvent(EVENT_OBJECT_DESCRIPTIONCHANGE);
- // Do not fire EVENT_OBJECT_STATECHANGE if the change was due to a focus
- // change.
- if ((state & ~STATE_SYSTEM_FOCUSED) !=
- (old_win_attributes_->ia_state & ~STATE_SYSTEM_FOCUSED) ||
- ComputeIA2State() != old_win_attributes_->ia2_state) {
- FireNativeEvent(EVENT_OBJECT_STATECHANGE);
- }
-
// Fire an event if this container object has scrolled.
int sx = 0;
int sy = 0;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.cc b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
index 739a19d13eb..6d9157618d7 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
@@ -996,7 +996,7 @@ BrowserAccessibility* BrowserAccessibilityManager::PreviousInTreeOrder(
BrowserAccessibility* BrowserAccessibilityManager::PreviousTextOnlyObject(
const BrowserAccessibility* object) {
BrowserAccessibility* previous_object = PreviousInTreeOrder(object, false);
- while (previous_object && !previous_object->IsTextOnlyObject())
+ while (previous_object && !previous_object->IsText())
previous_object = PreviousInTreeOrder(previous_object, false);
return previous_object;
@@ -1006,7 +1006,7 @@ BrowserAccessibility* BrowserAccessibilityManager::PreviousTextOnlyObject(
BrowserAccessibility* BrowserAccessibilityManager::NextTextOnlyObject(
const BrowserAccessibility* object) {
BrowserAccessibility* next_object = NextInTreeOrder(object);
- while (next_object && !next_object->IsTextOnlyObject())
+ while (next_object && !next_object->IsText())
next_object = NextInTreeOrder(next_object);
return next_object;
@@ -1119,9 +1119,9 @@ BrowserAccessibilityManager::FindTextOnlyObjectsInRange(
if (!end_text_object->PlatformIsLeaf())
end_text_object = end_text_object->PlatformDeepestLastChild();
- if (!start_text_object->IsTextOnlyObject())
+ if (!start_text_object->IsText())
start_text_object = NextTextOnlyObject(start_text_object);
- if (!end_text_object->IsTextOnlyObject())
+ if (!end_text_object->IsText())
end_text_object = PreviousTextOnlyObject(end_text_object);
if (!start_text_object || !end_text_object)
@@ -1190,7 +1190,7 @@ base::string16 BrowserAccessibilityManager::GetTextForRange(
const BrowserAccessibility* start_text_object = text_only_objects[0];
// Figure out if the start and end positions have been reversed.
const BrowserAccessibility* first_object = &start_object;
- if (!first_object->IsTextOnlyObject())
+ if (!first_object->IsText())
first_object = NextTextOnlyObject(first_object);
if (!first_object || first_object != start_text_object)
std::swap(start_offset, end_offset);
@@ -1258,7 +1258,7 @@ gfx::Rect BrowserAccessibilityManager::GetRootFrameInnerTextRangeBoundsRect(
const BrowserAccessibility* current = first;
do {
- if (current->IsTextOnlyObject()) {
+ if (current->IsText()) {
int len = static_cast<int>(current->GetInnerText().size());
int start_char_index = 0;
int end_char_index = len;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.h b/chromium/content/browser/accessibility/browser_accessibility_manager.h
index 809ca3a2ad2..38c9fb063d3 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.h
@@ -49,7 +49,7 @@ class BrowserAccessibilityManagerAndroid;
class BrowserAccessibilityManagerWin;
#elif BUILDFLAG(USE_ATK)
class BrowserAccessibilityManagerAuraLinux;
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
class BrowserAccessibilityManagerMac;
#endif
@@ -346,7 +346,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeObserver,
ToBrowserAccessibilityManagerAuraLinux();
#endif
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
BrowserAccessibilityManagerMac* ToBrowserAccessibilityManagerMac();
#endif
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
index d52cec13ea1..7abd3eb7e4d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -129,7 +129,6 @@ void BrowserAccessibilityManagerAndroid::FireFocusEvent(
return;
BrowserAccessibilityAndroid* android_node =
static_cast<BrowserAccessibilityAndroid*>(node);
- android_node->ResetContentInvalidTimer();
wcax->HandleFocusChanged(android_node->unique_id());
}
@@ -267,6 +266,7 @@ void BrowserAccessibilityManagerAndroid::FireGeneratedEvent(
case ui::AXEventGenerator::Event::MULTILINE_STATE_CHANGED:
case ui::AXEventGenerator::Event::MULTISELECTABLE_STATE_CHANGED:
case ui::AXEventGenerator::Event::NAME_CHANGED:
+ case ui::AXEventGenerator::Event::OBJECT_ATTRIBUTE_CHANGED:
case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
case ui::AXEventGenerator::Event::PLACEHOLDER_CHANGED:
case ui::AXEventGenerator::Event::PORTAL_ACTIVATED:
@@ -282,9 +282,11 @@ void BrowserAccessibilityManagerAndroid::FireGeneratedEvent(
case ui::AXEventGenerator::Event::SORT_CHANGED:
case ui::AXEventGenerator::Event::STATE_CHANGED:
case ui::AXEventGenerator::Event::SUBTREE_CREATED:
+ case ui::AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
+ case ui::AXEventGenerator::Event::WIN_IACCESSIBLE_STATE_CHANGED:
// There are some notifications that aren't meaningful on Android.
// It's okay to skip them.
break;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
index e4ee1b221bf..cffd90d4e01 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
@@ -78,6 +78,11 @@ void BrowserAccessibilityManagerAuraLinux::FireLoadingEvent(
g_signal_emit_by_name(obj, "load_complete");
}
+void BrowserAccessibilityManagerAuraLinux::FireEnabledChangedEvent(
+ BrowserAccessibility* node) {
+ ToBrowserAccessibilityAuraLinux(node)->GetNode()->OnEnabledChanged();
+}
+
void BrowserAccessibilityManagerAuraLinux::FireExpandedEvent(
BrowserAccessibility* node,
bool is_expanded) {
@@ -120,6 +125,11 @@ void BrowserAccessibilityManagerAuraLinux::FireSortDirectionChangedEvent(
ToBrowserAccessibilityAuraLinux(node)->GetNode()->OnSortDirectionChanged();
}
+void BrowserAccessibilityManagerAuraLinux::FireTextAttributesChangedEvent(
+ BrowserAccessibility* node) {
+ ToBrowserAccessibilityAuraLinux(node)->GetNode()->OnTextAttributesChanged();
+}
+
void BrowserAccessibilityManagerAuraLinux::FireSubtreeCreatedEvent(
BrowserAccessibility* node) {
// Sending events during a load would create a lot of spam, don't do that.
@@ -155,6 +165,9 @@ void BrowserAccessibilityManagerAuraLinux::FireGeneratedEvent(
case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
FireEvent(node, ax::mojom::Event::kDocumentTitleChanged);
break;
+ case ui::AXEventGenerator::Event::ENABLED_CHANGED:
+ FireEnabledChangedEvent(node);
+ break;
case ui::AXEventGenerator::Event::EXPANDED:
FireExpandedEvent(node, true);
break;
@@ -190,7 +203,58 @@ void BrowserAccessibilityManagerAuraLinux::FireGeneratedEvent(
case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
FireEvent(node, ax::mojom::Event::kInvalidStatusChanged);
break;
- default:
+ case ui::AXEventGenerator::Event::OBJECT_ATTRIBUTE_CHANGED:
+ // TODO(1108872): Fire event.
+ break;
+ case ui::AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
+ FireTextAttributesChangedEvent(node);
+ break;
+ case ui::AXEventGenerator::Event::ACCESS_KEY_CHANGED:
+ case ui::AXEventGenerator::Event::ALERT:
+ case ui::AXEventGenerator::Event::ATOMIC_CHANGED:
+ case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED:
+ case ui::AXEventGenerator::Event::BUSY_CHANGED:
+ case ui::AXEventGenerator::Event::CHILDREN_CHANGED:
+ case ui::AXEventGenerator::Event::CONTROLS_CHANGED:
+ case ui::AXEventGenerator::Event::CLASS_NAME_CHANGED:
+ case ui::AXEventGenerator::Event::DESCRIBED_BY_CHANGED:
+ case ui::AXEventGenerator::Event::DROPEFFECT_CHANGED:
+ case ui::AXEventGenerator::Event::FOCUS_CHANGED:
+ case ui::AXEventGenerator::Event::FLOW_FROM_CHANGED:
+ case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
+ case ui::AXEventGenerator::Event::GRABBED_CHANGED:
+ case ui::AXEventGenerator::Event::HASPOPUP_CHANGED:
+ case ui::AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
+ case ui::AXEventGenerator::Event::IGNORED_CHANGED:
+ case ui::AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED:
+ case ui::AXEventGenerator::Event::KEY_SHORTCUTS_CHANGED:
+ case ui::AXEventGenerator::Event::LABELED_BY_CHANGED:
+ case ui::AXEventGenerator::Event::LANGUAGE_CHANGED:
+ case ui::AXEventGenerator::Event::LAYOUT_INVALIDATED:
+ case ui::AXEventGenerator::Event::LIVE_REGION_CHANGED:
+ case ui::AXEventGenerator::Event::LIVE_REGION_CREATED:
+ case ui::AXEventGenerator::Event::LIVE_REGION_NODE_CHANGED:
+ case ui::AXEventGenerator::Event::LIVE_RELEVANT_CHANGED:
+ case ui::AXEventGenerator::Event::LIVE_STATUS_CHANGED:
+ case ui::AXEventGenerator::Event::MULTILINE_STATE_CHANGED:
+ case ui::AXEventGenerator::Event::MULTISELECTABLE_STATE_CHANGED:
+ case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
+ case ui::AXEventGenerator::Event::PLACEHOLDER_CHANGED:
+ case ui::AXEventGenerator::Event::PORTAL_ACTIVATED:
+ case ui::AXEventGenerator::Event::POSITION_IN_SET_CHANGED:
+ case ui::AXEventGenerator::Event::READONLY_CHANGED:
+ case ui::AXEventGenerator::Event::RELATED_NODE_CHANGED:
+ case ui::AXEventGenerator::Event::REQUIRED_STATE_CHANGED:
+ case ui::AXEventGenerator::Event::ROLE_CHANGED:
+ case ui::AXEventGenerator::Event::ROW_COUNT_CHANGED:
+ case ui::AXEventGenerator::Event::SCROLL_HORIZONTAL_POSITION_CHANGED:
+ case ui::AXEventGenerator::Event::SCROLL_VERTICAL_POSITION_CHANGED:
+ case ui::AXEventGenerator::Event::SET_SIZE_CHANGED:
+ case ui::AXEventGenerator::Event::STATE_CHANGED:
+ case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
+ case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
+ case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
+ case ui::AXEventGenerator::Event::WIN_IACCESSIBLE_STATE_CHANGED:
// Need to implement.
break;
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
index d86cba09251..834f2db06b8 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_auralinux.h
@@ -35,11 +35,13 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAuraLinux
BrowserAccessibility* node) override;
void FireSelectedEvent(BrowserAccessibility* node);
+ void FireEnabledChangedEvent(BrowserAccessibility* node);
void FireExpandedEvent(BrowserAccessibility* node, bool is_expanded);
void FireLoadingEvent(BrowserAccessibility* node, bool is_loading);
void FireNameChangedEvent(BrowserAccessibility* node);
void FireDescriptionChangedEvent(BrowserAccessibility* node);
void FireSortDirectionChangedEvent(BrowserAccessibility* node);
+ void FireTextAttributesChangedEvent(BrowserAccessibility* node);
void FireSubtreeCreatedEvent(BrowserAccessibility* node);
void OnFindInPageResult(int request_id,
int match_index,
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
index 8fb447a74cb..b4043f56341 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -60,12 +60,16 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
NSDictionary* GetUserInfoForValueChangedNotification(
const BrowserAccessibilityCocoa* native_node,
const base::string16& deleted_text,
- const base::string16& inserted_text) const;
+ const base::string16& inserted_text,
+ id edit_text_marker) const;
void AnnounceActiveDescendant(BrowserAccessibility* node) const;
bool IsInGeneratedEventBatch(ui::AXEventGenerator::Event event_type) const;
+ // Returns whether this page is a new tab page on Chrome.
+ bool IsChromeNewTabPage();
+
// Keeps track of any edits that have been made by the user during a tree
// update. Used by NSAccessibilityValueChangedNotification.
// Maps AXNode IDs to value attribute changes.
@@ -78,6 +82,6 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerMac);
};
-}
+} // namespace content
#endif // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_MAC_H_
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 9795a4ce389..5d7acab1b17 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -16,6 +16,7 @@
#import "content/browser/accessibility/browser_accessibility_mac.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/accessibility/ax_role_properties.h"
@@ -66,9 +67,9 @@ enum AXTextEditType {
AXTextEditTypeAttributesChange
};
+// Native mac notifications fired.
NSString* const NSAccessibilityAutocorrectionOccurredNotification =
@"AXAutocorrectionOccurred";
-NSString* const NSAccessibilityLayoutCompleteNotification = @"AXLayoutComplete";
NSString* const NSAccessibilityLoadCompleteNotification = @"AXLoadComplete";
NSString* const NSAccessibilityInvalidStatusChangedNotification =
@"AXInvalidStatusChanged";
@@ -80,6 +81,9 @@ NSString* const NSAccessibilityExpandedChanged = @"AXExpandedChanged";
NSString* const NSAccessibilityMenuItemSelectedNotification =
@"AXMenuItemSelected";
+// The following native mac notifications are not fired:
+// AXLayoutComplete: Voiceover does not use this, it is considered too spammy.
+
// Attributes used for NSAccessibilitySelectedTextChangedNotification and
// NSAccessibilityValueChangedNotification.
NSString* const NSAccessibilityTextStateChangeTypeKey =
@@ -94,6 +98,8 @@ NSString* const NSAccessibilityTextSelectionChangedFocus =
NSString* const NSAccessibilityTextChangeElement = @"AXTextChangeElement";
NSString* const NSAccessibilityTextEditType = @"AXTextEditType";
NSString* const NSAccessibilityTextChangeValue = @"AXTextChangeValue";
+NSString* const NSAccessibilityChangeValueStartMarker =
+ @"AXTextChangeValueStartMarker";
NSString* const NSAccessibilityTextChangeValueLength =
@"AXTextChangeValueLength";
NSString* const NSAccessibilityTextChangeValues = @"AXTextChangeValues";
@@ -140,11 +146,6 @@ BrowserAccessibility* BrowserAccessibilityManagerMac::GetFocus() const {
if (!focus)
return nullptr;
- // For editable combo boxes, focus should stay on the combo box so the user
- // will not be taken out of the combo box while typing.
- if (focus->GetRole() == ax::mojom::Role::kTextFieldWithComboBox)
- return focus;
-
// Otherwise, follow the active descendant.
return GetActiveDescendant(focus);
}
@@ -165,9 +166,6 @@ void BrowserAccessibilityManagerMac::FireBlinkEvent(
case ax::mojom::Event::kAutocorrectionOccured:
mac_notification = NSAccessibilityAutocorrectionOccurredNotification;
break;
- case ax::mojom::Event::kLayoutComplete:
- mac_notification = NSAccessibilityLayoutCompleteNotification;
- break;
default:
return;
}
@@ -224,19 +222,25 @@ void BrowserAccessibilityManagerMac::FireGeneratedEvent(
}
break;
case ui::AXEventGenerator::Event::LOAD_COMPLETE:
- // This notification should only be fired on the top document.
- // Iframes should use |ax::mojom::Event::kLayoutComplete| to signify that
- // they have finished loading.
- if (IsRootTree()) {
+ // On MacOS 10.15, firing AXLoadComplete causes focus to move to the
+ // webpage and read content, despite the "Automatically speak the webpage"
+ // checkbox in Voiceover utility being unchecked. The checkbox is
+ // unchecked by default in 10.15 so we don't fire AXLoadComplete events to
+ // support the default behavior.
+ if (base::mac::IsOS10_15())
+ return;
+ // |NSAccessibilityLoadCompleteNotification| should only be fired on the
+ // top document and when the document is not Chrome's new tab page.
+ if (IsRootTree() && !IsChromeNewTabPage()) {
mac_notification = NSAccessibilityLoadCompleteNotification;
} else {
- mac_notification = NSAccessibilityLayoutCompleteNotification;
+ // Voiceover moves focus to the web content when it receives an
+ // AXLoadComplete event. On Chrome's new tab page, focus should stay
+ // in the omnibox, so we purposefully do not fire the AXLoadComplete
+ // event in this case.
+ return;
}
break;
- case ui::AXEventGenerator::Event::PORTAL_ACTIVATED:
- DCHECK(IsRootTree());
- mac_notification = NSAccessibilityLoadCompleteNotification;
- break;
case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
mac_notification = NSAccessibilityInvalidStatusChangedNotification;
break;
@@ -313,16 +317,18 @@ void BrowserAccessibilityManagerMac::FireGeneratedEvent(
if (base::mac::IsAtLeastOS10_11() && !text_edits_.empty()) {
base::string16 deleted_text;
base::string16 inserted_text;
- int32_t id = node->GetId();
- const auto iterator = text_edits_.find(id);
+ int32_t node_id = node->GetId();
+ const auto iterator = text_edits_.find(node_id);
+ id edit_text_marker = nil;
if (iterator != text_edits_.end()) {
AXTextEdit text_edit = iterator->second;
deleted_text = text_edit.deleted_text;
inserted_text = text_edit.inserted_text;
+ edit_text_marker = text_edit.edit_text_marker;
}
NSDictionary* user_info = GetUserInfoForValueChangedNotification(
- native_node, deleted_text, inserted_text);
+ native_node, deleted_text, inserted_text, edit_text_marker);
BrowserAccessibility* root = GetRoot();
if (!root)
@@ -437,8 +443,10 @@ void BrowserAccessibilityManagerMac::FireGeneratedEvent(
case ui::AXEventGenerator::Event::MULTILINE_STATE_CHANGED:
case ui::AXEventGenerator::Event::MULTISELECTABLE_STATE_CHANGED:
case ui::AXEventGenerator::Event::NAME_CHANGED:
+ case ui::AXEventGenerator::Event::OBJECT_ATTRIBUTE_CHANGED:
case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
case ui::AXEventGenerator::Event::PLACEHOLDER_CHANGED:
+ case ui::AXEventGenerator::Event::PORTAL_ACTIVATED:
case ui::AXEventGenerator::Event::POSITION_IN_SET_CHANGED:
case ui::AXEventGenerator::Event::READONLY_CHANGED:
case ui::AXEventGenerator::Event::RELATED_NODE_CHANGED:
@@ -451,9 +459,11 @@ void BrowserAccessibilityManagerMac::FireGeneratedEvent(
case ui::AXEventGenerator::Event::SORT_CHANGED:
case ui::AXEventGenerator::Event::STATE_CHANGED:
case ui::AXEventGenerator::Event::SUBTREE_CREATED:
+ case ui::AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
+ case ui::AXEventGenerator::Event::WIN_IACCESSIBLE_STATE_CHANGED:
// There are some notifications that aren't meaningful on Mac.
// It's okay to skip them.
return;
@@ -542,29 +552,42 @@ NSDictionary*
BrowserAccessibilityManagerMac::GetUserInfoForValueChangedNotification(
const BrowserAccessibilityCocoa* native_node,
const base::string16& deleted_text,
- const base::string16& inserted_text) const {
+ const base::string16& inserted_text,
+ id edit_text_marker) const {
DCHECK(native_node);
if (deleted_text.empty() && inserted_text.empty())
return nil;
NSMutableArray* changes = [[[NSMutableArray alloc] init] autorelease];
if (!deleted_text.empty()) {
- [changes addObject:@{
- NSAccessibilityTextEditType : @(AXTextEditTypeDelete),
- NSAccessibilityTextChangeValueLength : @(deleted_text.length()),
- NSAccessibilityTextChangeValue : base::SysUTF16ToNSString(deleted_text)
- }];
+ NSMutableDictionary* change =
+ [NSMutableDictionary dictionaryWithDictionary:@{
+ NSAccessibilityTextEditType : @(AXTextEditTypeDelete),
+ NSAccessibilityTextChangeValueLength : @(deleted_text.length()),
+ NSAccessibilityTextChangeValue :
+ base::SysUTF16ToNSString(deleted_text)
+ }];
+ if (edit_text_marker) {
+ change[NSAccessibilityChangeValueStartMarker] = edit_text_marker;
+ }
+ [changes addObject:change];
}
if (!inserted_text.empty()) {
// TODO(nektar): Figure out if this is a paste, insertion or typing.
// Changes to Blink would be required. A heuristic is currently used.
auto edit_type = inserted_text.length() > 1 ? @(AXTextEditTypeInsert)
: @(AXTextEditTypeTyping);
- [changes addObject:@{
- NSAccessibilityTextEditType : edit_type,
- NSAccessibilityTextChangeValueLength : @(inserted_text.length()),
- NSAccessibilityTextChangeValue : base::SysUTF16ToNSString(inserted_text)
- }];
+ NSMutableDictionary* change =
+ [NSMutableDictionary dictionaryWithDictionary:@{
+ NSAccessibilityTextEditType : edit_type,
+ NSAccessibilityTextChangeValueLength : @(inserted_text.length()),
+ NSAccessibilityTextChangeValue :
+ base::SysUTF16ToNSString(inserted_text)
+ }];
+ if (edit_text_marker) {
+ change[NSAccessibilityChangeValueStartMarker] = edit_text_marker;
+ }
+ [changes addObject:change];
}
return @{
@@ -582,4 +605,14 @@ id BrowserAccessibilityManagerMac::GetWindow() {
return delegate()->AccessibilityGetNativeViewAccessibleForWindow();
}
+bool BrowserAccessibilityManagerMac::IsChromeNewTabPage() {
+ if (!delegate() || !IsRootTree())
+ return false;
+ content::WebContents* web_contents = delegate()->AccessibilityWebContents();
+ const GURL& url = web_contents->GetVisibleURL();
+ return url == GURL("chrome://newtab/") ||
+ url == GURL("chrome://new-tab-page") ||
+ url == GURL("chrome-search://local-ntp/local-ntp.html");
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
index 971f4519665..de5fb715c22 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -136,7 +136,7 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRange) {
inline_text1.role = ax::mojom::Role::kInlineTextBox;
inline_text1.SetName("Hello, ");
inline_text1.relative_bounds.bounds = gfx::RectF(100, 100, 29, 9);
- inline_text1.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text1.SetTextDirection(ax::mojom::WritingDirection::kLtr);
std::vector<int32_t> character_offsets1;
character_offsets1.push_back(6); // 0
character_offsets1.push_back(11); // 1
@@ -154,7 +154,7 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRange) {
inline_text2.role = ax::mojom::Role::kInlineTextBox;
inline_text2.SetName("world.");
inline_text2.relative_bounds.bounds = gfx::RectF(100, 109, 28, 9);
- inline_text2.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text2.SetTextDirection(ax::mojom::WritingDirection::kLtr);
std::vector<int32_t> character_offsets2;
character_offsets2.push_back(5);
character_offsets2.push_back(10);
@@ -242,7 +242,7 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRangeMultiElement) {
inline_text1.role = ax::mojom::Role::kInlineTextBox;
inline_text1.SetName("ABC");
inline_text1.relative_bounds.bounds = gfx::RectF(0, 20, 33, 9);
- inline_text1.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text1.SetTextDirection(ax::mojom::WritingDirection::kLtr);
std::vector<int32_t> character_offsets{10, 21, 33};
inline_text1.AddIntListAttribute(
ax::mojom::IntListAttribute::kCharacterOffsets, character_offsets);
@@ -260,7 +260,7 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRangeMultiElement) {
inline_text2.role = ax::mojom::Role::kInlineTextBox;
inline_text2.SetName("ABC");
inline_text2.relative_bounds.bounds = gfx::RectF(10, 40, 33, 9);
- inline_text2.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text2.SetTextDirection(ax::mojom::WritingDirection::kLtr);
inline_text2.AddIntListAttribute(
ax::mojom::IntListAttribute::kCharacterOffsets, character_offsets);
static_text2.child_ids.push_back(5);
@@ -360,7 +360,7 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRangeBiDi) {
inline_text1.role = ax::mojom::Role::kInlineTextBox;
inline_text1.SetName("123");
inline_text1.relative_bounds.bounds = gfx::RectF(100, 100, 30, 20);
- inline_text1.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text1.SetTextDirection(ax::mojom::WritingDirection::kLtr);
std::vector<int32_t> character_offsets1;
character_offsets1.push_back(10); // 0
character_offsets1.push_back(20); // 1
@@ -374,7 +374,7 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRangeBiDi) {
inline_text2.role = ax::mojom::Role::kInlineTextBox;
inline_text2.SetName("abc");
inline_text2.relative_bounds.bounds = gfx::RectF(130, 100, 30, 20);
- inline_text2.SetTextDirection(ax::mojom::TextDirection::kRtl);
+ inline_text2.SetTextDirection(ax::mojom::WritingDirection::kRtl);
std::vector<int32_t> character_offsets2;
character_offsets2.push_back(10);
character_offsets2.push_back(20);
@@ -457,7 +457,7 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRangeScrolledWindow) {
inline_text.role = ax::mojom::Role::kInlineTextBox;
inline_text.SetName("ABC");
inline_text.relative_bounds.bounds = gfx::RectF(100, 100, 16, 9);
- inline_text.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text.SetTextDirection(ax::mojom::WritingDirection::kLtr);
std::vector<int32_t> character_offsets1;
character_offsets1.push_back(6); // 0
character_offsets1.push_back(11); // 1
@@ -536,7 +536,7 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRangeOnParentElement) {
inline_text1.role = ax::mojom::Role::kInlineTextBox;
inline_text1.SetName("AB");
inline_text1.relative_bounds.bounds = gfx::RectF(100, 100, 40, 20);
- inline_text1.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text1.SetTextDirection(ax::mojom::WritingDirection::kLtr);
std::vector<int32_t> character_offsets1;
character_offsets1.push_back(20); // 0
character_offsets1.push_back(40); // 1
@@ -548,7 +548,7 @@ TEST_F(BrowserAccessibilityManagerTest, BoundsForRangeOnParentElement) {
inline_text2.role = ax::mojom::Role::kInlineTextBox;
inline_text2.SetName("CD");
inline_text2.relative_bounds.bounds = gfx::RectF(160, 100, 40, 20);
- inline_text2.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text2.SetTextDirection(ax::mojom::WritingDirection::kLtr);
std::vector<int32_t> character_offsets2;
character_offsets2.push_back(20); // 0
character_offsets2.push_back(40); // 1
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
index 579fafab388..d626899fd7a 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -151,10 +151,19 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
FireUiaAccessibilityEvent(UIA_SystemAlertEventId, node);
break;
case ui::AXEventGenerator::Event::ATOMIC_CHANGED:
+ aria_properties_events_.insert(node);
+ break;
case ui::AXEventGenerator::Event::BUSY_CHANGED:
aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::CHECKED_STATE_CHANGED:
+ // https://www.w3.org/TR/core-aam-1.1/#mapping_state-property_table
+ // SelectionItem.IsSelected is set according to the True or False value of
+ // aria-checked for 'radio' and 'menuitemradio' roles.
+ if (ui::IsRadio(node->GetRole())) {
+ HandleSelectedStateChanged(uia_selection_events_, node,
+ IsUIANodeSelected(node));
+ }
FireUiaPropertyChangedEvent(UIA_ToggleToggleStatePropertyId, node);
aria_properties_events_.insert(node);
break;
@@ -214,6 +223,8 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
break;
// aria-grabbed is deprecated in WAI-ARIA 1.1.
case ui::AXEventGenerator::Event::GRABBED_CHANGED:
+ aria_properties_events_.insert(node);
+ break;
case ui::AXEventGenerator::Event::HASPOPUP_CHANGED:
aria_properties_events_.insert(node);
break;
@@ -292,6 +303,10 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
if (node->GetData().GetNameFrom() != ax::mojom::NameFrom::kContents)
FireWinAccessibilityEvent(EVENT_OBJECT_NAMECHANGE, node);
break;
+ case ui::AXEventGenerator::Event::OBJECT_ATTRIBUTE_CHANGED:
+ FireWinAccessibilityEvent(IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED, node);
+ // TODO(crbug.com/1108871): Fire UIA event.
+ break;
case ui::AXEventGenerator::Event::PLACEHOLDER_CHANGED:
FireUiaPropertyChangedEvent(UIA_HelpTextPropertyId, node);
break;
@@ -324,7 +339,10 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
node);
break;
case ui::AXEventGenerator::Event::SELECTED_CHANGED:
- HandleSelectedStateChanged(node);
+ HandleSelectedStateChanged(ia2_selection_events_, node,
+ IsIA2NodeSelected(node));
+ HandleSelectedStateChanged(uia_selection_events_, node,
+ IsUIANodeSelected(node));
aria_properties_events_.insert(node);
break;
case ui::AXEventGenerator::Event::SELECTED_CHILDREN_CHANGED:
@@ -346,6 +364,10 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
FireUiaAccessibilityEvent(UIA_MenuOpenedEventId, node);
}
break;
+ case ui::AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
+ FireWinAccessibilityEvent(IA2_EVENT_TEXT_ATTRIBUTE_CHANGED, node);
+ FireUiaTextContainerEvent(UIA_Text_TextChangedEventId, node);
+ break;
case ui::AXEventGenerator::Event::VALUE_CHANGED:
FireWinAccessibilityEvent(EVENT_OBJECT_VALUECHANGE, node);
if (node->GetData().IsRangeValueSupported()) {
@@ -374,6 +396,9 @@ void BrowserAccessibilityManagerWin::FireGeneratedEvent(
FireUiaPropertyChangedEvent(UIA_RangeValueLargeChangePropertyId, node);
}
break;
+ case ui::AXEventGenerator::Event::WIN_IACCESSIBLE_STATE_CHANGED:
+ FireWinAccessibilityEvent(EVENT_OBJECT_STATECHANGE, node);
+ break;
case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED:
case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
case ui::AXEventGenerator::Event::FOCUS_CHANGED:
@@ -465,8 +490,7 @@ void BrowserAccessibilityManagerWin::FireUiaPropertyChangedEvent(
// UIA_AriaPropertiesPropertyId-hidden event on non-text node marked as
// ignored.
if (node->IsIgnored() || base::Contains(ignored_changed_nodes_, node)) {
- if (uia_property != UIA_AriaPropertiesPropertyId ||
- node->IsTextOnlyObject())
+ if (uia_property != UIA_AriaPropertiesPropertyId || node->IsText())
return;
}
@@ -636,34 +660,144 @@ void BrowserAccessibilityManagerWin::OnAtomicUpdateFinished(
}
}
-void BrowserAccessibilityManagerWin::HandleSelectedStateChanged(
+// static
+bool BrowserAccessibilityManagerWin::IsIA2NodeSelected(
BrowserAccessibility* node) {
- const bool is_selected =
- node->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected);
-
- // Nodes that have selection container may support multiselect, for such nodes
- // we add them to |selection_events_|, which FinalizeAccessibilityEvents
- // handles selection item events firing.
- // For nodes that do not have selection container, only single select is
- // supported, selection item events firing are handled here.
- if (auto* selection_container = node->PlatformGetSelectionContainer()) {
- if (is_selected) {
- selection_events_[selection_container].added.push_back(node);
- } else {
- selection_events_[selection_container].removed.push_back(node);
+ return node->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected);
+}
+
+// static
+bool BrowserAccessibilityManagerWin::IsUIANodeSelected(
+ BrowserAccessibility* node) {
+ // https://www.w3.org/TR/core-aam-1.1/#mapping_state-property_table
+ // SelectionItem.IsSelected is set according to the True or False value of
+ // aria-checked for 'radio' and 'menuitemradio' roles.
+ if (ui::IsRadio(node->GetRole()))
+ return node->GetData().GetCheckedState() == ax::mojom::CheckedState::kTrue;
+
+ return node->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected);
+}
+
+void BrowserAccessibilityManagerWin::FireIA2SelectionEvents(
+ BrowserAccessibility* container,
+ BrowserAccessibility* only_selected_child,
+ const SelectionEvents& changes) {
+ if (only_selected_child) {
+ // Fire 'ElementSelected' on the only selected child.
+ FireWinAccessibilityEvent(EVENT_OBJECT_SELECTION, only_selected_child);
+ } else {
+ const bool container_is_multiselectable =
+ container && container->HasState(ax::mojom::State::kMultiselectable);
+ for (auto* item : changes.added) {
+ if (container_is_multiselectable)
+ FireWinAccessibilityEvent(EVENT_OBJECT_SELECTIONADD, item);
+ else
+ FireWinAccessibilityEvent(EVENT_OBJECT_SELECTION, item);
}
+ for (auto* item : changes.removed)
+ FireWinAccessibilityEvent(EVENT_OBJECT_SELECTIONREMOVE, item);
+ }
+}
+
+void BrowserAccessibilityManagerWin::FireUIASelectionEvents(
+ BrowserAccessibility* container,
+ BrowserAccessibility* only_selected_child,
+ const SelectionEvents& changes) {
+ if (only_selected_child) {
+ // Fire 'ElementSelected' on the only selected child.
+ FireUiaAccessibilityEvent(UIA_SelectionItem_ElementSelectedEventId,
+ only_selected_child);
+ FireUiaPropertyChangedEvent(UIA_SelectionItemIsSelectedPropertyId,
+ only_selected_child);
+ for (auto* item : changes.removed)
+ FireUiaPropertyChangedEvent(UIA_SelectionItemIsSelectedPropertyId, item);
} else {
- if (is_selected) {
- FireWinAccessibilityEvent(EVENT_OBJECT_SELECTION, node);
- FireUiaAccessibilityEvent(UIA_SelectionItem_ElementSelectedEventId, node);
+ // Per UIA documentation, beyond the "invalidate limit" we're supposed to
+ // fire a 'SelectionInvalidated' event. The exact value isn't specified,
+ // but System.Windows.Automation.Provider uses a value of 20.
+ static const size_t kInvalidateLimit = 20;
+ if ((changes.added.size() + changes.removed.size()) > kInvalidateLimit) {
+ DCHECK_NE(container, nullptr);
+ FireUiaAccessibilityEvent(UIA_Selection_InvalidatedEventId, container);
} else {
- FireWinAccessibilityEvent(EVENT_OBJECT_SELECTIONREMOVE, node);
- FireUiaAccessibilityEvent(
- UIA_SelectionItem_ElementRemovedFromSelectionEventId, node);
+ const bool container_is_multiselectable =
+ container && container->HasState(ax::mojom::State::kMultiselectable);
+ for (auto* item : changes.added) {
+ if (container_is_multiselectable) {
+ FireUiaAccessibilityEvent(
+ UIA_SelectionItem_ElementAddedToSelectionEventId, item);
+ } else {
+ FireUiaAccessibilityEvent(UIA_SelectionItem_ElementSelectedEventId,
+ item);
+ }
+ FireUiaPropertyChangedEvent(UIA_SelectionItemIsSelectedPropertyId,
+ item);
+ }
+ for (auto* item : changes.removed) {
+ FireUiaAccessibilityEvent(
+ UIA_SelectionItem_ElementRemovedFromSelectionEventId, item);
+ FireUiaPropertyChangedEvent(UIA_SelectionItemIsSelectedPropertyId,
+ item);
+ }
}
}
}
+// static
+void BrowserAccessibilityManagerWin::HandleSelectedStateChanged(
+ SelectionEventsMap& selection_events_map,
+ BrowserAccessibility* node,
+ bool is_selected) {
+ // If |node| belongs to a selection container, then map the events with the
+ // selection container as the key because |FinalizeSelectionEvents| needs to
+ // determine whether or not there is only one element selected in order to
+ // optimize what platform events are sent.
+ BrowserAccessibility* key = node;
+ if (auto* selection_container = node->PlatformGetSelectionContainer())
+ key = selection_container;
+
+ if (is_selected)
+ selection_events_map[key].added.push_back(node);
+ else
+ selection_events_map[key].removed.push_back(node);
+}
+
+// static
+void BrowserAccessibilityManagerWin::FinalizeSelectionEvents(
+ SelectionEventsMap& selection_events_map,
+ IsSelectedPredicate is_selected_predicate,
+ FirePlatformSelectionEventsCallback fire_platform_events_callback) {
+ for (auto&& selected : selection_events_map) {
+ BrowserAccessibility* key_node = selected.first;
+ SelectionEvents& changes = selected.second;
+
+ // Determine if |node| is a selection container with one selected child in
+ // order to optimize what platform events are sent.
+ BrowserAccessibility* container = nullptr;
+ BrowserAccessibility* only_selected_child = nullptr;
+ if (ui::IsContainerWithSelectableChildren(key_node->GetRole())) {
+ container = key_node;
+ for (auto it = container->InternalChildrenBegin();
+ it != container->InternalChildrenEnd(); ++it) {
+ auto* child = it.get();
+ if (is_selected_predicate.Run(child)) {
+ if (!only_selected_child) {
+ only_selected_child = child;
+ continue;
+ }
+
+ only_selected_child = nullptr;
+ break;
+ }
+ }
+ }
+
+ fire_platform_events_callback.Run(container, only_selected_child, changes);
+ }
+
+ selection_events_map.clear();
+}
+
void BrowserAccessibilityManagerWin::BeforeAccessibilityEvents() {
BrowserAccessibilityManager::BeforeAccessibilityEvents();
@@ -700,56 +834,17 @@ void BrowserAccessibilityManagerWin::FinalizeAccessibilityEvents() {
text_selection_changed_events_.clear();
// Finalize selection item events.
- for (auto&& selected : selection_events_) {
- auto* container = selected.first;
- auto&& changes = selected.second;
-
- // Count the number of selected items
- size_t selected_count = 0;
- BrowserAccessibility* first_selected_child = nullptr;
- for (auto it = container->InternalChildrenBegin();
- it != container->InternalChildrenEnd(); ++it) {
- auto* child = it.get();
- if (child->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected)) {
- if (!first_selected_child)
- first_selected_child = child;
- selected_count++;
- }
- }
+ FinalizeSelectionEvents(
+ ia2_selection_events_, base::BindRepeating(&IsIA2NodeSelected),
+ base::BindRepeating(
+ &BrowserAccessibilityManagerWin::FireIA2SelectionEvents,
+ base::Unretained(this)));
+ FinalizeSelectionEvents(
+ uia_selection_events_, base::BindRepeating(&IsUIANodeSelected),
+ base::BindRepeating(
+ &BrowserAccessibilityManagerWin::FireUIASelectionEvents,
+ base::Unretained(this)));
- if (selected_count == 1) {
- // Fire 'ElementSelected' on the only selected child
- FireWinAccessibilityEvent(EVENT_OBJECT_SELECTION, first_selected_child);
- FireUiaAccessibilityEvent(UIA_SelectionItem_ElementSelectedEventId,
- first_selected_child);
- } else {
- // Per UIA documentation, beyond the "invalidate limit" we're supposed to
- // fire a 'SelectionInvalidated' event. The exact value isn't specified,
- // but System.Windows.Automation.Provider uses a value of 20.
- static const size_t kInvalidateLimit = 20;
- if ((changes.added.size() + changes.removed.size()) > kInvalidateLimit) {
- FireUiaAccessibilityEvent(UIA_Selection_InvalidatedEventId, container);
- } else {
- for (auto* item : changes.added) {
- if (container->HasState(ax::mojom::State::kMultiselectable)) {
- FireWinAccessibilityEvent(EVENT_OBJECT_SELECTIONADD, item);
- FireUiaAccessibilityEvent(
- UIA_SelectionItem_ElementAddedToSelectionEventId, item);
- } else {
- FireWinAccessibilityEvent(EVENT_OBJECT_SELECTION, item);
- FireUiaAccessibilityEvent(UIA_SelectionItem_ElementSelectedEventId,
- item);
- }
- }
- for (auto* item : changes.removed) {
- FireWinAccessibilityEvent(EVENT_OBJECT_SELECTIONREMOVE, item);
- FireUiaAccessibilityEvent(
- UIA_SelectionItem_ElementRemovedFromSelectionEventId, item);
- }
- }
- }
- }
- selection_events_.clear();
ignored_changed_nodes_.clear();
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
index 20c72281451..63a9ed71660 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -77,7 +77,40 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
const std::vector<ui::AXTreeObserver::Change>& changes) override;
private:
- void HandleSelectedStateChanged(BrowserAccessibility* node);
+ struct SelectionEvents {
+ std::vector<BrowserAccessibility*> added;
+ std::vector<BrowserAccessibility*> removed;
+ SelectionEvents();
+ ~SelectionEvents();
+ };
+
+ using SelectionEventsMap = std::map<BrowserAccessibility*, SelectionEvents>;
+ using IsSelectedPredicate =
+ base::RepeatingCallback<bool(BrowserAccessibility*)>;
+ using FirePlatformSelectionEventsCallback =
+ base::RepeatingCallback<void(BrowserAccessibility*,
+ BrowserAccessibility*,
+ const SelectionEvents&)>;
+
+ static bool IsIA2NodeSelected(BrowserAccessibility* node);
+ static bool IsUIANodeSelected(BrowserAccessibility* node);
+
+ void FireIA2SelectionEvents(BrowserAccessibility* container,
+ BrowserAccessibility* only_selected_child,
+ const SelectionEvents& changes);
+ void FireUIASelectionEvents(BrowserAccessibility* container,
+ BrowserAccessibility* only_selected_child,
+ const SelectionEvents& changes);
+
+ static void HandleSelectedStateChanged(
+ SelectionEventsMap& selection_events_map,
+ BrowserAccessibility* node,
+ bool is_selected);
+
+ static void FinalizeSelectionEvents(
+ SelectionEventsMap& selection_events_map,
+ IsSelectedPredicate is_selected_predicate,
+ FirePlatformSelectionEventsCallback fire_platform_events_callback);
// Give BrowserAccessibilityManager::Create access to our constructor.
friend class BrowserAccessibilityManager;
@@ -109,13 +142,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
// Keep track of selection changes so we can optimize UIA event firing.
// Pointers are only stored for the duration of |OnAccessibilityEvents|, and
// the map is cleared in |FinalizeAccessibilityEvents|.
- struct SelectionEvents {
- std::vector<BrowserAccessibility*> added;
- std::vector<BrowserAccessibility*> removed;
- SelectionEvents();
- ~SelectionEvents();
- };
- std::map<BrowserAccessibility*, SelectionEvents> selection_events_;
+ SelectionEventsMap ia2_selection_events_;
+ SelectionEventsMap uia_selection_events_;
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerWin);
};
diff --git a/chromium/content/browser/accessibility/browser_accessibility_position.cc b/chromium/content/browser/accessibility/browser_accessibility_position.cc
index f3faffebcda..ac66598c49b 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_position.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_position.cc
@@ -46,7 +46,7 @@ bool BrowserAccessibilityPosition::IsInTextObject() const {
if (IsNullPosition())
return false;
DCHECK(GetAnchor());
- return GetAnchor()->IsTextOnlyObject();
+ return GetAnchor()->IsText();
}
bool BrowserAccessibilityPosition::IsInWhiteSpace() const {
@@ -170,7 +170,7 @@ bool BrowserAccessibilityPosition::IsEmbeddedObjectInParent() const {
#if defined(OS_WIN) || BUILDFLAG(USE_ATK)
// Not all objects in the internal accessibility tree are exposed to platform
// APIs.
- return !IsNullPosition() && !GetAnchor()->IsTextOnlyObject() &&
+ return !IsNullPosition() && !GetAnchor()->IsText() &&
!GetAnchor()->IsChildOfLeaf();
#else
return false;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
index 68243d5ec48..8cf7fb7f787 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -157,11 +157,12 @@ void BrowserAccessibilityStateImpl::UpdateHistogramsForTesting() {
UpdateHistogramsOnOtherThread();
}
+void BrowserAccessibilityStateImpl::SetCaretBrowsingState(bool enabled) {
+ caret_browsing_enabled_ = enabled;
+}
+
bool BrowserAccessibilityStateImpl::IsCaretBrowsingEnabled() const {
- // TODO(crbug.com/1018947): Refine this check once UX provided to toggle caret
- // browsing mode.
- return base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableCaretBrowsing);
+ return caret_browsing_enabled_;
}
void BrowserAccessibilityStateImpl::UpdateHistogramsOnUIThread() {
@@ -199,7 +200,7 @@ ui::AXMode BrowserAccessibilityStateImpl::GetAccessibilityMode() {
return accessibility_mode_;
}
-#if !defined(OS_ANDROID) && !defined(OS_WIN) && !defined(OS_MACOSX)
+#if !defined(OS_ANDROID) && !defined(OS_WIN) && !defined(OS_MAC)
void BrowserAccessibilityStateImpl::PlatformInitialize() {}
void BrowserAccessibilityStateImpl::
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.h b/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
index 49aaf7ddec5..d266cb612bf 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
@@ -60,10 +60,11 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
bool IsAccessibleBrowser() override;
void AddUIThreadHistogramCallback(base::OnceClosure callback) override;
void AddOtherThreadHistogramCallback(base::OnceClosure callback) override;
-
void UpdateHistogramsForTesting() override;
+ void SetCaretBrowsingState(bool enabled) override;
- // Returns whether caret browsing is enabled for this browser session.
+ // Returns whether caret browsing is enabled for the most recently
+ // used profile.
bool IsCaretBrowsingEnabled() const;
// AXModeObserver
@@ -114,6 +115,10 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
bool disable_hot_tracking_;
+ // Keeps track of whether caret browsing is enabled for the most
+ // recently used profile.
+ bool caret_browsing_enabled_ = false;
+
#if defined(OS_WIN)
// Only used on Windows
std::unique_ptr<gfx::SingletonHwndObserver> singleton_hwnd_observer_;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl_android.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl_android.cc
index b8c53a642ce..e04b542ff2d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl_android.cc
@@ -56,7 +56,7 @@ void JNI_BrowserAccessibilityState_OnAnimatorDurationScaleChanged(JNIEnv* env) {
gfx::Animation::UpdatePrefersReducedMotion();
for (WebContentsImpl* wc : WebContentsImpl::GetAllWebContents()) {
- wc->GetRenderViewHost()->OnWebkitPreferencesChanged();
+ wc->OnWebPreferencesChanged();
}
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm
index 7a59582ea63..6950df73139 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm
@@ -46,7 +46,7 @@ void SetupAccessibilityDisplayOptionsNotifier() {
gfx::Animation::UpdatePrefersReducedMotion();
for (WebContentsImpl* wc :
WebContentsImpl::GetAllWebContents()) {
- wc->GetRenderViewHost()->OnWebkitPreferencesChanged();
+ wc->OnWebPreferencesChanged();
}
}];
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
index 3da5f132da5..fffcddd99fc 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
@@ -85,7 +85,7 @@ void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
if (message == WM_SETTINGCHANGE && wparam == SPI_SETCLIENTAREAANIMATION) {
gfx::Animation::UpdatePrefersReducedMotion();
for (WebContentsImpl* wc : WebContentsImpl::GetAllWebContents()) {
- wc->GetRenderViewHost()->OnWebkitPreferencesChanged();
+ wc->OnWebPreferencesChanged();
}
}
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_unittest.cc
index ed559c391b0..c4800985bb7 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_unittest.cc
@@ -289,7 +289,7 @@ TEST_F(BrowserAccessibilityTest, GetInnerTextRangeBoundsRect) {
inline_text1.role = ax::mojom::Role::kInlineTextBox;
inline_text1.SetName("Hello, ");
inline_text1.relative_bounds.bounds = gfx::RectF(100, 100, 29, 9);
- inline_text1.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text1.SetTextDirection(ax::mojom::WritingDirection::kLtr);
std::vector<int32_t> character_offsets1;
character_offsets1.push_back(6);
character_offsets1.push_back(11);
@@ -307,7 +307,7 @@ TEST_F(BrowserAccessibilityTest, GetInnerTextRangeBoundsRect) {
inline_text2.role = ax::mojom::Role::kInlineTextBox;
inline_text2.SetName("world.");
inline_text2.relative_bounds.bounds = gfx::RectF(100, 109, 28, 9);
- inline_text2.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text2.SetTextDirection(ax::mojom::WritingDirection::kLtr);
std::vector<int32_t> character_offsets2;
character_offsets2.push_back(5);
character_offsets2.push_back(10);
@@ -410,7 +410,7 @@ TEST_F(BrowserAccessibilityTest, GetInnerTextRangeBoundsRectMultiElement) {
inline_text1.role = ax::mojom::Role::kInlineTextBox;
inline_text1.SetName("ABC");
inline_text1.relative_bounds.bounds = gfx::RectF(0, 20, 33, 9);
- inline_text1.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text1.SetTextDirection(ax::mojom::WritingDirection::kLtr);
std::vector<int32_t> character_offsets{10, 21, 33};
inline_text1.AddIntListAttribute(
ax::mojom::IntListAttribute::kCharacterOffsets, character_offsets);
@@ -428,7 +428,7 @@ TEST_F(BrowserAccessibilityTest, GetInnerTextRangeBoundsRectMultiElement) {
inline_text2.role = ax::mojom::Role::kInlineTextBox;
inline_text2.SetName("ABC");
inline_text2.relative_bounds.bounds = gfx::RectF(10, 40, 33, 9);
- inline_text2.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text2.SetTextDirection(ax::mojom::WritingDirection::kLtr);
inline_text2.AddIntListAttribute(
ax::mojom::IntListAttribute::kCharacterOffsets, character_offsets);
static_text2.child_ids.push_back(5);
@@ -537,7 +537,7 @@ TEST_F(BrowserAccessibilityTest, GetInnerTextRangeBoundsRectBiDi) {
inline_text1.role = ax::mojom::Role::kInlineTextBox;
inline_text1.SetName("123");
inline_text1.relative_bounds.bounds = gfx::RectF(100, 100, 30, 20);
- inline_text1.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text1.SetTextDirection(ax::mojom::WritingDirection::kLtr);
std::vector<int32_t> character_offsets1;
character_offsets1.push_back(10); // 0
character_offsets1.push_back(20); // 1
@@ -551,7 +551,7 @@ TEST_F(BrowserAccessibilityTest, GetInnerTextRangeBoundsRectBiDi) {
inline_text2.role = ax::mojom::Role::kInlineTextBox;
inline_text2.SetName("abc");
inline_text2.relative_bounds.bounds = gfx::RectF(130, 100, 30, 20);
- inline_text2.SetTextDirection(ax::mojom::TextDirection::kRtl);
+ inline_text2.SetTextDirection(ax::mojom::WritingDirection::kRtl);
std::vector<int32_t> character_offsets2;
character_offsets2.push_back(10);
character_offsets2.push_back(20);
@@ -637,7 +637,7 @@ TEST_F(BrowserAccessibilityTest, GetInnerTextRangeBoundsRectScrolledWindow) {
inline_text.role = ax::mojom::Role::kInlineTextBox;
inline_text.SetName("ABC");
inline_text.relative_bounds.bounds = gfx::RectF(100, 100, 16, 9);
- inline_text.SetTextDirection(ax::mojom::TextDirection::kLtr);
+ inline_text.SetTextDirection(ax::mojom::WritingDirection::kLtr);
std::vector<int32_t> character_offsets1;
character_offsets1.push_back(6); // 0
character_offsets1.push_back(11); // 1
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
index ca9831ee1e2..3e914e2c530 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -14,6 +14,7 @@
#include <memory>
#include <utility>
+#include "base/command_line.h"
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/task_environment.h"
@@ -24,10 +25,10 @@
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/accessibility/test_browser_accessibility_delegate.h"
#include "content/browser/renderer_host/legacy_render_widget_host_win.h"
-#include "content/common/ax_content_node_data.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/accessibility/accessibility_switches.h"
+#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/ax_platform_node_win.h"
#include "ui/base/win/atl_module.h"
@@ -214,11 +215,11 @@ TEST_F(BrowserAccessibilityWinTest, TestChildrenChange) {
Microsoft::WRL::ComPtr<IDispatch> text_dispatch;
HRESULT hr = ToBrowserAccessibilityWin(manager->GetRoot())
->GetCOM()
- ->get_accChild(one, text_dispatch.GetAddressOf());
+ ->get_accChild(one, &text_dispatch);
ASSERT_EQ(S_OK, hr);
Microsoft::WRL::ComPtr<IAccessible> text_accessible;
- hr = text_dispatch.CopyTo(text_accessible.GetAddressOf());
+ hr = text_dispatch.As(&text_accessible);
ASSERT_EQ(S_OK, hr);
base::win::ScopedVariant childid_self(CHILDID_SELF);
@@ -232,7 +233,7 @@ TEST_F(BrowserAccessibilityWinTest, TestChildrenChange) {
text_accessible.Reset();
// Notify the BrowserAccessibilityManager that the text child has changed.
- AXContentNodeData text2;
+ ui::AXNodeData text2;
text2.id = 2;
text2.role = ax::mojom::Role::kStaticText;
text2.SetName("new text");
@@ -245,10 +246,10 @@ TEST_F(BrowserAccessibilityWinTest, TestChildrenChange) {
// as its value.
hr = ToBrowserAccessibilityWin(manager->GetRoot())
->GetCOM()
- ->get_accChild(one, text_dispatch.GetAddressOf());
+ ->get_accChild(one, &text_dispatch);
ASSERT_EQ(S_OK, hr);
- hr = text_dispatch.CopyTo(text_accessible.GetAddressOf());
+ hr = text_dispatch.As(&text_accessible);
ASSERT_EQ(S_OK, hr);
hr = text_accessible->get_accName(childid_self, name.Receive());
@@ -641,13 +642,11 @@ TEST_F(BrowserAccessibilityWinTest, TestSimpleHypertext) {
EXPECT_EQ(0, hyperlink_count);
Microsoft::WRL::ComPtr<IAccessibleHyperlink> hyperlink;
+ EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(-1, &hyperlink));
+ EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(0, &hyperlink));
+ EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(text_name_len, &hyperlink));
EXPECT_EQ(E_INVALIDARG,
- root_obj->get_hyperlink(-1, hyperlink.GetAddressOf()));
- EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(0, hyperlink.GetAddressOf()));
- EXPECT_EQ(E_INVALIDARG,
- root_obj->get_hyperlink(text_name_len, hyperlink.GetAddressOf()));
- EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(text_name_len + 1,
- hyperlink.GetAddressOf()));
+ root_obj->get_hyperlink(text_name_len + 1, &hyperlink));
LONG hyperlink_index;
EXPECT_EQ(S_FALSE, root_obj->get_hyperlinkIndex(0, &hyperlink_index));
@@ -762,14 +761,13 @@ TEST_F(BrowserAccessibilityWinTest, TestComplexHypertext) {
Microsoft::WRL::ComPtr<IAccessibleHyperlink> hyperlink;
Microsoft::WRL::ComPtr<IAccessibleText> hypertext;
- EXPECT_EQ(E_INVALIDARG,
- root_obj->get_hyperlink(-1, hyperlink.GetAddressOf()));
- EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(4, hyperlink.GetAddressOf()));
+ EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(-1, &hyperlink));
+ EXPECT_EQ(E_INVALIDARG, root_obj->get_hyperlink(4, &hyperlink));
// Get the text of the combo box.
// It should be its value.
- EXPECT_EQ(S_OK, root_obj->get_hyperlink(0, hyperlink.GetAddressOf()));
- EXPECT_EQ(S_OK, hyperlink.CopyTo(hypertext.GetAddressOf()));
+ EXPECT_EQ(S_OK, root_obj->get_hyperlink(0, &hyperlink));
+ EXPECT_EQ(S_OK, hyperlink.As(&hypertext));
EXPECT_EQ(S_OK,
hypertext->get_text(0, IA2_TEXT_OFFSET_LENGTH, text.Receive()));
EXPECT_STREQ(combo_box_value.c_str(), text.Get());
@@ -779,8 +777,8 @@ TEST_F(BrowserAccessibilityWinTest, TestComplexHypertext) {
// Get the text of the check box.
// It should be its name.
- EXPECT_EQ(S_OK, root_obj->get_hyperlink(1, hyperlink.GetAddressOf()));
- EXPECT_EQ(S_OK, hyperlink.CopyTo(hypertext.GetAddressOf()));
+ EXPECT_EQ(S_OK, root_obj->get_hyperlink(1, &hyperlink));
+ EXPECT_EQ(S_OK, hyperlink.As(&hypertext));
EXPECT_EQ(S_OK,
hypertext->get_text(0, IA2_TEXT_OFFSET_LENGTH, text.Receive()));
EXPECT_STREQ(check_box_name.c_str(), text.Get());
@@ -789,8 +787,8 @@ TEST_F(BrowserAccessibilityWinTest, TestComplexHypertext) {
hypertext.Reset();
// Get the text of the button.
- EXPECT_EQ(S_OK, root_obj->get_hyperlink(2, hyperlink.GetAddressOf()));
- EXPECT_EQ(S_OK, hyperlink.CopyTo(hypertext.GetAddressOf()));
+ EXPECT_EQ(S_OK, root_obj->get_hyperlink(2, &hyperlink));
+ EXPECT_EQ(S_OK, hyperlink.As(&hypertext));
EXPECT_EQ(S_OK,
hypertext->get_text(0, IA2_TEXT_OFFSET_LENGTH, text.Receive()));
EXPECT_STREQ(button_text_name.c_str(), text.Get());
@@ -799,8 +797,8 @@ TEST_F(BrowserAccessibilityWinTest, TestComplexHypertext) {
hypertext.Reset();
// Get the text of the link.
- EXPECT_EQ(S_OK, root_obj->get_hyperlink(3, hyperlink.GetAddressOf()));
- EXPECT_EQ(S_OK, hyperlink.CopyTo(hypertext.GetAddressOf()));
+ EXPECT_EQ(S_OK, root_obj->get_hyperlink(3, &hyperlink));
+ EXPECT_EQ(S_OK, hyperlink.As(&hypertext));
EXPECT_EQ(S_OK, hypertext->get_text(0, 4, text.Receive()));
EXPECT_STREQ(link_text_name.c_str(), text.Get());
text.Reset();
@@ -1385,12 +1383,10 @@ TEST_F(BrowserAccessibilityWinTest, TestWordBoundariesInTextControls) {
Microsoft::WRL::ComPtr<IAccessibleText> textarea_object;
EXPECT_HRESULT_SUCCEEDED(textarea_accessible->GetCOM()->QueryInterface(
- IID_IAccessibleText,
- reinterpret_cast<void**>(textarea_object.GetAddressOf())));
+ IID_PPV_ARGS(&textarea_object)));
Microsoft::WRL::ComPtr<IAccessibleText> text_field_object;
EXPECT_HRESULT_SUCCEEDED(text_field_accessible->GetCOM()->QueryInterface(
- IID_IAccessibleText,
- reinterpret_cast<void**>(text_field_object.GetAddressOf())));
+ IID_PPV_ARGS(&text_field_object)));
LONG offset = 0;
while (offset < static_cast<LONG>(text.length())) {
@@ -3046,26 +3042,26 @@ TEST_F(BrowserAccessibilityWinTest, UniqueIdWinInvalidAfterDeletingTree) {
base::win::ScopedVariant old_root_variant(-root_unique_id);
Microsoft::WRL::ComPtr<IDispatch> old_root_dispatch;
HRESULT hr = ToBrowserAccessibilityWin(root)->GetCOM()->get_accChild(
- old_root_variant, old_root_dispatch.GetAddressOf());
+ old_root_variant, &old_root_dispatch);
EXPECT_EQ(E_INVALIDARG, hr);
base::win::ScopedVariant old_child_variant(-child_unique_id);
Microsoft::WRL::ComPtr<IDispatch> old_child_dispatch;
hr = ToBrowserAccessibilityWin(root)->GetCOM()->get_accChild(
- old_child_variant, old_child_dispatch.GetAddressOf());
+ old_child_variant, &old_child_dispatch);
EXPECT_EQ(E_INVALIDARG, hr);
// Trying to access the unique IDs of the new objects should succeed.
base::win::ScopedVariant new_root_variant(-root_unique_id_2);
Microsoft::WRL::ComPtr<IDispatch> new_root_dispatch;
hr = ToBrowserAccessibilityWin(root)->GetCOM()->get_accChild(
- new_root_variant, new_root_dispatch.GetAddressOf());
+ new_root_variant, &new_root_dispatch);
EXPECT_EQ(S_OK, hr);
base::win::ScopedVariant new_child_variant(-child_unique_id_2);
Microsoft::WRL::ComPtr<IDispatch> new_child_dispatch;
hr = ToBrowserAccessibilityWin(root)->GetCOM()->get_accChild(
- new_child_variant, new_child_dispatch.GetAddressOf());
+ new_child_variant, &new_child_dispatch);
EXPECT_EQ(S_OK, hr);
}
@@ -3090,11 +3086,11 @@ TEST_F(BrowserAccessibilityWinTest, AccChildOnlyReturnsDescendants) {
Microsoft::WRL::ComPtr<IDispatch> result;
EXPECT_EQ(E_INVALIDARG,
ToBrowserAccessibilityWin(child)->GetCOM()->get_accChild(
- root_unique_id_variant, result.GetAddressOf()));
+ root_unique_id_variant, &result));
base::win::ScopedVariant child_unique_id_variant(-GetUniqueId(child));
EXPECT_EQ(S_OK, ToBrowserAccessibilityWin(root)->GetCOM()->get_accChild(
- child_unique_id_variant, result.GetAddressOf()));
+ child_unique_id_variant, &result));
}
// TODO(crbug.com/929563): Disabled due to flakiness.
@@ -3145,7 +3141,7 @@ TEST_F(BrowserAccessibilityWinTest, DISABLED_TestIAccessible2Relations) {
EXPECT_EQ(1, n_relations);
EXPECT_HRESULT_SUCCEEDED(
- ax_root->GetCOM()->get_relation(0, describedby_relation.GetAddressOf()));
+ ax_root->GetCOM()->get_relation(0, &describedby_relation));
EXPECT_HRESULT_SUCCEEDED(
describedby_relation->get_relationType(relation_type.Receive()));
EXPECT_EQ(L"describedBy", base::string16(relation_type.Get()));
@@ -3154,17 +3150,15 @@ TEST_F(BrowserAccessibilityWinTest, DISABLED_TestIAccessible2Relations) {
EXPECT_HRESULT_SUCCEEDED(describedby_relation->get_nTargets(&n_targets));
EXPECT_EQ(2, n_targets);
- EXPECT_HRESULT_SUCCEEDED(
- describedby_relation->get_target(0, target.GetAddressOf()));
- target.CopyTo(ax_target.GetAddressOf());
+ EXPECT_HRESULT_SUCCEEDED(describedby_relation->get_target(0, &target));
+ target.As(&ax_target);
EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
EXPECT_EQ(-GetUniqueId(ax_child1), unique_id);
ax_target.Reset();
target.Reset();
- EXPECT_HRESULT_SUCCEEDED(
- describedby_relation->get_target(1, target.GetAddressOf()));
- target.CopyTo(ax_target.GetAddressOf());
+ EXPECT_HRESULT_SUCCEEDED(describedby_relation->get_target(1, &target));
+ target.As(&ax_target);
EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
EXPECT_EQ(-GetUniqueId(ax_child2), unique_id);
ax_target.Reset();
@@ -3175,8 +3169,8 @@ TEST_F(BrowserAccessibilityWinTest, DISABLED_TestIAccessible2Relations) {
EXPECT_HRESULT_SUCCEEDED(ax_child1->GetCOM()->get_nRelations(&n_relations));
EXPECT_EQ(1, n_relations);
- EXPECT_HRESULT_SUCCEEDED(ax_child1->GetCOM()->get_relation(
- 0, description_for_relation.GetAddressOf()));
+ EXPECT_HRESULT_SUCCEEDED(
+ ax_child1->GetCOM()->get_relation(0, &description_for_relation));
EXPECT_HRESULT_SUCCEEDED(
description_for_relation->get_relationType(relation_type.Receive()));
EXPECT_EQ(L"descriptionFor", base::string16(relation_type.Get()));
@@ -3185,9 +3179,8 @@ TEST_F(BrowserAccessibilityWinTest, DISABLED_TestIAccessible2Relations) {
EXPECT_HRESULT_SUCCEEDED(description_for_relation->get_nTargets(&n_targets));
EXPECT_EQ(1, n_targets);
- EXPECT_HRESULT_SUCCEEDED(
- description_for_relation->get_target(0, target.GetAddressOf()));
- target.CopyTo(ax_target.GetAddressOf());
+ EXPECT_HRESULT_SUCCEEDED(description_for_relation->get_target(0, &target));
+ target.As(&ax_target);
EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
EXPECT_EQ(-GetUniqueId(ax_root), unique_id);
ax_target.Reset();
@@ -3197,8 +3190,8 @@ TEST_F(BrowserAccessibilityWinTest, DISABLED_TestIAccessible2Relations) {
EXPECT_HRESULT_SUCCEEDED(ax_child2->GetCOM()->get_nRelations(&n_relations));
EXPECT_EQ(1, n_relations);
- EXPECT_HRESULT_SUCCEEDED(ax_child2->GetCOM()->get_relation(
- 0, description_for_relation.GetAddressOf()));
+ EXPECT_HRESULT_SUCCEEDED(
+ ax_child2->GetCOM()->get_relation(0, &description_for_relation));
EXPECT_HRESULT_SUCCEEDED(
description_for_relation->get_relationType(relation_type.Receive()));
EXPECT_EQ(L"descriptionFor", base::string16(relation_type.Get()));
@@ -3207,9 +3200,8 @@ TEST_F(BrowserAccessibilityWinTest, DISABLED_TestIAccessible2Relations) {
EXPECT_HRESULT_SUCCEEDED(description_for_relation->get_nTargets(&n_targets));
EXPECT_EQ(1, n_targets);
- EXPECT_HRESULT_SUCCEEDED(
- description_for_relation->get_target(0, target.GetAddressOf()));
- target.CopyTo(ax_target.GetAddressOf());
+ EXPECT_HRESULT_SUCCEEDED(description_for_relation->get_target(0, &target));
+ target.As(&ax_target);
EXPECT_HRESULT_SUCCEEDED(ax_target->get_uniqueID(&unique_id));
EXPECT_EQ(-GetUniqueId(ax_root), unique_id);
ax_target.Reset();
diff --git a/chromium/content/browser/accessibility/captioning_controller.cc b/chromium/content/browser/accessibility/captioning_controller.cc
index cc5d6b72d50..f9a5f7ea1f4 100644
--- a/chromium/content/browser/accessibility/captioning_controller.cc
+++ b/chromium/content/browser/accessibility/captioning_controller.cc
@@ -89,10 +89,7 @@ void CaptioningController::SetTextTrackSettings(
const JavaParamRef<jstring>& textTrackTextColor,
const JavaParamRef<jstring>& textTrackTextShadow,
const JavaParamRef<jstring>& textTrackTextSize) {
- auto web_prefs = web_contents()
- ->GetMainFrame()
- ->GetRenderViewHost()
- ->GetWebkitPreferences();
+ auto web_prefs = web_contents()->GetOrCreateWebPreferences();
web_prefs.text_tracks_enabled = textTracksEnabled;
web_prefs.text_track_background_color =
AddCSSImportant(ConvertJavaStringToUTF8(env, textTrackBackgroundColor));
@@ -108,8 +105,7 @@ void CaptioningController::SetTextTrackSettings(
AddCSSImportant(ConvertJavaStringToUTF8(env, textTrackTextShadow));
web_prefs.text_track_text_size =
AddCSSImportant(ConvertJavaStringToUTF8(env, textTrackTextSize));
- web_contents()->GetMainFrame()->GetRenderViewHost()->UpdateWebkitPreferences(
- web_prefs);
+ web_contents()->SetWebPreferences(web_prefs);
}
jlong JNI_CaptioningController_Init(
diff --git a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index 9754f150103..34f0a76f92b 100644
--- a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -13,6 +13,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
+#include "build/chromecast_buildflags.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -27,6 +28,7 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "third_party/blink/public/common/features.h"
+#include "ui/accessibility/accessibility_switches.h"
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_tree.h"
@@ -66,6 +68,14 @@ class CrossPlatformAccessibilityBrowserTest : public ContentBrowserTest {
void SetUpOnMainThread() override;
void TearDownOnMainThread() override;
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ ContentBrowserTest::SetUpCommandLine(command_line);
+ // kDisableAXMenuList is true on Chrome OS by default. Make it consistent
+ // for these cross-platform tests.
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kDisableAXMenuList, "false");
+ }
+
protected:
void LoadInitialAccessibilityTreeFromUrl(
const GURL& url,
@@ -93,6 +103,36 @@ class CrossPlatformAccessibilityBrowserTest : public ContentBrowserTest {
return web_contents->GetRootBrowserAccessibilityManager();
}
+ BrowserAccessibility* FindNode(const std::string& name_or_value) {
+ return FindNodeInSubtree(*GetManager()->GetRoot(), name_or_value);
+ }
+
+ BrowserAccessibility* FindNodeInSubtree(BrowserAccessibility& node,
+ const std::string& name_or_value) {
+ const std::string& name =
+ node.GetStringAttribute(ax::mojom::StringAttribute::kName);
+ // Note that in the case of a text field, "BrowserAccessibility::GetValue"
+ // has the added functionality of computing the value of an ARIA text box
+ // from its inner text.
+ //
+ // <div contenteditable="true" role="textbox">Hello world.</div>
+ // Will expose no HTML value attribute, but some screen readers, such as
+ // Jaws, VoiceOver and Talkback, require one to be computed.
+ const std::string& value = base::UTF16ToUTF8(node.GetValue());
+ if ((name == name_or_value || value == name_or_value)) {
+ return &node;
+ }
+
+ for (unsigned int i = 0; i < node.PlatformChildCount(); ++i) {
+ BrowserAccessibility* result =
+ FindNodeInSubtree(*node.PlatformGetChild(i), name_or_value);
+ if (result)
+ return result;
+ }
+
+ return nullptr;
+ }
+
std::string GetAttr(const ui::AXNode* node,
const ax::mojom::StringAttribute attr);
int GetIntAttr(const ui::AXNode* node, const ax::mojom::IntAttribute attr);
@@ -427,6 +467,103 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
GetAttr(button3->node(), ax::mojom::StringAttribute::kName).c_str());
}
+// Android's text representation is different, so disable the test there.
+#if !defined(OS_ANDROID)
+IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
+ AXNodePositionTreeBoundary) {
+ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+ ui::kAXModeComplete,
+ ax::mojom::Event::kLoadComplete);
+ GURL url(
+ "data:text/html,"
+ "<!doctype html><html><body>"
+ "Text before iframe"
+ "<iframe src='data:text/html,"
+ "<!doctype html><html><body>Text in iframe</body></html>"
+ "'></iframe>"
+ "Text after iframe"
+ "</body></html>");
+
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ waiter.WaitForNotification();
+ WaitForAccessibilityTreeToContainNodeWithName(shell()->web_contents(),
+ "Text in iframe");
+
+ const BrowserAccessibility* root = GetManager()->GetRoot();
+ ASSERT_NE(root, nullptr);
+ const BrowserAccessibility* body = root->PlatformGetChild(0);
+ ASSERT_NE(body, nullptr);
+ const BrowserAccessibility* text_before_iframe =
+ FindNode("Text before iframe");
+ ASSERT_NE(text_before_iframe, nullptr);
+ const BrowserAccessibility* iframe = body->PlatformGetChild(1);
+ ASSERT_NE(iframe, nullptr);
+ const BrowserAccessibility* sub_document = iframe->PlatformGetChild(0);
+ ASSERT_NE(sub_document, nullptr);
+ const BrowserAccessibility* sub_body = sub_document->PlatformGetChild(0);
+ ASSERT_NE(sub_body, nullptr);
+
+ const BrowserAccessibility* text_in_iframe = FindNode("Text in iframe");
+ ASSERT_NE(text_in_iframe, nullptr);
+ const BrowserAccessibility* text_after_iframe = FindNode("Text after iframe");
+ ASSERT_NE(text_after_iframe, nullptr);
+
+ // Start at the beginning of the document. Anchor IDs can vary across
+ // platforms and test runs, so only check text offsets and tree IDs. In this
+ // case, the tree ID of position should match test_position since a tree
+ // boundary is not crossed.
+ ui::AXNodePosition::AXPositionInstance position =
+ text_before_iframe->CreateTextPositionAt(1);
+ EXPECT_EQ(position->text_offset(), 1);
+ EXPECT_FALSE(position->AtStartOfAXTree());
+ EXPECT_FALSE(position->AtEndOfAXTree());
+ ui::AXNodePosition::AXPositionInstance test_position =
+ position->CreatePositionAtStartOfAXTree();
+ EXPECT_EQ(test_position->tree_id(), position->tree_id());
+ EXPECT_EQ(test_position->text_offset(), 0);
+ EXPECT_TRUE(test_position->AtStartOfAXTree());
+ EXPECT_FALSE(test_position->AtEndOfAXTree());
+ test_position = position->CreatePositionAtEndOfAXTree();
+ EXPECT_EQ(test_position->tree_id(), position->tree_id());
+ EXPECT_EQ(test_position->text_offset(), 17);
+ EXPECT_FALSE(test_position->AtStartOfAXTree());
+ EXPECT_TRUE(test_position->AtEndOfAXTree());
+
+ // Test inside iframe.
+ position = text_in_iframe->CreateTextPositionAt(3);
+ EXPECT_EQ(position->text_offset(), 3);
+ EXPECT_NE(test_position->tree_id(), position->tree_id());
+ EXPECT_FALSE(position->AtStartOfAXTree());
+ EXPECT_FALSE(position->AtEndOfAXTree());
+ test_position = position->CreatePositionAtStartOfAXTree();
+ EXPECT_TRUE(test_position->AtStartOfAXTree());
+ EXPECT_FALSE(test_position->AtEndOfAXTree());
+ EXPECT_EQ(test_position->tree_id(), position->tree_id());
+ EXPECT_EQ(test_position->text_offset(), 0);
+ test_position = position->CreatePositionAtEndOfAXTree();
+ EXPECT_EQ(test_position->tree_id(), position->tree_id());
+ EXPECT_EQ(test_position->text_offset(), 14);
+ EXPECT_FALSE(test_position->AtStartOfAXTree());
+ EXPECT_TRUE(test_position->AtEndOfAXTree());
+
+ // Test after iframe.
+ position = text_after_iframe->CreateTextPositionAt(3);
+ EXPECT_FALSE(position->AtStartOfAXTree());
+ EXPECT_FALSE(position->AtEndOfAXTree());
+ EXPECT_NE(test_position->tree_id(), position->tree_id());
+ test_position = position->CreatePositionAtStartOfAXTree();
+ EXPECT_EQ(test_position->tree_id(), position->tree_id());
+ EXPECT_EQ(test_position->text_offset(), 0);
+ EXPECT_TRUE(test_position->AtStartOfAXTree());
+ EXPECT_FALSE(test_position->AtEndOfAXTree());
+ test_position = position->CreatePositionAtEndOfAXTree();
+ EXPECT_EQ(test_position->tree_id(), position->tree_id());
+ EXPECT_EQ(test_position->text_offset(), 17);
+ EXPECT_FALSE(test_position->AtStartOfAXTree());
+ EXPECT_TRUE(test_position->AtEndOfAXTree());
+}
+#endif
+
IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
PlatformIterator) {
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
@@ -634,7 +771,7 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
}
// TODO(https://crbug.com/1020456) re-enable when crashing on linux is resolved.
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
#define MAYBE_LocalizedRoleDescription DISABLED_LocalizedRoleDescription
#else
#define MAYBE_LocalizedRoleDescription LocalizedRoleDescription
@@ -826,7 +963,7 @@ IN_PROC_BROWSER_TEST_F(
// On Android root scroll offset is handled by the Java layer. The final rect
// bounds is device specific.
-#ifndef OS_ANDROID
+#if !defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
GetBoundsRectUnclippedRootFrameFromIFrame) {
// Start by loading a document with iframes.
@@ -935,6 +1072,7 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
const char url_str[] =
R"HTML(data:text/html,<!DOCTYPE html>
<html>
+ <div style="margin-top: 100px;"></div>
<input type="datetime-local" aria-label="datetime"
aria-controls="button1">
<button id="button1">button</button>
@@ -999,6 +1137,13 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
manager->GetFromID(controls_ids[1]);
ASSERT_NE(nullptr, popup_area);
EXPECT_EQ(ax::mojom::Role::kRootWebArea, popup_area->GetRole());
+
+#if !BUILDFLAG(IS_CHROMECAST)
+ // Ensure that the bounding box of the popup area is at least 100
+ // pixels down the page.
+ gfx::Rect popup_bounds = popup_area->GetUnclippedRootFrameBoundsRect();
+ EXPECT_GT(popup_bounds.y(), 100);
+#endif
}
}
@@ -1148,7 +1293,7 @@ IN_PROC_BROWSER_TEST_F(CrossPlatformAccessibilityBrowserTest,
root_accessibility_manager->GetFocus());
}
}
-#endif // ifndef OS_ANDROID
+#endif // !defined(OS_ANDROID)
class CrossPlatformAccessibilityBrowserTestWithImplicitRootScrolling
: public CrossPlatformAccessibilityBrowserTest {
diff --git a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index cd07323d855..0664002302f 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -145,8 +145,7 @@ base::string16
DumpAccessibilityTestBase::DumpUnfilteredAccessibilityTreeAsString() {
std::unique_ptr<AccessibilityTreeFormatter> formatter(formatter_factory_());
std::vector<PropertyFilter> property_filters;
- property_filters.push_back(
- PropertyFilter(base::ASCIIToUTF16("*"), PropertyFilter::ALLOW));
+ property_filters.emplace_back("*", PropertyFilter::ALLOW);
formatter->SetPropertyFilters(property_filters);
formatter->set_show_ids(true);
base::string16 ax_tree_dump;
@@ -171,21 +170,16 @@ void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives(
const std::string& no_load_expected_str = "@NO-LOAD-EXPECTED:";
const std::string& wait_str = "@WAIT-FOR:";
const std::string& execute_str = "@EXECUTE-AND-WAIT-FOR:";
- const std::string& until_str = "@RUN-UNTIL-EVENT:";
+ const std::string& until_str = formatter_->GetRunUntilEventString();
const std::string& default_action_on_str = "@DEFAULT-ACTION-ON:";
if (base::StartsWith(line, allow_empty_str, base::CompareCase::SENSITIVE)) {
- property_filters_.push_back(
- PropertyFilter(base::UTF8ToUTF16(line.substr(allow_empty_str.size())),
- PropertyFilter::ALLOW_EMPTY));
+ property_filters_.emplace_back(
+ line.substr(allow_empty_str.size()), PropertyFilter::ALLOW_EMPTY);
} else if (base::StartsWith(line, allow_str,
base::CompareCase::SENSITIVE)) {
- property_filters_.push_back(
- PropertyFilter(base::UTF8ToUTF16(line.substr(allow_str.size())),
- PropertyFilter::ALLOW));
+ property_filters_.emplace_back(line.substr(allow_str.size()), PropertyFilter::ALLOW);
} else if (base::StartsWith(line, deny_str, base::CompareCase::SENSITIVE)) {
- property_filters_.push_back(
- PropertyFilter(base::UTF8ToUTF16(line.substr(deny_str.size())),
- PropertyFilter::DENY));
+ property_filters_.emplace_back(line.substr(deny_str.size()), PropertyFilter::DENY);
} else if (base::StartsWith(line, deny_node_str,
base::CompareCase::SENSITIVE)) {
const auto& node_filter = line.substr(deny_node_str.size());
diff --git a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index 25a997f2935..d3af2983315 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -20,6 +20,7 @@
#include "content/browser/accessibility/accessibility_event_recorder.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/accessibility/dump_accessibility_browsertest_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/accessibility_tree_formatter.h"
@@ -30,6 +31,7 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
+#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
namespace content {
@@ -73,16 +75,13 @@ class DumpAccessibilityEventsTest : public DumpAccessibilityTestBase {
std::vector<PropertyFilter>* property_filters) override {
// Suppress spurious focus events on the document object.
property_filters->push_back(
- PropertyFilter(base::ASCIIToUTF16("EVENT_OBJECT_FOCUS*DOCUMENT*"),
- PropertyFilter::DENY));
- property_filters->push_back(
- PropertyFilter(base::ASCIIToUTF16("AutomationFocusChanged*document*"),
- PropertyFilter::DENY));
+ PropertyFilter("EVENT_OBJECT_FOCUS*DOCUMENT*", PropertyFilter::DENY));
+ property_filters->push_back(PropertyFilter(
+ "AutomationFocusChanged*document*", PropertyFilter::DENY));
// Implementing IRawElementProviderAdviseEvents causes Win7 to fire
// spurious focus events (regardless of what the implementation does).
property_filters->push_back(PropertyFilter(
- base::ASCIIToUTF16("AutomationFocusChanged on role=region"),
- PropertyFilter::DENY));
+ "AutomationFocusChanged on role=region", PropertyFilter::DENY));
}
std::vector<std::string> Dump(std::vector<std::string>& run_until) override;
@@ -91,13 +90,18 @@ class DumpAccessibilityEventsTest : public DumpAccessibilityTestBase {
void RunEventTest(const base::FilePath::CharType* file_path);
private:
+ void OnEventRecorded(AccessibilityNotificationWaiter* waiter,
+ const std::string& event) {
+ waiter->Quit();
+ }
+
base::string16 initial_tree_;
base::string16 final_tree_;
};
bool IsRecordingComplete(AccessibilityEventRecorder& event_recorder,
std::vector<std::string>& run_until) {
- // If no @RUN-UNTIL-EVENT directives, then having any events is enough.
+ // If no @*-RUN-UNTIL-EVENT directives, then having any events is enough.
LOG(ERROR) << "=== IsRecordingComplete#1 run_until size=" << run_until.size();
if (run_until.empty())
return true;
@@ -143,16 +147,27 @@ std::vector<std::string> DumpAccessibilityEventsTest::Dump(
waiter.reset(new AccessibilityNotificationWaiter(
shell()->web_contents(), ui::kAXModeComplete, ax::mojom::Event::kNone));
+ // It's possible for platform events to be received after all blink or
+ // generated events have been fired. Unblock the |waiter| when this happens.
+ event_recorder->ListenToEvents(
+ base::BindRepeating(&DumpAccessibilityEventsTest::OnEventRecorded,
+ base::Unretained(this), waiter.get()));
+
base::Value go_results =
ExecuteScriptAndGetValue(web_contents->GetMainFrame(), "go()");
run_go_again = go_results.is_bool() && go_results.GetBool();
for (;;) {
- waiter->WaitForNotification(); // Run at least once.
+ // Wait for at least one event. This may unblock either when |waiter|
+ // observes either an ax::mojom::Event or ui::AXEventGenerator::Event, or
+ // when |event_recorder| records a platform event.
+ waiter->WaitForNotification();
if (IsRecordingComplete(*event_recorder, run_until))
break;
}
+ event_recorder->StopListeningToEvents();
+
// More than one accessibility event could have been generated.
// To make sure we've received all accessibility events, add a
// sentinel by calling SignalEndOfTest and waiting for a kEndOfTest
@@ -181,7 +196,7 @@ std::vector<std::string> DumpAccessibilityEventsTest::Dump(
for (size_t i = 0; i < event_logs.size(); ++i) {
if (AccessibilityTreeFormatter::MatchesPropertyFilters(
- property_filters_, base::UTF8ToUTF16(event_logs[i]), true)) {
+ property_filters_, event_logs[i], true)) {
result.push_back(event_logs[i]);
}
}
@@ -470,6 +485,11 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
RunEventTest(FILE_PATH_LITERAL("checked-state-changed.html"));
}
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsCheckedMixedChanged) {
+ RunEventTest(FILE_PATH_LITERAL("checked-mixed-changed.html"));
+}
+
// http:/crbug.com/889013
IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
DISABLED_AccessibilityEventsCaretHide) {
@@ -497,9 +517,12 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
#endif
IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
MAYBE_AccessibilityEventsCaretBrowsingEnabled) {
- // Add command line switch that forces caret browsing on.
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableCaretBrowsing);
+ // This actually enables caret browsing without setting the pref.
+ shell()->web_contents()->GetMutableRendererPrefs()->caret_browsing_enabled =
+ true;
+ // This notifies accessibility that caret browsing is on so that it sends
+ // accessibility events when the caret moves.
+ BrowserAccessibilityStateImpl::GetInstance()->SetCaretBrowsingState(true);
RunEventTest(FILE_PATH_LITERAL("caret-browsing-enabled.html"));
}
@@ -519,6 +542,22 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaHiddenDescendants) {
+ RunEventTest(FILE_PATH_LITERAL("aria-hidden-descendants.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsAriaHiddenDescendantsAlreadyIgnored) {
+ RunEventTest(
+ FILE_PATH_LITERAL("aria-hidden-descendants-already-ignored.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsCSSDisplayDescendants) {
+ RunEventTest(FILE_PATH_LITERAL("css-display-descendants.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
AccessibilityEventsCSSFlexTextUpdate) {
RunEventTest(FILE_PATH_LITERAL("css-flex-text-update.html"));
}
@@ -529,6 +568,11 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsCSSVisibilityDescendants) {
+ RunEventTest(FILE_PATH_LITERAL("css-visibility-descendants.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
AccessibilityEventsCSSCollapse) {
RunEventTest(FILE_PATH_LITERAL("css-visibility-collapse.html"));
}
@@ -731,7 +775,7 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
}
// TODO(aboxhall): Fix flakiness on Windows and Mac
-#if defined(OS_WIN) || defined(OS_MACOSX)
+#if defined(OS_WIN) || defined(OS_MAC)
#define MAYBE_AccessibilityEventsReportValidityInvalidField \
DISABLED_AccessibilityEventsReportValidityInvalidField
#else
@@ -760,6 +804,11 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsStyleChanged) {
+ RunEventTest(FILE_PATH_LITERAL("style-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
AccessibilityEventsTabindexAddedOnPlainDiv) {
RunEventTest(FILE_PATH_LITERAL("tabindex-added-on-plain-div.html"));
}
@@ -786,6 +835,11 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsTextAlignChanged) {
+ RunEventTest(FILE_PATH_LITERAL("text-align-changed.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
AccessibilityEventsTextChanged) {
RunEventTest(FILE_PATH_LITERAL("text-changed.html"));
}
@@ -801,6 +855,16 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
}
IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsTextSelectionInsideHiddenElement) {
+ RunEventTest(FILE_PATH_LITERAL("text-selection-inside-hidden-element.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
+ AccessibilityEventsTextSelectionInsideVideo) {
+ RunEventTest(FILE_PATH_LITERAL("text-selection-inside-video.html"));
+}
+
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
AccessibilityEventsAriaCheckedChanged) {
RunEventTest(FILE_PATH_LITERAL("aria-checked-changed.html"));
}
@@ -902,7 +966,7 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest,
}
// Test is flaky on Linux. See crbug.com/990847 for more details.
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
#define MAYBE_DeleteSubtree DISABLED_DeleteSubtree
#else
#define MAYBE_DeleteSubtree DeleteSubtree
diff --git a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 86b7113203c..ca807ad5ae7 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -30,7 +30,7 @@
#include "ui/accessibility/accessibility_features.h"
#include "ui/accessibility/accessibility_switches.h"
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
#include "base/mac/mac_util.h"
#endif
@@ -62,10 +62,9 @@ class DumpAccessibilityTreeTest : public DumpAccessibilityTestBase {
void AddDefaultFilters(
std::vector<PropertyFilter>* property_filters) override;
void AddPropertyFilter(std::vector<PropertyFilter>* property_filters,
- std::string filter,
+ const std::string& filter,
PropertyFilter::Type type = PropertyFilter::ALLOW) {
- property_filters->push_back(
- PropertyFilter(base::ASCIIToUTF16(filter), type));
+ property_filters->push_back(PropertyFilter(filter, type));
}
void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -79,6 +78,10 @@ class DumpAccessibilityTreeTest : public DumpAccessibilityTestBase {
// Enable display locking, used in some tests.
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kEnableBlinkFeatures, "CSSContentVisibilityHiddenMatchable");
+ // kDisableAXMenuList is true on Chrome OS by default. Make it consistent
+ // for these cross-platform tests.
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kDisableAXMenuList, "false");
}
void RunAriaTest(const base::FilePath::CharType* file_path) {
@@ -420,6 +423,11 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
RunHtmlTest(FILE_PATH_LITERAL("combobox-optgroup.html"));
}
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+ AccessibilitySvgStyleElement) {
+ RunHtmlTest(FILE_PATH_LITERAL("svg-style-element.html"));
+}
+
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityAomBusy) {
RunAomTest(FILE_PATH_LITERAL("aom-busy.html"));
}
@@ -721,7 +729,14 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
RunAriaTest(FILE_PATH_LITERAL("aria-grid-extra-wrap-elems.html"));
}
-IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityAriaGridCell) {
+// https://crbug.com/1117594
+#if defined(OS_ANDROID)
+#define MAYBE_AccessibilityAriaGridCell DISABLED_AccessibilityAriaGridCell
+#else
+#define MAYBE_AccessibilityAriaGridCell AccessibilityAriaGridCell
+#endif
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+ MAYBE_AccessibilityAriaGridCell) {
RunAriaTest(FILE_PATH_LITERAL("aria-gridcell.html"));
}
@@ -786,6 +801,10 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityAriaListBox) {
RunAriaTest(FILE_PATH_LITERAL("aria-listbox.html"));
}
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+ AccessibilityAriaListBoxDisabled) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-listbox-disabled.html"));
+}
// TODO(crbug.com/983802): Flaky.
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
DISABLED_AccessibilityAriaListBoxActiveDescendant) {
@@ -843,6 +862,16 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityAriaMenuItem) {
RunAriaTest(FILE_PATH_LITERAL("aria-menuitem.html"));
}
+#if defined(OS_ANDROID)
+#define MAYBE_AccessibilityAriaMenuItemInGroup \
+ DISABLED_AccessibilityAriaMenuItemInGroup
+#else
+#define MAYBE_AccessibilityAriaMenuItemInGroup AccessibilityAriaMenuItemInGroup
+#endif
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+ MAYBE_AccessibilityAriaMenuItemInGroup) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-menuitem-in-group.html"));
+}
// crbug.com/442278 will stop creating new text elements representing title.
// Re-baseline after the Blink change goes in
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
@@ -1387,7 +1416,7 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityGraphicsRoles) {
RunAriaTest(FILE_PATH_LITERAL("graphics-roles.html"));
}
-#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#if defined(OS_ANDROID) || defined(OS_MAC)
// Flaky failures: http://crbug.com/445929.
// Mac failures: http://crbug.com/571712.
#define MAYBE_AccessibilityContenteditableDescendants \
@@ -1406,7 +1435,7 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
RunHtmlTest(FILE_PATH_LITERAL("element-class-id-src-attr.html"));
}
-#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#if defined(OS_ANDROID) || defined(OS_MAC)
// Flaky failures: http://crbug.com/445929.
// Mac failures: http://crbug.com/571712.
#define MAYBE_AccessibilityContenteditableDescendantsWithSelection \
@@ -1705,7 +1734,7 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityInputDateTime) {
}
// Fails on OS X 10.9 and higher <https://crbug.com/430622>.
-#if !defined(OS_MACOSX)
+#if !defined(OS_MAC)
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
AccessibilityInputDateTimeLocal) {
RunHtmlTest(FILE_PATH_LITERAL("input-datetime-local.html"));
@@ -1716,7 +1745,14 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityInputEmail) {
RunHtmlTest(FILE_PATH_LITERAL("input-email.html"));
}
-IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityInputFile) {
+// http://crbug.com/1114193
+#if defined(OS_ANDROID)
+#define MAYBE_AccessibilityInputFile DISABLED_AccessibilityInputFile
+#else
+#define MAYBE_AccessibilityInputFile AccessibilityInputFile
+#endif
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+ MAYBE_AccessibilityInputFile) {
RunHtmlTest(FILE_PATH_LITERAL("input-file.html"));
}
@@ -1855,7 +1891,7 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
RunHtmlTest(FILE_PATH_LITERAL("input-text-with-selection.html"));
}
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
// TODO(1038813): The /blink test pass is different on Windows and Mac, versus
// Linux.
#define MAYBE_AccessibilityInputTime DISABLED_AccessibilityInputTime
@@ -2098,10 +2134,12 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
RunHtmlTest(FILE_PATH_LITERAL("portal-name-from-text.html"));
}
+// Flaky on all platforms: crbug.com/1103753.
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
- AccessibilityPortalWithWidgetInside) {
+ DISABLED_AccessibilityPortalWithWidgetInside) {
RunHtmlTest(FILE_PATH_LITERAL("portal-with-widget-inside.html"));
}
+
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
AccessibilityPortalNameFromVisibleText) {
RunHtmlTest(FILE_PATH_LITERAL("portal-name-from-visible-text.html"));
@@ -2144,7 +2182,13 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
RunHtmlTest(FILE_PATH_LITERAL("selection-container.html"));
}
-IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilitySelect) {
+// https://crbug.com/1117594
+#if defined(OS_ANDROID)
+#define MAYBE_AccessibilitySelect DISABLED_AccessibilitySelect
+#else
+#define MAYBE_AccessibilitySelect AccessibilitySelect
+#endif
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MAYBE_AccessibilitySelect) {
RunHtmlTest(FILE_PATH_LITERAL("select.html"));
}
@@ -2159,12 +2203,20 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
FILE_PATH_LITERAL("select-follows-focus-aria-selected-false.html"));
}
+// https://crbug.com/1117594
+#if defined(OS_ANDROID)
+#define MAYBE_AccessibilitySelectFollowsFocusMultiselect \
+ DISABLED_AccessibilitySelectFollowsFocusMultiselect
+#else
+#define MAYBE_AccessibilitySelectFollowsFocusMultiselect \
+ AccessibilitySelectFollowsFocusMultiselect
+#endif
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
- AccessibilitySelectFollowsFocusMultiselect) {
+ MAYBE_AccessibilitySelectFollowsFocusMultiselect) {
RunHtmlTest(FILE_PATH_LITERAL("select-follows-focus-multiselect.html"));
}
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
#define MAYBE_AccessibilitySource DISABLED_AccessibilitySource
#else
#define MAYBE_AccessibilitySource AccessibilitySource
@@ -2205,6 +2257,10 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilitySvg) {
RunHtmlTest(FILE_PATH_LITERAL("svg.html"));
}
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilitySvgG) {
+ RunHtmlTest(FILE_PATH_LITERAL("svg-g.html"));
+}
+
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityTableSimple) {
RunHtmlTest(FILE_PATH_LITERAL("table-simple.html"));
}
@@ -2257,6 +2313,10 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
RunHtmlTest(FILE_PATH_LITERAL("table-multiple-row-and-column-headers.html"));
}
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityTextAlign) {
+ RunHtmlTest(FILE_PATH_LITERAL("text-align.html"));
+}
+
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
AccessibilityTextDecorationStyles) {
RunHtmlTest(FILE_PATH_LITERAL("text-decoration-styles.html"));
@@ -2288,7 +2348,7 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityTitleChanged) {
RunHtmlTest(FILE_PATH_LITERAL("title-changed.html"));
}
-#if defined(OS_WIN) || defined(OS_MACOSX)
+#if defined(OS_WIN) || defined(OS_MAC)
// Flaky on Win/Mac: crbug.com/508532
#define MAYBE_AccessibilityTransition DISABLED_AccessibilityTransition
#else
@@ -2307,6 +2367,11 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityUl) {
RunHtmlTest(FILE_PATH_LITERAL("ul.html"));
}
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
+ AccessibilityNotUserSelectable) {
+ RunCSSTest(FILE_PATH_LITERAL("user-select.html"));
+}
+
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityVar) {
RunHtmlTest(FILE_PATH_LITERAL("var.html"));
}
@@ -2316,6 +2381,10 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, DISABLED_AccessibilityVideo) {
RunHtmlTest(FILE_PATH_LITERAL("video.html"));
}
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityVideoTextOnly) {
+ RunHtmlTest(FILE_PATH_LITERAL("video-text-only.html"));
+}
+
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
AccessibilityNodeChangedCrashInEditableText) {
RunHtmlTest(FILE_PATH_LITERAL("node-changed-crash-in-editable-text.html"));
@@ -2462,6 +2531,10 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
RunLanguageDetectionTest(FILE_PATH_LITERAL("dynamic-reparenting.html"));
}
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, ComboboxItemVisibility) {
+ RunHtmlTest(FILE_PATH_LITERAL("combobox-item-visibility.html"));
+}
+
//
// These tests cover features of the testing infrastructure itself.
//
diff --git a/chromium/content/browser/accessibility/hit_testing_browsertest.cc b/chromium/content/browser/accessibility/hit_testing_browsertest.cc
index 26cbd0452b3..f0ca9de1290 100644
--- a/chromium/content/browser/accessibility/hit_testing_browsertest.cc
+++ b/chromium/content/browser/accessibility/hit_testing_browsertest.cc
@@ -268,12 +268,9 @@ AccessibilityHitTestingBrowserTest::FormatHitTestAccessibilityTree() {
AccessibilityTreeFormatterBlink::CreateBlink();
accessibility_tree_formatter->set_show_ids(true);
accessibility_tree_formatter->SetPropertyFilters(
- {{base::ASCIIToUTF16("name=*"),
- AccessibilityTreeFormatter::PropertyFilter::ALLOW},
- {base::ASCIIToUTF16("location=*"),
- AccessibilityTreeFormatter::PropertyFilter::ALLOW},
- {base::ASCIIToUTF16("size=*"),
- AccessibilityTreeFormatter::PropertyFilter::ALLOW}});
+ {{"name=*", AccessibilityTreeFormatter::PropertyFilter::ALLOW},
+ {"location=*", AccessibilityTreeFormatter::PropertyFilter::ALLOW},
+ {"size=*", AccessibilityTreeFormatter::PropertyFilter::ALLOW}});
base::string16 accessibility_tree;
accessibility_tree_formatter->FormatAccessibilityTreeForTesting(
GetRootAndAssertNonNull(), &accessibility_tree);
@@ -573,7 +570,7 @@ IN_PROC_BROWSER_TEST_P(AccessibilityHitTestingBrowserTest,
}
}
-#if !defined(OS_ANDROID) && !defined(OS_MACOSX)
+#if !defined(OS_ANDROID) && !defined(OS_MAC)
IN_PROC_BROWSER_TEST_P(AccessibilityHitTestingBrowserTest,
CachingAsyncHitTest_WithPinchZoom) {
ASSERT_TRUE(embedded_test_server()->Start());
@@ -665,7 +662,7 @@ IN_PROC_BROWSER_TEST_P(AccessibilityHitTestingBrowserTest,
}
// Timeouts on Linux. TODO(crbug.com/1083805): Enable this test.
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
#define MAYBE_CachingAsyncHitTestMissesElement_WithPinchZoom \
DISABLED_CachingAsyncHitTestMissesElement_WithPinchZoom
#else
@@ -728,7 +725,7 @@ IN_PROC_BROWSER_TEST_P(AccessibilityHitTestingBrowserTest,
}
}
-#endif // !defined(OS_ANDROID) && !defined(OS_MACOSX)
+#endif // !defined(OS_ANDROID) && !defined(OS_MAC)
// GetAXPlatformNode is currently only supported on windows and linux (excluding
// Chrome OS or Chromecast)
diff --git a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
index 6a36c176910..ab9e0e55316 100644
--- a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
+++ b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
@@ -236,7 +236,6 @@ bool AccessibilityButtonPredicate(BrowserAccessibility* start,
BrowserAccessibility* node) {
switch (node->GetRole()) {
case ax::mojom::Role::kButton:
- case ax::mojom::Role::kMenuButton:
case ax::mojom::Role::kPopUpButton:
case ax::mojom::Role::kSwitch:
case ax::mojom::Role::kToggleButton:
diff --git a/chromium/content/browser/accessibility/web_contents_accessibility_android.cc b/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
index b53ca692ff8..120d6e64a90 100644
--- a/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -797,7 +797,9 @@ jboolean WebContentsAccessibilityAndroid::PopulateAccessibilityNodeInfo(
base::android::ConvertUTF16ToJavaString(
env, node->GetInheritedString16Attribute(
ax::mojom::StringAttribute::kLanguage)),
- suggestion_starts_java, suggestion_ends_java, suggestion_text_java);
+ suggestion_starts_java, suggestion_ends_java, suggestion_text_java,
+ base::android::ConvertUTF16ToJavaString(env,
+ node->GetStateDescription()));
base::string16 element_id;
if (node->GetHtmlAttribute("id", &element_id)) {
@@ -808,9 +810,9 @@ jboolean WebContentsAccessibilityAndroid::PopulateAccessibilityNodeInfo(
UpdateAccessibilityNodeInfoBoundsRect(env, obj, info, unique_id, node);
- Java_WebContentsAccessibilityImpl_setAccessibilityNodeInfoLollipopAttributes(
- env, obj, info, node->CanOpenPopup(), node->IsContentInvalid(),
- node->IsDismissable(), node->IsMultiLine(), node->AndroidInputType(),
+ Java_WebContentsAccessibilityImpl_setAccessibilityNodeInfoAttributes(
+ env, obj, info, node->CanOpenPopup(), node->IsDismissable(),
+ node->IsMultiLine(), node->AndroidInputType(),
node->AndroidLiveRegionType(),
base::android::ConvertUTF16ToJavaString(
env, node->GetContentInvalidErrorMessage()));
@@ -894,30 +896,6 @@ jboolean WebContentsAccessibilityAndroid::PopulateAccessibilityEvent(
break;
}
- Java_WebContentsAccessibilityImpl_setAccessibilityEventLollipopAttributes(
- env, obj, event, node->CanOpenPopup(), node->IsContentInvalid(),
- node->IsDismissable(), node->IsMultiLine(), node->AndroidInputType(),
- node->AndroidLiveRegionType());
- if (node->IsCollection()) {
- Java_WebContentsAccessibilityImpl_setAccessibilityEventCollectionInfo(
- env, obj, event, node->RowCount(), node->ColumnCount(),
- node->IsHierarchical());
- }
- if (node->IsHeading()) {
- Java_WebContentsAccessibilityImpl_setAccessibilityEventHeadingFlag(
- env, obj, event, true);
- }
- if (node->IsCollectionItem()) {
- Java_WebContentsAccessibilityImpl_setAccessibilityEventCollectionItemInfo(
- env, obj, event, node->RowIndex(), node->RowSpan(), node->ColumnIndex(),
- node->ColumnSpan());
- }
- if (node->IsRangeType()) {
- Java_WebContentsAccessibilityImpl_setAccessibilityEventRangeInfo(
- env, obj, event, node->AndroidRangeType(), node->RangeMin(),
- node->RangeMax(), node->RangeCurrentValue());
- }
-
return true;
}