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