autofill_dialog_common.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2013 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/autofill/autofill_dialog_common.h"
6
7#include "base/strings/utf_string_conversions.h"
8#include "chrome/browser/browser_process.h"
9#include "components/autofill/core/browser/autofill_country.h"
10#include "components/autofill/core/browser/autofill_field.h"
11#include "components/autofill/core/browser/autofill_type.h"
12#include "grit/chromium_strings.h"
13#include "grit/component_strings.h"
14#include "grit/generated_resources.h"
15#include "grit/theme_resources.h"
16#include "grit/webkit_resources.h"
17#include "ui/base/l10n/l10n_util.h"
18
19#if !defined(OS_ANDROID)
20#include "chrome/browser/ui/autofill/autofill_dialog_i18n_input.h"
21#endif  // !defined(OS_ANDROID)
22
23namespace autofill {
24namespace common {
25
26// Returns true if |input| should be shown when |field_type| has been requested.
27bool ServerTypeMatchesFieldType(ServerFieldType type,
28                                const AutofillType& field_type) {
29  // If any credit card expiration info is asked for, show both month and year
30  // inputs.
31  ServerFieldType server_type = field_type.GetStorableType();
32  if (server_type == CREDIT_CARD_EXP_4_DIGIT_YEAR ||
33      server_type == CREDIT_CARD_EXP_2_DIGIT_YEAR ||
34      server_type == CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR ||
35      server_type == CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR ||
36      server_type == CREDIT_CARD_EXP_MONTH) {
37    return type == CREDIT_CARD_EXP_4_DIGIT_YEAR ||
38           type == CREDIT_CARD_EXP_MONTH;
39  }
40
41  if (server_type == CREDIT_CARD_TYPE)
42    return type == CREDIT_CARD_NUMBER;
43
44  // Check the groups to distinguish billing types from shipping ones.
45  AutofillType autofill_type = AutofillType(type);
46  if (autofill_type.group() != field_type.group())
47    return false;
48
49  // Street address (all lines) is matched to the first input address line.
50  if (server_type == ADDRESS_HOME_STREET_ADDRESS)
51    return autofill_type.GetStorableType() == ADDRESS_HOME_LINE1;
52
53  return autofill_type.GetStorableType() == server_type;
54}
55
56// Returns true if |input| in the given |section| should be used for a
57// site-requested |field|.
58bool ServerTypeMatchesField(DialogSection section,
59                            ServerFieldType type,
60                            const AutofillField& field) {
61  AutofillType field_type = field.Type();
62
63  // The credit card name is filled from the billing section's data.
64  if (field_type.GetStorableType() == CREDIT_CARD_NAME &&
65      (section == SECTION_BILLING || section == SECTION_CC_BILLING)) {
66    return type == NAME_BILLING_FULL;
67  }
68
69  return ServerTypeMatchesFieldType(type, field_type);
70}
71
72bool IsCreditCardType(ServerFieldType type) {
73  return AutofillType(type).group() == CREDIT_CARD;
74}
75
76// Constructs |inputs| from template data.
77void BuildInputs(const DetailInput* input_template,
78                 size_t template_size,
79                 DetailInputs* inputs) {
80  for (size_t i = 0; i < template_size; ++i) {
81    const DetailInput* input = &input_template[i];
82    inputs->push_back(*input);
83  }
84}
85
86bool IsI18nInputEnabled() {
87#if defined(OS_ANDROID)
88  return false;
89#else
90  return i18ninput::Enabled();
91#endif
92}
93
94void BuildI18nAddressInputs(AddressType address_type,
95                            const std::string& country_code,
96                            DetailInputs* inputs) {
97#if defined(OS_ANDROID)
98  NOTREACHED();
99#else
100  i18ninput::BuildAddressInputs(address_type, country_code, inputs);
101#endif
102}
103
104// Constructs |inputs| from template data for a given |dialog_section|.
105void BuildInputsForSection(DialogSection dialog_section,
106                           const std::string& country_code,
107                           DetailInputs* inputs) {
108  using l10n_util::GetStringUTF16;
109
110  const DetailInput kCCInputs[] = {
111    { DetailInput::LONG,
112      CREDIT_CARD_NUMBER,
113      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARD_NUMBER) },
114    { DetailInput::SHORT,
115      CREDIT_CARD_EXP_MONTH,
116      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_MONTH) },
117    { DetailInput::SHORT,
118      CREDIT_CARD_EXP_4_DIGIT_YEAR,
119      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_YEAR) },
120    { DetailInput::SHORT_EOL,
121      CREDIT_CARD_VERIFICATION_CODE,
122      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC),
123      1.5 },
124  };
125
126  const DetailInput kBillingInputs[] = {
127    { DetailInput::LONG,
128      NAME_BILLING_FULL,
129      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CARDHOLDER_NAME) },
130    { DetailInput::LONG,
131      ADDRESS_BILLING_LINE1,
132      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1) },
133    { DetailInput::LONG,
134      ADDRESS_BILLING_LINE2,
135      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2) },
136    { DetailInput::LONG,
137      ADDRESS_BILLING_CITY,
138      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY) },
139    { DetailInput::SHORT,
140      ADDRESS_BILLING_STATE,
141      GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_STATE) },
142    { DetailInput::SHORT_EOL,
143      ADDRESS_BILLING_ZIP,
144      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE) },
145    // We don't allow the user to change the country: http://crbug.com/247518
146    { DetailInput::NONE, ADDRESS_BILLING_COUNTRY },
147  };
148
149  const DetailInput kBillingPhoneInputs[] = {
150    { DetailInput::LONG,
151      PHONE_BILLING_WHOLE_NUMBER,
152      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER) },
153  };
154
155  const DetailInput kEmailInputs[] = {
156    { DetailInput::LONG,
157      EMAIL_ADDRESS,
158      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_EMAIL) },
159  };
160
161  const DetailInput kShippingInputs[] = {
162    { DetailInput::LONG,
163      NAME_FULL,
164      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESSEE_NAME) },
165    { DetailInput::LONG,
166      ADDRESS_HOME_LINE1,
167      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_1) },
168    { DetailInput::LONG,
169      ADDRESS_HOME_LINE2,
170      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_ADDRESS_LINE_2) },
171    { DetailInput::LONG,
172      ADDRESS_HOME_CITY,
173      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_LOCALITY) },
174    { DetailInput::SHORT,
175      ADDRESS_HOME_STATE,
176      GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_STATE) },
177    { DetailInput::SHORT_EOL,
178      ADDRESS_HOME_ZIP,
179      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_POSTAL_CODE) },
180    { DetailInput::NONE, ADDRESS_HOME_COUNTRY },
181  };
182
183  const DetailInput kShippingPhoneInputs[] = {
184    { DetailInput::LONG,
185      PHONE_HOME_WHOLE_NUMBER,
186      GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_PHONE_NUMBER) },
187  };
188
189  switch (dialog_section) {
190    case SECTION_CC:
191      BuildInputs(kCCInputs, arraysize(kCCInputs), inputs);
192      break;
193
194    case SECTION_BILLING:
195      if (IsI18nInputEnabled())
196        BuildI18nAddressInputs(ADDRESS_TYPE_BILLING, country_code, inputs);
197      else
198        BuildInputs(kBillingInputs, arraysize(kBillingInputs), inputs);
199
200      BuildInputs(kBillingPhoneInputs, arraysize(kBillingPhoneInputs), inputs);
201      BuildInputs(kEmailInputs, arraysize(kEmailInputs), inputs);
202      break;
203
204    case SECTION_CC_BILLING:
205      BuildInputs(kCCInputs, arraysize(kCCInputs), inputs);
206
207      if (IsI18nInputEnabled()) {
208        // Wallet only supports US billing addresses.
209        const std::string hardcoded_country_code = "US";
210        BuildI18nAddressInputs(ADDRESS_TYPE_BILLING,
211                               hardcoded_country_code,
212                               inputs);
213        DCHECK_EQ(inputs->back().type, ADDRESS_BILLING_COUNTRY);
214        inputs->back().length = DetailInput::NONE;
215        inputs->back().initial_value =
216            base::ASCIIToUTF16(hardcoded_country_code);
217      } else {
218        BuildInputs(kBillingInputs, arraysize(kBillingInputs), inputs);
219      }
220
221      BuildInputs(kBillingPhoneInputs, arraysize(kBillingPhoneInputs), inputs);
222      break;
223
224    case SECTION_SHIPPING:
225      if (IsI18nInputEnabled())
226        BuildI18nAddressInputs(ADDRESS_TYPE_SHIPPING, country_code, inputs);
227      else
228        BuildInputs(kShippingInputs, arraysize(kShippingInputs), inputs);
229
230      BuildInputs(
231          kShippingPhoneInputs, arraysize(kShippingPhoneInputs), inputs);
232      break;
233  }
234}
235
236AutofillMetrics::DialogUiEvent DialogSectionToUiItemAddedEvent(
237    DialogSection section) {
238  switch (section) {
239    case SECTION_BILLING:
240      return AutofillMetrics::DIALOG_UI_BILLING_ITEM_ADDED;
241
242    case SECTION_CC_BILLING:
243      return AutofillMetrics::DIALOG_UI_CC_BILLING_ITEM_ADDED;
244
245    case SECTION_SHIPPING:
246      return AutofillMetrics::DIALOG_UI_SHIPPING_ITEM_ADDED;
247
248    case SECTION_CC:
249      return AutofillMetrics::DIALOG_UI_CC_ITEM_ADDED;
250  }
251
252  NOTREACHED();
253  return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
254}
255
256AutofillMetrics::DialogUiEvent DialogSectionToUiSelectionChangedEvent(
257    DialogSection section) {
258  switch (section) {
259    case SECTION_BILLING:
260      return AutofillMetrics::DIALOG_UI_BILLING_SELECTED_SUGGESTION_CHANGED;
261
262    case SECTION_CC_BILLING:
263      return AutofillMetrics::DIALOG_UI_CC_BILLING_SELECTED_SUGGESTION_CHANGED;
264
265    case SECTION_SHIPPING:
266      return AutofillMetrics::DIALOG_UI_SHIPPING_SELECTED_SUGGESTION_CHANGED;
267
268    case SECTION_CC:
269      return AutofillMetrics::DIALOG_UI_CC_SELECTED_SUGGESTION_CHANGED;
270  }
271
272  NOTREACHED();
273  return AutofillMetrics::NUM_DIALOG_UI_EVENTS;
274}
275
276base::string16 GetHardcodedValueForType(ServerFieldType type) {
277  // TODO(dbeam): remove this entire function when i18n inputs are the default.
278  if (IsI18nInputEnabled())
279    return base::string16();
280
281  if (AutofillType(type).GetStorableType() == ADDRESS_HOME_COUNTRY) {
282    AutofillCountry country("US", g_browser_process->GetApplicationLocale());
283    return country.name();
284  }
285
286  return base::string16();
287}
288
289std::vector<ServerFieldType> TypesFromInputs(const DetailInputs& inputs) {
290  std::vector<ServerFieldType> types;
291  for (size_t i = 0; i < inputs.size(); ++i) {
292    types.push_back(inputs[i].type);
293  }
294  return types;
295}
296
297}  // namespace common
298}  // namespace autofill
299