From 8eba70e0045d85f2604bcd43e7bd5b51eb41883e Mon Sep 17 00:00:00 2001 From: Conor Breen Date: Tue, 21 Jun 2022 19:12:31 +0100 Subject: [PATCH] Fix for #5523 MauiWebView not loading local files on Windows (#7672) * Fix for #5523 MauiWebView not loading local files on Windows * Unpackaged app support for local HTML files. * Use property for path * Auto map/unmap virtual host for app dir when navigating to safe/unsafe URIs Co-authored-by: Conor Breen --- src/Core/src/Platform/Windows/MauiWebView.cs | 53 ++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) 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); }