blob: 9a9fc3b0db86cf0f9535e2fc44d5e69c61784ea5 [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
[email protected]3e3c4522012-04-13 21:16:299#include "base/command_line.h"
asvitkine30330812016-08-30 04:01:0810#include "base/metrics/histogram_macros.h"
sebmarchand41f774b2017-05-23 21:50:2111#include "base/task_scheduler/post_task.h"
avib7348942015-12-25 20:57:1012#include "build/build_config.h"
[email protected]df376972013-05-03 21:45:0313#include "content/browser/renderer_host/render_widget_host_impl.h"
[email protected]95640212014-07-26 18:14:3014#include "content/browser/web_contents/web_contents_impl.h"
[email protected]18df7362012-10-24 01:29:4015#include "content/public/browser/browser_thread.h"
[email protected]3e3c4522012-04-13 21:16:2916#include "content/public/common/content_switches.h"
mlamouri20bb4c4a2015-07-08 14:30:2217#include "ui/gfx/color_utils.h"
[email protected]fa4f91682012-02-21 19:53:2618
[email protected]e6b34872012-10-24 20:51:3219namespace content {
20
dmazzoni368ea132016-12-20 08:22:4221// IMPORTANT!
22// These values are written to logs. Do not renumber or delete
23// existing items; add new entries to the end of the list.
24enum ModeFlagHistogramValue {
dougtcd3dad732017-03-14 03:26:2325 UMA_AX_MODE_NATIVE_APIS = 0,
26 UMA_AX_MODE_WEB_CONTENTS = 1,
27 UMA_AX_MODE_INLINE_TEXT_BOXES = 2,
28 UMA_AX_MODE_SCREEN_READER = 3,
29 UMA_AX_MODE_HTML = 4,
dmazzoni368ea132016-12-20 08:22:4230
31 // This must always be the last enum. It's okay for its value to
32 // increase, but none of the other enum values may change.
dougtcd3dad732017-03-14 03:26:2333 UMA_AX_MODE_MAX
dmazzoni368ea132016-12-20 08:22:4234};
35
36// Record a histograms for an accessibility mode when it's enabled.
37void RecordNewAccessibilityModeFlags(ModeFlagHistogramValue mode_flag) {
dougtcd3dad732017-03-14 03:26:2338 UMA_HISTOGRAM_ENUMERATION("Accessibility.ModeFlag", mode_flag,
39 UMA_AX_MODE_MAX);
dmazzoni368ea132016-12-20 08:22:4240}
41
[email protected]fa4f91682012-02-21 19:53:2642// Update the accessibility histogram 45 seconds after initialization.
dmazzoni368ea132016-12-20 08:22:4243static const int ACCESSIBILITY_HISTOGRAM_DELAY_SECS = 45;
[email protected]fa4f91682012-02-21 19:53:2644
45// static
46BrowserAccessibilityState* BrowserAccessibilityState::GetInstance() {
47 return BrowserAccessibilityStateImpl::GetInstance();
48}
49
50// static
51BrowserAccessibilityStateImpl* BrowserAccessibilityStateImpl::GetInstance() {
olli.raula36aa8be2015-09-10 11:14:2252 return base::Singleton<
53 BrowserAccessibilityStateImpl,
54 base::LeakySingletonTraits<BrowserAccessibilityStateImpl>>::get();
[email protected]fa4f91682012-02-21 19:53:2655}
56
57BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl()
58 : BrowserAccessibilityState(),
dmazzonidea5ba62015-02-03 19:27:2459 disable_hot_tracking_(false) {
[email protected]1e558fa2014-02-12 23:28:5260 ResetAccessibilityModeValue();
[email protected]882db442012-12-04 16:37:5461
62 // We need to AddRef() the leaky singleton so that Bind doesn't
[email protected]3c17ae742012-10-24 17:37:2663 // delete it prematurely.
64 AddRef();
sebmarchand41f774b2017-05-23 21:50:2165
66#if defined(OS_WIN)
67 // The delay is necessary because assistive technology sometimes isn't
68 // detected until after the user interacts in some way, so a reasonable delay
69 // gives us better numbers.
70 base::PostDelayedTaskWithTraits(
71 FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
[email protected]30fdb362013-01-09 02:33:2772 base::Bind(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
dmazzoni368ea132016-12-20 08:22:4273 base::TimeDelta::FromSeconds(ACCESSIBILITY_HISTOGRAM_DELAY_SECS));
sebmarchand41f774b2017-05-23 21:50:2174#else
75 // On all other platforms, UpdateHistograms should be called on the UI
76 // thread because it needs to be able to access PrefService.
77 BrowserThread::PostDelayedTask(
78 BrowserThread::UI, FROM_HERE,
79 base::Bind(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
80 base::TimeDelta::FromSeconds(ACCESSIBILITY_HISTOGRAM_DELAY_SECS));
81#endif
[email protected]fa4f91682012-02-21 19:53:2682}
83
84BrowserAccessibilityStateImpl::~BrowserAccessibilityStateImpl() {
85}
86
87void BrowserAccessibilityStateImpl::OnScreenReaderDetected() {
[email protected]479278702014-08-11 20:32:0988 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]bfa71242014-03-27 21:10:2489 switches::kDisableRendererAccessibility)) {
90 return;
91 }
92 EnableAccessibility();
[email protected]fa4f91682012-02-21 19:53:2693}
94
[email protected]df376972013-05-03 21:45:0395void BrowserAccessibilityStateImpl::EnableAccessibility() {
Doug Turner63f3c7b2017-07-29 05:10:0196 AddAccessibilityModeFlags(ui::kAXModeComplete);
[email protected]fa4f91682012-02-21 19:53:2697}
98
[email protected]df376972013-05-03 21:45:0399void BrowserAccessibilityStateImpl::DisableAccessibility() {
[email protected]1e558fa2014-02-12 23:28:52100 ResetAccessibilityMode();
101}
102
103void BrowserAccessibilityStateImpl::ResetAccessibilityModeValue() {
Doug Turner63f3c7b2017-07-29 05:10:01104 accessibility_mode_ = ui::AXMode();
[email protected]479278702014-08-11 20:32:09105 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]1e558fa2014-02-12 23:28:52106 switches::kForceRendererAccessibility)) {
Doug Turner63f3c7b2017-07-29 05:10:01107 accessibility_mode_ = ui::kAXModeComplete;
[email protected]1e558fa2014-02-12 23:28:52108 }
109}
110
111void BrowserAccessibilityStateImpl::ResetAccessibilityMode() {
112 ResetAccessibilityModeValue();
113
[email protected]95640212014-07-26 18:14:30114 std::vector<WebContentsImpl*> web_contents_vector =
115 WebContentsImpl::GetAllWebContents();
116 for (size_t i = 0; i < web_contents_vector.size(); ++i)
117 web_contents_vector[i]->SetAccessibilityMode(accessibility_mode());
[email protected]df376972013-05-03 21:45:03118}
119
[email protected]fa4f91682012-02-21 19:53:26120bool BrowserAccessibilityStateImpl::IsAccessibleBrowser() {
Doug Turner63f3c7b2017-07-29 05:10:01121 return accessibility_mode_ == ui::kAXModeComplete;
[email protected]fa4f91682012-02-21 19:53:26122}
123
[email protected]89430152012-12-03 19:18:56124void BrowserAccessibilityStateImpl::AddHistogramCallback(
125 base::Closure callback) {
126 histogram_callbacks_.push_back(callback);
127}
128
[email protected]30fdb362013-01-09 02:33:27129void BrowserAccessibilityStateImpl::UpdateHistogramsForTesting() {
130 UpdateHistograms();
131}
132
133void BrowserAccessibilityStateImpl::UpdateHistograms() {
[email protected]18df7362012-10-24 01:29:40134 UpdatePlatformSpecificHistograms();
135
[email protected]89430152012-12-03 19:18:56136 for (size_t i = 0; i < histogram_callbacks_.size(); ++i)
137 histogram_callbacks_[i].Run();
138
dmazzoni368ea132016-12-20 08:22:42139 // TODO(dmazzoni): remove this in M59 since Accessibility.ModeFlag
140 // supercedes it. http://crbug.com/672205
[email protected]18df7362012-10-24 01:29:40141 UMA_HISTOGRAM_BOOLEAN("Accessibility.State", IsAccessibleBrowser());
dmazzoni368ea132016-12-20 08:22:42142
[email protected]18df7362012-10-24 01:29:40143 UMA_HISTOGRAM_BOOLEAN("Accessibility.InvertedColors",
mlamouri20bb4c4a2015-07-08 14:30:22144 color_utils::IsInvertedColorScheme());
[email protected]18df7362012-10-24 01:29:40145 UMA_HISTOGRAM_BOOLEAN("Accessibility.ManuallyEnabled",
[email protected]479278702014-08-11 20:32:09146 base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]18df7362012-10-24 01:29:40147 switches::kForceRendererAccessibility));
[email protected]fa4f91682012-02-21 19:53:26148}
[email protected]e2fa1cca42012-08-22 14:07:27149
ellyjonesa577c6cb2016-04-01 22:31:03150#if !defined(OS_WIN) && !defined(OS_MACOSX)
[email protected]18df7362012-10-24 01:29:40151void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
152}
153#endif
154
Doug Turner63f3c7b2017-07-29 05:10:01155void BrowserAccessibilityStateImpl::AddAccessibilityModeFlags(ui::AXMode mode) {
[email protected]479278702014-08-11 20:32:09156 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]1e558fa2014-02-12 23:28:52157 switches::kDisableRendererAccessibility)) {
[email protected]df376972013-05-03 21:45:03158 return;
[email protected]1e558fa2014-02-12 23:28:52159 }
[email protected]df376972013-05-03 21:45:03160
Doug Turner63f3c7b2017-07-29 05:10:01161 ui::AXMode previous_mode = accessibility_mode_;
dmazzonidd3d51a72016-12-14 18:41:01162 accessibility_mode_ |= mode;
dmazzoni368ea132016-12-20 08:22:42163 if (accessibility_mode_ == previous_mode)
164 return;
165
166 // Retrieve only newly added modes for the purposes of logging.
dougtcd3dad732017-03-14 03:26:23167 int new_mode_flags = mode.mode() & (~previous_mode.mode());
Doug Turner63f3c7b2017-07-29 05:10:01168 if (new_mode_flags & ui::AXMode::kNativeAPIs)
dougtcd3dad732017-03-14 03:26:23169 RecordNewAccessibilityModeFlags(UMA_AX_MODE_NATIVE_APIS);
Doug Turner63f3c7b2017-07-29 05:10:01170 if (new_mode_flags & ui::AXMode::kWebContents)
dougtcd3dad732017-03-14 03:26:23171 RecordNewAccessibilityModeFlags(UMA_AX_MODE_WEB_CONTENTS);
Doug Turner63f3c7b2017-07-29 05:10:01172 if (new_mode_flags & ui::AXMode::kInlineTextBoxes)
dougtcd3dad732017-03-14 03:26:23173 RecordNewAccessibilityModeFlags(UMA_AX_MODE_INLINE_TEXT_BOXES);
Doug Turner63f3c7b2017-07-29 05:10:01174 if (new_mode_flags & ui::AXMode::kScreenReader)
dougtcd3dad732017-03-14 03:26:23175 RecordNewAccessibilityModeFlags(UMA_AX_MODE_SCREEN_READER);
Doug Turner63f3c7b2017-07-29 05:10:01176 if (new_mode_flags & ui::AXMode::kHTML)
dougtcd3dad732017-03-14 03:26:23177 RecordNewAccessibilityModeFlags(UMA_AX_MODE_HTML);
dmazzoni368ea132016-12-20 08:22:42178
dmazzonidd3d51a72016-12-14 18:41:01179 std::vector<WebContentsImpl*> web_contents_vector =
180 WebContentsImpl::GetAllWebContents();
181 for (size_t i = 0; i < web_contents_vector.size(); ++i)
182 web_contents_vector[i]->AddAccessibilityMode(accessibility_mode_);
[email protected]1e558fa2014-02-12 23:28:52183}
184
dmazzonidd3d51a72016-12-14 18:41:01185void BrowserAccessibilityStateImpl::RemoveAccessibilityModeFlags(
Doug Turner63f3c7b2017-07-29 05:10:01186 ui::AXMode mode) {
[email protected]479278702014-08-11 20:32:09187 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
[email protected]1e558fa2014-02-12 23:28:52188 switches::kForceRendererAccessibility) &&
Doug Turner63f3c7b2017-07-29 05:10:01189 mode == ui::kAXModeComplete) {
[email protected]1e558fa2014-02-12 23:28:52190 return;
191 }
192
dougtcd3dad732017-03-14 03:26:23193 int raw_flags =
194 accessibility_mode_.mode() ^ (mode.mode() & accessibility_mode_.mode());
195 accessibility_mode_ = raw_flags;
196
[email protected]95640212014-07-26 18:14:30197 std::vector<WebContentsImpl*> web_contents_vector =
198 WebContentsImpl::GetAllWebContents();
dmazzonidd3d51a72016-12-14 18:41:01199 for (size_t i = 0; i < web_contents_vector.size(); ++i)
200 web_contents_vector[i]->SetAccessibilityMode(accessibility_mode());
[email protected]e2fa1cca42012-08-22 14:07:27201}
[email protected]e6b34872012-10-24 20:51:32202
203} // namespace content