1// Copyright (c) 2012 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/bind.h" 10#include "base/bind_helpers.h" 11#include "base/guid.h" 12#include "base/logging.h" 13#include "base/strings/string16.h" 14#include "base/strings/string_number_conversions.h" 15#include "base/strings/utf_string_conversions.h" 16#include "base/values.h" 17#include "chrome/browser/autofill/personal_data_manager_factory.h" 18#include "chrome/browser/browser_process.h" 19#include "chrome/browser/profiles/profile.h" 20#include "chrome/browser/ui/autofill/country_combobox_model.h" 21#include "chrome/common/url_constants.h" 22#include "components/autofill/core/browser/autofill_country.h" 23#include "components/autofill/core/browser/autofill_profile.h" 24#include "components/autofill/core/browser/credit_card.h" 25#include "components/autofill/core/browser/personal_data_manager.h" 26#include "components/autofill/core/browser/phone_number_i18n.h" 27#include "components/autofill/core/common/autofill_constants.h" 28#include "content/public/browser/web_ui.h" 29#include "grit/components_strings.h" 30#include "grit/generated_resources.h" 31#include "grit/libaddressinput_strings.h" 32#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_ui.h" 33#include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_ui_component.h" 34#include "ui/base/l10n/l10n_util.h" 35#include "ui/base/webui/web_ui_util.h" 36 37using autofill::AutofillCountry; 38using autofill::ServerFieldType; 39using autofill::AutofillProfile; 40using autofill::CreditCard; 41using autofill::PersonalDataManager; 42using i18n::addressinput::AddressUiComponent; 43 44namespace { 45 46const char kSettingsOrigin[] = "Chrome settings"; 47 48static const char kFullNameField[] = "fullName"; 49static const char kCompanyNameField[] = "companyName"; 50static const char kAddressLineField[] = "addrLines"; 51static const char kDependentLocalityField[] = "dependentLocality"; 52static const char kCityField[] = "city"; 53static const char kStateField[] = "state"; 54static const char kPostalCodeField[] = "postalCode"; 55static const char kSortingCodeField[] = "sortingCode"; 56static const char kCountryField[] = "country"; 57 58static const char kComponents[] = "components"; 59static const char kLanguageCode[] = "languageCode"; 60 61// Fills |components| with the address UI components that should be used to 62// input an address for |country_code| when UI BCP 47 language code is 63// |ui_language_code|. If |components_language_code| is not NULL, then sets it 64// to the BCP 47 language code that should be used to format the address for 65// display. 66void GetAddressComponents(const std::string& country_code, 67 const std::string& ui_language_code, 68 base::ListValue* address_components, 69 std::string* components_language_code) { 70 DCHECK(address_components); 71 72 std::vector<AddressUiComponent> components = 73 i18n::addressinput::BuildComponents( 74 country_code, ui_language_code, components_language_code); 75 if (components.empty()) { 76 static const char kDefaultCountryCode[] = "US"; 77 components = i18n::addressinput::BuildComponents( 78 kDefaultCountryCode, ui_language_code, components_language_code); 79 } 80 DCHECK(!components.empty()); 81 82 base::ListValue* line = NULL; 83 static const char kField[] = "field"; 84 static const char kLength[] = "length"; 85 for (size_t i = 0; i < components.size(); ++i) { 86 if (i == 0 || 87 components[i - 1].length_hint == AddressUiComponent::HINT_LONG || 88 components[i].length_hint == AddressUiComponent::HINT_LONG) { 89 line = new base::ListValue; 90 address_components->Append(line); 91 } 92 93 scoped_ptr<base::DictionaryValue> component(new base::DictionaryValue); 94 component->SetString( 95 "name", l10n_util::GetStringUTF16(components[i].name_id)); 96 97 switch (components[i].field) { 98 case i18n::addressinput::COUNTRY: 99 component->SetString(kField, kCountryField); 100 break; 101 case i18n::addressinput::ADMIN_AREA: 102 component->SetString(kField, kStateField); 103 break; 104 case i18n::addressinput::LOCALITY: 105 component->SetString(kField, kCityField); 106 break; 107 case i18n::addressinput::DEPENDENT_LOCALITY: 108 component->SetString(kField, kDependentLocalityField); 109 break; 110 case i18n::addressinput::SORTING_CODE: 111 component->SetString(kField, kSortingCodeField); 112 break; 113 case i18n::addressinput::POSTAL_CODE: 114 component->SetString(kField, kPostalCodeField); 115 break; 116 case i18n::addressinput::STREET_ADDRESS: 117 component->SetString(kField, kAddressLineField); 118 break; 119 case i18n::addressinput::ORGANIZATION: 120 component->SetString(kField, kCompanyNameField); 121 break; 122 case i18n::addressinput::RECIPIENT: 123 component->SetString(kField, kFullNameField); 124 component->SetString( 125 "placeholder", 126 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_NAME)); 127 break; 128 } 129 130 switch (components[i].length_hint) { 131 case AddressUiComponent::HINT_LONG: 132 component->SetString(kLength, "long"); 133 break; 134 case AddressUiComponent::HINT_SHORT: 135 component->SetString(kLength, "short"); 136 break; 137 } 138 139 line->Append(component.release()); 140 } 141} 142 143// Sets data related to the country <select>. 144void SetCountryData(const PersonalDataManager& manager, 145 base::DictionaryValue* localized_strings) { 146 autofill::CountryComboboxModel model( 147 manager, base::Callback<bool(const std::string&)>()); 148 const std::vector<AutofillCountry*>& countries = model.countries(); 149 localized_strings->SetString("defaultCountryCode", 150 countries.front()->country_code()); 151 152 // An ordered list of options to show in the <select>. 153 scoped_ptr<base::ListValue> country_list(new base::ListValue()); 154 for (size_t i = 0; i < countries.size(); ++i) { 155 scoped_ptr<base::DictionaryValue> option_details( 156 new base::DictionaryValue()); 157 option_details->SetString("name", model.GetItemAt(i)); 158 option_details->SetString( 159 "value", 160 countries[i] ? countries[i]->country_code() : "separator"); 161 country_list->Append(option_details.release()); 162 } 163 localized_strings->Set("autofillCountrySelectList", country_list.release()); 164 165 scoped_ptr<base::ListValue> default_country_components(new base::ListValue); 166 std::string default_country_language_code; 167 GetAddressComponents(countries.front()->country_code(), 168 g_browser_process->GetApplicationLocale(), 169 default_country_components.get(), 170 &default_country_language_code); 171 localized_strings->Set("autofillDefaultCountryComponents", 172 default_country_components.release()); 173 localized_strings->SetString("autofillDefaultCountryLanguageCode", 174 default_country_language_code); 175} 176 177// Get the multi-valued element for |type| and return it in |ListValue| form. 178void GetValueList(const AutofillProfile& profile, 179 ServerFieldType type, 180 scoped_ptr<base::ListValue>* list) { 181 list->reset(new base::ListValue); 182 183 std::vector<base::string16> values; 184 profile.GetRawMultiInfo(type, &values); 185 186 // |GetRawMultiInfo()| always returns at least one, potentially empty, item. 187 if (values.size() == 1 && values.front().empty()) 188 return; 189 190 for (size_t i = 0; i < values.size(); ++i) { 191 (*list)->Set(i, new base::StringValue(values[i])); 192 } 193} 194 195// Set the multi-valued element for |type| from input |list| values. 196void SetValueList(const base::ListValue* list, 197 ServerFieldType type, 198 AutofillProfile* profile) { 199 std::vector<base::string16> values(list->GetSize()); 200 for (size_t i = 0; i < list->GetSize(); ++i) { 201 base::string16 value; 202 if (list->GetString(i, &value)) 203 values[i] = value; 204 } 205 profile->SetRawMultiInfo(type, values); 206} 207 208// Pulls the phone number |index|, |phone_number_list|, and |country_code| from 209// the |args| input. 210void ExtractPhoneNumberInformation(const base::ListValue* args, 211 size_t* index, 212 const base::ListValue** phone_number_list, 213 std::string* country_code) { 214 // Retrieve index as a |double|, as that is how it comes across from 215 // JavaScript. 216 double number = 0.0; 217 if (!args->GetDouble(0, &number)) { 218 NOTREACHED(); 219 return; 220 } 221 *index = number; 222 223 if (!args->GetList(1, phone_number_list)) { 224 NOTREACHED(); 225 return; 226 } 227 228 if (!args->GetString(2, country_code)) { 229 NOTREACHED(); 230 return; 231 } 232} 233 234// Searches the |list| for the value at |index|. If this value is present 235// in any of the rest of the list, then the item (at |index|) is removed. 236// The comparison of phone number values is done on normalized versions of the 237// phone number values. 238void RemoveDuplicatePhoneNumberAtIndex(size_t index, 239 const std::string& country_code, 240 base::ListValue* list) { 241 base::string16 new_value; 242 if (!list->GetString(index, &new_value)) { 243 NOTREACHED() << "List should have a value at index " << index; 244 return; 245 } 246 247 bool is_duplicate = false; 248 std::string app_locale = g_browser_process->GetApplicationLocale(); 249 for (size_t i = 0; i < list->GetSize() && !is_duplicate; ++i) { 250 if (i == index) 251 continue; 252 253 base::string16 existing_value; 254 if (!list->GetString(i, &existing_value)) { 255 NOTREACHED() << "List should have a value at index " << i; 256 continue; 257 } 258 is_duplicate = autofill::i18n::PhoneNumbersMatch( 259 new_value, existing_value, country_code, app_locale); 260 } 261 262 if (is_duplicate) 263 list->Remove(index, NULL); 264} 265 266scoped_ptr<base::ListValue> ValidatePhoneArguments( 267 const base::ListValue* args) { 268 size_t index = 0; 269 std::string country_code; 270 const base::ListValue* extracted_list = NULL; 271 ExtractPhoneNumberInformation(args, &index, &extracted_list, &country_code); 272 273 scoped_ptr<base::ListValue> list(extracted_list->DeepCopy()); 274 RemoveDuplicatePhoneNumberAtIndex(index, country_code, list.get()); 275 return list.Pass(); 276} 277 278} // namespace 279 280namespace options { 281 282AutofillOptionsHandler::AutofillOptionsHandler() 283 : personal_data_(NULL) {} 284 285AutofillOptionsHandler::~AutofillOptionsHandler() { 286 if (personal_data_) 287 personal_data_->RemoveObserver(this); 288} 289 290///////////////////////////////////////////////////////////////////////////// 291// OptionsPageUIHandler implementation: 292void AutofillOptionsHandler::GetLocalizedValues( 293 base::DictionaryValue* localized_strings) { 294 DCHECK(localized_strings); 295 296 static OptionsStringResource resources[] = { 297 { "autofillAddresses", IDS_AUTOFILL_ADDRESSES_GROUP_NAME }, 298 { "autofillCreditCards", IDS_AUTOFILL_CREDITCARDS_GROUP_NAME }, 299 { "autofillAddAddress", IDS_AUTOFILL_ADD_ADDRESS_BUTTON }, 300 { "autofillAddCreditCard", IDS_AUTOFILL_ADD_CREDITCARD_BUTTON }, 301 { "autofillEditProfileButton", IDS_AUTOFILL_EDIT_PROFILE_BUTTON }, 302 { "helpButton", IDS_AUTOFILL_HELP_LABEL }, 303 { "addAddressTitle", IDS_AUTOFILL_ADD_ADDRESS_CAPTION }, 304 { "editAddressTitle", IDS_AUTOFILL_EDIT_ADDRESS_CAPTION }, 305 { "addCreditCardTitle", IDS_AUTOFILL_ADD_CREDITCARD_CAPTION }, 306 { "editCreditCardTitle", IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION }, 307#if defined(OS_MACOSX) 308 { "auxiliaryProfilesEnabled", IDS_AUTOFILL_USE_MAC_ADDRESS_BOOK }, 309#endif // defined(OS_MACOSX) 310 }; 311 312 RegisterStrings(localized_strings, resources, arraysize(resources)); 313 RegisterTitle(localized_strings, "autofillOptionsPage", 314 IDS_AUTOFILL_OPTIONS_TITLE); 315 316 localized_strings->SetString("helpUrl", autofill::kHelpURL); 317 SetAddressOverlayStrings(localized_strings); 318 SetCreditCardOverlayStrings(localized_strings); 319} 320 321void AutofillOptionsHandler::InitializeHandler() { 322 // personal_data_ is NULL in guest mode on Chrome OS. 323 if (personal_data_) 324 personal_data_->AddObserver(this); 325} 326 327void AutofillOptionsHandler::InitializePage() { 328 if (personal_data_) 329 LoadAutofillData(); 330} 331 332void AutofillOptionsHandler::RegisterMessages() { 333 personal_data_ = autofill::PersonalDataManagerFactory::GetForProfile( 334 Profile::FromWebUI(web_ui())); 335 336#if defined(OS_MACOSX) && !defined(OS_IOS) 337 web_ui()->RegisterMessageCallback( 338 "accessAddressBook", 339 base::Bind(&AutofillOptionsHandler::AccessAddressBook, 340 base::Unretained(this))); 341#endif // defined(OS_MACOSX) && !defined(OS_IOS) 342 web_ui()->RegisterMessageCallback( 343 "removeData", 344 base::Bind(&AutofillOptionsHandler::RemoveData, 345 base::Unretained(this))); 346 web_ui()->RegisterMessageCallback( 347 "loadAddressEditor", 348 base::Bind(&AutofillOptionsHandler::LoadAddressEditor, 349 base::Unretained(this))); 350 web_ui()->RegisterMessageCallback( 351 "loadAddressEditorComponents", 352 base::Bind(&AutofillOptionsHandler::LoadAddressEditorComponents, 353 base::Unretained(this))); 354 web_ui()->RegisterMessageCallback( 355 "loadCreditCardEditor", 356 base::Bind(&AutofillOptionsHandler::LoadCreditCardEditor, 357 base::Unretained(this))); 358 web_ui()->RegisterMessageCallback( 359 "setAddress", 360 base::Bind(&AutofillOptionsHandler::SetAddress, base::Unretained(this))); 361 web_ui()->RegisterMessageCallback( 362 "setCreditCard", 363 base::Bind(&AutofillOptionsHandler::SetCreditCard, 364 base::Unretained(this))); 365 web_ui()->RegisterMessageCallback( 366 "validatePhoneNumbers", 367 base::Bind(&AutofillOptionsHandler::ValidatePhoneNumbers, 368 base::Unretained(this))); 369} 370 371///////////////////////////////////////////////////////////////////////////// 372// PersonalDataManagerObserver implementation: 373void AutofillOptionsHandler::OnPersonalDataChanged() { 374 LoadAutofillData(); 375} 376 377void AutofillOptionsHandler::SetAddressOverlayStrings( 378 base::DictionaryValue* localized_strings) { 379 localized_strings->SetString("autofillEditAddressTitle", 380 l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_ADDRESS_CAPTION)); 381 localized_strings->SetString("autofillCountryLabel", 382 l10n_util::GetStringUTF16(IDS_LIBADDRESSINPUT_I18N_COUNTRY_LABEL)); 383 localized_strings->SetString("autofillPhoneLabel", 384 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_PHONE)); 385 localized_strings->SetString("autofillEmailLabel", 386 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_EMAIL)); 387 localized_strings->SetString("autofillAddPhonePlaceholder", 388 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_PHONE)); 389 localized_strings->SetString("autofillAddEmailPlaceholder", 390 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_EMAIL)); 391 SetCountryData(*personal_data_, localized_strings); 392} 393 394void AutofillOptionsHandler::SetCreditCardOverlayStrings( 395 base::DictionaryValue* localized_strings) { 396 localized_strings->SetString("autofillEditCreditCardTitle", 397 l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION)); 398 localized_strings->SetString("nameOnCardLabel", 399 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_NAME_ON_CARD)); 400 localized_strings->SetString("creditCardNumberLabel", 401 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_CREDIT_CARD_NUMBER)); 402 localized_strings->SetString("creditCardExpirationDateLabel", 403 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_EXPIRATION_DATE)); 404} 405 406void AutofillOptionsHandler::LoadAutofillData() { 407 if (!IsPersonalDataLoaded()) 408 return; 409 410 const std::vector<AutofillProfile*>& profiles = 411 personal_data_->web_profiles(); 412 std::vector<base::string16> labels; 413 AutofillProfile::CreateDifferentiatingLabels(profiles, &labels); 414 DCHECK_EQ(labels.size(), profiles.size()); 415 416 base::ListValue addresses; 417 for (size_t i = 0; i < profiles.size(); ++i) { 418 base::ListValue* entry = new base::ListValue(); 419 entry->Append(new base::StringValue(profiles[i]->guid())); 420 entry->Append(new base::StringValue(labels[i])); 421 addresses.Append(entry); 422 } 423 424 web_ui()->CallJavascriptFunction("AutofillOptions.setAddressList", addresses); 425 426 base::ListValue credit_cards; 427 const std::vector<CreditCard*>& cards = personal_data_->GetCreditCards(); 428 for (std::vector<CreditCard*>::const_iterator iter = cards.begin(); 429 iter != cards.end(); ++iter) { 430 const CreditCard* card = *iter; 431 // TODO(estade): this should be a dictionary. 432 base::ListValue* entry = new base::ListValue(); 433 entry->Append(new base::StringValue(card->guid())); 434 entry->Append(new base::StringValue(card->Label())); 435 entry->Append(new base::StringValue( 436 webui::GetBitmapDataUrlFromResource( 437 CreditCard::IconResourceId(card->type())))); 438 entry->Append(new base::StringValue(card->TypeForDisplay())); 439 credit_cards.Append(entry); 440 } 441 442 web_ui()->CallJavascriptFunction("AutofillOptions.setCreditCardList", 443 credit_cards); 444} 445 446#if defined(OS_MACOSX) && !defined(OS_IOS) 447void AutofillOptionsHandler::AccessAddressBook(const base::ListValue* args) { 448 personal_data_->AccessAddressBook(); 449} 450#endif // defined(OS_MACOSX) && !defined(OS_IOS) 451 452void AutofillOptionsHandler::RemoveData(const base::ListValue* args) { 453 DCHECK(IsPersonalDataLoaded()); 454 455 std::string guid; 456 if (!args->GetString(0, &guid)) { 457 NOTREACHED(); 458 return; 459 } 460 461 personal_data_->RemoveByGUID(guid); 462} 463 464void AutofillOptionsHandler::LoadAddressEditor(const base::ListValue* args) { 465 DCHECK(IsPersonalDataLoaded()); 466 467 std::string guid; 468 if (!args->GetString(0, &guid)) { 469 NOTREACHED(); 470 return; 471 } 472 473 AutofillProfile* profile = personal_data_->GetProfileByGUID(guid); 474 if (!profile) { 475 // There is a race where a user can click once on the close button and 476 // quickly click again on the list item before the item is removed (since 477 // the list is not updated until the model tells the list an item has been 478 // removed). This will activate the editor for a profile that has been 479 // removed. Do nothing in that case. 480 return; 481 } 482 483 base::DictionaryValue address; 484 address.SetString("guid", profile->guid()); 485 scoped_ptr<base::ListValue> list; 486 GetValueList(*profile, autofill::NAME_FULL, &list); 487 address.Set(kFullNameField, list.release()); 488 address.SetString( 489 kCompanyNameField, profile->GetRawInfo(autofill::COMPANY_NAME)); 490 address.SetString(kAddressLineField, 491 profile->GetRawInfo(autofill::ADDRESS_HOME_STREET_ADDRESS)); 492 address.SetString( 493 kCityField, profile->GetRawInfo(autofill::ADDRESS_HOME_CITY)); 494 address.SetString( 495 kStateField, profile->GetRawInfo(autofill::ADDRESS_HOME_STATE)); 496 address.SetString( 497 kDependentLocalityField, 498 profile->GetRawInfo(autofill::ADDRESS_HOME_DEPENDENT_LOCALITY)); 499 address.SetString(kSortingCodeField, 500 profile->GetRawInfo(autofill::ADDRESS_HOME_SORTING_CODE)); 501 address.SetString(kPostalCodeField, 502 profile->GetRawInfo(autofill::ADDRESS_HOME_ZIP)); 503 address.SetString(kCountryField, 504 profile->GetRawInfo(autofill::ADDRESS_HOME_COUNTRY)); 505 GetValueList(*profile, autofill::PHONE_HOME_WHOLE_NUMBER, &list); 506 address.Set("phone", list.release()); 507 GetValueList(*profile, autofill::EMAIL_ADDRESS, &list); 508 address.Set("email", list.release()); 509 address.SetString(kLanguageCode, profile->language_code()); 510 511 scoped_ptr<base::ListValue> components(new base::ListValue); 512 GetAddressComponents( 513 base::UTF16ToUTF8(profile->GetRawInfo(autofill::ADDRESS_HOME_COUNTRY)), 514 profile->language_code(), components.get(), NULL); 515 address.Set(kComponents, components.release()); 516 517 web_ui()->CallJavascriptFunction("AutofillOptions.editAddress", address); 518} 519 520void AutofillOptionsHandler::LoadAddressEditorComponents( 521 const base::ListValue* args) { 522 std::string country_code; 523 if (!args->GetString(0, &country_code)) { 524 NOTREACHED(); 525 return; 526 } 527 528 base::DictionaryValue input; 529 scoped_ptr<base::ListValue> components(new base::ListValue); 530 std::string language_code; 531 GetAddressComponents(country_code, g_browser_process->GetApplicationLocale(), 532 components.get(), &language_code); 533 input.Set(kComponents, components.release()); 534 input.SetString(kLanguageCode, language_code); 535 536 web_ui()->CallJavascriptFunction( 537 "AutofillEditAddressOverlay.loadAddressComponents", input); 538} 539 540void AutofillOptionsHandler::LoadCreditCardEditor(const base::ListValue* args) { 541 DCHECK(IsPersonalDataLoaded()); 542 543 std::string guid; 544 if (!args->GetString(0, &guid)) { 545 NOTREACHED(); 546 return; 547 } 548 549 CreditCard* credit_card = personal_data_->GetCreditCardByGUID(guid); 550 if (!credit_card) { 551 // There is a race where a user can click once on the close button and 552 // quickly click again on the list item before the item is removed (since 553 // the list is not updated until the model tells the list an item has been 554 // removed). This will activate the editor for a profile that has been 555 // removed. Do nothing in that case. 556 return; 557 } 558 559 base::DictionaryValue credit_card_data; 560 credit_card_data.SetString("guid", credit_card->guid()); 561 credit_card_data.SetString( 562 "nameOnCard", 563 credit_card->GetRawInfo(autofill::CREDIT_CARD_NAME)); 564 credit_card_data.SetString( 565 "creditCardNumber", 566 credit_card->GetRawInfo(autofill::CREDIT_CARD_NUMBER)); 567 credit_card_data.SetString( 568 "expirationMonth", 569 credit_card->GetRawInfo(autofill::CREDIT_CARD_EXP_MONTH)); 570 credit_card_data.SetString( 571 "expirationYear", 572 credit_card->GetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR)); 573 574 web_ui()->CallJavascriptFunction("AutofillOptions.editCreditCard", 575 credit_card_data); 576} 577 578void AutofillOptionsHandler::SetAddress(const base::ListValue* args) { 579 if (!IsPersonalDataLoaded()) 580 return; 581 582 int arg_counter = 0; 583 std::string guid; 584 if (!args->GetString(arg_counter++, &guid)) { 585 NOTREACHED(); 586 return; 587 } 588 589 AutofillProfile profile(guid, kSettingsOrigin); 590 591 base::string16 value; 592 const base::ListValue* list_value; 593 if (args->GetList(arg_counter++, &list_value)) 594 SetValueList(list_value, autofill::NAME_FULL, &profile); 595 596 if (args->GetString(arg_counter++, &value)) 597 profile.SetRawInfo(autofill::COMPANY_NAME, value); 598 599 if (args->GetString(arg_counter++, &value)) 600 profile.SetRawInfo(autofill::ADDRESS_HOME_STREET_ADDRESS, value); 601 602 if (args->GetString(arg_counter++, &value)) 603 profile.SetRawInfo(autofill::ADDRESS_HOME_DEPENDENT_LOCALITY, value); 604 605 if (args->GetString(arg_counter++, &value)) 606 profile.SetRawInfo(autofill::ADDRESS_HOME_CITY, value); 607 608 if (args->GetString(arg_counter++, &value)) 609 profile.SetRawInfo(autofill::ADDRESS_HOME_STATE, value); 610 611 if (args->GetString(arg_counter++, &value)) 612 profile.SetRawInfo(autofill::ADDRESS_HOME_ZIP, value); 613 614 if (args->GetString(arg_counter++, &value)) 615 profile.SetRawInfo(autofill::ADDRESS_HOME_SORTING_CODE, value); 616 617 if (args->GetString(arg_counter++, &value)) 618 profile.SetRawInfo(autofill::ADDRESS_HOME_COUNTRY, value); 619 620 if (args->GetList(arg_counter++, &list_value)) 621 SetValueList(list_value, autofill::PHONE_HOME_WHOLE_NUMBER, &profile); 622 623 if (args->GetList(arg_counter++, &list_value)) 624 SetValueList(list_value, autofill::EMAIL_ADDRESS, &profile); 625 626 if (args->GetString(arg_counter++, &value)) 627 profile.set_language_code(base::UTF16ToUTF8(value)); 628 629 if (!base::IsValidGUID(profile.guid())) { 630 profile.set_guid(base::GenerateGUID()); 631 personal_data_->AddProfile(profile); 632 } else { 633 personal_data_->UpdateProfile(profile); 634 } 635} 636 637void AutofillOptionsHandler::SetCreditCard(const base::ListValue* args) { 638 if (!IsPersonalDataLoaded()) 639 return; 640 641 std::string guid; 642 if (!args->GetString(0, &guid)) { 643 NOTREACHED(); 644 return; 645 } 646 647 CreditCard credit_card(guid, kSettingsOrigin); 648 649 base::string16 value; 650 if (args->GetString(1, &value)) 651 credit_card.SetRawInfo(autofill::CREDIT_CARD_NAME, value); 652 653 if (args->GetString(2, &value)) 654 credit_card.SetRawInfo(autofill::CREDIT_CARD_NUMBER, value); 655 656 if (args->GetString(3, &value)) 657 credit_card.SetRawInfo(autofill::CREDIT_CARD_EXP_MONTH, value); 658 659 if (args->GetString(4, &value)) 660 credit_card.SetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR, value); 661 662 if (!base::IsValidGUID(credit_card.guid())) { 663 credit_card.set_guid(base::GenerateGUID()); 664 personal_data_->AddCreditCard(credit_card); 665 } else { 666 personal_data_->UpdateCreditCard(credit_card); 667 } 668} 669 670void AutofillOptionsHandler::ValidatePhoneNumbers(const base::ListValue* args) { 671 if (!IsPersonalDataLoaded()) 672 return; 673 674 scoped_ptr<base::ListValue> list_value = ValidatePhoneArguments(args); 675 676 web_ui()->CallJavascriptFunction( 677 "AutofillEditAddressOverlay.setValidatedPhoneNumbers", *list_value); 678} 679 680bool AutofillOptionsHandler::IsPersonalDataLoaded() const { 681 return personal_data_ && personal_data_->IsDataLoaded(); 682} 683 684} // namespace options 685