diff --git a/src/Core/src/Handlers/WebView/WebViewHandler.Android.cs b/src/Core/src/Handlers/WebView/WebViewHandler.Android.cs index ef02fde79eb5..12fbc975f6d7 100644 --- a/src/Core/src/Handlers/WebView/WebViewHandler.Android.cs +++ b/src/Core/src/Handlers/WebView/WebViewHandler.Android.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Net; +using Android.Views; using Android.Webkit; using static Android.Views.ViewGroup; using AWebView = Android.Webkit.WebView; @@ -63,12 +64,15 @@ protected override void DisconnectHandler(AWebView platformView) webChromeClient.Disconnect(); } - platformView.SetWebViewClient(null!); platformView.SetWebChromeClient(null); platformView.StopLoading(); + if (platformView.Parent is ViewGroup parent) + parent.RemoveView(platformView); + platformView.RemoveAllViews(); base.DisconnectHandler(platformView); + platformView.Destroy(); } public static void MapSource(IWebViewHandler handler, IWebView webView) @@ -331,4 +335,4 @@ void InitialCookiePreloadIfNecessary(string url) return null; } } -} \ No newline at end of file +} diff --git a/src/Core/tests/DeviceTests/Handlers/WebView/WebViewHandlerTests.Android.cs b/src/Core/tests/DeviceTests/Handlers/WebView/WebViewHandlerTests.Android.cs index 47c352fdd6d3..49a655091c24 100644 --- a/src/Core/tests/DeviceTests/Handlers/WebView/WebViewHandlerTests.Android.cs +++ b/src/Core/tests/DeviceTests/Handlers/WebView/WebViewHandlerTests.Android.cs @@ -1,8 +1,12 @@ using System; using System.Threading; using System.Threading.Tasks; +using Android.Content; +using Android.Views; using Android.Webkit; +using Android.Widget; using Microsoft.Maui.DeviceTests.Stubs; +using Microsoft.Maui.Platform; using Xunit; using AWebView = Android.Webkit.WebView; @@ -15,5 +19,62 @@ AWebView GetNativeWebView(WebViewHandler webViewHandler) => string GetNativeSource(WebViewHandler webViewHandler) => GetNativeWebView(webViewHandler).Url; + + [Fact(DisplayName = "DisconnectHandler Destroys Native WebView")] + public async Task DisconnectHandlerDestroysNativeWebView() + { + var originalFactory = WebViewHandler.PlatformViewFactory; + + try + { + await InvokeOnMainThreadAsync(() => + { + DestroyTrackingMauiWebView platformView = null; + + WebViewHandler.PlatformViewFactory = handler => + { + platformView = new DestroyTrackingMauiWebView((WebViewHandler)handler, handler.MauiContext!.Context!); + return platformView; + }; + + var webView = new WebViewStub(); + var handler = CreateHandler(webView); + var parent = new FrameLayout(handler.MauiContext!.Context!); + parent.AddView(handler.PlatformView); + + Assert.Same(parent, handler.PlatformView.Parent); + + ((IElementHandler)handler).DisconnectHandler(); + + var destroyTrackingWebView = platformView ?? throw new InvalidOperationException("Expected the WebView factory to create a platform view."); + Assert.True(destroyTrackingWebView.DestroyCalled); + Assert.Null(destroyTrackingWebView.ParentWhenDestroyed); + Assert.Equal(0, parent.ChildCount); + }); + } + finally + { + WebViewHandler.PlatformViewFactory = originalFactory; + } + } + + class DestroyTrackingMauiWebView : MauiWebView + { + public DestroyTrackingMauiWebView(WebViewHandler handler, Context context) + : base(handler, context) + { + } + + public bool DestroyCalled { get; private set; } + + public IViewParent ParentWhenDestroyed { get; private set; } + + public override void Destroy() + { + DestroyCalled = true; + ParentWhenDestroyed = Parent; + base.Destroy(); + } + } } } \ No newline at end of file