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

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

Issue 2762123006: Android Autofill Accessibility, Phase I (Closed)
Patch Set: Creates AX proxy node only if Android autofill accessibility is enabled. 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_client.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 element_hosting_autofill_popup_id_ = -1;
dmazzoni 2017/03/28 16:47:35 I think globals like this are typically named some
csashi 2017/03/28 17:48:10 Done.
125
126 // The element that currently has focus. Will be used to set
127 // |element_hosting_autofill_popup_id_| when we display an autofill popup.
128 int32_t current_focused_id_ = -1;
dmazzoni 2017/03/28 16:47:35 You don't need to keep track of this. Just call Ge
129
130 // Autofill popup will not be part of the |AXTree| that is sent by renderer.
131 // Hence, we need a proxy |AXNode| to represent the autofill popup.
132 BrowserAccessibility* autofill_popup_proxy_node_ = nullptr;
133 ui::AXNode* autofill_popup_proxy_node_ax_node_ = nullptr;
134
120 } // anonymous namespace 135 } // anonymous namespace
121 136
122 namespace aria_strings { 137 namespace aria_strings {
123 const char kAriaLivePolite[] = "polite"; 138 const char kAriaLivePolite[] = "polite";
124 const char kAriaLiveAssertive[] = "assertive"; 139 const char kAriaLiveAssertive[] = "assertive";
125 } 140 }
126 141
142 const base::Feature kAutofillAccessibility{"AndroidAutofillAccessibility",
143 base::FEATURE_DISABLED_BY_DEFAULT};
144
127 // static 145 // static
128 BrowserAccessibilityManager* BrowserAccessibilityManager::Create( 146 BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
129 const ui::AXTreeUpdate& initial_tree, 147 const ui::AXTreeUpdate& initial_tree,
130 BrowserAccessibilityDelegate* delegate, 148 BrowserAccessibilityDelegate* delegate,
131 BrowserAccessibilityFactory* factory) { 149 BrowserAccessibilityFactory* factory) {
132 return new BrowserAccessibilityManagerAndroid( 150 return new BrowserAccessibilityManagerAndroid(
133 ScopedJavaLocalRef<jobject>(), initial_tree, delegate, factory); 151 ScopedJavaLocalRef<jobject>(), initial_tree, delegate, factory);
134 } 152 }
135 153
136 BrowserAccessibilityManagerAndroid* 154 BrowserAccessibilityManagerAndroid*
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 if (node) 628 if (node)
611 node->manager()->DoDefaultAction(*node); 629 node->manager()->DoDefaultAction(*node);
612 } 630 }
613 631
614 void BrowserAccessibilityManagerAndroid::Focus(JNIEnv* env, 632 void BrowserAccessibilityManagerAndroid::Focus(JNIEnv* env,
615 const JavaParamRef<jobject>& obj, 633 const JavaParamRef<jobject>& obj,
616 jint id) { 634 jint id) {
617 BrowserAccessibilityAndroid* node = GetFromUniqueID(id); 635 BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
618 if (node) 636 if (node)
619 node->manager()->SetFocus(*node); 637 node->manager()->SetFocus(*node);
638 current_focused_id_ = id;
620 } 639 }
621 640
622 void BrowserAccessibilityManagerAndroid::Blur( 641 void BrowserAccessibilityManagerAndroid::Blur(
623 JNIEnv* env, 642 JNIEnv* env,
624 const JavaParamRef<jobject>& obj) { 643 const JavaParamRef<jobject>& obj) {
625 SetFocus(*GetRoot()); 644 SetFocus(*GetRoot());
626 } 645 }
627 646
628 void BrowserAccessibilityManagerAndroid::ScrollToMakeNodeVisible( 647 void BrowserAccessibilityManagerAndroid::ScrollToMakeNodeVisible(
629 JNIEnv* env, 648 JNIEnv* env,
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 env, obj, android_node->unique_id()); 755 env, obj, android_node->unique_id());
737 } 756 }
738 } 757 }
739 758
740 jint BrowserAccessibilityManagerAndroid::FindElementType( 759 jint BrowserAccessibilityManagerAndroid::FindElementType(
741 JNIEnv* env, 760 JNIEnv* env,
742 const JavaParamRef<jobject>& obj, 761 const JavaParamRef<jobject>& obj,
743 jint start_id, 762 jint start_id,
744 const JavaParamRef<jstring>& element_type_str, 763 const JavaParamRef<jstring>& element_type_str,
745 jboolean forwards) { 764 jboolean forwards) {
765 // Navigate forwards to the autofill popup's proxy node if focus is currently
766 // on the element hosting the autofill popup. Once within the popup, a back
767 // press will navigate back to the element hosting the popup.
768 if (forwards && start_id == element_hosting_autofill_popup_id_ &&
769 autofill_popup_proxy_node_) {
770 return autofill_popup_proxy_node_->unique_id();
771 }
772
746 BrowserAccessibilityAndroid* start_node = GetFromUniqueID(start_id); 773 BrowserAccessibilityAndroid* start_node = GetFromUniqueID(start_id);
747 if (!start_node) 774 if (!start_node)
748 return 0; 775 return 0;
749 776
750 BrowserAccessibilityManager* root_manager = GetRootManager(); 777 BrowserAccessibilityManager* root_manager = GetRootManager();
751 if (!root_manager) 778 if (!root_manager)
752 return 0; 779 return 0;
753 780
754 BrowserAccessibility* root = root_manager->GetRoot(); 781 BrowserAccessibility* root = root_manager->GetRoot();
755 if (!root) 782 if (!root)
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 } 938 }
912 939
913 return true; 940 return true;
914 } 941 }
915 942
916 void BrowserAccessibilityManagerAndroid::SetAccessibilityFocus( 943 void BrowserAccessibilityManagerAndroid::SetAccessibilityFocus(
917 JNIEnv* env, 944 JNIEnv* env,
918 const JavaParamRef<jobject>& obj, 945 const JavaParamRef<jobject>& obj,
919 jint id) { 946 jint id) {
920 BrowserAccessibilityAndroid* node = GetFromUniqueID(id); 947 BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
921 if (!node) 948 if (node)
922 return; 949 node->manager()->SetAccessibilityFocus(*node);
923
924 node->manager()->SetAccessibilityFocus(*node);
925 } 950 }
926 951
927 bool BrowserAccessibilityManagerAndroid::IsSlider( 952 bool BrowserAccessibilityManagerAndroid::IsSlider(
928 JNIEnv* env, 953 JNIEnv* env,
929 const JavaParamRef<jobject>& obj, 954 const JavaParamRef<jobject>& obj,
930 jint id) { 955 jint id) {
931 BrowserAccessibilityAndroid* node = GetFromUniqueID(id); 956 BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
932 if (!node) 957 if (!node)
933 return false; 958 return false;
934 959
935 return node->GetRole() == ui::AX_ROLE_SLIDER; 960 return node->GetRole() == ui::AX_ROLE_SLIDER;
936 } 961 }
937 962
963 void BrowserAccessibilityManagerAndroid::OnAutofillPopupDisplayed(
964 JNIEnv* env,
965 const JavaParamRef<jobject>& obj) {
966 if (!base::FeatureList::IsEnabled(kAutofillAccessibility))
967 return;
968
969 if (autofill_popup_proxy_node_) {
970 LOG(ERROR) << "AutofillPopup proxy node exists, unique_id="
dmazzoni 2017/03/28 16:47:35 Remove this debugging
csashi 2017/03/28 17:48:10 Done.
971 << autofill_popup_proxy_node_->unique_id();
972 OnAutofillPopupDismissed(env, obj);
973 }
974
975 autofill_popup_proxy_node_ = BrowserAccessibility::Create();
dmazzoni 2017/03/28 16:47:35 Do we need a check that this doesn't already exist
csashi 2017/03/28 17:48:10 The if statement above checks that.
976 autofill_popup_proxy_node_ax_node_ = new ui::AXNode(nullptr, -1, -1);
977 ui::AXNodeData ax_node_data;
978 ax_node_data.role = ui::AX_ROLE_MENU;
979 content::ContentClient* content_client = content::GetContentClient();
980 ax_node_data.SetName(content_client->GetLocalizedString(
981 IDS_AX_AUTOFILL_POPUP_ACCESSIBLE_NODE_DATA));
982 ax_node_data.state = 1 << ui::AX_STATE_READ_ONLY;
983 ax_node_data.state |= 1 << ui::AX_STATE_FOCUSABLE;
984 ax_node_data.state |= 1 << ui::AX_STATE_SELECTABLE;
985 autofill_popup_proxy_node_ax_node_->SetData(ax_node_data);
986 autofill_popup_proxy_node_->Init(this, autofill_popup_proxy_node_ax_node_);
987
988 element_hosting_autofill_popup_id_ = current_focused_id_;
dmazzoni 2017/03/28 16:47:35 Use GetFocus()->GetId() here
csashi 2017/03/28 17:48:10 Done.
989 }
990
991 void BrowserAccessibilityManagerAndroid::OnAutofillPopupDismissed(
992 JNIEnv* env,
993 const JavaParamRef<jobject>& obj) {
994 element_hosting_autofill_popup_id_ = -1;
995
996 if (autofill_popup_proxy_node_) {
dmazzoni 2017/03/28 16:47:35 Do we also need to clean this up if BrowserAccessi
csashi 2017/03/28 17:48:10 Done.
997 autofill_popup_proxy_node_->Destroy();
998 delete autofill_popup_proxy_node_ax_node_;
999 autofill_popup_proxy_node_ = nullptr;
1000 }
1001 }
1002
1003 jboolean BrowserAccessibilityManagerAndroid::IsAutofillPopupNode(
1004 JNIEnv* env,
1005 const JavaParamRef<jobject>& obj,
1006 jint id) {
1007 return autofill_popup_proxy_node_ &&
1008 autofill_popup_proxy_node_->unique_id() == id;
1009 }
1010
1011 jint BrowserAccessibilityManagerAndroid::GetElementHostingAutofillPopupId(
1012 JNIEnv* env,
1013 const base::android::JavaParamRef<jobject>& obj) {
1014 return autofill_popup_proxy_node_ ? autofill_popup_proxy_node_->unique_id()
1015 : -1;
1016 }
1017
938 bool BrowserAccessibilityManagerAndroid::Scroll( 1018 bool BrowserAccessibilityManagerAndroid::Scroll(
939 JNIEnv* env, 1019 JNIEnv* env,
940 const JavaParamRef<jobject>& obj, 1020 const JavaParamRef<jobject>& obj,
941 jint id, 1021 jint id,
942 int direction) { 1022 int direction) {
943 BrowserAccessibilityAndroid* node = GetFromUniqueID(id); 1023 BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
944 if (!node) 1024 if (!node)
945 return false; 1025 return false;
946 1026
947 return node->Scroll(direction); 1027 return node->Scroll(direction);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 1066
987 JNIEnv* env = AttachCurrentThread(); 1067 JNIEnv* env = AttachCurrentThread();
988 return root_manager->java_ref().get(env); 1068 return root_manager->java_ref().get(env);
989 } 1069 }
990 1070
991 bool RegisterBrowserAccessibilityManager(JNIEnv* env) { 1071 bool RegisterBrowserAccessibilityManager(JNIEnv* env) {
992 return RegisterNativesImpl(env); 1072 return RegisterNativesImpl(env);
993 } 1073 }
994 1074
995 } // namespace content 1075 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698