1e3063e19de30e2991bed0c13320c1ee7c9a6d6f
[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/browser/web_contents/web_contents_impl.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/common/content_switches.h"
15 #include "ui/gfx/sys_color_change_listener.h"
16
17 #if defined(OS_WIN)
18 #include "base/win/windows_version.h"
19 #endif
20
21 namespace content {
22
23 // Update the accessibility histogram 45 seconds after initialization.
24 static const int kAccessibilityHistogramDelaySecs = 45;
25
26 // static
27 BrowserAccessibilityState* BrowserAccessibilityState::GetInstance() {
28   return BrowserAccessibilityStateImpl::GetInstance();
29 }
30
31 // static
32 BrowserAccessibilityStateImpl* BrowserAccessibilityStateImpl::GetInstance() {
33   return Singleton<BrowserAccessibilityStateImpl,
34                    LeakySingletonTraits<BrowserAccessibilityStateImpl> >::get();
35 }
36
37 BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl()
38     : BrowserAccessibilityState(),
39       accessibility_mode_(AccessibilityModeOff) {
40   ResetAccessibilityModeValue();
41 #if defined(OS_WIN)
42   // On Windows, UpdateHistograms calls some system functions with unknown
43   // runtime, so call it on the file thread to ensure there's no jank.
44   // Everything in that method must be safe to call on another thread.
45   BrowserThread::ID update_histogram_thread = BrowserThread::FILE;
46 #else
47   // On all other platforms, UpdateHistograms should be called on the main
48   // thread.
49   BrowserThread::ID update_histogram_thread = BrowserThread::UI;
50 #endif
51
52   // We need to AddRef() the leaky singleton so that Bind doesn't
53   // delete it prematurely.
54   AddRef();
55   BrowserThread::PostDelayedTask(
56       update_histogram_thread, FROM_HERE,
57       base::Bind(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
58       base::TimeDelta::FromSeconds(kAccessibilityHistogramDelaySecs));
59 }
60
61 BrowserAccessibilityStateImpl::~BrowserAccessibilityStateImpl() {
62 }
63
64 void BrowserAccessibilityStateImpl::OnScreenReaderDetected() {
65   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
66           switches::kDisableRendererAccessibility)) {
67     return;
68   }
69   EnableAccessibility();
70 }
71
72 void BrowserAccessibilityStateImpl::EnableAccessibility() {
73   AddAccessibilityMode(AccessibilityModeComplete);
74 }
75
76 void BrowserAccessibilityStateImpl::DisableAccessibility() {
77   ResetAccessibilityMode();
78 }
79
80 void BrowserAccessibilityStateImpl::ResetAccessibilityModeValue() {
81   accessibility_mode_ = AccessibilityModeOff;
82 #if defined(OS_WIN)
83   // On Windows 8, always enable accessibility for editable text controls
84   // so we can show the virtual keyboard when one is enabled.
85   if (base::win::GetVersion() >= base::win::VERSION_WIN8 &&
86       !base::CommandLine::ForCurrentProcess()->HasSwitch(
87           switches::kDisableRendererAccessibility)) {
88     accessibility_mode_ = AccessibilityModeEditableTextOnly;
89   }
90 #endif  // defined(OS_WIN)
91
92   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
93           switches::kForceRendererAccessibility)) {
94     accessibility_mode_ = AccessibilityModeComplete;
95   }
96 }
97
98 void BrowserAccessibilityStateImpl::ResetAccessibilityMode() {
99   ResetAccessibilityModeValue();
100
101   std::vector<WebContentsImpl*> web_contents_vector =
102       WebContentsImpl::GetAllWebContents();
103   for (size_t i = 0; i < web_contents_vector.size(); ++i)
104     web_contents_vector[i]->SetAccessibilityMode(accessibility_mode());
105 }
106
107 bool BrowserAccessibilityStateImpl::IsAccessibleBrowser() {
108   return ((accessibility_mode_ & AccessibilityModeComplete) ==
109           AccessibilityModeComplete);
110 }
111
112 void BrowserAccessibilityStateImpl::AddHistogramCallback(
113     base::Closure callback) {
114   histogram_callbacks_.push_back(callback);
115 }
116
117 void BrowserAccessibilityStateImpl::UpdateHistogramsForTesting() {
118   UpdateHistograms();
119 }
120
121 void BrowserAccessibilityStateImpl::UpdateHistograms() {
122   UpdatePlatformSpecificHistograms();
123
124   for (size_t i = 0; i < histogram_callbacks_.size(); ++i)
125     histogram_callbacks_[i].Run();
126
127   UMA_HISTOGRAM_BOOLEAN("Accessibility.State", IsAccessibleBrowser());
128   UMA_HISTOGRAM_BOOLEAN("Accessibility.InvertedColors",
129                         gfx::IsInvertedColorScheme());
130   UMA_HISTOGRAM_BOOLEAN("Accessibility.ManuallyEnabled",
131                         base::CommandLine::ForCurrentProcess()->HasSwitch(
132                             switches::kForceRendererAccessibility));
133 }
134
135 #if !defined(OS_WIN)
136 void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
137 }
138 #endif
139
140 void BrowserAccessibilityStateImpl::AddAccessibilityMode(
141     AccessibilityMode mode) {
142   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
143           switches::kDisableRendererAccessibility)) {
144     return;
145   }
146
147   accessibility_mode_ =
148       content::AddAccessibilityModeTo(accessibility_mode_, mode);
149
150   AddOrRemoveFromAllWebContents(mode, true);
151 }
152
153 void BrowserAccessibilityStateImpl::RemoveAccessibilityMode(
154     AccessibilityMode mode) {
155   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
156           switches::kForceRendererAccessibility) &&
157       mode == AccessibilityModeComplete) {
158     return;
159   }
160
161   accessibility_mode_ =
162       content::RemoveAccessibilityModeFrom(accessibility_mode_, mode);
163
164   AddOrRemoveFromAllWebContents(mode, false);
165 }
166
167 void BrowserAccessibilityStateImpl::AddOrRemoveFromAllWebContents(
168     AccessibilityMode mode,
169     bool add) {
170   std::vector<WebContentsImpl*> web_contents_vector =
171       WebContentsImpl::GetAllWebContents();
172   for (size_t i = 0; i < web_contents_vector.size(); ++i) {
173     if (add)
174       web_contents_vector[i]->AddAccessibilityMode(mode);
175     else
176       web_contents_vector[i]->RemoveAccessibilityMode(mode);
177   }
178 }
179
180 }  // namespace content