mirror of
https://github.com/bitwarden/mobile.git
synced 2024-11-29 12:45:20 +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.
|
// 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
|
// 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 readonly Queue<Action> _onResumeActions = new Queue<Action>();
|
||||||
private bool _hasNavigatedToAutofillWindow;
|
|
||||||
|
|
||||||
#if ANDROID
|
#if ANDROID
|
||||||
|
|
||||||
@ -108,8 +107,6 @@ namespace Bit.App
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasNavigatedToAccessibilitySettings { get; set; }
|
|
||||||
|
|
||||||
protected override Window CreateWindow(IActivationState activationState)
|
protected override Window CreateWindow(IActivationState activationState)
|
||||||
{
|
{
|
||||||
//When executing from AutofillExternalActivity we don't have "Options" so we need to filter "manually"
|
//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)
|
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
|
_isResumed = true;
|
||||||
if (Options != null && (Options.FromAutofillFramework || Options.Uri != null || Options.OtpData != null || Options.CreateSend != null))
|
return new ResumeWindow(new NavigationPage(new AndroidNavigationRedirectPage(Options)));
|
||||||
{
|
|
||||||
_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));
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
//iOS doesn't use the CreateWindow override used in Android so we just set the Application.Current.MainPage directly
|
//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;
|
Application.Current.MainPage = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public App() : this(null)
|
public App() : this(null)
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
|
using Bit.App.Models;
|
||||||
|
using Bit.App.Pages;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
|
||||||
@ -6,19 +8,32 @@ namespace Bit.Core.Pages;
|
|||||||
|
|
||||||
public partial class AndroidNavigationRedirectPage : ContentPage
|
public partial class AndroidNavigationRedirectPage : ContentPage
|
||||||
{
|
{
|
||||||
private readonly IAccountsManager _accountsManager;
|
private AppOptions _options;
|
||||||
private readonly IConditionedAwaiterManager _conditionedAwaiterManager;
|
public AndroidNavigationRedirectPage(AppOptions options)
|
||||||
|
|
||||||
public AndroidNavigationRedirectPage()
|
|
||||||
{
|
{
|
||||||
_accountsManager = ServiceContainer.Resolve<IAccountsManager>("accountsManager");
|
_options = options ?? new AppOptions();
|
||||||
_conditionedAwaiterManager = ServiceContainer.Resolve<IConditionedAwaiterManager>();
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AndroidNavigationRedirectPage_OnLoaded(object sender, EventArgs e)
|
private void AndroidNavigationRedirectPage_OnLoaded(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
_accountsManager.NavigateOnAccountChangeAsync().FireAndForget();
|
if (ServiceContainer.TryResolve<IAccountsManager>(out var accountsManager))
|
||||||
_conditionedAwaiterManager.SetAsCompleted(AwaiterPrecondition.AndroidWindowCreated);
|
{
|
||||||
|
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)));
|
await MainThread.InvokeOnMainThreadAsync(() => TriggerPropertyChanged(nameof(UseAccessibility)));
|
||||||
return;
|
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();
|
_deviceActionService.OpenAccessibilitySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,14 +32,4 @@
|
|||||||
IsActive = false;
|
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