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/renderer_host/render_widget_host_impl.h" 11 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/render_process_host.h" 13 #include "content/public/browser/render_widget_host_iterator.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 #if defined(OS_WIN) 41 // On Windows 8, always enable accessibility for editable text controls 42 // so we can show the virtual keyboard when one is enabled. 43 if (base::win::GetVersion() >= base::win::VERSION_WIN8 && 44 !CommandLine::ForCurrentProcess()->HasSwitch( 45 switches::kDisableRendererAccessibility)) { 46 accessibility_mode_ = AccessibilityModeEditableTextOnly; 47 } 48 #endif // defined(OS_WIN) 49 50 if (CommandLine::ForCurrentProcess()->HasSwitch( 51 switches::kForceRendererAccessibility)) { 52 accessibility_mode_ = AccessibilityModeComplete; 53 } 54 55 #if defined(OS_WIN) 56 // On Windows, UpdateHistograms calls some system functions with unknown 57 // runtime, so call it on the file thread to ensure there's no jank. 58 // Everything in that method must be safe to call on another thread. 59 BrowserThread::ID update_histogram_thread = BrowserThread::FILE; 60 #else 61 // On all other platforms, UpdateHistograms should be called on the main 62 // thread. 63 BrowserThread::ID update_histogram_thread = BrowserThread::UI; 64 #endif 65 66 // We need to AddRef() the leaky singleton so that Bind doesn't 67 // delete it prematurely. 68 AddRef(); 69 BrowserThread::PostDelayedTask( 70 update_histogram_thread, FROM_HERE, 71 base::Bind(&BrowserAccessibilityStateImpl::UpdateHistograms, this), 72 base::TimeDelta::FromSeconds(kAccessibilityHistogramDelaySecs)); 73 } 74 75 BrowserAccessibilityStateImpl::~BrowserAccessibilityStateImpl() { 76 } 77 78 void BrowserAccessibilityStateImpl::OnScreenReaderDetected() { 79 if (CommandLine::ForCurrentProcess()->HasSwitch( 80 switches::kDisableRendererAccessibility)) { 81 return; 82 } 83 SetAccessibilityMode(AccessibilityModeComplete); 84 } 85 86 void BrowserAccessibilityStateImpl::EnableAccessibility() { 87 // We may want to do something different with this later. 88 SetAccessibilityMode(AccessibilityModeComplete); 89 } 90 91 void BrowserAccessibilityStateImpl::DisableAccessibility() { 92 SetAccessibilityMode(AccessibilityModeOff); 93 } 94 95 bool BrowserAccessibilityStateImpl::IsAccessibleBrowser() { 96 return (accessibility_mode_ == AccessibilityModeComplete); 97 } 98 99 void BrowserAccessibilityStateImpl::AddHistogramCallback( 100 base::Closure callback) { 101 histogram_callbacks_.push_back(callback); 102 } 103 104 void BrowserAccessibilityStateImpl::UpdateHistogramsForTesting() { 105 UpdateHistograms(); 106 } 107 108 void BrowserAccessibilityStateImpl::UpdateHistograms() { 109 UpdatePlatformSpecificHistograms(); 110 111 for (size_t i = 0; i < histogram_callbacks_.size(); ++i) 112 histogram_callbacks_[i].Run(); 113 114 UMA_HISTOGRAM_BOOLEAN("Accessibility.State", IsAccessibleBrowser()); 115 UMA_HISTOGRAM_BOOLEAN("Accessibility.InvertedColors", 116 gfx::IsInvertedColorScheme()); 117 UMA_HISTOGRAM_BOOLEAN("Accessibility.ManuallyEnabled", 118 CommandLine::ForCurrentProcess()->HasSwitch( 119 switches::kForceRendererAccessibility)); 120 } 121 122 #if !defined(OS_WIN) 123 void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() { 124 } 125 #endif 126 127 void BrowserAccessibilityStateImpl::SetAccessibilityMode( 128 AccessibilityMode mode) { 129 if (accessibility_mode_ == mode) 130 return; 131 accessibility_mode_ = mode; 132 133 // Iterate over all RenderWidgetHosts, even swapped out ones in case 134 // they become active again. 135 scoped_ptr<RenderWidgetHostIterator> widgets( 136 RenderWidgetHostImpl::GetAllRenderWidgetHosts()); 137 while (RenderWidgetHost* widget = widgets->GetNextHost()) { 138 // Ignore processes that don't have a connection, such as crashed tabs. 139 if (!widget->GetProcess()->HasConnection()) 140 continue; 141 if (!widget->IsRenderView()) 142 continue; 143 144 RenderWidgetHostImpl::From(widget)->SetAccessibilityMode(mode); 145 } 146 } 147 148 } // namespace content 149