Commit d1bd596a authored by Vidhan's avatar Vidhan Committed by Commit Bot

[Autofill] Detection and filling of the augmented phone code selection

boxes

This CL introduces the functionality for detecting and filling of the
<select> fields, having options consisting of the phone country code
along with an additional text. Also, sending votes for the server
classification.

Bug: 1081219
Change-Id: I00ee0125d457abadf4f59fb16b3850e27274006b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2198785Reviewed-by: default avatarDominic Battré <battre@chromium.org>
Reviewed-by: default avatarMatthias Körber <koerber@google.com>
Commit-Queue: Vidhan Jain <vidhanj@google.com>
Cr-Commit-Position: refs/heads/master@{#781271}
parent f99b458e
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_regex_constants.h"
#include "components/autofill/core/common/autofill_regexes.h"
#include "third_party/icu/source/common/unicode/uloc.h" #include "third_party/icu/source/common/unicode/uloc.h"
#include "third_party/icu/source/i18n/unicode/dtfmtsym.h" #include "third_party/icu/source/i18n/unicode/dtfmtsym.h"
...@@ -141,6 +143,18 @@ bool SetExpirationYear(int value, int* expiration_year) { ...@@ -141,6 +143,18 @@ bool SetExpirationYear(int value, int* expiration_year) {
return true; return true;
} }
base::string16 FindPossiblePhoneCountryCode(const base::string16& text) {
base::string16 candidate;
if (text.find(base::ASCIIToUTF16("00")) != base::string16::npos ||
text.find('+') != base::string16::npos) {
if (MatchesPattern(text, base::ASCIIToUTF16(kAugmentedPhoneCountryCodeRe),
&candidate, 1))
return candidate;
}
return base::string16();
}
} // namespace data_util } // namespace data_util
} // namespace autofill } // namespace autofill
...@@ -47,6 +47,10 @@ bool SetExpirationMonth(int value, int* expiration_month); ...@@ -47,6 +47,10 @@ bool SetExpirationMonth(int value, int* expiration_month);
// made to |*expiration_year|. // made to |*expiration_year|.
bool SetExpirationYear(int value, int* expiration_year); bool SetExpirationYear(int value, int* expiration_year);
// Finds possible country code in |text| by fetching the first sub-group when
// matched with |kAugmentedPhoneCountryCodeRe| regex.
base::string16 FindPossiblePhoneCountryCode(const base::string16& text);
} // namespace data_util } // namespace data_util
} // namespace autofill } // namespace autofill
......
...@@ -13,9 +13,11 @@ ...@@ -13,9 +13,11 @@
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/data_model/data_model_utils.h"
#include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/geo/autofill_country.h" #include "components/autofill/core/browser/geo/autofill_country.h"
#include "components/autofill/core/browser/geo/phone_number_i18n.h" #include "components/autofill/core/browser/geo/phone_number_i18n.h"
#include "components/autofill/core/common/autofill_features.h"
namespace autofill { namespace autofill {
namespace { namespace {
...@@ -134,6 +136,18 @@ void PhoneNumber::GetMatchingTypes(const base::string16& text, ...@@ -134,6 +136,18 @@ void PhoneNumber::GetMatchingTypes(const base::string16& text,
matching_types->insert(PHONE_HOME_WHOLE_NUMBER); matching_types->insert(PHONE_HOME_WHOLE_NUMBER);
} }
} }
// |PHONE_HOME_COUNTRY_CODE| is added to the set of the |matching_types| when
// the digits extracted from the |stripped_text| match the |country_code|.
if (base::FeatureList::IsEnabled(
features::kAutofillEnableAugmentedPhoneCountryCode)) {
base::string16 candidate =
data_util::FindPossiblePhoneCountryCode(stripped_text);
base::string16 country_code =
GetInfo(AutofillType(PHONE_HOME_COUNTRY_CODE), app_locale);
if (candidate.size() > 0 && candidate == country_code)
matching_types->insert(PHONE_HOME_COUNTRY_CODE);
}
} }
// Normalize phones if |type| is a whole number: // Normalize phones if |type| is a whole number:
......
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/geo/phone_number_i18n.h" #include "components/autofill/core/browser/geo/phone_number_i18n.h"
#include "components/autofill/core/common/autofill_features.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -289,4 +291,78 @@ TEST(PhoneNumberTest, InternationalPhoneHomeCityAndNumber_DE) { ...@@ -289,4 +291,78 @@ TEST(PhoneNumberTest, InternationalPhoneHomeCityAndNumber_DE) {
phone_number.GetInfo(PHONE_HOME_CITY_AND_NUMBER, "en-US")); phone_number.GetInfo(PHONE_HOME_CITY_AND_NUMBER, "en-US"));
} }
// Tests whether the |PHONE_HOME_COUNTRY_CODE| is added to the set of matching
// types.
TEST(PhoneNumberTest, CountryCodeInMatchingTypes) {
base::test::ScopedFeatureList enabled;
enabled.InitAndEnableFeature(
features::kAutofillEnableAugmentedPhoneCountryCode);
AutofillProfile profile;
profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US"));
// Set the phone number such that country_code == 1, city_code = 650,
// number = 2345678.
base::string16 phone(ASCIIToUTF16("1 [650] 234-5678"));
PhoneNumber phone_number(&profile);
phone_number.SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), phone, "US");
std::vector<const char*> test_cases = {"+1", "1", "(+1) United States",
"US (+1)"};
for (size_t i = 0; i < test_cases.size(); i++) {
SCOPED_TRACE(testing::Message() << "i(US) = " << i);
ServerFieldTypeSet matching_types;
phone_number.GetMatchingTypes(ASCIIToUTF16(test_cases[i]), "US",
&matching_types);
EXPECT_THAT(matching_types, testing::ElementsAre(PHONE_HOME_COUNTRY_CODE));
}
profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE"));
base::string16 de_phone(ASCIIToUTF16("+49 0151 6679586"));
PhoneNumber phone_number_de(&profile);
phone_number_de.SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), de_phone,
"DE");
test_cases = {"49", "+49", "(+49) DE", "(0049) DE", "0049"};
for (size_t i = 0; i < test_cases.size(); i++) {
SCOPED_TRACE(testing::Message() << "i(DE) = " << i);
ServerFieldTypeSet matching_types;
phone_number_de.GetMatchingTypes(ASCIIToUTF16(test_cases[i]), "DE",
&matching_types);
EXPECT_THAT(matching_types, testing::ElementsAre(PHONE_HOME_COUNTRY_CODE));
}
}
// Tests that the |PHONE_HOME_COUNTRY_CODE| should not be added to the set of
// matching types.
TEST(PhoneNumberTest, CountryCodeNotInMatchingTypes) {
base::test::ScopedFeatureList enabled;
enabled.InitAndEnableFeature(
features::kAutofillEnableAugmentedPhoneCountryCode);
AutofillProfile profile;
profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US"));
// Set phone number so country_code == 1, city_code = 650, number = 2345678.
base::string16 phone(ASCIIToUTF16("1 [650] 234-5678"));
PhoneNumber phone_number(&profile);
phone_number.SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), phone, "US");
std::vector<const char*> test_cases = {
"01", "+16502", "11", "211", "0001", "++1", "+1abc2", "001abc2", "01"};
for (size_t i = 0; i < test_cases.size(); i++) {
SCOPED_TRACE(testing::Message() << "i = " << i);
ServerFieldTypeSet matching_types;
phone_number.GetMatchingTypes(ASCIIToUTF16(test_cases[i]), "US",
&matching_types);
EXPECT_THAT(matching_types, testing::IsEmpty());
}
}
} // namespace autofill } // namespace autofill
...@@ -705,6 +705,36 @@ base::string16 RemoveWhitespace(const base::string16& value) { ...@@ -705,6 +705,36 @@ base::string16 RemoveWhitespace(const base::string16& value) {
return stripped_value; return stripped_value;
} }
// Finds the best suitable option in the |field| that corresponds to the
// |country_code|.
// If the exact match is not found, extracts the digits (ignoring leading '00'
// or '+') from each option and compares them with the |country_code|.
void FillPhoneCountryCodeSelectControl(const base::string16& country_code,
FormFieldData* field,
std::string* failure_to_fill) {
if (country_code.empty())
return;
// Find the option that exactly matches the |country_code|.
if (SetSelectControlValue(country_code, field, /*best_match_index=*/nullptr,
failure_to_fill))
return;
for (size_t i = 0; i < field->option_contents.size(); i++) {
base::string16 cc_candidate_in_value =
data_util::FindPossiblePhoneCountryCode(
RemoveWhitespace(field->option_values[i]));
base::string16 cc_candidate_in_content =
data_util::FindPossiblePhoneCountryCode(
RemoveWhitespace(field->option_contents[i]));
if (cc_candidate_in_value == country_code ||
cc_candidate_in_content == country_code) {
field->value = field->option_values[i];
return;
}
}
}
} // namespace } // namespace
FieldFiller::FieldFiller(const std::string& app_locale, FieldFiller::FieldFiller(const std::string& app_locale,
...@@ -748,7 +778,16 @@ bool FieldFiller::FillFormField(const AutofillField& field, ...@@ -748,7 +778,16 @@ bool FieldFiller::FillFormField(const AutofillField& field,
} }
if (type.group() == PHONE_HOME) { if (type.group() == PHONE_HOME) {
// If the |field_data| is a selection box and having the type
// |PHONE_HOME_COUNTRY_CODE|, call |FillPhoneCountryCodeSelectControl|.
if (base::FeatureList::IsEnabled(
features::kAutofillEnableAugmentedPhoneCountryCode) &&
field_data->form_control_type == "select-one" &&
type.GetStorableType() == PHONE_HOME_COUNTRY_CODE) {
FillPhoneCountryCodeSelectControl(value, field_data, failure_to_fill);
} else {
FillPhoneNumberField(field, value, field_data); FillPhoneNumberField(field, value, field_data);
}
return true; return true;
} }
if (field_data->form_control_type == "select-one") { if (field_data->form_control_type == "select-one") {
......
...@@ -1495,4 +1495,132 @@ INSTANTIATE_TEST_SUITE_P( ...@@ -1495,4 +1495,132 @@ INSTANTIATE_TEST_SUITE_P(
FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 3, "Quebec", "", FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 3, "Quebec", "",
false})); false}));
// Tests that the correct option is chosen in the selection box when one of the
// options exactly matches the phone country code.
TEST_F(AutofillFieldFillerTest,
FillSelectControlPhoneCountryCodeWithExactMatch) {
base::test::ScopedFeatureList enabled;
enabled.InitAndEnableFeature(
features::kAutofillEnableAugmentedPhoneCountryCode);
std::vector<const char*> kPhoneCountryCode = {"91", "1", "20", "49"};
AutofillField field;
test::CreateTestSelectField(kPhoneCountryCode, &field);
field.set_heuristic_type(PHONE_HOME_COUNTRY_CODE);
AutofillProfile address;
address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("+15145554578"));
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
EXPECT_EQ(ASCIIToUTF16("1"), field.value);
}
// Tests that the correct option is chosen in the selection box when the options
// are preceded by a plus sign and the field is of |PHONE_HOME_COUNTRY_CODE|
// type.
TEST_F(AutofillFieldFillerTest,
FillSelectControlPhoneCountryCodePrecededByPlus) {
base::test::ScopedFeatureList enabled;
enabled.InitAndEnableFeature(
features::kAutofillEnableAugmentedPhoneCountryCode);
std::vector<const char*> kPhoneCountryCode = {"+91", "+1", "+20", "+49"};
AutofillField field;
test::CreateTestSelectField(kPhoneCountryCode, &field);
field.set_heuristic_type(PHONE_HOME_COUNTRY_CODE);
AutofillProfile address;
address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("+918890888888"));
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
EXPECT_EQ(ASCIIToUTF16("+91"), field.value);
}
// Tests that the correct option is chosen in the selection box when the options
// are preceded by a '00' and the field is of |PHONE_HOME_COUNTRY_CODE|
// type.
TEST_F(AutofillFieldFillerTest,
FillSelectControlPhoneCountryCodePrecededByDoubleZeros) {
base::test::ScopedFeatureList enabled;
enabled.InitAndEnableFeature(
features::kAutofillEnableAugmentedPhoneCountryCode);
std::vector<const char*> kPhoneCountryCode = {"0091", "001", "0020", "0049"};
AutofillField field;
test::CreateTestSelectField(kPhoneCountryCode, &field);
field.set_heuristic_type(PHONE_HOME_COUNTRY_CODE);
AutofillProfile address;
address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("+918890888888"));
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
EXPECT_EQ(ASCIIToUTF16("0091"), field.value);
}
// Tests that the correct option is chosen in the selection box when the options
// are composed of the country code and the country name.
TEST_F(AutofillFieldFillerTest, FillSelectControlAugmentedPhoneCountryCode) {
base::test::ScopedFeatureList enabled;
enabled.InitAndEnableFeature(
features::kAutofillEnableAugmentedPhoneCountryCode);
std::vector<const char*> kPhoneCountryCode = {
"Please select an option", "+91 (India)", "+1 (United States)",
"+20 (Egypt)", "+49 (Germany)"};
AutofillField field;
test::CreateTestSelectField(kPhoneCountryCode, &field);
field.set_heuristic_type(PHONE_HOME_COUNTRY_CODE);
AutofillProfile address;
address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("+49151669087345"));
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
EXPECT_EQ(ASCIIToUTF16("+49 (Germany)"), field.value);
}
// Tests that the correct option is chosen in the selection box when the options
// are composed of the country code having whitespace and the country name.
TEST_F(AutofillFieldFillerTest,
FillSelectControlAugmentedPhoneCountryCodeWithWhiteSpaces) {
base::test::ScopedFeatureList enabled;
enabled.InitAndEnableFeature(
features::kAutofillEnableAugmentedPhoneCountryCode);
std::vector<const char*> kPhoneCountryCode = {
"Please select an option", "(00 91) India", "(00 1) United States",
"(00 20) Egypt", "(00 49) Germany"};
AutofillField field;
test::CreateTestSelectField(kPhoneCountryCode, &field);
field.set_heuristic_type(PHONE_HOME_COUNTRY_CODE);
AutofillProfile address;
address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("+49151669087345"));
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
EXPECT_EQ(ASCIIToUTF16("(00 49) Germany"), field.value);
}
// Tests that the correct option is chosen in the selection box when the options
// are composed of the country code that is preceded by '00' and the country
// name.
TEST_F(AutofillFieldFillerTest,
FillSelectControlAugmentedPhoneCountryCodeHavingDoubleZeros) {
base::test::ScopedFeatureList enabled;
enabled.InitAndEnableFeature(
features::kAutofillEnableAugmentedPhoneCountryCode);
std::vector<const char*> kPhoneCountryCode = {
"Please select an option", "(0091) India", "(001) United States",
"(0020) Egypt", "(0049) Germany"};
AutofillField field;
test::CreateTestSelectField(kPhoneCountryCode, &field);
field.set_heuristic_type(PHONE_HOME_COUNTRY_CODE);
AutofillProfile address;
address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("+49151669087345"));
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
EXPECT_EQ(ASCIIToUTF16("(0049) Germany"), field.value);
}
} // namespace autofill } // namespace autofill
...@@ -17,11 +17,33 @@ ...@@ -17,11 +17,33 @@
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_field.h" #include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/form_parsing/autofill_scanner.h" #include "components/autofill/core/browser/form_parsing/autofill_scanner.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_regex_constants.h" #include "components/autofill/core/common/autofill_regex_constants.h"
#include "components/autofill/core/common/autofill_regexes.h"
namespace autofill { namespace autofill {
namespace { namespace {
// Minimum limit on the number of the options of the select field for
// determining the field to be of |PHONE_HOME_COUNTRY_CODE| type.
constexpr int kMinSelectOptionsForCountryCode = 5;
// Maximum limit on the number of the options of the select field for
// determining the field to be of |PHONE_HOME_COUNTRY_CODE| type.
// Currently, there are approximately 250 countries that have been assigned a
// phone country code, therefore, 275 is taken as the upper bound.
constexpr int kMaxSelectOptionsForCountryCode = 275;
// Minimum percentage of options in select field that should look like a
// country code in order to classify the field as a |PHONE_HOME_COUNTRY_CODE|.
constexpr int kMinCandidatePercentageForCountryCode = 90;
// If a <select> element has <= |kHeuristicThresholdForCountryCode| options,
// all or all-but-one need to look like country code options. Otherwise,
// |kMinCandidatePercentageForCountryCode| is used to check for a fraction
// of country code like options.
constexpr int kHeuristicThresholdForCountryCode = 10;
// This string includes all area code separators, including NoText. // This string includes all area code separators, including NoText.
std::string GetAreaRegex() { std::string GetAreaRegex() {
std::string area_code = kAreaCodeRe; std::string area_code = kAreaCodeRe;
...@@ -130,6 +152,65 @@ const PhoneField::Parser PhoneField::kPhoneFieldGrammars[] = { ...@@ -130,6 +152,65 @@ const PhoneField::Parser PhoneField::kPhoneFieldGrammars[] = {
{REGEX_SEPARATOR, FIELD_NONE, 0}, {REGEX_SEPARATOR, FIELD_NONE, 0},
}; };
// static
bool PhoneField::LikelyAugmentedPhoneCountryCode(
AutofillScanner* scanner,
AutofillField** matched_field) {
// If the experiment |kAutofillEnableAugmentedPhoneCountryCode| is not
// enabled, return false.
if (!base::FeatureList::IsEnabled(
features::kAutofillEnableAugmentedPhoneCountryCode))
return false;
AutofillField* field = scanner->Cursor();
// Return false if the field is not a selection box.
if (!MatchesFormControlType(field->form_control_type, MATCH_SELECT))
return false;
// If the number of the options is less than the minimum limit or more than
// the maximum limit, return false.
if (field->option_contents.size() < kMinSelectOptionsForCountryCode ||
field->option_contents.size() >= kMaxSelectOptionsForCountryCode)
return false;
// |total_covered_options| stores the count of the options that are
// compared with the regex.
int total_num_options = static_cast<int>(field->option_contents.size());
// |total_positive_options| stores the count of the options that match the
// regex.
int total_positive_options = 0;
for (const auto& option : field->option_contents) {
if (MatchesPattern(option,
base::ASCIIToUTF16(kAugmentedPhoneCountryCodeRe)))
total_positive_options++;
}
// If the number of the options compared is less or equal to
// |kHeuristicThresholdForCountryCode|, then either all the options or all
// options but one should match the regex.
if (total_num_options <= kHeuristicThresholdForCountryCode &&
total_positive_options + 1 < total_num_options)
return false;
// If the number of the options compared is more than
// |kHeuristicThresholdForCountryCode|,
// |kMinCandidatePercentageForCountryCode|% of the options should match the
// regex.
if (total_num_options > kHeuristicThresholdForCountryCode &&
total_positive_options * 100 <
total_num_options * kMinCandidatePercentageForCountryCode)
return false;
// Assign the |matched_field| and advance the cursor.
if (matched_field)
*matched_field = field;
scanner->Advance();
return true;
}
// static // static
std::unique_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner, std::unique_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner,
LogManager* log_manager) { LogManager* log_manager) {
...@@ -149,11 +230,22 @@ std::unique_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner, ...@@ -149,11 +230,22 @@ std::unique_ptr<FormField> PhoneField::Parse(AutofillScanner* scanner,
for (; i < base::size(kPhoneFieldGrammars) && for (; i < base::size(kPhoneFieldGrammars) &&
kPhoneFieldGrammars[i].regex != REGEX_SEPARATOR; kPhoneFieldGrammars[i].regex != REGEX_SEPARATOR;
++i) { ++i) {
const bool is_country_code_field =
kPhoneFieldGrammars[i].phone_part == FIELD_COUNTRY_CODE;
// The field length comparison with |kPhoneFieldGrammars[i].max_size| is
// not required in case of the selection boxes that are of phone country
// code type.
if (is_country_code_field &&
LikelyAugmentedPhoneCountryCode(scanner,
&parsed_fields[FIELD_COUNTRY_CODE]))
continue;
if (!ParsePhoneField( if (!ParsePhoneField(
scanner, GetRegExp(kPhoneFieldGrammars[i].regex), scanner, GetRegExp(kPhoneFieldGrammars[i].regex),
&parsed_fields[kPhoneFieldGrammars[i].phone_part], &parsed_fields[kPhoneFieldGrammars[i].phone_part],
{log_manager, GetRegExpName(kPhoneFieldGrammars[i].regex)}, {log_manager, GetRegExpName(kPhoneFieldGrammars[i].regex)},
(kPhoneFieldGrammars[i].phone_part == FIELD_COUNTRY_CODE))) is_country_code_field))
break; break;
if (kPhoneFieldGrammars[i].max_size && if (kPhoneFieldGrammars[i].max_size &&
(!parsed_fields[kPhoneFieldGrammars[i].phone_part]->max_length || (!parsed_fields[kPhoneFieldGrammars[i].phone_part]->max_length ||
......
...@@ -102,6 +102,13 @@ class PhoneField : public FormField { ...@@ -102,6 +102,13 @@ class PhoneField : public FormField {
const RegExLogging& logging, const RegExLogging& logging,
const bool is_country_code_field); const bool is_country_code_field);
// Returns true if |scanner| points to a <select> field that appears to be the
// phone country code by looking at its option contents.
// "Augmented" refers to the fact that we are looking for select options that
// contain not only a country code but also further text like "Germany (+49)".
static bool LikelyAugmentedPhoneCountryCode(AutofillScanner* scanner,
AutofillField** match);
// FIELD_PHONE is always present; holds suffix if prefix is present. // FIELD_PHONE is always present; holds suffix if prefix is present.
// The rest could be NULL. // The rest could be NULL.
AutofillField* parsed_phone_fields_[FIELD_MAX]; AutofillField* parsed_phone_fields_[FIELD_MAX];
......
...@@ -65,6 +65,12 @@ const base::Feature kAutofillEnableAccountWalletStorage { ...@@ -65,6 +65,12 @@ const base::Feature kAutofillEnableAccountWalletStorage {
#endif #endif
}; };
// Controls whether to detect and fill the augmented phone country code field
// when enabled.
const base::Feature kAutofillEnableAugmentedPhoneCountryCode{
"AutofillEnableAugmentedPhoneCountryCode",
base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether we use COMPANY as part of Autofill // Controls whether we use COMPANY as part of Autofill
const base::Feature kAutofillEnableCompanyName{ const base::Feature kAutofillEnableCompanyName{
"AutofillEnableCompanyName", base::FEATURE_ENABLED_BY_DEFAULT}; "AutofillEnableCompanyName", base::FEATURE_ENABLED_BY_DEFAULT};
......
...@@ -29,6 +29,7 @@ extern const base::Feature kAutofillCacheQueryResponses; ...@@ -29,6 +29,7 @@ extern const base::Feature kAutofillCacheQueryResponses;
extern const base::Feature kAutofillCreateDataForTest; extern const base::Feature kAutofillCreateDataForTest;
extern const base::Feature kAutofillCreditCardAssist; extern const base::Feature kAutofillCreditCardAssist;
extern const base::Feature kAutofillEnableAccountWalletStorage; extern const base::Feature kAutofillEnableAccountWalletStorage;
extern const base::Feature kAutofillEnableAugmentedPhoneCountryCode;
extern const base::Feature kAutofillEnableCompanyName; extern const base::Feature kAutofillEnableCompanyName;
extern const base::Feature kAutofillEnableHideSuggestionsUI; extern const base::Feature kAutofillEnableHideSuggestionsUI;
extern const base::Feature kAutofillEnforceMinRequiredFieldsForHeuristics; extern const base::Feature kAutofillEnforceMinRequiredFieldsForHeuristics;
......
...@@ -351,6 +351,8 @@ const char kPhoneRe[] = ...@@ -351,6 +351,8 @@ const char kPhoneRe[] =
"|电话" // zh-CN "|电话" // zh-CN
"|മൊബൈല്‍" // ml for mobile "|മൊബൈല്‍" // ml for mobile
"|(?:전화|핸드폰|휴대폰|휴대전화)(?:.?번호)?"; // ko-KR "|(?:전화|핸드폰|휴대폰|휴대전화)(?:.?번호)?"; // ko-KR
const char kAugmentedPhoneCountryCodeRe[] =
"^[^0-9+]*(?:\\+|00)\\s*([1-9]\\d{0,3})\\D*$";
const char kCountryCodeRe[] = const char kCountryCodeRe[] =
"country.*code|ccode|_cc|phone.*code|user.*phone.*code"; "country.*code|ccode|_cc|phone.*code|user.*phone.*code";
const char kAreaCodeNotextRe[] = "^\\($"; const char kAreaCodeNotextRe[] = "^\\($";
......
...@@ -47,6 +47,7 @@ extern const char kMiddleInitialRe[]; ...@@ -47,6 +47,7 @@ extern const char kMiddleInitialRe[];
extern const char kMiddleNameRe[]; extern const char kMiddleNameRe[];
extern const char kLastNameRe[]; extern const char kLastNameRe[];
extern const char kPhoneRe[]; extern const char kPhoneRe[];
extern const char kAugmentedPhoneCountryCodeRe[];
extern const char kCountryCodeRe[]; extern const char kCountryCodeRe[];
extern const char kAreaCodeNotextRe[]; extern const char kAreaCodeNotextRe[];
extern const char kAreaCodeRe[]; extern const char kAreaCodeRe[];
......
...@@ -64,7 +64,8 @@ namespace autofill { ...@@ -64,7 +64,8 @@ namespace autofill {
bool MatchesPattern(const base::string16& input, bool MatchesPattern(const base::string16& input,
const base::string16& pattern, const base::string16& pattern,
base::string16* match) { base::string16* match,
int32_t group_to_be_captured) {
static base::NoDestructor<AutofillRegexes> g_autofill_regexes; static base::NoDestructor<AutofillRegexes> g_autofill_regexes;
static base::NoDestructor<base::Lock> g_lock; static base::NoDestructor<base::Lock> g_lock;
base::AutoLock lock(*g_lock); base::AutoLock lock(*g_lock);
...@@ -78,7 +79,8 @@ bool MatchesPattern(const base::string16& input, ...@@ -78,7 +79,8 @@ bool MatchesPattern(const base::string16& input,
DCHECK(U_SUCCESS(status)); DCHECK(U_SUCCESS(status));
if (matched == TRUE && match) { if (matched == TRUE && match) {
icu::UnicodeString match_unicode = matcher->group(0, status); icu::UnicodeString match_unicode =
matcher->group(group_to_be_captured, status);
DCHECK(U_SUCCESS(status)); DCHECK(U_SUCCESS(status));
*match = base::i18n::UnicodeStringToString16(match_unicode); *match = base::i18n::UnicodeStringToString16(match_unicode);
} }
......
...@@ -12,10 +12,11 @@ namespace autofill { ...@@ -12,10 +12,11 @@ namespace autofill {
// Case-insensitive regular expression matching. // Case-insensitive regular expression matching.
// Returns true if |pattern| is found in |input|. // Returns true if |pattern| is found in |input|.
// If |match| is not nullptr, the matched part is assigned to it. // The |group_to_be_captured| numbered group is captured into |match|.
bool MatchesPattern(const base::string16& input, bool MatchesPattern(const base::string16& input,
const base::string16& pattern, const base::string16& pattern,
base::string16* match = nullptr); base::string16* match = nullptr,
int32_t group_to_be_captured = 0);
} // namespace autofill } // 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