新增 WebView3 拦截 Rsp

修复 更新进度条值不正确
版本更变 2.0.0.8
This commit is contained in:
Aigio Liu
2021-05-02 11:50:16 +08:00
parent 84490ef9b6
commit 25aa1951e3
6 changed files with 136 additions and 4 deletions
@@ -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);