maui icon indicating copy to clipboard operation
maui copied to clipboard

Android WebViewClient's ShouldInterceptRequest is never called in MAUI WebView

Open jessiezh0320 opened this issue 2 years ago • 8 comments

Description

Android WebViewClient's ShouldInterceptRequest is never called in MAUI WebView

Steps to Reproduce

1.create a maui demo; 2.copy the following code to MauiProgram.cs:

public static class MauiProgram
{
	public static MauiApp CreateMauiApp()
	{
		var builder = MauiApp.CreateBuilder();
		builder
			.UseMauiApp<App>()
			.ConfigureFonts(fonts =>
			{
				fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
				fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
			})
			.ConfigureMauiHandlers(handlers =>
			{
				handlers.AddHandler<Microsoft.Maui.Controls.WebView, ProblemHandler2>();
			});

		return builder.Build();
	}
}

internal class ProblemHandler1 : WebViewHandler
{

	protected override Android.Webkit.WebView CreatePlatformView()
	{
		var wv = base.CreatePlatformView();
		wv.SetWebViewClient(new CustomWebClient());

		return wv;
	}

}

internal class ProblemHandler2 : WebViewHandler
{

    protected override Android.Webkit.WebView CreatePlatformView()
    {
        var wv = new Android.Webkit.WebView(Android.App.Application.Context);
        wv.SetWebViewClient(new CustomWebClient());

        return wv;
    }

}

internal class CustomWebClient : WebViewClient
{

    public override WebResourceResponse ShouldInterceptRequest(Android.Webkit.WebView view, IWebResourceRequest request)
    {
        Debugger.Break();
        Debug.WriteLine(request.Url.ToString());

        return base.ShouldInterceptRequest(view, request);
    }

}

MainPage.xaml.cs

public partial class MainPage : ContentPage
{
	int count = 0;

	public MainPage()
	{
		InitializeComponent();

        WebViewHandler.Mapper.AppendToMapping("MyHandler", (handler, view) =>
        {
#if ANDROID
			var xWv = handler.PlatformView;

			// For ProblemHandler2, this is needed to actually navigate:
			xWv.LoadUrl("https://www.google.com/");
#endif
        });

        this.wv.Source = "https://www.google.com/";
	}

}

3.build and deploy this demo to android device. (I only tested on android 13 emulator )

Link to public reproduction project repository

https://github.com/datvm/DemoMauiWvClient

Version with bug

Unknown/Other (please specify)

Last version that worked well

Unknown/Other

Affected platforms

Android, I was not able test on other platforms

Affected platform versions

Android 13

Did you find any workaround?

No response

Relevant log output

No response

jessiezh0320 avatar Oct 31 '22 05:10 jessiezh0320

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

ghost avatar Oct 31 '22 15:10 ghost

Hi @hartez , is there any workaround ?

jessiezh0320 avatar Nov 01 '22 02:11 jessiezh0320

WebViewClient.OnPageFinished(Android.Webkit.WebView platformView, string url) is NOT being called as well.

ederbond avatar Nov 03 '22 23:11 ederbond

@ederbond you are correct. This issue was created from this question on StackOverflow (by me), and I tried a few other callbacks as well. I suspect none of them is called.

datvm avatar Nov 04 '22 07:11 datvm

Hi any update on this? This is very important because without it, we cannot load local HTML content in our app following the official Android guide

datvm avatar Nov 17 '22 03:11 datvm

Hi @jessiezh0320 @hartez Would you have any idea when this is likely to be fixed, or a workaround? Thank you

samuelwine avatar Nov 30 '22 16:11 samuelwine

@hartez @davidortinau @jsuarezruiz @maddymontaquila any due date about this? It totally prevents me to ship my MAUI app without this fixed.

ederbond avatar Dec 07 '22 20:12 ederbond

Still no reply from the team about this. It would be nice to at least get a rough timeline for a fix. 1 month, 6 months, longer??

CartBlanche avatar Dec 21 '22 09:12 CartBlanche

Any news about it? This is a very big issue, we cannot ship the app without this fix.

gianisimone avatar Jan 18 '23 18:01 gianisimone

I'm being blocked to ship my app too. Any news @jsuarezruiz or @hartez @StephaneDelcroix @PureWeen @rmarinho @davidortinau @maddymontaquila about this?

ederbond avatar Jan 19 '23 20:01 ederbond

Btw in the mean time, can anyone check their source code and see how they fix it for their MAUI Blazor? I think their MAUI Blazor uses a customized WebView as well and intercept the https://0.0.0.0. Maybe we can use that workaround in the mean time?

UPDATE: It's here, ~~they use WebChromeClient so it's irrelevant~~ they use a custom WebViewHandler defined here WebViewHandler.Android.cs. No idea why it works for them though. Can someone investigate?

datvm avatar Jan 20 '23 06:01 datvm

Whoever would work on this issue, please also make sure WebViewClient.OnPageFinished(Android.Webkit.WebView platformView, string url) will be called properly as well.

ederbond avatar Jan 20 '23 17:01 ederbond

Any news about this? More than a month passed and still no clues about when this will be fixed

gianisimone avatar Feb 20 '23 21:02 gianisimone

Hey sorry just get back to this now, you should override the specific mapper we added for this: https://github.com/dotnet/maui/blob/main/src/Core/src/Handlers/WebView/WebViewHandler.cs#L28

Microsoft.Maui.Handlers.WebViewHandler.ModifyMapping(nameof(WebViewClient), (handler, view) =>
{
	handler.PlatformView.SetWebViewClient(new CustomWebClient());
});

