OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |