Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / options / autofill_options_handler.cc
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
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;
44
45 namespace {
46
47 const char kSettingsOrigin[] = "Chrome settings";
48
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";
58
59 static const char kComponents[] = "components";
60 static 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.
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);
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               &not_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             &not_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>.
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());
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.
190 void 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.
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);
220   }
221 }
222
223 // Pulls the phone number |index|, |phone_number_list|, and |country_code| from
224 // the |args| input.
225 void 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.
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;
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
281 scoped_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
295 namespace options {
296
297 AutofillOptionsHandler::AutofillOptionsHandler()
298     : personal_data_(NULL) {}
299
300 AutofillOptionsHandler::~AutofillOptionsHandler() {
301   if (personal_data_)
302     personal_data_->RemoveObserver(this);
303 }
304
305 /////////////////////////////////////////////////////////////////////////////
306 // OptionsPageUIHandler implementation:
307 void 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
336 void AutofillOptionsHandler::InitializeHandler() {
337   // personal_data_ is NULL in guest mode on Chrome OS.
338   if (personal_data_)
339     personal_data_->AddObserver(this);
340 }
341
342 void AutofillOptionsHandler::InitializePage() {
343   if (personal_data_)
344     LoadAutofillData();
345 }
346
347 void 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:
388 void AutofillOptionsHandler::OnPersonalDataChanged() {
389   LoadAutofillData();
390 }
391
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);
407 }
408
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));
419 }
420
421 void 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)
465 void AutofillOptionsHandler::AccessAddressBook(const base::ListValue* args) {
466   personal_data_->AccessAddressBook();
467 }
468 #endif  // defined(OS_MACOSX) && !defined(OS_IOS)
469
470 void 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
482 void 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
507 void 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
527 void 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
565 void 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
635 void 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
668 void 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
678 bool AutofillOptionsHandler::IsPersonalDataLoaded() const {
679   return personal_data_ && personal_data_->IsDataLoaded();
680 }
681
682 // static
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));
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