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

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

Issue 1814193002: Better filling on suggestion of password fields in Password Manager. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments addressed Created 4 years, 8 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
« no previous file with comments | « components/autofill/content/renderer/password_autofill_agent.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 7579854439bcb3c1de64e752df976c716e099f6e..9d246a46189d532549a32f67cf12c2bda56207b9 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -729,12 +729,6 @@ void PasswordAutofillAgent::UpdateStateForTextChange(
if (element.isTextField())
nonscript_modified_values_[element] = element.value();
- WebInputToPasswordInfoMap::iterator password_info_iter =
- web_input_to_password_info_.find(element);
- if (password_info_iter != web_input_to_password_info_.end()) {
- password_info_iter->second.username_was_edited = true;
- }
-
blink::WebFrame* const element_frame = element.document().frame();
// The element's frame might have been detached in the meantime (see
// http://crbug.com/585363, comments 5 and 6), in which case frame() will
@@ -772,105 +766,148 @@ void PasswordAutofillAgent::UpdateStateForTextChange(
}
bool PasswordAutofillAgent::FillSuggestion(
- const blink::WebNode& node,
+ const blink::WebFormControlElement& control_element,
const blink::WebString& username,
const blink::WebString& password) {
// The element in context of the suggestion popup.
- blink::WebInputElement filled_element;
+ const blink::WebInputElement* element = toWebInputElement(&control_element);
+ if (!element)
+ return false;
+
+ blink::WebInputElement username_element;
+ blink::WebInputElement password_element;
PasswordInfo* password_info;
- if (!FindLoginInfo(node, &filled_element, &password_info) ||
- !IsElementAutocompletable(filled_element) ||
- !IsElementAutocompletable(password_info->password_field)) {
+ if (!FindPasswordInfoForElement(*element, &username_element,
+ &password_element, &password_info) ||
+ (!username_element.isNull() &&
+ !IsElementAutocompletable(username_element)) ||
+ !IsElementAutocompletable(password_element)) {
return false;
}
password_info->password_was_edited_last = false;
- // Note that in cases where filled_element is the password element, the value
- // gets overwritten with the correct one below.
- filled_element.setValue(username, true);
- filled_element.setAutofilled(true);
- nonscript_modified_values_[filled_element] = username;
+ if (element->isPasswordField()) {
+ password_info->password_field_suggestion_was_accepted = true;
+ password_info->password_field = password_element;
+ } else if (!username_element.isNull()) {
+ username_element.setValue(username, true);
+ username_element.setAutofilled(true);
+ nonscript_modified_values_[username_element] = username;
+ }
- password_info->password_field.setValue(password, true);
- password_info->password_field.setAutofilled(true);
- nonscript_modified_values_[password_info->password_field] = password;
+ password_element.setValue(password, true);
+ password_element.setAutofilled(true);
+ nonscript_modified_values_[password_element] = password;
- filled_element.setSelectionRange(filled_element.value().length(),
- filled_element.value().length());
+ blink::WebInputElement mutable_filled_element = *element;
+ mutable_filled_element.setSelectionRange(element->value().length(),
+ element->value().length());
return true;
}
bool PasswordAutofillAgent::PreviewSuggestion(
- const blink::WebNode& node,
+ const blink::WebFormControlElement& control_element,
const blink::WebString& username,
const blink::WebString& password) {
+ // The element in context of the suggestion popup.
+ const blink::WebInputElement* element = toWebInputElement(&control_element);
+ if (!element)
+ return false;
+
blink::WebInputElement username_element;
+ blink::WebInputElement password_element;
PasswordInfo* password_info;
- if (!FindLoginInfo(node, &username_element, &password_info) ||
- !IsElementAutocompletable(username_element) ||
- !IsElementAutocompletable(password_info->password_field)) {
+ if (!FindPasswordInfoForElement(*element, &username_element,
+ &password_element, &password_info) ||
+ (!username_element.isNull() &&
+ !IsElementAutocompletable(username_element)) ||
+ !IsElementAutocompletable(password_element)) {
return false;
}
- if (username_query_prefix_.empty())
- username_query_prefix_ = username_element.value();
+ if (!element->isPasswordField() && !username_element.isNull()) {
+ if (username_query_prefix_.empty())
+ username_query_prefix_ = username_element.value();
- was_username_autofilled_ = username_element.isAutofilled();
- username_element.setSuggestedValue(username);
- username_element.setAutofilled(true);
- form_util::PreviewSuggestion(username_element.suggestedValue(),
- username_query_prefix_, &username_element);
- was_password_autofilled_ = password_info->password_field.isAutofilled();
- password_info->password_field.setSuggestedValue(password);
- password_info->password_field.setAutofilled(true);
+ was_username_autofilled_ = username_element.isAutofilled();
+ username_element.setSuggestedValue(username);
+ username_element.setAutofilled(true);
+ form_util::PreviewSuggestion(username_element.suggestedValue(),
+ username_query_prefix_, &username_element);
+ }
+ was_password_autofilled_ = password_element.isAutofilled();
+ password_element.setSuggestedValue(password);
+ password_element.setAutofilled(true);
return true;
}
bool PasswordAutofillAgent::DidClearAutofillSelection(
- const blink::WebNode& node) {
+ const blink::WebFormControlElement& control_element) {
+ const blink::WebInputElement* element = toWebInputElement(&control_element);
+ if (!element)
+ return false;
+
blink::WebInputElement username_element;
+ blink::WebInputElement password_element;
PasswordInfo* password_info;
- if (!FindLoginInfo(node, &username_element, &password_info))
+
+ if (!FindPasswordInfoForElement(*element, &username_element,
+ &password_element, &password_info))
return false;
- ClearPreview(&username_element, &password_info->password_field);
+ ClearPreview(&username_element, &password_element);
return true;
}
bool PasswordAutofillAgent::FindPasswordInfoForElement(
const blink::WebInputElement& element,
- const blink::WebInputElement** username_element,
+ blink::WebInputElement* username_element,
+ blink::WebInputElement* password_element,
PasswordInfo** password_info) {
- DCHECK(username_element && password_info);
+ DCHECK(username_element && password_element && password_info);
+ username_element->reset();
+ password_element->reset();
if (!element.isPasswordField()) {
- *username_element = &element;
+ *username_element = element;
} else {
WebInputToPasswordInfoMap::iterator iter =
web_input_to_password_info_.find(element);
if (iter != web_input_to_password_info_.end()) {
// It's a password field without corresponding username field.
- *username_element = nullptr;
+ *password_element = element;
*password_info = &iter->second;
return true;
}
PasswordToLoginMap::const_iterator password_iter =
password_to_username_.find(element);
- if (password_iter == password_to_username_.end())
- return false;
- *username_element = &password_iter->second;
+ if (password_iter == password_to_username_.end()) {
+ if (web_input_to_password_info_.empty())
+ return false;
+
+ *password_element = element;
+ // Now all PasswordInfo items refer to the same set of credentials for
+ // fill, so it is ok to take any of them.
+ *password_info = &web_input_to_password_info_.begin()->second;
+ return true;
+ }
+ *username_element = password_iter->second;
+ *password_element = element;
}
WebInputToPasswordInfoMap::iterator iter =
- web_input_to_password_info_.find(**username_element);
+ web_input_to_password_info_.find(*username_element);
if (iter == web_input_to_password_info_.end())
return false;
*password_info = &iter->second;
+ if (password_element->isNull())
+ *password_element = (*password_info)->password_field;
+
return true;
}
@@ -878,9 +915,11 @@ bool PasswordAutofillAgent::ShowSuggestions(
const blink::WebInputElement& element,
bool show_all,
bool generation_popup_showing) {
- const blink::WebInputElement* username_element;
+ blink::WebInputElement username_element;
+ blink::WebInputElement password_element;
PasswordInfo* password_info;
- if (!FindPasswordInfoForElement(element, &username_element, &password_info))
+ if (!FindPasswordInfoForElement(element, &username_element, &password_element,
+ &password_info))
return false;
// If autocomplete='off' is set on the form elements, no suggestion dialog
@@ -900,16 +939,11 @@ bool PasswordAutofillAgent::ShowSuggestions(
if (element.value().length() > kMaximumTextSizeForAutocomplete)
return false;
- bool username_is_available = username_element &&
- !username_element->isNull() &&
- IsElementEditable(*username_element);
- // If the element is a password field, a popup should only be shown if there
- // is no username or the corresponding username element is not editable since
- // it is only in that case that the username element does not have a
- // suggestions popup.
- if (element.isPasswordField() && username_is_available &&
- (!password_info->fill_data.is_possible_change_password_form ||
- password_info->username_was_edited))
+ // If the element is a password field, do not to show a popup if the user has
+ // already accepted a password suggestion on another password field.
+ if (element.isPasswordField() &&
+ (password_info->password_field_suggestion_was_accepted &&
+ element != password_info->password_field))
return true;
UMA_HISTOGRAM_BOOLEAN(
@@ -923,11 +957,9 @@ bool PasswordAutofillAgent::ShowSuggestions(
// this implies that the username element cannot be modified. Thus even if
// |show_all| is true, check if the element in question is a password element
// for the call to ShowSuggestionPopup.
- return ShowSuggestionPopup(
- password_info->fill_data,
- (!username_element || username_element->isNull()) ? element
- : *username_element,
- show_all && !element.isPasswordField(), element.isPasswordField());
+ return ShowSuggestionPopup(*password_info, element,
+ show_all && !element.isPasswordField(),
+ element.isPasswordField());
}
bool PasswordAutofillAgent::OriginCanAccessPasswordManager(
@@ -1340,10 +1372,10 @@ void PasswordAutofillAgent::OnFillPasswordForm(
PasswordInfo password_info;
password_info.fill_data = form_data;
+ password_info.key = key;
password_info.password_field = password_element;
web_input_to_password_info_[main_element] = password_info;
password_to_username_[password_element] = username_element;
- web_element_to_password_info_key_[main_element] = key;
}
}
@@ -1389,13 +1421,8 @@ void PasswordAutofillAgent::OnFindFocusedPasswordForm() {
////////////////////////////////////////////////////////////////////////////////
// PasswordAutofillAgent, private:
-PasswordAutofillAgent::PasswordInfo::PasswordInfo()
- : password_was_edited_last(false),
- username_was_edited(false) {
-}
-
bool PasswordAutofillAgent::ShowSuggestionPopup(
- const PasswordFormFillData& fill_data,
+ const PasswordInfo& password_info,
const blink::WebInputElement& user_input,
bool show_all,
bool show_on_password_field) {
@@ -1418,46 +1445,27 @@ bool PasswordAutofillAgent::ShowSuggestionPopup(
FormFieldData field;
form_util::FindFormAndFieldForFormControlElement(user_input, &form, &field);
- blink::WebInputElement selected_element = user_input;
- if (show_on_password_field && !selected_element.isPasswordField()) {
- WebInputToPasswordInfoMap::const_iterator iter =
- web_input_to_password_info_.find(user_input);
- DCHECK(iter != web_input_to_password_info_.end());
- selected_element = iter->second.password_field;
- }
-
- blink::WebInputElement username;
- if (!show_on_password_field || !user_input.isPasswordField()) {
- username = user_input;
- }
- WebElementToPasswordInfoKeyMap::const_iterator key_it =
- web_element_to_password_info_key_.find(user_input);
- DCHECK(key_it != web_element_to_password_info_key_.end());
-
int options = 0;
if (show_all)
options |= SHOW_ALL;
if (show_on_password_field)
options |= IS_PASSWORD_FIELD;
+
base::string16 username_string(
- username.isNull() ? base::string16()
- : static_cast<base::string16>(user_input.value()));
+ user_input.isPasswordField()
+ ? base::string16()
+ : static_cast<base::string16>(user_input.value()));
Send(new AutofillHostMsg_ShowPasswordSuggestions(
- routing_id(),
- key_it->second,
- field.text_direction,
- username_string,
- options,
- render_frame()->GetRenderView()->ElementBoundsInWindow(
- selected_element)));
+ routing_id(), password_info.key, field.text_direction, username_string,
+ options,
+ render_frame()->GetRenderView()->ElementBoundsInWindow(user_input)));
username_query_prefix_ = username_string;
- return CanShowSuggestion(fill_data, username_string, show_all);
+ return CanShowSuggestion(password_info.fill_data, username_string, show_all);
}
void PasswordAutofillAgent::FrameClosing() {
for (auto const& iter : web_input_to_password_info_) {
- web_element_to_password_info_key_.erase(iter.first);
password_to_username_.erase(iter.second.password_field);
}
web_input_to_password_info_.clear();
@@ -1465,26 +1473,10 @@ void PasswordAutofillAgent::FrameClosing() {
nonscript_modified_values_.clear();
}
-bool PasswordAutofillAgent::FindLoginInfo(const blink::WebNode& node,
- blink::WebInputElement* found_input,
- PasswordInfo** found_password) {
- if (!node.isElementNode())
- return false;
-
- blink::WebElement element = node.toConst<blink::WebElement>();
- if (!element.hasHTMLTagName("input"))
- return false;
-
- *found_input = element.to<blink::WebInputElement>();
- const blink::WebInputElement* username_element; // ignored
- return FindPasswordInfoForElement(*found_input, &username_element,
- found_password);
-}
-
void PasswordAutofillAgent::ClearPreview(
blink::WebInputElement* username,
blink::WebInputElement* password) {
- if (!username->suggestedValue().isEmpty()) {
+ if (!username->isNull() && !username->suggestedValue().isEmpty()) {
username->setSuggestedValue(blink::WebString());
username->setAutofilled(was_username_autofilled_);
username->setSelectionRange(username_query_prefix_.length(),
« no previous file with comments | « components/autofill/content/renderer/password_autofill_agent.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698