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:
Philipp Crocoll
2024-01-04 19:06:49 +01:00
parent 5edc070aa8
commit 059280efd0
11 changed files with 212 additions and 96 deletions

View File

@@ -140,7 +140,7 @@ namespace keepass2android
//will return the results later //will return the results later
Intent i = new Intent(this, typeof (SelectCurrentDbActivity)); Intent i = new Intent(this, typeof (SelectCurrentDbActivity));
//don't show user notifications when an entry is opened. //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); task.ToIntent(i);
StartActivityForResult(i, RequestCodeQuery); StartActivityForResult(i, RequestCodeQuery);
_startedQuery = true; _startedQuery = true;

View File

@@ -47,6 +47,7 @@
<string name="oi_filemanager_web">https://openintents.googlecode.com/files/FileManager-2.0.2.apk</string> <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_desc2">KP2A Search</string>
<string name="permission_desc3">KP2A Choose autofill dataset</string> <string name="permission_desc3">KP2A Choose autofill dataset</string>
<string name="AutoFillTotp_prefs_screen_key">AutoFillTotp_prefs_screen_key</string>
<!-- Preference settings --> <!-- Preference settings -->

View File

@@ -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="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="AccServiceAutoFill_prefs">AutoFill Accessibility-Service</string>
<string name="AutoFill_prefs">AutoFill 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_title">KP2A keyboard notification</string>
<string name="ShowKp2aKeyboardNotification_summary">Make full entry accessible through the KP2A keyboard (recommended).</string> <string name="ShowKp2aKeyboardNotification_summary">Make full entry accessible through the KP2A keyboard (recommended).</string>
<string name="OpenKp2aKeyboardAutomatically_title">Switch keyboard</string> <string name="OpenKp2aKeyboardAutomatically_title">Switch keyboard</string>

View File

@@ -461,7 +461,8 @@
android:defaultValue="false" android:defaultValue="false"
android:title="@string/LogAutofillView_title" android:title="@string/LogAutofillView_title"
android:key="@string/LogAutofillView_key" /> android:key="@string/LogAutofillView_key" />
<CheckBoxPreference <CheckBoxPreference
android:enabled="true" android:enabled="true"
@@ -476,6 +477,38 @@
android:summary="@string/AutofillDisabledQueriesPreference_summary" android:summary="@string/AutofillDisabledQueriesPreference_summary"
android:persistent="false" android:persistent="false"
android:key="AutofillDisabledQueriesPreference_key"/> 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> </PreferenceScreen>

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -306,7 +307,27 @@ namespace keepass2android
} }
else if (Intent.Action == Intent.ActionSend) 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
};
} }
} }

View File

@@ -82,20 +82,15 @@ namespace keepass2android
//if user presses back to leave this activity: //if user presses back to leave this activity:
SetResult(Result.Canceled); SetResult(Result.Canceled);
UpdateBottomBarElementVisibility(Resource.Id.select_other_entry, true); UpdateBottomBarElementVisibility(Resource.Id.select_other_entry, true);
UpdateBottomBarElementVisibility(Resource.Id.add_url_entry, true); UpdateBottomBarElementVisibility(Resource.Id.add_url_entry, true);
if (App.Kp2a.DatabaseIsUnlocked) if (App.Kp2a.DatabaseIsUnlocked)
{ {
Query();
Query();
} }
// else: LockCloseListActivity.OnResume will trigger a broadcast (LockDatabase) which will cause the activity to be finished. // else: LockCloseListActivity.OnResume will trigger a broadcast (LockDatabase) which will cause the activity to be finished.
} }
protected override void OnSaveInstanceState(Bundle outState) protected override void OnSaveInstanceState(Bundle outState)
@@ -162,9 +157,17 @@ namespace keepass2android
String searchUrl = searchUrlTask.UrlToSearchFor; String searchUrl = searchUrlTask.UrlToSearchFor;
selectOtherEntry.Visibility = ViewStates.Visible; selectOtherEntry.Visibility = ViewStates.Visible;
var newTask = new SearchUrlTask() { AutoReturnFromQuery = false, UrlToSearchFor = searchUrl }; SearchUrlTask newTask;
if (AppTask is SelectEntryTask currentSelectTask) if (AppTask is SelectEntryTask currentSelectTask)
{
newTask = new SearchUrlTask() { AutoReturnFromQuery = false, UrlToSearchFor = searchUrl, ActivateKeyboard = currentSelectTask.ActivateKeyboard };
newTask.ShowUserNotifications = currentSelectTask.ShowUserNotifications; 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) => { selectOtherEntry.Click += (sender, e) => {
GroupActivity.Launch(this, newTask, new ActivityLaunchModeRequestCode(0)); GroupActivity.Launch(this, newTask, new ActivityLaunchModeRequestCode(0));
@@ -179,7 +182,7 @@ namespace keepass2android
createUrlEntry.Visibility = ViewStates.Visible; createUrlEntry.Visibility = ViewStates.Visible;
createUrlEntry.Click += (sender, e) => 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(); Toast.MakeText(this, GetString(Resource.String.select_group_then_add, new Java.Lang.Object[] { GetString(Resource.String.add_entry) }), ToastLength.Long).Show();
}; };
} }

