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
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_STATE_IMPL_H_
#define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_STATE_IMPL_H_
#include <vector>
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/metrics/metrics_provider.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_accessibility_state.h"
#include "ui/accessibility/ax_mode.h"
#include "ui/accessibility/ax_mode_observer.h"
namespace content {
struct FocusedNodeDetails;
// The BrowserAccessibilityState class is used to determine if Chrome should be
// customized for users with assistive technology, such as screen readers. We
// modify the behavior of certain user interfaces to provide a better experience
// for screen reader users. The way we detect a screen reader program is
// different for each platform.
//
// Screen Reader Detection
// (1) On windows many screen reader detection mechinisms will give false
// positives like relying on the SPI_GETSCREENREADER system parameter. In Chrome
// we attempt to dynamically detect a MSAA client screen reader by calling
// NotifiyWinEvent in NativeWidgetWin with a custom ID and wait to see if the ID
// is requested by a subsequent call to WM_GETOBJECT.
// (2) On mac we detect dynamically if VoiceOver is running. We rely upon the
// undocumented accessibility attribute @"AXEnhancedUserInterface" which is set
// when VoiceOver is launched and unset when VoiceOver is closed. This is an
// improvement over reading defaults preference values (which has no callback
// mechanism).
class CONTENT_EXPORT BrowserAccessibilityStateImpl
: public BrowserAccessibilityState,
public ui::AXModeObserver {
public:
BrowserAccessibilityStateImpl();
BrowserAccessibilityStateImpl(const BrowserAccessibilityStateImpl&) = delete;
BrowserAccessibilityStateImpl& operator=(
const BrowserAccessibilityStateImpl&) = delete;
~BrowserAccessibilityStateImpl() override;
static BrowserAccessibilityStateImpl* GetInstance();
// This needs to be called explicitly by content::BrowserMainLoop during
// initialization, in order to schedule tasks that need to be done, but
// don't need to block the main thread.
//
// This is called explicitly and not automatically just by
// instantiating this class so that tests can use
// BrowserAccessibilityState without worrying about threading.
virtual void InitBackgroundTasks();
// BrowserAccessibilityState implementation.
void EnableAccessibility() override;
void DisableAccessibility() override;
bool IsRendererAccessibilityEnabled() override;
ui::AXMode GetAccessibilityMode() override;
void AddAccessibilityModeFlags(ui::AXMode mode) override;
void RemoveAccessibilityModeFlags(ui::AXMode mode) override;
void ResetAccessibilityMode() override;
void OnScreenReaderDetected() override;
bool IsAccessibleBrowser() override;
void AddUIThreadHistogramCallback(base::OnceClosure callback) override;
void AddOtherThreadHistogramCallback(base::OnceClosure callback) override;
void UpdateUniqueUserHistograms() override;
void UpdateHistogramsForTesting() override;
void SetCaretBrowsingState(bool enabled) override;
#if BUILDFLAG(IS_ANDROID)
void SetImageLabelsModeForProfile(bool enabled,
BrowserContext* profile) override;
#endif
base::CallbackListSubscription RegisterFocusChangedCallback(
FocusChangedCallback callback) override;
// Returns whether caret browsing is enabled for the most recently
// used profile.
bool IsCaretBrowsingEnabled() const;
// AXModeObserver
void OnAXModeAdded(ui::AXMode mode) override;
// 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.
void OnUserInputEvent();
void OnAccessibilityApiUsage();
// Accessibility objects can have the "hot tracked" state set when
// the mouse is hovering over them, but this makes tests flaky because
// the test behaves differently when the mouse happens to be over an
// element. This is a global switch to not use the "hot tracked" state
// in a test.
void set_disable_hot_tracking_for_testing(bool disable_hot_tracking) {
disable_hot_tracking_ = disable_hot_tracking;
}
bool disable_hot_tracking_for_testing() const {
return disable_hot_tracking_;
}
// Calls InitBackgroundTasks with short delays for scheduled tasks,
// and then calls the given completion callback when done.
void CallInitBackgroundTasksForTesting(base::RepeatingClosure done_callback);
// Notifies listeners that the focused element changed inside a WebContents.
void OnFocusChangedInPage(const FocusedNodeDetails& details);
protected:
// Called a short while after startup to allow time for the accessibility
// state to be determined. Updates histograms with the current state.
// Two variants - one for things that must be run on the UI thread, and
// another that can be run on another thread.
virtual void UpdateHistogramsOnUIThread();
virtual void UpdateHistogramsOnOtherThread();
private:
// Resets accessibility_mode_ to the default value.
void ResetAccessibilityModeValue();
void OnOtherThreadDone();
void UpdateAccessibilityActivityTask();
ui::AXMode accessibility_mode_;
base::TimeDelta histogram_delay_;
std::vector<base::OnceClosure> ui_thread_histogram_callbacks_;
std::vector<base::OnceClosure> other_thread_histogram_callbacks_;
bool ui_thread_done_ = false;
bool other_thread_done_ = false;
base::RepeatingClosure background_thread_done_callback_;
// Whether there is a pending task to run UpdateAccessibilityActivityTask.
bool accessibility_update_task_pending_ = false;
// Whether the force-renderer-accessibility flag is enabled.
// Cached here so that we don't have to check base::CommandLine in
// a function that's called frequently.
bool force_renderer_accessibility_ = false;
// Disable hot tracking, i.e. hover state - needed just to avoid flaky tests.
bool disable_hot_tracking_ = false;
// Keeps track of whether caret browsing is enabled for the most
// recently used profile.
bool caret_browsing_enabled_ = false;
// The time of the first user input event; if we receive multiple
// user input events within a 30-second period and no
base::TimeTicks first_user_input_event_time_;
int user_input_event_count_ = 0;
// The time accessibility became active, used to calculate active time.
base::TimeTicks accessibility_active_start_time_;
// The time accessibility became inactive, used to calculate inactive time.
base::TimeTicks accessibility_inactive_start_time_;
// The last time accessibility was active, used to calculate active time.
base::TimeTicks accessibility_last_usage_time_;
// The time accessibility was enabled, for statistics.
base::TimeTicks accessibility_enabled_time_;
// The time accessibility was auto-disabled, for statistics.
base::TimeTicks accessibility_disabled_time_;
base::RepeatingCallbackList<void(const FocusedNodeDetails&)>
focus_changed_callbacks_;
};
} // namespace content
#endif // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_STATE_IMPL_H_
|