• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/content/browser/wallet/wallet_address.h"
6 
7 #include "base/logging.h"
8 #include "base/strings/string_split.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "components/autofill/core/browser/autofill_country.h"
13 #include "components/autofill/core/browser/autofill_profile.h"
14 #include "components/autofill/core/browser/autofill_type.h"
15 #include "components/autofill/core/browser/phone_number.h"
16 #include "components/autofill/core/browser/state_names.h"
17 
18 namespace autofill {
19 namespace wallet {
20 
21 // Server specified type for address with complete details.
22 const char kFullAddress[] = "FULL";
23 
24 namespace {
25 
CreateAddressInternal(const base::DictionaryValue & dictionary,const std::string & object_id)26 Address* CreateAddressInternal(const base::DictionaryValue& dictionary,
27                                const std::string& object_id) {
28   std::string country_name_code;
29   if (!dictionary.GetString("postal_address.country_name_code",
30                             &country_name_code)) {
31     DLOG(ERROR) << "Response from Google Wallet missing country name";
32     return NULL;
33   }
34 
35   base::string16 recipient_name;
36   if (!dictionary.GetString("postal_address.recipient_name",
37                             &recipient_name)) {
38     DLOG(ERROR) << "Response from Google Wallet missing recipient name";
39     return NULL;
40   }
41 
42   base::string16 postal_code_number;
43   if (!dictionary.GetString("postal_address.postal_code_number",
44                             &postal_code_number)) {
45     DLOG(ERROR) << "Response from Google Wallet missing postal code number";
46     return NULL;
47   }
48   // TODO(estade): what about postal_code_number_extension?
49 
50   base::string16 sorting_code;
51   if (!dictionary.GetString("postal_address.sorting_code",
52                             &sorting_code)) {
53     DVLOG(1) << "Response from Google Wallet missing sorting code";
54   }
55 
56   base::string16 phone_number;
57   if (!dictionary.GetString("phone_number", &phone_number))
58     DVLOG(1) << "Response from Google Wallet missing phone number";
59 
60   std::vector<base::string16> street_address;
61   const base::ListValue* address_line_list;
62   if (dictionary.GetList("postal_address.address_line", &address_line_list)) {
63     for (size_t i = 0; i < address_line_list->GetSize(); ++i) {
64       base::string16 line;
65       address_line_list->GetString(i, &line);
66       street_address.push_back(line);
67     }
68   } else {
69     DVLOG(1) << "Response from Google Wallet missing address lines";
70   }
71 
72   base::string16 locality_name;
73   if (!dictionary.GetString("postal_address.locality_name",
74                             &locality_name)) {
75     DVLOG(1) << "Response from Google Wallet missing locality name";
76   }
77 
78   base::string16 dependent_locality_name;
79   if (!dictionary.GetString("postal_address.dependent_locality_name",
80                             &dependent_locality_name)) {
81     DVLOG(1) << "Response from Google Wallet missing dependent locality name";
82   }
83 
84   base::string16 administrative_area_name;
85   if (!dictionary.GetString("postal_address.administrative_area_name",
86                             &administrative_area_name)) {
87     DVLOG(1) << "Response from Google Wallet missing administrative area name";
88   }
89 
90   std::string language_code;
91   if (!dictionary.GetString("postal_address.language_code",
92                             &language_code)) {
93     DVLOG(1) << "Response from Google Wallet missing language code";
94   }
95 
96   Address* address = new Address(country_name_code,
97                                  recipient_name,
98                                  street_address,
99                                  locality_name,
100                                  dependent_locality_name,
101                                  administrative_area_name,
102                                  postal_code_number,
103                                  sorting_code,
104                                  phone_number,
105                                  object_id,
106                                  language_code);
107 
108   bool is_minimal_address = false;
109   if (dictionary.GetBoolean("is_minimal_address", &is_minimal_address))
110     address->set_is_complete_address(!is_minimal_address);
111   else
112     DVLOG(1) << "Response from Google Wallet missing is_minimal_address bit";
113 
114   return address;
115 }
116 
117 }  // namespace
118 
Address()119 Address::Address() {}
120 
Address(const AutofillProfile & profile)121 Address::Address(const AutofillProfile& profile)
122     : country_name_code_(
123           base::UTF16ToASCII(profile.GetRawInfo(ADDRESS_HOME_COUNTRY))),
124       recipient_name_(profile.GetRawInfo(NAME_FULL)),
125       locality_name_(profile.GetRawInfo(ADDRESS_HOME_CITY)),
126       dependent_locality_name_(
127           profile.GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY)),
128       administrative_area_name_(profile.GetRawInfo(ADDRESS_HOME_STATE)),
129       postal_code_number_(profile.GetRawInfo(ADDRESS_HOME_ZIP)),
130       sorting_code_(profile.GetRawInfo(ADDRESS_HOME_SORTING_CODE)),
131       phone_number_(profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER)),
132       is_complete_address_(true),
133       language_code_(profile.language_code()) {
134   base::SplitString(
135       profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS), '\n', &street_address_);
136 
137   if (!country_name_code_.empty())
138     phone_object_ = i18n::PhoneObject(phone_number_, country_name_code_);
139 }
140 
Address(const std::string & country_name_code,const base::string16 & recipient_name,const std::vector<base::string16> & street_address,const base::string16 & locality_name,const base::string16 & dependent_locality_name,const base::string16 & administrative_area_name,const base::string16 & postal_code_number,const base::string16 & sorting_code,const base::string16 & phone_number,const std::string & object_id,const std::string & language_code)141 Address::Address(const std::string& country_name_code,
142                  const base::string16& recipient_name,
143                  const std::vector<base::string16>& street_address,
144                  const base::string16& locality_name,
145                  const base::string16& dependent_locality_name,
146                  const base::string16& administrative_area_name,
147                  const base::string16& postal_code_number,
148                  const base::string16& sorting_code,
149                  const base::string16& phone_number,
150                  const std::string& object_id,
151                  const std::string& language_code)
152     : country_name_code_(country_name_code),
153       recipient_name_(recipient_name),
154       street_address_(street_address),
155       locality_name_(locality_name),
156       dependent_locality_name_(dependent_locality_name),
157       administrative_area_name_(administrative_area_name),
158       postal_code_number_(postal_code_number),
159       sorting_code_(sorting_code),
160       phone_number_(phone_number),
161       phone_object_(phone_number, country_name_code),
162       object_id_(object_id),
163       is_complete_address_(true),
164       language_code_(language_code) {}
165 
~Address()166 Address::~Address() {}
167 
168 // static
CreateAddressWithID(const base::DictionaryValue & dictionary)169 scoped_ptr<Address> Address::CreateAddressWithID(
170     const base::DictionaryValue& dictionary) {
171   std::string object_id;
172   if (!dictionary.GetString("id", &object_id)) {
173     DLOG(ERROR) << "Response from Google Wallet missing object id";
174     return scoped_ptr<Address>();
175   }
176   return scoped_ptr<Address>(CreateAddressInternal(dictionary, object_id));
177 }
178 
179 // static
CreateAddress(const base::DictionaryValue & dictionary)180 scoped_ptr<Address> Address::CreateAddress(
181     const base::DictionaryValue& dictionary) {
182   std::string object_id;
183   dictionary.GetString("id", &object_id);
184   return scoped_ptr<Address>(CreateAddressInternal(dictionary, object_id));
185 }
186 
187 // static
CreateDisplayAddress(const base::DictionaryValue & dictionary)188 scoped_ptr<Address> Address::CreateDisplayAddress(
189     const base::DictionaryValue& dictionary) {
190   std::string country_code;
191   if (!dictionary.GetString("country_code", &country_code)) {
192     DLOG(ERROR) << "Reponse from Google Wallet missing country code";
193     return scoped_ptr<Address>();
194   }
195 
196   base::string16 name;
197   if (!dictionary.GetString("name", &name)) {
198     DLOG(ERROR) << "Reponse from Google Wallet missing name";
199     return scoped_ptr<Address>();
200   }
201 
202   base::string16 postal_code;
203   if (!dictionary.GetString("postal_code", &postal_code)) {
204     DLOG(ERROR) << "Reponse from Google Wallet missing postal code";
205     return scoped_ptr<Address>();
206   }
207 
208   base::string16 sorting_code;
209   if (!dictionary.GetString("sorting_code", &sorting_code)) {
210     DVLOG(1) << "Reponse from Google Wallet missing sorting code";
211   }
212 
213   std::vector<base::string16> street_address;
214   base::string16 address1;
215   if (dictionary.GetString("address1", &address1))
216     street_address.push_back(address1);
217   else
218     DVLOG(1) << "Reponse from Google Wallet missing address1";
219 
220   base::string16 address2;
221   if (dictionary.GetString("address2", &address2) && !address2.empty()) {
222     street_address.resize(2);
223     street_address[1] = address2;
224   } else {
225     DVLOG(1) << "Reponse from Google Wallet missing or empty address2";
226   }
227 
228   base::string16 city;
229   if (!dictionary.GetString("city", &city))
230     DVLOG(1) << "Reponse from Google Wallet missing city";
231 
232   base::string16 dependent_locality_name;
233   if (!dictionary.GetString("dependent_locality_name",
234                             &dependent_locality_name)) {
235     DVLOG(1) << "Reponse from Google Wallet missing district";
236   }
237 
238   base::string16 state;
239   if (!dictionary.GetString("state", &state))
240     DVLOG(1) << "Reponse from Google Wallet missing state";
241 
242   base::string16 phone_number;
243   if (!dictionary.GetString("phone_number", &phone_number))
244     DVLOG(1) << "Reponse from Google Wallet missing phone number";
245 
246   std::string address_state;
247   if (!dictionary.GetString("type", &address_state))
248     DVLOG(1) << "Response from Google Wallet missing type/state of address";
249 
250   std::string language_code;
251   if (!dictionary.GetString("language_code", &language_code))
252     DVLOG(1) << "Response from Google Wallet missing language code";
253 
254   scoped_ptr<Address> address(
255       new Address(country_code,
256                   name,
257                   street_address,
258                   city,
259                   dependent_locality_name,
260                   state,
261                   postal_code,
262                   sorting_code,
263                   phone_number,
264                   std::string(),
265                   language_code));
266   address->set_is_complete_address(address_state == kFullAddress);
267 
268   return address.Pass();
269 }
270 
ToDictionaryWithID() const271 scoped_ptr<base::DictionaryValue> Address::ToDictionaryWithID() const {
272   scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
273 
274   if (!object_id_.empty())
275     dict->SetString("id", object_id_);
276   dict->SetString("phone_number", phone_number_);
277   dict->Set("postal_address", ToDictionaryWithoutID().release());
278 
279   return dict.Pass();
280 }
281 
ToDictionaryWithoutID() const282 scoped_ptr<base::DictionaryValue> Address::ToDictionaryWithoutID() const {
283   scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
284 
285   scoped_ptr<base::ListValue> address_lines(new base::ListValue());
286   address_lines->AppendStrings(street_address_);
287   dict->Set("address_line", address_lines.release());
288 
289   dict->SetString("country_name_code", country_name_code_);
290   dict->SetString("recipient_name", recipient_name_);
291   dict->SetString("locality_name", locality_name_);
292   dict->SetString("dependent_locality_name", dependent_locality_name_);
293   dict->SetString("administrative_area_name",
294                   administrative_area_name_);
295   dict->SetString("postal_code_number", postal_code_number_);
296   dict->SetString("sorting_code", sorting_code_);
297   dict->SetString("language_code", language_code_);
298 
299   return dict.Pass();
300 }
301 
DisplayName() const302 base::string16 Address::DisplayName() const {
303 #if defined(OS_ANDROID)
304   // TODO(aruslan): improve this stub implementation.
305   return recipient_name();
306 #else
307   // TODO(estade): improve this stub implementation + l10n.
308   return recipient_name() + base::ASCIIToUTF16(", ") + GetStreetAddressLine(0);
309 #endif
310 }
311 
DisplayNameDetail() const312 base::string16 Address::DisplayNameDetail() const {
313 #if defined(OS_ANDROID)
314   // TODO(aruslan): improve this stub implementation.
315   return GetStreetAddressLine(0);
316 #else
317   return base::string16();
318 #endif
319 }
320 
DisplayPhoneNumber() const321 base::string16 Address::DisplayPhoneNumber() const {
322   // Return a formatted phone number. Wallet doesn't store user formatting, so
323   // impose our own. phone_number() always includes a country code, so using
324   // PhoneObject to format it would result in an internationalized format. Since
325   // Wallet only supports the US right now, stick to national formatting.
326   return i18n::PhoneObject(phone_number(), country_name_code()).
327       GetNationallyFormattedNumber();
328 }
329 
GetInfo(const AutofillType & type,const std::string & app_locale) const330 base::string16 Address::GetInfo(const AutofillType& type,
331                                 const std::string& app_locale) const {
332   if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
333     DCHECK(base::IsStringASCII(country_name_code()));
334     return base::ASCIIToUTF16(country_name_code());
335   }
336 
337   switch (type.GetStorableType()) {
338     case NAME_FULL:
339       return recipient_name();
340 
341     case ADDRESS_HOME_STREET_ADDRESS:
342       return JoinString(street_address_, base::ASCIIToUTF16("\n"));
343 
344     case ADDRESS_HOME_LINE1:
345       return GetStreetAddressLine(0);
346 
347     case ADDRESS_HOME_LINE2:
348       return GetStreetAddressLine(1);
349 
350     case ADDRESS_HOME_CITY:
351       return locality_name();
352 
353     case ADDRESS_HOME_STATE:
354       return administrative_area_name();
355 
356     case ADDRESS_HOME_ZIP:
357       return postal_code_number();
358 
359     case ADDRESS_HOME_COUNTRY: {
360       AutofillCountry country(country_name_code(), app_locale);
361       return country.name();
362     }
363 
364     case PHONE_HOME_WHOLE_NUMBER:
365       // Wallet doesn't store user phone number formatting, so just strip all
366       // formatting.
367       return phone_object_.GetWholeNumber();
368 
369     case ADDRESS_HOME_DEPENDENT_LOCALITY:
370       return dependent_locality_name_;
371 
372     case ADDRESS_HOME_SORTING_CODE:
373       return sorting_code_;
374 
375     case COMPANY_NAME:
376       // A field that Wallet doesn't support. TODO(dbeam): can it be supported?
377       return base::string16();
378 
379     default:
380       NOTREACHED();
381       return base::string16();
382   }
383 }
384 
SetPhoneNumber(const base::string16 & phone_number)385 void Address::SetPhoneNumber(const base::string16& phone_number) {
386   phone_number_ = phone_number;
387   phone_object_ = i18n::PhoneObject(phone_number_, country_name_code_);
388 }
389 
EqualsIgnoreID(const Address & other) const390 bool Address::EqualsIgnoreID(const Address& other) const {
391   return country_name_code_ == other.country_name_code_ &&
392          recipient_name_ == other.recipient_name_ &&
393          street_address_ == other.street_address_ &&
394          locality_name_ == other.locality_name_ &&
395          dependent_locality_name_ == other.dependent_locality_name_ &&
396          administrative_area_name_ == other.administrative_area_name_ &&
397          postal_code_number_ == other.postal_code_number_ &&
398          sorting_code_ == other.sorting_code_ &&
399          phone_number_ == other.phone_number_ &&
400          is_complete_address_ == other.is_complete_address_;
401 }
402 
GetStreetAddressLine(size_t line) const403 base::string16 Address::GetStreetAddressLine(size_t line) const {
404   return street_address_.size() > line ? street_address_[line] :
405                                          base::string16();
406 }
407 
operator ==(const Address & other) const408 bool Address::operator==(const Address& other) const {
409   return object_id_ == other.object_id_ &&
410          language_code_ == other.language_code_ &&
411          EqualsIgnoreID(other);
412 }
413 
operator !=(const Address & other) const414 bool Address::operator!=(const Address& other) const {
415   return !(*this == other);
416 }
417 
418 }  // namespace wallet
419 }  // namespace autofill
420