Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / ui / webui / options / autofill_options_handler.cc
blob3c4bc1b7aab045e9859a76c21149caf96857bcf8
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"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/command_line.h"
12 #include "base/guid.h"
13 #include "base/logging.h"
14 #include "base/strings/string16.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_split.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/values.h"
19 #include "chrome/browser/autofill/options_util.h"
20 #include "chrome/browser/autofill/personal_data_manager_factory.h"
21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/sync/profile_sync_service_factory.h"
24 #include "chrome/browser/ui/autofill/country_combobox_model.h"
25 #include "chrome/common/url_constants.h"
26 #include "chrome/grit/chromium_strings.h"
27 #include "chrome/grit/generated_resources.h"
28 #include "components/autofill/content/browser/wallet/wallet_service_url.h"
29 #include "components/autofill/core/browser/autofill_country.h"
30 #include "components/autofill/core/browser/autofill_profile.h"
31 #include "components/autofill/core/browser/credit_card.h"
32 #include "components/autofill/core/browser/personal_data_manager.h"
33 #include "components/autofill/core/browser/phone_number_i18n.h"
34 #include "components/autofill/core/common/autofill_constants.h"
35 #include "components/autofill/core/common/autofill_switches.h"
36 #include "content/public/browser/web_ui.h"
37 #include "grit/components_strings.h"
38 #include "third_party/libaddressinput/messages.h"
39 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui.h"
40 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui_component.h"
41 #include "third_party/libaddressinput/src/cpp/include/libaddressinput/localization.h"
42 #include "ui/base/l10n/l10n_util.h"
43 #include "ui/base/webui/web_ui_util.h"
45 using autofill::AutofillCountry;
46 using autofill::AutofillType;
47 using autofill::ServerFieldType;
48 using autofill::AutofillProfile;
49 using autofill::CreditCard;
50 using autofill::PersonalDataManager;
51 using i18n::addressinput::AddressUiComponent;
53 namespace {
55 const char kSettingsOrigin[] = "Chrome settings";
57 static const char kFullNameField[] = "fullName";
58 static const char kCompanyNameField[] = "companyName";
59 static const char kAddressLineField[] = "addrLines";
60 static const char kDependentLocalityField[] = "dependentLocality";
61 static const char kCityField[] = "city";
62 static const char kStateField[] = "state";
63 static const char kPostalCodeField[] = "postalCode";
64 static const char kSortingCodeField[] = "sortingCode";
65 static const char kCountryField[] = "country";
67 static const char kComponents[] = "components";
68 static const char kLanguageCode[] = "languageCode";
70 scoped_ptr<base::DictionaryValue> CreditCardToDictionary(
71 const CreditCard& card) {
72 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue);
73 value->SetString("guid", card.guid());
74 std::pair<base::string16, base::string16> label_pieces = card.LabelPieces();
75 value->SetString("label", label_pieces.first);
76 value->SetString("sublabel", label_pieces.second);
77 value->SetBoolean("isLocal", card.record_type() == CreditCard::LOCAL_CARD);
78 value->SetBoolean("isCached",
79 card.record_type() == CreditCard::FULL_SERVER_CARD);
80 return value.Pass();
83 // Fills |components| with the address UI components that should be used to
84 // input an address for |country_code| when UI BCP 47 language code is
85 // |ui_language_code|. If |components_language_code| is not NULL, then sets it
86 // to the BCP 47 language code that should be used to format the address for
87 // display.
88 void GetAddressComponents(const std::string& country_code,
89 const std::string& ui_language_code,
90 base::ListValue* address_components,
91 std::string* components_language_code) {
92 DCHECK(address_components);
94 i18n::addressinput::Localization localization;
95 localization.SetGetter(l10n_util::GetStringUTF8);
96 std::string not_used;
97 std::vector<AddressUiComponent> components =
98 i18n::addressinput::BuildComponents(
99 country_code,
100 localization,
101 ui_language_code,
102 components_language_code == NULL ?
103 &not_used : components_language_code);
104 if (components.empty()) {
105 static const char kDefaultCountryCode[] = "US";
106 components = i18n::addressinput::BuildComponents(
107 kDefaultCountryCode,
108 localization,
109 ui_language_code,
110 components_language_code == NULL ?
111 &not_used : components_language_code);
113 DCHECK(!components.empty());
115 base::ListValue* line = NULL;
116 static const char kField[] = "field";
117 static const char kLength[] = "length";
118 for (size_t i = 0; i < components.size(); ++i) {
119 if (i == 0 ||
120 components[i - 1].length_hint == AddressUiComponent::HINT_LONG ||
121 components[i].length_hint == AddressUiComponent::HINT_LONG) {
122 line = new base::ListValue;
123 address_components->Append(line);
126 scoped_ptr<base::DictionaryValue> component(new base::DictionaryValue);
127 component->SetString("name", components[i].name);
129 switch (components[i].field) {
130 case i18n::addressinput::COUNTRY:
131 component->SetString(kField, kCountryField);
132 break;
133 case i18n::addressinput::ADMIN_AREA:
134 component->SetString(kField, kStateField);
135 break;
136 case i18n::addressinput::LOCALITY:
137 component->SetString(kField, kCityField);
138 break;
139 case i18n::addressinput::DEPENDENT_LOCALITY:
140 component->SetString(kField, kDependentLocalityField);
141 break;
142 case i18n::addressinput::SORTING_CODE:
143 component->SetString(kField, kSortingCodeField);
144 break;
145 case i18n::addressinput::POSTAL_CODE:
146 component->SetString(kField, kPostalCodeField);
147 break;
148 case i18n::addressinput::STREET_ADDRESS:
149 component->SetString(kField, kAddressLineField);
150 break;
151 case i18n::addressinput::ORGANIZATION:
152 component->SetString(kField, kCompanyNameField);
153 break;
154 case i18n::addressinput::RECIPIENT:
155 component->SetString(kField, kFullNameField);
156 component->SetString(
157 "placeholder",
158 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_NAME));
159 break;
162 switch (components[i].length_hint) {
163 case AddressUiComponent::HINT_LONG:
164 component->SetString(kLength, "long");
165 break;
166 case AddressUiComponent::HINT_SHORT:
167 component->SetString(kLength, "short");
168 break;
171 line->Append(component.release());
175 // Sets data related to the country <select>.
176 void SetCountryData(const PersonalDataManager& manager,
177 base::DictionaryValue* localized_strings) {
178 autofill::CountryComboboxModel model;
179 model.SetCountries(manager, base::Callback<bool(const std::string&)>());
180 const std::vector<AutofillCountry*>& countries = model.countries();
181 localized_strings->SetString("defaultCountryCode",
182 countries.front()->country_code());
184 // An ordered list of options to show in the <select>.
185 scoped_ptr<base::ListValue> country_list(new base::ListValue());
186 for (size_t i = 0; i < countries.size(); ++i) {
187 scoped_ptr<base::DictionaryValue> option_details(
188 new base::DictionaryValue());
189 option_details->SetString("name", model.GetItemAt(i));
190 option_details->SetString(
191 "value",
192 countries[i] ? countries[i]->country_code() : "separator");
193 country_list->Append(option_details.release());
195 localized_strings->Set("autofillCountrySelectList", country_list.release());
197 scoped_ptr<base::ListValue> default_country_components(new base::ListValue);
198 std::string default_country_language_code;
199 GetAddressComponents(countries.front()->country_code(),
200 g_browser_process->GetApplicationLocale(),
201 default_country_components.get(),
202 &default_country_language_code);
203 localized_strings->Set("autofillDefaultCountryComponents",
204 default_country_components.release());
205 localized_strings->SetString("autofillDefaultCountryLanguageCode",
206 default_country_language_code);
209 // Get the multi-valued element for |type| and return it in |ListValue| form.
210 // Buyer beware: the type of data affects whether GetRawInfo or GetInfo is used.
211 void GetValueList(const AutofillProfile& profile,
212 ServerFieldType type,
213 scoped_ptr<base::ListValue>* list) {
214 list->reset(new base::ListValue);
216 std::vector<base::string16> values;
217 if (AutofillType(type).group() == autofill::NAME) {
218 profile.GetMultiInfo(
219 AutofillType(type), g_browser_process->GetApplicationLocale(), &values);
220 } else {
221 profile.GetRawMultiInfo(type, &values);
224 // |Get[Raw]MultiInfo()| always returns at least one, potentially empty, item.
225 if (values.size() == 1 && values.front().empty())
226 return;
228 for (size_t i = 0; i < values.size(); ++i) {
229 (*list)->Set(i, new base::StringValue(values[i]));
233 // Converts a ListValue of StringValues to a vector of string16s.
234 void ListValueToStringVector(const base::ListValue& list,
235 std::vector<base::string16>* output) {
236 output->resize(list.GetSize());
237 for (size_t i = 0; i < list.GetSize(); ++i) {
238 base::string16 value;
239 if (list.GetString(i, &value))
240 (*output)[i].swap(value);
244 // Pulls the phone number |index|, |phone_number_list|, and |country_code| from
245 // the |args| input.
246 void ExtractPhoneNumberInformation(const base::ListValue* args,
247 size_t* index,
248 const base::ListValue** phone_number_list,
249 std::string* country_code) {
250 // Retrieve index as a |double|, as that is how it comes across from
251 // JavaScript.
252 double number = 0.0;
253 if (!args->GetDouble(0, &number)) {
254 NOTREACHED();
255 return;
257 *index = number;
259 if (!args->GetList(1, phone_number_list)) {
260 NOTREACHED();
261 return;
264 if (!args->GetString(2, country_code)) {
265 NOTREACHED();
266 return;
270 // Searches the |list| for the value at |index|. If this value is present
271 // in any of the rest of the list, then the item (at |index|) is removed.
272 // The comparison of phone number values is done on normalized versions of the
273 // phone number values.
274 void RemoveDuplicatePhoneNumberAtIndex(size_t index,
275 const std::string& country_code,
276 base::ListValue* list) {
277 base::string16 new_value;
278 if (!list->GetString(index, &new_value)) {
279 NOTREACHED() << "List should have a value at index " << index;
280 return;
283 bool is_duplicate = false;
284 std::string app_locale = g_browser_process->GetApplicationLocale();
285 for (size_t i = 0; i < list->GetSize() && !is_duplicate; ++i) {
286 if (i == index)
287 continue;
289 base::string16 existing_value;
290 if (!list->GetString(i, &existing_value)) {
291 NOTREACHED() << "List should have a value at index " << i;
292 continue;
294 is_duplicate = autofill::i18n::PhoneNumbersMatch(
295 new_value, existing_value, country_code, app_locale);
298 if (is_duplicate)
299 list->Remove(index, NULL);
302 scoped_ptr<base::ListValue> ValidatePhoneArguments(
303 const base::ListValue* args) {
304 size_t index = 0;
305 std::string country_code;
306 const base::ListValue* extracted_list = NULL;
307 ExtractPhoneNumberInformation(args, &index, &extracted_list, &country_code);
309 scoped_ptr<base::ListValue> list(extracted_list->DeepCopy());
310 RemoveDuplicatePhoneNumberAtIndex(index, country_code, list.get());
311 return list.Pass();
314 } // namespace
316 namespace options {
318 AutofillOptionsHandler::AutofillOptionsHandler()
319 : personal_data_(NULL), observer_(this) {
322 AutofillOptionsHandler::~AutofillOptionsHandler() {
323 if (personal_data_)
324 personal_data_->RemoveObserver(this);
327 /////////////////////////////////////////////////////////////////////////////
328 // OptionsPageUIHandler implementation:
329 void AutofillOptionsHandler::GetLocalizedValues(
330 base::DictionaryValue* localized_strings) {
331 DCHECK(localized_strings);
333 static OptionsStringResource resources[] = {
334 { "autofillAddresses", IDS_AUTOFILL_ADDRESSES_GROUP_NAME },
335 { "autofillCreditCards", IDS_AUTOFILL_CREDITCARDS_GROUP_NAME },
336 { "autofillAddAddress", IDS_AUTOFILL_ADD_ADDRESS_BUTTON },
337 { "autofillAddCreditCard", IDS_AUTOFILL_ADD_CREDITCARD_BUTTON },
338 { "autofillEditProfileButton", IDS_AUTOFILL_EDIT_PROFILE_BUTTON },
339 { "autofillFromGoogleAccount", IDS_AUTOFILL_FROM_GOOGLE_ACCOUNT },
340 { "autofillDescribeLocalCopy", IDS_AUTOFILL_DESCRIBE_LOCAL_COPY },
341 { "autofillClearLocalCopyButton", IDS_AUTOFILL_CLEAR_LOCAL_COPY_BUTTON },
342 { "helpButton", IDS_AUTOFILL_HELP_LABEL },
343 { "addAddressTitle", IDS_AUTOFILL_ADD_ADDRESS_CAPTION },
344 { "editAddressTitle", IDS_AUTOFILL_EDIT_ADDRESS_CAPTION },
345 { "addCreditCardTitle", IDS_AUTOFILL_ADD_CREDITCARD_CAPTION },
346 { "editCreditCardTitle", IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION },
347 { "autofillWalletOption", IDS_AUTOFILL_USE_WALLET_DATA },
348 #if defined(OS_MACOSX)
349 { "auxiliaryProfilesEnabled", IDS_AUTOFILL_USE_MAC_ADDRESS_BOOK },
350 #endif // defined(OS_MACOSX)
353 RegisterStrings(localized_strings, resources, arraysize(resources));
354 RegisterTitle(localized_strings, "autofillOptionsPage",
355 IDS_AUTOFILL_OPTIONS_TITLE);
357 localized_strings->SetString("helpUrl", autofill::kHelpURL);
359 personal_data_ = autofill::PersonalDataManagerFactory::GetForProfile(
360 Profile::FromWebUI(web_ui()));
362 SetAddressOverlayStrings(localized_strings);
363 SetCreditCardOverlayStrings(localized_strings);
365 localized_strings->SetString(
366 "manageWalletAddressesUrl",
367 autofill::wallet::GetManageAddressesUrl(0).spec());
368 localized_strings->SetString(
369 "manageWalletPaymentMethodsUrl",
370 autofill::wallet::GetManageInstrumentsUrl(0).spec());
372 // This is set in loadTimeData to minimize the chance of a load-time flash of
373 // content.
374 ProfileSyncService* service =
375 ProfileSyncServiceFactory::GetInstance()->GetForProfile(
376 Profile::FromWebUI(web_ui()));
377 if (service)
378 observer_.Add(service);
380 localized_strings->SetBoolean("autofillWalletIntegrationAvailable",
381 autofill::WalletIntegrationAvailableForProfile(
382 Profile::FromWebUI(web_ui())));
385 void AutofillOptionsHandler::InitializeHandler() {
386 // personal_data_ is NULL in guest mode on Chrome OS.
387 if (personal_data_)
388 personal_data_->AddObserver(this);
391 void AutofillOptionsHandler::InitializePage() {
392 if (personal_data_)
393 LoadAutofillData();
395 // Also update the visibility of the Wallet checkbox (which may have
396 // changed since the localized string dictionary was built).
397 OnStateChanged();
400 void AutofillOptionsHandler::RegisterMessages() {
401 #if defined(OS_MACOSX) && !defined(OS_IOS)
402 web_ui()->RegisterMessageCallback(
403 "accessAddressBook",
404 base::Bind(&AutofillOptionsHandler::AccessAddressBook,
405 base::Unretained(this)));
406 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
407 web_ui()->RegisterMessageCallback(
408 "removeData",
409 base::Bind(&AutofillOptionsHandler::RemoveData,
410 base::Unretained(this)));
411 web_ui()->RegisterMessageCallback(
412 "loadAddressEditor",
413 base::Bind(&AutofillOptionsHandler::LoadAddressEditor,
414 base::Unretained(this)));
415 web_ui()->RegisterMessageCallback(
416 "loadAddressEditorComponents",
417 base::Bind(&AutofillOptionsHandler::LoadAddressEditorComponents,
418 base::Unretained(this)));
419 web_ui()->RegisterMessageCallback(
420 "loadCreditCardEditor",
421 base::Bind(&AutofillOptionsHandler::LoadCreditCardEditor,
422 base::Unretained(this)));
423 web_ui()->RegisterMessageCallback(
424 "setAddress",
425 base::Bind(&AutofillOptionsHandler::SetAddress, base::Unretained(this)));
426 web_ui()->RegisterMessageCallback(
427 "setCreditCard",
428 base::Bind(&AutofillOptionsHandler::SetCreditCard,
429 base::Unretained(this)));
430 web_ui()->RegisterMessageCallback(
431 "validatePhoneNumbers",
432 base::Bind(&AutofillOptionsHandler::ValidatePhoneNumbers,
433 base::Unretained(this)));
434 web_ui()->RegisterMessageCallback(
435 "clearLocalCardCopy",
436 base::Bind(&AutofillOptionsHandler::RemaskServerCard,
437 base::Unretained(this)));
440 /////////////////////////////////////////////////////////////////////////////
441 // PersonalDataManagerObserver implementation:
442 void AutofillOptionsHandler::OnPersonalDataChanged() {
443 LoadAutofillData();
444 OnStateChanged();
447 void AutofillOptionsHandler::OnStateChanged() {
448 web_ui()->CallJavascriptFunction(
449 "AutofillOptions.walletIntegrationAvailableStateChanged",
450 base::FundamentalValue(autofill::WalletIntegrationAvailableForProfile(
451 Profile::FromWebUI(web_ui()))));
454 void AutofillOptionsHandler::SetAddressOverlayStrings(
455 base::DictionaryValue* localized_strings) {
456 localized_strings->SetString("autofillEditAddressTitle",
457 l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_ADDRESS_CAPTION));
458 localized_strings->SetString("autofillCountryLabel",
459 l10n_util::GetStringUTF16(IDS_LIBADDRESSINPUT_COUNTRY_OR_REGION_LABEL));
460 localized_strings->SetString("autofillPhoneLabel",
461 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_PHONE));
462 localized_strings->SetString("autofillEmailLabel",
463 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_EMAIL));
464 localized_strings->SetString("autofillAddPhonePlaceholder",
465 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_PHONE));
466 localized_strings->SetString("autofillAddEmailPlaceholder",
467 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_ADD_EMAIL));
468 SetCountryData(*personal_data_, localized_strings);
471 void AutofillOptionsHandler::SetCreditCardOverlayStrings(
472 base::DictionaryValue* localized_strings) {
473 localized_strings->SetString("autofillEditCreditCardTitle",
474 l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION));
475 localized_strings->SetString("nameOnCardLabel",
476 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_NAME_ON_CARD));
477 localized_strings->SetString("creditCardNumberLabel",
478 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_CREDIT_CARD_NUMBER));
479 localized_strings->SetString("creditCardExpirationDateLabel",
480 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_EXPIRATION_DATE));
483 void AutofillOptionsHandler::LoadAutofillData() {
484 if (!IsPersonalDataLoaded())
485 return;
487 const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
488 std::vector<base::string16> labels;
489 AutofillProfile::CreateDifferentiatingLabels(
490 profiles,
491 g_browser_process->GetApplicationLocale(),
492 &labels);
493 DCHECK_EQ(labels.size(), profiles.size());
495 base::ListValue addresses;
496 for (size_t i = 0; i < profiles.size(); ++i) {
497 // Skip showing auxiliary profiles (e.g. Mac Contacts) for now.
498 if (profiles[i]->record_type() == AutofillProfile::AUXILIARY_PROFILE)
499 continue;
501 base::string16 separator =
502 l10n_util::GetStringUTF16(IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR);
503 std::vector<base::string16> label_parts;
504 base::SplitStringUsingSubstr(labels[i], separator, &label_parts);
506 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue);
507 value->SetString("guid", profiles[i]->guid());
508 value->SetString("label", label_parts[0]);
509 value->SetString("sublabel", labels[i].substr(label_parts[0].size()));
510 value->SetBoolean("isLocal", profiles[i]->record_type() ==
511 AutofillProfile::LOCAL_PROFILE);
512 addresses.Append(value.release());
515 web_ui()->CallJavascriptFunction("AutofillOptions.setAddressList", addresses);
517 base::ListValue credit_cards;
518 const std::vector<CreditCard*>& cards = personal_data_->GetCreditCards();
519 for (const CreditCard* card : cards) {
520 credit_cards.Append(CreditCardToDictionary(*card).release());
523 web_ui()->CallJavascriptFunction("AutofillOptions.setCreditCardList",
524 credit_cards);
527 #if defined(OS_MACOSX) && !defined(OS_IOS)
528 void AutofillOptionsHandler::AccessAddressBook(const base::ListValue* args) {
529 personal_data_->AccessAddressBook();
531 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
533 void AutofillOptionsHandler::RemoveData(const base::ListValue* args) {
534 DCHECK(IsPersonalDataLoaded());
536 std::string guid;
537 if (!args->GetString(0, &guid)) {
538 NOTREACHED();
539 return;
542 personal_data_->RemoveByGUID(guid);
545 void AutofillOptionsHandler::LoadAddressEditor(const base::ListValue* args) {
546 DCHECK(IsPersonalDataLoaded());
548 std::string guid;
549 if (!args->GetString(0, &guid)) {
550 NOTREACHED();
551 return;
554 AutofillProfile* profile = personal_data_->GetProfileByGUID(guid);
555 if (!profile) {
556 // There is a race where a user can click once on the close button and
557 // quickly click again on the list item before the item is removed (since
558 // the list is not updated until the model tells the list an item has been
559 // removed). This will activate the editor for a profile that has been
560 // removed. Do nothing in that case.
561 return;
564 base::DictionaryValue address;
565 AutofillProfileToDictionary(*profile, &address);
567 web_ui()->CallJavascriptFunction("AutofillOptions.editAddress", address);
570 void AutofillOptionsHandler::LoadAddressEditorComponents(
571 const base::ListValue* args) {
572 std::string country_code;
573 if (!args->GetString(0, &country_code)) {
574 NOTREACHED();
575 return;
578 base::DictionaryValue input;
579 scoped_ptr<base::ListValue> components(new base::ListValue);
580 std::string language_code;
581 GetAddressComponents(country_code, g_browser_process->GetApplicationLocale(),
582 components.get(), &language_code);
583 input.Set(kComponents, components.release());
584 input.SetString(kLanguageCode, language_code);
586 web_ui()->CallJavascriptFunction(
587 "AutofillEditAddressOverlay.loadAddressComponents", input);
590 void AutofillOptionsHandler::LoadCreditCardEditor(const base::ListValue* args) {
591 DCHECK(IsPersonalDataLoaded());
593 std::string guid;
594 if (!args->GetString(0, &guid)) {
595 NOTREACHED();
596 return;
599 CreditCard* credit_card = personal_data_->GetCreditCardByGUID(guid);
600 if (!credit_card) {
601 // There is a race where a user can click once on the close button and
602 // quickly click again on the list item before the item is removed (since
603 // the list is not updated until the model tells the list an item has been
604 // removed). This will activate the editor for a profile that has been
605 // removed. Do nothing in that case.
606 return;
609 base::DictionaryValue credit_card_data;
610 credit_card_data.SetString("guid", credit_card->guid());
611 credit_card_data.SetString(
612 "nameOnCard",
613 credit_card->GetRawInfo(autofill::CREDIT_CARD_NAME));
614 credit_card_data.SetString(
615 "creditCardNumber",
616 credit_card->GetRawInfo(autofill::CREDIT_CARD_NUMBER));
617 credit_card_data.SetString(
618 "expirationMonth",
619 credit_card->GetRawInfo(autofill::CREDIT_CARD_EXP_MONTH));
620 credit_card_data.SetString(
621 "expirationYear",
622 credit_card->GetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR));
624 web_ui()->CallJavascriptFunction("AutofillOptions.editCreditCard",
625 credit_card_data);
628 void AutofillOptionsHandler::SetAddress(const base::ListValue* args) {
629 if (!IsPersonalDataLoaded())
630 return;
632 int arg_counter = 0;
633 std::string guid;
634 if (!args->GetString(arg_counter++, &guid)) {
635 NOTREACHED();
636 return;
639 AutofillProfile profile(guid, kSettingsOrigin);
641 base::string16 value;
642 const base::ListValue* list_value;
643 if (args->GetList(arg_counter++, &list_value)) {
644 std::vector<base::string16> values;
645 ListValueToStringVector(*list_value, &values);
646 AutofillProfile* old_profile = personal_data_->GetProfileByGUID(guid);
647 profile.CopyAndUpdateNameList(values, old_profile,
648 g_browser_process->GetApplicationLocale());
651 if (args->GetString(arg_counter++, &value))
652 profile.SetRawInfo(autofill::COMPANY_NAME, value);
654 if (args->GetString(arg_counter++, &value))
655 profile.SetRawInfo(autofill::ADDRESS_HOME_STREET_ADDRESS, value);
657 if (args->GetString(arg_counter++, &value))
658 profile.SetRawInfo(autofill::ADDRESS_HOME_DEPENDENT_LOCALITY, value);
660 if (args->GetString(arg_counter++, &value))
661 profile.SetRawInfo(autofill::ADDRESS_HOME_CITY, value);
663 if (args->GetString(arg_counter++, &value))
664 profile.SetRawInfo(autofill::ADDRESS_HOME_STATE, value);
666 if (args->GetString(arg_counter++, &value))
667 profile.SetRawInfo(autofill::ADDRESS_HOME_ZIP, value);
669 if (args->GetString(arg_counter++, &value))
670 profile.SetRawInfo(autofill::ADDRESS_HOME_SORTING_CODE, value);
672 if (args->GetString(arg_counter++, &value))
673 profile.SetRawInfo(autofill::ADDRESS_HOME_COUNTRY, value);
675 if (args->GetList(arg_counter++, &list_value)) {
676 std::vector<base::string16> values;
677 ListValueToStringVector(*list_value, &values);
678 profile.SetRawMultiInfo(autofill::PHONE_HOME_WHOLE_NUMBER, values);
681 if (args->GetList(arg_counter++, &list_value)) {
682 std::vector<base::string16> values;
683 ListValueToStringVector(*list_value, &values);
684 profile.SetRawMultiInfo(autofill::EMAIL_ADDRESS, values);
687 if (args->GetString(arg_counter++, &value))
688 profile.set_language_code(base::UTF16ToUTF8(value));
690 if (!base::IsValidGUID(profile.guid())) {
691 profile.set_guid(base::GenerateGUID());
692 personal_data_->AddProfile(profile);
693 } else {
694 personal_data_->UpdateProfile(profile);
698 void AutofillOptionsHandler::SetCreditCard(const base::ListValue* args) {
699 if (!IsPersonalDataLoaded())
700 return;
702 std::string guid;
703 if (!args->GetString(0, &guid)) {
704 NOTREACHED();
705 return;
708 CreditCard credit_card(guid, kSettingsOrigin);
710 base::string16 value;
711 if (args->GetString(1, &value))
712 credit_card.SetRawInfo(autofill::CREDIT_CARD_NAME, value);
714 if (args->GetString(2, &value))
715 credit_card.SetRawInfo(autofill::CREDIT_CARD_NUMBER, value);
717 if (args->GetString(3, &value))
718 credit_card.SetRawInfo(autofill::CREDIT_CARD_EXP_MONTH, value);
720 if (args->GetString(4, &value))
721 credit_card.SetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR, value);
723 if (!base::IsValidGUID(credit_card.guid())) {
724 credit_card.set_guid(base::GenerateGUID());
725 personal_data_->AddCreditCard(credit_card);
726 } else {
727 personal_data_->UpdateCreditCard(credit_card);
731 void AutofillOptionsHandler::ValidatePhoneNumbers(const base::ListValue* args) {
732 if (!IsPersonalDataLoaded())
733 return;
735 scoped_ptr<base::ListValue> list_value = ValidatePhoneArguments(args);
737 web_ui()->CallJavascriptFunction(
738 "AutofillEditAddressOverlay.setValidatedPhoneNumbers", *list_value);
741 void AutofillOptionsHandler::RemaskServerCard(const base::ListValue* args) {
742 std::string guid;
743 if (!args->GetString(0, &guid)) {
744 NOTREACHED();
745 return;
748 personal_data_->ResetFullServerCard(guid);
751 bool AutofillOptionsHandler::IsPersonalDataLoaded() const {
752 return personal_data_ && personal_data_->IsDataLoaded();
755 // static
756 void AutofillOptionsHandler::AutofillProfileToDictionary(
757 const autofill::AutofillProfile& profile,
758 base::DictionaryValue* address) {
759 address->SetString("guid", profile.guid());
760 scoped_ptr<base::ListValue> list;
761 GetValueList(profile, autofill::NAME_FULL, &list);
762 address->Set(kFullNameField, list.release());
763 address->SetString(kCompanyNameField,
764 profile.GetRawInfo(autofill::COMPANY_NAME));
765 address->SetString(kAddressLineField,
766 profile.GetRawInfo(autofill::ADDRESS_HOME_STREET_ADDRESS));
767 address->SetString(kCityField,
768 profile.GetRawInfo(autofill::ADDRESS_HOME_CITY));
769 address->SetString(kStateField,
770 profile.GetRawInfo(autofill::ADDRESS_HOME_STATE));
771 address->SetString(
772 kDependentLocalityField,
773 profile.GetRawInfo(autofill::ADDRESS_HOME_DEPENDENT_LOCALITY));
774 address->SetString(kSortingCodeField,
775 profile.GetRawInfo(autofill::ADDRESS_HOME_SORTING_CODE));
776 address->SetString(kPostalCodeField,
777 profile.GetRawInfo(autofill::ADDRESS_HOME_ZIP));
778 address->SetString(kCountryField,
779 profile.GetRawInfo(autofill::ADDRESS_HOME_COUNTRY));
780 GetValueList(profile, autofill::PHONE_HOME_WHOLE_NUMBER, &list);
781 address->Set("phone", list.release());
782 GetValueList(profile, autofill::EMAIL_ADDRESS, &list);
783 address->Set("email", list.release());
784 address->SetString(kLanguageCode, profile.language_code());
786 scoped_ptr<base::ListValue> components(new base::ListValue);
787 GetAddressComponents(
788 base::UTF16ToUTF8(profile.GetRawInfo(autofill::ADDRESS_HOME_COUNTRY)),
789 profile.language_code(),
790 components.get(),
791 NULL);
792 address->Set(kComponents, components.release());
795 } // namespace options