| Index: components/autofill/core/browser/address_field.cc
|
| diff --git a/components/autofill/core/browser/address_field.cc b/components/autofill/core/browser/address_field.cc
|
| index 23644cd7f82e1973aeb4b927be387ef91ea0776e..bf96dc2e75860ca64d95a8be1e20ca9be5360e7a 100644
|
| --- a/components/autofill/core/browser/address_field.cc
|
| +++ b/components/autofill/core/browser/address_field.cc
|
| @@ -20,6 +20,26 @@ using base::UTF8ToUTF16;
|
|
|
| namespace autofill {
|
|
|
| +namespace {
|
| +
|
| +bool SetFieldAndAdvanceCursor(AutofillScanner* scanner, AutofillField** field) {
|
| + *field = scanner->Cursor();
|
| + scanner->Advance();
|
| + return true;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// Some sites use type="tel" for zip fields (to get a numerical input).
|
| +// http://crbug.com/426958
|
| +const int AddressField::kZipCodeMatchType =
|
| + MATCH_DEFAULT | MATCH_TELEPHONE | MATCH_NUMBER;
|
| +
|
| +// Select fields are allowed here. This occurs on top-100 site rediff.com.
|
| +const int AddressField::kCityMatchType = MATCH_DEFAULT | MATCH_SELECT;
|
| +
|
| +const int AddressField::kStateMatchType = MATCH_DEFAULT | MATCH_SELECT;
|
| +
|
| scoped_ptr<FormField> AddressField::Parse(AutofillScanner* scanner) {
|
| if (scanner->IsEnd())
|
| return NULL;
|
| @@ -37,9 +57,7 @@ scoped_ptr<FormField> AddressField::Parse(AutofillScanner* scanner) {
|
| while (!scanner->IsEnd()) {
|
| const size_t cursor = scanner->SaveCursor();
|
| if (address_field->ParseAddressLines(scanner) ||
|
| - address_field->ParseCity(scanner) ||
|
| - address_field->ParseState(scanner) ||
|
| - address_field->ParseZipCode(scanner) ||
|
| + address_field->ParseCityStateZipCode(scanner) ||
|
| address_field->ParseCountry(scanner) ||
|
| address_field->ParseCompany(scanner)) {
|
| has_trailing_non_labeled_fields = false;
|
| @@ -216,39 +234,29 @@ bool AddressField::ParseCountry(AutofillScanner* scanner) {
|
| }
|
|
|
| bool AddressField::ParseZipCode(AutofillScanner* scanner) {
|
| - // Parse a zip code. On some UK pages (e.g. The China Shop2.html) this
|
| - // is called a "post code".
|
| if (zip_)
|
| return false;
|
|
|
| - // Some sites use type="tel" for zip fields (to get a numerical input).
|
| - // http://crbug.com/426958
|
| if (!ParseFieldSpecifics(scanner,
|
| UTF8ToUTF16(kZipCodeRe),
|
| - MATCH_DEFAULT | MATCH_TELEPHONE,
|
| + kZipCodeMatchType,
|
| &zip_)) {
|
| return false;
|
| }
|
|
|
| // Look for a zip+4, whose field name will also often contain
|
| // the substring "zip".
|
| - ParseFieldSpecifics(scanner,
|
| - UTF8ToUTF16(kZip4Re),
|
| - MATCH_DEFAULT | MATCH_TELEPHONE,
|
| - &zip4_);
|
| + ParseFieldSpecifics(scanner, UTF8ToUTF16(kZip4Re), kZipCodeMatchType, &zip4_);
|
| return true;
|
| }
|
|
|
| bool AddressField::ParseCity(AutofillScanner* scanner) {
|
| - // Parse a city name. Some UK pages (e.g. The China Shop2.html) use
|
| - // the term "town".
|
| if (city_)
|
| return false;
|
|
|
| - // Select fields are allowed here. This occurs on top-100 site rediff.com.
|
| return ParseFieldSpecifics(scanner,
|
| UTF8ToUTF16(kCityRe),
|
| - MATCH_DEFAULT | MATCH_SELECT,
|
| + kCityMatchType,
|
| &city_);
|
| }
|
|
|
| @@ -258,8 +266,113 @@ bool AddressField::ParseState(AutofillScanner* scanner) {
|
|
|
| return ParseFieldSpecifics(scanner,
|
| UTF8ToUTF16(kStateRe),
|
| - MATCH_DEFAULT | MATCH_SELECT,
|
| + kStateMatchType,
|
| &state_);
|
| }
|
|
|
| +bool AddressField::ParseCityStateZipCode(AutofillScanner* scanner) {
|
| + // Simple cases.
|
| + if (scanner->IsEnd())
|
| + return false;
|
| + if (city_ && state_ && zip_)
|
| + return false;
|
| + if (state_ && zip_)
|
| + return ParseCity(scanner);
|
| + if (city_ && zip_)
|
| + return ParseState(scanner);
|
| + if (city_ && state_)
|
| + return ParseZipCode(scanner);
|
| +
|
| + // Check for matches to both name and label.
|
| + ParseNameLabelResult city_result = ParseNameAndLabelForCity(scanner);
|
| + if (city_result == RESULT_MATCH_NAME_LABEL)
|
| + return true;
|
| + ParseNameLabelResult state_result = ParseNameAndLabelForState(scanner);
|
| + if (state_result == RESULT_MATCH_NAME_LABEL)
|
| + return true;
|
| + ParseNameLabelResult zip_result = ParseNameAndLabelForZipCode(scanner);
|
| + if (zip_result == RESULT_MATCH_NAME_LABEL)
|
| + return true;
|
| +
|
| + // Check if there is only one potential match.
|
| + bool maybe_city = city_result != RESULT_MATCH_NONE;
|
| + bool maybe_state = state_result != RESULT_MATCH_NONE;
|
| + bool maybe_zip = zip_result != RESULT_MATCH_NONE;
|
| + if (maybe_city && !maybe_state && !maybe_zip)
|
| + return SetFieldAndAdvanceCursor(scanner, &city_);
|
| + if (maybe_state && !maybe_city && !maybe_zip)
|
| + return SetFieldAndAdvanceCursor(scanner, &state_);
|
| + if (maybe_zip && !maybe_city && !maybe_state)
|
| + return ParseZipCode(scanner);
|
| +
|
| + // Otherwise give name priority over label.
|
| + if (city_result == RESULT_MATCH_NAME)
|
| + return SetFieldAndAdvanceCursor(scanner, &city_);
|
| + if (state_result == RESULT_MATCH_NAME)
|
| + return SetFieldAndAdvanceCursor(scanner, &state_);
|
| + if (zip_result == RESULT_MATCH_NAME)
|
| + return ParseZipCode(scanner);
|
| +
|
| + if (city_result == RESULT_MATCH_LABEL)
|
| + return SetFieldAndAdvanceCursor(scanner, &city_);
|
| + if (state_result == RESULT_MATCH_LABEL)
|
| + return SetFieldAndAdvanceCursor(scanner, &state_);
|
| + if (zip_result == RESULT_MATCH_LABEL)
|
| + return ParseZipCode(scanner);
|
| +
|
| + return false;
|
| +}
|
| +
|
| +AddressField::ParseNameLabelResult AddressField::ParseNameAndLabelForZipCode(
|
| + AutofillScanner* scanner) {
|
| + if (zip_)
|
| + return RESULT_MATCH_NONE;
|
| +
|
| + ParseNameLabelResult result = ParseNameAndLabelSeparately(
|
| + scanner, UTF8ToUTF16(kZipCodeRe), kZipCodeMatchType, &zip_);
|
| +
|
| + if (result != RESULT_MATCH_NAME_LABEL || scanner->IsEnd())
|
| + return result;
|
| +
|
| + size_t saved_cursor = scanner->SaveCursor();
|
| + bool found_non_zip4 = ParseCity(scanner);
|
| + if (found_non_zip4)
|
| + city_ = nullptr;
|
| + scanner->RewindTo(saved_cursor);
|
| + if (!found_non_zip4) {
|
| + found_non_zip4 = ParseState(scanner);
|
| + if (found_non_zip4)
|
| + state_ = nullptr;
|
| + scanner->RewindTo(saved_cursor);
|
| + }
|
| +
|
| + if (!found_non_zip4) {
|
| + // Look for a zip+4, whose field name will also often contain
|
| + // the substring "zip".
|
| + ParseFieldSpecifics(scanner,
|
| + UTF8ToUTF16(kZip4Re),
|
| + kZipCodeMatchType,
|
| + &zip4_);
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +AddressField::ParseNameLabelResult AddressField::ParseNameAndLabelForCity(
|
| + AutofillScanner* scanner) {
|
| + if (city_)
|
| + return RESULT_MATCH_NONE;
|
| +
|
| + return ParseNameAndLabelSeparately(
|
| + scanner, UTF8ToUTF16(kCityRe), kCityMatchType, &city_);
|
| +}
|
| +
|
| +AddressField::ParseNameLabelResult AddressField::ParseNameAndLabelForState(
|
| + AutofillScanner* scanner) {
|
| + if (state_)
|
| + return RESULT_MATCH_NONE;
|
| +
|
| + return ParseNameAndLabelSeparately(
|
| + scanner, UTF8ToUTF16(kStateRe), kStateMatchType, &state_);
|
| +}
|
| +
|
| } // namespace autofill
|
|
|