wabbajack/Wabbajack.App.Wpf/View Models/BrowserWindowViewModel.cs

182 lines
5.1 KiB
C#
Raw Normal View History

2022-03-14 12:40:12 +00:00
using System;
2022-05-16 22:14:52 +00:00
using System.Collections.Generic;
2022-03-14 12:40:12 +00:00
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using HtmlAgilityPack;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.Wpf;
2022-05-15 22:38:22 +00:00
using ReactiveUI;
2022-03-14 12:40:12 +00:00
using ReactiveUI.Fody.Helpers;
2022-05-16 22:14:52 +00:00
using Wabbajack.DTOs.Interventions;
2022-03-14 12:40:12 +00:00
using Wabbajack.DTOs.Logins;
using Wabbajack.Hashing.xxHash64;
2022-05-15 22:38:22 +00:00
using Wabbajack.Messages;
using Wabbajack.Paths;
2022-03-14 12:40:12 +00:00
using Wabbajack.Views;
namespace Wabbajack;
2022-05-20 03:23:16 +00:00
public abstract class BrowserWindowViewModel : ViewModel
2022-03-14 12:40:12 +00:00
{
[Reactive] public string HeaderText { get; set; }
[Reactive] public string Instructions { get; set; }
2022-05-21 17:20:28 +00:00
[Reactive] public string Address { get; set; }
2022-03-14 12:40:12 +00:00
2022-05-20 03:23:16 +00:00
public BrowserWindow? Browser { get; set; }
2022-03-14 12:40:12 +00:00
private Microsoft.Web.WebView2.Wpf.WebView2 _browser => Browser!.Browser;
2022-03-14 12:40:12 +00:00
public async Task RunWrapper(CancellationToken token)
{
await Run(token);
2022-05-20 03:23:16 +00:00
//MessageBus.Current.SendMessage(new CloseBrowserTab(this));
2022-03-14 12:40:12 +00:00
}
protected abstract Task Run(CancellationToken token);
protected async Task WaitForReady()
{
while (Browser?.Browser.CoreWebView2 == null)
{
await Task.Delay(250);
}
}
public async Task NavigateTo(Uri uri)
{
var tcs = new TaskCompletionSource();
2022-05-21 17:20:28 +00:00
Address = uri.ToString();
2022-03-14 12:40:12 +00:00
void Completed(object? o, CoreWebView2NavigationCompletedEventArgs a)
{
if (a.IsSuccess)
{
tcs.TrySetResult();
}
else
{
2022-05-21 17:20:28 +00:00
if (a.WebErrorStatus is CoreWebView2WebErrorStatus.ConnectionAborted or CoreWebView2WebErrorStatus.Unknown )
2022-05-20 04:12:16 +00:00
{
tcs.TrySetResult();
}
else
{
tcs.TrySetException(new Exception($"Navigation error to {uri} - {a.WebErrorStatus}"));
}
2022-03-14 12:40:12 +00:00
}
}
_browser.NavigationCompleted += Completed;
_browser.Source = uri;
await tcs.Task;
_browser.NavigationCompleted -= Completed;
}
2022-08-18 23:02:19 +00:00
public async Task RunJavaScript(string script)
{
await _browser.ExecuteScriptAsync(script);
}
2022-03-14 12:40:12 +00:00
public async Task<Cookie[]> GetCookies(string domainEnding, CancellationToken token)
{
var cookies = (await _browser.CoreWebView2.CookieManager.GetCookiesAsync(""))
.Where(c => c.Domain.EndsWith(domainEnding));
return cookies.Select(c => new Cookie
{
Domain = c.Domain,
Name = c.Name,
Path = c.Path,
Value = c.Value
}).ToArray();
}
public async Task<string> EvaluateJavaScript(string js)
{
return await _browser.ExecuteScriptAsync(js);
}
public async Task<HtmlDocument> GetDom(CancellationToken token)
{
var source = await EvaluateJavaScript("document.body.outerHTML");
var decoded = JsonSerializer.Deserialize<string>(source);
var doc = new HtmlDocument();
doc.LoadHtml(decoded);
return doc;
}
2022-05-16 22:14:52 +00:00
2022-08-18 23:02:19 +00:00
public async Task<ManualDownload.BrowserDownloadState> WaitForDownloadUri(CancellationToken token, Func<Task>? whileWaiting)
2022-05-16 22:14:52 +00:00
{
var source = new TaskCompletionSource<Uri>();
var referer = _browser.Source;
_browser.CoreWebView2.DownloadStarting += (sender, args) =>
{
try
{
source.SetResult(new Uri(args.DownloadOperation.Uri));
}
catch (Exception ex)
{
source.SetCanceled();
}
2022-05-20 22:19:42 +00:00
2022-05-16 22:14:52 +00:00
args.Cancel = true;
2022-05-20 22:19:42 +00:00
args.Handled = true;
2022-05-16 22:14:52 +00:00
};
2022-08-18 23:02:19 +00:00
Uri uri;
while (true)
{
try
{
uri = await source.Task.WaitAsync(TimeSpan.FromMilliseconds(250), token);
break;
}
catch (TimeoutException)
{
if (whileWaiting != null)
await whileWaiting();
}
}
2022-05-16 22:14:52 +00:00
var cookies = await GetCookies(uri.Host, token);
return new ManualDownload.BrowserDownloadState(uri, cookies, new[]
{
("Referer", referer.ToString())
});
}
public async Task<Hash> WaitForDownload(AbsolutePath path, CancellationToken token)
{
var source = new TaskCompletionSource();
var referer = _browser.Source;
while (_browser.CoreWebView2 == null)
await Task.Delay(10, token);
_browser.CoreWebView2.DownloadStarting += (sender, args) =>
{
try
{
args.ResultFilePath = path.ToString();
args.Handled = true;
args.DownloadOperation.StateChanged += (o, o1) =>
{
var operation = (CoreWebView2DownloadOperation) o;
if (operation.State == CoreWebView2DownloadState.Completed)
source.TrySetResult();
};
}
catch (Exception ex)
{
source.SetCanceled();
}
};
await source.Task;
return default;
}
2022-03-14 12:40:12 +00:00
}