Home | History | Annotate | Download | only in options
      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/ui/webui/options/autofill_options_handler.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/logging.h"
     10 #include "base/string16.h"
     11 #include "base/string_number_conversions.h"
     12 #include "base/utf_string_conversions.h"
     13 #include "base/values.h"
     14 #include "chrome/browser/autofill/autofill_country.h"
     15 #include "chrome/browser/autofill/autofill_profile.h"
     16 #include "chrome/browser/autofill/credit_card.h"
     17 #include "chrome/browser/profiles/profile.h"
     18 #include "chrome/browser/ui/webui/web_ui_util.h"
     19 #include "chrome/common/guid.h"
     20 #include "grit/generated_resources.h"
     21 #include "grit/webkit_resources.h"
     22 #include "ui/base/l10n/l10n_util.h"
     23 
     24 namespace {
     25 
     26 // Converts a credit card type to the appropriate resource ID of the CC icon.
     27 int CreditCardTypeToResourceID(const std::string& type) {
     28   if (type == kAmericanExpressCard)
     29     return IDR_AUTOFILL_CC_AMEX;
     30   else if (type == kDinersCard)
     31     return IDR_AUTOFILL_CC_DINERS;
     32   else if (type == kDiscoverCard)
     33     return IDR_AUTOFILL_CC_DISCOVER;
     34   else if (type == kGenericCard)
     35     return IDR_AUTOFILL_CC_GENERIC;
     36   else if (type == kJCBCard)
     37     return IDR_AUTOFILL_CC_JCB;
     38   else if (type == kMasterCard)
     39     return IDR_AUTOFILL_CC_MASTERCARD;
     40   else if (type == kSoloCard)
     41     return IDR_AUTOFILL_CC_SOLO;
     42   else if (type == kVisaCard)
     43     return IDR_AUTOFILL_CC_VISA;
     44 
     45   NOTREACHED();
     46   return 0;
     47 }
     48 
     49 // Converts a credit card type to the appropriate localized card type.
     50 string16 LocalizedCreditCardType(const std::string& type) {
     51   if (type == kAmericanExpressCard)
     52     return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX);
     53   else if (type == kDinersCard)
     54     return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DINERS);
     55   else if (type == kDiscoverCard)
     56     return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DISCOVER);
     57   else if (type == kGenericCard)
     58     return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_GENERIC);
     59   else if (type == kJCBCard)
     60     return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_JCB);
     61   else if (type == kMasterCard)
     62     return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MASTERCARD);
     63   else if (type == kSoloCard)
     64     return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_SOLO);
     65   else if (type == kVisaCard)
     66     return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_VISA);
     67 
     68   NOTREACHED();
     69   return string16();
     70 }
     71 
     72 // Returns a dictionary that maps country codes to data for the country.
     73 DictionaryValue* GetCountryData() {
     74   std::string app_locale = AutofillCountry::ApplicationLocale();
     75   std::vector<std::string> country_codes;
     76   AutofillCountry::GetAvailableCountries(&country_codes);
     77 
     78   DictionaryValue* country_data = new DictionaryValue();
     79   for (size_t i = 0; i < country_codes.size(); ++i) {
     80     const AutofillCountry country(country_codes[i], app_locale);
     81 
     82     DictionaryValue* details = new DictionaryValue();
     83     details->SetString("name", country.name());
     84     details->SetString("postalCodeLabel", country.postal_code_label());
     85     details->SetString("stateLabel", country.state_label());
     86 
     87     country_data->Set(country.country_code(), details);
     88   }
     89 
     90   return country_data;
     91 }
     92 
     93 // Get the multi-valued element for |type| and return it in |ListValue| form.
     94 void GetValueList(const AutofillProfile& profile,
     95                   AutofillFieldType type,
     96                   scoped_ptr<ListValue>* list) {
     97   std::vector<string16> values;
     98   profile.GetMultiInfo(type, &values);
     99   list->reset(new ListValue);
    100   for (size_t i = 0; i < values.size(); ++i) {
    101     (*list)->Set(i, Value::CreateStringValue(values[i]));
    102   }
    103 }
    104 
    105 // Set the multi-valued element for |type| from input |list| values.
    106 void SetValueList(const ListValue* list,
    107                   AutofillFieldType type,
    108                   AutofillProfile* profile) {
    109   std::vector<string16> values(list->GetSize());
    110   for (size_t i = 0; i < list->GetSize(); ++i) {
    111     string16 value;
    112     if (list->GetString(i, &value))
    113       values[i] = value;
    114   }
    115   profile->SetMultiInfo(type, values);
    116 }
    117 
    118 }  // namespace
    119 
    120 AutofillOptionsHandler::AutofillOptionsHandler()
    121     : personal_data_(NULL) {
    122 }
    123 
    124 AutofillOptionsHandler::~AutofillOptionsHandler() {
    125   if (personal_data_)
    126     personal_data_->RemoveObserver(this);
    127 }
    128 
    129 /////////////////////////////////////////////////////////////////////////////
    130 // OptionsPageUIHandler implementation:
    131 void AutofillOptionsHandler::GetLocalizedValues(
    132     DictionaryValue* localized_strings) {
    133   DCHECK(localized_strings);
    134 
    135   static OptionsStringResource resources[] = {
    136     { "autofillAddresses", IDS_AUTOFILL_ADDRESSES_GROUP_NAME },
    137     { "autofillCreditCards", IDS_AUTOFILL_CREDITCARDS_GROUP_NAME },
    138     { "autofillAddAddress", IDS_AUTOFILL_ADD_ADDRESS_BUTTON },
    139     { "autofillAddCreditCard", IDS_AUTOFILL_ADD_CREDITCARD_BUTTON },
    140     { "helpButton", IDS_AUTOFILL_HELP_LABEL },
    141     { "addAddressTitle", IDS_AUTOFILL_ADD_ADDRESS_CAPTION },
    142     { "editAddressTitle", IDS_AUTOFILL_EDIT_ADDRESS_CAPTION },
    143     { "addCreditCardTitle", IDS_AUTOFILL_ADD_CREDITCARD_CAPTION },
    144     { "editCreditCardTitle", IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION },
    145 #if defined(OS_MACOSX)
    146     { "auxiliaryProfilesEnabled", IDS_AUTOFILL_USE_MAC_ADDRESS_BOOK },
    147 #endif  // defined(OS_MACOSX)
    148   };
    149 
    150   RegisterStrings(localized_strings, resources, arraysize(resources));
    151   RegisterTitle(localized_strings, "autofillOptionsPage",
    152                 IDS_AUTOFILL_OPTIONS_TITLE);
    153 
    154   SetAddressOverlayStrings(localized_strings);
    155   SetCreditCardOverlayStrings(localized_strings);
    156 }
    157 
    158 void AutofillOptionsHandler::Initialize() {
    159   personal_data_ = web_ui_->GetProfile()->GetPersonalDataManager();
    160   personal_data_->SetObserver(this);
    161 
    162   LoadAutofillData();
    163 }
    164 
    165 void AutofillOptionsHandler::RegisterMessages() {
    166   web_ui_->RegisterMessageCallback(
    167       "removeAddress",
    168       NewCallback(this, &AutofillOptionsHandler::RemoveAddress));
    169   web_ui_->RegisterMessageCallback(
    170       "removeCreditCard",
    171       NewCallback(this, &AutofillOptionsHandler::RemoveCreditCard));
    172   web_ui_->RegisterMessageCallback(
    173       "loadAddressEditor",
    174       NewCallback(this, &AutofillOptionsHandler::LoadAddressEditor));
    175   web_ui_->RegisterMessageCallback(
    176       "loadCreditCardEditor",
    177       NewCallback(this, &AutofillOptionsHandler::LoadCreditCardEditor));
    178   web_ui_->RegisterMessageCallback(
    179       "setAddress",
    180       NewCallback(this, &AutofillOptionsHandler::SetAddress));
    181   web_ui_->RegisterMessageCallback(
    182       "setCreditCard",
    183       NewCallback(this, &AutofillOptionsHandler::SetCreditCard));
    184 }
    185 
    186 /////////////////////////////////////////////////////////////////////////////
    187 // PersonalDataManager::Observer implementation:
    188 void  AutofillOptionsHandler::OnPersonalDataLoaded() {
    189   LoadAutofillData();
    190 }
    191 
    192 void AutofillOptionsHandler::OnPersonalDataChanged() {
    193   LoadAutofillData();
    194 }
    195 
    196 void AutofillOptionsHandler::SetAddressOverlayStrings(
    197     DictionaryValue* localized_strings) {
    198   localized_strings->SetString("autofillEditAddressTitle",
    199       l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_ADDRESS_CAPTION));
    200   localized_strings->SetString("fullNameLabel",
    201       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_FULL_NAME));
    202   localized_strings->SetString("companyNameLabel",
    203       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_COMPANY_NAME));
    204   localized_strings->SetString("addrLine1Label",
    205       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADDRESS_LINE_1));
    206   localized_strings->SetString("addrLine2Label",
    207       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADDRESS_LINE_2));
    208   localized_strings->SetString("cityLabel",
    209       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_CITY));
    210   localized_strings->SetString("countryLabel",
    211       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_COUNTRY));
    212   localized_strings->SetString("phoneLabel",
    213       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PHONE));
    214   localized_strings->SetString("faxLabel",
    215       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_FAX));
    216   localized_strings->SetString("emailLabel",
    217       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_EMAIL));
    218   localized_strings->SetString("addNewNamePlaceholder",
    219       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_NEW_NAME));
    220   localized_strings->SetString("addNewPhonePlaceholder",
    221       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_NEW_PHONE));
    222   localized_strings->SetString("addNewFaxPlaceholder",
    223       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_NEW_FAX));
    224   localized_strings->SetString("addNewEmailPlaceholder",
    225       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_NEW_EMAIL));
    226 
    227   std::string app_locale = AutofillCountry::ApplicationLocale();
    228   std::string default_country_code =
    229       AutofillCountry::CountryCodeForLocale(app_locale);
    230   localized_strings->SetString("defaultCountryCode", default_country_code);
    231   localized_strings->Set("autofillCountryData", GetCountryData());
    232 }
    233 
    234 void AutofillOptionsHandler::SetCreditCardOverlayStrings(
    235     DictionaryValue* localized_strings) {
    236   localized_strings->SetString("autofillEditCreditCardTitle",
    237       l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION));
    238   localized_strings->SetString("nameOnCardLabel",
    239       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_NAME_ON_CARD));
    240   localized_strings->SetString("creditCardNumberLabel",
    241       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_CREDIT_CARD_NUMBER));
    242   localized_strings->SetString("creditCardExpirationDateLabel",
    243       l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_EXPIRATION_DATE));
    244 }
    245 
    246 void AutofillOptionsHandler::LoadAutofillData() {
    247   if (!personal_data_->IsDataLoaded())
    248     return;
    249 
    250   ListValue addresses;
    251   for (std::vector<AutofillProfile*>::const_iterator i =
    252            personal_data_->web_profiles().begin();
    253        i != personal_data_->web_profiles().end(); ++i) {
    254     ListValue* entry = new ListValue();
    255     entry->Append(new StringValue((*i)->guid()));
    256     entry->Append(new StringValue((*i)->Label()));
    257     addresses.Append(entry);
    258   }
    259 
    260   web_ui_->CallJavascriptFunction("AutofillOptions.setAddressList", addresses);
    261 
    262   ListValue credit_cards;
    263   for (std::vector<CreditCard*>::const_iterator i =
    264            personal_data_->credit_cards().begin();
    265        i != personal_data_->credit_cards().end(); ++i) {
    266     ListValue* entry = new ListValue();
    267     entry->Append(new StringValue((*i)->guid()));
    268     entry->Append(new StringValue((*i)->Label()));
    269     int res = CreditCardTypeToResourceID((*i)->type());
    270     entry->Append(
    271         new StringValue(web_ui_util::GetImageDataUrlFromResource(res)));
    272     entry->Append(new StringValue(LocalizedCreditCardType((*i)->type())));
    273     credit_cards.Append(entry);
    274   }
    275 
    276   web_ui_->CallJavascriptFunction("AutofillOptions.setCreditCardList",
    277                                   credit_cards);
    278 }
    279 
    280 void AutofillOptionsHandler::RemoveAddress(const ListValue* args) {
    281   DCHECK(personal_data_->IsDataLoaded());
    282 
    283   std::string guid;
    284   if (!args->GetString(0, &guid)) {
    285     NOTREACHED();
    286     return;
    287   }
    288 
    289   personal_data_->RemoveProfile(guid);
    290 }
    291 
    292 void AutofillOptionsHandler::RemoveCreditCard(const ListValue* args) {
    293   DCHECK(personal_data_->IsDataLoaded());
    294 
    295   std::string guid;
    296   if (!args->GetString(0, &guid)) {
    297     NOTREACHED();
    298     return;
    299   }
    300 
    301   personal_data_->RemoveCreditCard(guid);
    302 }
    303 
    304 void AutofillOptionsHandler::LoadAddressEditor(const ListValue* args) {
    305   DCHECK(personal_data_->IsDataLoaded());
    306 
    307   std::string guid;
    308   if (!args->GetString(0, &guid)) {
    309     NOTREACHED();
    310     return;
    311   }
    312 
    313   AutofillProfile* profile = personal_data_->GetProfileByGUID(guid);
    314   if (!profile) {
    315     // There is a race where a user can click once on the close button and
    316     // quickly click again on the list item before the item is removed (since
    317     // the list is not updated until the model tells the list an item has been
    318     // removed). This will activate the editor for a profile that has been
    319     // removed. Do nothing in that case.
    320     return;
    321   }
    322 
    323   DictionaryValue address;
    324   address.SetString("guid", profile->guid());
    325   scoped_ptr<ListValue> list;
    326   GetValueList(*profile, NAME_FULL, &list);
    327   address.Set("fullName", list.release());
    328   address.SetString("companyName", profile->GetInfo(COMPANY_NAME));
    329   address.SetString("addrLine1", profile->GetInfo(ADDRESS_HOME_LINE1));
    330   address.SetString("addrLine2", profile->GetInfo(ADDRESS_HOME_LINE2));
    331   address.SetString("city", profile->GetInfo(ADDRESS_HOME_CITY));
    332   address.SetString("state", profile->GetInfo(ADDRESS_HOME_STATE));
    333   address.SetString("postalCode", profile->GetInfo(ADDRESS_HOME_ZIP));
    334   address.SetString("country", profile->CountryCode());
    335   GetValueList(*profile, PHONE_HOME_WHOLE_NUMBER, &list);
    336   address.Set("phone", list.release());
    337   GetValueList(*profile, PHONE_FAX_WHOLE_NUMBER, &list);
    338   address.Set("fax", list.release());
    339   GetValueList(*profile, EMAIL_ADDRESS, &list);
    340   address.Set("email", list.release());
    341 
    342   web_ui_->CallJavascriptFunction("AutofillOptions.editAddress", address);
    343 }
    344 
    345 void AutofillOptionsHandler::LoadCreditCardEditor(const ListValue* args) {
    346   DCHECK(personal_data_->IsDataLoaded());
    347 
    348   std::string guid;
    349   if (!args->GetString(0, &guid)) {
    350     NOTREACHED();
    351     return;
    352   }
    353 
    354   CreditCard* credit_card = personal_data_->GetCreditCardByGUID(guid);
    355   if (!credit_card) {
    356     // There is a race where a user can click once on the close button and
    357     // quickly click again on the list item before the item is removed (since
    358     // the list is not updated until the model tells the list an item has been
    359     // removed). This will activate the editor for a profile that has been
    360     // removed. Do nothing in that case.
    361     return;
    362   }
    363 
    364   DictionaryValue credit_card_data;
    365   credit_card_data.SetString("guid", credit_card->guid());
    366   credit_card_data.SetString("nameOnCard",
    367                              credit_card->GetInfo(CREDIT_CARD_NAME));
    368   credit_card_data.SetString("creditCardNumber",
    369                              credit_card->GetInfo(CREDIT_CARD_NUMBER));
    370   credit_card_data.SetString("expirationMonth",
    371                              credit_card->GetInfo(CREDIT_CARD_EXP_MONTH));
    372   credit_card_data.SetString(
    373       "expirationYear",
    374       credit_card->GetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
    375 
    376   web_ui_->CallJavascriptFunction("AutofillOptions.editCreditCard",
    377                                   credit_card_data);
    378 }
    379 
    380 void AutofillOptionsHandler::SetAddress(const ListValue* args) {
    381   if (!personal_data_->IsDataLoaded())
    382     return;
    383 
    384   std::string guid;
    385   if (!args->GetString(0, &guid)) {
    386     NOTREACHED();
    387     return;
    388   }
    389 
    390   AutofillProfile profile(guid);
    391 
    392   std::string country_code;
    393   string16 value;
    394   ListValue* list_value;
    395   if (args->GetList(1, &list_value))
    396     SetValueList(list_value, NAME_FULL, &profile);
    397   if (args->GetString(2, &value))
    398     profile.SetInfo(COMPANY_NAME, value);
    399   if (args->GetString(3, &value))
    400     profile.SetInfo(ADDRESS_HOME_LINE1, value);
    401   if (args->GetString(4, &value))
    402     profile.SetInfo(ADDRESS_HOME_LINE2, value);
    403   if (args->GetString(5, &value))
    404     profile.SetInfo(ADDRESS_HOME_CITY, value);
    405   if (args->GetString(6, &value))
    406     profile.SetInfo(ADDRESS_HOME_STATE, value);
    407   if (args->GetString(7, &value))
    408     profile.SetInfo(ADDRESS_HOME_ZIP, value);
    409   if (args->GetString(8, &country_code))
    410     profile.SetCountryCode(country_code);
    411   if (args->GetList(9, &list_value))
    412     SetValueList(list_value, PHONE_HOME_WHOLE_NUMBER, &profile);
    413   if (args->GetList(10, &list_value))
    414     SetValueList(list_value, PHONE_FAX_WHOLE_NUMBER, &profile);
    415   if (args->GetList(11, &list_value))
    416     SetValueList(list_value, EMAIL_ADDRESS, &profile);
    417 
    418   if (!guid::IsValidGUID(profile.guid())) {
    419     profile.set_guid(guid::GenerateGUID());
    420     personal_data_->AddProfile(profile);
    421   } else {
    422     personal_data_->UpdateProfile(profile);
    423   }
    424 }
    425 
    426 void AutofillOptionsHandler::SetCreditCard(const ListValue* args) {
    427   if (!personal_data_->IsDataLoaded())
    428     return;
    429 
    430   std::string guid;
    431   if (!args->GetString(0, &guid)) {
    432     NOTREACHED();
    433     return;
    434   }
    435 
    436   CreditCard credit_card(guid);
    437 
    438   string16 value;
    439   if (args->GetString(1, &value))
    440     credit_card.SetInfo(CREDIT_CARD_NAME, value);
    441   if (args->GetString(2, &value))
    442     credit_card.SetInfo(CREDIT_CARD_NUMBER, value);
    443   if (args->GetString(3, &value))
    444     credit_card.SetInfo(CREDIT_CARD_EXP_MONTH, value);
    445   if (args->GetString(4, &value))
    446     credit_card.SetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, value);
    447 
    448   if (!guid::IsValidGUID(credit_card.guid())) {
    449     credit_card.set_guid(guid::GenerateGUID());
    450     personal_data_->AddCreditCard(credit_card);
    451   } else {
    452     personal_data_->UpdateCreditCard(credit_card);
    453   }
    454 }
    455