summaryrefslogtreecommitdiff
path: root/chromium/components/autofill/content/renderer/password_generation_agent.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/autofill/content/renderer/password_generation_agent.cc')
-rw-r--r--chromium/components/autofill/content/renderer/password_generation_agent.cc102
1 files changed, 65 insertions, 37 deletions
diff --git a/chromium/components/autofill/content/renderer/password_generation_agent.cc b/chromium/components/autofill/content/renderer/password_generation_agent.cc
index bf50f220493..210d4f514f7 100644
--- a/chromium/components/autofill/content/renderer/password_generation_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_generation_agent.cc
@@ -4,10 +4,13 @@
#include "components/autofill/content/renderer/password_generation_agent.h"
+#include <algorithm>
#include <memory>
+#include <utility>
#include "base/command_line.h"
#include "base/logging.h"
+#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/content/renderer/form_classifier.h"
@@ -39,24 +42,24 @@ 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();
}
bool ContainsURL(const std::vector<GURL>& urls, const GURL& url) {
- return std::find(urls.begin(), urls.end(), url) != urls.end();
+ return base::ContainsValue(urls, url);
}
// Calculates the signature of |form| and searches it in |forms|.
@@ -71,10 +74,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 +111,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 +141,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;
@@ -152,7 +174,6 @@ PasswordGenerationAgent::PasswordGenerationAgent(
PasswordGenerationAgent::~PasswordGenerationAgent() {}
void PasswordGenerationAgent::BindRequest(
- const service_manager::BindSourceInfo& source_info,
mojom::PasswordGenerationAgentRequest request) {
binding_.Bind(std::move(request));
}
@@ -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));
}
}
@@ -314,6 +334,7 @@ void PasswordGenerationAgent::FormNotBlacklisted(const PasswordForm& form) {
void PasswordGenerationAgent::GeneratedPasswordAccepted(
const base::string16& password) {
password_is_generated_ = true;
+ password_edited_ = false;
password_generation::LogPasswordGenerationEvent(
password_generation::PASSWORD_ACCEPTED);
LogMessage(Logger::STRING_GENERATION_RENDERER_GENERATED_PASSWORD_ACCEPTED);
@@ -389,8 +410,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 +423,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];
@@ -539,6 +566,7 @@ void PasswordGenerationAgent::HidePopup() {
void PasswordGenerationAgent::PasswordNoLongerGenerated() {
// Do not treat the password as generated, either here or in the browser.
password_is_generated_ = false;
+ password_edited_ = false;
generation_element_.SetShouldRevealPassword(false);
for (blink::WebInputElement& password :
generation_form_data_->password_elements)
@@ -563,7 +591,7 @@ void PasswordGenerationAgent::UserTriggeredGeneratePassword() {
password_form = CreatePasswordFormFromWebForm(form, nullptr, nullptr);
control_elements = form_util::ExtractAutofillableElementsInForm(form);
} else {
- const blink::WebFrame& frame = *render_frame()->GetWebFrame();
+ const blink::WebLocalFrame& frame = *render_frame()->GetWebFrame();
blink::WebDocument doc = frame.GetDocument();
if (doc.IsNull())
return;