Files
RobustToolbox/Robust.Client.WebView/Cef/Program.cs
T
PJB3005 602d7833a1 Initial macOS WebView support
This is a gigantic kerfuffle because Chromium expects a very specific directory & app bundle layout. Have to change a bunch of resource loading code to account for content development being launched from an app bundle, and also had to make automatic MSBuild tooling & a python script to generate such an app bundle
2025-11-09 00:06:16 +01:00

94 lines
3.0 KiB
C#

using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Threading;
using Robust.Shared.ContentPack;
using Xilium.CefGlue;
namespace Robust.Client.WebView.Cef
{
internal static class Program
{
// This was supposed to be the main entry for the subprocess program... It doesn't work.
public static int Main(string[] args)
{
// This is a workaround for this to work on UNIX.
var argv = args;
if (CefRuntime.Platform != CefRuntimePlatform.Windows)
{
argv = new string[args.Length + 1];
Array.Copy(args, 0, argv, 1, args.Length);
argv[0] = "-";
}
#if MACOS
NativeLibrary.SetDllImportResolver(typeof(CefSettings).Assembly,
(name, assembly, path) =>
{
if (name == "libcef")
{
var libPath = PathHelpers.ExecutableRelativeFile("../../../../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework");
return NativeLibrary.Load(libPath, assembly, path);
}
return 0;
});
#endif
var mainArgs = new CefMainArgs(argv);
StartWatchThread();
// This will block executing until the subprocess is shut down.
var code = CefRuntime.ExecuteProcess(mainArgs, new RobustCefApp(null), IntPtr.Zero);
if (code != 0)
{
System.Console.WriteLine($"CEF Subprocess exited unsuccessfully with exit code {code}! Arguments: {string.Join(' ', argv)}");
}
return code;
}
private static void StartWatchThread()
{
//
// CEF has this nasty habit of not shutting down all its processes if the parent crashes.
// Great!
//
// We use a separate thread in each CEF child process to watch the main PID.
// If it exits, we kill ourselves after a couple seconds.
//
if (Environment.GetEnvironmentVariable("ROBUST_CEF_BROWSER_PROCESS_ID") is not { } parentIdString)
return;
if (Environment.GetEnvironmentVariable("ROBUST_CEF_BROWSER_PROCESS_MODULE") is not { } parentModuleString)
return;
if (!int.TryParse(parentIdString, CultureInfo.InvariantCulture, out var parentId))
return;
var process = Process.GetProcessById(parentId);
if ((process.MainModule?.FileName ?? "") != parentModuleString)
{
process.Dispose();
return;
}
new Thread(() => WatchThread(process)) { Name = "CEF Watch Thread", IsBackground = true }
.Start();
}
private static void WatchThread(Process p)
{
p.WaitForExit();
Thread.Sleep(3000);
Environment.Exit(1);
}
}
}