summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/views/accessibility_event_router_views.h
blob: bdf4b34d99d4a0de81cbf1c86795dc400e242316 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_VIEWS_ACCESSIBILITY_EVENT_ROUTER_VIEWS_H_
#define CHROME_BROWSER_UI_VIEWS_ACCESSIBILITY_EVENT_ROUTER_VIEWS_H_
#pragma once

#include <string>

#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/singleton.h"
#include "base/task.h"
#include "chrome/browser/accessibility_events.h"
#include "ui/base/accessibility/accessibility_types.h"

class Profile;
namespace views {
class View;
}

// NOTE: This class is part of the Accessibility Extension API, which lets
// extensions receive accessibility events. It's distinct from code that
// implements platform accessibility APIs like MSAA or ATK.
//
// Singleton class that adds listeners to many views, then sends an
// accessibility notification whenever a relevant event occurs in an
// accessible view.
//
// Views are not accessible by default. When you register a root widget,
// that widget and all of its descendants will start sending accessibility
// event notifications. You can then override the default behavior for
// specific descendants using other methods.
//
// You can use Profile::PauseAccessibilityEvents to prevent a flurry
// of accessibility events when a window is being created or initialized.
class AccessibilityEventRouterViews {
 public:
  // Internal information about a particular view to override the
  // information we get directly from the view.
  struct ViewInfo {
    ViewInfo() : ignore(false) {}

    // If nonempty, will use this name instead of the view's label.
    std::string name;

    // If true, will ignore this widget and not send accessibility events.
    bool ignore;
  };

  // Get the single instance of this class.
  static AccessibilityEventRouterViews* GetInstance();

  // Handle an accessibility event generated by a view.
  void HandleAccessibilityEvent(
      views::View* view, ui::AccessibilityTypes::Event event_type);

  // Handle a menu item being focused (separate because a menu item is
  // not necessarily its own view).
  void HandleMenuItemFocused(
      const std::wstring& menu_name,
      const std::wstring& menu_item_name,
      int item_index,
      int item_count,
      bool has_submenu);

 private:
  AccessibilityEventRouterViews();
  virtual ~AccessibilityEventRouterViews();

  friend struct DefaultSingletonTraits<AccessibilityEventRouterViews>;
  FRIEND_TEST_ALL_PREFIXES(AccessibilityEventRouterViewsTest,
                           TestFocusNotification);

  // Checks the type of the view and calls one of the more specific
  // Send*Notification methods, below.
  void DispatchAccessibilityNotification(
      views::View* view, NotificationType type);

  // Return the name of a view.
  std::string GetViewName(views::View* view);

  // Each of these methods constructs an AccessibilityControlInfo object
  // and sends a notification of a specific accessibility event.
  void SendButtonNotification(
      views::View* view, NotificationType type, Profile* profile);
  void SendLinkNotification(
      views::View* view, NotificationType type, Profile* profile);
  void SendMenuNotification(
      views::View* view, NotificationType type, Profile* profile);
  void SendMenuItemNotification(
      views::View* view, NotificationType type, Profile* profile);
  void SendLocationBarNotification(
      views::View* view, NotificationType type, Profile* profile);
  void SendTextfieldNotification(
      views::View* view, NotificationType type, Profile* profile);
  void SendComboboxNotification(
      views::View* view, NotificationType type, Profile* profile);

  // Return true if it's an event on a menu.
  bool IsMenuEvent(views::View* view, NotificationType type);

  // Recursively explore all menu items of |menu| and return in |count|
  // the total number of items, and in |index| the 0-based index of
  // |item|, if found. Initialize |count| to zero before calling this
  // method. |index| will be unchanged if the item is not found, so
  // initialize it to -1 to detect this case.
  void RecursiveGetMenuItemIndexAndCount(
      views::View* menu, views::View* item, int* index, int* count);

  // The profile associated with the most recent window event  - used to
  // figure out where to route a few events that can't be directly traced
  // to a window with a profile (like menu events).
  Profile* most_recent_profile_;

  // Used to defer handling of some events until the next time
  // through the event loop.
  ScopedRunnableMethodFactory<AccessibilityEventRouterViews> method_factory_;
};

#endif  // CHROME_BROWSER_UI_VIEWS_ACCESSIBILITY_EVENT_ROUTER_VIEWS_H_