Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/payments/AddressEditor.java

Issue 2680143002: Use dropdown list for admin areas in pr form. (Closed)
Patch Set: The one where I applied seb's comments. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.payments; 5 package org.chromium.chrome.browser.payments;
6 6
7 import android.os.Handler; 7 import android.os.Handler;
8 import android.util.Pair; 8 import android.util.Pair;
9 9
10 import org.chromium.base.Callback; 10 import org.chromium.base.Callback;
11 import org.chromium.chrome.R; 11 import org.chromium.chrome.R;
12 import org.chromium.chrome.browser.autofill.PersonalDataManager; 12 import org.chromium.chrome.browser.autofill.PersonalDataManager;
13 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; 13 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
14 import org.chromium.chrome.browser.autofill.PersonalDataManager.GetSubKeysReques tDelegate;
14 import org.chromium.chrome.browser.autofill.PhoneNumberUtil; 15 import org.chromium.chrome.browser.autofill.PhoneNumberUtil;
15 import org.chromium.chrome.browser.payments.ui.EditorFieldModel; 16 import org.chromium.chrome.browser.payments.ui.EditorFieldModel;
16 import org.chromium.chrome.browser.payments.ui.EditorFieldModel.EditorFieldValid ator; 17 import org.chromium.chrome.browser.payments.ui.EditorFieldModel.EditorFieldValid ator;
17 import org.chromium.chrome.browser.payments.ui.EditorModel; 18 import org.chromium.chrome.browser.payments.ui.EditorModel;
18 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge; 19 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge;
19 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.Ad dressField; 20 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.Ad dressField;
20 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.Ad dressUiComponent; 21 import org.chromium.chrome.browser.preferences.autofill.AutofillProfileBridge.Ad dressUiComponent;
21 22
22 import java.util.HashMap; 23 import java.util.HashMap;
23 import java.util.HashSet; 24 import java.util.HashSet;
24 import java.util.List; 25 import java.util.List;
25 import java.util.Locale; 26 import java.util.Locale;
26 import java.util.Map; 27 import java.util.Map;
27 import java.util.Set; 28 import java.util.Set;
28 29
29 import javax.annotation.Nullable; 30 import javax.annotation.Nullable;
30 31
31 /** 32 /**
32 * An address editor. Can be used for either shipping or billing address editing . 33 * An address editor. Can be used for either shipping or billing address editing .
33 */ 34 */
34 public class AddressEditor extends EditorBase<AutofillAddress> { 35 public class AddressEditor
36 extends EditorBase<AutofillAddress> implements GetSubKeysRequestDelegate {
35 private final Handler mHandler = new Handler(); 37 private final Handler mHandler = new Handler();
36 private final Map<Integer, EditorFieldModel> mAddressFields = new HashMap<>( ); 38 private final Map<Integer, EditorFieldModel> mAddressFields = new HashMap<>( );
37 private final Set<CharSequence> mPhoneNumbers = new HashSet<>(); 39 private final Set<CharSequence> mPhoneNumbers = new HashSet<>();
38 @Nullable private AutofillProfileBridge mAutofillProfileBridge; 40 @Nullable
39 @Nullable private EditorFieldModel mCountryField; 41 private AutofillProfileBridge mAutofillProfileBridge;
40 @Nullable private EditorFieldModel mPhoneField; 42 @Nullable
41 @Nullable private EditorFieldValidator mPhoneValidator; 43 private EditorFieldModel mCountryField;
42 @Nullable private List<AddressUiComponent> mAddressUiComponents; 44 @Nullable
45 private EditorFieldModel mPhoneField;
46 @Nullable
47 private EditorFieldValidator mPhoneValidator;
48 @Nullable
49 private List<AddressUiComponent> mAddressUiComponents;
50 private boolean mAdminAreasLoaded;
51 private boolean mOnCountryChange;
52 private Pair<String, Runnable> mEventData;
53 private AutofillProfile mProfile;
54 private EditorModel mEditor;
43 55
44 /** 56 /**
45 * Adds the given phone number to the autocomplete set, if it's valid. 57 * Adds the given phone number to the autocomplete set, if it's valid.
46 * 58 *
47 * @param phoneNumber The phone number to possibly add. 59 * @param phoneNumber The phone number to possibly add.
48 */ 60 */
49 public void addPhoneNumberIfValid(@Nullable CharSequence phoneNumber) { 61 public void addPhoneNumberIfValid(@Nullable CharSequence phoneNumber) {
50 if (getPhoneValidator().isValid(phoneNumber)) mPhoneNumbers.add(phoneNum ber); 62 if (getPhoneValidator().isValid(phoneNumber)) mPhoneNumbers.add(phoneNum ber);
51 } 63 }
52 64
(...skipping 12 matching lines...) Expand all
65 public void edit( 77 public void edit(
66 @Nullable final AutofillAddress toEdit, final Callback<AutofillAddre ss> callback) { 78 @Nullable final AutofillAddress toEdit, final Callback<AutofillAddre ss> callback) {
67 super.edit(toEdit, callback); 79 super.edit(toEdit, callback);
68 80
69 if (mAutofillProfileBridge == null) mAutofillProfileBridge = new Autofil lProfileBridge(); 81 if (mAutofillProfileBridge == null) mAutofillProfileBridge = new Autofil lProfileBridge();
70 82
71 // If |toEdit| is null, we're creating a new autofill profile with the c ountry code of the 83 // If |toEdit| is null, we're creating a new autofill profile with the c ountry code of the
72 // default locale on this device. 84 // default locale on this device.
73 boolean isNewAddress = toEdit == null; 85 boolean isNewAddress = toEdit == null;
74 86
75 // Ensure that |address| and |profile| are always not null. 87 // Ensure that |address| and |mProfile| are always not null.
76 final AutofillAddress address = 88 final AutofillAddress address =
77 isNewAddress ? new AutofillAddress(mContext, new AutofillProfile ()) : toEdit; 89 isNewAddress ? new AutofillAddress(mContext, new AutofillProfile ()) : toEdit;
78 final AutofillProfile profile = address.getProfile(); 90 mProfile = address.getProfile();
79 91
80 // The title of the editor depends on whether we're adding a new address or editing an 92 // The title of the editor depends on whether we're adding a new address or editing an
81 // existing address. 93 // existing address.
82 final EditorModel editor = 94 mEditor =
83 new EditorModel(isNewAddress 95 new EditorModel(isNewAddress ? mContext.getString(R.string.autof ill_create_profile)
84 ? mContext.getString(R.string.autofill_create_profile) 96 : toEdit.getEditTitle());
85 : toEdit.getEditTitle());
86 97
87 // The country dropdown is always present on the editor. 98 // The country dropdown is always present on the editor.
88 if (mCountryField == null) { 99 if (mCountryField == null) {
89 mCountryField = EditorFieldModel.createDropdown( 100 mCountryField = EditorFieldModel.createDropdown(
90 mContext.getString(R.string.autofill_profile_editor_country) , 101 mContext.getString(R.string.autofill_profile_editor_country) ,
91 AutofillProfileBridge.getSupportedCountries(), 102 AutofillProfileBridge.getSupportedCountries(),
92 null /* hint */); 103 null /* hint */);
93 } 104 }
94 105
95 // Changing the country will update which fields are in the model. The a ctual fields are not 106 // Changing the country will update which fields are in the model. The a ctual fields are not
96 // discarded, so their contents are preserved. 107 // discarded, so their contents are preserved.
97 mCountryField.setDropdownCallback(new Callback<Pair<String, Runnable>>() { 108 mCountryField.setDropdownCallback(new Callback<Pair<String, Runnable>>() {
98 @Override 109 @Override
99 public void onResult(Pair<String, Runnable> eventData) { 110 public void onResult(Pair<String, Runnable> eventData) {
100 editor.removeAllFields(); 111 mEditor.removeAllFields();
101 editor.addField(mCountryField); 112 mEventData = eventData;
102 addAddressTextFieldsToEditor(editor, eventData.first, 113 mOnCountryChange = true;
103 Locale.getDefault().getLanguage()); 114 loadAdminAreas();
104 editor.addField(mPhoneField);
105
106 // Notify EditorView that the fields in the model have changed. EditorView should
107 // re-read the model and update the UI accordingly.
108 mHandler.post(eventData.second);
109 } 115 }
110 }); 116 });
111 117
112 // Country dropdown is cached, so the selected item needs to be updated for the new profile 118 // Country dropdown is cached, so the selected item needs to be updated for the new profile
113 // that's being edited. This will not fire the dropdown callback. 119 // that's being edited. This will not fire the dropdown callback.
114 mCountryField.setValue(AutofillAddress.getCountryCode(profile)); 120 mCountryField.setValue(AutofillAddress.getCountryCode(mProfile));
115 editor.addField(mCountryField);
116 121
117 // There's a finite number of fields for address editing. Changing the c ountry will re-order 122 // There's a finite number of fields for address editing. Changing the c ountry will re-order
118 // and relabel the fields. The meaning of each field remains the same. 123 // and relabel the fields. The meaning of each field remains the same.
119 if (mAddressFields.isEmpty()) { 124 if (mAddressFields.isEmpty()) {
120 // City, dependent locality, and organization don't have any special formatting hints. 125 // City, dependent locality, and organization don't have any special formatting hints.
121 mAddressFields.put(AddressField.LOCALITY, EditorFieldModel.createTex tInput()); 126 mAddressFields.put(AddressField.LOCALITY, EditorFieldModel.createTex tInput());
122 mAddressFields.put(AddressField.DEPENDENT_LOCALITY, EditorFieldModel .createTextInput()); 127 mAddressFields.put(AddressField.DEPENDENT_LOCALITY, EditorFieldModel .createTextInput());
123 mAddressFields.put(AddressField.ORGANIZATION, EditorFieldModel.creat eTextInput()); 128 mAddressFields.put(AddressField.ORGANIZATION, EditorFieldModel.creat eTextInput());
124 129
125 // State should be formatted in all capitals.
126 mAddressFields.put(AddressField.ADMIN_AREA, EditorFieldModel.createT extInput(
127 EditorFieldModel.INPUT_TYPE_HINT_REGION));
128
129 // Sorting code and postal code (a.k.a. ZIP code) should show both l etters and digits on 130 // Sorting code and postal code (a.k.a. ZIP code) should show both l etters and digits on
130 // the keyboard, if possible. 131 // the keyboard, if possible.
131 mAddressFields.put(AddressField.SORTING_CODE, EditorFieldModel.creat eTextInput( 132 mAddressFields.put(AddressField.SORTING_CODE, EditorFieldModel.creat eTextInput(
132 EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC)); 133 EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC));
133 mAddressFields.put(AddressField.POSTAL_CODE, EditorFieldModel.create TextInput( 134 mAddressFields.put(AddressField.POSTAL_CODE, EditorFieldModel.create TextInput(
134 EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC)); 135 EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC));
135 136
136 // Street line field can contain \n to indicate line breaks. 137 // Street line field can contain \n to indicate line breaks.
137 mAddressFields.put(AddressField.STREET_ADDRESS, EditorFieldModel.cre ateTextInput( 138 mAddressFields.put(AddressField.STREET_ADDRESS, EditorFieldModel.cre ateTextInput(
138 EditorFieldModel.INPUT_TYPE_HINT_STREET_LINES)); 139 EditorFieldModel.INPUT_TYPE_HINT_STREET_LINES));
139 140
140 // Android has special formatting rules for names. 141 // Android has special formatting rules for names.
141 mAddressFields.put(AddressField.RECIPIENT, EditorFieldModel.createTe xtInput( 142 mAddressFields.put(AddressField.RECIPIENT, EditorFieldModel.createTe xtInput(
142 EditorFieldModel.INPUT_TYPE_HINT_PERSON_NAME)); 143 EditorFieldModel.INPUT_TYPE_HINT_PERSON_NAME));
143 } 144 }
144 145
145 // Address fields are cached, so their values need to be updated for eve ry new profile
146 // that's being edited.
147 for (Map.Entry<Integer, EditorFieldModel> entry : mAddressFields.entrySe t()) {
148 entry.getValue().setValue(AutofillAddress.getProfileField(profile, e ntry.getKey()));
149 }
150
151 // Both country code and language code dictate which fields should be ad ded to the editor.
152 // For example, "US" will not add dependent locality to the editor. A "J P" address will
153 // start with a person's full name or a with a prefecture name, dependin g on whether the
154 // language code is "ja-Latn" or "ja".
155 addAddressTextFieldsToEditor(editor, profile.getCountryCode(), profile.g etLanguageCode());
156 146
157 // Phone number is present and required for all countries. 147 // Phone number is present and required for all countries.
158 if (mPhoneField == null) { 148 if (mPhoneField == null) {
159 mPhoneField = EditorFieldModel.createTextInput(EditorFieldModel.INPU T_TYPE_HINT_PHONE, 149 mPhoneField = EditorFieldModel.createTextInput(EditorFieldModel.INPU T_TYPE_HINT_PHONE,
160 mContext.getString(R.string.autofill_profile_editor_phone_nu mber), 150 mContext.getString(R.string.autofill_profile_editor_phone_nu mber),
161 mPhoneNumbers, getPhoneValidator(), null, 151 mPhoneNumbers, getPhoneValidator(), null,
162 mContext.getString(R.string.payments_field_required_validati on_message), 152 mContext.getString(R.string.payments_field_required_validati on_message),
163 mContext.getString(R.string.payments_phone_invalid_validatio n_message), null); 153 mContext.getString(R.string.payments_phone_invalid_validatio n_message), null);
164 } 154 }
165 155
166 // Phone number field is cached, so its value needs to be updated for ev ery new profile 156 // Phone number field is cached, so its value needs to be updated for ev ery new profile
167 // that's being edited. 157 // that's being edited.
168 mPhoneField.setValue(profile.getPhoneNumber()); 158 mPhoneField.setValue(mProfile.getPhoneNumber());
169 editor.addField(mPhoneField);
170 159
171 // If the user clicks [Cancel], send |toEdit| address back to the caller , which was the 160 // If the user clicks [Cancel], send |toEdit| address back to the caller , which was the
172 // original state (could be null, a complete address, a partial address) . 161 // original state (could be null, a complete address, a partial address) .
173 editor.setCancelCallback(new Runnable() { 162 mEditor.setCancelCallback(new Runnable() {
174 @Override 163 @Override
175 public void run() { 164 public void run() {
165 mAdminAreasLoaded = true;
166 PersonalDataManager.getInstance().cancelPendingGetSubKeys();
176 callback.onResult(toEdit); 167 callback.onResult(toEdit);
177 } 168 }
178 }); 169 });
179 170
180 // If the user clicks [Done], save changes on disk, mark the address "co mplete," and send it 171 // If the user clicks [Done], save changes on disk, mark the address "co mplete," and send it
181 // back to the caller. 172 // back to the caller.
182 editor.setDoneCallback(new Runnable() { 173 mEditor.setDoneCallback(new Runnable() {
183 @Override 174 @Override
184 public void run() { 175 public void run() {
185 commitChanges(profile); 176 mAdminAreasLoaded = true;
186 address.completeAddress(profile); 177 PersonalDataManager.getInstance().cancelPendingGetSubKeys();
178 commitChanges(mProfile);
179 address.completeAddress(mProfile);
187 callback.onResult(address); 180 callback.onResult(address);
188 } 181 }
189 }); 182 });
190 183
191 mEditorView.show(editor); 184 mOnCountryChange = false;
185 loadAdminAreas();
192 } 186 }
193 187
194 /** Saves the edited profile on disk. */ 188 /** Saves the edited profile on disk. */
195 private void commitChanges(AutofillProfile profile) { 189 private void commitChanges(AutofillProfile profile) {
196 // Country code and phone number are always required and are always coll ected from the 190 // Country code and phone number are always required and are always coll ected from the
197 // editor model. 191 // editor model.
198 profile.setCountryCode(mCountryField.getValue().toString()); 192 profile.setCountryCode(mCountryField.getValue().toString());
199 profile.setPhoneNumber(mPhoneField.getValue().toString()); 193 profile.setPhoneNumber(mPhoneField.getValue().toString());
200 194
201 // Autofill profile bridge normalizes the language code for the autofill profile. 195 // Autofill profile bridge normalizes the language code for the autofill profile.
(...skipping 11 matching lines...) Expand all
213 207
214 // Clear the fields that are hidden from the user interface, so 208 // Clear the fields that are hidden from the user interface, so
215 // AutofillAddress.toPaymentAddress() will send them to the renderer as empty strings. 209 // AutofillAddress.toPaymentAddress() will send them to the renderer as empty strings.
216 for (Map.Entry<Integer, EditorFieldModel> entry : mAddressFields.entrySe t()) { 210 for (Map.Entry<Integer, EditorFieldModel> entry : mAddressFields.entrySe t()) {
217 if (!visibleFields.contains(entry.getKey())) { 211 if (!visibleFields.contains(entry.getKey())) {
218 setProfileField(profile, entry.getKey(), ""); 212 setProfileField(profile, entry.getKey(), "");
219 } 213 }
220 } 214 }
221 215
222 // Save the edited autofill profile locally. 216 // Save the edited autofill profile locally.
223 profile.setGUID(PersonalDataManager.getInstance().setProfileToLocal(prof ile)); 217 profile.setGUID(PersonalDataManager.getInstance().setProfileToLocal(mPro file));
224 profile.setIsLocal(true); 218 profile.setIsLocal(true);
225 } 219 }
226 220
227 /** Writes the given value into the specified autofill profile field. */ 221 /** Writes the given value into the specified autofill profile field. */
228 private static void setProfileField( 222 private static void setProfileField(
229 AutofillProfile profile, int field, @Nullable CharSequence value) { 223 AutofillProfile profile, int field, @Nullable CharSequence value) {
230 assert profile != null; 224 assert profile != null;
231 switch (field) { 225 switch (field) {
232 case AddressField.COUNTRY: 226 case AddressField.COUNTRY:
233 profile.setCountryCode(ensureNotNull(value)); 227 profile.setCountryCode(ensureNotNull(value));
(...skipping 24 matching lines...) Expand all
258 return; 252 return;
259 } 253 }
260 254
261 assert false; 255 assert false;
262 } 256 }
263 257
264 private static String ensureNotNull(@Nullable CharSequence value) { 258 private static String ensureNotNull(@Nullable CharSequence value) {
265 return value == null ? "" : value.toString(); 259 return value == null ? "" : value.toString();
266 } 260 }
267 261
262 private void setAddressFieldValuesFromCache() {
263 // Address fields are cached, so their values need to be updated for eve ry new profile
264 // that's being edited.
265 for (Map.Entry<Integer, EditorFieldModel> entry : mAddressFields.entrySe t()) {
266 entry.getValue().setValue(AutofillAddress.getProfileField(mProfile, entry.getKey()));
267 }
268 }
269 /* Callback of the sub keys request that is called when the sub keys are loa ded.
270 Here the sub keys are admin areas (sub keys of the region=country.) */
271 @Override
272 public void onSubKeysReceived(String[] adminAreas) {
273 if (mAdminAreasLoaded) return;
274 mAdminAreasLoaded = true;
275
276 // If can't get admin areas from server or there is no admin area on the
277 // server, then use text field. Otherwise, use drop down list.
278 if (adminAreas == null || adminAreas.length == 0
279 || PersonalDataManager.getInstance().isOnTestingMode()) {
sebsg 2017/03/21 20:49:31 I'm not sure I understand the need for this? Could
Parastoo 2017/03/21 21:13:38 If we are on the testing mode (we are testing for
280 mAddressFields.put(AddressField.ADMIN_AREA, EditorFieldModel.createT extInput());
281 } else {
282 mAddressFields.put(AddressField.ADMIN_AREA, EditorFieldModel.createD ropdown());
283 }
284
285 /* Admin Areas need to be fetched in two cases.
286 1. Initial loading of the form.
287 2. When the selected country is changed in the form.
288 mOnCountryChange is true iff it's the 2nd case. */
289 if (mOnCountryChange) {
290 // Both country code and language code dictate which fields should b e added to the
291 // editor.
292 // For example, "US" will not add dependent locality to the editor. A "JP" address will
293 // start with a person's full name or a with a prefecture name, depe nding on whether the
294 // language code is "ja-Latn" or "ja".
295 addAddressFieldsToEditor(mEventData.first,
296 Locale.getDefault().getLanguage(),
297 adminAreas);
298 // Notify EditorView that the fields in the model have changed. Edit orView should
299 // re-read the model and update the UI accordingly.
300 mHandler.post(mEventData.second);
301 } else {
302 // This should be called when all required fields are put in mAddres sField.
303 setAddressFieldValuesFromCache();
304 addAddressFieldsToEditor(mProfile.getCountryCode(),
305 mProfile.getLanguageCode(), adminAreas);
306 mEditorView.show(mEditor);
307 }
308 }
309
310 /** Requests the list of admin areas. */
311 public void loadAdminAreas() {
312 String countryCode = mOnCountryChange ? mEventData.first : mProfile.getC ountryCode();
313
314 // Used to check if the callback is called (for time-out).
315 mAdminAreasLoaded = false;
316
317 // In each rule, admin area keys are saved under sub keys of country.
318 PersonalDataManager.getInstance().loadRulesForSubKeys(countryCode);
319 PersonalDataManager.getInstance().getRegionSubKeys(countryCode, this);
320 onAdminAreasLoading();
321 }
322
323 /* In case the the admin areas are not loaded yet, starts a timer to cancel the request. */
324 public void onAdminAreasLoading() {
325 if (!mAdminAreasLoaded) {
326 new Handler().postDelayed(new Runnable() {
327 @Override
328 public void run() {
329 if (!mAdminAreasLoaded) {
330 onSubKeysReceived(null);
331 PersonalDataManager.getInstance().cancelPendingGetSubKey s();
332 }
333 }
334 }, PersonalDataManager.getInstance().getTimeoutMS());
335 }
336 }
337
268 /** 338 /**
269 * Adds text fields to the editor model based on the country and language co de of the profile 339 * Adds fields to the editor model based on the country and language code of
270 * that's being edited. 340 * the profile that's being edited.
271 */ 341 */
272 private void addAddressTextFieldsToEditor( 342 private void addAddressFieldsToEditor(
273 EditorModel container, String countryCode, String languageCode) { 343 String countryCode, String languageCode, String[] adminAreas) {
274 mAddressUiComponents = mAutofillProfileBridge.getAddressUiComponents(cou ntryCode, 344 mAddressUiComponents =
275 languageCode); 345 mAutofillProfileBridge.getAddressUiComponents(countryCode, langu ageCode);
276 346 // In terms of order, country must be the first field.
347 mEditor.addField(mCountryField);
277 for (int i = 0; i < mAddressUiComponents.size(); i++) { 348 for (int i = 0; i < mAddressUiComponents.size(); i++) {
278 AddressUiComponent component = mAddressUiComponents.get(i); 349 AddressUiComponent component = mAddressUiComponents.get(i);
279 350
280 // The country field is a dropdown, so there's no need to add a text field for it.
281 if (component.id == AddressField.COUNTRY) continue;
282
283 EditorFieldModel field = mAddressFields.get(component.id); 351 EditorFieldModel field = mAddressFields.get(component.id);
284 // Labels depend on country, e.g., state is called province in some countries. These are 352 // Labels depend on country, e.g., state is called province in some countries. These are
285 // already localized. 353 // already localized.
286 field.setLabel(component.label); 354 field.setLabel(component.label);
287 field.setIsFullLine(component.isFullLine); 355 field.setIsFullLine(component.isFullLine);
288 356
357 if (component.id == AddressField.ADMIN_AREA && field.isDropdownField ()) {
358 field.setDropdownKeyValues(
359 mAutofillProfileBridge.getAdminAreaDropdownList(adminAre as));
360 }
361
289 // Libaddressinput formats do not always require the full name (RECI PIENT), but 362 // Libaddressinput formats do not always require the full name (RECI PIENT), but
290 // PaymentRequest does. 363 // PaymentRequest does.
291 if (component.isRequired || component.id == AddressField.RECIPIENT) { 364 if (component.isRequired || component.id == AddressField.RECIPIENT) {
292 field.setRequiredErrorMessage(mContext.getString( 365 field.setRequiredErrorMessage(mContext.getString(
293 R.string.payments_field_required_validation_message)); 366 R.string.payments_field_required_validation_message));
294 } else { 367 } else {
295 field.setRequiredErrorMessage(null); 368 field.setRequiredErrorMessage(null);
296 } 369 }
297 370 mEditor.addField(field);
298 container.addField(field);
299 } 371 }
372 // Phone number must be the last field.
373 mEditor.addField(mPhoneField);
300 } 374 }
301 375
302 private EditorFieldValidator getPhoneValidator() { 376 private EditorFieldValidator getPhoneValidator() {
303 if (mPhoneValidator == null) { 377 if (mPhoneValidator == null) {
304 mPhoneValidator = new EditorFieldValidator() { 378 mPhoneValidator = new EditorFieldValidator() {
305 @Override 379 @Override
306 public boolean isValid(@Nullable CharSequence value) { 380 public boolean isValid(@Nullable CharSequence value) {
307 return value != null && PhoneNumberUtil.isValidNumber(value. toString()); 381 return value != null && PhoneNumberUtil.isValidNumber(value. toString());
308 } 382 }
309 383
310 @Override 384 @Override
311 public boolean isLengthMaximum(@Nullable CharSequence value) { 385 public boolean isLengthMaximum(@Nullable CharSequence value) {
312 return false; 386 return false;
313 } 387 }
314 }; 388 };
315 } 389 }
316 return mPhoneValidator; 390 return mPhoneValidator;
317 } 391 }
318 } 392 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698