Home | History | Annotate | Download | only in autofill
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/autofill/address.h"
      6 
      7 #include <stddef.h>
      8 
      9 #include "base/basictypes.h"
     10 #include "base/logging.h"
     11 #include "base/string_util.h"
     12 #include "chrome/browser/autofill/autofill_country.h"
     13 #include "chrome/browser/autofill/autofill_type.h"
     14 #include "chrome/browser/autofill/field_types.h"
     15 
     16 namespace {
     17 
     18 const char16 kAddressSplitChars[] = {'-', ',', '#', '.', ' ', 0};
     19 
     20 const AutofillType::FieldTypeSubGroup kAutofillAddressTypes[] = {
     21   AutofillType::ADDRESS_LINE1,
     22   AutofillType::ADDRESS_LINE2,
     23   AutofillType::ADDRESS_CITY,
     24   AutofillType::ADDRESS_STATE,
     25   AutofillType::ADDRESS_ZIP,
     26   AutofillType::ADDRESS_COUNTRY,
     27 };
     28 
     29 const int kAutofillAddressLength = arraysize(kAutofillAddressTypes);
     30 
     31 }  // namespace
     32 
     33 Address::Address() {}
     34 
     35 Address::Address(const Address& address) : FormGroup() {
     36   *this = address;
     37 }
     38 
     39 Address::~Address() {}
     40 
     41 Address& Address::operator=(const Address& address) {
     42   if (this == &address)
     43     return *this;
     44 
     45   line1_tokens_ = address.line1_tokens_;
     46   line2_tokens_= address.line2_tokens_;
     47   line1_ = address.line1_;
     48   line2_ = address.line2_;
     49   city_ = address.city_;
     50   state_ = address.state_;
     51   country_code_ = address.country_code_;
     52   zip_code_ = address.zip_code_;
     53   return *this;
     54 }
     55 
     56 void Address::GetPossibleFieldTypes(const string16& text,
     57                                     FieldTypeSet* possible_types) const {
     58   DCHECK(possible_types);
     59 
     60   // If the text to match against the field types is empty, then no results will
     61   // match.
     62   if (text.empty())
     63     return;
     64 
     65   if (IsLine1(text))
     66     possible_types->insert(ADDRESS_HOME_LINE1);
     67 
     68   if (IsLine2(text))
     69     possible_types->insert(ADDRESS_HOME_LINE2);
     70 
     71   if (IsCity(text))
     72     possible_types->insert(ADDRESS_HOME_CITY);
     73 
     74   if (IsState(text))
     75     possible_types->insert(ADDRESS_HOME_STATE);
     76 
     77   if (IsZipCode(text))
     78     possible_types->insert(ADDRESS_HOME_ZIP);
     79 
     80   if (IsCountry(text))
     81     possible_types->insert(ADDRESS_HOME_COUNTRY);
     82 }
     83 
     84 void Address::GetAvailableFieldTypes(FieldTypeSet* available_types) const {
     85   DCHECK(available_types);
     86 
     87   if (!line1_.empty())
     88     available_types->insert(ADDRESS_HOME_LINE1);
     89 
     90   if (!line2_.empty())
     91     available_types->insert(ADDRESS_HOME_LINE2);
     92 
     93   if (!city_.empty())
     94     available_types->insert(ADDRESS_HOME_CITY);
     95 
     96   if (!state_.empty())
     97     available_types->insert(ADDRESS_HOME_STATE);
     98 
     99   if (!zip_code_.empty())
    100     available_types->insert(ADDRESS_HOME_ZIP);
    101 
    102   if (!country_code_.empty())
    103     available_types->insert(ADDRESS_HOME_COUNTRY);
    104 }
    105 
    106 string16 Address::GetInfo(AutofillFieldType type) const {
    107   if (type == ADDRESS_HOME_LINE1)
    108     return line1_;
    109 
    110   if (type == ADDRESS_HOME_LINE2)
    111     return line2_;
    112 
    113   if (type == ADDRESS_HOME_CITY)
    114     return city_;
    115 
    116   if (type == ADDRESS_HOME_STATE)
    117     return state_;
    118 
    119   if (type ==  ADDRESS_HOME_ZIP)
    120     return zip_code_;
    121 
    122   if (type == ADDRESS_HOME_COUNTRY)
    123     return Country();
    124 
    125   return string16();
    126 }
    127 
    128 void Address::SetInfo(AutofillFieldType type, const string16& value) {
    129   FieldTypeSubGroup subgroup = AutofillType(type).subgroup();
    130   if (subgroup == AutofillType::ADDRESS_LINE1)
    131     set_line1(value);
    132   else if (subgroup == AutofillType::ADDRESS_LINE2)
    133     set_line2(value);
    134   else if (subgroup == AutofillType::ADDRESS_CITY)
    135     city_ = value;
    136   else if (subgroup == AutofillType::ADDRESS_STATE)
    137     state_ = value;
    138   else if (subgroup == AutofillType::ADDRESS_COUNTRY)
    139     SetCountry(value);
    140   else if (subgroup == AutofillType::ADDRESS_ZIP)
    141     zip_code_ = value;
    142   else
    143     NOTREACHED();
    144 }
    145 
    146 void Address::Clear() {
    147   line1_tokens_.clear();
    148   line1_.clear();
    149   line2_tokens_.clear();
    150   line2_.clear();
    151   city_.clear();
    152   state_.clear();
    153   country_code_.clear();
    154   zip_code_.clear();
    155 }
    156 
    157 string16 Address::Country() const {
    158   if (country_code().empty())
    159     return string16();
    160 
    161   std::string app_locale = AutofillCountry::ApplicationLocale();
    162   return AutofillCountry(country_code(), app_locale).name();
    163 }
    164 
    165 void Address::set_line1(const string16& line1) {
    166   line1_ = line1;
    167   line1_tokens_.clear();
    168   Tokenize(line1, kAddressSplitChars, &line1_tokens_);
    169   LineTokens::iterator iter;
    170   for (iter = line1_tokens_.begin(); iter != line1_tokens_.end(); ++iter)
    171     *iter = StringToLowerASCII(*iter);
    172 }
    173 
    174 void Address::set_line2(const string16& line2) {
    175   line2_ = line2;
    176   line2_tokens_.clear();
    177   Tokenize(line2, kAddressSplitChars, &line2_tokens_);
    178   LineTokens::iterator iter;
    179   for (iter = line2_tokens_.begin(); iter != line2_tokens_.end(); ++iter)
    180     *iter = StringToLowerASCII(*iter);
    181 }
    182 
    183 void Address::SetCountry(const string16& country) {
    184   std::string app_locale = AutofillCountry::ApplicationLocale();
    185   country_code_ = AutofillCountry::GetCountryCode(country, app_locale);
    186 }
    187 
    188 bool Address::IsLine1(const string16& text) const {
    189   return IsLineMatch(text, line1_tokens_);
    190 }
    191 
    192 bool Address::IsLine2(const string16& text) const {
    193   return IsLineMatch(text, line2_tokens_);
    194 }
    195 
    196 bool Address::IsCity(const string16& text) const {
    197   return (StringToLowerASCII(city_) == StringToLowerASCII(text));
    198 }
    199 
    200 bool Address::IsState(const string16& text) const {
    201   return (StringToLowerASCII(state_) == StringToLowerASCII(text));
    202 }
    203 
    204 bool Address::IsCountry(const string16& text) const {
    205   std::string app_locale = AutofillCountry::ApplicationLocale();
    206   std::string country_code = AutofillCountry::GetCountryCode(text, app_locale);
    207   return (!country_code.empty() && country_code_ == country_code);
    208 }
    209 
    210 bool Address::IsZipCode(const string16& text) const {
    211   return zip_code_ == text;
    212 }
    213 
    214 bool Address::IsLineMatch(const string16& text,
    215                           const LineTokens& line_tokens) const {
    216   size_t line_tokens_size = line_tokens.size();
    217   if (line_tokens_size == 0)
    218     return false;
    219 
    220   LineTokens text_tokens;
    221   Tokenize(text, kAddressSplitChars, &text_tokens);
    222   size_t text_tokens_size = text_tokens.size();
    223   if (text_tokens_size == 0)
    224     return false;
    225 
    226   if (text_tokens_size > line_tokens_size)
    227     return false;
    228 
    229   // If each of the 'words' contained in the text are also present in the line,
    230   // then we will consider the text to match the line.
    231   LineTokens::iterator iter;
    232   for (iter = text_tokens.begin(); iter != text_tokens.end(); ++iter) {
    233     if (!IsWordInLine(*iter, line_tokens))
    234       return false;
    235   }
    236 
    237   return true;
    238 }
    239 
    240 bool Address::IsWordInLine(const string16& word,
    241                            const LineTokens& line_tokens) const {
    242   LineTokens::const_iterator iter;
    243   for (iter = line_tokens.begin(); iter != line_tokens.end(); ++iter) {
    244     if (StringToLowerASCII(word) == *iter)
    245       return true;
    246   }
    247 
    248   return false;
    249 }
    250