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

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: Some fixes Created 4 years, 9 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 ba1b36cd1a314bda515a242db7ab4a621cf8a71e..d2bb222c9eb691a4fb5de47653589a6cd4194535 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -770,105 +770,146 @@ 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;
+ *password_info = &web_input_to_password_info_.begin()->second;
vabr (Chromium) 2016/04/01 14:07:37 nit: Please comment on the choice of the value for
dvadym 2016/04/07 17:30:20 Done.
+ 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;
}
@@ -876,9 +917,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
@@ -898,16 +941,18 @@ bool PasswordAutofillAgent::ShowSuggestions(
if (element.value().length() > kMaximumTextSizeForAutocomplete)
return false;
- bool username_is_available = username_element &&
- !username_element->isNull() &&
- IsElementEditable(*username_element);
+ bool username_is_available =
+ !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.
vabr (Chromium) 2016/04/01 14:07:37 Please update the comment to also speak about not
dvadym 2016/04/07 17:30:20 I've decided to simplify this condition, the only
vabr (Chromium) 2016/04/08 14:47:31 Acknowledged.
- if (element.isPasswordField() && username_is_available &&
- (!password_info->fill_data.is_possible_change_password_form ||
- password_info->username_was_edited))
+ if (element.isPasswordField() &&
+ ((username_is_available &&
+ (!password_info->fill_data.is_possible_change_password_form ||
+ password_info->username_was_edited)) ||
+ (password_info->password_field_suggestion_was_accepted &&
+ element != password_info->password_field)))
return true;
UMA_HISTOGRAM_BOOLEAN(
@@ -922,9 +967,7 @@ bool PasswordAutofillAgent::ShowSuggestions(
// |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,
+ *password_info, username_element.isNull() ? element : username_element,
show_all && !element.isPasswordField(), element.isPasswordField());
}
@@ -1339,10 +1382,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;
}
}
@@ -1394,7 +1437,7 @@ PasswordAutofillAgent::PasswordInfo::PasswordInfo()
}
bool PasswordAutofillAgent::ShowSuggestionPopup(
- const PasswordFormFillData& fill_data,
+ const PasswordInfo& password_info,
const blink::WebInputElement& user_input,
bool show_all,
bool show_on_password_field) {
@@ -1429,9 +1472,6 @@ bool PasswordAutofillAgent::ShowSuggestionPopup(
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)
@@ -1443,20 +1483,15 @@ bool PasswordAutofillAgent::ShowSuggestionPopup(
: 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(
+ selected_element)));
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();
@@ -1464,26 +1499,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(),

Powered by Google App Engine
This is Rietveld 408576698