further improvements for Autofill for usability with Firefox (see https://github.com/PhilippC/keepass2android/issues/1399), also fix security bug (closes https://github.com/PhilippC/keepass2android/issues/1527)

This commit is contained in:
Philipp Crocoll
2021-01-10 15:25:26 +01:00
parent 730af8b9ac
commit 3fb358ca85
6 changed files with 77 additions and 28 deletions

View File

@@ -24,18 +24,23 @@ namespace keepass2android.services.AutofillBase
public static Dataset NewDataset(Context context,
AutofillFieldMetadataCollection autofillFields, FilledAutofillFieldCollection filledAutofillFieldCollection, IAutofillIntentBuilder intentBuilder)
{
var datasetName = filledAutofillFieldCollection.DatasetName;
if (datasetName != null)
var datasetName = filledAutofillFieldCollection.DatasetName ?? "[noname]";
var datasetBuilder = new Dataset.Builder(NewRemoteViews(context.PackageName, datasetName, intentBuilder.AppIconResource));
datasetBuilder.SetId(datasetName);
var setValueAtLeastOnce = filledAutofillFieldCollection.ApplyToFields(autofillFields, datasetBuilder);
if (setValueAtLeastOnce)
{
var datasetBuilder = new Dataset.Builder(NewRemoteViews(context.PackageName, datasetName, intentBuilder.AppIconResource));
datasetBuilder.SetId(datasetName);
var setValueAtLeastOnce = filledAutofillFieldCollection.ApplyToFields(autofillFields, datasetBuilder);
if (setValueAtLeastOnce)
{
return datasetBuilder.Build();
}
return datasetBuilder.Build();
}
else
{
Kp2aLog.Log("Failed to set at least one value. #fields="+autofillFields.GetAutofillIds().Length + " " + autofillFields.FocusedAutofillCanonicalHints);
}
return null;
}

View File

@@ -252,5 +252,18 @@ namespace keepass2android.services.AutofillBase
return filteredCollection;
}
public static FilledAutofillFieldCollection FilterForPartition(FilledAutofillFieldCollection filledAutofillFieldCollection, List<string> autofillFieldsFocusedAutofillCanonicalHints)
{
//only apply partition data if we have FocusedAutofillCanonicalHints. This may be empty on buggy Firefox.
if (autofillFieldsFocusedAutofillCanonicalHints.Any())
{
int partitionIndex = AutofillHintsHelper.GetPartitionIndex(autofillFieldsFocusedAutofillCanonicalHints.FirstOrDefault());
return AutofillHintsHelper.FilterForPartition(filledAutofillFieldCollection, partitionIndex);
}
return filledAutofillFieldCollection;
}
}
}

View File

