From c30a6232df03e1efbd9f3b226777b07e087a1122 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 12 Oct 2020 14:27:29 +0200 Subject: BASELINE: Update Chromium to 85.0.4183.140 Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen --- chromium/ui/accessibility/BUILD.gn | 207 +++------ .../ui/accessibility/accessibility_features.cc | 32 ++ chromium/ui/accessibility/accessibility_features.h | 50 ++- chromium/ui/accessibility/accessibility_switches.h | 37 +- chromium/ui/accessibility/ax_enum_util.cc | 8 +- chromium/ui/accessibility/ax_enums.mojom | 28 +- chromium/ui/accessibility/ax_event.cc | 2 +- chromium/ui/accessibility/ax_event_generator.cc | 21 +- chromium/ui/accessibility/ax_event_generator.h | 13 +- chromium/ui/accessibility/ax_mode.cc | 3 + chromium/ui/accessibility/ax_mode.h | 7 +- chromium/ui/accessibility/ax_node.cc | 288 ++++++++---- chromium/ui/accessibility/ax_node.h | 74 ++- chromium/ui/accessibility/ax_node_data.cc | 49 +- chromium/ui/accessibility/ax_node_data.h | 7 +- chromium/ui/accessibility/ax_node_position.cc | 5 +- .../ui/accessibility/ax_node_position_unittest.cc | 129 ++++++ chromium/ui/accessibility/ax_param_traits_macros.h | 1 + chromium/ui/accessibility/ax_position.h | 27 +- chromium/ui/accessibility/ax_range_unittest.cc | 10 +- chromium/ui/accessibility/ax_role_properties.cc | 12 +- chromium/ui/accessibility/ax_role_properties.h | 8 +- chromium/ui/accessibility/ax_table_fuzzer.cc | 27 +- chromium/ui/accessibility/ax_tree.cc | 88 +++- chromium/ui/accessibility/ax_tree.h | 31 +- chromium/ui/accessibility/ax_tree_id.cc | 12 +- chromium/ui/accessibility/ax_tree_unittest.cc | 313 ++++++++++--- chromium/ui/accessibility/ax_tree_update.h | 17 +- .../extensions/chromevoxclassic/BUILD.gn | 6 +- .../testing/chromevox_unittest_base.js | 9 +- .../ui/accessibility/mojom/ax_tree_update.mojom | 2 + .../mojom/ax_tree_update_mojom_traits.cc | 2 +- .../mojom/ax_tree_update_mojom_traits.h | 7 + chromium/ui/accessibility/platform/BUILD.gn | 142 ++++++ .../accessibility/platform/ax_fragment_root_win.cc | 66 +++ .../platform/ax_fragment_root_win_unittest.cc | 104 ++++- .../ui/accessibility/platform/ax_platform_node.h | 2 +- .../platform/ax_platform_node_auralinux.cc | 169 ++++--- .../platform/ax_platform_node_auralinux.h | 3 +- .../ax_platform_node_auralinux_unittest.cc | 19 +- .../platform/ax_platform_node_base.cc | 108 ++--- .../accessibility/platform/ax_platform_node_base.h | 54 +-- .../platform/ax_platform_node_delegate.h | 30 +- .../platform/ax_platform_node_delegate_base.cc | 56 ++- .../platform/ax_platform_node_delegate_base.h | 12 +- .../accessibility/platform/ax_platform_node_mac.h | 1 + .../accessibility/platform/ax_platform_node_mac.mm | 21 +- ...platform_node_textchildprovider_win_unittest.cc | 2 +- .../ax_platform_node_textprovider_win_unittest.cc | 18 +- .../ax_platform_node_textrangeprovider_win.cc | 43 +- .../ax_platform_node_textrangeprovider_win.h | 10 + ...platform_node_textrangeprovider_win_unittest.cc | 27 +- .../platform/ax_platform_node_unittest.cc | 8 +- .../accessibility/platform/ax_platform_node_win.cc | 173 ++++++- .../accessibility/platform/ax_platform_node_win.h | 35 +- .../platform/ax_platform_node_win_unittest.cc | 496 ++++++++++++++++++++- .../platform/ax_platform_node_win_unittest.h | 3 + .../platform/ax_platform_relation_win.cc | 6 + .../accessibility/platform/ichromeaccessible.idl | 64 +++ .../accessibility/platform/test_ax_node_wrapper.cc | 54 ++- .../accessibility/platform/test_ax_node_wrapper.h | 4 + .../ui/accessibility/platform/uia_registrar_win.cc | 50 +++ .../ui/accessibility/platform/uia_registrar_win.h | 45 ++ chromium/ui/accessibility/test_ax_node_helper.cc | 204 +++++++++ chromium/ui/accessibility/test_ax_node_helper.h | 50 +++ 65 files changed, 2863 insertions(+), 748 deletions(-) create mode 100644 chromium/ui/accessibility/platform/BUILD.gn create mode 100644 chromium/ui/accessibility/platform/ichromeaccessible.idl create mode 100644 chromium/ui/accessibility/platform/uia_registrar_win.cc create mode 100644 chromium/ui/accessibility/platform/uia_registrar_win.h create mode 100644 chromium/ui/accessibility/test_ax_node_helper.cc create mode 100644 chromium/ui/accessibility/test_ax_node_helper.h (limited to 'chromium/ui/accessibility') diff --git a/chromium/ui/accessibility/BUILD.gn b/chromium/ui/accessibility/BUILD.gn index fc74899db46..0297bff6f13 100644 --- a/chromium/ui/accessibility/BUILD.gn +++ b/chromium/ui/accessibility/BUILD.gn @@ -16,6 +16,10 @@ if (is_android) { import("//build/config/android/rules.gni") } +if (is_win) { + import("//build/toolchain/win/midl.gni") +} + # Reset sources_assignment_filter for the BUILD.gn file to prevent # regression during the migration of Chromium away from the feature. # See docs/no_sources_assignment_filter.md for more information. @@ -41,6 +45,10 @@ jumbo_component("ax_base") { defines = [ "AX_BASE_IMPLEMENTATION" ] sources = [ + "accessibility_features.cc", + "accessibility_features.h", + "accessibility_switches.cc", + "accessibility_switches.h", "ax_base_export.h", "ax_enum_util.cc", "ax_enum_util.h", @@ -70,14 +78,18 @@ jumbo_component("ax_base") { ] } +#if (is_win) { +# midl("ichromeaccessible") { +# sources = [ +# "platform/ichromeaccessible.idl", +# ] +# } +#} + jumbo_component("accessibility") { defines = [ "AX_IMPLEMENTATION" ] sources = [ - "accessibility_features.cc", - "accessibility_features.h", - "accessibility_switches.cc", - "accessibility_switches.h", "ax_action_data.cc", "ax_action_data.h", "ax_action_handler.cc", @@ -132,85 +144,21 @@ jumbo_component("accessibility") { "ax_tree_update_forward.h", "null_ax_action_target.cc", "null_ax_action_target.h", - - # ax_android_constants* are used in ax_assistant_structure.cc. - "platform/ax_android_constants.cc", - "platform/ax_android_constants.h", - - # ax_platform_node* are used for enable/disable accessibility and - # test_ax_node_wrapper. - "platform/ax_platform_node.cc", - "platform/ax_platform_node.h", - "platform/ax_platform_node_base.cc", - "platform/ax_platform_node_base.h", - "platform/ax_platform_node_delegate.h", - "platform/ax_platform_node_delegate_base.cc", - "platform/ax_platform_node_delegate_base.h", - - # ax_platform_node_test_helper.{cc,h} are used in - # browser_view_browsertest.cc - "platform/ax_platform_node_test_helper.cc", - "platform/ax_platform_node_test_helper.h", - - # ax_unique_id.{cc,h} are used in browser_accessibility.cc and - # view_accessibility.cc - "platform/ax_unique_id.cc", - "platform/ax_unique_id.h", - - # compute_attributes.{cc,h} are used in - # accessibility_tree_formatter_blink.cc - "platform/compute_attributes.cc", - "platform/compute_attributes.h", ] - deps = [ "//third_party/cld_3/src/src:cld_3" ] + deps = [ + "//base/util/values:values_util", + "//third_party/cld_3/src/src:cld_3", + ] public_deps = [ ":ax_base", - "//ui/display", + "//ui/accessibility/platform", ] - if (has_native_accessibility) { - sources += [ - "platform/ax_platform_text_boundary.cc", - "platform/ax_platform_text_boundary.h", - ] - - if (use_atk) { - # ax_platform_text_boundary.h includes atk.h, so ATK is needed as a public - # config to ensure anything that includes this is able to find atk.h. - public_configs = [ "//build/config/linux/atk" ] - } - } - - if (is_win) { - sources += [ - "platform/ax_fragment_root_delegate_win.h", - "platform/ax_fragment_root_win.cc", - "platform/ax_fragment_root_win.h", - "platform/ax_platform_node_delegate_utils_win.cc", - "platform/ax_platform_node_delegate_utils_win.h", - "platform/ax_platform_node_textchildprovider_win.cc", - "platform/ax_platform_node_textchildprovider_win.h", - "platform/ax_platform_node_textprovider_win.cc", - "platform/ax_platform_node_textprovider_win.h", - "platform/ax_platform_node_textrangeprovider_win.cc", - "platform/ax_platform_node_textrangeprovider_win.h", - "platform/ax_platform_node_win.cc", - "platform/ax_platform_node_win.h", - "platform/ax_platform_relation_win.cc", - "platform/ax_platform_relation_win.h", - "platform/ax_system_caret_win.cc", - "platform/ax_system_caret_win.h", - ] - - public_deps += [ "//third_party/iaccessible2" ] - - libs = [ - "oleacc.lib", - "uiautomationcore.lib", - ] - } + # Allows the files from //ui/accessibility/platform includes headers + # from this directory. + allow_circular_includes_from = [ "//ui/accessibility/platform" ] if (!is_ios) { sources += [ @@ -225,40 +173,6 @@ jumbo_component("accessibility") { ] } - if (is_mac) { - sources += [ - "platform/ax_platform_node_mac.h", - "platform/ax_platform_node_mac.mm", - ] - - libs = [ - "AppKit.framework", - "Foundation.framework", - ] - } - - if (use_atk) { - sources += [ - "platform/atk_util_auralinux.cc", - "platform/atk_util_auralinux.h", - "platform/atk_util_auralinux_gtk.cc", - "platform/ax_platform_atk_hyperlink.cc", - "platform/ax_platform_atk_hyperlink.h", - "platform/ax_platform_node_auralinux.cc", - "platform/ax_platform_node_auralinux.h", - ] - - configs += [ "//build/config/linux/atk" ] - - if (use_glib) { - configs += [ "//build/config/linux:glib" ] - } - - if (use_x11) { - public_deps += [ "//ui/gfx/x" ] - } - } - if (use_aura) { sources += [ "aura/aura_window_properties.cc", @@ -281,15 +195,21 @@ source_set("ax_assistant") { static_library("test_support") { testonly = true sources = [ - # test_ax_node_wrapper.{cc,h} are used in ax_range_unittest.cc - "platform/test_ax_node_wrapper.cc", - "platform/test_ax_node_wrapper.h", + "test_ax_node_helper.cc", + "test_ax_node_helper.h", "test_ax_tree_manager.cc", "test_ax_tree_manager.h", "tree_generator.cc", "tree_generator.h", ] + if (has_native_accessibility) { + sources += [ + "platform/test_ax_node_wrapper.cc", + "platform/test_ax_node_wrapper.h", + ] + } + deps = [ ":accessibility" ] } @@ -325,23 +245,6 @@ test("accessibility_unittests") { "run_all_unittests.cc", ] - if (is_win) { - sources += [ - "platform/ax_fragment_root_win_unittest.cc", - "platform/ax_platform_node_textchildprovider_win_unittest.cc", - "platform/ax_platform_node_textprovider_win_unittest.cc", - "platform/ax_platform_node_textrangeprovider_win_unittest.cc", - "platform/ax_platform_node_win_unittest.cc", - "platform/ax_platform_node_win_unittest.h", - ] - } - - if (has_native_accessibility) { - # This test depends heavily on NativeViewAccessible, which is only - # implemented on these platforms. - sources += [ "platform/ax_platform_node_base_unittest.cc" ] - } - deps = [ ":accessibility", ":test_support", @@ -357,22 +260,40 @@ test("accessibility_unittests") { "//ui/gfx:test_support", ] - if (is_win) { - deps += [ "//third_party/iaccessible2" ] + if (has_native_accessibility) { + # This test depends heavily on NativeViewAccessible, which is only + # implemented on these platforms. + sources += [ "platform/ax_platform_node_base_unittest.cc" ] - libs = [ - "oleacc.lib", - "uiautomationcore.lib", - ] - } + if (is_win) { + sources += [ + "platform/ax_fragment_root_win_unittest.cc", + "platform/ax_platform_node_textchildprovider_win_unittest.cc", + "platform/ax_platform_node_textprovider_win_unittest.cc", + "platform/ax_platform_node_textrangeprovider_win_unittest.cc", + "platform/ax_platform_node_win_unittest.cc", + "platform/ax_platform_node_win_unittest.h", + ] + + deps += [ + "//third_party/iaccessible2", + "//ui/accessibility/platform:ichromeaccessible", + ] + + libs = [ + "oleacc.lib", + "uiautomationcore.lib", + ] + } - if (use_atk) { - sources += [ - "platform/atk_util_auralinux_unittest.cc", - "platform/ax_platform_node_auralinux_unittest.cc", - ] + if (use_atk) { + sources += [ + "platform/atk_util_auralinux_unittest.cc", + "platform/ax_platform_node_auralinux_unittest.cc", + ] - configs += [ "//build/config/linux/atk" ] + configs += [ "//build/config/linux/atk" ] + } } } diff --git a/chromium/ui/accessibility/accessibility_features.cc b/chromium/ui/accessibility/accessibility_features.cc index 6b6f63f1b90..4a52188c1b6 100644 --- a/chromium/ui/accessibility/accessibility_features.cc +++ b/chromium/ui/accessibility/accessibility_features.cc @@ -47,4 +47,36 @@ bool IsAccessibilityTreeForViewsEnabled() { ::features::kEnableAccessibilityTreeForViews); } +const base::Feature kAccessibilityFocusHighlight{ + "AccessibilityFocusHighlight", base::FEATURE_DISABLED_BY_DEFAULT}; + +bool IsAccessibilityFocusHighlightEnabled() { + return base::FeatureList::IsEnabled(::features::kAccessibilityFocusHighlight); +} + +#if defined(OS_WIN) +const base::Feature kIChromeAccessible{"IChromeAccessible", + base::FEATURE_DISABLED_BY_DEFAULT}; + +bool IsIChromeAccessibleEnabled() { + return base::FeatureList::IsEnabled(::features::kIChromeAccessible); +} +#endif // defined(OS_WIN) + +#if defined(OS_CHROMEOS) +const base::Feature kAccessibilityCursorColor{ + "AccessibilityCursorColor", base::FEATURE_DISABLED_BY_DEFAULT}; + +bool IsAccessibilityCursorColorEnabled() { + return base::FeatureList::IsEnabled(::features::kAccessibilityCursorColor); +} +#endif // defined(OS_CHROMEOS) + +const base::Feature kAugmentExistingImageLabels{ + "AugmentExistingImageLabels", base::FEATURE_DISABLED_BY_DEFAULT}; + +bool IsAugmentExistingImageLabelsEnabled() { + return base::FeatureList::IsEnabled(::features::kAugmentExistingImageLabels); +} + } // namespace features diff --git a/chromium/ui/accessibility/accessibility_features.h b/chromium/ui/accessibility/accessibility_features.h index b7fa71ec600..743a32c5bc7 100644 --- a/chromium/ui/accessibility/accessibility_features.h +++ b/chromium/ui/accessibility/accessibility_features.h @@ -8,35 +8,67 @@ #include "base/feature_list.h" #include "build/build_config.h" -#include "ui/accessibility/ax_export.h" +#include "ui/accessibility/ax_base_export.h" namespace features { -AX_EXPORT extern const base::Feature kEnableAccessibilityExposeARIAAnnotations; +AX_BASE_EXPORT extern const base::Feature + kEnableAccessibilityExposeARIAAnnotations; // Returns true if ARIA annotations should be exposed to the browser AX Tree. -AX_EXPORT bool IsAccessibilityExposeARIAAnnotationsEnabled(); +AX_BASE_EXPORT bool IsAccessibilityExposeARIAAnnotationsEnabled(); -AX_EXPORT extern const base::Feature kEnableAccessibilityExposeDisplayNone; +AX_BASE_EXPORT extern const base::Feature kEnableAccessibilityExposeDisplayNone; // Returns true if "display: none" nodes should be exposed to the // browser process AXTree. -AX_EXPORT bool IsAccessibilityExposeDisplayNoneEnabled(); +AX_BASE_EXPORT bool IsAccessibilityExposeDisplayNoneEnabled(); -AX_EXPORT extern const base::Feature kEnableAccessibilityExposeHTMLElement; +AX_BASE_EXPORT extern const base::Feature kEnableAccessibilityExposeHTMLElement; // Returns true if the element should be exposed to the // browser process AXTree (as an ignored node). -AX_EXPORT bool IsAccessibilityExposeHTMLElementEnabled(); +AX_BASE_EXPORT bool IsAccessibilityExposeHTMLElementEnabled(); // Serializes accessibility information from the Views tree and deserializes it // into an AXTree in the browser process. -AX_EXPORT extern const base::Feature kEnableAccessibilityTreeForViews; +AX_BASE_EXPORT extern const base::Feature kEnableAccessibilityTreeForViews; // Returns true if the Views tree is exposed using an AXTree in the browser // process. Returns false if the Views tree is exposed to accessibility // directly. -AX_EXPORT bool IsAccessibilityTreeForViewsEnabled(); +AX_BASE_EXPORT bool IsAccessibilityTreeForViewsEnabled(); + +AX_BASE_EXPORT extern const base::Feature kAccessibilityFocusHighlight; + +// Returns true if the accessibility focus highlight feature is enabled, +// which draws a visual highlight around the focused element on the page +// briefly whenever focus changes. +AX_BASE_EXPORT bool IsAccessibilityFocusHighlightEnabled(); + +#if defined(OS_WIN) +// Enables an experimental Chrome-specific accessibility COM API +AX_BASE_EXPORT extern const base::Feature kIChromeAccessible; + +// Returns true if the IChromeAccessible COM API is enabled. +AX_BASE_EXPORT bool IsIChromeAccessibleEnabled(); + +#endif // defined(OS_WIN) + +#if defined(OS_CHROMEOS) +AX_BASE_EXPORT extern const base::Feature kAccessibilityCursorColor; + +// Returns true if the accessibility cursor color feature is enabled, letting +// users pick a custom cursor color. +AX_BASE_EXPORT bool IsAccessibilityCursorColorEnabled(); +#endif // defined(OS_CHROMEOS) + +// Enables Get Image Descriptions to augment existing images labels, +// rather than only provide descriptions for completely unlabeled images. +AX_BASE_EXPORT extern const base::Feature kAugmentExistingImageLabels; + +// Returns true if augmenting existing image labels is enabled. +AX_BASE_EXPORT bool IsAugmentExistingImageLabelsEnabled(); } // namespace features diff --git a/chromium/ui/accessibility/accessibility_switches.h b/chromium/ui/accessibility/accessibility_switches.h index 3cc38c37f10..2d3b9f2761b 100644 --- a/chromium/ui/accessibility/accessibility_switches.h +++ b/chromium/ui/accessibility/accessibility_switches.h @@ -7,41 +7,46 @@ #define UI_ACCESSIBILITY_ACCESSIBILITY_SWITCHES_H_ #include "build/build_config.h" -#include "ui/accessibility/ax_export.h" +#include "ui/accessibility/ax_base_export.h" namespace switches { -AX_EXPORT extern const char kEnableExperimentalAccessibilityAutoclick[]; -AX_EXPORT extern const char kEnableExperimentalAccessibilityLabelsDebugging[]; -AX_EXPORT extern const char kEnableExperimentalAccessibilityLanguageDetection[]; -AX_EXPORT extern const char +AX_BASE_EXPORT extern const char kEnableExperimentalAccessibilityAutoclick[]; +AX_BASE_EXPORT extern const char + kEnableExperimentalAccessibilityLabelsDebugging[]; +AX_BASE_EXPORT extern const char + kEnableExperimentalAccessibilityLanguageDetection[]; +AX_BASE_EXPORT extern const char kEnableExperimentalAccessibilityLanguageDetectionDynamic[]; -AX_EXPORT extern const char kEnableExperimentalAccessibilitySwitchAccess[]; -AX_EXPORT extern const char kEnableExperimentalAccessibilitySwitchAccessText[]; -AX_EXPORT extern const char +AX_BASE_EXPORT extern const char kEnableExperimentalAccessibilitySwitchAccess[]; +AX_BASE_EXPORT extern const char + kEnableExperimentalAccessibilitySwitchAccessText[]; +AX_BASE_EXPORT extern const char kEnableExperimentalAccessibilityChromeVoxAnnotations[]; -AX_EXPORT extern const char +AX_BASE_EXPORT extern const char kDisableExperimentalAccessibilityChromeVoxLanguageSwitching[]; -AX_EXPORT extern const char +AX_BASE_EXPORT extern const char kDisableExperimentalAccessibilityChromeVoxSearchMenus[]; -AX_EXPORT extern const char kEnableExperimentalAccessibilityChromeVoxTutorial[]; +AX_BASE_EXPORT extern const char + kEnableExperimentalAccessibilityChromeVoxTutorial[]; // Returns true if experimental accessibility language detection is enabled. -AX_EXPORT bool IsExperimentalAccessibilityLanguageDetectionEnabled(); +AX_BASE_EXPORT bool IsExperimentalAccessibilityLanguageDetectionEnabled(); // Returns true if experimental accessibility language detection support for // dynamic content is enabled. -AX_EXPORT bool IsExperimentalAccessibilityLanguageDetectionDynamicEnabled(); +AX_BASE_EXPORT bool +IsExperimentalAccessibilityLanguageDetectionDynamicEnabled(); // Returns true if experimental accessibility Switch Access text is enabled. -AX_EXPORT bool IsExperimentalAccessibilitySwitchAccessTextEnabled(); +AX_BASE_EXPORT bool IsExperimentalAccessibilitySwitchAccessTextEnabled(); #if defined(OS_WIN) -AX_EXPORT extern const char kEnableExperimentalUIAutomation[]; +AX_BASE_EXPORT extern const char kEnableExperimentalUIAutomation[]; #endif // Returns true if experimental support for UIAutomation is enabled. -AX_EXPORT bool IsExperimentalAccessibilityPlatformUIAEnabled(); +AX_BASE_EXPORT bool IsExperimentalAccessibilityPlatformUIAEnabled(); } // namespace switches diff --git a/chromium/ui/accessibility/ax_enum_util.cc b/chromium/ui/accessibility/ax_enum_util.cc index 35bbef5afc6..6d592227fc2 100644 --- a/chromium/ui/accessibility/ax_enum_util.cc +++ b/chromium/ui/accessibility/ax_enum_util.cc @@ -81,8 +81,6 @@ const char* ToString(ax::mojom::Event event) { return "menuListValueChanged"; case ax::mojom::Event::kMenuPopupEnd: return "menuPopupEnd"; - case ax::mojom::Event::kMenuPopupHide: - return "menuPopupHide"; case ax::mojom::Event::kMenuPopupStart: return "menuPopupStart"; case ax::mojom::Event::kMenuStart: @@ -211,8 +209,6 @@ ax::mojom::Event ParseEvent(const char* event) { return ax::mojom::Event::kMenuListValueChanged; if (0 == strcmp(event, "menuPopupEnd")) return ax::mojom::Event::kMenuPopupEnd; - if (0 == strcmp(event, "menuPopupHide")) - return ax::mojom::Event::kMenuPopupHide; if (0 == strcmp(event, "menuPopupStart")) return ax::mojom::Event::kMenuPopupStart; if (0 == strcmp(event, "menuStart")) @@ -1884,6 +1880,8 @@ const char* ToString(ax::mojom::BoolAttribute bool_attribute) { return "clipsChildren"; case ax::mojom::BoolAttribute::kSelected: return "selected"; + case ax::mojom::BoolAttribute::kSelectedFromFocus: + return "selectedFromFocus"; case ax::mojom::BoolAttribute::kSupportsTextLocation: return "supportsTextLocation"; case ax::mojom::BoolAttribute::kIsLineBreakingObject: @@ -1926,6 +1924,8 @@ ax::mojom::BoolAttribute ParseBoolAttribute(const char* bool_attribute) { return ax::mojom::BoolAttribute::kClipsChildren; if (0 == strcmp(bool_attribute, "selected")) return ax::mojom::BoolAttribute::kSelected; + if (0 == strcmp(bool_attribute, "selectedFromFocus")) + return ax::mojom::BoolAttribute::kSelectedFromFocus; if (0 == strcmp(bool_attribute, "supportsTextLocation")) return ax::mojom::BoolAttribute::kSupportsTextLocation; if (0 == strcmp(bool_attribute, "isLineBreakingObject")) diff --git a/chromium/ui/accessibility/ax_enums.mojom b/chromium/ui/accessibility/ax_enums.mojom index a5c0fc5884f..b1523555d3b 100644 --- a/chromium/ui/accessibility/ax_enums.mojom +++ b/chromium/ui/accessibility/ax_enums.mojom @@ -27,7 +27,7 @@ module ax.mojom; enum Event { kNone, - kActiveDescendantChanged, // Web + kActiveDescendantChanged, kAlert, kAriaAttributeChanged, // Implicit kAutocorrectionOccured, // Unknown: http://crbug.com/392498 @@ -56,13 +56,12 @@ enum Event { kLocationChanged, // Web kMediaStartedPlaying, // Native / Automation kMediaStoppedPlaying, // Native / Automation - kMenuEnd, // Native / Win + kMenuEnd, // Native / web: menu interaction has ended. kMenuListItemSelected, // Web kMenuListValueChanged, // Web - kMenuPopupEnd, // Native - kMenuPopupHide, // Native / AuraLinux - kMenuPopupStart, // Native - kMenuStart, // Native / Win + kMenuPopupEnd, // Native / web: a menu/submenu is hidden/closed. + kMenuPopupStart, // Native / web: a menu/submenu is shown/opened. + kMenuStart, // Native / web: menu interaction has begun. kMouseCanceled, kMouseDragged, kMouseMoved, @@ -77,7 +76,7 @@ enum Event { kSelection, // Native kSelectionAdd, // Native kSelectionRemove, // Native - kShow, // Remove: http://crbug.com/392502 + kShow, // Native / Automation kStateChanged, // Native / Automation kTextChanged, kWindowActivated, // Native @@ -734,6 +733,9 @@ enum BoolAttribute { // Indicates whether this node is selected or unselected. kSelected, + // Indicates whether this node is selected due to selection follows focus. + kSelectedFromFocus, + // Indicates whether this node supports text location. kSupportsTextLocation, @@ -984,14 +986,14 @@ enum SortDirection { enum NameFrom { kNone, kUninitialized, - kAttribute, + kAttribute, // E.g. aria-label. kAttributeExplicitlyEmpty, - kCaption, + kCaption, // E.g. in the case of a table, from a caption element. kContents, - kPlaceholder, - kRelatedElement, - kTitle, - kValue, + kPlaceholder, // E.g. from an HTML placeholder attribute on a text field. + kRelatedElement, // E.g. from a figcaption Element in a figure. + kTitle, // E.g. . + kValue, // E.g. . }; enum DescriptionFrom { diff --git a/chromium/ui/accessibility/ax_event.cc b/chromium/ui/accessibility/ax_event.cc index 34327f466f1..ecb80d908e4 100644 --- a/chromium/ui/accessibility/ax_event.cc +++ b/chromium/ui/accessibility/ax_event.cc @@ -29,7 +29,7 @@ AXEvent::AXEvent(const AXEvent& event) = default; AXEvent& AXEvent::operator=(const AXEvent& event) = default; std::string AXEvent::ToString() const { - std::string result = "AXEvent"; + std::string result = "AXEvent "; result += ui::ToString(event_type); result += " on node id=" + base::NumberToString(id); diff --git a/chromium/ui/accessibility/ax_event_generator.cc b/chromium/ui/accessibility/ax_event_generator.cc index 472dd5b1579..7561e537be6 100644 --- a/chromium/ui/accessibility/ax_event_generator.cc +++ b/chromium/ui/accessibility/ax_event_generator.cc @@ -49,9 +49,13 @@ void RemoveEvent(std::set* node_events, } // namespace -AXEventGenerator::EventParams::EventParams(Event event, - ax::mojom::EventFrom event_from) - : event(event), event_from(event_from) {} +AXEventGenerator::EventParams::EventParams( + Event event, + ax::mojom::EventFrom event_from, + const std::vector& event_intents) + : event(event), event_from(event_from), event_intents(event_intents) {} + +AXEventGenerator::EventParams::~EventParams() = default; AXEventGenerator::TargetedEvent::TargetedEvent(AXNode* node, const EventParams& event_params) @@ -138,7 +142,8 @@ void AXEventGenerator::AddEvent(AXNode* node, AXEventGenerator::Event event) { return; std::set& node_events = tree_events_[node]; - node_events.emplace(event, ax::mojom::EventFrom::kNone); + node_events.emplace(event, ax::mojom::EventFrom::kNone, + tree_->event_intents()); } void AXEventGenerator::OnNodeDataChanged(AXTree* tree, @@ -154,7 +159,8 @@ void AXEventGenerator::OnNodeDataChanged(AXTree* tree, new_node_data.role != ax::mojom::Role::kStaticText) { AXNode* node = tree_->GetFromId(new_node_data.id); tree_events_[node].emplace(Event::CHILDREN_CHANGED, - ax::mojom::EventFrom::kNone); + ax::mojom::EventFrom::kNone, + tree_->event_intents()); } } @@ -543,7 +549,7 @@ void AXEventGenerator::FireLiveRegionEvents(AXNode* node) { .GetStringAttribute(ax::mojom::StringAttribute::kName) .empty()) AddEvent(node, Event::LIVE_REGION_NODE_CHANGED); - // Fire LIVE_REGION_CHANGED on the root of the live region. + // Fire LIVE_REGION_NODE_CHANGED on the root of the live region. AddEvent(live_root, Event::LIVE_REGION_CHANGED); } } @@ -610,6 +616,9 @@ void AXEventGenerator::FireRelationSourceEvents(AXTree* tree, // Attempts to suppress load-related events that we presume no AT will be // interested in under any circumstances, such as pages which have no size. bool AXEventGenerator::ShouldFireLoadEvents(AXNode* node) { + if (always_fire_load_complete_) + return true; + const AXNodeData& data = node->data(); return data.relative_bounds.bounds.width() || data.relative_bounds.bounds.height(); diff --git a/chromium/ui/accessibility/ax_event_generator.h b/chromium/ui/accessibility/ax_event_generator.h index 61d860b1e64..47c64ef7b80 100644 --- a/chromium/ui/accessibility/ax_event_generator.h +++ b/chromium/ui/accessibility/ax_event_generator.h @@ -11,6 +11,7 @@ #include #include "base/scoped_observer.h" +#include "ui/accessibility/ax_event_intent.h" #include "ui/accessibility/ax_export.h" #include "ui/accessibility/ax_tree.h" #include "ui/accessibility/ax_tree_observer.h" @@ -90,9 +91,13 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver { }; struct EventParams { - EventParams(Event event, ax::mojom::EventFrom event_from); + EventParams(Event event, + ax::mojom::EventFrom event_from, + const std::vector& event_intents); + ~EventParams(); Event event; ax::mojom::EventFrom event_from; + std::vector event_intents; bool operator==(const EventParams& rhs); bool operator<(const EventParams& rhs) const; @@ -165,6 +170,10 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver { // same order they were added. void AddEvent(ui::AXNode* node, Event event); + void set_always_fire_load_complete(bool val) { + always_fire_load_complete_ = val; + } + protected: // AXTreeObserver overrides. void OnNodeDataChanged(AXTree* tree, @@ -236,6 +245,8 @@ class AX_EXPORT AXEventGenerator : public AXTreeObserver { // OnAtomicUpdateFinished. List of nodes whose active descendant changed. std::vector active_descendant_changed_; + bool always_fire_load_complete_ = false; + // Please make sure that this ScopedObserver is always declared last in order // to prevent any use-after-free. ScopedObserver tree_event_observer_{this}; diff --git a/chromium/ui/accessibility/ax_mode.cc b/chromium/ui/accessibility/ax_mode.cc index 55d0fc130db..7919464eb0a 100644 --- a/chromium/ui/accessibility/ax_mode.cc +++ b/chromium/ui/accessibility/ax_mode.cc @@ -41,6 +41,9 @@ std::string AXMode::ToString() const { case AXMode::kLabelImages: flag_name = "kLabelImages"; break; + case AXMode::kPDF: + flag_name = "kPDF"; + break; } DCHECK(flag_name); diff --git a/chromium/ui/accessibility/ax_mode.h b/chromium/ui/accessibility/ax_mode.h index 8e0b2dc5fc0..2536ad56236 100644 --- a/chromium/ui/accessibility/ax_mode.h +++ b/chromium/ui/accessibility/ax_mode.h @@ -10,7 +10,6 @@ #include #include -#include "base/logging.h" #include "ui/accessibility/ax_export.h" namespace ui { @@ -60,10 +59,14 @@ class AX_EXPORT AXMode { // The accessibility tree will contain automatic image annotations. static constexpr uint32_t kLabelImages = 1 << 5; + // The accessibility tree will contain enough information to export + // an accessible PDF. + static constexpr uint32_t kPDF = 1 << 6; + // Update this to include the last supported mode flag. If you add // another, be sure to update the stream insertion operator for // logging and debugging. - static constexpr uint32_t kLastModeFlag = 1 << 5; + static constexpr uint32_t kLastModeFlag = 1 << 6; constexpr AXMode() : flags_(0) {} constexpr AXMode(uint32_t flags) : flags_(flags) {} diff --git a/chromium/ui/accessibility/ax_node.cc b/chromium/ui/accessibility/ax_node.cc index b81f1491c31..3c7b06ecd91 100644 --- a/chromium/ui/accessibility/ax_node.cc +++ b/chromium/ui/accessibility/ax_node.cc @@ -10,6 +10,7 @@ #include "base/strings/string16.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_language_detection.h" #include "ui/accessibility/ax_role_properties.h" @@ -36,6 +37,7 @@ AXNode::AXNode(AXNode::OwnerTree* tree, AXNode::~AXNode() = default; size_t AXNode::GetUnignoredChildCount() const { + // TODO(nektar): Should DCHECK if the node is not ignored. DCHECK(!tree_->GetTreeUpdateInProgressState()); return unignored_child_count_; } @@ -320,7 +322,7 @@ AXNode::UnignoredChildIterator AXNode::UnignoredChildrenEnd() const { // The first (direct) child, ignored or unignored. AXNode* AXNode::GetFirstChild() const { - if (children().size() == 0) + if (children().empty()) return nullptr; return children()[0]; } @@ -354,9 +356,13 @@ AXNode* AXNode::GetNextSibling() const { } bool AXNode::IsText() const { - return data().role == ax::mojom::Role::kStaticText || - data().role == ax::mojom::Role::kLineBreak || - data().role == ax::mojom::Role::kInlineTextBox; + // In Legacy Layout, a list marker has no children and is thus represented on + // all platforms as a leaf node that exposes the marker itself, i.e., it forms + // part of the AX tree's text representation. In contrast, in Layout NG, a + // list marker has a static text child. + if (data().role == ax::mojom::Role::kListMarker) + return !children().size(); + return ui::IsText(data().role); } bool AXNode::IsLineBreak() const { @@ -477,6 +483,61 @@ void AXNode::ClearLanguageInfo() { language_info_.reset(); } +std::string AXNode::GetInnerText() const { + // If a text field has no descendants, then we compute its inner text from its + // value or its placeholder. Otherwise we prefer to look at its descendant + // text nodes because Blink doesn't always add all trailing white space to the + // value attribute. + if (data().IsTextField() && children().empty()) { + std::string value = + data().GetStringAttribute(ax::mojom::StringAttribute::kValue); + // If the value is empty, then there might be some placeholder text in the + // text field, or any other name that is derived from visible contents, even + // if the text field has no children. + if (!value.empty()) + return value; + } + + // Ordinarily, plain text fields are leaves. We need to exclude them from the + // set of leaf nodes when they expose any descendants if we want to compute + // their inner text from their descendant text nodes. + if (IsLeaf() && !(data().IsTextField() && !children().empty())) { + switch (data().GetNameFrom()) { + case ax::mojom::NameFrom::kNone: + case ax::mojom::NameFrom::kUninitialized: + // The accessible name is not displayed on screen, e.g. aria-label, or is + // not displayed directly inside the node, e.g. an associated label + // element. + case ax::mojom::NameFrom::kAttribute: + // The node's accessible name is explicitly empty. + case ax::mojom::NameFrom::kAttributeExplicitlyEmpty: + // The accessible name does not represent the entirety of the node's inner + // text, e.g. a table's caption or a figure's figcaption. + case ax::mojom::NameFrom::kCaption: + case ax::mojom::NameFrom::kRelatedElement: + // The accessible name is not displayed directly inside the node but is + // visible via e.g. a tooltip. + case ax::mojom::NameFrom::kTitle: + return std::string(); + + case ax::mojom::NameFrom::kContents: + // The placeholder text is initially displayed inside the text field and + // takes the place of its value. + case ax::mojom::NameFrom::kPlaceholder: + // The value attribute takes the place of the node's inner text, e.g. the + // value of a submit button is displayed inside the button itself. + case ax::mojom::NameFrom::kValue: + return data().GetStringAttribute(ax::mojom::StringAttribute::kName); + } + } + + std::string inner_text; + for (auto it = UnignoredChildrenBegin(); it != UnignoredChildrenEnd(); ++it) { + inner_text += it->GetInnerText(); + } + return inner_text; +} + std::string AXNode::GetLanguage() const { // Walk up tree considering both detected and author declared languages. for (const AXNode* cur = this; cur; cur = cur->parent()) { @@ -584,44 +645,52 @@ AXNode* AXNode::GetTableCellFromCoords(int row_index, int col_index) const { table_info->cell_ids[size_t{row_index}][size_t{col_index}]); } -void AXNode::GetTableColHeaderNodeIds( - int col_index, - std::vector* col_header_ids) const { - DCHECK(col_header_ids); +std::vector AXNode::GetTableColHeaderNodeIds() const { + const AXTableInfo* table_info = GetAncestorTableInfo(); + if (!table_info) + return std::vector(); + + std::vector col_header_ids; + // Flatten and add column header ids of each column to |col_header_ids|. + for (std::vector col_headers_at_index : + table_info->col_headers) { + col_header_ids.insert(col_header_ids.end(), col_headers_at_index.begin(), + col_headers_at_index.end()); + } + + return col_header_ids; +} + +std::vector AXNode::GetTableColHeaderNodeIds( + int col_index) const { const AXTableInfo* table_info = GetAncestorTableInfo(); if (!table_info) - return; + return std::vector(); if (col_index < 0 || size_t{col_index} >= table_info->col_count) - return; + return std::vector(); - for (size_t i = 0; i < table_info->col_headers[size_t{col_index}].size(); i++) - col_header_ids->push_back(table_info->col_headers[size_t{col_index}][i]); + return std::vector(table_info->col_headers[size_t{col_index}]); } -void AXNode::GetTableRowHeaderNodeIds( - int row_index, - std::vector* row_header_ids) const { - DCHECK(row_header_ids); +std::vector AXNode::GetTableRowHeaderNodeIds( + int row_index) const { const AXTableInfo* table_info = GetAncestorTableInfo(); if (!table_info) - return; + return std::vector(); if (row_index < 0 || size_t{row_index} >= table_info->row_count) - return; + return std::vector(); - for (size_t i = 0; i < table_info->row_headers[size_t{row_index}].size(); i++) - row_header_ids->push_back(table_info->row_headers[size_t{row_index}][i]); + return std::vector(table_info->row_headers[size_t{row_index}]); } -void AXNode::GetTableUniqueCellIds(std::vector* cell_ids) const { - DCHECK(cell_ids); +std::vector AXNode::GetTableUniqueCellIds() const { const AXTableInfo* table_info = GetAncestorTableInfo(); if (!table_info) - return; + return std::vector(); - cell_ids->assign(table_info->unique_cell_ids.begin(), - table_info->unique_cell_ids.end()); + return std::vector(table_info->unique_cell_ids); } const std::vector* AXNode::GetExtraMacNodes() const { @@ -792,47 +861,39 @@ base::Optional AXNode::GetTableCellAriaRowIndex() const { return int{table_info->cell_data_vector[*index].aria_row_index}; } -void AXNode::GetTableCellColHeaderNodeIds( - std::vector* col_header_ids) const { - DCHECK(col_header_ids); +std::vector AXNode::GetTableCellColHeaderNodeIds() const { const AXTableInfo* table_info = GetAncestorTableInfo(); if (!table_info || table_info->col_count <= 0) - return; + return std::vector(); // If this node is not a cell, then return the headers for the first column. int col_index = GetTableCellColIndex().value_or(0); - const auto& col = table_info->col_headers[col_index]; - for (int header : col) - col_header_ids->push_back(header); + + return std::vector(table_info->col_headers[col_index]); } void AXNode::GetTableCellColHeaders(std::vector* col_headers) const { DCHECK(col_headers); - std::vector col_header_ids; - GetTableCellColHeaderNodeIds(&col_header_ids); + std::vector col_header_ids = GetTableCellColHeaderNodeIds(); IdVectorToNodeVector(col_header_ids, col_headers); } -void AXNode::GetTableCellRowHeaderNodeIds( - std::vector* row_header_ids) const { - DCHECK(row_header_ids); +std::vector AXNode::GetTableCellRowHeaderNodeIds() const { const AXTableInfo* table_info = GetAncestorTableInfo(); if (!table_info || table_info->row_count <= 0) - return; + return std::vector(); // If this node is not a cell, then return the headers for the first row. int row_index = GetTableCellRowIndex().value_or(0); - const auto& row = table_info->row_headers[row_index]; - for (int header : row) - row_header_ids->push_back(header); + + return std::vector(table_info->row_headers[row_index]); } void AXNode::GetTableCellRowHeaders(std::vector* row_headers) const { DCHECK(row_headers); - std::vector row_header_ids; - GetTableCellRowHeaderNodeIds(&row_header_ids); + std::vector row_header_ids = GetTableCellRowHeaderNodeIds(); IdVectorToNodeVector(row_header_ids, row_headers); } @@ -902,51 +963,14 @@ bool AXNode::IsOrderedSet() const { return ui::IsSetLike(data().role); } -// pos_in_set and set_size related functions. -// Uses AXTree's cache to calculate node's pos_in_set. +// Uses AXTree's cache to calculate node's PosInSet. base::Optional AXNode::GetPosInSet() { - // Only allow this to be called on nodes that can hold pos_in_set values, - // which are defined in the ARIA spec. - if (!IsOrderedSetItem() || IsIgnored()) - return base::nullopt; - - const AXNode* ordered_set = GetOrderedSet(); - if (!ordered_set) { - return base::nullopt; - } - - // If tree is being updated, return no value. - if (tree()->GetTreeUpdateInProgressState()) - return base::nullopt; - - // See AXTree::GetPosInSet - return tree_->GetPosInSet(*this, ordered_set); + return tree_->GetPosInSet(*this); } -// Uses AXTree's cache to calculate node's set_size. +// Uses AXTree's cache to calculate node's SetSize. base::Optional AXNode::GetSetSize() { - // Only allow this to be called on nodes that can hold set_size values, which - // are defined in the ARIA spec. - if ((!IsOrderedSetItem() && !IsOrderedSet()) || IsIgnored()) - return base::nullopt; - - // If node is item-like, find its outerlying ordered set. Otherwise, - // this node is the ordered set. - const AXNode* ordered_set = this; - if (IsItemLike(data().role)) - ordered_set = GetOrderedSet(); - if (!ordered_set) - return base::nullopt; - - // If tree is being updated, return no value. - if (tree()->GetTreeUpdateInProgressState()) - return base::nullopt; - - // See AXTree::GetSetSize - int32_t set_size = tree_->GetSetSize(*this, ordered_set); - if (set_size < 0) - return base::nullopt; - return set_size; + return tree_->GetSetSize(*this); } // Returns true if the role of ordered set matches the role of item. @@ -1001,7 +1025,8 @@ bool AXNode::SetRoleMatchesItemRole(const AXNode* ordered_set) const { } bool AXNode::IsIgnoredContainerForOrderedSet() const { - return IsIgnored() || data().role == ax::mojom::Role::kListItem || + return IsIgnored() || IsEmbeddedGroup() || + data().role == ax::mojom::Role::kListItem || data().role == ax::mojom::Role::kGenericContainer || data().role == ax::mojom::Role::kUnknown; } @@ -1020,17 +1045,16 @@ int AXNode::UpdateUnignoredCachedValuesRecursive(int startIndex) { return count; } -// Finds ordered set that immediately contains node. +// Finds ordered set that contains node. // Is not required for set's role to match node's role. AXNode* AXNode::GetOrderedSet() const { AXNode* result = parent(); // Continue walking up while parent is invalid, ignored, a generic container, - // or unknown. - while (result && (result->IsIgnored() || - result->data().role == ax::mojom::Role::kGenericContainer || - result->data().role == ax::mojom::Role::kUnknown)) { + // unknown, or embedded group. + while (result && result->IsIgnoredContainerForOrderedSet()) { result = result->parent(); } + return result; } @@ -1069,6 +1093,70 @@ bool AXNode::IsIgnored() const { return data().IsIgnored(); } +bool AXNode::IsChildOfLeaf() const { + const AXNode* ancestor = GetUnignoredParent(); + while (ancestor) { + if (ancestor->IsLeaf()) + return true; + ancestor = ancestor->GetUnignoredParent(); + } + return false; +} + +bool AXNode::IsLeaf() const { + return !GetUnignoredChildCount() || IsLeafIncludingIgnored(); +} + +bool AXNode::IsLeafIncludingIgnored() const { + if (children().empty()) + return true; + +#if defined(OS_WIN) + // On Windows, we want to hide the subtree of a collapsed , ,