blob: ee34b7b637afc5487520edea4539b3e1d91ca87e [file] [log] [blame]
[email protected]f07e4442013-06-06 23:03:481// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]679f128f2010-07-22 22:57:442// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]f07e4442013-06-06 23:03:485#include "components/autofill/content/renderer/autofill_agent.h"
[email protected]679f128f2010-07-22 22:57:446
avi4310d522015-12-25 19:37:597#include <stddef.h>
8
brettw9c68c512015-11-20 23:26:389#include <tuple>
10
[email protected]a1cb57f2011-09-28 22:41:2911#include "base/bind.h"
[email protected]f920d6e2013-03-12 20:20:5012#include "base/command_line.h"
Dominic Battre4f1c5ca2020-02-10 16:57:5013#include "base/debug/alias.h"
14#include "base/debug/dump_without_crashing.h"
Mathieu Perreaulta24d0c22017-11-10 01:22:0015#include "base/feature_list.h"
brettw94a2cc22015-07-01 19:26:5416#include "base/i18n/case_conversion.h"
skyostilb0daa012015-06-02 19:03:4817#include "base/location.h"
mathp4f6b0382016-04-12 20:41:1218#include "base/metrics/field_trial.h"
skyostilb0daa012015-06-02 19:03:4819#include "base/single_thread_task_runner.h"
mgiuca30f75882017-03-28 02:07:1920#include "base/strings/string_piece.h"
[email protected]1988e1c2013-02-28 20:27:4221#include "base/strings/string_split.h"
[email protected]c72674b2013-06-11 04:16:4322#include "base/strings/string_util.h"
[email protected]d2d79d52013-06-07 22:23:4823#include "base/strings/utf_string_conversions.h"
gab7966d312016-05-11 20:35:0124#include "base/threading/thread_task_runner_handle.h"
[email protected]bbd8da92013-06-28 02:12:2025#include "base/time/time.h"
avi4310d522015-12-25 19:37:5926#include "build/build_config.h"
sandromaggid10cf2a2020-04-22 18:53:1527#include "components/autofill/content/renderer/autofill_assistant_agent.h"
[email protected]f07e4442013-06-06 23:03:4828#include "components/autofill/content/renderer/form_autofill_util.h"
Tao Bai6cd41ad2017-12-04 18:48:1729#include "components/autofill/content/renderer/form_tracker.h"
[email protected]f07e4442013-06-06 23:03:4830#include "components/autofill/content/renderer/password_autofill_agent.h"
[email protected]3cbdf9362014-01-31 23:12:2331#include "components/autofill/content/renderer/password_generation_agent.h"
jwwfb2a1432016-06-13 22:44:1532#include "components/autofill/content/renderer/renderer_save_password_progress_logger.h"
[email protected]d04f81912013-06-18 14:52:1333#include "components/autofill/core/common/autofill_constants.h"
[email protected]d86263dcd2014-01-09 10:35:2134#include "components/autofill/core/common/autofill_data_validation.h"
Mathieu Perreaulta24d0c22017-11-10 01:22:0035#include "components/autofill/core/common/autofill_features.h"
[email protected]d04f81912013-06-18 14:52:1336#include "components/autofill/core/common/autofill_switches.h"
Christoph Schweringaa41ba842019-10-14 08:00:0637#include "components/autofill/core/common/autofill_tick_clock.h"
rouslanc31f81d2015-08-24 17:33:5238#include "components/autofill/core/common/autofill_util.h"
[email protected]d04f81912013-06-18 14:52:1339#include "components/autofill/core/common/form_data.h"
40#include "components/autofill/core/common/form_data_predictions.h"
41#include "components/autofill/core/common/form_field_data.h"
jwwfb2a1432016-06-13 22:44:1542#include "components/autofill/core/common/password_form_fill_data.h"
43#include "components/autofill/core/common/save_password_progress_logger.h"
[email protected]fed9d4f2013-12-17 21:32:4744#include "content/public/common/content_switches.h"
Tao Bai88d56d42017-07-17 16:07:1645#include "content/public/common/origin_util.h"
[email protected]ca5190f2013-07-08 11:10:3146#include "content/public/common/url_constants.h"
estadeb1bc9bd2014-12-02 22:44:1147#include "content/public/renderer/render_frame.h"
[email protected]a2ef54c2011-10-10 16:20:3148#include "content/public/renderer/render_view.h"
[email protected]ca5190f2013-07-08 11:10:3149#include "net/cert/cert_status_flags.h"
rockot734fb662016-10-15 16:41:3050#include "services/service_manager/public/cpp/interface_provider.h"
Anton Bikineev1156b5f2021-05-15 22:35:3651#include "third_party/abseil-cpp/absl/types/optional.h"
Ken Rockot0aad7ec2018-07-31 15:58:4452#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
Dave Tapuska129cef82019-12-19 16:36:4853#include "third_party/blink/public/common/input/web_keyboard_event.h"
Blink Reformata30d4232018-04-07 15:31:0654#include "third_party/blink/public/platform/web_url_request.h"
Akihiro Otab7c4cb12019-10-16 22:40:5955#include "third_party/blink/public/web/web_ax_enums.h"
Caitlin Fischerf23462e2019-06-21 15:30:4756#include "third_party/blink/public/web/web_ax_object.h"
Blink Reformata30d4232018-04-07 15:31:0657#include "third_party/blink/public/web/web_console_message.h"
58#include "third_party/blink/public/web/web_document.h"
59#include "third_party/blink/public/web/web_element_collection.h"
60#include "third_party/blink/public/web/web_form_control_element.h"
61#include "third_party/blink/public/web/web_form_element.h"
62#include "third_party/blink/public/web/web_local_frame.h"
63#include "third_party/blink/public/web/web_node.h"
64#include "third_party/blink/public/web/web_option_element.h"
Blink Reformata30d4232018-04-07 15:31:0665#include "third_party/blink/public/web/web_view.h"
[email protected]c051a1b2011-01-21 23:30:1766#include "ui/base/l10n/l10n_util.h"
[email protected]7e9acd082013-09-17 23:31:1667#include "ui/events/keycodes/keyboard_codes.h"
[email protected]679f128f2010-07-22 22:57:4468
[email protected]a1221aea2013-11-07 01:31:3069using blink::WebAutofillClient;
Caitlin Fischerf23462e2019-06-21 15:30:4770using blink::WebAutofillState;
71using blink::WebAXObject;
[email protected]dbdd60272014-04-14 22:48:4072using blink::WebConsoleMessage;
rouslanf7ebd8832015-01-22 01:54:1473using blink::WebDocument;
[email protected]5e7e8612014-03-20 14:43:1974using blink::WebElement;
75using blink::WebElementCollection;
[email protected]a1221aea2013-11-07 01:31:3076using blink::WebFormControlElement;
77using blink::WebFormElement;
78using blink::WebFrame;
79using blink::WebInputElement;
80using blink::WebKeyboardEvent;
[email protected]c5041c322014-04-08 05:06:4781using blink::WebLocalFrame;
[email protected]a1221aea2013-11-07 01:31:3082using blink::WebNode;
[email protected]a1221aea2013-11-07 01:31:3083using blink::WebOptionElement;
84using blink::WebString;
[email protected]5e7e8612014-03-20 14:43:1985using blink::WebVector;
[email protected]679f128f2010-07-22 22:57:4486
[email protected]d86263dcd2014-01-09 10:35:2187namespace autofill {
88
Tao Bai6e605e42020-05-20 20:05:5589using form_util::ExtractMask;
Maria Kazinova168a9ed92020-02-06 15:05:2090using form_util::FindFormAndFieldForFormControlElement;
Christoph Schwering06b96692021-03-09 16:59:0091using form_util::UnownedFormElementsAndFieldSetsToFormData;
Jan Wilken Dörrief3785c42019-06-21 10:47:3792using mojom::SubmissionSource;
Friedrich Horschigef921f52020-02-19 15:16:0493using ShowAll = PasswordAutofillAgent::ShowAll;
94using GenerationShowing = PasswordAutofillAgent::GenerationShowing;
Jan Wilken Dörrief3785c42019-06-21 10:47:3795
[email protected]e47aec52010-08-12 00:50:3096namespace {
97
sebsg1c436852018-04-18 16:54:3298// Time to wait, in ms, o ensure that only a single select change will be acted
99// upon, instead of multiple in close succession (debounce time).
sebsg248c6b02018-04-09 20:20:42100size_t kWaitTimeForSelectOptionsChangesMs = 50;
101
Tao Bai6e605e42020-05-20 20:05:55102// Helper function to return EXTRACT_DATALIST if kAutofillExtractAllDatalist is
103// enabled, otherwise EXTRACT_NONE is returned.
104ExtractMask GetExtractDatalistMask() {
105 return base::FeatureList::IsEnabled(features::kAutofillExtractAllDatalists)
106 ? form_util::EXTRACT_DATALIST
107 : form_util::EXTRACT_NONE;
108}
109
[email protected]e47aec52010-08-12 00:50:30110} // namespace
111
brettwb505b7a2014-11-26 22:05:32112AutofillAgent::ShowSuggestionsOptions::ShowSuggestionsOptions()
113 : autofill_on_empty_values(false),
114 requires_caret_at_end(false),
brettwb505b7a2014-11-26 22:05:32115 show_full_suggestion_list(false),
Fabio Tirelo83662a22018-07-06 15:03:48116 autoselect_first_suggestion(false) {}
brettwb505b7a2014-11-26 22:05:32117
estadeb1bc9bd2014-12-02 22:44:11118AutofillAgent::AutofillAgent(content::RenderFrame* render_frame,
[email protected]3cbdf9362014-01-31 23:12:23119 PasswordAutofillAgent* password_autofill_agent,
Ben Goodger205467b2017-08-02 19:33:55120 PasswordGenerationAgent* password_generation_agent,
sandromaggid10cf2a2020-04-22 18:53:15121 AutofillAssistantAgent* autofill_assistant_agent,
Ken Rockot0aad7ec2018-07-31 15:58:44122 blink::AssociatedInterfaceRegistry* registry)
estadeb1bc9bd2014-12-02 22:44:11123 : content::RenderFrameObserver(render_frame),
Mathieu Perreaultd7b56b492017-10-18 16:52:17124 form_cache_(render_frame->GetWebFrame()),
[email protected]ad19b302013-04-03 07:42:19125 password_autofill_agent_(password_autofill_agent),
[email protected]3cbdf9362014-01-31 23:12:23126 password_generation_agent_(password_generation_agent),
sandromaggid10cf2a2020-04-22 18:53:15127 autofill_assistant_agent_(autofill_assistant_agent),
[email protected]679f128f2010-07-22 22:57:44128 autofill_query_id_(0),
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39129 query_node_autofill_state_(WebAutofillState::kNotFilled),
[email protected]b648f242014-02-25 13:49:06130 is_popup_possibly_visible_(false),
gcastocdd33e0d2015-06-17 22:10:05131 is_generation_popup_possibly_visible_(false),
Tao Baie13b5ca2017-06-23 16:15:51132 is_user_gesture_required_(true),
Tao Bai88d56d42017-07-17 16:07:16133 is_secure_context_required_(false),
Maria Kazinova286b24e2020-02-05 13:20:12134 form_tracker_(render_frame),
135 field_data_manager_(password_autofill_agent->GetFieldDataManager()) {
Blink Reformat1c4d759e2017-04-09 16:34:54136 render_frame->GetWebFrame()->SetAutofillClient(this);
leon.han90fd63b2016-07-26 01:23:55137 password_autofill_agent->SetAutofillAgent(this);
Tao Bai6cd41ad2017-12-04 18:48:17138 AddFormObserver(this);
Ken Rockota9bb5912019-12-18 03:13:03139 registry->AddInterface(base::BindRepeating(
140 &AutofillAgent::BindPendingReceiver, base::Unretained(this)));
[email protected]679f128f2010-07-22 22:57:44141}
142
Christoph Schweringb8fa3822020-05-15 16:04:44143// The destructor is not guaranteed to be called. Destruction happens (only)
144// through the OnDestruct() event, which posts a task to delete this object.
145// The process may be killed before this deletion can happen.
Tao Bai6cd41ad2017-12-04 18:48:17146AutofillAgent::~AutofillAgent() {
147 RemoveFormObserver(this);
148}
[email protected]d2f05d02011-01-27 18:51:01149
Shimi Zhang6b72d292019-07-12 20:52:42150void AutofillAgent::BindPendingReceiver(
151 mojo::PendingAssociatedReceiver<mojom::AutofillAgent> pending_receiver) {
152 receiver_.Bind(std::move(pending_receiver));
leon.hande852902016-05-04 09:16:38153}
154
Dmitry Gozman02dd8272020-06-09 20:01:23155void AutofillAgent::DidCommitProvisionalLoad(ui::PageTransition transition) {
mathpffc78e22015-09-01 14:10:50156 blink::WebFrame* frame = render_frame()->GetWebFrame();
157 // TODO(dvadym): check if we need to check if it is main frame navigation
158 // http://crbug.com/443155
Blink Reformat1c4d759e2017-04-09 16:34:54159 if (frame->Parent())
mathpffc78e22015-09-01 14:10:50160 return; // Not a top-level navigation.
161
Tao Bai6cd41ad2017-12-04 18:48:17162 // Navigation to a new page or a page refresh.
Nektarios Paisios6b79cf6f2018-02-26 16:49:36163
Hajime Hoshi83c3f502018-03-14 05:49:01164 element_.Reset();
Nektarios Paisios6b79cf6f2018-02-26 16:49:36165
Tao Bai6cd41ad2017-12-04 18:48:17166 form_cache_.Reset();
167 ResetLastInteractedElements();
Tao Baia674b1d2018-01-18 22:33:43168 OnFormNoLongerSubmittable();
Christoph Schweringb09a3282020-08-20 13:05:19169 SendPotentiallySubmittedFormToBrowser();
[email protected]676126f72011-01-15 00:03:51170}
171
estadeb1bc9bd2014-12-02 22:44:11172void AutofillAgent::DidFinishDocumentLoad() {
173 ProcessForms();
[email protected]3609c962014-07-11 03:18:25174}
175
estade2792527072014-12-17 00:41:47176void AutofillAgent::DidChangeScrollOffset() {
Changwan Ryuf85180e52018-08-10 04:31:46177 if (element_.IsNull())
178 return;
179
Changwan Ryu9db32db42018-01-24 14:54:44180 if (!focus_requires_scroll_) {
181 // Post a task here since scroll offset may change during layout.
182 // (https://crbug.com/804886)
183 weak_ptr_factory_.InvalidateWeakPtrs();
Hajime Hoshi9f80e742018-04-13 03:35:04184 render_frame()
185 ->GetTaskRunner(blink::TaskType::kInternalUserInteraction)
186 ->PostTask(FROM_HERE,
187 base::BindOnce(&AutofillAgent::DidChangeScrollOffsetImpl,
Changwan Ryu9db32db42018-01-24 14:54:44188 weak_ptr_factory_.GetWeakPtr(), element_));
Friedrich Horschig35355312019-09-09 17:26:34189 } else {
Changwan Ryu9db32db42018-01-24 14:54:44190 HidePopup();
Changwan Ryueb8a057e2017-12-08 19:22:33191 }
Changwan Ryu9db32db42018-01-24 14:54:44192}
Changwan Ryueb8a057e2017-12-08 19:22:33193
Changwan Ryu9db32db42018-01-24 14:54:44194void AutofillAgent::DidChangeScrollOffsetImpl(
195 const WebFormControlElement& element) {
Changwan Ryuf85180e52018-08-10 04:31:46196 if (element != element_ || element_.IsNull() || focus_requires_scroll_ ||
Changwan Ryu9db32db42018-01-24 14:54:44197 !is_popup_possibly_visible_ || !element_.Focused())
estadeb5efbab62015-04-28 18:07:42198 return;
rouslanc31f81d2015-08-24 17:33:52199
Changwan Ryu9db32db42018-01-24 14:54:44200 FormData form;
201 FormFieldData field;
Tao Bai6e605e42020-05-20 20:05:55202 if (FindFormAndFieldForFormControlElement(
203 element_, field_data_manager_.get(),
204 static_cast<ExtractMask>(form_util::EXTRACT_BOUNDS |
205 GetExtractDatalistMask()),
206 &form, &field)) {
Tao Baid9c02cf52020-03-30 22:13:39207 GetAutofillDriver()->TextFieldDidScroll(form, field, field.bounds);
Changwan Ryu9db32db42018-01-24 14:54:44208 }
209
210 // Ignore subsequent scroll offset changes.
Friedrich Horschig35355312019-09-09 17:26:34211 HidePopup();
estadeb1bc9bd2014-12-02 22:44:11212}
213
Kent Tamura69d143e2019-05-22 00:31:45214void AutofillAgent::FocusedElementChanged(const WebElement& element) {
Ehsan Karamad3538c8a2017-11-20 16:31:40215 was_focused_before_now_ = false;
[email protected]91dcc6d32014-07-30 00:01:33216 HidePopup();
217
Kent Tamura69d143e2019-05-22 00:31:45218 if (element.IsNull()) {
Colin Blundell5ffa4c22020-10-22 09:33:45219 // Focus moved away from the last interacted form (if any) to somewhere else
220 // on the page.
221 GetAutofillDriver()->FocusNoLongerOnForm(!last_interacted_form_.IsNull());
estadeb1bc9bd2014-12-02 22:44:11222 return;
mathp8ac68ce2015-12-08 21:49:06223 }
estadeb1bc9bd2014-12-02 22:44:11224
Kent Tamura69d143e2019-05-22 00:31:45225 const WebInputElement* input = ToWebInputElement(&element);
mathpb4cf7b82015-12-11 16:42:24226
Tao Bai0c268902020-07-16 03:26:09227 bool focus_moved_to_new_form = false;
Blink Reformat1c4d759e2017-04-09 16:34:54228 if (!last_interacted_form_.IsNull() &&
Kent Tamura69d143e2019-05-22 00:31:45229 (!input || last_interacted_form_ != input->Form())) {
mathp8ac68ce2015-12-08 21:49:06230 // The focused element is not part of the last interacted form (could be
231 // in a different form).
Colin Blundell5ffa4c22020-10-22 09:33:45232 GetAutofillDriver()->FocusNoLongerOnForm(/*had_interacted_form=*/true);
Tao Bai0c268902020-07-16 03:26:09233 focus_moved_to_new_form = true;
mathp8ac68ce2015-12-08 21:49:06234 }
[email protected]f920d6e2013-03-12 20:20:50235
Tao Bai0c268902020-07-16 03:26:09236 // Calls HandleFocusChangeComplete() after notifying the focus is no longer on
237 // the previous form, then early return. No need to notify the newly focused
238 // element because that will be done by HandleFocusChangeComplete() which
239 // triggers FormControlElementClicked().
240 // Refer to http://crbug.com/1105254
241 if ((IsKeyboardAccessoryEnabled() || !focus_requires_scroll_) &&
242 !element.IsNull() &&
243 element.GetDocument().GetFrame()->HasTransientUserActivation()) {
244 focused_node_was_last_clicked_ = true;
245 HandleFocusChangeComplete();
246 }
247
248 if (focus_moved_to_new_form)
249 return;
250
Kent Tamura69d143e2019-05-22 00:31:45251 if (!input || !input->IsEnabled() || input->IsReadOnly() ||
252 !input->IsTextField())
[email protected]f920d6e2013-03-12 20:20:50253 return;
254
Kent Tamura69d143e2019-05-22 00:31:45255 element_ = *input;
Tao Bai168e4fc2017-06-19 18:46:38256
257 FormData form;
258 FormFieldData field;
Tao Bai6e605e42020-05-20 20:05:55259 if (FindFormAndFieldForFormControlElement(
260 element_, field_data_manager_.get(),
261 static_cast<ExtractMask>(form_util::EXTRACT_BOUNDS |
262 GetExtractDatalistMask()),
263 &form, &field)) {
Tao Baid9c02cf52020-03-30 22:13:39264 GetAutofillDriver()->FocusOnFormField(form, field, field.bounds);
Tao Bai168e4fc2017-06-19 18:46:38265 }
[email protected]e5057a22013-04-22 12:41:39266}
267
vabrd62bc3e2016-05-04 15:58:52268void AutofillAgent::OnDestruct() {
269 Shutdown();
270 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
271}
272
Tommy Martino542b42352019-07-22 20:39:37273void AutofillAgent::AccessibilityModeChanged(const ui::AXMode& mode) {
274 is_screen_reader_enabled_ = mode.has_mode(ui::AXMode::kScreenReader);
275}
276
tmartino1c5348c92016-05-26 18:50:56277void AutofillAgent::FireHostSubmitEvents(const WebFormElement& form,
Tao Baia674b1d2018-01-18 22:33:43278 bool known_success,
279 SubmissionSource source) {
tmartino1c5348c92016-05-26 18:50:56280 FormData form_data;
Maria Kazinova286b24e2020-02-05 13:20:12281 if (!form_util::ExtractFormData(form, *field_data_manager_.get(), &form_data))
tmartino1c5348c92016-05-26 18:50:56282 return;
283
Tao Baia674b1d2018-01-18 22:33:43284 FireHostSubmitEvents(form_data, known_success, source);
tmartino1c5348c92016-05-26 18:50:56285}
286
287void AutofillAgent::FireHostSubmitEvents(const FormData& form_data,
Tao Baia674b1d2018-01-18 22:33:43288 bool known_success,
289 SubmissionSource source) {
290 // We don't want to fire duplicate submission event.
Christoph Schweringb09a3282020-08-20 13:05:19291 if (!base::FeatureList::IsEnabled(
292 features::kAutofillAllowDuplicateFormSubmissions) &&
293 !submitted_forms_.insert(form_data.unique_renderer_id).second) {
Tao Baia674b1d2018-01-18 22:33:43294 return;
Christoph Schweringb09a3282020-08-20 13:05:19295 }
Tao Baia674b1d2018-01-18 22:33:43296
Sebastien Lalancetteb2020be32019-01-08 15:17:59297 GetAutofillDriver()->FormSubmitted(form_data, known_success, source);
tmartino1c5348c92016-05-26 18:50:56298}
299
vabrd62bc3e2016-05-04 15:58:52300void AutofillAgent::Shutdown() {
Shimi Zhang6b72d292019-07-12 20:52:42301 receiver_.reset();
vabrd62bc3e2016-05-04 15:58:52302 weak_ptr_factory_.InvalidateWeakPtrs();
303}
304
Blink Reformat1c4d759e2017-04-09 16:34:54305void AutofillAgent::TextFieldDidEndEditing(const WebInputElement& element) {
Vasilii Sukhanovacf9b5d2018-11-09 16:18:47306 // Sometimes "blur" events are side effects of the password generation
307 // handling the page. They should not affect any UI in the browser.
308 if (password_generation_agent_ &&
309 password_generation_agent_->ShouldIgnoreBlur()) {
310 return;
311 }
Friedrich Horschig8b10e3c62020-03-04 09:55:01312 GetAutofillDriver()->DidEndTextFieldEditing();
Ioana Pandele9e742fe2018-10-11 19:07:54313 password_autofill_agent_->DidEndTextFieldEditing();
Ioana Pandele0c36cd0e42018-11-05 17:51:31314 if (password_generation_agent_)
315 password_generation_agent_->DidEndTextFieldEditing(element);
Christoph Schweringb09a3282020-08-20 13:05:19316
317 SendPotentiallySubmittedFormToBrowser();
[email protected]676126f72011-01-15 00:03:51318}
319
Tao Baie13b5ca2017-06-23 16:15:51320void AutofillAgent::SetUserGestureRequired(bool required) {
Tao Bai6cd41ad2017-12-04 18:48:17321 form_tracker_.set_user_gesture_required(required);
Tao Baie13b5ca2017-06-23 16:15:51322}
323
Blink Reformat1c4d759e2017-04-09 16:34:54324void AutofillAgent::TextFieldDidChange(const WebFormControlElement& element) {
Tao Bai6cd41ad2017-12-04 18:48:17325 form_tracker_.TextFieldDidChange(element);
[email protected]676126f72011-01-15 00:03:51326}
327
Tao Bai6cd41ad2017-12-04 18:48:17328void AutofillAgent::OnTextFieldDidChange(const WebInputElement& element) {
329 if (password_generation_agent_ &&
330 password_generation_agent_->TextDidChangeInTextField(element)) {
331 is_popup_possibly_visible_ = true;
[email protected]f9af2832012-12-14 04:20:43332 return;
Tao Bai6cd41ad2017-12-04 18:48:17333 }
[email protected]f9af2832012-12-14 04:20:43334
Tao Bai6cd41ad2017-12-04 18:48:17335 if (password_autofill_agent_->TextDidChangeInTextField(element)) {
336 is_popup_possibly_visible_ = true;
337 element_ = element;
338 return;
[email protected]e7e83472012-04-05 02:56:26339 }
[email protected]676126f72011-01-15 00:03:51340
brettwb505b7a2014-11-26 22:05:32341 ShowSuggestionsOptions options;
342 options.requires_caret_at_end = true;
343 ShowSuggestions(element, options);
[email protected]7d24db72011-08-26 06:02:31344
[email protected]1ecbe862012-10-05 01:29:14345 FormData form;
346 FormFieldData field;
Tao Bai6e605e42020-05-20 20:05:55347 if (FindFormAndFieldForFormControlElement(
348 element, field_data_manager_.get(),
349 static_cast<ExtractMask>(form_util::EXTRACT_BOUNDS |
350 GetExtractDatalistMask()),
351 &form, &field)) {
Tao Baid9c02cf52020-03-30 22:13:39352 GetAutofillDriver()->TextFieldDidChange(form, field, field.bounds,
353 AutofillTickClock::NowTicks());
[email protected]1d14f582011-09-02 20:42:04354 }
[email protected]676126f72011-01-15 00:03:51355}
356
Blink Reformat1c4d759e2017-04-09 16:34:54357void AutofillAgent::TextFieldDidReceiveKeyDown(const WebInputElement& element,
[email protected]2fa18c22011-06-14 23:40:43358 const WebKeyboardEvent& event) {
Blink Reformat1c4d759e2017-04-09 16:34:54359 if (event.windows_key_code == ui::VKEY_DOWN ||
360 event.windows_key_code == ui::VKEY_UP) {
brettwb505b7a2014-11-26 22:05:32361 ShowSuggestionsOptions options;
362 options.autofill_on_empty_values = true;
363 options.requires_caret_at_end = true;
Fabio Tirelo83662a22018-07-06 15:03:48364 options.autoselect_first_suggestion =
365 ShouldAutoselectFirstSuggestionOnArrowDown();
brettwb505b7a2014-11-26 22:05:32366 ShowSuggestions(element, options);
367 }
[email protected]efeb565f2013-12-12 17:16:41368}
369
Blink Reformat1c4d759e2017-04-09 16:34:54370void AutofillAgent::OpenTextDataListChooser(const WebInputElement& element) {
brettwb505b7a2014-11-26 22:05:32371 ShowSuggestionsOptions options;
372 options.autofill_on_empty_values = true;
brettwb505b7a2014-11-26 22:05:32373 ShowSuggestions(element, options);
[email protected]676126f72011-01-15 00:03:51374}
375
Blink Reformat1c4d759e2017-04-09 16:34:54376void AutofillAgent::DataListOptionsChanged(const WebInputElement& element) {
377 if (!is_popup_possibly_visible_ || !element.Focused())
estadedf5088a2014-12-15 02:04:07378 return;
379
Tao Bai6cd41ad2017-12-04 18:48:17380 OnProvisionallySaveForm(WebFormElement(), element,
381 ElementChangeSource::TEXTFIELD_CHANGED);
estadedf5088a2014-12-15 02:04:07382}
383
vasiliifd0e8ca2017-04-12 11:11:22384void AutofillAgent::UserGestureObserved() {
385 password_autofill_agent_->UserGestureObserved();
[email protected]fc22ae52014-04-23 13:48:04386}
387
Parastoo Geranmayeh522c2222018-07-16 15:14:03388void AutofillAgent::TriggerRefillIfNeeded(const FormData& form) {
Parastoo Geranmayeh1421e632018-07-25 15:57:03389 ReplaceElementIfNowInvalid(form);
390
Parastoo Geranmayeh522c2222018-07-16 15:14:03391 FormFieldData field;
392 FormData updated_form;
Maria Kazinova168a9ed92020-02-06 15:05:20393 if (FindFormAndFieldForFormControlElement(element_, field_data_manager_.get(),
394 &updated_form, &field) &&
Parastoo Geranmayeh1421e632018-07-25 15:57:03395 (!element_.IsAutofilled() || !form.DynamicallySameFormAs(updated_form))) {
Parastoo Geranmayeh522c2222018-07-16 15:14:03396 WebLocalFrame* frame = render_frame()->GetWebFrame();
397 std::vector<FormData> forms;
398 forms.push_back(updated_form);
399 // Always communicate to browser process for topmost frame.
Parastoo Geranmayeh1421e632018-07-25 15:57:03400 if (!forms.empty() || !frame->Parent()) {
Christoph Schwering476c1df2020-11-27 02:50:07401 GetAutofillDriver()->FormsSeen(forms);
Parastoo Geranmayeh1421e632018-07-25 15:57:03402 }
Parastoo Geranmayeh522c2222018-07-16 15:14:03403 }
404}
405
leon.hande852902016-05-04 09:16:38406// mojom::AutofillAgent:
leon.han90fd63b2016-07-26 01:23:55407void AutofillAgent::FillForm(int32_t id, const FormData& form) {
Hajime Hoshie6104dc92018-03-20 05:58:02408 if (element_.IsNull())
409 return;
410
mathpf43ced42016-08-04 18:28:23411 if (id != autofill_query_id_ && id != kNoQueryId)
leon.han90fd63b2016-07-26 01:23:55412 return;
413
sebsg248c6b02018-04-09 20:20:42414 was_last_action_fill_ = true;
415
sebsge39d1172018-11-07 23:56:46416 // If this is a re-fill, replace the triggering element if it's invalid.
Fabio Tireloa0442b9b92019-03-19 23:59:18417 if (id == kNoQueryId)
sebsge35b762c2018-03-29 20:33:27418 ReplaceElementIfNowInvalid(form);
419
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39420 query_node_autofill_state_ = element_.GetAutofillState();
leon.han90fd63b2016-07-26 01:23:55421 form_util::FillForm(form, element_);
Blink Reformat1c4d759e2017-04-09 16:34:54422 if (!element_.Form().IsNull())
Tao Baie4d26212017-12-19 01:30:11423 UpdateLastInteractedForm(element_.Form());
leon.han90fd63b2016-07-26 01:23:55424
Michael Bai458713e42021-04-23 17:48:44425 // TODO(crbug.com/1198811): Inform the BrowserAutofillManager about the fields
426 // that were actually filled. It's possible that the form has changed since
427 // the time filling was triggered.
Christoph Schweringaa41ba842019-10-14 08:00:06428 GetAutofillDriver()->DidFillAutofillFormData(form,
429 AutofillTickClock::NowTicks());
Parastoo Geranmayeh522c2222018-07-16 15:14:03430
431 TriggerRefillIfNeeded(form);
Christoph Schweringb09a3282020-08-20 13:05:19432 SendPotentiallySubmittedFormToBrowser();
[email protected]8527a78f2014-06-12 12:49:15433}
434
leon.han90fd63b2016-07-26 01:23:55435void AutofillAgent::PreviewForm(int32_t id, const FormData& form) {
Hajime Hoshie6104dc92018-03-20 05:58:02436 if (element_.IsNull())
437 return;
438
leon.han90fd63b2016-07-26 01:23:55439 if (id != autofill_query_id_)
[email protected]63560b32014-03-04 07:06:26440 return;
441
Christoph Schweringd3cdbd52021-02-11 19:09:13442 ClearPreviewedForm();
443
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39444 query_node_autofill_state_ = element_.GetAutofillState();
Christoph Schweringd3cdbd52021-02-11 19:09:13445 previewed_elements_ = form_util::PreviewForm(form, element_);
leon.han90fd63b2016-07-26 01:23:55446
447 GetAutofillDriver()->DidPreviewAutofillFormData();
[email protected]6f001a6cf2012-02-09 15:21:53448}
449
leon.han90fd63b2016-07-26 01:23:55450void AutofillAgent::FieldTypePredictionsAvailable(
leon.han35ae41c2016-07-29 03:30:58451 const std::vector<FormDataPredictions>& forms) {
Mathieu Perreaultd7b56b492017-10-18 16:52:17452 bool attach_predictions_to_dom =
Mathieu Perreaulta24d0c22017-11-10 01:22:00453 base::FeatureList::IsEnabled(features::kAutofillShowTypePredictions);
leon.han90fd63b2016-07-26 01:23:55454 for (const auto& form : forms) {
Mathieu Perreaultd7b56b492017-10-18 16:52:17455 form_cache_.ShowPredictions(form, attach_predictions_to_dom);
leon.han90fd63b2016-07-26 01:23:55456 }
457}
458
Parastoo Geranmayeh7d8ea062018-05-15 22:16:25459void AutofillAgent::ClearSection() {
Hajime Hoshie6104dc92018-03-20 05:58:02460 if (element_.IsNull())
461 return;
462
Parastoo Geranmayeh7d8ea062018-05-15 22:16:25463 form_cache_.ClearSectionWithElement(element_);
[email protected]6f001a6cf2012-02-09 15:21:53464}
465
leon.han90fd63b2016-07-26 01:23:55466void AutofillAgent::ClearPreviewedForm() {
Hajime Hoshi83c3f502018-03-14 05:49:01467 // TODO(crbug.com/816533): It is very rare, but it looks like the |element_|
468 // can be null if a provisional load was committed immediately prior to
469 // clearing the previewed form.
470 if (element_.IsNull())
471 return;
[email protected]b5b1d69f2014-01-23 23:49:32472
Hajime Hoshi83c3f502018-03-14 05:49:01473 if (password_autofill_agent_->DidClearAutofillSelection(element_))
474 return;
475
Christoph Schweringd3cdbd52021-02-11 19:09:13476 form_util::ClearPreviewedElements(previewed_elements_, element_,
477 query_node_autofill_state_);
478 previewed_elements_ = {};
[email protected]6f001a6cf2012-02-09 15:21:53479}
480
Christoph Schwering7f933e452021-03-23 16:21:10481void AutofillAgent::FillFieldWithValue(FieldRendererId field_id,
482 const std::u16string& value) {
Christoph Schwering7f933e452021-03-23 16:21:10483 if (element_.IsNull() ||
Christoph Schwering48d2e6ae2021-03-30 02:05:27484 field_id != FieldRendererId(element_.UniqueRendererFormControlId())) {
Hajime Hoshie6104dc92018-03-20 05:58:02485 return;
Christoph Schwering7f933e452021-03-23 16:21:10486 }
Hajime Hoshie6104dc92018-03-20 05:58:02487
Blink Reformat1c4d759e2017-04-09 16:34:54488 WebInputElement* input_element = ToWebInputElement(&element_);
ziran.sunee0fd4432014-08-27 10:10:49489 if (input_element) {
leon.han35ae41c2016-07-29 03:30:58490 DoFillFieldWithValue(value, input_element);
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39491 input_element->SetAutofillState(WebAutofillState::kAutofilled);
ziran.sunee0fd4432014-08-27 10:10:49492 }
[email protected]ac9b92f2014-03-15 00:48:32493}
494
Christoph Schwering7f933e452021-03-23 16:21:10495void AutofillAgent::PreviewFieldWithValue(FieldRendererId field_id,
496 const std::u16string& value) {
497 if (element_.IsNull() ||
498 field_id != FieldRendererId(element_.UniqueRendererFormControlId())) {
Hajime Hoshie6104dc92018-03-20 05:58:02499 return;
Christoph Schwering7f933e452021-03-23 16:21:10500 }
Hajime Hoshie6104dc92018-03-20 05:58:02501
Blink Reformat1c4d759e2017-04-09 16:34:54502 WebInputElement* input_element = ToWebInputElement(&element_);
[email protected]e9d29d392014-03-25 01:15:15503 if (input_element)
leon.han35ae41c2016-07-29 03:30:58504 DoPreviewFieldWithValue(value, input_element);
[email protected]6f001a6cf2012-02-09 15:21:53505}
506
Akihiro Otab7c4cb12019-10-16 22:40:59507void AutofillAgent::SetSuggestionAvailability(
Christoph Schwering7f933e452021-03-23 16:21:10508 FieldRendererId field_id,
Akihiro Otab7c4cb12019-10-16 22:40:59509 const mojom::AutofillState state) {
Christoph Schwering7f933e452021-03-23 16:21:10510 if (element_.IsNull() ||
511 field_id != FieldRendererId(element_.UniqueRendererFormControlId())) {
Caitlin Fischerf23462e2019-06-21 15:30:47512 return;
Christoph Schwering7f933e452021-03-23 16:21:10513 }
Caitlin Fischerf23462e2019-06-21 15:30:47514
515 WebInputElement* input_element = ToWebInputElement(&element_);
Akihiro Otab7c4cb12019-10-16 22:40:59516 if (input_element) {
517 switch (state) {
518 case autofill::mojom::AutofillState::kAutofillAvailable:
519 WebAXObject::FromWebNode(*input_element)
520 .HandleAutofillStateChanged(
521 blink::WebAXAutofillState::kAutofillAvailable);
522 return;
523 case autofill::mojom::AutofillState::kAutocompleteAvailable:
524 WebAXObject::FromWebNode(*input_element)
525 .HandleAutofillStateChanged(
526 blink::WebAXAutofillState::kAutocompleteAvailable);
527 return;
528 case autofill::mojom::AutofillState::kNoSuggestions:
529 WebAXObject::FromWebNode(*input_element)
530 .HandleAutofillStateChanged(
531 blink::WebAXAutofillState::kNoSuggestions);
532 return;
533 }
534 NOTREACHED();
535 }
Caitlin Fischerf23462e2019-06-21 15:30:47536}
537
Christoph Schwering7f933e452021-03-23 16:21:10538void AutofillAgent::AcceptDataListSuggestion(
539 FieldRendererId field_id,
540 const std::u16string& suggested_value) {
541 if (element_.IsNull() ||
542 field_id != FieldRendererId(element_.UniqueRendererFormControlId())) {
543 return;
544 }
545
546 WebInputElement* input_element = ToWebInputElement(&element_);
547 if (!input_element) {
548 // For reasons not understood yet, this is triggered on elements which are
549 // not input elements.
550
551 // TODO(crbug.com/1048270) Gather debug data.
552 DEBUG_ALIAS_FOR_CSTR(element_name, element_.TagName().Latin1().c_str(), 64);
553 base::debug::DumpWithoutCrashing();
554
555 // Keep this return after removing the TODO(crbug.com/1048270) above.
556 return;
557 }
558 std::u16string new_value = suggested_value;
559 // If this element takes multiple values then replace the last part with
560 // the suggestion.
561 if (input_element->IsMultiple() && input_element->IsEmailField()) {
562 std::u16string value = input_element->EditingValue().Utf16();
563 std::vector<base::StringPiece16> parts = base::SplitStringPiece(
564 value, u",", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
565 if (parts.size() == 0)
566 parts.push_back(base::StringPiece16());
567
568 std::u16string last_part(parts.back());
569 // We want to keep just the leading whitespace.
570 for (size_t i = 0; i < last_part.size(); ++i) {
571 if (!base::IsUnicodeWhitespace(last_part[i])) {
572 last_part = last_part.substr(0, i);
573 break;
574 }
575 }
576 last_part.append(suggested_value);
577 parts.back() = last_part;
578
579 new_value = base::JoinString(parts, u",");
580 }
581 DoFillFieldWithValue(new_value, input_element);
[email protected]5c8de6b92012-06-08 21:24:08582}
583
Jan Wilken Dörrie812429a2021-03-11 16:59:19584void AutofillAgent::FillPasswordSuggestion(const std::u16string& username,
585 const std::u16string& password) {
Hajime Hoshie6104dc92018-03-20 05:58:02586 if (element_.IsNull())
587 return;
588
leon.han35ae41c2016-07-29 03:30:58589 bool handled =
590 password_autofill_agent_->FillSuggestion(element_, username, password);
[email protected]126b1ad2014-05-21 22:37:33591 DCHECK(handled);
592}
593
Jan Wilken Dörrie812429a2021-03-11 16:59:19594void AutofillAgent::PreviewPasswordSuggestion(const std::u16string& username,
595 const std::u16string& password) {
Hajime Hoshie6104dc92018-03-20 05:58:02596 if (element_.IsNull())
597 return;
598
kinuko0073e7c82017-01-24 00:42:40599 bool handled = password_autofill_agent_->PreviewSuggestion(
Blink Reformat1c4d759e2017-04-09 16:34:54600 element_, blink::WebString::FromUTF16(username),
601 blink::WebString::FromUTF16(password));
[email protected]e7e83472012-04-05 02:56:26602 DCHECK(handled);
603}
604
Christoph Schweringb09a3282020-08-20 13:05:19605bool AutofillAgent::CollectFormlessElements(FormData* output) const {
Tao Bai86ac37152018-03-02 14:35:33606 if (render_frame() == nullptr || render_frame()->GetWebFrame() == nullptr)
607 return false;
608
Blink Reformat1c4d759e2017-04-09 16:34:54609 WebDocument document = render_frame()->GetWebFrame()->GetDocument();
tmartino283dda12016-06-23 21:43:54610
611 // Build up the FormData from the unowned elements. This logic mostly
612 // mirrors the construction of the synthetic form in form_cache.cc, but
613 // happens at submit-time so we can capture the modifications the user
614 // has made, and doesn't depend on form_cache's internal state.
615 std::vector<WebElement> fieldsets;
616 std::vector<WebFormControlElement> control_elements =
Blink Reformat1c4d759e2017-04-09 16:34:54617 form_util::GetUnownedAutofillableFormFieldElements(document.All(),
tmartino283dda12016-06-23 21:43:54618 &fieldsets);
619
Christoph Schwering33bd21012020-04-26 15:57:24620 if (control_elements.size() > kMaxParseableFields)
tmartino283dda12016-06-23 21:43:54621 return false;
622
Tao Bai6e605e42020-05-20 20:05:55623 const ExtractMask extract_mask = static_cast<ExtractMask>(
624 form_util::EXTRACT_VALUE | form_util::EXTRACT_OPTIONS);
tmartino283dda12016-06-23 21:43:54625
Christoph Schwering06b96692021-03-09 16:59:00626 return UnownedFormElementsAndFieldSetsToFormData(
Maria Kazinova168a9ed92020-02-06 15:05:20627 fieldsets, control_elements, nullptr, document, field_data_manager_.get(),
628 extract_mask, output, nullptr);
mathpffc78e22015-09-01 14:10:50629}
630
[email protected]e9d29d392014-03-25 01:15:15631void AutofillAgent::ShowSuggestions(const WebFormControlElement& element,
brettwb505b7a2014-11-26 22:05:32632 const ShowSuggestionsOptions& options) {
Blink Reformat1c4d759e2017-04-09 16:34:54633 if (!element.IsEnabled() || element.IsReadOnly())
[email protected]efeb565f2013-12-12 17:16:41634 return;
Blink Reformat1c4d759e2017-04-09 16:34:54635 if (!element.SuggestedValue().IsEmpty())
[email protected]580c38052014-07-16 07:28:09636 return;
[email protected]e9d29d392014-03-25 01:15:15637
Blink Reformat1c4d759e2017-04-09 16:34:54638 const WebInputElement* input_element = ToWebInputElement(&element);
[email protected]e9d29d392014-03-25 01:15:15639 if (input_element) {
Blink Reformat1c4d759e2017-04-09 16:34:54640 if (!input_element->IsTextField())
[email protected]e9d29d392014-03-25 01:15:15641 return;
Blink Reformat1c4d759e2017-04-09 16:34:54642 if (!input_element->SuggestedValue().IsEmpty())
[email protected]e9d29d392014-03-25 01:15:15643 return;
644 } else {
mathp9172c62a2015-10-08 18:51:14645 DCHECK(form_util::IsTextAreaElement(element));
Blink Reformat1c4d759e2017-04-09 16:34:54646 if (!element.ToConst<WebFormControlElement>().SuggestedValue().IsEmpty())
[email protected]e9d29d392014-03-25 01:15:15647 return;
648 }
[email protected]e47aec52010-08-12 00:50:30649
[email protected]1c69f8b72012-03-14 03:18:50650 // Don't attempt to autofill with values that are too large or if filling
651 // criteria are not met.
Blink Reformat1c4d759e2017-04-09 16:34:54652 WebString value = element.EditingValue();
mathp5f90bce22015-11-22 20:16:58653 if (value.length() > kMaxDataLength ||
Friedrich Horschig35355312019-09-09 17:26:34654 (!options.autofill_on_empty_values && value.IsEmpty()) ||
mathp5f90bce22015-11-22 20:16:58655 (options.requires_caret_at_end &&
Blink Reformat1c4d759e2017-04-09 16:34:54656 (element.SelectionStart() != element.SelectionEnd() ||
657 element.SelectionEnd() != static_cast<int>(value.length())))) {
[email protected]1c69f8b72012-03-14 03:18:50658 // Any popup currently showing is obsolete.
[email protected]b648f242014-02-25 13:49:06659 HidePopup();
[email protected]e47aec52010-08-12 00:50:30660 return;
[email protected]1c69f8b72012-03-14 03:18:50661 }
[email protected]e47aec52010-08-12 00:50:30662
[email protected]bef7f9272012-04-17 10:47:49663 element_ = element;
mathp9172c62a2015-10-08 18:51:14664 if (form_util::IsAutofillableInputElement(input_element) &&
gcastocdd33e0d2015-06-17 22:10:05665 password_autofill_agent_->ShowSuggestions(
Friedrich Horschigef921f52020-02-19 15:16:04666 *input_element, ShowAll(options.show_full_suggestion_list),
667 GenerationShowing(is_generation_popup_possibly_visible_))) {
[email protected]b648f242014-02-25 13:49:06668 is_popup_possibly_visible_ = true;
[email protected]c66ba982013-04-05 09:56:17669 return;
[email protected]b648f242014-02-25 13:49:06670 }
[email protected]bef7f9272012-04-17 10:47:49671
gcastocdd33e0d2015-06-17 22:10:05672 if (is_generation_popup_possibly_visible_)
673 return;
674
jww20355072014-12-12 21:00:55675 // Password field elements should only have suggestions shown by the password
676 // autofill agent.
Dominic Battre9758fad2019-01-02 14:14:33677 // The /*disable presubmit*/ comment below is used to disable a presubmit
678 // script that ensures that only IsPasswordFieldForAutofill() is used in this
679 // code (it has to appear between the function name and the parentesis to not
680 // match a regex). In this specific case we are actually interested in whether
681 // the field is currently a password field, not whether it has ever been a
682 // password field.
683 if (input_element &&
684 input_element->IsPasswordField /*disable presubmit*/ () &&
Dominic Battre1bb521c2017-12-19 21:10:03685 !query_password_suggestion_) {
jww20355072014-12-12 21:00:55686 return;
Dominic Battre1bb521c2017-12-19 21:10:03687 }
jww20355072014-12-12 21:00:55688
Fabio Tirelo83662a22018-07-06 15:03:48689 QueryAutofillSuggestions(element, options.autoselect_first_suggestion);
[email protected]77bb0da2010-11-20 01:55:30690}
691
Tao Baia8c0d8bb2017-12-18 19:47:36692void AutofillAgent::SetQueryPasswordSuggestion(bool query) {
693 query_password_suggestion_ = query;
694}
695
Tao Bai88d56d42017-07-17 16:07:16696void AutofillAgent::SetSecureContextRequired(bool required) {
697 is_secure_context_required_ = required;
698}
699
Changwan Ryueb8a057e2017-12-08 19:22:33700void AutofillAgent::SetFocusRequiresScroll(bool require) {
701 focus_requires_scroll_ = require;
702}
703
sandromaggi2fbddc7dc2021-04-09 10:01:23704void AutofillAgent::GetElementFormAndFieldDataAtIndex(
705 const std::string& selector,
706 int index,
707 GetElementFormAndFieldDataAtIndexCallback callback) {
Christoph Schweringab66e432021-03-17 12:12:52708 blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
709 if (!frame)
710 return;
711
sandromaggi2fbddc7dc2021-04-09 10:01:23712 blink::WebElement target_element;
713 blink::WebVector<blink::WebElement> elements =
714 render_frame()->GetWebFrame()->GetDocument().QuerySelectorAll(
715 blink::WebString::FromUTF8(selector));
716 if (index >= 0 && static_cast<size_t>(index) < elements.size()) {
717 target_element = elements[index];
718 }
719
gogeraldd4f184b2018-09-19 22:24:24720 FormData form;
721 FormFieldData field;
Christoph Schwering8daaba02021-05-11 12:27:55722 if (base::FeatureList::IsEnabled(features::kAutofillAugmentFormsInRenderer)) {
723 form.host_frame = LocalFrameToken(frame->GetLocalFrameToken().value());
724 field.host_frame = LocalFrameToken(frame->GetLocalFrameToken().value());
725 }
Christoph Schweringab66e432021-03-17 12:12:52726
gogeraldd4f184b2018-09-19 22:24:24727 if (target_element.IsNull() || !target_element.IsFormControlElement()) {
728 return std::move(callback).Run(form, field);
729 }
730
731 blink::WebFormControlElement target_form_control_element =
732 target_element.To<blink::WebFormControlElement>();
Maria Kazinova168a9ed92020-02-06 15:05:20733 bool success = FindFormAndFieldForFormControlElement(
734 target_form_control_element, field_data_manager_.get(), &form, &field);
gogerald3e2f8a12018-10-11 21:46:54735 if (success) {
736 // Remember this element so as to autofill the form without focusing the
737 // field for Autofill Assistant.
738 element_ = target_form_control_element;
739 }
740 // Do not expect failure.
741 DCHECK(success);
742
gogeraldd4f184b2018-09-19 22:24:24743 return std::move(callback).Run(form, field);
744}
745
sandromaggid10cf2a2020-04-22 18:53:15746void AutofillAgent::SetAssistantActionState(bool running) {
747 DCHECK(autofill_assistant_agent_);
748 if (running) {
749 autofill_assistant_agent_->DisableKeyboard();
750 } else {
751 autofill_assistant_agent_->EnableKeyboard();
752 }
753}
754
Maxim Kolosovskiyd04e4602020-12-01 13:05:27755void AutofillAgent::EnableHeavyFormDataScraping() {
756 is_heavy_form_data_scraping_enabled_ = true;
757}
758
siashah6301ca4c2021-05-07 23:15:29759void AutofillAgent::SetFieldsEligibleForManualFilling(
760 const std::vector<FieldRendererId>& fields) {
761 form_cache_.SetFieldsEligibleForManualFilling(fields);
762}
763
[email protected]e9d29d392014-03-25 01:15:15764void AutofillAgent::QueryAutofillSuggestions(
Fabio Tirelo83662a22018-07-06 15:03:48765 const WebFormControlElement& element,
766 bool autoselect_first_suggestion) {
Christoph Schweringab66e432021-03-17 12:12:52767 blink::WebLocalFrame* frame = element.GetDocument().GetFrame();
768 if (!frame)
[email protected]e69b5f72013-01-24 00:59:13769 return;
770
Blink Reformat1c4d759e2017-04-09 16:34:54771 DCHECK(ToWebInputElement(&element) || form_util::IsTextAreaElement(element));
[email protected]e9d29d392014-03-25 01:15:15772
[email protected]77bb0da2010-11-20 01:55:30773 static int query_counter = 0;
774 autofill_query_id_ = query_counter++;
estade0ee91262014-10-23 19:29:19775
[email protected]1ecbe862012-10-05 01:29:14776 FormData form;
777 FormFieldData field;
Tao Bai6e605e42020-05-20 20:05:55778 if (!FindFormAndFieldForFormControlElement(
779 element, field_data_manager_.get(),
780 static_cast<ExtractMask>(form_util::EXTRACT_BOUNDS |
781 GetExtractDatalistMask()),
782 &form, &field)) {
Christoph Schwering8daaba02021-05-11 12:27:55783 if (base::FeatureList::IsEnabled(
784 features::kAutofillAugmentFormsInRenderer)) {
785 // |form| may be only partially initialized and may be sent to the browser
786 // in this state. Set at least the |host_frame| because sending an empty
787 // base::UnguessableToken is illegal.
788 form.host_frame = LocalFrameToken(frame->GetLocalFrameToken().value());
789 }
[email protected]7837be62011-01-18 23:45:08790 // If we didn't find the cached form, at least let autocomplete have a shot
791 // at providing suggestions.
Tao Baid9c02cf52020-03-30 22:13:39792 WebFormControlElementToFormField(
793 element, nullptr,
Tao Bai6e605e42020-05-20 20:05:55794 static_cast<ExtractMask>(form_util::EXTRACT_VALUE |
795 form_util::EXTRACT_BOUNDS |
796 GetExtractDatalistMask()),
Tao Baid9c02cf52020-03-30 22:13:39797 &field);
[email protected]7837be62011-01-18 23:45:08798 }
[email protected]77bb0da2010-11-20 01:55:30799
Tao Bai88d56d42017-07-17 16:07:16800 if (is_secure_context_required_ &&
Tao Bai6b032dd2017-09-19 18:44:07801 !(element.GetDocument().IsSecureContext())) {
Tao Bai88d56d42017-07-17 16:07:16802 LOG(WARNING) << "Autofill suggestions are disabled because the document "
Tao Bai6b032dd2017-09-19 18:44:07803 "isn't a secure context.";
Tao Bai88d56d42017-07-17 16:07:16804 return;
805 }
806
Tao Bai6e605e42020-05-20 20:05:55807 if (!base::FeatureList::IsEnabled(features::kAutofillExtractAllDatalists)) {
808 if (const WebInputElement* input_element = ToWebInputElement(&element)) {
809 // Find the datalist values and send them to the browser process.
810 form_util::GetDataListSuggestions(*input_element, &field.datalist_values,
811 &field.datalist_labels);
812 }
[email protected]e9d29d392014-03-25 01:15:15813 }
[email protected]5c8de6b92012-06-08 21:24:08814
[email protected]b648f242014-02-25 13:49:06815 is_popup_possibly_visible_ = true;
Tao Baid9c02cf52020-03-30 22:13:39816 GetAutofillDriver()->QueryFormFieldAutofill(autofill_query_id_, form, field,
817 field.bounds,
818 autoselect_first_suggestion);
[email protected]e47aec52010-08-12 00:50:30819}
820
Jan Wilken Dörrie812429a2021-03-11 16:59:19821void AutofillAgent::DoFillFieldWithValue(const std::u16string& value,
leon.han90fd63b2016-07-26 01:23:55822 WebInputElement* node) {
Tao Bai81483262018-03-02 05:38:12823 form_tracker_.set_ignore_control_changes(true);
sebsg778c43692018-01-24 20:01:32824 node->SetAutofillValue(blink::WebString::FromUTF16(value));
Vadym Doroshenkoa332ebc2017-09-14 11:46:53825 password_autofill_agent_->UpdateStateForTextChange(*node);
Tao Bai81483262018-03-02 05:38:12826 form_tracker_.set_ignore_control_changes(false);
[email protected]ac9b92f2014-03-15 00:48:32827}
828
Jan Wilken Dörrie812429a2021-03-11 16:59:19829void AutofillAgent::DoPreviewFieldWithValue(const std::u16string& value,
leon.han90fd63b2016-07-26 01:23:55830 WebInputElement* node) {
Christoph Schweringb49c73d62021-02-19 13:04:20831 ClearPreviewedForm();
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39832 query_node_autofill_state_ = element_.GetAutofillState();
sebsg778c43692018-01-24 20:01:32833 node->SetSuggestedValue(blink::WebString::FromUTF16(value));
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39834 node->SetAutofillState(WebAutofillState::kPreviewed);
Blink Reformat1c4d759e2017-04-09 16:34:54835 form_util::PreviewSuggestion(node->SuggestedValue().Utf16(),
836 node->Value().Utf16(), node);
Christoph Schweringb49c73d62021-02-19 13:04:20837 previewed_elements_.push_back(*node);
[email protected]6f001a6cf2012-02-09 15:21:53838}
839
estadeb1bc9bd2014-12-02 22:44:11840void AutofillAgent::ProcessForms() {
estadeb1bc9bd2014-12-02 22:44:11841 WebLocalFrame* frame = render_frame()->GetWebFrame();
Maria Kazinova168a9ed92020-02-06 15:05:20842 std::vector<FormData> forms =
843 form_cache_.ExtractNewForms(field_data_manager_.get());
[email protected]5193ea52014-05-14 01:10:02844
845 // Always communicate to browser process for topmost frame.
Blink Reformat1c4d759e2017-04-09 16:34:54846 if (!forms.empty() || !frame->Parent()) {
Christoph Schwering476c1df2020-11-27 02:50:07847 GetAutofillDriver()->FormsSeen(forms);
[email protected]5193ea52014-05-14 01:10:02848 }
[email protected]5193ea52014-05-14 01:10:02849}
850
[email protected]b648f242014-02-25 13:49:06851void AutofillAgent::HidePopup() {
852 if (!is_popup_possibly_visible_)
853 return;
[email protected]b648f242014-02-25 13:49:06854 is_popup_possibly_visible_ = false;
gcastocdd33e0d2015-06-17 22:10:05855 is_generation_popup_possibly_visible_ = false;
leon.han90fd63b2016-07-26 01:23:55856
Friedrich Horschig35355312019-09-09 17:26:34857 // The keyboard accessory has a separate, more complex hiding logic.
858 if (IsKeyboardAccessoryEnabled())
859 return;
860
leon.han90fd63b2016-07-26 01:23:55861 GetAutofillDriver()->HidePopup();
[email protected]81cd52332012-11-05 20:36:07862}
863
Blink Reformat1c4d759e2017-04-09 16:34:54864void AutofillAgent::DidAssociateFormControlsDynamically() {
vasilii31ba8c6c2017-04-28 21:35:08865 // If the control flow is here than the document was at least loaded. The
866 // whole page doesn't have to be loaded.
867 ProcessForms();
868 password_autofill_agent_->OnDynamicFormsSeen();
[email protected]17b6be72013-04-30 21:33:08869}
870
ekaramad27ca69b12017-04-20 18:34:29871void AutofillAgent::DidCompleteFocusChangeInFrame() {
872 WebDocument doc = render_frame()->GetWebFrame()->GetDocument();
873 WebElement focused_element;
874 if (!doc.IsNull())
875 focused_element = doc.FocusedElement();
Ioana Pandele67513a82019-06-11 10:21:00876
877 if (!focused_element.IsNull() && password_autofill_agent_)
878 password_autofill_agent_->FocusedNodeHasChanged(focused_element);
879
ekaramad27ca69b12017-04-20 18:34:29880 // PasswordGenerationAgent needs to know about focus changes, even if there is
881 // no focused element.
882 if (password_generation_agent_ &&
883 password_generation_agent_->FocusedNodeHasChanged(focused_element)) {
884 is_generation_popup_possibly_visible_ = true;
885 is_popup_possibly_visible_ = true;
886 }
ekaramad27ca69b12017-04-20 18:34:29887
Changwan Ryueb8a057e2017-12-08 19:22:33888 if (!IsKeyboardAccessoryEnabled() && focus_requires_scroll_)
Ehsan Karamad3538c8a2017-11-20 16:31:40889 HandleFocusChangeComplete();
Christoph Schweringb09a3282020-08-20 13:05:19890
891 SendPotentiallySubmittedFormToBrowser();
ekaramad27ca69b12017-04-20 18:34:29892}
893
894void AutofillAgent::DidReceiveLeftMouseDownOrGestureTapInNode(
895 const WebNode& node) {
Ehsan Karamad3538c8a2017-11-20 16:31:40896 DCHECK(!node.IsNull());
897 focused_node_was_last_clicked_ = node.Focused();
898
Jan Wilken Dörrie6f5eee5a2019-10-11 16:14:36899 if (IsTouchToFillEnabled() || IsKeyboardAccessoryEnabled() ||
900 !focus_requires_scroll_) {
Ehsan Karamad3538c8a2017-11-20 16:31:40901 HandleFocusChangeComplete();
Jan Wilken Dörrie6f5eee5a2019-10-11 16:14:36902 }
Ehsan Karamad3538c8a2017-11-20 16:31:40903}
904
Tao Bai81483262018-03-02 05:38:12905void AutofillAgent::SelectControlDidChange(
906 const WebFormControlElement& element) {
907 form_tracker_.SelectControlDidChange(element);
908}
909
sebsg248c6b02018-04-09 20:20:42910void AutofillAgent::SelectFieldOptionsChanged(
911 const blink::WebFormControlElement& element) {
912 if (!was_last_action_fill_ || element_.IsNull())
913 return;
914
sebsg1c436852018-04-18 16:54:32915 // Since a change of a select options often come in batches, use a timer
916 // to wait for other changes. Stop the timer if it was already running. It
917 // will be started again for this change.
918 if (on_select_update_timer_.IsRunning())
919 on_select_update_timer_.AbandonAndStop();
920
921 // Start the timer to notify the driver that the select field was updated
922 // after the options have finished changing,
923 on_select_update_timer_.Start(
924 FROM_HERE,
925 base::TimeDelta::FromMilliseconds(kWaitTimeForSelectOptionsChangesMs),
926 base::BindRepeating(&AutofillAgent::SelectWasUpdated,
927 weak_ptr_factory_.GetWeakPtr(), element));
928}
929
Jan Wilken Dörrief147dd772019-08-02 05:38:07930bool AutofillAgent::ShouldSuppressKeyboard(
931 const WebFormControlElement& element) {
sandromaggid10cf2a2020-04-22 18:53:15932 // Note: Consider supporting other autofill types in the future as well.
933 return password_autofill_agent_->ShouldSuppressKeyboard() ||
934 (autofill_assistant_agent_ &&
935 autofill_assistant_agent_->ShouldSuppressKeyboard());
Jan Wilken Dörriea1f2d0632019-05-08 09:29:00936}
937
Maria Kazinova2e53e2d2020-11-16 12:21:35938void AutofillAgent::FormElementReset(const WebFormElement& form) {
939 password_autofill_agent_->InformAboutFormClearing(form);
940}
941
Maria Kazinovad9f324d2020-11-20 23:29:54942void AutofillAgent::PasswordFieldReset(const WebInputElement& element) {
943 password_autofill_agent_->InformAboutFieldClearing(element);
944}
945
sebsg1c436852018-04-18 16:54:32946void AutofillAgent::SelectWasUpdated(
947 const blink::WebFormControlElement& element) {
948 // Look for the form and field associated with the select element. If they are
949 // found, notify the driver that the the form was modified dynamically.
sebsg248c6b02018-04-09 20:20:42950 FormData form;
951 FormFieldData field;
Ian Struiksma2988bc82020-02-18 09:13:13952 if (FindFormAndFieldForFormControlElement(element, field_data_manager_.get(),
Maria Kazinova168a9ed92020-02-06 15:05:20953 &form, &field) &&
sebsg248c6b02018-04-09 20:20:42954 !field.option_values.empty()) {
sebsg1c436852018-04-18 16:54:32955 GetAutofillDriver()->SelectFieldOptionsDidChange(form);
sebsg248c6b02018-04-09 20:20:42956 }
957}
958
Ehsan Karamad3538c8a2017-11-20 16:31:40959void AutofillAgent::FormControlElementClicked(
960 const WebFormControlElement& element,
961 bool was_focused) {
962 last_clicked_form_control_element_for_testing_ = element;
963 last_clicked_form_control_element_was_focused_for_testing_ = was_focused;
sebsg248c6b02018-04-09 20:20:42964 was_last_action_fill_ = false;
Ehsan Karamad3538c8a2017-11-20 16:31:40965
966 const WebInputElement* input_element = ToWebInputElement(&element);
967 if (!input_element && !form_util::IsTextAreaElement(element))
968 return;
969
Jan Wilken Dörrie6f5eee5a2019-10-11 16:14:36970 if (IsTouchToFillEnabled())
971 password_autofill_agent_->TryToShowTouchToFill(element);
972
Ehsan Karamad3538c8a2017-11-20 16:31:40973 ShowSuggestionsOptions options;
974 options.autofill_on_empty_values = true;
Roger McFarlane3a9c4402018-05-18 18:29:35975 // Show full suggestions when clicking on an already-focused form field.
976 options.show_full_suggestion_list = element.IsAutofilled() || was_focused;
Ehsan Karamad3538c8a2017-11-20 16:31:40977
Ehsan Karamad3538c8a2017-11-20 16:31:40978 ShowSuggestions(element, options);
Christoph Schweringb09a3282020-08-20 13:05:19979
980 SendPotentiallySubmittedFormToBrowser();
Ehsan Karamad3538c8a2017-11-20 16:31:40981}
982
983void AutofillAgent::HandleFocusChangeComplete() {
984 WebElement focused_element =
985 render_frame()->GetWebFrame()->GetDocument().FocusedElement();
Tommy Martino542b42352019-07-22 20:39:37986 // When using Talkback on Android, and possibly others, traversing to and
987 // focusing a field will not register as a click. Thus, when screen readers
988 // are used, treat the focused node as if it was the last clicked. Also check
989 // to ensure focus is on a field where text can be entered.
990 if ((focused_node_was_last_clicked_ || is_screen_reader_enabled_) &&
991 !focused_element.IsNull() && focused_element.IsFormControlElement() &&
Ehsan Karamad3538c8a2017-11-20 16:31:40992 (form_util::IsTextInput(blink::ToWebInputElement(&focused_element)) ||
993 focused_element.HasHTMLTagName("textarea"))) {
994 FormControlElementClicked(focused_element.ToConst<WebFormControlElement>(),
995 was_focused_before_now_);
996 }
997
998 was_focused_before_now_ = true;
999 focused_node_was_last_clicked_ = false;
Christoph Schweringb09a3282020-08-20 13:05:191000
1001 SendPotentiallySubmittedFormToBrowser();
ekaramad27ca69b12017-04-20 18:34:291002}
1003
Blink Reformat1c4d759e2017-04-09 16:34:541004void AutofillAgent::AjaxSucceeded() {
Tao Bai6cd41ad2017-12-04 18:48:171005 form_tracker_.AjaxSucceeded();
Christoph Schweringb09a3282020-08-20 13:05:191006
1007 SendPotentiallySubmittedFormToBrowser();
Tao Bai6cd41ad2017-12-04 18:48:171008}
1009
Tao Bai81483262018-03-02 05:38:121010void AutofillAgent::OnProvisionallySaveForm(
1011 const WebFormElement& form,
1012 const WebFormControlElement& element,
1013 ElementChangeSource source) {
Tao Bai6cd41ad2017-12-04 18:48:171014 if (source == ElementChangeSource::WILL_SEND_SUBMIT_EVENT) {
Tao Baia674b1d2018-01-18 22:33:431015 // Fire the form submission event to avoid missing submission when web site
1016 // handles the onsubmit event, this also gets the form before Javascript
1017 // could change it.
1018 // We don't clear submitted_forms_ because OnFormSubmitted will normally be
1019 // invoked afterwards and we don't want to fire the same event twice.
1020 FireHostSubmitEvents(form, /*known_success=*/false,
1021 SubmissionSource::FORM_SUBMISSION);
1022 ResetLastInteractedElements();
Tao Bai81483262018-03-02 05:38:121023 } else if (source == ElementChangeSource::TEXTFIELD_CHANGED ||
1024 source == ElementChangeSource::SELECT_CHANGED) {
Tao Baia674b1d2018-01-18 22:33:431025 // Remember the last form the user interacted with.
Tao Bai6cd41ad2017-12-04 18:48:171026 if (!element.Form().IsNull()) {
Tao Baie4d26212017-12-19 01:30:111027 UpdateLastInteractedForm(element.Form());
Tao Bai6cd41ad2017-12-04 18:48:171028 } else {
1029 // Remove invisible elements
Dominic Battre83bc9302021-01-18 16:42:311030 WebLocalFrame* frame = render_frame()->GetWebFrame();
Tao Bai6cd41ad2017-12-04 18:48:171031 for (auto it = formless_elements_user_edited_.begin();
1032 it != formless_elements_user_edited_.end();) {
Dominic Battre83bc9302021-01-18 16:42:311033 if (form_util::IsFormControlVisible(frame, *it)) {
Tao Bai6cd41ad2017-12-04 18:48:171034 it = formless_elements_user_edited_.erase(it);
1035 } else {
1036 ++it;
1037 }
1038 }
Dominic Battre83bc9302021-01-18 16:42:311039 formless_elements_user_edited_.insert(
1040 FieldRendererId(element.UniqueRendererFormControlId()));
Anton Bikineev1156b5f2021-05-15 22:35:361041 provisionally_saved_form_ = absl::make_optional<FormData>();
Christoph Schweringd54e56e2020-02-04 16:08:431042 if (!CollectFormlessElements(&provisionally_saved_form_.value())) {
Tao Baie4d26212017-12-19 01:30:111043 provisionally_saved_form_.reset();
Tao Bai6cd41ad2017-12-04 18:48:171044 } else {
1045 last_interacted_form_.Reset();
1046 }
1047 }
Tao Bai81483262018-03-02 05:38:121048
Christoph Schweringab66e432021-03-17 12:12:521049 if (source == ElementChangeSource::TEXTFIELD_CHANGED) {
Tao Bai81483262018-03-02 05:38:121050 OnTextFieldDidChange(*ToWebInputElement(&element));
Christoph Schweringab66e432021-03-17 12:12:521051 } else {
Tao Bai81483262018-03-02 05:38:121052 FormData form;
1053 FormFieldData field;
Maria Kazinova168a9ed92020-02-06 15:05:201054 if (FindFormAndFieldForFormControlElement(
Tao Bai6e605e42020-05-20 20:05:551055 element, field_data_manager_.get(),
1056 static_cast<ExtractMask>(form_util::EXTRACT_BOUNDS |
1057 GetExtractDatalistMask()),
Tao Baid9c02cf52020-03-30 22:13:391058 &form, &field)) {
1059 GetAutofillDriver()->SelectControlDidChange(form, field, field.bounds);
Tao Bai81483262018-03-02 05:38:121060 }
1061 }
Tao Bai6cd41ad2017-12-04 18:48:171062 }
Christoph Schweringb09a3282020-08-20 13:05:191063 SendPotentiallySubmittedFormToBrowser();
Tao Bai6cd41ad2017-12-04 18:48:171064}
1065
1066void AutofillAgent::OnProbablyFormSubmitted() {
Anton Bikineev1156b5f2021-05-15 22:35:361067 absl::optional<FormData> form_data = GetSubmittedForm();
Christoph Schweringb09a3282020-08-20 13:05:191068 if (form_data.has_value()) {
1069 FireHostSubmitEvents(form_data.value(), /*known_success=*/false,
Tao Baia674b1d2018-01-18 22:33:431070 SubmissionSource::PROBABLY_FORM_SUBMITTED);
1071 }
Tao Bai6cd41ad2017-12-04 18:48:171072 ResetLastInteractedElements();
Tao Baia674b1d2018-01-18 22:33:431073 OnFormNoLongerSubmittable();
Christoph Schweringb09a3282020-08-20 13:05:191074 SendPotentiallySubmittedFormToBrowser();
Tao Bai6cd41ad2017-12-04 18:48:171075}
1076
1077void AutofillAgent::OnFormSubmitted(const WebFormElement& form) {
Tao Baia674b1d2018-01-18 22:33:431078 // Fire the submission event here because WILL_SEND_SUBMIT_EVENT is skipped
1079 // if javascript calls submit() directly.
1080 FireHostSubmitEvents(form, /*known_success=*/false,
1081 SubmissionSource::FORM_SUBMISSION);
Tao Bai6cd41ad2017-12-04 18:48:171082 ResetLastInteractedElements();
Tao Baia674b1d2018-01-18 22:33:431083 OnFormNoLongerSubmittable();
Christoph Schweringb09a3282020-08-20 13:05:191084 SendPotentiallySubmittedFormToBrowser();
Tao Bai6cd41ad2017-12-04 18:48:171085}
1086
1087void AutofillAgent::OnInferredFormSubmission(SubmissionSource source) {
1088 // Only handle iframe for FRAME_DETACHED or main frame for
1089 // SAME_DOCUMENT_NAVIGATION.
1090 if ((source == SubmissionSource::FRAME_DETACHED &&
1091 !render_frame()->GetWebFrame()->Parent()) ||
1092 (source == SubmissionSource::SAME_DOCUMENT_NAVIGATION &&
1093 render_frame()->GetWebFrame()->Parent())) {
Tao Baia674b1d2018-01-18 22:33:431094 ResetLastInteractedElements();
1095 OnFormNoLongerSubmittable();
Christoph Schweringb09a3282020-08-20 13:05:191096 SendPotentiallySubmittedFormToBrowser();
Tao Bai6cd41ad2017-12-04 18:48:171097 return;
1098 }
1099
Tao Bai2c1b3d062017-12-07 17:20:281100 if (source == SubmissionSource::FRAME_DETACHED) {
1101 // Should not access the frame because it is now detached. Instead, use
Tao Baie4d26212017-12-19 01:30:111102 // |provisionally_saved_form_|.
Christoph Schweringd54e56e2020-02-04 16:08:431103 if (provisionally_saved_form_.has_value())
1104 FireHostSubmitEvents(provisionally_saved_form_.value(),
1105 /*known_success=*/true, source);
Tao Bai2c1b3d062017-12-07 17:20:281106 } else {
Anton Bikineev1156b5f2021-05-15 22:35:361107 absl::optional<FormData> form_data = GetSubmittedForm();
Christoph Schweringb09a3282020-08-20 13:05:191108 if (form_data.has_value())
1109 FireHostSubmitEvents(form_data.value(), /*known_success=*/true, source);
Tao Bai6cd41ad2017-12-04 18:48:171110 }
1111 ResetLastInteractedElements();
Tao Baia674b1d2018-01-18 22:33:431112 OnFormNoLongerSubmittable();
Christoph Schweringb09a3282020-08-20 13:05:191113 SendPotentiallySubmittedFormToBrowser();
Tao Bai6cd41ad2017-12-04 18:48:171114}
1115
1116void AutofillAgent::AddFormObserver(Observer* observer) {
1117 form_tracker_.AddObserver(observer);
1118}
1119
1120void AutofillAgent::RemoveFormObserver(Observer* observer) {
1121 form_tracker_.RemoveObserver(observer);
1122}
1123
Jan Wilken Dörried4119112c2020-11-09 18:42:121124void AutofillAgent::TrackAutofilledElement(
1125 const blink::WebFormControlElement& element) {
1126 form_tracker_.TrackAutofilledElement(element);
1127}
1128
Anton Bikineev1156b5f2021-05-15 22:35:361129absl::optional<FormData> AutofillAgent::GetSubmittedForm() const {
Tao Bai6cd41ad2017-12-04 18:48:171130 if (!last_interacted_form_.IsNull()) {
Christoph Schweringb09a3282020-08-20 13:05:191131 FormData form;
Maria Kazinova286b24e2020-02-05 13:20:121132 if (form_util::ExtractFormData(last_interacted_form_,
Christoph Schweringb09a3282020-08-20 13:05:191133 *field_data_manager_.get(), &form)) {
Anton Bikineev1156b5f2021-05-15 22:35:361134 return absl::make_optional(form);
Christoph Schweringd54e56e2020-02-04 16:08:431135 } else if (provisionally_saved_form_.has_value()) {
Anton Bikineev1156b5f2021-05-15 22:35:361136 return absl::make_optional(provisionally_saved_form_.value());
Tao Baie4d26212017-12-19 01:30:111137 }
Tao Bai6cd41ad2017-12-04 18:48:171138 } else if (formless_elements_user_edited_.size() != 0 &&
1139 !form_util::IsSomeControlElementVisible(
Dominic Battre83bc9302021-01-18 16:42:311140 render_frame()->GetWebFrame(),
Tao Bai6cd41ad2017-12-04 18:48:171141 formless_elements_user_edited_)) {
1142 // we check if all the elements the user has interacted with are gone,
Tao Baie4d26212017-12-19 01:30:111143 // to decide if submission has occurred, and use the
1144 // provisionally_saved_form_ saved in OnProvisionallySaveForm() if fail to
1145 // construct form.
Christoph Schweringb09a3282020-08-20 13:05:191146 FormData form;
1147 if (CollectFormlessElements(&form)) {
Anton Bikineev1156b5f2021-05-15 22:35:361148 return absl::make_optional(form);
Christoph Schweringd54e56e2020-02-04 16:08:431149 } else if (provisionally_saved_form_.has_value()) {
Anton Bikineev1156b5f2021-05-15 22:35:361150 return absl::make_optional(provisionally_saved_form_.value());
Tao Bai6cd41ad2017-12-04 18:48:171151 }
1152 }
Anton Bikineev1156b5f2021-05-15 22:35:361153 return absl::nullopt;
Christoph Schweringb09a3282020-08-20 13:05:191154}
1155
1156void AutofillAgent::SendPotentiallySubmittedFormToBrowser() {
1157 GetAutofillDriver()->SetFormToBeProbablySubmitted(GetSubmittedForm());
Tao Bai6cd41ad2017-12-04 18:48:171158}
1159
1160void AutofillAgent::ResetLastInteractedElements() {
1161 last_interacted_form_.Reset();
Alexander Timokhin3c45d1a2018-03-28 17:49:281162 last_clicked_form_control_element_for_testing_.Reset();
Tao Bai6cd41ad2017-12-04 18:48:171163 formless_elements_user_edited_.clear();
Tao Baie4d26212017-12-19 01:30:111164 provisionally_saved_form_.reset();
1165}
1166
1167void AutofillAgent::UpdateLastInteractedForm(blink::WebFormElement form) {
1168 last_interacted_form_ = form;
Anton Bikineev1156b5f2021-05-15 22:35:361169 provisionally_saved_form_ = absl::make_optional<FormData>();
Tao Baie4d26212017-12-19 01:30:111170 if (!form_util::ExtractFormData(last_interacted_form_,
Maria Kazinova286b24e2020-02-05 13:20:121171 *field_data_manager_.get(),
Christoph Schweringd54e56e2020-02-04 16:08:431172 &provisionally_saved_form_.value())) {
Tao Baie4d26212017-12-19 01:30:111173 provisionally_saved_form_.reset();
1174 }
gcastoc21f1c4c2015-03-19 21:57:031175}
1176
Tao Baia674b1d2018-01-18 22:33:431177void AutofillAgent::OnFormNoLongerSubmittable() {
1178 submitted_forms_.clear();
1179}
1180
Parastoo Geranmayeh1421e632018-07-25 15:57:031181bool AutofillAgent::FindTheUniqueNewVersionOfOldElement(
Parastoo Geranmayehc5d65c12018-11-21 05:32:021182 const WebVector<WebFormControlElement>& elements,
1183 bool& potential_match_encountered,
1184 WebFormControlElement& matching_element,
Parastoo Geranmayeh1421e632018-07-25 15:57:031185 const WebFormControlElement& original_element) {
Parastoo Geranmayehc5d65c12018-11-21 05:32:021186 if (original_element.IsNull())
1187 return false;
1188
1189 const auto original_element_section = original_element.AutofillSection();
Parastoo Geranmayeh1421e632018-07-25 15:57:031190 for (const WebFormControlElement& current_element : elements) {
1191 if (current_element.IsFocusable() &&
1192 original_element.NameForAutofill() ==
1193 current_element.NameForAutofill()) {
Parastoo Geranmayehc5d65c12018-11-21 05:32:021194 // If this is the first matching element, or is the first with the right
1195 // section, this is the best match so far.
1196 // In other words: bad, then good. => pick good.
1197 if (!potential_match_encountered ||
1198 (current_element.AutofillSection() == original_element_section &&
1199 (matching_element.IsNull() ||
1200 matching_element.AutofillSection() != original_element_section))) {
1201 matching_element = current_element;
1202 potential_match_encountered = true;
1203 } else if (current_element.AutofillSection() !=
1204 original_element_section &&
Parastoo Geranmayehd5f2cc262018-11-24 00:00:141205 !matching_element.IsNull() &&
Parastoo Geranmayehc5d65c12018-11-21 05:32:021206 matching_element.AutofillSection() !=
1207 original_element_section) {
1208 // The so far matching fields are equally bad. Continue the search if
1209 // none of them have the correct section.
1210 // In other words: bad, then bad => pick none.
1211 matching_element.Reset();
Parastoo Geranmayeh1421e632018-07-25 15:57:031212 } else if (current_element.AutofillSection() ==
Parastoo Geranmayehc5d65c12018-11-21 05:32:021213 original_element_section &&
Parastoo Geranmayehd5f2cc262018-11-24 00:00:141214 !matching_element.IsNull() &&
Parastoo Geranmayehc5d65c12018-11-21 05:32:021215 matching_element.AutofillSection() ==
1216 original_element_section) {
1217 // If two or more fields have the matching name and section, we can't
1218 // decide. Two equally good fields => fail.
1219 matching_element.Reset();
Parastoo Geranmayeh1421e632018-07-25 15:57:031220 return false;
Parastoo Geranmayehc5d65c12018-11-21 05:32:021221 } // For the good, then bad case => keep good. Continue the search.
Parastoo Geranmayeh1421e632018-07-25 15:57:031222 }
1223 }
1224 return true;
1225}
1226
sebsge39d1172018-11-07 23:56:461227// TODO(crbug.com/896689): Update this method to use the unique ids once they
1228// are implemented.
sebsge35b762c2018-03-29 20:33:271229void AutofillAgent::ReplaceElementIfNowInvalid(const FormData& original_form) {
1230 // If the document is invalid, bail out.
1231 if (element_.GetDocument().IsNull())
1232 return;
1233
Parastoo Geranmayehc5d65c12018-11-21 05:32:021234 const auto original_element = element_;
1235 WebFormControlElement matching_element;
1236 bool potential_match_encountered = false;
1237
Parastoo Geranmayeh1421e632018-07-25 15:57:031238 if (original_form.name.empty()) {
1239 // If the form has no name, check all the forms.
Jan Wilken Dörrie3f4a8a482020-04-23 07:30:241240 for (const WebFormElement& form : element_.GetDocument().Forms()) {
Parastoo Geranmayehc5d65c12018-11-21 05:32:021241 // If finding a unique element is impossible, don't look further.
Parastoo Geranmayeh1421e632018-07-25 15:57:031242 if (!FindTheUniqueNewVersionOfOldElement(
Jan Wilken Dörrie3f4a8a482020-04-23 07:30:241243 form.GetFormControlElements(), potential_match_encountered,
1244 matching_element, original_element))
Parastoo Geranmayeh1421e632018-07-25 15:57:031245 return;
1246 }
1247 // If the element is not found, we should still check for unowned elements.
Parastoo Geranmayehc5d65c12018-11-21 05:32:021248 if (!matching_element.IsNull()) {
1249 element_ = matching_element;
Parastoo Geranmayeh1421e632018-07-25 15:57:031250 return;
Parastoo Geranmayehc5d65c12018-11-21 05:32:021251 }
Parastoo Geranmayeh1421e632018-07-25 15:57:031252 }
1253
Jan Wilken Dörrie3f4a8a482020-04-23 07:30:241254 // If |element_|'s parent form has no elements, |element_| is now invalid
1255 // and should be updated.
1256 if (!element_.Form().IsNull() &&
1257 element_.Form().GetFormControlElements().empty()) {
1258 return;
sebsge35b762c2018-03-29 20:33:271259 }
1260
sebsge35b762c2018-03-29 20:33:271261 WebFormElement form_element;
Parastoo Geranmayehc5d65c12018-11-21 05:32:021262 bool form_is_found = false;
Parastoo Geranmayeh1421e632018-07-25 15:57:031263 if (!original_form.name.empty()) {
1264 // Try to find the new version of the form.
Jan Wilken Dörrie3f4a8a482020-04-23 07:30:241265 for (const WebFormElement& form : element_.GetDocument().Forms()) {
Parastoo Geranmayeh1421e632018-07-25 15:57:031266 if (original_form.name == form.GetName().Utf16() ||
1267 original_form.name == form.GetAttribute("id").Utf16()) {
Parastoo Geranmayehc5d65c12018-11-21 05:32:021268 if (!form_is_found)
1269 form_element = form;
1270 else // multiple forms with the matching name.
1271 return;
Parastoo Geranmayeh1421e632018-07-25 15:57:031272 }
sebsge35b762c2018-03-29 20:33:271273 }
1274 }
1275
sebsgf32e98d72018-05-11 14:43:011276 if (form_element.IsNull()) {
1277 // Could not find the new version of the form, get all the unowned elements.
1278 std::vector<WebElement> fieldsets;
Jan Wilken Dörrie3f4a8a482020-04-23 07:30:241279 WebVector<WebFormControlElement> elements =
1280 form_util::GetUnownedAutofillableFormFieldElements(
1281 element_.GetDocument().All(), &fieldsets);
Parastoo Geranmayehc5d65c12018-11-21 05:32:021282 // If a unique match was found.
1283 if (FindTheUniqueNewVersionOfOldElement(
1284 elements, potential_match_encountered, matching_element,
1285 original_element) &&
1286 !matching_element.IsNull()) {
1287 element_ = matching_element;
1288 }
Parastoo Geranmayeh1421e632018-07-25 15:57:031289 return;
sebsgf32e98d72018-05-11 14:43:011290 }
Parastoo Geranmayeh1421e632018-07-25 15:57:031291 // This is the case for owned fields that belong to the right named form.
1292 // Get all the elements of the new version of the form.
Parastoo Geranmayehc5d65c12018-11-21 05:32:021293 // If a unique match was found.
Jan Wilken Dörrie3f4a8a482020-04-23 07:30:241294 if (FindTheUniqueNewVersionOfOldElement(form_element.GetFormControlElements(),
1295 potential_match_encountered,
Parastoo Geranmayehc5d65c12018-11-21 05:32:021296 matching_element, original_element) &&
1297 !matching_element.IsNull()) {
1298 element_ = matching_element;
sebsge35b762c2018-03-29 20:33:271299 }
1300}
1301
Shimi Zhang6b72d292019-07-12 20:52:421302const mojo::AssociatedRemote<mojom::AutofillDriver>&
1303AutofillAgent::GetAutofillDriver() {
leon.han97e8f752016-09-06 06:13:201304 if (!autofill_driver_) {
Ken Rockot0aad7ec2018-07-31 15:58:441305 render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
Shimi Zhang6b72d292019-07-12 20:52:421306 &autofill_driver_);
leon.han90fd63b2016-07-26 01:23:551307 }
leon.hande852902016-05-04 09:16:381308
leon.han97e8f752016-09-06 06:13:201309 return autofill_driver_;
1310}
1311
Shimi Zhang6b72d292019-07-12 20:52:421312const mojo::AssociatedRemote<mojom::PasswordManagerDriver>&
leon.han97e8f752016-09-06 06:13:201313AutofillAgent::GetPasswordManagerDriver() {
1314 DCHECK(password_autofill_agent_);
1315 return password_autofill_agent_->GetPasswordManagerDriver();
leon.hande852902016-05-04 09:16:381316}
1317
[email protected]78192082011-01-29 05:43:441318} // namespace autofill