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