@@ -102,7 +102,8 @@ namespace keepass2android.services.AutofillBase
cancellationSignal.CancelEvent += (sender, e) =>
{
Log.Warn(CommonUtil.Tag, "Cancel autofill not implemented yet.");
Kp2aLog.Log("Cancel autofill not implemented yet.");
_lock.Set(false);
};
// Parse AutoFill data in Activity
StructureParser.AutofillTargetId query = null;
@@ -134,9 +135,10 @@ namespace keepass2android.services.AutofillBase
//domain and package are compatible. Use Domain if available and package otherwise. Can fill without warning.
foreach (var entryDataset in BuildEntryDatasets(query.DomainOrPackage, query.WebDomain,
query.PackageName,
autofillIds, parser, DisplayWarning.None)
autofillIds, parser, DisplayWarning.None).Where(ds => ds != null)
)
{
responseBuilder.AddDataset(entryDataset);
hasEntryDataset = true;
}
@@ -171,13 +173,19 @@ namespace keepass2android.services.AutofillBase
}
Kp2aLog.Log("return autofill success");
callback.OnSuccess(responseBuilder.Build());
}
else
{
Kp2aLog.Log("cannot autofill");
callback.OnSuccess(null);
}
}
else
{
Kp2aLog.Log("Ignoring onFillRequest as there is another request going on.");
}
}
private List<Dataset> BuildEntryDatasets(string query, string queryDomain, string queryPackage, AutofillId[] autofillIds, StructureParser parser,
@@ -193,12 +201,9 @@ namespace keepass2android.services.AutofillBase
if (warning == DisplayWarning.None)
{
//can return an actual dataset
int partitionIndex =
AutofillHintsHelper.GetPartitionIndex(parser.AutofillFields.FocusedAutofillCanonicalHints
.FirstOrDefault());
FilledAutofillFieldCollection partitionData =
AutofillHintsHelper.FilterForPartition(filledAutofillFieldCollection, partitionIndex);
AutofillHintsHelper.FilterForPartition(filledAutofillFieldCollection, parser.AutofillFields.FocusedAutofillCanonicalHints);
result.Add(AutofillHelper.NewDataset(this, parser.AutofillFields, partitionData, IntentBuilder));
}

View File

@@ -178,8 +178,10 @@ namespace keepass2android.services.AutofillBase
StructureParser parser = new StructureParser(this, structure);
parser.ParseForFill(isManual);
AutofillFieldMetadataCollection autofillFields = parser.AutofillFields;
int partitionIndex = AutofillHintsHelper.GetPartitionIndex(autofillFields.FocusedAutofillCanonicalHints.FirstOrDefault());
FilledAutofillFieldCollection partitionData = AutofillHintsHelper.FilterForPartition(clientFormDataMap, partitionIndex);
var partitionData = AutofillHintsHelper.FilterForPartition(clientFormDataMap, parser.AutofillFields.FocusedAutofillCanonicalHints);
ReplyIntent = new Intent();
SetDatasetIntent(AutofillHelper.NewDataset(this, autofillFields, partitionData, IntentBuilder));
SetResult(Result.Ok, ReplyIntent);
@@ -231,10 +233,14 @@ namespace keepass2android.services.AutofillBase
protected void SetDatasetIntent(Dataset dataset)
{
if (dataset == null)
{
Toast.MakeText(this, "Failed to build an autofill dataset.", ToastLength.Long).Show();
return;
}
var responseBuilder = new FillResponse.Builder();
responseBuilder.AddDataset(dataset);
ReplyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, responseBuilder.Build());
}
}
}
}

View File

@@ -289,18 +289,14 @@ namespace keepass2android.services.AutofillBase
if (viewHints != null && viewHints.Length == 1 && viewHints.First() == "off" && viewNode.IsFocused &&
isManualRequest)
viewHints[0] = "on";
if (viewHints != null && viewHints.Any())
/*if (viewHints != null && viewHints.Any())
{
CommonUtil.logd("viewHints=" + viewHints);
CommonUtil.logd("class=" + viewNode.ClassName);
CommonUtil.logd("tag=" + (viewNode?.HtmlInfo?.Tag ?? "(null)"));
}
}*/
if (viewNode?.HtmlInfo?.Tag == "input")
{
foreach (var p in viewNode.HtmlInfo.Attributes)
CommonUtil.logd("attr="+p.First + "/" + p.Second);
}
if (viewHints != null && viewHints.Length > 0 && viewHints.First() != "on" /*if hint is "on", treat as if there is no hint*/)
{
if (forFill)

View File

@@ -120,7 +120,31 @@ namespace keepass2android.services.AutofillBase.model
}
}
}
return setValueAtLeastOnce;
/*
if (!setValueAtLeastOnce)
{
Kp2aLog.Log("No value set. Hint keys : " + string.Join(",", HintMap.Keys));
foreach (string hint in autofillFieldMetadataCollection.AllAutofillCanonicalHints)
{
Kp2aLog.Log("No value set. Hint = " + hint);
foreach (AutofillFieldMetadata autofillFieldMetadata in autofillFieldMetadataCollection
.GetFieldsForHint(hint))
{
Kp2aLog.Log("No value set. fieldForHint = " + autofillFieldMetadata.AutofillId.ToString());
FilledAutofillField filledAutofillField;
if (!HintMap.TryGetValue(hint, out filledAutofillField) || (filledAutofillField == null))
{
Kp2aLog.Log("No value set. Hint map does not contain value, " +
(filledAutofillField == null));
continue;
}
Kp2aLog.Log("autofill type=" + autofillFieldMetadata.AutofillType);
}
}
}*/
return setValueAtLeastOnce;
}
/// <summary>