• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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