Chromium Code Reviews| Index: content/browser/accessibility/browser_accessibility_manager_android.cc |
| diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc |
| index 50238249d9767846b77a602dac1fa37e1159bf59..e4c86340e7b95db4003ff842d003f0bef6b0482b 100644 |
| --- a/content/browser/accessibility/browser_accessibility_manager_android.cc |
| +++ b/content/browser/accessibility/browser_accessibility_manager_android.cc |
| @@ -10,13 +10,16 @@ |
| #include "base/android/jni_android.h" |
| #include "base/android/jni_string.h" |
| +#include "base/feature_list.h" |
| #include "base/i18n/char_iterator.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/values.h" |
| +#include "content/app/strings/grit/content_strings.h" |
| #include "content/browser/accessibility/browser_accessibility_android.h" |
| #include "content/browser/accessibility/one_shot_accessibility_tree_search.h" |
| #include "content/common/accessibility_messages.h" |
| +#include "content/public/common/content_features.h" |
| #include "jni/BrowserAccessibilityManager_jni.h" |
| #include "ui/accessibility/ax_text_utils.h" |
| @@ -117,6 +120,22 @@ AccessibilityMatchPredicate PredicateForSearchKey( |
| return AllInterestingNodesPredicate; |
| } |
| +// The element in the document for which we may be displaying an autofill popup. |
| +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.
|
| + |
| +// Autofill popup will not be part of the |AXTree| that is sent by renderer. |
| +// Hence, we need a proxy |AXNode| to represent the autofill popup. |
| +BrowserAccessibility* g_autofill_popup_proxy_node_ = nullptr; |
| +ui::AXNode* g_autofill_popup_proxy_node_ax_node_ = nullptr; |
| + |
| +void DeleteAutofillPopupProxy() { |
| + if (g_autofill_popup_proxy_node_) { |
| + g_autofill_popup_proxy_node_->Destroy(); |
| + delete g_autofill_popup_proxy_node_ax_node_; |
| + g_autofill_popup_proxy_node_ = nullptr; |
| + } |
| +} |
| + |
| } // anonymous namespace |
| namespace aria_strings { |
| @@ -155,6 +174,9 @@ BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() { |
| if (obj.is_null()) |
| return; |
| + // Clean up autofill popup proxy node in case the popup was not dismissed. |
| + DeleteAutofillPopupProxy(); |
| + |
| Java_BrowserAccessibilityManager_onNativeObjectDestroyed( |
| env, obj, reinterpret_cast<intptr_t>(this)); |
| } |
| @@ -743,6 +765,14 @@ jint BrowserAccessibilityManagerAndroid::FindElementType( |
| jint start_id, |
| const JavaParamRef<jstring>& element_type_str, |
| jboolean forwards) { |
| + // Navigate forwards to the autofill popup's proxy node if focus is currently |
| + // on the element hosting the autofill popup. Once within the popup, a back |
| + // press will navigate back to the element hosting the popup. |
| + if (forwards && start_id == g_element_hosting_autofill_popup_id_ && |
| + g_autofill_popup_proxy_node_) { |
| + return g_autofill_popup_proxy_node_->unique_id(); |
| + } |
| + |
| BrowserAccessibilityAndroid* start_node = GetFromUniqueID(start_id); |
| if (!start_node) |
| return 0; |
| @@ -918,10 +948,8 @@ void BrowserAccessibilityManagerAndroid::SetAccessibilityFocus( |
| const JavaParamRef<jobject>& obj, |
| jint id) { |
| BrowserAccessibilityAndroid* node = GetFromUniqueID(id); |
| - if (!node) |
| - return; |
| - |
| - node->manager()->SetAccessibilityFocus(*node); |
| + if (node) |
| + node->manager()->SetAccessibilityFocus(*node); |
| } |
| bool BrowserAccessibilityManagerAndroid::IsSlider( |
| @@ -935,6 +963,49 @@ bool BrowserAccessibilityManagerAndroid::IsSlider( |
| return node->GetRole() == ui::AX_ROLE_SLIDER; |
| } |
| +void BrowserAccessibilityManagerAndroid::OnAutofillPopupDisplayed( |
| + JNIEnv* env, |
| + const JavaParamRef<jobject>& obj) { |
| + if (!base::FeatureList::IsEnabled(features::kAndroidAutofillAccessibility)) |
| + return; |
| + |
| + BrowserAccessibility* current_focus = GetFocus(); |
| + if (current_focus == nullptr) { |
| + return; |
| + } |
| + |
| + DeleteAutofillPopupProxy(); |
| + |
| + g_autofill_popup_proxy_node_ = BrowserAccessibility::Create(); |
| + g_autofill_popup_proxy_node_ax_node_ = new ui::AXNode(nullptr, -1, -1); |
| + ui::AXNodeData ax_node_data; |
| + ax_node_data.role = ui::AX_ROLE_MENU; |
| + ax_node_data.SetName("Autofill"); |
| + ax_node_data.state = 1 << ui::AX_STATE_READ_ONLY; |
| + ax_node_data.state |= 1 << ui::AX_STATE_FOCUSABLE; |
| + ax_node_data.state |= 1 << ui::AX_STATE_SELECTABLE; |
| + g_autofill_popup_proxy_node_ax_node_->SetData(ax_node_data); |
| + g_autofill_popup_proxy_node_->Init(this, |
| + g_autofill_popup_proxy_node_ax_node_); |
| + |
| + 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.
|
| +} |
| + |
| +void BrowserAccessibilityManagerAndroid::OnAutofillPopupDismissed( |
| + JNIEnv* env, |
| + const JavaParamRef<jobject>& obj) { |
| + g_element_hosting_autofill_popup_id_ = -1; |
| + DeleteAutofillPopupProxy(); |
| +} |
| + |
| +jboolean BrowserAccessibilityManagerAndroid::IsAutofillPopupNode( |
| + JNIEnv* env, |
| + const JavaParamRef<jobject>& obj, |
| + jint id) { |
| + return g_autofill_popup_proxy_node_ && |
| + g_autofill_popup_proxy_node_->unique_id() == id; |
| +} |
| + |
| bool BrowserAccessibilityManagerAndroid::Scroll( |
| JNIEnv* env, |
| const JavaParamRef<jobject>& obj, |