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:
		| @@ -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; | ||||
| 		} | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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)); | ||||
|                 } | ||||
|   | ||||
| @@ -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()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Philipp Crocoll
					Philipp Crocoll