| Index: components/autofill/content/renderer/password_generation_agent.cc
|
| diff --git a/components/autofill/content/renderer/password_generation_agent.cc b/components/autofill/content/renderer/password_generation_agent.cc
|
| index bf50f220493544252111f122723c9c80668fe832..f9fe4c97345751f016629265c79bd45d9554e130 100644
|
| --- a/components/autofill/content/renderer/password_generation_agent.cc
|
| +++ b/components/autofill/content/renderer/password_generation_agent.cc
|
| @@ -4,7 +4,9 @@
|
|
|
| #include "components/autofill/content/renderer/password_generation_agent.h"
|
|
|
| +#include <algorithm>
|
| #include <memory>
|
| +#include <utility>
|
|
|
| #include "base/command_line.h"
|
| #include "base/logging.h"
|
| @@ -39,17 +41,17 @@ namespace {
|
|
|
| using Logger = autofill::SavePasswordProgressLogger;
|
|
|
| -// Returns true if we think that this form is for account creation. |passwords|
|
| -// is filled with the password field(s) in the form.
|
| +// Returns true if we think that this form is for account creation. Password
|
| +// field(s) of the form are pushed back to |passwords|.
|
| bool GetAccountCreationPasswordFields(
|
| const std::vector<blink::WebFormControlElement>& control_elements,
|
| std::vector<blink::WebInputElement>* passwords) {
|
| - for (size_t i = 0; i < control_elements.size(); i++) {
|
| + for (const auto& control_element : control_elements) {
|
| const blink::WebInputElement* input_element =
|
| - ToWebInputElement(&control_elements[i]);
|
| - if (input_element && input_element->IsTextField()) {
|
| - if (input_element->IsPasswordField())
|
| - passwords->push_back(*input_element);
|
| + ToWebInputElement(&control_element);
|
| + if (input_element && input_element->IsTextField() &&
|
| + input_element->IsPasswordField()) {
|
| + passwords->push_back(*input_element);
|
| }
|
| }
|
| return !passwords->empty();
|
| @@ -71,10 +73,33 @@ const PasswordFormGenerationData* FindFormGenerationData(
|
| return nullptr;
|
| }
|
|
|
| -// This function returns a vector of password fields into which Chrome should
|
| -// fill the generated password. It assumes that |field_signature| describes the
|
| -// field where Chrome shows the password generation prompt. It returns no more
|
| -// than 2 elements.
|
| +// Returns a vector of up to 2 password fields with autocomplete attribute set
|
| +// to "new-password". These will be filled with the generated password.
|
| +std::vector<blink::WebInputElement> FindNewPasswordElementsMarkedBySite(
|
| + const std::vector<blink::WebInputElement>& all_password_elements) {
|
| + std::vector<blink::WebInputElement> passwords;
|
| +
|
| + auto is_new_password_field = [](const blink::WebInputElement& element) {
|
| + return HasAutocompleteAttributeValue(element, "new-password");
|
| + };
|
| +
|
| + auto field_iter =
|
| + std::find_if(all_password_elements.begin(), all_password_elements.end(),
|
| + is_new_password_field);
|
| + if (field_iter != all_password_elements.end()) {
|
| + passwords.push_back(*field_iter++);
|
| + field_iter = std::find_if(field_iter, all_password_elements.end(),
|
| + is_new_password_field);
|
| + if (field_iter != all_password_elements.end())
|
| + passwords.push_back(*field_iter);
|
| + }
|
| +
|
| + return passwords;
|
| +}
|
| +
|
| +// Returns a vector of up to 2 password fields into which Chrome should fill the
|
| +// generated password. It assumes that |field_signature| describes the field
|
| +// where Chrome shows the password generation prompt.
|
| std::vector<blink::WebInputElement> FindPasswordElementsForGeneration(
|
| const std::vector<blink::WebInputElement>& all_password_elements,
|
| const PasswordFormGenerationData& generation_data) {
|
| @@ -85,11 +110,12 @@ std::vector<blink::WebInputElement> FindPasswordElementsForGeneration(
|
| const blink::WebInputElement& input = *iter;
|
| FieldSignature signature = CalculateFieldSignatureByNameAndType(
|
| input.NameForAutofill().Utf16(), input.FormControlType().Utf8());
|
| - if (signature == generation_data.field_signature)
|
| + if (signature == generation_data.field_signature) {
|
| generation_field_iter = iter;
|
| - else if (generation_data.confirmation_field_signature &&
|
| - signature == *generation_data.confirmation_field_signature)
|
| + } else if (generation_data.confirmation_field_signature &&
|
| + signature == *generation_data.confirmation_field_signature) {
|
| confirmation_field_iter = iter;
|
| + }
|
| }
|
|
|
| std::vector<blink::WebInputElement> passwords;
|
| @@ -114,17 +140,12 @@ void CopyElementValueToOtherInputElements(
|
| }
|
| }
|
|
|
| -bool AutocompleteAttributesSetForGeneration(const PasswordForm& form) {
|
| - return form.username_marked_by_site && form.new_password_marked_by_site;
|
| -}
|
| -
|
| } // namespace
|
|
|
| PasswordGenerationAgent::AccountCreationFormData::AccountCreationFormData(
|
| linked_ptr<PasswordForm> password_form,
|
| std::vector<blink::WebInputElement> passwords)
|
| - : form(password_form),
|
| - password_elements(passwords) {}
|
| + : form(password_form), password_elements(std::move(passwords)) {}
|
|
|
| PasswordGenerationAgent::AccountCreationFormData::AccountCreationFormData(
|
| const AccountCreationFormData& other) = default;
|
| @@ -277,9 +298,8 @@ void PasswordGenerationAgent::FindPossibleGenerationForm() {
|
| &passwords)) {
|
| if (form_classifier_enabled_)
|
| RunFormClassifierAndSaveVote(forms[i], *password_form);
|
| - AccountCreationFormData ac_form_data(
|
| - make_linked_ptr(password_form.release()), passwords);
|
| - possible_account_creation_forms_.push_back(ac_form_data);
|
| + possible_account_creation_forms_.emplace_back(
|
| + make_linked_ptr(password_form.release()), std::move(passwords));
|
| }
|
| }
|
|
|
| @@ -389,8 +409,11 @@ void PasswordGenerationAgent::DetermineGenerationElement() {
|
| for (auto& possible_form_data : possible_account_creation_forms_) {
|
| PasswordForm* possible_password_form = possible_form_data.form.get();
|
| const PasswordFormGenerationData* generation_data = nullptr;
|
| +
|
| + std::vector<blink::WebInputElement> password_elements;
|
| if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
| switches::kLocalHeuristicsOnlyForPasswordGeneration)) {
|
| + password_elements = possible_form_data.password_elements;
|
| VLOG(2) << "Bypassing additional checks.";
|
| } else if (!ContainsURL(not_blacklisted_password_form_origins_,
|
| possible_password_form->origin)) {
|
| @@ -399,28 +422,31 @@ void PasswordGenerationAgent::DetermineGenerationElement() {
|
| } else {
|
| generation_data = FindFormGenerationData(generation_enabled_forms_,
|
| *possible_password_form);
|
| - if (!generation_data) {
|
| - if (AutocompleteAttributesSetForGeneration(*possible_password_form)) {
|
| - LogMessage(Logger::STRING_GENERATION_RENDERER_AUTOCOMPLETE_ATTRIBUTE);
|
| - password_generation::LogPasswordGenerationEvent(
|
| - password_generation::AUTOCOMPLETE_ATTRIBUTES_ENABLED_GENERATION);
|
| - } else {
|
| + if (generation_data) {
|
| + password_elements = FindPasswordElementsForGeneration(
|
| + possible_form_data.password_elements, *generation_data);
|
| + } else {
|
| + if (!possible_password_form->new_password_marked_by_site) {
|
| LogMessage(Logger::STRING_GENERATION_RENDERER_NO_SERVER_SIGNAL);
|
| continue;
|
| }
|
| +
|
| + LogMessage(Logger::STRING_GENERATION_RENDERER_AUTOCOMPLETE_ATTRIBUTE);
|
| + password_generation::LogPasswordGenerationEvent(
|
| + password_generation::AUTOCOMPLETE_ATTRIBUTES_ENABLED_GENERATION);
|
| +
|
| + password_elements = FindNewPasswordElementsMarkedBySite(
|
| + possible_form_data.password_elements);
|
| }
|
| }
|
| +
|
| LogMessage(Logger::STRING_GENERATION_RENDERER_ELIGIBLE_FORM_FOUND);
|
| - std::vector<blink::WebInputElement> password_elements =
|
| - generation_data
|
| - ? FindPasswordElementsForGeneration(
|
| - possible_form_data.password_elements, *generation_data)
|
| - : possible_form_data.password_elements;
|
| if (password_elements.empty()) {
|
| // It might be if JavaScript changes field names.
|
| LogMessage(Logger::STRING_GENERATION_RENDERER_NO_FIELD_FOUND);
|
| return;
|
| }
|
| +
|
| generation_form_data_.reset(new AccountCreationFormData(
|
| possible_form_data.form, std::move(password_elements)));
|
| generation_element_ = generation_form_data_->password_elements[0];
|
|
|