mirror of
https://github.com/bitwarden/mobile.git
synced 2024-11-04 08:50:18 +01:00
[PM-6552] Fix for Android Window issues when opening Autofill/Accessibility (#3051)
* PM-6552 Removed several of the Window Workarounds for Android. Now always relying on the AndroidNavigationRedirectPage. AndroidNavigationRedirectPage now more resilient to failure and navigates to HomePage as fallback. * Update src/Core/Pages/AndroidNavigationRedirectPage.xaml.cs Co-authored-by: Federico Maccaroni <fedemkr@gmail.com> --------- Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
This commit is contained in:
parent
bca5b95446
commit
40c80f082d
@ -46,7 +46,6 @@ namespace Bit.App
|
||||
// This queue keeps those actions so that when the app has resumed they can still be executed.
|
||||
// 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>();
|
||||
private bool _hasNavigatedToAutofillWindow;
|
||||
|
||||
#if ANDROID
|
||||
|
||||
@ -108,8 +107,6 @@ namespace Bit.App
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasNavigatedToAccessibilitySettings { get; set; }
|
||||
|
||||
protected override Window CreateWindow(IActivationState activationState)
|
||||
{
|
||||
//When executing from AutofillExternalActivity we don't have "Options" so we need to filter "manually"
|
||||
@ -122,53 +119,8 @@ namespace Bit.App
|
||||
return new Window(new NavigationPage()); //No actual page needed. Only used for auto-filling the fields directly (externally)
|
||||
}
|
||||
|
||||
//"Internal" Autofill and Uri/Otp/CreateSend. This is where we create the autofill specific Window
|
||||
if (Options != null && (Options.FromAutofillFramework || Options.Uri != null || Options.OtpData != null || Options.CreateSend != null))
|
||||
{
|
||||
_isResumed = true; //Specifically for the Autofill scenario we need to manually set the _isResumed here
|
||||
_hasNavigatedToAutofillWindow = true;
|
||||
return new AutoFillWindow(new NavigationPage(new AndroidNavigationRedirectPage()));
|
||||
}
|
||||
|
||||
var homePage = new HomePage(Options);
|
||||
// WORKAROUND: If the user autofills with Accessibility Services enabled and goes back to the application then there is currently an issue
|
||||
// where this method is called again
|
||||
// thus it goes through here and the user goes to HomePage as we see here.
|
||||
// So to solve this, the next flag check has been added which then turns on a flag on the home page
|
||||
// that will trigger a navigation on the accounts manager when it loads; workarounding this behavior and navigating the user
|
||||
// to the proper page depending on its state.
|
||||
// WARNING: this doens't navigate the user to where they were but it acts as if the user had changed their account.
|
||||
if(_hasNavigatedToAutofillWindow)
|
||||
{
|
||||
homePage.PerformNavigationOnAccountChangedOnLoad = true;
|
||||
// this is needed because when coming back from AutofillWindow OnResume won't be called and we need this flag
|
||||
// so that void Navigate(NavigationTarget navTarget, INavigationParams navParams) doesn't enqueue the navigation
|
||||
// and it performs it directly.
|
||||
_isResumed = true;
|
||||
_hasNavigatedToAutofillWindow = false;
|
||||
}
|
||||
|
||||
// WORKAROUND: This workaround is similar to the one above (_hasNavigatedToAutofillWindow) related with Accessibility Services but this one specifically
|
||||
// is due to trying to open the Accessibility Settings Page for enabled/disabling
|
||||
if(HasNavigatedToAccessibilitySettings)
|
||||
{
|
||||
homePage.PerformNavigationOnAccountChangedOnLoad = true;
|
||||
// this is needed because when coming back from AutofillWindow OnResume won't be called and we need this flag
|
||||
// so that void Navigate(NavigationTarget navTarget, INavigationParams navParams) doesn't enqueue the navigation
|
||||
// and it performs it directly.
|
||||
_isResumed = true;
|
||||
HasNavigatedToAccessibilitySettings = false;
|
||||
}
|
||||
|
||||
//If we have an existing MainAppWindow we can use that one
|
||||
var mainAppWindow = Windows.OfType<MainAppWindow>().FirstOrDefault();
|
||||
if (mainAppWindow != null)
|
||||
{
|
||||
mainAppWindow.PendingPage = new NavigationPage(homePage);
|
||||
}
|
||||
|
||||
//Create new main window
|
||||
return new MainAppWindow(new NavigationPage(homePage));
|
||||
_isResumed = true;
|
||||
return new ResumeWindow(new NavigationPage(new AndroidNavigationRedirectPage(Options)));
|
||||
}
|
||||
#else
|
||||
//iOS doesn't use the CreateWindow override used in Android so we just set the Application.Current.MainPage directly
|
||||
@ -185,7 +137,7 @@ namespace Bit.App
|
||||
Application.Current.MainPage = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public App() : this(null)
|
||||
|
@ -1,4 +1,6 @@
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Pages;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
@ -6,19 +8,32 @@ namespace Bit.Core.Pages;
|
||||
|
||||
public partial class AndroidNavigationRedirectPage : ContentPage
|
||||
{
|
||||
private readonly IAccountsManager _accountsManager;
|
||||
private readonly IConditionedAwaiterManager _conditionedAwaiterManager;
|
||||
|
||||
public AndroidNavigationRedirectPage()
|
||||
private AppOptions _options;
|
||||
public AndroidNavigationRedirectPage(AppOptions options)
|
||||
{
|
||||
_accountsManager = ServiceContainer.Resolve<IAccountsManager>("accountsManager");
|
||||
_conditionedAwaiterManager = ServiceContainer.Resolve<IConditionedAwaiterManager>();
|
||||
_options = options ?? new AppOptions();
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void AndroidNavigationRedirectPage_OnLoaded(object sender, EventArgs e)
|
||||
{
|
||||
_accountsManager.NavigateOnAccountChangeAsync().FireAndForget();
|
||||
_conditionedAwaiterManager.SetAsCompleted(AwaiterPrecondition.AndroidWindowCreated);
|
||||
if (ServiceContainer.TryResolve<IAccountsManager>(out var accountsManager))
|
||||
{
|
||||
accountsManager.NavigateOnAccountChangeAsync().FireAndForget();
|
||||
}
|
||||
else
|
||||
{
|
||||
Bit.App.App.MainPage = new NavigationPage(new HomePage(_options)); //Fallback scenario to load HomePage just in case something goes wrong when resolving IAccountsManager
|
||||
}
|
||||
|
||||
if (ServiceContainer.TryResolve<IConditionedAwaiterManager>(out var conditionedAwaiterManager))
|
||||
{
|
||||
conditionedAwaiterManager?.SetAsCompleted(AwaiterPrecondition.AndroidWindowCreated);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.LogEvenIfCantBeResolved(new InvalidOperationException("ConditionedAwaiterManager can't be resolved on Android Navigation redirection"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -158,11 +158,6 @@ namespace Bit.App.Pages
|
||||
await MainThread.InvokeOnMainThreadAsync(() => TriggerPropertyChanged(nameof(UseAccessibility)));
|
||||
return;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
// WORKAROUND: Set workaround property to avoid an issue when launching the app after being in Accessibility Settings. More Info on App.xaml.cs
|
||||
((App)Application.Current).HasNavigatedToAccessibilitySettings = true;
|
||||
#endif
|
||||
_deviceActionService.OpenAccessibilitySettings();
|
||||
}
|
||||
|
||||
|
@ -32,14 +32,4 @@
|
||||
IsActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
public class MainAppWindow : ResumeWindow
|
||||
{
|
||||
public MainAppWindow(Page page) : base(page) { }
|
||||
}
|
||||
|
||||
public class AutoFillWindow : ResumeWindow
|
||||
{
|
||||
public AutoFillWindow(Page page) : base(page){ }
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user