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