blob: e372068d96b4fe67c982573e6e36b36502362a76 [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"
Mathieu Perreaulta24d0c22017-11-10 01:22:0013#include "base/feature_list.h"
brettw94a2cc22015-07-01 19:26:5414#include "base/i18n/case_conversion.h"
skyostilb0daa012015-06-02 19:03:4815#include "base/location.h"
mathp4f6b0382016-04-12 20:41:1216#include "base/metrics/field_trial.h"
skyostilb0daa012015-06-02 19:03:4817#include "base/single_thread_task_runner.h"
mgiuca30f75882017-03-28 02:07:1918#include "base/strings/string_piece.h"
[email protected]1988e1c2013-02-28 20:27:4219#include "base/strings/string_split.h"
[email protected]c72674b2013-06-11 04:16:4320#include "base/strings/string_util.h"
[email protected]d2d79d52013-06-07 22:23:4821#include "base/strings/utf_string_conversions.h"
gab7966d312016-05-11 20:35:0122#include "base/threading/thread_task_runner_handle.h"
[email protected]bbd8da92013-06-28 02:12:2023#include "base/time/time.h"
avi4310d522015-12-25 19:37:5924#include "build/build_config.h"
[email protected]f07e4442013-06-06 23:03:4825#include "components/autofill/content/renderer/form_autofill_util.h"
Tao Bai6cd41ad2017-12-04 18:48:1726#include "components/autofill/content/renderer/form_tracker.h"
[email protected]f07e4442013-06-06 23:03:4827#include "components/autofill/content/renderer/password_autofill_agent.h"
[email protected]3cbdf9362014-01-31 23:12:2328#include "components/autofill/content/renderer/password_generation_agent.h"
jwwfb2a1432016-06-13 22:44:1529#include "components/autofill/content/renderer/renderer_save_password_progress_logger.h"
[email protected]d04f81912013-06-18 14:52:1330#include "components/autofill/core/common/autofill_constants.h"
[email protected]d86263dcd2014-01-09 10:35:2131#include "components/autofill/core/common/autofill_data_validation.h"
Mathieu Perreaulta24d0c22017-11-10 01:22:0032#include "components/autofill/core/common/autofill_features.h"
[email protected]d04f81912013-06-18 14:52:1333#include "components/autofill/core/common/autofill_switches.h"
Christoph Schweringaa41ba842019-10-14 08:00:0634#include "components/autofill/core/common/autofill_tick_clock.h"
rouslanc31f81d2015-08-24 17:33:5235#include "components/autofill/core/common/autofill_util.h"
[email protected]d04f81912013-06-18 14:52:1336#include "components/autofill/core/common/form_data.h"
37#include "components/autofill/core/common/form_data_predictions.h"
38#include "components/autofill/core/common/form_field_data.h"
[email protected]e620d362013-09-09 08:01:5339#include "components/autofill/core/common/password_form.h"
jwwfb2a1432016-06-13 22:44:1540#include "components/autofill/core/common/password_form_fill_data.h"
41#include "components/autofill/core/common/save_password_progress_logger.h"
[email protected]fed9d4f2013-12-17 21:32:4742#include "content/public/common/content_switches.h"
Tao Bai88d56d42017-07-17 16:07:1643#include "content/public/common/origin_util.h"
[email protected]ca5190f2013-07-08 11:10:3144#include "content/public/common/url_constants.h"
estadeb1bc9bd2014-12-02 22:44:1145#include "content/public/renderer/render_frame.h"
[email protected]a2ef54c2011-10-10 16:20:3146#include "content/public/renderer/render_view.h"
[email protected]ca5190f2013-07-08 11:10:3147#include "net/cert/cert_status_flags.h"
rockot734fb662016-10-15 16:41:3048#include "services/service_manager/public/cpp/interface_provider.h"
Ken Rockot0aad7ec2018-07-31 15:58:4449#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
Blink Reformata30d4232018-04-07 15:31:0650#include "third_party/blink/public/platform/web_keyboard_event.h"
51#include "third_party/blink/public/platform/web_url_request.h"
Akihiro Otab7c4cb12019-10-16 22:40:5952#include "third_party/blink/public/web/web_ax_enums.h"
Caitlin Fischerf23462e2019-06-21 15:30:4753#include "third_party/blink/public/web/web_ax_object.h"
Blink Reformata30d4232018-04-07 15:31:0654#include "third_party/blink/public/web/web_console_message.h"
55#include "third_party/blink/public/web/web_document.h"
56#include "third_party/blink/public/web/web_element_collection.h"
57#include "third_party/blink/public/web/web_form_control_element.h"
58#include "third_party/blink/public/web/web_form_element.h"
59#include "third_party/blink/public/web/web_local_frame.h"
60#include "third_party/blink/public/web/web_node.h"
61#include "third_party/blink/public/web/web_option_element.h"
62#include "third_party/blink/public/web/web_user_gesture_indicator.h"
63#include "third_party/blink/public/web/web_view.h"
[email protected]c051a1b2011-01-21 23:30:1764#include "ui/base/l10n/l10n_util.h"
[email protected]7e9acd082013-09-17 23:31:1665#include "ui/events/keycodes/keyboard_codes.h"
[email protected]679f128f2010-07-22 22:57:4466
[email protected]a1221aea2013-11-07 01:31:3067using blink::WebAutofillClient;
Caitlin Fischerf23462e2019-06-21 15:30:4768using blink::WebAutofillState;
69using blink::WebAXObject;
[email protected]dbdd60272014-04-14 22:48:4070using blink::WebConsoleMessage;
rouslanf7ebd8832015-01-22 01:54:1471using blink::WebDocument;
[email protected]5e7e8612014-03-20 14:43:1972using blink::WebElement;
73using blink::WebElementCollection;
[email protected]a1221aea2013-11-07 01:31:3074using blink::WebFormControlElement;
75using blink::WebFormElement;
76using blink::WebFrame;
77using blink::WebInputElement;
78using blink::WebKeyboardEvent;
[email protected]c5041c322014-04-08 05:06:4779using blink::WebLocalFrame;
[email protected]a1221aea2013-11-07 01:31:3080using blink::WebNode;
[email protected]a1221aea2013-11-07 01:31:3081using blink::WebOptionElement;
82using blink::WebString;
rouslan6a3f8d92015-04-28 01:00:0183using blink::WebUserGestureIndicator;
[email protected]5e7e8612014-03-20 14:43:1984using blink::WebVector;
[email protected]679f128f2010-07-22 22:57:4485
[email protected]d86263dcd2014-01-09 10:35:2186namespace autofill {
87
Jan Wilken Dörrief3785c42019-06-21 10:47:3788using mojom::SubmissionSource;
89
[email protected]e47aec52010-08-12 00:50:3090namespace {
91
sebsg1c436852018-04-18 16:54:3292// Time to wait, in ms, o ensure that only a single select change will be acted
93// upon, instead of multiple in close succession (debounce time).
sebsg248c6b02018-04-09 20:20:4294size_t kWaitTimeForSelectOptionsChangesMs = 50;
95
[email protected]45a07942013-07-26 08:28:2196// Gets all the data list values (with corresponding label) for the given
97// element.
[email protected]5e7e8612014-03-20 14:43:1998void GetDataListSuggestions(const WebInputElement& element,
[email protected]45a07942013-07-26 08:28:2199 std::vector<base::string16>* values,
100 std::vector<base::string16>* labels) {
Blink Reformat1c4d759e2017-04-09 16:34:54101 for (const auto& option : element.FilteredDataListOptions()) {
102 values->push_back(option.Value().Utf16());
103 if (option.Value() != option.Label())
104 labels->push_back(option.Label().Utf16());
[email protected]bef7f9272012-04-17 10:47:49105 else
[email protected]d5ca8fb2013-04-11 17:54:31106 labels->push_back(base::string16());
[email protected]bef7f9272012-04-17 10:47:49107 }
108}
109
[email protected]ead7fb02013-07-18 18:50:12110// Trim the vector before sending it to the browser process to ensure we
[email protected]5c8de6b92012-06-08 21:24:08111// don't send too much data through the IPC.
[email protected]ead7fb02013-07-18 18:50:12112void TrimStringVectorForIPC(std::vector<base::string16>* strings) {
113 // Limit the size of the vector.
[email protected]d86263dcd2014-01-09 10:35:21114 if (strings->size() > kMaxListSize)
115 strings->resize(kMaxListSize);
[email protected]5c8de6b92012-06-08 21:24:08116
[email protected]ead7fb02013-07-18 18:50:12117 // Limit the size of the strings in the vector.
118 for (size_t i = 0; i < strings->size(); ++i) {
[email protected]d86263dcd2014-01-09 10:35:21119 if ((*strings)[i].length() > kMaxDataLength)
120 (*strings)[i].resize(kMaxDataLength);
[email protected]5c8de6b92012-06-08 21:24:08121 }
122}
123
[email protected]e47aec52010-08-12 00:50:30124} // namespace
125
brettwb505b7a2014-11-26 22:05:32126AutofillAgent::ShowSuggestionsOptions::ShowSuggestionsOptions()
127 : autofill_on_empty_values(false),
128 requires_caret_at_end(false),
brettwb505b7a2014-11-26 22:05:32129 show_full_suggestion_list(false),
Fabio Tirelo83662a22018-07-06 15:03:48130 show_password_suggestions_only(false),
131 autoselect_first_suggestion(false) {}
brettwb505b7a2014-11-26 22:05:32132
estadeb1bc9bd2014-12-02 22:44:11133AutofillAgent::AutofillAgent(content::RenderFrame* render_frame,
[email protected]3cbdf9362014-01-31 23:12:23134 PasswordAutofillAgent* password_autofill_agent,
Ben Goodger205467b2017-08-02 19:33:55135 PasswordGenerationAgent* password_generation_agent,
Ken Rockot0aad7ec2018-07-31 15:58:44136 blink::AssociatedInterfaceRegistry* registry)
estadeb1bc9bd2014-12-02 22:44:11137 : content::RenderFrameObserver(render_frame),
Mathieu Perreaultd7b56b492017-10-18 16:52:17138 form_cache_(render_frame->GetWebFrame()),
[email protected]ad19b302013-04-03 07:42:19139 password_autofill_agent_(password_autofill_agent),
[email protected]3cbdf9362014-01-31 23:12:23140 password_generation_agent_(password_generation_agent),
[email protected]679f128f2010-07-22 22:57:44141 autofill_query_id_(0),
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39142 query_node_autofill_state_(WebAutofillState::kNotFilled),
[email protected]90f26252013-02-15 19:48:32143 ignore_text_changes_(false),
[email protected]b648f242014-02-25 13:49:06144 is_popup_possibly_visible_(false),
gcastocdd33e0d2015-06-17 22:10:05145 is_generation_popup_possibly_visible_(false),
Tao Baie13b5ca2017-06-23 16:15:51146 is_user_gesture_required_(true),
Tao Bai88d56d42017-07-17 16:07:16147 is_secure_context_required_(false),
Jeremy Roman5c341f6d2019-07-15 15:56:10148 form_tracker_(render_frame) {
Blink Reformat1c4d759e2017-04-09 16:34:54149 render_frame->GetWebFrame()->SetAutofillClient(this);
leon.han90fd63b2016-07-26 01:23:55150 password_autofill_agent->SetAutofillAgent(this);
Tao Bai6cd41ad2017-12-04 18:48:17151 AddFormObserver(this);
Ben Goodger205467b2017-08-02 19:33:55152 registry->AddInterface(
Shimi Zhang6b72d292019-07-12 20:52:42153 base::Bind(&AutofillAgent::BindPendingReceiver, base::Unretained(this)));
[email protected]679f128f2010-07-22 22:57:44154}
155
Tao Bai6cd41ad2017-12-04 18:48:17156AutofillAgent::~AutofillAgent() {
157 RemoveFormObserver(this);
158}
[email protected]d2f05d02011-01-27 18:51:01159
Shimi Zhang6b72d292019-07-12 20:52:42160void AutofillAgent::BindPendingReceiver(
161 mojo::PendingAssociatedReceiver<mojom::AutofillAgent> pending_receiver) {
162 receiver_.Bind(std::move(pending_receiver));
leon.hande852902016-05-04 09:16:38163}
164
mathp692aba82015-03-06 20:55:02165bool AutofillAgent::FormDataCompare::operator()(const FormData& lhs,
166 const FormData& rhs) const {
Vadym Doroshenko4147420a2019-04-16 14:27:51167 return std::tie(lhs.name, lhs.url, lhs.action, lhs.is_form_tag) <
168 std::tie(rhs.name, rhs.url, rhs.action, rhs.is_form_tag);
mathp692aba82015-03-06 20:55:02169}
170
Dmitry Gozman9cfe75d2018-09-18 21:36:08171void AutofillAgent::DidCommitProvisionalLoad(bool is_same_document_navigation,
172 ui::PageTransition transition) {
mathpffc78e22015-09-01 14:10:50173 blink::WebFrame* frame = render_frame()->GetWebFrame();
174 // TODO(dvadym): check if we need to check if it is main frame navigation
175 // http://crbug.com/443155
Blink Reformat1c4d759e2017-04-09 16:34:54176 if (frame->Parent())
mathpffc78e22015-09-01 14:10:50177 return; // Not a top-level navigation.
178
Tao Bai6cd41ad2017-12-04 18:48:17179 if (is_same_document_navigation)
180 return;
Hajime Hoshi53820e222017-08-17 02:28:11181
Tao Bai6cd41ad2017-12-04 18:48:17182 // Navigation to a new page or a page refresh.
Nektarios Paisios6b79cf6f2018-02-26 16:49:36183
Hajime Hoshi83c3f502018-03-14 05:49:01184 element_.Reset();
Nektarios Paisios6b79cf6f2018-02-26 16:49:36185
Tao Bai6cd41ad2017-12-04 18:48:17186 form_cache_.Reset();
187 ResetLastInteractedElements();
Tao Baia674b1d2018-01-18 22:33:43188 OnFormNoLongerSubmittable();
[email protected]676126f72011-01-15 00:03:51189}
190
estadeb1bc9bd2014-12-02 22:44:11191void AutofillAgent::DidFinishDocumentLoad() {
192 ProcessForms();
[email protected]3609c962014-07-11 03:18:25193}
194
estade2792527072014-12-17 00:41:47195void AutofillAgent::DidChangeScrollOffset() {
Changwan Ryuf85180e52018-08-10 04:31:46196 if (element_.IsNull())
197 return;
198
Changwan Ryu9db32db42018-01-24 14:54:44199 if (!focus_requires_scroll_) {
200 // Post a task here since scroll offset may change during layout.
201 // (https://crbug.com/804886)
202 weak_ptr_factory_.InvalidateWeakPtrs();
Hajime Hoshi9f80e742018-04-13 03:35:04203 render_frame()
204 ->GetTaskRunner(blink::TaskType::kInternalUserInteraction)
205 ->PostTask(FROM_HERE,
206 base::BindOnce(&AutofillAgent::DidChangeScrollOffsetImpl,
Changwan Ryu9db32db42018-01-24 14:54:44207 weak_ptr_factory_.GetWeakPtr(), element_));
Friedrich Horschig35355312019-09-09 17:26:34208 } else {
Changwan Ryu9db32db42018-01-24 14:54:44209 HidePopup();
Changwan Ryueb8a057e2017-12-08 19:22:33210 }
Changwan Ryu9db32db42018-01-24 14:54:44211}
Changwan Ryueb8a057e2017-12-08 19:22:33212
Changwan Ryu9db32db42018-01-24 14:54:44213void AutofillAgent::DidChangeScrollOffsetImpl(
214 const WebFormControlElement& element) {
Changwan Ryuf85180e52018-08-10 04:31:46215 if (element != element_ || element_.IsNull() || focus_requires_scroll_ ||
Changwan Ryu9db32db42018-01-24 14:54:44216 !is_popup_possibly_visible_ || !element_.Focused())
estadeb5efbab62015-04-28 18:07:42217 return;
rouslanc31f81d2015-08-24 17:33:52218
Changwan Ryu9db32db42018-01-24 14:54:44219 FormData form;
220 FormFieldData field;
221 if (form_util::FindFormAndFieldForFormControlElement(element_, &form,
222 &field)) {
223 GetAutofillDriver()->TextFieldDidScroll(
danakj3dcceba2019-10-09 22:16:23224 form, field, render_frame()->ElementBoundsInWindow(element_));
Changwan Ryu9db32db42018-01-24 14:54:44225 }
226
227 // Ignore subsequent scroll offset changes.
Friedrich Horschig35355312019-09-09 17:26:34228 HidePopup();
estadeb1bc9bd2014-12-02 22:44:11229}
230
Kent Tamura69d143e2019-05-22 00:31:45231void AutofillAgent::FocusedElementChanged(const WebElement& element) {
Ehsan Karamad3538c8a2017-11-20 16:31:40232 was_focused_before_now_ = false;
233
Changwan Ryueb8a057e2017-12-08 19:22:33234 if ((IsKeyboardAccessoryEnabled() || !focus_requires_scroll_) &&
Ehsan Karamad3538c8a2017-11-20 16:31:40235 WebUserGestureIndicator::IsProcessingUserGesture(
Kent Tamura69d143e2019-05-22 00:31:45236 element.IsNull() ? nullptr : element.GetDocument().GetFrame())) {
Ehsan Karamad3538c8a2017-11-20 16:31:40237 focused_node_was_last_clicked_ = true;
238 HandleFocusChangeComplete();
239 }
ekaramad27ca69b12017-04-20 18:34:29240
[email protected]91dcc6d32014-07-30 00:01:33241 HidePopup();
242
Kent Tamura69d143e2019-05-22 00:31:45243 if (element.IsNull()) {
Blink Reformat1c4d759e2017-04-09 16:34:54244 if (!last_interacted_form_.IsNull()) {
mathp8ac68ce2015-12-08 21:49:06245 // Focus moved away from the last interacted form to somewhere else on
246 // the page.
leon.han90fd63b2016-07-26 01:23:55247 GetAutofillDriver()->FocusNoLongerOnForm();
mathp8ac68ce2015-12-08 21:49:06248 }
estadeb1bc9bd2014-12-02 22:44:11249 return;
mathp8ac68ce2015-12-08 21:49:06250 }
estadeb1bc9bd2014-12-02 22:44:11251
Kent Tamura69d143e2019-05-22 00:31:45252 const WebInputElement* input = ToWebInputElement(&element);
mathpb4cf7b82015-12-11 16:42:24253
Blink Reformat1c4d759e2017-04-09 16:34:54254 if (!last_interacted_form_.IsNull() &&
Kent Tamura69d143e2019-05-22 00:31:45255 (!input || last_interacted_form_ != input->Form())) {
mathp8ac68ce2015-12-08 21:49:06256 // The focused element is not part of the last interacted form (could be
257 // in a different form).
leon.han90fd63b2016-07-26 01:23:55258 GetAutofillDriver()->FocusNoLongerOnForm();
mathp8ac68ce2015-12-08 21:49:06259 return;
260 }
[email protected]f920d6e2013-03-12 20:20:50261
Kent Tamura69d143e2019-05-22 00:31:45262 if (!input || !input->IsEnabled() || input->IsReadOnly() ||
263 !input->IsTextField())
[email protected]f920d6e2013-03-12 20:20:50264 return;
265
Kent Tamura69d143e2019-05-22 00:31:45266 element_ = *input;
Tao Bai168e4fc2017-06-19 18:46:38267
268 FormData form;
269 FormFieldData field;
270 if (form_util::FindFormAndFieldForFormControlElement(element_, &form,
271 &field)) {
272 GetAutofillDriver()->FocusOnFormField(
danakj3dcceba2019-10-09 22:16:23273 form, field, render_frame()->ElementBoundsInWindow(element_));
Tao Bai168e4fc2017-06-19 18:46:38274 }
[email protected]e5057a22013-04-22 12:41:39275}
276
vabrd62bc3e2016-05-04 15:58:52277void AutofillAgent::OnDestruct() {
278 Shutdown();
279 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
280}
281
Tommy Martino542b42352019-07-22 20:39:37282void AutofillAgent::AccessibilityModeChanged(const ui::AXMode& mode) {
283 is_screen_reader_enabled_ = mode.has_mode(ui::AXMode::kScreenReader);
284}
285
tmartino1c5348c92016-05-26 18:50:56286void AutofillAgent::FireHostSubmitEvents(const WebFormElement& form,
Tao Baia674b1d2018-01-18 22:33:43287 bool known_success,
288 SubmissionSource source) {
tmartino1c5348c92016-05-26 18:50:56289 FormData form_data;
290 if (!form_util::ExtractFormData(form, &form_data))
291 return;
292
Tao Baia674b1d2018-01-18 22:33:43293 FireHostSubmitEvents(form_data, known_success, source);
tmartino1c5348c92016-05-26 18:50:56294}
295
296void AutofillAgent::FireHostSubmitEvents(const FormData& form_data,
Tao Baia674b1d2018-01-18 22:33:43297 bool known_success,
298 SubmissionSource source) {
299 // We don't want to fire duplicate submission event.
300 if (!submitted_forms_.insert(form_data).second)
301 return;
302
Sebastien Lalancetteb2020be32019-01-08 15:17:59303 GetAutofillDriver()->FormSubmitted(form_data, known_success, source);
tmartino1c5348c92016-05-26 18:50:56304}
305
vabrd62bc3e2016-05-04 15:58:52306void AutofillAgent::Shutdown() {
Shimi Zhang6b72d292019-07-12 20:52:42307 receiver_.reset();
vabrd62bc3e2016-05-04 15:58:52308 weak_ptr_factory_.InvalidateWeakPtrs();
309}
310
Blink Reformat1c4d759e2017-04-09 16:34:54311void AutofillAgent::TextFieldDidEndEditing(const WebInputElement& element) {
Vasilii Sukhanovacf9b5d2018-11-09 16:18:47312 // Sometimes "blur" events are side effects of the password generation
313 // handling the page. They should not affect any UI in the browser.
314 if (password_generation_agent_ &&
315 password_generation_agent_->ShouldIgnoreBlur()) {
316 return;
317 }
leon.han90fd63b2016-07-26 01:23:55318 GetAutofillDriver()->DidEndTextFieldEditing();
Ioana Pandele9e742fe2018-10-11 19:07:54319 password_autofill_agent_->DidEndTextFieldEditing();
Ioana Pandele0c36cd0e42018-11-05 17:51:31320 if (password_generation_agent_)
321 password_generation_agent_->DidEndTextFieldEditing(element);
[email protected]676126f72011-01-15 00:03:51322}
323
Tao Baie13b5ca2017-06-23 16:15:51324void AutofillAgent::SetUserGestureRequired(bool required) {
Tao Bai6cd41ad2017-12-04 18:48:17325 form_tracker_.set_user_gesture_required(required);
Tao Baie13b5ca2017-06-23 16:15:51326}
327
Blink Reformat1c4d759e2017-04-09 16:34:54328void AutofillAgent::TextFieldDidChange(const WebFormControlElement& element) {
Tao Bai6cd41ad2017-12-04 18:48:17329 form_tracker_.TextFieldDidChange(element);
[email protected]676126f72011-01-15 00:03:51330}
331
Tao Bai6cd41ad2017-12-04 18:48:17332void AutofillAgent::OnTextFieldDidChange(const WebInputElement& element) {
333 if (password_generation_agent_ &&
334 password_generation_agent_->TextDidChangeInTextField(element)) {
335 is_popup_possibly_visible_ = true;
[email protected]f9af2832012-12-14 04:20:43336 return;
Tao Bai6cd41ad2017-12-04 18:48:17337 }
[email protected]f9af2832012-12-14 04:20:43338
Tao Bai6cd41ad2017-12-04 18:48:17339 if (password_autofill_agent_->TextDidChangeInTextField(element)) {
340 is_popup_possibly_visible_ = true;
341 element_ = element;
342 return;
[email protected]e7e83472012-04-05 02:56:26343 }
[email protected]676126f72011-01-15 00:03:51344
brettwb505b7a2014-11-26 22:05:32345 ShowSuggestionsOptions options;
346 options.requires_caret_at_end = true;
347 ShowSuggestions(element, options);
[email protected]7d24db72011-08-26 06:02:31348
[email protected]1ecbe862012-10-05 01:29:14349 FormData form;
350 FormFieldData field;
mathp9172c62a2015-10-08 18:51:14351 if (form_util::FindFormAndFieldForFormControlElement(element, &form,
352 &field)) {
Tao Bai168e4fc2017-06-19 18:46:38353 GetAutofillDriver()->TextFieldDidChange(
danakj3dcceba2019-10-09 22:16:23354 form, field, render_frame()->ElementBoundsInWindow(element),
Christoph Schweringaa41ba842019-10-14 08:00:06355 AutofillTickClock::NowTicks());
[email protected]1d14f582011-09-02 20:42:04356 }
[email protected]676126f72011-01-15 00:03:51357}
358
Blink Reformat1c4d759e2017-04-09 16:34:54359void AutofillAgent::TextFieldDidReceiveKeyDown(const WebInputElement& element,
[email protected]2fa18c22011-06-14 23:40:43360 const WebKeyboardEvent& event) {
Blink Reformat1c4d759e2017-04-09 16:34:54361 if (event.windows_key_code == ui::VKEY_DOWN ||
362 event.windows_key_code == ui::VKEY_UP) {
brettwb505b7a2014-11-26 22:05:32363 ShowSuggestionsOptions options;
364 options.autofill_on_empty_values = true;
365 options.requires_caret_at_end = true;
Fabio Tirelo83662a22018-07-06 15:03:48366 options.autoselect_first_suggestion =
367 ShouldAutoselectFirstSuggestionOnArrowDown();
brettwb505b7a2014-11-26 22:05:32368 ShowSuggestions(element, options);
369 }
[email protected]efeb565f2013-12-12 17:16:41370}
371
Blink Reformat1c4d759e2017-04-09 16:34:54372void AutofillAgent::OpenTextDataListChooser(const WebInputElement& element) {
brettwb505b7a2014-11-26 22:05:32373 ShowSuggestionsOptions options;
374 options.autofill_on_empty_values = true;
brettwb505b7a2014-11-26 22:05:32375 ShowSuggestions(element, options);
[email protected]676126f72011-01-15 00:03:51376}
377
Blink Reformat1c4d759e2017-04-09 16:34:54378void AutofillAgent::DataListOptionsChanged(const WebInputElement& element) {
379 if (!is_popup_possibly_visible_ || !element.Focused())
estadedf5088a2014-12-15 02:04:07380 return;
381
Tao Bai6cd41ad2017-12-04 18:48:17382 OnProvisionallySaveForm(WebFormElement(), element,
383 ElementChangeSource::TEXTFIELD_CHANGED);
estadedf5088a2014-12-15 02:04:07384}
385
vasiliifd0e8ca2017-04-12 11:11:22386void AutofillAgent::UserGestureObserved() {
387 password_autofill_agent_->UserGestureObserved();
[email protected]fc22ae52014-04-23 13:48:04388}
389
leon.han90fd63b2016-07-26 01:23:55390void AutofillAgent::DoAcceptDataListSuggestion(
[email protected]d5ca8fb2013-04-11 17:54:31391 const base::string16& suggested_value) {
Hajime Hoshie6104dc92018-03-20 05:58:02392 if (element_.IsNull())
393 return;
394
Blink Reformat1c4d759e2017-04-09 16:34:54395 WebInputElement* input_element = ToWebInputElement(&element_);
[email protected]e9d29d392014-03-25 01:15:15396 DCHECK(input_element);
[email protected]d5ca8fb2013-04-11 17:54:31397 base::string16 new_value = suggested_value;
[email protected]71a90b32012-05-18 09:16:53398 // If this element takes multiple values then replace the last part with
399 // the suggestion.
Blink Reformat1c4d759e2017-04-09 16:34:54400 if (input_element->IsMultiple() && input_element->IsEmailField()) {
Matt Giuca93bc1582017-08-01 05:09:57401 base::string16 value = input_element->EditingValue().Utf16();
402 std::vector<base::StringPiece16> parts =
403 base::SplitStringPiece(value, base::ASCIIToUTF16(","),
404 base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
[email protected]71a90b32012-05-18 09:16:53405 if (parts.size() == 0)
mgiuca30f75882017-03-28 02:07:19406 parts.push_back(base::StringPiece16());
[email protected]71a90b32012-05-18 09:16:53407
mgiuca30f75882017-03-28 02:07:19408 base::string16 last_part = parts.back().as_string();
[email protected]71a90b32012-05-18 09:16:53409 // We want to keep just the leading whitespace.
410 for (size_t i = 0; i < last_part.size(); ++i) {
brettwb3413062015-06-24 00:39:02411 if (!base::IsUnicodeWhitespace(last_part[i])) {
[email protected]71a90b32012-05-18 09:16:53412 last_part = last_part.substr(0, i);
413 break;
414 }
415 }
416 last_part.append(suggested_value);
thestigee1440b2016-07-08 01:06:55417 parts.back() = last_part;
[email protected]71a90b32012-05-18 09:16:53418
brettwd94a22142015-07-15 05:19:26419 new_value = base::JoinString(parts, base::ASCIIToUTF16(","));
[email protected]71a90b32012-05-18 09:16:53420 }
leon.han90fd63b2016-07-26 01:23:55421 DoFillFieldWithValue(new_value, input_element);
[email protected]63560b32014-03-04 07:06:26422}
423
Parastoo Geranmayeh522c2222018-07-16 15:14:03424void AutofillAgent::TriggerRefillIfNeeded(const FormData& form) {
Parastoo Geranmayeh1421e632018-07-25 15:57:03425 ReplaceElementIfNowInvalid(form);
426
Parastoo Geranmayeh522c2222018-07-16 15:14:03427 FormFieldData field;
428 FormData updated_form;
429 if (form_util::FindFormAndFieldForFormControlElement(element_, &updated_form,
430 &field) &&
Parastoo Geranmayeh1421e632018-07-25 15:57:03431 (!element_.IsAutofilled() || !form.DynamicallySameFormAs(updated_form))) {
Christoph Schweringaa41ba842019-10-14 08:00:06432 base::TimeTicks forms_seen_timestamp = AutofillTickClock::NowTicks();
Parastoo Geranmayeh522c2222018-07-16 15:14:03433 WebLocalFrame* frame = render_frame()->GetWebFrame();
434 std::vector<FormData> forms;
435 forms.push_back(updated_form);
436 // Always communicate to browser process for topmost frame.
Parastoo Geranmayeh1421e632018-07-25 15:57:03437 if (!forms.empty() || !frame->Parent()) {
Parastoo Geranmayeh522c2222018-07-16 15:14:03438 GetAutofillDriver()->FormsSeen(forms, forms_seen_timestamp);
Parastoo Geranmayeh1421e632018-07-25 15:57:03439 }
Parastoo Geranmayeh522c2222018-07-16 15:14:03440 }
441}
442
leon.hande852902016-05-04 09:16:38443// mojom::AutofillAgent:
leon.han90fd63b2016-07-26 01:23:55444void AutofillAgent::FillForm(int32_t id, const FormData& form) {
Hajime Hoshie6104dc92018-03-20 05:58:02445 if (element_.IsNull())
446 return;
447
mathpf43ced42016-08-04 18:28:23448 if (id != autofill_query_id_ && id != kNoQueryId)
leon.han90fd63b2016-07-26 01:23:55449 return;
450
sebsg248c6b02018-04-09 20:20:42451 was_last_action_fill_ = true;
452
sebsge39d1172018-11-07 23:56:46453 // If this is a re-fill, replace the triggering element if it's invalid.
Fabio Tireloa0442b9b92019-03-19 23:59:18454 if (id == kNoQueryId)
sebsge35b762c2018-03-29 20:33:27455 ReplaceElementIfNowInvalid(form);
456
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39457 query_node_autofill_state_ = element_.GetAutofillState();
leon.han90fd63b2016-07-26 01:23:55458 form_util::FillForm(form, element_);
Blink Reformat1c4d759e2017-04-09 16:34:54459 if (!element_.Form().IsNull())
Tao Baie4d26212017-12-19 01:30:11460 UpdateLastInteractedForm(element_.Form());
leon.han90fd63b2016-07-26 01:23:55461
Christoph Schweringaa41ba842019-10-14 08:00:06462 GetAutofillDriver()->DidFillAutofillFormData(form,
463 AutofillTickClock::NowTicks());
Parastoo Geranmayeh522c2222018-07-16 15:14:03464
465 TriggerRefillIfNeeded(form);
[email protected]8527a78f2014-06-12 12:49:15466}
467
leon.han90fd63b2016-07-26 01:23:55468void AutofillAgent::PreviewForm(int32_t id, const FormData& form) {
Hajime Hoshie6104dc92018-03-20 05:58:02469 if (element_.IsNull())
470 return;
471
leon.han90fd63b2016-07-26 01:23:55472 if (id != autofill_query_id_)
[email protected]63560b32014-03-04 07:06:26473 return;
474
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39475 query_node_autofill_state_ = element_.GetAutofillState();
mathp9172c62a2015-10-08 18:51:14476 form_util::PreviewForm(form, element_);
leon.han90fd63b2016-07-26 01:23:55477
478 GetAutofillDriver()->DidPreviewAutofillFormData();
[email protected]6f001a6cf2012-02-09 15:21:53479}
480
leon.han90fd63b2016-07-26 01:23:55481void AutofillAgent::FieldTypePredictionsAvailable(
leon.han35ae41c2016-07-29 03:30:58482 const std::vector<FormDataPredictions>& forms) {
Mathieu Perreaultd7b56b492017-10-18 16:52:17483 bool attach_predictions_to_dom =
Mathieu Perreaulta24d0c22017-11-10 01:22:00484 base::FeatureList::IsEnabled(features::kAutofillShowTypePredictions);
leon.han90fd63b2016-07-26 01:23:55485 for (const auto& form : forms) {
Mathieu Perreaultd7b56b492017-10-18 16:52:17486 form_cache_.ShowPredictions(form, attach_predictions_to_dom);
leon.han90fd63b2016-07-26 01:23:55487 }
488}
489
Parastoo Geranmayeh7d8ea062018-05-15 22:16:25490void AutofillAgent::ClearSection() {
Hajime Hoshie6104dc92018-03-20 05:58:02491 if (element_.IsNull())
492 return;
493
Parastoo Geranmayeh7d8ea062018-05-15 22:16:25494 form_cache_.ClearSectionWithElement(element_);
[email protected]6f001a6cf2012-02-09 15:21:53495}
496
leon.han90fd63b2016-07-26 01:23:55497void AutofillAgent::ClearPreviewedForm() {
Hajime Hoshi83c3f502018-03-14 05:49:01498 // TODO(crbug.com/816533): It is very rare, but it looks like the |element_|
499 // can be null if a provisional load was committed immediately prior to
500 // clearing the previewed form.
501 if (element_.IsNull())
502 return;
[email protected]b5b1d69f2014-01-23 23:49:32503
Hajime Hoshi83c3f502018-03-14 05:49:01504 if (password_autofill_agent_->DidClearAutofillSelection(element_))
505 return;
506
507 form_util::ClearPreviewedFormWithElement(element_,
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39508 query_node_autofill_state_);
[email protected]6f001a6cf2012-02-09 15:21:53509}
510
leon.han35ae41c2016-07-29 03:30:58511void AutofillAgent::FillFieldWithValue(const base::string16& value) {
Hajime Hoshie6104dc92018-03-20 05:58:02512 if (element_.IsNull())
513 return;
514
Blink Reformat1c4d759e2017-04-09 16:34:54515 WebInputElement* input_element = ToWebInputElement(&element_);
ziran.sunee0fd4432014-08-27 10:10:49516 if (input_element) {
leon.han35ae41c2016-07-29 03:30:58517 DoFillFieldWithValue(value, input_element);
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39518 input_element->SetAutofillState(WebAutofillState::kAutofilled);
ziran.sunee0fd4432014-08-27 10:10:49519 }
[email protected]ac9b92f2014-03-15 00:48:32520}
521
leon.han35ae41c2016-07-29 03:30:58522void AutofillAgent::PreviewFieldWithValue(const base::string16& value) {
Hajime Hoshie6104dc92018-03-20 05:58:02523 if (element_.IsNull())
524 return;
525
Blink Reformat1c4d759e2017-04-09 16:34:54526 WebInputElement* input_element = ToWebInputElement(&element_);
[email protected]e9d29d392014-03-25 01:15:15527 if (input_element)
leon.han35ae41c2016-07-29 03:30:58528 DoPreviewFieldWithValue(value, input_element);
[email protected]6f001a6cf2012-02-09 15:21:53529}
530
Akihiro Otab7c4cb12019-10-16 22:40:59531void AutofillAgent::SetSuggestionAvailability(
532 const mojom::AutofillState state) {
Caitlin Fischerf23462e2019-06-21 15:30:47533 if (element_.IsNull())
534 return;
535
536 WebInputElement* input_element = ToWebInputElement(&element_);
Akihiro Otab7c4cb12019-10-16 22:40:59537 if (input_element) {
538 switch (state) {
539 case autofill::mojom::AutofillState::kAutofillAvailable:
540 WebAXObject::FromWebNode(*input_element)
541 .HandleAutofillStateChanged(
542 blink::WebAXAutofillState::kAutofillAvailable);
543 return;
544 case autofill::mojom::AutofillState::kAutocompleteAvailable:
545 WebAXObject::FromWebNode(*input_element)
546 .HandleAutofillStateChanged(
547 blink::WebAXAutofillState::kAutocompleteAvailable);
548 return;
549 case autofill::mojom::AutofillState::kNoSuggestions:
550 WebAXObject::FromWebNode(*input_element)
551 .HandleAutofillStateChanged(
552 blink::WebAXAutofillState::kNoSuggestions);
553 return;
554 }
555 NOTREACHED();
556 }
Caitlin Fischerf23462e2019-06-21 15:30:47557}
558
leon.han35ae41c2016-07-29 03:30:58559void AutofillAgent::AcceptDataListSuggestion(const base::string16& value) {
560 DoAcceptDataListSuggestion(value);
[email protected]5c8de6b92012-06-08 21:24:08561}
562
leon.han35ae41c2016-07-29 03:30:58563void AutofillAgent::FillPasswordSuggestion(const base::string16& username,
564 const base::string16& password) {
Hajime Hoshie6104dc92018-03-20 05:58:02565 if (element_.IsNull())
566 return;
567
leon.han35ae41c2016-07-29 03:30:58568 bool handled =
569 password_autofill_agent_->FillSuggestion(element_, username, password);
[email protected]126b1ad2014-05-21 22:37:33570 DCHECK(handled);
571}
572
leon.han35ae41c2016-07-29 03:30:58573void AutofillAgent::PreviewPasswordSuggestion(const base::string16& username,
574 const base::string16& password) {
Hajime Hoshie6104dc92018-03-20 05:58:02575 if (element_.IsNull())
576 return;
577
kinuko0073e7c82017-01-24 00:42:40578 bool handled = password_autofill_agent_->PreviewSuggestion(
Blink Reformat1c4d759e2017-04-09 16:34:54579 element_, blink::WebString::FromUTF16(username),
580 blink::WebString::FromUTF16(password));
[email protected]e7e83472012-04-05 02:56:26581 DCHECK(handled);
582}
583
tmartino283dda12016-06-23 21:43:54584bool AutofillAgent::CollectFormlessElements(FormData* output) {
Tao Bai86ac37152018-03-02 14:35:33585 if (render_frame() == nullptr || render_frame()->GetWebFrame() == nullptr)
586 return false;
587
Blink Reformat1c4d759e2017-04-09 16:34:54588 WebDocument document = render_frame()->GetWebFrame()->GetDocument();
tmartino283dda12016-06-23 21:43:54589
590 // Build up the FormData from the unowned elements. This logic mostly
591 // mirrors the construction of the synthetic form in form_cache.cc, but
592 // happens at submit-time so we can capture the modifications the user
593 // has made, and doesn't depend on form_cache's internal state.
594 std::vector<WebElement> fieldsets;
595 std::vector<WebFormControlElement> control_elements =
Blink Reformat1c4d759e2017-04-09 16:34:54596 form_util::GetUnownedAutofillableFormFieldElements(document.All(),
tmartino283dda12016-06-23 21:43:54597 &fieldsets);
598
599 if (control_elements.size() > form_util::kMaxParseableFields)
600 return false;
601
602 const form_util::ExtractMask extract_mask =
603 static_cast<form_util::ExtractMask>(form_util::EXTRACT_VALUE |
604 form_util::EXTRACT_OPTIONS);
605
606 return form_util::UnownedCheckoutFormElementsAndFieldSetsToFormData(
607 fieldsets, control_elements, nullptr, document, extract_mask, output,
608 nullptr);
mathpffc78e22015-09-01 14:10:50609}
610
[email protected]e9d29d392014-03-25 01:15:15611void AutofillAgent::ShowSuggestions(const WebFormControlElement& element,
brettwb505b7a2014-11-26 22:05:32612 const ShowSuggestionsOptions& options) {
Blink Reformat1c4d759e2017-04-09 16:34:54613 if (!element.IsEnabled() || element.IsReadOnly())
[email protected]efeb565f2013-12-12 17:16:41614 return;
Blink Reformat1c4d759e2017-04-09 16:34:54615 if (!element.SuggestedValue().IsEmpty())
[email protected]580c38052014-07-16 07:28:09616 return;
[email protected]e9d29d392014-03-25 01:15:15617
Blink Reformat1c4d759e2017-04-09 16:34:54618 const WebInputElement* input_element = ToWebInputElement(&element);
[email protected]e9d29d392014-03-25 01:15:15619 if (input_element) {
Blink Reformat1c4d759e2017-04-09 16:34:54620 if (!input_element->IsTextField())
[email protected]e9d29d392014-03-25 01:15:15621 return;
Blink Reformat1c4d759e2017-04-09 16:34:54622 if (!input_element->SuggestedValue().IsEmpty())
[email protected]e9d29d392014-03-25 01:15:15623 return;
624 } else {
mathp9172c62a2015-10-08 18:51:14625 DCHECK(form_util::IsTextAreaElement(element));
Blink Reformat1c4d759e2017-04-09 16:34:54626 if (!element.ToConst<WebFormControlElement>().SuggestedValue().IsEmpty())
[email protected]e9d29d392014-03-25 01:15:15627 return;
628 }
[email protected]e47aec52010-08-12 00:50:30629
[email protected]1c69f8b72012-03-14 03:18:50630 // Don't attempt to autofill with values that are too large or if filling
631 // criteria are not met.
Blink Reformat1c4d759e2017-04-09 16:34:54632 WebString value = element.EditingValue();
mathp5f90bce22015-11-22 20:16:58633 if (value.length() > kMaxDataLength ||
Friedrich Horschig35355312019-09-09 17:26:34634 (!options.autofill_on_empty_values && value.IsEmpty()) ||
mathp5f90bce22015-11-22 20:16:58635 (options.requires_caret_at_end &&
Blink Reformat1c4d759e2017-04-09 16:34:54636 (element.SelectionStart() != element.SelectionEnd() ||
637 element.SelectionEnd() != static_cast<int>(value.length())))) {
[email protected]1c69f8b72012-03-14 03:18:50638 // Any popup currently showing is obsolete.
[email protected]b648f242014-02-25 13:49:06639 HidePopup();
[email protected]e47aec52010-08-12 00:50:30640 return;
[email protected]1c69f8b72012-03-14 03:18:50641 }
[email protected]e47aec52010-08-12 00:50:30642
[email protected]bef7f9272012-04-17 10:47:49643 element_ = element;
mathp9172c62a2015-10-08 18:51:14644 if (form_util::IsAutofillableInputElement(input_element) &&
gcastocdd33e0d2015-06-17 22:10:05645 password_autofill_agent_->ShowSuggestions(
646 *input_element, options.show_full_suggestion_list,
647 is_generation_popup_possibly_visible_)) {
[email protected]b648f242014-02-25 13:49:06648 is_popup_possibly_visible_ = true;
[email protected]c66ba982013-04-05 09:56:17649 return;
[email protected]b648f242014-02-25 13:49:06650 }
[email protected]bef7f9272012-04-17 10:47:49651
gcastocdd33e0d2015-06-17 22:10:05652 if (is_generation_popup_possibly_visible_)
653 return;
654
655 if (options.show_password_suggestions_only)
656 return;
657
jww20355072014-12-12 21:00:55658 // Password field elements should only have suggestions shown by the password
659 // autofill agent.
Dominic Battre9758fad2019-01-02 14:14:33660 // The /*disable presubmit*/ comment below is used to disable a presubmit
661 // script that ensures that only IsPasswordFieldForAutofill() is used in this
662 // code (it has to appear between the function name and the parentesis to not
663 // match a regex). In this specific case we are actually interested in whether
664 // the field is currently a password field, not whether it has ever been a
665 // password field.
666 if (input_element &&
667 input_element->IsPasswordField /*disable presubmit*/ () &&
Dominic Battre1bb521c2017-12-19 21:10:03668 !query_password_suggestion_) {
jww20355072014-12-12 21:00:55669 return;
Dominic Battre1bb521c2017-12-19 21:10:03670 }
jww20355072014-12-12 21:00:55671
Fabio Tirelo83662a22018-07-06 15:03:48672 QueryAutofillSuggestions(element, options.autoselect_first_suggestion);
[email protected]77bb0da2010-11-20 01:55:30673}
674
Tao Baia8c0d8bb2017-12-18 19:47:36675void AutofillAgent::SetQueryPasswordSuggestion(bool query) {
676 query_password_suggestion_ = query;
677}
678
Tao Bai88d56d42017-07-17 16:07:16679void AutofillAgent::SetSecureContextRequired(bool required) {
680 is_secure_context_required_ = required;
681}
682
Changwan Ryueb8a057e2017-12-08 19:22:33683void AutofillAgent::SetFocusRequiresScroll(bool require) {
684 focus_requires_scroll_ = require;
685}
686
gogeraldd4f184b2018-09-19 22:24:24687void AutofillAgent::GetElementFormAndFieldData(
688 const std::vector<std::string>& selectors,
689 GetElementFormAndFieldDataCallback callback) {
690 FormData form;
691 FormFieldData field;
692 blink::WebElement target_element = FindUniqueWebElement(selectors);
693 if (target_element.IsNull() || !target_element.IsFormControlElement()) {
694 return std::move(callback).Run(form, field);
695 }
696
697 blink::WebFormControlElement target_form_control_element =
698 target_element.To<blink::WebFormControlElement>();
gogerald3e2f8a12018-10-11 21:46:54699 bool success = form_util::FindFormAndFieldForFormControlElement(
700 target_form_control_element, &form, &field);
701 if (success) {
702 // Remember this element so as to autofill the form without focusing the
703 // field for Autofill Assistant.
704 element_ = target_form_control_element;
705 }
706 // Do not expect failure.
707 DCHECK(success);
708
gogeraldd4f184b2018-09-19 22:24:24709 return std::move(callback).Run(form, field);
710}
711
712blink::WebElement AutofillAgent::FindUniqueWebElement(
713 const std::vector<std::string>& selectors) {
714 DCHECK(selectors.size() > 0);
715
716 blink::WebVector<blink::WebElement> elements =
717 render_frame()->GetWebFrame()->GetDocument().QuerySelectorAll(
718 blink::WebString::FromUTF8(selectors[0]));
719 if (elements.size() != 1) {
720 return blink::WebElement();
721 }
722
723 // Get the unique element in |elements| and match the next selector inside it
724 // if there are remaining selectors haven't been matched.
725 blink::WebElement query_element = elements[0];
726 for (size_t i = 1; i < selectors.size(); i++) {
727 elements = query_element.QuerySelectorAll(
728 blink::WebString::FromUTF8(selectors[i]));
729
730 // Query shadow DOM if necessary.
731 if (elements.size() == 0 && !query_element.ShadowRoot().IsNull()) {
gogeraldd52275112018-09-21 02:17:22732 // TODO(806868): Query shadow dom when Autofill is available for forms in
733 // shadow DOM (crbug.com/746593).
734 return blink::WebElement();
gogeraldd4f184b2018-09-19 22:24:24735 }
736
737 // Return an empty element if there are multiple matching elements.
738 if (elements.size() != 1) {
739 return blink::WebElement();
740 }
741
742 query_element = elements[0];
743 }
744
745 return query_element;
746}
747
[email protected]e9d29d392014-03-25 01:15:15748void AutofillAgent::QueryAutofillSuggestions(
Fabio Tirelo83662a22018-07-06 15:03:48749 const WebFormControlElement& element,
750 bool autoselect_first_suggestion) {
Blink Reformat1c4d759e2017-04-09 16:34:54751 if (!element.GetDocument().GetFrame())
[email protected]e69b5f72013-01-24 00:59:13752 return;
753
Blink Reformat1c4d759e2017-04-09 16:34:54754 DCHECK(ToWebInputElement(&element) || form_util::IsTextAreaElement(element));
[email protected]e9d29d392014-03-25 01:15:15755
[email protected]77bb0da2010-11-20 01:55:30756 static int query_counter = 0;
757 autofill_query_id_ = query_counter++;
estade0ee91262014-10-23 19:29:19758
[email protected]1ecbe862012-10-05 01:29:14759 FormData form;
760 FormFieldData field;
mathp9172c62a2015-10-08 18:51:14761 if (!form_util::FindFormAndFieldForFormControlElement(element, &form,
762 &field)) {
[email protected]7837be62011-01-18 23:45:08763 // If we didn't find the cached form, at least let autocomplete have a shot
764 // at providing suggestions.
kolos66b4c292016-07-29 17:54:53765 WebFormControlElementToFormField(element, nullptr, form_util::EXTRACT_VALUE,
766 &field);
[email protected]7837be62011-01-18 23:45:08767 }
[email protected]77bb0da2010-11-20 01:55:30768
Tao Bai88d56d42017-07-17 16:07:16769 if (is_secure_context_required_ &&
Tao Bai6b032dd2017-09-19 18:44:07770 !(element.GetDocument().IsSecureContext())) {
Tao Bai88d56d42017-07-17 16:07:16771 LOG(WARNING) << "Autofill suggestions are disabled because the document "
Tao Bai6b032dd2017-09-19 18:44:07772 "isn't a secure context.";
Tao Bai88d56d42017-07-17 16:07:16773 return;
774 }
775
[email protected]7d0ea5362014-05-01 23:39:43776 std::vector<base::string16> data_list_values;
777 std::vector<base::string16> data_list_labels;
Blink Reformat1c4d759e2017-04-09 16:34:54778 const WebInputElement* input_element = ToWebInputElement(&element);
[email protected]e9d29d392014-03-25 01:15:15779 if (input_element) {
780 // Find the datalist values and send them to the browser process.
Christoph Schweringaa41ba842019-10-14 08:00:06781 GetDataListSuggestions(*input_element, &data_list_values,
[email protected]e9d29d392014-03-25 01:15:15782 &data_list_labels);
783 TrimStringVectorForIPC(&data_list_values);
784 TrimStringVectorForIPC(&data_list_labels);
[email protected]e9d29d392014-03-25 01:15:15785 }
[email protected]5c8de6b92012-06-08 21:24:08786
[email protected]b648f242014-02-25 13:49:06787 is_popup_possibly_visible_ = true;
[email protected]7d0ea5362014-05-01 23:39:43788
leon.han35ae41c2016-07-29 03:30:58789 GetAutofillDriver()->SetDataList(data_list_values, data_list_labels);
leon.han90fd63b2016-07-26 01:23:55790 GetAutofillDriver()->QueryFormFieldAutofill(
791 autofill_query_id_, form, field,
danakj3dcceba2019-10-09 22:16:23792 render_frame()->ElementBoundsInWindow(element_),
Fabio Tirelo83662a22018-07-06 15:03:48793 autoselect_first_suggestion);
[email protected]e47aec52010-08-12 00:50:30794}
795
leon.han90fd63b2016-07-26 01:23:55796void AutofillAgent::DoFillFieldWithValue(const base::string16& value,
797 WebInputElement* node) {
Tao Bai81483262018-03-02 05:38:12798 form_tracker_.set_ignore_control_changes(true);
sebsg778c43692018-01-24 20:01:32799 node->SetAutofillValue(blink::WebString::FromUTF16(value));
Vadym Doroshenkoa332ebc2017-09-14 11:46:53800 password_autofill_agent_->UpdateStateForTextChange(*node);
Tao Bai81483262018-03-02 05:38:12801 form_tracker_.set_ignore_control_changes(false);
[email protected]ac9b92f2014-03-15 00:48:32802}
803
leon.han90fd63b2016-07-26 01:23:55804void AutofillAgent::DoPreviewFieldWithValue(const base::string16& value,
805 WebInputElement* node) {
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39806 query_node_autofill_state_ = element_.GetAutofillState();
sebsg778c43692018-01-24 20:01:32807 node->SetSuggestedValue(blink::WebString::FromUTF16(value));
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39808 node->SetAutofillState(WebAutofillState::kPreviewed);
Blink Reformat1c4d759e2017-04-09 16:34:54809 form_util::PreviewSuggestion(node->SuggestedValue().Utf16(),
810 node->Value().Utf16(), node);
[email protected]6f001a6cf2012-02-09 15:21:53811}
812
estadeb1bc9bd2014-12-02 22:44:11813void AutofillAgent::ProcessForms() {
[email protected]5193ea52014-05-14 01:10:02814 // Record timestamp of when the forms are first seen. This is used to
815 // measure the overhead of the Autofill feature.
Christoph Schweringaa41ba842019-10-14 08:00:06816 base::TimeTicks forms_seen_timestamp = AutofillTickClock::NowTicks();
[email protected]5193ea52014-05-14 01:10:02817
estadeb1bc9bd2014-12-02 22:44:11818 WebLocalFrame* frame = render_frame()->GetWebFrame();
estadeff02e6d2014-12-15 21:18:31819 std::vector<FormData> forms = form_cache_.ExtractNewForms();
[email protected]5193ea52014-05-14 01:10:02820
821 // Always communicate to browser process for topmost frame.
Blink Reformat1c4d759e2017-04-09 16:34:54822 if (!forms.empty() || !frame->Parent()) {
leon.han35ae41c2016-07-29 03:30:58823 GetAutofillDriver()->FormsSeen(forms, forms_seen_timestamp);
[email protected]5193ea52014-05-14 01:10:02824 }
[email protected]5193ea52014-05-14 01:10:02825}
826
[email protected]b648f242014-02-25 13:49:06827void AutofillAgent::HidePopup() {
828 if (!is_popup_possibly_visible_)
829 return;
[email protected]b648f242014-02-25 13:49:06830 is_popup_possibly_visible_ = false;
gcastocdd33e0d2015-06-17 22:10:05831 is_generation_popup_possibly_visible_ = false;
leon.han90fd63b2016-07-26 01:23:55832
Friedrich Horschig35355312019-09-09 17:26:34833 // The keyboard accessory has a separate, more complex hiding logic.
834 if (IsKeyboardAccessoryEnabled())
835 return;
836
leon.han90fd63b2016-07-26 01:23:55837 GetAutofillDriver()->HidePopup();
[email protected]81cd52332012-11-05 20:36:07838}
839
Blink Reformat1c4d759e2017-04-09 16:34:54840void AutofillAgent::DidAssociateFormControlsDynamically() {
vasilii31ba8c6c2017-04-28 21:35:08841 // If the control flow is here than the document was at least loaded. The
842 // whole page doesn't have to be loaded.
843 ProcessForms();
844 password_autofill_agent_->OnDynamicFormsSeen();
[email protected]17b6be72013-04-30 21:33:08845}
846
ekaramad27ca69b12017-04-20 18:34:29847void AutofillAgent::DidCompleteFocusChangeInFrame() {
848 WebDocument doc = render_frame()->GetWebFrame()->GetDocument();
849 WebElement focused_element;
850 if (!doc.IsNull())
851 focused_element = doc.FocusedElement();
Ioana Pandele67513a82019-06-11 10:21:00852
853 if (!focused_element.IsNull() && password_autofill_agent_)
854 password_autofill_agent_->FocusedNodeHasChanged(focused_element);
855
ekaramad27ca69b12017-04-20 18:34:29856 // PasswordGenerationAgent needs to know about focus changes, even if there is
857 // no focused element.
858 if (password_generation_agent_ &&
859 password_generation_agent_->FocusedNodeHasChanged(focused_element)) {
860 is_generation_popup_possibly_visible_ = true;
861 is_popup_possibly_visible_ = true;
862 }
ekaramad27ca69b12017-04-20 18:34:29863
Changwan Ryueb8a057e2017-12-08 19:22:33864 if (!IsKeyboardAccessoryEnabled() && focus_requires_scroll_)
Ehsan Karamad3538c8a2017-11-20 16:31:40865 HandleFocusChangeComplete();
ekaramad27ca69b12017-04-20 18:34:29866}
867
868void AutofillAgent::DidReceiveLeftMouseDownOrGestureTapInNode(
869 const WebNode& node) {
Ehsan Karamad3538c8a2017-11-20 16:31:40870 DCHECK(!node.IsNull());
871 focused_node_was_last_clicked_ = node.Focused();
872
Jan Wilken Dörrie6f5eee5a2019-10-11 16:14:36873 if (IsTouchToFillEnabled() || IsKeyboardAccessoryEnabled() ||
874 !focus_requires_scroll_) {
Ehsan Karamad3538c8a2017-11-20 16:31:40875 HandleFocusChangeComplete();
Jan Wilken Dörrie6f5eee5a2019-10-11 16:14:36876 }
Ehsan Karamad3538c8a2017-11-20 16:31:40877}
878
Tao Bai81483262018-03-02 05:38:12879void AutofillAgent::SelectControlDidChange(
880 const WebFormControlElement& element) {
881 form_tracker_.SelectControlDidChange(element);
882}
883
sebsg248c6b02018-04-09 20:20:42884void AutofillAgent::SelectFieldOptionsChanged(
885 const blink::WebFormControlElement& element) {
886 if (!was_last_action_fill_ || element_.IsNull())
887 return;
888
sebsg1c436852018-04-18 16:54:32889 // Since a change of a select options often come in batches, use a timer
890 // to wait for other changes. Stop the timer if it was already running. It
891 // will be started again for this change.
892 if (on_select_update_timer_.IsRunning())
893 on_select_update_timer_.AbandonAndStop();
894
895 // Start the timer to notify the driver that the select field was updated
896 // after the options have finished changing,
897 on_select_update_timer_.Start(
898 FROM_HERE,
899 base::TimeDelta::FromMilliseconds(kWaitTimeForSelectOptionsChangesMs),
900 base::BindRepeating(&AutofillAgent::SelectWasUpdated,
901 weak_ptr_factory_.GetWeakPtr(), element));
902}
903
Jan Wilken Dörrief147dd772019-08-02 05:38:07904bool AutofillAgent::ShouldSuppressKeyboard(
905 const WebFormControlElement& element) {
Jan Wilken Dörrief147dd772019-08-02 05:38:07906 // Note: This is currently only implemented for passwords. Consider supporting
907 // other autofill types in the future as well.
Jan Wilken Dörrie6f5eee5a2019-10-11 16:14:36908 return password_autofill_agent_->ShouldSuppressKeyboard();
Jan Wilken Dörriea1f2d0632019-05-08 09:29:00909}
910
sebsg1c436852018-04-18 16:54:32911void AutofillAgent::SelectWasUpdated(
912 const blink::WebFormControlElement& element) {
913 // Look for the form and field associated with the select element. If they are
914 // found, notify the driver that the the form was modified dynamically.
sebsg248c6b02018-04-09 20:20:42915 FormData form;
916 FormFieldData field;
917 if (form_util::FindFormAndFieldForFormControlElement(element, &form,
918 &field) &&
919 !field.option_values.empty()) {
sebsg1c436852018-04-18 16:54:32920 GetAutofillDriver()->SelectFieldOptionsDidChange(form);
sebsg248c6b02018-04-09 20:20:42921 }
922}
923
Ehsan Karamad3538c8a2017-11-20 16:31:40924void AutofillAgent::FormControlElementClicked(
925 const WebFormControlElement& element,
926 bool was_focused) {
927 last_clicked_form_control_element_for_testing_ = element;
928 last_clicked_form_control_element_was_focused_for_testing_ = was_focused;
sebsg248c6b02018-04-09 20:20:42929 was_last_action_fill_ = false;
Ehsan Karamad3538c8a2017-11-20 16:31:40930
931 const WebInputElement* input_element = ToWebInputElement(&element);
932 if (!input_element && !form_util::IsTextAreaElement(element))
933 return;
934
Jan Wilken Dörrie6f5eee5a2019-10-11 16:14:36935 if (IsTouchToFillEnabled())
936 password_autofill_agent_->TryToShowTouchToFill(element);
937
Ehsan Karamad3538c8a2017-11-20 16:31:40938 ShowSuggestionsOptions options;
939 options.autofill_on_empty_values = true;
Roger McFarlane3a9c4402018-05-18 18:29:35940 // Show full suggestions when clicking on an already-focused form field.
941 options.show_full_suggestion_list = element.IsAutofilled() || was_focused;
Ehsan Karamad3538c8a2017-11-20 16:31:40942
Ehsan Karamad3538c8a2017-11-20 16:31:40943 ShowSuggestions(element, options);
944}
945
946void AutofillAgent::HandleFocusChangeComplete() {
947 WebElement focused_element =
948 render_frame()->GetWebFrame()->GetDocument().FocusedElement();
Tommy Martino542b42352019-07-22 20:39:37949 // When using Talkback on Android, and possibly others, traversing to and
950 // focusing a field will not register as a click. Thus, when screen readers
951 // are used, treat the focused node as if it was the last clicked. Also check
952 // to ensure focus is on a field where text can be entered.
953 if ((focused_node_was_last_clicked_ || is_screen_reader_enabled_) &&
954 !focused_element.IsNull() && focused_element.IsFormControlElement() &&
Ehsan Karamad3538c8a2017-11-20 16:31:40955 (form_util::IsTextInput(blink::ToWebInputElement(&focused_element)) ||
956 focused_element.HasHTMLTagName("textarea"))) {
957 FormControlElementClicked(focused_element.ToConst<WebFormControlElement>(),
958 was_focused_before_now_);
959 }
960
961 was_focused_before_now_ = true;
962 focused_node_was_last_clicked_ = false;
ekaramad27ca69b12017-04-20 18:34:29963}
964
Blink Reformat1c4d759e2017-04-09 16:34:54965void AutofillAgent::AjaxSucceeded() {
Tao Bai6cd41ad2017-12-04 18:48:17966 form_tracker_.AjaxSucceeded();
967}
968
Tao Bai81483262018-03-02 05:38:12969void AutofillAgent::OnProvisionallySaveForm(
970 const WebFormElement& form,
971 const WebFormControlElement& element,
972 ElementChangeSource source) {
Tao Bai6cd41ad2017-12-04 18:48:17973 if (source == ElementChangeSource::WILL_SEND_SUBMIT_EVENT) {
Tao Baia674b1d2018-01-18 22:33:43974 // Fire the form submission event to avoid missing submission when web site
975 // handles the onsubmit event, this also gets the form before Javascript
976 // could change it.
977 // We don't clear submitted_forms_ because OnFormSubmitted will normally be
978 // invoked afterwards and we don't want to fire the same event twice.
979 FireHostSubmitEvents(form, /*known_success=*/false,
980 SubmissionSource::FORM_SUBMISSION);
981 ResetLastInteractedElements();
982 return;
Tao Bai81483262018-03-02 05:38:12983 } else if (source == ElementChangeSource::TEXTFIELD_CHANGED ||
984 source == ElementChangeSource::SELECT_CHANGED) {
Tao Baia674b1d2018-01-18 22:33:43985 // Remember the last form the user interacted with.
Tao Bai6cd41ad2017-12-04 18:48:17986 if (!element.Form().IsNull()) {
Tao Baie4d26212017-12-19 01:30:11987 UpdateLastInteractedForm(element.Form());
Tao Bai6cd41ad2017-12-04 18:48:17988 } else {
989 // Remove invisible elements
990 for (auto it = formless_elements_user_edited_.begin();
991 it != formless_elements_user_edited_.end();) {
992 if (form_util::IsWebElementVisible(*it)) {
993 it = formless_elements_user_edited_.erase(it);
994 } else {
995 ++it;
996 }
997 }
998 formless_elements_user_edited_.insert(element);
Tao Baie4d26212017-12-19 01:30:11999 provisionally_saved_form_ = std::make_unique<FormData>();
1000 if (!CollectFormlessElements(provisionally_saved_form_.get())) {
1001 provisionally_saved_form_.reset();
Tao Bai6cd41ad2017-12-04 18:48:171002 } else {
1003 last_interacted_form_.Reset();
1004 }
1005 }
Tao Bai81483262018-03-02 05:38:121006
1007 if (source == ElementChangeSource::TEXTFIELD_CHANGED)
1008 OnTextFieldDidChange(*ToWebInputElement(&element));
1009 else {
1010 FormData form;
1011 FormFieldData field;
Tao Baiec24a4c22018-03-14 17:16:081012 if (form_util::FindFormAndFieldForFormControlElement(element, &form,
1013 &field)) {
1014 GetAutofillDriver()->SelectControlDidChange(
danakj3dcceba2019-10-09 22:16:231015 form, field, render_frame()->ElementBoundsInWindow(element));
Tao Bai81483262018-03-02 05:38:121016 }
1017 }
Tao Bai6cd41ad2017-12-04 18:48:171018 }
1019}
1020
1021void AutofillAgent::OnProbablyFormSubmitted() {
Tao Baia674b1d2018-01-18 22:33:431022 FormData form_data;
1023 if (GetSubmittedForm(&form_data)) {
1024 FireHostSubmitEvents(form_data, /*known_success=*/false,
1025 SubmissionSource::PROBABLY_FORM_SUBMITTED);
1026 }
Tao Bai6cd41ad2017-12-04 18:48:171027 ResetLastInteractedElements();
Tao Baia674b1d2018-01-18 22:33:431028 OnFormNoLongerSubmittable();
Tao Bai6cd41ad2017-12-04 18:48:171029}
1030
1031void AutofillAgent::OnFormSubmitted(const WebFormElement& form) {
Tao Baia674b1d2018-01-18 22:33:431032 // Fire the submission event here because WILL_SEND_SUBMIT_EVENT is skipped
1033 // if javascript calls submit() directly.
1034 FireHostSubmitEvents(form, /*known_success=*/false,
1035 SubmissionSource::FORM_SUBMISSION);
Tao Bai6cd41ad2017-12-04 18:48:171036 ResetLastInteractedElements();
Tao Baia674b1d2018-01-18 22:33:431037 OnFormNoLongerSubmittable();
Tao Bai6cd41ad2017-12-04 18:48:171038}
1039
1040void AutofillAgent::OnInferredFormSubmission(SubmissionSource source) {
1041 // Only handle iframe for FRAME_DETACHED or main frame for
1042 // SAME_DOCUMENT_NAVIGATION.
1043 if ((source == SubmissionSource::FRAME_DETACHED &&
1044 !render_frame()->GetWebFrame()->Parent()) ||
1045 (source == SubmissionSource::SAME_DOCUMENT_NAVIGATION &&
1046 render_frame()->GetWebFrame()->Parent())) {
Tao Baia674b1d2018-01-18 22:33:431047 ResetLastInteractedElements();
1048 OnFormNoLongerSubmittable();
Tao Bai6cd41ad2017-12-04 18:48:171049 return;
1050 }
1051
Tao Bai2c1b3d062017-12-07 17:20:281052 if (source == SubmissionSource::FRAME_DETACHED) {
1053 // Should not access the frame because it is now detached. Instead, use
Tao Baie4d26212017-12-19 01:30:111054 // |provisionally_saved_form_|.
1055 if (provisionally_saved_form_)
Tao Baia674b1d2018-01-18 22:33:431056 FireHostSubmitEvents(*provisionally_saved_form_, /*known_success=*/true,
1057 source);
Tao Bai2c1b3d062017-12-07 17:20:281058 } else {
1059 FormData form_data;
Tao Baie4d26212017-12-19 01:30:111060 if (GetSubmittedForm(&form_data))
Tao Baia674b1d2018-01-18 22:33:431061 FireHostSubmitEvents(form_data, /*known_success=*/true, source);
Tao Bai6cd41ad2017-12-04 18:48:171062 }
1063 ResetLastInteractedElements();
Tao Baia674b1d2018-01-18 22:33:431064 OnFormNoLongerSubmittable();
Tao Bai6cd41ad2017-12-04 18:48:171065}
1066
1067void AutofillAgent::AddFormObserver(Observer* observer) {
1068 form_tracker_.AddObserver(observer);
1069}
1070
1071void AutofillAgent::RemoveFormObserver(Observer* observer) {
1072 form_tracker_.RemoveObserver(observer);
1073}
1074
1075bool AutofillAgent::GetSubmittedForm(FormData* form) {
1076 if (!last_interacted_form_.IsNull()) {
Tao Baie4d26212017-12-19 01:30:111077 if (form_util::ExtractFormData(last_interacted_form_, form)) {
1078 return true;
1079 } else if (provisionally_saved_form_) {
1080 *form = *provisionally_saved_form_;
1081 return true;
1082 }
Tao Bai6cd41ad2017-12-04 18:48:171083 } else if (formless_elements_user_edited_.size() != 0 &&
1084 !form_util::IsSomeControlElementVisible(
1085 formless_elements_user_edited_)) {
1086 // we check if all the elements the user has interacted with are gone,
Tao Baie4d26212017-12-19 01:30:111087 // to decide if submission has occurred, and use the
1088 // provisionally_saved_form_ saved in OnProvisionallySaveForm() if fail to
1089 // construct form.
Tao Bai6cd41ad2017-12-04 18:48:171090 if (CollectFormlessElements(form)) {
1091 return true;
Tao Baie4d26212017-12-19 01:30:111092 } else if (provisionally_saved_form_) {
1093 *form = *provisionally_saved_form_;
Tao Bai6cd41ad2017-12-04 18:48:171094 return true;
1095 }
1096 }
1097 return false;
1098}
1099
1100void AutofillAgent::ResetLastInteractedElements() {
1101 last_interacted_form_.Reset();
Alexander Timokhin3c45d1a2018-03-28 17:49:281102 last_clicked_form_control_element_for_testing_.Reset();
Tao Bai6cd41ad2017-12-04 18:48:171103 formless_elements_user_edited_.clear();
Tao Baie4d26212017-12-19 01:30:111104 provisionally_saved_form_.reset();
1105}
1106
1107void AutofillAgent::UpdateLastInteractedForm(blink::WebFormElement form) {
1108 last_interacted_form_ = form;
1109 provisionally_saved_form_ = std::make_unique<FormData>();
1110 if (!form_util::ExtractFormData(last_interacted_form_,
1111 provisionally_saved_form_.get())) {
1112 provisionally_saved_form_.reset();
1113 }
gcastoc21f1c4c2015-03-19 21:57:031114}
1115
Tao Baia674b1d2018-01-18 22:33:431116void AutofillAgent::OnFormNoLongerSubmittable() {
1117 submitted_forms_.clear();
1118}
1119
Parastoo Geranmayeh1421e632018-07-25 15:57:031120bool AutofillAgent::FindTheUniqueNewVersionOfOldElement(
Parastoo Geranmayehc5d65c12018-11-21 05:32:021121 const WebVector<WebFormControlElement>& elements,
1122 bool& potential_match_encountered,
1123 WebFormControlElement& matching_element,
Parastoo Geranmayeh1421e632018-07-25 15:57:031124 const WebFormControlElement& original_element) {
Parastoo Geranmayehc5d65c12018-11-21 05:32:021125 if (original_element.IsNull())
1126 return false;
1127
1128 const auto original_element_section = original_element.AutofillSection();
Parastoo Geranmayeh1421e632018-07-25 15:57:031129 for (const WebFormControlElement& current_element : elements) {
1130 if (current_element.IsFocusable() &&
1131 original_element.NameForAutofill() ==
1132 current_element.NameForAutofill()) {
Parastoo Geranmayehc5d65c12018-11-21 05:32:021133 // If this is the first matching element, or is the first with the right
1134 // section, this is the best match so far.
1135 // In other words: bad, then good. => pick good.
1136 if (!potential_match_encountered ||
1137 (current_element.AutofillSection() == original_element_section &&
1138 (matching_element.IsNull() ||
1139 matching_element.AutofillSection() != original_element_section))) {
1140 matching_element = current_element;
1141 potential_match_encountered = true;
1142 } else if (current_element.AutofillSection() !=
1143 original_element_section &&
Parastoo Geranmayehd5f2cc262018-11-24 00:00:141144 !matching_element.IsNull() &&
Parastoo Geranmayehc5d65c12018-11-21 05:32:021145 matching_element.AutofillSection() !=
1146 original_element_section) {
1147 // The so far matching fields are equally bad. Continue the search if
1148 // none of them have the correct section.
1149 // In other words: bad, then bad => pick none.
1150 matching_element.Reset();
Parastoo Geranmayeh1421e632018-07-25 15:57:031151 } else if (current_element.AutofillSection() ==
Parastoo Geranmayehc5d65c12018-11-21 05:32:021152 original_element_section &&
Parastoo Geranmayehd5f2cc262018-11-24 00:00:141153 !matching_element.IsNull() &&
Parastoo Geranmayehc5d65c12018-11-21 05:32:021154 matching_element.AutofillSection() ==
1155 original_element_section) {
1156 // If two or more fields have the matching name and section, we can't
1157 // decide. Two equally good fields => fail.
1158 matching_element.Reset();
Parastoo Geranmayeh1421e632018-07-25 15:57:031159 return false;
Parastoo Geranmayehc5d65c12018-11-21 05:32:021160 } // For the good, then bad case => keep good. Continue the search.
Parastoo Geranmayeh1421e632018-07-25 15:57:031161 }
1162 }
1163 return true;
1164}
1165
sebsge39d1172018-11-07 23:56:461166// TODO(crbug.com/896689): Update this method to use the unique ids once they
1167// are implemented.
sebsge35b762c2018-03-29 20:33:271168void AutofillAgent::ReplaceElementIfNowInvalid(const FormData& original_form) {
1169 // If the document is invalid, bail out.
1170 if (element_.GetDocument().IsNull())
1171 return;
1172
Parastoo Geranmayeh1421e632018-07-25 15:57:031173 WebVector<WebFormElement> forms;
1174 WebVector<WebFormControlElement> elements;
1175
Parastoo Geranmayehc5d65c12018-11-21 05:32:021176 const auto original_element = element_;
1177 WebFormControlElement matching_element;
1178 bool potential_match_encountered = false;
1179
Parastoo Geranmayeh1421e632018-07-25 15:57:031180 if (original_form.name.empty()) {
1181 // If the form has no name, check all the forms.
Parastoo Geranmayeh1421e632018-07-25 15:57:031182 element_.GetDocument().Forms(forms);
1183 for (const WebFormElement& form : forms) {
1184 form.GetFormControlElements(elements);
Parastoo Geranmayehc5d65c12018-11-21 05:32:021185 // If finding a unique element is impossible, don't look further.
Parastoo Geranmayeh1421e632018-07-25 15:57:031186 if (!FindTheUniqueNewVersionOfOldElement(
Parastoo Geranmayehc5d65c12018-11-21 05:32:021187 elements, potential_match_encountered, matching_element,
1188 original_element))
Parastoo Geranmayeh1421e632018-07-25 15:57:031189 return;
1190 }
1191 // If the element is not found, we should still check for unowned elements.
Parastoo Geranmayehc5d65c12018-11-21 05:32:021192 if (!matching_element.IsNull()) {
1193 element_ = matching_element;
Parastoo Geranmayeh1421e632018-07-25 15:57:031194 return;
Parastoo Geranmayehc5d65c12018-11-21 05:32:021195 }
Parastoo Geranmayeh1421e632018-07-25 15:57:031196 }
1197
sebsge35b762c2018-03-29 20:33:271198 if (!element_.Form().IsNull()) {
1199 // If |element_|'s parent form has no elements, |element_| is now invalid
1200 // and should be updated.
1201 WebVector<WebFormControlElement> form_elements;
1202 element_.Form().GetFormControlElements(form_elements);
1203 if (!form_elements.empty())
1204 return;
1205 }
1206
sebsge35b762c2018-03-29 20:33:271207 WebFormElement form_element;
Parastoo Geranmayehc5d65c12018-11-21 05:32:021208 bool form_is_found = false;
Parastoo Geranmayeh1421e632018-07-25 15:57:031209 if (!original_form.name.empty()) {
1210 // Try to find the new version of the form.
1211 element_.GetDocument().Forms(forms);
1212 for (const WebFormElement& form : forms) {
1213 if (original_form.name == form.GetName().Utf16() ||
1214 original_form.name == form.GetAttribute("id").Utf16()) {
Parastoo Geranmayehc5d65c12018-11-21 05:32:021215 if (!form_is_found)
1216 form_element = form;
1217 else // multiple forms with the matching name.
1218 return;
Parastoo Geranmayeh1421e632018-07-25 15:57:031219 }
sebsge35b762c2018-03-29 20:33:271220 }
1221 }
1222
sebsgf32e98d72018-05-11 14:43:011223 if (form_element.IsNull()) {
1224 // Could not find the new version of the form, get all the unowned elements.
1225 std::vector<WebElement> fieldsets;
1226 elements = form_util::GetUnownedAutofillableFormFieldElements(
1227 element_.GetDocument().All(), &fieldsets);
Parastoo Geranmayehc5d65c12018-11-21 05:32:021228 // If a unique match was found.
1229 if (FindTheUniqueNewVersionOfOldElement(
1230 elements, potential_match_encountered, matching_element,
1231 original_element) &&
1232 !matching_element.IsNull()) {
1233 element_ = matching_element;
1234 }
Parastoo Geranmayeh1421e632018-07-25 15:57:031235 return;
sebsgf32e98d72018-05-11 14:43:011236 }
Parastoo Geranmayeh1421e632018-07-25 15:57:031237 // This is the case for owned fields that belong to the right named form.
1238 // Get all the elements of the new version of the form.
1239 form_element.GetFormControlElements(elements);
Parastoo Geranmayehc5d65c12018-11-21 05:32:021240 // If a unique match was found.
1241 if (FindTheUniqueNewVersionOfOldElement(elements, potential_match_encountered,
1242 matching_element, original_element) &&
1243 !matching_element.IsNull()) {
1244 element_ = matching_element;
sebsge35b762c2018-03-29 20:33:271245 }
1246}
1247
Shimi Zhang6b72d292019-07-12 20:52:421248const mojo::AssociatedRemote<mojom::AutofillDriver>&
1249AutofillAgent::GetAutofillDriver() {
leon.han97e8f752016-09-06 06:13:201250 if (!autofill_driver_) {
Ken Rockot0aad7ec2018-07-31 15:58:441251 render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
Shimi Zhang6b72d292019-07-12 20:52:421252 &autofill_driver_);
leon.han90fd63b2016-07-26 01:23:551253 }
leon.hande852902016-05-04 09:16:381254
leon.han97e8f752016-09-06 06:13:201255 return autofill_driver_;
1256}
1257
Shimi Zhang6b72d292019-07-12 20:52:421258const mojo::AssociatedRemote<mojom::PasswordManagerDriver>&
leon.han97e8f752016-09-06 06:13:201259AutofillAgent::GetPasswordManagerDriver() {
1260 DCHECK(password_autofill_agent_);
1261 return password_autofill_agent_->GetPasswordManagerDriver();
leon.hande852902016-05-04 09:16:381262}
1263
[email protected]78192082011-01-29 05:43:441264} // namespace autofill