diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index f3be82aed96acbaca4efcb6f816cd2f4a446927a..959f3937530096b938a464e5f55f46443d2481db 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc @@ -340,8 +340,16 @@ void AutofillAgent::FocusedElementChanged(const WebElement& element) { if ((IsKeyboardAccessoryEnabled() || !focus_requires_scroll_) && !element.IsNull() && element.GetDocument().GetFrame()->HasTransientUserActivation()) { - focused_node_was_last_clicked_ = true; - HandleFocusChangeComplete(); + // If the focus change was caused by a user gesture, + // DidReceiveLeftMouseDownOrGestureTapInNode() will show the autofill + // suggestions. See crbug.com/730764 for why showing autofill suggestions as + // a result of JavaScript changing focus is enabled on WebView. + bool focused_node_was_last_clicked = + !base::FeatureList::IsEnabled( + features::kAutofillAndroidDisableSuggestionsOnJSFocus) || + !focus_requires_scroll_; + HandleFocusChangeComplete( + /*focused_node_was_last_clicked=*/focused_node_was_last_clicked); } if (focus_moved_to_new_form) @@ -1031,7 +1039,10 @@ void AutofillAgent::DidCompleteFocusChangeInFrame() { } if (!IsKeyboardAccessoryEnabled() && focus_requires_scroll_) - HandleFocusChangeComplete(); + HandleFocusChangeComplete( + /*focused_node_was_last_clicked=*/ + last_left_mouse_down_or_gesture_tap_in_node_caused_focus_); + last_left_mouse_down_or_gesture_tap_in_node_caused_focus_ = false; SendPotentiallySubmittedFormToBrowser(); } @@ -1039,14 +1050,10 @@ void AutofillAgent::DidCompleteFocusChangeInFrame() { void AutofillAgent::DidReceiveLeftMouseDownOrGestureTapInNode( const WebNode& node) { DCHECK(!node.IsNull()); - focused_node_was_last_clicked_ = node.Focused(); - #if defined(ANDROID) - HandleFocusChangeComplete(); + HandleFocusChangeComplete(/*focused_node_was_last_clicked=*/node.Focused()); #else - if (!focus_requires_scroll_) { - HandleFocusChangeComplete(); - } + last_left_mouse_down_or_gesture_tap_in_node_caused_focus_ = node.Focused(); #endif } @@ -1146,22 +1153,21 @@ void AutofillAgent::FormControlElementClicked( SendPotentiallySubmittedFormToBrowser(); } -void AutofillAgent::HandleFocusChangeComplete() { +void AutofillAgent::HandleFocusChangeComplete( + bool focused_node_was_last_clicked) { WebElement focused_element = render_frame()->GetWebFrame()->GetDocument().FocusedElement(); // When using Talkback on Android, and possibly others, traversing to and // focusing a field will not register as a click. Thus, when screen readers // are used, treat the focused node as if it was the last clicked. Also check // to ensure focus is on a field where text can be entered. - if ((focused_node_was_last_clicked_ || is_screen_reader_enabled_) && + if ((focused_node_was_last_clicked || is_screen_reader_enabled_) && !focused_element.IsNull() && focused_element.IsFormControlElement() && (form_util::IsTextInput(blink::ToWebInputElement(&focused_element)) || focused_element.HasHTMLTagName("textarea"))) { FormControlElementClicked(focused_element.ToConst()); } - focused_node_was_last_clicked_ = false; - SendPotentiallySubmittedFormToBrowser(); } diff --git a/components/autofill/content/renderer/autofill_agent.h b/components/autofill/content/renderer/autofill_agent.h index 5fb4867be2c4ba7bbd6cc535aa032765ffbe7e68..94b4380f88a6353ebdbe81d354504ab7cf2837ce 100644 --- a/components/autofill/content/renderer/autofill_agent.h +++ b/components/autofill/content/renderer/autofill_agent.h @@ -225,7 +225,7 @@ class AutofillAgent : public content::RenderFrameObserver, void FormElementReset(const blink::WebFormElement& form) override; void PasswordFieldReset(const blink::WebInputElement& element) override; - void HandleFocusChangeComplete(); + void HandleFocusChangeComplete(bool focused_node_was_last_clicked); // Helper method which collects unowned elements (i.e., those not inside a // form tag) and writes them into |output|. Returns true if the process is @@ -377,7 +377,7 @@ class AutofillAgent : public content::RenderFrameObserver, // doesn't use PasswordAutofillAgent to handle password form. bool query_password_suggestion_ = false; - bool focused_node_was_last_clicked_ = false; + bool last_left_mouse_down_or_gesture_tap_in_node_caused_focus_= false; FieldRendererId last_clicked_form_control_element_for_testing_; FormTracker form_tracker_; diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index f0c121fb189b73a41764413b593e06a823ccca1f..50a2301990228a3ecee29677f71d0560cfb5b301 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc @@ -448,6 +448,18 @@ const base::FeatureParam kAutofillAblationStudyEnabledForPaymentsParam{ const base::FeatureParam kAutofillAblationStudyAblationWeightPerMilleParam{ &kAutofillEnableAblationStudy, "ablation_weight_per_mille", 10}; +// Controls whether user tap on an element is needed to show autofill +// suggestions. If enabled, this flag would disable android autofill suggestions +// if the focus on an element is Javascript-originated. +// DidReceiveLeftMouseDownOrGestureTapInNode() will show suggestions if the +// focus change occurred as a result of a gesture. See crbug.com/730764 for why +// showing autofill suggestions as a result of JavaScript changing focus is +// enabled on WebView. +// TODO(crbug.com/1496382) Clean up autofill feature flag +// `kAutofillAndroidDisableSuggestionsOnJSFocus` +extern const base::Feature kAutofillAndroidDisableSuggestionsOnJSFocus{ + "AutofillAndroidDisableSuggestionsOnJSFocus", base::FEATURE_DISABLED_BY_DEFAULT}; + #if BUILDFLAG(IS_ANDROID) // Controls whether the Autofill manual fallback for Addresses and Payments is // present on Android. diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 75b0fac36c111d44a321222b2195297c36ce84be..becca7d10e2f99bb3241061ca3bc4aa5c31746a6 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h @@ -171,6 +171,8 @@ extern const base::FeatureParam COMPONENT_EXPORT(AUTOFILL) extern const base::FeatureParam kAutofillAblationStudyAblationWeightPerMilleParam; +COMPONENT_EXPORT(AUTOFILL) +extern const base::Feature kAutofillAndroidDisableSuggestionsOnJSFocus; #if BUILDFLAG(IS_ANDROID) COMPONENT_EXPORT(AUTOFILL)