From be3a0fb522d96442a505ff82c2cf2a5459a06ed5 Mon Sep 17 00:00:00 2001 From: Martin Zikmund Date: Thu, 20 Apr 2023 15:05:17 -0700 Subject: [PATCH] feat: WebView and WebView2 on WebAssembly --- .../Given_WebView2.cs | 2 +- .../Windows_UI_Xaml_Controls/Given_WebView.cs | 2 +- .../WebView/Core/CoreWebView2.unsupported.cs | 2 +- .../WebView/Core/CoreWebView2.wasm.cs | 28 +++++++++ .../Native/Wasm/INativeWebView.wasm.cs | 11 ++++ .../WebView/Native/Wasm/NativeWebView.wasm.cs | 59 +++++++++++++++++++ .../Xaml/Controls/WebView/WebView1/WebView.cs | 2 +- .../Controls/WebView/WebView2/WebView2.cs | 4 +- src/Uno.UI/UI/Xaml/Style/Generic/Generic.xaml | 20 +++++++ src/Uno.UI/WasmCSS/Uno.UI.css | 6 +- 10 files changed, 129 insertions(+), 7 deletions(-) create mode 100644 src/Uno.UI/UI/Xaml/Controls/WebView/Core/CoreWebView2.wasm.cs create mode 100644 src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/INativeWebView.wasm.cs create mode 100644 src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.wasm.cs diff --git a/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_WebView2.cs b/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_WebView2.cs index abc69ebe6996..09d3e780852f 100644 --- a/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_WebView2.cs +++ b/src/Uno.UI.RuntimeTests/Tests/Microsoft_UI_Xaml_Controls/Given_WebView2.cs @@ -25,7 +25,7 @@ namespace Uno.UI.RuntimeTests.Tests.Microsoft_UI_Xaml_Controls; -#if !HAS_UNO || __ANDROID__ || __IOS__ +#if !HAS_UNO || __ANDROID__ || __IOS__ || __WASM__ [TestClass] [RunsOnUIThread] public class Given_WebView2 diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView.cs index b4ef0e6bbb57..21fdb57d13be 100644 --- a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView.cs +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView.cs @@ -39,7 +39,7 @@ public void When_Navigate() Assert.AreEqual("https://bing.com", uri.OriginalString); } -#if __ANDROID__ || __IOS__ || __MACOS__ +#if __ANDROID__ || __IOS__ || __MACOS__ || __WASM__ [TestMethod] public void When_NavigateWithHttpRequestMessage() { diff --git a/src/Uno.UI/UI/Xaml/Controls/WebView/Core/CoreWebView2.unsupported.cs b/src/Uno.UI/UI/Xaml/Controls/WebView/Core/CoreWebView2.unsupported.cs index 8f2acf9e9ebc..0a575c721a98 100644 --- a/src/Uno.UI/UI/Xaml/Controls/WebView/Core/CoreWebView2.unsupported.cs +++ b/src/Uno.UI/UI/Xaml/Controls/WebView/Core/CoreWebView2.unsupported.cs @@ -1,4 +1,4 @@ -#if !__ANDROID__ && !__IOS__ && !__MACOS__ && !__MACCATALYST__ && !__SKIA__ +#if !__ANDROID__ && !__IOS__ && !__MACOS__ && !__MACCATALYST__ && !__SKIA__ && !__WASM__ #nullable enable using Uno.UI.Xaml.Controls; diff --git a/src/Uno.UI/UI/Xaml/Controls/WebView/Core/CoreWebView2.wasm.cs b/src/Uno.UI/UI/Xaml/Controls/WebView/Core/CoreWebView2.wasm.cs new file mode 100644 index 000000000000..2585556420be --- /dev/null +++ b/src/Uno.UI/UI/Xaml/Controls/WebView/Core/CoreWebView2.wasm.cs @@ -0,0 +1,28 @@ +#nullable enable + +using System.Linq; +using Uno.UI; +using Uno.UI.Extensions; +using Uno.UI.Xaml.Controls; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace Microsoft.Web.WebView2.Core; + +public partial class CoreWebView2 +{ + internal INativeWebView? GetNativeWebViewFromTemplate() + { + var webView = ((UIElement)_owner) + .GetChildren() + .OfType() + .FirstOrDefault(); + + if (webView is null) + { + return null; + } + + return webView; + } +} diff --git a/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/INativeWebView.wasm.cs b/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/INativeWebView.wasm.cs new file mode 100644 index 000000000000..6245a0399dd6 --- /dev/null +++ b/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/INativeWebView.wasm.cs @@ -0,0 +1,11 @@ +using Microsoft.Web.WebView2.Core; + +namespace Uno.UI.Xaml.Controls; + +/// +/// Wrapper for a version-dependent native WASM WebView +/// +internal partial interface INativeWebView +{ + void SetOwner(CoreWebView2 xamlWebView); +} diff --git a/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.wasm.cs b/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.wasm.cs new file mode 100644 index 000000000000..18f20ddb5016 --- /dev/null +++ b/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.wasm.cs @@ -0,0 +1,59 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Web.WebView2.Core; +using Uno.Foundation; +using Uno.UI.Xaml.Controls; + +namespace Windows.UI.Xaml.Controls; + +public class NativeWebView : FrameworkElement, INativeWebView +{ + private CoreWebView2 _coreWebView; + + public NativeWebView() : base("iframe") + { + this.HorizontalAlignment = HorizontalAlignment.Stretch; + this.VerticalAlignment = VerticalAlignment.Stretch; + } + + public void SetOwner(CoreWebView2 coreWebView) + { + _coreWebView = coreWebView; + } + + public Task ExecuteScriptAsync(string script, CancellationToken token) + { + var scriptString = WebAssemblyRuntime.EscapeJs(script); + return Task.FromResult(WebAssemblyRuntime.InvokeJS($"document.getElementById('{HtmlId}').contentWindow.eval(\"{scriptString}\")")); + } + + public void GoBack() { } + public void GoForward() { } + public Task InvokeScriptAsync(string script, string[] arguments, CancellationToken token) => Task.FromResult(""); + public async void ProcessNavigation(Uri uri) + { + this.SetAttribute("src", uri.ToString()); + await Task.Delay(10); + _coreWebView.RaiseNavigationCompleted(uri, true, 200, CoreWebView2WebErrorStatus.Unknown); + } + + public async void ProcessNavigation(string html) + { + this.SetAttribute("srcdoc", html); + await Task.Delay(10); + _coreWebView.RaiseNavigationCompleted(null, true, 200, CoreWebView2WebErrorStatus.Unknown); + } + + public void ProcessNavigation(HttpRequestMessage httpRequestMessage) + { + + } + + public void Reload() + { + } + public void SetScrollingEnabled(bool isScrollingEnabled) { } + public void Stop() { } +} diff --git a/src/Uno.UI/UI/Xaml/Controls/WebView/WebView1/WebView.cs b/src/Uno.UI/UI/Xaml/Controls/WebView/WebView1/WebView.cs index 6e3ed4574135..edf19b3f405f 100644 --- a/src/Uno.UI/UI/Xaml/Controls/WebView/WebView1/WebView.cs +++ b/src/Uno.UI/UI/Xaml/Controls/WebView/WebView1/WebView.cs @@ -13,7 +13,7 @@ namespace Microsoft.UI.Xaml.Controls; -#if IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ +#if IS_UNIT_TESTS || __SKIA__ || __NETSTD_REFERENCE__ [Uno.NotImplemented("IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__")] #endif public partial class WebView : Control, IWebView diff --git a/src/Uno.UI/UI/Xaml/Controls/WebView/WebView2/WebView2.cs b/src/Uno.UI/UI/Xaml/Controls/WebView/WebView2/WebView2.cs index 5fd465cea5bc..07cd8e1bfc9c 100644 --- a/src/Uno.UI/UI/Xaml/Controls/WebView/WebView2/WebView2.cs +++ b/src/Uno.UI/UI/Xaml/Controls/WebView/WebView2/WebView2.cs @@ -13,8 +13,8 @@ namespace Microsoft/* UWP don't rename */.UI.Xaml.Controls; /// /// Represents an object that enables the hosting of web content. /// -#if IS_UNIT_TESTS || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ -[Uno.NotImplemented("IS_UNIT_TESTS", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__")] +#if IS_UNIT_TESTS || __SKIA__ || __NETSTD_REFERENCE__ +[Uno.NotImplemented("IS_UNIT_TESTS", "__SKIA__", "__NETSTD_REFERENCE__")] #endif public partial class WebView2 : Control, IWebView { diff --git a/src/Uno.UI/UI/Xaml/Style/Generic/Generic.xaml b/src/Uno.UI/UI/Xaml/Style/Generic/Generic.xaml index edb3e5f77ac2..dd82414e96e9 100644 --- a/src/Uno.UI/UI/Xaml/Style/Generic/Generic.xaml +++ b/src/Uno.UI/UI/Xaml/Style/Generic/Generic.xaml @@ -7740,6 +7740,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/Uno.UI/WasmCSS/Uno.UI.css b/src/Uno.UI/WasmCSS/Uno.UI.css index 2676a3da43f1..03bad8e83e7c 100644 --- a/src/Uno.UI/WasmCSS/Uno.UI.css +++ b/src/Uno.UI/WasmCSS/Uno.UI.css @@ -294,5 +294,9 @@ input::-ms-clear { /* Uno has its own HR indicator: hide default dotnet indicator. */ #dotnet-hotreload-toast { - visibility: collapse + visibility: collapse; +} + +.uno-nativewebview { + border: 0px; }