[M120 Migration] Build libchromium-impl.so with chrome implementation
[platform/framework/web/chromium-efl.git] / components / autofill / content / renderer / password_autofill_agent.cc
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.
4
5 #include "components/autofill/content/renderer/password_autofill_agent.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <string>
11 #include <utility>
12 #include <vector>
13
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"
58
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"
68 #endif
69
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"
82 #include "url/gurl.h"
83
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;
93 using blink::WebNode;
94 using blink::WebString;
95 using blink::WebVector;
96 using blink::WebView;
97 #if BUILDFLAG(IS_TIZEN_TV)
98 using blink::WebString;
99 #endif
100
101 using password_manager::util::IsRendererRecognizedCredentialForm;
102
103 namespace autofill {
104
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;
113
114 using mojom::SubmissionIndicatorEvent;
115 using mojom::SubmissionSource;
116
117 namespace {
118
119 // The size above which we stop triggering autocomplete.
120 const size_t kMaximumTextSizeForAutocomplete = 1000;
121
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
130 // debugging.
131 constexpr char kDebugAttributeForAutofill[] = "autofill-information";
132
133 // HTML attribute that is used as a tooltip if
134 // |kAutofillShowTypePredictions| is on.
135 constexpr char kHtmlAttributeForAutofillTooltip[] = "title";
136
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
142 #endif
143 // Maps element names to the actual elements to simplify form filling.
144 typedef std::map<std::u16string, WebInputElement> FormInputElementMap;
145
146 // Use the shorter name when referencing SavePasswordProgressLogger::StringID
147 // values to spare line breaks. The code provides enough context for that
148 // already.
149 typedef SavePasswordProgressLogger Logger;
150
151 typedef std::vector<FormInputElementMap> FormElementsList;
152
153 bool DoUsernamesMatch(const std::u16string& potential_suggestion,
154                       const std::u16string& current_username,
155                       bool exact_match) {
156   if (potential_suggestion == current_username)
157     return true;
158   return !exact_match && IsPrefixOfEmailEndingWithAtSign(current_username,
159                                                          potential_suggestion);
160 }
161
162 // Returns whether the |username_element| is allowed to be autofilled.
163 //
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());
173 }
174
175 // Log `message` if `logger` is not null.
176 void LogMessage(Logger* logger, Logger::StringID message) {
177   if (logger)
178     logger->LogMessage(message);
179 }
180
181 // Log `message` and `value` if `logger` is not null.
182 void LogBoolean(Logger* logger, Logger::StringID message, bool value) {
183   if (logger)
184     logger->LogBoolean(message, value);
185 }
186
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) {
191   if (logger) {
192     logger->LogHTMLForm(message_id, form.GetName().Utf8(),
193                         GURL(form.Action().Utf8()));
194   }
195 }
196
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)) {
205     return true;
206   }
207
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)) {
211       return true;
212     }
213   }
214
215   return false;
216 }
217
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);
233   } else {
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.
241         continue;
242       }
243       if (DoUsernamesMatch(it.username_value, current_username,
244                            exact_username_match)) {
245         *username = it.username_value;
246         *password = it.password_value;
247         break;
248       }
249     }
250     LogBoolean(logger, Logger::STRING_MATCH_IN_ADDITIONAL,
251                !(username->empty() && password->empty()));
252   }
253 }
254
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(
262       signon_realm,
263       net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
264 }
265
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) {
273   GURL gurl1(url1);
274   GURL gurl2(url2);
275
276   if (!gurl1.is_valid() || !gurl2.is_valid())
277     return false;
278
279   if (gurl1 == gurl2)
280     return true;
281
282   std::string domain1(GetRegistryControlledDomain(gurl1));
283   std::string domain2(GetRegistryControlledDomain(gurl2));
284
285   if (domain1.empty() || domain2.empty())
286     return false;
287
288   return gurl1.scheme() == gurl2.scheme() && domain1 == domain2 &&
289          gurl1.port() == gurl2.port();
290 }
291
292 // Helper function that calculates form signature for |form_data| and returns it
293 // as a string.
294 std::string GetFormSignatureAsString(const FormData& form_data) {
295   return base::NumberToString(CalculateFormSignature(form_data).value());
296 }
297 // Similar to `GetFormSignatureAsString` but returns alternative form signature
298 // as a string.
299 std::string GetAlternativeFormSignatureAsString(const FormData& form_data) {
300   return base::NumberToString(
301       CalculateAlternativeFormSignature(form_data).value());
302 }
303
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));
313 }
314
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) {
319   if (target.IsNull())
320     return;
321   target.GetDocument()
322       .GetFrame()
323       ->GetTaskRunner(blink::TaskType::kInternalDefault)
324       ->PostTask(FROM_HERE, base::BindOnce(&SetAttributeInternal, target,
325                                            attribute_utf8, value_utf8));
326 }
327
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,
342                       form_signature);
343     SetAttributeAsync(control_element,
344                       kDebugAttributeForAlternativeFormSignature,
345                       alternative_form_signature);
346     SetAttributeAsync(
347         control_element, kDebugAttributeForVisibility,
348         IsWebElementFocusableForAutofill(control_element) ? "true" : "false");
349   }
350 }
351
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);
360   };
361
362   WebDocument doc = frame.GetDocument();
363   return base::ranges::any_of(doc.Forms(), ContainsPasswordField,
364                               &WebFormElement::GetFormControlElements) ||
365          ContainsPasswordField(doc.UnassociatedFormControls());
366 }
367
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
370 // in the |frame|.
371 WebInputElement FindUsernameElementPrecedingPasswordElement(
372     WebLocalFrame* frame,
373     const WebInputElement& password_element) {
374   DCHECK(!password_element.IsNull());
375
376   std::vector<WebFormControlElement> elements;
377   if (password_element.Form().IsNull()) {
378     elements = form_util::GetUnownedAutofillableFormFieldElements(
379         frame->GetDocument());
380   } else {
381     elements = password_element.Form().GetFormControlElements().ReleaseVector();
382   }
383
384   auto iter = base::ranges::find(elements, password_element);
385   if (iter == elements.end())
386     return WebInputElement();
387
388   for (auto begin = elements.begin(); iter != begin;) {
389     --iter;
390     const WebInputElement input = iter->DynamicTo<WebInputElement>();
391     if (!input.IsNull() && input.IsTextField() &&
392         !input.IsPasswordFieldForAutofill() && IsElementEditable(input) &&
393         IsWebElementFocusableForAutofill(input)) {
394       return input;
395     }
396   }
397
398   return WebInputElement();
399 }
400
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();
406
407   DCHECK(cur_frame);
408
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())) {
414       return true;
415     }
416   }
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()) {
423       return true;
424     } else {
425       NOTREACHED();
426     }
427   }
428   return false;
429 }
430
431 void AnnotateFieldWithParsingResult(
432     WebDocument doc,
433     FieldRendererId renderer_id,
434     const std::string& password_managers_annotation) {
435   if (renderer_id.is_null())
436     return;
437   auto element = FindFormControlByRendererId(doc, renderer_id);
438   if (element.IsNull())
439     return;
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));
446
447   if (!base::FeatureList::IsEnabled(
448           features::test::kAutofillShowTypePredictions)) {
449     return;
450   }
451
452   if (!element.HasAttribute(kDebugAttributeForAutofill)) {
453     // No autofill tooltip yet, don't fill anything.
454     return;
455   }
456
457   std::string autofill_tooltip =
458       element.GetAttribute(kDebugAttributeForAutofill).Utf8();
459
460   element.SetAttribute(
461       kHtmlAttributeForAutofillTooltip,
462       WebString::FromUTF8(
463           base::StrCat({element.GetAttribute(kDebugAttributeForAutofill).Utf8(),
464                         "\n", kDebugAttributeForParserAnnotations, ": ",
465                         password_managers_annotation})));
466 }
467
468 bool HasDocumentWithValidFrame(const WebInputElement& element) {
469   WebFrame* frame = element.GetDocument().GetFrame();
470   return frame && frame->View();
471 }
472
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.
476 //
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;
483
484   for (auto& field : *fields) {
485     if (field.properties_mask & kFilledOrTyped)
486       continue;
487
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;
493         break;
494       }
495     }
496   }
497 }
498
499 size_t GetIndexOfElement(const FormData& form_data,
500                          const WebInputElement& element) {
501   if (element.IsNull()) {
502     return form_data.fields.size();
503   }
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)) {
507       return i;
508     }
509   }
510   return form_data.fields.size();
511 }
512
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
516 // elements.
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
521 // only two fields.
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;
528   }
529
530   if (username_element.IsNull())
531     return mojom::SubmissionReadinessState::kNoUsernameField;
532
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;
541   }
542
543   auto ShouldIgnoreField = [](const FormFieldData& field) {
544     if (!field.IsFocusable())
545       return true;
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;
551   };
552
553   for (size_t i = username_index + 1; i < password_index; ++i) {
554     if (ShouldIgnoreField(form_data.fields[i]))
555       continue;
556     return mojom::SubmissionReadinessState::kFieldBetweenUsernameAndPassword;
557   }
558
559   if (!password_element.IsLastInputElementInForm())
560     return mojom::SubmissionReadinessState::kFieldAfterPasswordField;
561
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]))
565       continue;
566
567     if (username_index != i && password_index != i &&
568         form_data.fields[i].value.empty()) {
569       return mojom::SubmissionReadinessState::kEmptyFields;
570     }
571     number_of_visible_elements++;
572   }
573
574   if (number_of_visible_elements > 2)
575     return mojom::SubmissionReadinessState::kMoreThanTwoFields;
576
577   return mojom::SubmissionReadinessState::kTwoFields;
578 }
579 #endif  // BUILDFLAG(IS_ANDROID)
580
581 }  // namespace
582
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 {
591  public:
592   explicit DeferringPasswordManagerDriver(PasswordAutofillAgent* agent)
593       : agent_(agent) {}
594   ~DeferringPasswordManagerDriver() override = default;
595
596  private:
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)...);
604   }
605   template <typename F, typename... Args>
606   void DeferMsg(F fn, Args... args) {
607     DCHECK(agent_->IsPrerendering());
608     agent_->render_frame()
609         ->GetWebFrame()
610         ->GetDocument()
611         .AddPostPrerenderingActivationStep(base::BindOnce(
612             &DeferringPasswordManagerDriver::SendMsg<F, Args...>,
613             weak_ptr_factory_.GetWeakPtr(), fn, std::forward<Args>(args)...));
614   }
615   void PasswordFormsParsed(const std::vector<FormData>& forms_data) override {
616     DeferMsg(&mojom::PasswordManagerDriver::PasswordFormsParsed, forms_data);
617   }
618   void PasswordFormsRendered(
619       const std::vector<FormData>& visible_forms_data) override {
620     DeferMsg(&mojom::PasswordManagerDriver::PasswordFormsRendered,
621              visible_forms_data);
622   }
623   void PasswordFormSubmitted(const FormData& form_data) override {
624     DeferMsg(&mojom::PasswordManagerDriver::PasswordFormSubmitted, form_data);
625   }
626   void InformAboutUserInput(const FormData& form_data) override {
627     DeferMsg(&mojom::PasswordManagerDriver::InformAboutUserInput, form_data);
628   }
629   void DynamicFormSubmission(
630       mojom::SubmissionIndicatorEvent submission_indication_event) override {
631     DeferMsg(&mojom::PasswordManagerDriver::DynamicFormSubmission,
632              submission_indication_event);
633   }
634   void PasswordFormCleared(const FormData& form_data) override {
635     DeferMsg(&mojom::PasswordManagerDriver::PasswordFormCleared, form_data);
636   }
637   void RecordSavePasswordProgress(const std::string& log) override {
638     DeferMsg(&mojom::PasswordManagerDriver::RecordSavePasswordProgress, log);
639   }
640   void UserModifiedPasswordField() override {
641     DeferMsg(&mojom::PasswordManagerDriver::UserModifiedPasswordField);
642   }
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,
649              is_likely_otp);
650   }
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,
657                                int32_t options,
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);
662   }
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);
669   }
670 #endif
671   void CheckSafeBrowsingReputation(const GURL& form_action,
672                                    const GURL& frame_url) override {
673     DeferMsg(&mojom::PasswordManagerDriver::CheckSafeBrowsingReputation,
674              form_action, frame_url);
675   }
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);
681   }
682   void LogFirstFillingResult(FormRendererId form_renderer_id,
683                              int32_t result) override {
684     DeferMsg(&mojom::PasswordManagerDriver::LogFirstFillingResult,
685              form_renderer_id, result);
686   }
687
688   raw_ptr<PasswordAutofillAgent, ExperimentalRenderer> agent_ = nullptr;
689   base::WeakPtrFactory<DeferringPasswordManagerDriver> weak_ptr_factory_{this};
690 };
691
692 ////////////////////////////////////////////////////////////////////////////////
693 // PasswordAutofillAgent, public:
694
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)));
709 }
710
711 PasswordAutofillAgent::~PasswordAutofillAgent() = default;
712
713 void PasswordAutofillAgent::Init(AutofillAgent* autofill_agent) {
714   autofill_agent_ = autofill_agent;
715 }
716
717 void PasswordAutofillAgent::BindPendingReceiver(
718     mojo::PendingAssociatedReceiver<mojom::PasswordAutofillAgent>
719         pending_receiver) {
720   receiver_.Bind(std::move(pending_receiver));
721 }
722
723 void PasswordAutofillAgent::SetPasswordGenerationAgent(
724     PasswordGenerationAgent* generation_agent) {
725   password_generation_agent_ = generation_agent;
726 }
727
728 PasswordAutofillAgent::FormStructureInfo::FormStructureInfo() = default;
729
730 PasswordAutofillAgent::FormStructureInfo::FormStructureInfo(
731     const FormStructureInfo& other) = default;
732
733 PasswordAutofillAgent::FormStructureInfo&
734 PasswordAutofillAgent::FormStructureInfo::operator=(
735     const PasswordAutofillAgent::FormStructureInfo& other) = default;
736
737 PasswordAutofillAgent::FormStructureInfo::FormStructureInfo(
738     FormStructureInfo&& other) = default;
739
740 PasswordAutofillAgent::FormStructureInfo&
741 PasswordAutofillAgent::FormStructureInfo::operator=(
742     PasswordAutofillAgent::FormStructureInfo&& other) = default;
743
744 PasswordAutofillAgent::FormStructureInfo::~FormStructureInfo() = default;
745
746 PasswordAutofillAgent::PasswordValueGatekeeper::PasswordValueGatekeeper()
747     : was_user_gesture_seen_(false) {}
748
749 PasswordAutofillAgent::PasswordValueGatekeeper::~PasswordValueGatekeeper() =
750     default;
751
752 void PasswordAutofillAgent::PasswordValueGatekeeper::RegisterElement(
753     WebInputElement* element) {
754   if (was_user_gesture_seen_)
755     ShowValue(element);
756   else
757     elements_.push_back(*element);
758 }
759
760 void PasswordAutofillAgent::PasswordValueGatekeeper::OnUserGesture() {
761   if (was_user_gesture_seen_)
762     return;
763
764   was_user_gesture_seen_ = true;
765
766   for (WebInputElement& element : elements_)
767     ShowValue(&element);
768
769   elements_.clear();
770 }
771
772 void PasswordAutofillAgent::PasswordValueGatekeeper::Reset() {
773   was_user_gesture_seen_ = false;
774   elements_.clear();
775 }
776
777 void PasswordAutofillAgent::PasswordValueGatekeeper::ShowValue(
778     WebInputElement* element) {
779   if (!element->IsNull() && !element->SuggestedValue().IsEmpty())
780     element->SetAutofillValue(element->SuggestedValue());
781 }
782
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;
788   }
789
790   // Show the popup with the list of available usernames.
791   return ShowSuggestions(element, ShowAll(false));
792 }
793
794 void PasswordAutofillAgent::UpdateStateForTextChange(
795     const WebInputElement& element) {
796   if (!element.IsTextField())
797     return;
798   // TODO(crbug.com/415449): Do this through const WebInputElement.
799   WebInputElement mutable_element = element;  // We need a non-const.
800
801   const std::u16string element_value = element.Value().Utf16();
802   field_data_manager_->UpdateFieldDataMap(
803       form_util::GetFieldRendererId(element), element_value,
804       FieldPropertiesFlags::kUserTyped);
805
806   InformBrowserAboutUserInput(element.Form(), element);
807
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
813       // value changed.
814       mutable_element.SetAutofillState(WebAutofillState::kNotFilled);
815     }
816     GetPasswordManagerDriver().UserModifiedPasswordField();
817     return;
818   }
819
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()) {
824     return;
825   }
826
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) {
831     return;
832   }
833
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();
840
841   bool is_likely_otp =
842       autofill::MatchesRegex<password_manager::constants::kOneTimePwdRe>(
843           name_attribute) ||
844       autofill::MatchesRegex<password_manager::constants::kOneTimePwdRe>(
845           id_attribute) ||
846       base::Contains(autocomplete_attribute,
847                      password_manager::constants::kAutocompleteOneTimePassword);
848
849   GetPasswordManagerDriver().UserModifiedNonPasswordField(
850       GetFieldRendererId(element), element_value,
851       base::Contains(autocomplete_attribute,
852                      password_manager::constants::kAutocompleteUsername),
853       is_likely_otp);
854 }
855
856 void PasswordAutofillAgent::TrackAutofilledElement(
857     const blink::WebFormControlElement& element) {
858   autofill_agent_->TrackAutofilledElement(element);
859 }
860
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()) {
866     return;
867   }
868
869   WebInputElement username_element;
870   WebInputElement password_element;
871   PasswordInfo* password_info = nullptr;
872
873   if (!FindPasswordInfoForElement(element, UseFallbackData(true),
874                                   &username_element, &password_element,
875                                   &password_info) ||
876       (!password_element.IsNull() && !IsElementEditable(password_element))) {
877     return;
878   }
879
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;
884   }
885
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);
890
891   if (IsUsernameAmendable(username_element,
892                           element.IsPasswordFieldForAutofill()) &&
893       !(username.empty() && element.IsPasswordFieldForAutofill()) &&
894       username_element.Value().Utf16() != username) {
895     FillField(&username_element, username);
896   }
897
898   if (!password_element.IsNull()) {
899     FillPasswordFieldAndSave(&password_element, password);
900
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
907     // Enter listener.
908     if (!username_element.IsNull() &&
909         IsWebElementFocusableForAutofill(username_element) &&
910         !IsWebElementFocusableForAutofill(password_element)) {
911       field_renderer_id_to_submit_ = GetFieldRendererId(username_element);
912     } else {
913       field_renderer_id_to_submit_ = GetFieldRendererId(password_element);
914     }
915   }
916
917   auto length = base::checked_cast<unsigned>(element.Value().length());
918   element.SetSelectionRange(length, length);
919 }
920
921 void PasswordAutofillAgent::FillIntoFocusedField(
922     bool is_password,
923     const std::u16string& credential) {
924   auto focused_input_element = focused_element().DynamicTo<WebInputElement>();
925   if (focused_input_element.IsNull() || focused_input_element.IsReadOnly()) {
926     return;
927   }
928   if (!is_password) {
929     FillField(&focused_input_element, credential);
930   }
931   if (!focused_input_element.IsPasswordFieldForAutofill()) {
932     return;
933   }
934   FillPasswordFieldAndSave(&focused_input_element, credential);
935 }
936
937 void PasswordAutofillAgent::FillField(WebInputElement* input,
938                                       const std::u16string& credential) {
939   DCHECK(input);
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);
946 }
947
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);
955 }
956
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())
964     return false;
965
966   WebInputElement username_element;
967   WebInputElement password_element;
968   PasswordInfo* password_info;
969
970   if (!FindPasswordInfoForElement(element, UseFallbackData(true),
971                                   &username_element, &password_element,
972                                   &password_info) ||
973       (!password_element.IsNull() && !IsElementEditable(password_element))) {
974     return false;
975   }
976
977   if (IsUsernameAmendable(username_element,
978                           element.IsPasswordFieldForAutofill())) {
979     if (username_query_prefix_.empty())
980       username_query_prefix_ = username_element.Value().Utf16();
981
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);
986   }
987   if (!password_element.IsNull()) {
988     password_autofill_state_ = password_element.GetAutofillState();
989     password_element.SetSuggestedValue(password);
990   }
991
992   return true;
993 }
994
995 bool PasswordAutofillAgent::DidClearAutofillSelection(
996     const WebFormControlElement& control_element) {
997   const WebInputElement element = control_element.DynamicTo<WebInputElement>();
998   if (element.IsNull())
999     return false;
1000
1001   WebInputElement username_element;
1002   WebInputElement password_element;
1003   PasswordInfo* password_info;
1004
1005   if (!FindPasswordInfoForElement(element, UseFallbackData(true),
1006                                   &username_element, &password_element,
1007                                   &password_info)) {
1008     return false;
1009   }
1010
1011   ClearPreview(&username_element, &password_element);
1012   return true;
1013 }
1014
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;
1026   } else {
1027     *password_element = element;
1028
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);
1033       return false;
1034     }
1035
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())
1042           return false;
1043         iter = last_supplied_password_info_iter_;
1044       } else {
1045         *username_element = password_iter->second;
1046       }
1047     }
1048
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;
1055       return true;
1056     }
1057     // Otherwise |username_element| has been set above.
1058   }
1059
1060   auto iter = web_input_to_password_info_.find(*username_element);
1061   if (iter == web_input_to_password_info_.end())
1062     return false;
1063
1064   *password_info = &iter->second;
1065   if (password_element->IsNull())
1066     *password_element = (*password_info)->password_field;
1067
1068   return true;
1069 }
1070
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())
1079     return;
1080   if (checked_safe_browsing_reputation_)
1081     return;
1082
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()
1087                         ? GURL()
1088                         : form_util::GetCanonicalActionForForm(element.Form());
1089   GetPasswordManagerDriver().CheckSafeBrowsingReputation(action_url, frame_url);
1090 #endif
1091 }
1092
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;
1099 }
1100
1101 bool PasswordAutofillAgent::TryToShowKeyboardReplacingSurface(
1102     const WebFormControlElement& control_element) {
1103   if (keyboard_replacing_surface_state_ !=
1104       KeyboardReplacingSurfaceState::kShouldShow) {
1105     return false;
1106   }
1107
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,
1116                                   &password_info)) {
1117     return false;
1118   }
1119
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);
1125
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) !=
1135            std::string::npos;
1136   };
1137   bool is_webauthn_form =
1138       form_data &&
1139       base::ranges::any_of(form_data->fields, has_webauthn_attribute);
1140   GetPasswordManagerDriver().ShowKeyboardReplacingSurface(
1141       form_data ? CalculateSubmissionReadiness(*form_data, username_element,
1142                                                password_element)
1143                 : mojom::SubmissionReadinessState::kNoInformation,
1144       is_webauthn_form);
1145
1146   keyboard_replacing_surface_state_ = KeyboardReplacingSurfaceState::kIsShowing;
1147   return true;
1148 }
1149 #endif
1150
1151 bool PasswordAutofillAgent::ShowSuggestions(const WebInputElement& element,
1152                                             ShowAll show_all) {
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);
1158
1159   if (!password_info) {
1160     MaybeCheckSafeBrowsingReputation(element);
1161     if (!CanShowPopupWithoutPasswords(password_element))
1162       return false;
1163   }
1164
1165   // Check that all fillable elements are editable.
1166   if (!element.IsTextField() || !IsElementEditable(element) ||
1167       (!password_element.IsNull() && !IsElementEditable(password_element))) {
1168     return true;
1169   }
1170
1171   // Don't attempt to autofill with values that are too large.
1172   if (element.Value().length() > kMaximumTextSizeForAutocomplete)
1173     return false;
1174
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) {
1182     return true;
1183   }
1184 #endif
1185
1186   if (!HasDocumentWithValidFrame(element))
1187     return false;
1188
1189   // If a username element is focused, show suggestions unless all possible
1190   // usernames are filtered.
1191   if (!element.IsPasswordFieldForAutofill()) {
1192     if (show_all ||
1193         (password_info && CanShowUsernameSuggestion(password_info->fill_data,
1194                                                     element.Value().Utf16()))) {
1195       ShowSuggestionPopup(element.Value().Utf16(), element, show_all,
1196                           OnPasswordField(false));
1197       return true;
1198     }
1199     return false;
1200   }
1201
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) {
1206     return true;
1207   }
1208
1209   // Show suggestions for password fields only while they are empty.
1210   if (!element.IsAutofilled() && !element.Value().IsEmpty()) {
1211     HidePopup();
1212     return false;
1213   }
1214
1215   ShowSuggestionPopup(std::u16string(), element, show_all,
1216                       OnPasswordField(true));
1217   return true;
1218 }
1219
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))
1226     return false;
1227   return frame->GetSecurityOrigin().CanAccessPasswordManager();
1228 }
1229
1230 void PasswordAutofillAgent::OnDynamicFormsSeen() {
1231   SendPasswordForms(false /* only_visible */);
1232 }
1233
1234 void PasswordAutofillAgent::UserGestureObserved() {
1235   autofilled_elements_cache_.clear();
1236
1237   gatekeeper_.OnUserGesture();
1238 }
1239
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;
1246     if (form_data) {
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);
1255     }
1256     std::vector<WebFormControlElement> form_fields =
1257         form_util::ExtractAutofillableElementsInForm(form);
1258     AnnotateFieldsWithSignatures(form_fields, form_signature,
1259                                  alternative_form_signature);
1260   }
1261
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;
1268   if (form_data) {
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);
1274   }
1275   AnnotateFieldsWithSignatures(unowned_elements, form_signature,
1276                                alternative_form_signature);
1277 }
1278
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);
1286   }
1287
1288   WebLocalFrame* frame = render_frame()->GetWebFrame();
1289
1290   // Make sure that this security origin is allowed to use password manager.
1291   blink::WebSecurityOrigin origin = frame->GetDocument().GetSecurityOrigin();
1292   if (logger) {
1293     logger->LogURL(Logger::STRING_SECURITY_ORIGIN,
1294                    GURL(origin.ToString().Utf8()));
1295   }
1296   if (!FrameCanAccessPasswordManager()) {
1297     LogMessage(logger.get(), Logger::STRING_SECURITY_ORIGIN_FAILURE);
1298     return;
1299   }
1300
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);
1304     return;
1305   }
1306
1307   WebVector<WebFormElement> forms = frame->GetDocument().Forms();
1308
1309   if (IsShowAutofillSignaturesEnabled())
1310     AnnotateFormsAndFieldsWithSignatures(forms);
1311   if (logger)
1312     logger->LogNumber(Logger::STRING_NUMBER_OF_ALL_FORMS, forms.size());
1313
1314   std::vector<FormData> password_forms_data;
1315   for (const WebFormElement& form : forms) {
1316     if (only_visible) {
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);
1321
1322       // If requested, ignore non-rendered forms, e.g., those styled with
1323       // display:none.
1324       if (!is_form_visible)
1325         continue;
1326     }
1327
1328     std::unique_ptr<FormData> form_data(GetFormDataFromWebForm(form));
1329     if (!form_data || !IsRendererRecognizedCredentialForm(*form_data)) {
1330       continue;
1331     }
1332
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);
1338
1339       password_forms_data.push_back(std::move(*form_data));
1340       continue;
1341     }
1342
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);
1348   }
1349
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;
1355   if (only_visible) {
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);
1363   }
1364
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));
1369     }
1370   }
1371
1372   if (only_visible) {
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);
1377   } else {
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();
1385     }
1386     if (!password_forms_data.empty()) {
1387       sent_request_to_store_ = true;
1388       GetPasswordManagerDriver().PasswordFormsParsed(password_forms_data);
1389     }
1390   }
1391
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);
1398 #endif
1399 }
1400
1401 void PasswordAutofillAgent::DidDispatchDOMContentLoadedEvent() {
1402   SendPasswordForms(false);
1403 }
1404
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
1409   // form.
1410   SendPasswordForms(true);
1411 }
1412
1413 void PasswordAutofillAgent::DidCommitProvisionalLoad(
1414     ui::PageTransition transition) {
1415   checked_safe_browsing_reputation_ = false;
1416   recorded_first_filling_result_ = false;
1417 }
1418
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
1424   // on purpose.
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);
1431   }
1432   CleanupOnDocumentShutdown();
1433 }
1434
1435 void PasswordAutofillAgent::OnDestruct() {
1436   receiver_.reset();
1437 }
1438
1439 bool PasswordAutofillAgent::IsPrerendering() const {
1440   return render_frame()->GetWebFrame()->GetDocument().IsPrerendering();
1441 }
1442
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);
1447 }
1448
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);
1456   }
1457
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
1461     // passwords.
1462     gatekeeper_.Reset();
1463   } else {
1464     LogMessage(logger.get(), Logger::STRING_FRAME_NOT_MAIN_FRAME);
1465   }
1466
1467   CleanupOnDocumentShutdown();
1468 }
1469
1470 void PasswordAutofillAgent::OnProbablyFormSubmitted() {}
1471
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;
1478 #endif
1479
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);
1485   }
1486
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);
1494     return;
1495   }
1496
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);
1508     return;
1509   }
1510
1511   StoreDataForFillOnAccountSelect(form_data, username_element,
1512                                   password_element);
1513
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
1519 #else
1520     LogFirstFillingResult(form_data, FillingResult::kWaitForUsername);
1521     return;
1522 #endif
1523   }
1524
1525   FillUserNameAndPassword(username_element, password_element, form_data,
1526                           logger.get());
1527 #if BUILDFLAG(IS_TIZEN_TV)
1528   if (SupportAutoLogin())
1529     SubmitFormForAutoLogin(password_element);
1530 #endif
1531 }
1532
1533 void PasswordAutofillAgent::SetLoggingState(bool active) {
1534   logging_state_active_ = active;
1535 }
1536
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");
1549 }
1550
1551 void PasswordAutofillAgent::InformNoSavedCredentials(
1552     bool should_show_popup_without_passwords) {
1553   should_show_popup_without_passwords_ = should_show_popup_without_passwords;
1554
1555   autofilled_elements_cache_.clear();
1556
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())
1564       continue;
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());
1569     }
1570     element.SetSuggestedValue(blink::WebString());
1571   }
1572   all_autofilled_elements_.clear();
1573
1574   field_data_manager_->ClearData();
1575 }
1576
1577 #if BUILDFLAG(IS_ANDROID)
1578 void PasswordAutofillAgent::KeyboardReplacingSurfaceClosed(
1579     bool show_virtual_keyboard) {
1580   keyboard_replacing_surface_state_ = KeyboardReplacingSurfaceState::kWasShown;
1581
1582   auto focused_input_element = focused_element().DynamicTo<WebInputElement>();
1583   if (focused_input_element.IsNull() || focused_element().IsReadOnly()) {
1584     return;
1585   }
1586
1587   if (show_virtual_keyboard) {
1588     render_frame()->ShowVirtualKeyboard();
1589
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
1594     // time.
1595     if (IsKeyboardAccessoryEnabled()) {
1596       ShowSuggestions(focused_input_element, ShowAll(false));
1597     }
1598   }
1599 }
1600
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.
1608     return;
1609   }
1610
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();
1615 }
1616 #endif
1617
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_);
1623 }
1624
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();
1632   if (!frame)
1633     return nullptr;
1634   WebLocalFrame* web_frame = frame->GetWebFrame();
1635   if (!web_frame)
1636     return nullptr;
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_
1641           : nullptr);
1642 }
1643
1644 void PasswordAutofillAgent::InformAboutFormClearing(
1645     const WebFormElement& form) {
1646   if (!FrameCanAccessPasswordManager())
1647     return;
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);
1653       return;
1654     }
1655   }
1656 }
1657
1658 void PasswordAutofillAgent::InformAboutFieldClearing(
1659     const WebInputElement& cleared_element) {
1660   if (!FrameCanAccessPasswordManager())
1661     return;
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)) {
1667     return;
1668   }
1669
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);
1675     return;
1676   }
1677   // Process field clearing for a form under a <form> tag.
1678   // Only notify PasswordManager in case all user filled password fields were
1679   // cleared.
1680   bool cleared_all_password_fields = base::ranges::all_of(
1681       form.GetFormControlElements(), [this](const auto& el) {
1682         return !IsPasswordFieldFilledByUser(el) || el.Value().IsEmpty();
1683       });
1684   if (cleared_all_password_fields)
1685     NotifyPasswordManagerAboutClearedForm(form);
1686 }
1687
1688 ////////////////////////////////////////////////////////////////////////////////
1689 // PasswordAutofillAgent, private:
1690
1691 void PasswordAutofillAgent::ShowSuggestionPopup(
1692     const std::u16string& typed_username,
1693     const WebInputElement& user_input,
1694     ShowAll show_all,
1695     OnPasswordField show_on_password_field) {
1696   username_query_prefix_ = typed_username;
1697   FormData form;
1698   FormFieldData field;
1699   form_util::FindFormAndFieldForFormControlElement(
1700       user_input, field_data_manager_.get(), /*extract_options=*/{}, &form,
1701       &field);
1702
1703   int options = 0;
1704   if (show_all)
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;
1710
1711   WebInputElement username_element;
1712   WebInputElement password_element;
1713   PasswordInfo* password_info = nullptr;
1714   FindPasswordInfoForElement(user_input, UseFallbackData(false),
1715                              &username_element, &password_element,
1716                              &password_info);
1717
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));
1723 }
1724
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;
1747 #endif
1748 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
1749   page_passwords_analyser_.Reset();
1750 #endif
1751 }
1752
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()));
1761   }
1762   if (!password->IsNull() && !password->SuggestedValue().IsEmpty()) {
1763     if (base::FeatureList::IsEnabled(blink::features::kPasswordStrongLabel)) {
1764       password->SetShouldShowStrongPasswordLabel(false);
1765     }
1766     password->SetSuggestedValue(WebString());
1767     password->SetAutofillState(password_autofill_state_);
1768   }
1769 }
1770 void PasswordAutofillAgent::InformBrowserAboutUserInput(
1771     const WebFormElement& form,
1772     const WebInputElement& element) {
1773   DCHECK(!form.IsNull() || !element.IsNull());
1774   if (!FrameCanAccessPasswordManager())
1775     return;
1776   SetLastUpdatedFormAndField(form, element);
1777   std::unique_ptr<FormData> form_data =
1778       form.IsNull() ? GetFormDataFromUnownedInputElements()
1779                     : GetFormDataFromWebForm(form);
1780   if (!form_data)
1781     return;
1782
1783   if (!IsRendererRecognizedCredentialForm(*form_data)) {
1784     return;
1785   }
1786
1787   GetPasswordManagerDriver().InformAboutUserInput(*form_data);
1788
1789   browser_has_form_to_process_ = true;
1790 }
1791
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);
1798
1799   bool is_single_username_fill = password_element.IsNull();
1800   WebInputElement main_element =
1801       is_single_username_fill ? username_element : password_element;
1802
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
1814   }
1815 #else
1816   if (IsInCrossOriginIframeOrEmbeddedFrame(main_element)) {
1817     LogMessage(logger, Logger::STRING_FAILED_TO_FILL_INTO_IFRAME);
1818     LogFirstFillingResult(fill_data, FillingResult::kBlockedByFrameHierarchy);
1819     return false;
1820   }
1821 #endif
1822
1823   // Don't fill username if password can't be set.
1824   if (!IsElementEditable(main_element)) {
1825     LogMessage(logger,
1826                Logger::STRING_FAILED_TO_FILL_NO_AUTOCOMPLETEABLE_ELEMENT);
1827     LogFirstFillingResult(fill_data,
1828                           FillingResult::kPasswordElementIsNotAutocompleteable);
1829     return false;
1830   }
1831
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
1838   // autocompletable.
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;
1842
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;
1847
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);
1853
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)));
1862
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;
1872     }
1873   }
1874
1875   // |username| and |password| will contain the match found if any.
1876   std::u16string username;
1877   std::u16string password;
1878
1879   bool exact_username_match =
1880       username_element.IsNull() || IsElementEditable(username_element);
1881
1882   FindMatchesByUsername(fill_data, current_username, exact_username_match,
1883                         logger, &username, &password);
1884
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);
1890
1891       LogMessage(logger, Logger::STRING_FAILED_TO_FILL_PREFILLED_USERNAME);
1892       LogFirstFillingResult(
1893           fill_data, FillingResult::kUsernamePrefilledWithIncompatibleValue);
1894       return false;
1895     }
1896     LogMessage(logger,
1897                Logger::STRING_FAILED_TO_FILL_FOUND_NO_PASSWORD_FOR_USERNAME);
1898     LogFirstFillingResult(fill_data,
1899                           FillingResult::kFoundNoPasswordForUsername);
1900     return false;
1901   }
1902
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);
1907
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);
1917     }
1918 #else
1919       AutofillField(username, username_element);
1920       if (prefilled_placeholder_username) {
1921         LogPrefilledUsernameFillOutcome(
1922             PrefilledUsernameFillOutcome::
1923                 kPrefilledPlaceholderUsernameOverridden);
1924       }
1925     }
1926 #endif
1927     if (logger)
1928       logger->LogElementName(Logger::STRING_USERNAME_FILLED, username_element);
1929   }
1930
1931   if (!is_single_username_fill) {
1932 #if defined(TIZEN_AUTOFILL_FW)
1933     FillPasswordFieldAndSave(&password_element, password);
1934 #else
1935     AutofillField(password, password_element);
1936 #endif
1937     if (logger)
1938       logger->LogElementName(Logger::STRING_PASSWORD_FILLED, password_element);
1939   }
1940
1941   LogFirstFillingResult(fill_data, FillingResult::kSuccess);
1942   return true;
1943 }
1944
1945 void PasswordAutofillAgent::LogPrefilledUsernameFillOutcome(
1946     PrefilledUsernameFillOutcome outcome) {
1947   if (prefilled_username_metrics_logged_)
1948     return;
1949   prefilled_username_metrics_logged_ = true;
1950   UMA_HISTOGRAM_ENUMERATION("PasswordManager.PrefilledUsernameFillOutcome",
1951                             outcome);
1952 }
1953
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)
1960     return;
1961
1962   WebInputElement input_element = element.DynamicTo<WebInputElement>();
1963
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);
1968     return;
1969   }
1970
1971   DCHECK_EQ(ElementChangeSource::WILL_SEND_SUBMIT_EVENT, source);
1972   InformBrowserAboutUserInput(form, input_element);
1973 }
1974
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);
1981   }
1982
1983   if (!FrameCanAccessPasswordManager()) {
1984     LogMessage(logger.get(), Logger::STRING_SECURITY_ORIGIN_FAILURE);
1985     return;
1986   }
1987
1988   std::unique_ptr<FormData> submitted_form_data = GetFormDataFromWebForm(form);
1989
1990   if (!submitted_form_data)
1991     return;
1992
1993   submitted_form_data->submission_event =
1994       SubmissionIndicatorEvent::HTML_FORM_SUBMISSION;
1995
1996   FillNonTypedOrFilledPropertiesMasks(&submitted_form_data->fields,
1997                                       *field_data_manager_);
1998
1999   GetPasswordManagerDriver().PasswordFormSubmitted(*submitted_form_data);
2000   browser_has_form_to_process_ = false;
2001 }
2002
2003 void PasswordAutofillAgent::OnInferredFormSubmission(SubmissionSource source) {
2004   switch (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:
2010       OnFrameDetached();
2011       return;
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));
2020       }
2021       return;
2022   }
2023 }
2024
2025 void PasswordAutofillAgent::HidePopup() {
2026   if (autofill_agent_->unsafe_autofill_driver()) {
2027     autofill_agent_->unsafe_autofill_driver()->HidePopup();
2028   }
2029 }
2030
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);
2037     }
2038     return *deferring_password_manager_driver_;
2039   }
2040
2041   // Lazily bind this interface.
2042   if (!password_manager_driver_) {
2043     render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
2044         &password_manager_driver_);
2045   }
2046
2047   return *password_manager_driver_;
2048 }
2049
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();
2059
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);
2065
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);
2072
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>();
2078
2079   // Set username element.
2080   WebInputElement username_field;
2081   if (is_username_present)
2082     username_field = elements[current_index++].DynamicTo<WebInputElement>();
2083
2084   return std::make_pair(username_field, password_field);
2085 }
2086
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;
2093
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;
2102 }
2103
2104 void PasswordAutofillAgent::MaybeStoreFallbackData(
2105     const PasswordFormFillData& form_data) {
2106   if (!web_input_to_password_info_.empty())
2107     return;
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();
2118 }
2119
2120 void PasswordAutofillAgent::LogFirstFillingResult(
2121     const PasswordFormFillData& form_data,
2122     FillingResult result) {
2123   if (recorded_first_filling_result_)
2124     return;
2125   UMA_HISTOGRAM_ENUMERATION("PasswordManager.FirstRendererFillingResult",
2126                             result);
2127   GetPasswordManagerDriver().LogFirstFillingResult(
2128       form_data.form_renderer_id, base::strict_cast<int32_t>(result));
2129   recorded_first_filling_result_ = true;
2130 }
2131
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());
2137
2138   for (size_t i = 0; i < form_data.fields.size(); ++i) {
2139     const FormFieldData& form_field = form_data.fields[i];
2140
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;
2147   }
2148
2149   return result;
2150 }
2151
2152 bool PasswordAutofillAgent::WasFormStructureChanged(
2153     const FormStructureInfo& form_info) const {
2154   if (form_info.unique_renderer_id.is_null())
2155     return true;
2156
2157   auto cached_form = forms_structure_cache_.find(form_info.unique_renderer_id);
2158   if (cached_form == forms_structure_cache_.end())
2159     return true;
2160
2161   const FormStructureInfo& cached_form_info = cached_form->second;
2162
2163   if (form_info.fields.size() != cached_form_info.fields.size())
2164     return true;
2165
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];
2169
2170     if (form_field.unique_renderer_id != cached_form_field.unique_renderer_id)
2171       return true;
2172
2173     if (form_field.form_control_type != cached_form_field.form_control_type)
2174       return true;
2175
2176     if (form_field.autocomplete_attribute !=
2177         cached_form_field.autocomplete_attribute) {
2178       return true;
2179     }
2180
2181     if (form_field.is_focusable != cached_form_field.is_focusable)
2182       return true;
2183   }
2184   return false;
2185 }
2186
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())
2193       continue;
2194
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);
2202   }
2203 }
2204
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))
2210     return;
2211
2212   if (field.Value().Utf16() == value)
2213     return;
2214
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);
2225 }
2226
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);
2233 }
2234
2235 bool PasswordAutofillAgent::CanShowPopupWithoutPasswords(
2236     const WebInputElement& password_element) const {
2237   return should_show_popup_without_passwords_ && !password_element.IsNull() &&
2238          IsElementEditable(password_element);
2239 }
2240
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));
2248 }
2249
2250 void PasswordAutofillAgent::NotifyPasswordManagerAboutClearedForm(
2251     const WebFormElement& cleared_form) {
2252   const auto extract_options = {ExtractOption::kValue, ExtractOption::kOptions};
2253   FormData form_data;
2254   if (WebFormElementToFormData(cleared_form, WebFormControlElement(),
2255                                field_data_manager_.get(), extract_options,
2256                                &form_data, /*field=*/nullptr)) {
2257     GetPasswordManagerDriver().PasswordFormCleared(form_data);
2258   }
2259 }
2260
2261 #if BUILDFLAG(IS_TIZEN_TV)
2262 void PasswordAutofillAgent::SendEnterKeyBoardEvent() {
2263   if (!render_frame())
2264     return;
2265   blink::WebView* web_view = render_frame()->GetWebView();
2266   if (!web_view)
2267     return;
2268   blink::WebWidget* widget = web_view->MainFrameWidget();
2269
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()));
2281 }
2282
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 == '_'; }),
2287                value->end());
2288 }
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) {
2294   DCHECK(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);
2300
2301     if (filtered_value.empty())
2302       continue;
2303     for (size_t j = 0; j < number_of_features; ++j) {
2304       if (filtered_value.find(features[j]) != std::string::npos)
2305         return true;
2306     }
2307   }
2308 #endif
2309   return false;
2310 }
2311
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);
2317 }
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;
2323
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))
2329       continue;
2330
2331     if (FindTextFeaturesForClass(element, kCaptchaFeatures,
2332                                  kNumberOfCaptchaFeatures)) {
2333       return true;
2334     }
2335   }
2336   return false;
2337 }
2338
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";
2345     return;
2346   }
2347   if (FindCaptchaInImgElements(password_input.Form())) {
2348     LOG(INFO) << "[Autofill] - " << __FUNCTION__
2349               << " Page include captcha image, do not autologin";
2350     return;
2351   }
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.
2357
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
2361   render_frame()
2362       ->GetTaskRunner(blink::TaskType::kInternalUserInteraction)
2363       ->PostDelayedTask(
2364           FROM_HERE,
2365           base::BindOnce(&PasswordAutofillAgent::SendEnterKeyBoardEvent,
2366                          base::Unretained(this)),
2367           base::Milliseconds(kSendEnterKeyTimeout));
2368 }
2369
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.
2375
2376   const std::string tizen_app_id =
2377       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
2378           switches::kTizenAppId);
2379   return tizen_app_id == "org.tizen.browser";
2380 }
2381 #endif
2382
2383 }  // namespace autofill