Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(267)

Unified Diff: components/autofill/content/renderer/password_autofill_agent.cc

Issue 548953002: [Password Manager] Modified to support saving passwords on forms without username fields. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/autofill/content/renderer/password_autofill_agent.cc
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index 86ff3779dc76fb185f1e36c899ca5c95f9d6cf88..3a0391768ed7b332543e8831c2fb35a39a965b69 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -71,6 +71,11 @@ static bool FindFormInputElements(blink::WebFormElement* fe,
// autofill it. If we don't find any one of them, abort processing this
// form; it can't be the right one.
for (size_t j = 0; j < data.fields.size(); j++) {
+ // The password form may not contain a username field
+ // (http://crbug.com/406343), but continue autofilling password field.
+ if (data.fields[j].name.empty())
vabr (Chromium) 2014/09/24 16:17:21 Looking at InitPasswordFormFillData, the username
Pritam Nikam 2014/09/25 07:22:28 Done. I've refactored code, and these changes are
+ continue;
+
blink::WebVector<blink::WebNode> temp_elements;
fe->getNamedElements(data.fields[j].name, temp_elements);
@@ -218,6 +223,10 @@ void LogHTMLForm(SavePasswordProgressLogger* logger,
GURL(form.action().utf8()));
}
+bool FillDataContainsUsername(const PasswordFormFillData& fill_data) {
+ return !fill_data.basic_data.fields[0].name.empty();
+}
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -802,13 +811,22 @@ void PasswordAutofillAgent::OnFillPasswordForm(
scoped_ptr<FormElements> form_elements(*iter);
// Attach autocomplete listener to enable selecting alternate logins.
- // First, get pointers to username element.
- blink::WebInputElement username_element =
- form_elements->input_elements[form_data.basic_data.fields[0].name];
+ blink::WebInputElement username_element, password_element;
+
+ // Check whether the password form has a username input field.
+ bool form_contains_username_field = FillDataContainsUsername(form_data);
+ if (form_contains_username_field) {
+ username_element =
+ form_elements->input_elements[form_data.basic_data.fields[0].name];
+ }
+
+ // No password field, bail out.
+ if (form_data.basic_data.fields[1].name.empty())
+ break;
// Get pointer to password element. (We currently only support single
// password forms).
- blink::WebInputElement password_element =
+ password_element =
form_elements->input_elements[form_data.basic_data.fields[1].name];
// If wait_for_username is true, we don't want to initially fill the form
@@ -830,8 +848,11 @@ void PasswordAutofillAgent::OnFillPasswordForm(
FormData form;
FormFieldData field;
- FindFormAndFieldForFormControlElement(
- username_element, &form, &field, REQUIRE_NONE);
+ if (form_contains_username_field) {
+ FindFormAndFieldForFormControlElement(
+ username_element, &form, &field, REQUIRE_NONE);
+ }
+
Send(new AutofillHostMsg_AddPasswordFormMapping(
routing_id(), field, form_data));
}
@@ -929,8 +950,9 @@ void PasswordAutofillAgent::FillFormOnPasswordRecieved(
if (password_element.document().frame()->parent())
return;
+ bool form_contains_username_field = FillDataContainsUsername(fill_data);
if (!ShouldIgnoreAutocompleteOffForPasswordFields() &&
- !username_element.form().autoComplete())
+ form_contains_username_field && !username_element.form().autoComplete())
return;
// If we can't modify the password, don't try to set the username
@@ -939,7 +961,8 @@ void PasswordAutofillAgent::FillFormOnPasswordRecieved(
// Try to set the username to the preferred name, but only if the field
// can be set and isn't prefilled.
- if (IsElementAutocompletable(username_element) &&
+ if (form_contains_username_field &&
+ IsElementAutocompletable(username_element) &&
username_element.value().isEmpty()) {
// TODO(tkent): Check maxlength and pattern.
username_element.setValue(fill_data.basic_data.fields[0].value, true);
@@ -960,7 +983,6 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
const PasswordFormFillData& fill_data,
bool exact_username_match,
bool set_selection) {
- base::string16 current_username = username_element->value();
// username and password will contain the match found if any.
base::string16 username;
base::string16 password;
@@ -969,65 +991,71 @@ bool PasswordAutofillAgent::FillUserNameAndPassword(
if (!IsElementAutocompletable(*password_element))
return false;
- // Look for any suitable matches to current field text.
- if (DoUsernamesMatch(fill_data.basic_data.fields[0].value,
vabr (Chromium) 2014/09/24 16:17:21 Wouldn't this actually work just fine if there was
Pritam Nikam 2014/09/25 07:22:27 Done. Right! I did it this way now.
vabr (Chromium) 2014/09/25 10:39:59 Actually, I don't think you did it the way suggest
- current_username,
- exact_username_match)) {
- username = fill_data.basic_data.fields[0].value;
- password = fill_data.basic_data.fields[1].value;
- } else {
- // Scan additional logins for a match.
- PasswordFormFillData::LoginCollection::const_iterator iter;
- for (iter = fill_data.additional_logins.begin();
- iter != fill_data.additional_logins.end();
- ++iter) {
- if (DoUsernamesMatch(
- iter->first, current_username, exact_username_match)) {
- username = iter->first;
- password = iter->second.password;
- break;
- }
- }
+ if (FillDataContainsUsername(fill_data)) {
+ base::string16 current_username = username_element->value();
- // Check possible usernames.
- if (username.empty() && password.empty()) {
- for (PasswordFormFillData::UsernamesCollection::const_iterator iter =
- fill_data.other_possible_usernames.begin();
- iter != fill_data.other_possible_usernames.end();
+ // Look for any suitable matches to current field text.
+ if (DoUsernamesMatch(fill_data.basic_data.fields[0].value,
+ current_username,
+ exact_username_match)) {
+ username = fill_data.basic_data.fields[0].value;
+ password = fill_data.basic_data.fields[1].value;
+ } else {
+ // Scan additional logins for a match.
+ PasswordFormFillData::LoginCollection::const_iterator iter;
+ for (iter = fill_data.additional_logins.begin();
+ iter != fill_data.additional_logins.end();
++iter) {
- for (size_t i = 0; i < iter->second.size(); ++i) {
- if (DoUsernamesMatch(
- iter->second[i], current_username, exact_username_match)) {
- usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED;
- username = iter->second[i];
- password = iter->first.password;
- break;
+ if (DoUsernamesMatch(
+ iter->first, current_username, exact_username_match)) {
+ username = iter->first;
+ password = iter->second.password;
+ break;
+ }
+ }
+
+ // Check possible usernames.
+ if (username.empty() && password.empty()) {
+ for (PasswordFormFillData::UsernamesCollection::const_iterator iter =
+ fill_data.other_possible_usernames.begin();
+ iter != fill_data.other_possible_usernames.end();
+ ++iter) {
+ for (size_t i = 0; i < iter->second.size(); ++i) {
+ if (DoUsernamesMatch(
+ iter->second[i], current_username, exact_username_match)) {
+ usernames_usage_ = OTHER_POSSIBLE_USERNAME_SELECTED;
+ username = iter->second[i];
+ password = iter->first.password;
+ break;
+ }
}
+ if (!username.empty() && !password.empty())
+ break;
}
- if (!username.empty() && !password.empty())
- break;
}
}
- }
- if (password.empty())
- return false; // No match was found.
+ if (password.empty())
+ return false; // No match was found.
- // TODO(tkent): Check maxlength and pattern for both username and password
- // fields.
+ // TODO(tkent): Check maxlength and pattern for both username and password
+ // fields.
- // Input matches the username, fill in required values.
- if (IsElementAutocompletable(*username_element)) {
- username_element->setValue(username, true);
- username_element->setAutofilled(true);
+ // Input matches the username, fill in required values.
+ if (IsElementAutocompletable(*username_element)) {
+ username_element->setValue(username, true);
+ username_element->setAutofilled(true);
- if (set_selection) {
- username_element->setSelectionRange(current_username.length(),
- username.length());
+ if (set_selection) {
+ username_element->setSelectionRange(current_username.length(),
+ username.length());
+ }
+ } else if (current_username != username) {
+ // If the username can't be filled and it doesn't match a saved password
+ // as is, don't autofill a password.
+ return false;
}
- } else if (current_username != username) {
- // If the username can't be filled and it doesn't match a saved password
- // as is, don't autofill a password.
- return false;
+ } else {
+ password = fill_data.basic_data.fields[1].value;
}
// Wait to fill in the password until a user gesture occurs. This is to make
@@ -1074,7 +1102,9 @@ void PasswordAutofillAgent::PerformInlineAutocomplete(
void PasswordAutofillAgent::FrameClosing(const blink::WebFrame* frame) {
for (LoginToPasswordInfoMap::iterator iter = login_to_password_info_.begin();
iter != login_to_password_info_.end();) {
- if (iter->first.document().frame() == frame) {
+ // There may not be a username field, so get the frame from the password
+ // field.
+ if (iter->second.password_field.document().frame() == frame) {
password_to_username_.erase(iter->second.password_field);
login_to_password_info_.erase(iter++);
} else {

Powered by Google App Engine
This is Rietveld 408576698