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 namespace content { 18 19 // Update the accessibility histogram 45 seconds after initialization. 20 static const int kAccessibilityHistogramDelaySecs = 45; 21 22 // static 23 BrowserAccessibilityState* BrowserAccessibilityState::GetInstance() { 24 return BrowserAccessibilityStateImpl::GetInstance(); 25 } 26 27 // static 28 BrowserAccessibilityStateImpl* BrowserAccessibilityStateImpl::GetInstance() { 29 return Singleton<BrowserAccessibilityStateImpl, 30 LeakySingletonTraits<BrowserAccessibilityStateImpl> >::get(); 31 } 32 33 BrowserAccessibilityStateImpl::BrowserAccessibilityStateImpl() 34 : BrowserAccessibilityState(), 35 accessibility_mode_(AccessibilityModeOff) { 36 ResetAccessibilityModeValue(); 37 #if defined(OS_WIN) 38 // On Windows, UpdateHistograms calls some system functions with unknown 39 // runtime, so call it on the file thread to ensure there's no jank. 40 // Everything in that method must be safe to call on another thread. 41 BrowserThread::ID update_histogram_thread = BrowserThread::FILE; 42 #else 43 // On all other platforms, UpdateHistograms should be called on the main 44 // thread. 45 BrowserThread::ID update_histogram_thread = BrowserThread::UI; 46 #endif 47 48 // We need to AddRef() the leaky singleton so that Bind doesn't 49 // delete it prematurely. 50 AddRef(); 51 BrowserThread::PostDelayedTask( 52 update_histogram_thread, FROM_HERE, 53 base::Bind(&BrowserAccessibilityStateImpl::UpdateHistograms, this), 54 base::TimeDelta::FromSeconds(kAccessibilityHistogramDelaySecs)); 55 } 56 57 BrowserAccessibilityStateImpl::~BrowserAccessibilityStateImpl() { 58 } 59 60 void BrowserAccessibilityStateImpl::OnScreenReaderDetected() { 61 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 62 switches::kDisableRendererAccessibility)) { 63 return; 64 } 65 EnableAccessibility(); 66 } 67 68 void BrowserAccessibilityStateImpl::EnableAccessibility() { 69 AddAccessibilityMode(AccessibilityModeComplete); 70 } 71 72 void BrowserAccessibilityStateImpl::DisableAccessibility() { 73 ResetAccessibilityMode(); 74 } 75 76 void BrowserAccessibilityStateImpl::ResetAccessibilityModeValue() { 77 accessibility_mode_ = AccessibilityModeOff; 78 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 79 switches::kForceRendererAccessibility)) { 80 accessibility_mode_ = AccessibilityModeComplete; 81 } 82 } 83 84 void BrowserAccessibilityStateImpl::ResetAccessibilityMode() { 85 ResetAccessibilityModeValue(); 86 87 std::vector<WebContentsImpl*> web_contents_vector = 88 WebContentsImpl::GetAllWebContents(); 89 for (size_t i = 0; i < web_contents_vector.size(); ++i) 90 web_contents_vector[i]->SetAccessibilityMode(accessibility_mode()); 91 } 92 93 bool BrowserAccessibilityStateImpl::IsAccessibleBrowser() { 94 return ((accessibility_mode_ & AccessibilityModeComplete) == 95 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 base::CommandLine::ForCurrentProcess()->HasSwitch( 118 switches::kForceRendererAccessibility)); 119 } 120 121 #if !defined(OS_WIN) 122 void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() { 123 } 124 #endif 125 126 void BrowserAccessibilityStateImpl::AddAccessibilityMode( 127 AccessibilityMode mode) { 128 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 129 switches::kDisableRendererAccessibility)) { 130 return; 131 } 132 133 accessibility_mode_ = 134 content::AddAccessibilityModeTo(accessibility_mode_, mode); 135 136 AddOrRemoveFromAllWebContents(mode, true); 137 } 138 139 void BrowserAccessibilityStateImpl::RemoveAccessibilityMode( 140 AccessibilityMode mode) { 141 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 142 switches::kForceRendererAccessibility) && 143 mode == AccessibilityModeComplete) { 144 return; 145 } 146 147 accessibility_mode_ = 148 content::RemoveAccessibilityModeFrom(accessibility_mode_, mode); 149 150 AddOrRemoveFromAllWebContents(mode, false); 151 } 152 153 void BrowserAccessibilityStateImpl::AddOrRemoveFromAllWebContents( 154 AccessibilityMode mode, 155 bool add) { 156 std::vector<WebContentsImpl*> web_contents_vector = 157 WebContentsImpl::GetAllWebContents(); 158 for (size_t i = 0; i < web_contents_vector.size(); ++i) { 159 if (add) 160 web_contents_vector[i]->AddAccessibilityMode(mode); 161 else 162 web_contents_vector[i]->RemoveAccessibilityMode(mode); 163 } 164 } 165 166 } // namespace content 167