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.
5 #include "chrome/browser/ui/webui/options/autofill_options_handler.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"
37 using autofill::AutofillCountry;
38 using autofill::AutofillType;
39 using autofill::ServerFieldType;
40 using autofill::AutofillProfile;
41 using autofill::CreditCard;
42 using autofill::PersonalDataManager;
43 using i18n::addressinput::AddressUiComponent;
47 const char kSettingsOrigin[] = "Chrome settings";
49 static const char kFullNameField[] = "fullName";
50 static const char kCompanyNameField[] = "companyName";
51 static const char kAddressLineField[] = "addrLines";
52 static const char kDependentLocalityField[] = "dependentLocality";
53 static const char kCityField[] = "city";
54 static const char kStateField[] = "state";
55 static const char kPostalCodeField[] = "postalCode";
56 static const char kSortingCodeField[] = "sortingCode";
57 static const char kCountryField[] = "country";
59 static const char kComponents[] = "components";
60 static const char kLanguageCode[] = "languageCode";
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
67 void 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);
73 i18n::addressinput::Localization localization;
74 localization.SetGetter(l10n_util::GetStringUTF8);
76 std::vector<AddressUiComponent> components =
77 i18n::addressinput::BuildComponents(
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(
89 components_language_code == NULL ?
90 ¬_used : components_language_code);
92 DCHECK(!components.empty());
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) {
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);
105 scoped_ptr<base::DictionaryValue> component(new base::DictionaryValue);
106 component->SetString("name", components[i].name);
108 switch (components[i].field) {
109 case i18n::addressinput::COUNTRY:
110 component->SetString(kField, kCountryField);
112 case i18n::addressinput::ADMIN_AREA:
113 component->SetString(kField, kStateField);
115 case i18n::addressinput::LOCALITY:
116 component->SetString(kField, kCityField);
118 case i18n::addressinput::DEPENDENT_LOCALITY:
119 component->SetString(kField, kDependentLocalityField);
121 case i18n::addressinput::SORTING_CODE:
122 component->SetString(kField, kSortingCodeField);
124 case i18n::addressinput::POSTAL_CODE:
125 component->SetString(kField, kPostalCodeField);
127 case i18n::addressinput::STREET_ADDRESS:
128 component->SetString(kField, kAddressLineField);
130 case i18n::addressinput::ORGANIZATION:
131 component->SetString(kField, kCompanyNameField);
133 case i18n::addressinput::RECIPIENT:
134 component->SetString(kField, kFullNameField);
135 component->SetString(
137 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_NAME));
141 switch (components[i].length_hint) {
142 case AddressUiComponent::HINT_LONG:
143 component->SetString(kLength, "long");
145 case AddressUiComponent::HINT_SHORT:
146 component->SetString(kLength, "short");
150 line->Append(component.release());
154 // Sets data related to the country <select>.
155 void 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());
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(
171 countries[i] ? countries[i]->country_code() : "separator");
172 country_list->Append(option_details.release());
174 localized_strings->Set("autofillCountrySelectList", country_list.release());
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);
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.
190 void GetValueList(const AutofillProfile& profile,
191 ServerFieldType type,
192 scoped_ptr<base::ListValue>* list) {
193 list->reset(new base::ListValue);
195 std::vector<base::string16> values;
196 if (AutofillType(type).group() == autofill::NAME) {
197 profile.GetMultiInfo(
198 AutofillType(type), g_browser_process->GetApplicationLocale(), &values);
200 profile.GetRawMultiInfo(type, &values);
203 // |Get[Raw]MultiInfo()| always returns at least one, potentially empty, item.
204 if (values.size() == 1 && values.front().empty())
207 for (size_t i = 0; i < values.size(); ++i) {
208 (*list)->Set(i, new base::StringValue(values[i]));
212 // Converts a ListValue of StringValues to a vector of string16s.
213 void 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);
223 // Pulls the phone number |index|, |phone_number_list|, and |country_code| from
225 void ExtractPhoneNumberInformation(const base::ListValue* args,
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
232 if (!args->GetDouble(0, &number)) {
238 if (!args->GetList(1, phone_number_list)) {
243 if (!args->GetString(2, country_code)) {
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.
253 void 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;
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) {
268 base::string16 existing_value;
269 if (!list->GetString(i, &existing_value)) {
270 NOTREACHED() << "List should have a value at index " << i;
273 is_duplicate = autofill::i18n::PhoneNumbersMatch(
274 new_value, existing_value, country_code, app_locale);
278 list->Remove(index, NULL);
281 scoped_ptr<base::ListValue> ValidatePhoneArguments(
282 const base::ListValue* args) {
284 std::string country_code;
285 const base::ListValue* extracted_list = NULL;
286 ExtractPhoneNumberInformation(args, &index, &extracted_list, &country_code);
288 scoped_ptr<base::ListValue> list(extracted_list->DeepCopy());
289 RemoveDuplicatePhoneNumberAtIndex(index, country_code, list.get());
297 AutofillOptionsHandler::AutofillOptionsHandler()
298 : personal_data_(NULL) {}
300 AutofillOptionsHandler::~AutofillOptionsHandler() {
302 personal_data_->RemoveObserver(this);
305 /////////////////////////////////////////////////////////////////////////////
306 // OptionsPageUIHandler implementation:
307 void AutofillOptionsHandler::GetLocalizedValues(
308 base::DictionaryValue* localized_strings) {
309 DCHECK(localized_strings);
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)
327 RegisterStrings(localized_strings, resources, arraysize(resources));
328 RegisterTitle(localized_strings, "autofillOptionsPage",
329 IDS_AUTOFILL_OPTIONS_TITLE);
331 localized_strings->SetString("helpUrl", autofill::kHelpURL);
332 SetAddressOverlayStrings(localized_strings);
333 SetCreditCardOverlayStrings(localized_strings);
336 void AutofillOptionsHandler::InitializeHandler() {
337 // personal_data_ is NULL in guest mode on Chrome OS.
339 personal_data_->AddObserver(this);
342 void AutofillOptionsHandler::InitializePage() {
347 void AutofillOptionsHandler::RegisterMessages() {
348 personal_data_ = autofill::PersonalDataManagerFactory::GetForProfile(
349 Profile::FromWebUI(web_ui()));
351 #if defined(OS_MACOSX) && !defined(OS_IOS)
352 web_ui()->RegisterMessageCallback(
354 base::Bind(&AutofillOptionsHandler::AccessAddressBook,
355 base::Unretained(this)));
356 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
357 web_ui()->RegisterMessageCallback(
359 base::Bind(&AutofillOptionsHandler::RemoveData,
360 base::Unretained(this)));
361 web_ui()->RegisterMessageCallback(
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(
375 base::Bind(&AutofillOptionsHandler::SetAddress, base::Unretained(this)));
376 web_ui()->RegisterMessageCallback(
378 base::Bind(&AutofillOptionsHandler::SetCreditCard,
379 base::Unretained(this)));
380 web_ui()->RegisterMessageCallback(
381 "validatePhoneNumbers",
382 base::Bind(&AutofillOptionsHandler::ValidatePhoneNumbers,
383 base::Unretained(this)));
386 /////////////////////////////////////////////////////////////////////////////
387 // PersonalDataManagerObserver implementation:
388 void AutofillOptionsHandler::OnPersonalDataChanged() {
392 void 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);
409 void 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));
421 void AutofillOptionsHandler::LoadAutofillData() {
422 if (!IsPersonalDataLoaded())
425 const std::vector<AutofillProfile*>& profiles =
426 personal_data_->web_profiles();
427 std::vector<base::string16> labels;
428 AutofillProfile::CreateDifferentiatingLabels(
430 g_browser_process->GetApplicationLocale(),
432 DCHECK_EQ(labels.size(), profiles.size());
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);
442 web_ui()->CallJavascriptFunction("AutofillOptions.setAddressList", addresses);
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);
460 web_ui()->CallJavascriptFunction("AutofillOptions.setCreditCardList",
464 #if defined(OS_MACOSX) && !defined(OS_IOS)
465 void AutofillOptionsHandler::AccessAddressBook(const base::ListValue* args) {
466 personal_data_->AccessAddressBook();
468 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
470 void AutofillOptionsHandler::RemoveData(const base::ListValue* args) {
471 DCHECK(IsPersonalDataLoaded());
474 if (!args->GetString(0, &guid)) {
479 personal_data_->RemoveByGUID(guid);
482 void AutofillOptionsHandler::LoadAddressEditor(const base::ListValue* args) {
483 DCHECK(IsPersonalDataLoaded());
486 if (!args->GetString(0, &guid)) {
491 AutofillProfile* profile = personal_data_->GetProfileByGUID(guid);
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.
501 base::DictionaryValue address;
502 AutofillProfileToDictionary(*profile, &address);
504 web_ui()->CallJavascriptFunction("AutofillOptions.editAddress", address);
507 void AutofillOptionsHandler::LoadAddressEditorComponents(
508 const base::ListValue* args) {
509 std::string country_code;
510 if (!args->GetString(0, &country_code)) {
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);
523 web_ui()->CallJavascriptFunction(
524 "AutofillEditAddressOverlay.loadAddressComponents", input);
527 void AutofillOptionsHandler::LoadCreditCardEditor(const base::ListValue* args) {
528 DCHECK(IsPersonalDataLoaded());
531 if (!args->GetString(0, &guid)) {
536 CreditCard* credit_card = personal_data_->GetCreditCardByGUID(guid);
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.
546 base::DictionaryValue credit_card_data;
547 credit_card_data.SetString("guid", credit_card->guid());
548 credit_card_data.SetString(
550 credit_card->GetRawInfo(autofill::CREDIT_CARD_NAME));
551 credit_card_data.SetString(
553 credit_card->GetRawInfo(autofill::CREDIT_CARD_NUMBER));
554 credit_card_data.SetString(
556 credit_card->GetRawInfo(autofill::CREDIT_CARD_EXP_MONTH));
557 credit_card_data.SetString(
559 credit_card->GetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR));
561 web_ui()->CallJavascriptFunction("AutofillOptions.editCreditCard",
565 void AutofillOptionsHandler::SetAddress(const base::ListValue* args) {
566 if (!IsPersonalDataLoaded())
571 if (!args->GetString(arg_counter++, &guid)) {
576 AutofillProfile profile(guid, kSettingsOrigin);
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),
585 g_browser_process->GetApplicationLocale());
588 if (args->GetString(arg_counter++, &value))
589 profile.SetRawInfo(autofill::COMPANY_NAME, value);
591 if (args->GetString(arg_counter++, &value))
592 profile.SetRawInfo(autofill::ADDRESS_HOME_STREET_ADDRESS, value);
594 if (args->GetString(arg_counter++, &value))
595 profile.SetRawInfo(autofill::ADDRESS_HOME_DEPENDENT_LOCALITY, value);
597 if (args->GetString(arg_counter++, &value))
598 profile.SetRawInfo(autofill::ADDRESS_HOME_CITY, value);
600 if (args->GetString(arg_counter++, &value))
601 profile.SetRawInfo(autofill::ADDRESS_HOME_STATE, value);
603 if (args->GetString(arg_counter++, &value))
604 profile.SetRawInfo(autofill::ADDRESS_HOME_ZIP, value);
606 if (args->GetString(arg_counter++, &value))
607 profile.SetRawInfo(autofill::ADDRESS_HOME_SORTING_CODE, value);
609 if (args->GetString(arg_counter++, &value))
610 profile.SetRawInfo(autofill::ADDRESS_HOME_COUNTRY, value);
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);
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);
624 if (args->GetString(arg_counter++, &value))
625 profile.set_language_code(base::UTF16ToUTF8(value));
627 if (!base::IsValidGUID(profile.guid())) {
628 profile.set_guid(base::GenerateGUID());
629 personal_data_->AddProfile(profile);
631 personal_data_->UpdateProfile(profile);
635 void AutofillOptionsHandler::SetCreditCard(const base::ListValue* args) {
636 if (!IsPersonalDataLoaded())
640 if (!args->GetString(0, &guid)) {
645 CreditCard credit_card(guid, kSettingsOrigin);
647 base::string16 value;
648 if (args->GetString(1, &value))
649 credit_card.SetRawInfo(autofill::CREDIT_CARD_NAME, value);
651 if (args->GetString(2, &value))
652 credit_card.SetRawInfo(autofill::CREDIT_CARD_NUMBER, value);
654 if (args->GetString(3, &value))
655 credit_card.SetRawInfo(autofill::CREDIT_CARD_EXP_MONTH, value);
657 if (args->GetString(4, &value))
658 credit_card.SetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR, value);
660 if (!base::IsValidGUID(credit_card.guid())) {
661 credit_card.set_guid(base::GenerateGUID());
662 personal_data_->AddCreditCard(credit_card);
664 personal_data_->UpdateCreditCard(credit_card);
668 void AutofillOptionsHandler::ValidatePhoneNumbers(const base::ListValue* args) {
669 if (!IsPersonalDataLoaded())
672 scoped_ptr<base::ListValue> list_value = ValidatePhoneArguments(args);
674 web_ui()->CallJavascriptFunction(
675 "AutofillEditAddressOverlay.setValidatedPhoneNumbers", *list_value);
678 bool AutofillOptionsHandler::IsPersonalDataLoaded() const {
679 return personal_data_ && personal_data_->IsDataLoaded();
683 void 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));
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());
713 scoped_ptr<base::ListValue> components(new base::ListValue);
714 GetAddressComponents(
715 base::UTF16ToUTF8(profile.GetRawInfo(autofill::ADDRESS_HOME_COUNTRY)),
716 profile.language_code(),
719 address->Set(kComponents, components.release());
722 } // namespace options