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