diff --git a/Microsoft.Maui.sln b/Microsoft.Maui.sln index 054f8f34ed15..5e5024e8bcf2 100644 --- a/Microsoft.Maui.sln +++ b/Microsoft.Maui.sln @@ -198,10 +198,10 @@ 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\ExternalLinkNavigationEventArgs.cs = src\BlazorWebView\src\SharedSource\ExternalLinkNavigationEventArgs.cs - src\BlazorWebView\src\SharedSource\ExternalLinkNavigationPolicy.cs = src\BlazorWebView\src\SharedSource\ExternalLinkNavigationPolicy.cs src\BlazorWebView\src\SharedSource\QueryStringHelper.cs = src\BlazorWebView\src\SharedSource\QueryStringHelper.cs + src\BlazorWebView\src\SharedSource\UrlLoadingStrategy.cs = src\BlazorWebView\src\SharedSource\UrlLoadingStrategy.cs src\BlazorWebView\src\SharedSource\WebView2WebViewManager.cs = src\BlazorWebView\src\SharedSource\WebView2WebViewManager.cs + src\BlazorWebView\src\SharedSource\UrlLoadingEventArgs.cs = src\BlazorWebView\src\SharedSource\UrlLoadingEventArgs.cs EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks.Droid", "src\Core\tests\Benchmarks.Droid\Benchmarks.Droid.csproj", "{5B56A734-D53C-4635-A53E-F889FCFCDD66}" diff --git a/src/BlazorWebView/src/Maui/Android/BlazorWebChromeClient.cs b/src/BlazorWebView/src/Maui/Android/BlazorWebChromeClient.cs index 8384723132d0..840a2298e223 100644 --- a/src/BlazorWebView/src/Maui/Android/BlazorWebChromeClient.cs +++ b/src/BlazorWebView/src/Maui/Android/BlazorWebChromeClient.cs @@ -19,7 +19,7 @@ public override bool OnCreateWindow(Android.Webkit.WebView? view, bool isDialog, if (view?.Context is not null) { // Intercept _blank target tags to always open in device browser - // regardless of ExternalLinkMode.OpenInWebview + // regardless of UrlLoadingStrategy.OpenInWebview var requestUrl = view.GetHitTestResult().Extra; var intent = new Intent(Intent.ActionView, Uri.Parse(requestUrl)); view.Context.StartActivity(intent); diff --git a/src/BlazorWebView/src/Maui/Android/BlazorWebViewHandler.Android.cs b/src/BlazorWebView/src/Maui/Android/BlazorWebViewHandler.Android.cs index 2f28827a8f56..800ec6f49714 100644 --- a/src/BlazorWebView/src/Maui/Android/BlazorWebViewHandler.Android.cs +++ b/src/BlazorWebView/src/Maui/Android/BlazorWebViewHandler.Android.cs @@ -26,7 +26,7 @@ protected override BlazorAndroidWebView CreatePlatformView() #pragma warning restore 618 }; - // To allow overriding ExternalLinkMode.InsecureOpenInWebView and open links in browser with a _blank target + // To allow overriding UrlLoadingStrategy.OpenInWebView and open links in browser with a _blank target blazorAndroidWebView.Settings.SetSupportMultipleWindows(true); BlazorAndroidWebView.SetWebContentsDebuggingEnabled(enabled: DeveloperTools.Enabled); diff --git a/src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs b/src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs index 561e0f3fc54e..caf991765e2a 100644 --- a/src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs +++ b/src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs @@ -1,10 +1,9 @@ using System; -using System.IO; using Android.Content; using Android.Runtime; using Android.Webkit; +using Java.Net; using AWebView = Android.Webkit.WebView; -using AUri = Android.Net.Uri; namespace Microsoft.AspNetCore.Components.WebView.Maui { @@ -32,40 +31,41 @@ protected WebKitWebViewClient(IntPtr javaReference, JniHandleOwnership transfer) } public override bool ShouldOverrideUrlLoading(AWebView? view, IWebResourceRequest? request) + => ShouldOverrideUrlLoadingCore(request) || base.ShouldOverrideUrlLoading(view, request); + + private bool ShouldOverrideUrlLoadingCore(IWebResourceRequest? request) { - // Handle redirects to the app custom scheme by reloading the URL in the view. - // Handle navigation to external URLs using the system browser, unless overriden. - var requestUri = request?.Url?.ToString(); - if (Uri.TryCreate(requestUri, UriKind.RelativeOrAbsolute, out var uri)) + if (_webViewHandler is null || !Uri.TryCreate(request?.Url?.ToString(), UriKind.RelativeOrAbsolute, out var uri)) + { + return false; + } + + // This method never gets called for navigation to a new window ('_blank'), + // so we know we can safely invoke the UrlLoading event. + var callbackArgs = UrlLoadingEventArgs.CreateWithDefaultLoadingStrategy(uri, AppOriginUri); + _webViewHandler.UrlLoading?.Invoke(callbackArgs); + + if (callbackArgs.UrlLoadingStrategy == UrlLoadingStrategy.OpenExternally) { - if (uri.Host == BlazorWebView.AppHostAddress && - view is not null && - request is not null && - request.IsRedirect && - request.IsForMainFrame) + try + { + var intent = Intent.ParseUri(uri.OriginalString, IntentUriType.Scheme); + _webViewHandler.Context.StartActivity(intent); + } + catch (URISyntaxException) { - view.LoadUrl(uri.ToString()); - return true; + // This can occur if there is a problem with the URI formatting given its specified scheme. + // Other platforms will silently ignore formatting issues, so we do the same here. } - else if (uri.Host != BlazorWebView.AppHostAddress && _webViewHandler != null) + catch (ActivityNotFoundException) { - var callbackArgs = new ExternalLinkNavigationEventArgs(uri); - _webViewHandler.ExternalNavigationStarting?.Invoke(callbackArgs); - - if (callbackArgs.ExternalLinkNavigationPolicy == ExternalLinkNavigationPolicy.OpenInExternalBrowser) - { - var intent = new Intent(Intent.ActionView, AUri.Parse(requestUri)); - _webViewHandler.Context.StartActivity(intent); - } - - if (callbackArgs.ExternalLinkNavigationPolicy != ExternalLinkNavigationPolicy.InsecureOpenInWebView) - { - return true; - } + // Do nothing if there is no activity to handle the intent. This is consistent with the + // behavior on other platforms when a URL with an unknown scheme is clicked. } + return true; } - return base.ShouldOverrideUrlLoading(view, request); + return callbackArgs.UrlLoadingStrategy != UrlLoadingStrategy.OpenInWebView; } public override WebResourceResponse? ShouldInterceptRequest(AWebView? view, IWebResourceRequest? request) diff --git a/src/BlazorWebView/src/Maui/BlazorWebView.cs b/src/BlazorWebView/src/Maui/BlazorWebView.cs index 9512cde3674e..db366066b22f 100644 --- a/src/BlazorWebView/src/Maui/BlazorWebView.cs +++ b/src/BlazorWebView/src/Maui/BlazorWebView.cs @@ -34,7 +34,7 @@ public BlazorWebView() public RootComponentsCollection RootComponents { get; } /// - public event EventHandler? ExternalNavigationStarting; + public event EventHandler? UrlLoading; /// public virtual IFileProvider CreateFileProvider(string contentRootDir) @@ -43,9 +43,9 @@ public virtual IFileProvider CreateFileProvider(string contentRootDir) return ((BlazorWebViewHandler)(Handler!)).CreateFileProvider(contentRootDir); } - internal void NotifyExternalNavigationStarting(ExternalLinkNavigationEventArgs args) + internal void NotifyUrlLoading(UrlLoadingEventArgs args) { - ExternalNavigationStarting?.Invoke(this, args); + UrlLoading?.Invoke(this, args); } } } diff --git a/src/BlazorWebView/src/Maui/BlazorWebViewHandler.cs b/src/BlazorWebView/src/Maui/BlazorWebViewHandler.cs index 142e974d308e..7563a6593188 100644 --- a/src/BlazorWebView/src/Maui/BlazorWebViewHandler.cs +++ b/src/BlazorWebView/src/Maui/BlazorWebViewHandler.cs @@ -16,7 +16,7 @@ public partial class BlazorWebViewHandler { [nameof(IBlazorWebView.HostPage)] = MapHostPage, [nameof(IBlazorWebView.RootComponents)] = MapRootComponents, - [nameof(IBlazorWebView.ExternalNavigationStarting)] = MapNotifyExternalNavigationStarting, + [nameof(IBlazorWebView.UrlLoading)] = MapNotifyUrlLoading, }; /// @@ -63,23 +63,23 @@ public static void MapRootComponents(BlazorWebViewHandler handler, IBlazorWebVie } /// - /// Maps the property to the specified handler. + /// Maps the property to the specified handler. /// /// The . /// The . - public static void MapNotifyExternalNavigationStarting(BlazorWebViewHandler handler, IBlazorWebView webView) + public static void MapNotifyUrlLoading(BlazorWebViewHandler handler, IBlazorWebView webView) { #if !NETSTANDARD if (webView is BlazorWebView bwv) { - handler.ExternalNavigationStarting = bwv.NotifyExternalNavigationStarting; + handler.UrlLoading = bwv.NotifyUrlLoading; } #endif } #if !NETSTANDARD private string? HostPage { get; set; } - internal Action? ExternalNavigationStarting; + internal Action? UrlLoading; private RootComponentsCollection? _rootComponents; private RootComponentsCollection? RootComponents diff --git a/src/BlazorWebView/src/Maui/IBlazorWebView.cs b/src/BlazorWebView/src/Maui/IBlazorWebView.cs index 2edc8a22350e..6bf941b9ddd2 100644 --- a/src/BlazorWebView/src/Maui/IBlazorWebView.cs +++ b/src/BlazorWebView/src/Maui/IBlazorWebView.cs @@ -26,10 +26,10 @@ public interface IBlazorWebView : IView JSComponentConfigurationStore JSComponents { get; } /// - /// Allows customizing how external links are opened. - /// Opens external links in the system browser by default. + /// Allows customizing how links are opened. + /// By default, opens internal links in the webview and external links in an external app. /// - event EventHandler? ExternalNavigationStarting; + event EventHandler? UrlLoading; /// /// Creates a file provider for static assets used in the . The default implementation diff --git a/src/BlazorWebView/src/Maui/iOS/BlazorWebViewHandler.iOS.cs b/src/BlazorWebView/src/Maui/iOS/BlazorWebViewHandler.iOS.cs index 4f7486491d9f..9183c94543cd 100644 --- a/src/BlazorWebView/src/Maui/iOS/BlazorWebViewHandler.iOS.cs +++ b/src/BlazorWebView/src/Maui/iOS/BlazorWebViewHandler.iOS.cs @@ -20,7 +20,7 @@ public partial class BlazorWebViewHandler : ViewHandler decisionHandler) { - var callbackArgs = new ExternalLinkNavigationEventArgs(new Uri(navigationAction.Request.Url.ToString())); + var requestUrl = navigationAction.Request.Url; + UrlLoadingStrategy strategy; // TargetFrame is null for navigation to a new window (`_blank`) if (navigationAction.TargetFrame is null) { - // Open in a new browser window regardless of ExternalLinkNavigationPolicy - callbackArgs.ExternalLinkNavigationPolicy = ExternalLinkNavigationPolicy.OpenInExternalBrowser; - } - else if (callbackArgs.Uri.Host == BlazorWebView.AppHostAddress) - { - callbackArgs.ExternalLinkNavigationPolicy = ExternalLinkNavigationPolicy.InsecureOpenInWebView; + // Open in a new browser window regardless of UrlLoadingStrategy + strategy = UrlLoadingStrategy.OpenExternally; } else { - _webView.ExternalNavigationStarting?.Invoke(callbackArgs); + // Invoke the UrlLoading event to allow overriding the default link handling behavior + var uri = new Uri(requestUrl.ToString()); + var callbackArgs = UrlLoadingEventArgs.CreateWithDefaultLoadingStrategy(uri, BlazorWebViewHandler.AppOriginUri); + _webView.UrlLoading?.Invoke(callbackArgs); + strategy = callbackArgs.UrlLoadingStrategy; } - var url = new NSUrl(callbackArgs.Uri.ToString()); - - if (callbackArgs.ExternalLinkNavigationPolicy == ExternalLinkNavigationPolicy.OpenInExternalBrowser) + if (strategy == UrlLoadingStrategy.OpenExternally) { - UIApplication.SharedApplication.OpenUrl(url); + UIApplication.SharedApplication.OpenUrl(requestUrl); } - if (callbackArgs.ExternalLinkNavigationPolicy != ExternalLinkNavigationPolicy.InsecureOpenInWebView) + if (strategy != UrlLoadingStrategy.OpenInWebView) { // Cancel any further navigation as we've either opened the link in the external browser // or canceled the underlying navigation action. @@ -237,7 +236,7 @@ public override void DecidePolicy(WKWebView webView, WKNavigationAction navigati if (navigationAction.TargetFrame!.MainFrame) { - _currentUri = url; + _currentUri = requestUrl; } decisionHandler(WKNavigationActionPolicy.Allow); diff --git a/src/BlazorWebView/src/SharedSource/ExternalLinkNavigationEventArgs.cs b/src/BlazorWebView/src/SharedSource/ExternalLinkNavigationEventArgs.cs deleted file mode 100644 index 2b9ddd74f409..000000000000 --- a/src/BlazorWebView/src/SharedSource/ExternalLinkNavigationEventArgs.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; - -namespace Microsoft.AspNetCore.Components.WebView -{ - /// - /// Used to provide information about a link (]]>) clicked within a Blazor WebView. - /// - /// Anchor tags with target="_blank" will always open in the default - /// browser and the ExternalNavigationStarting event won't be called. - /// - /// - public class ExternalLinkNavigationEventArgs : EventArgs - { - /// - /// Initializes a new instance of . - /// - /// The external URI to be navigated to. - public ExternalLinkNavigationEventArgs(Uri uri) - { - Uri = uri; - } - - /// - /// Gets the external URI to be navigated to. - /// - public Uri Uri { get; } - - /// - /// The policy to use when opening external links from the webview. - /// - /// Defaults to opening links in an external browser. - /// - public ExternalLinkNavigationPolicy ExternalLinkNavigationPolicy { get; set; } = ExternalLinkNavigationPolicy.OpenInExternalBrowser; - } -} diff --git a/src/BlazorWebView/src/SharedSource/ExternalLinkNavigationPolicy.cs b/src/BlazorWebView/src/SharedSource/ExternalLinkNavigationPolicy.cs deleted file mode 100644 index 36e1fe4485ee..000000000000 --- a/src/BlazorWebView/src/SharedSource/ExternalLinkNavigationPolicy.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace Microsoft.AspNetCore.Components.WebView -{ - /// - /// External link handling policy for anchor tags ]]> within a Blazor WebView. - /// - /// Anchor tags with target="_blank" will always open in the default - /// browser and the ExternalNavigationStarting event won't be called. - /// - public enum ExternalLinkNavigationPolicy - { - /// - /// Allows navigation to external links using the system default browser. - /// This is the default navigation policy. - /// - OpenInExternalBrowser, - - /// - /// Allows navigation to external links within the Blazor WebView. - /// This navigation policy can introduce security concerns and should not be enabled unless you can ensure all external links are fully trusted. - /// - InsecureOpenInWebView, - - /// - /// Cancels the current navigation attempt to an external link. - /// - CancelNavigation - } -} diff --git a/src/BlazorWebView/src/SharedSource/UrlLoadingEventArgs.cs b/src/BlazorWebView/src/SharedSource/UrlLoadingEventArgs.cs new file mode 100644 index 000000000000..5bb0141a3491 --- /dev/null +++ b/src/BlazorWebView/src/SharedSource/UrlLoadingEventArgs.cs @@ -0,0 +1,45 @@ +using System; + +namespace Microsoft.AspNetCore.Components.WebView +{ + /// + /// Used to provide information about a link (]]>) clicked within a Blazor WebView. + /// + /// Anchor tags with target="_blank" will always open in the default + /// browser and the UrlLoading event won't be called. + /// + /// + public class UrlLoadingEventArgs : EventArgs + { + internal static UrlLoadingEventArgs CreateWithDefaultLoadingStrategy(Uri urlToLoad, Uri appOriginUri) + { + var strategy = appOriginUri.IsBaseOf(urlToLoad) ? + UrlLoadingStrategy.OpenInWebView : + UrlLoadingStrategy.OpenExternally; + + return new(urlToLoad, strategy); + } + + private UrlLoadingEventArgs(Uri url, UrlLoadingStrategy urlLoadingStrategy) + { + Url = url; + UrlLoadingStrategy = urlLoadingStrategy; + } + + /// + /// Gets the URL to be loaded. + /// + public Uri Url { get; } + + /// + /// The policy to use when loading links from the webview. + /// Defaults to unless has a host + /// matching the app origin, in which case the default becomes . + /// + /// This value should not be changed to for external links + /// unless you can ensure they are fully trusted. + /// + /// + public UrlLoadingStrategy UrlLoadingStrategy { get; set; } + } +} diff --git a/src/BlazorWebView/src/SharedSource/UrlLoadingStrategy.cs b/src/BlazorWebView/src/SharedSource/UrlLoadingStrategy.cs new file mode 100644 index 000000000000..ded4d608d11a --- /dev/null +++ b/src/BlazorWebView/src/SharedSource/UrlLoadingStrategy.cs @@ -0,0 +1,31 @@ +namespace Microsoft.AspNetCore.Components.WebView +{ + /// + /// URL loading strategy for anchor tags ]]> within a Blazor WebView. + /// + /// Anchor tags with target="_blank" will always open in the default + /// browser and the UrlLoading event won't be called. + /// + public enum UrlLoadingStrategy + { + /// + /// Allows loading URLs using an app determined by the system. + /// This is the default strategy for URLs with an external host. + /// + OpenExternally, + + /// + /// Allows loading URLs within the Blazor WebView. + /// This is the default strategy for URLs with a host matching the app origin. + /// + /// This strategy should not be used for external links unless you can ensure they are fully trusted. + /// + /// + OpenInWebView, + + /// + /// Cancels the current URL loading attempt. + /// + CancelLoad + } +} diff --git a/src/BlazorWebView/src/SharedSource/WebView2WebViewManager.cs b/src/BlazorWebView/src/SharedSource/WebView2WebViewManager.cs index 2ac10ac2bed0..c34c81790fed 100644 --- a/src/BlazorWebView/src/SharedSource/WebView2WebViewManager.cs +++ b/src/BlazorWebView/src/SharedSource/WebView2WebViewManager.cs @@ -59,12 +59,14 @@ public class WebView2WebViewManager : WebViewManager /// protected static readonly string AppOrigin = $"https://{AppHostAddress}/"; + private static readonly Uri AppOriginUri = new(AppOrigin); + private readonly WebView2Control _webview; private readonly Task _webviewReadyTask; #if WEBVIEW2_WINFORMS || WEBVIEW2_WPF private protected CoreWebView2Environment _coreWebView2Environment; - private readonly Action _externalNavigationStarting; + private readonly Action _urlLoading; private readonly BlazorWebViewDeveloperTools _developerTools; /// @@ -76,7 +78,7 @@ public class WebView2WebViewManager : WebViewManager /// Provides static content to the webview. /// Describes configuration for adding, removing, and updating root components from JavaScript code. /// Path to the host page within the . - /// Callback invoked when external navigation starts. + /// Callback invoked when a url is about to load. internal WebView2WebViewManager( WebView2Control webview!!, IServiceProvider services, @@ -84,8 +86,8 @@ internal WebView2WebViewManager( IFileProvider fileProvider, JSComponentConfigurationStore jsComponents, string hostPageRelativePath, - Action externalNavigationStarting) - : base(services, dispatcher, new Uri(AppOrigin), fileProvider, jsComponents, hostPageRelativePath) + Action urlLoading) + : base(services, dispatcher, AppOriginUri, fileProvider, jsComponents, hostPageRelativePath) { #if WEBVIEW2_WINFORMS @@ -105,7 +107,7 @@ internal WebView2WebViewManager( #endif _webview = webview; - _externalNavigationStarting = externalNavigationStarting; + _urlLoading = urlLoading; _developerTools = services.GetRequiredService(); // Unfortunately the CoreWebView2 can only be instantiated asynchronously. @@ -258,22 +260,22 @@ protected virtual void QueueBlazorStart() private void CoreWebView2_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs args) { - if (Uri.TryCreate(args.Uri, UriKind.RelativeOrAbsolute, out var uri) && uri.Host != AppHostAddress) + if (Uri.TryCreate(args.Uri, UriKind.RelativeOrAbsolute, out var uri)) { - var callbackArgs = new ExternalLinkNavigationEventArgs(uri); + var callbackArgs = UrlLoadingEventArgs.CreateWithDefaultLoadingStrategy(uri, AppOriginUri); #if WEBVIEW2_WINFORMS || WEBVIEW2_WPF - _externalNavigationStarting?.Invoke(callbackArgs); + _urlLoading?.Invoke(callbackArgs); #elif WEBVIEW2_MAUI - _blazorWebViewHandler.ExternalNavigationStarting?.Invoke(callbackArgs); + _blazorWebViewHandler.UrlLoading?.Invoke(callbackArgs); #endif - if (callbackArgs.ExternalLinkNavigationPolicy == ExternalLinkNavigationPolicy.OpenInExternalBrowser) + if (callbackArgs.UrlLoadingStrategy == UrlLoadingStrategy.OpenExternally) { LaunchUriInExternalBrowser(uri); } - args.Cancel = callbackArgs.ExternalLinkNavigationPolicy != ExternalLinkNavigationPolicy.InsecureOpenInWebView; + args.Cancel = callbackArgs.UrlLoadingStrategy != UrlLoadingStrategy.OpenInWebView; } } diff --git a/src/BlazorWebView/src/WindowsForms/BlazorWebView.cs b/src/BlazorWebView/src/WindowsForms/BlazorWebView.cs index 6ba6bf487c3b..a977485bb9de 100644 --- a/src/BlazorWebView/src/WindowsForms/BlazorWebView.cs +++ b/src/BlazorWebView/src/WindowsForms/BlazorWebView.cs @@ -118,7 +118,7 @@ public IServiceProvider Services /// [Category("Action")] [Description("Allows customizing how external links are opened. Opens external links in the system browser by default.")] - public EventHandler ExternalNavigationStarting; + public EventHandler UrlLoading; private void OnHostPagePropertyChanged() => StartWebViewCoreIfPossible(); @@ -170,7 +170,7 @@ private void StartWebViewCoreIfPossible() fileProvider, RootComponents.JSComponents, hostPageRelativePath, - (args) => ExternalNavigationStarting?.Invoke(this, args)); + (args) => UrlLoading?.Invoke(this, args)); foreach (var rootComponent in RootComponents) { diff --git a/src/BlazorWebView/src/Wpf/BlazorWebView.cs b/src/BlazorWebView/src/Wpf/BlazorWebView.cs index b04de9b7df42..252ba3a9e3b1 100644 --- a/src/BlazorWebView/src/Wpf/BlazorWebView.cs +++ b/src/BlazorWebView/src/Wpf/BlazorWebView.cs @@ -51,11 +51,11 @@ public class BlazorWebView : Control, IAsyncDisposable typeMetadata: new PropertyMetadata(OnServicesPropertyChanged)); /// - /// The backing store for the property. + /// The backing store for the property. /// - public static readonly DependencyProperty ExternalNavigationStartingProperty = DependencyProperty.Register( - name: nameof(ExternalNavigationStarting), - propertyType: typeof(EventHandler), + public static readonly DependencyProperty UrlLoadingProperty = DependencyProperty.Register( + name: nameof(UrlLoading), + propertyType: typeof(EventHandler), ownerType: typeof(BlazorWebView)); #endregion @@ -108,13 +108,13 @@ public string HostPage (RootComponentsCollection)GetValue(RootComponentsProperty); /// - /// Allows customizing how external links are opened. - /// Opens external links in the system browser by default. + /// Allows customizing how links are opened. + /// By default, opens internal links in the webview and external links in an external app. /// - public EventHandler ExternalNavigationStarting + public EventHandler UrlLoading { - get => (EventHandler)GetValue(ExternalNavigationStartingProperty); - set => SetValue(ExternalNavigationStartingProperty, value); + get => (EventHandler)GetValue(UrlLoadingProperty); + set => SetValue(UrlLoadingProperty, value); } /// @@ -197,7 +197,7 @@ private void StartWebViewCoreIfPossible() fileProvider, RootComponents.JSComponents, hostPageRelativePath, - (args) => ExternalNavigationStarting?.Invoke(this, args)); + (args) => UrlLoading?.Invoke(this, args)); foreach (var rootComponent in RootComponents) {