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 "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"
34 using autofill::AutofillCountry
;
35 using autofill::ServerFieldType
;
36 using autofill::AutofillProfile
;
37 using autofill::CreditCard
;
38 using autofill::PersonalDataManager
;
42 const char kSettingsOrigin
[] = "Chrome settings";
44 // Sets data related to the country <select>.
45 void SetCountryData(const PersonalDataManager
& manager
,
46 base::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());
52 // An ordered list of options to show in the <select>.
53 scoped_ptr
<base::ListValue
> country_list(new base::ListValue());
54 // A dictionary of postal code and state info, keyed on country code.
55 scoped_ptr
<base::DictionaryValue
> country_data(new base::DictionaryValue());
56 for (size_t i
= 0; i
< countries
.size(); ++i
) {
57 scoped_ptr
<base::DictionaryValue
> option_details(
58 new base::DictionaryValue());
59 option_details
->SetString("name", model
.GetItemAt(i
));
60 option_details
->SetString(
62 countries
[i
] ? countries
[i
]->country_code() : "separator");
63 country_list
->Append(option_details
.release());
68 scoped_ptr
<base::DictionaryValue
> details(new base::DictionaryValue());
69 details
->SetString("postalCodeLabel", countries
[i
]->postal_code_label());
70 details
->SetString("stateLabel", countries
[i
]->state_label());
71 country_data
->Set(countries
[i
]->country_code(), details
.release());
74 localized_strings
->Set("autofillCountrySelectList", country_list
.release());
75 localized_strings
->Set("autofillCountryData", country_data
.release());
78 // Get the multi-valued element for |type| and return it in |ListValue| form.
79 void GetValueList(const AutofillProfile
& profile
,
81 scoped_ptr
<base::ListValue
>* list
) {
82 list
->reset(new base::ListValue
);
84 std::vector
<base::string16
> values
;
85 profile
.GetRawMultiInfo(type
, &values
);
87 // |GetRawMultiInfo()| always returns at least one, potentially empty, item.
88 if (values
.size() == 1 && values
.front().empty())
91 for (size_t i
= 0; i
< values
.size(); ++i
) {
92 (*list
)->Set(i
, new base::StringValue(values
[i
]));
96 // Set the multi-valued element for |type| from input |list| values.
97 void SetValueList(const base::ListValue
* list
,
99 AutofillProfile
* profile
) {
100 std::vector
<base::string16
> values(list
->GetSize());
101 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
102 base::string16 value
;
103 if (list
->GetString(i
, &value
))
106 profile
->SetRawMultiInfo(type
, values
);
109 // Get the multi-valued element for |type| and return it in |ListValue| form.
110 void GetNameList(const AutofillProfile
& profile
,
111 scoped_ptr
<base::ListValue
>* names
) {
112 names
->reset(new base::ListValue
);
114 std::vector
<base::string16
> first_names
;
115 std::vector
<base::string16
> middle_names
;
116 std::vector
<base::string16
> last_names
;
117 profile
.GetRawMultiInfo(autofill::NAME_FIRST
, &first_names
);
118 profile
.GetRawMultiInfo(autofill::NAME_MIDDLE
, &middle_names
);
119 profile
.GetRawMultiInfo(autofill::NAME_LAST
, &last_names
);
120 DCHECK_EQ(first_names
.size(), middle_names
.size());
121 DCHECK_EQ(first_names
.size(), last_names
.size());
123 // |GetRawMultiInfo()| always returns at least one, potentially empty, item.
124 if (first_names
.size() == 1 && first_names
.front().empty() &&
125 middle_names
.front().empty() && last_names
.front().empty()) {
129 for (size_t i
= 0; i
< first_names
.size(); ++i
) {
130 base::ListValue
* name
= new base::ListValue
; // owned by |list|
131 name
->Set(0, new base::StringValue(first_names
[i
]));
132 name
->Set(1, new base::StringValue(middle_names
[i
]));
133 name
->Set(2, new base::StringValue(last_names
[i
]));
134 (*names
)->Set(i
, name
);
138 // Set the multi-valued element for |type| from input |list| values.
139 void SetNameList(const base::ListValue
* names
, AutofillProfile
* profile
) {
140 const size_t size
= names
->GetSize();
141 std::vector
<base::string16
> first_names(size
);
142 std::vector
<base::string16
> middle_names(size
);
143 std::vector
<base::string16
> last_names(size
);
145 for (size_t i
= 0; i
< size
; ++i
) {
146 const base::ListValue
* name
;
147 bool success
= names
->GetList(i
, &name
);
150 base::string16 first_name
;
151 success
= name
->GetString(0, &first_name
);
153 first_names
[i
] = first_name
;
155 base::string16 middle_name
;
156 success
= name
->GetString(1, &middle_name
);
158 middle_names
[i
] = middle_name
;
160 base::string16 last_name
;
161 success
= name
->GetString(2, &last_name
);
163 last_names
[i
] = last_name
;
166 profile
->SetRawMultiInfo(autofill::NAME_FIRST
, first_names
);
167 profile
->SetRawMultiInfo(autofill::NAME_MIDDLE
, middle_names
);
168 profile
->SetRawMultiInfo(autofill::NAME_LAST
, last_names
);
171 // Pulls the phone number |index|, |phone_number_list|, and |country_code| from
173 void ExtractPhoneNumberInformation(const base::ListValue
* args
,
175 const base::ListValue
** phone_number_list
,
176 std::string
* country_code
) {
177 // Retrieve index as a |double|, as that is how it comes across from
180 if (!args
->GetDouble(0, &number
)) {
186 if (!args
->GetList(1, phone_number_list
)) {
191 if (!args
->GetString(2, country_code
)) {
197 // Searches the |list| for the value at |index|. If this value is present
198 // in any of the rest of the list, then the item (at |index|) is removed.
199 // The comparison of phone number values is done on normalized versions of the
200 // phone number values.
201 void RemoveDuplicatePhoneNumberAtIndex(size_t index
,
202 const std::string
& country_code
,
203 base::ListValue
* list
) {
204 base::string16 new_value
;
205 if (!list
->GetString(index
, &new_value
)) {
206 NOTREACHED() << "List should have a value at index " << index
;
210 bool is_duplicate
= false;
211 std::string app_locale
= g_browser_process
->GetApplicationLocale();
212 for (size_t i
= 0; i
< list
->GetSize() && !is_duplicate
; ++i
) {
216 base::string16 existing_value
;
217 if (!list
->GetString(i
, &existing_value
)) {
218 NOTREACHED() << "List should have a value at index " << i
;
221 is_duplicate
= autofill::i18n::PhoneNumbersMatch(
222 new_value
, existing_value
, country_code
, app_locale
);
226 list
->Remove(index
, NULL
);
229 scoped_ptr
<base::ListValue
> ValidatePhoneArguments(
230 const base::ListValue
* args
) {
232 std::string country_code
;
233 const base::ListValue
* extracted_list
= NULL
;
234 ExtractPhoneNumberInformation(args
, &index
, &extracted_list
, &country_code
);
236 scoped_ptr
<base::ListValue
> list(extracted_list
->DeepCopy());
237 RemoveDuplicatePhoneNumberAtIndex(index
, country_code
, list
.get());
245 AutofillOptionsHandler::AutofillOptionsHandler()
246 : personal_data_(NULL
) {}
248 AutofillOptionsHandler::~AutofillOptionsHandler() {
250 personal_data_
->RemoveObserver(this);
253 /////////////////////////////////////////////////////////////////////////////
254 // OptionsPageUIHandler implementation:
255 void AutofillOptionsHandler::GetLocalizedValues(
256 base::DictionaryValue
* localized_strings
) {
257 DCHECK(localized_strings
);
259 static OptionsStringResource resources
[] = {
260 { "autofillAddresses", IDS_AUTOFILL_ADDRESSES_GROUP_NAME
},
261 { "autofillCreditCards", IDS_AUTOFILL_CREDITCARDS_GROUP_NAME
},
262 { "autofillAddAddress", IDS_AUTOFILL_ADD_ADDRESS_BUTTON
},
263 { "autofillAddCreditCard", IDS_AUTOFILL_ADD_CREDITCARD_BUTTON
},
264 { "autofillEditProfileButton", IDS_AUTOFILL_EDIT_PROFILE_BUTTON
},
265 { "helpButton", IDS_AUTOFILL_HELP_LABEL
},
266 { "addAddressTitle", IDS_AUTOFILL_ADD_ADDRESS_CAPTION
},
267 { "editAddressTitle", IDS_AUTOFILL_EDIT_ADDRESS_CAPTION
},
268 { "addCreditCardTitle", IDS_AUTOFILL_ADD_CREDITCARD_CAPTION
},
269 { "editCreditCardTitle", IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION
},
270 #if defined(OS_MACOSX)
271 { "auxiliaryProfilesEnabled", IDS_AUTOFILL_USE_MAC_ADDRESS_BOOK
},
272 #endif // defined(OS_MACOSX)
275 RegisterStrings(localized_strings
, resources
, arraysize(resources
));
276 RegisterTitle(localized_strings
, "autofillOptionsPage",
277 IDS_AUTOFILL_OPTIONS_TITLE
);
279 localized_strings
->SetString("helpUrl", autofill::kHelpURL
);
280 SetAddressOverlayStrings(localized_strings
);
281 SetCreditCardOverlayStrings(localized_strings
);
284 void AutofillOptionsHandler::InitializeHandler() {
285 // personal_data_ is NULL in guest mode on Chrome OS.
287 personal_data_
->AddObserver(this);
290 void AutofillOptionsHandler::InitializePage() {
295 void AutofillOptionsHandler::RegisterMessages() {
296 personal_data_
= autofill::PersonalDataManagerFactory::GetForProfile(
297 Profile::FromWebUI(web_ui()));
299 web_ui()->RegisterMessageCallback(
301 base::Bind(&AutofillOptionsHandler::RemoveData
,
302 base::Unretained(this)));
303 web_ui()->RegisterMessageCallback(
305 base::Bind(&AutofillOptionsHandler::LoadAddressEditor
,
306 base::Unretained(this)));
307 web_ui()->RegisterMessageCallback(
308 "loadCreditCardEditor",
309 base::Bind(&AutofillOptionsHandler::LoadCreditCardEditor
,
310 base::Unretained(this)));
311 web_ui()->RegisterMessageCallback(
313 base::Bind(&AutofillOptionsHandler::SetAddress
, base::Unretained(this)));
314 web_ui()->RegisterMessageCallback(
316 base::Bind(&AutofillOptionsHandler::SetCreditCard
,
317 base::Unretained(this)));
318 web_ui()->RegisterMessageCallback(
319 "validatePhoneNumbers",
320 base::Bind(&AutofillOptionsHandler::ValidatePhoneNumbers
,
321 base::Unretained(this)));
324 /////////////////////////////////////////////////////////////////////////////
325 // PersonalDataManagerObserver implementation:
326 void AutofillOptionsHandler::OnPersonalDataChanged() {
330 void AutofillOptionsHandler::SetAddressOverlayStrings(
331 base::DictionaryValue
* localized_strings
) {
332 localized_strings
->SetString("autofillEditAddressTitle",
333 l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_ADDRESS_CAPTION
));
334 localized_strings
->SetString("autofillFirstNameLabel",
335 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_FIRST_NAME
));
336 localized_strings
->SetString("autofillMiddleNameLabel",
337 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_MIDDLE_NAME
));
338 localized_strings
->SetString("autofillLastNameLabel",
339 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_LAST_NAME
));
340 localized_strings
->SetString("autofillCompanyNameLabel",
341 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_COMPANY_NAME
));
342 localized_strings
->SetString("autofillAddrLine1Label",
343 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADDRESS_LINE_1
));
344 localized_strings
->SetString("autofillAddrLine2Label",
345 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADDRESS_LINE_2
));
346 localized_strings
->SetString("autofillCityLabel",
347 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_CITY
));
348 localized_strings
->SetString("autofillCountryLabel",
349 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_COUNTRY
));
350 localized_strings
->SetString("autofillPhoneLabel",
351 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_PHONE
));
352 localized_strings
->SetString("autofillEmailLabel",
353 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_EMAIL
));
354 localized_strings
->SetString("autofillAddFirstNamePlaceholder",
355 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_FIRST_NAME
));
356 localized_strings
->SetString("autofillAddMiddleNamePlaceholder",
357 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_MIDDLE_NAME
));
358 localized_strings
->SetString("autofillAddLastNamePlaceholder",
359 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_LAST_NAME
));
360 localized_strings
->SetString("autofillAddPhonePlaceholder",
361 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_PHONE
));
362 localized_strings
->SetString("autofillAddEmailPlaceholder",
363 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_EMAIL
));
364 SetCountryData(*personal_data_
, localized_strings
);
367 void AutofillOptionsHandler::SetCreditCardOverlayStrings(
368 base::DictionaryValue
* localized_strings
) {
369 localized_strings
->SetString("autofillEditCreditCardTitle",
370 l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION
));
371 localized_strings
->SetString("nameOnCardLabel",
372 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_NAME_ON_CARD
));
373 localized_strings
->SetString("creditCardNumberLabel",
374 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_CREDIT_CARD_NUMBER
));
375 localized_strings
->SetString("creditCardExpirationDateLabel",
376 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_EXPIRATION_DATE
));
379 void AutofillOptionsHandler::LoadAutofillData() {
380 if (!IsPersonalDataLoaded())
383 const std::vector
<AutofillProfile
*>& profiles
=
384 personal_data_
->web_profiles();
385 std::vector
<base::string16
> labels
;
386 AutofillProfile::CreateDifferentiatingLabels(profiles
, &labels
);
387 DCHECK_EQ(labels
.size(), profiles
.size());
389 base::ListValue addresses
;
390 for (size_t i
= 0; i
< profiles
.size(); ++i
) {
391 base::ListValue
* entry
= new base::ListValue();
392 entry
->Append(new base::StringValue(profiles
[i
]->guid()));
393 entry
->Append(new base::StringValue(labels
[i
]));
394 addresses
.Append(entry
);
397 web_ui()->CallJavascriptFunction("AutofillOptions.setAddressList", addresses
);
399 base::ListValue credit_cards
;
400 const std::vector
<CreditCard
*>& cards
= personal_data_
->GetCreditCards();
401 for (std::vector
<CreditCard
*>::const_iterator iter
= cards
.begin();
402 iter
!= cards
.end(); ++iter
) {
403 const CreditCard
* card
= *iter
;
404 // TODO(estade): this should be a dictionary.
405 base::ListValue
* entry
= new base::ListValue();
406 entry
->Append(new base::StringValue(card
->guid()));
407 entry
->Append(new base::StringValue(card
->Label()));
408 entry
->Append(new base::StringValue(
409 webui::GetBitmapDataUrlFromResource(
410 CreditCard::IconResourceId(card
->type()))));
411 entry
->Append(new base::StringValue(card
->TypeForDisplay()));
412 credit_cards
.Append(entry
);
415 web_ui()->CallJavascriptFunction("AutofillOptions.setCreditCardList",
419 void AutofillOptionsHandler::RemoveData(const base::ListValue
* args
) {
420 DCHECK(IsPersonalDataLoaded());
423 if (!args
->GetString(0, &guid
)) {
428 personal_data_
->RemoveByGUID(guid
);
431 void AutofillOptionsHandler::LoadAddressEditor(const base::ListValue
* args
) {
432 DCHECK(IsPersonalDataLoaded());
435 if (!args
->GetString(0, &guid
)) {
440 AutofillProfile
* profile
= personal_data_
->GetProfileByGUID(guid
);
442 // There is a race where a user can click once on the close button and
443 // quickly click again on the list item before the item is removed (since
444 // the list is not updated until the model tells the list an item has been
445 // removed). This will activate the editor for a profile that has been
446 // removed. Do nothing in that case.
450 base::DictionaryValue address
;
451 address
.SetString("guid", profile
->guid());
452 scoped_ptr
<base::ListValue
> list
;
453 GetNameList(*profile
, &list
);
454 address
.Set("fullName", list
.release());
455 address
.SetString("companyName", profile
->GetRawInfo(autofill::COMPANY_NAME
));
456 address
.SetString("addrLine1",
457 profile
->GetRawInfo(autofill::ADDRESS_HOME_LINE1
));
458 address
.SetString("addrLine2",
459 profile
->GetRawInfo(autofill::ADDRESS_HOME_LINE2
));
460 address
.SetString("city", profile
->GetRawInfo(autofill::ADDRESS_HOME_CITY
));
461 address
.SetString("state", profile
->GetRawInfo(autofill::ADDRESS_HOME_STATE
));
462 address
.SetString("postalCode",
463 profile
->GetRawInfo(autofill::ADDRESS_HOME_ZIP
));
464 address
.SetString("country",
465 profile
->GetRawInfo(autofill::ADDRESS_HOME_COUNTRY
));
466 GetValueList(*profile
, autofill::PHONE_HOME_WHOLE_NUMBER
, &list
);
467 address
.Set("phone", list
.release());
468 GetValueList(*profile
, autofill::EMAIL_ADDRESS
, &list
);
469 address
.Set("email", list
.release());
471 web_ui()->CallJavascriptFunction("AutofillOptions.editAddress", address
);
474 void AutofillOptionsHandler::LoadCreditCardEditor(const base::ListValue
* args
) {
475 DCHECK(IsPersonalDataLoaded());
478 if (!args
->GetString(0, &guid
)) {
483 CreditCard
* credit_card
= personal_data_
->GetCreditCardByGUID(guid
);
485 // There is a race where a user can click once on the close button and
486 // quickly click again on the list item before the item is removed (since
487 // the list is not updated until the model tells the list an item has been
488 // removed). This will activate the editor for a profile that has been
489 // removed. Do nothing in that case.
493 base::DictionaryValue credit_card_data
;
494 credit_card_data
.SetString("guid", credit_card
->guid());
495 credit_card_data
.SetString(
497 credit_card
->GetRawInfo(autofill::CREDIT_CARD_NAME
));
498 credit_card_data
.SetString(
500 credit_card
->GetRawInfo(autofill::CREDIT_CARD_NUMBER
));
501 credit_card_data
.SetString(
503 credit_card
->GetRawInfo(autofill::CREDIT_CARD_EXP_MONTH
));
504 credit_card_data
.SetString(
506 credit_card
->GetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR
));
508 web_ui()->CallJavascriptFunction("AutofillOptions.editCreditCard",
512 void AutofillOptionsHandler::SetAddress(const base::ListValue
* args
) {
513 if (!IsPersonalDataLoaded())
517 if (!args
->GetString(0, &guid
)) {
522 AutofillProfile
profile(guid
, kSettingsOrigin
);
524 std::string country_code
;
525 base::string16 value
;
526 const base::ListValue
* list_value
;
527 if (args
->GetList(1, &list_value
))
528 SetNameList(list_value
, &profile
);
530 if (args
->GetString(2, &value
))
531 profile
.SetRawInfo(autofill::COMPANY_NAME
, value
);
533 if (args
->GetString(3, &value
))
534 profile
.SetRawInfo(autofill::ADDRESS_HOME_LINE1
, value
);
536 if (args
->GetString(4, &value
))
537 profile
.SetRawInfo(autofill::ADDRESS_HOME_LINE2
, value
);
539 if (args
->GetString(5, &value
))
540 profile
.SetRawInfo(autofill::ADDRESS_HOME_CITY
, value
);
542 if (args
->GetString(6, &value
))
543 profile
.SetRawInfo(autofill::ADDRESS_HOME_STATE
, value
);
545 if (args
->GetString(7, &value
))
546 profile
.SetRawInfo(autofill::ADDRESS_HOME_ZIP
, value
);
548 if (args
->GetString(8, &country_code
))
549 profile
.SetRawInfo(autofill::ADDRESS_HOME_COUNTRY
,
550 base::ASCIIToUTF16(country_code
));
552 if (args
->GetList(9, &list_value
))
553 SetValueList(list_value
, autofill::PHONE_HOME_WHOLE_NUMBER
, &profile
);
555 if (args
->GetList(10, &list_value
))
556 SetValueList(list_value
, autofill::EMAIL_ADDRESS
, &profile
);
558 if (!base::IsValidGUID(profile
.guid())) {
559 profile
.set_guid(base::GenerateGUID());
560 personal_data_
->AddProfile(profile
);
562 personal_data_
->UpdateProfile(profile
);
566 void AutofillOptionsHandler::SetCreditCard(const base::ListValue
* args
) {
567 if (!IsPersonalDataLoaded())
571 if (!args
->GetString(0, &guid
)) {
576 CreditCard
credit_card(guid
, kSettingsOrigin
);
578 base::string16 value
;
579 if (args
->GetString(1, &value
))
580 credit_card
.SetRawInfo(autofill::CREDIT_CARD_NAME
, value
);
582 if (args
->GetString(2, &value
))
583 credit_card
.SetRawInfo(autofill::CREDIT_CARD_NUMBER
, value
);
585 if (args
->GetString(3, &value
))
586 credit_card
.SetRawInfo(autofill::CREDIT_CARD_EXP_MONTH
, value
);
588 if (args
->GetString(4, &value
))
589 credit_card
.SetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR
, value
);
591 if (!base::IsValidGUID(credit_card
.guid())) {
592 credit_card
.set_guid(base::GenerateGUID());
593 personal_data_
->AddCreditCard(credit_card
);
595 personal_data_
->UpdateCreditCard(credit_card
);
599 void AutofillOptionsHandler::ValidatePhoneNumbers(const base::ListValue
* args
) {
600 if (!IsPersonalDataLoaded())
603 scoped_ptr
<base::ListValue
> list_value
= ValidatePhoneArguments(args
);
605 web_ui()->CallJavascriptFunction(
606 "AutofillEditAddressOverlay.setValidatedPhoneNumbers", *list_value
);
609 bool AutofillOptionsHandler::IsPersonalDataLoaded() const {
610 return personal_data_
&& personal_data_
->IsDataLoaded();
613 } // namespace options