From 84830aac2313af735a786fa3284cddabbb12ae63 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 13 Jul 2026 10:04:17 +0000 Subject: [PATCH] Fix WebResource routing and harden initialization/security defaults --- README.md | 8 ++-- .../Classes.Startup/WinFormedgeApp.cs | 3 +- .../Classes.WebView/WebViewCore.cs | 46 +++++++++++++------ src/WinFormedge/README.md | 8 ++-- .../WebResource/base/WebResourceHandler.cs | 4 +- .../WebResource/base/WebResourceManager.cs | 19 ++++---- 6 files changed, 54 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 894dea6..84d00f5 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ First of all, you should create a WinForm Application by using default project t **1. Replace initialization code by using WinFormedge application initialization procedure.** -You should use `FormedgeApp` instead of `Application` class to initialize your WinForm application in the `program.cs` file. The `FormedgeApp` class is a builder for creating a WinFormedge application. It provides methods for configuring the application and running it. +You should use `WinFormedgeApp` instead of `Application` class to initialize your WinForm application in the `program.cs` file. The `WinFormedgeApp` class is a builder for creating a WinFormedge application. It provides methods for configuring the application and running it. ```csharp using WinFormedge; @@ -68,7 +68,7 @@ internal static class Program { ApplicationConfiguration.Initialize(); - var app = FormedgeApp.CreateBuilder() + var app = WinFormedgeApp.CreateAppBuilder() .UseDevTools() .UseWinFormedgeApp().Build(); @@ -77,13 +77,13 @@ internal static class Program } ``` -When the `FormedgeApp` class is created, it will automatically initialize the WebView2 environment and run the message loop. +When the `WinFormedgeApp` class is created, it will automatically initialize the WebView2 environment and run the message loop. **2. Create a AppStartup class.** The `AppStartup` class is the entry point of your WinFormedge application. It provides methods for configuring the application. You can override the `OnApplicationLaunched` method to perform any initialization tasks before the application starts. -And you must override the `OnApplicationStartup` method to create the main window of your application. If the `OnApplicationStartup` method returns values created by `StartupSettings` class, the `FormedgeApp` class will create the main window of your application. Otherwise if the `OnApplicationStartup` method returns `null` the application will be closed. +And you must override the `OnApplicationStartup` method to create the main window of your application. If the `OnApplicationStartup` method returns values created by `StartupSettings` class, the `WinFormedgeApp` class will create the main window of your application. Otherwise if the `OnApplicationStartup` method returns `null` the application will be closed. ```csharp using WinFormedge; diff --git a/src/WinFormedge/Classes.Startup/WinFormedgeApp.cs b/src/WinFormedge/Classes.Startup/WinFormedgeApp.cs index 5bc4d89..b51c1b5 100644 --- a/src/WinFormedge/Classes.Startup/WinFormedgeApp.cs +++ b/src/WinFormedge/Classes.Startup/WinFormedgeApp.cs @@ -242,7 +242,7 @@ public void Run() AreBrowserExtensionsEnabled = false, ExclusiveUserDataFolderAccess = false, AdditionalBrowserArguments = string.Empty, - EnableTrackingPrevention = false, + EnableTrackingPrevention = true, IsCustomCrashReportingEnabled = true, ReleaseChannels = CoreWebView2ReleaseChannels.Stable, ScrollBarStyle = FluentOverlayStyleScrollbar ? CoreWebView2ScrollbarStyle.FluentOverlay : CoreWebView2ScrollbarStyle.Default, @@ -309,4 +309,3 @@ public void Run() } } - diff --git a/src/WinFormedge/Classes.WebView/WebViewCore.cs b/src/WinFormedge/Classes.WebView/WebViewCore.cs index 31fda17..bc77ab1 100644 --- a/src/WinFormedge/Classes.WebView/WebViewCore.cs +++ b/src/WinFormedge/Classes.WebView/WebViewCore.cs @@ -20,6 +20,7 @@ internal partial class WebViewCore /// Holds the current WebView2 controller instance. /// private CoreWebView2Controller? _controller; + private Exception? _initializationException; /// /// Stores a deferred URL to navigate to after initialization. @@ -129,7 +130,7 @@ public string Url /// Gets the current WebView2 controller instance. /// /// Thrown if the controller is not initialized. - internal CoreWebView2Controller Controller => _controller ?? throw new NullReferenceException(nameof(Controller)); + internal CoreWebView2Controller Controller => _controller ?? throw new InvalidOperationException("WebView2 controller is not initialized.", _initializationException); /// /// Gets the current WebView2 environment instance. @@ -225,8 +226,10 @@ internal bool HostWndProc(ref Message m) /// Asynchronously creates and initializes the WebView2 controller and browser instance. /// Configures settings, event handlers, and resource management. /// - private async void CreateWebView2() + private async Task CreateWebView2Async() { + _initializationException = null; + var opts = WebViewEnvironment.CreateCoreWebView2ControllerOptions(); Environment.SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "--autoplay-policy=no-user-gesture-required"); @@ -262,7 +265,7 @@ private async void CreateWebView2() webview.Settings.IsZoomControlEnabled = false; webview.Settings.IsStatusBarEnabled = false; webview.Settings.IsSwipeNavigationEnabled = false; - webview.Settings.IsReputationCheckingRequired = false; + webview.Settings.IsReputationCheckingRequired = true; webview.Settings.IsPinchZoomEnabled = false; webview.Settings.IsNonClientRegionSupportEnabled = true; @@ -379,23 +382,34 @@ private void HandleSystemColorMode() /// /// The event sender. /// An that contains the event data. - private void HostHandleCreated(object? sender, EventArgs e) + private async void HostHandleCreated(object? sender, EventArgs e) { - if (Container.RecreatingHandle) + try { - if (_temporaryContainerControl == null) throw new NullReferenceException("Temporary container control is null."); + if (Container.RecreatingHandle) + { + if (_temporaryContainerControl == null) throw new NullReferenceException("Temporary container control is null."); - Controller.ParentWindow = Container.Handle; + if (Initialized) + { + Controller.ParentWindow = Container.Handle; + } - _temporaryContainerControl.Dispose(); - _temporaryContainerControl = null; + _temporaryContainerControl.Dispose(); + _temporaryContainerControl = null; + } + else + { + await CreateWebView2Async(); + } + + HandleSystemColorMode(); } - else + catch (Exception ex) { - CreateWebView2(); + _initializationException = ex; + WinFormedgeApp.Current.Startup?.OnApplicationException(ex); } - - HandleSystemColorMode(); } /// @@ -410,7 +424,11 @@ private void HostHandleDestroyed(object? sender, EventArgs e) { _temporaryContainerControl = new Control(); _temporaryContainerControl.CreateControl(); - Controller.ParentWindow = _temporaryContainerControl.Handle; + + if (Initialized) + { + Controller.ParentWindow = _temporaryContainerControl.Handle; + } } } diff --git a/src/WinFormedge/README.md b/src/WinFormedge/README.md index 16361b6..ae93501 100644 --- a/src/WinFormedge/README.md +++ b/src/WinFormedge/README.md @@ -24,7 +24,7 @@ The minimum supported operating system is Windows 10 version 1903 (May 2019 Upda **1. Replace initialization code by using WinFormedge application initialization procedure.** -You should use `FormedgeApp` instead of `Application` class to initialize your WinForm application in the `program.cs` file. The `FormedgeApp` class is a builder for creating a WinFormedge application. It provides methods for configuring the application and running it. +You should use `WinFormedgeApp` instead of `Application` class to initialize your WinForm application in the `program.cs` file. The `WinFormedgeApp` class is a builder for creating a WinFormedge application. It provides methods for configuring the application and running it. ```csharp using WinFormedge; @@ -38,7 +38,7 @@ internal static class Program { ApplicationConfiguration.Initialize(); - var app = FormedgeApp.CreateBuilder() + var app = WinFormedgeApp.CreateAppBuilder() .UseDevTools() .UseWinFormedgeApp() .Build(); @@ -48,14 +48,14 @@ internal static class Program } ``` -When the `FormedgeApp` class is created, it will automatically initialize the WebView2 environment and run the message loop. +When the `WinFormedgeApp` class is created, it will automatically initialize the WebView2 environment and run the message loop. **2. Create a AppStartup class.** The `AppStartup` class is the entry point of your WinFormedge application. It provides methods for configuring the application. You can override the `OnApplicationLaunched` method to perform any initialization tasks before the application starts. -And you must override the `OnApplicationStartup` method to create the main window of your application. If the `OnApplicationStartup` method returns values created by `StartupSettings` class, the `FormedgeApp` class will create the main window of your application. Otherwise if the `OnApplicationStartup` method returns `null` the application will be closed. +And you must override the `OnApplicationStartup` method to create the main window of your application. If the `OnApplicationStartup` method returns values created by `StartupSettings` class, the `WinFormedgeApp` class will create the main window of your application. Otherwise if the `OnApplicationStartup` method returns `null` the application will be closed. ```csharp using WinFormedge; diff --git a/src/WinFormedge/WebResource/base/WebResourceHandler.cs b/src/WinFormedge/WebResource/base/WebResourceHandler.cs index e3ecab4..2d92d36 100644 --- a/src/WinFormedge/WebResource/base/WebResourceHandler.cs +++ b/src/WinFormedge/WebResource/base/WebResourceHandler.cs @@ -977,9 +977,9 @@ internal void HandleRequest(CoreWebView2 webview, CoreWebView2WebResourceRequest args.Response = webview.Environment.CreateWebResourceResponse(response.ContentBody is null ? null : new ManagedStream(response.ContentBody), response.HttpStatus, StatusCodes.GetStatusPhrase(response.HttpStatus), headers); } - catch (Exception ex) + catch (Exception) { - args.Response = webview.Environment.CreateWebResourceResponse(null, StatusCodes.Status500InternalServerError, ex.Message, string.Empty); + args.Response = webview.Environment.CreateWebResourceResponse(null, StatusCodes.Status500InternalServerError, StatusCodes.GetStatusPhrase(StatusCodes.Status500InternalServerError), string.Empty); } //finally diff --git a/src/WinFormedge/WebResource/base/WebResourceManager.cs b/src/WinFormedge/WebResource/base/WebResourceManager.cs index 08735a5..2038869 100644 --- a/src/WinFormedge/WebResource/base/WebResourceManager.cs +++ b/src/WinFormedge/WebResource/base/WebResourceManager.cs @@ -77,7 +77,7 @@ private void CoreWebView2WebResourceRequested(object? sender, CoreWebView2WebRes matchedHandlers = matchedHandlers.Where(x => uri.AbsolutePath.StartsWith(x.Uri.AbsolutePath)); - var targetHandler = matchedHandlers.OrderBy(x => x.Uri.AbsolutePath.Length).FirstOrDefault(); + var targetHandler = matchedHandlers.OrderByDescending(x => x.Uri.AbsolutePath.Length).FirstOrDefault(); if (targetHandler == null) { @@ -151,17 +151,20 @@ public void RegisterWebResourceHander(WebResourceHandler handler) /// The host name of the handler to unregister. public void UnregisterWebResourceHander(string scheme, string hostName) { - var handler = Handlers.Find(x=>x.Scheme == scheme && x.HostName == hostName); + var handlers = Handlers + .Where(x => x.Scheme.Equals(scheme, StringComparison.InvariantCultureIgnoreCase) + && x.HostName.Equals(hostName, StringComparison.InvariantCultureIgnoreCase)) + .ToList(); - if (handler != null) + foreach (var handler in handlers) { Handlers.Remove(handler); - } - if (_initialized) - { - var url = GetFilterUrl(scheme, hostName); - _webView2!.RemoveWebResourceRequestedFilter(url + "*", CoreWebView2WebResourceContext.All); + if (_initialized) + { + var url = GetFilterUrl(handler.Scheme, handler.HostName); + _webView2!.RemoveWebResourceRequestedFilter(url + "*", handler.WebResourceContext); + } } } } \ No newline at end of file