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 17namespace content { 18 19// Update the accessibility histogram 45 seconds after initialization. 20static const int kAccessibilityHistogramDelaySecs = 45; 21 22// static 23BrowserAccessibilityState* BrowserAccessibilityState::GetInstance() { 24 return BrowserAccessibilityStateImpl::GetInstance(); 25} 26 27// static 28BrowserAccessibilityStateImpl* BrowserAccessibilityStateImpl::GetInstance() { 29 return Singleton<BrowserAccessibilityStateImpl, 30 LeakySingletonTraits<BrowserAccessibilityStateImpl> >::get(); 31} 32 33BrowserAccessibilityStateImpl::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 57BrowserAccessibilityStateImpl::~BrowserAccessibilityStateImpl() { 58} 59 60void BrowserAccessibilityStateImpl::OnScreenReaderDetected() { 61 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 62 switches::kDisableRendererAccessibility)) { 63 return; 64 } 65 EnableAccessibility(); 66} 67 68void BrowserAccessibilityStateImpl::EnableAccessibility() { 69 AddAccessibilityMode(AccessibilityModeComplete); 70} 71 72void BrowserAccessibilityStateImpl::DisableAccessibility() { 73 ResetAccessibilityMode(); 74} 75 76void BrowserAccessibilityStateImpl::ResetAccessibilityModeValue() { 77 accessibility_mode_ = AccessibilityModeOff; 78 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 79 switches::kForceRendererAccessibility)) { 80 accessibility_mode_ = AccessibilityModeComplete; 81 } 82} 83 84void 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 93bool BrowserAccessibilityStateImpl::IsAccessibleBrowser() { 94 return ((accessibility_mode_ & AccessibilityModeComplete) == 95 AccessibilityModeComplete); 96} 97 98void BrowserAccessibilityStateImpl::AddHistogramCallback( 99 base::Closure callback) { 100 histogram_callbacks_.push_back(callback); 101} 102 103void BrowserAccessibilityStateImpl::UpdateHistogramsForTesting() { 104 UpdateHistograms(); 105} 106 107void 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) 122void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() { 123} 124#endif 125 126void 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 139void 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 153void 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