improve implementation of Oreo autofill (#9), now supporting all Android/W3cHints, using all Keepass fields (if hints match field name). Make hint comparison code clearer and always compare case insensitive
This commit is contained in:
@@ -14,8 +14,8 @@ namespace keepass2android.services.AutofillBase
|
||||
public class AutofillFieldMetadata
|
||||
{
|
||||
public SaveDataType SaveType { get; set; }
|
||||
|
||||
public string[] AutofillHints { get; set; }
|
||||
|
||||
public string[] AutofillCanonicalHints { get; set; }
|
||||
|
||||
public AutofillId AutofillId { get; }
|
||||
public AutofillType AutofillType { get; }
|
||||
@@ -29,14 +29,14 @@ namespace keepass2android.services.AutofillBase
|
||||
AutofillOptions = view.GetAutofillOptions();
|
||||
Focused = view.IsFocused;
|
||||
var supportedHints = AutofillHintsHelper.FilterForSupportedHints(view.GetAutofillHints());
|
||||
var storedHints = AutofillHintsHelper.ConvertToStoredHints(supportedHints);
|
||||
SetHints(storedHints.ToArray());
|
||||
var canonicalHints = AutofillHintsHelper.ConvertToCanonicalHints(supportedHints);
|
||||
SetHints(canonicalHints.ToArray());
|
||||
|
||||
}
|
||||
|
||||
void SetHints(string[] value)
|
||||
{
|
||||
AutofillHints = value;
|
||||
AutofillCanonicalHints = value;
|
||||
UpdateSaveTypeFromHints();
|
||||
}
|
||||
|
||||
@@ -62,11 +62,11 @@ namespace keepass2android.services.AutofillBase
|
||||
{
|
||||
//TODO future add savetypes for W3cHints
|
||||
SaveType = 0;
|
||||
if (AutofillHints == null)
|
||||
if (AutofillCanonicalHints == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var hint in AutofillHints)
|
||||
foreach (var hint in AutofillCanonicalHints)
|
||||
{
|
||||
switch (hint)
|
||||
{
|
||||
|
@@ -12,17 +12,19 @@ namespace keepass2android.services.AutofillBase
|
||||
public class AutofillFieldMetadataCollection
|
||||
{
|
||||
List<AutofillId> AutofillIds = new List<AutofillId>();
|
||||
Dictionary<string, List<AutofillFieldMetadata>> AutofillHintsToFieldsMap = new Dictionary<string, List<AutofillFieldMetadata>>();
|
||||
public List<string> AllAutofillHints { get; }
|
||||
public List<string> FocusedAutofillHints { get; }
|
||||
|
||||
Dictionary<string, List<AutofillFieldMetadata>> AutofillCanonicalHintsToFieldsMap = new Dictionary<string, List<AutofillFieldMetadata>>();
|
||||
|
||||
public List<string> AllAutofillCanonicalHints { get; }
|
||||
public List<string> FocusedAutofillCanonicalHints { get; }
|
||||
int Size = 0;
|
||||
public SaveDataType SaveType { get; set; }
|
||||
|
||||
public AutofillFieldMetadataCollection()
|
||||
{
|
||||
SaveType = 0;
|
||||
FocusedAutofillHints = new List<string>();
|
||||
AllAutofillHints = new List<string>();
|
||||
FocusedAutofillCanonicalHints = new List<string>();
|
||||
AllAutofillCanonicalHints = new List<string>();
|
||||
}
|
||||
|
||||
public void Add(AutofillFieldMetadata autofillFieldMetadata)
|
||||
@@ -30,19 +32,19 @@ namespace keepass2android.services.AutofillBase
|
||||
SaveType |= autofillFieldMetadata.SaveType;
|
||||
Size++;
|
||||
AutofillIds.Add(autofillFieldMetadata.AutofillId);
|
||||
var hintsList = autofillFieldMetadata.AutofillHints;
|
||||
AllAutofillHints.AddRange(hintsList);
|
||||
var hintsList = autofillFieldMetadata.AutofillCanonicalHints;
|
||||
AllAutofillCanonicalHints.AddRange(hintsList);
|
||||
if (autofillFieldMetadata.Focused)
|
||||
{
|
||||
FocusedAutofillHints.AddRange(hintsList);
|
||||
FocusedAutofillCanonicalHints.AddRange(hintsList);
|
||||
}
|
||||
foreach (var hint in autofillFieldMetadata.AutofillHints)
|
||||
foreach (var hint in autofillFieldMetadata.AutofillCanonicalHints)
|
||||
{
|
||||
if (!AutofillHintsToFieldsMap.ContainsKey(hint))
|
||||
if (!AutofillCanonicalHintsToFieldsMap.ContainsKey(hint))
|
||||
{
|
||||
AutofillHintsToFieldsMap.Add(hint, new List<AutofillFieldMetadata>());
|
||||
AutofillCanonicalHintsToFieldsMap.Add(hint, new List<AutofillFieldMetadata>());
|
||||
}
|
||||
AutofillHintsToFieldsMap[hint].Add(autofillFieldMetadata);
|
||||
AutofillCanonicalHintsToFieldsMap[hint].Add(autofillFieldMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,9 +53,17 @@ namespace keepass2android.services.AutofillBase
|
||||
return AutofillIds.ToArray();
|
||||
}
|
||||
|
||||
public List<AutofillFieldMetadata> GetFieldsForHint(String hint)
|
||||
/// <summary>
|
||||
/// returns the fields for the given hint or an empty list.
|
||||
/// </summary>
|
||||
public List<AutofillFieldMetadata> GetFieldsForHint(String canonicalHint)
|
||||
{
|
||||
return AutofillHintsToFieldsMap[hint];
|
||||
List<AutofillFieldMetadata> result;
|
||||
if (!AutofillCanonicalHintsToFieldsMap.TryGetValue(canonicalHint, out result))
|
||||
{
|
||||
result = new List<AutofillFieldMetadata>();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -16,16 +16,76 @@ namespace keepass2android.services.AutofillBase
|
||||
{
|
||||
class AutofillHintsHelper
|
||||
{
|
||||
private static readonly HashSet<string> validHints = new HashSet<string>()
|
||||
private static readonly HashSet<string> _allSupportedHints = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
View.AutofillHintUsername,
|
||||
View.AutofillHintCreditCardExpirationDate,
|
||||
View.AutofillHintCreditCardExpirationDay,
|
||||
View.AutofillHintCreditCardExpirationMonth,
|
||||
View.AutofillHintCreditCardExpirationYear,
|
||||
View.AutofillHintCreditCardNumber,
|
||||
View.AutofillHintCreditCardSecurityCode,
|
||||
View.AutofillHintEmailAddress,
|
||||
View.AutofillHintPhone,
|
||||
View.AutofillHintName,
|
||||
View.AutofillHintPassword,
|
||||
View.AutofillHintPostalAddress,
|
||||
View.AutofillHintPostalCode,
|
||||
View.AutofillHintUsername,
|
||||
W3cHints.HONORIFIC_PREFIX,
|
||||
W3cHints.NAME,
|
||||
W3cHints.GIVEN_NAME,
|
||||
W3cHints.ADDITIONAL_NAME,
|
||||
W3cHints.FAMILY_NAME,
|
||||
W3cHints.HONORIFIC_SUFFIX,
|
||||
W3cHints.USERNAME,
|
||||
W3cHints.NEW_PASSWORD,
|
||||
W3cHints.CURRENT_PASSWORD,
|
||||
W3cHints.NEW_PASSWORD
|
||||
W3cHints.ORGANIZATION_TITLE,
|
||||
W3cHints.ORGANIZATION,
|
||||
W3cHints.STREET_ADDRESS,
|
||||
W3cHints.ADDRESS_LINE1,
|
||||
W3cHints.ADDRESS_LINE2,
|
||||
W3cHints.ADDRESS_LINE3,
|
||||
W3cHints.ADDRESS_LEVEL4,
|
||||
W3cHints.ADDRESS_LEVEL3,
|
||||
W3cHints.ADDRESS_LEVEL2,
|
||||
W3cHints.ADDRESS_LEVEL1,
|
||||
W3cHints.COUNTRY,
|
||||
W3cHints.COUNTRY_NAME,
|
||||
W3cHints.POSTAL_CODE,
|
||||
W3cHints.CC_NAME,
|
||||
W3cHints.CC_GIVEN_NAME,
|
||||
W3cHints.CC_ADDITIONAL_NAME,
|
||||
W3cHints.CC_FAMILY_NAME,
|
||||
W3cHints.CC_NUMBER,
|
||||
W3cHints.CC_EXPIRATION,
|
||||
W3cHints.CC_EXPIRATION_MONTH,
|
||||
W3cHints.CC_EXPIRATION_YEAR,
|
||||
W3cHints.CC_CSC,
|
||||
W3cHints.CC_TYPE,
|
||||
W3cHints.TRANSACTION_CURRENCY,
|
||||
W3cHints.TRANSACTION_AMOUNT,
|
||||
W3cHints.LANGUAGE,
|
||||
W3cHints.BDAY,
|
||||
W3cHints.BDAY_DAY,
|
||||
W3cHints.BDAY_MONTH,
|
||||
W3cHints.BDAY_YEAR,
|
||||
W3cHints.SEX,
|
||||
W3cHints.URL,
|
||||
W3cHints.PHOTO,
|
||||
W3cHints.TEL,
|
||||
W3cHints.TEL_COUNTRY_CODE,
|
||||
W3cHints.TEL_NATIONAL,
|
||||
W3cHints.TEL_AREA_CODE,
|
||||
W3cHints.TEL_LOCAL,
|
||||
W3cHints.TEL_LOCAL_PREFIX,
|
||||
W3cHints.TEL_LOCAL_SUFFIX,
|
||||
W3cHints.TEL_EXTENSION,
|
||||
W3cHints.EMAIL,
|
||||
W3cHints.IMPP,
|
||||
};
|
||||
|
||||
private static readonly Dictionary<string, string> hintReplacements= new Dictionary<string, string>()
|
||||
private static readonly Dictionary<string, string> hintToCanonicalReplacement= new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{W3cHints.EMAIL, View.AutofillHintEmailAddress},
|
||||
{W3cHints.USERNAME, View.AutofillHintUsername},
|
||||
@@ -41,9 +101,9 @@ namespace keepass2android.services.AutofillBase
|
||||
|
||||
};
|
||||
|
||||
public static bool IsValidHint(string hint)
|
||||
public static bool IsSupportedHint(string hint)
|
||||
{
|
||||
return validHints.Contains(hint);
|
||||
return _allSupportedHints.Contains(hint);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +113,7 @@ namespace keepass2android.services.AutofillBase
|
||||
int i = 0;
|
||||
foreach (var hint in hints)
|
||||
{
|
||||
if (IsValidHint(hint))
|
||||
if (IsSupportedHint(hint))
|
||||
{
|
||||
filteredHints[i++] = hint;
|
||||
}
|
||||
@@ -69,16 +129,18 @@ namespace keepass2android.services.AutofillBase
|
||||
|
||||
|
||||
|
||||
public static List<string> ConvertToStoredHints(string[] supportedHints)
|
||||
/// <summary>
|
||||
/// transforms hints by replacing some W3cHints by their Android counterparts and transforming everything to lowercase
|
||||
/// </summary>
|
||||
public static List<string> ConvertToCanonicalHints(string[] supportedHints)
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
foreach (string hint in supportedHints)
|
||||
{
|
||||
string storedHint = hint;
|
||||
if (hintReplacements.ContainsKey(hint))
|
||||
storedHint = hintReplacements[hint];
|
||||
result.Add(storedHint);
|
||||
|
||||
string canonicalHint;
|
||||
if (!hintToCanonicalReplacement.TryGetValue(hint, out canonicalHint))
|
||||
canonicalHint = hint;
|
||||
result.Add(canonicalHint.ToLower());
|
||||
}
|
||||
return result;
|
||||
|
||||
|
@@ -1,25 +1,89 @@
|
||||
using Android.App.Assist;
|
||||
using System.Collections.Generic;
|
||||
using Android.App.Assist;
|
||||
using Android.Views.Autofill;
|
||||
|
||||
namespace keepass2android.services.AutofillBase.model
|
||||
{
|
||||
public class FilledAutofillField
|
||||
{
|
||||
public string TextValue { get; set; }
|
||||
private string[] _autofillHints;
|
||||
public string TextValue { get; set; }
|
||||
public long? DateValue { get; set; }
|
||||
public bool? ToggleValue { get; set; }
|
||||
|
||||
public string[] AutofillHints { get; set; }
|
||||
|
||||
|
||||
public FilledAutofillField()
|
||||
/// <summary>
|
||||
/// returns the autofill hints for the filled field. These are always lowercased for simpler string comparison.
|
||||
/// </summary>
|
||||
public string[] AutofillHints
|
||||
{
|
||||
get
|
||||
{
|
||||
return _autofillHints;
|
||||
}
|
||||
set
|
||||
{
|
||||
_autofillHints = value;
|
||||
for (int i = 0; i < _autofillHints.Length; i++)
|
||||
_autofillHints[i] = _autofillHints[i].ToLower();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Protected { get; set; }
|
||||
|
||||
|
||||
public FilledAutofillField()
|
||||
{}
|
||||
|
||||
public FilledAutofillField(AssistStructure.ViewNode viewNode)
|
||||
{
|
||||
|
||||
string[] rawHints = AutofillHintsHelper.FilterForSupportedHints(viewNode.GetAutofillHints());
|
||||
List<string> hintList = new List<string>();
|
||||
|
||||
string nextHint = null;
|
||||
for (int i = 0; i < rawHints.Length; i++)
|
||||
{
|
||||
string hint = rawHints[i];
|
||||
if (i < rawHints.Length - 1)
|
||||
{
|
||||
nextHint = rawHints[i + 1];
|
||||
}
|
||||
// First convert the compound W3C autofill hints
|
||||
if (W3cHints.isW3cSectionPrefix(hint) && i < rawHints.Length - 1)
|
||||
{
|
||||
hint = rawHints[++i];
|
||||
CommonUtil.logd($"Hint is a W3C section prefix; using {hint} instead");
|
||||
if (i < rawHints.Length - 1)
|
||||
{
|
||||
nextHint = rawHints[i + 1];
|
||||
}
|
||||
}
|
||||
if (W3cHints.isW3cTypePrefix(hint) && nextHint != null && W3cHints.isW3cTypeHint(nextHint))
|
||||
{
|
||||
hint = nextHint;
|
||||
i++;
|
||||
CommonUtil.logd($"Hint is a W3C type prefix; using {hint} instead");
|
||||
}
|
||||
if (W3cHints.isW3cAddressType(hint) && nextHint != null)
|
||||
{
|
||||
hint = nextHint;
|
||||
i++;
|
||||
CommonUtil.logd($"Hint is a W3C address prefix; using {hint} instead");
|
||||
}
|
||||
|
||||
/*public FilledAutofillField(AssistStructure.ViewNode viewNode)
|
||||
{
|
||||
AutofillHintsHelper = AutofillHelper.FilterForSupportedHints(viewNode.GetAutofillHints());
|
||||
// Then check if the "actual" hint is supported.
|
||||
if (AutofillHintsHelper.IsSupportedHint(hint))
|
||||
{
|
||||
hintList.Add(hint);
|
||||
}
|
||||
else
|
||||
{
|
||||
CommonUtil.loge($"Invalid hint: {rawHints[i]}");
|
||||
}
|
||||
}
|
||||
AutofillHints = hintList.ToArray();
|
||||
|
||||
//TODO port updated FilledAutofillField?
|
||||
//TODO port updated FilledAutofillField
|
||||
AutofillValue autofillValue = viewNode.AutofillValue;
|
||||
if (autofillValue != null)
|
||||
{
|
||||
@@ -41,9 +105,9 @@ namespace keepass2android.services.AutofillBase.model
|
||||
TextValue = autofillValue.TextValue;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public bool IsNull()
|
||||
public bool IsNull()
|
||||
{
|
||||
return TextValue == null && DateValue == null && ToggleValue == null;
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Android.Service.Autofill;
|
||||
using Android.Util;
|
||||
using Android.Views;
|
||||
@@ -12,121 +13,48 @@ namespace keepass2android.services.AutofillBase.model
|
||||
/// </summary>
|
||||
public class FilledAutofillFieldCollection
|
||||
{
|
||||
public Dictionary<string, FilledAutofillField> HintMap { get; set; }
|
||||
public Dictionary<string, FilledAutofillField> HintMap { get; }
|
||||
public string DatasetName { get; set; }
|
||||
|
||||
public FilledAutofillFieldCollection(Dictionary<string, FilledAutofillField> hintMap, string datasetName = "")
|
||||
{
|
||||
HintMap = hintMap;
|
||||
//recreate hint map making sure we compare case insensitive
|
||||
HintMap = BuildHintMap();
|
||||
foreach (var p in hintMap)
|
||||
HintMap.Add(p.Key, p.Value);
|
||||
DatasetName = datasetName;
|
||||
}
|
||||
|
||||
public FilledAutofillFieldCollection() : this(new Dictionary<string, FilledAutofillField>())
|
||||
public FilledAutofillFieldCollection() : this(BuildHintMap())
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
private static Dictionary<string, FilledAutofillField> BuildHintMap()
|
||||
{
|
||||
return new Dictionary<string, FilledAutofillField>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a filledAutofillField to the collection, indexed by all of its hints.
|
||||
/// </summary>
|
||||
/// <returns>The add.</returns>
|
||||
/// <param name="filledAutofillField">Filled autofill field.</param>
|
||||
public void Add(FilledAutofillField filledAutofillField)
|
||||
{
|
||||
string[] autofillHints = filledAutofillField.AutofillHints;
|
||||
|
||||
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];
|
||||
CommonUtil.logd($"Hint is a W3C section prefix; using {hint} instead");
|
||||
if (i < autofillHints.Length - 1)
|
||||
{
|
||||
nextHint = autofillHints[i + 1];
|
||||
}
|
||||
}
|
||||
if (isW3cTypePrefix(hint) && nextHint != null && isW3cTypeHint(nextHint))
|
||||
{
|
||||
hint = nextHint;
|
||||
i++;
|
||||
CommonUtil.logd($"Hint is a W3C type prefix; using {hint} instead");
|
||||
}
|
||||
if (isW3cAddressType(hint) && nextHint != null)
|
||||
{
|
||||
hint = nextHint;
|
||||
i++;
|
||||
CommonUtil.logd($"Hint is a W3C address prefix; using {hint} instead");
|
||||
}
|
||||
|
||||
// Then check if the "actual" hint is supported.
|
||||
if (AutofillHintsHelper.IsValidHint(hint))
|
||||
foreach (string hint in filledAutofillField.AutofillHints)
|
||||
{
|
||||
if (AutofillHintsHelper.IsSupportedHint(hint))
|
||||
{
|
||||
HintMap.Add(hint, filledAutofillField);
|
||||
}
|
||||
else
|
||||
{
|
||||
CommonUtil.loge($"Invalid hint: {autofillHints[i]}");
|
||||
CommonUtil.loge($"Invalid hint: {hint}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static bool isW3cSectionPrefix(string hint)
|
||||
{
|
||||
return hint.StartsWith(W3cHints.PREFIX_SECTION);
|
||||
}
|
||||
|
||||
private static bool isW3cAddressType(string hint)
|
||||
{
|
||||
switch (hint)
|
||||
{
|
||||
case W3cHints.SHIPPING:
|
||||
case W3cHints.BILLING:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool 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 bool 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;
|
||||
}
|
||||
Log.Warn(CommonUtil.Tag, "Invalid W3C type hint: " + hint);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates a Dataset.Builder with appropriate values for each AutofillId
|
||||
/// in a AutofillFieldMetadataCollection.
|
||||
@@ -142,16 +70,10 @@ namespace keepass2android.services.AutofillBase.model
|
||||
public bool ApplyToFields(AutofillFieldMetadataCollection autofillFieldMetadataCollection, Dataset.Builder datasetBuilder)
|
||||
{
|
||||
bool setValueAtLeastOnce = false;
|
||||
List<string> allHints = autofillFieldMetadataCollection.AllAutofillHints;
|
||||
for (int hintIndex = 0; hintIndex < allHints.Count; hintIndex++)
|
||||
|
||||
foreach (string hint in autofillFieldMetadataCollection.AllAutofillCanonicalHints)
|
||||
{
|
||||
string hint = allHints[hintIndex];
|
||||
List<AutofillFieldMetadata> fillableAutofillFields = autofillFieldMetadataCollection.GetFieldsForHint(hint);
|
||||
if (fillableAutofillFields == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach (AutofillFieldMetadata autofillFieldMetadata in fillableAutofillFields)
|
||||
foreach (AutofillFieldMetadata autofillFieldMetadata in autofillFieldMetadataCollection.GetFieldsForHint(hint))
|
||||
{
|
||||
FilledAutofillField filledAutofillField;
|
||||
if (!HintMap.TryGetValue(hint, out filledAutofillField) || (filledAutofillField == null))
|
||||
|
@@ -1,4 +1,6 @@
|
||||
namespace keepass2android.services.AutofillBase.model
|
||||
using Android.Util;
|
||||
|
||||
namespace keepass2android.services.AutofillBase.model
|
||||
{
|
||||
public class W3cHints
|
||||
{
|
||||
@@ -70,5 +72,56 @@
|
||||
private W3cHints()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static bool isW3cSectionPrefix(string hint)
|
||||
{
|
||||
return hint.ToLower().StartsWith(W3cHints.PREFIX_SECTION);
|
||||
}
|
||||
|
||||
public static bool isW3cAddressType(string hint)
|
||||
{
|
||||
switch (hint.ToLower())
|
||||
{
|
||||
case W3cHints.SHIPPING:
|
||||
case W3cHints.BILLING:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool isW3cTypePrefix(string hint)
|
||||
{
|
||||
switch (hint.ToLower())
|
||||
{
|
||||
case W3cHints.PREFIX_WORK:
|
||||
case W3cHints.PREFIX_FAX:
|
||||
case W3cHints.PREFIX_HOME:
|
||||
case W3cHints.PREFIX_PAGER:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool isW3cTypeHint(string hint)
|
||||
{
|
||||
switch (hint.ToLower())
|
||||
{
|
||||
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;
|
||||
}
|
||||
Log.Warn(CommonUtil.Tag, "Invalid W3C type hint: " + hint);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -41,32 +41,44 @@ namespace keepass2android.services.Kp2aAutofill
|
||||
if (!App.Kp2a.GetDb().Loaded || (App.Kp2a.QuickLocked))
|
||||
return null;
|
||||
|
||||
string username = App.Kp2a.GetDb().LastOpenedEntry.Entry.Strings.ReadSafe(PwDefs.UserNameField);
|
||||
string password = App.Kp2a.GetDb().LastOpenedEntry.Entry.Strings.ReadSafe(PwDefs.PasswordField);
|
||||
|
||||
FilledAutofillField pwdField =
|
||||
new FilledAutofillField
|
||||
{
|
||||
AutofillHints = new[] {View.AutofillHintPassword},
|
||||
TextValue = password
|
||||
};
|
||||
|
||||
FilledAutofillField userField = new FilledAutofillField
|
||||
{
|
||||
AutofillHints = new[] {View.AutofillHintUsername},
|
||||
TextValue = username
|
||||
};
|
||||
|
||||
FilledAutofillFieldCollection fieldCollection = new FilledAutofillFieldCollection();
|
||||
fieldCollection.HintMap = new Dictionary<string, FilledAutofillField>();
|
||||
fieldCollection.Add(userField);
|
||||
fieldCollection.Add(pwdField);
|
||||
|
||||
fieldCollection.DatasetName = App.Kp2a.GetDb().LastOpenedEntry.Entry.Strings.ReadSafe(PwDefs.TitleField);
|
||||
var pwEntry = App.Kp2a.GetDb().LastOpenedEntry.Entry;
|
||||
foreach (string key in pwEntry.Strings.GetKeys())
|
||||
{
|
||||
FilledAutofillField field =
|
||||
new FilledAutofillField
|
||||
{
|
||||
AutofillHints = new[] { GetCanonicalHintFromKp2aField(pwEntry, key) },
|
||||
TextValue = pwEntry.Strings.ReadSafe(key),
|
||||
Protected = pwEntry.Strings.Get(key).IsProtected
|
||||
};
|
||||
fieldCollection.Add(field);
|
||||
}
|
||||
//TODO add support for Keepass templates
|
||||
//TODO add values like expiration?
|
||||
//TODO if cc-exp is there, also set cc-exp-month etc.
|
||||
|
||||
fieldCollection.DatasetName = pwEntry.Strings.ReadSafe(PwDefs.TitleField);
|
||||
|
||||
return fieldCollection;
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, string> keyToHint = new Dictionary<string, string>()
|
||||
{
|
||||
{PwDefs.UserNameField, View.AutofillHintUsername },
|
||||
{PwDefs.PasswordField, View.AutofillHintPassword },
|
||||
{PwDefs.UrlField, W3cHints.URL },
|
||||
};
|
||||
|
||||
private string GetCanonicalHintFromKp2aField(PwEntry pwEntry, string key)
|
||||
{
|
||||
if (!keyToHint.TryGetValue(key, out string result))
|
||||
result = key;
|
||||
result = result.ToLower();
|
||||
return result;
|
||||
}
|
||||
|
||||
public override IAutofillIntentBuilder IntentBuilder => new Kp2aAutofillIntentBuilder();
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user