accessibility_event_router_views.h revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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#ifndef CHROME_BROWSER_UI_VIEWS_ACCESSIBILITY_ACCESSIBILITY_EVENT_ROUTER_VIEWS_H_ 6#define CHROME_BROWSER_UI_VIEWS_ACCESSIBILITY_ACCESSIBILITY_EVENT_ROUTER_VIEWS_H_ 7 8#include <string> 9 10#include "base/basictypes.h" 11#include "base/gtest_prod_util.h" 12#include "base/strings/string16.h" 13#include "chrome/browser/accessibility/accessibility_events.h" 14#include "content/public/browser/notification_observer.h" 15#include "content/public/browser/notification_registrar.h" 16#include "ui/base/accessibility/accessibility_types.h" 17 18class Profile; 19 20template <typename T> struct DefaultSingletonTraits; 21 22namespace views { 23class View; 24} 25 26// NOTE: This class is part of the Accessibility Extension API, which lets 27// extensions receive accessibility events. It's distinct from code that 28// implements platform accessibility APIs like MSAA or ATK. 29// 30// Singleton class that adds listeners to many views, then sends an 31// accessibility notification whenever a relevant event occurs in an 32// accessible view. 33// 34// Views are not accessible by default. When you register a root widget, 35// that widget and all of its descendants will start sending accessibility 36// event notifications. You can then override the default behavior for 37// specific descendants using other methods. 38// 39// You can use Profile::PauseAccessibilityEvents to prevent a flurry 40// of accessibility events when a window is being created or initialized. 41class AccessibilityEventRouterViews : public content::NotificationObserver { 42 public: 43 // Get the single instance of this class. 44 static AccessibilityEventRouterViews* GetInstance(); 45 46 // Handle an accessibility event generated by a view. 47 void HandleAccessibilityEvent( 48 views::View* view, ui::AccessibilityTypes::Event event_type); 49 50 // Handle a menu item being focused (separate because a menu item is 51 // not necessarily its own view). 52 void HandleMenuItemFocused(const base::string16& menu_name, 53 const base::string16& menu_item_name, 54 int item_index, 55 int item_count, 56 bool has_submenu); 57 58 // NotificationObserver implementation. 59 virtual void Observe(int type, 60 const content::NotificationSource& source, 61 const content::NotificationDetails& details) OVERRIDE; 62 63 private: 64 friend struct DefaultSingletonTraits<AccessibilityEventRouterViews>; 65 66 FRIEND_TEST_ALL_PREFIXES(AccessibilityEventRouterViewsTest, 67 TestFocusNotification); 68 FRIEND_TEST_ALL_PREFIXES(AccessibilityEventRouterViewsTest, 69 MenuIndexAndCountForInvisibleMenu); 70 71 AccessibilityEventRouterViews(); 72 virtual ~AccessibilityEventRouterViews(); 73 74 // Call DispatchAccessibilityEvent using a view storage id. 75 static void DispatchEventOnViewStorageId( 76 int view_storage_id, 77 ui::AccessibilityTypes::Event event); 78 79 // Checks the type of the view and calls one of the more specific 80 // Send*Notification methods, below. 81 void DispatchAccessibilityEvent( 82 views::View* view, 83 ui::AccessibilityTypes::Event event); 84 85 // Each of these methods constructs an AccessibilityControlInfo object 86 // and sends a notification of a specific accessibility event. 87 static void SendButtonNotification( 88 views::View* view, 89 ui::AccessibilityTypes::Event event, 90 Profile* profile); 91 static void SendLinkNotification( 92 views::View* view, 93 ui::AccessibilityTypes::Event event, 94 Profile* profile); 95 static void SendMenuNotification( 96 views::View* view, 97 ui::AccessibilityTypes::Event event, 98 Profile* profile); 99 static void SendMenuItemNotification( 100 views::View* view, 101 ui::AccessibilityTypes::Event event, 102 Profile* profile); 103 static void SendTreeNotification( 104 views::View* view, 105 ui::AccessibilityTypes::Event event, 106 Profile* profile); 107 static void SendTreeItemNotification( 108 views::View* view, 109 ui::AccessibilityTypes::Event event, 110 Profile* profile); 111 static void SendTextfieldNotification( 112 views::View* view, 113 ui::AccessibilityTypes::Event event, 114 Profile* profile); 115 static void SendComboboxNotification( 116 views::View* view, 117 ui::AccessibilityTypes::Event event, 118 Profile* profile); 119 static void SendCheckboxNotification( 120 views::View* view, 121 ui::AccessibilityTypes::Event event, 122 Profile* profile); 123 static void SendWindowNotification( 124 views::View* view, 125 ui::AccessibilityTypes::Event event, 126 Profile* profile); 127 static void SendSliderNotification( 128 views::View* view, 129 ui::AccessibilityTypes::Event event, 130 Profile* profile); 131 static void SendAlertControlNotification( 132 views::View* view, 133 ui::AccessibilityTypes::Event event, 134 Profile* profile); 135 136 // Return the name of a view. 137 static std::string GetViewName(views::View* view); 138 139 // Get the context of a view - the name of the enclosing group, toolbar, etc. 140 static std::string GetViewContext(views::View* view); 141 142 // Return a descendant of this view with a given accessible role, if found. 143 static views::View* FindDescendantWithAccessibleRole( 144 views::View* view, 145 ui::AccessibilityTypes::Role role); 146 147 // Recursively explore all menu items of |menu| and return in |count| 148 // the total number of items, and in |index| the 0-based index of 149 // |item|, if found. Initialize |count| to zero before calling this 150 // method. |index| will be unchanged if the item is not found, so 151 // initialize it to -1 to detect this case. 152 static void RecursiveGetMenuItemIndexAndCount(views::View* menu, 153 views::View* item, 154 int* index, 155 int* count); 156 157 // Recursively explore the subviews and return the text from the first 158 // subview with a role of STATIC_TEXT. 159 static std::string RecursiveGetStaticText(views::View* view); 160 161 // The profile associated with the most recent window event - used to 162 // figure out where to route a few events that can't be directly traced 163 // to a window with a profile (like menu events). 164 Profile* most_recent_profile_; 165 166 // Notification registrar so we can clear most_recent_profile_ when a 167 // profile is destroyed. 168 content::NotificationRegistrar registrar_; 169 170 DISALLOW_COPY_AND_ASSIGN(AccessibilityEventRouterViews); 171}; 172 173#endif // CHROME_BROWSER_UI_VIEWS_ACCESSIBILITY_ACCESSIBILITY_EVENT_ROUTER_VIEWS_H_ 174