using System; using System.Collections.Generic; using Robust.Client.Graphics; using Robust.Shared.IoC; using Robust.Shared.Log; using Robust.Shared.ViewVariables; using Xilium.CefGlue; namespace Robust.Client.WebView.Cef { internal partial class WebViewManagerCef { [Dependency] private IClydeInternal _clyde = default!; private readonly List _browserWindows = new(); public IEnumerable AllBrowserWindows => _browserWindows; public IWebViewWindow CreateBrowserWindow(BrowserWindowCreateParameters createParams) { var mainHWnd = (_clyde.MainWindow as IClydeWindowInternal)?.WindowsHWnd ?? 0; var info = CefWindowInfo.Create(); info.Bounds = new CefRectangle(0, 0, createParams.Width, createParams.Height); info.SetAsPopup(mainHWnd, "ss14cef"); info.RuntimeStyle = CefRuntimeStyle.Alloy; var impl = new WebViewWindowImpl(this); var lifeSpanHandler = new WindowLifeSpanHandler(impl); var reqHandler = new RobustRequestHandler(_sawmill); var client = new WindowCefClient(lifeSpanHandler, reqHandler); var settings = new CefBrowserSettings(); impl.Browser = CefBrowserHost.CreateBrowserSync(info, client, settings, createParams.Url); impl.RequestHandler = reqHandler; _browserWindows.Add(impl); return impl; } private sealed class WebViewWindowImpl : IWebViewWindow { private readonly WebViewManagerCef _manager; internal CefBrowser Browser = default!; internal RobustRequestHandler RequestHandler = default!; public Action? OnResourceRequest { get; set; } [ViewVariables(VVAccess.ReadWrite)] public string Url { get { CheckClosed(); return Browser.GetMainFrame().Url; } set { CheckClosed(); Browser.GetMainFrame().LoadUrl(value); } } [ViewVariables] public bool IsLoading { get { CheckClosed(); return Browser.IsLoading; } } public WebViewWindowImpl(WebViewManagerCef manager) { _manager = manager; } public void StopLoad() { CheckClosed(); Browser.StopLoad(); } public void Reload() { CheckClosed(); Browser.Reload(); } public bool GoBack() { CheckClosed(); if (!Browser.CanGoBack) return false; Browser.GoBack(); return true; } public bool GoForward() { CheckClosed(); if (!Browser.CanGoForward) return false; Browser.GoForward(); return true; } public void ExecuteJavaScript(string code) { CheckClosed(); Browser.GetMainFrame().ExecuteJavaScript(code, string.Empty, 1); } public void AddResourceRequestHandler(Action handler) { RequestHandler.AddResourceRequestHandler(handler); } public void RemoveResourceRequestHandler(Action handler) { RequestHandler.RemoveResourceRequestHandler(handler); } public void Dispose() { if (Closed) return; Browser.GetHost().CloseBrowser(true); Closed = true; } public bool Closed { get; private set; } public void OnClose() { Closed = true; _manager._browserWindows.Remove(this); _manager._sawmill.Debug("Removing window"); } private void CheckClosed() { if (Closed) throw new ObjectDisposedException("BrowserWindow"); } } private sealed class WindowCefClient : BaseRobustCefClient { private readonly CefLifeSpanHandler _lifeSpanHandler; private readonly CefRequestHandler _requestHandler; public WindowCefClient(CefLifeSpanHandler lifeSpanHandler, CefRequestHandler requestHandler) { _lifeSpanHandler = lifeSpanHandler; _requestHandler = requestHandler; } protected override CefLifeSpanHandler GetLifeSpanHandler() => _lifeSpanHandler; protected override CefRequestHandler GetRequestHandler() => _requestHandler; } private sealed class WindowLifeSpanHandler : CefLifeSpanHandler { private readonly WebViewWindowImpl _windowImpl; public WindowLifeSpanHandler(WebViewWindowImpl windowImpl) { _windowImpl = windowImpl; } protected override void OnBeforeClose(CefBrowser browser) { base.OnBeforeClose(browser); _windowImpl.OnClose(); } } } }