using System; using System.IO; using System.Threading.Tasks; using Android.App; using Android.Content; using Android.OS; using Android.Runtime; using Bit.App.Abstractions; using Bit.App.Services; using Bit.Core; using Bit.Core.Abstractions; using Bit.Core.Services; using Bit.Core.Utilities; using Bit.Droid.Services; using Plugin.Fingerprint; using Xamarin.Android.Net; using System.Net.Http; using System.Net; using Bit.App.Utilities; using Bit.App.Pages; using Bit.App.Utilities.AccountManagement; using Bit.App.Controls; using Bit.App.Platforms.Android.Autofill; using Bit.Core.Enums; using Bit.Core.Services.UserVerification; #if !FDROID using Android.Gms.Security; #endif using DeviceType = Bit.Core.Enums.DeviceType; namespace Bit.Droid { #if DEBUG [Application(Debuggable = true)] #else [Application(Debuggable = false)] #endif [Register("com.x8bit.bitwarden.MainApplication")] #if FDROID public class MainApplication : MauiApplication #else public class MainApplication : MauiApplication, ProviderInstaller.IProviderInstallListener #endif { public MainApplication(IntPtr handle, JniHandleOwnership transer) : base(handle, transer) { if (ServiceContainer.RegisteredServices.Count == 0) { RegisterLocalServices(); var deviceActionService = ServiceContainer.Resolve("deviceActionService"); ServiceContainer.Init(deviceActionService.DeviceUserAgent, Core.Constants.ClearCiphersCacheKey, Core.Constants.AndroidAllClearCipherCacheKeys); ServiceContainer.Register(new WatchDeviceService(ServiceContainer.Resolve(), ServiceContainer.Resolve(), ServiceContainer.Resolve(), ServiceContainer.Resolve())); InitializeAppSetup(); // TODO: Update when https://github.com/bitwarden/mobile/pull/1662 gets merged var deleteAccountActionFlowExecutioner = new DeleteAccountActionFlowExecutioner( ServiceContainer.Resolve("apiService"), ServiceContainer.Resolve("messagingService"), ServiceContainer.Resolve("platformUtilsService"), ServiceContainer.Resolve("deviceActionService"), ServiceContainer.Resolve("logger")); ServiceContainer.Register("deleteAccountActionFlowExecutioner", deleteAccountActionFlowExecutioner); var verificationActionsFlowHelper = new VerificationActionsFlowHelper( ServiceContainer.Resolve("passwordRepromptService"), ServiceContainer.Resolve("cryptoService"), ServiceContainer.Resolve()); ServiceContainer.Register("verificationActionsFlowHelper", verificationActionsFlowHelper); var accountsManager = new AccountsManager( ServiceContainer.Resolve("broadcasterService"), ServiceContainer.Resolve("vaultTimeoutService"), ServiceContainer.Resolve("secureStorageService"), ServiceContainer.Resolve("stateService"), ServiceContainer.Resolve("platformUtilsService"), ServiceContainer.Resolve("authService"), ServiceContainer.Resolve("logger"), ServiceContainer.Resolve("messagingService"), ServiceContainer.Resolve(), ServiceContainer.Resolve()); ServiceContainer.Register("accountsManager", accountsManager); var userPinService = new UserPinService( ServiceContainer.Resolve(), ServiceContainer.Resolve(), ServiceContainer.Resolve()); ServiceContainer.Register(userPinService); var userVerificationMediatorService = new UserVerificationMediatorService( ServiceContainer.Resolve("platformUtilsService"), ServiceContainer.Resolve("passwordRepromptService"), userPinService, deviceActionService, ServiceContainer.Resolve()); ServiceContainer.Register(userVerificationMediatorService); var fido2AuthenticatorService = new Fido2AuthenticatorService( ServiceContainer.Resolve(), ServiceContainer.Resolve(), ServiceContainer.Resolve(), userVerificationMediatorService); ServiceContainer.Register(fido2AuthenticatorService); var fido2GetAssertionUserInterface = new Fido2GetAssertionUserInterface( ServiceContainer.Resolve(), ServiceContainer.Resolve(), ServiceContainer.Resolve(), ServiceContainer.Resolve()); ServiceContainer.Register(fido2GetAssertionUserInterface); var fido2MakeCredentialUserInterface = new Fido2MakeCredentialUserInterface( ServiceContainer.Resolve(), ServiceContainer.Resolve(), ServiceContainer.Resolve(), ServiceContainer.Resolve(), ServiceContainer.Resolve(), ServiceContainer.Resolve()); ServiceContainer.Register(fido2MakeCredentialUserInterface); var fido2ClientService = new Fido2ClientService( ServiceContainer.Resolve(), ServiceContainer.Resolve(), ServiceContainer.Resolve(), ServiceContainer.Resolve(), fido2GetAssertionUserInterface, fido2MakeCredentialUserInterface); ServiceContainer.Register(fido2ClientService); ServiceContainer.Register(new Fido2MediatorService( fido2AuthenticatorService, fido2ClientService, ServiceContainer.Resolve())); } #if !FDROID if (Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat) { ProviderInstaller.InstallIfNeededAsync(ApplicationContext, this); } #endif } protected override MauiApp CreateMauiApp() => App.MauiProgram.CreateMauiApp(); public override void OnCreate() { base.OnCreate(); Bootstrap(); } public void OnProviderInstallFailed(int errorCode, Intent recoveryIntent) { } public void OnProviderInstalled() { } private void RegisterLocalServices() { ServiceContainer.Register("nativeLogService", new AndroidLogService()); #if FDROID var logger = new StubLogger(); #elif DEBUG var logger = DebugLogger.Instance; #else var logger = Logger.Instance; #endif ServiceContainer.Register("logger", logger); // Note: This might cause a race condition. Investigate more. //Task.Run(() => //{ // FFImageLoading.Forms.Platform.CachedImageRenderer.Init(true); // FFImageLoading.ImageService.Instance.Initialize(new FFImageLoading.Config.Configuration // { // FadeAnimationEnabled = false, // FadeAnimationForCachedImages = false, // HttpClient = new HttpClient(new AndroidClientHandler() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }) // }); // ZXing.Net.Mobile.Forms.Android.Platform.Init(); //}); CrossFingerprint.SetCurrentActivityResolver(() => Microsoft.Maui.ApplicationModel.Platform.CurrentActivity); var preferencesStorage = new PreferencesStorageService(null); var localAppDataFolderPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData); var liteDbStorage = new LiteDbStorageService(Path.Combine(localAppDataFolderPath, "bitwarden.db")); var localizeService = new LocalizeService(); var broadcasterService = new BroadcasterService(logger); var messagingService = new MobileBroadcasterMessagingService(broadcasterService); var i18nService = new MobileI18nService(localizeService.GetCurrentCultureInfo()); var secureStorageService = new SecureStorageService(); var cryptoPrimitiveService = new CryptoPrimitiveService(); var mobileStorageService = new MobileStorageService(preferencesStorage, liteDbStorage); var storageMediatorService = new StorageMediatorService(mobileStorageService, secureStorageService, preferencesStorage); var stateService = new StateService(mobileStorageService, secureStorageService, storageMediatorService, messagingService); var stateMigrationService = new StateMigrationService(Bit.Core.Enums.DeviceType.Android, liteDbStorage, preferencesStorage, secureStorageService); var clipboardService = new ClipboardService(stateService); var deviceActionService = new DeviceActionService(stateService, messagingService); var fileService = new FileService(stateService, broadcasterService); var platformUtilsService = new MobilePlatformUtilsService(deviceActionService, clipboardService, messagingService, broadcasterService); var autofillHandler = new AutofillHandler(stateService, messagingService, clipboardService, platformUtilsService, new LazyResolve()); var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService); var cryptoService = new CryptoService(stateService, cryptoFunctionService, logger); var biometricService = new BiometricService(stateService, cryptoService); var passwordRepromptService = new MobilePasswordRepromptService(platformUtilsService, cryptoService, stateService); ServiceContainer.Register(preferencesStorage); ServiceContainer.Register("broadcasterService", broadcasterService); ServiceContainer.Register("messagingService", messagingService); ServiceContainer.Register("localizeService", localizeService); ServiceContainer.Register("i18nService", i18nService); ServiceContainer.Register("cryptoPrimitiveService", cryptoPrimitiveService); ServiceContainer.Register("storageService", mobileStorageService); ServiceContainer.Register("secureStorageService", secureStorageService); ServiceContainer.Register(storageMediatorService); ServiceContainer.Register("stateService", stateService); ServiceContainer.Register("stateMigrationService", stateMigrationService); ServiceContainer.Register("clipboardService", clipboardService); ServiceContainer.Register("deviceActionService", deviceActionService); ServiceContainer.Register(fileService); ServiceContainer.Register(autofillHandler); ServiceContainer.Register("platformUtilsService", platformUtilsService); ServiceContainer.Register("biometricService", biometricService); ServiceContainer.Register("cryptoFunctionService", cryptoFunctionService); ServiceContainer.Register("cryptoService", cryptoService); ServiceContainer.Register("passwordRepromptService", passwordRepromptService); ServiceContainer.Register("avatarImageSourcePool", new AvatarImageSourcePool()); // Push #if FDROID ServiceContainer.Register( "pushNotificationListenerService", new NoopPushNotificationListenerService()); ServiceContainer.Register( "pushNotificationService", new NoopPushNotificationService()); #else var notificationListenerService = new PushNotificationListenerService(); ServiceContainer.Register( "pushNotificationListenerService", notificationListenerService); var androidPushNotificationService = new AndroidPushNotificationService( stateService, notificationListenerService); ServiceContainer.Register( "pushNotificationService", androidPushNotificationService); #endif } private void Bootstrap() { var locale = ServiceContainer.Resolve().GetLocale(); (ServiceContainer.Resolve("i18nService") as MobileI18nService) .Init(locale != null ? new System.Globalization.CultureInfo(locale) : null); ServiceContainer.Resolve("authService").Init(); // Note: This is not awaited var bootstrapTask = BootstrapAsync(); } private async Task BootstrapAsync() { await ServiceContainer.Resolve("environmentService").SetUrlsFromStorageAsync(); } private void InitializeAppSetup() { var appSetup = new AppSetup(); appSetup.InitializeServicesLastChance(); ServiceContainer.Register("appSetup", appSetup); } } }