Home | History | Annotate | Download | only in accessibility
      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