Skip to content

Commit

Permalink
PR Feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
TanayParikh committed Feb 16, 2022
1 parent 9639b8c commit 35f637e
Show file tree
Hide file tree
Showing 14 changed files with 116 additions and 65 deletions.
1 change: 1 addition & 0 deletions Microsoft.Maui.sln
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.DeviceTes
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SharedSource", "SharedSource", "{4F2926C8-43AB-4328-A735-D9EAD699F81D}"
ProjectSection(SolutionItems) = preProject
src\BlazorWebView\src\SharedSource\ExternalLinkMode.cs = src\BlazorWebView\src\SharedSource\ExternalLinkMode.cs
src\BlazorWebView\src\SharedSource\QueryStringHelper.cs = src\BlazorWebView\src\SharedSource\QueryStringHelper.cs
src\BlazorWebView\src\SharedSource\WebView2WebViewManager.cs = src\BlazorWebView\src\SharedSource\WebView2WebViewManager.cs
EndProjectSection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ public class AndroidWebKitWebViewManager : WebViewManager
// Using an IP address means that WebView doesn't wait for any DNS resolution,
// making it substantially faster. Note that this isn't real HTTP traffic, since
// we intercept all the requests within this origin.
private const string AppOrigin = "https://0.0.0.0/";
private static readonly string AppOrigin = $"https://{BlazorWebView.AppHostAddress}/";
private static readonly AUri AndroidAppOriginUri = AUri.Parse(AppOrigin)!;
private readonly BlazorWebViewHandler _blazorWebViewHandler;
private readonly AWebView _webview;

/// <summary>
Expand All @@ -31,11 +30,10 @@ public class AndroidWebKitWebViewManager : WebViewManager
/// <param name="dispatcher">A <see cref="Dispatcher"/> instance that can marshal calls to the required thread or sync context.</param>
/// <param name="fileProvider">Provides static content to the webview.</param>
/// <param name="hostPageRelativePath">Path to the host page within the <paramref name="fileProvider"/>.</param>
public AndroidWebKitWebViewManager(BlazorWebViewHandler blazorMauiWebViewHandler, AWebView webview, IServiceProvider services, Dispatcher dispatcher, IFileProvider fileProvider, JSComponentConfigurationStore jsComponents, string hostPageRelativePath)
public AndroidWebKitWebViewManager(AWebView webview!!, IServiceProvider services, Dispatcher dispatcher, IFileProvider fileProvider, JSComponentConfigurationStore jsComponents, string hostPageRelativePath)
: base(services, dispatcher, new Uri(AppOrigin), fileProvider, jsComponents, hostPageRelativePath)
{
_blazorWebViewHandler = blazorMauiWebViewHandler ?? throw new ArgumentNullException(nameof(blazorMauiWebViewHandler));
_webview = webview ?? throw new ArgumentNullException(nameof(webview));
_webview = webview;
}

/// <inheritdoc />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ private void StartWebViewCoreIfPossible()

var fileProvider = VirtualView.CreateFileProvider(contentRootDir);

_webviewManager = new AndroidWebKitWebViewManager(this, NativeView, Services!, ComponentsDispatcher, fileProvider, VirtualView.JSComponents, hostPageRelativePath);
_webviewManager = new AndroidWebKitWebViewManager(NativeView, Services!, ComponentsDispatcher, fileProvider, VirtualView.JSComponents, hostPageRelativePath);

