Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 16 additions & 14 deletions src/InfiniFrame.BlazorWebView/InfiniFrameWebViewManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,8 @@ protected override void NavigateCore(Uri absoluteUri) {
}

protected override void SendMessage(string message) {
while (!_channel.Writer.TryWrite(message)) {
Thread.Sleep(200);
}
if (_channel.Writer.TryWrite(message)) return;
LazyLogger.Value?.LogDebug("Skipping WebView message because the message channel is closed.");
}

private async Task MessagePump() {
Expand All @@ -253,20 +252,23 @@ private async Task MessagePump() {
}

protected override async ValueTask DisposeAsyncCore() {
try { _channel.Writer.Complete(); }
catch (ChannelClosedException ex) {
LazyLogger.Value?.LogDebug(ex, "Channel was already closed during dispose.");
}

try {
await _messagePumpTask.WaitAsync(TimeSpan.FromSeconds(5));
}
catch (TimeoutException) {
LazyLogger.Value?.LogWarning(
"Timed out while waiting for WebView message pump shutdown.");
await base.DisposeAsyncCore();
}
finally {
try { _channel.Writer.Complete(); }
catch (ChannelClosedException ex) {
LazyLogger.Value?.LogDebug(ex, "Channel was already closed during dispose.");
}

await base.DisposeAsyncCore();
try {
await _messagePumpTask.WaitAsync(TimeSpan.FromSeconds(5));
}
catch (TimeoutException) {
LazyLogger.Value?.LogWarning(
"Timed out while waiting for WebView message pump shutdown.");
}
}
}

private static bool IsNonFatalException(Exception exception)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// ---------------------------------------------------------------------------------------------------------------------
// Imports
// ---------------------------------------------------------------------------------------------------------------------
using InfiniFrame;
using InfiniFrame.BlazorWebView;
using InfiniFrameTests.Shared;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;
using NSubstitute;

namespace InfiniFrameTests.BlazorWebView;

// ---------------------------------------------------------------------------------------------------------------------
// Code
// ---------------------------------------------------------------------------------------------------------------------
public class InfiniFrameWebViewManagerTests {
private sealed class TestableInfiniFrameWebViewManager(
IInfiniFrameWindowBuilder builder,
IServiceProvider provider,
Dispatcher dispatcher,
IFileProvider fileProvider,
JSComponentConfigurationStore jsComponents,
IOptions<InfiniFrameBlazorAppConfiguration> config
) : InfiniFrameWebViewManager(builder, provider, dispatcher, fileProvider, jsComponents, config) {
public void SendMessageForTest(string message) => SendMessage(message);
}

[Test]
[Timeout(TimeoutUtility.DefaultTimeout)]
public async Task SendMessage_AfterDispose_ShouldReturnPromptly(CancellationToken ct) {
// Arrange
IInfiniFrameWindow window = Substitute.For<IInfiniFrameWindow>();
window.SendWebMessageAsync(Arg.Any<string>(), Arg.Any<CancellationToken>())
.Returns(Task.CompletedTask);

await using ServiceProvider provider = new ServiceCollection()
.AddLogging()
.AddSingleton(window)
.BuildServiceProvider();

var dispatcher = Substitute.For<Dispatcher>();
var manager = new TestableInfiniFrameWebViewManager(
InfiniFrameWindowBuilder.Create(),
provider,
dispatcher,
new NullFileProvider(),
new JSComponentConfigurationStore(),
Options.Create(new InfiniFrameBlazorAppConfiguration()));

await manager.DisposeAsync();

// Act
Task sendTask = Task.Run(() => manager.SendMessageForTest("late-dispose-message"), ct);

// Assert
await sendTask.WaitAsync(TimeSpan.FromSeconds(1), ct);
await window.DidNotReceive().SendWebMessageAsync("late-dispose-message", Arg.Any<CancellationToken>());
}
}
Loading