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/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