mirror of
https://github.com/bitwarden/mobile.git
synced 2025-01-23 21:21:27 +01:00
PM-3349 Added base structure for avoiding Android Autofill crash. This workaround works but it's not complete as it can't handle the entire workflow when showing CipherSelectionPAge (like checking if it should show LockPage)
This commit is contained in:
parent
5803635f44
commit
17acb57732
@ -74,6 +74,10 @@ namespace Bit.Droid
|
||||
// this needs to be called here before base.OnCreate(...)
|
||||
Intent?.Validate();
|
||||
|
||||
//We need to get and set the Options before calling OnCreate as that will "trigger" CreateWindow on App.xaml.cs
|
||||
_appOptions = GetOptions();
|
||||
((Bit.App.App)Microsoft.Maui.Controls.Application.Current).SetOptions(_appOptions);
|
||||
|
||||
base.OnCreate(savedInstanceState);
|
||||
|
||||
_deviceActionService.SetScreenCaptureAllowedAsync().FireAndForget(_ =>
|
||||
@ -89,7 +93,6 @@ namespace Bit.Droid
|
||||
toplayout.FilterTouchesWhenObscured = true;
|
||||
}
|
||||
|
||||
_appOptions = GetOptions();
|
||||
CreateNotificationChannel();
|
||||
DisableAndroidFontScale();
|
||||
|
||||
|
@ -44,6 +44,85 @@ namespace Bit.App
|
||||
// Links: https://github.com/dotnet/maui/issues/11501 and https://bitwarden.atlassian.net/wiki/spaces/NMME/pages/664862722/MainPage+Assignments+not+working+on+Android+on+Background+or+App+resume
|
||||
private readonly Queue<Action> _onResumeActions = new Queue<Action>();
|
||||
|
||||
#if ANDROID
|
||||
|
||||
/*
|
||||
* ** Workaround for our Android crashes when trying to use Autofill **
|
||||
*
|
||||
* This workaround works by managing the "Window Creation" ourselves. When we get an Autofill initialization we should create a new window instead of reusing the "Main/Current Window".
|
||||
* While this workaround works, it's hard to execute the "workflow" that devices where we should navigate to. Below are some of the things we tried:
|
||||
* 1 - Tried creating "new Window(new NavigationPage)" and invoking the code for handling the Navigations afterward. Issue with this is that the code that handles the navigations doesn't know which "Window" to use and calls the default "Window.Page"
|
||||
* 2 - Tried using CustomWindow implementations to track the "WindowCreated" event and to be able to distinguish the different Window types (Default Window or Window for Autofill for example).
|
||||
* This solution had a bit of overhear work and still required the app to set something line "new Window(new NavigationPage)" before actually knowing where we wanted to navigate to.
|
||||
*
|
||||
* Ideally we could figure out the Navigation we want to do before CreateWindow (on MainActivity.OnCreate) for example. But this needs to be done in async anyway we can't do async in both CreateWindow and MainActivity.OnCreate
|
||||
*/
|
||||
|
||||
public new static Page MainPage
|
||||
{
|
||||
get
|
||||
{
|
||||
return CurrentWindow?.Page;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (CurrentWindow != null)
|
||||
{
|
||||
CurrentWindow.Page = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Window CurrentWindow { get; private set; }
|
||||
|
||||
public void SetOptions(AppOptions appOptions)
|
||||
{
|
||||
Options = appOptions;
|
||||
}
|
||||
|
||||
protected override Window CreateWindow(IActivationState activationState)
|
||||
{
|
||||
if (activationState != null
|
||||
&& activationState.State.TryGetValue("autofillFramework", out string autofillFramework)
|
||||
&& autofillFramework == "true") //TODO: There are likely better ways to filter this. Maybe using Options.
|
||||
{
|
||||
if (activationState.State.ContainsKey("autofillFrameworkCipherId")) //TODO: There are likely better ways to filter this. Maybe using Options.
|
||||
{
|
||||
return new Window(new NavigationPage()); //No actual page needed. Only used for auto-filling the fields directly (externally)
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: IMPORTANT Question: this works if we want to show the CipherSelection, but we are skipping all our ASYNC Navigation workflows where we (for example) check if the user is logged in and/or needs to enter auth again.
|
||||
var autofillWindow = new Window(new NavigationPage(new CipherSelectionPage(Options)));
|
||||
return autofillWindow;
|
||||
}
|
||||
}
|
||||
else if(CurrentWindow != null)
|
||||
{
|
||||
//TODO: This likely crashes if we try to have two apps side-by-side on Android
|
||||
//TODO: Question: In these scenarios should a new Window be created or can the same one be reused?
|
||||
return CurrentWindow;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentWindow = new Window(new NavigationPage(new HomePage(Options)));
|
||||
return CurrentWindow;
|
||||
}
|
||||
}
|
||||
#elif IOS
|
||||
public new static Page MainPage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Application.Current.MainPage;
|
||||
}
|
||||
set
|
||||
{
|
||||
Application.Current.MainPage = value;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public App() : this(null)
|
||||
{
|
||||
}
|
||||
@ -432,11 +511,11 @@ namespace Bit.App
|
||||
Options.Uri = null;
|
||||
if (isLocked)
|
||||
{
|
||||
MainPage = new NavigationPage(new LockPage());
|
||||
App.MainPage = new NavigationPage(new LockPage());
|
||||
}
|
||||
else
|
||||
{
|
||||
MainPage = new TabsPage();
|
||||
App.MainPage = new TabsPage();
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -463,7 +542,6 @@ namespace Bit.App
|
||||
{
|
||||
UpdateThemeAsync();
|
||||
};
|
||||
MainPage = new NavigationPage(new HomePage(Options));
|
||||
_accountsManager.NavigateOnAccountChangeAsync().FireAndForget();
|
||||
ServiceContainer.Resolve<MobilePlatformUtilsService>("platformUtilsService").Init();
|
||||
}
|
||||
@ -535,36 +613,36 @@ namespace Bit.App
|
||||
switch (navTarget)
|
||||
{
|
||||
case NavigationTarget.HomeLogin:
|
||||
MainPage = new NavigationPage(new HomePage(Options));
|
||||
App.MainPage = new NavigationPage(new HomePage(Options));
|
||||
break;
|
||||
case NavigationTarget.Login:
|
||||
if (navParams is LoginNavigationParams loginParams)
|
||||
{
|
||||
MainPage = new NavigationPage(new LoginPage(loginParams.Email, Options));
|
||||
App.MainPage = new NavigationPage(new LoginPage(loginParams.Email, Options));
|
||||
}
|
||||
break;
|
||||
case NavigationTarget.Lock:
|
||||
if (navParams is LockNavigationParams lockParams)
|
||||
{
|
||||
MainPage = new NavigationPage(new LockPage(Options, lockParams.AutoPromptBiometric));
|
||||
App.MainPage = new NavigationPage(new LockPage(Options, lockParams.AutoPromptBiometric));
|
||||
}
|
||||
else
|
||||
{
|
||||
MainPage = new NavigationPage(new LockPage(Options));
|
||||
App.MainPage = new NavigationPage(new LockPage(Options));
|
||||
}
|
||||
break;
|
||||
case NavigationTarget.Home:
|
||||
MainPage = new TabsPage(Options);
|
||||
App.MainPage = new TabsPage(Options);
|
||||
break;
|
||||
case NavigationTarget.AddEditCipher:
|
||||
MainPage = new NavigationPage(new CipherAddEditPage(appOptions: Options));
|
||||
App.MainPage = new NavigationPage(new CipherAddEditPage(appOptions: Options));
|
||||
break;
|
||||
case NavigationTarget.AutofillCiphers:
|
||||
case NavigationTarget.OtpCipherSelection:
|
||||
MainPage = new NavigationPage(new CipherSelectionPage(Options));
|
||||
App.MainPage = new NavigationPage(new CipherSelectionPage(Options));
|
||||
break;
|
||||
case NavigationTarget.SendAddEdit:
|
||||
MainPage = new NavigationPage(new SendAddEditPage(Options));
|
||||
App.MainPage = new NavigationPage(new SendAddEditPage(Options));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ namespace Bit.App.Pages
|
||||
}
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
|
||||
Application.Current.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ namespace Bit.App.Pages
|
||||
return;
|
||||
}
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
Application.Current.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
||||
private async Task StartLogInWithMasterPasswordAsync()
|
||||
|
@ -193,7 +193,7 @@ namespace Bit.App.Pages
|
||||
return;
|
||||
}
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
Application.Current.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
||||
private async Task UpdateTempPasswordAsync()
|
||||
|
@ -53,7 +53,7 @@ namespace Bit.App.Pages
|
||||
return;
|
||||
}
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
Application.Current.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
||||
private async Task UpdateTempPasswordAsync()
|
||||
|
@ -120,11 +120,11 @@ namespace Bit.App.Pages
|
||||
|
||||
if (await _vaultTimeoutService.IsLockedAsync())
|
||||
{
|
||||
Application.Current.MainPage = new NavigationPage(new LockPage(_appOptions));
|
||||
App.MainPage = new NavigationPage(new LockPage(_appOptions));
|
||||
}
|
||||
else
|
||||
{
|
||||
Application.Current.MainPage = new TabsPage(_appOptions, null);
|
||||
App.MainPage = new TabsPage(_appOptions, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ namespace Bit.App.Pages
|
||||
return;
|
||||
}
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
Application.Current.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ namespace Bit.App.Pages
|
||||
|
||||
private void TwoFactorAuthSuccessWithSSOLocked()
|
||||
{
|
||||
Application.Current.MainPage = new NavigationPage(new LockPage(_appOptions));
|
||||
App.MainPage = new NavigationPage(new LockPage(_appOptions));
|
||||
}
|
||||
|
||||
private async Task TwoFactorAuthSuccessToMainAsync()
|
||||
@ -202,7 +202,7 @@ namespace Bit.App.Pages
|
||||
return;
|
||||
}
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
Application.Current.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
||||
private void Token_TextChanged(object sender, TextChangedEventArgs e)
|
||||
|
@ -184,7 +184,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
if (FromAutofillFramework)
|
||||
{
|
||||
Microsoft.Maui.Controls.Application.Current.MainPage = new TabsPage();
|
||||
App.MainPage = new TabsPage();
|
||||
return true;
|
||||
}
|
||||
return base.OnBackButtonPressed();
|
||||
|
@ -430,19 +430,19 @@ namespace Bit.App.Utilities
|
||||
{
|
||||
if (appOptions.FromAutofillFramework && appOptions.SaveType.HasValue)
|
||||
{
|
||||
Application.Current.MainPage = new NavigationPage(new CipherAddEditPage(appOptions: appOptions));
|
||||
App.MainPage = new NavigationPage(new CipherAddEditPage(appOptions: appOptions));
|
||||
return true;
|
||||
}
|
||||
if (appOptions.Uri != null
|
||||
||
|
||||
appOptions.OtpData != null)
|
||||
{
|
||||
Application.Current.MainPage = new NavigationPage(new CipherSelectionPage(appOptions));
|
||||
App.MainPage = new NavigationPage(new CipherSelectionPage(appOptions));
|
||||
return true;
|
||||
}
|
||||
if (appOptions.CreateSend != null)
|
||||
{
|
||||
Application.Current.MainPage = new NavigationPage(new SendAddEditPage(appOptions));
|
||||
App.MainPage = new NavigationPage(new SendAddEditPage(appOptions));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ namespace Bit.iOS.Core.Services
|
||||
{
|
||||
if (Application.Current is App.App app && app.Options != null && !app.Options.IosExtension)
|
||||
{
|
||||
return app.MainPage.DisplayActionSheet(title, cancel, destruction, buttons);
|
||||
return Bit.App.App.MainPage.DisplayActionSheet(title, cancel, destruction, buttons);
|
||||
}
|
||||
var vc = GetPresentedViewController();
|
||||
if (vc is null)
|
||||
|
Loading…
Reference in New Issue
Block a user