[A11yPerformance] Refactor on-demand AXModes and use on more platforms
Remove WinAccessibilityAPIUsageObserver and replace with generic calls in AXPlatform::Delegate() that can be used on any platform. Not only is this simpler, removing 50+ lines of code, but future CLs can use it to reduce AXMode usage on other platforms, especially Mac, which usually turns on all of the expensive AXModes for most API consumers. Finally, this provides a better signal to use for turning off the auto disable feature (will use more in upcoming CLs for the Auto Disable Refresh feature). The previous method, OnAccessibilityApiUsage(), could be triggered by a simple AXPlatformNodeDelegate::GetRole() call, which occurs naturally during deserialization (which itself can be delayed long after the conditions are present that should turn off a11y). Fixed: 337737555 Change-Id: I389ee6ef3e71810db8c39b3298c4b4f48253b5a9 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6505214 Reviewed-by: Greg Thompson <grt@chromium.org> Reviewed-by: Jacques Newman <janewman@microsoft.com> Reviewed-by: Jonathan Ross <jonross@chromium.org> Auto-Submit: Aaron Leventhal <aleventhal@chromium.org> Commit-Queue: Jonathan Ross <jonross@chromium.org> Cr-Commit-Position: refs/heads/main@{#1455895}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
9fb1048c5c
commit
244d6997f8
content/browser
accessibility
browser_accessibility_state_impl.ccbrowser_accessibility_state_impl.hbrowser_accessibility_state_impl_auralinux.ccbrowser_accessibility_state_impl_win.cc
renderer_host
ui/accessibility/platform
@ -186,7 +186,8 @@ BrowserAccessibilityStateImpl::Create() {
|
||||
}
|
||||
#endif
|
||||
|
||||
BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl() {
|
||||
BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl()
|
||||
: platform_ax_mode_(CreateScopedModeForProcess(ui::AXMode())) {
|
||||
DCHECK_EQ(g_instance, nullptr);
|
||||
g_instance = this;
|
||||
|
||||
@ -442,7 +443,18 @@ BrowserAccessibilityStateImpl::RegisterFocusChangedCallback(
|
||||
return focus_changed_callbacks_.Add(std::move(callback));
|
||||
}
|
||||
|
||||
void BrowserAccessibilityStateImpl::OnAccessibilityApiUsage() {
|
||||
void BrowserAccessibilityStateImpl::EnableAXModeFromPlatform(
|
||||
ui::AXMode modes_to_add) {
|
||||
ui::AXMode old_mode = platform_ax_mode_->mode();
|
||||
ui::AXMode new_mode = old_mode | modes_to_add;
|
||||
if (old_mode != new_mode) {
|
||||
platform_ax_mode_ =
|
||||
CreateScopedModeForProcess(new_mode | ui::AXMode::kFromPlatform);
|
||||
}
|
||||
|
||||
// If AXMode::kWebContent is being requested, turn off auto-disable.
|
||||
// TODO(accessibility) Re-work the auto-disable feature.
|
||||
// Platform accessibility API usage affects auto-disable.
|
||||
// See OnUserInputEvent for how this is used to disable accessibility.
|
||||
user_input_event_count_ = 0;
|
||||
|
||||
@ -459,6 +471,43 @@ void BrowserAccessibilityStateImpl::OnAccessibilityApiUsage() {
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserAccessibilityStateImpl::OnMinimalPropertiesUsed() {
|
||||
// When only basic minimal functionality is used, just enable kNativeAPIs.
|
||||
// Enabling kNativeAPIs gives little perf impact, but allows these APIs to
|
||||
// interact with the BrowserAccessibilityManager allowing ATs to be able at
|
||||
// least find the document without using any advanced APIs.
|
||||
EnableAXModeFromPlatform(ui::AXMode::kNativeAPIs);
|
||||
}
|
||||
|
||||
void BrowserAccessibilityStateImpl::OnPropertiesUsedInBrowserUI() {
|
||||
EnableAXModeFromPlatform(ui::AXMode::kNativeAPIs);
|
||||
}
|
||||
|
||||
void BrowserAccessibilityStateImpl::OnPropertiesUsedInWebContent() {
|
||||
// When accessibility APIs have been used in content, enable basic web
|
||||
// accessibility support. Full screen reader support is detected later when
|
||||
// specific more advanced APIs are accessed.
|
||||
EnableAXModeFromPlatform(ui::kAXModeBasic);
|
||||
}
|
||||
|
||||
void BrowserAccessibilityStateImpl::OnInlineTextBoxesUsedInWebContent() {
|
||||
EnableAXModeFromPlatform(ui::kAXModeBasic | ui::AXMode::kInlineTextBoxes);
|
||||
}
|
||||
|
||||
void BrowserAccessibilityStateImpl::OnExtendedPropertiesUsedInWebContent() {
|
||||
EnableAXModeFromPlatform(ui::kAXModeBasic | ui::AXMode::kExtendedProperties);
|
||||
}
|
||||
|
||||
void BrowserAccessibilityStateImpl::OnHTMLAttributesUsed() {
|
||||
EnableAXModeFromPlatform(ui::kAXModeBasic | ui::AXMode::kHTML);
|
||||
}
|
||||
|
||||
void BrowserAccessibilityStateImpl::OnActionFromAssistiveTech() {
|
||||
// Ensure that auto-disable is turned off, e.g. if screen reader scrolls
|
||||
// content into view.
|
||||
EnableAXModeFromPlatform(ui::AXMode::kNativeAPIs);
|
||||
}
|
||||
|
||||
void BrowserAccessibilityStateImpl::OnPageNavigationComplete() {
|
||||
++num_page_navs_before_first_use_;
|
||||
}
|
||||
@ -487,13 +536,6 @@ BrowserAccessibilityStateImpl::CreateScopedModeForProcess(ui::AXMode mode) {
|
||||
// scopers targeting the process changes.
|
||||
void BrowserAccessibilityStateImpl::OnModeChanged(ui::AXMode old_mode,
|
||||
ui::AXMode new_mode) {
|
||||
if (!new_mode.is_mode_off()) {
|
||||
// Unless the mode is being turned off, setting accessibility flags is
|
||||
// generally caused by accessibility API call, so we should also reset the
|
||||
// auto-disable accessibility code.
|
||||
OnAccessibilityApiUsage();
|
||||
}
|
||||
|
||||
ui::RecordAccessibilityModeHistograms(ui::AXHistogramPrefix::kNone, new_mode,
|
||||
old_mode);
|
||||
|
||||
|
@ -85,7 +85,13 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
|
||||
void NotifyWebContentsPreferencesChanged() const override;
|
||||
|
||||
// ui::AXPlatform::Delegate:
|
||||
void OnAccessibilityApiUsage() override;
|
||||
void OnMinimalPropertiesUsed() override;
|
||||
void OnPropertiesUsedInBrowserUI() override;
|
||||
void OnPropertiesUsedInWebContent() override;
|
||||
void OnInlineTextBoxesUsedInWebContent() override;
|
||||
void OnExtendedPropertiesUsedInWebContent() override;
|
||||
void OnHTMLAttributesUsed() override;
|
||||
void OnActionFromAssistiveTech() override;
|
||||
|
||||
// content::RenderWidgetHost::InputEventObserver:
|
||||
void OnInputEvent(const RenderWidgetHost& widget,
|
||||
@ -151,6 +157,10 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
|
||||
ui::AXMode old_mode,
|
||||
ui::AXMode new_mode);
|
||||
|
||||
// Add the AXModes + AXMode::kFromPlatform, when corresponding platform APIs
|
||||
// are used.
|
||||
void EnableAXModeFromPlatform(ui::AXMode modes_to_add);
|
||||
|
||||
// Refreshes the instance's notion of active assistive technologies.
|
||||
// Implementations must call `OnAssistiveTechFound()` with the results of any
|
||||
// discovery.
|
||||
@ -219,6 +229,10 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
|
||||
// via --force-renderer-accessibility on the command line.
|
||||
std::unique_ptr<ScopedAccessibilityMode> forced_accessibility_mode_;
|
||||
|
||||
// A ScopedAccessibilityMode that holds process-wide mode flags required to
|
||||
// support the platform API calls being used.
|
||||
std::unique_ptr<ScopedAccessibilityMode> platform_ax_mode_;
|
||||
|
||||
friend class ui::AXPlatform;
|
||||
};
|
||||
|
||||
|
@ -92,7 +92,6 @@ class BrowserAccessibilityStateImplAuralinux
|
||||
// BrowserAccessibilityStateImpl:
|
||||
void RefreshAssistiveTech() override;
|
||||
void RefreshAssistiveTechIfNecessary(ui::AXMode new_mode) override;
|
||||
void OnExtendedPropertiesUsed() override;
|
||||
|
||||
private:
|
||||
void OnDiscoveredOrca(bool is_orca_active);
|
||||
@ -104,8 +103,6 @@ class BrowserAccessibilityStateImplAuralinux
|
||||
// The presence of an AssistiveTech is currently being recomputed.
|
||||
// Will be updated via DiscoverOrca().
|
||||
bool awaiting_known_assistive_tech_computation_ = false;
|
||||
|
||||
std::unique_ptr<ScopedAccessibilityMode> complete_ax_mode_;
|
||||
};
|
||||
|
||||
void BrowserAccessibilityStateImplAuralinux::RefreshAssistiveTech() {
|
||||
@ -148,13 +145,6 @@ void BrowserAccessibilityStateImplAuralinux::RefreshAssistiveTechIfNecessary(
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserAccessibilityStateImplAuralinux::OnExtendedPropertiesUsed() {
|
||||
if (!complete_ax_mode_) {
|
||||
complete_ax_mode_ = CreateScopedModeForProcess(ui::kAXModeComplete |
|
||||
ui::AXMode::kFromPlatform);
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserAccessibilityStateImplAuralinux::OnDiscoveredOrca(
|
||||
bool is_orca_active) {
|
||||
awaiting_known_assistive_tech_computation_ = false;
|
||||
|
@ -307,145 +307,6 @@ std::vector<AssistiveTechInfo> DiscoverAssistiveTech() {
|
||||
return discovered_ats;
|
||||
}
|
||||
|
||||
// Enables accessibility based on clues that indicate accessibility API usage.
|
||||
class WindowsAccessibilityEnabler
|
||||
: public ui::WinAccessibilityAPIUsageObserver {
|
||||
public:
|
||||
WindowsAccessibilityEnabler() {}
|
||||
|
||||
private:
|
||||
void EnableAXMode(ui::AXMode modes_to_add) {
|
||||
modes_to_add |= ui::AXMode::kFromPlatform;
|
||||
ui::AXMode old_mode = scoped_windows_ax_mode_
|
||||
? scoped_windows_ax_mode_->mode()
|
||||
: ui::AXMode();
|
||||
ui::AXMode new_mode = old_mode | modes_to_add;
|
||||
if (old_mode != new_mode) {
|
||||
scoped_windows_ax_mode_ = BrowserAccessibilityStateImpl::GetInstance()
|
||||
->CreateScopedModeForProcess(new_mode);
|
||||
}
|
||||
}
|
||||
|
||||
// WinAccessibilityAPIUsageObserver
|
||||
void OnMSAAUsed() override {
|
||||
// When only basic MSAA functionality is used, just enable kNativeAPIs.
|
||||
// Enabling kNativeAPIs gives little perf impact, but allows these APIs to
|
||||
// interact with the BrowserAccessibilityManager allowing ATs to be able at
|
||||
// least find the document without using any advanced APIs.
|
||||
EnableAXMode(ui::AXMode::kNativeAPIs);
|
||||
}
|
||||
|
||||
void OnIAccessible2UsedInBrowserUI() override {
|
||||
EnableAXMode(ui::AXMode::kNativeAPIs);
|
||||
}
|
||||
|
||||
void OnIAccessible2UsedInWebContent() override {
|
||||
// When IAccessible2 APIs have been used in content, enable basic web
|
||||
// accessibility support. Full screen reader support is detected later when
|
||||
// specific more advanced APIs are accessed.
|
||||
EnableAXMode(ui::kAXModeBasic);
|
||||
}
|
||||
|
||||
void OnScreenReaderHoneyPotQueried() override {
|
||||
// We used to trust this as a signal that a screen reader is running,
|
||||
// but it's been abused. Now only enable accessibility if we also
|
||||
// detect a call to get_accName.
|
||||
if (screen_reader_honeypot_queried_) {
|
||||
return;
|
||||
}
|
||||
screen_reader_honeypot_queried_ = true;
|
||||
if (acc_name_called_) {
|
||||
EnableAXMode(ui::kAXModeBasic);
|
||||
}
|
||||
}
|
||||
|
||||
void OnAccNameCalled() override {
|
||||
// See OnScreenReaderHoneyPotQueried, above.
|
||||
if (acc_name_called_) {
|
||||
return;
|
||||
}
|
||||
acc_name_called_ = true;
|
||||
if (screen_reader_honeypot_queried_) {
|
||||
EnableAXMode(ui::kAXModeBasic);
|
||||
}
|
||||
}
|
||||
|
||||
void OnInlineTextBoxesUsed() override {
|
||||
EnableAXMode(ui::kAXModeBasic | ui::AXMode::kExtendedProperties |
|
||||
ui::AXMode::kInlineTextBoxes);
|
||||
}
|
||||
|
||||
void OnExtendedPropertiesUsed() override {
|
||||
EnableAXMode(ui::kAXModeBasic | ui::AXMode::kExtendedProperties);
|
||||
}
|
||||
|
||||
void OnHTMLAttributesUsed() override {
|
||||
EnableAXMode(ui::kAXModeBasic | ui::AXMode::kExtendedProperties |
|
||||
ui::AXMode::kHTML);
|
||||
}
|
||||
|
||||
void OnUIAutomationUsedInWebContent() override {
|
||||
DCHECK(::ui::AXPlatform::GetInstance().IsUiaProviderEnabled());
|
||||
|
||||
// Firing a UIA event can cause UIA to call back into our APIs, don't
|
||||
// consider this to be usage.
|
||||
if (firing_uia_events_) {
|
||||
return;
|
||||
}
|
||||
|
||||
EnableAXMode(ui::kAXModeBasic);
|
||||
}
|
||||
|
||||
void OnUIAutomationUsedInBrowserUI() override {
|
||||
DCHECK(::ui::AXPlatform::GetInstance().IsUiaProviderEnabled());
|
||||
|
||||
// Firing a UIA event can cause UIA to call back into our APIs, don't
|
||||
// consider this to be usage.
|
||||
if (firing_uia_events_) {
|
||||
return;
|
||||
}
|
||||
|
||||
EnableAXMode(ui::AXMode::kNativeAPIs);
|
||||
}
|
||||
|
||||
void OnProbableUIAutomationScreenReaderDetected() override {
|
||||
DCHECK(::ui::AXPlatform::GetInstance().IsUiaProviderEnabled());
|
||||
|
||||
// Firing a UIA event can cause UIA to call back into our APIs, don't
|
||||
// consider this to be usage.
|
||||
if (firing_uia_events_) {
|
||||
return;
|
||||
}
|
||||
|
||||
OnExtendedPropertiesUsed();
|
||||
}
|
||||
|
||||
void OnTextPatternRequested() override {
|
||||
DCHECK(::ui::AXPlatform::GetInstance().IsUiaProviderEnabled());
|
||||
|
||||
// Firing a UIA event can cause UIA to call back into our APIs, don't
|
||||
// consider this to be usage.
|
||||
if (firing_uia_events_) {
|
||||
return;
|
||||
}
|
||||
|
||||
OnInlineTextBoxesUsed();
|
||||
}
|
||||
|
||||
void StartFiringUIAEvents() override { firing_uia_events_ = true; }
|
||||
|
||||
void EndFiringUIAEvents() override { firing_uia_events_ = false; }
|
||||
|
||||
// This should be set to true while we are firing uia events. Firing UIA
|
||||
// events causes UIA to call back into our APIs, this should not be considered
|
||||
// usage.
|
||||
bool firing_uia_events_ = false;
|
||||
bool screen_reader_honeypot_queried_ = false;
|
||||
bool acc_name_called_ = false;
|
||||
|
||||
std::unique_ptr<ScopedAccessibilityMode> scoped_windows_ax_mode_;
|
||||
};
|
||||
|
||||
void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
if (message == WM_SETTINGCHANGE && wparam == SPI_SETCLIENTAREAANIMATION) {
|
||||
@ -484,9 +345,6 @@ class BrowserAccessibilityStateImplWin : public BrowserAccessibilityStateImpl {
|
||||
};
|
||||
|
||||
BrowserAccessibilityStateImplWin::BrowserAccessibilityStateImplWin() {
|
||||
ui::GetWinAccessibilityAPIUsageObserverList().AddObserver(
|
||||
new WindowsAccessibilityEnabler());
|
||||
|
||||
if (base::SingleThreadTaskRunner::HasCurrentDefault()) {
|
||||
singleton_hwnd_observer_ = std::make_unique<gfx::SingletonHwndObserver>(
|
||||
base::BindRepeating(&OnWndProc));
|
||||
|
@ -245,10 +245,7 @@ LRESULT LegacyRenderWidgetHostHWND::OnGetObject(UINT message,
|
||||
// When an MSAA client has responded to fake event for this id,
|
||||
// only basic accessibility support is enabled. (Full screen reader support
|
||||
// is detected later when specific, more advanced APIs are accessed.)
|
||||
for (ui::WinAccessibilityAPIUsageObserver& observer :
|
||||
ui::GetWinAccessibilityAPIUsageObserverList()) {
|
||||
observer.OnScreenReaderHoneyPotQueried();
|
||||
}
|
||||
ui::AXPlatform::GetInstance().OnScreenReaderHoneyPotQueried();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "base/win/scoped_safearray.h"
|
||||
#include "ui/accessibility/accessibility_features.h"
|
||||
#include "ui/accessibility/platform/ax_fragment_root_delegate_win.h"
|
||||
#include "ui/accessibility/platform/ax_platform.h"
|
||||
#include "ui/accessibility/platform/ax_platform_node_win.h"
|
||||
#include "ui/accessibility/platform/uia_registrar_win.h"
|
||||
#include "ui/base/win/atl_module.h"
|
||||
@ -338,11 +339,8 @@ AXFragmentRootWin* AXFragmentRootWin::GetFragmentRootParentOf(
|
||||
|
||||
gfx::NativeViewAccessible AXFragmentRootWin::GetNativeViewAccessible() {
|
||||
// The fragment root is the entry point from the operating system for UI
|
||||
// Automation. Signal observers when we're asked for a platform object on it.
|
||||
for (WinAccessibilityAPIUsageObserver& observer :
|
||||
GetWinAccessibilityAPIUsageObserverList()) {
|
||||
observer.OnUIAutomationUsedInBrowserUI();
|
||||
}
|
||||
// Automation. Signal when we're asked for a platform object on it.
|
||||
AXPlatform::GetInstance().OnPropertiesUsedInBrowserUI();
|
||||
return static_cast<AXFragmentRootPlatformNodeWin*>(platform_node_.get());
|
||||
}
|
||||
|
||||
|
@ -74,11 +74,6 @@ bool AXPlatform::IsScreenReaderActive() {
|
||||
return IsScreenReader(active_assistive_tech_);
|
||||
}
|
||||
|
||||
void AXPlatform::NotifyAccessibilityApiUsage() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
delegate_->OnAccessibilityApiUsage();
|
||||
}
|
||||
|
||||
bool AXPlatform::IsCaretBrowsingEnabled() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
return caret_browsing_enabled_;
|
||||
@ -147,12 +142,67 @@ void AXPlatform::OnUiaProviderRequested(bool uia_provider_enabled) {
|
||||
}
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
void AXPlatform::OnExtendedPropertiesUsed() {
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
void AXPlatform::OnScreenReaderHoneyPotQueried() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
delegate_->OnExtendedPropertiesUsed();
|
||||
// We used to trust this as a signal that a screen reader is running,
|
||||
// but it's been abused. Now only enable accessibility if we detect that a
|
||||
// minimal property (name, role, location) is also used..
|
||||
if (screen_reader_honeypot_queried_) {
|
||||
return;
|
||||
}
|
||||
screen_reader_honeypot_queried_ = true;
|
||||
if (minimal_properties_used_) {
|
||||
OnPropertiesUsedInWebContent();
|
||||
}
|
||||
}
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
void AXPlatform::OnMinimalPropertiesUsed() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
delegate_->OnMinimalPropertiesUsed();
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// See OnScreenReaderHoneyPotQueried, above.
|
||||
if (minimal_properties_used_) {
|
||||
return;
|
||||
}
|
||||
minimal_properties_used_ = true;
|
||||
if (screen_reader_honeypot_queried_) {
|
||||
OnPropertiesUsedInWebContent();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void AXPlatform::OnPropertiesUsedInBrowserUI() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
delegate_->OnPropertiesUsedInBrowserUI();
|
||||
}
|
||||
|
||||
void AXPlatform::OnPropertiesUsedInWebContent() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
delegate_->OnPropertiesUsedInWebContent();
|
||||
}
|
||||
|
||||
void AXPlatform::OnInlineTextBoxesUsedInWebContent() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
delegate_->OnInlineTextBoxesUsedInWebContent();
|
||||
}
|
||||
|
||||
void AXPlatform::OnExtendedPropertiesUsedInWebContent() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
delegate_->OnExtendedPropertiesUsedInWebContent();
|
||||
}
|
||||
|
||||
void AXPlatform::OnHTMLAttributesUsed() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
delegate_->OnHTMLAttributesUsed();
|
||||
}
|
||||
|
||||
void AXPlatform::OnActionFromAssistiveTech() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
delegate_->OnActionFromAssistiveTech();
|
||||
}
|
||||
#endif // BUILDFLAG(IS_LINUX)
|
||||
|
||||
void AXPlatform::DetachFromThreadForTesting() {
|
||||
DETACH_FROM_THREAD(thread_checker_);
|
||||
|
@ -44,13 +44,6 @@ class COMPONENT_EXPORT(AX_PLATFORM) AXPlatform {
|
||||
// Returns the effective process-wide accessibility mode.
|
||||
virtual AXMode GetAccessibilityMode() = 0;
|
||||
|
||||
// The global accessibility mode is automatically enabled based on
|
||||
// usage of accessibility APIs. When we detect a significant amount
|
||||
// of user inputs within a certain time period, but no accessibility
|
||||
// API usage, we automatically disable accessibility. This method
|
||||
// should be called when we detect accessibility API usage.
|
||||
virtual void OnAccessibilityApiUsage() = 0;
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// Used to retrieve the product name, version, and toolkit version for IA2.
|
||||
// Only called the first time the data is needed to fill in the
|
||||
@ -68,13 +61,22 @@ class COMPONENT_EXPORT(AX_PLATFORM) AXPlatform {
|
||||
virtual void OnUiaProviderDisabled() {}
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
// Enables AXMode::kExtendedProperties, for advanced ATs such as Orca.
|
||||
// TODO(accessibility): Consider unifying with
|
||||
// WinAccessibilityAPIUsageObserver into a single system for turning on
|
||||
// useful AXModes.
|
||||
virtual void OnExtendedPropertiesUsed() {}
|
||||
#endif
|
||||
// A very basic accessible property was used, such as role, name or
|
||||
// location. Only enables AXMode::kNativeAPIs unless the screen reader
|
||||
// honeypot is used.
|
||||
virtual void OnMinimalPropertiesUsed() {}
|
||||
// An a11y property was used in the browser UI. Enable AXMode::kNativeAPIs.
|
||||
virtual void OnPropertiesUsedInBrowserUI() {}
|
||||
// A basic property was used in web content. Enable AXMode::kWebContents.
|
||||
virtual void OnPropertiesUsedInWebContent() {}
|
||||
// Inline textboxes were used. Enable AXMode::kInlineTextBoxes.
|
||||
virtual void OnInlineTextBoxesUsedInWebContent() {}
|
||||
// Extended properties were used. Enable AXMode::kExtendedProperties.
|
||||
virtual void OnExtendedPropertiesUsedInWebContent() {}
|
||||
// HTML properties were used. Enable AXMode::kHTML.
|
||||
virtual void OnHTMLAttributesUsed() {}
|
||||
// An a11y action was used in web content. Enable AXMode::kNativeAPIs.
|
||||
virtual void OnActionFromAssistiveTech() {}
|
||||
|
||||
protected:
|
||||
Delegate() = default;
|
||||
@ -119,9 +121,6 @@ class COMPONENT_EXPORT(AX_PLATFORM) AXPlatform {
|
||||
// Is the current active assistive tech a screen reader.
|
||||
bool IsScreenReaderActive();
|
||||
|
||||
// Notifies the delegate that an accessibility API has been used.
|
||||
void NotifyAccessibilityApiUsage();
|
||||
|
||||
// Returns whether caret browsing is enabled. When caret browsing is enabled,
|
||||
// we need to ensure that we keep ATs aware of caret movement.
|
||||
bool IsCaretBrowsingEnabled();
|
||||
@ -159,9 +158,31 @@ class COMPONENT_EXPORT(AX_PLATFORM) AXPlatform {
|
||||
void OnUiaProviderRequested(bool uia_provider_enabled);
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
// Enables AXMode::kExtendedProperties, for advanced ATs such as Orca.
|
||||
void OnExtendedPropertiesUsed();
|
||||
// A very basic accessible property was used, such as role, name or location.
|
||||
// Always enables AXMode::kNativeAPIs by calling OnMinimalPropertiesUsed() on
|
||||
// the delegate. If the screen reader honeypot is used (currently windows
|
||||
// only), OnPropertiesUsedInWebContent() will also be called, enabling web
|
||||
// content accessibility via AXMode::kWebContents.
|
||||
void OnMinimalPropertiesUsed();
|
||||
// An a11y property was used in the browser UI. Enable AXMode::kNativeAPIs.
|
||||
void OnPropertiesUsedInBrowserUI();
|
||||
// A basic property was used in web content. Enable AXMode::kWebContents.
|
||||
void OnPropertiesUsedInWebContent();
|
||||
// Inline textboxes were used. Enable AXMode::kInlineTextBoxes.
|
||||
void OnInlineTextBoxesUsedInWebContent();
|
||||
// Extended properties were used. Enable AXMode::kExtendedProperties.
|
||||
void OnExtendedPropertiesUsedInWebContent();
|
||||
// HTML properties were used. Enable AXMode::kHTML.
|
||||
void OnHTMLAttributesUsed();
|
||||
// An a11y action was used in web content. Enable AXMode::kNativeAPIs.
|
||||
void OnActionFromAssistiveTech();
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// The honeypot is a fake alert object that is created, with a fake alert
|
||||
// event fired on it. It is considered unlikely that anything but a screen
|
||||
// reader would be query that object, and also query other minimal properties.
|
||||
// TODO(accessibility): We may no longer need this method because we
|
||||
// detect all screen readers directly, although this may happen earlier.
|
||||
void OnScreenReaderHoneyPotQueried();
|
||||
#endif
|
||||
|
||||
void DetachFromThreadForTesting();
|
||||
@ -210,6 +231,12 @@ class COMPONENT_EXPORT(AX_PLATFORM) AXPlatform {
|
||||
// Keeps track of whether caret browsing is enabled.
|
||||
bool caret_browsing_enabled_ GUARDED_BY_CONTEXT(thread_checker_) = false;
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
bool screen_reader_honeypot_queried_ GUARDED_BY_CONTEXT(thread_checker_) =
|
||||
false;
|
||||
bool minimal_properties_used_ GUARDED_BY_CONTEXT(thread_checker_) = false;
|
||||
#endif
|
||||
|
||||
THREAD_CHECKER(thread_checker_);
|
||||
};
|
||||
|
||||
|
@ -38,8 +38,6 @@ AXMode AXPlatformForTest::GetAccessibilityMode() {
|
||||
return mode_;
|
||||
}
|
||||
|
||||
void AXPlatformForTest::OnAccessibilityApiUsage() {}
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
AXPlatform::ProductStrings AXPlatformForTest::GetProductStrings() {
|
||||
return {{}, {}, {}};
|
||||
|
@ -27,7 +27,6 @@ class AXPlatformForTest : public AXPlatform::Delegate {
|
||||
|
||||
// AXPlatform::Delegate:
|
||||
AXMode GetAccessibilityMode() override;
|
||||
void OnAccessibilityApiUsage() override;
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
AXPlatform::ProductStrings GetProductStrings() override;
|
||||
#endif
|
||||
|
@ -2196,7 +2196,7 @@ AtkRelationSet* AtkRefRelationSet(AtkObject* atk_object) {
|
||||
// Enables AX mode. Most AT does not call AtkRefRelationSet, but Orca does,
|
||||
// which is why it's a good signal to enable accessibility for Orca users
|
||||
// without too many false positives.
|
||||
AXPlatform::GetInstance().OnExtendedPropertiesUsed();
|
||||
AXPlatform::GetInstance().OnExtendedPropertiesUsedInWebContent();
|
||||
return RefRelationSet(atk_object);
|
||||
}
|
||||
|
||||
@ -2216,7 +2216,7 @@ AtkAttributeSet* AtkGetAttributes(AtkObject* atk_object) {
|
||||
// Enables AX mode. Most AT does not call AtkGetAttributes, but Orca does,
|
||||
// which is why it's a good signal to enable accessibility for Orca users
|
||||
// without too many false positives.
|
||||
AXPlatform::GetInstance().OnExtendedPropertiesUsed();
|
||||
AXPlatform::GetInstance().OnExtendedPropertiesUsedInWebContent();
|
||||
return GetAttributes(atk_object);
|
||||
}
|
||||
|
||||
|
@ -246,10 +246,6 @@ typedef std::unordered_set<AXPlatformNodeWin*> AXPlatformNodeWinSet;
|
||||
base::LazyInstance<AXPlatformNodeWinSet>::Leaky g_alert_targets =
|
||||
LAZY_INSTANCE_INITIALIZER;
|
||||
|
||||
base::LazyInstance<
|
||||
base::ObserverList<WinAccessibilityAPIUsageObserver>::Unchecked>::Leaky
|
||||
g_win_accessibility_api_usage_observer_list = LAZY_INSTANCE_INITIALIZER;
|
||||
|
||||
// Sets the multiplier by which large changes to a RangeValueProvider are
|
||||
// greater than small changes.
|
||||
constexpr int kLargeChangeScaleFactor = 10;
|
||||
@ -346,32 +342,19 @@ void AXPlatformNodeWin::AddAttributeToList(const char* name,
|
||||
base::UTF8ToWide(str_value));
|
||||
}
|
||||
|
||||
//
|
||||
// WinAccessibilityAPIUsageObserver
|
||||
//
|
||||
|
||||
WinAccessibilityAPIUsageObserver::WinAccessibilityAPIUsageObserver() = default;
|
||||
|
||||
WinAccessibilityAPIUsageObserver::~WinAccessibilityAPIUsageObserver() = default;
|
||||
|
||||
// static
|
||||
base::ObserverList<WinAccessibilityAPIUsageObserver>::Unchecked&
|
||||
GetWinAccessibilityAPIUsageObserverList() {
|
||||
return g_win_accessibility_api_usage_observer_list.Get();
|
||||
}
|
||||
|
||||
// Used to simplify calling StartFiringUIAEvents and EndFiringEvents
|
||||
// Used to avoid AXMode changes caused by UIA infrastructure reacting to events.
|
||||
WinAccessibilityAPIUsageScopedUIAEventsNotifier::
|
||||
WinAccessibilityAPIUsageScopedUIAEventsNotifier() {
|
||||
GetWinAccessibilityAPIUsageObserverList().Notify(
|
||||
&WinAccessibilityAPIUsageObserver::StartFiringUIAEvents);
|
||||
AXPlatformNodeWin::PauseAXModeChanges(true);
|
||||
}
|
||||
WinAccessibilityAPIUsageScopedUIAEventsNotifier::
|
||||
~WinAccessibilityAPIUsageScopedUIAEventsNotifier() {
|
||||
GetWinAccessibilityAPIUsageObserverList().Notify(
|
||||
&WinAccessibilityAPIUsageObserver::EndFiringUIAEvents);
|
||||
AXPlatformNodeWin::PauseAXModeChanges(false);
|
||||
}
|
||||
|
||||
// static
|
||||
bool AXPlatformNodeWin::pause_ax_mode_changes_ = false;
|
||||
|
||||
//
|
||||
// AXPlatformNode::Create
|
||||
//
|
||||
@ -1658,7 +1641,7 @@ IFACEMETHODIMP AXPlatformNodeWin::accLocation(LONG* physical_pixel_left,
|
||||
AXPlatformNodeWin* target;
|
||||
COM_OBJECT_VALIDATE_VAR_ID_4_ARGS_AND_GET_TARGET(
|
||||
var_id, physical_pixel_left, physical_pixel_top, width, height, target);
|
||||
NotifyObserverForMSAAUsage();
|
||||
AXPlatform::GetInstance().OnMinimalPropertiesUsed();
|
||||
|
||||
gfx::Rect bounds = target->GetDelegate()->GetBoundsRect(
|
||||
AXCoordinateSystem::kScreenPhysicalPixels,
|
||||
@ -1889,10 +1872,8 @@ IFACEMETHODIMP AXPlatformNodeWin::get_accName(VARIANT var_id, BSTR* name_bstr) {
|
||||
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_NAME);
|
||||
AXPlatformNodeWin* target;
|
||||
COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(var_id, name_bstr, target);
|
||||
NotifyObserverForMSAAUsage();
|
||||
|
||||
GetWinAccessibilityAPIUsageObserverList().Notify(
|
||||
&WinAccessibilityAPIUsageObserver::OnAccNameCalled);
|
||||
AXPlatform::GetInstance().OnMinimalPropertiesUsed();
|
||||
|
||||
if (!IsNameExposed())
|
||||
return S_FALSE;
|
||||
@ -1925,7 +1906,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_accRole(VARIANT var_id, VARIANT* role) {
|
||||
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_ROLE);
|
||||
AXPlatformNodeWin* target;
|
||||
COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(var_id, role, target);
|
||||
NotifyObserverForMSAAUsage();
|
||||
AXPlatform::GetInstance().OnMinimalPropertiesUsed();
|
||||
|
||||
role->vt = VT_I4;
|
||||
role->lVal = target->MSAARole();
|
||||
@ -1937,7 +1918,7 @@ IFACEMETHODIMP AXPlatformNodeWin::get_accState(VARIANT var_id, VARIANT* state) {
|
||||
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_STATE);
|
||||
AXPlatformNodeWin* target;
|
||||
COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(var_id, state, target);
|
||||
NotifyObserverForMSAAUsage();
|
||||
OnPropertiesUsed();
|
||||
|
||||
state->vt = VT_I4;
|
||||
state->lVal = target->MSAAState();
|
||||
@ -5927,15 +5908,9 @@ IFACEMETHODIMP AXPlatformNodeWin::QueryService(REFGUID guidService,
|
||||
"riid", base::WideToASCII(base::win::WStringFromGUID(riid)));
|
||||
COM_OBJECT_VALIDATE_1_ARG(object);
|
||||
|
||||
if (riid == IID_IAccessible2) {
|
||||
for (WinAccessibilityAPIUsageObserver& observer :
|
||||
GetWinAccessibilityAPIUsageObserverList()) {
|
||||
if (GetDelegate()->IsWebContent()) {
|
||||
observer.OnIAccessible2UsedInWebContent();
|
||||
} else {
|
||||
observer.OnIAccessible2UsedInBrowserUI();
|
||||
}
|
||||
}
|
||||
if (riid == IID_IAccessible2 || riid == IID_IAccessible2_2 ||
|
||||
riid == IID_IAccessible2_3 || riid == IID_IAccessible2_4) {
|
||||
OnPropertiesUsed();
|
||||
}
|
||||
|
||||
if (guidService == IID_IAccessible || guidService == IID_IAccessible2 ||
|
||||
@ -8557,41 +8532,30 @@ void AXPlatformNodeWin::SanitizeTextAttributeValue(const std::string& input,
|
||||
SanitizeStringAttributeForIA2(input, output);
|
||||
}
|
||||
|
||||
void AXPlatformNodeWin::NotifyObserverForMSAAUsage() const {
|
||||
GetWinAccessibilityAPIUsageObserverList().Notify(
|
||||
&WinAccessibilityAPIUsageObserver::OnMSAAUsed);
|
||||
}
|
||||
|
||||
void AXPlatformNodeWin::NotifyAPIObserverForPatternRequest(
|
||||
PATTERNID pattern_id) const {
|
||||
if (!GetDelegate()->IsWebContent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool probable_advanced_client_detected = false;
|
||||
bool text_pattern_support_needed = false;
|
||||
if (pause_ax_mode_changes_) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pattern_id) {
|
||||
case UIA_TextPatternId:
|
||||
case UIA_TextChildPatternId:
|
||||
// These properties require information gated behind the kInlineTextBoxes
|
||||
// AXMode. See kInlineTextBoxes for details.
|
||||
text_pattern_support_needed = true;
|
||||
OnInlineTextBoxesUsed();
|
||||
break;
|
||||
// These properties require more advanced accessibility features to be
|
||||
// enabled See kExtendedProperties for details.
|
||||
case UIA_RangeValuePatternId:
|
||||
case UIA_TableItemPatternId:
|
||||
probable_advanced_client_detected = true;
|
||||
OnPropertiesUsed();
|
||||
break;
|
||||
}
|
||||
|
||||
for (WinAccessibilityAPIUsageObserver& observer :
|
||||
GetWinAccessibilityAPIUsageObserverList()) {
|
||||
if (probable_advanced_client_detected)
|
||||
observer.OnUIAutomationUsedInWebContent();
|
||||
if (text_pattern_support_needed)
|
||||
observer.OnTextPatternRequested();
|
||||
}
|
||||
}
|
||||
|
||||
void AXPlatformNodeWin::NotifyAPIObserverForPropertyRequest(
|
||||
@ -8602,8 +8566,10 @@ void AXPlatformNodeWin::NotifyAPIObserverForPropertyRequest(
|
||||
return;
|
||||
}
|
||||
|
||||
bool probable_advanced_client_detected = false;
|
||||
bool probable_screen_reader_detected = false;
|
||||
if (pause_ax_mode_changes_) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (property_id) {
|
||||
// These properties are used by non-screenreader UIA clients. They should
|
||||
// not cause additional enablement.
|
||||
@ -8675,18 +8641,10 @@ void AXPlatformNodeWin::NotifyAPIObserverForPropertyRequest(
|
||||
case UIA_LocalizedLandmarkTypePropertyId:
|
||||
case UIA_FullDescriptionPropertyId:
|
||||
case UIA_IsDialogPropertyId:
|
||||
probable_screen_reader_detected = true;
|
||||
probable_advanced_client_detected = true;
|
||||
OnPropertiesUsed();
|
||||
OnExtendedPropertiesUsed();
|
||||
break;
|
||||
}
|
||||
|
||||
for (WinAccessibilityAPIUsageObserver& observer :
|
||||
GetWinAccessibilityAPIUsageObserverList()) {
|
||||
if (probable_advanced_client_detected)
|
||||
observer.OnUIAutomationUsedInWebContent();
|
||||
if (probable_screen_reader_detected)
|
||||
observer.OnProbableUIAutomationScreenReaderDetected();
|
||||
}
|
||||
}
|
||||
|
||||
AXPlatformNodeWin* AXPlatformNodeWin::GetUIATableAncestor() const {
|
||||
@ -8835,17 +8793,23 @@ bool AXPlatformNodeWin::IsInvokeSupported() const {
|
||||
return GetData().IsInvocable();
|
||||
}
|
||||
|
||||
void AXPlatformNodeWin::OnPropertiesUsed() const {
|
||||
if (GetDelegate()->IsWebContent()) {
|
||||
AXPlatform::GetInstance().OnPropertiesUsedInWebContent();
|
||||
} else {
|
||||
AXPlatform::GetInstance().OnPropertiesUsedInBrowserUI();
|
||||
}
|
||||
}
|
||||
|
||||
void AXPlatformNodeWin::OnExtendedPropertiesUsed() const {
|
||||
if (GetDelegate()->IsWebContent()) {
|
||||
GetWinAccessibilityAPIUsageObserverList().Notify(
|
||||
&WinAccessibilityAPIUsageObserver::OnExtendedPropertiesUsed);
|
||||
AXPlatform::GetInstance().OnExtendedPropertiesUsedInWebContent();
|
||||
}
|
||||
}
|
||||
|
||||
void AXPlatformNodeWin::OnInlineTextBoxesUsed() const {
|
||||
if (GetDelegate()->IsWebContent()) {
|
||||
GetWinAccessibilityAPIUsageObserverList().Notify(
|
||||
&WinAccessibilityAPIUsageObserver::OnInlineTextBoxesUsed);
|
||||
AXPlatform::GetInstance().OnInlineTextBoxesUsedInWebContent();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,35 +363,6 @@ namespace ui {
|
||||
class AXFragmentRootWin;
|
||||
class AXPlatformNodeWin;
|
||||
|
||||
// A simple interface for a class that wants to be notified when Windows
|
||||
// accessibility APIs are used by a client, a strong indication that full
|
||||
// accessibility support should be enabled.
|
||||
class COMPONENT_EXPORT(AX_PLATFORM) WinAccessibilityAPIUsageObserver {
|
||||
public:
|
||||
WinAccessibilityAPIUsageObserver();
|
||||
virtual ~WinAccessibilityAPIUsageObserver();
|
||||
virtual void OnMSAAUsed() = 0;
|
||||
virtual void OnIAccessible2UsedInBrowserUI() = 0;
|
||||
virtual void OnIAccessible2UsedInWebContent() = 0;
|
||||
virtual void OnScreenReaderHoneyPotQueried() = 0;
|
||||
virtual void OnAccNameCalled() = 0;
|
||||
virtual void OnInlineTextBoxesUsed() = 0;
|
||||
virtual void OnExtendedPropertiesUsed() = 0;
|
||||
virtual void OnHTMLAttributesUsed() = 0;
|
||||
virtual void OnUIAutomationUsedInWebContent() = 0;
|
||||
virtual void OnUIAutomationUsedInBrowserUI() = 0;
|
||||
virtual void OnProbableUIAutomationScreenReaderDetected() = 0;
|
||||
virtual void OnTextPatternRequested() = 0;
|
||||
virtual void StartFiringUIAEvents() = 0;
|
||||
virtual void EndFiringUIAEvents() = 0;
|
||||
};
|
||||
|
||||
// Get an observer list that allows modules across the codebase to
|
||||
// listen to when usage of Windows accessibility APIs is detected.
|
||||
extern COMPONENT_EXPORT(
|
||||
AX_PLATFORM) base::ObserverList<WinAccessibilityAPIUsageObserver>::
|
||||
Unchecked& GetWinAccessibilityAPIUsageObserverList();
|
||||
|
||||
// Used to simplify calling StartFiringUIAEvents and EndFiringEvents
|
||||
class COMPONENT_EXPORT(AX_PLATFORM)
|
||||
WinAccessibilityAPIUsageScopedUIAEventsNotifier {
|
||||
@ -1208,6 +1179,10 @@ class COMPONENT_EXPORT(AX_PLATFORM)
|
||||
bool HasEventListenerForEvent(EVENTID event_id);
|
||||
bool HasEventListenerForProperty(PROPERTYID property_id);
|
||||
|
||||
// Firing a UIA event can cause UIA to call back into our APIs, don't
|
||||
// consider this to be usage.
|
||||
static void PauseAXModeChanges(bool pause) { pause_ax_mode_changes_ = pause; }
|
||||
|
||||
// Convert a mojo event to an MSAA event. Exposed for testing.
|
||||
static std::optional<DWORD> MojoEventToMSAAEvent(ax::mojom::Event event);
|
||||
|
||||
@ -1300,6 +1275,9 @@ class COMPONENT_EXPORT(AX_PLATFORM)
|
||||
static void SanitizeStringAttributeForIA2(const std::string& input,
|
||||
std::string* output);
|
||||
|
||||
// Turn on AXMode::kWebContent if in web content, otherwise just kNativeAPIs.
|
||||
void OnPropertiesUsed() const;
|
||||
|
||||
// Turn on AXMode::kExtendedProperties if in web content.
|
||||
void OnExtendedPropertiesUsed() const;
|
||||
|
||||
@ -1596,6 +1574,8 @@ class COMPONENT_EXPORT(AX_PLATFORM)
|
||||
|
||||
friend AXPlatformNode::Pointer AXPlatformNode::Create(
|
||||
AXPlatformNodeDelegate& delegate);
|
||||
|
||||
static bool pause_ax_mode_changes_;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
@ -907,16 +907,6 @@ std::string BrowserAccessibility::SubtreeToStringHelper(size_t level) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO(crbug.com/337737555): This extra hop seems redundant, but
|
||||
// unintuitively, this is the only override of NotifyAccessibilityApiUsage, so
|
||||
// the the other inheritors of AXPlatformNodeDelegate don't actually ever send
|
||||
// this notification. But, if this was refactored to be directly called, we end
|
||||
// up failing bots due to the fact that this can be called by our own API usage,
|
||||
// which is tracked by the linked bug.
|
||||
void BrowserAccessibility::NotifyAccessibilityApiUsage() const {
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
}
|
||||
|
||||
const std::vector<gfx::NativeViewAccessible>
|
||||
BrowserAccessibility::GetUIADirectChildrenInRange(AXPlatformNodeDelegate* start,
|
||||
AXPlatformNodeDelegate* end) {
|
||||
|
@ -478,8 +478,6 @@ class COMPONENT_EXPORT(AX_PLATFORM) BrowserAccessibility
|
||||
|
||||
std::string SubtreeToStringHelper(size_t level) override;
|
||||
|
||||
void NotifyAccessibilityApiUsage() const override;
|
||||
|
||||
// The UIA tree formatter needs access to GetUniqueId() to identify the
|
||||
// starting point for tree dumps.
|
||||
friend class AccessibilityTreeFormatterUia;
|
||||
|
@ -1132,11 +1132,11 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_attributes(USHORT max_attribs,
|
||||
if (!GetDelegate()->IsWebContent()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (!attrib_names || !name_space_id || !attrib_values || !num_attribs)
|
||||
return E_INVALIDARG;
|
||||
|
||||
GetWinAccessibilityAPIUsageObserverList().Notify(
|
||||
&WinAccessibilityAPIUsageObserver::OnHTMLAttributesUsed);
|
||||
AXPlatform::GetInstance().OnHTMLAttributesUsed();
|
||||
|
||||
#define ADD_ATTRIBUTE(name, value) \
|
||||
if (index < max_attribs) { \
|
||||
@ -1398,8 +1398,7 @@ IFACEMETHODIMP BrowserAccessibilityComWin::get_innerHTML(BSTR* innerHTML) {
|
||||
return E_FAIL;
|
||||
}
|
||||
// Inner HTML is exposed only for math, only when kExtendedProperties is on.
|
||||
GetWinAccessibilityAPIUsageObserverList().Notify(
|
||||
&WinAccessibilityAPIUsageObserver::OnExtendedPropertiesUsed);
|
||||
OnExtendedPropertiesUsed();
|
||||
BrowserAccessibilityWin* const owner = GetOwner();
|
||||
if (owner->GetRole() != ax::mojom::Role::kMath &&
|
||||
owner->GetRole() != ax::mojom::Role::kMathMLMath) {
|
||||
|
@ -882,7 +882,7 @@ void BrowserAccessibilityManager::Blur(const BrowserAccessibility& node) {
|
||||
action_data.action = ax::mojom::Action::kBlur;
|
||||
action_data.target_node_id = node.GetId();
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::SetFocus(const BrowserAccessibility& node) {
|
||||
@ -898,7 +898,7 @@ void BrowserAccessibilityManager::SetFocus(const BrowserAccessibility& node) {
|
||||
if (!delegate_->AccessibilityViewHasFocus())
|
||||
delegate_->AccessibilityViewSetFocus();
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::SetSequentialFocusNavigationStartingPoint(
|
||||
@ -911,7 +911,7 @@ void BrowserAccessibilityManager::SetSequentialFocusNavigationStartingPoint(
|
||||
ax::mojom::Action::kSetSequentialFocusNavigationStartingPoint;
|
||||
action_data.target_node_id = node.GetId();
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::SetGeneratedEventCallbackForTesting(
|
||||
@ -937,7 +937,7 @@ void BrowserAccessibilityManager::Decrement(const BrowserAccessibility& node) {
|
||||
action_data.action = ax::mojom::Action::kDecrement;
|
||||
action_data.target_node_id = node.GetId();
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::DoDefaultAction(
|
||||
@ -960,7 +960,7 @@ void BrowserAccessibilityManager::DoDefaultAction(
|
||||
action_data.action = ax::mojom::Action::kDoDefault;
|
||||
action_data.target_node_id = node.GetId();
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::GetImageData(const BrowserAccessibility& node,
|
||||
@ -973,7 +973,7 @@ void BrowserAccessibilityManager::GetImageData(const BrowserAccessibility& node,
|
||||
action_data.target_node_id = node.GetId();
|
||||
action_data.target_rect = gfx::Rect(gfx::Point(), max_size);
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::Increment(const BrowserAccessibility& node) {
|
||||
@ -984,7 +984,7 @@ void BrowserAccessibilityManager::Increment(const BrowserAccessibility& node) {
|
||||
action_data.action = ax::mojom::Action::kIncrement;
|
||||
action_data.target_node_id = node.GetId();
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::Expand(const BrowserAccessibility& node) {
|
||||
@ -996,7 +996,7 @@ void BrowserAccessibilityManager::Expand(const BrowserAccessibility& node) {
|
||||
action_data.action = ax::mojom::Action::kExpand;
|
||||
action_data.target_node_id = node.GetId();
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::Collapse(const BrowserAccessibility& node) {
|
||||
@ -1008,7 +1008,7 @@ void BrowserAccessibilityManager::Collapse(const BrowserAccessibility& node) {
|
||||
action_data.action = ax::mojom::Action::kCollapse;
|
||||
action_data.target_node_id = node.GetId();
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::ShowContextMenu(
|
||||
@ -1020,7 +1020,7 @@ void BrowserAccessibilityManager::ShowContextMenu(
|
||||
action_data.action = ax::mojom::Action::kShowContextMenu;
|
||||
action_data.target_node_id = node.GetId();
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::SignalEndOfTest() {
|
||||
@ -1052,7 +1052,7 @@ void BrowserAccessibilityManager::Scroll(const BrowserAccessibility& node,
|
||||
action_data.action = scroll_action;
|
||||
action_data.target_node_id = node.GetId();
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::ScrollToMakeVisible(
|
||||
@ -1078,7 +1078,7 @@ void BrowserAccessibilityManager::ScrollToMakeVisible(
|
||||
action_data.vertical_scroll_alignment = vertical_scroll_alignment;
|
||||
action_data.scroll_behavior = scroll_behavior;
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
|
||||
// Android has an official api for accessibility focus.
|
||||
#if !BUILDFLAG(IS_ANDROID)
|
||||
@ -1102,7 +1102,7 @@ void BrowserAccessibilityManager::ScrollToPoint(
|
||||
action_data.action = ax::mojom::Action::kScrollToPoint;
|
||||
action_data.target_point = point;
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::SetScrollOffset(
|
||||
@ -1116,7 +1116,7 @@ void BrowserAccessibilityManager::SetScrollOffset(
|
||||
action_data.action = ax::mojom::Action::kSetScrollOffset;
|
||||
action_data.target_point = offset;
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::SetValue(const BrowserAccessibility& node,
|
||||
@ -1129,7 +1129,7 @@ void BrowserAccessibilityManager::SetValue(const BrowserAccessibility& node,
|
||||
action_data.action = ax::mojom::Action::kSetValue;
|
||||
action_data.value = value;
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::SetSelection(
|
||||
@ -1137,7 +1137,7 @@ void BrowserAccessibilityManager::SetSelection(
|
||||
if (!delegate_)
|
||||
return;
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::SetSelection(
|
||||
@ -1152,7 +1152,7 @@ void BrowserAccessibilityManager::SetSelection(
|
||||
action_data.focus_offset = range.focus()->text_offset();
|
||||
action_data.action = ax::mojom::Action::kSetSelection;
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::StitchChildTree(
|
||||
@ -1169,7 +1169,7 @@ void BrowserAccessibilityManager::StitchChildTree(
|
||||
action_data.target_node_id = node.GetId();
|
||||
action_data.child_tree_id = child_tree_id;
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::LoadInlineTextBoxes(
|
||||
@ -1185,7 +1185,7 @@ void BrowserAccessibilityManager::LoadInlineTextBoxes(
|
||||
action_data.action = ax::mojom::Action::kLoadInlineTextBoxes;
|
||||
action_data.target_node_id = node.GetId();
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::SetAccessibilityFocus(
|
||||
@ -1197,7 +1197,7 @@ void BrowserAccessibilityManager::SetAccessibilityFocus(
|
||||
action_data.action = ax::mojom::Action::kSetAccessibilityFocus;
|
||||
action_data.target_node_id = node.GetId();
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::ClearAccessibilityFocus(
|
||||
@ -1209,7 +1209,7 @@ void BrowserAccessibilityManager::ClearAccessibilityFocus(
|
||||
action_data.action = ax::mojom::Action::kClearAccessibilityFocus;
|
||||
action_data.target_node_id = node.GetId();
|
||||
delegate_->AccessibilityPerformAction(action_data);
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
void BrowserAccessibilityManager::HitTest(const gfx::Point& frame_point,
|
||||
@ -1220,7 +1220,7 @@ void BrowserAccessibilityManager::HitTest(const gfx::Point& frame_point,
|
||||
delegate_->AccessibilityHitTest(frame_point, ax::mojom::Event::kHover,
|
||||
request_id,
|
||||
/*opt_callback=*/{});
|
||||
AXPlatform::GetInstance().NotifyAccessibilityApiUsage();
|
||||
AXPlatform::GetInstance().OnActionFromAssistiveTech();
|
||||
}
|
||||
|
||||
gfx::Rect BrowserAccessibilityManager::GetViewBoundsInScreenCoordinates()
|
||||
|
Reference in New Issue
Block a user