hintMap) {
mHintMap = hintMap;
mDatasetName = datasetName;
}
private static boolean isW3cSectionPrefix(String hint) {
return hint.startsWith(W3cHints.PREFIX_SECTION);
}
private static boolean isW3cAddressType(String hint) {
switch (hint) {
case W3cHints.SHIPPING:
case W3cHints.BILLING:
return true;
}
return false;
}
private static boolean isW3cTypePrefix(String hint) {
switch (hint) {
case W3cHints.PREFIX_WORK:
case W3cHints.PREFIX_FAX:
case W3cHints.PREFIX_HOME:
case W3cHints.PREFIX_PAGER:
return true;
}
return false;
}
private static boolean isW3cTypeHint(String hint) {
switch (hint) {
case W3cHints.TEL:
case W3cHints.TEL_COUNTRY_CODE:
case W3cHints.TEL_NATIONAL:
case W3cHints.TEL_AREA_CODE:
case W3cHints.TEL_LOCAL:
case W3cHints.TEL_LOCAL_PREFIX:
case W3cHints.TEL_LOCAL_SUFFIX:
case W3cHints.TEL_EXTENSION:
case W3cHints.EMAIL:
case W3cHints.IMPP:
return true;
}
logw("Invalid W3C type hint: %s", hint);
return false;
}
/**
* Returns the name of the {@link Dataset}.
*/
public String getDatasetName() {
return mDatasetName;
}
/**
* Sets the {@link Dataset} name.
*/
public void setDatasetName(String datasetName) {
mDatasetName = datasetName;
}
/**
* Adds a {@code FilledAutofillField} to the collection, indexed by all of its hints.
*/
public void add(@NonNull FilledAutofillField filledAutofillField) {
String[] autofillHints = filledAutofillField.getAutofillHints();
String nextHint = null;
for (int i = 0; i < autofillHints.length; i++) {
String hint = autofillHints[i];
if (i < autofillHints.length - 1) {
nextHint = autofillHints[i + 1];
}
// First convert the compound W3C autofill hints
if (isW3cSectionPrefix(hint) && i < autofillHints.length - 1) {
hint = autofillHints[++i];
logd("Hint is a W3C section prefix; using %s instead", hint);
if (i < autofillHints.length - 1) {
nextHint = autofillHints[i + 1];
}
}
if (isW3cTypePrefix(hint) && nextHint != null && isW3cTypeHint(nextHint)) {
hint = nextHint;
i++;
logd("Hint is a W3C type prefix; using %s instead", hint);
}
if (isW3cAddressType(hint) && nextHint != null) {
hint = nextHint;
i++;
logd("Hint is a W3C address prefix; using %s instead", hint);
}
// Then check if the "actual" hint is supported.
if (AutofillHints.isValidHint(hint)) {
mHintMap.put(hint, filledAutofillField);
} else {
loge("Invalid hint: %s", autofillHints[i]);
}
}
}
/**
* Populates a {@link Dataset.Builder} with appropriate values for each {@link AutofillId}
* in a {@code AutofillFieldMetadataCollection}.
*
* In other words, it constructs an autofill
* {@link Dataset.Builder} by applying saved values (from this {@code FilledAutofillFieldCollection})
* to Views specified in a {@code AutofillFieldMetadataCollection}, which represents the current
* page the user is on.
*/
public boolean applyToFields(AutofillFieldMetadataCollection autofillFieldMetadataCollection,
Dataset.Builder datasetBuilder) {
boolean setValueAtLeastOnce = false;
List allHints = autofillFieldMetadataCollection.getAllHints();
for (int hintIndex = 0; hintIndex < allHints.size(); hintIndex++) {
String hint = allHints.get(hintIndex);
List fillableAutofillFields =
autofillFieldMetadataCollection.getFieldsForHint(hint);
if (fillableAutofillFields == null) {
continue;
}
for (int autofillFieldIndex = 0; autofillFieldIndex < fillableAutofillFields.size(); autofillFieldIndex++) {
FilledAutofillField filledAutofillField = mHintMap.get(hint);
if (filledAutofillField == null) {
continue;
}
AutofillFieldMetadata autofillFieldMetadata = fillableAutofillFields.get(autofillFieldIndex);
AutofillId autofillId = autofillFieldMetadata.getId();
int autofillType = autofillFieldMetadata.getAutofillType();
switch (autofillType) {
case View.AUTOFILL_TYPE_LIST:
int listValue = autofillFieldMetadata.getAutofillOptionIndex(filledAutofillField.getTextValue());
if (listValue != -1) {
datasetBuilder.setValue(autofillId, AutofillValue.forList(listValue));
setValueAtLeastOnce = true;
}
break;
case View.AUTOFILL_TYPE_DATE:
Long dateValue = filledAutofillField.getDateValue();
if (dateValue != null) {
datasetBuilder.setValue(autofillId, AutofillValue.forDate(dateValue));
setValueAtLeastOnce = true;
}
break;
case View.AUTOFILL_TYPE_TEXT:
String textValue = filledAutofillField.getTextValue();
if (textValue != null) {
datasetBuilder.setValue(autofillId, AutofillValue.forText(textValue));
setValueAtLeastOnce = true;
}
break;
case View.AUTOFILL_TYPE_TOGGLE:
Boolean toggleValue = filledAutofillField.getToggleValue();
if (toggleValue != null) {
datasetBuilder.setValue(autofillId, AutofillValue.forToggle(toggleValue));
setValueAtLeastOnce = true;
}
break;
case View.AUTOFILL_TYPE_NONE:
default:
logw("Invalid autofill type - %d", autofillType);
break;
}
}
}
return setValueAtLeastOnce;
}
/**
* Takes in a list of autofill hints (autofillHints), usually associated with a View or set of
* Views. Returns whether any of the filled fields on the page have at least 1 of these
* autofillHints.
*/
public boolean helpsWithHints(List autofillHints) {
for (int i = 0; i < autofillHints.size(); i++) {
String autofillHint = autofillHints.get(i);
if (mHintMap.containsKey(autofillHint) && !mHintMap.get(autofillHint).isNull()) {
return true;
}
}
return false;
}
}