public static FillResponse BuildFillResponse(Parser parser, List <FilledItem> items, bool locked, bool inlineAutofillEnabled, FillRequest fillRequest = null) { // Acquire inline presentation specs on Android 11+ IList <InlinePresentationSpec> inlinePresentationSpecs = null; var inlinePresentationSpecsCount = 0; var inlineMaxSuggestedCount = 0; if (inlineAutofillEnabled && fillRequest != null && (int)Build.VERSION.SdkInt >= 30) { var inlineSuggestionsRequest = fillRequest.InlineSuggestionsRequest; inlineMaxSuggestedCount = inlineSuggestionsRequest?.MaxSuggestionCount ?? 0; inlinePresentationSpecs = inlineSuggestionsRequest?.InlinePresentationSpecs; inlinePresentationSpecsCount = inlinePresentationSpecs?.Count ?? 0; } // Build response var responseBuilder = new FillResponse.Builder(); if (items != null && items.Count > 0) { var maxItems = items.Count; if (inlineMaxSuggestedCount > 0) { // -1 to adjust for 'open vault' option maxItems = Math.Min(maxItems, inlineMaxSuggestedCount - 1); } for (int i = 0; i < maxItems; i++) { InlinePresentationSpec inlinePresentationSpec = null; if (inlinePresentationSpecs != null) { if (i < inlinePresentationSpecsCount) { inlinePresentationSpec = inlinePresentationSpecs[i]; } else { // If the max suggestion count is larger than the number of specs in the list, then // the last spec is used for the remainder of the suggestions inlinePresentationSpec = inlinePresentationSpecs[inlinePresentationSpecsCount - 1]; } } var dataset = BuildDataset(parser.ApplicationContext, parser.FieldCollection, items[i], inlinePresentationSpec); if (dataset != null) { responseBuilder.AddDataset(dataset); } } } responseBuilder.AddDataset(BuildVaultDataset(parser.ApplicationContext, parser.FieldCollection, parser.Uri, locked, inlinePresentationSpecs)); AddSaveInfo(parser, fillRequest, responseBuilder, parser.FieldCollection); responseBuilder.SetIgnoredIds(parser.FieldCollection.IgnoreAutofillIds.ToArray()); return(responseBuilder.Build()); }
private void AddDisableDataset(string query, AutofillId[] autofillIds, FillResponse.Builder responseBuilder, bool isManual) { bool isQueryDisabled = IsQueryDisabled(query); if (isQueryDisabled && !isManual) { return; } bool isForDisable = !isQueryDisabled; var sender = IntentBuilder.GetDisableIntentSenderForResponse(this, query, isManual, isForDisable); RemoteViews presentation = AutofillHelper.NewRemoteViews(PackageName, GetString(isForDisable ? Resource.String.autofill_disable : Resource.String.autofill_enable_for, new Java.Lang.Object[] { GetDisplayNameForQuery(query, this) }), Resource.Drawable.ic_menu_close_grey); var datasetBuilder = new Dataset.Builder(presentation); datasetBuilder.SetAuthentication(sender); foreach (var autofillId in autofillIds) { datasetBuilder.SetValue(autofillId, AutofillValue.ForText("PLACEHOLDER")); } responseBuilder.AddDataset(datasetBuilder.Build()); }
/// <summary> /// Wraps autofill data in a Response object (essentially a series of Datasets) which can then /// be sent back to the client View. /// </summary> /// <returns>The response.</returns> /// <param name="context">Context.</param> /// <param name="datasetAuth">If set to <c>true</c> dataset auth.</param> /// <param name="autofillFields">Autofill fields.</param> /// <param name="clientFormDataMap">Client form data map.</param> /// <param name="intentBuilder"></param> public static FillResponse NewResponse(Context context, bool datasetAuth, AutofillFieldMetadataCollection autofillFields, Dictionary <string, FilledAutofillFieldCollection> clientFormDataMap, IAutofillIntentBuilder intentBuilder) { var responseBuilder = new FillResponse.Builder(); if (clientFormDataMap != null) { var datasetNames = clientFormDataMap.Keys; foreach (var datasetName in datasetNames) { var filledAutofillFieldCollection = clientFormDataMap[datasetName]; if (filledAutofillFieldCollection != null) { var dataset = NewDataset(context, autofillFields, filledAutofillFieldCollection, intentBuilder); if (dataset != null) { responseBuilder.AddDataset(dataset); } } } } if (autofillFields.SaveType != 0) { //TODO implement save var autofillIds = autofillFields.GetAutofillIds(); responseBuilder.SetSaveInfo (new SaveInfo.Builder(autofillFields.SaveType, autofillIds).Build()); return(responseBuilder.Build()); } else { Log.Debug(CommonUtil.Tag, "These fields are not meant to be saved by autofill."); return(null); } }
/** * Wraps autofill data in a Response object (essentially a series of Datasets) which can then * be sent back to the client View. */ public static FillResponse NewResponse(Context context, bool datasetAuth, AutofillFieldMetadataCollection autofillFields, Dictionary <string, FilledAutofillFieldCollection> clientFormDataMap) { FillResponse.Builder responseBuilder = new FillResponse.Builder(); if (clientFormDataMap != null) { var datasetNames = clientFormDataMap.Keys; foreach (var datasetName in datasetNames) { var filledAutofillFieldCollection = clientFormDataMap[datasetName]; if (filledAutofillFieldCollection != null) { var dataset = NewDataset(context, autofillFields, filledAutofillFieldCollection, datasetAuth); if (dataset != null) { responseBuilder.AddDataset(dataset); } } } } if (autofillFields.GetSaveType() != 0) { AutofillId[] autofillIds = autofillFields.GetAutofillIds(); responseBuilder.SetSaveInfo (new SaveInfo.Builder((SaveDataType)autofillFields.GetSaveType(), autofillIds).Build()); return(responseBuilder.Build()); } Log.Debug(CommonUtil.TAG, "These fields are not meant to be saved by autofill."); return(null); }
public override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal, FillCallback callback) { bool isManual = (request.Flags & FillRequest.FlagManualRequest) != 0; CommonUtil.logd("onFillRequest " + (isManual ? "manual" : "auto")); var structure = request.FillContexts[request.FillContexts.Count - 1].Structure; //TODO support package signature verification as soon as this is supported in Keepass storage var clientState = request.ClientState; CommonUtil.logd("onFillRequest(): data=" + CommonUtil.BundleToString(clientState)); cancellationSignal.CancelEvent += (sender, e) => { Log.Warn(CommonUtil.Tag, "Cancel autofill not implemented yet."); }; // Parse AutoFill data in Activity string query = null; var parser = new StructureParser(this, structure); try { query = parser.ParseForFill(isManual); } catch (Java.Lang.SecurityException e) { Log.Warn(CommonUtil.Tag, "Security exception handling request"); callback.OnFailure(e.Message); return; } AutofillFieldMetadataCollection autofillFields = parser.AutofillFields; var autofillIds = autofillFields.GetAutofillIds(); if (autofillIds.Length != 0 && CanAutofill(query, isManual)) { var responseBuilder = new FillResponse.Builder(); var entryDataset = AddEntryDataset(query, parser); bool hasEntryDataset = entryDataset != null; if (entryDataset != null) { responseBuilder.AddDataset(entryDataset); } AddQueryDataset(query, isManual, autofillIds, responseBuilder, !hasEntryDataset); AddDisableDataset(query, autofillIds, responseBuilder, isManual); responseBuilder.SetSaveInfo(new SaveInfo.Builder(parser.AutofillFields.SaveType, parser.AutofillFields.GetAutofillIds()).Build()); callback.OnSuccess(responseBuilder.Build()); } else { callback.OnSuccess(null); } }
/** * Wraps autofill data in a Response object (essentially a series of Datasets) which can then * be sent back to the client View. */ public static FillResponse NewResponse(Context context, bool datasetAuth, AutofillFieldMetadataCollection autofillFields, IDictionary <string, FilledAutofillFieldCollection> clientFormDataMap) { var responseBuilder = new FillResponse.Builder(); if (clientFormDataMap != null) { foreach (var datasetName in clientFormDataMap.Keys) { if (clientFormDataMap.ContainsKey(datasetName)) { var dataset = NewDataset(context, autofillFields, clientFormDataMap[datasetName], datasetAuth); if (dataset != null) { responseBuilder.AddDataset(dataset); } } } } if (autofillFields.SaveType != SaveDataType.Generic) { responseBuilder.SetSaveInfo( new SaveInfo.Builder(autofillFields.SaveType, autofillFields.AutofillIds.ToArray()).Build()); return(responseBuilder.Build()); } else { //Log.d(TAG, "These fields are not meant to be saved by autofill."); return(null); } }
protected void SetDatasetIntent(Dataset dataset) { if (dataset == null) { return; } var responseBuilder = new FillResponse.Builder(); responseBuilder.AddDataset(dataset); ReplyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, responseBuilder.Build()); }
public static FillResponse BuildFillResponse(Parser parser, List <FilledItem> items, bool locked) { var responseBuilder = new FillResponse.Builder(); if (items != null && items.Count > 0) { foreach (var item in items) { var dataset = BuildDataset(parser.ApplicationContext, parser.FieldCollection, item); if (dataset != null) { responseBuilder.AddDataset(dataset); } } } responseBuilder.AddDataset(BuildVaultDataset(parser.ApplicationContext, parser.FieldCollection, parser.Uri, locked)); AddSaveInfo(parser, responseBuilder, parser.FieldCollection); responseBuilder.SetIgnoredIds(parser.FieldCollection.IgnoreAutofillIds.ToArray()); return(responseBuilder.Build()); }
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()); }
public FillResponse BuildResponseForFocusedNode(string datasetName, FilledAutofillField field, FieldType fieldType) { FillResponse.Builder responseBuilder = new FillResponse.Builder(); RemoteViews remoteViews = RemoteViewsHelper.ViewsWithNoAuth( mPackageName, datasetName); Dataset dataset = mDatasetAdapter.BuildDatasetForFocusedNode(field, fieldType, remoteViews); if (dataset != null) { responseBuilder.AddDataset(dataset); return(responseBuilder.Build()); } return(null); }
private void AddQueryDataset(string query, string queryDomain, string queryPackage, bool isManual, AutofillId[] autofillIds, FillResponse.Builder responseBuilder, bool autoReturnFromQuery, DisplayWarning warning) { var sender = IntentBuilder.GetAuthIntentSenderForResponse(this, query, queryDomain, queryPackage, isManual, autoReturnFromQuery, warning); RemoteViews presentation = AutofillHelper.NewRemoteViews(PackageName, GetString(Resource.String.autofill_sign_in_prompt), AppNames.LauncherIcon); var datasetBuilder = new Dataset.Builder(presentation); datasetBuilder.SetAuthentication(sender); //need to add placeholders so we can directly fill after ChooseActivity foreach (var autofillId in autofillIds) { datasetBuilder.SetValue(autofillId, AutofillValue.ForText("PLACEHOLDER")); } responseBuilder.AddDataset(datasetBuilder.Build()); }
/** * Wraps autofill data in a Response object (essentially a series of Datasets) which can then * be sent back to the client View. */ public FillResponse BuildResponse(Dictionary <string, FieldTypeWithHeuristics> fieldTypesByAutofillHint, List <DatasetWithFilledAutofillFields> datasets, bool datasetAuth) { FillResponse.Builder responseBuilder = new FillResponse.Builder(); if (datasets != null) { foreach (var datasetWithFilledAutofillFields in datasets) { if (datasetWithFilledAutofillFields != null) { Dataset dataset; String datasetName = datasetWithFilledAutofillFields.autofillDataset.GetDatasetName(); if (datasetAuth) { IntentSender intentSender = AuthActivity.GetAuthIntentSenderForDataset( mContext, datasetName); RemoteViews remoteViews = RemoteViewsHelper.ViewsWithAuth( mPackageName, datasetName); dataset = mDatasetAdapter.BuildDataset(fieldTypesByAutofillHint, datasetWithFilledAutofillFields, remoteViews, intentSender); } else { RemoteViews remoteViews = RemoteViewsHelper.ViewsWithNoAuth( mPackageName, datasetName); dataset = mDatasetAdapter.BuildDataset(fieldTypesByAutofillHint, datasetWithFilledAutofillFields, remoteViews); } if (dataset != null) { responseBuilder.AddDataset(dataset); } } } } int saveType = 0; AutofillId[] autofillIds = mClientViewMetadata.mFocusedIds; if (autofillIds != null && autofillIds.Length > 0) { SaveInfo saveInfo = new SaveInfo.Builder((SaveDataType)saveType, autofillIds).Build(); responseBuilder.SetSaveInfo(saveInfo); return(responseBuilder.Build()); } return(null); }
public override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal, FillCallback callback) { bool isManual = (request.Flags & FillRequest.FlagManualRequest) != 0; CommonUtil.logd("onFillRequest " + (isManual ? "manual" : "auto")); var structure = request.FillContexts[request.FillContexts.Count - 1].Structure; //TODO support package signature verification as soon as this is supported in Keepass storage var clientState = request.ClientState; CommonUtil.logd("onFillRequest(): data=" + CommonUtil.BundleToString(clientState)); cancellationSignal.CancelEvent += (sender, e) => { Log.Warn(CommonUtil.Tag, "Cancel autofill not implemented yet."); }; // Parse AutoFill data in Activity StructureParser.AutofillTargetId query = null; var parser = new StructureParser(this, structure); try { query = parser.ParseForFill(isManual); } catch (Java.Lang.SecurityException e) { Log.Warn(CommonUtil.Tag, "Security exception handling request"); callback.OnFailure(e.Message); return; } AutofillFieldMetadataCollection autofillFields = parser.AutofillFields; var autofillIds = autofillFields.GetAutofillIds(); if (autofillIds.Length != 0 && CanAutofill(query, isManual)) { var responseBuilder = new FillResponse.Builder(); Dataset entryDataset = null; if (query.IncompatiblePackageAndDomain == false) { //domain and package are compatible. Use Domain if available and package otherwise. Can fill without warning. entryDataset = BuildEntryDataset(query.DomainOrPackage, query.WebDomain, query.PackageName, autofillIds, parser, DisplayWarning.None); } else { //domain or package are incompatible. Don't show the entry. (Tried to do so first but behavior was not consistent) //entryDataset = BuildEntryDataset(query.WebDomain, query.WebDomain, query.PackageName, autofillIds, parser, DisplayWarning.FillDomainInUntrustedApp); } bool hasEntryDataset = entryDataset != null; if (entryDataset != null) { responseBuilder.AddDataset(entryDataset); } if (query.WebDomain != null) { AddQueryDataset(query.WebDomain, query.WebDomain, query.PackageName, isManual, autofillIds, responseBuilder, !hasEntryDataset, query.IncompatiblePackageAndDomain ? DisplayWarning.FillDomainInUntrustedApp : DisplayWarning.None); } else { AddQueryDataset(query.PackageNameWithPseudoSchema, query.WebDomain, query.PackageName, isManual, autofillIds, responseBuilder, !hasEntryDataset, DisplayWarning.None); } AddDisableDataset(query.DomainOrPackage, autofillIds, responseBuilder, isManual); if (PreferenceManager.GetDefaultSharedPreferences(this) .GetBoolean(GetString(Resource.String.OfferSaveCredentials_key), true)) { if (!CompatBrowsers.Contains(parser.PackageId)) { responseBuilder.SetSaveInfo(new SaveInfo.Builder(parser.AutofillFields.SaveType, parser.AutofillFields.GetAutofillIds()).Build()); } } callback.OnSuccess(responseBuilder.Build()); } else { callback.OnSuccess(null); } }
public override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal, FillCallback callback) { bool isManual = (request.Flags & FillRequest.FlagManualRequest) != 0; CommonUtil.logd("onFillRequest " + (isManual ? "manual" : "auto")); var structure = request.FillContexts.Last().Structure; if (_lockTime + _lockTimeout < DateTime.Now) { _lockTime = DateTime.Now; //TODO support package signature verification as soon as this is supported in Keepass storage var clientState = request.ClientState; CommonUtil.logd("onFillRequest(): data=" + CommonUtil.BundleToString(clientState)); cancellationSignal.CancelEvent += (sender, e) => { Kp2aLog.Log("Cancel autofill not implemented yet."); _lockTime = DateTime.MinValue; }; // Parse AutoFill data in Activity StructureParser.AutofillTargetId query = null; var parser = new StructureParser(this, structure); try { query = parser.ParseForFill(isManual); } catch (Java.Lang.SecurityException e) { Log.Warn(CommonUtil.Tag, "Security exception handling request"); callback.OnFailure(e.Message); return; } AutofillFieldMetadataCollection autofillFields = parser.AutofillFields; InlineSuggestionsRequest inlineSuggestionsRequest = null; IList <InlinePresentationSpec> inlinePresentationSpecs = null; if (((int)Build.VERSION.SdkInt >= 30) && (PreferenceManager.GetDefaultSharedPreferences(this).GetBoolean(GetString(Resource.String.InlineSuggestions_key), true))) { inlineSuggestionsRequest = request.InlineSuggestionsRequest; inlinePresentationSpecs = inlineSuggestionsRequest?.InlinePresentationSpecs; } var autofillIds = autofillFields.GetAutofillIds(); if (autofillIds.Length != 0 && CanAutofill(query, isManual)) { var responseBuilder = new FillResponse.Builder(); bool hasEntryDataset = false; IList <Dataset> entryDatasets = new List <Dataset>(); if (query.IncompatiblePackageAndDomain == false) { Kp2aLog.Log("AF: (query.IncompatiblePackageAndDomain == false)"); //domain and package are compatible. Use Domain if available and package otherwise. Can fill without warning. entryDatasets = BuildEntryDatasets(query.DomainOrPackage, query.WebDomain, query.PackageName, autofillIds, parser, DisplayWarning.None, inlinePresentationSpecs ).Where(ds => ds != null).ToList(); if (entryDatasets.Count > inlineSuggestionsRequest?.MaxSuggestionCount - 2 /*disable dataset and query*/) { //we have too many elements. disable inline suggestions inlinePresentationSpecs = null; entryDatasets = BuildEntryDatasets(query.DomainOrPackage, query.WebDomain, query.PackageName, autofillIds, parser, DisplayWarning.None, null ).Where(ds => ds != null).ToList(); } foreach (var entryDataset in entryDatasets ) { Kp2aLog.Log("AF: Got EntryDataset " + (entryDataset == null)); responseBuilder.AddDataset(entryDataset); hasEntryDataset = true; } } { if (query.WebDomain != null) { AddQueryDataset(query.WebDomain, query.WebDomain, query.PackageName, isManual, autofillIds, responseBuilder, !hasEntryDataset, query.IncompatiblePackageAndDomain ? DisplayWarning.FillDomainInUntrustedApp : DisplayWarning.None, AutofillHelper.ExtractSpec(inlinePresentationSpecs, entryDatasets.Count)); } else { AddQueryDataset(query.PackageNameWithPseudoSchema, query.WebDomain, query.PackageName, isManual, autofillIds, responseBuilder, !hasEntryDataset, DisplayWarning.None, AutofillHelper.ExtractSpec(inlinePresentationSpecs, entryDatasets.Count)); } } if (!PreferenceManager.GetDefaultSharedPreferences(this) .GetBoolean(GetString(Resource.String.NoAutofillDisabling_key), false)) { AddDisableDataset(query.DomainOrPackage, autofillIds, responseBuilder, isManual, AutofillHelper.ExtractSpec(inlinePresentationSpecs, entryDatasets.Count)); } if (PreferenceManager.GetDefaultSharedPreferences(this) .GetBoolean(GetString(Resource.String.OfferSaveCredentials_key), true)) { if (!CompatBrowsers.Contains(parser.PackageId)) { responseBuilder.SetSaveInfo(new SaveInfo.Builder(parser.AutofillFields.SaveType, parser.AutofillFields.GetAutofillIds()).Build()); } } 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."); } }
public override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal, FillCallback callback) { bool isManual = (request.Flags & FillRequest.FlagManualRequest) != 0; CommonUtil.logd("onFillRequest " + (isManual ? "manual" : "auto")); var structure = request.FillContexts[request.FillContexts.Count - 1].Structure; //TODO support package signature verification as soon as this is supported in Keepass storage var clientState = request.ClientState; CommonUtil.logd("onFillRequest(): data=" + CommonUtil.BundleToString(clientState)); cancellationSignal.CancelEvent += (sender, e) => { Log.Warn(CommonUtil.Tag, "Cancel autofill not implemented yet."); }; // Parse AutoFill data in Activity string query = null; var parser = new StructureParser(this, structure); try { query = parser.ParseForFill(isManual); } catch (Java.Lang.SecurityException e) { Log.Warn(CommonUtil.Tag, "Security exception handling request"); callback.OnFailure(e.Message); return; } AutofillFieldMetadataCollection autofillFields = parser.AutofillFields; bool responseAuth = true; var autofillIds = autofillFields.GetAutofillIds(); if (responseAuth && autofillIds.Length != 0 && CanAutofill(query)) { var responseBuilder = new FillResponse.Builder(); var sender = IntentBuilder.GetAuthIntentSenderForResponse(this, query, isManual); RemoteViews presentation = AutofillHelper.NewRemoteViews(PackageName, GetString(Resource.String.autofill_sign_in_prompt), AppNames.LauncherIcon); var datasetBuilder = new Dataset.Builder(presentation); datasetBuilder.SetAuthentication(sender); //need to add placeholders so we can directly fill after ChooseActivity foreach (var autofillId in autofillIds) { datasetBuilder.SetValue(autofillId, AutofillValue.ForText("PLACEHOLDER")); } responseBuilder.AddDataset(datasetBuilder.Build()); callback.OnSuccess(responseBuilder.Build()); } else { var datasetAuth = true; var response = AutofillHelper.NewResponse(this, datasetAuth, autofillFields, null, IntentBuilder); callback.OnSuccess(response); } }