/**
         * 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);
        }
Ejemplo n.º 2
0
        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);
            }
        }
Ejemplo n.º 3
0
        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());
        }
Ejemplo n.º 4
0
        public static void AddSaveInfo(Parser parser, FillResponse.Builder responseBuilder, FieldCollection fields)
        {
            // Docs state that password fields cannot be reliably saved in Compat mode since they will show as
            // masked values.
            var compatBrowser = CompatBrowsers.Contains(parser.PackageName);

            if (compatBrowser && fields.SaveType == SaveDataType.Password)
            {
                return;
            }

            var requiredIds = fields.GetRequiredSaveFields();

            if (fields.SaveType == SaveDataType.Generic || requiredIds.Length == 0)
            {
                return;
            }

            var saveBuilder = new SaveInfo.Builder(fields.SaveType, requiredIds);
            var optionalIds = fields.GetOptionalSaveIds();

            if (optionalIds.Length > 0)
            {
                saveBuilder.SetOptionalIds(optionalIds);
            }
            if (compatBrowser)
            {
                saveBuilder.SetFlags(SaveFlags.SaveOnAllViewsInvisible);
            }
            responseBuilder.SetSaveInfo(saveBuilder.Build());
        }
        /**
         * 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);
            }
        }
Ejemplo n.º 6
0
        /// <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);
            }
        }
        public override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal,
                                           FillCallback callback)
        {
            var structure = request.FillContexts?.LastOrDefault()?.Structure;

            if (structure == null)
            {
                return;
            }

            var clientState = request.ClientState;

            var parser = new StructureParser(structure);

            parser.ParseForFill();

            // build response
            var responseBuilder = new FillResponse.Builder();

            var username1 = new FilledAutofillField {
                TextValue = "username1"
            };
            var password1 = new FilledAutofillField {
                TextValue = "pass1"
            };
            var login1 = new Dictionary <string, FilledAutofillField>
            {
                { View.AutofillHintUsername, username1 },
                { View.AutofillHintPassword, password1 }
            };
            var coll = new FilledAutofillFieldCollection("Login 1 Name", login1);

            var username2 = new FilledAutofillField {
                TextValue = "username2"
            };
            var password2 = new FilledAutofillField {
                TextValue = "pass2"
            };
            var login2 = new Dictionary <string, FilledAutofillField>
            {
                { View.AutofillHintUsername, username2 },
                { View.AutofillHintPassword, password2 }
            };
            var col2 = new FilledAutofillFieldCollection("Login 2 Name", login2);

            var clientFormDataMap = new Dictionary <string, FilledAutofillFieldCollection>
            {
                { "login-1-guid", coll },
                { "login-2-guid", col2 }
            };

            var response = AutofillHelper.NewResponse(this, false, parser.AutofillFields, clientFormDataMap);

            // end build response

            callback.OnSuccess(response);
        }
Ejemplo n.º 8
0
        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());
        }
Ejemplo n.º 9
0
        protected void SetDatasetIntent(Dataset dataset)
        {
            if (dataset == null)
            {
                return;
            }
            var responseBuilder = new FillResponse.Builder();

            responseBuilder.AddDataset(dataset);
            ReplyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, 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);
        }
        public FillResponse BuildResponse(IntentSender sender, RemoteViews remoteViews)
        {
            FillResponse.Builder responseBuilder = new FillResponse.Builder();
            int saveType = mClientViewMetadata.mSaveType;

            AutofillId[] autofillIds = mClientViewMetadata.mFocusedIds;
            if (autofillIds != null && autofillIds.Length > 0)
            {
                SaveInfo saveInfo = new SaveInfo.Builder((SaveDataType)saveType, autofillIds).Build();
                responseBuilder.SetSaveInfo(saveInfo);
                responseBuilder.SetAuthentication(autofillIds, sender, remoteViews);
                return(responseBuilder.Build());
            }
            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 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);
        }
Ejemplo n.º 14
0
        public static void AddSaveInfo(FillResponse.Builder responseBuilder, FieldCollection fields)
        {
            var requiredIds = fields.GetRequiredSaveFields();

            if (fields.SaveType == SaveDataType.Generic || requiredIds.Length == 0)
            {
                return;
            }

            var saveBuilder = new SaveInfo.Builder(fields.SaveType, requiredIds);
            var optionalIds = fields.GetOptionalSaveIds();

            if (optionalIds.Length > 0)
            {
                saveBuilder.SetOptionalIds(optionalIds);
            }
            responseBuilder.SetSaveInfo(saveBuilder.Build());
        }
Ejemplo n.º 15
0
        public override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal, FillCallback callback)
        {
            var structure = request.FillContexts[request.FillContexts.Count - 1].Structure;
            var data      = request.ClientState;

            Log.Debug(CommonUtil.Tag, "onFillRequest(): data=" + CommonUtil.BundleToString(data));

            cancellationSignal.CancelEvent += (sender, e) => {
                Log.Warn(CommonUtil.Tag, "Cancel autofill not implemented in this sample.");
            };
            // Parse AutoFill data in Activity
            var parser = new StructureParser(structure);

            parser.ParseForFill();
            AutofillFieldMetadataCollection autofillFields = parser.AutofillFields;
            var responseBuilder = new FillResponse.Builder();
            // Check user's settings for authenticating Responses and Datasets.
            bool responseAuth = MyPreferences.GetInstance(this).IsResponseAuth();
            var  autofillIds  = autofillFields.GetAutofillIds();

            if (responseAuth && !(autofillIds.Length == 0))
            {
                // If the entire Autofill Response is authenticated, AuthActivity is used
                // to generate Response.
                var sender       = AuthActivity.GetAuthIntentSenderForResponse(this);
                var presentation = AutofillHelper
                                   .NewRemoteViews(PackageName, GetString(Resource.String.autofill_sign_in_prompt),
                                                   Resource.Drawable.ic_lock_black_24dp);
                responseBuilder
                .SetAuthentication(autofillIds, sender, presentation);
                callback.OnSuccess(responseBuilder.Build());
            }
            else
            {
                var datasetAuth       = MyPreferences.GetInstance(this).IsDatasetAuth();
                var clientFormDataMap = SharedPrefsAutofillRepository.GetInstance(this).GetFilledAutofillFieldCollection
                                            (autofillFields.FocusedAutofillHints, autofillFields.AllAutofillHints);
                var response = AutofillHelper.NewResponse(this, datasetAuth, autofillFields, clientFormDataMap);
                callback.OnSuccess(response);
            }
        }
Ejemplo n.º 16
0
        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());
        }
Ejemplo n.º 17
0
        public static void AddSaveInfo(Parser parser, FillRequest fillRequest, FillResponse.Builder responseBuilder,
                                       FieldCollection fields)
        {
            // Docs state that password fields cannot be reliably saved in Compat mode since they will show as
            // masked values.
            bool?compatRequest = null;

            if (Build.VERSION.SdkInt >= BuildVersionCodes.Q && fillRequest != null)
            {
                // Attempt to automatically establish compat request mode on Android 10+
                compatRequest = (fillRequest.Flags | FillRequest.FlagCompatibilityModeRequest) == fillRequest.Flags;
            }
            var compatBrowser = compatRequest ?? CompatBrowsers.Contains(parser.PackageName);

            if (compatBrowser && fields.SaveType == SaveDataType.Password)
            {
                return;
            }

            var requiredIds = fields.GetRequiredSaveFields();

            if (fields.SaveType == SaveDataType.Generic || requiredIds.Length == 0)
            {
                return;
            }

            var saveBuilder = new SaveInfo.Builder(fields.SaveType, requiredIds);
            var optionalIds = fields.GetOptionalSaveIds();

            if (optionalIds.Length > 0)
            {
                saveBuilder.SetOptionalIds(optionalIds);
            }
            if (compatBrowser)
            {
                saveBuilder.SetFlags(SaveFlags.SaveOnAllViewsInvisible);
            }
            responseBuilder.SetSaveInfo(saveBuilder.Build());
        }
Ejemplo n.º 18
0
        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);
            }
        }
Ejemplo n.º 19
0
        public override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal,
                                           FillCallback callback)
        {
            var structure   = request.FillContexts[request.FillContexts.Count - 1].Structure;
            var packageName = structure.ActivityComponent.PackageName;

            if (!SharedPrefsPackageVerificationRepository.GetInstance()
                .PutPackageSignatures(ApplicationContext, packageName))
            {
                callback.OnFailure(
                    ApplicationContext.GetString(AutofillService.Resource.String.invalid_package_signature));
                return;
            }

            var data = request.ClientState;

            if (CommonUtil.VERBOSE)
            {
                Log.Verbose(CommonUtil.TAG, "onFillRequest(): data=" + CommonUtil.BundleToString(data));
                CommonUtil.DumpStructure(structure);
            }

            cancellationSignal.SetOnCancelListener(new CancelListener());

            // Parse AutoFill data in Activity
            var parser = new StructureParser(ApplicationContext, structure);

            // TODO: try / catch on other places (onSave, auth activity, etc...)
            try
            {
                parser.ParseForFill();
            }
            catch (SecurityException e)
            {
                // TODO: handle cases where DAL didn't pass by showing a custom UI asking the user
                // to confirm the mapping. Might require subclassing SecurityException.
                Log.Warn(CommonUtil.TAG, "Security exception handling " + request, e);
                callback.OnFailure(e.Message);
                return;
            }

            var autofillFields  = parser.GetAutofillFields();
            var responseBuilder = new FillResponse.Builder();
            // Check user's settings for authenticating Responses and Datasets.
            var responseAuth = MyPreferences.GetInstance(this).IsResponseAuth();
            var autofillIds  = autofillFields.GetAutofillIds();

            if (responseAuth && autofillIds.Length != 0)
            {
                // If the entire Autofill Response is authenticated, AuthActivity is used
                // to generate Response.
                var sender       = AuthActivity.GetAuthIntentSenderForResponse(this);
                var presentation = AutofillHelper.NewRemoteViews(PackageName,
                                                                 GetString(Resource.String.autofill_sign_in_prompt), Resource.Drawable.ic_lock_black_24dp);
                responseBuilder.SetAuthentication(autofillIds, sender, presentation);
                callback.OnSuccess(responseBuilder.Build());
            }
            else
            {
                var datasetAuth       = MyPreferences.GetInstance(this).IsDatasetAuth();
                var clientFormDataMap = SharedPrefsAutofillRepository.GetInstance().GetFilledAutofillFieldCollection(
                    this, autofillFields.GetFocusedHints(), autofillFields.GetAllHints());
                var response = AutofillHelper.NewResponse(this, datasetAuth, autofillFields, clientFormDataMap);
                callback.OnSuccess(response);
            }
        }
Ejemplo n.º 20
0
        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);
            }
        }
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);


            string requestedUrl = Intent.GetStringExtra(ChooseForAutofillActivityBase.ExtraQueryString);

            if (requestedUrl == null)
            {
                Toast.MakeText(this, "Cannot execute query for null.", ToastLength.Long).Show();
                RestartApp();
                return;
            }

            var prefs = PreferenceManager.GetDefaultSharedPreferences(this);

            bool isDisable = Intent.GetBooleanExtra(ExtraIsDisable, true);

            var disabledValues = prefs.GetStringSet("AutoFillDisabledQueries", new HashSet <string>()
            {
            }).ToHashSet();

            if (isDisable)
            {
                disabledValues.Add(requestedUrl);
            }
            else
            {
                disabledValues.Remove(requestedUrl);
            }


            prefs.Edit().PutStringSet("AutoFillDisabledQueries", disabledValues).Commit();

            bool isManual = Intent.GetBooleanExtra(ChooseForAutofillActivityBase.ExtraIsManualRequest, false);

            Intent reply = new Intent();

            FillResponse.Builder builder   = new FillResponse.Builder();
            AssistStructure      structure = (AssistStructure)Intent.GetParcelableExtra(AutofillManager.ExtraAssistStructure);
            StructureParser      parser    = new StructureParser(this, structure);

            try
            {
                parser.ParseForFill(isManual);
            }
            catch (Java.Lang.SecurityException e)
            {
                Log.Warn(CommonUtil.Tag, "Security exception handling request");
                SetResult(Result.Canceled);
                return;
            }

            try
            {
                reply.PutExtra(AutofillManager.ExtraAuthenticationResult, (FillResponse)null);
            }
            catch (Exception e)
            {
                Kp2aLog.LogUnexpectedError(e);
                throw;
            }

            SetResult(Result.Ok, reply);


            Finish();
        }
Ejemplo n.º 22
0
        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());
        }
Ejemplo n.º 23
0
        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.");
            }
        }