| Index: components/autofill/browser/address_field.cc
|
| diff --git a/components/autofill/browser/address_field.cc b/components/autofill/browser/address_field.cc
|
| deleted file mode 100644
|
| index 408a4db001539547d73134adfbdd475ec25c4373..0000000000000000000000000000000000000000
|
| --- a/components/autofill/browser/address_field.cc
|
| +++ /dev/null
|
| @@ -1,341 +0,0 @@
|
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "components/autofill/browser/address_field.h"
|
| -
|
| -#include <stddef.h>
|
| -
|
| -#include "base/logging.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/strings/string16.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "base/strings/utf_string_conversions.h"
|
| -#include "components/autofill/browser/autofill_field.h"
|
| -#include "components/autofill/browser/autofill_regex_constants.h"
|
| -#include "components/autofill/browser/autofill_scanner.h"
|
| -#include "components/autofill/browser/field_types.h"
|
| -#include "ui/base/l10n/l10n_util.h"
|
| -
|
| -namespace autofill {
|
| -
|
| -FormField* AddressField::Parse(AutofillScanner* scanner) {
|
| - if (scanner->IsEnd())
|
| - return NULL;
|
| -
|
| - scoped_ptr<AddressField> address_field(new AddressField);
|
| - const AutofillField* const initial_field = scanner->Cursor();
|
| - size_t saved_cursor = scanner->SaveCursor();
|
| -
|
| - base::string16 attention_ignored = UTF8ToUTF16(autofill::kAttentionIgnoredRe);
|
| - base::string16 region_ignored = UTF8ToUTF16(autofill::kRegionIgnoredRe);
|
| -
|
| - // Allow address fields to appear in any order.
|
| - size_t begin_trailing_non_labeled_fields = 0;
|
| - bool has_trailing_non_labeled_fields = false;
|
| - while (!scanner->IsEnd()) {
|
| - const size_t cursor = scanner->SaveCursor();
|
| - if (ParseAddressLines(scanner, address_field.get()) ||
|
| - ParseCity(scanner, address_field.get()) ||
|
| - ParseState(scanner, address_field.get()) ||
|
| - ParseZipCode(scanner, address_field.get()) ||
|
| - ParseCountry(scanner, address_field.get()) ||
|
| - ParseCompany(scanner, address_field.get())) {
|
| - has_trailing_non_labeled_fields = false;
|
| - continue;
|
| - } else if (ParseField(scanner, attention_ignored, NULL) ||
|
| - ParseField(scanner, region_ignored, NULL)) {
|
| - // We ignore the following:
|
| - // * Attention.
|
| - // * Province/Region/Other.
|
| - continue;
|
| - } else if (scanner->Cursor() != initial_field &&
|
| - ParseEmptyLabel(scanner, NULL)) {
|
| - // Ignore non-labeled fields within an address; the page
|
| - // MapQuest Driving Directions North America.html contains such a field.
|
| - // We only ignore such fields after we've parsed at least one other field;
|
| - // otherwise we'd effectively parse address fields before other field
|
| - // types after any non-labeled fields, and we want email address fields to
|
| - // have precedence since some pages contain fields labeled
|
| - // "Email address".
|
| - if (!has_trailing_non_labeled_fields) {
|
| - has_trailing_non_labeled_fields = true;
|
| - begin_trailing_non_labeled_fields = cursor;
|
| - }
|
| -
|
| - continue;
|
| - } else {
|
| - // No field found.
|
| - break;
|
| - }
|
| - }
|
| -
|
| - // If we have identified any address fields in this field then it should be
|
| - // added to the list of fields.
|
| - if (address_field->company_ != NULL ||
|
| - address_field->address1_ != NULL || address_field->address2_ != NULL ||
|
| - address_field->city_ != NULL || address_field->state_ != NULL ||
|
| - address_field->zip_ != NULL || address_field->zip4_ ||
|
| - address_field->country_ != NULL) {
|
| - // Don't slurp non-labeled fields at the end into the address.
|
| - if (has_trailing_non_labeled_fields)
|
| - scanner->RewindTo(begin_trailing_non_labeled_fields);
|
| -
|
| - address_field->type_ = address_field->FindType();
|
| - return address_field.release();
|
| - }
|
| -
|
| - scanner->RewindTo(saved_cursor);
|
| - return NULL;
|
| -}
|
| -
|
| -AddressField::AddressType AddressField::FindType() const {
|
| - // First look at the field name, which itself will sometimes contain
|
| - // "bill" or "ship".
|
| - if (company_) {
|
| - base::string16 name = StringToLowerASCII(company_->name);
|
| - return AddressTypeFromText(name);
|
| - }
|
| - if (address1_) {
|
| - base::string16 name = StringToLowerASCII(address1_->name);
|
| - return AddressTypeFromText(name);
|
| - }
|
| - if (address2_) {
|
| - base::string16 name = StringToLowerASCII(address2_->name);
|
| - return AddressTypeFromText(name);
|
| - }
|
| - if (city_) {
|
| - base::string16 name = StringToLowerASCII(city_->name);
|
| - return AddressTypeFromText(name);
|
| - }
|
| - if (zip_) {
|
| - base::string16 name = StringToLowerASCII(zip_->name);
|
| - return AddressTypeFromText(name);
|
| - }
|
| - if (state_) {
|
| - base::string16 name = StringToLowerASCII(state_->name);
|
| - return AddressTypeFromText(name);
|
| - }
|
| - if (country_) {
|
| - base::string16 name = StringToLowerASCII(country_->name);
|
| - return AddressTypeFromText(name);
|
| - }
|
| -
|
| - return kGenericAddress;
|
| -}
|
| -
|
| -AddressField::AddressField()
|
| - : company_(NULL),
|
| - address1_(NULL),
|
| - address2_(NULL),
|
| - city_(NULL),
|
| - state_(NULL),
|
| - zip_(NULL),
|
| - zip4_(NULL),
|
| - country_(NULL),
|
| - type_(kGenericAddress) {
|
| -}
|
| -
|
| -bool AddressField::ClassifyField(FieldTypeMap* map) const {
|
| - AutofillFieldType address_company;
|
| - AutofillFieldType address_line1;
|
| - AutofillFieldType address_line2;
|
| - AutofillFieldType address_city;
|
| - AutofillFieldType address_state;
|
| - AutofillFieldType address_zip;
|
| - AutofillFieldType address_country;
|
| -
|
| - switch (type_) {
|
| - case kShippingAddress:
|
| - // Fall through. Autofill does not support shipping addresses.
|
| - case kGenericAddress:
|
| - address_company = COMPANY_NAME;
|
| - address_line1 = ADDRESS_HOME_LINE1;
|
| - address_line2 = ADDRESS_HOME_LINE2;
|
| - address_city = ADDRESS_HOME_CITY;
|
| - address_state = ADDRESS_HOME_STATE;
|
| - address_zip = ADDRESS_HOME_ZIP;
|
| - address_country = ADDRESS_HOME_COUNTRY;
|
| - break;
|
| -
|
| - case kBillingAddress:
|
| - address_company = COMPANY_NAME;
|
| - address_line1 = ADDRESS_BILLING_LINE1;
|
| - address_line2 = ADDRESS_BILLING_LINE2;
|
| - address_city = ADDRESS_BILLING_CITY;
|
| - address_state = ADDRESS_BILLING_STATE;
|
| - address_zip = ADDRESS_BILLING_ZIP;
|
| - address_country = ADDRESS_BILLING_COUNTRY;
|
| - break;
|
| -
|
| - default:
|
| - NOTREACHED();
|
| - return false;
|
| - }
|
| -
|
| - bool ok = AddClassification(company_, address_company, map);
|
| - ok = ok && AddClassification(address1_, address_line1, map);
|
| - ok = ok && AddClassification(address2_, address_line2, map);
|
| - ok = ok && AddClassification(city_, address_city, map);
|
| - ok = ok && AddClassification(state_, address_state, map);
|
| - ok = ok && AddClassification(zip_, address_zip, map);
|
| - ok = ok && AddClassification(country_, address_country, map);
|
| - return ok;
|
| -}
|
| -
|
| -// static
|
| -bool AddressField::ParseCompany(AutofillScanner* scanner,
|
| - AddressField* address_field) {
|
| - if (address_field->company_ && !address_field->company_->IsEmpty())
|
| - return false;
|
| -
|
| - return ParseField(scanner, UTF8ToUTF16(autofill::kCompanyRe),
|
| - &address_field->company_);
|
| -}
|
| -
|
| -// static
|
| -bool AddressField::ParseAddressLines(AutofillScanner* scanner,
|
| - AddressField* address_field) {
|
| - // We only match the string "address" in page text, not in element names,
|
| - // because sometimes every element in a group of address fields will have
|
| - // a name containing the string "address"; for example, on the page
|
| - // Kohl's - Register Billing Address.html the text element labeled "city"
|
| - // has the name "BILL_TO_ADDRESS<>city". We do match address labels
|
| - // such as "address1", which appear as element names on various pages (eg
|
| - // AmericanGirl-Registration.html, BloomingdalesBilling.html,
|
| - // EBay Registration Enter Information.html).
|
| - if (address_field->address1_)
|
| - return false;
|
| -
|
| - base::string16 pattern = UTF8ToUTF16(autofill::kAddressLine1Re);
|
| - base::string16 label_pattern = UTF8ToUTF16(autofill::kAddressLine1LabelRe);
|
| -
|
| - if (!ParseField(scanner, pattern, &address_field->address1_) &&
|
| - !ParseFieldSpecifics(scanner, label_pattern, MATCH_LABEL | MATCH_TEXT,
|
| - &address_field->address1_)) {
|
| - return false;
|
| - }
|
| -
|
| - // Optionally parse more address lines, which may have empty labels.
|
| - // Some pages have 3 address lines (eg SharperImageModifyAccount.html)
|
| - // Some pages even have 4 address lines (e.g. uk/ShoesDirect2.html)!
|
| - pattern = UTF8ToUTF16(autofill::kAddressLine2Re);
|
| - label_pattern = UTF8ToUTF16(autofill::kAddressLine2LabelRe);
|
| - if (!ParseEmptyLabel(scanner, &address_field->address2_) &&
|
| - !ParseField(scanner, pattern, &address_field->address2_)) {
|
| - ParseFieldSpecifics(scanner, label_pattern, MATCH_LABEL | MATCH_TEXT,
|
| - &address_field->address2_);
|
| - }
|
| -
|
| - // Try for surplus lines, which we will promptly discard.
|
| - if (address_field->address2_ != NULL) {
|
| - pattern = UTF8ToUTF16(autofill::kAddressLinesExtraRe);
|
| - while (ParseField(scanner, pattern, NULL)) {
|
| - // Consumed a surplus line, try for another.
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// static
|
| -bool AddressField::ParseCountry(AutofillScanner* scanner,
|
| - AddressField* address_field) {
|
| - // Parse a country. The occasional page (e.g.
|
| - // Travelocity_New Member Information1.html) calls this a "location".
|
| - if (address_field->country_ && !address_field->country_->IsEmpty())
|
| - return false;
|
| -
|
| - return ParseFieldSpecifics(scanner,
|
| - UTF8ToUTF16(autofill::kCountryRe),
|
| - MATCH_DEFAULT | MATCH_SELECT,
|
| - &address_field->country_);
|
| -}
|
| -
|
| -// static
|
| -bool AddressField::ParseZipCode(AutofillScanner* scanner,
|
| - AddressField* address_field) {
|
| - // Parse a zip code. On some UK pages (e.g. The China Shop2.html) this
|
| - // is called a "post code".
|
| - //
|
| - // HACK: Just for the MapQuest driving directions page we match the
|
| - // exact name "1z", which MapQuest uses to label its zip code field.
|
| - // Hopefully before long we'll be smart enough to find the zip code
|
| - // on that page automatically.
|
| - if (address_field->zip_)
|
| - return false;
|
| -
|
| - base::string16 pattern = UTF8ToUTF16(autofill::kZipCodeRe);
|
| - if (!ParseField(scanner, pattern, &address_field->zip_))
|
| - return false;
|
| -
|
| - address_field->type_ = kGenericAddress;
|
| - // Look for a zip+4, whose field name will also often contain
|
| - // the substring "zip".
|
| - ParseField(scanner,
|
| - UTF8ToUTF16(autofill::kZip4Re),
|
| - &address_field->zip4_);
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// static
|
| -bool AddressField::ParseCity(AutofillScanner* scanner,
|
| - AddressField* address_field) {
|
| - // Parse a city name. Some UK pages (e.g. The China Shop2.html) use
|
| - // the term "town".
|
| - if (address_field->city_)
|
| - return false;
|
| -
|
| - // Select fields are allowed here. This occurs on top-100 site rediff.com.
|
| - return ParseFieldSpecifics(scanner,
|
| - UTF8ToUTF16(autofill::kCityRe),
|
| - MATCH_DEFAULT | MATCH_SELECT,
|
| - &address_field->city_);
|
| -}
|
| -
|
| -// static
|
| -bool AddressField::ParseState(AutofillScanner* scanner,
|
| - AddressField* address_field) {
|
| - if (address_field->state_)
|
| - return false;
|
| -
|
| - return ParseFieldSpecifics(scanner,
|
| - UTF8ToUTF16(autofill::kStateRe),
|
| - MATCH_DEFAULT | MATCH_SELECT,
|
| - &address_field->state_);
|
| -}
|
| -
|
| -AddressField::AddressType AddressField::AddressTypeFromText(
|
| - const base::string16 &text) {
|
| - size_t same_as = text.find(UTF8ToUTF16(autofill::kAddressTypeSameAsRe));
|
| - size_t use_shipping = text.find(UTF8ToUTF16(autofill::kAddressTypeUseMyRe));
|
| - if (same_as != base::string16::npos || use_shipping != base::string16::npos)
|
| - // This text could be a checkbox label such as "same as my billing
|
| - // address" or "use my shipping address".
|
| - // ++ It would help if we generally skipped all text that appears
|
| - // after a check box.
|
| - return kGenericAddress;
|
| -
|
| - // Not all pages say "billing address" and "shipping address" explicitly;
|
| - // for example, Craft Catalog1.html has "Bill-to Address" and
|
| - // "Ship-to Address".
|
| - size_t bill = text.rfind(UTF8ToUTF16(autofill::kBillingDesignatorRe));
|
| - size_t ship = text.rfind(UTF8ToUTF16(autofill::kShippingDesignatorRe));
|
| -
|
| - if (bill == base::string16::npos && ship == base::string16::npos)
|
| - return kGenericAddress;
|
| -
|
| - if (bill != base::string16::npos && ship == base::string16::npos)
|
| - return kBillingAddress;
|
| -
|
| - if (bill == base::string16::npos && ship != base::string16::npos)
|
| - return kShippingAddress;
|
| -
|
| - if (bill > ship)
|
| - return kBillingAddress;
|
| -
|
| - return kShippingAddress;
|
| -}
|
| -
|
| -} // namespace autofill
|
|
|