1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/autofill/content/renderer/password_autofill_agent.h"
14 #include "base/check.h"
15 #include "base/containers/contains.h"
16 #include "base/feature_list.h"
17 #include "base/functional/bind.h"
18 #include "base/i18n/case_conversion.h"
19 #include "base/memory/raw_ptr.h"
20 #include "base/metrics/field_trial_params.h"
21 #include "base/metrics/histogram_macros.h"
22 #include "base/no_destructor.h"
23 #include "base/notreached.h"
24 #include "base/numerics/safe_conversions.h"
25 #include "base/ranges/algorithm.h"
26 #include "base/strings/strcat.h"
27 #include "base/strings/string_number_conversions.h"
28 #include "base/strings/string_util.h"
29 #include "base/strings/utf_string_conversions.h"
30 #include "base/task/single_thread_task_runner.h"
31 #include "build/build_config.h"
32 #include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
33 #include "components/autofill/content/renderer/form_autofill_util.h"
34 #include "components/autofill/content/renderer/password_form_conversion_utils.h"
35 #include "components/autofill/content/renderer/password_generation_agent.h"
36 #include "components/autofill/content/renderer/prefilled_values_detector.h"
37 #include "components/autofill/content/renderer/renderer_save_password_progress_logger.h"
38 #include "components/autofill/core/common/autofill_constants.h"
39 #include "components/autofill/core/common/autofill_features.h"
40 #include "components/autofill/core/common/autofill_regexes.h"
41 #include "components/autofill/core/common/autofill_util.h"
42 #include "components/autofill/core/common/form_field_data.h"
43 #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
44 #include "components/autofill/core/common/mojom/autofill_types.mojom.h"
45 #include "components/autofill/core/common/password_form_fill_data.h"
46 #include "components/autofill/core/common/signatures.h"
47 #include "components/password_manager/core/common/password_manager_constants.h"
48 #include "components/password_manager/core/common/password_manager_features.h"
49 #include "components/password_manager/core/common/password_manager_util.h"
50 #include "components/safe_browsing/buildflags.h"
51 #include "content/public/renderer/render_frame.h"
52 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
53 #include "services/service_manager/public/cpp/interface_provider.h"
54 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
55 #include "third_party/blink/public/common/features.h"
56 #include "third_party/blink/public/common/features_generated.h"
57 #include "third_party/blink/public/common/input/web_input_event.h"
59 #if BUILDFLAG(IS_TIZEN_TV)
60 #include "base/command_line.h"
61 #include "ewk/efl_integration/common/content_switches_efl.h"
62 #include "third_party/blink/public/common/input/web_coalesced_input_event.h"
63 #include "third_party/blink/public/common/input/web_keyboard_event.h"
64 #include "third_party/blink/public/platform/web_application_type.h"
65 #include "third_party/blink/public/platform/web_string.h"
66 #include "third_party/blink/public/web/web_frame_widget.h"
67 #include "third_party/blink/public/web/web_widget.h"
70 #include "third_party/blink/public/platform/web_security_origin.h"
71 #include "third_party/blink/public/platform/web_vector.h"
72 #include "third_party/blink/public/web/web_autofill_client.h"
73 #include "third_party/blink/public/web/web_document.h"
74 #include "third_party/blink/public/web/web_element.h"
75 #include "third_party/blink/public/web/web_form_control_element.h"
76 #include "third_party/blink/public/web/web_form_element.h"
77 #include "third_party/blink/public/web/web_local_frame.h"
78 #include "third_party/blink/public/web/web_node.h"
79 #include "third_party/blink/public/web/web_view.h"
80 #include "ui/base/page_transition_types.h"
81 #include "ui/events/keycodes/keyboard_codes.h"
84 using blink::WebAutofillState;
85 using blink::WebDocument;
86 using blink::WebElement;
87 using blink::WebElementCollection;
88 using blink::WebFormControlElement;
89 using blink::WebFormElement;
90 using blink::WebFrame;
91 using blink::WebInputElement;
92 using blink::WebLocalFrame;
94 using blink::WebString;
95 using blink::WebVector;
97 #if BUILDFLAG(IS_TIZEN_TV)
98 using blink::WebString;
101 using password_manager::util::IsRendererRecognizedCredentialForm;
105 using form_util::ExtractOption;
106 using form_util::FindFormByRendererId;
107 using form_util::FindFormControlByRendererId;
108 using form_util::FindFormControlsByRendererId;
109 using form_util::GetFieldRendererId;
110 using form_util::GetFormRendererId;
111 using form_util::IsElementEditable;
112 using form_util::IsWebElementFocusableForAutofill;
114 using mojom::SubmissionIndicatorEvent;
115 using mojom::SubmissionSource;
119 // The size above which we stop triggering autocomplete.
120 const size_t kMaximumTextSizeForAutocomplete = 1000;
122 // Names of HTML attributes to show form and field signatures for debugging.
123 const char kDebugAttributeForFormSignature[] = "form_signature";
124 const char kDebugAttributeForAlternativeFormSignature[] =
125 "alternative_form_signature";
126 const char kDebugAttributeForFieldSignature[] = "field_signature";
127 const char kDebugAttributeForParserAnnotations[] = "pm_parser_annotation";
128 const char kDebugAttributeForVisibility[] = "visibility_annotation";
129 // Name of HTML attribute that stores the copy of autofill tooltip for
131 constexpr char kDebugAttributeForAutofill[] = "autofill-information";
133 // HTML attribute that is used as a tooltip if
134 // |kAutofillShowTypePredictions| is on.
135 constexpr char kHtmlAttributeForAutofillTooltip[] = "title";
137 #if BUILDFLAG(IS_TIZEN_TV)
138 // The words that frequently appear in attribute values of captcha elements.
139 const char* const kCaptchaFeatures[] = {"captcha", "security", "code"};
140 constexpr size_t kNumberOfCaptchaFeatures = std::size(kCaptchaFeatures);
141 #define kSendEnterKeyTimeout 200
143 // Maps element names to the actual elements to simplify form filling.
144 typedef std::map<std::u16string, WebInputElement> FormInputElementMap;
146 // Use the shorter name when referencing SavePasswordProgressLogger::StringID
147 // values to spare line breaks. The code provides enough context for that
149 typedef SavePasswordProgressLogger Logger;
151 typedef std::vector<FormInputElementMap> FormElementsList;
153 bool DoUsernamesMatch(const std::u16string& potential_suggestion,
154 const std::u16string& current_username,
156 if (potential_suggestion == current_username)
158 return !exact_match && IsPrefixOfEmailEndingWithAtSign(current_username,
159 potential_suggestion);
162 // Returns whether the |username_element| is allowed to be autofilled.
164 // Note that if the user interacts with the |password_field| and the
165 // |username_element| is user-defined (i.e., non-empty and non-autofilled), then
166 // this function returns false. This is a precaution, to not override the field
167 // if it has been classified as username by accident.
168 bool IsUsernameAmendable(const WebInputElement& username_element,
169 bool is_password_field_selected) {
170 return !username_element.IsNull() && IsElementEditable(username_element) &&
171 (!is_password_field_selected || username_element.IsAutofilled() ||
172 username_element.IsPreviewed() || username_element.Value().IsEmpty());
175 // Log `message` if `logger` is not null.
176 void LogMessage(Logger* logger, Logger::StringID message) {
178 logger->LogMessage(message);
181 // Log `message` and `value` if `logger` is not null.
182 void LogBoolean(Logger* logger, Logger::StringID message, bool value) {
184 logger->LogBoolean(message, value);
187 // Log a message including the name, method and action of |form|.
188 void LogHTMLForm(Logger* logger,
189 Logger::StringID message_id,
190 const WebFormElement& form) {
192 logger->LogHTMLForm(message_id, form.GetName().Utf8(),
193 GURL(form.Action().Utf8()));
197 // Returns true if there are any suggestions to be derived from |fill_data|.
198 // Only considers suggestions with usernames having |typed_username| as prefix.
199 bool CanShowUsernameSuggestion(const PasswordFormFillData& fill_data,
200 const std::u16string& typed_username) {
201 std::u16string typed_username_lower = base::i18n::ToLower(typed_username);
202 if (base::StartsWith(
203 base::i18n::ToLower(fill_data.preferred_login.username_value),
204 typed_username_lower, base::CompareCase::SENSITIVE)) {
208 for (const auto& login : fill_data.additional_logins) {
209 if (base::StartsWith(base::i18n::ToLower(login.username_value),
210 typed_username_lower, base::CompareCase::SENSITIVE)) {
218 // This function attempts to find the matching credentials for the
219 // |current_username| by scanning |fill_data|. The result is written in
220 // |username| and |password| parameters.
221 void FindMatchesByUsername(const PasswordFormFillData& fill_data,
222 const std::u16string& current_username,
223 bool exact_username_match,
224 RendererSavePasswordProgressLogger* logger,
225 std::u16string* username,
226 std::u16string* password) {
227 // Look for any suitable matches to current field text.
228 if (DoUsernamesMatch(fill_data.preferred_login.username_value,
229 current_username, exact_username_match)) {
230 *username = fill_data.preferred_login.username_value;
231 *password = fill_data.preferred_login.password_value;
232 LogMessage(logger, Logger::STRING_USERNAMES_MATCH);
234 // Scan additional logins for a match.
235 for (const auto& it : fill_data.additional_logins) {
236 if (!it.realm.empty()) {
237 // Non-empty realm means PSL match. Do not autofill PSL matched
238 // credentials. The reason for this is that PSL matched sites are
239 // different sites, so a password for a PSL matched site should be never
240 // filled without explicit user selection.
243 if (DoUsernamesMatch(it.username_value, current_username,
244 exact_username_match)) {
245 *username = it.username_value;
246 *password = it.password_value;
250 LogBoolean(logger, Logger::STRING_MATCH_IN_ADDITIONAL,
251 !(username->empty() && password->empty()));
255 // TODO(crbug.com/564578): This duplicates code from
256 // components/password_manager/core/browser/psl_matching_helper.h. The logic
257 // using this code should ultimately end up in
258 // components/password_manager/core/browser, at which point it can use the
259 // original code directly.
260 std::string GetRegistryControlledDomain(const GURL& signon_realm) {
261 return net::registry_controlled_domains::GetDomainAndRegistry(
263 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
266 // TODO(crbug.com/564578): This duplicates code from
267 // components/password_manager/core/browser/psl_matching_helper.h. The logic
268 // using this code should ultimately end up in
269 // components/password_manager/core/browser, at which point it can use the
270 // original code directly.
271 bool IsPublicSuffixDomainMatch(const std::string& url1,
272 const std::string& url2) {
276 if (!gurl1.is_valid() || !gurl2.is_valid())
282 std::string domain1(GetRegistryControlledDomain(gurl1));
283 std::string domain2(GetRegistryControlledDomain(gurl2));
285 if (domain1.empty() || domain2.empty())
288 return gurl1.scheme() == gurl2.scheme() && domain1 == domain2 &&
289 gurl1.port() == gurl2.port();
292 // Helper function that calculates form signature for |form_data| and returns it
294 std::string GetFormSignatureAsString(const FormData& form_data) {
295 return base::NumberToString(CalculateFormSignature(form_data).value());
297 // Similar to `GetFormSignatureAsString` but returns alternative form signature
299 std::string GetAlternativeFormSignatureAsString(const FormData& form_data) {
300 return base::NumberToString(
301 CalculateAlternativeFormSignature(form_data).value());
304 // Sets the specified attribute of |target| to the given value. This must not
305 // happen while ScriptForbiddenScope is active (e.g. during
306 // blink::FrameLoader::FinishedParsing(), see crbug.com/1219852). Therefore,
307 // this function should be called asynchronously via SetAttributeAsync.
308 void SetAttributeInternal(blink::WebElement target,
309 const std::string& attribute_utf8,
310 const std::string& value_utf8) {
311 target.SetAttribute(WebString::FromUTF8(attribute_utf8),
312 WebString::FromUTF8(value_utf8));
315 // Posts an async task to call SetAttributeInternal.
316 void SetAttributeAsync(blink::WebElement target,
317 const std::string& attribute_utf8,
318 const std::string& value_utf8) {
323 ->GetTaskRunner(blink::TaskType::kInternalDefault)
324 ->PostTask(FROM_HERE, base::BindOnce(&SetAttributeInternal, target,
325 attribute_utf8, value_utf8));
328 // Annotate |fields| with field signatures, form signature and visibility state
329 // as HTML attributes.
330 void AnnotateFieldsWithSignatures(
331 std::vector<blink::WebFormControlElement>& fields,
332 const std::string& form_signature,
333 const std::string& alternative_form_signature) {
334 for (blink::WebFormControlElement& control_element : fields) {
335 FieldSignature field_signature = CalculateFieldSignatureByNameAndType(
336 control_element.NameForAutofill().Utf16(),
337 form_util::ToAutofillFormControlType(
338 control_element.FormControlTypeForAutofill()));
339 SetAttributeAsync(control_element, kDebugAttributeForFieldSignature,
340 base::NumberToString(field_signature.value()));
341 SetAttributeAsync(control_element, kDebugAttributeForFormSignature,
343 SetAttributeAsync(control_element,
344 kDebugAttributeForAlternativeFormSignature,
345 alternative_form_signature);
347 control_element, kDebugAttributeForVisibility,
348 IsWebElementFocusableForAutofill(control_element) ? "true" : "false");
352 // Returns true iff there is a password field in |frame|.
353 // We don't have to iterate through the whole DOM to find password fields.
354 // Instead, we can iterate through the fields of the forms and the unowned
355 // fields, both of which are cached in the Document.
356 bool HasPasswordField(const WebLocalFrame& frame) {
357 auto ContainsPasswordField = [&](const auto& fields) {
358 return base::Contains(fields, blink::mojom::FormControlType::kInputPassword,
359 &WebFormControlElement::FormControlTypeForAutofill);
362 WebDocument doc = frame.GetDocument();
363 return base::ranges::any_of(doc.Forms(), ContainsPasswordField,
364 &WebFormElement::GetFormControlElements) ||
365 ContainsPasswordField(doc.UnassociatedFormControls());
368 // Returns the closest visible autocompletable non-password text element
369 // preceding the |password_element| either in a form, if it belongs to one, or
371 WebInputElement FindUsernameElementPrecedingPasswordElement(
372 WebLocalFrame* frame,
373 const WebInputElement& password_element) {
374 DCHECK(!password_element.IsNull());
376 std::vector<WebFormControlElement> elements;
377 if (password_element.Form().IsNull()) {
378 elements = form_util::GetUnownedAutofillableFormFieldElements(
379 frame->GetDocument());
381 elements = password_element.Form().GetFormControlElements().ReleaseVector();
384 auto iter = base::ranges::find(elements, password_element);
385 if (iter == elements.end())
386 return WebInputElement();
388 for (auto begin = elements.begin(); iter != begin;) {
390 const WebInputElement input = iter->DynamicTo<WebInputElement>();
391 if (!input.IsNull() && input.IsTextField() &&
392 !input.IsPasswordFieldForAutofill() && IsElementEditable(input) &&
393 IsWebElementFocusableForAutofill(input)) {
398 return WebInputElement();
401 // Returns true if |element|'s frame origin is not PSL matched with the origin
402 // of any parent frame.
403 bool IsInCrossOriginIframeOrEmbeddedFrame(const WebInputElement& element) {
404 WebFrame* cur_frame = element.GetDocument().GetFrame();
405 WebString bottom_frame_origin = cur_frame->GetSecurityOrigin().ToString();
409 while (cur_frame->Parent()) {
410 cur_frame = cur_frame->Parent();
411 if (!IsPublicSuffixDomainMatch(
412 bottom_frame_origin.Utf8(),
413 cur_frame->GetSecurityOrigin().ToString().Utf8())) {
417 // In MPArch, if we haven't reached the primary main frame, it means
418 // we are in a nested frame tree. Fenced Frames are always considered
419 // cross origin so we should return true here. Adding NOTREACHED for now
420 // for future nested inner frame trees.
421 if (!cur_frame->IsOutermostMainFrame()) {
422 if (element.GetDocument().GetFrame()->IsInFencedFrameTree()) {
431 void AnnotateFieldWithParsingResult(
433 FieldRendererId renderer_id,
434 const std::string& password_managers_annotation) {
435 if (renderer_id.is_null())
437 auto element = FindFormControlByRendererId(doc, renderer_id);
438 if (element.IsNull())
440 // Calling SetAttribute synchronously here is safe because
441 // AnnotateFieldWithParsingResult is triggered via a call from the the
442 // browser. This means that we should not be in a ScriptForbiddenScope.
443 element.SetAttribute(
444 WebString::FromASCII(kDebugAttributeForParserAnnotations),
445 WebString::FromASCII(password_managers_annotation));
447 if (!base::FeatureList::IsEnabled(
448 features::test::kAutofillShowTypePredictions)) {
452 if (!element.HasAttribute(kDebugAttributeForAutofill)) {
453 // No autofill tooltip yet, don't fill anything.
457 std::string autofill_tooltip =
458 element.GetAttribute(kDebugAttributeForAutofill).Utf8();
460 element.SetAttribute(
461 kHtmlAttributeForAutofillTooltip,
463 base::StrCat({element.GetAttribute(kDebugAttributeForAutofill).Utf8(),
464 "\n", kDebugAttributeForParserAnnotations, ": ",
465 password_managers_annotation})));
468 bool HasDocumentWithValidFrame(const WebInputElement& element) {
469 WebFrame* frame = element.GetDocument().GetFrame();
470 return frame && frame->View();
473 // This method tries to fix `fields` with empty typed or filled properties by
474 // matching them against previously filled or typed in fields with the same
475 // value and copying their filled or typed mask.
477 // This helps against websites where submitted fields differ from fields that
478 // had previously been autofilled or typed into.
479 void FillNonTypedOrFilledPropertiesMasks(std::vector<FormFieldData>* fields,
480 const FieldDataManager& manager) {
481 static constexpr FieldPropertiesMask kFilledOrTyped =
482 FieldPropertiesFlags::kAutofilled | FieldPropertiesFlags::kUserTyped;
484 for (auto& field : *fields) {
485 if (field.properties_mask & kFilledOrTyped)
488 for (const auto& [field_id, field_data] : manager.field_data_map()) {
489 const absl::optional<std::u16string>& value = field_data.first;
490 FieldPropertiesMask properties = field_data.second;
491 if ((properties & kFilledOrTyped) && value == field.value) {
492 field.properties_mask |= properties & kFilledOrTyped;
499 size_t GetIndexOfElement(const FormData& form_data,
500 const WebInputElement& element) {
501 if (element.IsNull()) {
502 return form_data.fields.size();
504 for (size_t i = 0; i < form_data.fields.size(); ++i) {
505 if (form_data.fields[i].unique_renderer_id ==
506 form_util::GetFieldRendererId(element)) {
510 return form_data.fields.size();
513 #if BUILDFLAG(IS_ANDROID)
514 // Returns a prediction whether the form that contains |username_element| and
515 // |password_element| will be ready for submission after filling these two
517 // TODO(crbug/1393271): Consider to reduce |SubmissionReadinessState| to a
518 // boolean value (ready or not). The non-binary state is not needed for
519 // auto-submission (crbug.com/1283004), but showing TTF proactively
520 // (crbug.com/1393043) may need to check whether or not a given form comprises
522 mojom::SubmissionReadinessState CalculateSubmissionReadiness(
523 const FormData& form_data,
524 WebInputElement& username_element,
525 WebInputElement& password_element) {
526 if (password_element.IsNull()) {
527 return mojom::SubmissionReadinessState::kNoPasswordField;
530 if (username_element.IsNull())
531 return mojom::SubmissionReadinessState::kNoUsernameField;
533 size_t username_index = GetIndexOfElement(form_data, username_element);
534 size_t password_index = GetIndexOfElement(form_data, password_element);
535 size_t number_of_elements = form_data.fields.size();
536 if (username_index == number_of_elements ||
537 password_index == number_of_elements) {
538 // This is unexpected. |form_data| is supposed to contain username and
539 // password elements.
540 return mojom::SubmissionReadinessState::kError;
543 auto ShouldIgnoreField = [](const FormFieldData& field) {
544 if (!field.IsFocusable())
546 // Don't treat a checkbox (e.g. "remember me") as an input field that may
547 // block a form submission. Note: Don't use |check_status !=
548 // kNotCheckable|, a radio button is considered a "checkable" element too,
549 // but it should block a submission.
550 return field.form_control_type == mojom::FormControlType::kInputCheckbox;
553 for (size_t i = username_index + 1; i < password_index; ++i) {
554 if (ShouldIgnoreField(form_data.fields[i]))
556 return mojom::SubmissionReadinessState::kFieldBetweenUsernameAndPassword;
559 if (!password_element.IsLastInputElementInForm())
560 return mojom::SubmissionReadinessState::kFieldAfterPasswordField;
562 size_t number_of_visible_elements = 0;
563 for (size_t i = 0; i < number_of_elements; ++i) {
564 if (ShouldIgnoreField(form_data.fields[i]))
567 if (username_index != i && password_index != i &&
568 form_data.fields[i].value.empty()) {
569 return mojom::SubmissionReadinessState::kEmptyFields;
571 number_of_visible_elements++;
574 if (number_of_visible_elements > 2)
575 return mojom::SubmissionReadinessState::kMoreThanTwoFields;
577 return mojom::SubmissionReadinessState::kTwoFields;
579 #endif // BUILDFLAG(IS_ANDROID)
583 // During prerendering, we do not want the renderer to send messages to the
584 // corresponding driver. Since we use a channel associated interface, we still
585 // need to set up the mojo connection as before (i.e., we can't defer binding
586 // the interface). Instead, we enqueue our messages here as post-activation
587 // tasks. See post-prerendering activation steps here:
588 // https://wicg.github.io/nav-speculation/prerendering.html#prerendering-bcs-subsection
589 class PasswordAutofillAgent::DeferringPasswordManagerDriver
590 : public mojom::PasswordManagerDriver {
592 explicit DeferringPasswordManagerDriver(PasswordAutofillAgent* agent)
594 ~DeferringPasswordManagerDriver() override = default;
597 template <typename F, typename... Args>
598 void SendMsg(F fn, Args&&... args) {
599 DCHECK(!agent_->IsPrerendering());
600 mojom::PasswordManagerDriver& password_manager_driver =
601 agent_->GetPasswordManagerDriver();
602 DCHECK_NE(&password_manager_driver, this);
603 (password_manager_driver.*fn)(std::forward<Args>(args)...);
605 template <typename F, typename... Args>
606 void DeferMsg(F fn, Args... args) {
607 DCHECK(agent_->IsPrerendering());
608 agent_->render_frame()
611 .AddPostPrerenderingActivationStep(base::BindOnce(
612 &DeferringPasswordManagerDriver::SendMsg<F, Args...>,
613 weak_ptr_factory_.GetWeakPtr(), fn, std::forward<Args>(args)...));
615 void PasswordFormsParsed(const std::vector<FormData>& forms_data) override {
616 DeferMsg(&mojom::PasswordManagerDriver::PasswordFormsParsed, forms_data);
618 void PasswordFormsRendered(
619 const std::vector<FormData>& visible_forms_data) override {
620 DeferMsg(&mojom::PasswordManagerDriver::PasswordFormsRendered,
623 void PasswordFormSubmitted(const FormData& form_data) override {
624 DeferMsg(&mojom::PasswordManagerDriver::PasswordFormSubmitted, form_data);
626 void InformAboutUserInput(const FormData& form_data) override {
627 DeferMsg(&mojom::PasswordManagerDriver::InformAboutUserInput, form_data);
629 void DynamicFormSubmission(
630 mojom::SubmissionIndicatorEvent submission_indication_event) override {
631 DeferMsg(&mojom::PasswordManagerDriver::DynamicFormSubmission,
632 submission_indication_event);
634 void PasswordFormCleared(const FormData& form_data) override {
635 DeferMsg(&mojom::PasswordManagerDriver::PasswordFormCleared, form_data);
637 void RecordSavePasswordProgress(const std::string& log) override {
638 DeferMsg(&mojom::PasswordManagerDriver::RecordSavePasswordProgress, log);
640 void UserModifiedPasswordField() override {
641 DeferMsg(&mojom::PasswordManagerDriver::UserModifiedPasswordField);
643 void UserModifiedNonPasswordField(FieldRendererId renderer_id,
644 const std::u16string& value,
645 bool autocomplete_attribute_has_username,
646 bool is_likely_otp) override {
647 DeferMsg(&mojom::PasswordManagerDriver::UserModifiedNonPasswordField,
648 renderer_id, value, autocomplete_attribute_has_username,
651 void ShowPasswordSuggestions(FieldRendererId element_id,
652 const FormData& form,
653 uint64_t username_field_index,
654 uint64_t password_field_index,
655 ::base::i18n::TextDirection text_direction,
656 const std::u16string& typed_username,
658 const gfx::RectF& bounds) override {
659 DeferMsg(&mojom::PasswordManagerDriver::ShowPasswordSuggestions, element_id,
660 form, username_field_index, password_field_index, text_direction,
661 typed_username, options, bounds);
663 #if BUILDFLAG(IS_ANDROID)
664 void ShowKeyboardReplacingSurface(
665 mojom::SubmissionReadinessState submission_readiness,
666 bool is_webauthn_form) override {
667 DeferMsg(&mojom::PasswordManagerDriver::ShowKeyboardReplacingSurface,
668 submission_readiness, is_webauthn_form);
671 void CheckSafeBrowsingReputation(const GURL& form_action,
672 const GURL& frame_url) override {
673 DeferMsg(&mojom::PasswordManagerDriver::CheckSafeBrowsingReputation,
674 form_action, frame_url);
676 void FocusedInputChanged(
677 FieldRendererId focused_field_id,
678 mojom::FocusedFieldType focused_field_type) override {
679 DeferMsg(&mojom::PasswordManagerDriver::FocusedInputChanged,
680 focused_field_id, focused_field_type);
682 void LogFirstFillingResult(FormRendererId form_renderer_id,
683 int32_t result) override {
684 DeferMsg(&mojom::PasswordManagerDriver::LogFirstFillingResult,
685 form_renderer_id, result);
688 raw_ptr<PasswordAutofillAgent, ExperimentalRenderer> agent_ = nullptr;
689 base::WeakPtrFactory<DeferringPasswordManagerDriver> weak_ptr_factory_{this};
692 ////////////////////////////////////////////////////////////////////////////////
693 // PasswordAutofillAgent, public:
695 PasswordAutofillAgent::PasswordAutofillAgent(
696 content::RenderFrame* render_frame,
697 blink::AssociatedInterfaceRegistry* registry)
698 : content::RenderFrameObserver(render_frame),
699 last_supplied_password_info_iter_(web_input_to_password_info_.end()),
700 field_data_manager_(base::MakeRefCounted<FieldDataManager>()),
701 logging_state_active_(false),
702 username_autofill_state_(WebAutofillState::kNotFilled),
703 password_autofill_state_(WebAutofillState::kNotFilled),
704 sent_request_to_store_(false),
705 checked_safe_browsing_reputation_(false),
706 password_generation_agent_(nullptr) {
707 registry->AddInterface<mojom::PasswordAutofillAgent>(base::BindRepeating(
708 &PasswordAutofillAgent::BindPendingReceiver, base::Unretained(this)));
711 PasswordAutofillAgent::~PasswordAutofillAgent() = default;
713 void PasswordAutofillAgent::Init(AutofillAgent* autofill_agent) {
714 autofill_agent_ = autofill_agent;
717 void PasswordAutofillAgent::BindPendingReceiver(
718 mojo::PendingAssociatedReceiver<mojom::PasswordAutofillAgent>
720 receiver_.Bind(std::move(pending_receiver));
723 void PasswordAutofillAgent::SetPasswordGenerationAgent(
724 PasswordGenerationAgent* generation_agent) {
725 password_generation_agent_ = generation_agent;
728 PasswordAutofillAgent::FormStructureInfo::FormStructureInfo() = default;
730 PasswordAutofillAgent::FormStructureInfo::FormStructureInfo(
731 const FormStructureInfo& other) = default;
733 PasswordAutofillAgent::FormStructureInfo&
734 PasswordAutofillAgent::FormStructureInfo::operator=(
735 const PasswordAutofillAgent::FormStructureInfo& other) = default;
737 PasswordAutofillAgent::FormStructureInfo::FormStructureInfo(
738 FormStructureInfo&& other) = default;
740 PasswordAutofillAgent::FormStructureInfo&
741 PasswordAutofillAgent::FormStructureInfo::operator=(
742 PasswordAutofillAgent::FormStructureInfo&& other) = default;
744 PasswordAutofillAgent::FormStructureInfo::~FormStructureInfo() = default;
746 PasswordAutofillAgent::PasswordValueGatekeeper::PasswordValueGatekeeper()
747 : was_user_gesture_seen_(false) {}
749 PasswordAutofillAgent::PasswordValueGatekeeper::~PasswordValueGatekeeper() =
752 void PasswordAutofillAgent::PasswordValueGatekeeper::RegisterElement(
753 WebInputElement* element) {
754 if (was_user_gesture_seen_)
757 elements_.push_back(*element);
760 void PasswordAutofillAgent::PasswordValueGatekeeper::OnUserGesture() {
761 if (was_user_gesture_seen_)
764 was_user_gesture_seen_ = true;
766 for (WebInputElement& element : elements_)
772 void PasswordAutofillAgent::PasswordValueGatekeeper::Reset() {
773 was_user_gesture_seen_ = false;
777 void PasswordAutofillAgent::PasswordValueGatekeeper::ShowValue(
778 WebInputElement* element) {
779 if (!element->IsNull() && !element->SuggestedValue().IsEmpty())
780 element->SetAutofillValue(element->SuggestedValue());
783 bool PasswordAutofillAgent::TextDidChangeInTextField(
784 const WebInputElement& element) {
785 auto iter = web_input_to_password_info_.find(element);
786 if (iter != web_input_to_password_info_.end()) {
787 iter->second.password_was_edited_last = false;
790 // Show the popup with the list of available usernames.
791 return ShowSuggestions(element, ShowAll(false));
794 void PasswordAutofillAgent::UpdateStateForTextChange(
795 const WebInputElement& element) {
796 if (!element.IsTextField())
798 // TODO(crbug.com/415449): Do this through const WebInputElement.
799 WebInputElement mutable_element = element; // We need a non-const.
801 const std::u16string element_value = element.Value().Utf16();
802 field_data_manager_->UpdateFieldDataMap(
803 form_util::GetFieldRendererId(element), element_value,
804 FieldPropertiesFlags::kUserTyped);
806 InformBrowserAboutUserInput(element.Form(), element);
808 if (element.IsPasswordFieldForAutofill()) {
809 auto iter = password_to_username_.find(element);
810 if (iter != password_to_username_.end()) {
811 web_input_to_password_info_[iter->second].password_was_edited_last = true;
812 // Note that the suggested value of |mutable_element| was reset when its
814 mutable_element.SetAutofillState(WebAutofillState::kNotFilled);
816 GetPasswordManagerDriver().UserModifiedPasswordField();
820 // Notify PasswordManager about potential username fields for UFF.
821 // Do not consider fields that have no names or ids to avoid aggregation
822 // of multiple unrelated fields. (crbug.com/1209143)
823 if (element.NameForAutofill().IsEmpty()) {
827 // Exclude 1-symbol inputs, as they are unlikely to be usernames and likely
828 // to be characters/digits of OTPs.
829 // Exclude too large inputs, as they are usually not usernames.
830 if (element_value.size() == 1 || element_value.size() > 100) {
834 static base::NoDestructor<WebString> kAutocomplete("autocomplete");
835 std::string autocomplete_attribute =
836 element.GetAttribute(*kAutocomplete).Utf8();
837 static base::NoDestructor<WebString> kName("name");
838 std::u16string name_attribute = element.GetAttribute(*kName).Utf16();
839 std::u16string id_attribute = element.GetIdAttribute().Utf16();
842 autofill::MatchesRegex<password_manager::constants::kOneTimePwdRe>(
844 autofill::MatchesRegex<password_manager::constants::kOneTimePwdRe>(
846 base::Contains(autocomplete_attribute,
847 password_manager::constants::kAutocompleteOneTimePassword);
849 GetPasswordManagerDriver().UserModifiedNonPasswordField(
850 GetFieldRendererId(element), element_value,
851 base::Contains(autocomplete_attribute,
852 password_manager::constants::kAutocompleteUsername),
856 void PasswordAutofillAgent::TrackAutofilledElement(
857 const blink::WebFormControlElement& element) {
858 autofill_agent_->TrackAutofilledElement(element);
861 void PasswordAutofillAgent::FillPasswordSuggestion(
862 const std::u16string& username,
863 const std::u16string& password) {
864 auto element = focused_element().DynamicTo<WebInputElement>();
865 if (element.IsNull() || focused_element().IsReadOnly()) {
869 WebInputElement username_element;
870 WebInputElement password_element;
871 PasswordInfo* password_info = nullptr;
873 if (!FindPasswordInfoForElement(element, UseFallbackData(true),
874 &username_element, &password_element,
876 (!password_element.IsNull() && !IsElementEditable(password_element))) {
880 password_info->password_was_edited_last = false;
881 if (element.IsPasswordFieldForAutofill()) {
882 password_info->password_field_suggestion_was_accepted = true;
883 password_info->password_field = password_element;
886 // Call OnFieldAutofilled before WebInputElement::SetAutofillState which may
887 // cause frame closing.
888 if (!password_element.IsNull() && password_generation_agent_)
889 password_generation_agent_->OnFieldAutofilled(password_element);
891 if (IsUsernameAmendable(username_element,
892 element.IsPasswordFieldForAutofill()) &&
893 !(username.empty() && element.IsPasswordFieldForAutofill()) &&
894 username_element.Value().Utf16() != username) {
895 FillField(&username_element, username);
898 if (!password_element.IsNull()) {
899 FillPasswordFieldAndSave(&password_element, password);
901 // TODO(crbug.com/1319364): As Touch-To-Fill and auto-submission don't
902 // currently support filling single username fields, the code below is
903 // within |!password_element.IsNull()|. Support such fields too and move the
904 // code out the condition.
905 // If the |username_element| is visible/focusable and the |password_element|
906 // is not, trigger submission on the former as the latter unlikely has an
908 if (!username_element.IsNull() &&
909 IsWebElementFocusableForAutofill(username_element) &&
910 !IsWebElementFocusableForAutofill(password_element)) {
911 field_renderer_id_to_submit_ = GetFieldRendererId(username_element);
913 field_renderer_id_to_submit_ = GetFieldRendererId(password_element);
917 auto length = base::checked_cast<unsigned>(element.Value().length());
918 element.SetSelectionRange(length, length);
921 void PasswordAutofillAgent::FillIntoFocusedField(
923 const std::u16string& credential) {
924 auto focused_input_element = focused_element().DynamicTo<WebInputElement>();
925 if (focused_input_element.IsNull() || focused_input_element.IsReadOnly()) {
929 FillField(&focused_input_element, credential);
931 if (!focused_input_element.IsPasswordFieldForAutofill()) {
934 FillPasswordFieldAndSave(&focused_input_element, credential);
937 void PasswordAutofillAgent::FillField(WebInputElement* input,
938 const std::u16string& credential) {
940 DCHECK(!input->IsNull());
941 input->SetAutofillValue(WebString::FromUTF16(credential));
942 field_data_manager_->UpdateFieldDataMap(
943 form_util::GetFieldRendererId(*input), credential,
944 FieldPropertiesFlags::kAutofilledOnUserTrigger);
945 TrackAutofilledElement(*input);
948 void PasswordAutofillAgent::FillPasswordFieldAndSave(
949 WebInputElement* password_input,
950 const std::u16string& credential) {
951 DCHECK(password_input);
952 DCHECK(password_input->IsPasswordFieldForAutofill());
953 FillField(password_input, credential);
954 InformBrowserAboutUserInput(password_input->Form(), *password_input);
957 bool PasswordAutofillAgent::PreviewSuggestion(
958 const WebFormControlElement& control_element,
959 const WebString& username,
960 const WebString& password) {
961 // The element in context of the suggestion popup.
962 const WebInputElement element = control_element.DynamicTo<WebInputElement>();
963 if (element.IsNull())
966 WebInputElement username_element;
967 WebInputElement password_element;
968 PasswordInfo* password_info;
970 if (!FindPasswordInfoForElement(element, UseFallbackData(true),
971 &username_element, &password_element,
973 (!password_element.IsNull() && !IsElementEditable(password_element))) {
977 if (IsUsernameAmendable(username_element,
978 element.IsPasswordFieldForAutofill())) {
979 if (username_query_prefix_.empty())
980 username_query_prefix_ = username_element.Value().Utf16();
982 username_autofill_state_ = username_element.GetAutofillState();
983 username_element.SetSuggestedValue(username);
984 form_util::PreviewSuggestion(username_element.SuggestedValue().Utf16(),
985 username_query_prefix_, &username_element);
987 if (!password_element.IsNull()) {
988 password_autofill_state_ = password_element.GetAutofillState();
989 password_element.SetSuggestedValue(password);
995 bool PasswordAutofillAgent::DidClearAutofillSelection(
996 const WebFormControlElement& control_element) {
997 const WebInputElement element = control_element.DynamicTo<WebInputElement>();
998 if (element.IsNull())
1001 WebInputElement username_element;
1002 WebInputElement password_element;
1003 PasswordInfo* password_info;
1005 if (!FindPasswordInfoForElement(element, UseFallbackData(true),
1006 &username_element, &password_element,
1011 ClearPreview(&username_element, &password_element);
1015 bool PasswordAutofillAgent::FindPasswordInfoForElement(
1016 const WebInputElement& element,
1017 UseFallbackData use_fallback_data,
1018 WebInputElement* username_element,
1019 WebInputElement* password_element,
1020 PasswordInfo** password_info) {
1021 DCHECK(username_element && password_element && password_info);
1022 username_element->Reset();
1023 password_element->Reset();
1024 if (!element.IsPasswordFieldForAutofill()) {
1025 *username_element = element;
1027 *password_element = element;
1029 // If there is a password field, but a request to the store hasn't been sent
1030 // yet, then do fetch saved credentials now.
1031 if (!sent_request_to_store_) {
1032 SendPasswordForms(false);
1036 auto iter = web_input_to_password_info_.find(element);
1037 if (iter == web_input_to_password_info_.end()) {
1038 PasswordToLoginMap::const_iterator password_iter =
1039 password_to_username_.find(element);
1040 if (password_iter == password_to_username_.end()) {
1041 if (!use_fallback_data || web_input_to_password_info_.empty())
1043 iter = last_supplied_password_info_iter_;
1045 *username_element = password_iter->second;
1049 if (iter != web_input_to_password_info_.end()) {
1050 // It's a password field without corresponding username field. Try to find
1051 // the username field based on visibility.
1052 *username_element = FindUsernameElementPrecedingPasswordElement(
1053 render_frame()->GetWebFrame(), *password_element);
1054 *password_info = &iter->second;
1057 // Otherwise |username_element| has been set above.
1060 auto iter = web_input_to_password_info_.find(*username_element);
1061 if (iter == web_input_to_password_info_.end())
1064 *password_info = &iter->second;
1065 if (password_element->IsNull())
1066 *password_element = (*password_info)->password_field;
1071 void PasswordAutofillAgent::MaybeCheckSafeBrowsingReputation(
1072 const WebInputElement& element) {
1073 // Enabled on desktop and Android
1074 #if BUILDFLAG(FULL_SAFE_BROWSING) || BUILDFLAG(SAFE_BROWSING_DB_REMOTE)
1075 // Note: A site may use a Password field to collect a CVV or a Credit Card
1076 // number, but showing a slightly misleading warning here is better than
1077 // showing no warning at all.
1078 if (!element.IsPasswordFieldForAutofill())
1080 if (checked_safe_browsing_reputation_)
1083 checked_safe_browsing_reputation_ = true;
1084 WebLocalFrame* frame = render_frame()->GetWebFrame();
1085 GURL frame_url = GURL(frame->GetDocument().Url());
1086 GURL action_url = element.Form().IsNull()
1088 : form_util::GetCanonicalActionForForm(element.Form());
1089 GetPasswordManagerDriver().CheckSafeBrowsingReputation(action_url, frame_url);
1093 #if BUILDFLAG(IS_ANDROID)
1094 bool PasswordAutofillAgent::ShouldSuppressKeyboard() {
1095 // The keyboard should be suppressed if a keyboard replacing surface is
1096 // displayed (e.g. TouchToFill).
1097 return keyboard_replacing_surface_state_ ==
1098 KeyboardReplacingSurfaceState::kIsShowing;
1101 bool PasswordAutofillAgent::TryToShowKeyboardReplacingSurface(
1102 const WebFormControlElement& control_element) {
1103 if (keyboard_replacing_surface_state_ !=
1104 KeyboardReplacingSurfaceState::kShouldShow) {
1108 const WebInputElement input_element =
1109 control_element.DynamicTo<WebInputElement>();
1110 WebInputElement username_element;
1111 WebInputElement password_element;
1112 PasswordInfo* password_info = nullptr;
1113 if (input_element.IsNull() || !IsElementEditable(input_element) ||
1114 !FindPasswordInfoForElement(input_element, UseFallbackData(false),
1115 &username_element, &password_element,
1120 bool has_amendable_username_element = IsUsernameAmendable(
1121 username_element, input_element.IsPasswordFieldForAutofill());
1122 bool has_editable_password_element =
1123 !password_element.IsNull() && IsElementEditable(password_element);
1124 CHECK(has_amendable_username_element || has_editable_password_element);
1126 WebFormElement form = !password_element.IsNull() ? password_element.Form()
1127 : username_element.Form();
1128 std::unique_ptr<FormData> form_data =
1129 form.IsNull() ? GetFormDataFromUnownedInputElements()
1130 : GetFormDataFromWebForm(form);
1131 // TODO(crbug.com/1465793): Use FormFieldData::parsed_autocomplete.
1132 auto has_webauthn_attribute = [](const FormFieldData& field) {
1133 return field.autocomplete_attribute.find(
1134 password_manager::constants::kAutocompleteWebAuthn) !=
1137 bool is_webauthn_form =
1139 base::ranges::any_of(form_data->fields, has_webauthn_attribute);
1140 GetPasswordManagerDriver().ShowKeyboardReplacingSurface(
1141 form_data ? CalculateSubmissionReadiness(*form_data, username_element,
1143 : mojom::SubmissionReadinessState::kNoInformation,
1146 keyboard_replacing_surface_state_ = KeyboardReplacingSurfaceState::kIsShowing;
1151 bool PasswordAutofillAgent::ShowSuggestions(const WebInputElement& element,
1153 WebInputElement username_element;
1154 WebInputElement password_element;
1155 PasswordInfo* password_info = nullptr;
1156 FindPasswordInfoForElement(element, UseFallbackData(true), &username_element,
1157 &password_element, &password_info);
1159 if (!password_info) {
1160 MaybeCheckSafeBrowsingReputation(element);
1161 if (!CanShowPopupWithoutPasswords(password_element))
1165 // Check that all fillable elements are editable.
1166 if (!element.IsTextField() || !IsElementEditable(element) ||
1167 (!password_element.IsNull() && !IsElementEditable(password_element))) {
1171 // Don't attempt to autofill with values that are too large.
1172 if (element.Value().length() > kMaximumTextSizeForAutocomplete)
1175 #if BUILDFLAG(IS_ANDROID)
1176 // Don't call ShowSuggestionPopup if a keyboard replacing surface is currently
1177 // showing. Since a keyboard replacing surface in spirit is very similar to a
1178 // suggestion pop-up, return true so that the AutofillAgent does not try to
1179 // show other autofill suggestions instead.
1180 if (keyboard_replacing_surface_state_ ==
1181 KeyboardReplacingSurfaceState::kIsShowing) {
1186 if (!HasDocumentWithValidFrame(element))
1189 // If a username element is focused, show suggestions unless all possible
1190 // usernames are filtered.
1191 if (!element.IsPasswordFieldForAutofill()) {
1193 (password_info && CanShowUsernameSuggestion(password_info->fill_data,
1194 element.Value().Utf16()))) {
1195 ShowSuggestionPopup(element.Value().Utf16(), element, show_all,
1196 OnPasswordField(false));
1202 // If the element is a password field, do not to show a popup if the user has
1203 // already accepted a password suggestion on another password field.
1204 if (password_info && password_info->password_field_suggestion_was_accepted &&
1205 element != password_info->password_field) {
1209 // Show suggestions for password fields only while they are empty.
1210 if (!element.IsAutofilled() && !element.Value().IsEmpty()) {
1215 ShowSuggestionPopup(std::u16string(), element, show_all,
1216 OnPasswordField(true));
1220 bool PasswordAutofillAgent::FrameCanAccessPasswordManager() {
1221 // about:blank or about:srcdoc frames should not be allowed to use password
1222 // manager. See https://crbug.com/756587.
1223 WebLocalFrame* frame = render_frame()->GetWebFrame();
1224 blink::WebURL url = frame->GetDocument().Url();
1225 if (!url.ProtocolIs(url::kHttpScheme) && !url.ProtocolIs(url::kHttpsScheme))
1227 return frame->GetSecurityOrigin().CanAccessPasswordManager();
1230 void PasswordAutofillAgent::OnDynamicFormsSeen() {
1231 SendPasswordForms(false /* only_visible */);
1234 void PasswordAutofillAgent::UserGestureObserved() {
1235 autofilled_elements_cache_.clear();
1237 gatekeeper_.OnUserGesture();
1240 void PasswordAutofillAgent::AnnotateFormsAndFieldsWithSignatures(
1241 WebVector<WebFormElement>& forms) {
1242 for (WebFormElement& form : forms) {
1243 std::unique_ptr<FormData> form_data = GetFormDataFromWebForm(form);
1244 std::string form_signature;
1245 std::string alternative_form_signature;
1247 // GetAlternativeFormSignatureAsString() require the FormData::url.
1248 form_data->url = render_frame()->GetWebFrame()->GetDocument().Url();
1249 form_signature = GetFormSignatureAsString(*form_data);
1250 alternative_form_signature =
1251 GetAlternativeFormSignatureAsString(*form_data);
1252 SetAttributeAsync(form, kDebugAttributeForFormSignature, form_signature);
1253 SetAttributeAsync(form, kDebugAttributeForAlternativeFormSignature,
1254 alternative_form_signature);
1256 std::vector<WebFormControlElement> form_fields =
1257 form_util::ExtractAutofillableElementsInForm(form);
1258 AnnotateFieldsWithSignatures(form_fields, form_signature,
1259 alternative_form_signature);
1262 std::vector<WebFormControlElement> unowned_elements =
1263 form_util::GetUnownedAutofillableFormFieldElements(
1264 render_frame()->GetWebFrame()->GetDocument());
1265 std::unique_ptr<FormData> form_data = GetFormDataFromUnownedInputElements();
1266 std::string form_signature;
1267 std::string alternative_form_signature;
1269 // GetFormSignatureAsString() may require the FormData::url.
1270 form_data->url = render_frame()->GetWebFrame()->GetDocument().Url();
1271 form_signature = GetFormSignatureAsString(*form_data);
1272 alternative_form_signature =
1273 GetAlternativeFormSignatureAsString(*form_data);
1275 AnnotateFieldsWithSignatures(unowned_elements, form_signature,
1276 alternative_form_signature);
1279 void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
1280 std::unique_ptr<RendererSavePasswordProgressLogger> logger;
1281 if (logging_state_active_) {
1282 logger = std::make_unique<RendererSavePasswordProgressLogger>(
1283 &GetPasswordManagerDriver());
1284 logger->LogMessage(Logger::STRING_SEND_PASSWORD_FORMS_METHOD);
1285 logger->LogBoolean(Logger::STRING_ONLY_VISIBLE, only_visible);
1288 WebLocalFrame* frame = render_frame()->GetWebFrame();
1290 // Make sure that this security origin is allowed to use password manager.
1291 blink::WebSecurityOrigin origin = frame->GetDocument().GetSecurityOrigin();
1293 logger->LogURL(Logger::STRING_SECURITY_ORIGIN,
1294 GURL(origin.ToString().Utf8()));
1296 if (!FrameCanAccessPasswordManager()) {
1297 LogMessage(logger.get(), Logger::STRING_SECURITY_ORIGIN_FAILURE);
1301 // Checks whether the webpage is a redirect page or an empty page.
1302 if (form_util::IsWebpageEmpty(frame)) {
1303 LogMessage(logger.get(), Logger::STRING_WEBPAGE_EMPTY);
1307 WebVector<WebFormElement> forms = frame->GetDocument().Forms();
1309 if (IsShowAutofillSignaturesEnabled())
1310 AnnotateFormsAndFieldsWithSignatures(forms);
1312 logger->LogNumber(Logger::STRING_NUMBER_OF_ALL_FORMS, forms.size());
1314 std::vector<FormData> password_forms_data;
1315 for (const WebFormElement& form : forms) {
1317 bool is_form_visible = base::ranges::any_of(
1318 form.GetFormControlElements(), &IsWebElementFocusableForAutofill);
1319 LogHTMLForm(logger.get(), Logger::STRING_FORM_FOUND_ON_PAGE, form);
1320 LogBoolean(logger.get(), Logger::STRING_FORM_IS_VISIBLE, is_form_visible);
1322 // If requested, ignore non-rendered forms, e.g., those styled with
1324 if (!is_form_visible)
1328 std::unique_ptr<FormData> form_data(GetFormDataFromWebForm(form));
1329 if (!form_data || !IsRendererRecognizedCredentialForm(*form_data)) {
1333 FormStructureInfo form_structure_info =
1334 ExtractFormStructureInfo(*form_data);
1335 if (only_visible || WasFormStructureChanged(form_structure_info)) {
1336 forms_structure_cache_[form_structure_info.unique_renderer_id] =
1337 std::move(form_structure_info);
1339 password_forms_data.push_back(std::move(*form_data));
1343 std::vector<WebFormControlElement> control_elements =
1344 form.GetFormControlElements().ReleaseVector();
1345 // Sometimes JS can change autofilled forms. In this case we try to restore
1346 // values for the changed elements.
1347 TryFixAutofilledForm(&control_elements);
1350 // See if there are any unassociated input elements that could be used for
1351 // password submission.
1352 // TODO(crbug/898109): Consider using TryFixAutofilledForm for the cases when
1353 // there is no form tag.
1354 bool add_unowned_inputs = true;
1356 std::vector<WebFormControlElement> control_elements =
1357 form_util::GetUnownedAutofillableFormFieldElements(
1358 frame->GetDocument());
1359 add_unowned_inputs = base::ranges::any_of(
1360 control_elements, &IsWebElementFocusableForAutofill);
1361 LogBoolean(logger.get(), Logger::STRING_UNOWNED_INPUTS_VISIBLE,
1362 add_unowned_inputs);
1365 if (add_unowned_inputs) {
1366 std::unique_ptr<FormData> form_data(GetFormDataFromUnownedInputElements());
1367 if (form_data && IsRendererRecognizedCredentialForm(*form_data)) {
1368 password_forms_data.push_back(std::move(*form_data));
1373 // Send the PasswordFormsRendered message regardless of whether
1374 // |password_forms_data| is empty. The empty |password_forms_data| are a
1375 // possible signal to the browser that a pending login attempt succeeded.
1376 GetPasswordManagerDriver().PasswordFormsRendered(password_forms_data);
1378 // If there is a password field, but the list of password forms is empty for
1379 // some reason, add a dummy form to the list. It will cause a request to the
1380 // store. Therefore, saved passwords will be available for filling on click.
1381 if (!sent_request_to_store_ && password_forms_data.empty() &&
1382 HasPasswordField(*frame)) {
1383 // Set everything that |FormDigest| needs.
1384 password_forms_data.emplace_back();
1386 if (!password_forms_data.empty()) {
1387 sent_request_to_store_ = true;
1388 GetPasswordManagerDriver().PasswordFormsParsed(password_forms_data);
1392 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
1393 // Provide warnings about the accessibility of password forms on the page.
1394 if (!password_forms_data.empty() &&
1395 (frame->GetDocument().Url().ProtocolIs(url::kHttpScheme) ||
1396 frame->GetDocument().Url().ProtocolIs(url::kHttpsScheme)))
1397 page_passwords_analyser_.AnalyseDocumentDOM(frame);
1401 void PasswordAutofillAgent::DidDispatchDOMContentLoadedEvent() {
1402 SendPasswordForms(false);
1405 void PasswordAutofillAgent::DidFinishLoad() {
1406 // The |frame| contents have been rendered. Let the PasswordManager know
1407 // which of the loaded frames are actually visible to the user. This also
1408 // triggers the "Save password?" infobar if the user just submitted a password
1410 SendPasswordForms(true);
1413 void PasswordAutofillAgent::DidCommitProvisionalLoad(
1414 ui::PageTransition transition) {
1415 checked_safe_browsing_reputation_ = false;
1416 recorded_first_filling_result_ = false;
1419 void PasswordAutofillAgent::OnFrameDetached() {
1420 // If a sub frame has been destroyed while the user was entering information
1421 // into a password form, try to save the data. See https://crbug.com/450806
1422 // for examples of sites that perform login using this technique.
1423 // We are treating primary main frame and the root of embedded frames the same
1425 if (browser_has_form_to_process_ && render_frame()->GetWebFrame()->Parent()) {
1426 DCHECK(FrameCanAccessPasswordManager());
1427 // We should set `browser_has_form_to_process_ = false` here but
1428 // `CleanupOnDocumentShutdown()` takes care of that.
1429 GetPasswordManagerDriver().DynamicFormSubmission(
1430 SubmissionIndicatorEvent::FRAME_DETACHED);
1432 CleanupOnDocumentShutdown();
1435 void PasswordAutofillAgent::OnDestruct() {
1439 bool PasswordAutofillAgent::IsPrerendering() const {
1440 return render_frame()->GetWebFrame()->GetDocument().IsPrerendering();
1443 bool PasswordAutofillAgent::IsUsernameInputField(
1444 const blink::WebInputElement& input_element) const {
1445 return !input_element.IsPasswordFieldForAutofill() &&
1446 base::Contains(web_input_to_password_info_, input_element);
1449 void PasswordAutofillAgent::ReadyToCommitNavigation(
1450 blink::WebDocumentLoader* document_loader) {
1451 std::unique_ptr<RendererSavePasswordProgressLogger> logger;
1452 if (logging_state_active_) {
1453 logger = std::make_unique<RendererSavePasswordProgressLogger>(
1454 &GetPasswordManagerDriver());
1455 logger->LogMessage(Logger::STRING_DID_START_PROVISIONAL_LOAD_METHOD);
1458 WebLocalFrame* navigated_frame = render_frame()->GetWebFrame();
1459 if (navigated_frame->IsOutermostMainFrame()) {
1460 // This is a new navigation, so require a new user gesture before filling in
1462 gatekeeper_.Reset();
1464 LogMessage(logger.get(), Logger::STRING_FRAME_NOT_MAIN_FRAME);
1467 CleanupOnDocumentShutdown();
1470 void PasswordAutofillAgent::OnProbablyFormSubmitted() {}
1472 // mojom::PasswordAutofillAgent:
1473 void PasswordAutofillAgent::SetPasswordFillData(
1474 const PasswordFormFillData& form_data) {
1475 #if defined(TIZEN_AUTOFILL_FW)
1476 LOG(INFO) << "[Autofill] " << __FUNCTION__
1477 << " wait_for_username: " << form_data.wait_for_username;
1480 std::unique_ptr<RendererSavePasswordProgressLogger> logger;
1481 if (logging_state_active_) {
1482 logger = std::make_unique<RendererSavePasswordProgressLogger>(
1483 &GetPasswordManagerDriver());
1484 logger->LogMessage(Logger::STRING_ON_FILL_PASSWORD_FORM_METHOD);
1487 bool username_password_fields_not_set =
1488 form_data.username_element_renderer_id.is_null() &&
1489 form_data.password_element_renderer_id.is_null();
1490 if (username_password_fields_not_set) {
1491 // No fields for filling were found during parsing, which means filling
1492 // fallback case. So save data for fallback filling.
1493 MaybeStoreFallbackData(form_data);
1497 WebInputElement username_element, password_element;
1498 std::tie(username_element, password_element) =
1499 FindUsernamePasswordElements(form_data);
1500 bool is_single_username_fill =
1501 form_data.password_element_renderer_id.is_null();
1502 WebElement main_element =
1503 is_single_username_fill ? username_element : password_element;
1504 if (main_element.IsNull()) {
1505 MaybeStoreFallbackData(form_data);
1506 // TODO(https://crbug.com/959776): Fix logging for single username.
1507 LogFirstFillingResult(form_data, FillingResult::kNoPasswordElement);
1511 StoreDataForFillOnAccountSelect(form_data, username_element,
1514 // If wait_for_username is true, we don't want to initially fill the form
1515 // until the user types in a valid username.
1516 if (form_data.wait_for_username) {
1517 #if defined(TIZEN_AUTOFILL_FW)
1518 // TODO(djmix.kim) : skip temporary for autofill form
1520 LogFirstFillingResult(form_data, FillingResult::kWaitForUsername);
1525 FillUserNameAndPassword(username_element, password_element, form_data,
1527 #if BUILDFLAG(IS_TIZEN_TV)
1528 if (SupportAutoLogin())
1529 SubmitFormForAutoLogin(password_element);
1533 void PasswordAutofillAgent::SetLoggingState(bool active) {
1534 logging_state_active_ = active;
1537 void PasswordAutofillAgent::AnnotateFieldsWithParsingResult(
1538 const ParsingResult& parsing_result) {
1539 WebDocument doc = render_frame()->GetWebFrame()->GetDocument();
1540 AnnotateFieldWithParsingResult(doc, parsing_result.username_renderer_id,
1541 "username_element");
1542 AnnotateFieldWithParsingResult(doc, parsing_result.password_renderer_id,
1543 "password_element");
1544 AnnotateFieldWithParsingResult(doc, parsing_result.new_password_renderer_id,
1545 "new_password_element");
1546 AnnotateFieldWithParsingResult(doc,
1547 parsing_result.confirm_password_renderer_id,
1548 "confirmation_password_element");
1551 void PasswordAutofillAgent::InformNoSavedCredentials(
1552 bool should_show_popup_without_passwords) {
1553 should_show_popup_without_passwords_ = should_show_popup_without_passwords;
1555 autofilled_elements_cache_.clear();
1557 // Clear the actual field values.
1558 WebDocument doc = render_frame()->GetWebFrame()->GetDocument();
1559 std::vector<WebFormControlElement> elements = FindFormControlsByRendererId(
1560 doc, std::vector<FieldRendererId>(all_autofilled_elements_.begin(),
1561 all_autofilled_elements_.end()));
1562 for (WebFormControlElement& element : elements) {
1563 if (element.IsNull())
1565 // Don't clear the actual value of fields that the user has edited manually
1566 // (which changes the autofill state back to kNotFilled).
1567 if (element.IsAutofilled()) {
1568 element.SetValue(blink::WebString());
1570 element.SetSuggestedValue(blink::WebString());
1572 all_autofilled_elements_.clear();
1574 field_data_manager_->ClearData();
1577 #if BUILDFLAG(IS_ANDROID)
1578 void PasswordAutofillAgent::KeyboardReplacingSurfaceClosed(
1579 bool show_virtual_keyboard) {
1580 keyboard_replacing_surface_state_ = KeyboardReplacingSurfaceState::kWasShown;
1582 auto focused_input_element = focused_element().DynamicTo<WebInputElement>();
1583 if (focused_input_element.IsNull() || focused_element().IsReadOnly()) {
1587 if (show_virtual_keyboard) {
1588 render_frame()->ShowVirtualKeyboard();
1590 // Since a keyboard replacing surface suppresses the Autofill popup,
1591 // re-trigger the suggestions in case the virtual keyboard should be shown.
1592 // This is limited to the keyboard accessory, as otherwise it would result
1593 // in a flickering of the popup, due to showing the keyboard at the same
1595 if (IsKeyboardAccessoryEnabled()) {
1596 ShowSuggestions(focused_input_element, ShowAll(false));
1601 void PasswordAutofillAgent::TriggerFormSubmission() {
1602 // Find the last interacted element to simulate an enter keystroke at.
1603 WebFormControlElement form_control =
1604 FindFormControlByRendererId(render_frame()->GetWebFrame()->GetDocument(),
1605 field_renderer_id_to_submit_);
1606 if (form_control.IsNull()) {
1607 // The target field doesn't exist anymore. Don't try to submit it.
1611 // |form_control| can only be |WebInputElement|, not |WebSelectElement|.
1612 WebInputElement input = form_control.To<WebInputElement>();
1613 input.DispatchSimulatedEnter();
1614 field_renderer_id_to_submit_ = FieldRendererId();
1618 std::unique_ptr<FormData> PasswordAutofillAgent::GetFormDataFromWebForm(
1619 const WebFormElement& web_form) {
1620 return CreateFormDataFromWebForm(web_form, field_data_manager_.get(),
1621 &username_detector_cache_,
1622 &button_titles_cache_);
1625 std::unique_ptr<FormData>
1626 PasswordAutofillAgent::GetFormDataFromUnownedInputElements() {
1627 // The element's frame might have been detached in the meantime (see
1628 // http://crbug.com/585363, comments 5 and 6), in which case |frame| will
1629 // be null. This was hardly caused by form submission (unless the user is
1630 // supernaturally quick), so it is OK to drop the ball here.
1631 content::RenderFrame* frame = render_frame();
1634 WebLocalFrame* web_frame = frame->GetWebFrame();
1637 return CreateFormDataFromUnownedInputElements(
1638 *web_frame, field_data_manager_.get(), &username_detector_cache_,
1639 autofill_agent_->is_heavy_form_data_scraping_enabled()
1640 ? &button_titles_cache_
1644 void PasswordAutofillAgent::InformAboutFormClearing(
1645 const WebFormElement& form) {
1646 if (!FrameCanAccessPasswordManager())
1648 for (const auto& element : form.GetFormControlElements()) {
1649 // Notify PasswordManager if |form| has password fields that have user typed
1650 // input or input autofilled on user trigger.
1651 if (IsPasswordFieldFilledByUser(element)) {
1652 NotifyPasswordManagerAboutClearedForm(form);
1658 void PasswordAutofillAgent::InformAboutFieldClearing(
1659 const WebInputElement& cleared_element) {
1660 if (!FrameCanAccessPasswordManager())
1662 DCHECK(cleared_element.Value().IsEmpty());
1663 FieldRendererId field_id = form_util::GetFieldRendererId(cleared_element);
1664 // Ignore fields that had no user input or autofill on user trigger.
1665 if (!field_data_manager_->DidUserType(field_id) &&
1666 !field_data_manager_->WasAutofilledOnUserTrigger(field_id)) {
1670 WebFormElement form = cleared_element.Form();
1671 if (form.IsNull()) {
1672 // Process password field clearing for fields outside the <form> tag.
1673 if (auto unowned_form_data = GetFormDataFromUnownedInputElements())
1674 GetPasswordManagerDriver().PasswordFormCleared(*unowned_form_data);
1677 // Process field clearing for a form under a <form> tag.
1678 // Only notify PasswordManager in case all user filled password fields were
1680 bool cleared_all_password_fields = base::ranges::all_of(
1681 form.GetFormControlElements(), [this](const auto& el) {
1682 return !IsPasswordFieldFilledByUser(el) || el.Value().IsEmpty();
1684 if (cleared_all_password_fields)
1685 NotifyPasswordManagerAboutClearedForm(form);
1688 ////////////////////////////////////////////////////////////////////////////////
1689 // PasswordAutofillAgent, private:
1691 void PasswordAutofillAgent::ShowSuggestionPopup(
1692 const std::u16string& typed_username,
1693 const WebInputElement& user_input,
1695 OnPasswordField show_on_password_field) {
1696 username_query_prefix_ = typed_username;
1698 FormFieldData field;
1699 form_util::FindFormAndFieldForFormControlElement(
1700 user_input, field_data_manager_.get(), /*extract_options=*/{}, &form,
1705 options |= SHOW_ALL;
1706 if (show_on_password_field)
1707 options |= IS_PASSWORD_FIELD;
1708 if (field.parsed_autocomplete && field.parsed_autocomplete->webauthn)
1709 options |= ACCEPTS_WEBAUTHN_CREDENTIALS;
1711 WebInputElement username_element;
1712 WebInputElement password_element;
1713 PasswordInfo* password_info = nullptr;
1714 FindPasswordInfoForElement(user_input, UseFallbackData(false),
1715 &username_element, &password_element,
1718 GetPasswordManagerDriver().ShowPasswordSuggestions(
1719 field.unique_renderer_id, form, GetIndexOfElement(form, username_element),
1720 GetIndexOfElement(form, password_element), field.text_direction,
1721 typed_username, options,
1722 render_frame()->ElementBoundsInWindow(user_input));
1725 void PasswordAutofillAgent::CleanupOnDocumentShutdown() {
1726 web_input_to_password_info_.clear();
1727 password_to_username_.clear();
1728 last_supplied_password_info_iter_ = web_input_to_password_info_.end();
1729 should_show_popup_without_passwords_ = false;
1730 browser_has_form_to_process_ = false;
1731 field_data_manager_.get()->ClearData();
1732 username_autofill_state_ = WebAutofillState::kNotFilled;
1733 password_autofill_state_ = WebAutofillState::kNotFilled;
1734 sent_request_to_store_ = false;
1735 checked_safe_browsing_reputation_ = false;
1736 username_query_prefix_.clear();
1737 username_detector_cache_.clear();
1738 forms_structure_cache_.clear();
1739 autofilled_elements_cache_.clear();
1740 all_autofilled_elements_.clear();
1741 last_updated_field_renderer_id_ = FieldRendererId();
1742 last_updated_form_renderer_id_ = FormRendererId();
1743 field_renderer_id_to_submit_ = FieldRendererId();
1744 #if BUILDFLAG(IS_ANDROID)
1745 keyboard_replacing_surface_state_ =
1746 KeyboardReplacingSurfaceState::kShouldShow;
1748 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
1749 page_passwords_analyser_.Reset();
1753 void PasswordAutofillAgent::ClearPreview(WebInputElement* username,
1754 WebInputElement* password) {
1755 if (!username->IsNull() && !username->SuggestedValue().IsEmpty()) {
1756 username->SetSuggestedValue(WebString());
1757 username->SetAutofillState(username_autofill_state_);
1758 username->SetSelectionRange(
1759 base::checked_cast<unsigned>(username_query_prefix_.length()),
1760 base::checked_cast<unsigned>(username->Value().length()));
1762 if (!password->IsNull() && !password->SuggestedValue().IsEmpty()) {
1763 if (base::FeatureList::IsEnabled(blink::features::kPasswordStrongLabel)) {
1764 password->SetShouldShowStrongPasswordLabel(false);
1766 password->SetSuggestedValue(WebString());
1767 password->SetAutofillState(password_autofill_state_);
1770 void PasswordAutofillAgent::InformBrowserAboutUserInput(
1771 const WebFormElement& form,
1772 const WebInputElement& element) {
1773 DCHECK(!form.IsNull() || !element.IsNull());
1774 if (!FrameCanAccessPasswordManager())
1776 SetLastUpdatedFormAndField(form, element);
1777 std::unique_ptr<FormData> form_data =
1778 form.IsNull() ? GetFormDataFromUnownedInputElements()
1779 : GetFormDataFromWebForm(form);
1783 if (!IsRendererRecognizedCredentialForm(*form_data)) {
1787 GetPasswordManagerDriver().InformAboutUserInput(*form_data);
1789 browser_has_form_to_process_ = true;
1792 bool PasswordAutofillAgent::FillUserNameAndPassword(
1793 WebInputElement username_element,
1794 WebInputElement password_element,
1795 const PasswordFormFillData& fill_data,
1796 RendererSavePasswordProgressLogger* logger) {
1797 LogMessage(logger, Logger::STRING_FILL_USERNAME_AND_PASSWORD_METHOD);
1799 bool is_single_username_fill = password_element.IsNull();
1800 WebInputElement main_element =
1801 is_single_username_fill ? username_element : password_element;
1803 #if defined(TIZEN_AUTOFILL_FW)
1804 WebFrame* cur_frame = main_element.GetDocument().GetFrame();
1805 WebString bottom_frame_origin = cur_frame->GetSecurityOrigin().ToString();
1806 LOG(INFO) << "[Autofill] " << __FUNCTION__
1807 << " bottom_frame_origin : " << bottom_frame_origin.Utf8().c_str()
1808 << ", cur_frame->GetSecurityOrigin() : "
1809 << cur_frame->GetSecurityOrigin().ToString().Utf8().c_str();
1810 if (IsInCrossOriginIframeOrEmbeddedFrame(main_element)) {
1811 LOG(INFO) << "[Autofill] " << __FUNCTION__
1812 << " daum login issue, skip temporary";
1813 // TODO(djmix.kim) : skip temporary for daum login issue
1816 if (IsInCrossOriginIframeOrEmbeddedFrame(main_element)) {
1817 LogMessage(logger, Logger::STRING_FAILED_TO_FILL_INTO_IFRAME);
1818 LogFirstFillingResult(fill_data, FillingResult::kBlockedByFrameHierarchy);
1823 // Don't fill username if password can't be set.
1824 if (!IsElementEditable(main_element)) {
1826 Logger::STRING_FAILED_TO_FILL_NO_AUTOCOMPLETEABLE_ELEMENT);
1827 LogFirstFillingResult(fill_data,
1828 FillingResult::kPasswordElementIsNotAutocompleteable);
1832 // |current_username| is the username for credentials that are going to be
1833 // autofilled. It is selected according to the algorithm:
1834 // 1. If the page already contains a non-empty value in |username_element|
1835 // that is not found in the list of values known to be used as placeholders,
1836 // this is adopted and not overridden.
1837 // 2. Default username from |fill_data| if the username field is
1839 // 3. Empty if username field doesn't exist or if username field is empty and
1840 // not autocompletable (no username case).
1841 std::u16string current_username;
1843 // Whether the username element was prefilled with content that was on a
1844 // list of known placeholder texts that should be overridden (e.g. "username
1845 // or email" or there is a server hint that it is just a placeholder).
1846 bool prefilled_placeholder_username = false;
1848 if (!username_element.IsNull()) {
1849 // This is a heuristic guess. If the credential is stored for
1850 // www.example.com, the username may be prefilled with "@example.com".
1851 std::string possible_email_domain =
1852 GetRegistryControlledDomain(fill_data.url);
1854 prefilled_placeholder_username =
1855 !username_element.Value().IsEmpty() &&
1856 (PossiblePrefilledUsernameValue(username_element.Value().Utf8(),
1857 possible_email_domain) ||
1858 (fill_data.username_may_use_prefilled_placeholder &&
1859 base::FeatureList::IsEnabled(
1860 password_manager::features::
1861 kEnableOverwritingPlaceholderUsernames)));
1863 if (!username_element.Value().IsEmpty() &&
1864 username_element.GetAutofillState() == WebAutofillState::kNotFilled &&
1865 !prefilled_placeholder_username) {
1866 // Username is filled with content that was not on a list of known
1867 // placeholder texts (e.g. "username or email") nor there is server-side
1868 // data that this value is placeholder.
1869 current_username = username_element.Value().Utf16();
1870 } else if (IsElementEditable(username_element)) {
1871 current_username = fill_data.preferred_login.username_value;
1875 // |username| and |password| will contain the match found if any.
1876 std::u16string username;
1877 std::u16string password;
1879 bool exact_username_match =
1880 username_element.IsNull() || IsElementEditable(username_element);
1882 FindMatchesByUsername(fill_data, current_username, exact_username_match,
1883 logger, &username, &password);
1885 if (password.empty() && !is_single_username_fill) {
1886 if (!username_element.IsNull() && !username_element.Value().IsEmpty() &&
1887 !prefilled_placeholder_username) {
1888 LogPrefilledUsernameFillOutcome(
1889 PrefilledUsernameFillOutcome::kPrefilledUsernameNotOverridden);
1891 LogMessage(logger, Logger::STRING_FAILED_TO_FILL_PREFILLED_USERNAME);
1892 LogFirstFillingResult(
1893 fill_data, FillingResult::kUsernamePrefilledWithIncompatibleValue);
1897 Logger::STRING_FAILED_TO_FILL_FOUND_NO_PASSWORD_FOR_USERNAME);
1898 LogFirstFillingResult(fill_data,
1899 FillingResult::kFoundNoPasswordForUsername);
1903 // Call OnFieldAutofilled before WebInputElement::SetAutofillState which may
1904 // cause frame closing.
1905 if (password_generation_agent_ && !is_single_username_fill)
1906 password_generation_agent_->OnFieldAutofilled(password_element);
1908 // Input matches the username, fill in required values.
1909 if (!username_element.IsNull() && IsElementEditable(username_element)) {
1910 if (!username.empty() &&
1911 (username_element.Value().IsEmpty() ||
1912 username_element.GetAutofillState() != WebAutofillState::kNotFilled ||
1913 prefilled_placeholder_username)) {
1914 #if defined(TIZEN_AUTOFILL_FW)
1915 // We fill username and password directly
1916 FillField(&username_element, username);
1919 AutofillField(username, username_element);
1920 if (prefilled_placeholder_username) {
1921 LogPrefilledUsernameFillOutcome(
1922 PrefilledUsernameFillOutcome::
1923 kPrefilledPlaceholderUsernameOverridden);
1928 logger->LogElementName(Logger::STRING_USERNAME_FILLED, username_element);
1931 if (!is_single_username_fill) {
1932 #if defined(TIZEN_AUTOFILL_FW)
1933 FillPasswordFieldAndSave(&password_element, password);
1935 AutofillField(password, password_element);
1938 logger->LogElementName(Logger::STRING_PASSWORD_FILLED, password_element);
1941 LogFirstFillingResult(fill_data, FillingResult::kSuccess);
1945 void PasswordAutofillAgent::LogPrefilledUsernameFillOutcome(
1946 PrefilledUsernameFillOutcome outcome) {
1947 if (prefilled_username_metrics_logged_)
1949 prefilled_username_metrics_logged_ = true;
1950 UMA_HISTOGRAM_ENUMERATION("PasswordManager.PrefilledUsernameFillOutcome",
1954 void PasswordAutofillAgent::OnProvisionallySaveForm(
1955 const WebFormElement& form,
1956 const WebFormControlElement& element,
1957 ElementChangeSource source) {
1958 // PasswordAutofillAgent isn't interested in SELECT control change.
1959 if (source == ElementChangeSource::SELECT_CHANGED)
1962 WebInputElement input_element = element.DynamicTo<WebInputElement>();
1964 if (source == ElementChangeSource::TEXTFIELD_CHANGED) {
1965 DCHECK(!input_element.IsNull());
1966 // keeps track of all text changes even if it isn't displaying UI.
1967 UpdateStateForTextChange(input_element);
1971 DCHECK_EQ(ElementChangeSource::WILL_SEND_SUBMIT_EVENT, source);
1972 InformBrowserAboutUserInput(form, input_element);
1975 void PasswordAutofillAgent::OnFormSubmitted(const WebFormElement& form) {
1976 std::unique_ptr<RendererSavePasswordProgressLogger> logger;
1977 if (logging_state_active_) {
1978 logger = std::make_unique<RendererSavePasswordProgressLogger>(
1979 &GetPasswordManagerDriver());
1980 LogHTMLForm(logger.get(), Logger::STRING_HTML_FORM_FOR_SUBMIT, form);
1983 if (!FrameCanAccessPasswordManager()) {
1984 LogMessage(logger.get(), Logger::STRING_SECURITY_ORIGIN_FAILURE);
1988 std::unique_ptr<FormData> submitted_form_data = GetFormDataFromWebForm(form);
1990 if (!submitted_form_data)
1993 submitted_form_data->submission_event =
1994 SubmissionIndicatorEvent::HTML_FORM_SUBMISSION;
1996 FillNonTypedOrFilledPropertiesMasks(&submitted_form_data->fields,
1997 *field_data_manager_);
1999 GetPasswordManagerDriver().PasswordFormSubmitted(*submitted_form_data);
2000 browser_has_form_to_process_ = false;
2003 void PasswordAutofillAgent::OnInferredFormSubmission(SubmissionSource source) {
2005 case mojom::SubmissionSource::NONE:
2006 case mojom::SubmissionSource::PROBABLY_FORM_SUBMITTED:
2007 case mojom::SubmissionSource::FORM_SUBMISSION:
2008 NOTREACHED_NORETURN();
2009 case mojom::SubmissionSource::FRAME_DETACHED:
2012 case mojom::SubmissionSource::DOM_MUTATION_AFTER_XHR:
2013 case mojom::SubmissionSource::SAME_DOCUMENT_NAVIGATION:
2014 case mojom::SubmissionSource::XHR_SUCCEEDED:
2015 if (browser_has_form_to_process_) {
2016 CHECK(FrameCanAccessPasswordManager());
2017 browser_has_form_to_process_ = false;
2018 GetPasswordManagerDriver().DynamicFormSubmission(
2019 ToSubmissionIndicatorEvent(source));
2025 void PasswordAutofillAgent::HidePopup() {
2026 if (autofill_agent_->unsafe_autofill_driver()) {
2027 autofill_agent_->unsafe_autofill_driver()->HidePopup();
2031 mojom::PasswordManagerDriver&
2032 PasswordAutofillAgent::GetPasswordManagerDriver() {
2033 if (IsPrerendering()) {
2034 if (!deferring_password_manager_driver_) {
2035 deferring_password_manager_driver_ =
2036 std::make_unique<DeferringPasswordManagerDriver>(this);
2038 return *deferring_password_manager_driver_;
2041 // Lazily bind this interface.
2042 if (!password_manager_driver_) {
2043 render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
2044 &password_manager_driver_);
2047 return *password_manager_driver_;
2050 std::pair<WebInputElement, WebInputElement>
2051 PasswordAutofillAgent::FindUsernamePasswordElements(
2052 const PasswordFormFillData& form_data) {
2053 const FieldRendererId username_renderer_id =
2054 form_data.username_element_renderer_id;
2055 const FieldRendererId password_renderer_id =
2056 form_data.password_element_renderer_id;
2057 const bool is_username_present = !username_renderer_id.is_null();
2058 const bool is_password_present = !password_renderer_id.is_null();
2060 std::vector<FieldRendererId> element_ids;
2061 if (is_password_present)
2062 element_ids.push_back(password_renderer_id);
2063 if (is_username_present)
2064 element_ids.push_back(username_renderer_id);
2066 WebDocument doc = render_frame()->GetWebFrame()->GetDocument();
2067 bool wrapped_in_form_tag = !form_data.form_renderer_id.is_null();
2068 std::vector<WebFormControlElement> elements =
2069 wrapped_in_form_tag ? FindFormControlsByRendererId(
2070 doc, form_data.form_renderer_id, element_ids)
2071 : FindFormControlsByRendererId(doc, element_ids);
2073 // Set password element.
2074 WebInputElement password_field;
2075 size_t current_index = 0;
2076 if (is_password_present)
2077 password_field = elements[current_index++].DynamicTo<WebInputElement>();
2079 // Set username element.
2080 WebInputElement username_field;
2081 if (is_username_present)
2082 username_field = elements[current_index++].DynamicTo<WebInputElement>();
2084 return std::make_pair(username_field, password_field);
2087 void PasswordAutofillAgent::StoreDataForFillOnAccountSelect(
2088 const PasswordFormFillData& form_data,
2089 WebInputElement username_element,
2090 WebInputElement password_element) {
2091 WebInputElement main_element =
2092 username_element.IsNull() ? password_element : username_element;
2094 PasswordInfo password_info;
2095 password_info.fill_data = form_data;
2096 password_info.password_field = password_element;
2097 web_input_to_password_info_[main_element] = password_info;
2098 last_supplied_password_info_iter_ =
2099 web_input_to_password_info_.find(main_element);
2100 if (!main_element.IsPasswordFieldForAutofill())
2101 password_to_username_[password_element] = username_element;
2104 void PasswordAutofillAgent::MaybeStoreFallbackData(
2105 const PasswordFormFillData& form_data) {
2106 if (!web_input_to_password_info_.empty())
2108 // If for some reasons elements for filling were not found (for example
2109 // because they were renamed by JavaScript) then add fill data for
2110 // |web_input_to_password_info_|. When the user clicks on a password field
2111 // which is not a key in |web_input_to_password_info_|, the first element from
2112 // |web_input_to_password_info_| will be used in
2113 // PasswordAutofillAgent::FindPasswordInfoForElement to propose to fill.
2114 PasswordInfo password_info;
2115 password_info.fill_data = form_data;
2116 web_input_to_password_info_[WebInputElement()] = password_info;
2117 last_supplied_password_info_iter_ = web_input_to_password_info_.begin();
2120 void PasswordAutofillAgent::LogFirstFillingResult(
2121 const PasswordFormFillData& form_data,
2122 FillingResult result) {
2123 if (recorded_first_filling_result_)
2125 UMA_HISTOGRAM_ENUMERATION("PasswordManager.FirstRendererFillingResult",
2127 GetPasswordManagerDriver().LogFirstFillingResult(
2128 form_data.form_renderer_id, base::strict_cast<int32_t>(result));
2129 recorded_first_filling_result_ = true;
2132 PasswordAutofillAgent::FormStructureInfo
2133 PasswordAutofillAgent::ExtractFormStructureInfo(const FormData& form_data) {
2134 FormStructureInfo result;
2135 result.unique_renderer_id = form_data.unique_renderer_id;
2136 result.fields.resize(form_data.fields.size());
2138 for (size_t i = 0; i < form_data.fields.size(); ++i) {
2139 const FormFieldData& form_field = form_data.fields[i];
2141 FormFieldInfo& field_info = result.fields[i];
2142 field_info.unique_renderer_id = form_field.unique_renderer_id;
2143 field_info.form_control_type =
2144 FormControlTypeToString(form_field.form_control_type);
2145 field_info.autocomplete_attribute = form_field.autocomplete_attribute;
2146 field_info.is_focusable = form_field.is_focusable;
2152 bool PasswordAutofillAgent::WasFormStructureChanged(
2153 const FormStructureInfo& form_info) const {
2154 if (form_info.unique_renderer_id.is_null())
2157 auto cached_form = forms_structure_cache_.find(form_info.unique_renderer_id);
2158 if (cached_form == forms_structure_cache_.end())
2161 const FormStructureInfo& cached_form_info = cached_form->second;
2163 if (form_info.fields.size() != cached_form_info.fields.size())
2166 for (size_t i = 0; i < form_info.fields.size(); ++i) {
2167 const FormFieldInfo& form_field = form_info.fields[i];
2168 const FormFieldInfo& cached_form_field = cached_form_info.fields[i];
2170 if (form_field.unique_renderer_id != cached_form_field.unique_renderer_id)
2173 if (form_field.form_control_type != cached_form_field.form_control_type)
2176 if (form_field.autocomplete_attribute !=
2177 cached_form_field.autocomplete_attribute) {
2181 if (form_field.is_focusable != cached_form_field.is_focusable)
2187 void PasswordAutofillAgent::TryFixAutofilledForm(
2188 std::vector<WebFormControlElement>* control_elements) const {
2189 for (auto& element : *control_elements) {
2190 auto cached_element =
2191 autofilled_elements_cache_.find(form_util::GetFieldRendererId(element));
2192 if (cached_element == autofilled_elements_cache_.end())
2195 // autofilled_elements_cache_ stores values filled at page load time and
2196 // gets wiped when we observe a user gesture. During this time, the
2197 // username/password fields can be in preview state and we restore this
2198 // state if JavaScript modifies the field's value.
2199 const WebString& cached_value = cached_element->second;
2200 if (cached_value != element.SuggestedValue())
2201 element.SetSuggestedValue(cached_value);
2205 void PasswordAutofillAgent::AutofillField(const std::u16string& value,
2206 WebInputElement field) {
2207 // Do not autofill on load fields that have any user typed input.
2208 const FieldRendererId field_id = form_util::GetFieldRendererId(field);
2209 if (field_data_manager_->DidUserType(field_id))
2212 if (field.Value().Utf16() == value)
2215 field.SetSuggestedValue(WebString::FromUTF16(value));
2216 field.SetAutofillState(WebAutofillState::kAutofilled);
2217 // Wait to fill until a user gesture occurs. This is to make sure that we do
2218 // not fill in the DOM with a password until we believe the user is
2219 // intentionally interacting with the page.
2220 gatekeeper_.RegisterElement(&field);
2221 field_data_manager_.get()->UpdateFieldDataMap(
2222 field_id, value, FieldPropertiesFlags::kAutofilledOnPageLoad);
2223 autofilled_elements_cache_.emplace(field_id, WebString::FromUTF16(value));
2224 all_autofilled_elements_.insert(field_id);
2227 void PasswordAutofillAgent::SetLastUpdatedFormAndField(
2228 const WebFormElement& form,
2229 const WebFormControlElement& input) {
2230 last_updated_form_renderer_id_ = GetFormRendererId(form);
2231 last_updated_field_renderer_id_ =
2232 input.IsNull() ? FieldRendererId() : GetFieldRendererId(input);
2235 bool PasswordAutofillAgent::CanShowPopupWithoutPasswords(
2236 const WebInputElement& password_element) const {
2237 return should_show_popup_without_passwords_ && !password_element.IsNull() &&
2238 IsElementEditable(password_element);
2241 bool PasswordAutofillAgent::IsPasswordFieldFilledByUser(
2242 const WebFormControlElement& element) const {
2243 FieldRendererId element_id = form_util::GetFieldRendererId(element);
2244 return element.FormControlTypeForAutofill() ==
2245 blink::mojom::FormControlType::kInputPassword &&
2246 (field_data_manager_->DidUserType(element_id) ||
2247 field_data_manager_->WasAutofilledOnUserTrigger(element_id));
2250 void PasswordAutofillAgent::NotifyPasswordManagerAboutClearedForm(
2251 const WebFormElement& cleared_form) {
2252 const auto extract_options = {ExtractOption::kValue, ExtractOption::kOptions};
2254 if (WebFormElementToFormData(cleared_form, WebFormControlElement(),
2255 field_data_manager_.get(), extract_options,
2256 &form_data, /*field=*/nullptr)) {
2257 GetPasswordManagerDriver().PasswordFormCleared(form_data);
2261 #if BUILDFLAG(IS_TIZEN_TV)
2262 void PasswordAutofillAgent::SendEnterKeyBoardEvent() {
2263 if (!render_frame())
2265 blink::WebView* web_view = render_frame()->GetWebView();
2268 blink::WebWidget* widget = web_view->MainFrameWidget();
2270 LOG(INFO) << "[Autofill] - " << __FUNCTION__;
2271 blink::WebKeyboardEvent keyboard_event;
2272 keyboard_event.windows_key_code = ui::VKEY_RETURN;
2273 keyboard_event.SetModifiers(blink::WebInputEvent::kIsKeyPad);
2274 keyboard_event.text[0] = ui::VKEY_RETURN;
2275 keyboard_event.SetType(blink::WebInputEvent::Type::kKeyDown);
2276 widget->HandleInputEvent(
2277 blink::WebCoalescedInputEvent(keyboard_event, ui::LatencyInfo()));
2278 keyboard_event.SetType(blink::WebInputEvent::Type::kKeyUp);
2279 widget->HandleInputEvent(
2280 blink::WebCoalescedInputEvent(keyboard_event, ui::LatencyInfo()));
2283 // Removes some characters from attribute value.
2284 void ClearAttributeValue(std::string* value) {
2285 value->erase(std::remove_if(value->begin(), value->end(),
2286 [](char x) { return x == '-' || x == '_'; }),
2289 // Find |features| in |element|'s attribute values. Returns true if at least one
2290 // text feature was found.
2291 bool FindTextFeaturesForClass(const blink::WebElement& element,
2292 const char* const features[],
2293 size_t number_of_features) {
2295 #if !defined(EWK_BRINGUP)
2296 for (unsigned i = 0; i < element.AttributeCount(); ++i) {
2297 std::string filtered_value =
2298 base::ToLowerASCII(element.AttributeValue(i).Utf8());
2299 ClearAttributeValue(&filtered_value);
2301 if (filtered_value.empty())
2303 for (size_t j = 0; j < number_of_features; ++j) {
2304 if (filtered_value.find(features[j]) != std::string::npos)
2312 // Returns true if at least one captcha feature was found in |element|'s
2313 // attribute values.
2314 bool IsCaptchaInput(const blink::WebInputElement& element) {
2315 return FindTextFeaturesForClass(element, kCaptchaFeatures,
2316 kNumberOfCaptchaFeatures);
2318 // Finds <img>'s inside |form| and checks if <img>'s attributes contains captcha
2319 // text features. Returns true, if at least one occurrence was found.
2320 bool FindCaptchaInImgElements(const blink::WebElement& form) {
2321 static const base::NoDestructor<WebString> wrapper("img");
2322 const WebString& kImageTag = *wrapper;
2324 blink::WebElementCollection img_elements =
2325 form.GetElementsByHTMLTagName(kImageTag);
2326 for (blink::WebElement element = img_elements.FirstItem(); !element.IsNull();
2327 element = img_elements.NextItem()) {
2328 if (!form_util::IsWebElementVisible(element))
2331 if (FindTextFeaturesForClass(element, kCaptchaFeatures,
2332 kNumberOfCaptchaFeatures)) {
2339 void PasswordAutofillAgent::SubmitFormForAutoLogin(
2340 blink::WebInputElement& password_input) {
2341 LOG(INFO) << "[Autofill] - " << __FUNCTION__;
2342 if (IsCaptchaInput(password_input)) {
2343 LOG(INFO) << "[Autofill] - " << __FUNCTION__
2344 << " Page include captcha input, do not autologin";
2347 if (FindCaptchaInImgElements(password_input.Form())) {
2348 LOG(INFO) << "[Autofill] - " << __FUNCTION__
2349 << " Page include captcha image, do not autologin";
2352 // FIXME: sometimes focus is on other field but login form,
2353 // it will cause key event send to wrong element.
2354 password_input.Focus();
2355 // Attention: if password_input element is not focusable at the time of
2356 // calling Focus(), it will still be unfocused after Focus() is returned.
2358 // TODO(daoning.ren): this is workaround solution for google.com
2359 // there is delay page switch during login, key event will send
2360 // before page switch, so make a delay here
2362 ->GetTaskRunner(blink::TaskType::kInternalUserInteraction)
2365 base::BindOnce(&PasswordAutofillAgent::SendEnterKeyBoardEvent,
2366 base::Unretained(this)),
2367 base::Milliseconds(kSendEnterKeyTimeout));
2370 bool PasswordAutofillAgent::SupportAutoLogin() {
2371 // There are 2 browser types from Tizen5.5:
2372 // org.tizen.browser, com.samsung.tv.knox-browser
2373 // Only org.tizen.browser app need AutoLogin behavior according to their spec.
2374 // The latter just wants Autofill.
2376 const std::string tizen_app_id =
2377 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
2378 switches::kTizenAppId);
2379 return tizen_app_id == "org.tizen.browser";
2383 } // namespace autofill