diff --git a/src/Core/src/Platform/Windows/MauiWebView.cs b/src/Core/src/Platform/Windows/MauiWebView.cs
index 2880166c15d9..a4028f258c39 100644
--- a/src/Core/src/Platform/Windows/MauiWebView.cs
+++ b/src/Core/src/Platform/Windows/MauiWebView.cs
@@ -1,15 +1,39 @@
using System;
using System.Diagnostics;
using System.Text.RegularExpressions;
+using Microsoft.Maui.ApplicationModel;
using Microsoft.UI.Xaml.Controls;
+using Windows.ApplicationModel;
namespace Microsoft.Maui.Platform
{
public class MauiWebView : WebView2, IWebViewDelegate
{
+ public MauiWebView()
+ {
+ NavigationStarting += (sender, args) =>
+ {
+ // Auto map local virtual app dir host, e.g. if navigating back to local site from a link to an external site
+ if (args?.Uri?.ToLowerInvariant().StartsWith(LocalScheme.TrimEnd('/').ToLowerInvariant()) == true)
+ {
+ CoreWebView2.SetVirtualHostNameToFolderMapping(
+ LocalHostName,
+ ApplicationPath,
+ Web.WebView2.Core.CoreWebView2HostResourceAccessKind.Allow);
+ }
+ // Auto unmap local virtual app dir host if navigating to any other potentially unsafe domain
+ else
+ {
+ CoreWebView2.ClearVirtualHostNameToFolderMapping(LocalHostName);
+ }
+ };
+ }
+
WebView2? _internalWebView;
- const string LocalScheme = "ms-appx-web:///";
+ // Arbitrary local host name for virtual folder mapping
+ const string LocalHostName = "appdir";
+ const string LocalScheme = $"https://{LocalHostName}/";
// Script to insert a tag into an HTML document
const string BaseInsertionScript = @"
@@ -19,11 +43,19 @@ public class MauiWebView : WebView2, IWebViewDelegate
head.innerHTML = 'baseTag' + head.innerHTML;
}";
+ // Allow for packaged/unpackaged app support
+ string ApplicationPath => AppInfoUtils.IsPackagedApp
+ ? Package.Current.InstalledLocation.Path
+ : AppContext.BaseDirectory;
+
public async void LoadHtml(string? html, string? baseUrl)
{
+ var mapBaseDirectory = false;
+
if (string.IsNullOrEmpty(baseUrl))
{
baseUrl = LocalScheme;
+ mapBaseDirectory = true;
}
// Generate a base tag for the document
@@ -36,7 +68,7 @@ public async void LoadHtml(string? html, string? baseUrl)
_internalWebView = new WebView2();
// TODO: For now, the CoreWebView2 won't be created without either setting Source or
- // calling EnsureCoreWebView2Async().
+ // calling EnsureCoreWebView2Async().
await _internalWebView.EnsureCoreWebView2Async();
// When the 'navigation' to the original HTML string is done, we can modify it to include our tag
@@ -55,6 +87,14 @@ public async void LoadHtml(string? html, string? baseUrl)
await EnsureCoreWebView2Async();
+ if (mapBaseDirectory)
+ {
+ CoreWebView2.SetVirtualHostNameToFolderMapping(
+ LocalHostName,
+ ApplicationPath,
+ Web.WebView2.Core.CoreWebView2HostResourceAccessKind.Allow);
+ }
+
// Set the HTML for the 'real' WebView to the updated HTML
NavigateToString(!string.IsNullOrEmpty(htmlWithBaseTag) ? htmlWithBaseTag : html);
@@ -66,12 +106,19 @@ public async void LoadHtml(string? html, string? baseUrl)
_internalWebView.NavigateToString(html);
}
- public void LoadUrl(string? url)
+ public async void LoadUrl(string? url)
{
Uri uri = new Uri(url ?? string.Empty, UriKind.RelativeOrAbsolute);
if (!uri.IsAbsoluteUri)
{
+ await EnsureCoreWebView2Async();
+
+ CoreWebView2.SetVirtualHostNameToFolderMapping(
+ LocalHostName,
+ ApplicationPath,
+ Web.WebView2.Core.CoreWebView2HostResourceAccessKind.Allow);
+
uri = new Uri(LocalScheme + url, UriKind.RelativeOrAbsolute);
}