mirror of
https://github.com/bitwarden/mobile
synced 2026-01-21 03:43:17 +00:00
PM-3349 Implemented HybridWebViewHandler for Android which enables 2nd factor auth flows
Ensured CustomTabbedPageHandler had it's DisconnectHandler called Some minor code upgrades of older obsolete Xamarin Forms code.
This commit is contained in:
25
src/App/Handlers/HybridWebViewHandler.cs
Normal file
25
src/App/Handlers/HybridWebViewHandler.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
#if IOS || MACCATALYST
|
||||
using PlatformView = WebKit.WKWebView;
|
||||
#elif ANDROID
|
||||
using PlatformView = Android.Webkit.WebView;
|
||||
#elif (NETSTANDARD || !PLATFORM) || (NET6_0_OR_GREATER && !IOS && !ANDROID)
|
||||
using PlatformView = System.Object;
|
||||
#endif
|
||||
|
||||
using Bit.App.Controls;
|
||||
using Microsoft.Maui.Handlers;
|
||||
|
||||
namespace Bit.App.Handlers
|
||||
{
|
||||
public partial class HybridWebViewHandler
|
||||
{
|
||||
public static PropertyMapper<HybridWebView, HybridWebViewHandler> PropertyMapper = new PropertyMapper<HybridWebView, HybridWebViewHandler>(ViewHandler.ViewMapper)
|
||||
{
|
||||
[nameof(HybridWebView.Uri)] = MapUri
|
||||
};
|
||||
|
||||
public HybridWebViewHandler() : base(PropertyMapper)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Bit.App
|
||||
namespace Bit.App
|
||||
{
|
||||
public class MauiProgram
|
||||
{
|
||||
@@ -28,7 +28,8 @@ namespace Bit.App
|
||||
Bit.App.Handlers.TimePickerHandlerMappings.Setup();
|
||||
Bit.App.Handlers.ButtonHandlerMappings.Setup();
|
||||
|
||||
handlers.AddHandler(typeof(TabbedPage), typeof(Bit.App.Handlers.CustomTabbedPageHandler));
|
||||
handlers.AddHandler(typeof(Bit.App.Pages.TabsPage), typeof(Bit.App.Handlers.CustomTabbedPageHandler));
|
||||
handlers.AddHandler(typeof(Bit.App.Controls.HybridWebView), typeof(Bit.App.Handlers.HybridWebViewHandler));
|
||||
#else
|
||||
iOS.Core.Utilities.iOSCoreHelpers.ConfigureMAUIHandlers(handlers);
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using AndroidX.AppCompat.View.Menu;
|
||||
using AndroidX.Navigation.UI;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using Google.Android.Material.BottomNavigation;
|
||||
@@ -95,6 +94,7 @@ namespace Bit.App.Handlers
|
||||
}
|
||||
}
|
||||
|
||||
//Currently the Disconnect Handler needs to be manually called from the App: https://github.com/dotnet/maui/issues/3604
|
||||
protected override void DisconnectHandler(global::Android.Views.View platformView)
|
||||
{
|
||||
if(_bottomNavigationViewGroup != null)
|
||||
|
||||
96
src/App/Platforms/Android/Handlers/HybridWebViewHandler.cs
Normal file
96
src/App/Platforms/Android/Handlers/HybridWebViewHandler.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using Bit.App.Controls;
|
||||
using Java.Interop;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Maui.Handlers;
|
||||
using AWebkit = Android.Webkit;
|
||||
|
||||
namespace Bit.App.Handlers
|
||||
{
|
||||
public partial class HybridWebViewHandler : ViewHandler<HybridWebView, AWebkit.WebView>
|
||||
{
|
||||
private const string JSFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";
|
||||
|
||||
public HybridWebViewHandler([NotNull] IPropertyMapper mapper, CommandMapper commandMapper = null) : base(mapper, commandMapper)
|
||||
{
|
||||
}
|
||||
|
||||
protected override AWebkit.WebView CreatePlatformView()
|
||||
{
|
||||
var context = MauiContext?.Context ?? throw new InvalidOperationException($"Context cannot be null here");
|
||||
var webView = new AWebkit.WebView(context);
|
||||
webView.Settings.JavaScriptEnabled = true;
|
||||
webView.SetWebViewClient(new JSWebViewClient(string.Format("javascript: {0}", JSFunction)));
|
||||
return webView;
|
||||
}
|
||||
|
||||
public static void MapUri(HybridWebViewHandler handler, HybridWebView view)
|
||||
{
|
||||
if (view != null && view.Uri != null)
|
||||
{
|
||||
handler?.PlatformView?.LoadUrl(view.Uri);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ConnectHandler(AWebkit.WebView platformView)
|
||||
{
|
||||
platformView?.AddJavascriptInterface(new JSBridge(this), "jsBridge");
|
||||
platformView?.LoadUrl(VirtualView?.Uri);
|
||||
|
||||
base.ConnectHandler(platformView);
|
||||
}
|
||||
|
||||
//Currently the Disconnect Handler needs to be manually called from the App: https://github.com/dotnet/maui/issues/3604
|
||||
protected override void DisconnectHandler(AWebkit.WebView platformView)
|
||||
{
|
||||
platformView?.RemoveJavascriptInterface("jsBridge");
|
||||
platformView?.Dispose();
|
||||
VirtualView?.Cleanup();
|
||||
|
||||
base.DisconnectHandler(platformView);
|
||||
}
|
||||
|
||||
internal void InvokeActionOnVirtual(string data)
|
||||
{
|
||||
VirtualView?.InvokeAction(data);
|
||||
}
|
||||
}
|
||||
|
||||
public class JSBridge : Java.Lang.Object
|
||||
{
|
||||
private readonly WeakReference<HybridWebViewHandler> _hybridWebViewRenderer;
|
||||
|
||||
public JSBridge(HybridWebViewHandler hybridRenderer)
|
||||
{
|
||||
_hybridWebViewRenderer = new WeakReference<HybridWebViewHandler>(hybridRenderer);
|
||||
}
|
||||
|
||||
[AWebkit.JavascriptInterface]
|
||||
[Export("invokeAction")]
|
||||
public void InvokeAction(string data)
|
||||
{
|
||||
if (_hybridWebViewRenderer != null &&_hybridWebViewRenderer.TryGetTarget(out HybridWebViewHandler hybridRenderer))
|
||||
{
|
||||
hybridRenderer?.InvokeActionOnVirtual(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class JSWebViewClient : AWebkit.WebViewClient
|
||||
{
|
||||
private readonly string _javascript;
|
||||
|
||||
public JSWebViewClient(string javascript)
|
||||
{
|
||||
_javascript = javascript;
|
||||
}
|
||||
|
||||
public override void OnPageFinished(AWebkit.WebView view, string url)
|
||||
{
|
||||
base.OnPageFinished(view, url);
|
||||
if (view != null)
|
||||
{
|
||||
view.EvaluateJavascript(_javascript, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user