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