Skip to content

Commit

Permalink
Add more logging for BlazorWebView (#12357)
Browse files Browse the repository at this point in the history
Fixes #9792
  • Loading branch information
Eilon authored and rmarinho committed Jan 27, 2023
1 parent 8a6e5a5 commit ee0ea01
Show file tree
Hide file tree
Showing 16 changed files with 247 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
<ProjectReference Include="..\WebViewAppShared\WebViewAppShared.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Debug" />
</ItemGroup>

<Import Project="..\..\src\WindowsForms\build\Microsoft.AspNetCore.Components.WebView.WindowsForms.targets" />

</Project>
7 changes: 7 additions & 0 deletions src/BlazorWebView/samples/BlazorWinFormsApp/Form1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebView.WindowsForms;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using WebViewAppShared;

namespace BlazorWinFormsApp
Expand All @@ -17,6 +18,12 @@ public partial class Form1 : Form
public Form1()
{
var services1 = new ServiceCollection();
services1.AddLogging(c =>
{
c.AddDebug();
// Enable maximum logging for BlazorWebView
c.AddFilter("Microsoft.AspNetCore.Components.WebView", LogLevel.Trace);
});
services1.AddWindowsFormsBlazorWebView();
#if DEBUG
services1.AddBlazorWebViewDeveloperTools();
Expand Down
4 changes: 4 additions & 0 deletions src/BlazorWebView/samples/BlazorWpfApp/BlazorWpfApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
<ProjectReference Include="..\WebViewAppShared\WebViewAppShared.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Debug" />
</ItemGroup>

<Import Project="..\..\src\Wpf\build\Microsoft.AspNetCore.Components.WebView.Wpf.targets" />

</Project>
7 changes: 7 additions & 0 deletions src/BlazorWebView/samples/BlazorWpfApp/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Windows;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using WebViewAppShared;

namespace BlazorWpfApp
Expand All @@ -18,6 +19,12 @@ public partial class MainWindow : Window
public MainWindow()
{
var services1 = new ServiceCollection();
services1.AddLogging(c =>
{
c.AddDebug();
// Enable maximum logging for BlazorWebView
c.AddFilter("Microsoft.AspNetCore.Components.WebView", LogLevel.Trace);
});
services1.AddWpfBlazorWebView();
#if DEBUG
services1.AddBlazorWebViewDeveloperTools();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
using System.Collections.Generic;
using System.IO;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using Android.Webkit;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using AUri = Android.Net.Uri;
using AWebView = Android.Webkit.WebView;

Expand All @@ -25,6 +25,7 @@ internal class AndroidWebKitWebViewManager : WebViewManager
private static readonly string AppOrigin = $"https://{BlazorWebView.AppHostAddress}/";
private static readonly Uri AppOriginUri = new(AppOrigin);
private static readonly AUri AndroidAppOriginUri = AUri.Parse(AppOrigin)!;
private readonly ILogger _logger;
private readonly AWebView _webview;
private readonly string _contentRootRelativeToAppRoot;

Expand All @@ -37,7 +38,8 @@ internal class AndroidWebKitWebViewManager : WebViewManager
/// <param name="fileProvider">Provides static content to the webview.</param>
/// <param name="contentRootRelativeToAppRoot">Path to the directory containing application content files.</param>
/// <param name="hostPageRelativePath">Path to the host page within the <paramref name="fileProvider"/>.</param>
public AndroidWebKitWebViewManager(AWebView webview, IServiceProvider services, Dispatcher dispatcher, IFileProvider fileProvider, JSComponentConfigurationStore jsComponents, string contentRootRelativeToAppRoot, string hostPageRelativePath)
/// <param name="logger">Logger to send log messages to.</param>
public AndroidWebKitWebViewManager(AWebView webview, IServiceProvider services, Dispatcher dispatcher, IFileProvider fileProvider, JSComponentConfigurationStore jsComponents, string contentRootRelativeToAppRoot, string hostPageRelativePath, ILogger logger)
: base(services, dispatcher, AppOriginUri, fileProvider, jsComponents, hostPageRelativePath)
{
ArgumentNullException.ThrowIfNull(webview);
Expand All @@ -50,13 +52,16 @@ public AndroidWebKitWebViewManager(AWebView webview, IServiceProvider services,
$"Please add all the required services by calling '{nameof(IServiceCollection)}.{nameof(BlazorWebViewServiceCollectionExtensions.AddMauiBlazorWebView)}' in the application startup code.");
}
#endif
_logger = logger;

_webview = webview;
_contentRootRelativeToAppRoot = contentRootRelativeToAppRoot;
}

/// <inheritdoc />
protected override void NavigateCore(Uri absoluteUri)
{
_logger.NavigatingToUri(absoluteUri);
_webview.LoadUrl(absoluteUri.AbsoluteUri);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using Android.Webkit;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Maui;
using Microsoft.Maui.Dispatching;
using Microsoft.Maui.Handlers;
Expand All @@ -18,8 +20,13 @@ public partial class BlazorWebViewHandler : ViewHandler<IBlazorWebView, AWebView
private AndroidWebKitWebViewManager? _webviewManager;
internal AndroidWebKitWebViewManager? WebviewManager => _webviewManager;

private ILogger? _logger;
internal ILogger Logger => _logger ??= Services!.GetService<ILogger<BlazorWebViewHandler>>() ?? NullLogger<BlazorWebViewHandler>.Instance;

protected override AWebView CreatePlatformView()
{
Logger.CreatingAndroidWebkitWebView();

#pragma warning disable CA1416, CA1412, CA1422 // Validate platform compatibility
var blazorAndroidWebView = new BlazorAndroidWebView(Context!)
{
Expand All @@ -46,6 +53,8 @@ protected override AWebView CreatePlatformView()
_webChromeClient = new BlazorWebChromeClient();
blazorAndroidWebView.SetWebChromeClient(_webChromeClient);

Logger.CreatedAndroidWebkitWebView();

return blazorAndroidWebView;
}

Expand Down Expand Up @@ -92,6 +101,8 @@ private void StartWebViewCoreIfPossible()
var contentRootDir = Path.GetDirectoryName(HostPage!) ?? string.Empty;
var hostPageRelativePath = Path.GetRelativePath(contentRootDir, HostPage!);

Logger.CreatingFileProvider(contentRootDir, hostPageRelativePath);

var fileProvider = VirtualView.CreateFileProvider(contentRootDir);

_webviewManager = new AndroidWebKitWebViewManager(
Expand All @@ -101,7 +112,8 @@ private void StartWebViewCoreIfPossible()
fileProvider,
VirtualView.JSComponents,
contentRootDir,
hostPageRelativePath);
hostPageRelativePath,
Logger);

StaticContentHotReloadManager.AttachToWebViewManagerIfEnabled(_webviewManager);

Expand All @@ -115,11 +127,14 @@ private void StartWebViewCoreIfPossible()
{
foreach (var rootComponent in RootComponents)
{
Logger.AddingRootComponent(rootComponent.ComponentType?.FullName ?? string.Empty, rootComponent.Selector ?? string.Empty, rootComponent.Parameters?.Count ?? 0);

// Since the page isn't loaded yet, this will always complete synchronously
_ = rootComponent.AddToWebViewManagerAsync(_webviewManager);
}
}

Logger.StartingInitialNavigation(VirtualView.StartPath);
_webviewManager.Navigate(VirtualView.StartPath);
}

Expand Down
13 changes: 13 additions & 0 deletions src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ private bool ShouldOverrideUrlLoadingCore(IWebResourceRequest? request)
// so we know we can safely invoke the UrlLoading event.
var callbackArgs = UrlLoadingEventArgs.CreateWithDefaultLoadingStrategy(uri, AppOriginUri);
_webViewHandler.UrlLoading(callbackArgs);
_webViewHandler.Logger.NavigationEvent(uri, callbackArgs.UrlLoadingStrategy);

if (callbackArgs.UrlLoadingStrategy == UrlLoadingStrategy.OpenExternally)
{
_webViewHandler.Logger.LaunchExternalBrowser(uri);
try
{
var intent = Intent.ParseUri(uri.OriginalString, IntentUriType.Scheme);
Expand Down Expand Up @@ -84,15 +86,23 @@ private bool ShouldOverrideUrlLoadingCore(IWebResourceRequest? request)
var allowFallbackOnHostPage = AppOriginUri.IsBaseOfPage(requestUri);
requestUri = QueryStringHelper.RemovePossibleQueryString(requestUri);

_webViewHandler?.Logger.HandlingWebRequest(requestUri);

if (requestUri != null &&
_webViewHandler != null &&
_webViewHandler.WebviewManager != null &&
_webViewHandler.WebviewManager.TryGetResponseContentInternal(requestUri, allowFallbackOnHostPage, out var statusCode, out var statusMessage, out var content, out var headers))
{
var contentType = headers["Content-Type"];

_webViewHandler?.Logger.ResponseContentBeingSent(requestUri, statusCode);

return new WebResourceResponse(contentType, "UTF-8", statusCode, statusMessage, headers, content);
}
else
{
_webViewHandler?.Logger.ReponseContentNotFound(requestUri ?? string.Empty);
}

return base.ShouldInterceptRequest(view, request);
}
Expand All @@ -111,6 +121,8 @@ public override void OnPageFinished(AWebView? view, string? url)

private void RunBlazorStartupScripts(AWebView view)
{
_webViewHandler?.Logger.RunningBlazorStartupScripts();

// Confirm Blazor hasn't already initialized
view.EvaluateJavascript(@"
(function() { return typeof(window.__BlazorStarted); })();
Expand Down Expand Up @@ -171,6 +183,7 @@ private void RunBlazorStartupScripts(AWebView view)
", new JavaScriptValueCallback(_ =>
{
// Done; no more action required
_webViewHandler?.Logger.BlazorStartupScriptsFinished();
}));
}));
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using Microsoft.AspNetCore.Components.WebView.WebView2;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Maui.Dispatching;
using Microsoft.Maui.Handlers;
using WebView2Control = Microsoft.UI.Xaml.Controls.WebView2;
Expand Down Expand Up @@ -56,11 +58,14 @@ private void StartWebViewCoreIfPossible()
throw new InvalidOperationException($"Can't start {nameof(BlazorWebView)} without native web view instance.");
}

