address.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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_DEPENDENT_LOCALITY:
53      return dependent_locality_;
54
55    case ADDRESS_HOME_CITY:
56      return city_;
57
58    case ADDRESS_HOME_STATE:
59      return state_;
60
61    case ADDRESS_HOME_ZIP:
62      return zip_code_;
63
64    case ADDRESS_HOME_SORTING_CODE:
65      return sorting_code_;
66
67    case ADDRESS_HOME_COUNTRY:
68      return base::ASCIIToUTF16(country_code_);
69
70    case ADDRESS_HOME_STREET_ADDRESS:
71      return JoinString(street_address_, '\n');
72
73    default:
74      NOTREACHED();
75      return base::string16();
76  }
77}
78
79void Address::SetRawInfo(ServerFieldType type, const base::string16& value) {
80  DCHECK_EQ(ADDRESS_HOME, AutofillType(type).group());
81  switch (type) {
82    case ADDRESS_HOME_LINE1:
83      if (street_address_.empty())
84        street_address_.resize(1);
85      street_address_[0] = value;
86      TrimStreetAddress();
87      break;
88
89    case ADDRESS_HOME_LINE2:
90      if (street_address_.size() < 2)
91        street_address_.resize(2);
92      street_address_[1] = value;
93      TrimStreetAddress();
94      break;
95
96    case ADDRESS_HOME_DEPENDENT_LOCALITY:
97      dependent_locality_ = value;
98      break;
99
100    case ADDRESS_HOME_CITY:
101      city_ = value;
102      break;
103
104    case ADDRESS_HOME_STATE:
105      state_ = value;
106      break;
107
108    case ADDRESS_HOME_COUNTRY:
109      DCHECK(value.empty() ||
110             (value.length() == 2u && IsStringASCII(value)));
111      country_code_ = UTF16ToASCII(value);
112      break;
113
114    case ADDRESS_HOME_ZIP:
115      zip_code_ = value;
116      break;
117
118    case ADDRESS_HOME_SORTING_CODE:
119      sorting_code_ = value;
120      break;
121
122    case ADDRESS_HOME_STREET_ADDRESS:
123      base::SplitString(value, base::char16('\n'), &street_address_);
124      break;
125
126    default:
127      NOTREACHED();
128  }
129}
130
131base::string16 Address::GetInfo(const AutofillType& type,
132                                const std::string& app_locale) const {
133  if (type.html_type() == HTML_TYPE_COUNTRY_CODE)
134    return base::ASCIIToUTF16(country_code_);
135
136  ServerFieldType storable_type = type.GetStorableType();
137  if (storable_type == ADDRESS_HOME_COUNTRY && !country_code_.empty())
138    return AutofillCountry(country_code_, app_locale).name();
139
140  return GetRawInfo(storable_type);
141}
142
143bool Address::SetInfo(const AutofillType& type,
144                      const base::string16& value,
145                      const std::string& app_locale) {
146  if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
147    if (!value.empty() && (value.size() != 2u || !IsStringASCII(value))) {
148      country_code_ = std::string();
149      return false;
150    }
151
152    country_code_ = StringToUpperASCII(UTF16ToASCII(value));
153    return true;
154  }
155
156  ServerFieldType storable_type = type.GetStorableType();
157  if (storable_type == ADDRESS_HOME_COUNTRY && !value.empty()) {
158    country_code_ = AutofillCountry::GetCountryCode(value, app_locale);
159    return !country_code_.empty();
160  }
161
162  // If the address doesn't have any newlines, don't attempt to parse it into
163  // lines, since this is potentially a user-entered address in the user's own
164  // format, so the code would have to rely on iffy heuristics at best.
165  // Instead, just give up when importing addresses like this.
166  if (storable_type == ADDRESS_HOME_STREET_ADDRESS && !value.empty() &&
167      value.find(base::char16('\n')) == base::string16::npos) {
168    street_address_.clear();
169    return false;
170  }
171
172  SetRawInfo(storable_type, value);
173
174  // Likewise, give up when importing addresses with any entirely blank lines.
175  // There's a good chance that this formatting is not intentional, but it's
176  // also not obviously safe to just strip the newlines.
177  if (storable_type == ADDRESS_HOME_STREET_ADDRESS &&
178      std::find(street_address_.begin(), street_address_.end(),
179                base::string16()) != street_address_.end()) {
180    street_address_.clear();
181    return false;
182  }
183
184  return true;
185}
186
187void Address::GetMatchingTypes(const base::string16& text,
188                               const std::string& app_locale,
189                               ServerFieldTypeSet* matching_types) const {
190  FormGroup::GetMatchingTypes(text, app_locale, matching_types);
191
192  // Check to see if the |text| canonicalized as a country name is a match.
193  std::string country_code = AutofillCountry::GetCountryCode(text, app_locale);
194  if (!country_code.empty() && country_code_ == country_code)
195    matching_types->insert(ADDRESS_HOME_COUNTRY);
196}
197
198void Address::GetSupportedTypes(ServerFieldTypeSet* supported_types) const {
199  supported_types->insert(ADDRESS_HOME_LINE1);
200  supported_types->insert(ADDRESS_HOME_LINE2);
201  supported_types->insert(ADDRESS_HOME_STREET_ADDRESS);
202  supported_types->insert(ADDRESS_HOME_DEPENDENT_LOCALITY);
203  supported_types->insert(ADDRESS_HOME_CITY);
204  supported_types->insert(ADDRESS_HOME_STATE);
205  supported_types->insert(ADDRESS_HOME_ZIP);
206  supported_types->insert(ADDRESS_HOME_SORTING_CODE);
207  supported_types->insert(ADDRESS_HOME_COUNTRY);
208}
209
210void Address::TrimStreetAddress() {
211  while (!street_address_.empty() && street_address_.back().empty()) {
212    street_address_.pop_back();
213  }
214}
215
216}  // namespace autofill
217