Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(533)

Side by Side Diff: content/browser/accessibility/browser_accessibility_manager_android.cc

Issue 2762123006: Android Autofill Accessibility, Phase I (Closed)
Patch Set: Adds android autofill accessibility to about-flags.cc Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/accessibility/browser_accessibility_manager_android.h" 5 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <cmath> 9 #include <cmath>
10 10
11 #include "base/android/jni_android.h" 11 #include "base/android/jni_android.h"
12 #include "base/android/jni_string.h" 12 #include "base/android/jni_string.h"
13 #include "base/feature_list.h"
13 #include "base/i18n/char_iterator.h" 14 #include "base/i18n/char_iterator.h"
14 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
16 #include "base/values.h" 17 #include "base/values.h"
18 #include "content/app/strings/grit/content_strings.h"
17 #include "content/browser/accessibility/browser_accessibility_android.h" 19 #include "content/browser/accessibility/browser_accessibility_android.h"
18 #include "content/browser/accessibility/one_shot_accessibility_tree_search.h" 20 #include "content/browser/accessibility/one_shot_accessibility_tree_search.h"
19 #include "content/common/accessibility_messages.h" 21 #include "content/common/accessibility_messages.h"
22 #include "content/public/common/content_features.h"
20 #include "jni/BrowserAccessibilityManager_jni.h" 23 #include "jni/BrowserAccessibilityManager_jni.h"
21 #include "ui/accessibility/ax_text_utils.h" 24 #include "ui/accessibility/ax_text_utils.h"
22 25
23 using base::android::AttachCurrentThread; 26 using base::android::AttachCurrentThread;
24 using base::android::JavaParamRef; 27 using base::android::JavaParamRef;
25 using base::android::ScopedJavaLocalRef; 28 using base::android::ScopedJavaLocalRef;
26 29
27 namespace content { 30 namespace content {
28 31
29 namespace { 32 namespace {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 InitSearchKeyToPredicateMapIfNeeded(); 113 InitSearchKeyToPredicateMapIfNeeded();
111 const auto& iter = g_search_key_to_predicate_map.Get().find(element_type); 114 const auto& iter = g_search_key_to_predicate_map.Get().find(element_type);
112 if (iter != g_search_key_to_predicate_map.Get().end()) 115 if (iter != g_search_key_to_predicate_map.Get().end())
113 return iter->second; 116 return iter->second;
114 117
115 // If we don't recognize the selector, return any element that a 118 // If we don't recognize the selector, return any element that a
116 // screen reader should navigate to. 119 // screen reader should navigate to.
117 return AllInterestingNodesPredicate; 120 return AllInterestingNodesPredicate;
118 } 121 }
119 122
123 // The element in the document for which we may be displaying an autofill popup.
124 int32_t g_element_hosting_autofill_popup_id_ = -1;
dmazzoni 2017/03/29 17:28:43 Nit: no training underscore on globals, only on cl
csashi 2017/03/29 18:26:27 Done.
125
126 // Autofill popup will not be part of the |AXTree| that is sent by renderer.
127 // Hence, we need a proxy |AXNode| to represent the autofill popup.
128 BrowserAccessibility* g_autofill_popup_proxy_node_ = nullptr;
129 ui::AXNode* g_autofill_popup_proxy_node_ax_node_ = nullptr;
130
131 void DeleteAutofillPopupProxy() {
132 if (g_autofill_popup_proxy_node_) {
133 g_autofill_popup_proxy_node_->Destroy();
134 delete g_autofill_popup_proxy_node_ax_node_;
135 g_autofill_popup_proxy_node_ = nullptr;
136 }
137 }
138
120 } // anonymous namespace 139 } // anonymous namespace
121 140
122 namespace aria_strings { 141 namespace aria_strings {
123 const char kAriaLivePolite[] = "polite"; 142 const char kAriaLivePolite[] = "polite";
124 const char kAriaLiveAssertive[] = "assertive"; 143 const char kAriaLiveAssertive[] = "assertive";
125 } 144 }
126 145
127 // static 146 // static
128 BrowserAccessibilityManager* BrowserAccessibilityManager::Create( 147 BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
129 const ui::AXTreeUpdate& initial_tree, 148 const ui::AXTreeUpdate& initial_tree,
(...skipping 18 matching lines...) Expand all
148 Initialize(initial_tree); 167 Initialize(initial_tree);
149 SetContentViewCore(content_view_core); 168 SetContentViewCore(content_view_core);
150 } 169 }
151 170
152 BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() { 171 BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() {
153 JNIEnv* env = AttachCurrentThread(); 172 JNIEnv* env = AttachCurrentThread();
154 ScopedJavaLocalRef<jobject> obj = GetJavaRefFromRootManager(); 173 ScopedJavaLocalRef<jobject> obj = GetJavaRefFromRootManager();
155 if (obj.is_null()) 174 if (obj.is_null())
156 return; 175 return;
157 176
177 // Clean up autofill popup proxy node in case the popup was not dismissed.
178 DeleteAutofillPopupProxy();
179
158 Java_BrowserAccessibilityManager_onNativeObjectDestroyed( 180 Java_BrowserAccessibilityManager_onNativeObjectDestroyed(
159 env, obj, reinterpret_cast<intptr_t>(this)); 181 env, obj, reinterpret_cast<intptr_t>(this));
160 } 182 }
161 183
162 // static 184 // static
163 ui::AXTreeUpdate 185 ui::AXTreeUpdate
164 BrowserAccessibilityManagerAndroid::GetEmptyDocument() { 186 BrowserAccessibilityManagerAndroid::GetEmptyDocument() {
165 ui::AXNodeData empty_document; 187 ui::AXNodeData empty_document;
166 empty_document.id = 0; 188 empty_document.id = 0;
167 empty_document.role = ui::AX_ROLE_ROOT_WEB_AREA; 189 empty_document.role = ui::AX_ROLE_ROOT_WEB_AREA;
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 env, obj, android_node->unique_id()); 758 env, obj, android_node->unique_id());
737 } 759 }
738 } 760 }
739 761
740 jint BrowserAccessibilityManagerAndroid::FindElementType( 762 jint BrowserAccessibilityManagerAndroid::FindElementType(
741 JNIEnv* env, 763 JNIEnv* env,
742 const JavaParamRef<jobject>& obj, 764 const JavaParamRef<jobject>& obj,
743 jint start_id, 765 jint start_id,
744 const JavaParamRef<jstring>& element_type_str, 766 const JavaParamRef<jstring>& element_type_str,
745 jboolean forwards) { 767 jboolean forwards) {
768 // Navigate forwards to the autofill popup's proxy node if focus is currently
769 // on the element hosting the autofill popup. Once within the popup, a back
770 // press will navigate back to the element hosting the popup.
771 if (forwards && start_id == g_element_hosting_autofill_popup_id_ &&
772 g_autofill_popup_proxy_node_) {
773 return g_autofill_popup_proxy_node_->unique_id();
774 }
775
746 BrowserAccessibilityAndroid* start_node = GetFromUniqueID(start_id); 776 BrowserAccessibilityAndroid* start_node = GetFromUniqueID(start_id);
747 if (!start_node) 777 if (!start_node)
748 return 0; 778 return 0;
749 779
750 BrowserAccessibilityManager* root_manager = GetRootManager(); 780 BrowserAccessibilityManager* root_manager = GetRootManager();
751 if (!root_manager) 781 if (!root_manager)
752 return 0; 782 return 0;
753 783
754 BrowserAccessibility* root = root_manager->GetRoot(); 784 BrowserAccessibility* root = root_manager->GetRoot();
755 if (!root) 785 if (!root)
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 } 941 }
912 942
913 return true; 943 return true;
914 } 944 }
915 945
916 void BrowserAccessibilityManagerAndroid::SetAccessibilityFocus( 946 void BrowserAccessibilityManagerAndroid::SetAccessibilityFocus(
917 JNIEnv* env, 947 JNIEnv* env,
918 const JavaParamRef<jobject>& obj, 948 const JavaParamRef<jobject>& obj,
919 jint id) { 949 jint id) {
920 BrowserAccessibilityAndroid* node = GetFromUniqueID(id); 950 BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
921 if (!node) 951 if (node)
922 return; 952 node->manager()->SetAccessibilityFocus(*node);
923
924 node->manager()->SetAccessibilityFocus(*node);
925 } 953 }
926 954
927 bool BrowserAccessibilityManagerAndroid::IsSlider( 955 bool BrowserAccessibilityManagerAndroid::IsSlider(
928 JNIEnv* env, 956 JNIEnv* env,
929 const JavaParamRef<jobject>& obj, 957 const JavaParamRef<jobject>& obj,
930 jint id) { 958 jint id) {
931 BrowserAccessibilityAndroid* node = GetFromUniqueID(id); 959 BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
932 if (!node) 960 if (!node)
933 return false; 961 return false;
934 962
935 return node->GetRole() == ui::AX_ROLE_SLIDER; 963 return node->GetRole() == ui::AX_ROLE_SLIDER;
936 } 964 }
937 965
966 void BrowserAccessibilityManagerAndroid::OnAutofillPopupDisplayed(
967 JNIEnv* env,
968 const JavaParamRef<jobject>& obj) {
969 if (!base::FeatureList::IsEnabled(features::kAndroidAutofillAccessibility))
970 return;
971
972 BrowserAccessibility* current_focus = GetFocus();
973 if (current_focus == nullptr) {
974 return;
975 }
976
977 DeleteAutofillPopupProxy();
978
979 g_autofill_popup_proxy_node_ = BrowserAccessibility::Create();
980 g_autofill_popup_proxy_node_ax_node_ = new ui::AXNode(nullptr, -1, -1);
981 ui::AXNodeData ax_node_data;
982 ax_node_data.role = ui::AX_ROLE_MENU;
983 ax_node_data.SetName("Autofill");
984 ax_node_data.state = 1 << ui::AX_STATE_READ_ONLY;
985 ax_node_data.state |= 1 << ui::AX_STATE_FOCUSABLE;
986 ax_node_data.state |= 1 << ui::AX_STATE_SELECTABLE;
987 g_autofill_popup_proxy_node_ax_node_->SetData(ax_node_data);
988 g_autofill_popup_proxy_node_->Init(this,
989 g_autofill_popup_proxy_node_ax_node_);
990
991 g_element_hosting_autofill_popup_id_ = current_focus->unique_id();
dmazzoni 2017/03/29 17:28:43 Rename g_element_hosting_autofill_popup_id_ g_elem
csashi 2017/03/29 18:26:27 Done.
992 }
993
994 void BrowserAccessibilityManagerAndroid::OnAutofillPopupDismissed(
995 JNIEnv* env,
996 const JavaParamRef<jobject>& obj) {
997 g_element_hosting_autofill_popup_id_ = -1;
998 DeleteAutofillPopupProxy();
999 }
1000
1001 jboolean BrowserAccessibilityManagerAndroid::IsAutofillPopupNode(
1002 JNIEnv* env,
1003 const JavaParamRef<jobject>& obj,
1004 jint id) {
1005 return g_autofill_popup_proxy_node_ &&
1006 g_autofill_popup_proxy_node_->unique_id() == id;
1007 }
1008
938 bool BrowserAccessibilityManagerAndroid::Scroll( 1009 bool BrowserAccessibilityManagerAndroid::Scroll(
939 JNIEnv* env, 1010 JNIEnv* env,
940 const JavaParamRef<jobject>& obj, 1011 const JavaParamRef<jobject>& obj,
941 jint id, 1012 jint id,
942 int direction) { 1013 int direction) {
943 BrowserAccessibilityAndroid* node = GetFromUniqueID(id); 1014 BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
944 if (!node) 1015 if (!node)
945 return false; 1016 return false;
946 1017
947 return node->Scroll(direction); 1018 return node->Scroll(direction);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 1057
987 JNIEnv* env = AttachCurrentThread(); 1058 JNIEnv* env = AttachCurrentThread();
988 return root_manager->java_ref().get(env); 1059 return root_manager->java_ref().get(env);
989 } 1060 }
990 1061
991 bool RegisterBrowserAccessibilityManager(JNIEnv* env) { 1062 bool RegisterBrowserAccessibilityManager(JNIEnv* env) {
992 return RegisterNativesImpl(env); 1063 return RegisterNativesImpl(env);
993 } 1064 }
994 1065
995 } // namespace content 1066 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698