1 // Copyright 2014 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/autofill/autofill_dialog_i18n_input.h"
7 #include "base/strings/string_split.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/browser_process.h"
10 #include "components/autofill/core/browser/autofill_profile.h"
11 #include "components/autofill/core/browser/credit_card.h"
12 #include "components/autofill/core/browser/field_types.h"
13 #include "grit/component_strings.h"
14 #include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h"
15 #include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_field.h"
16 #include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_ui.h"
17 #include "third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_ui_component.h"
18 #include "ui/base/l10n/l10n_util.h"
25 using base::UTF16ToUTF8
;
26 using ::i18n::addressinput::AddressData
;
27 using ::i18n::addressinput::AddressField
;
28 using ::i18n::addressinput::AddressUiComponent
;
30 DetailInput::Length
LengthFromHint(AddressUiComponent::LengthHint hint
) {
31 if (hint
== AddressUiComponent::HINT_SHORT
)
32 return DetailInput::SHORT
;
33 DCHECK_EQ(hint
, AddressUiComponent::HINT_LONG
);
34 return DetailInput::LONG
;
39 void BuildAddressInputs(common::AddressType address_type
,
40 const std::string
& country_code
,
41 DetailInputs
* inputs
) {
42 // TODO(rouslan): Store the language code for the autofill profile.
43 // http://crbug.com/354955
44 std::vector
<AddressUiComponent
> components(
45 ::i18n::addressinput::BuildComponents(
46 country_code
, g_browser_process
->GetApplicationLocale(), NULL
));
48 const bool billing
= address_type
== common::ADDRESS_TYPE_BILLING
;
50 for (size_t i
= 0; i
< components
.size(); ++i
) {
51 const AddressUiComponent
& component
= components
[i
];
52 if (component
.field
== ::i18n::addressinput::ORGANIZATION
) {
53 // TODO(dbeam): figure out when we actually need this.
57 ServerFieldType server_type
= TypeForField(component
.field
, address_type
);
58 DetailInput::Length length
= LengthFromHint(component
.length_hint
);
59 base::string16 placeholder
= l10n_util::GetStringUTF16(component
.name_id
);
60 DetailInput input
= { length
, server_type
, placeholder
};
61 inputs
->push_back(input
);
63 #if defined(OS_MACOSX) || defined(OS_ANDROID)
64 if (component
.field
== ::i18n::addressinput::STREET_ADDRESS
&&
65 component
.length_hint
== AddressUiComponent::HINT_LONG
) {
66 // TODO(dbeam): support more than 2 address lines. http://crbug.com/324889
67 ServerFieldType server_type
=
68 billing
? ADDRESS_BILLING_LINE2
: ADDRESS_HOME_LINE2
;
69 base::string16 placeholder
= l10n_util::GetStringUTF16(component
.name_id
);
70 DetailInput input
= { length
, server_type
, placeholder
};
71 inputs
->push_back(input
);
76 ServerFieldType server_type
=
77 billing
? ADDRESS_BILLING_COUNTRY
: ADDRESS_HOME_COUNTRY
;
78 base::string16 placeholder_text
=
79 l10n_util::GetStringUTF16(IDS_AUTOFILL_FIELD_LABEL_COUNTRY
);
80 DetailInput input
= { DetailInput::LONG
, server_type
, placeholder_text
};
81 inputs
->push_back(input
);
84 bool CardHasCompleteAndVerifiedData(const CreditCard
& card
) {
85 if (!card
.IsVerified())
88 const ServerFieldType required_fields
[] = {
90 CREDIT_CARD_EXP_MONTH
,
91 CREDIT_CARD_EXP_4_DIGIT_YEAR
,
94 for (size_t i
= 0; i
< arraysize(required_fields
); ++i
) {
95 if (card
.GetRawInfo(required_fields
[i
]).empty())
102 bool AddressHasCompleteAndVerifiedData(const AutofillProfile
& profile
) {
103 if (!profile
.IsVerified())
106 base::string16 country_code
= profile
.GetRawInfo(ADDRESS_HOME_COUNTRY
);
107 if (country_code
.empty())
110 std::vector
<AddressField
> required_fields
=
111 ::i18n::addressinput::GetRequiredFields(base::UTF16ToUTF8(country_code
));
113 for (size_t i
= 0; i
< required_fields
.size(); ++i
) {
114 ServerFieldType type
=
115 TypeForField(required_fields
[i
], common::ADDRESS_TYPE_SHIPPING
);
116 if (profile
.GetRawInfo(type
).empty())
120 const ServerFieldType more_required_fields
[] = {
122 PHONE_HOME_WHOLE_NUMBER
125 for (size_t i
= 0; i
< arraysize(more_required_fields
); ++i
) {
126 if (profile
.GetRawInfo(more_required_fields
[i
]).empty())
133 ServerFieldType
TypeForField(AddressField address_field
,
134 common::AddressType address_type
) {
135 bool billing
= address_type
== common::ADDRESS_TYPE_BILLING
;
136 switch (address_field
) {
137 case ::i18n::addressinput::COUNTRY
:
138 return billing
? ADDRESS_BILLING_COUNTRY
: ADDRESS_HOME_COUNTRY
;
139 case ::i18n::addressinput::ADMIN_AREA
:
140 return billing
? ADDRESS_BILLING_STATE
: ADDRESS_HOME_STATE
;
141 case ::i18n::addressinput::LOCALITY
:
142 return billing
? ADDRESS_BILLING_CITY
: ADDRESS_HOME_CITY
;
143 case ::i18n::addressinput::DEPENDENT_LOCALITY
:
144 return billing
? ADDRESS_BILLING_DEPENDENT_LOCALITY
:
145 ADDRESS_HOME_DEPENDENT_LOCALITY
;
146 case ::i18n::addressinput::POSTAL_CODE
:
147 return billing
? ADDRESS_BILLING_ZIP
: ADDRESS_HOME_ZIP
;
148 case ::i18n::addressinput::SORTING_CODE
:
149 return billing
? ADDRESS_BILLING_SORTING_CODE
: ADDRESS_HOME_SORTING_CODE
;
150 #if defined(OS_MACOSX) || defined(OS_ANDROID)
151 case ::i18n::addressinput::STREET_ADDRESS
:
152 return billing
? ADDRESS_BILLING_LINE1
: ADDRESS_HOME_LINE1
;
154 case ::i18n::addressinput::STREET_ADDRESS
:
155 return billing
? ADDRESS_BILLING_STREET_ADDRESS
:
156 ADDRESS_HOME_STREET_ADDRESS
;
158 case ::i18n::addressinput::RECIPIENT
:
159 return billing
? NAME_BILLING_FULL
: NAME_FULL
;
160 case ::i18n::addressinput::ORGANIZATION
:
167 bool FieldForType(ServerFieldType server_type
,
168 ::i18n::addressinput::AddressField
* field
) {
169 switch (server_type
) {
170 case ADDRESS_BILLING_COUNTRY
:
171 case ADDRESS_HOME_COUNTRY
:
173 *field
= ::i18n::addressinput::COUNTRY
;
175 case ADDRESS_BILLING_STATE
:
176 case ADDRESS_HOME_STATE
:
178 *field
= ::i18n::addressinput::ADMIN_AREA
;
180 case ADDRESS_BILLING_CITY
:
181 case ADDRESS_HOME_CITY
:
183 *field
= ::i18n::addressinput::LOCALITY
;
185 case ADDRESS_BILLING_DEPENDENT_LOCALITY
:
186 case ADDRESS_HOME_DEPENDENT_LOCALITY
:
188 *field
= ::i18n::addressinput::DEPENDENT_LOCALITY
;
190 case ADDRESS_BILLING_SORTING_CODE
:
191 case ADDRESS_HOME_SORTING_CODE
:
193 *field
= ::i18n::addressinput::SORTING_CODE
;
195 case ADDRESS_BILLING_ZIP
:
196 case ADDRESS_HOME_ZIP
:
198 *field
= ::i18n::addressinput::POSTAL_CODE
;
200 case ADDRESS_BILLING_STREET_ADDRESS
:
201 case ADDRESS_BILLING_LINE1
:
202 case ADDRESS_BILLING_LINE2
:
203 case ADDRESS_HOME_STREET_ADDRESS
:
204 case ADDRESS_HOME_LINE1
:
205 case ADDRESS_HOME_LINE2
:
207 *field
= ::i18n::addressinput::STREET_ADDRESS
;
211 *field
= ::i18n::addressinput::ORGANIZATION
;
213 case NAME_BILLING_FULL
:
216 *field
= ::i18n::addressinput::RECIPIENT
;
223 void CreateAddressData(
224 const base::Callback
<base::string16(const AutofillType
&)>& get_info
,
225 AddressData
* address_data
) {
226 address_data
->recipient
= UTF16ToUTF8(get_info
.Run(AutofillType(NAME_FULL
)));
227 address_data
->country_code
= UTF16ToUTF8(
228 get_info
.Run(AutofillType(HTML_TYPE_COUNTRY_CODE
, HTML_MODE_SHIPPING
)));
229 DCHECK_EQ(2U, address_data
->country_code
.size());
230 address_data
->administrative_area
= UTF16ToUTF8(
231 get_info
.Run(AutofillType(ADDRESS_HOME_STATE
)));
232 address_data
->locality
= UTF16ToUTF8(
233 get_info
.Run(AutofillType(ADDRESS_HOME_CITY
)));
234 address_data
->dependent_locality
= UTF16ToUTF8(
235 get_info
.Run(AutofillType(ADDRESS_HOME_DEPENDENT_LOCALITY
)));
236 address_data
->sorting_code
= UTF16ToUTF8(
237 get_info
.Run(AutofillType(ADDRESS_HOME_SORTING_CODE
)));
238 address_data
->postal_code
= UTF16ToUTF8(
239 get_info
.Run(AutofillType(ADDRESS_HOME_ZIP
)));
241 UTF16ToUTF8(get_info
.Run(AutofillType(ADDRESS_HOME_STREET_ADDRESS
))),
243 &address_data
->address_lines
);
246 bool CountryIsFullySupported(const std::string
& country_code
) {
247 DCHECK_EQ(2U, country_code
.size());
248 std::vector
< ::i18n::addressinput::AddressUiComponent
> components
=
249 ::i18n::addressinput::BuildComponents(
250 country_code
, g_browser_process
->GetApplicationLocale(), NULL
);
251 for (size_t i
= 0; i
< components
.size(); ++i
) {
252 if (components
[i
].field
== ::i18n::addressinput::DEPENDENT_LOCALITY
)
258 } // namespace i18ninput
259 } // namespace autofill