blob: 73c4c4622685d1bef0c6a724d8b8cd4e8874a0a1 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.autofill.settings;
import android.app.Activity;
import android.util.Pair;
import androidx.annotation.IntDef;
import androidx.fragment.app.Fragment;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.browser.settings.SettingsLauncher;
import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
import org.chromium.content_public.browser.WebContents;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
/**
* Static methods to fetch information needed to create the address fields for the autofill profile
* form.
*/
@JNINamespace("autofill")
public class AutofillProfileBridge {
/**
* Address field types.
* This list must be kept in-sync with the corresponding enum in
* third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h
*/
@IntDef({AddressField.COUNTRY, AddressField.ADMIN_AREA, AddressField.LOCALITY,
AddressField.DEPENDENT_LOCALITY, AddressField.SORTING_CODE, AddressField.POSTAL_CODE,
AddressField.STREET_ADDRESS, AddressField.ORGANIZATION, AddressField.RECIPIENT})
@Retention(RetentionPolicy.SOURCE)
public @interface AddressField {
int COUNTRY = 0;
int ADMIN_AREA = 1;
int LOCALITY = 2;
int DEPENDENT_LOCALITY = 3;
int SORTING_CODE = 4;
int POSTAL_CODE = 5;
int STREET_ADDRESS = 6;
int ORGANIZATION = 7;
int RECIPIENT = 8;
int NUM_ENTRIES = 9;
}
/**
* A convenience class for displaying keyed values in a dropdown.
*/
public static class DropdownKeyValue extends Pair<String, CharSequence> {
public DropdownKeyValue(String key, CharSequence value) {
super(key, value);
}
/** @return The key identifier. */
public String getKey() {
return super.first;
}
/** @return The human-readable localized display value. */
public CharSequence getValue() {
return super.second;
}
@Override
public String toString() {
return super.second.toString();
}
}
private String mCurrentBestLanguageCode;
/**
* @return The CLDR region code for the default locale.
*/
public static String getDefaultCountryCode() {
return AutofillProfileBridgeJni.get().getDefaultCountryCode();
}
/** @return The list of supported countries sorted by their localized display names. */
public static List<DropdownKeyValue> getSupportedCountries() {
List<String> countryCodes = new ArrayList<>();
List<String> countryNames = new ArrayList<>();
List<DropdownKeyValue> countries = new ArrayList<>();
AutofillProfileBridgeJni.get().getSupportedCountries(countryCodes, countryNames);
for (int i = 0; i < countryCodes.size(); i++) {
countries.add(new DropdownKeyValue(countryCodes.get(i), countryNames.get(i)));
}
final Collator collator = Collator.getInstance(Locale.getDefault());
collator.setStrength(Collator.PRIMARY);
Collections.sort(countries, new Comparator<DropdownKeyValue>() {
@Override
public int compare(DropdownKeyValue lhs, DropdownKeyValue rhs) {
int result = collator.compare(lhs.getValue(), rhs.getValue());
if (result == 0) result = lhs.getKey().compareTo(rhs.getKey());
return result;
}
});
return countries;
}
/** @return The list of admin areas sorted by their localized display names. */
public static List<DropdownKeyValue> getAdminAreaDropdownList(
String[] adminAreaCodes, String[] adminAreaNames) {
List<DropdownKeyValue> adminAreas = new ArrayList<>();
for (int i = 0; i < adminAreaCodes.length; ++i) {
adminAreas.add(new DropdownKeyValue(adminAreaCodes[i], adminAreaNames[i]));
}
final Collator collator = Collator.getInstance(Locale.getDefault());
collator.setStrength(Collator.PRIMARY);
Collections.sort(adminAreas, new Comparator<DropdownKeyValue>() {
@Override
public int compare(DropdownKeyValue lhs, DropdownKeyValue rhs) {
// Sorted according to the admin area values, such as Quebec,
// rather than the admin area keys, such as QC.
return collator.compare(lhs.getValue(), rhs.getValue());
}
});
return adminAreas;
}
/** @return The list of required fields. COUNTRY is always included. RECIPIENT often omitted. */
public static List<Integer> getRequiredAddressFields(String countryCode) {
List<Integer> requiredFields = new ArrayList<>();
AutofillProfileBridgeJni.get().getRequiredFields(countryCode, requiredFields);
return requiredFields;
}
/**
* Description of an address editor input field.
*/
public static class AddressUiComponent {
/** The type of the field, e.g., AddressField.LOCALITY. */
public final int id;
/** The localized display label for the field, e.g., "City." */
public final String label;
/** Whether the field is required. */
public final boolean isRequired;
/** Whether the field takes up the full line.*/
public final boolean isFullLine;
/**
* Builds a description of an address editor input field.
*
* @param id The type of the field, .e.g., AddressField.LOCALITY.
* @param label The localized display label for the field, .e.g., "City."
* @param isRequired Whether the field is required.
* @param isFullLine Whether the field takes up the full line.
*/
public AddressUiComponent(int id, String label, boolean isRequired, boolean isFullLine) {
this.id = id;
this.label = label;
this.isRequired = isRequired;
this.isFullLine = isFullLine;
}
}
/**
* Returns the UI components for the CLDR countryCode and languageCode provided. If no language
* code is provided, the application's default locale is used instead. Also stores the
* currentBestLanguageCode, retrievable via getCurrentBestLanguageCode, to be used when saving
* an autofill profile.
*
* @param countryCode The CLDR code used to retrieve address components.
* @param languageCode The language code associated with the saved autofill profile that ui
* components are being retrieved for; can be null if ui components are
* being retrieved for a new profile.
* @return A list of address UI components. The ordering in the list specifies the order these
* components should appear in the UI.
*/
public List<AddressUiComponent> getAddressUiComponents(
String countryCode, String languageCode) {
List<Integer> componentIds = new ArrayList<>();
List<String> componentNames = new ArrayList<>();
List<Integer> componentRequired = new ArrayList<>();
List<Integer> componentLengths = new ArrayList<>();
List<AddressUiComponent> uiComponents = new ArrayList<>();
mCurrentBestLanguageCode =
AutofillProfileBridgeJni.get().getAddressUiComponents(countryCode, languageCode,
componentIds, componentNames, componentRequired, componentLengths);
for (int i = 0; i < componentIds.size(); i++) {
uiComponents.add(new AddressUiComponent(componentIds.get(i), componentNames.get(i),
componentRequired.get(i) == 1, componentLengths.get(i) == 1));
}
return uiComponents;
}
/**
* @return The language code associated with the most recently retrieved address ui components.
* Will return null if getAddressUiComponents() has not been called yet.
*/
public String getCurrentBestLanguageCode() {
return mCurrentBestLanguageCode;
}
@CalledByNative
private static void stringArrayToList(String[] array, List<String> list) {
for (String s : array) {
list.add(s);
}
}
@CalledByNative
private static void intArrayToList(int[] array, List<Integer> list) {
for (int s : array) {
list.add(s);
}
}
@CalledByNative
private static void showAutofillProfileSettings(WebContents webContents) {
RecordUserAction.record("AutofillAddressesViewed");
showSettingSubpage(webContents, AutofillProfilesFragment.class);
}
@CalledByNative
private static void showAutofillCreditCardSettings(WebContents webContents) {
RecordUserAction.record("AutofillCreditCardsViewed");
showSettingSubpage(webContents, AutofillPaymentMethodsFragment.class);
}
private static void showSettingSubpage(
WebContents webContents, Class<? extends Fragment> fragment) {
WeakReference<Activity> currentActivity =
webContents.getTopLevelNativeWindow().getActivity();
SettingsLauncher settingsLauncher = new SettingsLauncherImpl();
settingsLauncher.launchSettingsActivity(currentActivity.get(), fragment);
}
@NativeMethods
interface Natives {
String getDefaultCountryCode();
void getSupportedCountries(List<String> countryCodes, List<String> countryNames);
void getRequiredFields(String countryCode, List<Integer> requiredFields);
String getAddressUiComponents(String countryCode, String languageCode,
List<Integer> componentIds, List<String> componentNames,
List<Integer> componentRequired, List<Integer> componentLengths);
}
}