View File

@@ -10,8 +10,9 @@ namespace keepass2android
{ {
class Kp2aTotp class Kp2aTotp
{ {
public const string TotpKey = "TOTP";
readonly ITotpPluginAdapter[] _pluginAdapters = new ITotpPluginAdapter[] readonly ITotpPluginAdapter[] _pluginAdapters = new ITotpPluginAdapter[]
{ {
new TrayTotpPluginAdapter(), new TrayTotpPluginAdapter(),
new KeeOtpPluginAdapter(), new KeeOtpPluginAdapter(),

View File

@@ -13,7 +13,7 @@ namespace PluginTOTP
{ {
class UpdateTotpTimerTask: TimerTask class UpdateTotpTimerTask: TimerTask
{ {
public const string TotpKey = "TOTP"; public const string TotpKey = Kp2aTotp.TotpKey;
private readonly Context _context; private readonly Context _context;
private readonly ITotpPluginAdapter _adapter; private readonly ITotpPluginAdapter _adapter;

View File

@@ -10,6 +10,9 @@ using System.Threading;
using KeePassLib; using KeePassLib;
using KeePassLib.Security; using KeePassLib.Security;
using KeePassLib.Utility; using KeePassLib.Utility;
using KeeTrayTOTP.Libraries;
using Android.Content.Res;
using Android.Preferences;
namespace keepass2android namespace keepass2android
{ {
@@ -342,7 +345,15 @@ namespace keepass2android
public virtual void CompleteOnCreateEntryActivity(EntryActivity activity, Thread notifyPluginsOnOpenThread) 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) public virtual void PopulatePasswordAccessServiceIntent(Intent intent)
@@ -354,7 +365,8 @@ namespace keepass2android
protected static bool GetBoolFromBundle(Bundle b, string key, bool defaultValue) protected static bool GetBoolFromBundle(Bundle b, string key, bool defaultValue)
{ {
bool boolValue; bool boolValue;
if (!Boolean.TryParse(b.GetString(key), out boolValue)) string stringValue = b.GetString(key);
if (!Boolean.TryParse(stringValue, out boolValue))
{ {
boolValue = defaultValue; boolValue = defaultValue;
} }
@@ -364,7 +376,8 @@ namespace keepass2android
protected static int GetIntFromBundle(Bundle b, string key, int defaultValue) protected static int GetIntFromBundle(Bundle b, string key, int defaultValue)
{ {
int intValue; int intValue;
if (!Int32.TryParse(b.GetString(key), out intValue)) var strValue = b.GetString(key);
if (!Int32.TryParse(strValue, out intValue))
{ {
intValue = defaultValue; intValue = defaultValue;
} }
@@ -384,7 +397,7 @@ namespace keepass2android
/// User is about to search an entry for a given URL /// User is about to search an entry for a given URL
/// </summary> /// </summary>
/// Derive from SelectEntryTask. This means that as soon as an Entry is opened, we're returning with /// 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 class SearchUrlTask: SelectEntryTask
{ {
public SearchUrlTask() public SearchUrlTask()
@@ -393,8 +406,9 @@ namespace keepass2android
} }
public const String UrlToSearchKey = "UrlToSearch"; public const String UrlToSearchKey = "UrlToSearch";
public const String AutoReturnFromQueryKey = "AutoReturnFromQuery";
public string UrlToSearchFor public string UrlToSearchFor
{ {
get; get;
set; set;
@@ -417,7 +431,7 @@ namespace keepass2android
} }
} }
public const String AutoReturnFromQueryKey = "AutoReturnFromQuery";
public bool AutoReturnFromQuery { get; set; } public bool AutoReturnFromQuery { get; set; }
@@ -425,15 +439,19 @@ namespace keepass2android
{ {
if (String.IsNullOrEmpty(UrlToSearchFor)) 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 else
{ {
ShareUrlResults.Launch(act, this, new ActivityLaunchModeRequestCode(0)); 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 //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 //to switch to another database. But the Task is removed already the first time when going through PasswordActivity
// (with the wrong db). // (with the wrong db).
@@ -536,7 +554,7 @@ namespace keepass2android
} }
public enum ShowUserNotificationsMode public enum ActivationCondition
{ {
Never, Never,
WhenTotp, WhenTotp,
@@ -549,29 +567,34 @@ namespace keepass2android
{ {
public SelectEntryTask() public SelectEntryTask()
{ {
ShowUserNotifications = ShowUserNotificationsMode.Always; ShowUserNotifications = ActivationCondition.Always;
CloseAfterCreate = true; CloseAfterCreate = true;
ActivateKeyboard = true; ActivateKeyboard = ActivationCondition.Never;
CopyTotpToClipboard = false;
} }
public const String ShowUserNotificationsKey = "ShowUserNotifications"; public const String ShowUserNotificationsKey = "ShowUserNotifications";
public ShowUserNotificationsMode ShowUserNotifications { get; set; } public ActivationCondition ShowUserNotifications { get; set; }
public const String CloseAfterCreateKey = "CloseAfterCreate"; public const String CloseAfterCreateKey = "CloseAfterCreate";
public const String ActivateKeyboardKey = "ActivateKeyboard"; public const String ActivateKeyboardKey = "ActivateKeyboard";
public const String CopyTotpToClipboardKey = "CopyTotpToClipboard";
public bool CloseAfterCreate { get; set; } 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) 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); 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 = ShowUserNotificationsKey, Value = ((int)ShowUserNotifications).ToString() };
yield return new StringExtra { Key = CloseAfterCreateKey, Value = CloseAfterCreate.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) if (ctx == null)
ctx = LocaleManager.LocalizedAppContext; ctx = LocaleManager.LocalizedAppContext;
if ((ShowUserNotifications == ShowUserNotificationsMode.Always) var pwEntryOutput = new PwEntryOutput(activity.Entry, App.Kp2a.CurrentDb);
|| ((ShowUserNotifications == ShowUserNotificationsMode.WhenTotp) && new Kp2aTotp().TryGetAdapter(new PwEntryOutput(activity.Entry, App.Kp2a.CurrentDb)) != null)) var totpPluginAdapter = new Kp2aTotp().TryGetAdapter(pwEntryOutput);
{ bool isTotpEntry = totpPluginAdapter != null;
//show the notifications
activity.StartNotificationsService(ActivateKeyboard); 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 else
{ {
//to avoid getting into inconsistent state (LastOpenedEntry and Notifications): clear notifications: //to avoid getting into inconsistent state (LastOpenedEntry and Notifications): clear notifications:
CopyToClipboardService.CancelNotifications(activity); 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: //give plugins and TOTP time to do their work:
notifyPluginsOnOpenThread.Join(TimeSpan.FromSeconds(1)); notifyPluginsOnOpenThread.Join(TimeSpan.FromSeconds(1));
@@ -671,8 +720,8 @@ namespace keepass2android
public class CreateEntryThenCloseTask: AppTask public class CreateEntryThenCloseTask: AppTask
{ {
public CreateEntryThenCloseTask() public CreateEntryThenCloseTask()
{ {
ShowUserNotifications = ShowUserNotificationsMode.Always; ShowUserNotifications = ActivationCondition.Always;
} }
public override bool CanActivateSearchViewOnStart public override bool CanActivateSearchViewOnStart
@@ -712,13 +761,13 @@ namespace keepass2android
public IList<string> ProtectedFieldsList { get; set; } public IList<string> ProtectedFieldsList { get; set; }
public ShowUserNotificationsMode ShowUserNotifications { get; set; } public ActivationCondition ShowUserNotifications { get; set; }
public override void Setup(Bundle b) 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); Url = b.GetString(UrlKey);
AllFields = b.GetString(AllFieldsKey); AllFields = b.GetString(AllFieldsKey);
@@ -766,7 +815,7 @@ namespace keepass2android
public override void AfterAddNewEntry(EntryEditActivity entryEditActivity, PwEntry newEntry) public override void AfterAddNewEntry(EntryEditActivity entryEditActivity, PwEntry newEntry)
{ {
EntryActivity.Launch(entryEditActivity, newEntry, -1, EntryActivity.Launch(entryEditActivity, newEntry, -1,
new SelectEntryTask { ShowUserNotifications = this.ShowUserNotifications}, new SelectEntryTask() { ShowUserNotifications = this.ShowUserNotifications, ActivateKeyboard = ActivationCondition.Never },
ActivityFlags.ForwardResult); ActivityFlags.ForwardResult);
//no need to call Finish here, that's done in EntryEditActivity ("closeOrShowError") //no need to call Finish here, that's done in EntryEditActivity ("closeOrShowError")
} }

View File

@@ -501,24 +501,8 @@ namespace keepass2android
if (hasKeyboardDataNow) if (hasKeyboardDataNow)
{ {
notBuilder.AddKeyboardAccess(); notBuilder.AddKeyboardAccess();
if (prefs.GetBoolean("kp2a_switch_rooted", false)) if (activateKeyboard)
{ ActivateKp2aKeyboard();
//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();
}
}
} }
@@ -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() private bool ClearNotifications()
{ {
// Notification Manager // Notification Manager
@@ -865,14 +824,9 @@ namespace keepass2android
{ {
//let's bring up the keyboard switching dialog. //let's bring up the keyboard switching dialog.
//Unfortunately this no longer works starting with Android 9 if our app is not in foreground. //Unfortunately this no longer works starting with Android 9 if our app is not in foreground.
bool mustUseHelperActivity = false; //first it seemed to be required for Samsung mostly, but there are use cases where it is required for other devices as well.
if ((int)Build.VERSION.SdkInt >= 28) //Let's be sure and use the helper activity.
{ bool mustUseHelperActivity = (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");
}
if (mustUseHelperActivity) if (mustUseHelperActivity)
{ {
try try

View File

@@ -10,6 +10,7 @@ using Android.OS;
using Android.Runtime; using Android.Runtime;
using Android.Views; using Android.Views;
using Android.Widget; using Android.Widget;
using AndroidX.Preference;
using KeePass.Util.Spr; using KeePass.Util.Spr;
using keepass2android.services.AutofillBase; using keepass2android.services.AutofillBase;
using keepass2android.services.AutofillBase.model; using keepass2android.services.AutofillBase.model;
@@ -26,6 +27,32 @@ namespace keepass2android.services.Kp2aAutofill
Permission = "keepass2android." + AppNames.PackagePart + ".permission.Kp2aChooseAutofill")] Permission = "keepass2android." + AppNames.PackagePart + ".permission.Kp2aChooseAutofill")]
public class ChooseForAutofillActivity : ChooseForAutofillActivityBase 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) protected override Intent GetQueryIntent(string requestedUrl, bool autoReturnFromQuery, bool useLastOpenedEntry)
{ {
if (useLastOpenedEntry && (App.Kp2a.LastOpenedEntry?.SearchUrl == requestedUrl)) if (useLastOpenedEntry && (App.Kp2a.LastOpenedEntry?.SearchUrl == requestedUrl))
@@ -36,16 +63,33 @@ namespace keepass2android.services.Kp2aAutofill
//will return the results later //will return the results later
Intent i = new Intent(this, typeof(SelectCurrentDbActivity)); Intent i = new Intent(this, typeof(SelectCurrentDbActivity));
//don't show user notifications when an entry is opened. //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); task.ToIntent(i);
return 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) protected override Intent GetOpenEntryIntent(string entryUuid)
{ {
Intent i = new Intent(this, typeof(SelectCurrentDbActivity)); Intent i = new Intent(this, typeof(SelectCurrentDbActivity));
//don't show user notifications when an entry is opened. //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); task.ToIntent(i);
return i; return i;
} }