diff --git a/src/Android/MainApplication.cs b/src/Android/MainApplication.cs index 95ef08b3b..ecb9ca277 100644 --- a/src/Android/MainApplication.cs +++ b/src/Android/MainApplication.cs @@ -130,7 +130,7 @@ namespace Bit.Droid var secureStorageService = new SecureStorageService(); var cryptoPrimitiveService = new CryptoPrimitiveService(); var mobileStorageService = new MobileStorageService(preferencesStorage, liteDbStorage); - var stateService = new StateService(mobileStorageService, secureStorageService); + var stateService = new StateService(mobileStorageService, secureStorageService, messagingService); var stateMigrationService = new StateMigrationService(liteDbStorage, preferencesStorage, secureStorageService); var clipboardService = new ClipboardService(stateService); diff --git a/src/App/App.xaml.cs b/src/App/App.xaml.cs index 3b2b1229e..9e534cd72 100644 --- a/src/App/App.xaml.cs +++ b/src/App/App.xaml.cs @@ -202,6 +202,7 @@ namespace Bit.App private async Task ResumedAsync() { + await _stateService.CheckExtensionActiveUserAndSwitchIfNeededAsync(); await _vaultTimeoutService.CheckVaultTimeoutAsync(); _messagingService.Send("startEventTimer"); await UpdateThemeAsync(); diff --git a/src/App/Controls/AccountSwitchingOverlay/AccountSwitchingOverlayViewModel.cs b/src/App/Controls/AccountSwitchingOverlay/AccountSwitchingOverlayViewModel.cs index 3f789b4d1..f9cd86b73 100644 --- a/src/App/Controls/AccountSwitchingOverlay/AccountSwitchingOverlayViewModel.cs +++ b/src/App/Controls/AccountSwitchingOverlay/AccountSwitchingOverlayViewModel.cs @@ -45,23 +45,28 @@ namespace Bit.App.Controls public ICommand LongPressAccountCommand { get; } + public bool FromIOSExtension { get; set; } + private async Task SelectAccountAsync(AccountViewCellViewModel item) { - if (item.AccountView.IsAccount) + if (!item.AccountView.IsAccount) { - if (!item.AccountView.IsActive) + _messagingService.Send(AccountsManagerMessageCommands.ADD_ACCOUNT); + return; + } + + if (!item.AccountView.IsActive) + { + await _stateService.SetActiveUserAsync(item.AccountView.UserId); + _messagingService.Send(AccountsManagerMessageCommands.SWITCHED_ACCOUNT); + if (FromIOSExtension) { - await _stateService.SetActiveUserAsync(item.AccountView.UserId); - _messagingService.Send("switchedAccount"); - } - else if (AllowActiveAccountSelection) - { - _messagingService.Send("switchedAccount"); + await _stateService.SaveExtensionActiveUserIdToStorageAsync(item.AccountView.UserId); } } - else + else if (AllowActiveAccountSelection) { - _messagingService.Send("addAccount"); + _messagingService.Send(AccountsManagerMessageCommands.SWITCHED_ACCOUNT); } } diff --git a/src/App/Services/MobileStorageService.cs b/src/App/Services/MobileStorageService.cs index 723048604..d510f3130 100644 --- a/src/App/Services/MobileStorageService.cs +++ b/src/App/Services/MobileStorageService.cs @@ -25,6 +25,7 @@ namespace Bit.App.Services Constants.LastBuildKey, Constants.ClearCiphersCacheKey, Constants.BiometricIntegrityKey, + Constants.iOSExtensionActiveUserIdKey, Constants.iOSAutoFillClearCiphersCacheKey, Constants.iOSAutoFillBiometricIntegrityKey, Constants.iOSExtensionClearCiphersCacheKey, @@ -32,7 +33,7 @@ namespace Bit.App.Services Constants.iOSShareExtensionClearCiphersCacheKey, Constants.iOSShareExtensionBiometricIntegrityKey, Constants.RememberedEmailKey, - Constants.RememberedOrgIdentifierKey, + Constants.RememberedOrgIdentifierKey }; public MobileStorageService( diff --git a/src/App/Utilities/AccountManagement/AccountsManager.cs b/src/App/Utilities/AccountManagement/AccountsManager.cs index 875078af9..1fac4b900 100644 --- a/src/App/Utilities/AccountManagement/AccountsManager.cs +++ b/src/App/Utilities/AccountManagement/AccountsManager.cs @@ -6,21 +6,11 @@ using Bit.App.Resources; using Bit.Core.Abstractions; using Bit.Core.Enums; using Bit.Core.Models.Domain; +using Bit.Core.Utilities; using Xamarin.Forms; namespace Bit.App.Utilities.AccountManagement { - public static class AccountsManagerMessageCommands - { - public const string LOCKED = "locked"; - public const string LOCK_VAULT = "lockVault"; - public const string LOGOUT = "logout"; - public const string LOGGED_OUT = "loggedOut"; - public const string ADD_ACCOUNT = "addAccount"; - public const string ACCOUNT_ADDED = "accountAdded"; - public const string SWITCHED_ACCOUNT = "switchedAccount"; - } - public class AccountsManager : IAccountsManager { private readonly IBroadcasterService _broadcasterService; @@ -209,7 +199,7 @@ namespace Bit.App.Utilities.AccountManagement private async Task SwitchedAccountAsync() { await AppHelpers.OnAccountSwitchAsync(); - Device.BeginInvokeOnMainThread(async () => + await Device.InvokeOnMainThreadAsync(async () => { if (await _vaultTimeoutService.ShouldTimeoutAsync()) { diff --git a/src/Core/Abstractions/IStateService.cs b/src/Core/Abstractions/IStateService.cs index 8eac4804f..d1a8d68d8 100644 --- a/src/Core/Abstractions/IStateService.cs +++ b/src/Core/Abstractions/IStateService.cs @@ -14,6 +14,7 @@ namespace Bit.Core.Abstractions Task GetActiveUserIdAsync(); Task IsActiveAccountAsync(string userId = null); Task SetActiveUserAsync(string userId); + Task CheckExtensionActiveUserAndSwitchIfNeededAsync(); Task IsAuthenticatedAsync(string userId = null); Task GetUserIdAsync(string email); Task RefreshAccountViewsAsync(bool allowAddAccountRow); @@ -145,5 +146,6 @@ namespace Bit.Core.Abstractions Task SetRefreshTokenAsync(string value, bool skipTokenStorage, string userId = null); Task GetTwoFactorTokenAsync(string email = null); Task SetTwoFactorTokenAsync(string value, string email = null); + Task SaveExtensionActiveUserIdToStorageAsync(string userId); } } diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs index 996358876..a86f246b9 100644 --- a/src/Core/Constants.cs +++ b/src/Core/Constants.cs @@ -25,6 +25,7 @@ public static string iOSExtensionBiometricIntegrityKey = "iOSExtensionBiometricIntegrityState"; public static string iOSShareExtensionClearCiphersCacheKey = "iOSShareExtensionClearCiphersCache"; public static string iOSShareExtensionBiometricIntegrityKey = "iOSShareExtensionBiometricIntegrityState"; + public static string iOSExtensionActiveUserIdKey = "iOSExtensionActiveUserId"; public static string EventCollectionKey = "eventCollection"; public static string RememberedEmailKey = "rememberedEmail"; public static string RememberedOrgIdentifierKey = "rememberedOrgIdentifier"; diff --git a/src/Core/Services/StateService.cs b/src/Core/Services/StateService.cs index 23d8de670..508076b24 100644 --- a/src/Core/Services/StateService.cs +++ b/src/Core/Services/StateService.cs @@ -15,16 +15,20 @@ namespace Bit.Core.Services { private readonly IStorageService _storageService; private readonly IStorageService _secureStorageService; + private readonly IMessagingService _messagingService; private State _state; private bool _migrationChecked; public List AccountViews { get; set; } - public StateService(IStorageService storageService, IStorageService secureStorageService) + public StateService(IStorageService storageService, + IStorageService secureStorageService, + IMessagingService messagingService) { _storageService = storageService; _secureStorageService = secureStorageService; + _messagingService = messagingService; } public async Task GetActiveUserIdAsync() @@ -67,6 +71,28 @@ namespace Bit.Core.Services await SetPreAuthEnvironmentUrlsAsync(await GetEnvironmentUrlsAsync()); } + public async Task CheckExtensionActiveUserAndSwitchIfNeededAsync() + { + var extensionUserId = await GetExtensionActiveUserIdFromStorageAsync(); + if (string.IsNullOrEmpty(extensionUserId)) + { + return; + } + + if (_state?.ActiveUserId == extensionUserId) + { + // Clear the value in case the user changes the active user from the app + // so if that happens and the user sends the app to background and comes back + // the user is not changed again. + await SaveExtensionActiveUserIdToStorageAsync(null); + return; + } + + await SetActiveUserAsync(extensionUserId); + await SaveExtensionActiveUserIdToStorageAsync(null); + _messagingService.Send(AccountsManagerMessageCommands.SWITCHED_ACCOUNT); + } + public async Task IsAuthenticatedAsync(string userId = null) { return await GetAccessTokenAsync(userId) != null; @@ -1510,6 +1536,16 @@ namespace Bit.Core.Services await _storageService.SaveAsync(Constants.StateKey, state); } + private async Task GetExtensionActiveUserIdFromStorageAsync() + { + return await _storageService.GetAsync(Constants.iOSExtensionActiveUserIdKey); + } + + public async Task SaveExtensionActiveUserIdToStorageAsync(string userId) + { + await _storageService.SaveAsync(Constants.iOSExtensionActiveUserIdKey, userId); + } + private async Task CheckStateAsync() { if (!_migrationChecked) diff --git a/src/Core/Utilities/AccountsManagerMessageCommands.cs b/src/Core/Utilities/AccountsManagerMessageCommands.cs new file mode 100644 index 000000000..bdd80a867 --- /dev/null +++ b/src/Core/Utilities/AccountsManagerMessageCommands.cs @@ -0,0 +1,13 @@ +namespace Bit.Core.Utilities +{ + public static class AccountsManagerMessageCommands + { + public const string LOCKED = "locked"; + public const string LOCK_VAULT = "lockVault"; + public const string LOGOUT = "logout"; + public const string LOGGED_OUT = "loggedOut"; + public const string ADD_ACCOUNT = "addAccount"; + public const string ACCOUNT_ADDED = "accountAdded"; + public const string SWITCHED_ACCOUNT = "switchedAccount"; + } +} diff --git a/src/iOS.Core/Utilities/AccountSwitchingOverlayHelper.cs b/src/iOS.Core/Utilities/AccountSwitchingOverlayHelper.cs index 2f771677b..527d98ef2 100644 --- a/src/iOS.Core/Utilities/AccountSwitchingOverlayHelper.cs +++ b/src/iOS.Core/Utilities/AccountSwitchingOverlayHelper.cs @@ -35,7 +35,10 @@ namespace Bit.iOS.Core.Utilities LongPressAccountEnabled = false }; - var vm = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger); + var vm = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger) + { + FromIOSExtension = true + }; overlay.BindingContext = vm; var renderer = Platform.CreateRenderer(overlay.Content); diff --git a/src/iOS.Core/Utilities/iOSCoreHelpers.cs b/src/iOS.Core/Utilities/iOSCoreHelpers.cs index c43a1e180..cfd0bf1bb 100644 --- a/src/iOS.Core/Utilities/iOSCoreHelpers.cs +++ b/src/iOS.Core/Utilities/iOSCoreHelpers.cs @@ -59,7 +59,7 @@ namespace Bit.iOS.Core.Utilities () => ServiceContainer.Resolve("appIdService").GetAppIdAsync()); var cryptoPrimitiveService = new CryptoPrimitiveService(); var mobileStorageService = new MobileStorageService(preferencesStorage, liteDbStorage); - var stateService = new StateService(mobileStorageService, secureStorageService); + var stateService = new StateService(mobileStorageService, secureStorageService, messagingService); var stateMigrationService = new StateMigrationService(liteDbStorage, preferencesStorage, secureStorageService); var deviceActionService = new DeviceActionService(stateService, messagingService);