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