mirror of
https://github.com/bitwarden/android.git
synced 2024-12-26 10:58:29 +03:00
Improved BroadcastService and added try...catch on async void callbacks (#1917)
This commit is contained in:
parent
dbc1e5ea3e
commit
448cce38e1
12 changed files with 335 additions and 257 deletions
|
@ -99,12 +99,13 @@ namespace Bit.Droid
|
||||||
{
|
{
|
||||||
ServiceContainer.Register<INativeLogService>("nativeLogService", new AndroidLogService());
|
ServiceContainer.Register<INativeLogService>("nativeLogService", new AndroidLogService());
|
||||||
#if FDROID
|
#if FDROID
|
||||||
ServiceContainer.Register<ILogger>("logger", new StubLogger());
|
var logger = new StubLogger();
|
||||||
#elif DEBUG
|
#elif DEBUG
|
||||||
ServiceContainer.Register<ILogger>("logger", DebugLogger.Instance);
|
var logger = DebugLogger.Instance;
|
||||||
#else
|
#else
|
||||||
ServiceContainer.Register<ILogger>("logger", Logger.Instance);
|
var logger = Logger.Instance;
|
||||||
#endif
|
#endif
|
||||||
|
ServiceContainer.Register("logger", logger);
|
||||||
|
|
||||||
// Note: This might cause a race condition. Investigate more.
|
// Note: This might cause a race condition. Investigate more.
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
|
@ -124,7 +125,7 @@ namespace Bit.Droid
|
||||||
var documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
|
var documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
|
||||||
var liteDbStorage = new LiteDbStorageService(Path.Combine(documentsPath, "bitwarden.db"));
|
var liteDbStorage = new LiteDbStorageService(Path.Combine(documentsPath, "bitwarden.db"));
|
||||||
var localizeService = new LocalizeService();
|
var localizeService = new LocalizeService();
|
||||||
var broadcasterService = new BroadcasterService();
|
var broadcasterService = new BroadcasterService(logger);
|
||||||
var messagingService = new MobileBroadcasterMessagingService(broadcasterService);
|
var messagingService = new MobileBroadcasterMessagingService(broadcasterService);
|
||||||
var i18nService = new MobileI18nService(localizeService.GetCurrentCultureInfo());
|
var i18nService = new MobileI18nService(localizeService.GetCurrentCultureInfo());
|
||||||
var secureStorageService = new SecureStorageService();
|
var secureStorageService = new SecureStorageService();
|
||||||
|
|
|
@ -10,6 +10,7 @@ using Bit.App.Utilities.AccountManagement;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Models.Data;
|
using Bit.Core.Models.Data;
|
||||||
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using Xamarin.Forms.Xaml;
|
using Xamarin.Forms.Xaml;
|
||||||
|
@ -56,86 +57,93 @@ namespace Bit.App
|
||||||
Bootstrap();
|
Bootstrap();
|
||||||
_broadcasterService.Subscribe(nameof(App), async (message) =>
|
_broadcasterService.Subscribe(nameof(App), async (message) =>
|
||||||
{
|
{
|
||||||
if (message.Command == "showDialog")
|
try
|
||||||
{
|
{
|
||||||
var details = message.Data as DialogDetails;
|
if (message.Command == "showDialog")
|
||||||
var confirmed = true;
|
|
||||||
var confirmText = string.IsNullOrWhiteSpace(details.ConfirmText) ?
|
|
||||||
AppResources.Ok : details.ConfirmText;
|
|
||||||
Device.BeginInvokeOnMainThread(async () =>
|
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(details.CancelText))
|
var details = message.Data as DialogDetails;
|
||||||
|
var confirmed = true;
|
||||||
|
var confirmText = string.IsNullOrWhiteSpace(details.ConfirmText) ?
|
||||||
|
AppResources.Ok : details.ConfirmText;
|
||||||
|
Device.BeginInvokeOnMainThread(async () =>
|
||||||
{
|
{
|
||||||
confirmed = await Current.MainPage.DisplayAlert(details.Title, details.Text, confirmText,
|
if (!string.IsNullOrWhiteSpace(details.CancelText))
|
||||||
details.CancelText);
|
{
|
||||||
}
|
confirmed = await Current.MainPage.DisplayAlert(details.Title, details.Text, confirmText,
|
||||||
else
|
details.CancelText);
|
||||||
{
|
}
|
||||||
await Current.MainPage.DisplayAlert(details.Title, details.Text, confirmText);
|
else
|
||||||
}
|
{
|
||||||
_messagingService.Send("showDialogResolve", new Tuple<int, bool>(details.DialogId, confirmed));
|
await Current.MainPage.DisplayAlert(details.Title, details.Text, confirmText);
|
||||||
});
|
}
|
||||||
}
|
_messagingService.Send("showDialogResolve", new Tuple<int, bool>(details.DialogId, confirmed));
|
||||||
else if (message.Command == "resumed")
|
});
|
||||||
{
|
}
|
||||||
if (Device.RuntimePlatform == Device.iOS)
|
else if (message.Command == "resumed")
|
||||||
{
|
{
|
||||||
ResumedAsync().FireAndForget();
|
if (Device.RuntimePlatform == Device.iOS)
|
||||||
|
{
|
||||||
|
ResumedAsync().FireAndForget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (message.Command == "slept")
|
||||||
|
{
|
||||||
|
if (Device.RuntimePlatform == Device.iOS)
|
||||||
|
{
|
||||||
|
await SleptAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (message.Command == "migrated")
|
||||||
|
{
|
||||||
|
await Task.Delay(1000);
|
||||||
|
await _accountsManager.NavigateOnAccountChangeAsync();
|
||||||
|
}
|
||||||
|
else if (message.Command == "popAllAndGoToTabGenerator" ||
|
||||||
|
message.Command == "popAllAndGoToTabMyVault" ||
|
||||||
|
message.Command == "popAllAndGoToTabSend" ||
|
||||||
|
message.Command == "popAllAndGoToAutofillCiphers")
|
||||||
|
{
|
||||||
|
Device.BeginInvokeOnMainThread(async () =>
|
||||||
|
{
|
||||||
|
if (Current.MainPage is TabsPage tabsPage)
|
||||||
|
{
|
||||||
|
while (tabsPage.Navigation.ModalStack.Count > 0)
|
||||||
|
{
|
||||||
|
await tabsPage.Navigation.PopModalAsync(false);
|
||||||
|
}
|
||||||
|
if (message.Command == "popAllAndGoToAutofillCiphers")
|
||||||
|
{
|
||||||
|
Current.MainPage = new NavigationPage(new AutofillCiphersPage(Options));
|
||||||
|
}
|
||||||
|
else if (message.Command == "popAllAndGoToTabMyVault")
|
||||||
|
{
|
||||||
|
Options.MyVaultTile = false;
|
||||||
|
tabsPage.ResetToVaultPage();
|
||||||
|
}
|
||||||
|
else if (message.Command == "popAllAndGoToTabGenerator")
|
||||||
|
{
|
||||||
|
Options.GeneratorTile = false;
|
||||||
|
tabsPage.ResetToGeneratorPage();
|
||||||
|
}
|
||||||
|
else if (message.Command == "popAllAndGoToTabSend")
|
||||||
|
{
|
||||||
|
tabsPage.ResetToSendPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (message.Command == "convertAccountToKeyConnector")
|
||||||
|
{
|
||||||
|
Device.BeginInvokeOnMainThread(async () =>
|
||||||
|
{
|
||||||
|
await Application.Current.MainPage.Navigation.PushModalAsync(
|
||||||
|
new NavigationPage(new RemoveMasterPasswordPage()));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (message.Command == "slept")
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (Device.RuntimePlatform == Device.iOS)
|
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||||
{
|
|
||||||
await SleptAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (message.Command == "migrated")
|
|
||||||
{
|
|
||||||
await Task.Delay(1000);
|
|
||||||
await _accountsManager.NavigateOnAccountChangeAsync();
|
|
||||||
}
|
|
||||||
else if (message.Command == "popAllAndGoToTabGenerator" ||
|
|
||||||
message.Command == "popAllAndGoToTabMyVault" ||
|
|
||||||
message.Command == "popAllAndGoToTabSend" ||
|
|
||||||
message.Command == "popAllAndGoToAutofillCiphers")
|
|
||||||
{
|
|
||||||
Device.BeginInvokeOnMainThread(async () =>
|
|
||||||
{
|
|
||||||
if (Current.MainPage is TabsPage tabsPage)
|
|
||||||
{
|
|
||||||
while (tabsPage.Navigation.ModalStack.Count > 0)
|
|
||||||
{
|
|
||||||
await tabsPage.Navigation.PopModalAsync(false);
|
|
||||||
}
|
|
||||||
if (message.Command == "popAllAndGoToAutofillCiphers")
|
|
||||||
{
|
|
||||||
Current.MainPage = new NavigationPage(new AutofillCiphersPage(Options));
|
|
||||||
}
|
|
||||||
else if (message.Command == "popAllAndGoToTabMyVault")
|
|
||||||
{
|
|
||||||
Options.MyVaultTile = false;
|
|
||||||
tabsPage.ResetToVaultPage();
|
|
||||||
}
|
|
||||||
else if (message.Command == "popAllAndGoToTabGenerator")
|
|
||||||
{
|
|
||||||
Options.GeneratorTile = false;
|
|
||||||
tabsPage.ResetToGeneratorPage();
|
|
||||||
}
|
|
||||||
else if (message.Command == "popAllAndGoToTabSend")
|
|
||||||
{
|
|
||||||
tabsPage.ResetToSendPage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (message.Command == "convertAccountToKeyConnector")
|
|
||||||
{
|
|
||||||
Device.BeginInvokeOnMainThread(async () =>
|
|
||||||
{
|
|
||||||
await Application.Current.MainPage.Navigation.PushModalAsync(
|
|
||||||
new NavigationPage(new RemoveMasterPasswordPage()));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
_vm.AvatarImageSource = await GetAvatarImageSourceAsync();
|
_vm.AvatarImageSource = await GetAvatarImageSourceAsync();
|
||||||
}
|
}
|
||||||
_broadcasterService.Subscribe(nameof(HomePage), async (message) =>
|
_broadcasterService.Subscribe(nameof(HomePage), (message) =>
|
||||||
{
|
{
|
||||||
if (message.Command == "updatedTheme")
|
if (message.Command == "updatedTheme")
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,7 @@ using Bit.App.Controls;
|
||||||
using Bit.App.Models;
|
using Bit.App.Models;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
@ -68,21 +69,28 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
_broadcasterService.Subscribe(_pageName, async (message) =>
|
_broadcasterService.Subscribe(_pageName, async (message) =>
|
||||||
{
|
{
|
||||||
if (message.Command == "syncStarted")
|
try
|
||||||
{
|
{
|
||||||
Device.BeginInvokeOnMainThread(() => IsBusy = true);
|
if (message.Command == "syncStarted")
|
||||||
}
|
|
||||||
else if (message.Command == "syncCompleted" || message.Command == "sendUpdated")
|
|
||||||
{
|
|
||||||
await Task.Delay(500);
|
|
||||||
Device.BeginInvokeOnMainThread(() =>
|
|
||||||
{
|
{
|
||||||
IsBusy = false;
|
Device.BeginInvokeOnMainThread(() => IsBusy = true);
|
||||||
if (_vm.LoadedOnce)
|
}
|
||||||
|
else if (message.Command == "syncCompleted" || message.Command == "sendUpdated")
|
||||||
|
{
|
||||||
|
await Task.Delay(500);
|
||||||
|
Device.BeginInvokeOnMainThread(() =>
|
||||||
{
|
{
|
||||||
var task = _vm.LoadAsync();
|
IsBusy = false;
|
||||||
}
|
if (_vm.LoadedOnce)
|
||||||
});
|
{
|
||||||
|
var task = _vm.LoadAsync();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ using Bit.App.Models;
|
||||||
using Bit.App.Utilities;
|
using Bit.App.Utilities;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
@ -55,21 +56,28 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
_broadcasterService.Subscribe(nameof(AutofillCiphersPage), async (message) =>
|
_broadcasterService.Subscribe(nameof(AutofillCiphersPage), async (message) =>
|
||||||
{
|
{
|
||||||
if (message.Command == "syncStarted")
|
try
|
||||||
{
|
{
|
||||||
Device.BeginInvokeOnMainThread(() => IsBusy = true);
|
if (message.Command == "syncStarted")
|
||||||
}
|
|
||||||
else if (message.Command == "syncCompleted")
|
|
||||||
{
|
|
||||||
await Task.Delay(500);
|
|
||||||
Device.BeginInvokeOnMainThread(() =>
|
|
||||||
{
|
{
|
||||||
IsBusy = false;
|
Device.BeginInvokeOnMainThread(() => IsBusy = true);
|
||||||
if (_vm.LoadedOnce)
|
}
|
||||||
|
else if (message.Command == "syncCompleted")
|
||||||
|
{
|
||||||
|
await Task.Delay(500);
|
||||||
|
Device.BeginInvokeOnMainThread(() =>
|
||||||
{
|
{
|
||||||
var task = _vm.LoadAsync();
|
IsBusy = false;
|
||||||
}
|
if (_vm.LoadedOnce)
|
||||||
});
|
{
|
||||||
|
var task = _vm.LoadAsync();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ using Bit.App.Resources;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Models.Data;
|
using Bit.Core.Models.Data;
|
||||||
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
@ -95,21 +96,28 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
_broadcasterService.Subscribe(_pageName, async (message) =>
|
_broadcasterService.Subscribe(_pageName, async (message) =>
|
||||||
{
|
{
|
||||||
if (message.Command == "syncStarted")
|
try
|
||||||
{
|
{
|
||||||
Device.BeginInvokeOnMainThread(() => IsBusy = true);
|
if (message.Command == "syncStarted")
|
||||||
}
|
|
||||||
else if (message.Command == "syncCompleted")
|
|
||||||
{
|
|
||||||
await Task.Delay(500);
|
|
||||||
Device.BeginInvokeOnMainThread(() =>
|
|
||||||
{
|
{
|
||||||
IsBusy = false;
|
Device.BeginInvokeOnMainThread(() => IsBusy = true);
|
||||||
if (_vm.LoadedOnce)
|
}
|
||||||
|
else if (message.Command == "syncCompleted")
|
||||||
|
{
|
||||||
|
await Task.Delay(500);
|
||||||
|
Device.BeginInvokeOnMainThread(() =>
|
||||||
{
|
{
|
||||||
var task = _vm.LoadAsync();
|
IsBusy = false;
|
||||||
}
|
if (_vm.LoadedOnce)
|
||||||
});
|
{
|
||||||
|
var task = _vm.LoadAsync();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
@ -56,37 +57,44 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
_broadcasterService.Subscribe(nameof(ViewPage), async (message) =>
|
_broadcasterService.Subscribe(nameof(ViewPage), async (message) =>
|
||||||
{
|
{
|
||||||
if (message.Command == "syncStarted")
|
try
|
||||||
{
|
{
|
||||||
Device.BeginInvokeOnMainThread(() => IsBusy = true);
|
if (message.Command == "syncStarted")
|
||||||
}
|
|
||||||
else if (message.Command == "syncCompleted")
|
|
||||||
{
|
|
||||||
await Task.Delay(500);
|
|
||||||
Device.BeginInvokeOnMainThread(() =>
|
|
||||||
{
|
{
|
||||||
IsBusy = false;
|
Device.BeginInvokeOnMainThread(() => IsBusy = true);
|
||||||
if (message.Data is Dictionary<string, object> data && data.ContainsKey("successfully"))
|
}
|
||||||
|
else if (message.Command == "syncCompleted")
|
||||||
|
{
|
||||||
|
await Task.Delay(500);
|
||||||
|
Device.BeginInvokeOnMainThread(() =>
|
||||||
{
|
{
|
||||||
var success = data["successfully"] as bool?;
|
IsBusy = false;
|
||||||
if (success.GetValueOrDefault())
|
if (message.Data is Dictionary<string, object> data && data.ContainsKey("successfully"))
|
||||||
{
|
{
|
||||||
var task = _vm.LoadAsync(() => AdjustToolbar());
|
var success = data["successfully"] as bool?;
|
||||||
|
if (success.GetValueOrDefault())
|
||||||
|
{
|
||||||
|
var task = _vm.LoadAsync(() => AdjustToolbar());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
else if (message.Command == "selectSaveFileResult")
|
||||||
else if (message.Command == "selectSaveFileResult")
|
|
||||||
{
|
|
||||||
Device.BeginInvokeOnMainThread(() =>
|
|
||||||
{
|
{
|
||||||
var data = message.Data as Tuple<string, string>;
|
Device.BeginInvokeOnMainThread(() =>
|
||||||
if (data == null)
|
|
||||||
{
|
{
|
||||||
return;
|
var data = message.Data as Tuple<string, string>;
|
||||||
}
|
if (data == null)
|
||||||
_vm.SaveFileSelected(data.Item1, data.Item2);
|
{
|
||||||
});
|
return;
|
||||||
|
}
|
||||||
|
_vm.SaveFileSelected(data.Item1, data.Item2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await LoadOnAppearedAsync(_scrollView, true, async () =>
|
await LoadOnAppearedAsync(_scrollView, true, async () =>
|
||||||
|
|
|
@ -5,7 +5,8 @@ namespace Bit.Core.Abstractions
|
||||||
{
|
{
|
||||||
public interface IBroadcasterService
|
public interface IBroadcasterService
|
||||||
{
|
{
|
||||||
void Send(Message message, string id = null);
|
void Send(Message message);
|
||||||
|
void Send(Message message, string id);
|
||||||
void Subscribe(string id, Action<Message> messageCallback);
|
void Subscribe(string id, Action<Message> messageCallback);
|
||||||
void Unsubscribe(string id);
|
void Unsubscribe(string id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,24 +8,58 @@ namespace Bit.App.Services
|
||||||
{
|
{
|
||||||
public class BroadcasterService : IBroadcasterService
|
public class BroadcasterService : IBroadcasterService
|
||||||
{
|
{
|
||||||
|
private readonly ILogger _logger;
|
||||||
private readonly Dictionary<string, Action<Message>> _subscribers = new Dictionary<string, Action<Message>>();
|
private readonly Dictionary<string, Action<Message>> _subscribers = new Dictionary<string, Action<Message>>();
|
||||||
private object _myLock = new object();
|
private object _myLock = new object();
|
||||||
|
|
||||||
public void Send(Message message, string id = null)
|
public BroadcasterService(ILogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(Message message)
|
||||||
{
|
{
|
||||||
lock (_myLock)
|
lock (_myLock)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(id))
|
|
||||||
{
|
|
||||||
if (_subscribers.ContainsKey(id))
|
|
||||||
{
|
|
||||||
Task.Run(() => _subscribers[id].Invoke(message));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
foreach (var sub in _subscribers)
|
foreach (var sub in _subscribers)
|
||||||
{
|
{
|
||||||
Task.Run(() => sub.Value.Invoke(message));
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sub.Value(message);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Exception(ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(Message message, string id)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(id))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (_myLock)
|
||||||
|
{
|
||||||
|
if (_subscribers.TryGetValue(id, out var action))
|
||||||
|
{
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
action(message);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Exception(ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,14 +68,7 @@ namespace Bit.App.Services
|
||||||
{
|
{
|
||||||
lock (_myLock)
|
lock (_myLock)
|
||||||
{
|
{
|
||||||
if (_subscribers.ContainsKey(id))
|
_subscribers[id] = messageCallback;
|
||||||
{
|
|
||||||
_subscribers[id] = messageCallback;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_subscribers.Add(id, messageCallback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Bit.iOS.Core.Renderers
|
||||||
public CustomTabbedRenderer()
|
public CustomTabbedRenderer()
|
||||||
{
|
{
|
||||||
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
|
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
|
||||||
_broadcasterService.Subscribe(nameof(CustomTabbedRenderer), async (message) =>
|
_broadcasterService.Subscribe(nameof(CustomTabbedRenderer), (message) =>
|
||||||
{
|
{
|
||||||
if (message.Command == "updatedTheme")
|
if (message.Command == "updatedTheme")
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,13 +38,15 @@ namespace Bit.iOS.Core.Utilities
|
||||||
ServiceContainer.Register<INativeLogService>("nativeLogService", new ConsoleLogService());
|
ServiceContainer.Register<INativeLogService>("nativeLogService", new ConsoleLogService());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ILogger logger = null;
|
||||||
if (ServiceContainer.Resolve<ILogger>("logger", true) == null)
|
if (ServiceContainer.Resolve<ILogger>("logger", true) == null)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
ServiceContainer.Register<ILogger>("logger", DebugLogger.Instance);
|
logger = DebugLogger.Instance;
|
||||||
#else
|
#else
|
||||||
ServiceContainer.Register<ILogger>("logger", Logger.Instance);
|
logger = Logger.Instance;
|
||||||
#endif
|
#endif
|
||||||
|
ServiceContainer.Register("logger", logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
var preferencesStorage = new PreferencesStorageService(AppGroupId);
|
var preferencesStorage = new PreferencesStorageService(AppGroupId);
|
||||||
|
@ -52,7 +54,7 @@ namespace Bit.iOS.Core.Utilities
|
||||||
var liteDbStorage = new LiteDbStorageService(
|
var liteDbStorage = new LiteDbStorageService(
|
||||||
Path.Combine(appGroupContainer.Path, "Library", "bitwarden.db"));
|
Path.Combine(appGroupContainer.Path, "Library", "bitwarden.db"));
|
||||||
var localizeService = new LocalizeService();
|
var localizeService = new LocalizeService();
|
||||||
var broadcasterService = new BroadcasterService();
|
var broadcasterService = new BroadcasterService(logger);
|
||||||
var messagingService = new MobileBroadcasterMessagingService(broadcasterService);
|
var messagingService = new MobileBroadcasterMessagingService(broadcasterService);
|
||||||
var i18nService = new MobileI18nService(localizeService.GetCurrentCultureInfo());
|
var i18nService = new MobileI18nService(localizeService.GetCurrentCultureInfo());
|
||||||
var secureStorageService = new KeyChainStorageService(AppId, AccessGroup,
|
var secureStorageService = new KeyChainStorageService(AppId, AccessGroup,
|
||||||
|
|
|
@ -59,114 +59,121 @@ namespace Bit.iOS
|
||||||
|
|
||||||
_broadcasterService.Subscribe(nameof(AppDelegate), async (message) =>
|
_broadcasterService.Subscribe(nameof(AppDelegate), async (message) =>
|
||||||
{
|
{
|
||||||
if (message.Command == "startEventTimer")
|
try
|
||||||
{
|
{
|
||||||
StartEventTimer();
|
if (message.Command == "startEventTimer")
|
||||||
}
|
|
||||||
else if (message.Command == "stopEventTimer")
|
|
||||||
{
|
|
||||||
var task = StopEventTimerAsync();
|
|
||||||
}
|
|
||||||
else if (message.Command == "updatedTheme")
|
|
||||||
{
|
|
||||||
Device.BeginInvokeOnMainThread(() =>
|
|
||||||
{
|
{
|
||||||
iOSCoreHelpers.AppearanceAdjustments();
|
StartEventTimer();
|
||||||
});
|
}
|
||||||
}
|
else if (message.Command == "stopEventTimer")
|
||||||
else if (message.Command == "listenYubiKeyOTP")
|
{
|
||||||
{
|
var task = StopEventTimerAsync();
|
||||||
iOSCoreHelpers.ListenYubiKey((bool)message.Data, _deviceActionService, _nfcSession, _nfcDelegate);
|
}
|
||||||
}
|
else if (message.Command == "updatedTheme")
|
||||||
else if (message.Command == "unlocked")
|
{
|
||||||
{
|
Device.BeginInvokeOnMainThread(() =>
|
||||||
var needsAutofillReplacement = await _storageService.GetAsync<bool?>(
|
{
|
||||||
Core.Constants.AutofillNeedsIdentityReplacementKey);
|
iOSCoreHelpers.AppearanceAdjustments();
|
||||||
if (needsAutofillReplacement.GetValueOrDefault())
|
});
|
||||||
|
}
|
||||||
|
else if (message.Command == "listenYubiKeyOTP")
|
||||||
|
{
|
||||||
|
iOSCoreHelpers.ListenYubiKey((bool)message.Data, _deviceActionService, _nfcSession, _nfcDelegate);
|
||||||
|
}
|
||||||
|
else if (message.Command == "unlocked")
|
||||||
|
{
|
||||||
|
var needsAutofillReplacement = await _storageService.GetAsync<bool?>(
|
||||||
|
Core.Constants.AutofillNeedsIdentityReplacementKey);
|
||||||
|
if (needsAutofillReplacement.GetValueOrDefault())
|
||||||
|
{
|
||||||
|
await ASHelpers.ReplaceAllIdentities();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (message.Command == "showAppExtension")
|
||||||
|
{
|
||||||
|
Device.BeginInvokeOnMainThread(() => ShowAppExtension((ExtensionPageViewModel)message.Data));
|
||||||
|
}
|
||||||
|
else if (message.Command == "syncCompleted")
|
||||||
|
{
|
||||||
|
if (message.Data is Dictionary<string, object> data && data.ContainsKey("successfully"))
|
||||||
|
{
|
||||||
|
var success = data["successfully"] as bool?;
|
||||||
|
if (success.GetValueOrDefault() && _deviceActionService.SystemMajorVersion() >= 12)
|
||||||
|
{
|
||||||
|
await ASHelpers.ReplaceAllIdentities();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (message.Command == "addedCipher" || message.Command == "editedCipher" ||
|
||||||
|
message.Command == "restoredCipher")
|
||||||
|
{
|
||||||
|
if (_deviceActionService.SystemMajorVersion() >= 12)
|
||||||
|
{
|
||||||
|
if (await ASHelpers.IdentitiesCanIncremental())
|
||||||
|
{
|
||||||
|
var cipherId = message.Data as string;
|
||||||
|
if (message.Command == "addedCipher" && !string.IsNullOrWhiteSpace(cipherId))
|
||||||
|
{
|
||||||
|
var identity = await ASHelpers.GetCipherIdentityAsync(cipherId);
|
||||||
|
if (identity == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await ASCredentialIdentityStore.SharedStore?.SaveCredentialIdentitiesAsync(
|
||||||
|
new ASPasswordCredentialIdentity[] { identity });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await ASHelpers.ReplaceAllIdentities();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (message.Command == "deletedCipher" || message.Command == "softDeletedCipher")
|
||||||
|
{
|
||||||
|
if (_deviceActionService.SystemMajorVersion() >= 12)
|
||||||
|
{
|
||||||
|
if (await ASHelpers.IdentitiesCanIncremental())
|
||||||
|
{
|
||||||
|
var identity = ASHelpers.ToCredentialIdentity(
|
||||||
|
message.Data as Bit.Core.Models.View.CipherView);
|
||||||
|
if (identity == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await ASCredentialIdentityStore.SharedStore?.RemoveCredentialIdentitiesAsync(
|
||||||
|
new ASPasswordCredentialIdentity[] { identity });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await ASHelpers.ReplaceAllIdentities();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (message.Command == "logout")
|
||||||
|
{
|
||||||
|
if (_deviceActionService.SystemMajorVersion() >= 12)
|
||||||
|
{
|
||||||
|
await ASCredentialIdentityStore.SharedStore?.RemoveAllCredentialIdentitiesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((message.Command == "softDeletedCipher" || message.Command == "restoredCipher")
|
||||||
|
&& _deviceActionService.SystemMajorVersion() >= 12)
|
||||||
{
|
{
|
||||||
await ASHelpers.ReplaceAllIdentities();
|
await ASHelpers.ReplaceAllIdentities();
|
||||||
}
|
}
|
||||||
}
|
else if (message.Command == "vaultTimeoutActionChanged")
|
||||||
else if (message.Command == "showAppExtension")
|
|
||||||
{
|
|
||||||
Device.BeginInvokeOnMainThread(() => ShowAppExtension((ExtensionPageViewModel)message.Data));
|
|
||||||
}
|
|
||||||
else if (message.Command == "syncCompleted")
|
|
||||||
{
|
|
||||||
if (message.Data is Dictionary<string, object> data && data.ContainsKey("successfully"))
|
|
||||||
{
|
{
|
||||||
var success = data["successfully"] as bool?;
|
var timeoutAction = await _stateService.GetVaultTimeoutActionAsync();
|
||||||
if (success.GetValueOrDefault() && _deviceActionService.SystemMajorVersion() >= 12)
|
if (timeoutAction == VaultTimeoutAction.Logout)
|
||||||
|
{
|
||||||
|
await ASCredentialIdentityStore.SharedStore?.RemoveAllCredentialIdentitiesAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
await ASHelpers.ReplaceAllIdentities();
|
await ASHelpers.ReplaceAllIdentities();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (message.Command == "addedCipher" || message.Command == "editedCipher" ||
|
catch (Exception ex)
|
||||||
message.Command == "restoredCipher")
|
|
||||||
{
|
{
|
||||||
if (_deviceActionService.SystemMajorVersion() >= 12)
|
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||||
{
|
|
||||||
if (await ASHelpers.IdentitiesCanIncremental())
|
|
||||||
{
|
|
||||||
var cipherId = message.Data as string;
|
|
||||||
if (message.Command == "addedCipher" && !string.IsNullOrWhiteSpace(cipherId))
|
|
||||||
{
|
|
||||||
var identity = await ASHelpers.GetCipherIdentityAsync(cipherId);
|
|
||||||
if (identity == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await ASCredentialIdentityStore.SharedStore?.SaveCredentialIdentitiesAsync(
|
|
||||||
new ASPasswordCredentialIdentity[] { identity });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await ASHelpers.ReplaceAllIdentities();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (message.Command == "deletedCipher" || message.Command == "softDeletedCipher")
|
|
||||||
{
|
|
||||||
if (_deviceActionService.SystemMajorVersion() >= 12)
|
|
||||||
{
|
|
||||||
if (await ASHelpers.IdentitiesCanIncremental())
|
|
||||||
{
|
|
||||||
var identity = ASHelpers.ToCredentialIdentity(
|
|
||||||
message.Data as Bit.Core.Models.View.CipherView);
|
|
||||||
if (identity == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await ASCredentialIdentityStore.SharedStore?.RemoveCredentialIdentitiesAsync(
|
|
||||||
new ASPasswordCredentialIdentity[] { identity });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await ASHelpers.ReplaceAllIdentities();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (message.Command == "logout")
|
|
||||||
{
|
|
||||||
if (_deviceActionService.SystemMajorVersion() >= 12)
|
|
||||||
{
|
|
||||||
await ASCredentialIdentityStore.SharedStore?.RemoveAllCredentialIdentitiesAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((message.Command == "softDeletedCipher" || message.Command == "restoredCipher")
|
|
||||||
&& _deviceActionService.SystemMajorVersion() >= 12)
|
|
||||||
{
|
|
||||||
await ASHelpers.ReplaceAllIdentities();
|
|
||||||
}
|
|
||||||
else if (message.Command == "vaultTimeoutActionChanged")
|
|
||||||
{
|
|
||||||
var timeoutAction = await _stateService.GetVaultTimeoutActionAsync();
|
|
||||||
if (timeoutAction == VaultTimeoutAction.Logout)
|
|
||||||
{
|
|
||||||
await ASCredentialIdentityStore.SharedStore?.RemoveAllCredentialIdentitiesAsync();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await ASHelpers.ReplaceAllIdentities();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue