mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-28 14:08:16 +08:00
新增 WebView3 拦截 Rsp
修复 更新进度条值不正确 版本更变 2.0.0.8
This commit is contained in:
@@ -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";
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在浏览器中打开新窗口
|
||||
/// </summary>
|
||||
public bool OpenInBrowser { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 需要拦截响应流的Url
|
||||
/// </summary>
|
||||
public string[]? StreamResponseFilterUrls { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 拦截响应流的处理
|
||||
/// </summary>
|
||||
public Action<string, byte[]>? 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<ulong, StreamResponseFilter> 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// https://stackoverflow.com/questions/45816851/using-cefsharp-to-capture-resource-response-data-body
|
||||
/// </summary>
|
||||
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(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
@@ -6,6 +6,7 @@
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<!--(SignAssembly)对此程序集进行签名会导致编译失败(CompileAvaloniaXamlTask)-->
|
||||
<AssemblyName>System.Application.SteamTools.Client.Desktop.Avalonia</AssemblyName>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -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<string, byte[]>? OnStreamResponseFilterResourceLoadComplete { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -315,7 +315,7 @@ namespace System.Application.Services.Implementation
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
OnReportDownloading3_(i / (float)incrementalUpdate.Count);
|
||||
OnReportDownloading3_(i / (float)incrementalUpdate.Count * MaxProgressValue);
|
||||
}
|
||||
|
||||
OnReport(MaxProgressValue);
|
||||
|
||||
Reference in New Issue
Block a user