Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / browser / accessibility / browser_accessibility_state_impl.cc
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.
4
5 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
6
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"
17
18 #if defined(OS_WIN)
19 #include "base/win/windows_version.h"
20 #endif
21
22 namespace content {
23
24 // Update the accessibility histogram 45 seconds after initialization.
25 static const int kAccessibilityHistogramDelaySecs = 45;
26
27 // static
28 BrowserAccessibilityState* BrowserAccessibilityState::GetInstance() {
29   return BrowserAccessibilityStateImpl::GetInstance();
30 }
31
32 // static
33 BrowserAccessibilityStateImpl* BrowserAccessibilityStateImpl::GetInstance() {
34   return Singleton<BrowserAccessibilityStateImpl,
35                    LeakySingletonTraits<BrowserAccessibilityStateImpl> >::get();
36 }
37
38 BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl()
39     : BrowserAccessibilityState(),
40       accessibility_mode_(AccessibilityModeOff) {
41   ResetAccessibilityModeValue();
42 #if defined(OS_WIN)
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;
47 #else
48   // On all other platforms, UpdateHistograms should be called on the main
49   // thread.
50   BrowserThread::ID update_histogram_thread = BrowserThread::UI;
51 #endif
52
53   // We need to AddRef() the leaky singleton so that Bind doesn't
54   // delete it prematurely.
55   AddRef();
56   BrowserThread::PostDelayedTask(
57       update_histogram_thread, FROM_HERE,
58       base::Bind(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
59       base::TimeDelta::FromSeconds(kAccessibilityHistogramDelaySecs));
60 }
61
62 BrowserAccessibilityStateImpl::~BrowserAccessibilityStateImpl() {
63 }
64
65 void BrowserAccessibilityStateImpl::OnScreenReaderDetected() {
66   AddAccessibilityMode(AccessibilityModeComplete);
67 }
68
69 void BrowserAccessibilityStateImpl::EnableAccessibility() {
70   // We may want to do something different with this later.
71   AddAccessibilityMode(AccessibilityModeComplete);
72 }
73
74 void BrowserAccessibilityStateImpl::DisableAccessibility() {
75   ResetAccessibilityMode();
76 }
77
78 void BrowserAccessibilityStateImpl::ResetAccessibilityModeValue() {
79   accessibility_mode_ = AccessibilityModeOff;
80 #if defined(OS_WIN)
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;
87   }
88 #endif  // defined(OS_WIN)
89
90   if (CommandLine::ForCurrentProcess()->HasSwitch(
91           switches::kForceRendererAccessibility)) {
92     accessibility_mode_ = AccessibilityModeComplete;
93   }
94 }
95
96 void BrowserAccessibilityStateImpl::ResetAccessibilityMode() {
97   ResetAccessibilityModeValue();
98
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())
106       continue;
107     if (!widget->IsRenderView())
108       continue;
109
110     RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(widget);
111     rwhi->ResetAccessibilityMode();
112   }
113 }
114
115 bool BrowserAccessibilityStateImpl::IsAccessibleBrowser() {
116   return ((accessibility_mode_ & AccessibilityModeComplete) ==
117           AccessibilityModeComplete);
118 }
119
120 void BrowserAccessibilityStateImpl::AddHistogramCallback(
121     base::Closure callback) {
122   histogram_callbacks_.push_back(callback);
123 }
124
125 void BrowserAccessibilityStateImpl::UpdateHistogramsForTesting() {
126   UpdateHistograms();
127 }
128
129 void BrowserAccessibilityStateImpl::UpdateHistograms() {
130   UpdatePlatformSpecificHistograms();
131
132   for (size_t i = 0; i < histogram_callbacks_.size(); ++i)
133     histogram_callbacks_[i].Run();
134
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));
141 }
142
143 #if !defined(OS_WIN)
144 void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
145 }
146 #endif
147
148 void BrowserAccessibilityStateImpl::AddAccessibilityMode(
149     AccessibilityMode mode) {
150   if (CommandLine::ForCurrentProcess()->HasSwitch(
151           switches::kDisableRendererAccessibility)) {
152     return;
153   }
154
155   accessibility_mode_ =
156       content::AddAccessibilityModeTo(accessibility_mode_, mode);
157
158   AddOrRemoveFromRenderWidgets(mode, true);
159 }
160
161 void BrowserAccessibilityStateImpl::RemoveAccessibilityMode(
162     AccessibilityMode mode) {
163   if (CommandLine::ForCurrentProcess()->HasSwitch(
164           switches::kForceRendererAccessibility) &&
165       mode == AccessibilityModeComplete) {
166     return;
167   }
168
169   accessibility_mode_ =
170       content::RemoveAccessibilityModeFrom(accessibility_mode_, mode);
171
172   AddOrRemoveFromRenderWidgets(mode, false);
173 }
174
175 void BrowserAccessibilityStateImpl::AddOrRemoveFromRenderWidgets(
176     AccessibilityMode mode,
177     bool add) {
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())
185       continue;
186     if (!widget->IsRenderView())
187       continue;
188
189     RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(widget);
190     if (add)
191       rwhi->AddAccessibilityMode(mode);
192     else
193       rwhi->RemoveAccessibilityMode(mode);
194   }
195 }
196
197 }  // namespace content