Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

[Bug] WebView.EvaluateJavascriptAsync is encoding input and output #11648

Open
rowillis opened this issue Aug 4, 2020 · 10 comments
Open

[Bug] WebView.EvaluateJavascriptAsync is encoding input and output #11648

rowillis opened this issue Aug 4, 2020 · 10 comments
Labels
a/webview e/2 🕑 2 p/Android p/iOS 🍎 t/bug 🐛 up-for-grabs We welcome community contributions to any issue, but these might be a good place to start!

Comments

@rowillis
Copy link

rowillis commented Aug 4, 2020

Description

The implementation of WebView.EvaluateJavascriptAsync is non-standard and appears to be encoding the input and output in unexpected ways. Other 3rd party plugins and other toolsets/languages (such as flutter) are behaving as expected.

Steps to Reproduce

  1. Create a new XF project
  2. Add a webview to the XAML with any webpage as the source, and a "Navigated" event handler
  3. In the "Navigated" eventhandler, add the following:
    var webView = sender as WebView; var html = webView.EvaluateJavascriptAsync("document.documentElement.outerHTML");

See https://stackoverflow.com/questions/63228670/get-html-document-from-xamarin-forms-webview and attached sample for more info.

Expected Behavior

The html should a standard HTML string with no encoding.

Actual Behavior

The html is encoded instead the straight HTML. Even after decoding, you will notice that string literals are double-escaped.

NOTE: If this behavior is deemed correct for some reason, then I would convert this into a feature request for an additional method that does not munge the input/output.

Basic Information

  • Version with issue: XF 4.7.0.1239
  • Last known good version: unknown
  • IDE: VS Mac
  • Platform Target Frameworks:
    • iOS: 11.6
    • Android: 10.0, API level 29
    • UWP: n/a
  • Android Support Library Version:
  • Nuget Packages: Default (Xamarin.Essentials 1.5.3.2, Xamarin.Forms 4.7.0.1239)
  • Affected Devices:

Reproduction Link

Workaround

Lucas Zhang suggested using WebUtility.HtmlDecode(html) and regex to decode the string, but other well-formed JS scripts still fail (whereas they do not with other 3rd party implementations and other tools such as flutter), leading me to believe that the implementation is targeted at some very specific use case and is doing more than it should.
TestWebView.zip

@rowillis rowillis added s/unverified New report that has yet to be verified t/bug 🐛 labels Aug 4, 2020
@PureWeen PureWeen added up-for-grabs We welcome community contributions to any issue, but these might be a good place to start! e/2 🕑 2 a/webview p/Android p/iOS 🍎 and removed s/unverified New report that has yet to be verified labels Aug 5, 2020
@jgold6
Copy link
Contributor

jgold6 commented Aug 13, 2020

It seems that the 3rd party Plugin.HybridWebView strips out the extraneous stuff:
https://github.com/devsmadeofsteel/Plugin.HybridWebView/blob/master/HybridWebView/Droid/HybridWebViewRenderer.cs#L359

                // Unescape that damn Unicode Java bull.
                response = Regex.Replace(_callback.Value.ToString(), @"\\[Uu]([0-9A-Fa-f]{4})", m => char.ToString((char)ushort.Parse(m.Groups[1].Value, NumberStyles.AllowHexSpecifier)));
                response = Regex.Unescape(response);

Xam.Forms just returns whatever the platform returns from the native web view EvaluateJavascript methods.

@samhouts samhouts added this to the 5.0.0 milestone Aug 13, 2020
@B2alex
Copy link

B2alex commented Oct 13, 2020

any update on this? the solution that jgold6 has mentioned doesn't fully work for me.

@samhouts samhouts removed this from the 5.0.0 milestone Nov 2, 2020
@KyNam
Copy link
Contributor

KyNam commented Mar 1, 2021

Why JSON.stringify the result?

script = "try{JSON.stringify(eval('" + script + "'))}catch(e){'null'};";

			//make all the platforms mimic Android's implementation, which is by far the most complete.
			if (Xamarin.Forms.Device.RuntimePlatform != "Android")
			{
				script = EscapeJsString(script);
				script = "try{JSON.stringify(eval('" + script + "'))}catch(e){'null'};";
			}

@dzebas
Copy link

dzebas commented May 31, 2021

Is this going to be fixed?

@n-ate
Copy link

n-ate commented Dec 2, 2022

Stumbled on this bug. I noticed that I can send
"alert(99); true;"
and it works fine, but if I send
"alert(99);\ntrue;"
or
"alert(99);\r\ntrue;"
that it fails silently.
Are multiline scripts not supported? Is this related to this bug?

Update: if I escape \ with a second \ then it seems to work.

@trivalik
Copy link

Stumbled on this bug. I noticed that I can send "alert(99); true;" and it works fine, but if I send "alert(99);\ntrue;" or "alert(99);\r\ntrue;" that it fails silently. Are multiline scripts not supported? Is this related to this bug?

Update: if I escape \ with a second \ then it seems to work.

This is no bug. I created a bug for MAUI WebView and it seems it is wanted, for whatever reason.

@bricefriha
Copy link

bricefriha commented Jul 13, 2023

Stumbled on this bug. I noticed that I can send "alert(99); true;" and it works fine, but if I send "alert(99);\ntrue;" or "alert(99);\r\ntrue;" that it fails silently. Are multiline scripts not supported? Is this related to this bug?

Update: if I escape \ with a second \ then it seems to work.

Thanks @n-ate!

So basically, the workaround is:

// Your js
string script = @"
                           alert(99);
                           true;";

await webView.EvaluateJavaScriptAsync(script.Trim().Replace("\r", "\\r").Replace("\n", "\\n"); 

At least it works on my side

@trivalik
Copy link

@bricefriha it is enought to replace with an empty string. This will save you a few nanoseconds on the browser side ignoring newlines. The only exception is if you have text which require the newline.

@bricefriha
Copy link

@bricefriha it is enought to replace with an empty string. This will save you a few nanoseconds on the browser side ignoring newlines. The only exception is if you have text which require the newline.

It's what I was thinking about at first as well, but when I tested it didn't work.

But feel free to test it on your side, I might have done something wrong 😉

@trivalik
Copy link

It looks like this bug will be fixed for MAUI: dotnet/maui#11905

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a/webview e/2 🕑 2 p/Android p/iOS 🍎 t/bug 🐛 up-for-grabs We welcome community contributions to any issue, but these might be a good place to start!
Projects
None yet
Development

No branches or pull requests

10 participants