var logger = Services!.GetService<ILogger<BlazorWebViewHandler>>() ?? NullLogger<BlazorWebViewHandler>.Instance;

// We assume the host page is always in the root of the content directory, because it's
// unclear there's any other use case. We can add more options later if so.
var contentRootDir = Path.GetDirectoryName(HostPage!) ?? string.Empty;
var hostPageRelativePath = Path.GetRelativePath(contentRootDir, HostPage!);

logger.CreatingFileProvider(contentRootDir, hostPageRelativePath);
var fileProvider = VirtualView.CreateFileProvider(contentRootDir);

_webviewManager = new WinUIWebViewManager(
Expand All @@ -71,18 +76,28 @@ private void StartWebViewCoreIfPossible()
VirtualView.JSComponents,
contentRootDir,
hostPageRelativePath,
this);
this,
logger);

StaticContentHotReloadManager.AttachToWebViewManagerIfEnabled(_webviewManager);

if (RootComponents != null)
{
foreach (var rootComponent in RootComponents)
{
if (rootComponent is null)
{
continue;
}

logger.AddingRootComponent(rootComponent.ComponentType?.FullName ?? string.Empty, rootComponent.Selector ?? string.Empty, rootComponent.Parameters?.Count ?? 0);

// Since the page isn't loaded yet, this will always complete synchronously
_ = rootComponent.AddToWebViewManagerAsync(_webviewManager);
}
}

