Skip to content

Commit

Permalink
feat: Add support for ExecuteScriptAsync on iOS/macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund committed Apr 7, 2023
1 parent 3e93f4b commit 6da41f4
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public partial class WebView2
throw new global::System.NotImplementedException("The member IAsyncAction WebView2.EnsureCoreWebView2Async() is not implemented. For more information, visit https://aka.platform.uno/notimplemented?m=IAsyncAction%20WebView2.EnsureCoreWebView2Async%28%29");
}
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public global::Windows.Foundation.IAsyncOperation<string> ExecuteScriptAsync( string javascriptCode)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ public void RemoveScriptToExecuteOnDocumentCreated( string id)
global::Windows.Foundation.Metadata.ApiInformation.TryRaiseNotImplemented("Microsoft.Web.WebView2.Core.CoreWebView2", "void CoreWebView2.RemoveScriptToExecuteOnDocumentCreated(string id)");
}
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public global::Windows.Foundation.IAsyncOperation<string> ExecuteScriptAsync( string javaScript)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ public void Stop()
throw new global::System.NotImplementedException("The member IAsyncAction WebView.CapturePreviewToStreamAsync(IRandomAccessStream stream) is not implemented. For more information, visit https://aka.platform.uno/notimplemented?m=IAsyncAction%20WebView.CapturePreviewToStreamAsync%28IRandomAccessStream%20stream%29");
}
#endif
#if __ANDROID__ || __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
#if false
[global::Uno.NotImplemented("__ANDROID__", "__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
public global::Windows.Foundation.IAsyncOperation<string> InvokeScriptAsync( string scriptName, global::System.Collections.Generic.IEnumerable<string> arguments)
{
Expand Down
24 changes: 13 additions & 11 deletions src/Uno.UI/UI/Xaml/Controls/WebView/Core/CoreWebView2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
using System.Linq;
using System.Threading;
using System.Globalization;
using Windows.Foundation;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;

namespace Microsoft.Web.WebView2.Core;

Expand Down Expand Up @@ -80,6 +82,17 @@ internal void NavigateWithHttpRequestMessage(HttpRequestMessage requestMessage)

public void Reload() => _nativeWebView?.Reload();

public IAsyncOperation<string> ExecuteScriptAsync(string javaScript) =>
AsyncOperation.FromTask(ct =>
{
if (_nativeWebView is null)
{
return Task.FromResult<string>(null);
}

return _nativeWebView.ExecuteScriptAsync(javaScript, ct);
});

internal void OnOwnerApplyTemplate()
{
_nativeWebView = GetNativeWebViewFromTemplate();
Expand Down Expand Up @@ -121,17 +134,6 @@ internal static bool GetIsHistoryEntryValid(string url) =>
!url.IsNullOrWhiteSpace() &&
!url.Equals(BlankUrl, StringComparison.OrdinalIgnoreCase);

internal static string ConcatenateJavascriptArguments(string[] arguments)
{
var argument = string.Empty;
if (arguments != null && arguments.Any())
{
argument = string.Join(",", arguments);
}

return argument;
}

[MemberNotNullWhen(true, nameof(_nativeWebView))]
private bool VerifyWebViewAvailability()
{
Expand Down
8 changes: 8 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/WebView/Native/INativeWebView.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Uno.Disposables;

namespace Uno.UI.Xaml.Controls;

internal partial interface INativeWebView
{
void GoBack();

void GoForward();

void Stop();

void Reload();

void ProcessNavigation(Uri uri);

void ProcessNavigation(string html);

void ProcessNavigation(HttpRequestMessage httpRequestMessage);

Task<string> ExecuteScriptAsync(string script, CancellationToken token);
}
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ internal bool OnUnsupportedUriSchemeIdentified(Uri targetUri)
/// Url of the last navigation ; is null if the last web page was displayed by other means,
/// such as raw HTML
/// </summary>
private object _lastNavigationData;
internal object _lastNavigationData;

internal void OnNavigationFinished(Uri destinationUrl)
{
Expand Down Expand Up @@ -203,49 +203,49 @@ private WKWebView OnCreateWebView(WKWebView owner, WKWebViewConfiguration config
_coreWebView.RaiseNewWindowRequested(); //TODO:MZ:

//TODO:MZ:
// if (args.Handled)
// {
// return null;
// }
// else
// {
// //var navigationArgs = new WebViewNavigationStartingEventArgs()
// //{
// // Cancel = false,
// // Uri = target
// //};

// _coreWebView.RaiseNavigationStarting(); //TODO:MZ:

// if (!navigationArgs.Cancel)
// {
//#if __IOS__
// if (UIKit.UIApplication.SharedApplication.CanOpenUrl(target))
// {
// UIKit.UIApplication.SharedApplication.OpenUrl(target);
// // TODO:MZ:
// _coreWebView.RaiseNavigationCompleted();
// //_coreWebView.OnComplete(target, isSuccessful: true, status: WebErrorStatus.Unknown);
// }
//#else
// if (target != null && NSWorkspace.SharedWorkspace.UrlForApplication(new NSUrl(target.AbsoluteUri)) != null)
// {
// NSWorkspace.SharedWorkspace.OpenUrl(target);
// _coreWebView.OnComplete(target, isSuccessful: true, status: WebErrorStatus.Unknown);
// }
//#endif
// else
// {
// // TODO:MZ:
// _coreWebView.RaiseNavigationCompleted();
// //_coreWebView.OnNavigationFailed(new WebViewNavigationFailedEventArgs()
// //{
// // Uri = target,
// // WebErrorStatus = WebErrorStatus.Unknown
// //});
// }
// }
// }
// if (args.Handled)
// {
// return null;
// }
// else
// {
// //var navigationArgs = new WebViewNavigationStartingEventArgs()
// //{
// // Cancel = false,
// // Uri = target
// //};

// _coreWebView.RaiseNavigationStarting(); //TODO:MZ:

// if (!navigationArgs.Cancel)
// {
//#if __IOS__
// if (UIKit.UIApplication.SharedApplication.CanOpenUrl(target))
// {
// UIKit.UIApplication.SharedApplication.OpenUrl(target);
// // TODO:MZ:
// _coreWebView.RaiseNavigationCompleted();
// //_coreWebView.OnComplete(target, isSuccessful: true, status: WebErrorStatus.Unknown);
// }
//#else
// if (target != null && NSWorkspace.SharedWorkspace.UrlForApplication(new NSUrl(target.AbsoluteUri)) != null)
// {
// NSWorkspace.SharedWorkspace.OpenUrl(target);
// _coreWebView.OnComplete(target, isSuccessful: true, status: WebErrorStatus.Unknown);
// }
//#endif
// else
// {
// // TODO:MZ:
// _coreWebView.RaiseNavigationCompleted();
// //_coreWebView.OnNavigationFailed(new WebViewNavigationFailedEventArgs()
// //{
// // Uri = target,
// // WebErrorStatus = WebErrorStatus.Unknown
// //});
// }
// }
// }

return null;
}
Expand Down Expand Up @@ -382,9 +382,9 @@ internal bool OnStarted(Uri targetUrl, bool stopLoadingOnCanceled = true)

_isCancelling = false;

_coreWebView.RaiseNavigationStarting(targetUrl, out var cancel); //TODO:MZ: For HTML content var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(htmlContent);
//var base64String = System.Convert.ToBase64String(plainTextBytes);
//var htmlUri = new Uri(string.Format(CultureInfo.InvariantCulture, DataUriFormatString, base64String));
_coreWebView.RaiseNavigationStarting(null, out var cancel); //TODO:MZ: For HTML content var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(htmlContent);
//var base64String = System.Convert.ToBase64String(plainTextBytes);
//var htmlUri = new Uri(string.Format(CultureInfo.InvariantCulture, DataUriFormatString, base64String));

if (cancel)
{
Expand Down Expand Up @@ -455,18 +455,20 @@ void INativeWebView.GoForward()
GoTo(GetNearestValidHistoryItem(direction: 1));
}

public async Task<string> EvaluateJavascriptAsync(CancellationToken ct, string javascript)
internal async Task<string> ExecuteScriptAsync(string script, CancellationToken token)
{
var executedScript = string.Format(CultureInfo.InvariantCulture, "javascript:{0}", script);

if (this.Log().IsEnabled(Uno.Foundation.Logging.LogLevel.Debug))
{
this.Log().Debug($"EvaluateJavascriptAsync: {javascript}");
this.Log().Debug($"ExecuteScriptAsync: {executedScript}");
}

var tcs = new TaskCompletionSource<string>();

using (ct.Register(() => tcs.TrySetCanceled()))
using (token.Register(() => tcs.TrySetCanceled()))
{
EvaluateJavaScript(javascript, (result, error) =>
EvaluateJavaScript(executedScript, (result, error) =>
{
if (error != null)
{
Expand All @@ -482,17 +484,6 @@ public async Task<string> EvaluateJavascriptAsync(CancellationToken ct, string j
}
}

//_owner should be IAsyncOperation<string> instead of Task<string> but we use an extension method to enable the same signature in Win.
//IAsyncOperation is not available in Xamarin.
internal async Task<string> InvokeScriptAsync(CancellationToken ct, string script, string[] arguments)
{
var argumentString = CoreWebView2.ConcatenateJavascriptArguments(arguments);
return await EvaluateJavascriptAsync(ct, string.Format(CultureInfo.InvariantCulture, "javascript:{0}(\"{1}\")", script, argumentString));
}

internal IAsyncOperation<string> InvokeScriptAsync(string scriptName, IEnumerable<string> arguments) =>
AsyncOperation.FromTask(ct => InvokeScriptAsync(ct, scriptName, arguments?.ToArray()));

private void ProcessNSUrlRequest(NSUrlRequest request)
{
if (request == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ bool GetIsAnchorNavigation()

// To detect an anchor navigation, both the previous and new urls need to match on the left part of the anchor indicator ("#")
// AND the new url needs to have content on the right of the anchor indicator.
if (_lastNavigationData is Uri urlLastNavigation)
if (unoWKWebView._lastNavigationData is Uri urlLastNavigation)
{
var currentUrlParts = urlLastNavigation?.AbsoluteUrl?.ToString().Split(new string[] { "#" }, StringSplitOptions.None);
var currentUrlParts = urlLastNavigation?.AbsoluteUri?.ToString().Split(new string[] { "#" }, StringSplitOptions.None);
var newUrlParts = requestUrl?.AbsoluteUri?.ToString().Split(new string[] { "#" }, StringSplitOptions.None);

return currentUrlParts?.Length > 0
Expand Down
22 changes: 22 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/WebView/WebView1/WebView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
using System.Net.Http;
using Microsoft.Web.WebView2.Core;
using Uno.UI.Xaml.Controls;
using System.Collections.Generic;
using Windows.Foundation;
using System.Globalization;
using System.Linq;

namespace Windows.UI.Xaml.Controls;

Expand Down Expand Up @@ -49,6 +53,13 @@ public WebView()

public void Stop() => CoreWebView2.Stop();

public IAsyncOperation<string> InvokeScriptAsync(string scriptName, IEnumerable<string> arguments)
{
var argumentString = ConcatenateJavascriptArguments(arguments);
var javaScript = string.Format(CultureInfo.InvariantCulture, "{0}(\"{1}\")", scriptName, argumentString);
return CoreWebView2.ExecuteScriptAsync(javaScript);
}

internal void NavigateWithHttpRequestMessage(HttpRequestMessage requestMessage) =>
CoreWebView2.NavigateWithHttpRequestMessage(requestMessage);

Expand Down Expand Up @@ -87,4 +98,15 @@ private void CoreWebView2_SourceChanged(CoreWebView2 sender, CoreWebView2SourceC
{
// TODO:MZ:
}

private static string ConcatenateJavascriptArguments(IEnumerable<string> arguments)
{
var argument = string.Empty;
if (arguments != null && arguments.Any())
{
argument = string.Join(",", arguments);
}

return argument;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static WebViewDOMContentLoadedEventArgs ToWebViewArgs(this CoreWebView2DO
new WebViewDOMContentLoadedEventArgs(args.Uri);

public static WebViewNavigationStartingEventArgs ToWebViewArgs(this CoreWebView2NavigationStartingEventArgs args) =>
new WebViewNavigationStartingEventArgs(args.Uri);
new WebViewNavigationStartingEventArgs(args.Uri.Length <= 2048 ? new global::System.Uri(args.Uri) : CoreWebView2.BlankUri);

public static WebViewNavigationCompletedEventArgs ToWebViewArgs(this CoreWebView2NavigationCompletedEventArgs args) =>
new WebViewNavigationCompletedEventArgs(args.IsSuccess, args.Uri, args.WebErrorStatus.ToWebErrorStatus()); //TODO:MZ:
Expand Down
3 changes: 3 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/WebView/WebView2/WebView2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ public IAsyncAction EnsureCoreWebView2Async() =>
return Task.CompletedTask;
});

public IAsyncOperation<string> ExecuteScriptAsync(string javascriptCode) =>
CoreWebView2.ExecuteScriptAsync(javascriptCode);

public void Reload() => CoreWebView2.Reload();

public void GoForward() => CoreWebView2.GoForward();
Expand Down

0 comments on commit 6da41f4

Please sign in to comment.