Home | History | Annotate | Download | only in wallet
      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_util.h"
      9 #include "base/strings/utf_string_conversions.h"
     10 #include "base/values.h"
     11 #include "components/autofill/core/browser/autofill_country.h"
     12 #include "components/autofill/core/browser/autofill_profile.h"
     13 #include "components/autofill/core/browser/autofill_type.h"
     14 #include "components/autofill/core/browser/state_names.h"
     15 
     16 namespace autofill {
     17 namespace wallet {
     18 
     19 // Server specified type for address with complete details.
     20 const char kFullAddress[] = "FULL";
     21 
     22 namespace {
     23 
     24 Address* CreateAddressInternal(const base::DictionaryValue& dictionary,
     25                                const std::string& object_id) {
     26   std::string country_name_code;
     27   if (!dictionary.GetString("postal_address.country_name_code",
     28                             &country_name_code)) {
     29     DLOG(ERROR) << "Response from Google Wallet missing country name";
     30     return NULL;
     31   }
     32 
     33   string16 recipient_name;
     34   if (!dictionary.GetString("postal_address.recipient_name",
     35                             &recipient_name)) {
     36     DLOG(ERROR) << "Response from Google Wallet missing recipient name";
     37     return NULL;
     38   }
     39 
     40   string16 postal_code_number;
     41   if (!dictionary.GetString("postal_address.postal_code_number",
     42                             &postal_code_number)) {
     43     DLOG(ERROR) << "Response from Google Wallet missing postal code number";
     44     return NULL;
     45   }
     46 
     47   string16 phone_number;
     48   if (!dictionary.GetString("phone_number", &phone_number))
     49     DVLOG(1) << "Response from Google Wallet missing phone number";
     50 
     51   string16 address_line_1;
     52   string16 address_line_2;
     53   const ListValue* address_line_list;
     54   if (dictionary.GetList("postal_address.address_line", &address_line_list)) {
     55     if (!address_line_list->GetString(0, &address_line_1))
     56       DVLOG(1) << "Response from Google Wallet missing address line 1";
     57     if (!address_line_list->GetString(1, &address_line_2))
     58       DVLOG(1) << "Response from Google Wallet missing address line 2";
     59   } else {
     60     DVLOG(1) << "Response from Google Wallet missing address lines";
     61   }
     62 
     63   string16 locality_name;
     64   if (!dictionary.GetString("postal_address.locality_name",
     65                             &locality_name)) {
     66     DVLOG(1) << "Response from Google Wallet missing locality name";
     67   }
     68 
     69   string16 administrative_area_name;
     70   if (!dictionary.GetString("postal_address.administrative_area_name",
     71                             &administrative_area_name)) {
     72     DVLOG(1) << "Response from Google Wallet missing administrative area name";
     73   }
     74 
     75   Address* address = new Address(country_name_code,
     76                                  recipient_name,
     77                                  address_line_1,
     78                                  address_line_2,
     79                                  locality_name,
     80                                  administrative_area_name,
     81                                  postal_code_number,
     82                                  phone_number,
     83                                  object_id);
     84 
     85   bool is_minimal_address = false;
     86   if (dictionary.GetBoolean("is_minimal_address", &is_minimal_address))
     87     address->set_is_complete_address(!is_minimal_address);
     88   else
     89     DVLOG(1) << "Response from Google Wallet missing is_minimal_address bit";
     90 
     91   return address;
     92 }
     93 
     94 }  // namespace
     95 
     96 Address::Address() {}
     97 
     98 Address::Address(const AutofillProfile& profile)
     99     : country_name_code_(
    100           UTF16ToASCII(profile.GetRawInfo(ADDRESS_HOME_COUNTRY))),
    101       recipient_name_(profile.GetRawInfo(NAME_FULL)),
    102       address_line_1_(profile.GetRawInfo(ADDRESS_HOME_LINE1)),
    103       address_line_2_(profile.GetRawInfo(ADDRESS_HOME_LINE2)),
    104       locality_name_(profile.GetRawInfo(ADDRESS_HOME_CITY)),
    105       postal_code_number_(profile.GetRawInfo(ADDRESS_HOME_ZIP)),
    106       phone_number_(profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER)),
    107       is_complete_address_(true) {
    108   state_names::GetNameAndAbbreviation(profile.GetRawInfo(ADDRESS_HOME_STATE),
    109                                       NULL,
    110                                       &administrative_area_name_);
    111   StringToUpperASCII(&administrative_area_name_);
    112 }
    113 
    114 Address::Address(const std::string& country_name_code,
    115                  const string16& recipient_name,
    116                  const string16& address_line_1,
    117                  const string16& address_line_2,
    118                  const string16& locality_name,
    119                  const string16& administrative_area_name,
    120                  const string16& postal_code_number,
    121                  const string16& phone_number,
    122                  const std::string& object_id)
    123     : country_name_code_(country_name_code),
    124       recipient_name_(recipient_name),
    125       address_line_1_(address_line_1),
    126       address_line_2_(address_line_2),
    127       locality_name_(locality_name),
    128       administrative_area_name_(administrative_area_name),
    129       postal_code_number_(postal_code_number),
    130       phone_number_(phone_number),
    131       object_id_(object_id),
    132       is_complete_address_(true) {
    133 }
    134 
    135 Address::~Address() {}
    136 
    137 // static
    138 scoped_ptr<Address> Address::CreateAddressWithID(
    139     const base::DictionaryValue& dictionary) {
    140   std::string object_id;
    141   if (!dictionary.GetString("id", &object_id)) {
    142     DLOG(ERROR) << "Response from Google Wallet missing object id";
    143     return scoped_ptr<Address>();
    144   }
    145   return scoped_ptr<Address>(CreateAddressInternal(dictionary, object_id));
    146 }
    147 
    148 // static
    149 scoped_ptr<Address> Address::CreateAddress(
    150     const base::DictionaryValue& dictionary) {
    151   std::string object_id;
    152   dictionary.GetString("id", &object_id);
    153   return scoped_ptr<Address>(CreateAddressInternal(dictionary, object_id));
    154 }
    155 
    156 // static
    157 scoped_ptr<Address> Address::CreateDisplayAddress(
    158     const base::DictionaryValue& dictionary) {
    159   std::string country_code;
    160   if (!dictionary.GetString("country_code", &country_code)) {
    161     DLOG(ERROR) << "Reponse from Google Wallet missing country code";
    162     return scoped_ptr<Address>();
    163   }
    164 
    165   string16 name;
    166   if (!dictionary.GetString("name", &name)) {
    167     DLOG(ERROR) << "Reponse from Google Wallet missing name";
    168     return scoped_ptr<Address>();
    169   }
    170 
    171   string16 postal_code;
    172   if (!dictionary.GetString("postal_code", &postal_code)) {
    173     DLOG(ERROR) << "Reponse from Google Wallet missing postal code";
    174     return scoped_ptr<Address>();
    175   }
    176 
    177   string16 address1;
    178   if (!dictionary.GetString("address1", &address1))
    179     DVLOG(1) << "Reponse from Google Wallet missing address1";
    180 
    181   string16 address2;
    182   if (!dictionary.GetString("address2", &address2))
    183     DVLOG(1) << "Reponse from Google Wallet missing address2";
    184 
    185   string16 city;
    186   if (!dictionary.GetString("city", &city))
    187     DVLOG(1) << "Reponse from Google Wallet missing city";
    188 
    189   string16 state;
    190   if (!dictionary.GetString("state", &state))
    191     DVLOG(1) << "Reponse from Google Wallet missing state";
    192 
    193   string16 phone_number;
    194   if (!dictionary.GetString("phone_number", &phone_number))
    195     DVLOG(1) << "Reponse from Google Wallet missing phone number";
    196 
    197   std::string address_state;
    198   if (!dictionary.GetString("type", &address_state))
    199     DVLOG(1) << "Response from Google Wallet missing type/state of address";
    200 
    201   scoped_ptr<Address> address(
    202       new Address(country_code,
    203                   name,
    204                   address1,
    205                   address2,
    206                   city,
    207                   state,
    208                   postal_code,
    209                   phone_number,
    210                   std::string()));
    211   address->set_is_complete_address(address_state == kFullAddress);
    212 
    213   return address.Pass();
    214 }
    215 
    216 scoped_ptr<base::DictionaryValue> Address::ToDictionaryWithID() const {
    217   scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
    218 
    219   if (!object_id_.empty())
    220     dict->SetString("id", object_id_);
    221   dict->SetString("phone_number", phone_number_);
    222   dict->Set("postal_address", ToDictionaryWithoutID().release());
    223 
    224   return dict.Pass();
    225 }
    226 
    227 scoped_ptr<base::DictionaryValue> Address::ToDictionaryWithoutID() const {
    228   scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
    229 
    230   scoped_ptr<base::ListValue> address_lines(new base::ListValue());
    231   address_lines->AppendString(address_line_1_);
    232   if (!address_line_2_.empty())
    233     address_lines->AppendString(address_line_2_);
    234   dict->Set("address_line", address_lines.release());
    235 
    236   dict->SetString("country_name_code", country_name_code_);
    237   dict->SetString("recipient_name", recipient_name_);
    238   dict->SetString("locality_name", locality_name_);
    239   dict->SetString("administrative_area_name",
    240                   administrative_area_name_);
    241   dict->SetString("postal_code_number", postal_code_number_);
    242 
    243   return dict.Pass();
    244 }
    245 
    246 string16 Address::DisplayName() const {
    247 #if defined(OS_ANDROID)
    248   // TODO(aruslan): improve this stub implementation.
    249   return recipient_name();
    250 #else
    251   // TODO(estade): improve this stub implementation + l10n.
    252   return recipient_name() + ASCIIToUTF16(", ") + address_line_1();
    253 #endif
    254 }
    255 
    256 string16 Address::DisplayNameDetail() const {
    257 #if defined(OS_ANDROID)
    258   // TODO(aruslan): improve this stub implementation.
    259   return address_line_1();
    260 #else
    261   return string16();
    262 #endif
    263 }
    264 
    265 string16 Address::GetInfo(const AutofillType& type,
    266                           const std::string& app_locale) const {
    267   if (type.html_type() == HTML_TYPE_COUNTRY_CODE) {
    268     DCHECK(IsStringASCII(country_name_code()));
    269     return ASCIIToUTF16(country_name_code());
    270   } else if (type.html_type() == HTML_TYPE_STREET_ADDRESS) {
    271     base::string16 address = address_line_1();
    272     if (!address_line_2().empty())
    273       address += ASCIIToUTF16(", ") + address_line_2();
    274     return address;
    275   }
    276 
    277   switch (type.GetStorableType()) {
    278     case NAME_FULL:
    279       return recipient_name();
    280 
    281     case ADDRESS_HOME_LINE1:
    282       return address_line_1();
    283 
    284     case ADDRESS_HOME_LINE2:
    285       return address_line_2();
    286 
    287     case ADDRESS_HOME_CITY:
    288       return locality_name();
    289 
    290     case ADDRESS_HOME_STATE:
    291       return administrative_area_name();
    292 
    293     case ADDRESS_HOME_ZIP:
    294       return postal_code_number();
    295 
    296     case ADDRESS_HOME_COUNTRY: {
    297       AutofillCountry country(country_name_code(), app_locale);
    298       return country.name();
    299     }
    300 
    301     case PHONE_HOME_WHOLE_NUMBER:
    302       return phone_number();
    303 
    304     // TODO(estade): implement more.
    305     default:
    306       NOTREACHED();
    307       return string16();
    308   }
    309 }
    310 
    311 bool Address::EqualsIgnoreID(const Address& other) const {
    312   return country_name_code_ == other.country_name_code_ &&
    313          recipient_name_ == other.recipient_name_ &&
    314          address_line_1_ == other.address_line_1_ &&
    315          address_line_2_ == other.address_line_2_ &&
    316          locality_name_ == other.locality_name_ &&
    317          administrative_area_name_ == other.administrative_area_name_ &&
    318          postal_code_number_ == other.postal_code_number_ &&
    319          phone_number_ == other.phone_number_ &&
    320          is_complete_address_ == other.is_complete_address_;
    321 }
    322 
    323 bool Address::operator==(const Address& other) const {
    324   return object_id_ == other.object_id_ && EqualsIgnoreID(other);
    325 }
    326 
    327 bool Address::operator!=(const Address& other) const {
    328   return !(*this == other);
    329 }
    330 
    331 }  // namespace wallet
    332 }  // namespace autofill
    333