address.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
1// Copyright 2013 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 "components/autofill/core/browser/address.h"
6
7#include <stddef.h>
8#include <algorithm>
9
10#include "base/basictypes.h"
11#include "base/logging.h"
12#include "base/strings/string_split.h"
13#include "base/strings/string_util.h"
14#include "base/strings/utf_string_conversions.h"
15#include "components/autofill/core/browser/autofill_country.h"
16#include "components/autofill/core/browser/autofill_field.h"
17#include "components/autofill/core/browser/autofill_type.h"
18
19namespace autofill {
20
21Address::Address() {}
22
23Address::Address(const Address& address) : FormGroup() {
24  *this = address;
25}
26
27Address::~Address() {}
28
29Address& Address::operator=(const Address& address) {
30  if (this == &address)
31    return *this;
32
33  street_address_ = address.street_address_;
34  dependent_locality_ = address.dependent_locality_;
35  city_ = address.city_;
36  state_ = address.state_;
37  country_code_ = address.country_code_;
38  zip_code_ = address.zip_code_;
39  sorting_code_ = address.sorting_code_;
40  return *this;
41}
42
43base::string16 Address::GetRawInfo(ServerFieldType type) const {
44  DCHECK_EQ(ADDRESS_HOME, AutofillType(type).group());
45  switch (type) {
46    case ADDRESS_HOME_LINE1:
47      return street_address_.size() > 0 ? street_address_[0] : base::string16();
48
49    case ADDRESS_HOME_LINE2:
50      return street_address_.size() > 1 ? street_address_[1] : base::string16();
51
52    case ADDRESS_HOME_LINE3:
53      return street_address_.size() > 2 ? street_address_[2] : base::string16();
54
55    case ADDRESS_HOME_DEPENDENT_LOCALITY:
56      return dependent_locality_;
57
58    case ADDRESS_HOME_CITY:
59      return city_;
60
61    case ADDRESS_HOME_STATE:
62      return state_;
63
64    case ADDRESS_HOME_ZIP:
65      return zip_code_;
66
67    case ADDRESS_HOME_SORTING_CODE:
68      return sorting_code_;
69
70    case ADDRESS_HOME_COUNTRY:
71      return base::ASCIIToUTF16(country_code_);
72
73    case ADDRESS_HOME_STREET_ADDRESS:
74      return JoinString(street_address_, '\n');
75
76    default:
77      NOTREACHED();
78      return base::string16();
79  }
80}
81
82void Address::SetRawInfo(ServerFieldType type, const base::string16& value) {
83  DCHECK_EQ(ADDRESS_HOME, AutofillType(type).group());
84  switch (type) {
85    case ADDRESS_HOME_LINE1:
86      if (street_address_.empty())
87        street_address_.resize(1);
88      street_address_[0] = value;
89      TrimStreetAddress();
90      break;
91
92    case ADDRESS_HOME_LINE2:
93      if (street_address_.size() < 2)
94        street_address_.resize(2);
95      street_address_[1] = value;
96      TrimStreetAddress();
97      break;
98
99    case ADDRESS_HOME_LINE3:
100      if (street_address_.size() < 3)
101        street_address_.resize(3);
102      street_address_[2] = value;
103      TrimStreetAddress();
104      break;
105
106    case ADDRESS_HOME_DEPENDENT_LOCALITY:
107      dependent_locality_ = value;
108      break;
109
110    case ADDRESS_HOME_CITY:
111      city_ = value;
112      break;
113
114    case ADDRESS_HOME_STATE:
115      state_ = value;
116      break;
117
118    case ADDRESS_HOME_COUNTRY:
119      DCHECK(value.empty() ||
120             (value.length() == 2u && base::IsStringASCII(value)));
121      country_code_ = base::UTF16ToASCII(value);
122      break;
123
124    case ADDRESS_HOME_ZIP:
125      zip_code_ = value;
126      break;
127
128    case ADDRESS_HOME_SORTING_CODE:
129      sorting_code_ = value;
130      break;
131
132    case ADDRESS_HOME_STREET_ADDRESS:
133      base::SplitString(value, base::char16('\n'), &street_address_);
134      break;
135
136    default:
137      NOTREACHED();
138  }
139}
140
141base::string16 Address::GetInfo(const AutofillType& type,
142                                const std::string& app_locale) const {
143  if (type.html_type() == HTML_TYPE_COUNTRY_CODE)
144    return base::ASCIIToUTF16(country_code_);
145
146  ServerFieldType storable_type = type.GetStorableType();
147  if (storable_type == ADDRESS_HOME_COUNTRY && !country_code_.empty())
148    return AutofillCountry(country_code_, app_locale).name();
149
150  return GetRawInfo(storable_type);
151}
152
153bool Address::SetInfo(const AutofillType& type,
154                      const base::string16& value,
155                      const std::string& app_locale) {
156  if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
157    if (!value.empty() && (value.size() != 2u || !base::IsStringASCII(value))) {
158      country_code_ = std::string();
159      return false;
160    }
161
162    country_code_ = StringToUpperASCII(base::UTF16ToASCII(value));
163    return true;
164  } else if (type.html_type() == HTML_TYPE_FULL_ADDRESS) {
165    // Parsing a full address is too hard.
166    return false;
167  }
168
169  ServerFieldType storable_type = type.GetStorableType();
170  if (storable_type == ADDRESS_HOME_COUNTRY && !value.empty()) {
171    country_code_ = AutofillCountry::GetCountryCode(value, app_locale);
172    return !country_code_.empty();
173  }
174
175  // If the address doesn't have any newlines, don't attempt to parse it into
176  // lines, since this is potentially a user-entered address in the user's own
177  // format, so the code would have to rely on iffy heuristics at best.
178  // Instead, just give up when importing addresses like this.
179  if (storable_type == ADDRESS_HOME_STREET_ADDRESS && !value.empty() &&
180      value.find(base::char16('\n')) == base::string16::npos) {
181    street_address_.clear();
182    return false;
183  }
184
185  SetRawInfo(storable_type, value);
186
187  // Likewise, give up when importing addresses with any entirely blank lines.
188  // There's a good chance that this formatting is not intentional, but it's
189  // also not obviously safe to just strip the newlines.
190  if (storable_type == ADDRESS_HOME_STREET_ADDRESS &&
191      std::find(street_address_.begin(), street_address_.end(),
192                base::string16()) != street_address_.end()) {
193    street_address_.clear();
194    return false;
195  }
196
197  return true;
198}
199
200void Address::GetMatchingTypes(const base::string16& text,
201                               const std::string& app_locale,
202                               ServerFieldTypeSet* matching_types) const {
203  FormGroup::GetMatchingTypes(text, app_locale, matching_types);
204
205  // Check to see if the |text| canonicalized as a country name is a match.
206  std::string country_code = AutofillCountry::GetCountryCode(text, app_locale);
207  if (!country_code.empty() && country_code_ == country_code)
208    matching_types->insert(ADDRESS_HOME_COUNTRY);
209}
210
211void Address::GetSupportedTypes(ServerFieldTypeSet* supported_types) const {
212  supported_types->insert(ADDRESS_HOME_LINE1);
213  supported_types->insert(ADDRESS_HOME_LINE2);
214  supported_types->insert(ADDRESS_HOME_LINE3);
215  supported_types->insert(ADDRESS_HOME_STREET_ADDRESS);
216  supported_types->insert(ADDRESS_HOME_DEPENDENT_LOCALITY);
217  supported_types->insert(ADDRESS_HOME_CITY);
218  supported_types->insert(ADDRESS_HOME_STATE);
219  supported_types->insert(ADDRESS_HOME_ZIP);
220  supported_types->insert(ADDRESS_HOME_SORTING_CODE);
221  supported_types->insert(ADDRESS_HOME_COUNTRY);
222}
223
224void Address::TrimStreetAddress() {
225  while (!street_address_.empty() && street_address_.back().empty()) {
226    street_address_.pop_back();
227  }
228}
229
230}  // namespace autofill
231