blob: 9ac04d7778bbbdc7eebd9ed0e0b1cab7ca5a6684 [file] [log] [blame]
// Copyright 2013 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;
import android.content.Context;
import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ResourceId;
import org.chromium.content_public.browser.WebContents;
import java.util.ArrayList;
import java.util.List;
/**
* Android wrapper of the PersonalDataManager which provides access from the Java
* layer.
*
* Only usable from the UI thread as it's primary purpose is for supporting the Android
* preferences UI.
*
* See chrome/browser/autofill/personal_data_manager.h for more details.
*/
@JNINamespace("autofill")
public class PersonalDataManager {
/**
* Observer of PersonalDataManager events.
*/
public interface PersonalDataManagerObserver {
/**
* Called when the data is changed.
*/
void onPersonalDataChanged();
}
/**
* Callback for full card request.
*/
public interface FullCardRequestDelegate {
/**
* Called when user provided the full card details, including the CVC and the full PAN.
*
* @param card The full card.
* @param cvc The CVC for the card.
*/
@CalledByNative("FullCardRequestDelegate")
void onFullCardDetails(CreditCard card, String cvc);
/**
* Called when user did not provide full card details.
*/
@CalledByNative("FullCardRequestDelegate")
void onFullCardError();
}
/**
* Autofill address information.
*/
public static class AutofillProfile {
private String mGUID;
private String mOrigin;
private boolean mIsLocal;
private String mFullName;
private String mCompanyName;
private String mStreetAddress;
private String mRegion;
private String mLocality;
private String mDependentLocality;
private String mPostalCode;
private String mSortingCode;
private String mCountryCode;
private String mPhoneNumber;
private String mEmailAddress;
private String mLabel;
private String mLanguageCode;
@CalledByNative("AutofillProfile")
public static AutofillProfile create(String guid, String origin, boolean isLocal,
String fullName, String companyName, String streetAddress, String region,
String locality, String dependentLocality, String postalCode, String sortingCode,
String country, String phoneNumber, String emailAddress, String languageCode) {
return new AutofillProfile(guid, origin, isLocal, fullName, companyName, streetAddress,
region, locality, dependentLocality, postalCode, sortingCode, country,
phoneNumber, emailAddress, languageCode);
}
public AutofillProfile(String guid, String origin, boolean isLocal, String fullName,
String companyName, String streetAddress, String region, String locality,
String dependentLocality, String postalCode, String sortingCode, String countryCode,
String phoneNumber, String emailAddress, String languageCode) {
mGUID = guid;
mOrigin = origin;
mIsLocal = isLocal;
mFullName = fullName;
mCompanyName = companyName;
mStreetAddress = streetAddress;
mRegion = region;
mLocality = locality;
mDependentLocality = dependentLocality;
mPostalCode = postalCode;
mSortingCode = sortingCode;
mCountryCode = countryCode;
mPhoneNumber = phoneNumber;
mEmailAddress = emailAddress;
mLanguageCode = languageCode;
}
/** TODO(estade): remove this constructor. */
@VisibleForTesting
public AutofillProfile(String guid, String origin, String fullName, String companyName,
String streetAddress, String region, String locality, String dependentLocality,
String postalCode, String sortingCode, String countryCode, String phoneNumber,
String emailAddress, String languageCode) {
mGUID = guid;
mOrigin = origin;
mIsLocal = true;
mFullName = fullName;
mCompanyName = companyName;
mStreetAddress = streetAddress;
mRegion = region;
mLocality = locality;
mDependentLocality = dependentLocality;
mPostalCode = postalCode;
mSortingCode = sortingCode;
mCountryCode = countryCode;
mPhoneNumber = phoneNumber;
mEmailAddress = emailAddress;
mLanguageCode = languageCode;
}
@CalledByNative("AutofillProfile")
public String getGUID() {
return mGUID;
}
@CalledByNative("AutofillProfile")
public String getOrigin() {
return mOrigin;
}
@CalledByNative("AutofillProfile")
public String getFullName() {
return mFullName;
}
@CalledByNative("AutofillProfile")
public String getCompanyName() {
return mCompanyName;
}
@CalledByNative("AutofillProfile")
public String getStreetAddress() {
return mStreetAddress;
}
@CalledByNative("AutofillProfile")
public String getRegion() {
return mRegion;
}
@CalledByNative("AutofillProfile")
public String getLocality() {
return mLocality;
}
@CalledByNative("AutofillProfile")
public String getDependentLocality() {
return mDependentLocality;
}
public String getLabel() {
return mLabel;
}
@CalledByNative("AutofillProfile")
public String getPostalCode() {
return mPostalCode;
}
@CalledByNative("AutofillProfile")
public String getSortingCode() {
return mSortingCode;
}
@CalledByNative("AutofillProfile")
public String getCountryCode() {
return mCountryCode;
}
@CalledByNative("AutofillProfile")
public String getPhoneNumber() {
return mPhoneNumber;
}
@CalledByNative("AutofillProfile")
public String getEmailAddress() {
return mEmailAddress;
}
@CalledByNative("AutofillProfile")
public String getLanguageCode() {
return mLanguageCode;
}
public boolean getIsLocal() {
return mIsLocal;
}
@VisibleForTesting
public void setGUID(String guid) {
mGUID = guid;
}
public void setLabel(String label) {
mLabel = label;
}
public void setOrigin(String origin) {
mOrigin = origin;
}
public void setFullName(String fullName) {
mFullName = fullName;
}
public void setCompanyName(String companyName) {
mCompanyName = companyName;
}
@VisibleForTesting
public void setStreetAddress(String streetAddress) {
mStreetAddress = streetAddress;
}
public void setRegion(String region) {
mRegion = region;
}
public void setLocality(String locality) {
mLocality = locality;
}
public void setDependentLocality(String dependentLocality) {
mDependentLocality = dependentLocality;
}
public void setPostalCode(String postalCode) {
mPostalCode = postalCode;
}
public void setSortingCode(String sortingCode) {
mSortingCode = sortingCode;
}
@VisibleForTesting
public void setCountryCode(String countryCode) {
mCountryCode = countryCode;
}
public void setPhoneNumber(String phoneNumber) {
mPhoneNumber = phoneNumber;
}
public void setEmailAddress(String emailAddress) {
mEmailAddress = emailAddress;
}
@VisibleForTesting
public void setLanguageCode(String languageCode) {
mLanguageCode = languageCode;
}
}
/**
* Autofill credit card information.
*/
public static class CreditCard {
// Note that while some of these fields are numbers, they're predominantly read,
// marshaled and compared as strings. To save conversions, we use strings everywhere.
private String mGUID;
private String mOrigin;
private boolean mIsLocal;
private boolean mIsCached;
private String mName;
private String mNumber;
private String mObfuscatedNumber;
private String mMonth;
private String mYear;
private String mBasicCardPaymentType;
private int mIssuerIconDrawableId;
@CalledByNative("CreditCard")
public static CreditCard create(String guid, String origin, boolean isLocal,
boolean isCached, String name, String number, String obfuscatedNumber, String month,
String year, String basicCardPaymentType, int enumeratedIconId) {
return new CreditCard(guid, origin, isLocal, isCached, name, number, obfuscatedNumber,
month, year, basicCardPaymentType,
ResourceId.mapToDrawableId(enumeratedIconId));
}
public CreditCard(String guid, String origin, boolean isLocal, boolean isCached,
String name, String number, String obfuscatedNumber, String month, String year,
String basicCardPaymentType, int issuerIconDrawableId) {
mGUID = guid;
mOrigin = origin;
mIsLocal = isLocal;
mIsCached = isCached;
mName = name;
mNumber = number;
mObfuscatedNumber = obfuscatedNumber;
mMonth = month;
mYear = year;
mBasicCardPaymentType = basicCardPaymentType;
mIssuerIconDrawableId = issuerIconDrawableId;
}
/** TODO(estade): remove this constructor. */
@VisibleForTesting
public CreditCard(String guid, String origin, String name, String number,
String obfuscatedNumber, String month, String year) {
mGUID = guid;
mOrigin = origin;
mIsLocal = true;
mIsCached = false;
mName = name;
mNumber = number;
mObfuscatedNumber = obfuscatedNumber;
mMonth = month;
mYear = year;
}
@CalledByNative("CreditCard")
public String getGUID() {
return mGUID;
}
@CalledByNative("CreditCard")
public String getOrigin() {
return mOrigin;
}
@CalledByNative("CreditCard")
public String getName() {
return mName;
}
@CalledByNative("CreditCard")
public String getNumber() {
return mNumber;
}
public String getObfuscatedNumber() {
return mObfuscatedNumber;
}
@CalledByNative("CreditCard")
public String getMonth() {
return mMonth;
}
@CalledByNative("CreditCard")
public String getYear() {
return mYear;
}
public String getFormattedExpirationDate(Context context) {
return getMonth()
+ context.getResources().getString(
R.string.autofill_card_unmask_expiration_date_separator) + getYear();
}
public boolean getIsLocal() {
return mIsLocal;
}
public boolean getIsCached() {
return mIsCached;
}
public String getBasicCardPaymentType() {
return mBasicCardPaymentType;
}
public int getIssuerIconDrawableId() {
return mIssuerIconDrawableId;
}
@VisibleForTesting
public void setGUID(String guid) {
mGUID = guid;
}
public void setOrigin(String origin) {
mOrigin = origin;
}
public void setName(String name) {
mName = name;
}
@VisibleForTesting
public void setNumber(String number) {
mNumber = number;
}
public void setObfuscatedNumber(String obfuscatedNumber) {
mObfuscatedNumber = obfuscatedNumber;
}
@VisibleForTesting
public void setMonth(String month) {
mMonth = month;
}
public void setYear(String year) {
mYear = year;
}
}
private static PersonalDataManager sManager;
public static PersonalDataManager getInstance() {
ThreadUtils.assertOnUiThread();
if (sManager == null) {
sManager = new PersonalDataManager();
}
return sManager;
}
private final long mPersonalDataManagerAndroid;
private final List<PersonalDataManagerObserver> mDataObservers =
new ArrayList<PersonalDataManagerObserver>();
private PersonalDataManager() {
// Note that this technically leaks the native object, however, PersonalDataManager
// is a singleton that lives forever and there's no clean shutdown of Chrome on Android
mPersonalDataManagerAndroid = nativeInit();
}
/**
* Called from native when template URL service is done loading.
*/
@CalledByNative
private void personalDataChanged() {
ThreadUtils.assertOnUiThread();
for (PersonalDataManagerObserver observer : mDataObservers) {
observer.onPersonalDataChanged();
}
}
/**
* Registers a PersonalDataManagerObserver on the native side.
*/
public void registerDataObserver(PersonalDataManagerObserver observer) {
ThreadUtils.assertOnUiThread();
assert !mDataObservers.contains(observer);
mDataObservers.add(observer);
}
/**
* Unregisters the provided observer.
*/
public void unregisterDataObserver(PersonalDataManagerObserver observer) {
ThreadUtils.assertOnUiThread();
assert (mDataObservers.size() > 0);
assert (mDataObservers.contains(observer));
mDataObservers.remove(observer);
}
public List<AutofillProfile> getProfiles() {
ThreadUtils.assertOnUiThread();
String[] profileLabels = nativeGetProfileLabels(mPersonalDataManagerAndroid);
int profileCount = nativeGetProfileCount(mPersonalDataManagerAndroid);
List<AutofillProfile> profiles = new ArrayList<AutofillProfile>(profileCount);
for (int i = 0; i < profileCount; i++) {
AutofillProfile profile = nativeGetProfileByIndex(mPersonalDataManagerAndroid, i);
profile.setLabel(profileLabels[i]);
profiles.add(profile);
}
return profiles;
}
public AutofillProfile getProfile(String guid) {
ThreadUtils.assertOnUiThread();
return nativeGetProfileByGUID(mPersonalDataManagerAndroid, guid);
}
public void deleteProfile(String guid) {
ThreadUtils.assertOnUiThread();
nativeRemoveByGUID(mPersonalDataManagerAndroid, guid);
}
public String setProfile(AutofillProfile profile) {
ThreadUtils.assertOnUiThread();
return nativeSetProfile(mPersonalDataManagerAndroid, profile);
}
public List<CreditCard> getCreditCards() {
ThreadUtils.assertOnUiThread();
int count = nativeGetCreditCardCount(mPersonalDataManagerAndroid);
List<CreditCard> cards = new ArrayList<CreditCard>(count);
for (int i = 0; i < count; i++) {
cards.add(nativeGetCreditCardByIndex(mPersonalDataManagerAndroid, i));
}
return cards;
}
public CreditCard getCreditCard(String guid) {
ThreadUtils.assertOnUiThread();
return nativeGetCreditCardByGUID(mPersonalDataManagerAndroid, guid);
}
public String setCreditCard(CreditCard card) {
ThreadUtils.assertOnUiThread();
return nativeSetCreditCard(mPersonalDataManagerAndroid, card);
}
public void deleteCreditCard(String guid) {
ThreadUtils.assertOnUiThread();
nativeRemoveByGUID(mPersonalDataManagerAndroid, guid);
}
public void clearUnmaskedCache(String guid) {
nativeClearUnmaskedCache(mPersonalDataManagerAndroid, guid);
}
public void unmaskCard(WebContents webContents, String guid, FullCardRequestDelegate delegate) {
nativeGetFullCardForPaymentRequest(
mPersonalDataManagerAndroid, webContents, guid, delegate);
}
/**
* @return Whether the Autofill feature is enabled.
*/
public static boolean isAutofillEnabled() {
return nativeIsAutofillEnabled();
}
/**
* Enables or disables the Autofill feature.
* @param enable True to disable Autofill, false otherwise.
*/
public static void setAutofillEnabled(boolean enable) {
nativeSetAutofillEnabled(enable);
}
/**
* @return Whether the Autofill feature is managed.
*/
public static boolean isAutofillManaged() {
return nativeIsAutofillManaged();
}
/**
* @return Whether the Payments integration feature is enabled.
*/
public static boolean isPaymentsIntegrationEnabled() {
return nativeIsPaymentsIntegrationEnabled();
}
/**
* Enables or disables the Payments integration.
* @param enable True to enable Payments data import.
*/
public static void setPaymentsIntegrationEnabled(boolean enable) {
nativeSetPaymentsIntegrationEnabled(enable);
}
private native long nativeInit();
private native int nativeGetProfileCount(long nativePersonalDataManagerAndroid);
private native String[] nativeGetProfileLabels(long nativePersonalDataManagerAndroid);
private native AutofillProfile nativeGetProfileByIndex(long nativePersonalDataManagerAndroid,
int index);
private native AutofillProfile nativeGetProfileByGUID(long nativePersonalDataManagerAndroid,
String guid);
private native String nativeSetProfile(long nativePersonalDataManagerAndroid,
AutofillProfile profile);
private native int nativeGetCreditCardCount(long nativePersonalDataManagerAndroid);
private native CreditCard nativeGetCreditCardByIndex(long nativePersonalDataManagerAndroid,
int index);
private native CreditCard nativeGetCreditCardByGUID(long nativePersonalDataManagerAndroid,
String guid);
private native String nativeSetCreditCard(long nativePersonalDataManagerAndroid,
CreditCard card);
private native void nativeRemoveByGUID(long nativePersonalDataManagerAndroid, String guid);
private native void nativeClearUnmaskedCache(
long nativePersonalDataManagerAndroid, String guid);
private native void nativeGetFullCardForPaymentRequest(long nativePersonalDataManagerAndroid,
WebContents webContents, String guid, FullCardRequestDelegate delegate);
private static native boolean nativeIsAutofillEnabled();
private static native void nativeSetAutofillEnabled(boolean enable);
private static native boolean nativeIsAutofillManaged();
private static native boolean nativeIsPaymentsIntegrationEnabled();
private static native void nativeSetPaymentsIntegrationEnabled(boolean enable);
private static native String nativeToCountryCode(String countryName);
}