diff options
author | gcasto@chromium.org <gcasto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-05 06:38:35 +0000 |
---|---|---|
committer | gcasto@chromium.org <gcasto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-05 06:38:35 +0000 |
commit | 18d3cedce1b461437713213e446fca2b29c6270b (patch) | |
tree | dd39db78e57450e61a0a0551c2244a0c335e8544 /components | |
parent | cd7db286804526957c8f98748e615c2e4a33f71c (diff) | |
download | chromium_src-18d3cedce1b461437713213e446fca2b29c6270b.zip chromium_src-18d3cedce1b461437713213e446fca2b29c6270b.tar.gz chromium_src-18d3cedce1b461437713213e446fca2b29c6270b.tar.bz2 |
[Password Autofill] Make better use of prefilled usernames.
If a username field is prefilled, make sure to check all possible usernames
to see if we can fill instead of only filling with the preferred username if
it matches.
BUG=309817
R=isherman@chromium.org
Review URL: https://codereview.chromium.org/56653002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@232928 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components')
-rw-r--r-- | components/autofill/content/renderer/password_autofill_agent.cc | 113 | ||||
-rw-r--r-- | components/autofill/content/renderer/password_autofill_agent.h | 9 |
2 files changed, 73 insertions, 49 deletions
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index ce2f103..754ff32 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc @@ -164,39 +164,6 @@ bool IsElementEditable(const WebKit::WebInputElement& element) { return element.isEnabled() && !element.isReadOnly(); } -void FillForm(FormElements* fe, const FormData& data) { - if (!fe->form_element.autoComplete()) - return; - - std::map<base::string16, base::string16> data_map; - for (size_t i = 0; i < data.fields.size(); i++) - data_map[data.fields[i].name] = data.fields[i].value; - - for (FormInputElementMap::iterator it = fe->input_elements.begin(); - it != fe->input_elements.end(); ++it) { - WebKit::WebInputElement element = it->second; - // Don't fill a form that has pre-filled values distinct from the ones we - // want to fill with. - if (!element.value().isEmpty() && element.value() != data_map[it->first]) - return; - - // Don't fill forms with uneditable fields or fields with autocomplete - // disabled. - if (!IsElementEditable(element) || !element.autoComplete()) - return; - } - - for (FormInputElementMap::iterator it = fe->input_elements.begin(); - it != fe->input_elements.end(); ++it) { - WebKit::WebInputElement element = it->second; - - // TODO(tkent): Check maxlength and pattern. - element.setValue(data_map[it->first]); - element.setAutofilled(true); - element.dispatchFormControlChangeEvent(); - } -} - void SetElementAutofilled(WebKit::WebInputElement* element, bool autofilled) { if (element->isAutofilled() == autofilled) return; @@ -250,7 +217,9 @@ bool PasswordAutofillAgent::TextFieldDidEndEditing( // Do not set selection when ending an editing session, otherwise it can // mess with focus. - FillUserNameAndPassword(&username, &password, fill_data, true, false); + FillUserNameAndPassword(&username, &password, fill_data, + true /* exact_username_match */, + false /* set_selection */); return true; } @@ -331,7 +300,9 @@ bool PasswordAutofillAgent::DidAcceptAutofillSuggestion( // will do the rest. input.setValue(value, true); return FillUserNameAndPassword(&input, &password.password_field, - password.fill_data, true, true); + password.fill_data, + true /* exact_username_match */, + true /* set_selection */); } bool PasswordAutofillAgent::DidClearAutofillSelection( @@ -516,11 +487,6 @@ void PasswordAutofillAgent::OnFillPasswordForm( for (iter = forms.begin(); iter != forms.end(); ++iter) { scoped_ptr<FormElements> form_elements(*iter); - // If wait_for_username is true, we don't want to initially fill the form - // until the user types in a valid username. - if (!form_data.wait_for_username) - FillForm(form_elements.get(), form_data.basic_data); - // Attach autocomplete listener to enable selecting alternate logins. // First, get pointers to username element. WebKit::WebInputElement username_element = @@ -531,6 +497,11 @@ void PasswordAutofillAgent::OnFillPasswordForm( WebKit::WebInputElement 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 + // until the user types in a valid username. + if (!form_data.wait_for_username) + FillFormOnPasswordRecieved(form_data, username_element, password_element); + // We might have already filled this form if there are two <form> elements // with identical markup. if (login_to_password_info_.find(username_element) != @@ -625,6 +596,33 @@ bool PasswordAutofillAgent::ShowSuggestionPopup( return !suggestions.empty(); } +void PasswordAutofillAgent::FillFormOnPasswordRecieved( + const PasswordFormFillData& fill_data, + WebKit::WebInputElement username_element, + WebKit::WebInputElement password_element) { + if (!username_element.form().autoComplete()) + return; + + // If we can't modify the password, don't try to set the username + if (!IsElementEditable(password_element) || !password_element.autoComplete()) + return; + + // Try to set the username to the preferred name, but only if the field + // can be set and isn't prefilled. + if (IsElementEditable(username_element) && + username_element.autoComplete() && + username_element.value().isEmpty()) { + // TODO(tkent): Check maxlength and pattern. + username_element.setValue(fill_data.basic_data.fields[0].value); + } + + // Fill if we have an exact match for the username. Note that this sets + // username to autofilled. + FillUserNameAndPassword(&username_element, &password_element, fill_data, + true /* exact_username_match */, + false /* set_selection */); +} + bool PasswordAutofillAgent::FillUserNameAndPassword( WebKit::WebInputElement* username_element, WebKit::WebInputElement* password_element, @@ -676,17 +674,32 @@ bool PasswordAutofillAgent::FillUserNameAndPassword( if (password.empty()) return false; // No match was found. - // Input matches the username, fill in required values. - username_element->setValue(username); + // TODO(tkent): Check maxlength and pattern for both username and password + // fields. + + // Don't fill username if password can't be set. + if (!IsElementEditable(*password_element) || + !password_element->autoComplete()) { + return false; + } - if (set_selection) { - username_element->setSelectionRange(current_username.length(), - username.length()); + // Input matches the username, fill in required values. + if (IsElementEditable(*username_element) && + username_element->autoComplete()) { + username_element->setValue(username); + SetElementAutofilled(username_element, true); + + 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; } - SetElementAutofilled(username_element, true); - if (IsElementEditable(*password_element)) - password_element->setValue(password); + password_element->setValue(password); SetElementAutofilled(password_element, true); return true; } @@ -715,7 +728,9 @@ void PasswordAutofillAgent::PerformInlineAutocomplete( #if !defined(OS_ANDROID) // Fill the user and password field with the most relevant match. Android // only fills in the fields after the user clicks on the suggestion popup. - FillUserNameAndPassword(&username, &password, fill_data, false, true); + FillUserNameAndPassword(&username, &password, fill_data, + false /* exact_username_match */, + true /* set_selection */); #endif } diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h index a389ed2..99f7b8f 100644 --- a/components/autofill/content/renderer/password_autofill_agent.h +++ b/components/autofill/content/renderer/password_autofill_agent.h @@ -107,6 +107,15 @@ class PasswordAutofillAgent : public content::RenderViewObserver { bool ShowSuggestionPopup(const PasswordFormFillData& fill_data, const WebKit::WebInputElement& user_input); + // Attempts to fill |username_element| and |password_element| with the + // |fill_data|. Will use the data corresponding to the preferred username, + // unless the |username_element| already has a value set. In that case, + // attempts to fill the password matching the already filled username, if + // such a password exists. + void FillFormOnPasswordRecieved(const PasswordFormFillData& fill_data, + WebKit::WebInputElement username_element, + WebKit::WebInputElement password_element); + bool FillUserNameAndPassword( WebKit::WebInputElement* username_element, WebKit::WebInputElement* password_element, |