if (RootComponents != null)
{
Expand Down
19 changes: 11 additions & 8 deletions src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ namespace Microsoft.AspNetCore.Components.WebView.Maui
{
internal class WebKitWebViewClient : WebViewClient
{
private const string AppOrigin = "https://0.0.0.0/";
// Using an IP address means that WebView doesn't wait for any DNS resolution,
// making it substantially faster. Note that this isn't real HTTP traffic, since
// we intercept all the requests within this origin.
private static readonly string AppOrigin = $"https://{BlazorWebView.AppHostAddress}/";

private readonly BlazorWebViewHandler? _webViewHandler;

public WebKitWebViewClient(BlazorWebViewHandler webViewHandler)
public WebKitWebViewClient(BlazorWebViewHandler webViewHandler!!)
{
_webViewHandler = webViewHandler ?? throw new ArgumentNullException(nameof(webViewHandler));
_webViewHandler = webViewHandler;
}

protected WebKitWebViewClient(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
Expand All @@ -34,7 +37,7 @@ public override bool ShouldOverrideUrlLoading(AWebView? view, IWebResourceReques
{
var uri = new Uri(requestUri);

if (uri.Host == "0.0.0.0" &&
if (uri.Host == BlazorWebView.AppHostAddress &&
view is not null &&
request is not null &&
request.IsRedirect &&
Expand All @@ -43,8 +46,8 @@ request is not null &&
view.LoadUrl(uri.ToString());
return true;
}
else if (uri.Host != "0.0.0.0" &&
_webViewHandler is not null &&
else if (uri.Host != BlazorWebView.AppHostAddress &&
_webViewHandler != null &&
_webViewHandler.ExternalLinkMode == ExternalLinkMode.OpenInExternalBrowser)
{
var intent = new Intent(Intent.ActionView, AUri.Parse(requestUri));
Expand Down Expand Up @@ -181,9 +184,9 @@ private class JavaScriptValueCallback : Java.Lang.Object, IValueCallback
{
private readonly Action _callback;

public JavaScriptValueCallback(Action callback)
public JavaScriptValueCallback(Action callback!!)
{
_callback = callback ?? throw new ArgumentNullException(nameof(callback));
_callback = callback;
}

public void OnReceiveValue(Java.Lang.Object? value)
Expand Down
11 changes: 9 additions & 2 deletions src/BlazorWebView/src/Maui/BlazorWebView.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebView;
using Microsoft.Extensions.FileProviders;

namespace Microsoft.AspNetCore.Components.WebView.Maui
{
public class BlazorWebView : Microsoft.Maui.Controls.View, IBlazorWebView
{
internal static readonly string AppHostAddress = "0.0.0.0";

private readonly JSComponentConfigurationStore _jSComponents = new();

public BlazorWebView()
Expand All @@ -19,6 +21,11 @@ public BlazorWebView()

public RootComponentsCollection RootComponents { get; }

/// <summary>
/// Specify whether links should be opened in the external
/// system default browser, or within the webview.
/// </summary>
/// <value>Defaults to opening links in the system default browser.</value>
public ExternalLinkMode ExternalLinkMode { get; set; } = ExternalLinkMode.OpenInExternalBrowser;

/// <inheritdoc/>
Expand Down
12 changes: 10 additions & 2 deletions src/BlazorWebView/src/Maui/BlazorWebViewHandler.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
using System.Linq;
using Microsoft.AspNetCore.Components.WebView;
using Microsoft.Maui;
using Microsoft.Maui.Handlers;

namespace Microsoft.AspNetCore.Components.WebView.Maui
{
public partial class BlazorWebViewHandler
{
public static PropertyMapper<IBlazorWebView, BlazorWebViewHandler> BlazorWebViewMapper = new(ViewMapper)
private static readonly PropertyMapper<IBlazorWebView, BlazorWebViewHandler> BlazorWebViewMapper = new(ViewMapper)
{
[nameof(IBlazorWebView.HostPage)] = MapHostPage,
[nameof(IBlazorWebView.RootComponents)] = MapRootComponents,
[nameof(IBlazorWebView.ExternalLinkMode)] = MapExternalLinkMode,
};

public BlazorWebViewHandler() : base(BlazorWebViewMapper)
Expand All @@ -28,7 +30,6 @@ public static void MapHostPage(BlazorWebViewHandler handler, IBlazorWebView webV
{
#if !NETSTANDARD
handler.HostPage = webView.HostPage;
handler.ExternalLinkMode = webView.ExternalLinkMode;
handler.StartWebViewCoreIfPossible();
#endif
}
Expand All @@ -37,6 +38,13 @@ public static void MapRootComponents(BlazorWebViewHandler handler, IBlazorWebVie
{
#if !NETSTANDARD
handler.RootComponents = webView.RootComponents;
handler.StartWebViewCoreIfPossible();
#endif
}

public static void MapExternalLinkMode(BlazorWebViewHandler handler, IBlazorWebView webView)
{
#if !NETSTANDARD
handler.ExternalLinkMode = webView.ExternalLinkMode;
handler.StartWebViewCoreIfPossible();
#endif
Expand Down
8 changes: 0 additions & 8 deletions src/BlazorWebView/src/Maui/ExternalLinkMode.cs

This file was deleted.

6 changes: 6 additions & 0 deletions src/BlazorWebView/src/Maui/IBlazorWebView.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebView;
using Microsoft.Extensions.FileProviders;
using Microsoft.Maui;

Expand All @@ -9,6 +10,11 @@ public interface IBlazorWebView : IView
string? HostPage { get; set; }
RootComponentsCollection RootComponents { get; }
JSComponentConfigurationStore JSComponents { get; }

/// <summary>
/// Specify whether links should be opened in the external
/// system default browser, or within the webview.
/// </summary>
ExternalLinkMode ExternalLinkMode { get; set; }

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ private void StartWebViewCoreIfPossible()
VirtualView.JSComponents,
hostPageRelativePath,
contentRootDir,
ExternalLinkMode);
this);

if (RootComponents != null)
{
Expand Down
46 changes: 19 additions & 27 deletions src/BlazorWebView/src/Maui/Windows/WinUIWebViewManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,23 @@ public class WinUIWebViewManager : WebView2WebViewManager
private readonly WebView2Control _webview;
private readonly string _hostPageRelativePath;
private readonly string _contentRootDir;
private readonly ExternalLinkMode _externalLinkMode;
private readonly BlazorWebViewHandler _blazorWebViewHandler;

public WinUIWebViewManager(
WebView2Control webview!!,
WebView2Control webview,
IServiceProvider services,
Dispatcher dispatcher,
IFileProvider fileProvider,
JSComponentConfigurationStore jsComponents,
string hostPageRelativePath,
string contentRootDir,
ExternalLinkMode externalLinkMode)
BlazorWebViewHandler blazorWebViewHandler)
: base(webview, services, dispatcher, fileProvider, jsComponents, hostPageRelativePath)
{
_webview = webview;
_hostPageRelativePath = hostPageRelativePath;
_contentRootDir = contentRootDir;
_externalLinkMode = externalLinkMode;

_webview.CoreWebView2Initialized += Webview_CoreWebView2Initialized;
_blazorWebViewHandler = blazorWebViewHandler;
}

protected override async Task HandleWebResourceRequest(CoreWebView2WebResourceRequestedEventArgs eventArgs)
Expand Down Expand Up @@ -105,35 +103,18 @@ protected override async Task HandleWebResourceRequest(CoreWebView2WebResourceRe
deferral.Complete();
}

protected override void QueueBlazorStart()
{
// In .NET MAUI we use autostart='false' for the Blazor script reference, so we start it up manually in this event
_webview.CoreWebView2.DOMContentLoaded += async (_, __) =>
{
await _webview.CoreWebView2!.ExecuteScriptAsync(@"
Blazor.start();
");
};
}

private void Webview_CoreWebView2Initialized(WebView2Control sender, UI.Xaml.Controls.CoreWebView2InitializedEventArgs args)
{
_webview.CoreWebView2.NavigationStarting += CoreWebView2_NavigationStarting;
_webview.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested;
}

private void CoreWebView2_NavigationStarting(CoreWebView2 sender, CoreWebView2NavigationStartingEventArgs args)
protected override void CoreWebView2_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs args)
{
if (Uri.TryCreate(args.Uri, UriKind.RelativeOrAbsolute, out var uri) &&
uri.Host != "0.0.0.0" &&
_externalLinkMode == ExternalLinkMode.OpenInExternalBrowser)
uri.Host != AppHostAddress &&
_blazorWebViewHandler.ExternalLinkMode == ExternalLinkMode.OpenInExternalBrowser)
{
_ = Launcher.LaunchUriAsync(uri);
args.Cancel = true;
}
}

private void CoreWebView2_NewWindowRequested(CoreWebView2 sender, CoreWebView2NewWindowRequestedEventArgs args)
protected override void CoreWebView2_NewWindowRequested(object sender, CoreWebView2NewWindowRequestedEventArgs args)
{
// Intercept _blank target <a> tags to always open in device browser
// regardless of ExternalLinkMode.OpenInWebview
Expand All @@ -143,5 +124,16 @@ private void CoreWebView2_NewWindowRequested(CoreWebView2 sender, CoreWebView2Ne
args.Handled = true;
}
}

protected override void QueueBlazorStart()
{
// In .NET MAUI we use autostart='false' for the Blazor script reference, so we start it up manually in this event
_webview.CoreWebView2.DOMContentLoaded += async (_, __) =>
{
await _webview.CoreWebView2!.ExecuteScriptAsync(@"
Blazor.start();
");
};
}
}
}
2 changes: 1 addition & 1 deletion src/BlazorWebView/src/Maui/iOS/BlazorWebViewHandler.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public partial class BlazorWebViewHandler : ViewHandler<IBlazorWebView, WKWebVie
{
private IOSWebViewManager? _webviewManager;

private const string AppOrigin = "app://0.0.0.0/";
internal static readonly string AppOrigin = $"app://{BlazorWebView.AppHostAddress}/";
private const string BlazorInitScript = @"
window.__receiveMessageCallbacks = [];
window.__dispatchMessageCallback = function(message) {
Expand Down
12 changes: 5 additions & 7 deletions src/BlazorWebView/src/Maui/iOS/IOSWebViewManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,14 @@ namespace Microsoft.AspNetCore.Components.WebView.Maui
{
public class IOSWebViewManager : WebViewManager
{
private const string AppOrigin = "app://0.0.0.0/";

private readonly BlazorWebViewHandler _blazorMauiWebViewHandler;
private readonly WKWebView _webview;

public IOSWebViewManager(BlazorWebViewHandler blazorMauiWebViewHandler, WKWebView webview, IServiceProvider services, Dispatcher dispatcher, IFileProvider fileProvider, JSComponentConfigurationStore jsComponents, string hostPageRelativePath)
: base(services, dispatcher, new Uri(AppOrigin), fileProvider, jsComponents, hostPageRelativePath)
public IOSWebViewManager(BlazorWebViewHandler blazorMauiWebViewHandler!!, WKWebView webview!!, IServiceProvider services, Dispatcher dispatcher, IFileProvider fileProvider, JSComponentConfigurationStore jsComponents, string hostPageRelativePath)
: base(services, dispatcher, new Uri(BlazorWebViewHandler.AppOrigin), fileProvider, jsComponents, hostPageRelativePath)
{
_blazorMauiWebViewHandler = blazorMauiWebViewHandler ?? throw new ArgumentNullException(nameof(blazorMauiWebViewHandler));
_webview = webview ?? throw new ArgumentNullException(nameof(webview));
_blazorMauiWebViewHandler = blazorMauiWebViewHandler;
_webview = webview;

InitializeWebView();
}
Expand Down Expand Up @@ -204,7 +202,7 @@ public override void DidReceiveServerRedirectForProvisionalNavigation(WKWebView
{
// We need to intercept the redirects to the app scheme because Safari will block them.
// We will handle these redirects through the Navigation Manager.
if (_currentUri?.Host == "0.0.0.0")
if (_currentUri?.Host == BlazorWebView.AppHostAddress)
{
var uri = _currentUri;
_currentUri = null;
Expand Down
21 changes: 21 additions & 0 deletions src/BlazorWebView/src/SharedSource/ExternalLinkMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Microsoft.AspNetCore.Components.WebView
{
/// <summary>
/// Link handling mode for anchor tags <![CDATA[<a>]]> within a Blazor WebView.
///
/// `_blank` target links will always open in the default browser
/// regardless of this setting.
/// </summary>
public enum ExternalLinkMode
{
/// <summary>
/// Opens anchor tags <![CDATA[<a>]]> in the system default browser.
/// </summary>
OpenInExternalBrowser,

/// <summary>
/// Opens anchor tags <![CDATA[<a>]]> in the WebView. This is not recommended.
/// </summary>
OpenInWebView
}
}
Loading

0 comments on commit 35f637e

Please sign in to comment.