diff --git a/app/src/main/java/eu/faircode/email/ActivityBase.java b/app/src/main/java/eu/faircode/email/ActivityBase.java index c90456780c..a660facaf8 100644 --- a/app/src/main/java/eu/faircode/email/ActivityBase.java +++ b/app/src/main/java/eu/faircode/email/ActivityBase.java @@ -244,7 +244,8 @@ abstract class ActivityBase extends AppCompatActivity implements SharedPreferenc visible = false; - if (!this.getClass().equals(ActivityMain.class) && Helper.shouldAuthenticate(this)) + if (!this.getClass().equals(ActivityMain.class) && + Helper.shouldAuthenticate(this, true)) finishAndRemoveTask(); } @@ -258,7 +259,8 @@ abstract class ActivityBase extends AppCompatActivity implements SharedPreferenc public void onUserInteraction() { Log.d("User interaction"); - if (!this.getClass().equals(ActivityMain.class) && Helper.shouldAuthenticate(this)) { + if (!this.getClass().equals(ActivityMain.class) && + Helper.shouldAuthenticate(this, false)) { finishAndRemoveTask(); Intent main = new Intent(this, ActivityMain.class); main.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); @@ -365,7 +367,8 @@ abstract class ActivityBase extends AppCompatActivity implements SharedPreferenc } private void checkAuthentication() { - if (!this.getClass().equals(ActivityMain.class) && Helper.shouldAuthenticate(this)) { + if (!this.getClass().equals(ActivityMain.class) && + Helper.shouldAuthenticate(this, false)) { Intent intent = getIntent(); finishAndRemoveTask(); processStreams(intent); diff --git a/app/src/main/java/eu/faircode/email/ActivityMain.java b/app/src/main/java/eu/faircode/email/ActivityMain.java index c709979ed5..3cf7be79b4 100644 --- a/app/src/main/java/eu/faircode/email/ActivityMain.java +++ b/app/src/main/java/eu/faircode/email/ActivityMain.java @@ -231,7 +231,7 @@ public class ActivityMain extends ActivityBase implements FragmentManager.OnBack } }; - if (Helper.shouldAuthenticate(this)) + if (Helper.shouldAuthenticate(this, false)) Helper.authenticate(ActivityMain.this, ActivityMain.this, null, new Runnable() { @Override diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsPrivacy.java b/app/src/main/java/eu/faircode/email/FragmentOptionsPrivacy.java index 60edf332ed..963b9250bb 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsPrivacy.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsPrivacy.java @@ -73,6 +73,8 @@ public class FragmentOptionsPrivacy extends FragmentBase implements SharedPrefer private Button btnBiometrics; private Spinner spBiometricsTimeout; private SwitchCompat swAutoLock; + private SwitchCompat swAutoLockNav; + private TextView tvAutoLockNavHint; private SwitchCompat swClientId; private TextView tvClientId; private SwitchCompat swDisplayHidden; @@ -97,7 +99,7 @@ public class FragmentOptionsPrivacy extends FragmentBase implements SharedPrefer "confirm_links", "check_links_dbl", "browse_links", "confirm_images", "ask_images", "html_always_images", "confirm_html", "ask_html", "disable_tracking", "hide_timezone", - "pin", "biometrics", "biometrics_timeout", "autolock", + "pin", "biometrics", "biometrics_timeout", "autolock", "autolock_nav", "client_id", "display_hidden", "incognito_keyboard", "secure", "generic_ua", "safe_browsing", "load_emoji", "disconnect_auto_update", "disconnect_links", "disconnect_images" @@ -127,6 +129,8 @@ public class FragmentOptionsPrivacy extends FragmentBase implements SharedPrefer btnBiometrics = view.findViewById(R.id.btnBiometrics); spBiometricsTimeout = view.findViewById(R.id.spBiometricsTimeout); swAutoLock = view.findViewById(R.id.swAutoLock); + swAutoLockNav = view.findViewById(R.id.swAutoLockNav); + tvAutoLockNavHint = view.findViewById(R.id.tvAutoLockNavHint); swClientId = view.findViewById(R.id.swClientId); tvClientId = view.findViewById(R.id.tvClientId); swDisplayHidden = view.findViewById(R.id.swDisplayHidden); @@ -286,6 +290,15 @@ public class FragmentOptionsPrivacy extends FragmentBase implements SharedPrefer } }); + swAutoLockNav.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { + prefs.edit().putBoolean("autolock_nav", checked).apply(); + } + }); + + tvAutoLockNavHint.setText(getString(R.string.title_advanced_display_autolock_nav_hint, Helper.AUTOLOCK_GRACE)); + swClientId.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { @@ -488,6 +501,7 @@ public class FragmentOptionsPrivacy extends FragmentBase implements SharedPrefer } swAutoLock.setChecked(prefs.getBoolean("autolock", true)); + swAutoLockNav.setChecked(prefs.getBoolean("autolock_nav", false)); swClientId.setChecked(prefs.getBoolean("client_id", true)); swDisplayHidden.setChecked(prefs.getBoolean("display_hidden", false)); diff --git a/app/src/main/java/eu/faircode/email/Helper.java b/app/src/main/java/eu/faircode/email/Helper.java index 7cd01a8782..6d27a50ad7 100644 --- a/app/src/main/java/eu/faircode/email/Helper.java +++ b/app/src/main/java/eu/faircode/email/Helper.java @@ -158,6 +158,7 @@ public class Helper { static final int BUFFER_SIZE = 8192; // Same as in Files class static final long MIN_REQUIRED_SPACE = 250 * 1024L * 1024L; static final int MAX_REDIRECTS = 5; // https://www.freesoft.org/CIE/RFC/1945/46.htm + static final int AUTOLOCK_GRACE = 7; // seconds static final String PGP_BEGIN_MESSAGE = "-----BEGIN PGP MESSAGE-----"; static final String PGP_END_MESSAGE = "-----END PGP MESSAGE-----"; @@ -1866,7 +1867,7 @@ public class Helper { } } - static boolean shouldAuthenticate(Context context) { + static boolean shouldAuthenticate(Context context, boolean pausing) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); boolean biometrics = prefs.getBoolean("biometrics", false); String pin = prefs.getString("pin", null); @@ -1875,12 +1876,17 @@ public class Helper { long now = new Date().getTime(); long last_authentication = prefs.getLong("last_authentication", 0); long biometrics_timeout = prefs.getInt("biometrics_timeout", 2) * 60 * 1000L; + boolean autolock_nav = prefs.getBoolean("autolock_nav", false); Log.i("Authentication valid until=" + new Date(last_authentication + biometrics_timeout)); if (last_authentication + biometrics_timeout < now) return true; - prefs.edit().putLong("last_authentication", now).apply(); + if (autolock_nav && pausing) + last_authentication = now - biometrics_timeout + AUTOLOCK_GRACE * 1000L; + else + last_authentication = now; + prefs.edit().putLong("last_authentication", last_authentication).apply(); } return false; @@ -2005,7 +2011,7 @@ public class Helper { @Override public void onDismiss(DialogInterface dialog) { Log.i("Authenticate PIN dismissed"); - if (shouldAuthenticate(activity)) // Some Android versions call dismiss on OK + if (shouldAuthenticate(activity, false)) // Some Android versions call dismiss on OK ApplicationEx.getMainHandler().post(cancelled); } }) diff --git a/app/src/main/res/layout/fragment_options_privacy.xml b/app/src/main/res/layout/fragment_options_privacy.xml index 9af2e468e9..9738961da4 100644 --- a/app/src/main/res/layout/fragment_options_privacy.xml +++ b/app/src/main/res/layout/fragment_options_privacy.xml @@ -307,6 +307,33 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/spBiometricsTimeout" app:switchPadding="12dp" /> + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d88bde9aec..0413e080f2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -601,6 +601,7 @@ PIN Biometric authentication timeout Lock on screen off + Lock on leaving the app Use generic browser user agent Google Safe browsing (Android 8+) Load updated Emoji from Google Play Services @@ -755,6 +756,7 @@ Disabling this option might be harmful to your privacy This can result in odd looking and double texts A PIN takes precedence over biometrics authentication + There will be a grace time of %1$d seconds The Google server knows which addresses are being looked up Only available on supported launchers