OLD | NEW |
---|---|
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 |
43 | 45 private EditorFieldModel mPhoneField; |
46 @Nullable | |
47 private EditorFieldValidator mPhoneValidator; | |
48 @Nullable | |
49 private List<AddressUiComponent> mAddressUiComponents; | |
50 private boolean mAdminAreasLoaded; | |
51 private String mRecentlySelectedCountry; | |
52 private Runnable mCountryChangeCallback; | |
53 private AutofillProfile mProfile; | |
54 private EditorModel mEditor; | |
44 /** | 55 /** |
please use gerrit instead
2017/03/30 18:48:58
Need a newline above.
Parastoo
2017/03/31 15:44:14
Done.
| |
45 * Adds the given phone number to the autocomplete set, if it's valid. | 56 * Adds the given phone number to the autocomplete set, if it's valid. |
46 * | 57 * |
47 * @param phoneNumber The phone number to possibly add. | 58 * @param phoneNumber The phone number to possibly add. |
48 */ | 59 */ |
49 public void addPhoneNumberIfValid(@Nullable CharSequence phoneNumber) { | 60 public void addPhoneNumberIfValid(@Nullable CharSequence phoneNumber) { |
50 if (getPhoneValidator().isValid(phoneNumber)) mPhoneNumbers.add(phoneNum ber); | 61 if (getPhoneValidator().isValid(phoneNumber)) mPhoneNumbers.add(phoneNum ber); |
51 } | 62 } |
52 | 63 |
53 /** | 64 /** |
54 * Builds and shows an editor model with the following fields. | 65 * Builds and shows an editor model with the following fields. |
(...skipping 10 matching lines...) Expand all Loading... | |
65 public void edit( | 76 public void edit( |
66 @Nullable final AutofillAddress toEdit, final Callback<AutofillAddre ss> callback) { | 77 @Nullable final AutofillAddress toEdit, final Callback<AutofillAddre ss> callback) { |
67 super.edit(toEdit, callback); | 78 super.edit(toEdit, callback); |
68 | 79 |
69 if (mAutofillProfileBridge == null) mAutofillProfileBridge = new Autofil lProfileBridge(); | 80 if (mAutofillProfileBridge == null) mAutofillProfileBridge = new Autofil lProfileBridge(); |
70 | 81 |
71 // If |toEdit| is null, we're creating a new autofill profile with the c ountry code of the | 82 // If |toEdit| is null, we're creating a new autofill profile with the c ountry code of the |
72 // default locale on this device. | 83 // default locale on this device. |
73 boolean isNewAddress = toEdit == null; | 84 boolean isNewAddress = toEdit == null; |
74 | 85 |
75 // Ensure that |address| and |profile| are always not null. | 86 // Ensure that |address| and |mProfile| are always not null. |
76 final AutofillAddress address = | 87 final AutofillAddress address = |
77 isNewAddress ? new AutofillAddress(mContext, new AutofillProfile ()) : toEdit; | 88 isNewAddress ? new AutofillAddress(mContext, new AutofillProfile ()) : toEdit; |
78 final AutofillProfile profile = address.getProfile(); | 89 mProfile = address.getProfile(); |
79 | 90 |
80 // The title of the editor depends on whether we're adding a new address or editing an | 91 // The title of the editor depends on whether we're adding a new address or editing an |
81 // existing address. | 92 // existing address. |
82 final EditorModel editor = | 93 mEditor = |
83 new EditorModel(isNewAddress | 94 new EditorModel(isNewAddress ? mContext.getString(R.string.autof ill_create_profile) |
84 ? mContext.getString(R.string.autofill_create_profile) | 95 : toEdit.getEditTitle()); |
85 : toEdit.getEditTitle()); | 96 |
97 // When edit is called, a new form is started, so the country on the | |
98 // drop-down list is not changed. => mRecentlySelectedCountry should be null. | |
99 mRecentlySelectedCountry = null; | |
86 | 100 |
87 // The country dropdown is always present on the editor. | 101 // The country dropdown is always present on the editor. |
88 if (mCountryField == null) { | 102 if (mCountryField == null) { |
89 mCountryField = EditorFieldModel.createDropdown( | 103 mCountryField = EditorFieldModel.createDropdown( |
90 mContext.getString(R.string.autofill_profile_editor_country) , | 104 mContext.getString(R.string.autofill_profile_editor_country) , |
91 AutofillProfileBridge.getSupportedCountries(), | 105 AutofillProfileBridge.getSupportedCountries(), |
92 null /* hint */); | 106 null /* hint */); |
93 } | 107 } |
94 | 108 |
95 // Changing the country will update which fields are in the model. The a ctual fields are not | 109 // Changing the country will update which fields are in the model. The a ctual fields are not |
96 // discarded, so their contents are preserved. | 110 // discarded, so their contents are preserved. |
97 mCountryField.setDropdownCallback(new Callback<Pair<String, Runnable>>() { | 111 mCountryField.setDropdownCallback(new Callback<Pair<String, Runnable>>() { |
98 @Override | 112 @Override |
113 /* | |
114 * If the selected country on the country dropdown list is changed, | |
115 * the first element of eventData is the recently selected dropdown key, | |
116 * the second element is the callback to invoke for when the dropdow n | |
117 * change has been processed. | |
118 */ | |
99 public void onResult(Pair<String, Runnable> eventData) { | 119 public void onResult(Pair<String, Runnable> eventData) { |
100 editor.removeAllFields(); | 120 mEditor.removeAllFields(); |
please use gerrit instead
2017/03/30 18:48:58
Should there be a spinner or "Loading..." text whi
Parastoo
2017/03/31 15:44:14
I don't know. But, later, the sub-keys will be fet
please use gerrit instead
2017/03/31 16:06:20
Let's put a "Loading..." text in the editor view w
Parastoo
2017/04/03 16:18:23
Note: There is a limit of 5 secs, if the data is n
Parastoo
2017/04/03 16:18:23
Done.
| |
101 editor.addField(mCountryField); | 121 mRecentlySelectedCountry = eventData.first; |
102 addAddressTextFieldsToEditor(editor, eventData.first, | 122 mCountryChangeCallback = eventData.second; |
103 Locale.getDefault().getLanguage()); | 123 loadAdminAreasForCountry(mRecentlySelectedCountry); |
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 } | 124 } |
110 }); | 125 }); |
111 | 126 |
112 // Country dropdown is cached, so the selected item needs to be updated for the new profile | 127 // 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. | 128 // that's being edited. This will not fire the dropdown callback. |
114 mCountryField.setValue(AutofillAddress.getCountryCode(profile)); | 129 mCountryField.setValue(AutofillAddress.getCountryCode(mProfile)); |
115 editor.addField(mCountryField); | |
116 | 130 |
117 // There's a finite number of fields for address editing. Changing the c ountry will re-order | 131 // 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. | 132 // and relabel the fields. The meaning of each field remains the same. |
119 if (mAddressFields.isEmpty()) { | 133 if (mAddressFields.isEmpty()) { |
120 // City, dependent locality, and organization don't have any special formatting hints. | 134 // City, dependent locality, and organization don't have any special formatting hints. |
121 mAddressFields.put(AddressField.LOCALITY, EditorFieldModel.createTex tInput()); | 135 mAddressFields.put(AddressField.LOCALITY, EditorFieldModel.createTex tInput()); |
122 mAddressFields.put(AddressField.DEPENDENT_LOCALITY, EditorFieldModel .createTextInput()); | 136 mAddressFields.put(AddressField.DEPENDENT_LOCALITY, EditorFieldModel .createTextInput()); |
123 mAddressFields.put(AddressField.ORGANIZATION, EditorFieldModel.creat eTextInput()); | 137 mAddressFields.put(AddressField.ORGANIZATION, EditorFieldModel.creat eTextInput()); |
124 | 138 |
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 | 139 // Sorting code and postal code (a.k.a. ZIP code) should show both l etters and digits on |
130 // the keyboard, if possible. | 140 // the keyboard, if possible. |
131 mAddressFields.put(AddressField.SORTING_CODE, EditorFieldModel.creat eTextInput( | 141 mAddressFields.put(AddressField.SORTING_CODE, EditorFieldModel.creat eTextInput( |
132 EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC)); | 142 EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC)); |
133 mAddressFields.put(AddressField.POSTAL_CODE, EditorFieldModel.create TextInput( | 143 mAddressFields.put(AddressField.POSTAL_CODE, EditorFieldModel.create TextInput( |
134 EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC)); | 144 EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC)); |
135 | 145 |
136 // Street line field can contain \n to indicate line breaks. | 146 // Street line field can contain \n to indicate line breaks. |
137 mAddressFields.put(AddressField.STREET_ADDRESS, EditorFieldModel.cre ateTextInput( | 147 mAddressFields.put(AddressField.STREET_ADDRESS, EditorFieldModel.cre ateTextInput( |
138 EditorFieldModel.INPUT_TYPE_HINT_STREET_LINES)); | 148 EditorFieldModel.INPUT_TYPE_HINT_STREET_LINES)); |
139 | 149 |
140 // Android has special formatting rules for names. | 150 // Android has special formatting rules for names. |
141 mAddressFields.put(AddressField.RECIPIENT, EditorFieldModel.createTe xtInput( | 151 mAddressFields.put(AddressField.RECIPIENT, EditorFieldModel.createTe xtInput( |
142 EditorFieldModel.INPUT_TYPE_HINT_PERSON_NAME)); | 152 EditorFieldModel.INPUT_TYPE_HINT_PERSON_NAME)); |
143 } | 153 } |
144 | 154 |
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 | 155 |
157 // Phone number is present and required for all countries. | 156 // Phone number is present and required for all countries. |
158 if (mPhoneField == null) { | 157 if (mPhoneField == null) { |
159 mPhoneField = EditorFieldModel.createTextInput(EditorFieldModel.INPU T_TYPE_HINT_PHONE, | 158 mPhoneField = EditorFieldModel.createTextInput(EditorFieldModel.INPU T_TYPE_HINT_PHONE, |
160 mContext.getString(R.string.autofill_profile_editor_phone_nu mber), | 159 mContext.getString(R.string.autofill_profile_editor_phone_nu mber), |
161 mPhoneNumbers, getPhoneValidator(), null, | 160 mPhoneNumbers, getPhoneValidator(), null, |
162 mContext.getString(R.string.payments_field_required_validati on_message), | 161 mContext.getString(R.string.payments_field_required_validati on_message), |
163 mContext.getString(R.string.payments_phone_invalid_validatio n_message), null); | 162 mContext.getString(R.string.payments_phone_invalid_validatio n_message), null); |
164 } | 163 } |
165 | 164 |
166 // Phone number field is cached, so its value needs to be updated for ev ery new profile | 165 // Phone number field is cached, so its value needs to be updated for ev ery new profile |
167 // that's being edited. | 166 // that's being edited. |
168 mPhoneField.setValue(profile.getPhoneNumber()); | 167 mPhoneField.setValue(mProfile.getPhoneNumber()); |
169 editor.addField(mPhoneField); | |
170 | 168 |
171 // If the user clicks [Cancel], send |toEdit| address back to the caller , which was the | 169 // 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) . | 170 // original state (could be null, a complete address, a partial address) . |
173 editor.setCancelCallback(new Runnable() { | 171 mEditor.setCancelCallback(new Runnable() { |
174 @Override | 172 @Override |
175 public void run() { | 173 public void run() { |
174 /* This makes sure that onSubKeysReceived returns early if it's | |
175 ever called when Cancel has already occurred.*/ | |
176 mAdminAreasLoaded = true; | |
177 PersonalDataManager.getInstance().cancelPendingGetSubKeys(); | |
176 callback.onResult(toEdit); | 178 callback.onResult(toEdit); |
177 } | 179 } |
178 }); | 180 }); |
179 | 181 |
180 // If the user clicks [Done], save changes on disk, mark the address "co mplete," and send it | 182 // If the user clicks [Done], save changes on disk, mark the address "co mplete," and send it |
181 // back to the caller. | 183 // back to the caller. |
182 editor.setDoneCallback(new Runnable() { | 184 mEditor.setDoneCallback(new Runnable() { |
183 @Override | 185 @Override |
184 public void run() { | 186 public void run() { |
185 commitChanges(profile); | 187 mAdminAreasLoaded = true; |
186 address.completeAddress(profile); | 188 PersonalDataManager.getInstance().cancelPendingGetSubKeys(); |
189 commitChanges(mProfile); | |
190 address.completeAddress(mProfile); | |
187 callback.onResult(address); | 191 callback.onResult(address); |
188 } | 192 } |
189 }); | 193 }); |
190 | 194 |
191 mEditorView.show(editor); | 195 loadAdminAreasForCountry(mProfile.getCountryCode()); |
192 } | 196 } |
193 | 197 |
194 /** Saves the edited profile on disk. */ | 198 /** Saves the edited profile on disk. */ |
195 private void commitChanges(AutofillProfile profile) { | 199 private void commitChanges(AutofillProfile profile) { |
196 // Country code and phone number are always required and are always coll ected from the | 200 // Country code and phone number are always required and are always coll ected from the |
197 // editor model. | 201 // editor model. |
198 profile.setCountryCode(mCountryField.getValue().toString()); | 202 profile.setCountryCode(mCountryField.getValue().toString()); |
199 profile.setPhoneNumber(mPhoneField.getValue().toString()); | 203 profile.setPhoneNumber(mPhoneField.getValue().toString()); |
200 | 204 |
201 // Autofill profile bridge normalizes the language code for the autofill profile. | 205 // Autofill profile bridge normalizes the language code for the autofill profile. |
(...skipping 11 matching lines...) Expand all Loading... | |
213 | 217 |
214 // Clear the fields that are hidden from the user interface, so | 218 // Clear the fields that are hidden from the user interface, so |
215 // AutofillAddress.toPaymentAddress() will send them to the renderer as empty strings. | 219 // AutofillAddress.toPaymentAddress() will send them to the renderer as empty strings. |
216 for (Map.Entry<Integer, EditorFieldModel> entry : mAddressFields.entrySe t()) { | 220 for (Map.Entry<Integer, EditorFieldModel> entry : mAddressFields.entrySe t()) { |
217 if (!visibleFields.contains(entry.getKey())) { | 221 if (!visibleFields.contains(entry.getKey())) { |
218 setProfileField(profile, entry.getKey(), ""); | 222 setProfileField(profile, entry.getKey(), ""); |
219 } | 223 } |
220 } | 224 } |
221 | 225 |
222 // Save the edited autofill profile locally. | 226 // Save the edited autofill profile locally. |
223 profile.setGUID(PersonalDataManager.getInstance().setProfileToLocal(prof ile)); | 227 profile.setGUID(PersonalDataManager.getInstance().setProfileToLocal(mPro file)); |
224 profile.setIsLocal(true); | 228 profile.setIsLocal(true); |
225 } | 229 } |
226 | 230 |
227 /** Writes the given value into the specified autofill profile field. */ | 231 /** Writes the given value into the specified autofill profile field. */ |
228 private static void setProfileField( | 232 private static void setProfileField( |
229 AutofillProfile profile, int field, @Nullable CharSequence value) { | 233 AutofillProfile profile, int field, @Nullable CharSequence value) { |
230 assert profile != null; | 234 assert profile != null; |
231 switch (field) { | 235 switch (field) { |
232 case AddressField.COUNTRY: | 236 case AddressField.COUNTRY: |
233 profile.setCountryCode(ensureNotNull(value)); | 237 profile.setCountryCode(ensureNotNull(value)); |
(...skipping 24 matching lines...) Expand all Loading... | |
258 return; | 262 return; |
259 } | 263 } |
260 | 264 |
261 assert false; | 265 assert false; |
262 } | 266 } |
263 | 267 |
264 private static String ensureNotNull(@Nullable CharSequence value) { | 268 private static String ensureNotNull(@Nullable CharSequence value) { |
265 return value == null ? "" : value.toString(); | 269 return value == null ? "" : value.toString(); |
266 } | 270 } |
267 | 271 |
272 private void setAddressFieldValuesFromCache() { | |
273 // Address fields are cached, so their values need to be updated for eve ry new profile | |
274 // that's being edited. | |
275 for (Map.Entry<Integer, EditorFieldModel> entry : mAddressFields.entrySe t()) { | |
276 entry.getValue().setValue(AutofillAddress.getProfileField(mProfile, entry.getKey())); | |
277 } | |
278 } | |
279 | |
280 /* Callback of the sub keys request that is called when the sub keys are loa ded. | |
281 Here the sub keys are admin areas (sub keys of the region=country.) */ | |
282 @Override | |
283 public void onSubKeysReceived(String[] adminAreas) { | |
284 if (mAdminAreasLoaded) return; | |
285 mAdminAreasLoaded = true; | |
286 | |
287 // If can't get admin areas from server or there is no admin area on the | |
288 // server, then use text field. Otherwise, use drop down list. | |
289 if (adminAreas == null || adminAreas.length == 0) { | |
290 mAddressFields.put(AddressField.ADMIN_AREA, EditorFieldModel.createT extInput()); | |
291 } else { | |
292 mAddressFields.put(AddressField.ADMIN_AREA, EditorFieldModel.createD ropdown()); | |
293 } | |
294 | |
295 /* Admin Areas need to be fetched in two cases. | |
296 1. Initial loading of the form. | |
297 2. When the selected country is changed in the form. | |
298 mRecentlySelectedCountry is not null <=> the 2nd case */ | |
299 if (mRecentlySelectedCountry != null) { | |
300 // Both country code and language code dictate which fields should b e added to the | |
301 // editor. | |
302 // For example, "US" will not add dependent locality to the editor. A "JP" address will | |
303 // start with a person's full name or a with a prefecture name, depe nding on whether the | |
304 // language code is "ja-Latn" or "ja". | |
305 addAddressFieldsToEditor(mRecentlySelectedCountry, | |
306 Locale.getDefault().getLanguage(), | |
307 adminAreas); | |
308 // Notify EditorView that the fields in the model have changed. Edit orView should | |
309 // re-read the model and update the UI accordingly. | |
310 mHandler.post(mCountryChangeCallback); | |
311 } else { | |
312 // This should be called when all required fields are put in mAddres sField. | |
313 setAddressFieldValuesFromCache(); | |
314 addAddressFieldsToEditor(mProfile.getCountryCode(), | |
315 mProfile.getLanguageCode(), adminAreas); | |
316 mEditorView.show(mEditor); | |
317 } | |
318 } | |
319 | |
320 /** Requests the list of admin areas. */ | |
321 private void loadAdminAreasForCountry(String countryCode) { | |
322 // Used to check if the callback is called (for time-out). | |
323 mAdminAreasLoaded = false; | |
324 | |
325 // In each rule, admin area keys are saved under sub keys of country. | |
326 PersonalDataManager.getInstance().loadRulesForSubKeys(countryCode); | |
327 PersonalDataManager.getInstance().getRegionSubKeys(countryCode, this); | |
328 onAdminAreasLoading(); | |
329 } | |
330 | |
331 /* In case the the admin areas are not loaded yet, starts a timer to cancel the request. */ | |
332 public void onAdminAreasLoading() { | |
333 if (!mAdminAreasLoaded) { | |
334 if (PersonalDataManager.getInstance().getRequestTimeoutMS() == 0) { | |
335 onSubKeysReceived(null); | |
336 PersonalDataManager.getInstance().cancelPendingGetSubKeys(); | |
337 } else { | |
338 new Handler().postDelayed(new Runnable() { | |
339 @Override | |
340 public void run() { | |
341 if (!mAdminAreasLoaded) { | |
342 onSubKeysReceived(null); | |
343 PersonalDataManager.getInstance().cancelPendingGetSu bKeys(); | |
344 } | |
345 } | |
346 }, PersonalDataManager.getInstance().getRequestTimeoutMS()); | |
347 } | |
348 } | |
349 } | |
350 | |
268 /** | 351 /** |
269 * Adds text fields to the editor model based on the country and language co de of the profile | 352 * Adds fields to the editor model based on the country and language code of |
270 * that's being edited. | 353 * the profile that's being edited. |
271 */ | 354 */ |
272 private void addAddressTextFieldsToEditor( | 355 private void addAddressFieldsToEditor( |
273 EditorModel container, String countryCode, String languageCode) { | 356 String countryCode, String languageCode, String[] adminAreas) { |
274 mAddressUiComponents = mAutofillProfileBridge.getAddressUiComponents(cou ntryCode, | 357 mAddressUiComponents = |
275 languageCode); | 358 mAutofillProfileBridge.getAddressUiComponents(countryCode, langu ageCode); |
276 | 359 // In terms of order, country must be the first field. |
360 mEditor.addField(mCountryField); | |
277 for (int i = 0; i < mAddressUiComponents.size(); i++) { | 361 for (int i = 0; i < mAddressUiComponents.size(); i++) { |
278 AddressUiComponent component = mAddressUiComponents.get(i); | 362 AddressUiComponent component = mAddressUiComponents.get(i); |
279 | 363 |
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); | 364 EditorFieldModel field = mAddressFields.get(component.id); |
284 // Labels depend on country, e.g., state is called province in some countries. These are | 365 // Labels depend on country, e.g., state is called province in some countries. These are |
285 // already localized. | 366 // already localized. |
286 field.setLabel(component.label); | 367 field.setLabel(component.label); |
287 field.setIsFullLine(component.isFullLine); | 368 field.setIsFullLine(component.isFullLine); |
288 | 369 |
370 if (component.id == AddressField.ADMIN_AREA && field.isDropdownField ()) { | |
371 field.setDropdownKeyValues( | |
372 mAutofillProfileBridge.getAdminAreaDropdownList(adminAre as)); | |
373 } | |
374 | |
289 // Libaddressinput formats do not always require the full name (RECI PIENT), but | 375 // Libaddressinput formats do not always require the full name (RECI PIENT), but |
290 // PaymentRequest does. | 376 // PaymentRequest does. |
291 if (component.isRequired || component.id == AddressField.RECIPIENT) { | 377 if (component.isRequired || component.id == AddressField.RECIPIENT) { |
292 field.setRequiredErrorMessage(mContext.getString( | 378 field.setRequiredErrorMessage(mContext.getString( |
293 R.string.payments_field_required_validation_message)); | 379 R.string.payments_field_required_validation_message)); |
294 } else { | 380 } else { |
295 field.setRequiredErrorMessage(null); | 381 field.setRequiredErrorMessage(null); |
296 } | 382 } |
297 | 383 mEditor.addField(field); |
298 container.addField(field); | |
299 } | 384 } |
385 // Phone number must be the last field. | |
386 mEditor.addField(mPhoneField); | |
300 } | 387 } |
301 | 388 |
302 private EditorFieldValidator getPhoneValidator() { | 389 private EditorFieldValidator getPhoneValidator() { |
303 if (mPhoneValidator == null) { | 390 if (mPhoneValidator == null) { |
304 mPhoneValidator = new EditorFieldValidator() { | 391 mPhoneValidator = new EditorFieldValidator() { |
305 @Override | 392 @Override |
306 public boolean isValid(@Nullable CharSequence value) { | 393 public boolean isValid(@Nullable CharSequence value) { |
307 return value != null && PhoneNumberUtil.isValidNumber(value. toString()); | 394 return value != null && PhoneNumberUtil.isValidNumber(value. toString()); |
308 } | 395 } |
309 | 396 |
310 @Override | 397 @Override |
311 public boolean isLengthMaximum(@Nullable CharSequence value) { | 398 public boolean isLengthMaximum(@Nullable CharSequence value) { |
312 return false; | 399 return false; |
313 } | 400 } |
314 }; | 401 }; |
315 } | 402 } |
316 return mPhoneValidator; | 403 return mPhoneValidator; |
317 } | 404 } |
318 } | 405 } |
OLD | NEW |