Commit d4119112 authored by Jan Wilken Dörrie's avatar Jan Wilken Dörrie Committed by Commit Bot

[Passwords] Add FormTracker::TrackAutofilledElement

This change adds a new TrackAutofilledElement() API to FormTracker,
allowing it to track elements that have been autofilled following a
user trigger.

Bug: 1140497
Change-Id: I4a772a01dfc33315be3110e17db1d169b834ead7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2517533
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Reviewed-by: default avatarChristoph Schwering <schwering@google.com>
Cr-Commit-Position: refs/heads/master@{#825392}
parent 4b10404d
...@@ -267,6 +267,10 @@ const char kDivWrappedFormHTML[] = ...@@ -267,6 +267,10 @@ const char kDivWrappedFormHTML[] =
" </DIV>" " </DIV>"
"</DIV>"; "</DIV>";
const char kJavaScriptRemoveForm[] =
"var form = document.getElementById('LoginTestForm');"
"form.parentNode.removeChild(form);";
// Sets the "readonly" attribute of |element| to the value given by |read_only|. // Sets the "readonly" attribute of |element| to the value given by |read_only|.
void SetElementReadOnly(WebInputElement& element, bool read_only) { void SetElementReadOnly(WebInputElement& element, bool read_only) {
element.SetAttribute(WebString::FromUTF8("readonly"), element.SetAttribute(WebString::FromUTF8("readonly"),
...@@ -3454,10 +3458,7 @@ TEST_F(PasswordAutofillAgentTest, ...@@ -3454,10 +3458,7 @@ TEST_F(PasswordAutofillAgentTest,
// Simulate that JavaScript removes the submitted form from DOM. That means // Simulate that JavaScript removes the submitted form from DOM. That means
// that a submission was successful. // that a submission was successful.
std::string remove_form = ExecuteJavaScriptForTests(kJavaScriptRemoveForm);
"var form = document.getElementById('LoginTestForm');"
"form.parentNode.removeChild(form);";
ExecuteJavaScriptForTests(remove_form.c_str());
FireDidFinishSameDocumentNavigation(); FireDidFinishSameDocumentNavigation();
...@@ -3962,4 +3963,35 @@ TEST_F(PasswordAutofillAgentTest, NoRefillOfUserInput) { ...@@ -3962,4 +3963,35 @@ TEST_F(PasswordAutofillAgentTest, NoRefillOfUserInput) {
false); false);
} }
// Tests that a JavaScript submission (e.g. via removing the form from a DOM)
// gets registered following a autofill after user trigger.
TEST_F(PasswordAutofillAgentTest, XhrSubmissionAfterFillingSuggestion) {
SimulateOnFillPasswordForm(fill_data_);
SimulateSuggestionChoiceOfUsernameAndPassword(username_element_,
ASCIIToUTF16(kBobUsername),
ASCIIToUTF16(kBobPassword));
// Simulate that JavaScript removes the submitted form from DOM. That means
// that a submission was successful.
ExecuteJavaScriptForTests(kJavaScriptRemoveForm);
ExpectSameDocumentNavigationWithUsernameAndPasswords(
fill_data_.form_renderer_id, kBobUsername, kBobPassword, std::string(),
SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR);
}
// Tests that a JavaScript submission (e.g. via removing the form from a DOM)
// does not get registered following a mere autofill on page load. This is
// necessary, because we potentially fill many forms on pageload, which the user
// likely won't interact with.
TEST_F(PasswordAutofillAgentTest, NoXhrSubmissionAfterFillingOnPageload) {
SimulateOnFillPasswordForm(fill_data_);
// Simulate that JavaScript removes the submitted form from DOM. That means
// that a submission was successful.
ExecuteJavaScriptForTests(kJavaScriptRemoveForm);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(fake_driver_.called_same_document_navigation());
}
} // namespace autofill } // namespace autofill
...@@ -1103,6 +1103,11 @@ void AutofillAgent::RemoveFormObserver(Observer* observer) { ...@@ -1103,6 +1103,11 @@ void AutofillAgent::RemoveFormObserver(Observer* observer) {
form_tracker_.RemoveObserver(observer); form_tracker_.RemoveObserver(observer);
} }
void AutofillAgent::TrackAutofilledElement(
const blink::WebFormControlElement& element) {
form_tracker_.TrackAutofilledElement(element);
}
base::Optional<FormData> AutofillAgent::GetSubmittedForm() const { base::Optional<FormData> AutofillAgent::GetSubmittedForm() const {
if (!last_interacted_form_.IsNull()) { if (!last_interacted_form_.IsNull()) {
FormData form; FormData form;
......
...@@ -118,6 +118,9 @@ class AutofillAgent : public content::RenderFrameObserver, ...@@ -118,6 +118,9 @@ class AutofillAgent : public content::RenderFrameObserver,
void AddFormObserver(Observer* observer); void AddFormObserver(Observer* observer);
void RemoveFormObserver(Observer* observer); void RemoveFormObserver(Observer* observer);
// Instructs `form_tracker_` to track the autofilled `element`.
void TrackAutofilledElement(const blink::WebFormControlElement& element);
FormTracker* form_tracker_for_testing() { return &form_tracker_; } FormTracker* form_tracker_for_testing() { return &form_tracker_; }
void SelectWasUpdated(const blink::WebFormControlElement& element); void SelectWasUpdated(const blink::WebFormControlElement& element);
......
...@@ -106,6 +106,21 @@ void FormTracker::SelectControlDidChange(const WebFormControlElement& element) { ...@@ -106,6 +106,21 @@ void FormTracker::SelectControlDidChange(const WebFormControlElement& element) {
Observer::ElementChangeSource::SELECT_CHANGED)); Observer::ElementChangeSource::SELECT_CHANGED));
} }
void FormTracker::TrackAutofilledElement(const WebFormControlElement& element) {
DCHECK_CALLED_ON_VALID_SEQUENCE(form_tracker_sequence_checker_);
DCHECK(element.IsAutofilled());
if (ignore_control_changes_)
return;
ResetLastInteractedElements();
if (element.Form().IsNull())
last_interacted_formless_element_ = element;
else
last_interacted_form_ = element.Form();
TrackElement();
}
void FormTracker::FireProbablyFormSubmittedForTesting() { void FormTracker::FireProbablyFormSubmittedForTesting() {
FireProbablyFormSubmitted(); FireProbablyFormSubmitted();
} }
......
...@@ -73,6 +73,11 @@ class FormTracker : public content::RenderFrameObserver { ...@@ -73,6 +73,11 @@ class FormTracker : public content::RenderFrameObserver {
void TextFieldDidChange(const blink::WebFormControlElement& element); void TextFieldDidChange(const blink::WebFormControlElement& element);
void SelectControlDidChange(const blink::WebFormControlElement& element); void SelectControlDidChange(const blink::WebFormControlElement& element);
// Tells the tracker to track the autofilled `element`. Since autofilling a
// form or field won't trigger the regular *DidChange events, the tracker
// won't be notified of this `element` otherwise.
void TrackAutofilledElement(const blink::WebFormControlElement& element);
void set_ignore_control_changes(bool ignore_control_changes) { void set_ignore_control_changes(bool ignore_control_changes) {
ignore_control_changes_ = ignore_control_changes; ignore_control_changes_ = ignore_control_changes;
} }
......
...@@ -640,6 +640,7 @@ void PasswordAutofillAgent::FillField(WebInputElement* input, ...@@ -640,6 +640,7 @@ void PasswordAutofillAgent::FillField(WebInputElement* input,
const FieldRendererId input_id(input->UniqueRendererFormControlId()); const FieldRendererId input_id(input->UniqueRendererFormControlId());
field_data_manager_->UpdateFieldDataMap( field_data_manager_->UpdateFieldDataMap(
input_id, credential, FieldPropertiesFlags::kAutofilledOnUserTrigger); input_id, credential, FieldPropertiesFlags::kAutofilledOnUserTrigger);
autofill_agent_->TrackAutofilledElement(*input);
} }
void PasswordAutofillAgent::FillPasswordFieldAndSave( void PasswordAutofillAgent::FillPasswordFieldAndSave(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment