diff --git a/Microsoft.Maui-dev.sln b/Microsoft.Maui-dev.sln
index efaad84182ac..a31db7a6b1ac 100644
--- a/Microsoft.Maui-dev.sln
+++ b/Microsoft.Maui-dev.sln
@@ -133,6 +133,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{A9C514B9
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.DeviceTests", "src\BlazorWebView\tests\DeviceTests\MauiBlazorWebView.DeviceTests.csproj", "{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.UnitTests", "src\BlazorWebView\tests\MauiBlazorWebView.UnitTests\MauiBlazorWebView.UnitTests.csproj", "{00E708AA-402D-4BB5-AD88-348274F8E1DF}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SharedSource", "SharedSource", "{4F2926C8-43AB-4328-A735-D9EAD699F81D}"
ProjectSection(SolutionItems) = preProject
src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs = src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs
@@ -463,6 +465,10 @@ Global
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}.Release|Any CPU.Build.0 = Release|Any CPU
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.Build.0 = Release|Any CPU
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
@@ -746,6 +752,7 @@ Global
{71FFE8BF-EBE4-4078-8484-86C6EA685D14} = {50C758FE-4E10-409A-94F5-A75480960864}
{A9C514B9-1EE2-4A12-8E8A-CE16D87545C3} = {1614D1A4-5C3D-4D5B-8C89-426E37A564EF}
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
{4F2926C8-43AB-4328-A735-D9EAD699F81D} = {ED7F28E0-D0AF-417D-983D-3D874EEE8554}
{5B56A734-D53C-4635-A53E-F889FCFCDD66} = {C564DDD6-DE79-45CD-88EA-3F690481572A}
{E8728693-3537-4007-A4DB-9F9634548755} = {E8AD265B-3C67-4640-AC58-A522F9FB3361}
diff --git a/Microsoft.Maui-mac.slnf b/Microsoft.Maui-mac.slnf
index 623e1571661a..57f6a7e0562b 100644
--- a/Microsoft.Maui-mac.slnf
+++ b/Microsoft.Maui-mac.slnf
@@ -11,6 +11,7 @@
"src\\BlazorWebView\\samples\\WebViewAppShared\\WebViewAppShared.csproj",
"src\\BlazorWebView\\src\\Maui\\Microsoft.AspNetCore.Components.WebView.Maui.csproj",
"src\\BlazorWebView\\tests\\DeviceTests\\MauiBlazorWebView.DeviceTests.csproj",
+ "src\\BlazorWebView\\tests\\MauiBlazorWebView.UnitTests\\MauiBlazorWebView.UnitTests.csproj",
"src\\Controls\\Foldable\\src\\Controls.Foldable.csproj",
"src\\Controls\\Maps\\src\\Controls.Maps.csproj",
"src\\Controls\\samples\\Controls.Sample.Profiling\\Maui.Controls.Sample.Profiling.csproj",
@@ -71,4 +72,4 @@
"src\\Workload\\Microsoft.NET.Sdk.Maui.Manifest\\Microsoft.NET.Sdk.Maui.Manifest.csproj"
]
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Maui-vscode.sln b/Microsoft.Maui-vscode.sln
index 3e88b3db593e..eb588bd623bc 100644
--- a/Microsoft.Maui-vscode.sln
+++ b/Microsoft.Maui-vscode.sln
@@ -125,6 +125,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{A9C514B9
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.DeviceTests", "src\BlazorWebView\tests\DeviceTests\MauiBlazorWebView.DeviceTests.csproj", "{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.UnitTests", "src\BlazorWebView\tests\MauiBlazorWebView.UnitTests\MauiBlazorWebView.UnitTests.csproj", "{00E708AA-402D-4BB5-AD88-348274F8E1DF}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SharedSource", "SharedSource", "{4F2926C8-43AB-4328-A735-D9EAD699F81D}"
ProjectSection(SolutionItems) = preProject
src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs = src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs
@@ -414,6 +416,10 @@ Global
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}.Release|Any CPU.Build.0 = Release|Any CPU
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.Build.0 = Release|Any CPU
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
@@ -659,6 +665,7 @@ Global
{71FFE8BF-EBE4-4078-8484-86C6EA685D14} = {50C758FE-4E10-409A-94F5-A75480960864}
{A9C514B9-1EE2-4A12-8E8A-CE16D87545C3} = {1614D1A4-5C3D-4D5B-8C89-426E37A564EF}
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
{4F2926C8-43AB-4328-A735-D9EAD699F81D} = {ED7F28E0-D0AF-417D-983D-3D874EEE8554}
{5B56A734-D53C-4635-A53E-F889FCFCDD66} = {C564DDD6-DE79-45CD-88EA-3F690481572A}
{E8728693-3537-4007-A4DB-9F9634548755} = {E8AD265B-3C67-4640-AC58-A522F9FB3361}
diff --git a/Microsoft.Maui-windows.slnf b/Microsoft.Maui-windows.slnf
index 4ed4c36e2225..00903f73421b 100644
--- a/Microsoft.Maui-windows.slnf
+++ b/Microsoft.Maui-windows.slnf
@@ -15,6 +15,7 @@
"src\\BlazorWebView\\src\\WindowsForms\\Microsoft.AspNetCore.Components.WebView.WindowsForms.csproj",
"src\\BlazorWebView\\src\\Wpf\\Microsoft.AspNetCore.Components.WebView.Wpf.csproj",
"src\\BlazorWebView\\tests\\DeviceTests\\MauiBlazorWebView.DeviceTests.csproj",
+ "src\\BlazorWebView\\tests\\MauiBlazorWebView.UnitTests\\MauiBlazorWebView.UnitTests.csproj",
"src\\Controls\\Foldable\\src\\Controls.Foldable.csproj",
"src\\Controls\\Maps\\src\\Controls.Maps.csproj",
"src\\Controls\\samples\\Controls.Sample.Profiling\\Maui.Controls.Sample.Profiling.csproj",
@@ -88,4 +89,4 @@
"src\\Workload\\Microsoft.NET.Sdk.Maui.Manifest\\Microsoft.NET.Sdk.Maui.Manifest.csproj"
]
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Maui.LegacyControlGallery.sln b/Microsoft.Maui.LegacyControlGallery.sln
index e555b8990ce5..5a44235aa330 100644
--- a/Microsoft.Maui.LegacyControlGallery.sln
+++ b/Microsoft.Maui.LegacyControlGallery.sln
@@ -132,6 +132,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{A9C514B9
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.DeviceTests", "src\BlazorWebView\tests\DeviceTests\MauiBlazorWebView.DeviceTests.csproj", "{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.UnitTests", "src\BlazorWebView\tests\MauiBlazorWebView.UnitTests\MauiBlazorWebView.UnitTests.csproj", "{00E708AA-402D-4BB5-AD88-348274F8E1DF}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SharedSource", "SharedSource", "{4F2926C8-43AB-4328-A735-D9EAD699F81D}"
ProjectSection(SolutionItems) = preProject
src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs = src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs
@@ -456,6 +458,10 @@ Global
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}.Release|Any CPU.Build.0 = Release|Any CPU
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.Build.0 = Release|Any CPU
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
@@ -737,6 +743,7 @@ Global
{71FFE8BF-EBE4-4078-8484-86C6EA685D14} = {50C758FE-4E10-409A-94F5-A75480960864}
{A9C514B9-1EE2-4A12-8E8A-CE16D87545C3} = {1614D1A4-5C3D-4D5B-8C89-426E37A564EF}
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
{4F2926C8-43AB-4328-A735-D9EAD699F81D} = {ED7F28E0-D0AF-417D-983D-3D874EEE8554}
{5B56A734-D53C-4635-A53E-F889FCFCDD66} = {C564DDD6-DE79-45CD-88EA-3F690481572A}
{E8728693-3537-4007-A4DB-9F9634548755} = {E8AD265B-3C67-4640-AC58-A522F9FB3361}
diff --git a/Microsoft.Maui.sln b/Microsoft.Maui.sln
index 37c133515923..f3fd76fdc61d 100644
--- a/Microsoft.Maui.sln
+++ b/Microsoft.Maui.sln
@@ -140,6 +140,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{A9C514B9
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.DeviceTests", "src\BlazorWebView\tests\DeviceTests\MauiBlazorWebView.DeviceTests.csproj", "{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiBlazorWebView.UnitTests", "src\BlazorWebView\tests\MauiBlazorWebView.UnitTests\MauiBlazorWebView.UnitTests.csproj", "{00E708AA-402D-4BB5-AD88-348274F8E1DF}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SharedSource", "SharedSource", "{4F2926C8-43AB-4328-A735-D9EAD699F81D}"
ProjectSection(SolutionItems) = preProject
src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs = src\BlazorWebView\src\SharedSource\AutoCloseOnReadCompleteStream.cs
@@ -469,6 +471,10 @@ Global
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}.Release|Any CPU.Build.0 = Release|Any CPU
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF}.Release|Any CPU.Build.0 = Release|Any CPU
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B56A734-D53C-4635-A53E-F889FCFCDD66}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
@@ -751,6 +757,7 @@ Global
{71FFE8BF-EBE4-4078-8484-86C6EA685D14} = {50C758FE-4E10-409A-94F5-A75480960864}
{A9C514B9-1EE2-4A12-8E8A-CE16D87545C3} = {1614D1A4-5C3D-4D5B-8C89-426E37A564EF}
{5FEA7500-0ACE-4C26-9A7B-2EB3958CBBC6} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
+ {00E708AA-402D-4BB5-AD88-348274F8E1DF} = {A9C514B9-1EE2-4A12-8E8A-CE16D87545C3}
{4F2926C8-43AB-4328-A735-D9EAD699F81D} = {ED7F28E0-D0AF-417D-983D-3D874EEE8554}
{5B56A734-D53C-4635-A53E-F889FCFCDD66} = {C564DDD6-DE79-45CD-88EA-3F690481572A}
{E8728693-3537-4007-A4DB-9F9634548755} = {E8AD265B-3C67-4640-AC58-A522F9FB3361}
diff --git a/eng/cake/dotnet.cake b/eng/cake/dotnet.cake
index 09b7378ab229..86596fe5e78e 100644
--- a/eng/cake/dotnet.cake
+++ b/eng/cake/dotnet.cake
@@ -274,6 +274,7 @@ Task("dotnet-test")
"**/Resizetizer.UnitTests.csproj",
"**/Graphics.Tests.csproj",
"**/Compatibility.Core.UnitTests.csproj",
+ "**/MauiBlazorWebView.UnitTests.csproj",
};
var success = true;
diff --git a/eng/helix.proj b/eng/helix.proj
index 565ce270a50c..a6cae39a8567 100644
--- a/eng/helix.proj
+++ b/eng/helix.proj
@@ -37,6 +37,7 @@
+
diff --git a/src/BlazorWebView/src/Maui/Extensions/UriExtensions.cs b/src/BlazorWebView/src/Maui/Extensions/UriExtensions.cs
index 3767e19237c5..7e8b137b2fc8 100644
--- a/src/BlazorWebView/src/Maui/Extensions/UriExtensions.cs
+++ b/src/BlazorWebView/src/Maui/Extensions/UriExtensions.cs
@@ -1,20 +1,27 @@
using System;
using System.IO;
-namespace Microsoft.AspNetCore.Components.WebView.Maui
+namespace Microsoft.AspNetCore.Components.WebView.Maui;
+
+internal static class UriExtensions
{
- internal static class UriExtensions
+ internal static bool IsBaseOfPage(this Uri baseUri, string? uriString)
{
- internal static bool IsBaseOfPage(this Uri baseUri, string? uriString)
+ if (string.IsNullOrWhiteSpace(uriString))
{
- if (Path.HasExtension(uriString))
- {
- // If the path ends in a file extension, it's not referring to a page.
- return false;
- }
+ return false;
+ }
- var uri = new Uri(uriString!);
- return baseUri.IsBaseOf(uri);
+ if (!Uri.TryCreate(uriString, UriKind.Absolute, out var uri))
+ {
+ return false;
}
+
+ if (Path.HasExtension(uri.GetComponents(UriComponents.Path, UriFormat.Unescaped)))
+ {
+ return false;
+ }
+
+ return baseUri.IsBaseOf(uri);
}
}
diff --git a/src/BlazorWebView/src/Maui/Properties/AssemblyInfo.cs b/src/BlazorWebView/src/Maui/Properties/AssemblyInfo.cs
index 75fc9e1e0adb..6ad8b3a8aa4b 100644
--- a/src/BlazorWebView/src/Maui/Properties/AssemblyInfo.cs
+++ b/src/BlazorWebView/src/Maui/Properties/AssemblyInfo.cs
@@ -1,6 +1,9 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Internals;
+using System.Runtime.CompilerServices;
+
[assembly: Preserve]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/dotnet/2021/maui", "Microsoft.AspNetCore.Components.WebView.Maui")]
+[assembly: InternalsVisibleTo("Microsoft.Maui.MauiBlazorWebView.UnitTests")]
diff --git a/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/MauiBlazorWebView.UnitTests.csproj b/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/MauiBlazorWebView.UnitTests.csproj
new file mode 100644
index 000000000000..0f164bfb04ea
--- /dev/null
+++ b/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/MauiBlazorWebView.UnitTests.csproj
@@ -0,0 +1,26 @@
+
+
+
+ $(_MauiDotNetTfm)
+ enable
+ Microsoft.Maui.MauiBlazorWebView.UnitTests
+ Microsoft.Maui.MauiBlazorWebView.UnitTests
+ enable
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/UriExtensions_Tests.cs b/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/UriExtensions_Tests.cs
new file mode 100644
index 000000000000..33ff4c061911
--- /dev/null
+++ b/src/BlazorWebView/tests/MauiBlazorWebView.UnitTests/UriExtensions_Tests.cs
@@ -0,0 +1,81 @@
+using Microsoft.AspNetCore.Components.WebView.Maui;
+
+namespace Microsoft.Maui.MauiBlazorWebView.UnitTests;
+
+public class UriExtensions_Tests
+{
+ private readonly Uri _baseUri = new("https://example.com/");
+
+ [Theory]
+ [InlineData("https://example.com/page", true)]
+ [InlineData("page/subpage", false)]
+ [InlineData("this is not a uri!", false)]
+ [InlineData("https://example.com/", true)]
+ [InlineData("https://example.com/page/", true)]
+ [InlineData("https://example.com/page?weight=62.5", true)]
+ [InlineData("https://example.com/page#section.1", true)]
+ [InlineData("https://example.com/file.txt", false)]
+ [InlineData("https://example.com/page.json?foo=bar", false)]
+ [InlineData("ftp://example.com/page", false)]
+ [InlineData("/relative/path", false)]
+ [InlineData("", false)]
+ [InlineData(null, false)]
+ [InlineData("https://example.com/test", true)]
+ [InlineData("https://example.com/folder/subfolder/", true)]
+ [InlineData("https://example.com/folder/file.exe", false)]
+ [InlineData("https://subdomain.example.com/page", false)]
+ [InlineData("https://example.com/path/with/.dot/segment", true)]
+ [InlineData("https://example.com/path/with space", true)]
+ [InlineData("https://example.com/path/with%20encoded%20space", true)]
+ [InlineData("https://example.com/page?param=value¶m2=value2", true)]
+ [InlineData("https://example.com/page.html", false)]
+ [InlineData("HTTPS://EXAMPLE.COM/PAGE", true)]
+ [InlineData("https://subdomain.example.com/", false)]
+ [InlineData("https://subdomain.example.com/page/", false)]
+ [InlineData("https://subdomain.example.com/page?weight=62.5", false)]
+ [InlineData("https://subdomain.example.com/page#section.1", false)]
+ [InlineData("https://subdomain.example.com/file.txt", false)]
+ [InlineData("https://subdomain.example.com/page.json?foo=bar", false)]
+ [InlineData("ftp://subdomain.example.com/page", false)]
+ [InlineData("https://subdomain.example.com/test", false)]
+ [InlineData("https://subdomain.example.com/folder/subfolder/", false)]
+ [InlineData("https://subdomain.example.com/folder/file.exe", false)]
+ [InlineData("https://subdomain.example.com/path/with/.dot/segment", false)]
+ [InlineData("https://subdomain.example.com/path/with space", false)]
+ [InlineData("https://subdomain.example.com/path/with%20encoded%20space", false)]
+ [InlineData("https://subdomain.example.com/page?param=value¶m2=value2", false)]
+ [InlineData("https://subdomain.example.com/page.html", false)]
+ [InlineData("HTTPS://SUBDOMAIN.EXAMPLE.COM/PAGE", false)]
+ public void IsBaseOfPage_HandlesVariousUris(string? uriString, bool expected)
+ {
+ var result = _baseUri.IsBaseOfPage(uriString);
+ Assert.Equal(expected, result);
+ }
+
+ // Regression test for https://github.com/dotnet/maui/issues/25689
+ // A URL with a dot in the query parameter (e.g. ?weight=62.5) must not be
+ // treated as a file-extension path and must be allowed to fall back to the host page.
+ [Fact]
+ public void IsBaseOfPage_DoesNotTreatDotInQueryAsExtension()
+ {
+ var baseUri = new Uri("https://example.com");
+ var urlWithDotInQuery = "https://example.com/customer?weight=62.5";
+ Assert.True(baseUri.IsBaseOfPage(urlWithDotInQuery));
+ }
+
+ // Regression tests using the actual BlazorWebView platform app origins (https://github.com/dotnet/maui/issues/25689).
+ // Android/Windows use https://0.0.0.1/ and iOS/MacCatalyst use app://0.0.0.1/ as the host origin,
+ // so the original ?weight=62.5 bug must be verified against those real origins, not just a generic host.
+ [Theory]
+ [InlineData("https://0.0.0.1/", "https://0.0.0.1/customer?weight=62.5", true)] // Android/Windows: dot in query
+ [InlineData("https://0.0.0.1/", "https://0.0.0.1/customer#section.1", true)] // Android/Windows: dot in fragment
+ [InlineData("https://0.0.0.1/", "https://0.0.0.1/customer.json", false)] // Android/Windows: real file extension
+ [InlineData("app://0.0.0.1/", "app://0.0.0.1/customer?weight=62.5", true)] // iOS/MacCatalyst: dot in query
+ [InlineData("app://0.0.0.1/", "app://0.0.0.1/customer#section.1", true)] // iOS/MacCatalyst: dot in fragment
+ [InlineData("app://0.0.0.1/", "app://0.0.0.1/customer.json", false)] // iOS/MacCatalyst: real file extension
+ public void IsBaseOfPage_HandlesPlatformAppOrigins(string baseUri, string uriString, bool expected)
+ {
+ var result = new Uri(baseUri).IsBaseOfPage(uriString);
+ Assert.Equal(expected, result);
+ }
+}