- add sources.
[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 "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/component_strings.h"
30 #include "grit/generated_resources.h"
31 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/base/webui/web_ui_util.h"
33
34 using autofill::AutofillCountry;
35 using autofill::ServerFieldType;
36 using autofill::AutofillProfile;
37 using autofill::CreditCard;
38 using autofill::PersonalDataManager;
39
40 namespace {
41
42 const char kSettingsOrigin[] = "Chrome settings";
43
44 // Sets data related to the country <select>.
45 void SetCountryData(const PersonalDataManager& manager,
46                     DictionaryValue* localized_strings) {
47   autofill::CountryComboboxModel model(manager);
48   const std::vector<AutofillCountry*>& countries = model.countries();
49   localized_strings->SetString("defaultCountryCode",
50                                countries.front()->country_code());
51
52   // An ordered list of options to show in the <select>.
53   scoped_ptr<ListValue> country_list(new ListValue());
54   // A dictionary of postal code and state info, keyed on country code.
55   scoped_ptr<DictionaryValue> country_data(new DictionaryValue());
56   for (size_t i = 0; i < countries.size(); ++i) {
57     scoped_ptr<DictionaryValue> option_details(new DictionaryValue());
58     option_details->SetString("name", model.GetItemAt(i));
59     option_details->SetString(
60         "value",
61         countries[i] ? countries[i]->country_code() : "separator");
62     country_list->Append(option_details.release());
63
64     if (!countries[i])
65       continue;
66
67     scoped_ptr<DictionaryValue> details(new DictionaryValue());
68     details->SetString("postalCodeLabel", countries[i]->postal_code_label());
69     details->SetString("stateLabel", countries[i]->state_label());
70     country_data->Set(countries[i]->country_code(), details.release());
71
72   }
73   localized_strings->Set("autofillCountrySelectList", country_list.release());
74   localized_strings->Set("autofillCountryData", country_data.release());
75 }
76
77 // Get the multi-valued element for |type| and return it in |ListValue| form.
78 void GetValueList(const AutofillProfile& profile,
79                   ServerFieldType type,
80                   scoped_ptr<ListValue>* list) {
81   list->reset(new ListValue);
82
83   std::vector<string16> values;
84   profile.GetRawMultiInfo(type, &values);
85
86   // |GetRawMultiInfo()| always returns at least one, potentially empty, item.
87   if (values.size() == 1 && values.front().empty())
88     return;
89
90   for (size_t i = 0; i < values.size(); ++i) {
91     (*list)->Set(i, new base::StringValue(values[i]));
92   }
93 }
94
95 // Set the multi-valued element for |type| from input |list| values.
96 void SetValueList(const ListValue* list,
97                   ServerFieldType type,
98                   AutofillProfile* profile) {
99   std::vector<string16> values(list->GetSize());
100   for (size_t i = 0; i < list->GetSize(); ++i) {
101     string16 value;
102     if (list->GetString(i, &value))
103       values[i] = value;
104   }
105   profile->SetRawMultiInfo(type, values);
106 }
107
108 // Get the multi-valued element for |type| and return it in |ListValue| form.
109 void GetNameList(const AutofillProfile& profile,
110                  scoped_ptr<ListValue>* names) {
111   names->reset(new ListValue);
112
113   std::vector<string16> first_names;
114   std::vector<string16> middle_names;
115   std::vector<string16> last_names;
116   profile.GetRawMultiInfo(autofill::NAME_FIRST, &first_names);
117   profile.GetRawMultiInfo(autofill::NAME_MIDDLE, &middle_names);
118   profile.GetRawMultiInfo(autofill::NAME_LAST, &last_names);
119   DCHECK_EQ(first_names.size(), middle_names.size());
120   DCHECK_EQ(first_names.size(), last_names.size());
121
122   // |GetRawMultiInfo()| always returns at least one, potentially empty, item.
123   if (first_names.size() == 1 && first_names.front().empty() &&
124       middle_names.front().empty() && last_names.front().empty()) {
125     return;
126   }
127
128   for (size_t i = 0; i < first_names.size(); ++i) {
129     ListValue* name = new ListValue;  // owned by |list|
130     name->Set(0, new base::StringValue(first_names[i]));
131     name->Set(1, new base::StringValue(middle_names[i]));
132     name->Set(2, new base::StringValue(last_names[i]));
133     (*names)->Set(i, name);
134   }
135 }
136
137 // Set the multi-valued element for |type| from input |list| values.
138 void SetNameList(const ListValue* names, AutofillProfile* profile) {
139   const size_t size = names->GetSize();
140   std::vector<string16> first_names(size);
141   std::vector<string16> middle_names(size);
142   std::vector<string16> last_names(size);
143
144   for (size_t i = 0; i < size; ++i) {
145     const ListValue* name;
146     bool success = names->GetList(i, &name);
147     DCHECK(success);
148
149     string16 first_name;
150     success = name->GetString(0, &first_name);
151     DCHECK(success);
152     first_names[i] = first_name;
153
154     string16 middle_name;
155     success = name->GetString(1, &middle_name);
156     DCHECK(success);
157     middle_names[i] = middle_name;
158
159     string16 last_name;
160     success = name->GetString(2, &last_name);
161     DCHECK(success);
162     last_names[i] = last_name;
163   }
164
165   profile->SetRawMultiInfo(autofill::NAME_FIRST, first_names);
166   profile->SetRawMultiInfo(autofill::NAME_MIDDLE, middle_names);
167   profile->SetRawMultiInfo(autofill::NAME_LAST, last_names);
168 }
169
170 // Pulls the phone number |index|, |phone_number_list|, and |country_code| from
171 // the |args| input.
172 void ExtractPhoneNumberInformation(const ListValue* args,
173                                    size_t* index,
174                                    const ListValue** phone_number_list,
175                                    std::string* country_code) {
176   // Retrieve index as a |double|, as that is how it comes across from
177   // JavaScript.
178   double number = 0.0;
179   if (!args->GetDouble(0, &number)) {
180     NOTREACHED();
181     return;
182   }
183   *index = number;
184
185   if (!args->GetList(1, phone_number_list)) {
186     NOTREACHED();
187     return;
188   }
189
190   if (!args->GetString(2, country_code)) {
191     NOTREACHED();
192     return;
193   }
194 }
195
196 // Searches the |list| for the value at |index|.  If this value is present
197 // in any of the rest of the list, then the item (at |index|) is removed.
198 // The comparison of phone number values is done on normalized versions of the
199 // phone number values.
200 void RemoveDuplicatePhoneNumberAtIndex(size_t index,
201                                        const std::string& country_code,
202                                        ListValue* list) {
203   string16 new_value;
204   if (!list->GetString(index, &new_value)) {
205     NOTREACHED() << "List should have a value at index " << index;
206     return;
207   }
208
209   bool is_duplicate = false;
210   std::string app_locale = g_browser_process->GetApplicationLocale();
211   for (size_t i = 0; i < list->GetSize() && !is_duplicate; ++i) {
212     if (i == index)
213       continue;
214
215     string16 existing_value;
216     if (!list->GetString(i, &existing_value)) {
217       NOTREACHED() << "List should have a value at index " << i;
218       continue;
219     }
220     is_duplicate = autofill::i18n::PhoneNumbersMatch(
221         new_value, existing_value, country_code, app_locale);
222   }
223
224   if (is_duplicate)
225     list->Remove(index, NULL);
226 }
227
228 scoped_ptr<ListValue> ValidatePhoneArguments(const ListValue* args) {
229   size_t index = 0;
230   std::string country_code;
231   const ListValue* extracted_list = NULL;
232   ExtractPhoneNumberInformation(args, &index, &extracted_list, &country_code);
233
234   scoped_ptr<ListValue> list(extracted_list->DeepCopy());
235   RemoveDuplicatePhoneNumberAtIndex(index, country_code, list.get());
236   return list.Pass();
237 }
238
239 }  // namespace
240
241 namespace options {
242
243 AutofillOptionsHandler::AutofillOptionsHandler()
244     : personal_data_(NULL) {}
245
246 AutofillOptionsHandler::~AutofillOptionsHandler() {
247   if (personal_data_)
248     personal_data_->RemoveObserver(this);
249 }
250
251 /////////////////////////////////////////////////////////////////////////////
252 // OptionsPageUIHandler implementation:
253 void AutofillOptionsHandler::GetLocalizedValues(
254     DictionaryValue* localized_strings) {
255   DCHECK(localized_strings);
256
257   static OptionsStringResource resources[] = {
258     { "autofillAddresses", IDS_AUTOFILL_ADDRESSES_GROUP_NAME },
259     { "autofillCreditCards", IDS_AUTOFILL_CREDITCARDS_GROUP_NAME },
260     { "autofillAddAddress", IDS_AUTOFILL_ADD_ADDRESS_BUTTON },
261     { "autofillAddCreditCard", IDS_AUTOFILL_ADD_CREDITCARD_BUTTON },
262     { "autofillEditProfileButton", IDS_AUTOFILL_EDIT_PROFILE_BUTTON },
263     { "helpButton", IDS_AUTOFILL_HELP_LABEL },
264     { "addAddressTitle", IDS_AUTOFILL_ADD_ADDRESS_CAPTION },
265     { "editAddressTitle", IDS_AUTOFILL_EDIT_ADDRESS_CAPTION },
266     { "addCreditCardTitle", IDS_AUTOFILL_ADD_CREDITCARD_CAPTION },
267     { "editCreditCardTitle", IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION },
268 #if defined(OS_MACOSX)
269     { "auxiliaryProfilesEnabled", IDS_AUTOFILL_USE_MAC_ADDRESS_BOOK },
270 #endif  // defined(OS_MACOSX)
271   };
272
273   RegisterStrings(localized_strings, resources, arraysize(resources));
274   RegisterTitle(localized_strings, "autofillOptionsPage",
275                 IDS_AUTOFILL_OPTIONS_TITLE);
276
277   localized_strings->SetString("helpUrl", autofill::kHelpURL);
278   SetAddressOverlayStrings(localized_strings);
279   SetCreditCardOverlayStrings(localized_strings);
280 }
281
282 void AutofillOptionsHandler::InitializeHandler() {
283   // personal_data_ is NULL in guest mode on Chrome OS.
284   if (personal_data_)
285     personal_data_->AddObserver(this);
286 }
287
288 void AutofillOptionsHandler::InitializePage() {
289   if (personal_data_)
290     LoadAutofillData();
291 }
292
293 void AutofillOptionsHandler::RegisterMessages() {
294   personal_data_ = autofill::PersonalDataManagerFactory::GetForProfile(
295       Profile::FromWebUI(web_ui()));
296
297   web_ui()->RegisterMessageCallback(
298       "removeData",
299       base::Bind(&AutofillOptionsHandler::RemoveData,
300                  base::Unretained(this)));
301   web_ui()->RegisterMessageCallback(
302       "loadAddressEditor",
303       base::Bind(&AutofillOptionsHandler::LoadAddressEditor,
304                  base::Unretained(this)));
305   web_ui()->RegisterMessageCallback(
306       "loadCreditCardEditor",
307       base::Bind(&AutofillOptionsHandler::LoadCreditCardEditor,
308                  base::Unretained(this)));
309   web_ui()->RegisterMessageCallback(
310       "setAddress",
311       base::Bind(&AutofillOptionsHandler::SetAddress, base::Unretained(this)));
312   web_ui()->RegisterMessageCallback(
313       "setCreditCard",
314       base::Bind(&AutofillOptionsHandler::SetCreditCard,
315                  base::Unretained(this)));
316   web_ui()->RegisterMessageCallback(
317       "validatePhoneNumbers",
318       base::Bind(&AutofillOptionsHandler::ValidatePhoneNumbers,
319                  base::Unretained(this)));
320 }
321
322 /////////////////////////////////////////////////////////////////////////////
323 // PersonalDataManagerObserver implementation:
324 void AutofillOptionsHandler::OnPersonalDataChanged() {
325   LoadAutofillData();
326 }
327
328 void AutofillOptionsHandler::SetAddressOverlayStrings(
329     DictionaryValue* localized_strings) {
330   localized_strings->SetString("autofillEditAddressTitle",
331       l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_ADDRESS_CAPTION));
332   localized_strings->SetString("autofillFirstNameLabel",
333       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_FIRST_NAME));
334   localized_strings->SetString("autofillMiddleNameLabel",
335       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_MIDDLE_NAME));
336   localized_strings->SetString("autofillLastNameLabel",
337       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_LAST_NAME));
338   localized_strings->SetString("autofillCompanyNameLabel",
339       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_COMPANY_NAME));
340   localized_strings->SetString("autofillAddrLine1Label",
341       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADDRESS_LINE_1));
342   localized_strings->SetString("autofillAddrLine2Label",
343       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADDRESS_LINE_2));
344   localized_strings->SetString("autofillCityLabel",
345       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_CITY));
346   localized_strings->SetString("autofillCountryLabel",
347       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_COUNTRY));
348   localized_strings->SetString("autofillPhoneLabel",
349       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_PHONE));
350   localized_strings->SetString("autofillEmailLabel",
351       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_EMAIL));
352   localized_strings->SetString("autofillAddFirstNamePlaceholder",
353       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_FIRST_NAME));
354   localized_strings->SetString("autofillAddMiddleNamePlaceholder",
355       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_MIDDLE_NAME));
356   localized_strings->SetString("autofillAddLastNamePlaceholder",
357       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_LAST_NAME));
358   localized_strings->SetString("autofillAddPhonePlaceholder",
359       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_PHONE));
360   localized_strings->SetString("autofillAddEmailPlaceholder",
361       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_EMAIL));
362   SetCountryData(*personal_data_, localized_strings);
363 }
364
365 void AutofillOptionsHandler::SetCreditCardOverlayStrings(
366     DictionaryValue* localized_strings) {
367   localized_strings->SetString("autofillEditCreditCardTitle",
368       l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION));
369   localized_strings->SetString("nameOnCardLabel",
370       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_NAME_ON_CARD));
371   localized_strings->SetString("creditCardNumberLabel",
372       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_CREDIT_CARD_NUMBER));
373   localized_strings->SetString("creditCardExpirationDateLabel",
374       l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_EXPIRATION_DATE));
375 }
376
377 void AutofillOptionsHandler::LoadAutofillData() {
378   if (!IsPersonalDataLoaded())
379     return;
380
381   ListValue addresses;
382   for (std::vector<AutofillProfile*>::const_iterator i =
383            personal_data_->web_profiles().begin();
384        i != personal_data_->web_profiles().end(); ++i) {
385     ListValue* entry = new ListValue();
386     entry->Append(new StringValue((*i)->guid()));
387     entry->Append(new StringValue((*i)->Label()));
388     addresses.Append(entry);
389   }
390
391   web_ui()->CallJavascriptFunction("AutofillOptions.setAddressList", addresses);
392
393   ListValue credit_cards;
394   const std::vector<CreditCard*>& cards = personal_data_->GetCreditCards();
395   for (std::vector<CreditCard*>::const_iterator iter = cards.begin();
396        iter != cards.end(); ++iter) {
397     const CreditCard* card = *iter;
398     // TODO(estade): this should be a dictionary.
399     ListValue* entry = new ListValue();
400     entry->Append(new StringValue(card->guid()));
401     entry->Append(new StringValue(card->Label()));
402     entry->Append(new StringValue(
403         webui::GetBitmapDataUrlFromResource(
404             CreditCard::IconResourceId(card->type()))));
405     entry->Append(new StringValue(card->TypeForDisplay()));
406     credit_cards.Append(entry);
407   }
408
409   web_ui()->CallJavascriptFunction("AutofillOptions.setCreditCardList",
410                                    credit_cards);
411 }
412
413 void AutofillOptionsHandler::RemoveData(const ListValue* args) {
414   DCHECK(IsPersonalDataLoaded());
415
416   std::string guid;
417   if (!args->GetString(0, &guid)) {
418     NOTREACHED();
419     return;
420   }
421
422   personal_data_->RemoveByGUID(guid);
423 }
424
425 void AutofillOptionsHandler::LoadAddressEditor(const ListValue* args) {
426   DCHECK(IsPersonalDataLoaded());
427
428   std::string guid;
429   if (!args->GetString(0, &guid)) {
430     NOTREACHED();
431     return;
432   }
433
434   AutofillProfile* profile = personal_data_->GetProfileByGUID(guid);
435   if (!profile) {
436     // There is a race where a user can click once on the close button and
437     // quickly click again on the list item before the item is removed (since
438     // the list is not updated until the model tells the list an item has been
439     // removed). This will activate the editor for a profile that has been
440     // removed. Do nothing in that case.
441     return;
442   }
443
444   DictionaryValue address;
445   address.SetString("guid", profile->guid());
446   scoped_ptr<ListValue> list;
447   GetNameList(*profile, &list);
448   address.Set("fullName", list.release());
449   address.SetString("companyName", profile->GetRawInfo(autofill::COMPANY_NAME));
450   address.SetString("addrLine1",
451                     profile->GetRawInfo(autofill::ADDRESS_HOME_LINE1));
452   address.SetString("addrLine2",
453                     profile->GetRawInfo(autofill::ADDRESS_HOME_LINE2));
454   address.SetString("city", profile->GetRawInfo(autofill::ADDRESS_HOME_CITY));
455   address.SetString("state", profile->GetRawInfo(autofill::ADDRESS_HOME_STATE));
456   address.SetString("postalCode",
457                     profile->GetRawInfo(autofill::ADDRESS_HOME_ZIP));
458   address.SetString("country",
459                     profile->GetRawInfo(autofill::ADDRESS_HOME_COUNTRY));
460   GetValueList(*profile, autofill::PHONE_HOME_WHOLE_NUMBER, &list);
461   address.Set("phone", list.release());
462   GetValueList(*profile, autofill::EMAIL_ADDRESS, &list);
463   address.Set("email", list.release());
464
465   web_ui()->CallJavascriptFunction("AutofillOptions.editAddress", address);
466 }
467
468 void AutofillOptionsHandler::LoadCreditCardEditor(const ListValue* args) {
469   DCHECK(IsPersonalDataLoaded());
470
471   std::string guid;
472   if (!args->GetString(0, &guid)) {
473     NOTREACHED();
474     return;
475   }
476
477   CreditCard* credit_card = personal_data_->GetCreditCardByGUID(guid);
478   if (!credit_card) {
479     // There is a race where a user can click once on the close button and
480     // quickly click again on the list item before the item is removed (since
481     // the list is not updated until the model tells the list an item has been
482     // removed). This will activate the editor for a profile that has been
483     // removed. Do nothing in that case.
484     return;
485   }
486
487   DictionaryValue credit_card_data;
488   credit_card_data.SetString("guid", credit_card->guid());
489   credit_card_data.SetString(
490       "nameOnCard",
491       credit_card->GetRawInfo(autofill::CREDIT_CARD_NAME));
492   credit_card_data.SetString(
493       "creditCardNumber",
494       credit_card->GetRawInfo(autofill::CREDIT_CARD_NUMBER));
495   credit_card_data.SetString(
496       "expirationMonth",
497       credit_card->GetRawInfo(autofill::CREDIT_CARD_EXP_MONTH));
498   credit_card_data.SetString(
499       "expirationYear",
500       credit_card->GetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR));
501
502   web_ui()->CallJavascriptFunction("AutofillOptions.editCreditCard",
503                                    credit_card_data);
504 }
505
506 void AutofillOptionsHandler::SetAddress(const ListValue* args) {
507   if (!IsPersonalDataLoaded())
508     return;
509
510   std::string guid;
511   if (!args->GetString(0, &guid)) {
512     NOTREACHED();
513     return;
514   }
515
516   AutofillProfile profile(guid, kSettingsOrigin);
517
518   std::string country_code;
519   string16 value;
520   const ListValue* list_value;
521   if (args->GetList(1, &list_value))
522     SetNameList(list_value, &profile);
523
524   if (args->GetString(2, &value))
525     profile.SetRawInfo(autofill::COMPANY_NAME, value);
526
527   if (args->GetString(3, &value))
528     profile.SetRawInfo(autofill::ADDRESS_HOME_LINE1, value);
529
530   if (args->GetString(4, &value))
531     profile.SetRawInfo(autofill::ADDRESS_HOME_LINE2, value);
532
533   if (args->GetString(5, &value))
534     profile.SetRawInfo(autofill::ADDRESS_HOME_CITY, value);
535
536   if (args->GetString(6, &value))
537     profile.SetRawInfo(autofill::ADDRESS_HOME_STATE, value);
538
539   if (args->GetString(7, &value))
540     profile.SetRawInfo(autofill::ADDRESS_HOME_ZIP, value);
541
542   if (args->GetString(8, &country_code))
543     profile.SetRawInfo(autofill::ADDRESS_HOME_COUNTRY,
544                        ASCIIToUTF16(country_code));
545
546   if (args->GetList(9, &list_value))
547     SetValueList(list_value, autofill::PHONE_HOME_WHOLE_NUMBER, &profile);
548
549   if (args->GetList(10, &list_value))
550     SetValueList(list_value, autofill::EMAIL_ADDRESS, &profile);
551
552   if (!base::IsValidGUID(profile.guid())) {
553     profile.set_guid(base::GenerateGUID());
554     personal_data_->AddProfile(profile);
555   } else {
556     personal_data_->UpdateProfile(profile);
557   }
558 }
559
560 void AutofillOptionsHandler::SetCreditCard(const ListValue* args) {
561   if (!IsPersonalDataLoaded())
562     return;
563
564   std::string guid;
565   if (!args->GetString(0, &guid)) {
566     NOTREACHED();
567     return;
568   }
569
570   CreditCard credit_card(guid, kSettingsOrigin);
571
572   string16 value;
573   if (args->GetString(1, &value))
574     credit_card.SetRawInfo(autofill::CREDIT_CARD_NAME, value);
575
576   if (args->GetString(2, &value))
577     credit_card.SetRawInfo(autofill::CREDIT_CARD_NUMBER, value);
578
579   if (args->GetString(3, &value))
580     credit_card.SetRawInfo(autofill::CREDIT_CARD_EXP_MONTH, value);
581
582   if (args->GetString(4, &value))
583     credit_card.SetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR, value);
584
585   if (!base::IsValidGUID(credit_card.guid())) {
586     credit_card.set_guid(base::GenerateGUID());
587     personal_data_->AddCreditCard(credit_card);
588   } else {
589     personal_data_->UpdateCreditCard(credit_card);
590   }
591 }
592
593 void AutofillOptionsHandler::ValidatePhoneNumbers(const ListValue* args) {
594   if (!IsPersonalDataLoaded())
595     return;
596
597   scoped_ptr<ListValue> list_value = ValidatePhoneArguments(args);
598
599   web_ui()->CallJavascriptFunction(
600     "AutofillEditAddressOverlay.setValidatedPhoneNumbers", *list_value);
601 }
602
603 bool AutofillOptionsHandler::IsPersonalDataLoaded() const {
604   return personal_data_ && personal_data_->IsDataLoaded();
605 }
606
607 }  // namespace options