1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
|
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_H_
#define UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_H_
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ref.h"
#include "base/observer_list.h"
#include "base/scoped_observation_traits.h"
#include "base/threading/thread_checker.h"
#include "build/build_config.h"
#include "ui/accessibility/ax_mode.h"
#include "ui/accessibility/platform/assistive_tech.h"
namespace ui {
class AXModeObserver;
class AXPlatformNode;
// Process-wide accessibility platform state.
class COMPONENT_EXPORT(AX_PLATFORM) AXPlatform {
public:
#if BUILDFLAG(IS_WIN)
// These strings are only needed for IA2 support.
struct ProductStrings {
// Product name, e.g. "Chrome".
std::string product_name;
// Version number, e.g. "aa.bb.cc.dd".
std::string product_version;
// Toolkit version of the product, for example, the User Agent string.
std::string toolkit_version;
};
#endif
class COMPONENT_EXPORT(AX_PLATFORM) Delegate {
public:
Delegate(const Delegate&) = delete;
Delegate& operator=(const Delegate&) = delete;
virtual ~Delegate() = default;
// Returns the effective process-wide accessibility mode.
virtual AXMode GetAccessibilityMode() = 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
// product_strings_ member of AXPlatform.
virtual ProductStrings GetProductStrings() = 0;
// Invoked when an accessibility client requests the UI automation root
// object for a window. `uia_provider_enabled` is true when the request was
// satisfied, and false when the request was refused.
virtual void OnUiaProviderRequested(bool uia_provider_enabled) {}
// Invoked when the UI Automation Provider for Windows has been disabled due
// to a detected assistive technology that may cause issues with the
// provider, such as JAWS.
virtual void OnUiaProviderDisabled() {}
#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;
};
// Returns the single process-wide instance.
static AXPlatform& GetInstance();
// Constructs a new instance. Only one instance may be alive in a process at
// any given time. Typically, the embedder creates one during process startup
// and ensures that it is kept alive throughout the process's UX.
explicit AXPlatform(Delegate& delegate);
AXPlatform(const AXPlatform&) = delete;
AXPlatform& operator=(const AXPlatform&) = delete;
~AXPlatform();
// Returns the process-wide accessibility mode.
AXMode GetMode();
void AddModeObserver(AXModeObserver* observer);
void RemoveModeObserver(AXModeObserver* observer);
// Notifies observers that the mode flags in `mode` have been added to the
// process-wide accessibility mode.
void NotifyModeAdded(AXMode mode);
// Notify observers that an assistive technology was launched or exited.
// Note: in some cases we do not yet have a perfect signal when the user
// quits their assistive tech, so in that case the tool will continue to
// appear to be present.
// The only known assistive tech that this affects currently is JAWS.
// TODO(crbug.com/402069423) Improve JAWS exit detection.
void NotifyAssistiveTechChanged(AssistiveTech assistive_tech);
// The current active assistive tech, such as a screen reader, where a
// detection algorithm has been implemented.
AssistiveTech active_assistive_tech() const {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return active_assistive_tech_;
}
// Is the current active assistive tech a screen reader.
bool IsScreenReaderActive();
// 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();
void SetCaretBrowsingState(bool enabled);
#if BUILDFLAG(IS_WIN)
// Returns the product name, e.g. "Chrome".
const std::string& GetProductName() const;
// Returns the version number, e.g. "aa.bb.cc.dd".
const std::string& GetProductVersion() const;
// Returns the toolkit version of the product, for example, the User Agent
// string.
const std::string& GetToolkitVersion() const;
// Enables or disables use of the UI Automation Provider on Windows. If this
// function is not called, the provider is enabled or disabled on the basis of
// the "UiaProvider" base::Feature. In such cases, the `--enable-features` or
// `--disable-features` switches on the browser's command line may be used to
// enable or disable use of the provider, respectively. This function may only
// be called during browser process startup before any UI is presented.
void SetUiaProviderEnabled(bool is_enabled);
// Disables the UI Automation Provider on Windows, and signals to UIA that the
// previous providers that might have been returned are no longer valid.
void DisableActiveUiaProvider();
// Returns true if the UI Automation Provider for Windows is enabled.
bool IsUiaProviderEnabled() const;
// Notifies the platform that an accessibility client requested the UI
// automation root object for a window. `uia_provider_enabled` is true when
// the request was satisfied, and false when the request was refused.
void OnUiaProviderRequested(bool uia_provider_enabled);
#endif
// 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(bool is_name_used = false);
// 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();
private:
friend class ::ui::AXPlatformNode;
FRIEND_TEST_ALL_PREFIXES(AXPlatformTest, Observer);
#if BUILDFLAG(IS_WIN)
// Retrieves the product name, version, and toolkit version from the delegate
// if they have not already been retrieved.
void RetrieveProductStringsIfNeeded() const
VALID_CONTEXT_REQUIRED(thread_checker_);
#endif
// The embedder's delegate.
const raw_ref<Delegate> delegate_ GUARDED_BY_CONTEXT(thread_checker_);
base::ObserverList<AXModeObserver,
/*check_empty=*/true,
/*allow_reentrancy=*/false>
observers_ GUARDED_BY_CONTEXT(thread_checker_);
#if BUILDFLAG(IS_WIN)
// See product_name() product_version(), and toolkit_version().
// These are lazily cached upon first use. Mutable to allow caching.
mutable std::optional<ProductStrings> product_strings_
GUARDED_BY_CONTEXT(thread_checker_);
enum class UiaProviderEnablement {
// Enabled or disabled via Chrome Variations (base::FeatureList).
kVariations,
// Explicitly enabled at runtime.
kEnabled,
// Explicitly disabled at runtime.
kDisabled,
};
UiaProviderEnablement uia_provider_enablement_
GUARDED_BY_CONTEXT(thread_checker_) = UiaProviderEnablement::kVariations;
#endif // BUILDFLAG(IS_WIN)
// Keeps track of the active AssistiveTech.
AssistiveTech active_assistive_tech_ GUARDED_BY_CONTEXT(thread_checker_) =
AssistiveTech::kUninitialized;
// 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 is_name_used_ GUARDED_BY_CONTEXT(thread_checker_) = false;
#endif
THREAD_CHECKER(thread_checker_);
};
} // namespace ui
namespace base {
// Traits type in support of base::ScopedObservation.
template <>
struct ScopedObservationTraits<ui::AXPlatform, ui::AXModeObserver> {
static void AddObserver(ui::AXPlatform* source,
ui::AXModeObserver* observer) {
source->AddModeObserver(observer);
}
static void RemoveObserver(ui::AXPlatform* source,
ui::AXModeObserver* observer) {
source->RemoveModeObserver(observer);
}
};
} // namespace base
#endif // UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_H_
|