blob: c7338c6a205d695d65da562c835c96402896e62f [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"
rouslanc31f81d2015-08-24 17:33:5234#include "components/autofill/core/common/autofill_util.h"
[email protected]d04f81912013-06-18 14:52:1335#include "components/autofill/core/common/form_data.h"
36#include "components/autofill/core/common/form_data_predictions.h"
37#include "components/autofill/core/common/form_field_data.h"
[email protected]e620d362013-09-09 08:01:5338#include "components/autofill/core/common/password_form.h"
jwwfb2a1432016-06-13 22:44:1539#include "components/autofill/core/common/password_form_fill_data.h"
40#include "components/autofill/core/common/save_password_progress_logger.h"
[email protected]fed9d4f2013-12-17 21:32:4741#include "content/public/common/content_switches.h"
Tao Bai88d56d42017-07-17 16:07:1642#include "content/public/common/origin_util.h"
[email protected]ca5190f2013-07-08 11:10:3143#include "content/public/common/url_constants.h"
estadeb1bc9bd2014-12-02 22:44:1144#include "content/public/renderer/render_frame.h"
[email protected]a2ef54c2011-10-10 16:20:3145#include "content/public/renderer/render_view.h"
[email protected]ca5190f2013-07-08 11:10:3146#include "net/cert/cert_status_flags.h"
rockot734fb662016-10-15 16:41:3047#include "services/service_manager/public/cpp/interface_provider.h"
Ken Rockot0aad7ec2018-07-31 15:58:4448#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
Blink Reformata30d4232018-04-07 15:31:0649#include "third_party/blink/public/platform/web_keyboard_event.h"
50#include "third_party/blink/public/platform/web_url_request.h"
51#include "third_party/blink/public/web/web_console_message.h"
52#include "third_party/blink/public/web/web_document.h"
53#include "third_party/blink/public/web/web_element_collection.h"
54#include "third_party/blink/public/web/web_form_control_element.h"
55#include "third_party/blink/public/web/web_form_element.h"
56#include "third_party/blink/public/web/web_local_frame.h"
57#include "third_party/blink/public/web/web_node.h"
58#include "third_party/blink/public/web/web_option_element.h"
59#include "third_party/blink/public/web/web_user_gesture_indicator.h"
60#include "third_party/blink/public/web/web_view.h"
[email protected]c051a1b2011-01-21 23:30:1761#include "ui/base/l10n/l10n_util.h"
[email protected]7e9acd082013-09-17 23:31:1662#include "ui/events/keycodes/keyboard_codes.h"
[email protected]679f128f2010-07-22 22:57:4463
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:3964using blink::WebAutofillState;
[email protected]a1221aea2013-11-07 01:31:3065using blink::WebAutofillClient;
[email protected]dbdd60272014-04-14 22:48:4066using blink::WebConsoleMessage;
rouslanf7ebd8832015-01-22 01:54:1467using blink::WebDocument;
[email protected]5e7e8612014-03-20 14:43:1968using blink::WebElement;
69using blink::WebElementCollection;
[email protected]a1221aea2013-11-07 01:31:3070using blink::WebFormControlElement;
71using blink::WebFormElement;
72using blink::WebFrame;
73using blink::WebInputElement;
74using blink::WebKeyboardEvent;
[email protected]c5041c322014-04-08 05:06:4775using blink::WebLocalFrame;
[email protected]a1221aea2013-11-07 01:31:3076using blink::WebNode;
[email protected]a1221aea2013-11-07 01:31:3077using blink::WebOptionElement;
78using blink::WebString;
rouslan6a3f8d92015-04-28 01:00:0179using blink::WebUserGestureIndicator;
[email protected]5e7e8612014-03-20 14:43:1980using blink::WebVector;
[email protected]679f128f2010-07-22 22:57:4481
[email protected]d86263dcd2014-01-09 10:35:2182namespace autofill {
83
[email protected]e47aec52010-08-12 00:50:3084namespace {
85
sebsg1c436852018-04-18 16:54:3286// Time to wait, in ms, o ensure that only a single select change will be acted
87// upon, instead of multiple in close succession (debounce time).
sebsg248c6b02018-04-09 20:20:4288size_t kWaitTimeForSelectOptionsChangesMs = 50;
89
mathp4f6b0382016-04-12 20:41:1290// Whether the "single click" autofill feature is enabled, through command-line
91// or field trial.
92bool IsSingleClickEnabled() {
Roger McFarlane3a9c4402018-05-18 18:29:3593 return base::FeatureList::IsEnabled(features::kSingleClickAutofill);
mathp4f6b0382016-04-12 20:41:1294}
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),
Tao Bai6cd41ad2017-12-04 18:48:17148 form_tracker_(render_frame),
leon.han90fd63b2016-07-26 01:23:55149 binding_(this),
[email protected]2c305252013-04-26 19:57:05150 weak_ptr_factory_(this) {
Blink Reformat1c4d759e2017-04-09 16:34:54151 render_frame->GetWebFrame()->SetAutofillClient(this);
leon.han90fd63b2016-07-26 01:23:55152 password_autofill_agent->SetAutofillAgent(this);
Tao Bai6cd41ad2017-12-04 18:48:17153 AddFormObserver(this);
Ben Goodger205467b2017-08-02 19:33:55154 registry->AddInterface(
leon.hande852902016-05-04 09:16:38155 base::Bind(&AutofillAgent::BindRequest, base::Unretained(this)));
[email protected]679f128f2010-07-22 22:57:44156}
157
Tao Bai6cd41ad2017-12-04 18:48:17158AutofillAgent::~AutofillAgent() {
159 RemoveFormObserver(this);
160}
[email protected]d2f05d02011-01-27 18:51:01161
Ken Rockot0aad7ec2018-07-31 15:58:44162void AutofillAgent::BindRequest(mojom::AutofillAgentAssociatedRequest request) {
leon.han90fd63b2016-07-26 01:23:55163 binding_.Bind(std::move(request));
leon.hande852902016-05-04 09:16:38164}
165
mathp692aba82015-03-06 20:55:02166bool AutofillAgent::FormDataCompare::operator()(const FormData& lhs,
167 const FormData& rhs) const {
brettw9c68c512015-11-20 23:26:38168 return std::tie(lhs.name, lhs.origin, lhs.action, lhs.is_form_tag) <
169 std::tie(rhs.name, rhs.origin, rhs.action, rhs.is_form_tag);
mathp692aba82015-03-06 20:55:02170}
171
Dmitry Gozman9cfe75d2018-09-18 21:36:08172void AutofillAgent::DidCommitProvisionalLoad(bool is_same_document_navigation,
173 ui::PageTransition transition) {
mathpffc78e22015-09-01 14:10:50174 blink::WebFrame* frame = render_frame()->GetWebFrame();
175 // TODO(dvadym): check if we need to check if it is main frame navigation
176 // http://crbug.com/443155
Blink Reformat1c4d759e2017-04-09 16:34:54177 if (frame->Parent())
mathpffc78e22015-09-01 14:10:50178 return; // Not a top-level navigation.
179
Tao Bai6cd41ad2017-12-04 18:48:17180 if (is_same_document_navigation)
181 return;
Hajime Hoshi53820e222017-08-17 02:28:11182
Tao Bai6cd41ad2017-12-04 18:48:17183 // Navigation to a new page or a page refresh.
Nektarios Paisios6b79cf6f2018-02-26 16:49:36184
Hajime Hoshi83c3f502018-03-14 05:49:01185 element_.Reset();
Nektarios Paisios6b79cf6f2018-02-26 16:49:36186
Tao Bai6cd41ad2017-12-04 18:48:17187 form_cache_.Reset();
188 ResetLastInteractedElements();
Tao Baia674b1d2018-01-18 22:33:43189 OnFormNoLongerSubmittable();
[email protected]676126f72011-01-15 00:03:51190}
191
estadeb1bc9bd2014-12-02 22:44:11192void AutofillAgent::DidFinishDocumentLoad() {
193 ProcessForms();
[email protected]3609c962014-07-11 03:18:25194}
195
estade2792527072014-12-17 00:41:47196void AutofillAgent::DidChangeScrollOffset() {
Changwan Ryuf85180e52018-08-10 04:31:46197 if (element_.IsNull())
198 return;
199
Changwan Ryu9db32db42018-01-24 14:54:44200 if (!focus_requires_scroll_) {
201 // Post a task here since scroll offset may change during layout.
202 // (https://crbug.com/804886)
203 weak_ptr_factory_.InvalidateWeakPtrs();
Hajime Hoshi9f80e742018-04-13 03:35:04204 render_frame()
205 ->GetTaskRunner(blink::TaskType::kInternalUserInteraction)
206 ->PostTask(FROM_HERE,
207 base::BindOnce(&AutofillAgent::DidChangeScrollOffsetImpl,
Changwan Ryu9db32db42018-01-24 14:54:44208 weak_ptr_factory_.GetWeakPtr(), element_));
209 } else if (!IsKeyboardAccessoryEnabled()) {
210 HidePopup();
Changwan Ryueb8a057e2017-12-08 19:22:33211 }
Changwan Ryu9db32db42018-01-24 14:54:44212}
Changwan Ryueb8a057e2017-12-08 19:22:33213
Changwan Ryu9db32db42018-01-24 14:54:44214void AutofillAgent::DidChangeScrollOffsetImpl(
215 const WebFormControlElement& element) {
Changwan Ryuf85180e52018-08-10 04:31:46216 if (element != element_ || element_.IsNull() || focus_requires_scroll_ ||
Changwan Ryu9db32db42018-01-24 14:54:44217 !is_popup_possibly_visible_ || !element_.Focused())
estadeb5efbab62015-04-28 18:07:42218 return;
rouslanc31f81d2015-08-24 17:33:52219
Changwan Ryu9db32db42018-01-24 14:54:44220 FormData form;
221 FormFieldData field;
222 if (form_util::FindFormAndFieldForFormControlElement(element_, &form,
223 &field)) {
224 GetAutofillDriver()->TextFieldDidScroll(
225 form, field,
226 render_frame()->GetRenderView()->ElementBoundsInWindow(element_));
227 }
228
229 // Ignore subsequent scroll offset changes.
230 if (!IsKeyboardAccessoryEnabled())
231 HidePopup();
estadeb1bc9bd2014-12-02 22:44:11232}
233
[email protected]5e7e8612014-03-20 14:43:19234void AutofillAgent::FocusedNodeChanged(const WebNode& node) {
Ehsan Karamad3538c8a2017-11-20 16:31:40235 was_focused_before_now_ = false;
236
Changwan Ryueb8a057e2017-12-08 19:22:33237 if ((IsKeyboardAccessoryEnabled() || !focus_requires_scroll_) &&
Ehsan Karamad3538c8a2017-11-20 16:31:40238 WebUserGestureIndicator::IsProcessingUserGesture(
239 node.IsNull() ? nullptr : node.GetDocument().GetFrame())) {
240 focused_node_was_last_clicked_ = true;
241 HandleFocusChangeComplete();
242 }
ekaramad27ca69b12017-04-20 18:34:29243
[email protected]91dcc6d32014-07-30 00:01:33244 HidePopup();
245
Blink Reformat1c4d759e2017-04-09 16:34:54246 if (node.IsNull() || !node.IsElementNode()) {
247 if (!last_interacted_form_.IsNull()) {
mathp8ac68ce2015-12-08 21:49:06248 // Focus moved away from the last interacted form to somewhere else on
249 // the page.
leon.han90fd63b2016-07-26 01:23:55250 GetAutofillDriver()->FocusNoLongerOnForm();
mathp8ac68ce2015-12-08 21:49:06251 }
estadeb1bc9bd2014-12-02 22:44:11252 return;
mathp8ac68ce2015-12-08 21:49:06253 }
estadeb1bc9bd2014-12-02 22:44:11254
Blink Reformat1c4d759e2017-04-09 16:34:54255 WebElement web_element = node.ToConst<WebElement>();
256 const WebInputElement* element = ToWebInputElement(&web_element);
mathpb4cf7b82015-12-11 16:42:24257
Blink Reformat1c4d759e2017-04-09 16:34:54258 if (!last_interacted_form_.IsNull() &&
259 (!element || last_interacted_form_ != element->Form())) {
mathp8ac68ce2015-12-08 21:49:06260 // The focused element is not part of the last interacted form (could be
261 // in a different form).
leon.han90fd63b2016-07-26 01:23:55262 GetAutofillDriver()->FocusNoLongerOnForm();
mathp8ac68ce2015-12-08 21:49:06263 return;
264 }
[email protected]f920d6e2013-03-12 20:20:50265
Blink Reformat1c4d759e2017-04-09 16:34:54266 if (!element || !element->IsEnabled() || element->IsReadOnly() ||
267 !element->IsTextField())
[email protected]f920d6e2013-03-12 20:20:50268 return;
269
[email protected]e5057a22013-04-22 12:41:39270 element_ = *element;
Tao Bai168e4fc2017-06-19 18:46:38271
272 FormData form;
273 FormFieldData field;
274 if (form_util::FindFormAndFieldForFormControlElement(element_, &form,
275 &field)) {
276 GetAutofillDriver()->FocusOnFormField(
277 form, field,
278 render_frame()->GetRenderView()->ElementBoundsInWindow(element_));
279 }
[email protected]e5057a22013-04-22 12:41:39280}
281
vabrd62bc3e2016-05-04 15:58:52282void AutofillAgent::OnDestruct() {
283 Shutdown();
284 base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
285}
286
tmartino1c5348c92016-05-26 18:50:56287void AutofillAgent::FireHostSubmitEvents(const WebFormElement& form,
Tao Baia674b1d2018-01-18 22:33:43288 bool known_success,
289 SubmissionSource source) {
tmartino1c5348c92016-05-26 18:50:56290 FormData form_data;
291 if (!form_util::ExtractFormData(form, &form_data))
292 return;
293
Tao Baia674b1d2018-01-18 22:33:43294 FireHostSubmitEvents(form_data, known_success, source);
tmartino1c5348c92016-05-26 18:50:56295}
296
297void AutofillAgent::FireHostSubmitEvents(const FormData& form_data,
Tao Baia674b1d2018-01-18 22:33:43298 bool known_success,
299 SubmissionSource source) {
300 // We don't want to fire duplicate submission event.
301 if (!submitted_forms_.insert(form_data).second)
302 return;
303
304 GetAutofillDriver()->FormSubmitted(form_data, known_success, source,
305 base::TimeTicks::Now());
tmartino1c5348c92016-05-26 18:50:56306}
307
vabrd62bc3e2016-05-04 15:58:52308void AutofillAgent::Shutdown() {
leon.han7e8c85b2016-09-08 14:24:42309 binding_.Close();
vabrd62bc3e2016-05-04 15:58:52310 weak_ptr_factory_.InvalidateWeakPtrs();
311}
312
Blink Reformat1c4d759e2017-04-09 16:34:54313void AutofillAgent::TextFieldDidEndEditing(const WebInputElement& element) {
leon.han90fd63b2016-07-26 01:23:55314 GetAutofillDriver()->DidEndTextFieldEditing();
Ioana Pandele9e742fe2018-10-11 19:07:54315 password_autofill_agent_->DidEndTextFieldEditing();
Ioana Pandele0c36cd0e42018-11-05 17:51:31316 if (password_generation_agent_)
317 password_generation_agent_->DidEndTextFieldEditing(element);
[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;
mathp9172c62a2015-10-08 18:51:14347 if (form_util::FindFormAndFieldForFormControlElement(element, &form,
348 &field)) {
Tao Bai168e4fc2017-06-19 18:46:38349 GetAutofillDriver()->TextFieldDidChange(
350 form, field,
351 render_frame()->GetRenderView()->ElementBoundsInWindow(element),
352 base::TimeTicks::Now());
[email protected]1d14f582011-09-02 20:42:04353 }
[email protected]676126f72011-01-15 00:03:51354}
355
Blink Reformat1c4d759e2017-04-09 16:34:54356void AutofillAgent::TextFieldDidReceiveKeyDown(const WebInputElement& element,
[email protected]2fa18c22011-06-14 23:40:43357 const WebKeyboardEvent& event) {
Blink Reformat1c4d759e2017-04-09 16:34:54358 if (event.windows_key_code == ui::VKEY_DOWN ||
359 event.windows_key_code == ui::VKEY_UP) {
brettwb505b7a2014-11-26 22:05:32360 ShowSuggestionsOptions options;
361 options.autofill_on_empty_values = true;
362 options.requires_caret_at_end = true;
Fabio Tirelo83662a22018-07-06 15:03:48363 options.autoselect_first_suggestion =
364 ShouldAutoselectFirstSuggestionOnArrowDown();
brettwb505b7a2014-11-26 22:05:32365 ShowSuggestions(element, options);
366 }
[email protected]efeb565f2013-12-12 17:16:41367}
368
Blink Reformat1c4d759e2017-04-09 16:34:54369void AutofillAgent::OpenTextDataListChooser(const WebInputElement& element) {
brettwb505b7a2014-11-26 22:05:32370 ShowSuggestionsOptions options;
371 options.autofill_on_empty_values = true;
brettwb505b7a2014-11-26 22:05:32372 ShowSuggestions(element, options);
[email protected]676126f72011-01-15 00:03:51373}
374
Blink Reformat1c4d759e2017-04-09 16:34:54375void AutofillAgent::DataListOptionsChanged(const WebInputElement& element) {
376 if (!is_popup_possibly_visible_ || !element.Focused())
estadedf5088a2014-12-15 02:04:07377 return;
378
Tao Bai6cd41ad2017-12-04 18:48:17379 OnProvisionallySaveForm(WebFormElement(), element,
380 ElementChangeSource::TEXTFIELD_CHANGED);
estadedf5088a2014-12-15 02:04:07381}
382
vasiliifd0e8ca2017-04-12 11:11:22383void AutofillAgent::UserGestureObserved() {
384 password_autofill_agent_->UserGestureObserved();
[email protected]fc22ae52014-04-23 13:48:04385}
386
leon.han90fd63b2016-07-26 01:23:55387void AutofillAgent::DoAcceptDataListSuggestion(
[email protected]d5ca8fb2013-04-11 17:54:31388 const base::string16& suggested_value) {
Hajime Hoshie6104dc92018-03-20 05:58:02389 if (element_.IsNull())
390 return;
391
Blink Reformat1c4d759e2017-04-09 16:34:54392 WebInputElement* input_element = ToWebInputElement(&element_);
[email protected]e9d29d392014-03-25 01:15:15393 DCHECK(input_element);
[email protected]d5ca8fb2013-04-11 17:54:31394 base::string16 new_value = suggested_value;
[email protected]71a90b32012-05-18 09:16:53395 // If this element takes multiple values then replace the last part with
396 // the suggestion.
Blink Reformat1c4d759e2017-04-09 16:34:54397 if (input_element->IsMultiple() && input_element->IsEmailField()) {
Matt Giuca93bc1582017-08-01 05:09:57398 base::string16 value = input_element->EditingValue().Utf16();
399 std::vector<base::StringPiece16> parts =
400 base::SplitStringPiece(value, base::ASCIIToUTF16(","),
401 base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
[email protected]71a90b32012-05-18 09:16:53402 if (parts.size() == 0)
mgiuca30f75882017-03-28 02:07:19403 parts.push_back(base::StringPiece16());
[email protected]71a90b32012-05-18 09:16:53404
mgiuca30f75882017-03-28 02:07:19405 base::string16 last_part = parts.back().as_string();
[email protected]71a90b32012-05-18 09:16:53406 // We want to keep just the leading whitespace.
407 for (size_t i = 0; i < last_part.size(); ++i) {
brettwb3413062015-06-24 00:39:02408 if (!base::IsUnicodeWhitespace(last_part[i])) {
[email protected]71a90b32012-05-18 09:16:53409 last_part = last_part.substr(0, i);
410 break;
411 }
412 }
413 last_part.append(suggested_value);
thestigee1440b2016-07-08 01:06:55414 parts.back() = last_part;
[email protected]71a90b32012-05-18 09:16:53415
brettwd94a22142015-07-15 05:19:26416 new_value = base::JoinString(parts, base::ASCIIToUTF16(","));
[email protected]71a90b32012-05-18 09:16:53417 }
leon.han90fd63b2016-07-26 01:23:55418 DoFillFieldWithValue(new_value, input_element);
[email protected]63560b32014-03-04 07:06:26419}
420
Parastoo Geranmayeh522c2222018-07-16 15:14:03421void AutofillAgent::TriggerRefillIfNeeded(const FormData& form) {
422 if (!base::FeatureList::IsEnabled(features::kAutofillDynamicForms))
423 return;
Parastoo Geranmayeh1421e632018-07-25 15:57:03424
425 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))) {
Parastoo Geranmayeh522c2222018-07-16 15:14:03432 base::TimeTicks forms_seen_timestamp = base::TimeTicks::Now();
433 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
sebsge35b762c2018-03-29 20:33:27453 if (base::FeatureList::IsEnabled(features::kAutofillDynamicForms))
454 ReplaceElementIfNowInvalid(form);
455
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39456 query_node_autofill_state_ = element_.GetAutofillState();
leon.han90fd63b2016-07-26 01:23:55457 form_util::FillForm(form, element_);
Blink Reformat1c4d759e2017-04-09 16:34:54458 if (!element_.Form().IsNull())
Tao Baie4d26212017-12-19 01:30:11459 UpdateLastInteractedForm(element_.Form());
leon.han90fd63b2016-07-26 01:23:55460
461 GetAutofillDriver()->DidFillAutofillFormData(form, base::TimeTicks::Now());
Parastoo Geranmayeh522c2222018-07-16 15:14:03462
463 TriggerRefillIfNeeded(form);
[email protected]8527a78f2014-06-12 12:49:15464}
465
leon.han90fd63b2016-07-26 01:23:55466void AutofillAgent::PreviewForm(int32_t id, const FormData& form) {
Hajime Hoshie6104dc92018-03-20 05:58:02467 if (element_.IsNull())
468 return;
469
leon.han90fd63b2016-07-26 01:23:55470 if (id != autofill_query_id_)
[email protected]63560b32014-03-04 07:06:26471 return;
472
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39473 query_node_autofill_state_ = element_.GetAutofillState();
mathp9172c62a2015-10-08 18:51:14474 form_util::PreviewForm(form, element_);
leon.han90fd63b2016-07-26 01:23:55475
476 GetAutofillDriver()->DidPreviewAutofillFormData();
[email protected]6f001a6cf2012-02-09 15:21:53477}
478
leon.han90fd63b2016-07-26 01:23:55479void AutofillAgent::FieldTypePredictionsAvailable(
leon.han35ae41c2016-07-29 03:30:58480 const std::vector<FormDataPredictions>& forms) {
Mathieu Perreaultd7b56b492017-10-18 16:52:17481 bool attach_predictions_to_dom =
Mathieu Perreaulta24d0c22017-11-10 01:22:00482 base::FeatureList::IsEnabled(features::kAutofillShowTypePredictions);
leon.han90fd63b2016-07-26 01:23:55483 for (const auto& form : forms) {
Mathieu Perreaultd7b56b492017-10-18 16:52:17484 form_cache_.ShowPredictions(form, attach_predictions_to_dom);
leon.han90fd63b2016-07-26 01:23:55485 }
486}
487
Parastoo Geranmayeh7d8ea062018-05-15 22:16:25488void AutofillAgent::ClearSection() {
Hajime Hoshie6104dc92018-03-20 05:58:02489 if (element_.IsNull())
490 return;
491
Parastoo Geranmayeh7d8ea062018-05-15 22:16:25492 form_cache_.ClearSectionWithElement(element_);
[email protected]6f001a6cf2012-02-09 15:21:53493}
494
leon.han90fd63b2016-07-26 01:23:55495void AutofillAgent::ClearPreviewedForm() {
Hajime Hoshi83c3f502018-03-14 05:49:01496 // TODO(crbug.com/816533): It is very rare, but it looks like the |element_|
497 // can be null if a provisional load was committed immediately prior to
498 // clearing the previewed form.
499 if (element_.IsNull())
500 return;
[email protected]b5b1d69f2014-01-23 23:49:32501
Hajime Hoshi83c3f502018-03-14 05:49:01502 if (password_autofill_agent_->DidClearAutofillSelection(element_))
503 return;
504
505 form_util::ClearPreviewedFormWithElement(element_,
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39506 query_node_autofill_state_);
[email protected]6f001a6cf2012-02-09 15:21:53507}
508
leon.han35ae41c2016-07-29 03:30:58509void AutofillAgent::FillFieldWithValue(const base::string16& value) {
Hajime Hoshie6104dc92018-03-20 05:58:02510 if (element_.IsNull())
511 return;
512
Blink Reformat1c4d759e2017-04-09 16:34:54513 WebInputElement* input_element = ToWebInputElement(&element_);
ziran.sunee0fd4432014-08-27 10:10:49514 if (input_element) {
leon.han35ae41c2016-07-29 03:30:58515 DoFillFieldWithValue(value, input_element);
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39516 input_element->SetAutofillState(WebAutofillState::kAutofilled);
ziran.sunee0fd4432014-08-27 10:10:49517 }
[email protected]ac9b92f2014-03-15 00:48:32518}
519
leon.han35ae41c2016-07-29 03:30:58520void AutofillAgent::PreviewFieldWithValue(const base::string16& value) {
Hajime Hoshie6104dc92018-03-20 05:58:02521 if (element_.IsNull())
522 return;
523
Blink Reformat1c4d759e2017-04-09 16:34:54524 WebInputElement* input_element = ToWebInputElement(&element_);
[email protected]e9d29d392014-03-25 01:15:15525 if (input_element)
leon.han35ae41c2016-07-29 03:30:58526 DoPreviewFieldWithValue(value, input_element);
[email protected]6f001a6cf2012-02-09 15:21:53527}
528
leon.han35ae41c2016-07-29 03:30:58529void AutofillAgent::AcceptDataListSuggestion(const base::string16& value) {
530 DoAcceptDataListSuggestion(value);
[email protected]5c8de6b92012-06-08 21:24:08531}
532
leon.han35ae41c2016-07-29 03:30:58533void AutofillAgent::FillPasswordSuggestion(const base::string16& username,
534 const base::string16& password) {
Hajime Hoshie6104dc92018-03-20 05:58:02535 if (element_.IsNull())
536 return;
537
leon.han35ae41c2016-07-29 03:30:58538 bool handled =
539 password_autofill_agent_->FillSuggestion(element_, username, password);
[email protected]126b1ad2014-05-21 22:37:33540 DCHECK(handled);
541}
542
leon.han35ae41c2016-07-29 03:30:58543void AutofillAgent::PreviewPasswordSuggestion(const base::string16& username,
544 const base::string16& password) {
Hajime Hoshie6104dc92018-03-20 05:58:02545 if (element_.IsNull())
546 return;
547
kinuko0073e7c82017-01-24 00:42:40548 bool handled = password_autofill_agent_->PreviewSuggestion(
Blink Reformat1c4d759e2017-04-09 16:34:54549 element_, blink::WebString::FromUTF16(username),
550 blink::WebString::FromUTF16(password));
[email protected]e7e83472012-04-05 02:56:26551 DCHECK(handled);
552}
553
leon.han90fd63b2016-07-26 01:23:55554void AutofillAgent::ShowInitialPasswordAccountSuggestions(
jwwfb2a1432016-06-13 22:44:15555 const PasswordFormFillData& form_data) {
556 std::vector<blink::WebInputElement> elements;
557 std::unique_ptr<RendererSavePasswordProgressLogger> logger;
558 if (password_autofill_agent_->logging_state_active()) {
leon.han97e8f752016-09-06 06:13:20559 logger.reset(new RendererSavePasswordProgressLogger(
560 GetPasswordManagerDriver().get()));
jwwfb2a1432016-06-13 22:44:15561 logger->LogMessage(SavePasswordProgressLogger::
562 STRING_ON_SHOW_INITIAL_PASSWORD_ACCOUNT_SUGGESTIONS);
563 }
564 password_autofill_agent_->GetFillableElementFromFormData(
Vasilii Sukhanovc2705472018-09-07 16:23:13565 form_data, logger.get(), &elements);
jwwfb2a1432016-06-13 22:44:15566
567 // If wait_for_username is true, we don't want to initially show form options
568 // until the user types in a valid username.
569 if (form_data.wait_for_username)
570 return;
571
572 ShowSuggestionsOptions options;
573 options.autofill_on_empty_values = true;
574 options.show_full_suggestion_list = true;
575 for (auto element : elements)
576 ShowSuggestions(element, options);
577}
578
tmartino283dda12016-06-23 21:43:54579bool AutofillAgent::CollectFormlessElements(FormData* output) {
Tao Bai86ac37152018-03-02 14:35:33580 if (render_frame() == nullptr || render_frame()->GetWebFrame() == nullptr)
581 return false;
582
Blink Reformat1c4d759e2017-04-09 16:34:54583 WebDocument document = render_frame()->GetWebFrame()->GetDocument();
tmartino283dda12016-06-23 21:43:54584
585 // Build up the FormData from the unowned elements. This logic mostly
586 // mirrors the construction of the synthetic form in form_cache.cc, but
587 // happens at submit-time so we can capture the modifications the user
588 // has made, and doesn't depend on form_cache's internal state.
589 std::vector<WebElement> fieldsets;
590 std::vector<WebFormControlElement> control_elements =
Blink Reformat1c4d759e2017-04-09 16:34:54591 form_util::GetUnownedAutofillableFormFieldElements(document.All(),
tmartino283dda12016-06-23 21:43:54592 &fieldsets);
593
594 if (control_elements.size() > form_util::kMaxParseableFields)
595 return false;
596
597 const form_util::ExtractMask extract_mask =
598 static_cast<form_util::ExtractMask>(form_util::EXTRACT_VALUE |
599 form_util::EXTRACT_OPTIONS);
600
601 return form_util::UnownedCheckoutFormElementsAndFieldSetsToFormData(
602 fieldsets, control_elements, nullptr, document, extract_mask, output,
603 nullptr);
mathpffc78e22015-09-01 14:10:50604}
605
[email protected]e9d29d392014-03-25 01:15:15606void AutofillAgent::ShowSuggestions(const WebFormControlElement& element,
brettwb505b7a2014-11-26 22:05:32607 const ShowSuggestionsOptions& options) {
Blink Reformat1c4d759e2017-04-09 16:34:54608 if (!element.IsEnabled() || element.IsReadOnly())
[email protected]efeb565f2013-12-12 17:16:41609 return;
Blink Reformat1c4d759e2017-04-09 16:34:54610 if (!element.SuggestedValue().IsEmpty())
[email protected]580c38052014-07-16 07:28:09611 return;
[email protected]e9d29d392014-03-25 01:15:15612
Blink Reformat1c4d759e2017-04-09 16:34:54613 const WebInputElement* input_element = ToWebInputElement(&element);
[email protected]e9d29d392014-03-25 01:15:15614 if (input_element) {
Blink Reformat1c4d759e2017-04-09 16:34:54615 if (!input_element->IsTextField())
[email protected]e9d29d392014-03-25 01:15:15616 return;
Blink Reformat1c4d759e2017-04-09 16:34:54617 if (!input_element->SuggestedValue().IsEmpty())
[email protected]e9d29d392014-03-25 01:15:15618 return;
619 } else {
mathp9172c62a2015-10-08 18:51:14620 DCHECK(form_util::IsTextAreaElement(element));
Blink Reformat1c4d759e2017-04-09 16:34:54621 if (!element.ToConst<WebFormControlElement>().SuggestedValue().IsEmpty())
[email protected]e9d29d392014-03-25 01:15:15622 return;
623 }
[email protected]e47aec52010-08-12 00:50:30624
[email protected]1c69f8b72012-03-14 03:18:50625 // Don't attempt to autofill with values that are too large or if filling
626 // criteria are not met.
Blink Reformat1c4d759e2017-04-09 16:34:54627 WebString value = element.EditingValue();
mathp5f90bce22015-11-22 20:16:58628 if (value.length() > kMaxDataLength ||
Blink Reformat1c4d759e2017-04-09 16:34:54629 (!options.autofill_on_empty_values && value.IsEmpty()) ||
mathp5f90bce22015-11-22 20:16:58630 (options.requires_caret_at_end &&
Blink Reformat1c4d759e2017-04-09 16:34:54631 (element.SelectionStart() != element.SelectionEnd() ||
632 element.SelectionEnd() != static_cast<int>(value.length())))) {
[email protected]1c69f8b72012-03-14 03:18:50633 // Any popup currently showing is obsolete.
[email protected]b648f242014-02-25 13:49:06634 HidePopup();
[email protected]e47aec52010-08-12 00:50:30635 return;
[email protected]1c69f8b72012-03-14 03:18:50636 }
[email protected]e47aec52010-08-12 00:50:30637
[email protected]bef7f9272012-04-17 10:47:49638 element_ = element;
mathp9172c62a2015-10-08 18:51:14639 if (form_util::IsAutofillableInputElement(input_element) &&
gcastocdd33e0d2015-06-17 22:10:05640 password_autofill_agent_->ShowSuggestions(
641 *input_element, options.show_full_suggestion_list,
642 is_generation_popup_possibly_visible_)) {
[email protected]b648f242014-02-25 13:49:06643 is_popup_possibly_visible_ = true;
[email protected]c66ba982013-04-05 09:56:17644 return;
[email protected]b648f242014-02-25 13:49:06645 }
[email protected]bef7f9272012-04-17 10:47:49646
gcastocdd33e0d2015-06-17 22:10:05647 if (is_generation_popup_possibly_visible_)
648 return;
649
650 if (options.show_password_suggestions_only)
651 return;
652
jww20355072014-12-12 21:00:55653 // Password field elements should only have suggestions shown by the password
654 // autofill agent.
Dominic Battre1bb521c2017-12-19 21:10:03655 if (input_element && input_element->IsPasswordFieldForAutofill() &&
656 !query_password_suggestion_) {
jww20355072014-12-12 21:00:55657 return;
Dominic Battre1bb521c2017-12-19 21:10:03658 }
jww20355072014-12-12 21:00:55659
Fabio Tirelo83662a22018-07-06 15:03:48660 QueryAutofillSuggestions(element, options.autoselect_first_suggestion);
[email protected]77bb0da2010-11-20 01:55:30661}
662
Tao Baia8c0d8bb2017-12-18 19:47:36663void AutofillAgent::SetQueryPasswordSuggestion(bool query) {
664 query_password_suggestion_ = query;
665}
666
Tao Bai88d56d42017-07-17 16:07:16667void AutofillAgent::SetSecureContextRequired(bool required) {
668 is_secure_context_required_ = required;
669}
670
Changwan Ryueb8a057e2017-12-08 19:22:33671void AutofillAgent::SetFocusRequiresScroll(bool require) {
672 focus_requires_scroll_ = require;
673}
674
gogeraldd4f184b2018-09-19 22:24:24675void AutofillAgent::GetElementFormAndFieldData(
676 const std::vector<std::string>& selectors,
677 GetElementFormAndFieldDataCallback callback) {
678 FormData form;
679 FormFieldData field;
680 blink::WebElement target_element = FindUniqueWebElement(selectors);
681 if (target_element.IsNull() || !target_element.IsFormControlElement()) {
682 return std::move(callback).Run(form, field);
683 }
684
685 blink::WebFormControlElement target_form_control_element =
686 target_element.To<blink::WebFormControlElement>();
gogerald3e2f8a12018-10-11 21:46:54687 bool success = form_util::FindFormAndFieldForFormControlElement(
688 target_form_control_element, &form, &field);
689 if (success) {
690 // Remember this element so as to autofill the form without focusing the
691 // field for Autofill Assistant.
692 element_ = target_form_control_element;
693 }
694 // Do not expect failure.
695 DCHECK(success);
696
gogeraldd4f184b2018-09-19 22:24:24697 return std::move(callback).Run(form, field);
698}
699
700blink::WebElement AutofillAgent::FindUniqueWebElement(
701 const std::vector<std::string>& selectors) {
702 DCHECK(selectors.size() > 0);
703
704 blink::WebVector<blink::WebElement> elements =
705 render_frame()->GetWebFrame()->GetDocument().QuerySelectorAll(
706 blink::WebString::FromUTF8(selectors[0]));
707 if (elements.size() != 1) {
708 return blink::WebElement();
709 }
710
711 // Get the unique element in |elements| and match the next selector inside it
712 // if there are remaining selectors haven't been matched.
713 blink::WebElement query_element = elements[0];
714 for (size_t i = 1; i < selectors.size(); i++) {
715 elements = query_element.QuerySelectorAll(
716 blink::WebString::FromUTF8(selectors[i]));
717
718 // Query shadow DOM if necessary.
719 if (elements.size() == 0 && !query_element.ShadowRoot().IsNull()) {
gogeraldd52275112018-09-21 02:17:22720 // TODO(806868): Query shadow dom when Autofill is available for forms in
721 // shadow DOM (crbug.com/746593).
722 return blink::WebElement();
gogeraldd4f184b2018-09-19 22:24:24723 }
724
725 // Return an empty element if there are multiple matching elements.
726 if (elements.size() != 1) {
727 return blink::WebElement();
728 }
729
730 query_element = elements[0];
731 }
732
733 return query_element;
734}
735
[email protected]e9d29d392014-03-25 01:15:15736void AutofillAgent::QueryAutofillSuggestions(
Fabio Tirelo83662a22018-07-06 15:03:48737 const WebFormControlElement& element,
738 bool autoselect_first_suggestion) {
Blink Reformat1c4d759e2017-04-09 16:34:54739 if (!element.GetDocument().GetFrame())
[email protected]e69b5f72013-01-24 00:59:13740 return;
741
Blink Reformat1c4d759e2017-04-09 16:34:54742 DCHECK(ToWebInputElement(&element) || form_util::IsTextAreaElement(element));
[email protected]e9d29d392014-03-25 01:15:15743
[email protected]77bb0da2010-11-20 01:55:30744 static int query_counter = 0;
745 autofill_query_id_ = query_counter++;
estade0ee91262014-10-23 19:29:19746
[email protected]1ecbe862012-10-05 01:29:14747 FormData form;
748 FormFieldData field;
mathp9172c62a2015-10-08 18:51:14749 if (!form_util::FindFormAndFieldForFormControlElement(element, &form,
750 &field)) {
[email protected]7837be62011-01-18 23:45:08751 // If we didn't find the cached form, at least let autocomplete have a shot
752 // at providing suggestions.
kolos66b4c292016-07-29 17:54:53753 WebFormControlElementToFormField(element, nullptr, form_util::EXTRACT_VALUE,
754 &field);
[email protected]7837be62011-01-18 23:45:08755 }
[email protected]77bb0da2010-11-20 01:55:30756
Tao Bai88d56d42017-07-17 16:07:16757 if (is_secure_context_required_ &&
Tao Bai6b032dd2017-09-19 18:44:07758 !(element.GetDocument().IsSecureContext())) {
Tao Bai88d56d42017-07-17 16:07:16759 LOG(WARNING) << "Autofill suggestions are disabled because the document "
Tao Bai6b032dd2017-09-19 18:44:07760 "isn't a secure context.";
Tao Bai88d56d42017-07-17 16:07:16761 return;
762 }
763
[email protected]7d0ea5362014-05-01 23:39:43764 std::vector<base::string16> data_list_values;
765 std::vector<base::string16> data_list_labels;
Blink Reformat1c4d759e2017-04-09 16:34:54766 const WebInputElement* input_element = ToWebInputElement(&element);
[email protected]e9d29d392014-03-25 01:15:15767 if (input_element) {
768 // Find the datalist values and send them to the browser process.
[email protected]e9d29d392014-03-25 01:15:15769 GetDataListSuggestions(*input_element,
[email protected]e9d29d392014-03-25 01:15:15770 &data_list_values,
771 &data_list_labels);
772 TrimStringVectorForIPC(&data_list_values);
773 TrimStringVectorForIPC(&data_list_labels);
[email protected]e9d29d392014-03-25 01:15:15774 }
[email protected]5c8de6b92012-06-08 21:24:08775
[email protected]b648f242014-02-25 13:49:06776 is_popup_possibly_visible_ = true;
[email protected]7d0ea5362014-05-01 23:39:43777
leon.han35ae41c2016-07-29 03:30:58778 GetAutofillDriver()->SetDataList(data_list_values, data_list_labels);
leon.han90fd63b2016-07-26 01:23:55779 GetAutofillDriver()->QueryFormFieldAutofill(
780 autofill_query_id_, form, field,
Fabio Tirelo83662a22018-07-06 15:03:48781 render_frame()->GetRenderView()->ElementBoundsInWindow(element_),
782 autoselect_first_suggestion);
[email protected]e47aec52010-08-12 00:50:30783}
784
leon.han90fd63b2016-07-26 01:23:55785void AutofillAgent::DoFillFieldWithValue(const base::string16& value,
786 WebInputElement* node) {
Tao Bai81483262018-03-02 05:38:12787 form_tracker_.set_ignore_control_changes(true);
sebsg778c43692018-01-24 20:01:32788 node->SetAutofillValue(blink::WebString::FromUTF16(value));
Vadym Doroshenkoa332ebc2017-09-14 11:46:53789 password_autofill_agent_->UpdateStateForTextChange(*node);
Tao Bai81483262018-03-02 05:38:12790 form_tracker_.set_ignore_control_changes(false);
[email protected]ac9b92f2014-03-15 00:48:32791}
792
leon.han90fd63b2016-07-26 01:23:55793void AutofillAgent::DoPreviewFieldWithValue(const base::string16& value,
794 WebInputElement* node) {
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39795 query_node_autofill_state_ = element_.GetAutofillState();
sebsg778c43692018-01-24 20:01:32796 node->SetSuggestedValue(blink::WebString::FromUTF16(value));
Parastoo Geranmayeh2dcd14f92018-06-01 17:08:39797 node->SetAutofillState(WebAutofillState::kPreviewed);
Blink Reformat1c4d759e2017-04-09 16:34:54798 form_util::PreviewSuggestion(node->SuggestedValue().Utf16(),
799 node->Value().Utf16(), node);
[email protected]6f001a6cf2012-02-09 15:21:53800}
801
estadeb1bc9bd2014-12-02 22:44:11802void AutofillAgent::ProcessForms() {
[email protected]5193ea52014-05-14 01:10:02803 // Record timestamp of when the forms are first seen. This is used to
804 // measure the overhead of the Autofill feature.
805 base::TimeTicks forms_seen_timestamp = base::TimeTicks::Now();
806
estadeb1bc9bd2014-12-02 22:44:11807 WebLocalFrame* frame = render_frame()->GetWebFrame();
estadeff02e6d2014-12-15 21:18:31808 std::vector<FormData> forms = form_cache_.ExtractNewForms();
[email protected]5193ea52014-05-14 01:10:02809
810 // Always communicate to browser process for topmost frame.
Blink Reformat1c4d759e2017-04-09 16:34:54811 if (!forms.empty() || !frame->Parent()) {
leon.han35ae41c2016-07-29 03:30:58812 GetAutofillDriver()->FormsSeen(forms, forms_seen_timestamp);
[email protected]5193ea52014-05-14 01:10:02813 }
[email protected]5193ea52014-05-14 01:10:02814}
815
[email protected]b648f242014-02-25 13:49:06816void AutofillAgent::HidePopup() {
817 if (!is_popup_possibly_visible_)
818 return;
[email protected]b648f242014-02-25 13:49:06819 is_popup_possibly_visible_ = false;
gcastocdd33e0d2015-06-17 22:10:05820 is_generation_popup_possibly_visible_ = false;
leon.han90fd63b2016-07-26 01:23:55821
822 GetAutofillDriver()->HidePopup();
[email protected]81cd52332012-11-05 20:36:07823}
824
rouslan42b090872015-05-17 05:04:33825bool AutofillAgent::IsUserGesture() const {
Mustaq Ahmede473e4352017-11-04 01:04:25826 return WebUserGestureIndicator::IsProcessingUserGesture(
827 render_frame()->GetWebFrame());
rouslan42b090872015-05-17 05:04:33828}
829
Blink Reformat1c4d759e2017-04-09 16:34:54830void AutofillAgent::DidAssociateFormControlsDynamically() {
vasilii31ba8c6c2017-04-28 21:35:08831 // If the control flow is here than the document was at least loaded. The
832 // whole page doesn't have to be loaded.
833 ProcessForms();
834 password_autofill_agent_->OnDynamicFormsSeen();
835 if (password_generation_agent_)
836 password_generation_agent_->OnDynamicFormsSeen();
[email protected]17b6be72013-04-30 21:33:08837}
838
ekaramad27ca69b12017-04-20 18:34:29839void AutofillAgent::DidCompleteFocusChangeInFrame() {
840 WebDocument doc = render_frame()->GetWebFrame()->GetDocument();
841 WebElement focused_element;
842 if (!doc.IsNull())
843 focused_element = doc.FocusedElement();
844 // PasswordGenerationAgent needs to know about focus changes, even if there is
845 // no focused element.
846 if (password_generation_agent_ &&
847 password_generation_agent_->FocusedNodeHasChanged(focused_element)) {
848 is_generation_popup_possibly_visible_ = true;
849 is_popup_possibly_visible_ = true;
850 }
851 if (!focused_element.IsNull() && password_autofill_agent_)
852 password_autofill_agent_->FocusedNodeHasChanged(focused_element);
853
Changwan Ryueb8a057e2017-12-08 19:22:33854 if (!IsKeyboardAccessoryEnabled() && focus_requires_scroll_)
Ehsan Karamad3538c8a2017-11-20 16:31:40855 HandleFocusChangeComplete();
ekaramad27ca69b12017-04-20 18:34:29856}
857
858void AutofillAgent::DidReceiveLeftMouseDownOrGestureTapInNode(
859 const WebNode& node) {
Ehsan Karamad3538c8a2017-11-20 16:31:40860 DCHECK(!node.IsNull());
861 focused_node_was_last_clicked_ = node.Focused();
862
Changwan Ryueb8a057e2017-12-08 19:22:33863 if (IsKeyboardAccessoryEnabled() || !focus_requires_scroll_)
Ehsan Karamad3538c8a2017-11-20 16:31:40864 HandleFocusChangeComplete();
865}
866
Tao Bai81483262018-03-02 05:38:12867void AutofillAgent::SelectControlDidChange(
868 const WebFormControlElement& element) {
869 form_tracker_.SelectControlDidChange(element);
870}
871
sebsg248c6b02018-04-09 20:20:42872void AutofillAgent::SelectFieldOptionsChanged(
873 const blink::WebFormControlElement& element) {
874 if (!was_last_action_fill_ || element_.IsNull())
875 return;
876
sebsg1c436852018-04-18 16:54:32877 // Since a change of a select options often come in batches, use a timer
878 // to wait for other changes. Stop the timer if it was already running. It
879 // will be started again for this change.
880 if (on_select_update_timer_.IsRunning())
881 on_select_update_timer_.AbandonAndStop();
882
883 // Start the timer to notify the driver that the select field was updated
884 // after the options have finished changing,
885 on_select_update_timer_.Start(
886 FROM_HERE,
887 base::TimeDelta::FromMilliseconds(kWaitTimeForSelectOptionsChangesMs),
888 base::BindRepeating(&AutofillAgent::SelectWasUpdated,
889 weak_ptr_factory_.GetWeakPtr(), element));
890}
891
892void AutofillAgent::SelectWasUpdated(
893 const blink::WebFormControlElement& element) {
894 // Look for the form and field associated with the select element. If they are
895 // found, notify the driver that the the form was modified dynamically.
sebsg248c6b02018-04-09 20:20:42896 FormData form;
897 FormFieldData field;
898 if (form_util::FindFormAndFieldForFormControlElement(element, &form,
899 &field) &&
900 !field.option_values.empty()) {
sebsg1c436852018-04-18 16:54:32901 GetAutofillDriver()->SelectFieldOptionsDidChange(form);
sebsg248c6b02018-04-09 20:20:42902 }
903}
904
Ehsan Karamad3538c8a2017-11-20 16:31:40905void AutofillAgent::FormControlElementClicked(
906 const WebFormControlElement& element,
907 bool was_focused) {
908 last_clicked_form_control_element_for_testing_ = element;
909 last_clicked_form_control_element_was_focused_for_testing_ = was_focused;
sebsg248c6b02018-04-09 20:20:42910 was_last_action_fill_ = false;
Ehsan Karamad3538c8a2017-11-20 16:31:40911
912 const WebInputElement* input_element = ToWebInputElement(&element);
913 if (!input_element && !form_util::IsTextAreaElement(element))
914 return;
915
916 ShowSuggestionsOptions options;
917 options.autofill_on_empty_values = true;
Roger McFarlane3a9c4402018-05-18 18:29:35918 // Show full suggestions when clicking on an already-focused form field.
919 options.show_full_suggestion_list = element.IsAutofilled() || was_focused;
Ehsan Karamad3538c8a2017-11-20 16:31:40920
921 if (!IsSingleClickEnabled()) {
Roger McFarlane3a9c4402018-05-18 18:29:35922 // On the initial click (not focused yet), only show password suggestions.
Ehsan Karamad3538c8a2017-11-20 16:31:40923 options.show_password_suggestions_only = !was_focused;
924 }
925 ShowSuggestions(element, options);
926}
927
928void AutofillAgent::HandleFocusChangeComplete() {
929 WebElement focused_element =
930 render_frame()->GetWebFrame()->GetDocument().FocusedElement();
931
932 if (focused_node_was_last_clicked_ && !focused_element.IsNull() &&
933 focused_element.IsFormControlElement() &&
934 (form_util::IsTextInput(blink::ToWebInputElement(&focused_element)) ||
935 focused_element.HasHTMLTagName("textarea"))) {
936 FormControlElementClicked(focused_element.ToConst<WebFormControlElement>(),
937 was_focused_before_now_);
938 }
939
940 was_focused_before_now_ = true;
941 focused_node_was_last_clicked_ = false;
ekaramad27ca69b12017-04-20 18:34:29942}
943
Blink Reformat1c4d759e2017-04-09 16:34:54944void AutofillAgent::AjaxSucceeded() {
Tao Bai6cd41ad2017-12-04 18:48:17945 form_tracker_.AjaxSucceeded();
946}
947
Tao Bai81483262018-03-02 05:38:12948void AutofillAgent::OnProvisionallySaveForm(
949 const WebFormElement& form,
950 const WebFormControlElement& element,
951 ElementChangeSource source) {
Tao Bai6cd41ad2017-12-04 18:48:17952 if (source == ElementChangeSource::WILL_SEND_SUBMIT_EVENT) {
Tao Baia674b1d2018-01-18 22:33:43953 // Fire the form submission event to avoid missing submission when web site
954 // handles the onsubmit event, this also gets the form before Javascript
955 // could change it.
956 // We don't clear submitted_forms_ because OnFormSubmitted will normally be
957 // invoked afterwards and we don't want to fire the same event twice.
958 FireHostSubmitEvents(form, /*known_success=*/false,
959 SubmissionSource::FORM_SUBMISSION);
960 ResetLastInteractedElements();
961 return;
Tao Bai81483262018-03-02 05:38:12962 } else if (source == ElementChangeSource::TEXTFIELD_CHANGED ||
963 source == ElementChangeSource::SELECT_CHANGED) {
Tao Baia674b1d2018-01-18 22:33:43964 // Remember the last form the user interacted with.
Tao Bai6cd41ad2017-12-04 18:48:17965 if (!element.Form().IsNull()) {
Tao Baie4d26212017-12-19 01:30:11966 UpdateLastInteractedForm(element.Form());
Tao Bai6cd41ad2017-12-04 18:48:17967 } else {
968 // Remove invisible elements
969 for (auto it = formless_elements_user_edited_.begin();
970 it != formless_elements_user_edited_.end();) {
971 if (form_util::IsWebElementVisible(*it)) {
972 it = formless_elements_user_edited_.erase(it);
973 } else {
974 ++it;
975 }
976 }
977 formless_elements_user_edited_.insert(element);
Tao Baie4d26212017-12-19 01:30:11978 provisionally_saved_form_ = std::make_unique<FormData>();
979 if (!CollectFormlessElements(provisionally_saved_form_.get())) {
980 provisionally_saved_form_.reset();
Tao Bai6cd41ad2017-12-04 18:48:17981 } else {
982 last_interacted_form_.Reset();
983 }
984 }
Tao Bai81483262018-03-02 05:38:12985
986 if (source == ElementChangeSource::TEXTFIELD_CHANGED)
987 OnTextFieldDidChange(*ToWebInputElement(&element));
988 else {
989 FormData form;
990 FormFieldData field;
Tao Baiec24a4c22018-03-14 17:16:08991 if (form_util::FindFormAndFieldForFormControlElement(element, &form,
992 &field)) {
993 GetAutofillDriver()->SelectControlDidChange(
Tao Bai81483262018-03-02 05:38:12994 form, field,
995 render_frame()->GetRenderView()->ElementBoundsInWindow(element));
996 }
997 }
Tao Bai6cd41ad2017-12-04 18:48:17998 }
999}
1000
1001void AutofillAgent::OnProbablyFormSubmitted() {
Tao Baia674b1d2018-01-18 22:33:431002 FormData form_data;
1003 if (GetSubmittedForm(&form_data)) {
1004 FireHostSubmitEvents(form_data, /*known_success=*/false,
1005 SubmissionSource::PROBABLY_FORM_SUBMITTED);
1006 }
Tao Bai6cd41ad2017-12-04 18:48:171007 ResetLastInteractedElements();
Tao Baia674b1d2018-01-18 22:33:431008 OnFormNoLongerSubmittable();
Tao Bai6cd41ad2017-12-04 18:48:171009}
1010
1011void AutofillAgent::OnFormSubmitted(const WebFormElement& form) {
Tao Baia674b1d2018-01-18 22:33:431012 // Fire the submission event here because WILL_SEND_SUBMIT_EVENT is skipped
1013 // if javascript calls submit() directly.
1014 FireHostSubmitEvents(form, /*known_success=*/false,
1015 SubmissionSource::FORM_SUBMISSION);
Tao Bai6cd41ad2017-12-04 18:48:171016 ResetLastInteractedElements();
Tao Baia674b1d2018-01-18 22:33:431017 OnFormNoLongerSubmittable();
Tao Bai6cd41ad2017-12-04 18:48:171018}
1019
1020void AutofillAgent::OnInferredFormSubmission(SubmissionSource source) {
1021 // Only handle iframe for FRAME_DETACHED or main frame for
1022 // SAME_DOCUMENT_NAVIGATION.
1023 if ((source == SubmissionSource::FRAME_DETACHED &&
1024 !render_frame()->GetWebFrame()->Parent()) ||
1025 (source == SubmissionSource::SAME_DOCUMENT_NAVIGATION &&
1026 render_frame()->GetWebFrame()->Parent())) {
Tao Baia674b1d2018-01-18 22:33:431027 ResetLastInteractedElements();
1028 OnFormNoLongerSubmittable();
Tao Bai6cd41ad2017-12-04 18:48:171029 return;
1030 }
1031
Tao Bai2c1b3d062017-12-07 17:20:281032 if (source == SubmissionSource::FRAME_DETACHED) {
1033 // Should not access the frame because it is now detached. Instead, use
Tao Baie4d26212017-12-19 01:30:111034 // |provisionally_saved_form_|.
1035 if (provisionally_saved_form_)
Tao Baia674b1d2018-01-18 22:33:431036 FireHostSubmitEvents(*provisionally_saved_form_, /*known_success=*/true,
1037 source);
Tao Bai2c1b3d062017-12-07 17:20:281038 } else {
1039 FormData form_data;
Tao Baie4d26212017-12-19 01:30:111040 if (GetSubmittedForm(&form_data))
Tao Baia674b1d2018-01-18 22:33:431041 FireHostSubmitEvents(form_data, /*known_success=*/true, source);
Tao Bai6cd41ad2017-12-04 18:48:171042 }
1043 ResetLastInteractedElements();
Tao Baia674b1d2018-01-18 22:33:431044 OnFormNoLongerSubmittable();
Tao Bai6cd41ad2017-12-04 18:48:171045}
1046
1047void AutofillAgent::AddFormObserver(Observer* observer) {
1048 form_tracker_.AddObserver(observer);
1049}
1050
1051void AutofillAgent::RemoveFormObserver(Observer* observer) {
1052 form_tracker_.RemoveObserver(observer);
1053}
1054
1055bool AutofillAgent::GetSubmittedForm(FormData* form) {
1056 if (!last_interacted_form_.IsNull()) {
Tao Baie4d26212017-12-19 01:30:111057 if (form_util::ExtractFormData(last_interacted_form_, form)) {
1058 return true;
1059 } else if (provisionally_saved_form_) {
1060 *form = *provisionally_saved_form_;
1061 return true;
1062 }
Tao Bai6cd41ad2017-12-04 18:48:171063 } else if (formless_elements_user_edited_.size() != 0 &&
1064 !form_util::IsSomeControlElementVisible(
1065 formless_elements_user_edited_)) {
1066 // we check if all the elements the user has interacted with are gone,
Tao Baie4d26212017-12-19 01:30:111067 // to decide if submission has occurred, and use the
1068 // provisionally_saved_form_ saved in OnProvisionallySaveForm() if fail to
1069 // construct form.
Tao Bai6cd41ad2017-12-04 18:48:171070 if (CollectFormlessElements(form)) {
1071 return true;
Tao Baie4d26212017-12-19 01:30:111072 } else if (provisionally_saved_form_) {
1073 *form = *provisionally_saved_form_;
Tao Bai6cd41ad2017-12-04 18:48:171074 return true;
1075 }
1076 }
1077 return false;
1078}
1079
1080void AutofillAgent::ResetLastInteractedElements() {
1081 last_interacted_form_.Reset();
Alexander Timokhin3c45d1a2018-03-28 17:49:281082 last_clicked_form_control_element_for_testing_.Reset();
Tao Bai6cd41ad2017-12-04 18:48:171083 formless_elements_user_edited_.clear();
Tao Baie4d26212017-12-19 01:30:111084 provisionally_saved_form_.reset();
1085}
1086
1087void AutofillAgent::UpdateLastInteractedForm(blink::WebFormElement form) {
1088 last_interacted_form_ = form;
1089 provisionally_saved_form_ = std::make_unique<FormData>();
1090 if (!form_util::ExtractFormData(last_interacted_form_,
1091 provisionally_saved_form_.get())) {
1092 provisionally_saved_form_.reset();
1093 }
gcastoc21f1c4c2015-03-19 21:57:031094}
1095
Tao Baia674b1d2018-01-18 22:33:431096void AutofillAgent::OnFormNoLongerSubmittable() {
1097 submitted_forms_.clear();
1098}
1099
Parastoo Geranmayeh1421e632018-07-25 15:57:031100bool AutofillAgent::FindTheUniqueNewVersionOfOldElement(
1101 WebVector<WebFormControlElement>& elements,
1102 bool& element_found,
1103 const WebString& original_element_section,
1104 const WebFormControlElement& original_element) {
1105 for (const WebFormControlElement& current_element : elements) {
1106 if (current_element.IsFocusable() &&
1107 original_element.NameForAutofill() ==
1108 current_element.NameForAutofill()) {
1109 if (!element_found) {
1110 element_ = current_element;
1111 element_found = true;
1112 } else if (current_element.AutofillSection() ==
1113 element_.AutofillSection() ||
1114 (current_element.AutofillSection() !=
1115 original_element_section &&
1116 element_.AutofillSection() != original_element_section)) {
1117 // If there are two elements that share the same name with the element_,
1118 // and the section can't tell them apart, we can't decide between the
1119 // two.
1120 element_ = original_element;
1121 return false;
1122 } else if (current_element.AutofillSection() ==
1123 original_element_section) {
1124 // If the current element has the right section, update the element_.
1125 element_ = current_element;
1126 }
1127 }
1128 }
1129 return true;
1130}
1131
sebsge35b762c2018-03-29 20:33:271132void AutofillAgent::ReplaceElementIfNowInvalid(const FormData& original_form) {
1133 // If the document is invalid, bail out.
1134 if (element_.GetDocument().IsNull())
1135 return;
1136
Parastoo Geranmayeh1421e632018-07-25 15:57:031137 WebVector<WebFormElement> forms;
1138 WebVector<WebFormControlElement> elements;
1139
1140 if (original_form.name.empty()) {
1141 // If the form has no name, check all the forms.
1142 bool element_found = false;
1143 element_.GetDocument().Forms(forms);
1144 for (const WebFormElement& form : forms) {
1145 form.GetFormControlElements(elements);
1146 // If finding a unique element is impossible, return.
1147 if (!FindTheUniqueNewVersionOfOldElement(
1148 elements, element_found, element_.AutofillSection(), element_))
1149 return;
1150 }
1151 // If the element is not found, we should still check for unowned elements.
1152 if (element_found)
1153 return;
1154 }
1155
sebsge35b762c2018-03-29 20:33:271156 if (!element_.Form().IsNull()) {
1157 // If |element_|'s parent form has no elements, |element_| is now invalid
1158 // and should be updated.
1159 WebVector<WebFormControlElement> form_elements;
1160 element_.Form().GetFormControlElements(form_elements);
1161 if (!form_elements.empty())
1162 return;
1163 }
1164
sebsge35b762c2018-03-29 20:33:271165 WebFormElement form_element;
Parastoo Geranmayeh1421e632018-07-25 15:57:031166 if (!original_form.name.empty()) {
1167 // Try to find the new version of the form.
1168 element_.GetDocument().Forms(forms);
1169 for (const WebFormElement& form : forms) {
1170 if (original_form.name == form.GetName().Utf16() ||
1171 original_form.name == form.GetAttribute("id").Utf16()) {
1172 form_element = form;
1173 break;
1174 }
sebsge35b762c2018-03-29 20:33:271175 }
1176 }
1177
sebsgf32e98d72018-05-11 14:43:011178 if (form_element.IsNull()) {
1179 // Could not find the new version of the form, get all the unowned elements.
1180 std::vector<WebElement> fieldsets;
1181 elements = form_util::GetUnownedAutofillableFormFieldElements(
1182 element_.GetDocument().All(), &fieldsets);
Parastoo Geranmayeh1421e632018-07-25 15:57:031183 bool element_found = false;
1184 FindTheUniqueNewVersionOfOldElement(elements, element_found,
1185 element_.AutofillSection(), element_);
1186 return;
sebsgf32e98d72018-05-11 14:43:011187 }
Parastoo Geranmayeh1421e632018-07-25 15:57:031188 // This is the case for owned fields that belong to the right named form.
1189 // Get all the elements of the new version of the form.
1190 form_element.GetFormControlElements(elements);
sebsge35b762c2018-03-29 20:33:271191 // Try to find the new version of the last interacted element.
sebsge35b762c2018-03-29 20:33:271192 for (const WebFormControlElement& element : elements) {
1193 if (element_.NameForAutofill() == element.NameForAutofill()) {
1194 element_ = element;
1195 return;
1196 }
1197 }
1198}
1199
Ken Rockot0aad7ec2018-07-31 15:58:441200const mojom::AutofillDriverAssociatedPtr& AutofillAgent::GetAutofillDriver() {
leon.han97e8f752016-09-06 06:13:201201 if (!autofill_driver_) {
Ken Rockot0aad7ec2018-07-31 15:58:441202 render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
blundelle0a9f1582016-12-20 11:23:321203 mojo::MakeRequest(&autofill_driver_));
leon.han90fd63b2016-07-26 01:23:551204 }
leon.hande852902016-05-04 09:16:381205
leon.han97e8f752016-09-06 06:13:201206 return autofill_driver_;
1207}
1208
Friedrich Horschig9c896332018-07-16 16:09:071209const mojom::PasswordManagerDriverAssociatedPtr&
leon.han97e8f752016-09-06 06:13:201210AutofillAgent::GetPasswordManagerDriver() {
1211 DCHECK(password_autofill_agent_);
1212 return password_autofill_agent_->GetPasswordManagerDriver();
leon.hande852902016-05-04 09:16:381213}
1214
[email protected]78192082011-01-29 05:43:441215} // namespace autofill