Commit e64db336 authored by Maxim Kolosovskiy's avatar Maxim Kolosovskiy Committed by Commit Bot

[Password Manager] Add parser annotations to HTML <form> if

#enable-show-autofill-signatures flag is enabled.

<form name="change_password_form" >
  <input type="text" name="username" pm_parser_annotation="username_element" >
  <input type="password" name="current-password" pm_parser_annotation="password_element" >
  <input type="password" name="new-password" pm_parser_annotation="new_password_element" >
  <input type="password" name="password-again" pm_parser_annotation="confirmation_password_element" >
</form>

Bug: 824793
Change-Id: Ie02de13798abfc0aca0dfe9c47667ff4c52b4163
Reviewed-on: https://chromium-review.googlesource.com/1151315
Commit-Queue: Maxim Kolosovskiy <kolos@chromium.org>
Reviewed-by: default avatarDominic Battré <battre@chromium.org>
Cr-Commit-Position: refs/heads/master@{#579335}
parent 06780ee6
......@@ -3284,8 +3284,7 @@ TEST_F(PasswordAutofillAgentTest, ShowAutofillSignaturesFlag) {
// Check only form signature attribute. The full test is in
// "PasswordGenerationAgentTestForHtmlAnnotation.*".
WebString form_signature_attribute =
WebString::FromASCII(kDebugAttributeForFormSignature);
WebString form_signature_attribute = WebString::FromASCII("form_signature");
EXPECT_EQ(form_element.HasAttribute(form_signature_attribute),
show_signatures);
}
......
......@@ -1001,6 +1001,11 @@ TEST_F(PasswordGenerationAgentTestForHtmlAnnotation, AnnotateForm) {
blink::WebString form_signature_in_username = username_element.GetAttribute(
blink::WebString::FromUTF8("form_signature"));
EXPECT_EQ(kFormSignature, form_signature_in_username.Ascii());
EXPECT_EQ(
"username_element",
username_element
.GetAttribute(blink::WebString::FromUTF8("pm_parser_annotation"))
.Ascii());
blink::WebElement password_element =
document.GetElementById(blink::WebString::FromUTF8("first_password"));
......@@ -1012,12 +1017,31 @@ TEST_F(PasswordGenerationAgentTestForHtmlAnnotation, AnnotateForm) {
blink::WebString form_signature_in_password = password_element.GetAttribute(
blink::WebString::FromUTF8("form_signature"));
EXPECT_EQ(kFormSignature, form_signature_in_password.Ascii());
// The parser annotation is based on local heuristics, but not server side
// prediction. So, the new password element is classified as the current
// password.
EXPECT_EQ(
"password_element",
password_element
.GetAttribute(blink::WebString::FromUTF8("pm_parser_annotation"))
.Ascii());
// Check the generation element is marked.
blink::WebString generation_mark = password_element.GetAttribute(
blink::WebString::FromUTF8("password_creation_field"));
ASSERT_FALSE(generation_mark.IsNull());
EXPECT_EQ("1", generation_mark.Utf8());
blink::WebElement confirmation_password_element =
document.GetElementById(blink::WebString::FromUTF8("second_password"));
// The parser annotation is based on local heuristics, but not server side
// prediction. So, the confirmation password element is classified as the
// new password.
EXPECT_EQ(
"new_password_element",
confirmation_password_element
.GetAttribute(blink::WebString::FromUTF8("pm_parser_annotation"))
.Ascii());
}
}
......
......@@ -79,6 +79,11 @@ const size_t kMaximumTextSizeForAutocomplete = 1000;
const char kDummyUsernameField[] = "anonymous_username";
const char kDummyPasswordField[] = "anonymous_password";
// Names of HTML attributes to show form and field signatures for debugging.
const char kDebugAttributeForFormSignature[] = "form_signature";
const char kDebugAttributeForFieldSignature[] = "field_signature";
const char kDebugAttributeForParserAnnotations[] = "pm_parser_annotation";
// Maps element names to the actual elements to simplify form filling.
typedef std::map<base::string16, WebInputElement> FormInputElementMap;
......@@ -524,11 +529,33 @@ WebString GetFormSignatureAsWebString(const PasswordForm& password_form) {
base::NumberToString(CalculateFormSignature(password_form.form_data)));
}
// Add parser annotations saved in |password_form| to |element|.
void AddParserAnnotations(PasswordForm* password_form,
blink::WebFormControlElement* element) {
base::string16 element_name = element->NameForAutofill().Utf16();
std::string attribute_value;
if (password_form->username_element == element_name) {
attribute_value = "username_element";
} else if (password_form->password_element == element_name) {
attribute_value = "password_element";
} else if (password_form->new_password_element == element_name) {
attribute_value = "new_password_element";
} else if (password_form->confirmation_password_element == element_name) {
attribute_value = "confirmation_password_element";
}
element->SetAttribute(
blink::WebString::FromASCII(kDebugAttributeForParserAnnotations),
attribute_value.empty() ? blink::WebString()
: blink::WebString::FromASCII(attribute_value));
}
// Annotate |fields| with field signatures and form signature as HTML
// attributes.
void AnnotateFieldsWithSignatures(std::vector<WebFormControlElement>* fields,
const WebString& form_signature) {
for (WebFormControlElement& control_element : *fields) {
void AnnotateFieldsWithSignatures(
std::vector<blink::WebFormControlElement>* fields,
const blink::WebString& form_signature,
PasswordForm* password_form) {
for (blink::WebFormControlElement& control_element : *fields) {
FieldSignature field_signature = CalculateFieldSignatureByNameAndType(
control_element.NameForAutofill().Utf16(),
control_element.FormControlTypeForAutofill().Utf8());
......@@ -536,7 +563,10 @@ void AnnotateFieldsWithSignatures(std::vector<WebFormControlElement>* fields,
WebString::FromASCII(kDebugAttributeForFieldSignature),
WebString::FromUTF8(base::NumberToString(field_signature)));
control_element.SetAttribute(
WebString::FromASCII(kDebugAttributeForFormSignature), form_signature);
blink::WebString::FromASCII(kDebugAttributeForFormSignature),
form_signature);
if (password_form)
AddParserAnnotations(password_form, &control_element);
}
}
......@@ -555,7 +585,8 @@ void AnnotateFormsAndFieldsWithSignatures(WebLocalFrame* frame,
}
std::vector<WebFormControlElement> form_fields =
form_util::ExtractAutofillableElementsInForm(form);
AnnotateFieldsWithSignatures(&form_fields, form_signature);
AnnotateFieldsWithSignatures(&form_fields, form_signature,
password_form ? password_form.get() : nullptr);
}
std::vector<WebFormControlElement> unowned_elements =
......@@ -567,7 +598,8 @@ void AnnotateFormsAndFieldsWithSignatures(WebLocalFrame* frame,
WebString form_signature;
if (password_form)
form_signature = GetFormSignatureAsWebString(*password_form);
AnnotateFieldsWithSignatures(&unowned_elements, form_signature);
AnnotateFieldsWithSignatures(&unowned_elements, form_signature,
password_form ? password_form.get() : nullptr);
}
// Returns true iff there is a password field in |frame|.
......@@ -650,9 +682,6 @@ WebInputElement ConvertToWebInput(const WebFormControlElement& element) {
////////////////////////////////////////////////////////////////////////////////
// PasswordAutofillAgent, public:
const char kDebugAttributeForFormSignature[] = "form_signature";
const char kDebugAttributeForFieldSignature[] = "field_signature";
PasswordAutofillAgent::PasswordAutofillAgent(
content::RenderFrame* render_frame,
service_manager::BinderRegistry* registry)
......
......@@ -59,10 +59,6 @@ enum class PrefilledUsernameFillOutcome {
kMaxValue = kPrefilledUsernameNotOverridden,
};
// Names of HTML attributes to show form and field signatures for debugging.
extern const char kDebugAttributeForFormSignature[];
extern const char kDebugAttributeForFieldSignature[];
class RendererSavePasswordProgressLogger;
class PasswordGenerationAgent;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment