summaryrefslogtreecommitdiffstats
path: root/content/browser/accessibility/browser_accessibility_manager_android.h
blob: 4c69b236ccc35ec9a0af440a1fb307ae7da3fcba (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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Copyright 2013 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 CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_ANDROID_H_
#define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_ANDROID_H_

#include "base/android/scoped_java_ref.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/android/content_view_core_impl.h"

namespace content {

namespace aria_strings {
  extern const char kAriaLivePolite[];
  extern const char kAriaLiveAssertive[];
}

// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content.browser.accessibility
enum ScrollDirection {
  FORWARD,
  BACKWARD,
  UP,
  DOWN,
  LEFT,
  RIGHT
};

// From android.view.accessibility.AccessibilityNodeInfo in Java:
enum AndroidMovementGranularity {
  ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_CHARACTER = 1,
  ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_WORD = 2,
  ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_LINE = 4
};

// From android.view.accessibility.AccessibilityEvent in Java:
enum {
  ANDROID_ACCESSIBILITY_EVENT_TEXT_CHANGED = 16,
  ANDROID_ACCESSIBILITY_EVENT_TEXT_SELECTION_CHANGED = 8192,
  ANDROID_ACCESSIBILITY_EVENT_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 131072
};

class BrowserAccessibilityAndroid;

class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
    : public BrowserAccessibilityManager {
 public:
  BrowserAccessibilityManagerAndroid(
      base::android::ScopedJavaLocalRef<jobject> content_view_core,
      const ui::AXTreeUpdate& initial_tree,
      BrowserAccessibilityDelegate* delegate,
      BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactory());

  ~BrowserAccessibilityManagerAndroid() override;

  static ui::AXTreeUpdate GetEmptyDocument();

  void SetContentViewCore(
      base::android::ScopedJavaLocalRef<jobject> content_view_core);

  // By default, the tree is pruned for a better screen reading experience,
  // including:
  //   * If the node has only static text children
  //   * If the node is focusable and has no focusable children
  //   * If the node is a heading
  // This can be turned off to generate a tree that more accurately reflects
  // the DOM and includes style changes within these nodes.
  void set_prune_tree_for_screen_reader(bool prune) {
    prune_tree_for_screen_reader_ = prune;
  }
  bool prune_tree_for_screen_reader() { return prune_tree_for_screen_reader_; }

  // Implementation of BrowserAccessibilityManager.
  void NotifyAccessibilityEvent(ui::AXEvent event_type,
                                BrowserAccessibility* node) override;

  // --------------------------------------------------------------------------
  // Methods called from Java via JNI
  // --------------------------------------------------------------------------

  // Tree methods.
  jint GetRootId(JNIEnv* env, jobject obj);
  jboolean IsNodeValid(JNIEnv* env, jobject obj, jint id);
  void HitTest(JNIEnv* env, jobject obj, jint x, jint y);

  // Methods to get information about a specific node.
  jboolean IsEditableText(JNIEnv* env, jobject obj, jint id);
  jint GetEditableTextSelectionStart(JNIEnv* env, jobject obj, jint id);
  jint GetEditableTextSelectionEnd(JNIEnv* env, jobject obj, jint id);

  // Populate Java accessibility data structures with info about a node.
  jboolean PopulateAccessibilityNodeInfo(
      JNIEnv* env, jobject obj, jobject info, jint id);
  jboolean PopulateAccessibilityEvent(
      JNIEnv* env, jobject obj, jobject event, jint id, jint event_type);

  // Perform actions.
  void Click(JNIEnv* env, jobject obj, jint id);
  void Focus(JNIEnv* env, jobject obj, jint id);
  void Blur(JNIEnv* env, jobject obj);
  void ScrollToMakeNodeVisible(JNIEnv* env, jobject obj, jint id);
  void SetTextFieldValue(JNIEnv* env, jobject obj, jint id, jstring value);
  void SetSelection(JNIEnv* env, jobject obj, jint id, jint start, jint end);
  jboolean AdjustSlider(JNIEnv* env, jobject obj, jint id, jboolean increment);

  // Return the id of the next node in tree order in the direction given by
  // |forwards|, starting with |start_id|, that matches |element_type|,
  // where |element_type| is a special uppercase string from TalkBack or
  // BrailleBack indicating general categories of web content like
  // "SECTION" or "CONTROL".  Return 0 if not found.
  jint FindElementType(JNIEnv* env, jobject obj, jint start_id,
                       jstring element_type, jboolean forwards);

  // Respond to a ACTION_[NEXT/PREVIOUS]_AT_MOVEMENT_GRANULARITY action
  // and move the cursor/selection within the given node id. We keep track
  // of our own selection in BrowserAccessibilityManager.java for static
  // text, but if this is an editable text node, updates the selected text
  // in Blink, too, and either way calls
  // Java_BrowserAccessibilityManager_finishGranularityMove with the
  // result.
  jboolean NextAtGranularity(JNIEnv* env, jobject obj,
                             jint granularity, jboolean extend_selection,
                             jint id, jint cursor_index);
  jboolean PreviousAtGranularity(JNIEnv* env, jobject obj,
                                 jint granularity, jboolean extend_selection,
                                 jint id, jint cursor_index);

  // Helper functions to compute the next start and end index when moving
  // forwards or backwards by character, word, or line. This part is
  // unit-tested; the Java interfaces above are just wrappers. Both of these
  // take a single cursor index as input and return the boundaries surrounding
  // the next word or line. If moving by character, the output start and
  // end index will be the same.
  bool NextAtGranularity(
      int32 granularity, int cursor_index,
      BrowserAccessibilityAndroid* node, int32* start_index, int32* end_index);
  bool PreviousAtGranularity(
      int32 granularity, int cursor_index,
      BrowserAccessibilityAndroid* node, int32* start_index, int32* end_index);

  // Set accessibility focus. This sends a message to the renderer to
  // asynchronously load inline text boxes for this node only, enabling more
  // accurate movement by granularities on this node.
  void SetAccessibilityFocus(JNIEnv* env, jobject obj, jint id);

  // Returns true if the object is a slider.
  bool IsSlider(JNIEnv* env, jobject obj, jint id);

  // Scrolls any scrollable container by about 80% of one page in the
  // given direction.
  bool Scroll(JNIEnv* env, jobject obj, jint id, int direction);

 protected:
  // AXTreeDelegate overrides.
  void OnAtomicUpdateFinished(
      ui::AXTree* tree,
      bool root_changed,
      const std::vector<ui::AXTreeDelegate::Change>& changes) override;

  bool UseRootScrollOffsetsWhenComputingBounds() override;

 private:
  // This gives BrowserAccessibilityManager::Create access to the class
  // constructor.
  friend class BrowserAccessibilityManager;

  // A weak reference to the Java BrowserAccessibilityManager object.
  // This avoids adding another reference to BrowserAccessibilityManager and
  // preventing garbage collection.
  // Premature garbage collection is prevented by the long-lived reference in
  // ContentViewCore.
  JavaObjectWeakGlobalRef java_ref_;

  // Handle a hover event from the renderer process.
  void HandleHoverEvent(BrowserAccessibility* node);

  // See docs for set_prune_tree_for_screen_reader, above.
  bool prune_tree_for_screen_reader_;

  DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerAndroid);
};

bool RegisterBrowserAccessibilityManager(JNIEnv* env);

}

#endif  // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_ANDROID_H_