From 25aa1951e3564a446ae95b77b2bbd097d3690bd2 Mon Sep 17 00:00:00 2001 From: Aigio Liu Date: Sun, 2 May 2021 11:50:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20WebView3=20=E6=8B=A6?= =?UTF-8?q?=E6=88=AA=20Rsp=20=E4=BF=AE=E5=A4=8D=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E6=9D=A1=E5=80=BC=E4=B8=8D=E6=AD=A3=E7=A1=AE?= =?UTF-8?q?=20=E7=89=88=E6=9C=AC=E6=9B=B4=E5=8F=98=202.0.0.8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common.CoreLib/Properties/ThisAssembly.cs | 2 +- .../Application/UI/Views/Controls/WebView3.cs | 114 ++++++++++++++++++ .../UI/Views/Windows/WebView3Window.axaml.cs | 10 +- .../ST.Client.Desktop.Avalonia.csproj | 3 +- .../Windows/WebView3WindowViewModel.cs | 9 ++ .../Implementation/AppUpdateServiceImpl.cs | 2 +- 6 files changed, 136 insertions(+), 4 deletions(-) diff --git a/src/Common.CoreLib/Properties/ThisAssembly.cs b/src/Common.CoreLib/Properties/ThisAssembly.cs index 9e788beac..9a4914d08 100644 --- a/src/Common.CoreLib/Properties/ThisAssembly.cs +++ b/src/Common.CoreLib/Properties/ThisAssembly.cs @@ -2,7 +2,7 @@ namespace System.Properties { public static class ThisAssembly { - public const string Version = "2.0.0.7"; + public const string Version = "2.0.0.8"; public const string InfoVersion = Version + "-beta"; diff --git a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Controls/WebView3.cs b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Controls/WebView3.cs index 29ffdf7f2..ad3494a4b 100644 --- a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Controls/WebView3.cs +++ b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Controls/WebView3.cs @@ -5,6 +5,8 @@ using CefNet.Internal; using System.Application.Services.CloudService; using System.Collections.Generic; using System.Diagnostics; +using System.IO; +using System.Linq; using static System.Application.Services.CloudService.Constants; // ReSharper disable once CheckNamespace @@ -43,7 +45,20 @@ namespace System.Application.UI.Views.Controls RaiseEvent(e); } + /// + /// 在浏览器中打开新窗口 + /// public bool OpenInBrowser { get; set; } = true; + + /// + /// 需要拦截响应流的Url + /// + public string[]? StreamResponseFilterUrls { get; set; } + + /// + /// 拦截响应流的处理 + /// + public Action? OnStreamResponseFilterResourceLoadComplete { get; set; } } public class FullscreenModeChangeEventArgs : RoutedEventArgs @@ -217,5 +232,104 @@ namespace System.Application.UI.Views.Controls // var returnValue = base.OnBeforeResourceLoad(browser, frame, request, callback); // return returnValue; //} + + protected override void OnResourceLoadComplete(CefBrowser browser, CefFrame frame, CefRequest request, CefResponse response, CefUrlRequestStatus status, long receivedContentLength) + { + base.OnResourceLoadComplete(browser, frame, request, response, status, receivedContentLength); + if (responseDictionary.TryGetValue(request.Identifier, out var filter)) + { + webView.OnStreamResponseFilterResourceLoadComplete?.Invoke(request.Url, filter.Data); + } + } + + readonly Dictionary responseDictionary = new(); + + protected override CefResponseFilter GetResourceResponseFilter(CefBrowser browser, CefFrame frame, CefRequest request, CefResponse response) + { + if (webView.StreamResponseFilterUrls != null && webView.StreamResponseFilterUrls.Contains(request.Url, StringComparer.OrdinalIgnoreCase)) + { + var dataFilter = new StreamResponseFilter(); + responseDictionary.Add(request.Identifier, dataFilter); + return dataFilter; + } + return base.GetResourceResponseFilter(browser, frame, request, response); + } + + /// + /// https://stackoverflow.com/questions/45816851/using-cefsharp-to-capture-resource-response-data-body + /// + unsafe class StreamResponseFilter : CefResponseFilter + { + MemoryStream? memoryStream; + + protected override bool InitFilter() + { + memoryStream = new(); + return true; + } + + protected override CefResponseFilterStatus Filter(IntPtr dataIn, long dataInSize, ref long dataInRead, IntPtr dataOut, long dataOutSize, ref long dataOutWritten) + { + Stream? dataInStream; + if (dataIn == default) + { + dataInStream = default; + } + else + { + var dataInBytePtr = (byte*)dataIn.ToPointer(); + dataInStream = new UnmanagedMemoryStream(dataInBytePtr, dataInSize, dataInSize, FileAccess.Read); + } + + var dataOutBytePtr = (byte*)dataOut.ToPointer(); + UnmanagedMemoryStream dataOutStream = new(dataOutBytePtr, dataOutSize, dataOutSize, FileAccess.Write); + + return Filter(dataInStream, dataInSize, ref dataInRead, dataOutStream, dataOutSize, ref dataOutWritten); + } + + protected virtual CefResponseFilterStatus Filter(Stream? dataIn, long dataInSize, ref long dataInRead, Stream dataOut, long dataOutSize, ref long dataOutWritten) + { + if (dataIn == null) + { + dataInRead = 0; + dataOutWritten = 0; + + return CefResponseFilterStatus.Done; + } + + dataInRead = dataIn.Length; + dataOutWritten = Math.Min(dataInRead, dataOut.Length); + + //Important we copy dataIn to dataOut + dataIn.CopyTo(dataOut); + + //Copy data to stream + dataIn.Position = 0; + dataIn.CopyTo(memoryStream!); + + return CefResponseFilterStatus.Done; + } + + protected override void Dispose(bool disposing) + { + if (!disposing) + { + if (disposing) + { + if (memoryStream != null) + { + memoryStream.Dispose(); + memoryStream = null; + } + } + } + base.Dispose(disposing); + } + + public byte[] Data + { + get { return memoryStream!.ToArray(); } + } + } } } \ No newline at end of file diff --git a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/WebView3Window.axaml.cs b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/WebView3Window.axaml.cs index 2ad252e80..db4d5a0d1 100644 --- a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/WebView3Window.axaml.cs +++ b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/WebView3Window.axaml.cs @@ -2,7 +2,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; using CefNet; -using CefNet.Avalonia; using ReactiveUI; using System.Application.UI.Resx; using System.Application.UI.ViewModels; @@ -57,6 +56,11 @@ namespace System.Application.UI.Views.Windows } } }).AddTo(vm); + vm.WhenAnyValue(x => x.StreamResponseFilterUrls).Subscribe(x => + { + webView.StreamResponseFilterUrls = x; + }).AddTo(vm); + webView.OnStreamResponseFilterResourceLoadComplete += vm.OnStreamResponseFilterResourceLoadComplete; } } @@ -92,6 +96,10 @@ namespace System.Application.UI.Views.Windows // TODO: 释放托管状态(托管对象) if (webView != null) { + if (DataContext is WebView3WindowViewModel vm) + { + webView.OnStreamResponseFilterResourceLoadComplete -= vm.OnStreamResponseFilterResourceLoadComplete; + } ((IDisposable)webView).Dispose(); } if (DataContext is IDisposable d) diff --git a/src/ST.Client.Desktop.Avalonia/ST.Client.Desktop.Avalonia.csproj b/src/ST.Client.Desktop.Avalonia/ST.Client.Desktop.Avalonia.csproj index b1454ae41..226aeec45 100644 --- a/src/ST.Client.Desktop.Avalonia/ST.Client.Desktop.Avalonia.csproj +++ b/src/ST.Client.Desktop.Avalonia/ST.Client.Desktop.Avalonia.csproj @@ -1,4 +1,4 @@ - + net5.0 @@ -6,6 +6,7 @@ false System.Application.SteamTools.Client.Desktop.Avalonia + true diff --git a/src/ST.Client.Desktop/UI/ViewModels/Windows/WebView3WindowViewModel.cs b/src/ST.Client.Desktop/UI/ViewModels/Windows/WebView3WindowViewModel.cs index c04507395..764f3bc9a 100644 --- a/src/ST.Client.Desktop/UI/ViewModels/Windows/WebView3WindowViewModel.cs +++ b/src/ST.Client.Desktop/UI/ViewModels/Windows/WebView3WindowViewModel.cs @@ -12,5 +12,14 @@ namespace System.Application.UI.ViewModels get => _Url; set => this.RaiseAndSetIfChanged(ref _Url, value); } + + string[]? _StreamResponseFilterUrls; + public string[]? StreamResponseFilterUrls + { + get => _StreamResponseFilterUrls; + set => this.RaiseAndSetIfChanged(ref _StreamResponseFilterUrls, value); + } + + public Action? OnStreamResponseFilterResourceLoadComplete { get; set; } } } \ No newline at end of file diff --git a/src/ST.Client/Services/Implementation/AppUpdateServiceImpl.cs b/src/ST.Client/Services/Implementation/AppUpdateServiceImpl.cs index 9b88af271..f814143be 100644 --- a/src/ST.Client/Services/Implementation/AppUpdateServiceImpl.cs +++ b/src/ST.Client/Services/Implementation/AppUpdateServiceImpl.cs @@ -315,7 +315,7 @@ namespace System.Application.Services.Implementation break; } i++; - OnReportDownloading3_(i / (float)incrementalUpdate.Count); + OnReportDownloading3_(i / (float)incrementalUpdate.Count * MaxProgressValue); } OnReport(MaxProgressValue);