rmarinho avatar May 04 '23 11:05 rmarinho

Sorry I gave up on this a long time ago and just use the MAUI Blazor. Can anyone confirm this is fixed?

datvm avatar May 04 '23 14:05 datvm

@jessiezh0320 can you try it out?

rmarinho avatar May 04 '23 15:05 rmarinho

Microsoft.Maui.Handlers.WebViewHandler.ModifyMapping(nameof(WebViewClient), (handler, view) =>
{
	handler.PlatformView.SetWebViewClient(new CustomWebClient());
});

@rmarinho please correct me, but WebViewHandler does not contain such method (or extension).

On the other hand the static PropertyMapper in WebViewHandler has an extension method with the name of ModifyMapping, but with a different signature. Unfortunately calling this method did not solve the issue.

#if ANDROID
            WebViewHandler.Mapper.ModifyMapping(nameof(Android.Webkit.WebViewClient), (handler, view, setter) =>
            {
                handler.PlatformView.SetWebViewClient(new CustomWebClient());
            });
#endif

Maybe one has to provide a custom setter?

mihaly-bence16 avatar May 10 '23 06:05 mihaly-bence16

@rmarinho I've tried also on my side the suggested workaround and as said by @mihaly-bence16 the signature of the method is different. Even so it does not work. So any updates regarding this?

unombun avatar May 31 '23 10:05 unombun

Found this accidently thinking I had coded something incorrectly but every single guide online says this is the way to handle SSL/TLS certificate errors. Can confirm that the constructor of the WebViewClient is called but none of these are:

  • ShouldOverrideUrlLoading(WebView, IWebResourceRequest)
  • ShouldOverrideUrlLoading(WebView, string)
  • WebResourceResponse ShouldInterceptRequest(WebView, IWebResourceRequest)
  • OnReceivedSslError(WebView, SslErrorHandler, SslError)
  • OnReceivedError(WebView, IWebResourceRequest, WebResourceError)
  • OnPageStarted(WebView, string, Bitmap)
  • OnPageFinished(WebView, string)

I overrode EVERY possible method and put breakpoints in them. None of them were hit.

I tried the work-around mentioned above, it does not work!

//DOES NOT WORK!
Microsoft.Maui.Handlers.WebViewHandler.Mapper.ModifyMapping(nameof(global::Android.Webkit.WebViewClient), (handler, view, setter) =>
{
    handler.PlatformView.SetWebViewClient(new DweWebViewClient());
});

pauldavis-dwe avatar Jun 14 '23 07:06 pauldavis-dwe

Hopefully this helps anyone running into this issue. I got it working after some poking around in the debugger. Added this below into my MauiProgram.cs and in 'platforms/Android' have my CustomWebviewClient with the overrides for the following below.

  • WebResourceResponse ShouldInterceptRequest(WebView, IWebResourceRequest)

  • OnReceivedSslError(WebView, SslErrorHandler, SslError)

#If ANDROID Microsoft.Maui.Handlers.WebViewHandler.Mapper.AppendToMapping(nameof(Android.Webkit.WebViewClient), (handler, view) => { handler.PlatformView.SetWebViewClient(new CustomWebViewClient()); }); #endif

ddavid456 avatar Jun 22 '23 01:06 ddavid456

Well... This partially works... I added this to my MauiBuilderExtensions and my custom WebViewClient starts working! Yay!

Microsoft.Maui.Handlers.WebViewHandler.Mapper.AppendToMapping(
            nameof(global::Android.Webkit.WebViewClient),
            (handler, _) => handler.PlatformView.SetWebViewClient(new DweWebViewClient()));

But that then breaks my code that hooks up to the WebView.Navigated event! Boo! The event simply does not fire. I have checked the order of execution and the setting of the WebViewClient is happening before the += to the Navigated event.

So we're back to square one in need of a fix

pauldavis-dwe avatar Jun 22 '23 06:06 pauldavis-dwe

UPDATE: I have managed to get the work-around functional! I changed my custom WebViewClient to inherit from MauiWebViewClient (instead of WebViewClient) and updated the code in my MauiAppBuilderExtensions to be:

Microsoft.Maui.Handlers.WebViewHandler.Mapper.AppendToMapping(
            nameof(global::Android.Webkit.WebViewClient),
            (handler, _) => handler.PlatformView.SetWebViewClient(new DweWebViewClient((Microsoft.Maui.Handlers.WebViewHandler)handler)));

This seems to work as the OnReceivedSslError() method is now being hit and the WebView.Navigated event is being fired too.

NOTE: This AppendToMapping work-around also seems to work for SetWebChromeClient() as that is now working for me too

pauldavis-dwe avatar Jun 22 '23 07:06 pauldavis-dwe

I wonder why ModifyMapper doens't work

rmarinho avatar Jun 22 '23 17:06 rmarinho

@rmarinho I'm not fully sure why either without spending some more time debugging, but when using ModifyMapping my new CustomWebviewClient is being set in SetWebviewClient. Though non of the override methods are being called. There might be some form of order of operations going on.

ddavid456 avatar Jun 22 '23 17:06 ddavid456

I think I found out why:

public static void MapWebViewClient(IWebViewHandler handler, IWebView webView)
{
	if (handler is WebViewHandler platformHandler)
		handler.PlatformView.SetWebViewClient(platformHandler._webViewClient ??= new MauiWebViewClient(platformHandler));
}

The existing mapper would set a field in the handler and use that in other places. Let me see if there is a better way we can do this to avoid the field or at least retrieve the client you set.

mattleibow avatar Jul 06 '23 08:07 mattleibow