Introduce preference options to control the behavior when autofilling TOTP entries (show entry notification, activate keyboard, copy TOTP to clipboard)
Required a bit of refactoring to decide when to bring up keyboard selection dialog. Also changed the code so it shows e.g. on Pixel 6a with Android 14, previously did not. closes #2308 closes #1286 as it now shows up the entry notificaton (unless disabled) and solves the underlying issue in the best found way
This commit is contained in:
		| @@ -140,7 +140,7 @@ namespace keepass2android | ||||
|             //will return the results later | ||||
|             Intent i = new Intent(this, typeof (SelectCurrentDbActivity)); | ||||
| 			//don't show user notifications when an entry is opened. | ||||
| 			var task = new SearchUrlTask() {UrlToSearchFor = _requestedUrl, ShowUserNotifications = ShowUserNotificationsMode.WhenTotp}; | ||||
| 			var task = new SearchUrlTask() {UrlToSearchFor = _requestedUrl, ShowUserNotifications = ActivationCondition.WhenTotp, ActivateKeyboard = ActivationCondition.Never }; | ||||
| 			task.ToIntent(i); | ||||
| 			StartActivityForResult(i, RequestCodeQuery); | ||||
| 			_startedQuery = true; | ||||
|   | ||||
| @@ -47,6 +47,7 @@ | ||||
|     <string name="oi_filemanager_web">https://openintents.googlecode.com/files/FileManager-2.0.2.apk</string> | ||||
|   <string name="permission_desc2">KP2A Search</string> | ||||
|   <string name="permission_desc3">KP2A Choose autofill dataset</string> | ||||
|   <string name="AutoFillTotp_prefs_screen_key">AutoFillTotp_prefs_screen_key</string> | ||||
|    | ||||
|  | ||||
|   <!--  Preference settings --> | ||||
|   | ||||
| @@ -402,6 +402,16 @@ | ||||
|   <string name="ShowSeparateNotifications_summary">Show separate notifications for copying username and password to clipboard and activating the keyboard.</string> | ||||
|   <string name="AccServiceAutoFill_prefs">AutoFill Accessibility-Service</string> | ||||
|   <string name="AutoFill_prefs">AutoFill Service</string> | ||||
|   <string name="AutoFillTotp_prefs_ShowNotification_summary">When autofilling an entry with TOTP, show the entry notification with a Copy TOTP button</string> | ||||
|   <string name="AutoFillTotp_prefs_ShowNotification_title">Show entry notification</string> | ||||
|   <string name="AutoFillTotp_prefs_title">Autofill for TOTP entries</string> | ||||
|   <string name="AutoFillTotp_prefs_CopyTotpToClipboard_title">Copy TOTP to clipboard</string> | ||||
|   <string name="AutoFillTotp_prefs_CopyTotpToClipboard_summary">When autofilling an entry with TOTP, copy the TOTP to the clipboard</string> | ||||
|   <string name="AutoFillTotp_prefs_ActivateKeyboard_summary">When autofilling an entry with TOTP, activate the built-in keyboard. The keyboard has a TOTP button.</string> | ||||
|   <string name="AutoFillTotp_prefs_ActivateKeyboard_title">Activate built-in keyboard</string> | ||||
|    | ||||
|   <string name="TotpCopiedToClipboard">Copied TOTP to clipboard</string> | ||||
|  | ||||
|   <string name="ShowKp2aKeyboardNotification_title">KP2A keyboard notification</string> | ||||
|   <string name="ShowKp2aKeyboardNotification_summary">Make full entry accessible through the KP2A keyboard (recommended).</string> | ||||
|   <string name="OpenKp2aKeyboardAutomatically_title">Switch keyboard</string> | ||||
|   | ||||
| @@ -461,7 +461,8 @@ | ||||
|           android:defaultValue="false" | ||||
|           android:title="@string/LogAutofillView_title" | ||||
|           android:key="@string/LogAutofillView_key" /> | ||||
|          | ||||
|  | ||||
|      | ||||
|  | ||||
|         <CheckBoxPreference | ||||
|           android:enabled="true" | ||||
| @@ -476,6 +477,38 @@ | ||||
| 		    android:summary="@string/AutofillDisabledQueriesPreference_summary" | ||||
| 		    android:persistent="false" | ||||
| 		    android:key="AutofillDisabledQueriesPreference_key"/> | ||||
|  | ||||
|         <PreferenceScreen | ||||
|           android:key="@string/AutoFillTotp_prefs_screen_key" | ||||
|           android:title="@string/AutoFillTotp_prefs_title" | ||||
|         > | ||||
|           <keepass2android.ToolbarPreference | ||||
|             android:key="@string/AutoFillTotp_prefs_screen_key" | ||||
|             android:title="@string/AutoFillTotp_prefs_title" /> | ||||
|  | ||||
| 					<CheckBoxPreference android:key="AutoFillTotp_prefs_ShowNotification_key" | ||||
|                               android:enabled="true" | ||||
|                               android:persistent="true" | ||||
|                               android:summary="@string/AutoFillTotp_prefs_ShowNotification_summary" | ||||
|                               android:defaultValue="true" | ||||
|                               android:title="@string/AutoFillTotp_prefs_ShowNotification_title" | ||||
|                               /> | ||||
|           <CheckBoxPreference android:key="AutoFillTotp_prefs_CopyTotpToClipboard_key" | ||||
|                               android:enabled="true" | ||||
|                               android:persistent="true" | ||||
|                               android:summary="@string/AutoFillTotp_prefs_CopyTotpToClipboard_summary" | ||||
|                               android:defaultValue="true" | ||||
|                               android:title="@string/AutoFillTotp_prefs_CopyTotpToClipboard_title" | ||||
|           /> | ||||
|           <CheckBoxPreference android:key="AutoFillTotp_prefs_ActivateKeyboard_key" | ||||
|                               android:enabled="true" | ||||
|                               android:persistent="true" | ||||
|                               android:summary="@string/AutoFillTotp_prefs_ActivateKeyboard_summary" | ||||
|                               android:defaultValue="false" | ||||
|                               android:title="@string/AutoFillTotp_prefs_ActivateKeyboard_title" | ||||
|           /> | ||||
|  | ||||
|         </PreferenceScreen> | ||||
|          | ||||
|       </PreferenceScreen> | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Diagnostics; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
|  | ||||
| @@ -306,7 +307,27 @@ namespace keepass2android | ||||
|                 } | ||||
|                 else if (Intent.Action == Intent.ActionSend) | ||||
|                 { | ||||
|                     AppTask = new SearchUrlTask { UrlToSearchFor = Intent.GetStringExtra(Intent.ExtraText) }; | ||||
|                     ActivationCondition activationCondition = ActivationCondition.Never; | ||||
|                     ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this); | ||||
|                     if (prefs.GetBoolean("kp2a_switch_rooted", false)) | ||||
|                     { | ||||
|                         activationCondition = ActivationCondition.Always; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         //if the app is about to be closed again (e.g. after searching for a URL and returning to the browser: | ||||
|                         // automatically bring up the Keyboard selection dialog | ||||
|                         if (prefs.GetBoolean(this.GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), this.Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default))) | ||||
|                         { | ||||
|                             activationCondition = ActivationCondition.Always; | ||||
|                         } | ||||
|                     } | ||||
|                      | ||||
|                     AppTask = new SearchUrlTask() | ||||
|                     { | ||||
|                         UrlToSearchFor = Intent.GetStringExtra(Intent.ExtraText), | ||||
|                         ActivateKeyboard = activationCondition | ||||
|                     }; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -82,20 +82,15 @@ namespace keepass2android | ||||
| 			//if user presses back to leave this activity: | ||||
| 			SetResult(Result.Canceled); | ||||
|              | ||||
|  | ||||
| 		    UpdateBottomBarElementVisibility(Resource.Id.select_other_entry, true); | ||||
| 		    UpdateBottomBarElementVisibility(Resource.Id.add_url_entry, true); | ||||
|  | ||||
|  | ||||
|             if (App.Kp2a.DatabaseIsUnlocked) | ||||
| 			{ | ||||
| 			     | ||||
| 				Query();	 | ||||
|                 Query(); | ||||
| 			} | ||||
|             // else: LockCloseListActivity.OnResume will trigger a broadcast (LockDatabase) which will cause the activity to be finished. | ||||
|  | ||||
|  | ||||
|  | ||||
|              | ||||
|         } | ||||
|  | ||||
|         protected override void OnSaveInstanceState(Bundle outState) | ||||
| @@ -162,9 +157,17 @@ namespace keepass2android | ||||
|                 String searchUrl = searchUrlTask.UrlToSearchFor; | ||||
|                 selectOtherEntry.Visibility =  ViewStates.Visible; | ||||
|  | ||||
|                 var newTask = new SearchUrlTask() { AutoReturnFromQuery = false, UrlToSearchFor = searchUrl }; | ||||
|                 SearchUrlTask newTask; | ||||
|                 if (AppTask is SelectEntryTask currentSelectTask) | ||||
|                 { | ||||
|                     newTask = new SearchUrlTask() { AutoReturnFromQuery = false, UrlToSearchFor = searchUrl, ActivateKeyboard = currentSelectTask.ActivateKeyboard }; | ||||
|                     newTask.ShowUserNotifications = currentSelectTask.ShowUserNotifications; | ||||
|                     newTask.ActivateKeyboard = currentSelectTask.ActivateKeyboard;   | ||||
|                     newTask.CopyTotpToClipboard = currentSelectTask.CopyTotpToClipboard; | ||||
|                 } | ||||
|                 else | ||||
|                     newTask = new SearchUrlTask() { AutoReturnFromQuery = false, UrlToSearchFor = searchUrl, ActivateKeyboard = ActivationCondition.Never }; | ||||
|  | ||||
|  | ||||
|                 selectOtherEntry.Click += (sender, e) => { | ||||
|                     GroupActivity.Launch(this, newTask, new ActivityLaunchModeRequestCode(0)); | ||||
| @@ -179,7 +182,7 @@ namespace keepass2android | ||||
|                     createUrlEntry.Visibility = ViewStates.Visible; | ||||
|                     createUrlEntry.Click += (sender, e) => | ||||
|                     { | ||||
|                         GroupActivity.Launch(this, new CreateEntryThenCloseTask { Url = searchUrl, ShowUserNotifications = (AppTask as SelectEntryTask)?.ShowUserNotifications ?? ShowUserNotificationsMode.Always }, new ActivityLaunchModeRequestCode(0)); | ||||
|                         GroupActivity.Launch(this, new CreateEntryThenCloseTask { Url = searchUrl, ShowUserNotifications = (AppTask as SelectEntryTask)?.ShowUserNotifications ?? ActivationCondition.Always }, new ActivityLaunchModeRequestCode(0)); | ||||
|                         Toast.MakeText(this, GetString(Resource.String.select_group_then_add, new Java.Lang.Object[] { GetString(Resource.String.add_entry) }), ToastLength.Long).Show(); | ||||
|                     }; | ||||
|                 } | ||||
|   | ||||
| @@ -10,8 +10,9 @@ namespace keepass2android | ||||
| { | ||||
| 	class Kp2aTotp | ||||
| 	{ | ||||
|         public const string TotpKey = "TOTP"; | ||||
|  | ||||
| 		readonly ITotpPluginAdapter[] _pluginAdapters = new ITotpPluginAdapter[] | ||||
|         readonly ITotpPluginAdapter[] _pluginAdapters = new ITotpPluginAdapter[] | ||||
|         { | ||||
|             new TrayTotpPluginAdapter(),  | ||||
|             new KeeOtpPluginAdapter(),  | ||||
|   | ||||
| @@ -13,7 +13,7 @@ namespace PluginTOTP | ||||
| { | ||||
| 	class UpdateTotpTimerTask: TimerTask | ||||
| 	{ | ||||
| 		public const string TotpKey = "TOTP"; | ||||
| 		public const string TotpKey = Kp2aTotp.TotpKey; | ||||
| 		private readonly Context _context; | ||||
| 		private readonly ITotpPluginAdapter _adapter; | ||||
|  | ||||
|   | ||||
| @@ -10,6 +10,9 @@ using System.Threading; | ||||
| using KeePassLib; | ||||
| using KeePassLib.Security; | ||||
| using KeePassLib.Utility; | ||||
| using KeeTrayTOTP.Libraries; | ||||
| using Android.Content.Res; | ||||
| using Android.Preferences; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| @@ -342,7 +345,15 @@ namespace keepass2android | ||||
|  | ||||
| 		public virtual void CompleteOnCreateEntryActivity(EntryActivity activity, Thread notifyPluginsOnOpenThread) | ||||
| 		{ | ||||
| 			activity.StartNotificationsService(false); | ||||
| 			//this default implementation is executed when we're opening an entry manually, i.e. without search/autofill. | ||||
| 			//We only activate the keyboard if this is enabled in "silent mode" | ||||
|             ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(activity); | ||||
|             bool activateKeyboard = prefs.GetBoolean("kp2a_switch_rooted", false) && | ||||
|                                     !prefs.GetBoolean( | ||||
|                                         activity.GetString(Resource.String | ||||
|                                             .OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key), false); | ||||
|  | ||||
|             activity.StartNotificationsService(activateKeyboard); | ||||
| 		} | ||||
|  | ||||
| 		public virtual void PopulatePasswordAccessServiceIntent(Intent intent) | ||||
| @@ -354,7 +365,8 @@ namespace keepass2android | ||||
|         protected static bool GetBoolFromBundle(Bundle b, string key, bool defaultValue) | ||||
|         { | ||||
|             bool boolValue; | ||||
|             if (!Boolean.TryParse(b.GetString(key), out boolValue)) | ||||
|             string stringValue = b.GetString(key); | ||||
|             if (!Boolean.TryParse(stringValue, out boolValue)) | ||||
|             { | ||||
|                 boolValue = defaultValue; | ||||
|             } | ||||
| @@ -364,7 +376,8 @@ namespace keepass2android | ||||
|         protected static int GetIntFromBundle(Bundle b, string key, int defaultValue) | ||||
|         { | ||||
|             int intValue; | ||||
|             if (!Int32.TryParse(b.GetString(key), out intValue)) | ||||
|             var strValue = b.GetString(key); | ||||
|             if (!Int32.TryParse(strValue, out intValue)) | ||||
|             { | ||||
|                 intValue = defaultValue; | ||||
|             } | ||||
| @@ -384,7 +397,7 @@ namespace keepass2android | ||||
| 	/// User is about to search an entry for a given URL | ||||
| 	/// </summary> | ||||
| 	/// Derive from SelectEntryTask. This means that as soon as an Entry is opened, we're returning with | ||||
| 	/// ExitAfterTaskComplete. This also allows te specify the flag if we need to display the user notifications. | ||||
| 	/// ExitAfterTaskComplete. This also allows to specify the flag if we need to display the user notifications. | ||||
| 	public class SearchUrlTask: SelectEntryTask | ||||
| 	{ | ||||
| 	    public SearchUrlTask() | ||||
| @@ -393,8 +406,9 @@ namespace keepass2android | ||||
| 	    } | ||||
|  | ||||
|         public const String UrlToSearchKey = "UrlToSearch"; | ||||
|         public const String AutoReturnFromQueryKey = "AutoReturnFromQuery"; | ||||
|  | ||||
| 		public string UrlToSearchFor | ||||
|         public string UrlToSearchFor | ||||
| 		{ | ||||
| 			get; | ||||
| 			set; | ||||
| @@ -417,7 +431,7 @@ namespace keepass2android | ||||
|             } | ||||
| 		} | ||||
|  | ||||
| 	    public const String AutoReturnFromQueryKey = "AutoReturnFromQuery"; | ||||
| 	     | ||||
|  | ||||
|         public bool AutoReturnFromQuery { get; set; } | ||||
|  | ||||
| @@ -425,15 +439,19 @@ namespace keepass2android | ||||
| 		{ | ||||
| 			if (String.IsNullOrEmpty(UrlToSearchFor)) | ||||
| 			{ | ||||
| 				GroupActivity.Launch(act, new SelectEntryTask() { ShowUserNotifications =  ShowUserNotifications}, new ActivityLaunchModeRequestCode(0)); | ||||
| 				GroupActivity.Launch(act, new SelectEntryTask() {  | ||||
|                         ShowUserNotifications =  ShowUserNotifications, | ||||
|                         CopyTotpToClipboard = CopyTotpToClipboard, | ||||
|                         ActivateKeyboard = ActivateKeyboard | ||||
|                 },  | ||||
|                     new ActivityLaunchModeRequestCode(0)); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				ShareUrlResults.Launch(act, this, new ActivityLaunchModeRequestCode(0)); | ||||
| 			} | ||||
| 			 | ||||
|  | ||||
| 			//removed. this causes an issue in the following workflow: | ||||
|             //removed. this causes an issue in the following workflow: | ||||
| 			//When the user wants to find an entry for a URL but has the wrong database open he needs  | ||||
| 			//to switch to another database. But the Task is removed already the first time when going through PasswordActivity  | ||||
| 			// (with the wrong db). | ||||
| @@ -536,7 +554,7 @@ namespace keepass2android | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public enum ShowUserNotificationsMode | ||||
|     public enum ActivationCondition | ||||
|     { | ||||
|         Never, | ||||
|         WhenTotp, | ||||
| @@ -549,29 +567,34 @@ namespace keepass2android | ||||
| 	{ | ||||
| 		public SelectEntryTask() | ||||
| 		{ | ||||
| 			ShowUserNotifications = ShowUserNotificationsMode.Always; | ||||
| 			ShowUserNotifications = ActivationCondition.Always; | ||||
| 			CloseAfterCreate = true; | ||||
|             ActivateKeyboard = true; | ||||
|             ActivateKeyboard = ActivationCondition.Never; | ||||
|             CopyTotpToClipboard = false; | ||||
|         } | ||||
|  | ||||
| 		public const String ShowUserNotificationsKey = "ShowUserNotifications"; | ||||
|  | ||||
|  | ||||
|  | ||||
|         public ShowUserNotificationsMode ShowUserNotifications { get; set; } | ||||
|         public ActivationCondition ShowUserNotifications { get; set; } | ||||
|  | ||||
| 		public const String CloseAfterCreateKey = "CloseAfterCreate"; | ||||
|         public const String ActivateKeyboardKey = "ActivateKeyboard"; | ||||
|         public const String CopyTotpToClipboardKey = "CopyTotpToClipboard"; | ||||
|  | ||||
|         public bool CloseAfterCreate { get; set; } | ||||
|         public bool ActivateKeyboard { get; set; } | ||||
|         public ActivationCondition ActivateKeyboard { get; set; } | ||||
|  | ||||
|         public bool CopyTotpToClipboard { get; set; } | ||||
|  | ||||
|  | ||||
|         public override void Setup(Bundle b) | ||||
| 		{ | ||||
| 			ShowUserNotifications = (ShowUserNotificationsMode) GetIntFromBundle(b, ShowUserNotificationsKey, (int)ShowUserNotificationsMode.Always); | ||||
| 			ShowUserNotifications = (ActivationCondition) GetIntFromBundle(b, ShowUserNotificationsKey, (int)ActivationCondition.Always); | ||||
| 			CloseAfterCreate = GetBoolFromBundle(b, CloseAfterCreateKey, true); | ||||
|             ActivateKeyboard = GetBoolFromBundle(b, ActivateKeyboardKey, true); | ||||
|             ActivateKeyboard = (ActivationCondition)GetIntFromBundle(b, ActivateKeyboardKey, (int)ActivationCondition.Always); | ||||
|             CopyTotpToClipboard = GetBoolFromBundle(b, CopyTotpToClipboardKey, false); | ||||
|         } | ||||
|  | ||||
|  | ||||
| @@ -581,7 +604,8 @@ namespace keepass2android | ||||
| 			{ | ||||
| 				yield return new StringExtra { Key = ShowUserNotificationsKey, Value = ((int)ShowUserNotifications).ToString() }; | ||||
| 				yield return new StringExtra { Key = CloseAfterCreateKey, Value = CloseAfterCreate.ToString() }; | ||||
|                 yield return new StringExtra { Key = ActivateKeyboardKey, Value = ActivateKeyboard.ToString() }; | ||||
|                 yield return new StringExtra { Key = ActivateKeyboardKey, Value = ((int)ActivateKeyboard).ToString() }; | ||||
|                 yield return new StringExtra { Key = CopyTotpToClipboardKey, Value = CopyTotpToClipboard.ToString() }; | ||||
|             } | ||||
| 		} | ||||
|  | ||||
| @@ -591,18 +615,43 @@ namespace keepass2android | ||||
| 		    if (ctx == null) | ||||
| 		        ctx = LocaleManager.LocalizedAppContext; | ||||
|  | ||||
| 			if ((ShowUserNotifications == ShowUserNotificationsMode.Always) | ||||
|                 || ((ShowUserNotifications == ShowUserNotificationsMode.WhenTotp) && new Kp2aTotp().TryGetAdapter(new PwEntryOutput(activity.Entry, App.Kp2a.CurrentDb)) != null)) | ||||
| 			{ | ||||
| 				//show the notifications | ||||
| 				activity.StartNotificationsService(ActivateKeyboard); | ||||
| 			} | ||||
|             var pwEntryOutput = new PwEntryOutput(activity.Entry, App.Kp2a.CurrentDb); | ||||
|             var totpPluginAdapter = new Kp2aTotp().TryGetAdapter(pwEntryOutput); | ||||
|             bool isTotpEntry = totpPluginAdapter != null; | ||||
| 			 | ||||
|             bool activateKeyboard = ActivateKeyboard == ActivationCondition.Always || (ActivateKeyboard == ActivationCondition.WhenTotp && isTotpEntry); | ||||
|  | ||||
|             if ((ShowUserNotifications == ActivationCondition.Always) | ||||
|                 || ((ShowUserNotifications == ActivationCondition.WhenTotp) && isTotpEntry) | ||||
|                 || activateKeyboard) | ||||
|             { | ||||
|                 //show the notifications | ||||
|                 activity.StartNotificationsService(activateKeyboard); | ||||
|             } | ||||
| 			else | ||||
| 			{ | ||||
| 				//to avoid getting into inconsistent state (LastOpenedEntry and Notifications): clear notifications: | ||||
| 				CopyToClipboardService.CancelNotifications(activity); | ||||
| 			} | ||||
| 			if (CloseAfterCreate) | ||||
|  | ||||
|             if (CopyTotpToClipboard && isTotpEntry) | ||||
|             { | ||||
|                 Dictionary<string, string> entryFields = pwEntryOutput.OutputStrings.ToDictionary(pair => StrUtil.SafeXmlString(pair.Key), pair => pair.Value.ReadString()); | ||||
|                 var totpData= totpPluginAdapter.GetTotpData(entryFields, activity, true); | ||||
|                 if (totpData.IsTotpEntry) | ||||
|                 { | ||||
|                     TOTPProvider prov = new TOTPProvider(totpData); | ||||
|                     string totp = prov.GenerateByByte(totpData.TotpSecret); | ||||
|                     CopyToClipboardService.CopyValueToClipboardWithTimeout(activity, totp, true); | ||||
|  | ||||
|                     Toast.MakeText(activity, activity.GetString(Resource.String.TotpCopiedToClipboard), | ||||
|                         ToastLength.Long).Show(); | ||||
|                 } | ||||
|  | ||||
|                  | ||||
|             } | ||||
|  | ||||
|             if (CloseAfterCreate) | ||||
|             { | ||||
| 				//give plugins and TOTP time to do their work: | ||||
|                 notifyPluginsOnOpenThread.Join(TimeSpan.FromSeconds(1)); | ||||
| @@ -671,8 +720,8 @@ namespace keepass2android | ||||
| 	public class CreateEntryThenCloseTask: AppTask | ||||
| 	{ | ||||
| 		public CreateEntryThenCloseTask() | ||||
| 		{ | ||||
| 			ShowUserNotifications = ShowUserNotificationsMode.Always; | ||||
|         { | ||||
| 			ShowUserNotifications = ActivationCondition.Always; | ||||
| 		} | ||||
|  | ||||
| 	    public override bool CanActivateSearchViewOnStart | ||||
| @@ -712,13 +761,13 @@ namespace keepass2android | ||||
|  | ||||
| 		public IList<string> ProtectedFieldsList { get; set; } | ||||
|  | ||||
| 		public ShowUserNotificationsMode ShowUserNotifications { get; set; } | ||||
| 		public ActivationCondition ShowUserNotifications { get; set; } | ||||
|  | ||||
|  | ||||
| 		public override void Setup(Bundle b) | ||||
| 		{ | ||||
| 			 | ||||
| 			ShowUserNotifications = (ShowUserNotificationsMode)GetIntFromBundle(b,ShowUserNotificationsKey, (int)ShowUserNotificationsMode.Always); | ||||
| 			ShowUserNotifications = (ActivationCondition)GetIntFromBundle(b,ShowUserNotificationsKey, (int)ActivationCondition.Always); | ||||
| 			 | ||||
| 			Url = b.GetString(UrlKey); | ||||
| 			AllFields = b.GetString(AllFieldsKey); | ||||
| @@ -766,7 +815,7 @@ namespace keepass2android | ||||
| 		public override void AfterAddNewEntry(EntryEditActivity entryEditActivity, PwEntry newEntry) | ||||
| 		{ | ||||
| 			EntryActivity.Launch(entryEditActivity, newEntry, -1,  | ||||
| 				new SelectEntryTask { ShowUserNotifications = this.ShowUserNotifications},  | ||||
| 				new SelectEntryTask() { ShowUserNotifications = this.ShowUserNotifications, ActivateKeyboard = ActivationCondition.Never },  | ||||
| 				ActivityFlags.ForwardResult); | ||||
| 			//no need to call Finish here, that's done in EntryEditActivity ("closeOrShowError")	 | ||||
| 		} | ||||
|   | ||||
| @@ -501,24 +501,8 @@ namespace keepass2android | ||||
|                 if (hasKeyboardDataNow) | ||||
|                 { | ||||
|                     notBuilder.AddKeyboardAccess(); | ||||
|                     if (prefs.GetBoolean("kp2a_switch_rooted", false)) | ||||
|                     { | ||||
|                         //switch rooted | ||||
|                         bool onlySwitchOnSearch = prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key), false); | ||||
|                         if (activateKeyboard || (!onlySwitchOnSearch)) | ||||
|                         { | ||||
|                             ActivateKp2aKeyboard(); | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         //if the app is about to be closed again (e.g. after searching for a URL and returning to the browser: | ||||
|                         // automatically bring up the Keyboard selection dialog | ||||
|                         if ((activateKeyboard) && prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default))) | ||||
|                         { | ||||
|                             ActivateKp2aKeyboard(); | ||||
|                         } | ||||
|                     } | ||||
|                     if (activateKeyboard) | ||||
|                         ActivateKp2aKeyboard(); | ||||
|  | ||||
|                 } | ||||
|  | ||||
| @@ -548,31 +532,6 @@ namespace keepass2android | ||||
|              | ||||
|         } | ||||
|  | ||||
|         public void ActivateKeyboardIfAppropriate(bool closeAfterCreate, ISharedPreferences prefs) | ||||
|         { | ||||
|             if (prefs.GetBoolean("kp2a_switch_rooted", false)) | ||||
|             { | ||||
|                 //switch rooted | ||||
|                 bool onlySwitchOnSearch = prefs.GetBoolean( | ||||
|                     GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key), false); | ||||
|                 if (closeAfterCreate || (!onlySwitchOnSearch)) | ||||
|                 { | ||||
|                     ActivateKp2aKeyboard(); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 //if the app is about to be closed again (e.g. after searching for a URL and returning to the browser: | ||||
|                 // automatically bring up the Keyboard selection dialog | ||||
|                 if ((closeAfterCreate) && | ||||
|                     prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), | ||||
|                         Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default))) | ||||
|                 { | ||||
|                     ActivateKp2aKeyboard(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private bool ClearNotifications() | ||||
|         { | ||||
|             // Notification Manager | ||||
| @@ -865,14 +824,9 @@ namespace keepass2android | ||||
|                 { | ||||
|                     //let's bring up the keyboard switching dialog. | ||||
|                     //Unfortunately this no longer works starting with Android 9 if our app is not in foreground. | ||||
|                     bool mustUseHelperActivity = false; | ||||
|                     if ((int)Build.VERSION.SdkInt >= 28) | ||||
|                     { | ||||
|                         ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo(); | ||||
|                         ActivityManager.GetMyMemoryState(appProcessInfo); | ||||
|                         //at least on Samsung devices, we always need the helper activity | ||||
|                         mustUseHelperActivity = (appProcessInfo.Importance != Importance.Foreground) || (Build.Manufacturer != "Google"); | ||||
|                     } | ||||
|                     //first it seemed to be required for Samsung mostly, but there are use cases where it is required for other devices as well. | ||||
|                     //Let's be sure and use the helper activity. | ||||
|                     bool mustUseHelperActivity = (int)Build.VERSION.SdkInt >= 28; | ||||
|                     if (mustUseHelperActivity) | ||||
|                     { | ||||
|                         try | ||||
|   | ||||
| @@ -10,6 +10,7 @@ using Android.OS; | ||||
| using Android.Runtime; | ||||
| using Android.Views; | ||||
| using Android.Widget; | ||||
| using AndroidX.Preference; | ||||
| using KeePass.Util.Spr; | ||||
| using keepass2android.services.AutofillBase; | ||||
| using keepass2android.services.AutofillBase.model; | ||||
| @@ -26,6 +27,32 @@ namespace keepass2android.services.Kp2aAutofill | ||||
|         Permission = "keepass2android." + AppNames.PackagePart + ".permission.Kp2aChooseAutofill")] | ||||
|     public class ChooseForAutofillActivity : ChooseForAutofillActivityBase | ||||
|     { | ||||
|         public bool ActivateKeyboardWhenTotpPreference | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return PreferenceManager.GetDefaultSharedPreferences(this) | ||||
|                     .GetBoolean("AutoFillTotp_prefs_ActivateKeyboard_key", false); | ||||
|             } | ||||
|         } | ||||
|         public bool CopyTotpToClipboardPreference | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return PreferenceManager.GetDefaultSharedPreferences(this) | ||||
|                     .GetBoolean("AutoFillTotp_prefs_CopyTotpToClipboard_key", true); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public bool ShowNotificationPreference | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return PreferenceManager.GetDefaultSharedPreferences(this) | ||||
|                     .GetBoolean("AutoFillTotp_prefs_ShowNotification_key", true); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         protected override Intent GetQueryIntent(string requestedUrl, bool autoReturnFromQuery, bool useLastOpenedEntry) | ||||
|         { | ||||
|             if (useLastOpenedEntry && (App.Kp2a.LastOpenedEntry?.SearchUrl == requestedUrl)) | ||||
| @@ -36,16 +63,33 @@ namespace keepass2android.services.Kp2aAutofill | ||||
|             //will return the results later | ||||
|             Intent i = new Intent(this, typeof(SelectCurrentDbActivity)); | ||||
|             //don't show user notifications when an entry is opened. | ||||
|             var task = new SearchUrlTask() { UrlToSearchFor = requestedUrl, ShowUserNotifications = ShowUserNotificationsMode.WhenTotp, AutoReturnFromQuery = autoReturnFromQuery, ActivateKeyboard = false }; | ||||
|             var task = new SearchUrlTask() | ||||
|             { | ||||
|                 UrlToSearchFor = requestedUrl, | ||||
|                 AutoReturnFromQuery = autoReturnFromQuery | ||||
|             }; | ||||
|             SetTotpDependantActionsOnTask(task); | ||||
|  | ||||
|             task.ToIntent(i); | ||||
|             return i; | ||||
|         } | ||||
|  | ||||
|         private void SetTotpDependantActionsOnTask(SelectEntryTask task) | ||||
|         { | ||||
|             task.ShowUserNotifications = | ||||
|                 ShowNotificationPreference ? ActivationCondition.WhenTotp : ActivationCondition.Never; | ||||
|             task.CopyTotpToClipboard = CopyTotpToClipboardPreference; | ||||
|             task.ActivateKeyboard = ActivateKeyboardWhenTotpPreference | ||||
|                 ? ActivationCondition.WhenTotp | ||||
|                 : ActivationCondition.Never; | ||||
|         } | ||||
|  | ||||
|         protected override Intent GetOpenEntryIntent(string entryUuid) | ||||
|         { | ||||
|             Intent i = new Intent(this, typeof(SelectCurrentDbActivity)); | ||||
|             //don't show user notifications when an entry is opened. | ||||
|             var task = new OpenSpecificEntryTask() { EntryUuid = entryUuid, ShowUserNotifications = ShowUserNotificationsMode.WhenTotp, ActivateKeyboard = false}; | ||||
|             var task = new OpenSpecificEntryTask() { EntryUuid = entryUuid }; | ||||
|             SetTotpDependantActionsOnTask(task); | ||||
|             task.ToIntent(i); | ||||
|             return i; | ||||
|         } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Philipp Crocoll
					Philipp Crocoll