1 // 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.
5 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
7 #include "base/command_line.h"
8 #include "base/metrics/histogram.h"
9 #include "base/timer/timer.h"
10 #include "content/browser/accessibility/accessibility_mode_helper.h"
11 #include "content/browser/renderer_host/render_widget_host_impl.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/render_process_host.h"
14 #include "content/public/browser/render_widget_host_iterator.h"
15 #include "content/public/common/content_switches.h"
16 #include "ui/gfx/sys_color_change_listener.h"
19 #include "base/win/windows_version.h"
24 // Update the accessibility histogram 45 seconds after initialization.
25 static const int kAccessibilityHistogramDelaySecs = 45;
28 BrowserAccessibilityState* BrowserAccessibilityState::GetInstance() {
29 return BrowserAccessibilityStateImpl::GetInstance();
33 BrowserAccessibilityStateImpl* BrowserAccessibilityStateImpl::GetInstance() {
34 return Singleton<BrowserAccessibilityStateImpl,
35 LeakySingletonTraits<BrowserAccessibilityStateImpl> >::get();
38 BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl()
39 : BrowserAccessibilityState(),
40 accessibility_mode_(AccessibilityModeOff) {
41 ResetAccessibilityModeValue();
43 // On Windows, UpdateHistograms calls some system functions with unknown
44 // runtime, so call it on the file thread to ensure there's no jank.
45 // Everything in that method must be safe to call on another thread.
46 BrowserThread::ID update_histogram_thread = BrowserThread::FILE;
48 // On all other platforms, UpdateHistograms should be called on the main
50 BrowserThread::ID update_histogram_thread = BrowserThread::UI;
53 // We need to AddRef() the leaky singleton so that Bind doesn't
54 // delete it prematurely.
56 BrowserThread::PostDelayedTask(
57 update_histogram_thread, FROM_HERE,
58 base::Bind(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
59 base::TimeDelta::FromSeconds(kAccessibilityHistogramDelaySecs));
62 BrowserAccessibilityStateImpl::~BrowserAccessibilityStateImpl() {
65 void BrowserAccessibilityStateImpl::OnScreenReaderDetected() {
66 AddAccessibilityMode(AccessibilityModeComplete);
69 void BrowserAccessibilityStateImpl::EnableAccessibility() {
70 // We may want to do something different with this later.
71 AddAccessibilityMode(AccessibilityModeComplete);
74 void BrowserAccessibilityStateImpl::DisableAccessibility() {
75 ResetAccessibilityMode();
78 void BrowserAccessibilityStateImpl::ResetAccessibilityModeValue() {
79 accessibility_mode_ = AccessibilityModeOff;
81 // On Windows 8, always enable accessibility for editable text controls
82 // so we can show the virtual keyboard when one is enabled.
83 if (base::win::GetVersion() >= base::win::VERSION_WIN8 &&
84 !CommandLine::ForCurrentProcess()->HasSwitch(
85 switches::kDisableRendererAccessibility)) {
86 accessibility_mode_ = AccessibilityModeEditableTextOnly;
88 #endif // defined(OS_WIN)
90 if (CommandLine::ForCurrentProcess()->HasSwitch(
91 switches::kForceRendererAccessibility)) {
92 accessibility_mode_ = AccessibilityModeComplete;
96 void BrowserAccessibilityStateImpl::ResetAccessibilityMode() {
97 ResetAccessibilityModeValue();
99 // Iterate over all RenderWidgetHosts, even swapped out ones in case
100 // they become active again.
101 scoped_ptr<RenderWidgetHostIterator> widgets(
102 RenderWidgetHostImpl::GetAllRenderWidgetHosts());
103 while (RenderWidgetHost* widget = widgets->GetNextHost()) {
104 // Ignore processes that don't have a connection, such as crashed tabs.
105 if (!widget->GetProcess()->HasConnection())
107 if (!widget->IsRenderView())
110 RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(widget);
111 rwhi->ResetAccessibilityMode();
115 bool BrowserAccessibilityStateImpl::IsAccessibleBrowser() {
116 return ((accessibility_mode_ & AccessibilityModeComplete) ==
117 AccessibilityModeComplete);
120 void BrowserAccessibilityStateImpl::AddHistogramCallback(
121 base::Closure callback) {
122 histogram_callbacks_.push_back(callback);
125 void BrowserAccessibilityStateImpl::UpdateHistogramsForTesting() {
129 void BrowserAccessibilityStateImpl::UpdateHistograms() {
130 UpdatePlatformSpecificHistograms();
132 for (size_t i = 0; i < histogram_callbacks_.size(); ++i)
133 histogram_callbacks_[i].Run();
135 UMA_HISTOGRAM_BOOLEAN("Accessibility.State", IsAccessibleBrowser());
136 UMA_HISTOGRAM_BOOLEAN("Accessibility.InvertedColors",
137 gfx::IsInvertedColorScheme());
138 UMA_HISTOGRAM_BOOLEAN("Accessibility.ManuallyEnabled",
139 CommandLine::ForCurrentProcess()->HasSwitch(
140 switches::kForceRendererAccessibility));
144 void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
148 void BrowserAccessibilityStateImpl::AddAccessibilityMode(
149 AccessibilityMode mode) {
150 if (CommandLine::ForCurrentProcess()->HasSwitch(
151 switches::kDisableRendererAccessibility)) {
155 accessibility_mode_ =
156 content::AddAccessibilityModeTo(accessibility_mode_, mode);
158 AddOrRemoveFromRenderWidgets(mode, true);
161 void BrowserAccessibilityStateImpl::RemoveAccessibilityMode(
162 AccessibilityMode mode) {
163 if (CommandLine::ForCurrentProcess()->HasSwitch(
164 switches::kForceRendererAccessibility) &&
165 mode == AccessibilityModeComplete) {
169 accessibility_mode_ =
170 content::RemoveAccessibilityModeFrom(accessibility_mode_, mode);
172 AddOrRemoveFromRenderWidgets(mode, false);
175 void BrowserAccessibilityStateImpl::AddOrRemoveFromRenderWidgets(
176 AccessibilityMode mode,
178 // Iterate over all RenderWidgetHosts, even swapped out ones in case
179 // they become active again.
180 scoped_ptr<RenderWidgetHostIterator> widgets(
181 RenderWidgetHostImpl::GetAllRenderWidgetHosts());
182 while (RenderWidgetHost* widget = widgets->GetNextHost()) {
183 // Ignore processes that don't have a connection, such as crashed tabs.
184 if (!widget->GetProcess()->HasConnection())
186 if (!widget->IsRenderView())
189 RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(widget);
191 rwhi->AddAccessibilityMode(mode);
193 rwhi->RemoveAccessibilityMode(mode);
197 } // namespace content