diff --git a/AuthenticatorPro.Droid/src/Activity/AsyncActivity.cs b/AuthenticatorPro.Droid/src/Activity/AsyncActivity.cs index 0becda9fad..8dfc0c9f5e 100644 --- a/AuthenticatorPro.Droid/src/Activity/AsyncActivity.cs +++ b/AuthenticatorPro.Droid/src/Activity/AsyncActivity.cs @@ -51,8 +51,15 @@ protected override async void OnResume() base.OnResume(); await _onResumeLock.WaitAsync(); - await OnResumeAsync(); - _onResumeLock.Release(); + + try + { + await OnResumeAsync(); + } + finally + { + _onResumeLock.Release(); + } } protected abstract Task OnResumeAsync(); @@ -63,9 +70,15 @@ protected override async void OnActivityResult(int requestCode, [GeneratedEnum] base.OnActivityResult(requestCode, resultCode, intent); await _onResumeLock.WaitAsync(); - _onResumeLock.Release(); - await OnActivityResultAsync(requestCode, resultCode, intent); + try + { + await OnActivityResultAsync(requestCode, resultCode, intent); + } + finally + { + _onResumeLock.Release(); + } } protected abstract Task diff --git a/AuthenticatorPro.Droid/src/Activity/MainActivity.cs b/AuthenticatorPro.Droid/src/Activity/MainActivity.cs index 3c1cf60ffd..2427b1ca3c 100644 --- a/AuthenticatorPro.Droid/src/Activity/MainActivity.cs +++ b/AuthenticatorPro.Droid/src/Activity/MainActivity.cs @@ -245,7 +245,7 @@ protected override async Task OnResumeAsync() _authenticatorList.Visibility = ViewStates.Invisible; }); - switch (await _database.IsOpen(Database.Origin.Activity)) + switch (await _database.IsOpenAsync(Database.Origin.Activity)) { // Unlocked, no need to do anything case true: @@ -266,7 +266,7 @@ protected override async Task OnResumeAsync() { _unlockFragmentOpen = false; - if (!await _database.IsOpen(Database.Origin.Activity)) + if (!await _database.IsOpenAsync(Database.Origin.Activity)) { Finish(); } @@ -283,7 +283,7 @@ protected override async Task OnResumeAsync() { try { - await _database.Open(null, Database.Origin.Activity); + await _database.OpenAsync(null, Database.Origin.Activity); } catch (Exception e) { @@ -670,7 +670,7 @@ private async void OnUnlockAttempted(object sender, string password) try { - await _database.Open(password, Database.Origin.Activity); + await _database.OpenAsync(password, Database.Origin.Activity); } catch (Exception e) { @@ -752,7 +752,7 @@ private void ShowDatabaseErrorDialog(Exception exception) builder.SetPositiveButton(Resource.String.retry, async delegate { - await _database.Close(Database.Origin.Activity); + await _database.CloseAsync(Database.Origin.Activity); Recreate(); }); diff --git a/AuthenticatorPro.Droid/src/Activity/SensitiveSubActivity.cs b/AuthenticatorPro.Droid/src/Activity/SensitiveSubActivity.cs index 28267afcd3..2d87afc757 100644 --- a/AuthenticatorPro.Droid/src/Activity/SensitiveSubActivity.cs +++ b/AuthenticatorPro.Droid/src/Activity/SensitiveSubActivity.cs @@ -14,7 +14,7 @@ protected override async void OnResume() base.OnResume(); var database = Dependencies.Resolve(); - if (!await database.IsOpen(Database.Origin.Activity)) + if (!await database.IsOpenAsync(Database.Origin.Activity)) { Finish(); } diff --git a/AuthenticatorPro.Droid/src/AutoBackupWorker.cs b/AuthenticatorPro.Droid/src/AutoBackupWorker.cs index 5aeb377ee8..503bb0fb62 100644 --- a/AuthenticatorPro.Droid/src/AutoBackupWorker.cs +++ b/AuthenticatorPro.Droid/src/AutoBackupWorker.cs @@ -54,12 +54,12 @@ public AutoBackupWorker(Context context, WorkerParameters workerParams) : base(c private async Task OpenDatabase() { var password = _secureStorageWrapper.GetDatabasePassword(); - await _database.Open(password, Database.Origin.AutoBackup); + await _database.OpenAsync(password, Database.Origin.AutoBackup); } private async Task CloseDatabase() { - await _database.Close(Database.Origin.AutoBackup); + await _database.CloseAsync(Database.Origin.AutoBackup); } private bool HasPersistentPermissionsAtUri(Uri uri) diff --git a/AuthenticatorPro.Droid/src/BaseApplication.cs b/AuthenticatorPro.Droid/src/BaseApplication.cs index 480fe9b49d..adafdeba5e 100644 --- a/AuthenticatorPro.Droid/src/BaseApplication.cs +++ b/AuthenticatorPro.Droid/src/BaseApplication.cs @@ -30,13 +30,13 @@ internal class BaseApplication : Application, ILifecycleObserver public BaseApplication(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { - Dependencies.Register(); + _database = new Database(); + + Dependencies.Register(_database); Dependencies.RegisterApplicationContext(this); AutoLockEnabled = false; PreventNextAutoLock = false; - - _database = Dependencies.Resolve(); } public override void OnCreate() @@ -100,7 +100,7 @@ public async void OnStopped() if (!_preferences.PasswordProtected || _preferences.Timeout == 0) { - await _database.Close(Database.Origin.Application); + await _database.CloseAsync(Database.Origin.Application); } else { @@ -108,7 +108,7 @@ public async void OnStopped() _timeoutTimer.Elapsed += async delegate { - await _database.Close(Database.Origin.Application); + await _database.CloseAsync(Database.Origin.Application); }; _timeoutTimer.Start(); @@ -126,7 +126,7 @@ public void OnStarted() [Export] public async void OnDestroyed() { - await _database.Close(Database.Origin.Application); + await _database.CloseAsync(Database.Origin.Application); } } } \ No newline at end of file diff --git a/AuthenticatorPro.Droid/src/Database.cs b/AuthenticatorPro.Droid/src/Database.cs index 3dc38e8251..ca69e987c2 100644 --- a/AuthenticatorPro.Droid/src/Database.cs +++ b/AuthenticatorPro.Droid/src/Database.cs @@ -25,43 +25,54 @@ public enum Origin Application, Activity, Wear, AutoBackup, Gc, Other } - public async Task GetConnection() + public async Task GetConnectionAsync() { await _lock.WaitAsync(); - if (_connection == null) + try + { + if (_connection == null) + { + throw new InvalidOperationException("Connection not open"); + } + + return _connection; + } + finally { _lock.Release(); - throw new InvalidOperationException("Connection not open"); } - - _lock.Release(); - return _connection; - } - - public async Task IsOpen(Origin origin) - { - await _lock.WaitAsync(); - var isOpen = _connection != null; - Logger.Debug($"Is database open from {origin}? {isOpen}"); - _lock.Release(); - return isOpen; } - public async Task Close(Origin origin) + public async Task IsOpenAsync(Origin origin) { await _lock.WaitAsync(); - if (_connection == null) + try + { + var isOpen = _connection != null; + Logger.Debug($"Is database open from {origin}? {isOpen}"); + return isOpen; + } + finally { _lock.Release(); - return; } + } - Logger.Debug($"Closing database from {origin}"); + public async Task CloseAsync(Origin origin) + { + await _lock.WaitAsync(); try { + if (_connection == null) + { + return; + } + + Logger.Debug($"Closing database from {origin}"); + await _connection.CloseAsync(); _connection = null; } @@ -71,9 +82,8 @@ public async Task Close(Origin origin) } } - public async Task Open(string password, Origin origin) + public async Task OpenAsync(string password, Origin origin) { - await Close(origin); Logger.Debug($"Opening database from {origin}"); var path = GetPath(); @@ -95,26 +105,37 @@ public async Task Open(string password, Origin origin) }); await _lock.WaitAsync(); - _connection = new SQLiteAsyncConnection(connStr); try { - await MigrateAsync(firstLaunch); - } - catch - { - _lock.Release(); - await Close(origin); - throw; - } + if (_connection != null) + { + await _connection.CloseAsync(); + } + + _connection = new SQLiteAsyncConnection(connStr); + + try + { + await MigrateAsync(firstLaunch); + } + catch + { + await _connection.CloseAsync(); + _connection = null; + throw; + } #if DEBUG _connection.Trace = true; _connection.Tracer = Logger.Debug; _connection.TimeExecution = true; #endif - - _lock.Release(); + } + finally + { + _lock.Release(); + } } private async Task MigrateAsync(bool firstLaunch) @@ -140,7 +161,7 @@ private static string GetPath() ); } - public async Task SetPassword(string currentPassword, string newPassword) + public async Task SetPasswordAsync(string currentPassword, string newPassword) { if (currentPassword == newPassword) { @@ -168,7 +189,7 @@ void RestoreBackup() try { - conn = await GetConnection(); + conn = await GetConnectionAsync(); await conn.ExecuteScalarAsync("PRAGMA wal_checkpoint(TRUNCATE)"); } catch @@ -209,17 +230,17 @@ void RestoreBackup() try { - await Close(Origin.Other); + await CloseAsync(Origin.Other); DeleteDatabase(); File.Move(tempPath, dbPath); - await Open(newPassword, Origin.Other); + await OpenAsync(newPassword, Origin.Other); } catch { // Perhaps it wasn't moved correctly File.Delete(tempPath); RestoreBackup(); - await Open(currentPassword, Origin.Other); + await OpenAsync(currentPassword, Origin.Other); throw; } finally @@ -237,13 +258,13 @@ void RestoreBackup() { await conn.ExecuteScalarAsync($"PRAGMA rekey = {quoted}"); - await Close(Origin.Other); - await Open(newPassword, Origin.Other); + await CloseAsync(Origin.Other); + await OpenAsync(newPassword, Origin.Other); } catch { RestoreBackup(); - await Open(currentPassword, Origin.Other); + await OpenAsync(currentPassword, Origin.Other); throw; } finally @@ -255,7 +276,7 @@ void RestoreBackup() public async ValueTask DisposeAsync() { - await Close(Origin.Gc); + await CloseAsync(Origin.Gc); } } } \ No newline at end of file diff --git a/AuthenticatorPro.Droid/src/Dependencies.cs b/AuthenticatorPro.Droid/src/Dependencies.cs index d22a4780a2..7917d71a8e 100644 --- a/AuthenticatorPro.Droid/src/Dependencies.cs +++ b/AuthenticatorPro.Droid/src/Dependencies.cs @@ -23,9 +23,9 @@ internal static class Dependencies { private static readonly TinyIoCContainer Container = TinyIoCContainer.Current; - public static void Register() + public static void Register(Database database) { - Container.Register().AsSingleton(); + Container.Register(database); Container.RegisterMultiple(new [] { typeof(StrongBackupEncryption), typeof(LegacyBackupEncryption), typeof(NoBackupEncryption) diff --git a/AuthenticatorPro.Droid/src/Interface/Fragment/PasswordSetupBottomSheet.cs b/AuthenticatorPro.Droid/src/Interface/Fragment/PasswordSetupBottomSheet.cs index e8aa276266..7d3677fa82 100644 --- a/AuthenticatorPro.Droid/src/Interface/Fragment/PasswordSetupBottomSheet.cs +++ b/AuthenticatorPro.Droid/src/Interface/Fragment/PasswordSetupBottomSheet.cs @@ -107,7 +107,7 @@ private async void OnSetPasswordButtonClick(object sender, EventArgs args) try { var currentPassword = _secureStorageWrapper.GetDatabasePassword(); - await _database.SetPassword(currentPassword, newPassword); + await _database.SetPasswordAsync(currentPassword, newPassword); try { @@ -116,7 +116,7 @@ private async void OnSetPasswordButtonClick(object sender, EventArgs args) catch { // Revert changes - await _database.SetPassword(newPassword, currentPassword); + await _database.SetPasswordAsync(newPassword, currentPassword); throw; } } diff --git a/AuthenticatorPro.Droid/src/Persistence/AsyncRepository.cs b/AuthenticatorPro.Droid/src/Persistence/AsyncRepository.cs index aebde93b94..623d2c5379 100644 --- a/AuthenticatorPro.Droid/src/Persistence/AsyncRepository.cs +++ b/AuthenticatorPro.Droid/src/Persistence/AsyncRepository.cs @@ -21,7 +21,7 @@ protected AsyncRepository(Database database) public async Task CreateAsync(T item) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); try { @@ -35,7 +35,7 @@ public async Task CreateAsync(T item) public async Task GetAsync(TU id) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); try { @@ -49,19 +49,19 @@ public async Task GetAsync(TU id) public async Task> GetAllAsync() { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); return await conn.Table().ToListAsync(); } public async Task UpdateAsync(T item) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); await conn.UpdateAsync(item); } public async Task DeleteAsync(T item) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); await conn.DeleteAsync(item); } } diff --git a/AuthenticatorPro.Droid/src/Persistence/AuthenticatorCategoryRepository.cs b/AuthenticatorPro.Droid/src/Persistence/AuthenticatorCategoryRepository.cs index 0ea4bccbb1..723916d85a 100644 --- a/AuthenticatorPro.Droid/src/Persistence/AuthenticatorCategoryRepository.cs +++ b/AuthenticatorPro.Droid/src/Persistence/AuthenticatorCategoryRepository.cs @@ -21,7 +21,7 @@ public AuthenticatorCategoryRepository(Database database) public async Task CreateAsync(AuthenticatorCategory item) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); var id = new ValueTuple(item.AuthenticatorSecret, item.CategoryId); if (await GetAsync(id) != null) @@ -34,7 +34,7 @@ public async Task CreateAsync(AuthenticatorCategory item) public async Task GetAsync(ValueTuple id) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); var (authSecret, categoryId) = id; try @@ -50,13 +50,13 @@ public async Task GetAsync(ValueTuple id) public async Task> GetAllAsync() { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); return await conn.Table().ToListAsync(); } public async Task UpdateAsync(AuthenticatorCategory item) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); await conn.ExecuteAsync( "UPDATE authenticatorcategory SET authenticatorSecret = ?, categoryId = ?, ranking = ? WHERE authenticatorSecret = ? AND categoryId = ?", item.AuthenticatorSecret, item.CategoryId, item.Ranking, item.AuthenticatorSecret, item.CategoryId); @@ -64,7 +64,7 @@ await conn.ExecuteAsync( public async Task DeleteAsync(AuthenticatorCategory item) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); await conn.ExecuteAsync( "DELETE FROM authenticatorcategory WHERE authenticatorSecret = ? AND categoryId = ?", item.AuthenticatorSecret, item.CategoryId); @@ -72,40 +72,40 @@ await conn.ExecuteAsync( public async Task> GetAllForAuthenticatorAsync(Authenticator auth) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); return await conn.Table().Where(ac => ac.AuthenticatorSecret == auth.Secret) .ToListAsync(); } public async Task> GetAllForCategoryAsync(Category category) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); return await conn.Table().Where(ac => ac.CategoryId == category.Id).ToListAsync(); } public async Task DeleteAllForAuthenticatorAsync(Authenticator authenticator) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); await conn.ExecuteAsync("DELETE FROM authenticatorcategory WHERE authenticatorSecret = ?", authenticator.Secret); } public async Task DeleteAllForCategoryAsync(Category category) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); await conn.ExecuteAsync("DELETE FROM authenticatorcategory WHERE categoryId = ?", category.Id); } public async Task TransferCategoryAsync(Category initial, Category next) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); await conn.ExecuteAsync( "UPDATE authenticatorcategory SET categoryId = ? WHERE categoryId = ?", next.Id, initial.Id); } public async Task TransferAuthenticatorAsync(Authenticator initial, Authenticator next) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); await conn.ExecuteAsync( "UPDATE authenticatorcategory SET authenticatorSecret = ? WHERE authenticatorSecret = ?", next.Secret, initial.Secret); } diff --git a/AuthenticatorPro.Droid/src/Persistence/AuthenticatorRepository.cs b/AuthenticatorPro.Droid/src/Persistence/AuthenticatorRepository.cs index dc05e63673..eab6948696 100644 --- a/AuthenticatorPro.Droid/src/Persistence/AuthenticatorRepository.cs +++ b/AuthenticatorPro.Droid/src/Persistence/AuthenticatorRepository.cs @@ -20,7 +20,7 @@ public AuthenticatorRepository(Database database) : base(database) public async Task ChangeSecretAsync(string oldSecret, string newSecret) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); try { diff --git a/AuthenticatorPro.Droid/src/Persistence/IconPackEntryRepository.cs b/AuthenticatorPro.Droid/src/Persistence/IconPackEntryRepository.cs index 56e1432458..06128da06f 100644 --- a/AuthenticatorPro.Droid/src/Persistence/IconPackEntryRepository.cs +++ b/AuthenticatorPro.Droid/src/Persistence/IconPackEntryRepository.cs @@ -21,7 +21,7 @@ public IconPackEntryRepository(Database database) public async Task CreateAsync(IconPackEntry item) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); var id = new ValueTuple(item.IconPackName, item.Name); if (await GetAsync(id) != null) @@ -34,7 +34,7 @@ public async Task CreateAsync(IconPackEntry item) public async Task GetAsync(ValueTuple id) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); var (packName, name) = id; try @@ -49,13 +49,13 @@ public async Task GetAsync(ValueTuple id) public async Task> GetAllAsync() { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); return await conn.Table().ToListAsync(); } public async Task UpdateAsync(IconPackEntry item) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); await conn.ExecuteAsync( "UPDATE iconpackentry SET iconPackName = ?, name = ?, data = ? WHERE iconPackName = ? AND name = ?", item.IconPackName, item.Name, item.Data, item.IconPackName, item.Name); @@ -63,20 +63,20 @@ await conn.ExecuteAsync( public async Task DeleteAsync(IconPackEntry item) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); await conn.ExecuteAsync( "DELETE FROM iconpackentry WHERE iconPackName = ? AND name = ?", item.IconPackName, item.Name); } public async Task> GetAllForPackAsync(IconPack pack) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); return await conn.Table().Where(e => e.IconPackName == pack.Name).ToListAsync(); } public async Task DeleteAllForPackAsync(IconPack pack) { - var conn = await _database.GetConnection(); + var conn = await _database.GetConnectionAsync(); await conn.ExecuteAsync("DELETE FROM iconpackentry WHERE iconPackName = ?", pack.Name); } } diff --git a/AuthenticatorPro.Droid/src/WearQueryService.cs b/AuthenticatorPro.Droid/src/WearQueryService.cs index d6c4db1959..38d203652f 100644 --- a/AuthenticatorPro.Droid/src/WearQueryService.cs +++ b/AuthenticatorPro.Droid/src/WearQueryService.cs @@ -62,12 +62,12 @@ public override void OnCreate() private async Task OpenDatabaseAsync() { var password = _secureStorageWrapper.GetDatabasePassword(); - await _database.Open(password, Database.Origin.Wear); + await _database.OpenAsync(password, Database.Origin.Wear); } private async Task CloseDatabaseAsync() { - await _database.Close(Database.Origin.Wear); + await _database.CloseAsync(Database.Origin.Wear); } private async Task UseDatabaseAsync(Func> action)