detect/WebViewControl.Avalonia/AsyncResourceHandler.cs

90 lines
2.9 KiB
C#
Raw Permalink Normal View History

2024-11-13 17:09:15 +08:00
using System.IO;
using System.Text;
using Xilium.CefGlue;
using Xilium.CefGlue.Common.Handlers;
namespace WebViewControl {
internal class AsyncResourceHandler : DefaultResourceHandler {
private CefCallback responseCallback;
private bool autoDisposeStream;
private object SyncRoot { get; } = new object();
protected override RequestHandlingFashion ProcessRequestAsync(CefRequest request, CefCallback callback) {
lock (SyncRoot) {
if (Response == null && string.IsNullOrEmpty(RedirectUrl)) {
responseCallback = callback;
return RequestHandlingFashion.ContinueAsync;
}
return RequestHandlingFashion.Continue;
}
}
public void SetResponse(string response, string mimeType = null) {
var responseStream = GetMemoryStream(response, Encoding.UTF8, includePreamble: true);
SetResponse(responseStream, mimeType, autoDisposeStream);
}
public void SetResponse(Stream response, string mimeType = null, bool autoDisposeStream = false) {
lock (SyncRoot) {
Response = response;
MimeType = mimeType;
this.autoDisposeStream = autoDisposeStream;
}
}
public void RedirectTo(string targetUrl) {
lock (SyncRoot) {
RedirectUrl = targetUrl;
}
}
public void Continue() {
lock (SyncRoot) {
if (responseCallback != null) {
using (responseCallback) {
responseCallback.Continue();
}
}
}
}
public static DefaultResourceHandler FromText(string text) {
var handler = new AsyncResourceHandler();
handler.SetResponse(text);
return handler;
}
private static MemoryStream GetMemoryStream(string text, Encoding encoding, bool includePreamble = true) {
if (includePreamble) {
var preamble = encoding.GetPreamble();
var bytes = encoding.GetBytes(text);
var memoryStream = new MemoryStream(preamble.Length + bytes.Length);
memoryStream.Write(preamble, 0, preamble.Length);
memoryStream.Write(bytes, 0, bytes.Length);
memoryStream.Position = 0;
return memoryStream;
}
return new MemoryStream(encoding.GetBytes(text));
}
protected override void Dispose(bool disposing) {
base.Dispose(disposing);
if (autoDisposeStream) {
var response = Response;
if (response != null) {
lock (SyncRoot) {
response.Dispose();
}
}
}
}
}
}