| // 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; |
| #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. |
| 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; |
| |
| // Notes that an inbound request from a UIA client has been serviced; for |
| // example, by calling UiaReturnRawElementProvider to give it a window's |
| // root object. |
| void SetUiaClientServiced(bool uia_client_serviced); |
| |
| // Returns true if a UIA client has been serviced; see above. |
| bool HasServicedUiaClients(); |
| #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. |
| 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; |
| bool has_serviced_uia_clients_ 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_ |