blob: 01b8057df34d9e84ed458fe18bf43d48a58bdce1 [file] [log] [blame]
[email protected]fa4f91682012-02-21 19:53:261// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/accessibility/browser_accessibility_state_impl.h"
6
avib7348942015-12-25 20:57:107#include <stddef.h>
8
Sebastien Marchandf8cbfab2019-01-25 16:02:309#include "base/bind.h"
[email protected]3e3c4522012-04-13 21:16:2910#include "base/command_line.h"
asvitkine30330812016-08-30 04:01:0811#include "base/metrics/histogram_macros.h"
Gabriel Charette44db1422018-08-06 11:19:3312#include "base/task/post_task.h"
avib7348942015-12-25 20:57:1013#include "build/build_config.h"
[email protected]df376972013-05-03 21:45:0314#include "content/browser/renderer_host/render_widget_host_impl.h"
[email protected]95640212014-07-26 18:14:3015#include "content/browser/web_contents/web_contents_impl.h"
Eric Seckler8652dcd52018-09-20 10:42:2816#include "content/public/browser/browser_task_traits.h"
[email protected]18df7362012-10-24 01:29:4017#include "content/public/browser/browser_thread.h"
[email protected]3e3c4522012-04-13 21:16:2918#include "content/public/common/content_switches.h"
Doug Turneraff275f2017-08-15 22:40:3519#include "ui/accessibility/platform/ax_platform_node.h"
mlamouri20bb4c4a2015-07-08 14:30:2220#include "ui/gfx/color_utils.h"
[email protected]fa4f91682012-02-21 19:53:2621
[email protected]e6b34872012-10-24 20:51:3222namespace content {
23
dmazzoni368ea132016-12-20 08:22:4224// IMPORTANT!
25// These values are written to logs. Do not renumber or delete
26// existing items; add new entries to the end of the list.
27enum ModeFlagHistogramValue {
dougtcd3dad732017-03-14 03:26:2328 UMA_AX_MODE_NATIVE_APIS = 0,
29 UMA_AX_MODE_WEB_CONTENTS = 1,
30 UMA_AX_MODE_INLINE_TEXT_BOXES = 2,
31 UMA_AX_MODE_SCREEN_READER = 3,
32 UMA_AX_MODE_HTML = 4,
dmazzoni368ea132016-12-20 08:22:4233
34 // This must always be the last enum. It's okay for its value to
35 // increase, but none of the other enum values may change.
dougtcd3dad732017-03-14 03:26:2336 UMA_AX_MODE_MAX
dmazzoni368ea132016-12-20 08:22:4237};
38
39// Record a histograms for an accessibility mode when it's enabled.
40void RecordNewAccessibilityModeFlags(ModeFlagHistogramValue mode_flag) {
dougtcd3dad732017-03-14 03:26:2341 UMA_HISTOGRAM_ENUMERATION("Accessibility.ModeFlag", mode_flag,
42 UMA_AX_MODE_MAX);
dmazzoni368ea132016-12-20 08:22:4243}
44
[email protected]fa4f91682012-02-21 19:53:2645// Update the accessibility histogram 45 seconds after initialization.
dmazzoni368ea132016-12-20 08:22:4246static const int ACCESSIBILITY_HISTOGRAM_DELAY_SECS = 45;
[email protected]fa4f91682012-02-21 19:53:2647
48// static
49BrowserAccessibilityState* BrowserAccessibilityState::GetInstance() {
50 return BrowserAccessibilityStateImpl::GetInstance();
51}
52
53// static
54BrowserAccessibilityStateImpl* BrowserAccessibilityStateImpl::GetInstance() {
olli.raula36aa8be2015-09-10 11:14:2255 return base::Singleton<
56 BrowserAccessibilityStateImpl,
57 base::LeakySingletonTraits<BrowserAccessibilityStateImpl>>::get();
[email protected]fa4f91682012-02-21 19:53:2658}
59
60BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl()
Aran Gilman0bdeadbf2019-03-05 01:15:4161 : BrowserAccessibilityState(), disable_hot_tracking_(false) {
[email protected]1e558fa2014-02-12 23:28:5262 ResetAccessibilityModeValue();
[email protected]882db442012-12-04 16:37:5463
64 // We need to AddRef() the leaky singleton so that Bind doesn't
[email protected]3c17ae742012-10-24 17:37:2665 // delete it prematurely.
66 AddRef();
sebmarchand41f774b2017-05-23 21:50:2167
Doug Turneraff275f2017-08-15 22:40:3568 // Hook ourselves up to observe ax mode changes.
69 ui::AXPlatformNode::AddAXModeObserver(this);
70
Dominic Mazzoni190a6cd2018-09-26 11:24:0871 // Let each platform do its own initialization.
72 PlatformInitialize();
73
Stephen McGruera73dfdb2018-11-14 18:19:4774#if defined(OS_WIN) || defined(OS_ANDROID)
sebmarchand41f774b2017-05-23 21:50:2175 // The delay is necessary because assistive technology sometimes isn't
76 // detected until after the user interacts in some way, so a reasonable delay
77 // gives us better numbers.
78 base::PostDelayedTaskWithTraits(
Gabriel Charetteb10aeeb2018-07-26 20:15:0079 FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
kylechar9bfa6552019-02-25 22:48:4680 base::BindOnce(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
dmazzoni368ea132016-12-20 08:22:4281 base::TimeDelta::FromSeconds(ACCESSIBILITY_HISTOGRAM_DELAY_SECS));
sebmarchand41f774b2017-05-23 21:50:2182#else
Stephen McGruera73dfdb2018-11-14 18:19:4783 // On MacOS, UpdateHistograms should be called on the UI thread because it
84 // needs to be able to access PrefService.
Eric Seckler8652dcd52018-09-20 10:42:2885 base::PostDelayedTaskWithTraits(
86 FROM_HERE, {BrowserThread::UI},
tzik4fea24af2017-08-23 11:41:4787 base::BindOnce(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
sebmarchand41f774b2017-05-23 21:50:2188 base::TimeDelta::FromSeconds(ACCESSIBILITY_HISTOGRAM_DELAY_SECS));
89#endif
[email protected]fa4f91682012-02-21 19:53:2690}
91
92BrowserAccessibilityStateImpl::~BrowserAccessibilityStateImpl() {
Doug Turneraff275f2017-08-15 22:40:3593 // Remove ourselves from the AXMode global observer list.
94 ui::AXPlatformNode::RemoveAXModeObserver(this);
[email protected]fa4f91682012-02-21 19:53:2695}
96
97void BrowserAccessibilityStateImpl::OnScreenReaderDetected() {
[email protected]479278702014-08-11 20:32:0998 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]bfa71242014-03-27 21:10:2499 switches::kDisableRendererAccessibility)) {
100 return;
101 }
102 EnableAccessibility();
[email protected]fa4f91682012-02-21 19:53:26103}
104
[email protected]df376972013-05-03 21:45:03105void BrowserAccessibilityStateImpl::EnableAccessibility() {
Doug Turner63f3c7b2017-07-29 05:10:01106 AddAccessibilityModeFlags(ui::kAXModeComplete);
[email protected]fa4f91682012-02-21 19:53:26107}
108
[email protected]df376972013-05-03 21:45:03109void BrowserAccessibilityStateImpl::DisableAccessibility() {
[email protected]1e558fa2014-02-12 23:28:52110 ResetAccessibilityMode();
111}
112
James Wallace-Leeeafc94cb92018-07-23 21:35:09113bool BrowserAccessibilityStateImpl::IsRendererAccessibilityEnabled() {
114 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
115 switches::kDisableRendererAccessibility);
116}
117
[email protected]1e558fa2014-02-12 23:28:52118void BrowserAccessibilityStateImpl::ResetAccessibilityModeValue() {
Doug Turner63f3c7b2017-07-29 05:10:01119 accessibility_mode_ = ui::AXMode();
[email protected]479278702014-08-11 20:32:09120 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]1e558fa2014-02-12 23:28:52121 switches::kForceRendererAccessibility)) {
Doug Turner63f3c7b2017-07-29 05:10:01122 accessibility_mode_ = ui::kAXModeComplete;
[email protected]1e558fa2014-02-12 23:28:52123 }
124}
125
126void BrowserAccessibilityStateImpl::ResetAccessibilityMode() {
127 ResetAccessibilityModeValue();
128
[email protected]95640212014-07-26 18:14:30129 std::vector<WebContentsImpl*> web_contents_vector =
130 WebContentsImpl::GetAllWebContents();
131 for (size_t i = 0; i < web_contents_vector.size(); ++i)
James Wallace-Leeeafc94cb92018-07-23 21:35:09132 web_contents_vector[i]->SetAccessibilityMode(accessibility_mode_);
[email protected]df376972013-05-03 21:45:03133}
134
[email protected]fa4f91682012-02-21 19:53:26135bool BrowserAccessibilityStateImpl::IsAccessibleBrowser() {
Doug Turner63f3c7b2017-07-29 05:10:01136 return accessibility_mode_ == ui::kAXModeComplete;
[email protected]fa4f91682012-02-21 19:53:26137}
138
[email protected]89430152012-12-03 19:18:56139void BrowserAccessibilityStateImpl::AddHistogramCallback(
140 base::Closure callback) {
Tommy Nyquist4b749d02018-03-20 21:46:29141 histogram_callbacks_.push_back(std::move(callback));
[email protected]89430152012-12-03 19:18:56142}
143
[email protected]30fdb362013-01-09 02:33:27144void BrowserAccessibilityStateImpl::UpdateHistogramsForTesting() {
145 UpdateHistograms();
146}
147
148void BrowserAccessibilityStateImpl::UpdateHistograms() {
[email protected]18df7362012-10-24 01:29:40149 UpdatePlatformSpecificHistograms();
150
[email protected]89430152012-12-03 19:18:56151 for (size_t i = 0; i < histogram_callbacks_.size(); ++i)
152 histogram_callbacks_[i].Run();
153
dmazzoni368ea132016-12-20 08:22:42154 // TODO(dmazzoni): remove this in M59 since Accessibility.ModeFlag
155 // supercedes it. http://crbug.com/672205
[email protected]18df7362012-10-24 01:29:40156 UMA_HISTOGRAM_BOOLEAN("Accessibility.State", IsAccessibleBrowser());
dmazzoni368ea132016-12-20 08:22:42157
[email protected]18df7362012-10-24 01:29:40158 UMA_HISTOGRAM_BOOLEAN("Accessibility.InvertedColors",
mlamouri20bb4c4a2015-07-08 14:30:22159 color_utils::IsInvertedColorScheme());
[email protected]18df7362012-10-24 01:29:40160 UMA_HISTOGRAM_BOOLEAN("Accessibility.ManuallyEnabled",
[email protected]479278702014-08-11 20:32:09161 base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]18df7362012-10-24 01:29:40162 switches::kForceRendererAccessibility));
[email protected]fa4f91682012-02-21 19:53:26163}
[email protected]e2fa1cca42012-08-22 14:07:27164
Doug Turneraff275f2017-08-15 22:40:35165void BrowserAccessibilityStateImpl::OnAXModeAdded(ui::AXMode mode) {
166 AddAccessibilityModeFlags(mode);
167}
168
James Wallace-Leeeafc94cb92018-07-23 21:35:09169ui::AXMode BrowserAccessibilityStateImpl::GetAccessibilityMode() const {
170 return accessibility_mode_;
171}
172
Stephen McGruera73dfdb2018-11-14 18:19:47173#if !defined(OS_ANDROID) && !defined(OS_WIN) && !defined(OS_MACOSX)
Dominic Mazzoni190a6cd2018-09-26 11:24:08174void BrowserAccessibilityStateImpl::PlatformInitialize() {}
175
Aran Gilman0bdeadbf2019-03-05 01:15:41176void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {}
[email protected]18df7362012-10-24 01:29:40177#endif
178
Doug Turner63f3c7b2017-07-29 05:10:01179void BrowserAccessibilityStateImpl::AddAccessibilityModeFlags(ui::AXMode mode) {
[email protected]479278702014-08-11 20:32:09180 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]1e558fa2014-02-12 23:28:52181 switches::kDisableRendererAccessibility)) {
[email protected]df376972013-05-03 21:45:03182 return;
[email protected]1e558fa2014-02-12 23:28:52183 }
[email protected]df376972013-05-03 21:45:03184
Doug Turner63f3c7b2017-07-29 05:10:01185 ui::AXMode previous_mode = accessibility_mode_;
dmazzonidd3d51a72016-12-14 18:41:01186 accessibility_mode_ |= mode;
dmazzoni368ea132016-12-20 08:22:42187 if (accessibility_mode_ == previous_mode)
188 return;
189
190 // Retrieve only newly added modes for the purposes of logging.
dougtcd3dad732017-03-14 03:26:23191 int new_mode_flags = mode.mode() & (~previous_mode.mode());
Doug Turner63f3c7b2017-07-29 05:10:01192 if (new_mode_flags & ui::AXMode::kNativeAPIs)
dougtcd3dad732017-03-14 03:26:23193 RecordNewAccessibilityModeFlags(UMA_AX_MODE_NATIVE_APIS);
Doug Turner63f3c7b2017-07-29 05:10:01194 if (new_mode_flags & ui::AXMode::kWebContents)
dougtcd3dad732017-03-14 03:26:23195 RecordNewAccessibilityModeFlags(UMA_AX_MODE_WEB_CONTENTS);
Doug Turner63f3c7b2017-07-29 05:10:01196 if (new_mode_flags & ui::AXMode::kInlineTextBoxes)
dougtcd3dad732017-03-14 03:26:23197 RecordNewAccessibilityModeFlags(UMA_AX_MODE_INLINE_TEXT_BOXES);
Doug Turner63f3c7b2017-07-29 05:10:01198 if (new_mode_flags & ui::AXMode::kScreenReader)
dougtcd3dad732017-03-14 03:26:23199 RecordNewAccessibilityModeFlags(UMA_AX_MODE_SCREEN_READER);
Doug Turner63f3c7b2017-07-29 05:10:01200 if (new_mode_flags & ui::AXMode::kHTML)
dougtcd3dad732017-03-14 03:26:23201 RecordNewAccessibilityModeFlags(UMA_AX_MODE_HTML);
dmazzoni368ea132016-12-20 08:22:42202
dmazzonidd3d51a72016-12-14 18:41:01203 std::vector<WebContentsImpl*> web_contents_vector =
204 WebContentsImpl::GetAllWebContents();
205 for (size_t i = 0; i < web_contents_vector.size(); ++i)
206 web_contents_vector[i]->AddAccessibilityMode(accessibility_mode_);
[email protected]1e558fa2014-02-12 23:28:52207}
208
dmazzonidd3d51a72016-12-14 18:41:01209void BrowserAccessibilityStateImpl::RemoveAccessibilityModeFlags(
Doug Turner63f3c7b2017-07-29 05:10:01210 ui::AXMode mode) {
[email protected]479278702014-08-11 20:32:09211 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]1e558fa2014-02-12 23:28:52212 switches::kForceRendererAccessibility) &&
Doug Turner63f3c7b2017-07-29 05:10:01213 mode == ui::kAXModeComplete) {
[email protected]1e558fa2014-02-12 23:28:52214 return;
215 }
216
dougtcd3dad732017-03-14 03:26:23217 int raw_flags =
218 accessibility_mode_.mode() ^ (mode.mode() & accessibility_mode_.mode());
219 accessibility_mode_ = raw_flags;
220
[email protected]95640212014-07-26 18:14:30221 std::vector<WebContentsImpl*> web_contents_vector =
222 WebContentsImpl::GetAllWebContents();
dmazzonidd3d51a72016-12-14 18:41:01223 for (size_t i = 0; i < web_contents_vector.size(); ++i)
James Wallace-Leeeafc94cb92018-07-23 21:35:09224 web_contents_vector[i]->SetAccessibilityMode(accessibility_mode_);
[email protected]e2fa1cca42012-08-22 14:07:27225}
[email protected]e6b34872012-10-24 20:51:32226
227} // namespace content