Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HybridWebViewHandler "VirtualView cannot be null here" #26883

Closed
michalpobuta opened this issue Dec 31, 2024 · 5 comments · Fixed by #26928
Closed

HybridWebViewHandler "VirtualView cannot be null here" #26883

michalpobuta opened this issue Dec 31, 2024 · 5 comments · Fixed by #26928
Labels
area-controls-hybridwebview HybridWebView control platform/iOS 🍎 s/needs-attention Issue has more information and needs another look t/bug Something isn't working

Comments

@michalpobuta
Copy link
Contributor

michalpobuta commented Dec 31, 2024

Description

In my app, during executing js code, when I go back from web view, sometimes I get this error.

System.InvalidOperationException: VirtualView cannot be null here
   at Microsoft.Maui.Handlers.ViewHandler\u00602[[Microsoft.Maui.IHybridWebView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[WebKit.WKWebView, Microsoft.iOS, Version=18.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065]].get_VirtualView()
   at Microsoft.Maui.Handlers.HybridWebViewHandler.SchemeHandler.GetResponseBytes(String url)
   at Microsoft.Maui.Handlers.HybridWebViewHandler.SchemeHandler.StartUrlSchemeTask(WKWebView webView, IWKUrlSchemeTask urlSchemeTask)
   at Microsoft.Maui.Handlers.HybridWebViewHandler.SchemeHandler._Registrar_Callbacks.callback_1064_Microsoft_Maui_Handlers_HybridWebViewHandler_SchemeHandler_StartUrlSchemeTask(IntPtr pobj, IntPtr sel, IntPtr p0, IntPtr p1, IntPtr* exception_gchandle)","ModelException":{"Type":"System.InvalidOperationException","Message":"VirtualView cannot be null here","StackTrace":"   at Microsoft.Maui.Handlers.ViewHandler\u00602[[Microsoft.Maui.IHybridWebView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[WebKit.WKWebView, Microsoft.iOS, Version=18.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065]].get_VirtualView()
   at Microsoft.Maui.Handlers.HybridWebViewHandler.SchemeHandler.GetResponseBytes(String url)
   at Microsoft.Maui.Handlers.HybridWebViewHandler.SchemeHandler.StartUrlSchemeTask(WKWebView webView, IWKUrlSchemeTask urlSchemeTask)
   at Microsoft.Maui.Handlers.HybridWebViewHandler.SchemeHandler.Registrar_Callbacks_.callback_1064_Microsoft_Maui_Handlers_HybridWebViewHandler_SchemeHandler_StartUrlSchemeTask(IntPtr pobj, IntPtr sel, IntPtr p0, IntPtr p1, IntPtr* exception_gchandle)

Steps to Reproduce

To hard to reproduce, but change that line:

if (Handler is null)
				{
					return (Array.Empty<byte>(), ContentType: string.Empty, StatusCode: 404);
				}

to that:

if (Handler is null || Handler.VirtualView is null)
				{
					return (Array.Empty<byte>(), ContentType: string.Empty, StatusCode: 404);
				}

should help

Link to public reproduction project repository

No response

Version with bug

9.0.21 SR2.1

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

iOS

Affected platform versions

all iOS

Did you find any workaround?

nope

Relevant log output

System.InvalidOperationException: VirtualView cannot be null here
   at Microsoft.Maui.Handlers.ViewHandler\u00602[[Microsoft.Maui.IHybridWebView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[WebKit.WKWebView, Microsoft.iOS, Version=18.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065]].get_VirtualView()
   at Microsoft.Maui.Handlers.HybridWebViewHandler.SchemeHandler.GetResponseBytes(String url)
   at Microsoft.Maui.Handlers.HybridWebViewHandler.SchemeHandler.StartUrlSchemeTask(WKWebView webView, IWKUrlSchemeTask urlSchemeTask)
   at Microsoft.Maui.Handlers.HybridWebViewHandler.SchemeHandler._Registrar_Callbacks.callback_1064_Microsoft_Maui_Handlers_HybridWebViewHandler_SchemeHandler_StartUrlSchemeTask(IntPtr pobj, IntPtr sel, IntPtr p0, IntPtr p1, IntPtr* exception_gchandle)","ModelException":{"Type":"System.InvalidOperationException","Message":"VirtualView cannot be null here","StackTrace":"   at Microsoft.Maui.Handlers.ViewHandler\u00602[[Microsoft.Maui.IHybridWebView, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[WebKit.WKWebView, Microsoft.iOS, Version=18.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065]].get_VirtualView()
   at Microsoft.Maui.Handlers.HybridWebViewHandler.SchemeHandler.GetResponseBytes(String url)
   at Microsoft.Maui.Handlers.HybridWebViewHandler.SchemeHandler.StartUrlSchemeTask(WKWebView webView, IWKUrlSchemeTask urlSchemeTask)
   at Microsoft.Maui.Handlers.HybridWebViewHandler.SchemeHandler.Registrar_Callbacks_.callback_1064_Microsoft_Maui_Handlers_HybridWebViewHandler_SchemeHandler_StartUrlSchemeTask(IntPtr pobj, IntPtr sel, IntPtr p0, IntPtr p1, IntPtr* exception_gchandle)
@michalpobuta michalpobuta added the t/bug Something isn't working label Dec 31, 2024
@jfversluis jfversluis added s/needs-repro Attach a solution or code which reproduces the issue area-controls-hybridwebview HybridWebView control labels Jan 1, 2025
@michalpobuta
Copy link
Contributor Author

Hi @jfversluis, I am not able to create repro for that. My company product is not open source, but i can tell you that, this problem shows sometimes when naviagate back from view with TradingView.

I created workaround for this problem:

public partial class CustomHybridWebViewHandler
{
    protected override WKWebView CreatePlatformView()
    {
        var configOrigin = base.CreatePlatformView().Configuration;

        var config = new WKWebViewConfiguration();
        if (OperatingSystem.IsMacCatalystVersionAtLeast(10) || OperatingSystem.IsIOSVersionAtLeast(10))
        {
            config.AllowsPictureInPictureMediaPlayback = true;
            config.AllowsInlineMediaPlayback = true;
            config.MediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypes.None;
        }

        config.DefaultWebpagePreferences!.AllowsContentJavaScript = true;

        config.UserContentController = configOrigin.UserContentController;
        config.SetUrlSchemeHandler(new SchemeHandler(this, configOrigin.GetUrlSchemeHandler("app")!), "app");

        var webview = new MauiHybridWebView(this, RectangleF.Empty, config)
        {
            BackgroundColor = UIColor.Clear,
            AutosizesSubviews = true
        };

        return webview;
    }

    private class SchemeHandler : NSObject, IWKUrlSchemeHandler
    {
        private readonly IWKUrlSchemeHandler _originalHandler;
        private readonly HybridWebViewHandler _webViewHandler;

        public SchemeHandler(HybridWebViewHandler webViewHandler, IWKUrlSchemeHandler originalHandler)
        {
            _originalHandler = originalHandler;
            _webViewHandler = webViewHandler;
        }


        [Export("webView:startURLSchemeTask:")]
        [SupportedOSPlatform("ios11.0")]
        public void StartUrlSchemeTask(WKWebView webView, IWKUrlSchemeTask urlSchemeTask)
        {
            try
            {
                var _ = _webViewHandler.VirtualView;
            }
            catch (InvalidOperationException e)
            {
                return; //ignore
            }

            _originalHandler.StartUrlSchemeTask(webView, urlSchemeTask);
        }

        [Export("webView:stopURLSchemeTask:")]
        public void StopUrlSchemeTask(WKWebView webView, IWKUrlSchemeTask urlSchemeTask)
        {
        }
    }
}

@dotnet-policy-service dotnet-policy-service bot added s/needs-attention Issue has more information and needs another look and removed s/needs-repro Attach a solution or code which reproduces the issue labels Jan 2, 2025
@jfversluis
Copy link
Member

I understand that you can't just share your whole application, that is also not what a reproduction is. Please create a minimal project with just enough of your code to show the issue. That will greatly increase the changes of diagnosing what might be going on and fixing it. Additionally a lot of times this exercise helps developers detect a fix or workaround themselves.

@jfversluis jfversluis added s/needs-repro Attach a solution or code which reproduces the issue and removed s/needs-attention Issue has more information and needs another look labels Jan 2, 2025
@michalpobuta
Copy link
Contributor Author

@jfversluis here you have PR #26928 :)

@dotnet-policy-service dotnet-policy-service bot added s/needs-attention Issue has more information and needs another look and removed s/needs-repro Attach a solution or code which reproduces the issue labels Jan 2, 2025
@mattleibow
Copy link
Member

mattleibow commented Jan 4, 2025

I commented on the PR with something that you mentioned before, but for this issue to happen, the hybrid view will have to have been collected/detached.

Are you calling DisconnectHandler in your code at all? Are you using some community toolkit and/or nuget that may be doing this for you? @jfversluis @PureWeen what is the best way to debug this? An idea that I think may work is creating a custom handler and overriding the DisconnectHandler method?

Maybe this is part of some popup and or page that is being navigated away in a stack? @michalpobuta Maybe you can describe a possible navigation flow that this happens in? You may be able to repro if you create some part of the navigation flow and have a hybrid webview control with a dummy html page that just keeps requesting some data. Then when you navigate around you can repro.

The only reason the VirtualView would be null would be:

  1. you called DisconnectHandler
  2. someone else called DisconnectHandler
  3. you popped a page that had a HWV that was still working and then we called DisconnectHandler

Another test you can try is to add the HandlerProperties.DisconnectPolicy="Manual" property to your HWV and see if this error still happens. Keep in mind, this will mean the view, handler and native view will probably never be collected and lead to leaks. But, if this helps then you know someone is calling disconnect prematurely. Setting this will prevent 3. from happening.

Your PR will prevent the crash, but you should first determine who is disposing the view while it is still running.

@mattleibow mattleibow added s/needs-info Issue needs more info from the author and removed s/needs-attention Issue has more information and needs another look labels Jan 4, 2025
@mattleibow mattleibow modified the milestones: Backlog, .NET 9 Servicing Jan 4, 2025
@michalpobuta
Copy link
Contributor Author

Hi @mattleibow, I don't use any DisconnectHandler in my code.

I am 99% sure, that this happens because of executing js code while page is not anymore on stack. This is because i have TradingView on my page, and I am using InvokeJsMethodAsync. So sometimes, when I am going to left the page, and some data will be received, just before navigation, InvokeJsMethodAsync could be invoked, and then after navigation, some js code will try to executed and this happens.

This isn't any popup page, this is regular page based on ContentPage.

I could try with HandlerProperties.DisconnectPolicy="Manual" but still I think that this check in PR have to be there, because app cannot crash randomly like right now

@dotnet-policy-service dotnet-policy-service bot added s/needs-attention Issue has more information and needs another look and removed s/needs-info Issue needs more info from the author labels Jan 7, 2025
@github-actions github-actions bot locked and limited conversation to collaborators Feb 17, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-controls-hybridwebview HybridWebView control platform/iOS 🍎 s/needs-attention Issue has more information and needs another look t/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants