1 // Copyright (c) 2011 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/logging.h"
10 #include "base/string16.h"
11 #include "base/string_number_conversions.h"
12 #include "base/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/autofill/autofill_country.h"
15 #include "chrome/browser/autofill/autofill_profile.h"
16 #include "chrome/browser/autofill/credit_card.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/webui/web_ui_util.h"
19 #include "chrome/common/guid.h"
20 #include "grit/generated_resources.h"
21 #include "grit/webkit_resources.h"
22 #include "ui/base/l10n/l10n_util.h"
23
24 namespace {
25
26 // Converts a credit card type to the appropriate resource ID of the CC icon.
CreditCardTypeToResourceID(const std::string & type)27 int CreditCardTypeToResourceID(const std::string& type) {
28 if (type == kAmericanExpressCard)
29 return IDR_AUTOFILL_CC_AMEX;
30 else if (type == kDinersCard)
31 return IDR_AUTOFILL_CC_DINERS;
32 else if (type == kDiscoverCard)
33 return IDR_AUTOFILL_CC_DISCOVER;
34 else if (type == kGenericCard)
35 return IDR_AUTOFILL_CC_GENERIC;
36 else if (type == kJCBCard)
37 return IDR_AUTOFILL_CC_JCB;
38 else if (type == kMasterCard)
39 return IDR_AUTOFILL_CC_MASTERCARD;
40 else if (type == kSoloCard)
41 return IDR_AUTOFILL_CC_SOLO;
42 else if (type == kVisaCard)
43 return IDR_AUTOFILL_CC_VISA;
44
45 NOTREACHED();
46 return 0;
47 }
48
49 // Converts a credit card type to the appropriate localized card type.
LocalizedCreditCardType(const std::string & type)50 string16 LocalizedCreditCardType(const std::string& type) {
51 if (type == kAmericanExpressCard)
52 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_AMEX);
53 else if (type == kDinersCard)
54 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DINERS);
55 else if (type == kDiscoverCard)
56 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_DISCOVER);
57 else if (type == kGenericCard)
58 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_GENERIC);
59 else if (type == kJCBCard)
60 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_JCB);
61 else if (type == kMasterCard)
62 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_MASTERCARD);
63 else if (type == kSoloCard)
64 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_SOLO);
65 else if (type == kVisaCard)
66 return l10n_util::GetStringUTF16(IDS_AUTOFILL_CC_VISA);
67
68 NOTREACHED();
69 return string16();
70 }
71
72 // Returns a dictionary that maps country codes to data for the country.
GetCountryData()73 DictionaryValue* GetCountryData() {
74 std::string app_locale = AutofillCountry::ApplicationLocale();
75 std::vector<std::string> country_codes;
76 AutofillCountry::GetAvailableCountries(&country_codes);
77
78 DictionaryValue* country_data = new DictionaryValue();
79 for (size_t i = 0; i < country_codes.size(); ++i) {
80 const AutofillCountry country(country_codes[i], app_locale);
81
82 DictionaryValue* details = new DictionaryValue();
83 details->SetString("name", country.name());
84 details->SetString("postalCodeLabel", country.postal_code_label());
85 details->SetString("stateLabel", country.state_label());
86
87 country_data->Set(country.country_code(), details);
88 }
89
90 return country_data;
91 }
92
93 // Get the multi-valued element for |type| and return it in |ListValue| form.
GetValueList(const AutofillProfile & profile,AutofillFieldType type,scoped_ptr<ListValue> * list)94 void GetValueList(const AutofillProfile& profile,
95 AutofillFieldType type,
96 scoped_ptr<ListValue>* list) {
97 std::vector<string16> values;
98 profile.GetMultiInfo(type, &values);
99 list->reset(new ListValue);
100 for (size_t i = 0; i < values.size(); ++i) {
101 (*list)->Set(i, Value::CreateStringValue(values[i]));
102 }
103 }
104
105 // Set the multi-valued element for |type| from input |list| values.
SetValueList(const ListValue * list,AutofillFieldType type,AutofillProfile * profile)106 void SetValueList(const ListValue* list,
107 AutofillFieldType type,
108 AutofillProfile* profile) {
109 std::vector<string16> values(list->GetSize());
110 for (size_t i = 0; i < list->GetSize(); ++i) {
111 string16 value;
112 if (list->GetString(i, &value))
113 values[i] = value;
114 }
115 profile->SetMultiInfo(type, values);
116 }
117
118 } // namespace
119
AutofillOptionsHandler()120 AutofillOptionsHandler::AutofillOptionsHandler()
121 : personal_data_(NULL) {
122 }
123
~AutofillOptionsHandler()124 AutofillOptionsHandler::~AutofillOptionsHandler() {
125 if (personal_data_)
126 personal_data_->RemoveObserver(this);
127 }
128
129 /////////////////////////////////////////////////////////////////////////////
130 // OptionsPageUIHandler implementation:
GetLocalizedValues(DictionaryValue * localized_strings)131 void AutofillOptionsHandler::GetLocalizedValues(
132 DictionaryValue* localized_strings) {
133 DCHECK(localized_strings);
134
135 static OptionsStringResource resources[] = {
136 { "autofillAddresses", IDS_AUTOFILL_ADDRESSES_GROUP_NAME },
137 { "autofillCreditCards", IDS_AUTOFILL_CREDITCARDS_GROUP_NAME },
138 { "autofillAddAddress", IDS_AUTOFILL_ADD_ADDRESS_BUTTON },
139 { "autofillAddCreditCard", IDS_AUTOFILL_ADD_CREDITCARD_BUTTON },
140 { "helpButton", IDS_AUTOFILL_HELP_LABEL },
141 { "addAddressTitle", IDS_AUTOFILL_ADD_ADDRESS_CAPTION },
142 { "editAddressTitle", IDS_AUTOFILL_EDIT_ADDRESS_CAPTION },
143 { "addCreditCardTitle", IDS_AUTOFILL_ADD_CREDITCARD_CAPTION },
144 { "editCreditCardTitle", IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION },
145 #if defined(OS_MACOSX)
146 { "auxiliaryProfilesEnabled", IDS_AUTOFILL_USE_MAC_ADDRESS_BOOK },
147 #endif // defined(OS_MACOSX)
148 };
149
150 RegisterStrings(localized_strings, resources, arraysize(resources));
151 RegisterTitle(localized_strings, "autofillOptionsPage",
152 IDS_AUTOFILL_OPTIONS_TITLE);
153
154 SetAddressOverlayStrings(localized_strings);
155 SetCreditCardOverlayStrings(localized_strings);
156 }
157
Initialize()158 void AutofillOptionsHandler::Initialize() {
159 personal_data_ = web_ui_->GetProfile()->GetPersonalDataManager();
160 personal_data_->SetObserver(this);
161
162 LoadAutofillData();
163 }
164
RegisterMessages()165 void AutofillOptionsHandler::RegisterMessages() {
166 web_ui_->RegisterMessageCallback(
167 "removeAddress",
168 NewCallback(this, &AutofillOptionsHandler::RemoveAddress));
169 web_ui_->RegisterMessageCallback(
170 "removeCreditCard",
171 NewCallback(this, &AutofillOptionsHandler::RemoveCreditCard));
172 web_ui_->RegisterMessageCallback(
173 "loadAddressEditor",
174 NewCallback(this, &AutofillOptionsHandler::LoadAddressEditor));
175 web_ui_->RegisterMessageCallback(
176 "loadCreditCardEditor",
177 NewCallback(this, &AutofillOptionsHandler::LoadCreditCardEditor));
178 web_ui_->RegisterMessageCallback(
179 "setAddress",
180 NewCallback(this, &AutofillOptionsHandler::SetAddress));
181 web_ui_->RegisterMessageCallback(
182 "setCreditCard",
183 NewCallback(this, &AutofillOptionsHandler::SetCreditCard));
184 }
185
186 /////////////////////////////////////////////////////////////////////////////
187 // PersonalDataManager::Observer implementation:
OnPersonalDataLoaded()188 void AutofillOptionsHandler::OnPersonalDataLoaded() {
189 LoadAutofillData();
190 }
191
OnPersonalDataChanged()192 void AutofillOptionsHandler::OnPersonalDataChanged() {
193 LoadAutofillData();
194 }
195
SetAddressOverlayStrings(DictionaryValue * localized_strings)196 void AutofillOptionsHandler::SetAddressOverlayStrings(
197 DictionaryValue* localized_strings) {
198 localized_strings->SetString("autofillEditAddressTitle",
199 l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_ADDRESS_CAPTION));
200 localized_strings->SetString("fullNameLabel",
201 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_FULL_NAME));
202 localized_strings->SetString("companyNameLabel",
203 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_COMPANY_NAME));
204 localized_strings->SetString("addrLine1Label",
205 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADDRESS_LINE_1));
206 localized_strings->SetString("addrLine2Label",
207 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADDRESS_LINE_2));
208 localized_strings->SetString("cityLabel",
209 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_CITY));
210 localized_strings->SetString("countryLabel",
211 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_COUNTRY));
212 localized_strings->SetString("phoneLabel",
213 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PHONE));
214 localized_strings->SetString("faxLabel",
215 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_FAX));
216 localized_strings->SetString("emailLabel",
217 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_EMAIL));
218 localized_strings->SetString("addNewNamePlaceholder",
219 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_NEW_NAME));
220 localized_strings->SetString("addNewPhonePlaceholder",
221 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_NEW_PHONE));
222 localized_strings->SetString("addNewFaxPlaceholder",
223 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_NEW_FAX));
224 localized_strings->SetString("addNewEmailPlaceholder",
225 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_ADD_NEW_EMAIL));
226
227 std::string app_locale = AutofillCountry::ApplicationLocale();
228 std::string default_country_code =
229 AutofillCountry::CountryCodeForLocale(app_locale);
230 localized_strings->SetString("defaultCountryCode", default_country_code);
231 localized_strings->Set("autofillCountryData", GetCountryData());
232 }
233
SetCreditCardOverlayStrings(DictionaryValue * localized_strings)234 void AutofillOptionsHandler::SetCreditCardOverlayStrings(
235 DictionaryValue* localized_strings) {
236 localized_strings->SetString("autofillEditCreditCardTitle",
237 l10n_util::GetStringUTF16(IDS_AUTOFILL_EDIT_CREDITCARD_CAPTION));
238 localized_strings->SetString("nameOnCardLabel",
239 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_NAME_ON_CARD));
240 localized_strings->SetString("creditCardNumberLabel",
241 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_CREDIT_CARD_NUMBER));
242 localized_strings->SetString("creditCardExpirationDateLabel",
243 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_EXPIRATION_DATE));
244 }
245
LoadAutofillData()246 void AutofillOptionsHandler::LoadAutofillData() {
247 if (!personal_data_->IsDataLoaded())
248 return;
249
250 ListValue addresses;
251 for (std::vector<AutofillProfile*>::const_iterator i =
252 personal_data_->web_profiles().begin();
253 i != personal_data_->web_profiles().end(); ++i) {
254 ListValue* entry = new ListValue();
255 entry->Append(new StringValue((*i)->guid()));
256 entry->Append(new StringValue((*i)->Label()));
257 addresses.Append(entry);
258 }
259
260 web_ui_->CallJavascriptFunction("AutofillOptions.setAddressList", addresses);
261
262 ListValue credit_cards;
263 for (std::vector<CreditCard*>::const_iterator i =
264 personal_data_->credit_cards().begin();
265 i != personal_data_->credit_cards().end(); ++i) {
266 ListValue* entry = new ListValue();
267 entry->Append(new StringValue((*i)->guid()));
268 entry->Append(new StringValue((*i)->Label()));
269 int res = CreditCardTypeToResourceID((*i)->type());
270 entry->Append(
271 new StringValue(web_ui_util::GetImageDataUrlFromResource(res)));
272 entry->Append(new StringValue(LocalizedCreditCardType((*i)->type())));
273 credit_cards.Append(entry);
274 }
275
276 web_ui_->CallJavascriptFunction("AutofillOptions.setCreditCardList",
277 credit_cards);
278 }
279
RemoveAddress(const ListValue * args)280 void AutofillOptionsHandler::RemoveAddress(const ListValue* args) {
281 DCHECK(personal_data_->IsDataLoaded());
282
283 std::string guid;
284 if (!args->GetString(0, &guid)) {
285 NOTREACHED();
286 return;
287 }
288
289 personal_data_->RemoveProfile(guid);
290 }
291
RemoveCreditCard(const ListValue * args)292 void AutofillOptionsHandler::RemoveCreditCard(const ListValue* args) {
293 DCHECK(personal_data_->IsDataLoaded());
294
295 std::string guid;
296 if (!args->GetString(0, &guid)) {
297 NOTREACHED();
298 return;
299 }
300
301 personal_data_->RemoveCreditCard(guid);
302 }
303
LoadAddressEditor(const ListValue * args)304 void AutofillOptionsHandler::LoadAddressEditor(const ListValue* args) {
305 DCHECK(personal_data_->IsDataLoaded());
306
307 std::string guid;
308 if (!args->GetString(0, &guid)) {
309 NOTREACHED();
310 return;
311 }
312
313 AutofillProfile* profile = personal_data_->GetProfileByGUID(guid);
314 if (!profile) {
315 // There is a race where a user can click once on the close button and
316 // quickly click again on the list item before the item is removed (since
317 // the list is not updated until the model tells the list an item has been
318 // removed). This will activate the editor for a profile that has been
319 // removed. Do nothing in that case.
320 return;
321 }
322
323 DictionaryValue address;
324 address.SetString("guid", profile->guid());
325 scoped_ptr<ListValue> list;
326 GetValueList(*profile, NAME_FULL, &list);
327 address.Set("fullName", list.release());
328 address.SetString("companyName", profile->GetInfo(COMPANY_NAME));
329 address.SetString("addrLine1", profile->GetInfo(ADDRESS_HOME_LINE1));
330 address.SetString("addrLine2", profile->GetInfo(ADDRESS_HOME_LINE2));
331 address.SetString("city", profile->GetInfo(ADDRESS_HOME_CITY));
332 address.SetString("state", profile->GetInfo(ADDRESS_HOME_STATE));
333 address.SetString("postalCode", profile->GetInfo(ADDRESS_HOME_ZIP));
334 address.SetString("country", profile->CountryCode());
335 GetValueList(*profile, PHONE_HOME_WHOLE_NUMBER, &list);
336 address.Set("phone", list.release());
337 GetValueList(*profile, PHONE_FAX_WHOLE_NUMBER, &list);
338 address.Set("fax", list.release());
339 GetValueList(*profile, EMAIL_ADDRESS, &list);
340 address.Set("email", list.release());
341
342 web_ui_->CallJavascriptFunction("AutofillOptions.editAddress", address);
343 }
344
LoadCreditCardEditor(const ListValue * args)345 void AutofillOptionsHandler::LoadCreditCardEditor(const ListValue* args) {
346 DCHECK(personal_data_->IsDataLoaded());
347
348 std::string guid;
349 if (!args->GetString(0, &guid)) {
350 NOTREACHED();
351 return;
352 }
353
354 CreditCard* credit_card = personal_data_->GetCreditCardByGUID(guid);
355 if (!credit_card) {
356 // There is a race where a user can click once on the close button and
357 // quickly click again on the list item before the item is removed (since
358 // the list is not updated until the model tells the list an item has been
359 // removed). This will activate the editor for a profile that has been
360 // removed. Do nothing in that case.
361 return;
362 }
363
364 DictionaryValue credit_card_data;
365 credit_card_data.SetString("guid", credit_card->guid());
366 credit_card_data.SetString("nameOnCard",
367 credit_card->GetInfo(CREDIT_CARD_NAME));
368 credit_card_data.SetString("creditCardNumber",
369 credit_card->GetInfo(CREDIT_CARD_NUMBER));
370 credit_card_data.SetString("expirationMonth",
371 credit_card->GetInfo(CREDIT_CARD_EXP_MONTH));
372 credit_card_data.SetString(
373 "expirationYear",
374 credit_card->GetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR));
375
376 web_ui_->CallJavascriptFunction("AutofillOptions.editCreditCard",
377 credit_card_data);
378 }
379
SetAddress(const ListValue * args)380 void AutofillOptionsHandler::SetAddress(const ListValue* args) {
381 if (!personal_data_->IsDataLoaded())
382 return;
383
384 std::string guid;
385 if (!args->GetString(0, &guid)) {
386 NOTREACHED();
387 return;
388 }
389
390 AutofillProfile profile(guid);
391
392 std::string country_code;
393 string16 value;
394 ListValue* list_value;
395 if (args->GetList(1, &list_value))
396 SetValueList(list_value, NAME_FULL, &profile);
397 if (args->GetString(2, &value))
398 profile.SetInfo(COMPANY_NAME, value);
399 if (args->GetString(3, &value))
400 profile.SetInfo(ADDRESS_HOME_LINE1, value);
401 if (args->GetString(4, &value))
402 profile.SetInfo(ADDRESS_HOME_LINE2, value);
403 if (args->GetString(5, &value))
404 profile.SetInfo(ADDRESS_HOME_CITY, value);
405 if (args->GetString(6, &value))
406 profile.SetInfo(ADDRESS_HOME_STATE, value);
407 if (args->GetString(7, &value))
408 profile.SetInfo(ADDRESS_HOME_ZIP, value);
409 if (args->GetString(8, &country_code))
410 profile.SetCountryCode(country_code);
411 if (args->GetList(9, &list_value))
412 SetValueList(list_value, PHONE_HOME_WHOLE_NUMBER, &profile);
413 if (args->GetList(10, &list_value))
414 SetValueList(list_value, PHONE_FAX_WHOLE_NUMBER, &profile);
415 if (args->GetList(11, &list_value))
416 SetValueList(list_value, EMAIL_ADDRESS, &profile);
417
418 if (!guid::IsValidGUID(profile.guid())) {
419 profile.set_guid(guid::GenerateGUID());
420 personal_data_->AddProfile(profile);
421 } else {
422 personal_data_->UpdateProfile(profile);
423 }
424 }
425
SetCreditCard(const ListValue * args)426 void AutofillOptionsHandler::SetCreditCard(const ListValue* args) {
427 if (!personal_data_->IsDataLoaded())
428 return;
429
430 std::string guid;
431 if (!args->GetString(0, &guid)) {
432 NOTREACHED();
433 return;
434 }
435
436 CreditCard credit_card(guid);
437
438 string16 value;
439 if (args->GetString(1, &value))
440 credit_card.SetInfo(CREDIT_CARD_NAME, value);
441 if (args->GetString(2, &value))
442 credit_card.SetInfo(CREDIT_CARD_NUMBER, value);
443 if (args->GetString(3, &value))
444 credit_card.SetInfo(CREDIT_CARD_EXP_MONTH, value);
445 if (args->GetString(4, &value))
446 credit_card.SetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, value);
447
448 if (!guid::IsValidGUID(credit_card.guid())) {
449 credit_card.set_guid(guid::GenerateGUID());
450 personal_data_->AddCreditCard(credit_card);
451 } else {
452 personal_data_->UpdateCreditCard(credit_card);
453 }
454 }
455