blob: 95febe9509bb99efb757ce15f1baacd2263b8c8a [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()
61 : BrowserAccessibilityState(),
dmazzonidea5ba62015-02-03 19:27:2462 disable_hot_tracking_(false) {
[email protected]1e558fa2014-02-12 23:28:5263 ResetAccessibilityModeValue();
[email protected]882db442012-12-04 16:37:5464
65 // We need to AddRef() the leaky singleton so that Bind doesn't
[email protected]3c17ae742012-10-24 17:37:2666 // delete it prematurely.
67 AddRef();
sebmarchand41f774b2017-05-23 21:50:2168
Doug Turneraff275f2017-08-15 22:40:3569 // Hook ourselves up to observe ax mode changes.
70 ui::AXPlatformNode::AddAXModeObserver(this);
71
Dominic Mazzoni190a6cd2018-09-26 11:24:0872 // Let each platform do its own initialization.
73 PlatformInitialize();
74
Stephen McGruera73dfdb2018-11-14 18:19:4775#if defined(OS_WIN) || defined(OS_ANDROID)
sebmarchand41f774b2017-05-23 21:50:2176 // The delay is necessary because assistive technology sometimes isn't
77 // detected until after the user interacts in some way, so a reasonable delay
78 // gives us better numbers.
79 base::PostDelayedTaskWithTraits(
Gabriel Charetteb10aeeb2018-07-26 20:15:0080 FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
[email protected]30fdb362013-01-09 02:33:2781 base::Bind(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
dmazzoni368ea132016-12-20 08:22:4282 base::TimeDelta::FromSeconds(ACCESSIBILITY_HISTOGRAM_DELAY_SECS));
sebmarchand41f774b2017-05-23 21:50:2183#else
Stephen McGruera73dfdb2018-11-14 18:19:4784 // On MacOS, UpdateHistograms should be called on the UI thread because it
85 // needs to be able to access PrefService.
Eric Seckler8652dcd52018-09-20 10:42:2886 base::PostDelayedTaskWithTraits(
87 FROM_HERE, {BrowserThread::UI},
tzik4fea24af2017-08-23 11:41:4788 base::BindOnce(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
sebmarchand41f774b2017-05-23 21:50:2189 base::TimeDelta::FromSeconds(ACCESSIBILITY_HISTOGRAM_DELAY_SECS));
90#endif
[email protected]fa4f91682012-02-21 19:53:2691}
92
93BrowserAccessibilityStateImpl::~BrowserAccessibilityStateImpl() {
Doug Turneraff275f2017-08-15 22:40:3594 // Remove ourselves from the AXMode global observer list.
95 ui::AXPlatformNode::RemoveAXModeObserver(this);
[email protected]fa4f91682012-02-21 19:53:2696}
97
98void BrowserAccessibilityStateImpl::OnScreenReaderDetected() {
[email protected]479278702014-08-11 20:32:0999 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]bfa71242014-03-27 21:10:24100 switches::kDisableRendererAccessibility)) {
101 return;
102 }
103 EnableAccessibility();
[email protected]fa4f91682012-02-21 19:53:26104}
105
[email protected]df376972013-05-03 21:45:03106void BrowserAccessibilityStateImpl::EnableAccessibility() {
Doug Turner63f3c7b2017-07-29 05:10:01107 AddAccessibilityModeFlags(ui::kAXModeComplete);
[email protected]fa4f91682012-02-21 19:53:26108}
109
[email protected]df376972013-05-03 21:45:03110void BrowserAccessibilityStateImpl::DisableAccessibility() {
[email protected]1e558fa2014-02-12 23:28:52111 ResetAccessibilityMode();
112}
113
James Wallace-Leeeafc94cb92018-07-23 21:35:09114bool BrowserAccessibilityStateImpl::IsRendererAccessibilityEnabled() {
115 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
116 switches::kDisableRendererAccessibility);
117}
118
[email protected]1e558fa2014-02-12 23:28:52119void BrowserAccessibilityStateImpl::ResetAccessibilityModeValue() {
Doug Turner63f3c7b2017-07-29 05:10:01120 accessibility_mode_ = ui::AXMode();
[email protected]479278702014-08-11 20:32:09121 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]1e558fa2014-02-12 23:28:52122 switches::kForceRendererAccessibility)) {
Doug Turner63f3c7b2017-07-29 05:10:01123 accessibility_mode_ = ui::kAXModeComplete;
[email protected]1e558fa2014-02-12 23:28:52124 }
125}
126
127void BrowserAccessibilityStateImpl::ResetAccessibilityMode() {
128 ResetAccessibilityModeValue();
129
[email protected]95640212014-07-26 18:14:30130 std::vector<WebContentsImpl*> web_contents_vector =
131 WebContentsImpl::GetAllWebContents();
132 for (size_t i = 0; i < web_contents_vector.size(); ++i)
James Wallace-Leeeafc94cb92018-07-23 21:35:09133 web_contents_vector[i]->SetAccessibilityMode(accessibility_mode_);
[email protected]df376972013-05-03 21:45:03134}
135
[email protected]fa4f91682012-02-21 19:53:26136bool BrowserAccessibilityStateImpl::IsAccessibleBrowser() {
Doug Turner63f3c7b2017-07-29 05:10:01137 return accessibility_mode_ == ui::kAXModeComplete;
[email protected]fa4f91682012-02-21 19:53:26138}
139
[email protected]89430152012-12-03 19:18:56140void BrowserAccessibilityStateImpl::AddHistogramCallback(
141 base::Closure callback) {
Tommy Nyquist4b749d02018-03-20 21:46:29142 histogram_callbacks_.push_back(std::move(callback));
[email protected]89430152012-12-03 19:18:56143}
144
[email protected]30fdb362013-01-09 02:33:27145void BrowserAccessibilityStateImpl::UpdateHistogramsForTesting() {
146 UpdateHistograms();
147}
148
149void BrowserAccessibilityStateImpl::UpdateHistograms() {
[email protected]18df7362012-10-24 01:29:40150 UpdatePlatformSpecificHistograms();
151
[email protected]89430152012-12-03 19:18:56152 for (size_t i = 0; i < histogram_callbacks_.size(); ++i)
153 histogram_callbacks_[i].Run();
154
dmazzoni368ea132016-12-20 08:22:42155 // TODO(dmazzoni): remove this in M59 since Accessibility.ModeFlag
156 // supercedes it. http://crbug.com/672205
[email protected]18df7362012-10-24 01:29:40157 UMA_HISTOGRAM_BOOLEAN("Accessibility.State", IsAccessibleBrowser());
dmazzoni368ea132016-12-20 08:22:42158
[email protected]18df7362012-10-24 01:29:40159 UMA_HISTOGRAM_BOOLEAN("Accessibility.InvertedColors",
mlamouri20bb4c4a2015-07-08 14:30:22160 color_utils::IsInvertedColorScheme());
[email protected]18df7362012-10-24 01:29:40161 UMA_HISTOGRAM_BOOLEAN("Accessibility.ManuallyEnabled",
[email protected]479278702014-08-11 20:32:09162 base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]18df7362012-10-24 01:29:40163 switches::kForceRendererAccessibility));
[email protected]fa4f91682012-02-21 19:53:26164}
[email protected]e2fa1cca42012-08-22 14:07:27165
Doug Turneraff275f2017-08-15 22:40:35166void BrowserAccessibilityStateImpl::OnAXModeAdded(ui::AXMode mode) {
167 AddAccessibilityModeFlags(mode);
168}
169
James Wallace-Leeeafc94cb92018-07-23 21:35:09170ui::AXMode BrowserAccessibilityStateImpl::GetAccessibilityMode() const {
171 return accessibility_mode_;
172}
173
Stephen McGruera73dfdb2018-11-14 18:19:47174#if !defined(OS_ANDROID) && !defined(OS_WIN) && !defined(OS_MACOSX)
Dominic Mazzoni190a6cd2018-09-26 11:24:08175void BrowserAccessibilityStateImpl::PlatformInitialize() {}
176
[email protected]18df7362012-10-24 01:29:40177void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
178}
179#endif
180
Doug Turner63f3c7b2017-07-29 05:10:01181void BrowserAccessibilityStateImpl::AddAccessibilityModeFlags(ui::AXMode mode) {
[email protected]479278702014-08-11 20:32:09182 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]1e558fa2014-02-12 23:28:52183 switches::kDisableRendererAccessibility)) {
[email protected]df376972013-05-03 21:45:03184 return;
[email protected]1e558fa2014-02-12 23:28:52185 }
[email protected]df376972013-05-03 21:45:03186
Doug Turner63f3c7b2017-07-29 05:10:01187 ui::AXMode previous_mode = accessibility_mode_;
dmazzonidd3d51a72016-12-14 18:41:01188 accessibility_mode_ |= mode;
dmazzoni368ea132016-12-20 08:22:42189 if (accessibility_mode_ == previous_mode)
190 return;
191
192 // Retrieve only newly added modes for the purposes of logging.
dougtcd3dad732017-03-14 03:26:23193 int new_mode_flags = mode.mode() & (~previous_mode.mode());
Doug Turner63f3c7b2017-07-29 05:10:01194 if (new_mode_flags & ui::AXMode::kNativeAPIs)
dougtcd3dad732017-03-14 03:26:23195 RecordNewAccessibilityModeFlags(UMA_AX_MODE_NATIVE_APIS);
Doug Turner63f3c7b2017-07-29 05:10:01196 if (new_mode_flags & ui::AXMode::kWebContents)
dougtcd3dad732017-03-14 03:26:23197 RecordNewAccessibilityModeFlags(UMA_AX_MODE_WEB_CONTENTS);
Doug Turner63f3c7b2017-07-29 05:10:01198 if (new_mode_flags & ui::AXMode::kInlineTextBoxes)
dougtcd3dad732017-03-14 03:26:23199 RecordNewAccessibilityModeFlags(UMA_AX_MODE_INLINE_TEXT_BOXES);
Doug Turner63f3c7b2017-07-29 05:10:01200 if (new_mode_flags & ui::AXMode::kScreenReader)
dougtcd3dad732017-03-14 03:26:23201 RecordNewAccessibilityModeFlags(UMA_AX_MODE_SCREEN_READER);
Doug Turner63f3c7b2017-07-29 05:10:01202 if (new_mode_flags & ui::AXMode::kHTML)
dougtcd3dad732017-03-14 03:26:23203 RecordNewAccessibilityModeFlags(UMA_AX_MODE_HTML);
dmazzoni368ea132016-12-20 08:22:42204
dmazzonidd3d51a72016-12-14 18:41:01205 std::vector<WebContentsImpl*> web_contents_vector =
206 WebContentsImpl::GetAllWebContents();
207 for (size_t i = 0; i < web_contents_vector.size(); ++i)
208 web_contents_vector[i]->AddAccessibilityMode(accessibility_mode_);
[email protected]1e558fa2014-02-12 23:28:52209}
210
dmazzonidd3d51a72016-12-14 18:41:01211void BrowserAccessibilityStateImpl::RemoveAccessibilityModeFlags(
Doug Turner63f3c7b2017-07-29 05:10:01212 ui::AXMode mode) {
[email protected]479278702014-08-11 20:32:09213 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]1e558fa2014-02-12 23:28:52214 switches::kForceRendererAccessibility) &&
Doug Turner63f3c7b2017-07-29 05:10:01215 mode == ui::kAXModeComplete) {
[email protected]1e558fa2014-02-12 23:28:52216 return;
217 }
218
dougtcd3dad732017-03-14 03:26:23219 int raw_flags =
220 accessibility_mode_.mode() ^ (mode.mode() & accessibility_mode_.mode());
221 accessibility_mode_ = raw_flags;
222
[email protected]95640212014-07-26 18:14:30223 std::vector<WebContentsImpl*> web_contents_vector =
224 WebContentsImpl::GetAllWebContents();
dmazzonidd3d51a72016-12-14 18:41:01225 for (size_t i = 0; i < web_contents_vector.size(); ++i)
James Wallace-Leeeafc94cb92018-07-23 21:35:09226 web_contents_vector[i]->SetAccessibilityMode(accessibility_mode_);
[email protected]e2fa1cca42012-08-22 14:07:27227}
[email protected]e6b34872012-10-24 20:51:32228
229} // namespace content