logger.StartingInitialNavigation(VirtualView.StartPath);
_webviewManager.Navigate(VirtualView.StartPath);
}

Expand Down
21 changes: 19 additions & 2 deletions src/BlazorWebView/src/Maui/Windows/WinUIWebViewManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebView.WebView2;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Web.WebView2.Core;
using Windows.ApplicationModel;
using Windows.Storage.Streams;
Expand All @@ -22,6 +23,7 @@ internal class WinUIWebViewManager : WebView2WebViewManager
private readonly string _hostPageRelativePath;
private readonly string _contentRootRelativeToAppRoot;
private static readonly bool _isPackagedApp;
private readonly ILogger _logger;

static WinUIWebViewManager()
{
Expand All @@ -46,6 +48,7 @@ static WinUIWebViewManager()
/// <param name="contentRootRelativeToAppRoot">Path to the directory containing application content files.</param>
/// <param name="hostPagePathWithinFileProvider">Path to the host page within the <paramref name="fileProvider"/>.</param>
/// <param name="webViewHandler">The <see cref="BlazorWebViewHandler" />.</param>
/// <param name="logger">Logger to send log messages to.</param>
public WinUIWebViewManager(
WebView2Control webview,
IServiceProvider services,
Expand All @@ -54,9 +57,11 @@ public WinUIWebViewManager(
JSComponentConfigurationStore jsComponents,
string contentRootRelativeToAppRoot,
string hostPagePathWithinFileProvider,
BlazorWebViewHandler webViewHandler)
: base(webview, services, dispatcher, fileProvider, jsComponents, contentRootRelativeToAppRoot, hostPagePathWithinFileProvider, webViewHandler)
BlazorWebViewHandler webViewHandler,
ILogger logger)
: base(webview, services, dispatcher, fileProvider, jsComponents, contentRootRelativeToAppRoot, hostPagePathWithinFileProvider, webViewHandler, logger)
{
_logger = logger;
_webview = webview;
_hostPageRelativePath = hostPagePathWithinFileProvider;
_contentRootRelativeToAppRoot = contentRootRelativeToAppRoot;
Expand All @@ -77,13 +82,16 @@ protected override async Task HandleWebResourceRequest(CoreWebView2WebResourceRe

var requestUri = QueryStringHelper.RemovePossibleQueryString(eventArgs.Request.Uri);

_logger.HandlingWebRequest(requestUri);

// First, call into WebViewManager to see if it has a framework file for this request. It will
// fall back to an IFileProvider, but on WinUI it's always a NullFileProvider, so that will never
// return a file.
if (TryGetResponseContent(requestUri, allowFallbackOnHostPage, out var statusCode, out var statusMessage, out var content, out var headers)
&& statusCode != 404)
{
var headerString = GetHeaderString(headers);
_logger.ResponseContentBeingSent(requestUri, statusCode);
eventArgs.Response = _coreWebView2Environment!.CreateWebResourceResponse(content.AsRandomAccessStream(), statusCode, statusMessage, headerString);
}
else if (new Uri(requestUri) is Uri uri && AppOriginUri.IsBaseOf(uri))
Expand Down Expand Up @@ -130,12 +138,19 @@ protected override async Task HandleWebResourceRequest(CoreWebView2WebResourceRe
if (stream != null)
{
var headerString = GetHeaderString(headers);

_logger.ResponseContentBeingSent(requestUri, statusCode);

eventArgs.Response = _coreWebView2Environment!.CreateWebResourceResponse(
stream,
statusCode,
statusMessage,
headerString);
}
else
{
_logger.ReponseContentNotFound(requestUri);
}

async Task<IRandomAccessStream> CopyContentToRandomAccessStreamAsync(Stream content)
{
Expand All @@ -157,6 +172,8 @@ 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 (_, __) =>
{
_logger.CallingBlazorStart();

await _webview.CoreWebView2!.ExecuteScriptAsync(@"
Blazor.start();
");
Expand Down
Loading

0 comments on commit ee0ea01

Please sign in to comment.