Commit aea837d1 authored by sebsg's avatar sebsg Committed by Commit Bot

[AF] Rationalize forms with multiple street address predictions.

Some forms have multiple sequential fields predicted as being the whole
street address. We should rationalize those to a set of address lines
1, 2 and possibly 3 depending on the situation.

Bug: 835975
Change-Id: I75b2fa891a9ca3006066df6ba418f3475ffe01b8
Reviewed-on: https://chromium-review.googlesource.com/1089804
Commit-Queue: Sebastien Seguin-Gagnon <sebsg@chromium.org>
Reviewed-by: default avatarRoger McFarlane <rogerm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#565344}
parent d5102480
......@@ -1257,8 +1257,57 @@ void FormStructure::RationalizePhoneNumbersInSection(std::string section) {
phone_rationalized_[section] = true;
}
void FormStructure::RationalizeAddressFields() {
// TODO(crbug.com/850552): Add UKM logging.
// Get the number of fields predicted as being the whole street address.
int nb_street_address = 0;
for (const auto& field : fields_) {
ServerFieldType current_field_type =
field->ComputedType().GetStorableType();
if (current_field_type == ADDRESS_HOME_STREET_ADDRESS) {
++nb_street_address;
}
}
// The rationalization only applies to forms that have 2 or 3 whole street
// address predictions.
if (nb_street_address != 2 && nb_street_address != 3) {
return;
}
// Rationalize the street address fields to be address lines 1 to 3 instead.
int nb_address_rationalized = 0;
for (auto it = fields_.begin(); it != fields_.end(); ++it) {
auto& field = *it;
ServerFieldType current_field_type = field->Type().GetStorableType();
if (current_field_type == ADDRESS_HOME_STREET_ADDRESS) {
switch (nb_address_rationalized) {
case 0:
field->SetTypeTo(AutofillType(ADDRESS_HOME_LINE1));
break;
case 1:
field->SetTypeTo(AutofillType(ADDRESS_HOME_LINE2));
break;
case 2:
field->SetTypeTo(AutofillType(ADDRESS_HOME_LINE3));
break;
default:
NOTREACHED();
break;
}
++nb_address_rationalized;
}
}
}
void FormStructure::RationalizeFieldTypePredictions() {
RationalizeCreditCardFieldPredictions();
RationalizeAddressFields();
for (const auto& field : fields_) {
field->SetTypeTo(field->Type());
}
......
......@@ -286,11 +286,25 @@ class FormStructure {
FRIEND_TEST_ALL_PREFIXES(FormStructureTest, FindLongestCommonPrefix);
FRIEND_TEST_ALL_PREFIXES(FormStructureTest,
RationalizePhoneNumber_RunsOncePerSection);
FRIEND_TEST_ALL_PREFIXES(FormStructureTest,
RationalizeAddressFields_OneAddress);
FRIEND_TEST_ALL_PREFIXES(FormStructureTest,
RationalizeAddressFields_TwoAddresses);
FRIEND_TEST_ALL_PREFIXES(FormStructureTest,
RationalizeAddressFields_ThreeAddresses);
FRIEND_TEST_ALL_PREFIXES(FormStructureTest,
RationalizeAddressFields_FourAddresses);
// A function to fine tune the credit cards related predictions. For example:
// lone credit card fields in an otherwise non-credit-card related form is
// unlikely to be correct, the function will override that prediction.
void RationalizeCreditCardFieldPredictions();
// A function to fine tune the address related predictions. For example: two
// fields predicted as the whole address should be address lines 1 and 2
// instead.
void RationalizeAddressFields();
// A helper function to review the predictions and do appropriate adjustments
// when it considers neccessary.
void RationalizeFieldTypePredictions();
......
......@@ -4577,4 +4577,229 @@ TEST_F(FormStructureTest, RationalizePhoneNumber_RunsOncePerSection) {
EXPECT_TRUE(forms[0]->field(3)->only_fill_when_focused());
}
// Tests that a form that has only one address predicted as being a
// ADDRESS_HOME_STREET_ADDRESS is not modified by the address rationalization.
TEST_F(FormStructureTest, RationalizeAddressFields_OneAddress) {
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
field.form_control_type = "text";
field.max_length = 10000;
field.label = ASCIIToUTF16("Full Name");
field.name = ASCIIToUTF16("fullName");
form.fields.push_back(field);
field.label = ASCIIToUTF16("Address");
field.name = ASCIIToUTF16("address");
form.fields.push_back(field);
field.label = ASCIIToUTF16("City");
field.name = ASCIIToUTF16("city");
form.fields.push_back(field);
AutofillQueryResponseContents response;
response.add_field()->set_overall_type_prediction(NAME_FULL);
response.add_field()->set_overall_type_prediction(
ADDRESS_HOME_STREET_ADDRESS);
response.add_field()->set_overall_type_prediction(ADDRESS_HOME_CITY);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
FormStructure form_structure(form);
std::vector<FormStructure*> forms;
forms.push_back(&form_structure);
FormStructure::ParseQueryResponse(response_string, forms);
form_structure.RationalizeAddressFields();
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(3U, forms[0]->field_count());
EXPECT_EQ(NAME_FULL, forms[0]->field(0)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_STREET_ADDRESS,
forms[0]->field(1)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_CITY, forms[0]->field(2)->Type().GetStorableType());
}
// Tests that a form that has two address predicted as being a
// ADDRESS_HOME_STREET_ADDRESS is modified by the address rationalization to be
// ADDRESS_HOME_LINE1 and ADDRESS_HOME_LINE2 instead.
TEST_F(FormStructureTest, RationalizeAddressFields_TwoAddresses) {
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
field.form_control_type = "text";
field.max_length = 10000;
field.label = ASCIIToUTF16("Full Name");
field.name = ASCIIToUTF16("fullName");
form.fields.push_back(field);
field.label = ASCIIToUTF16("Address");
field.name = ASCIIToUTF16("address");
form.fields.push_back(field);
field.label = ASCIIToUTF16("Address");
field.name = ASCIIToUTF16("address");
form.fields.push_back(field);
field.label = ASCIIToUTF16("City");
field.name = ASCIIToUTF16("city");
form.fields.push_back(field);
AutofillQueryResponseContents response;
response.add_field()->set_overall_type_prediction(NAME_FULL);
response.add_field()->set_overall_type_prediction(
ADDRESS_HOME_STREET_ADDRESS);
response.add_field()->set_overall_type_prediction(
ADDRESS_HOME_STREET_ADDRESS);
response.add_field()->set_overall_type_prediction(ADDRESS_HOME_CITY);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
FormStructure form_structure(form);
std::vector<FormStructure*> forms;
forms.push_back(&form_structure);
FormStructure::ParseQueryResponse(response_string, forms);
form_structure.RationalizeAddressFields();
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(4U, forms[0]->field_count());
EXPECT_EQ(NAME_FULL, forms[0]->field(0)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_LINE1, forms[0]->field(1)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_LINE2, forms[0]->field(2)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_CITY, forms[0]->field(3)->Type().GetStorableType());
}
// Tests that a form that has three address predicted as being a
// ADDRESS_HOME_STREET_ADDRESS is modified by the address rationalization to be
// ADDRESS_HOME_LINE1, ADDRESS_HOME_LINE2 and ADDRESS_HOME_LINE3 instead.
TEST_F(FormStructureTest, RationalizeAddressFields_ThreeAddresses) {
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
field.form_control_type = "text";
field.max_length = 10000;
field.label = ASCIIToUTF16("Full Name");
field.name = ASCIIToUTF16("fullName");
form.fields.push_back(field);
field.label = ASCIIToUTF16("Address");
field.name = ASCIIToUTF16("address");
form.fields.push_back(field);
field.label = ASCIIToUTF16("Address");
field.name = ASCIIToUTF16("address");
form.fields.push_back(field);
field.label = ASCIIToUTF16("Address");
field.name = ASCIIToUTF16("address");
form.fields.push_back(field);
field.label = ASCIIToUTF16("City");
field.name = ASCIIToUTF16("city");
form.fields.push_back(field);
AutofillQueryResponseContents response;
response.add_field()->set_overall_type_prediction(NAME_FULL);
response.add_field()->set_overall_type_prediction(
ADDRESS_HOME_STREET_ADDRESS);
response.add_field()->set_overall_type_prediction(
ADDRESS_HOME_STREET_ADDRESS);
response.add_field()->set_overall_type_prediction(
ADDRESS_HOME_STREET_ADDRESS);
response.add_field()->set_overall_type_prediction(ADDRESS_HOME_CITY);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
FormStructure form_structure(form);
std::vector<FormStructure*> forms;
forms.push_back(&form_structure);
FormStructure::ParseQueryResponse(response_string, forms);
form_structure.RationalizeAddressFields();
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(5U, forms[0]->field_count());
EXPECT_EQ(NAME_FULL, forms[0]->field(0)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_LINE1, forms[0]->field(1)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_LINE2, forms[0]->field(2)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_LINE3, forms[0]->field(3)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_CITY, forms[0]->field(4)->Type().GetStorableType());
}
// Tests that a form that has four address predicted as being a
// ADDRESS_HOME_STREET_ADDRESS is not modified by the address rationalization.
TEST_F(FormStructureTest, RationalizeAddressFields_FourAddresses) {
FormData form;
form.origin = GURL("http://foo.com");
FormFieldData field;
field.form_control_type = "text";
field.max_length = 10000;
field.label = ASCIIToUTF16("Full Name");
field.name = ASCIIToUTF16("fullName");
form.fields.push_back(field);
field.label = ASCIIToUTF16("Address");
field.name = ASCIIToUTF16("address");
form.fields.push_back(field);
field.label = ASCIIToUTF16("Address");
field.name = ASCIIToUTF16("address");
form.fields.push_back(field);
field.label = ASCIIToUTF16("Address");
field.name = ASCIIToUTF16("address");
form.fields.push_back(field);
field.label = ASCIIToUTF16("Address");
field.name = ASCIIToUTF16("address");
form.fields.push_back(field);
field.label = ASCIIToUTF16("City");
field.name = ASCIIToUTF16("city");
form.fields.push_back(field);
AutofillQueryResponseContents response;
response.add_field()->set_overall_type_prediction(NAME_FULL);
response.add_field()->set_overall_type_prediction(
ADDRESS_HOME_STREET_ADDRESS);
response.add_field()->set_overall_type_prediction(
ADDRESS_HOME_STREET_ADDRESS);
response.add_field()->set_overall_type_prediction(
ADDRESS_HOME_STREET_ADDRESS);
response.add_field()->set_overall_type_prediction(
ADDRESS_HOME_STREET_ADDRESS);
response.add_field()->set_overall_type_prediction(ADDRESS_HOME_CITY);
std::string response_string;
ASSERT_TRUE(response.SerializeToString(&response_string));
FormStructure form_structure(form);
std::vector<FormStructure*> forms;
forms.push_back(&form_structure);
FormStructure::ParseQueryResponse(response_string, forms);
form_structure.RationalizeAddressFields();
ASSERT_EQ(1U, forms.size());
ASSERT_EQ(6U, forms[0]->field_count());
EXPECT_EQ(NAME_FULL, forms[0]->field(0)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_STREET_ADDRESS,
forms[0]->field(1)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_STREET_ADDRESS,
forms[0]->field(2)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_STREET_ADDRESS,
forms[0]->field(3)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_STREET_ADDRESS,
forms[0]->field(4)->Type().GetStorableType());
EXPECT_EQ(ADDRESS_HOME_CITY, forms[0]->field(5)->Type().GetStorableType());
}
} // namespace autofill
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