#ifndef ASH_ACCESSIBILITY_ACCESSIBILITY_CONTROLLER_IMPL_H_
#define ASH_ACCESSIBILITY_ACCESSIBILITY_CONTROLLER_IMPL_H_
#include <memory>
#include "ash/accessibility/a11y_feature_type.h"
#include "ash/ash_export.h"
#include "ash/constants/ash_constants.h"
#include "ash/public/cpp/accessibility_controller.h"
#include "ash/public/cpp/session/session_observer.h"
#include "ash/public/cpp/tablet_mode_observer.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
class PrefChangeRegistrar;
class PrefRegistrySimple;
class PrefService;
namespace aura {
class Window;
}
namespace ax {
namespace mojom {
enum class Gesture;
}
}
namespace gfx {
class Point;
class PointF;
struct VectorIcon;
}
namespace ash {
class AccessibilityConfirmationDialog;
class AccessibilityEventRewriter;
class AccessibilityHighlightController;
class AccessibilityObserver;
class DictationBubbleController;
class DictationNudgeController;
class FloatingAccessibilityController;
class PointScanController;
class ScopedBacklightsForcedOff;
class SelectToSpeakEventHandler;
class SelectToSpeakMenuBubbleController;
class SwitchAccessMenuBubbleController;
enum class Sound;
enum AccessibilityNotificationVisibility {
A11Y_NOTIFICATION_NONE,
A11Y_NOTIFICATION_SHOW,
};
enum class A11yNotificationType {
kNone,
kSpokenFeedbackEnabled,
kBrailleDisplayConnected,
kDictationAllDlcsDownloaded,
kDictationNoDlcsDownloaded,
kDicationOnlyPumpkinDownloaded,
kDictationOnlySodaDownloaded,
kSpokenFeedbackBrailleEnabled,
kSwitchAccessEnabled,
};
class ASH_EXPORT AccessibilityControllerImpl : public AccessibilityController,
public SessionObserver,
public TabletModeObserver {
public:
class Feature {
public:
Feature(A11yFeatureType type,
const std::string& pref_name,
const gfx::VectorIcon* icon,
AccessibilityControllerImpl* controller);
Feature(const Feature&) = delete;
Feature& operator=(Feature const&) = delete;
virtual ~Feature();
A11yFeatureType type() const { return type_; }
virtual void SetEnabled(bool enabled);
bool enabled() const { return enabled_; }
bool IsVisibleInTray() const;
bool IsEnterpriseIconVisible() const;
const std::string& pref_name() const { return pref_name_; }
const gfx::VectorIcon& icon() const;
void UpdateFromPref();
void SetConflictingFeature(A11yFeatureType feature);
protected:
const A11yFeatureType type_;
A11yFeatureType conflicting_feature_ =
A11yFeatureType::kNoConflictingFeature;
bool enabled_ = false;
const std::string pref_name_;
raw_ptr<const gfx::VectorIcon, ExperimentalAsh> icon_;
const raw_ptr<AccessibilityControllerImpl, ExperimentalAsh> owner_;
};
struct Dialog {
std::string pref_name;
int title_resource_id;
int body_resource_id;
bool mandatory;
};
class FeatureWithDialog : public Feature {
public:
FeatureWithDialog(A11yFeatureType type,
const std::string& pref_name,
const gfx::VectorIcon* icon,
const Dialog& dialog,
AccessibilityControllerImpl* controller);
~FeatureWithDialog() override;
void SetEnabled(bool enabled) override;
void SetEnabledWithDialog(bool enabled,
base::OnceClosure completion_callback);
void SetDialogAccepted();
bool WasDialogAccepted() const;
private:
Dialog dialog_;
};
struct A11yNotificationWrapper {
A11yNotificationWrapper();
A11yNotificationWrapper(A11yNotificationType type_in,
std::vector<std::u16string> replacements_in);
~A11yNotificationWrapper();
A11yNotificationWrapper(const A11yNotificationWrapper&);
A11yNotificationType type = A11yNotificationType::kNone;
std::vector<std::u16string> replacements;
};
AccessibilityControllerImpl();
AccessibilityControllerImpl(const AccessibilityControllerImpl&) = delete;
AccessibilityControllerImpl& operator=(const AccessibilityControllerImpl&) =
delete;
~AccessibilityControllerImpl() override;
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
void Shutdown();
void AddObserver(AccessibilityObserver* observer);
void RemoveObserver(AccessibilityObserver* observer);
Feature& GetFeature(A11yFeatureType feature) const;
base::WeakPtr<AccessibilityControllerImpl> GetWeakPtr();
Feature& autoclick() const;
Feature& caret_highlight() const;
Feature& cursor_highlight() const;
Feature& dictation() const;
Feature& floating_menu() const;
Feature& focus_highlight() const;
FeatureWithDialog& fullscreen_magnifier() const;
FeatureWithDialog& docked_magnifier() const;
FeatureWithDialog& high_contrast() const;
Feature& large_cursor() const;
Feature& live_caption() const;
Feature& mono_audio() const;
Feature& spoken_feedback() const;
Feature& select_to_speak() const;
Feature& sticky_keys() const;
Feature& switch_access() const;
Feature& virtual_keyboard() const;
Feature& cursor_color() const;
void SetDisplayRotationAcceleratorDialogBeenAccepted();
bool HasDisplayRotationAcceleratorDialogBeenAccepted() const;
bool IsAutoclickSettingVisibleInTray();
bool IsEnterpriseIconVisibleForAutoclick();
void SetAutoclickEventType(AutoclickEventType event_type);
AutoclickEventType GetAutoclickEventType();
void SetAutoclickMenuPosition(FloatingMenuPosition position);
FloatingMenuPosition GetAutoclickMenuPosition();
void RequestAutoclickScrollableBoundsForPoint(gfx::Point& point_in_screen);
void MagnifierBoundsChanged(const gfx::Rect& bounds_in_screen);
void SetFloatingMenuPosition(FloatingMenuPosition position);
FloatingMenuPosition GetFloatingMenuPosition();
FloatingAccessibilityController* GetFloatingMenuController();
PointScanController* GetPointScanController();
void UpdateFloatingPanelBoundsIfNeeded();
void UpdateAutoclickMenuBoundsIfNeeded();
bool IsCaretHighlightSettingVisibleInTray();
bool IsEnterpriseIconVisibleForCaretHighlight();
bool IsCursorHighlightSettingVisibleInTray();
bool IsEnterpriseIconVisibleForCursorHighlight();
bool IsDictationSettingVisibleInTray();
bool IsEnterpriseIconVisibleForDictation();
bool IsFocusHighlightSettingVisibleInTray();
bool IsEnterpriseIconVisibleForFocusHighlight();
bool IsFullScreenMagnifierSettingVisibleInTray();
bool IsEnterpriseIconVisibleForFullScreenMagnifier();
bool IsDockedMagnifierSettingVisibleInTray();
bool IsEnterpriseIconVisibleForDockedMagnifier();
bool IsHighContrastSettingVisibleInTray();
bool IsEnterpriseIconVisibleForHighContrast();
bool IsLargeCursorSettingVisibleInTray();
bool IsEnterpriseIconVisibleForLargeCursor();
bool IsLiveCaptionSettingVisibleInTray();
bool IsEnterpriseIconVisibleForLiveCaption();
bool IsMonoAudioSettingVisibleInTray();
bool IsEnterpriseIconVisibleForMonoAudio();
void SetSpokenFeedbackEnabled(bool enabled,
AccessibilityNotificationVisibility notify);
bool IsSpokenFeedbackSettingVisibleInTray();
bool IsEnterpriseIconVisibleForSpokenFeedback();
bool IsSelectToSpeakSettingVisibleInTray();
bool IsEnterpriseIconVisibleForSelectToSpeak();
void RequestSelectToSpeakStateChange();
SelectToSpeakState GetSelectToSpeakState() const;
bool IsStickyKeysSettingVisibleInTray();
bool IsEnterpriseIconVisibleForStickyKeys();
bool IsSwitchAccessRunning() const;
bool IsSwitchAccessSettingVisibleInTray();
bool IsEnterpriseIconVisibleForSwitchAccess();
void SetAccessibilityEventRewriter(
AccessibilityEventRewriter* accessibility_event_rewriter);
bool IsPointScanEnabled();
bool IsVirtualKeyboardSettingVisibleInTray();
bool IsEnterpriseIconVisibleForVirtualKeyboard();
void SetTabletModeShelfNavigationButtonsEnabled(bool enabled);
bool tablet_mode_shelf_navigation_buttons_enabled() const {
return tablet_mode_shelf_navigation_buttons_enabled_;
}
void ShowFloatingMenuIfEnabled() override;
bool dictation_active() const { return dictation_active_; }
bool accessibility_shortcuts_enabled() const { return shortcuts_enabled_; }
void TriggerAccessibilityAlert(AccessibilityAlert alert);
void TriggerAccessibilityAlertWithMessage(const std::string& message);
void PlayEarcon(Sound sound_key);
base::TimeDelta PlayShutdownSound();
void HandleAccessibilityGesture(ax::mojom::Gesture gesture,
gfx::PointF location);
void ToggleDictation();
void OnTwoFingerTouchStart();
void OnTwoFingerTouchStop();
bool ShouldToggleSpokenFeedbackViaTouch() const;
void PlaySpokenFeedbackToggleCountdown(int tick_count);
bool IsEnterpriseIconVisibleInTrayMenu(const std::string& path);
bool IsPrimarySettingsViewVisibleInTray();
bool IsAdditionalSettingsViewVisibleInTray();
bool IsAdditionalSettingsSeparatorVisibleInTray();
void StartPointScanning();
void SetA11yOverrideWindow(aura::Window* a11y_override_window);
void SetClient(AccessibilityControllerClient* client) override;
void SetDarkenScreen(bool darken) override;
void BrailleDisplayStateChanged(bool connected) override;
void SetFocusHighlightRect(const gfx::Rect& bounds_in_screen) override;
void SetCaretBounds(const gfx::Rect& bounds_in_screen) override;
void SetAccessibilityPanelAlwaysVisible(bool always_visible) override;
void SetAccessibilityPanelBounds(const gfx::Rect& bounds,
AccessibilityPanelState state) override;
void SetSelectToSpeakState(SelectToSpeakState state) override;
void SetSelectToSpeakEventHandlerDelegate(
SelectToSpeakEventHandlerDelegate* delegate) override;
void ShowSelectToSpeakPanel(const gfx::Rect& anchor,
bool is_paused,
double speech_rate) override;
void HideSelectToSpeakPanel() override;
void OnSelectToSpeakPanelAction(SelectToSpeakPanelAction action,
double value) override;
void HideSwitchAccessBackButton() override;
void HideSwitchAccessMenu() override;
void ShowSwitchAccessBackButton(const gfx::Rect& anchor) override;
void ShowSwitchAccessMenu(const gfx::Rect& anchor,
std::vector<std::string> actions_to_show) override;
void StartPointScan() override;
void StopPointScan() override;
void SetPointScanSpeedDipsPerSecond(
int point_scan_speed_dips_per_second) override;
void SetDictationActive(bool is_active) override;
void ToggleDictationFromSource(DictationToggleSource source) override;
void ShowDictationLanguageUpgradedNudge(
const std::string& dictation_locale,
const std::string& application_locale) override;
void HandleAutoclickScrollableBoundsFound(
gfx::Rect& bounds_in_screen) override;
std::u16string GetBatteryDescription() const override;
void SetVirtualKeyboardVisible(bool is_visible) override;
void PerformAcceleratorAction(AcceleratorAction accelerator_action) override;
void NotifyAccessibilityStatusChanged() override;
bool IsAccessibilityFeatureVisibleInTrayMenu(
const std::string& path) override;
void DisablePolicyRecommendationRestorerForTesting() override;
void SuspendSwitchAccessKeyHandling(bool suspend) override;
void EnableChromeVoxVolumeSlideGesture() override;
void UpdateDictationButtonOnSpeechRecognitionDownloadChanged(
int download_progress) override;
void ShowNotificationForDictation(
DictationNotificationType type,
const std::u16string& display_language) override;
void UpdateDictationBubble(
bool visible,
DictationBubbleIconType icon,
const absl::optional<std::u16string>& text,
const absl::optional<std::vector<DictationBubbleHintType>>& hints)
override;
void SilenceSpokenFeedback() override;
void ShowConfirmationDialog(const std::u16string& title,
const std::u16string& description,
base::OnceClosure on_accept_callback,
base::OnceClosure on_cancel_callback,
base::OnceClosure on_close_callback) override;
void OnSigninScreenPrefServiceInitialized(PrefService* prefs) override;
void OnActiveUserPrefServiceChanged(PrefService* prefs) override;
void OnSessionStateChanged(session_manager::SessionState state) override;
AccessibilityEventRewriter* GetAccessibilityEventRewriterForTest();
SwitchAccessMenuBubbleController* GetSwitchAccessBubbleControllerForTest() {
return switch_access_bubble_controller_.get();
}
void DisableSwitchAccessDisableConfirmationDialogTesting() override;
SelectToSpeakMenuBubbleController*
GetSelectToSpeakMenuBubbleControllerForTest() {
return select_to_speak_bubble_controller_.get();
}
AccessibilityConfirmationDialog* GetConfirmationDialogForTest() {
return confirmation_dialog_.get();
}
bool enable_chromevox_volume_slide_gesture() {
return enable_chromevox_volume_slide_gesture_;
}
DictationNudgeController* GetDictationNudgeControllerForTest() {
return dictation_nudge_controller_.get();
}
int dictation_soda_download_progress() {
return dictation_soda_download_progress_;
}
DictationBubbleController* GetDictationBubbleControllerForTest();
private:
void CreateAccessibilityFeatures();
void OnFeatureChanged(A11yFeatureType feature);
void OnTabletModeStarted() override;
void OnTabletModeEnded() override;
void ObservePrefs(PrefService* prefs);
void UpdateFeatureFromPref(A11yFeatureType feature);
void UpdateAutoclickDelayFromPref();
void UpdateAutoclickEventTypeFromPref();
void UpdateAutoclickRevertToLeftClickFromPref();
void UpdateAutoclickStabilizePositionFromPref();
void UpdateAutoclickMovementThresholdFromPref();
void UpdateAutoclickMenuPositionFromPref();
void UpdateFloatingMenuPositionFromPref();
void UpdateLargeCursorFromPref();
void UpdateLiveCaptionFromPref();
void UpdateCursorColorFromPrefs();
void UpdateColorFilteringFromPrefs();
void UpdateSwitchAccessKeyCodesFromPref(SwitchAccessCommand command);
void UpdateSwitchAccessAutoScanEnabledFromPref();
void UpdateSwitchAccessAutoScanSpeedFromPref();
void UpdateSwitchAccessAutoScanKeyboardSpeedFromPref();
void UpdateSwitchAccessPointScanSpeedFromPref();
void UpdateAccessibilityHighlightingFromPrefs();
void UpdateShortcutsEnabledFromPref();
void UpdateTabletModeShelfNavigationButtonsFromPref();
void SwitchAccessDisableDialogClosed(bool disable_dialog_accepted);
void MaybeCreateSelectToSpeakEventHandler();
void ActivateSwitchAccess();
void DeactivateSwitchAccess();
void SyncSwitchAccessPrefsToSignInProfile();
void UpdateKeyCodesAfterSwitchAccessEnabled();
int dictation_soda_download_progress_ = 0;
raw_ptr<AccessibilityControllerClient, ExperimentalAsh> client_ = nullptr;
std::unique_ptr<Feature> features_[kA11yFeatureTypeCount];
base::TimeDelta autoclick_delay_;
int large_cursor_size_in_dip_ = kDefaultLargeCursorSize;
bool dictation_active_ = false;
bool shortcuts_enabled_ = true;
bool tablet_mode_shelf_navigation_buttons_enabled_ = false;
SelectToSpeakState select_to_speak_state_ =
SelectToSpeakState::kSelectToSpeakStateInactive;
std::unique_ptr<SelectToSpeakEventHandler> select_to_speak_event_handler_;
raw_ptr<SelectToSpeakEventHandlerDelegate, ExperimentalAsh>
select_to_speak_event_handler_delegate_ = nullptr;
std::unique_ptr<SelectToSpeakMenuBubbleController>
select_to_speak_bubble_controller_;
std::vector<int> switch_access_keys_to_capture_;
std::unique_ptr<SwitchAccessMenuBubbleController>
switch_access_bubble_controller_;
raw_ptr<AccessibilityEventRewriter, ExperimentalAsh>
accessibility_event_rewriter_ = nullptr;
bool no_switch_access_disable_confirmation_dialog_for_testing_ = false;
bool switch_access_disable_dialog_showing_ = false;
bool skip_switch_access_notification_ = false;
std::unique_ptr<AccessibilityHighlightController>
accessibility_highlight_controller_;
std::unique_ptr<FloatingAccessibilityController> floating_menu_controller_;
bool always_show_floating_menu_when_enabled_ = false;
std::unique_ptr<PointScanController> point_scan_controller_;
std::unique_ptr<ScopedBacklightsForcedOff> scoped_backlights_forced_off_;
std::unique_ptr<DictationNudgeController> dictation_nudge_controller_;
std::unique_ptr<DictationBubbleController> dictation_bubble_controller_;
bool enable_chromevox_volume_slide_gesture_ = false;
base::ObserverList<AccessibilityObserver> observers_;
raw_ptr<PrefService, ExperimentalAsh> active_user_prefs_ = nullptr;
std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
base::WeakPtr<AccessibilityConfirmationDialog> confirmation_dialog_;
base::WeakPtrFactory<AccessibilityControllerImpl> weak_ptr_factory_{this};
};
}
#endif