1136 lines
38 KiB
C#
1136 lines
38 KiB
C#
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && !UNITY_EDITOR)
|
|
#define ZF_WINDOWS
|
|
#endif
|
|
|
|
#define PROXY_BROWSER_API
|
|
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using UnityEngine;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using UnityEngine.Assertions;
|
|
using System.Reflection;
|
|
using AOT;
|
|
using UnityEngine.Profiling;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
using System.Diagnostics;
|
|
using Debug = UnityEngine.Debug;
|
|
#endif
|
|
|
|
|
|
|
|
// ReSharper disable InconsistentNaming
|
|
|
|
namespace ZenFulcrum.EmbeddedBrowser {
|
|
|
|
/**
|
|
* Wrapper/native callbacks for CEF browser implementation.
|
|
* When changing code in this file you may have to restart the Unity Editor for things to get working again.
|
|
*
|
|
* Note that callbacks given to the native side may be invoked on any thread.
|
|
*
|
|
* Make sure IntPtrs are pinned and callbacks are kept alive from GC while their object lives.
|
|
*/
|
|
public static class BrowserNative {
|
|
#if UNITY_EDITOR
|
|
public const int DebugPort = 9848;
|
|
#else
|
|
public const int DebugPort = 9849;
|
|
#endif
|
|
|
|
public static bool NativeLoaded { get; private set; }
|
|
|
|
public static bool SymbolsLoaded { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Lock this object before touching any of the zfb_* functions outside the main thread.
|
|
/// (While many of them are thread safe, the shared library can be unloaded, leading
|
|
/// to a possible race condition at shutdown. For example thread A grabs the value of zfb_sendRequestData,
|
|
/// the main thread unloads the shared library, then thread A tries to execute the pointer it has for
|
|
/// zfb_sendRequestData, resulting in sadness.)
|
|
/// </summary>
|
|
public static readonly object symbolsLock = new object();
|
|
|
|
#if PROXY_BROWSER_API
|
|
public const bool UsingAPIProxy = true;
|
|
#else
|
|
public const bool UsingAPIProxy = false;
|
|
#endif
|
|
|
|
/**
|
|
* List of command-line switches given to Chromium.
|
|
* http://peter.sh/experiments/chromium-command-line-switches/
|
|
*
|
|
* If you want to change this, be sure to change it before LoadNative gets called.
|
|
*
|
|
* Adding or removing flags may lead to instability and/or insecurity.
|
|
* Make sure you understand what a flag does before you use it.
|
|
* Be sure to test your use cases thoroughly after changing any flags as
|
|
* things are more likely to crash or break if you aren't using the default
|
|
* configuration.
|
|
*
|
|
* Extra non-Chromium arguments:
|
|
* --zf-cef-log-verbose
|
|
* if enabled, we'll write a lot more CEF/Chromium logging to your editor/player log file than usual
|
|
* --zf-log-internal
|
|
* If enabled, some extra logs will be dumped to the current working directory.
|
|
*
|
|
*/
|
|
public static List<string> commandLineSwitches = new List<string>() {
|
|
//Smooth scrolling tends to make scrolling act wonky or break.
|
|
"--disable-smooth-scrolling",
|
|
|
|
//If you install the PPAPI version of Flash on your system this tells Chromium to try to use it.
|
|
//(download at https://get.adobe.com/flashplayer/otherversions/)
|
|
"--enable-system-flash",
|
|
//For Linux use probably need something like this instead (see docs)
|
|
//"--ppapi-flash-version=29.0.0.113", "--ppapi-flash-path=/usr/lib/adobe-flashplugin/libpepflashplayer.so",
|
|
|
|
//getUserMedia (microphone/webcam).
|
|
//Turning this on has security implications, it appears there's no
|
|
//CEF API for authorizing access, it just allows it. (ergo, any website can record the user)
|
|
//"--enable-media-stream",
|
|
|
|
//Enable these to get a higher browser framerate at the expense of more CPU usage:
|
|
// "--disable-gpu-vsync",
|
|
|
|
//If you want to specify a proxy by hand:
|
|
//"--proxy-server=localhost:8000",
|
|
|
|
|
|
//"--zf-log-cef-verbose",
|
|
//"--zf-log-internal",
|
|
};
|
|
|
|
/**
|
|
* WebResources used to resolve local requests.
|
|
*
|
|
* This may be replaced with an implementation of your choice, but be sure to set it up before requesting
|
|
* any URLs.
|
|
*/
|
|
public static WebResources webResources;
|
|
public static string LocalUrlPrefix { get { return "https://game.local/"; } }
|
|
|
|
[MonoPInvokeCallback(typeof(MessageFunc))]
|
|
private static void LogCallback(string message) {
|
|
Debug.Log("ZFWeb: " + message);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Because AppDomain.CurrentDomain.IsFinalizingForUnload() doesn't work and we don't like crashing the
|
|
/// Unity Editor.
|
|
/// </summary>
|
|
private static bool isAppDomainUnloading = false;
|
|
|
|
private static string _profilePath = null;
|
|
/**
|
|
* Where should we save the user's data and cookies? Leave null to not save them.
|
|
* Set before the browser system initializes. Also, restart the Editor to apply changes.
|
|
*/
|
|
public static string ProfilePath {
|
|
get { return _profilePath; }
|
|
set {
|
|
if (NativeLoaded) throw new InvalidOperationException("ProfilePath must be set before initializing the browser system.");
|
|
_profilePath = value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loads the shared library and the function symbols so we can call zfb_* functions.
|
|
*/
|
|
public static void LoadSymbols() {
|
|
if (SymbolsLoaded) return;
|
|
|
|
if (isAppDomainUnloading) {
|
|
throw new Exception("Tried to start up browser backend while unloading app domain.");
|
|
}
|
|
|
|
var dirs = FileLocations.Dirs;
|
|
|
|
HandLoadSymbols(dirs.binariesPath);
|
|
}
|
|
|
|
|
|
public static void LoadNative() {
|
|
if (NativeLoaded) return;
|
|
|
|
Profiler.BeginSample("BrowserNative.LoadNative");
|
|
|
|
if (webResources == null) {
|
|
//if the user hasn't given us a WebResources to use, use the default
|
|
#if UNITY_EDITOR
|
|
webResources = new EditorWebResources();
|
|
#else
|
|
var swr = new StandaloneWebResources(Application.dataPath + "/" + StandaloneWebResources.DefaultPath);
|
|
swr.LoadIndex();
|
|
webResources = swr;
|
|
#endif
|
|
}
|
|
|
|
|
|
//For Editor/debug builds, we'll open a port you can just http:// to inspect pages.
|
|
//Don't do this for real builds, though. It makes it really, really easy for the end user to call
|
|
//random JS in the page, potentially affecting or bypassing game logic.
|
|
var debugPort = Debug.isDebugBuild ? DebugPort : 0;
|
|
|
|
|
|
var dirs = FileLocations.Dirs;
|
|
|
|
#if UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX
|
|
FixProcessPermissions(dirs);
|
|
#endif
|
|
|
|
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
|
//make sure the child processes can be started (their dependent .dlls are next to the main .exe, not in the Plugins folder)
|
|
var loadDir = Directory.GetParent(Application.dataPath).FullName;
|
|
var path = Environment.GetEnvironmentVariable("PATH");
|
|
path += ";" + loadDir;
|
|
Environment.SetEnvironmentVariable("PATH", path);
|
|
#elif UNITY_EDITOR_WIN
|
|
//help it find our .dlls
|
|
//var path =Environment.GetEnvironmentVariable("PATH");
|
|
//path += ";" + dirs.binariesPath;
|
|
// object value = Environment.GetEnvironmentVariable("PATH", path);
|
|
#endif
|
|
|
|
LoadSymbols();
|
|
|
|
StandaloneShutdown.Create();
|
|
|
|
//There never should be any, but just in case, destroy any existing browsers on a re-init
|
|
zfb_destroyAllBrowsers();
|
|
|
|
//Caution: Careful with these functions you pass to native. The Unity Editor will
|
|
//reload assemblies, leaving the function pointers dangling. If any native calls try to use them
|
|
//before we load back up and re-register them we can crash.
|
|
//To prevent this, we call zfb_setCallbacksEnabled to disable callbacks before we get unloaded.
|
|
zfb_setDebugFunc(LogCallback);
|
|
zfb_setLocalRequestHandler(NewRequestCallback);
|
|
zfb_setCallbacksEnabled(true);
|
|
|
|
var settings = new ZFBInitialSettings() {
|
|
cefPath = dirs.resourcesPath,
|
|
localePath = dirs.localesPath,
|
|
subprocessFile = dirs.subprocessFile,
|
|
userAgent = UserAgent.GetUserAgent(),
|
|
logFile = dirs.logFile,
|
|
profilePath = _profilePath,
|
|
debugPort = debugPort,
|
|
multiThreadedMessageLoop = 0,//this argument is pretty much defunct, the slave just blocks on CefRunMessageLoop on all platforms
|
|
};
|
|
|
|
foreach (var arg in commandLineSwitches) zfb_addCLISwitch(arg);
|
|
|
|
var initRes = zfb_init(settings);
|
|
if (!initRes) throw new Exception("Failed to initialize browser system.");
|
|
|
|
NativeLoaded = true;
|
|
Profiler.EndSample();
|
|
|
|
AppDomain.CurrentDomain.DomainUnload += (sender, args) => {
|
|
isAppDomainUnloading = true;
|
|
|
|
//Shutdown should happen StandaloneShutdown, but in some cases, like the Unity Editor
|
|
//reloading assemblies, we don't get OnApplicationQuit because we didn't "quit", even though
|
|
//everything gets shut down.
|
|
//Make sure the backend shuts down, in this case, or it will crash when we try to start it again.
|
|
UnloadNative();
|
|
};
|
|
}
|
|
|
|
private static void FixProcessPermissions(FileLocations.CEFDirs dirs) {
|
|
/*
|
|
* The package we get from the Asset Store probably won't have the right executable permissions for
|
|
* ZFGameBrowser for OS X, so let's fix that for the user right now.
|
|
*/
|
|
|
|
var attrs = (uint)File.GetAttributes(dirs.subprocessFile);
|
|
|
|
//From https://github.com/mono/mono/blob/master/mono/io-layer/io.c under SetFileAttributes() (also noted in FileAttributes.cs):
|
|
//"Currently we only handle one *internal* case [...]: 0x80000000, which means `set executable bit'"
|
|
//Let's use that now.
|
|
attrs |= 0x80000000;
|
|
|
|
//Make it executable.
|
|
File.SetAttributes(dirs.subprocessFile, unchecked((FileAttributes)attrs));
|
|
}
|
|
|
|
|
|
private static IntPtr moduleHandle;
|
|
/// <summary>
|
|
/// Loads the browser symbols.
|
|
///
|
|
/// We don't use DllImport for a few reasons, historically for DEEPBIND support and multiple CEF versions in the same process,
|
|
/// but now mostly so we can unload the .dll whenever we want and to simplify picking and loading our shared library how we want.
|
|
/// </summary>
|
|
/// <param name="binariesPath"></param>
|
|
private static void HandLoadSymbols(string binariesPath) {
|
|
Profiler.BeginSample("BrowserNative.HandLoadSymbols");
|
|
|
|
#if PROXY_BROWSER_API
|
|
var coreType = "ZFProxyWeb";
|
|
#else
|
|
var coreType = "ZFEmbedWeb";
|
|
#endif
|
|
|
|
#if UNITY_EDITOR_OSX || (!UNITY_EDITOR && UNITY_STANDALONE_OSX)
|
|
var libFile = binariesPath + "/lib" + coreType + ".dylib";
|
|
#elif UNITY_EDITOR_LINUX || (!UNITY_EDITOR && UNITY_STANDALONE_LINUX)
|
|
var libFile = binariesPath + "/lib" + coreType + ".so";
|
|
#elif UNITY_EDITOR_WIN || (!UNITY_EDITOR && UNITY_STANDALONE_WIN)
|
|
var libFile = binariesPath + "/" + coreType + ".dll";
|
|
#else
|
|
#error Unknown OS.
|
|
#endif
|
|
|
|
//Debug.Log("Loading " + libFile);
|
|
|
|
moduleHandle = OpenLib(libFile);
|
|
|
|
//Now go through and fill our functions with life.
|
|
int i = 0;
|
|
var fields = typeof(BrowserNative).GetFields(BindingFlags.Static | BindingFlags.Public);
|
|
foreach (var field in fields) {
|
|
if (!field.Name.StartsWith("zfb_")) continue;
|
|
|
|
var fp = GetFunc(moduleHandle, field.Name);
|
|
|
|
var func = Marshal.GetDelegateForFunctionPointer(fp, field.FieldType);
|
|
field.SetValue(null, func);
|
|
++i;
|
|
}
|
|
|
|
//Debug.Log("Loaded " + i + " symbols");
|
|
|
|
SymbolsLoaded = true;
|
|
|
|
Profiler.EndSample();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clears out the symbols so, if the shared library has been unloaded, we get null exceptions instead
|
|
/// of crashes.
|
|
/// </summary>
|
|
private static void ClearSymbols() {
|
|
SymbolsLoaded = false;
|
|
|
|
var fields = typeof(BrowserNative).GetFields(BindingFlags.Static | BindingFlags.Public);
|
|
foreach (var field in fields) {
|
|
if (!field.Name.StartsWith("zfb_")) continue;
|
|
field.SetValue(null, null);
|
|
}
|
|
}
|
|
|
|
|
|
private static string GetLibError() {
|
|
#if ZF_WINDOWS
|
|
return new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()).Message;
|
|
#else
|
|
return Marshal.PtrToStringAnsi(dlerror());
|
|
#endif
|
|
}
|
|
|
|
private static IntPtr OpenLib(string name) {
|
|
#if ZF_WINDOWS
|
|
var handle = LoadLibraryW(name);
|
|
if (handle == IntPtr.Zero) {
|
|
// throw new DllNotFoundException("ZFBrowser failed to load " + name + ": " + Marshal.GetLastWin32Error());
|
|
throw new DllNotFoundException("ZFBrowser failed to load " + name + ": " +
|
|
new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()).Message
|
|
);
|
|
}
|
|
return handle;
|
|
#else
|
|
//Call this now because running a DllImport method the first time will end up calling dlerror
|
|
//which will clear the error we were trying to get from dlerror.
|
|
dlerror();
|
|
|
|
var handle = dlopen(name, (int)(DLFlags.RTLD_LAZY));
|
|
if (handle == IntPtr.Zero) {
|
|
throw new DllNotFoundException("ZFBrowser failed to load " + name + ": " + getDlError());
|
|
}
|
|
return handle;
|
|
#endif
|
|
}
|
|
|
|
private static void CloseLib() {
|
|
if (moduleHandle == IntPtr.Zero) return;
|
|
|
|
ClearSymbols();
|
|
|
|
#if ZF_WINDOWS
|
|
var success = FreeLibrary(moduleHandle);
|
|
#else
|
|
var success = dlclose(moduleHandle) == 0;
|
|
#endif
|
|
|
|
if (!success) {
|
|
throw new DllNotFoundException(
|
|
"Failed to unload library: " +
|
|
GetLibError()
|
|
);
|
|
}
|
|
|
|
//Debug.Log("Unloaded shared library");
|
|
|
|
moduleHandle = IntPtr.Zero;
|
|
}
|
|
|
|
private static IntPtr GetFunc(IntPtr libHandle, string fnName) {
|
|
#if ZF_WINDOWS
|
|
var addr = GetProcAddress(libHandle, fnName);
|
|
if (addr == IntPtr.Zero) {
|
|
throw new DllNotFoundException("ZFBrowser failed to load method " + fnName + ": " + Marshal.GetLastWin32Error());
|
|
}
|
|
return addr;
|
|
#else
|
|
var fp = dlsym(libHandle, fnName);
|
|
if (fp == IntPtr.Zero) {
|
|
throw new DllNotFoundException("ZFBrowser failed to load method " + fnName + ": " + getDlError());
|
|
}
|
|
return fp;
|
|
#endif
|
|
}
|
|
|
|
#if !ZF_WINDOWS
|
|
[Flags]
|
|
public enum DLFlags {
|
|
RTLD_LAZY = 1,
|
|
RTLD_NOW = 2,
|
|
RTLD_DEEPBIND = 8,
|
|
}
|
|
[DllImport("__Internal")] static extern IntPtr dlopen(string filename, int flags);
|
|
[DllImport("__Internal")] static extern IntPtr dlsym(IntPtr handle, string symbol);
|
|
[DllImport("__Internal")] static extern int dlclose(IntPtr handle);
|
|
[DllImport("__Internal")] static extern IntPtr dlerror();
|
|
private static string getDlError() {
|
|
var err = dlerror();
|
|
return Marshal.PtrToStringAnsi(err);
|
|
}
|
|
|
|
#else
|
|
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
|
|
static extern IntPtr LoadLibraryW([MarshalAs(UnmanagedType.LPWStr)]string lpFileName);
|
|
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
|
|
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
|
|
[DllImport("kernel32", SetLastError = true)]
|
|
private static extern bool FreeLibrary(IntPtr hModule);
|
|
#endif
|
|
|
|
[MonoPInvokeCallback(typeof(NewRequestFunc))]
|
|
private static void NewRequestCallback(int requestId, string url) {
|
|
webResources.HandleRequest(requestId, url);
|
|
}
|
|
|
|
|
|
/** Shuts down the native browser library and CEF. */
|
|
public static void UnloadNative() {
|
|
if (!NativeLoaded) return;
|
|
|
|
lock (symbolsLock) {
|
|
//Debug.Log("Stop CEF");
|
|
|
|
zfb_destroyAllBrowsers();
|
|
zfb_shutdown();
|
|
zfb_setCallbacksEnabled(false);
|
|
NativeLoaded = false;
|
|
CloseLib();
|
|
}
|
|
}
|
|
|
|
|
|
/** Call this with a message to debug it to a console somewhere. */
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
public delegate void MessageFunc(string message);
|
|
|
|
/**
|
|
* Callback for starting a new local request.
|
|
* url is the url requested
|
|
* At present only GET requests with no added headers are supported.
|
|
* After this is called, you are responsible for calling zfb_sendRequestHeaders (once)
|
|
* then zfb_sendRequestData (as much as needed) to finish up the request.
|
|
*/
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
public delegate void NewRequestFunc(int requestId, string url);
|
|
|
|
|
|
/** Called when the native backend is ready to start receiving orders. */
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
public delegate void ReadyFunc(int browserId);
|
|
|
|
/** Called on console.log, console.err, etc. */
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
public delegate void ConsoleFunc(int browserId, string message, string source, int line);
|
|
|
|
/**
|
|
* Called when JS calls back to us.
|
|
* callbackId is the first argument,
|
|
* data (UTF-8 null-terminated string) (and its included size) are the second argument.
|
|
*/
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
public delegate void ForwardJSCallFunc(int browserId, int callbackId, string data, int size);
|
|
|
|
/**
|
|
* Called when a browser opens a new window.
|
|
* creatorBrowserId - id of the browser that cause the window to be created
|
|
* newBrowserId - a newly created (as if by zfb_createBrowser) browser tab
|
|
*
|
|
* May be called on any thread.
|
|
*/
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
public delegate void NewWindowFunc(int creatorBrowserId, int newBrowserId, IntPtr initialURL);
|
|
|
|
/**
|
|
* Called when an item from ChangeType happens.
|
|
* See the documentation for the given ChangeType for info on what the args mean or how to get more information.
|
|
*/
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
public delegate void ChangeFunc(int browserId, ChangeType changeType, string arg1);
|
|
|
|
/**
|
|
* This is called when the browser wants to display a dialog of some sort.
|
|
* dialogType - the type, or DLT_HIDE to hide any existing dialogs.
|
|
* dialogText - main text for the dialog, usually from in-page JavaScript
|
|
* initialPromptText - if we are doing a JavaScript prompt(), the default text to display
|
|
* sourceURL - the URL of the page that is causing the dialog
|
|
*
|
|
* Once the user has responded to the dialog (if we were showing one), call zfb_sendDialogResults
|
|
* with the user's input.
|
|
*/
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
public delegate void DisplayDialogFunc(
|
|
int browserId, DialogType dialogType, IntPtr dialogText,
|
|
IntPtr initialPromptText, IntPtr sourceURL
|
|
);
|
|
|
|
/**
|
|
* Called by the backend when a context menu should be shown or hidden.
|
|
* If menuJSON is null, hide the context menu.
|
|
* If it's not, show the given menu and eventually call zfb_sendContextMenuResults.
|
|
* For more information on the menu format, look at BrowserDialogs.html
|
|
*
|
|
* x and y report the position the menu was summoned, relative to the top-left of the view.
|
|
* origin indicates on what type of item the context menu was created.
|
|
*/
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
public delegate void ShowContextMenuFunc(int browserId, string menuJSON, int x, int y, ContextMenuOrigin origin);
|
|
|
|
/**
|
|
* Used with zfb_getCookies, this will be called once for each cookie.
|
|
*/
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
public delegate void GetCookieFunc(NativeCookie cookie);
|
|
|
|
/**
|
|
* Called when nav state (can go back/forward, loaded, url) changes.
|
|
*/
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
public delegate void NavStateFunc(int browserId, bool canGoBack, bool canGoForward, bool lodaing, IntPtr url);
|
|
|
|
/**
|
|
* Called by a native OS windows gets an event like mouse move click, etc.
|
|
* data contains json details on the event
|
|
*/
|
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
public delegate void WindowCallbackFunc(int windowId, IntPtr data);
|
|
|
|
|
|
|
|
public enum LoadChange : int {
|
|
LC_STOP = 1,
|
|
LC_RELOAD,
|
|
LC_FORCE_RELOAD,
|
|
}
|
|
|
|
public enum MouseButton : int {
|
|
MBT_LEFT = 0,
|
|
MBT_MIDDLE,
|
|
MBT_RIGHT,
|
|
}
|
|
|
|
public enum ChangeType : int {
|
|
/** The cursor has changed. Use zfb_getMouseCursor/zfb_getMouseCustomCursor to see what it is now. */
|
|
CHT_CURSOR = 0,
|
|
/** The browser has been closed and can no longer receive commands. */
|
|
CHT_BROWSER_CLOSE,
|
|
/**
|
|
* We have the HTML for the top-level page.
|
|
* arg1 (JSON) contains HTTP {status} code and the {url}
|
|
* Note that successfully fetching errors from a server (404, 500) are treated
|
|
* as successful, CHT_FETCH_FAILED won't be triggered.
|
|
*/
|
|
CHT_FETCH_FINISHED,
|
|
/**
|
|
* Failed to fetch a page (timeout, network issues, etc)
|
|
* arg1 (JSON) contains an {error} code and the {url}
|
|
*/
|
|
CHT_FETCH_FAILED,
|
|
/**
|
|
* The page has reached onload
|
|
* arg1 (JSON) contains HTTP {status} code and the {url}
|
|
*/
|
|
CHT_LOAD_FINISHED,
|
|
/** SSL certificate error. arg1 has some JSON about the issue. Often followed by a CHT_FETCH_FAILED */
|
|
CHT_CERT_ERROR,
|
|
/** Renderer process crashed/was killed/etc. */
|
|
CHT_SAD_TAB,
|
|
/**
|
|
* The user/page has initialized a download.
|
|
* arg1 (JSON) contains:
|
|
* download {id}
|
|
* {mimeType}
|
|
* {url} of the download
|
|
* {originalURL} of the download before redirection
|
|
* {suggestedName} you might save the file as
|
|
* {size} number of bytes in the download (if known)
|
|
* {contentDisposition}
|
|
*
|
|
* Call zfb_downloadCommand(browserId, download["id"], DownloadAction.xxyy, fileName) to cancel or save the file
|
|
* (and afterward control it).
|
|
*/
|
|
CHT_DOWNLOAD_STARTED,
|
|
/**
|
|
* Progress/status update on a download.
|
|
* arg1 (JSON) contains:
|
|
* download {id}
|
|
* {speed} in bytes/sec
|
|
* {percentComplete} int in [0, 100], or -1 if unknown
|
|
* {received} number of bytes received
|
|
* {statusStr} download status. One of: complete, canceled, working, unknown
|
|
* {fullPath} we are saving to. (If you had the user pick the destination you can get it here.)
|
|
*
|
|
* Call zfb_downloadCommand(browserId, download["id"], DownloadAction.xxyy, null) to cancel/pause/resume the download.
|
|
*/
|
|
CHT_DOWNLOAD_STATUS,
|
|
/**
|
|
* The element with keyboard focus has changed.
|
|
* You can use this to show/hide a keyboard when needed.
|
|
* arg1 (JSON) contains:
|
|
* {tagName} of the focused node, or empty of no node is focused (focus loss)
|
|
* {editable} true if it's some sort of editable text
|
|
* textual {value} of the node, if it's simple (doesn't work for things like ContentEditable nodes)
|
|
*/
|
|
CHT_FOCUSED_NODE,
|
|
}
|
|
|
|
public enum DownloadAction {
|
|
Begin,
|
|
Cancel,
|
|
Pause,
|
|
Resume,
|
|
}
|
|
|
|
/** @see cef_cursor_type_t in cef_types.h */
|
|
public enum CursorType : int {
|
|
Pointer = 0,
|
|
Cross,
|
|
Hand,
|
|
IBeam,
|
|
Wait,
|
|
Help,
|
|
EastResize,
|
|
NorthResize,
|
|
NorthEastResize,
|
|
NorthWestResize,
|
|
SouthResize,
|
|
SouthEastResize,
|
|
SouthWestResize,
|
|
WestResize,
|
|
NorthSouthResize,
|
|
EastWestResize,
|
|
NorthEastSouthWestResize,
|
|
NorthWestSouthEastResize,
|
|
ColumnResize,
|
|
RowResize,
|
|
MiddlePanning,
|
|
EastPanning,
|
|
NorthPanning,
|
|
NorthEastPanning,
|
|
NorthWestPanning,
|
|
SouthPanning,
|
|
SouthEastPanning,
|
|
SouthWestPanning,
|
|
WestPanning,
|
|
Move,
|
|
VerticalText,
|
|
Cell,
|
|
ContextMenu,
|
|
Alias,
|
|
Progress,
|
|
NoDrop,
|
|
Copy,
|
|
None,
|
|
NotAllowed,
|
|
ZoomIn,
|
|
ZoomOut,
|
|
Grab,
|
|
Grabbing,
|
|
Custom,
|
|
}
|
|
|
|
public enum DialogType {
|
|
DLT_HIDE = 0,
|
|
DLT_ALERT,
|
|
DLT_CONFIRM,
|
|
DLT_PROMPT,
|
|
DLT_PAGE_UNLOAD,
|
|
DLT_PAGE_RELOAD,//like unload, but the user is just refreshing the page
|
|
DLT_GET_AUTH,
|
|
};
|
|
|
|
public enum NewWindowAction {
|
|
NWA_IGNORE = 1,
|
|
NWA_REDIRECT,
|
|
NWA_NEW_BROWSER,
|
|
NWA_NEW_WINDOW,
|
|
};
|
|
|
|
[Flags]
|
|
public enum ContextMenuOrigin {
|
|
Editable = 1 << 1,
|
|
Image = 1 << 2,
|
|
Selection = 1 << 3,
|
|
Other = 1 << 0,
|
|
}
|
|
|
|
public enum FrameCommand {
|
|
Undo,
|
|
Redo,
|
|
Cut,
|
|
Copy,
|
|
Paste,
|
|
Delete,
|
|
SelectAll,
|
|
ViewSource,
|
|
};
|
|
|
|
public enum CookieAction {
|
|
Delete,
|
|
Create,
|
|
};
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
public struct ZFBInitialSettings {
|
|
public string cefPath, localePath, subprocessFile, userAgent, logFile, profilePath;
|
|
public int debugPort, multiThreadedMessageLoop;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
public struct ZFBSettings {
|
|
public int bgR, bgG, bgB, bgA;
|
|
public int offscreen;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
public struct RenderData {
|
|
public IntPtr pixels;
|
|
public int w, h;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
public class NativeCookie {
|
|
public string name, value, domain, path;
|
|
public string creation, lastAccess, expires;
|
|
public byte secure, httpOnly;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* See HandLoadSymbols() for an explanation of what's going on here and why we use a bunch of delegates instead
|
|
* of DllImport.
|
|
*
|
|
* Don't use this API directly unless you want to deal with things breaking.
|
|
* Though it is accessible, it's not considered part of the public API for versioning purposes.
|
|
* That, and you can shoot yourself in the foot and crash your app.
|
|
*
|
|
* Also, if you want to call any of these functions off the main thread make sure:
|
|
* - It's documented as supporting such.
|
|
* - To acquire a lock on symbolsLock first. (See its docs for why.)
|
|
*/
|
|
|
|
/** Does nothing. */
|
|
public delegate void Calltype_zfb_noop();
|
|
public static Calltype_zfb_noop zfb_noop;
|
|
|
|
|
|
/**
|
|
* Allocates and initializes a block of memory suitable for use with LoadRawTextureData to clear a texture
|
|
* to the given color.
|
|
* Call zfb_free on the pointer when your are done using it.
|
|
* Does not require the browser system to be initialized, thread safe.
|
|
*/
|
|
public delegate IntPtr Calltype_zfb_flatColorTexture(int pixelCount, int r, int g, int b, int a);
|
|
public static Calltype_zfb_flatColorTexture zfb_flatColorTexture;
|
|
|
|
/**
|
|
* Copies from a zfb_getImage buffer to a Color32[] buffer.
|
|
* Does not require the browser system to be initialized, thread safe.
|
|
*/
|
|
public delegate void Calltype_zfb_copyToColor32(IntPtr src, IntPtr dest, int pixelCount);
|
|
public static Calltype_zfb_copyToColor32 zfb_copyToColor32;
|
|
|
|
/**
|
|
* Some functions allocate memory to give you a response (see their docs). Call this to free it.
|
|
* Does not require the browser system to be initialized, thread safe.
|
|
*/
|
|
public delegate void Calltype_zfb_free(IntPtr mem);
|
|
public static Calltype_zfb_free zfb_free;
|
|
|
|
|
|
/**
|
|
* Plain old memcpy. Because sometimes Marshal.Copy falls short of our needs.
|
|
* Does not require the browser system to be initialized, thread safe.
|
|
*/
|
|
public delegate void Calltype_zfb_memcpy(IntPtr dst, IntPtr src, int size);
|
|
public static Calltype_zfb_memcpy zfb_memcpy;
|
|
|
|
|
|
/**
|
|
* Returns the Chrome(ium) version as a static C string.
|
|
* Does not require the browser system to be initialized, thread safe.
|
|
*/
|
|
public delegate IntPtr Calltype_zfb_getVersion();
|
|
public static Calltype_zfb_getVersion zfb_getVersion;
|
|
|
|
|
|
/** Sets a function to call for Debug.Log-style messages. */
|
|
public delegate void Calltype_zfb_setDebugFunc(MessageFunc debugFunc);
|
|
public static Calltype_zfb_setDebugFunc zfb_setDebugFunc;
|
|
|
|
|
|
/** Sets callbacks for when a local (https://game.local/) request is started. */
|
|
public delegate void Calltype_zfb_setLocalRequestHandler(NewRequestFunc requestFunc);
|
|
public static Calltype_zfb_setLocalRequestHandler zfb_setLocalRequestHandler;
|
|
|
|
/**
|
|
* Sends the headers for a response.
|
|
* responseLength should be the number of bytes in the response, or -1 if unknown.
|
|
* headersJSON should contain a string:string map of headers, JSON encoded
|
|
* - You should include a "Content-Type" header.
|
|
* - You may also include a ":status:" pseudoheader to set the status to a non-200 value
|
|
* - You may also include a ":statusText:" pseudoheader to set the status text
|
|
* After calling this, call zfb_sendRequestData to send the actual response body.
|
|
*
|
|
* May be called from any thread.
|
|
*/
|
|
public delegate void Calltype_zfb_sendRequestHeaders(int requestId, int responseLength, string headersJSON);
|
|
public static Calltype_zfb_sendRequestHeaders zfb_sendRequestHeaders;
|
|
|
|
/**
|
|
* Sends the body for a response after calling zfb_sendRequestHeaders.
|
|
*
|
|
* You must always write at least one byte except as described below.
|
|
*
|
|
* If you sent a responseLength >= 0, make sure all calls to this function add up to exactly that value.
|
|
* If you sent a responseLength < 0, call this a final time with size = 0 to signify the
|
|
* end of the response.
|
|
*
|
|
* May be called from any thread.
|
|
*/
|
|
public delegate void Calltype_zfb_sendRequestData(int requestId, IntPtr data, int dataSize);
|
|
public static Calltype_zfb_sendRequestData zfb_sendRequestData;
|
|
|
|
|
|
|
|
/** Enabled/disables user callbacks. Useful for disabling all callbacks when mono assemblies reload. */
|
|
public delegate void Calltype_zfb_setCallbacksEnabled(bool enabled);
|
|
public static Calltype_zfb_setCallbacksEnabled zfb_setCallbacksEnabled;
|
|
|
|
|
|
/** Destroys all browser instances. */
|
|
public delegate void Calltype_zfb_destroyAllBrowsers();
|
|
public static Calltype_zfb_destroyAllBrowsers zfb_destroyAllBrowsers;
|
|
|
|
|
|
/** Adds a command-line switch to Chromium, must call before zfb_init */
|
|
public delegate void Calltype_zfb_addCLISwitch(string value);
|
|
public static Calltype_zfb_addCLISwitch zfb_addCLISwitch;
|
|
|
|
|
|
/** Initializes the system so we can start making browsers. */
|
|
public delegate bool Calltype_zfb_init(ZFBInitialSettings settings);
|
|
public static Calltype_zfb_init zfb_init;
|
|
|
|
|
|
/** Shuts down the system. It cannot be re-initialized. */
|
|
public delegate void Calltype_zfb_shutdown();
|
|
public static Calltype_zfb_shutdown zfb_shutdown;
|
|
|
|
|
|
/**
|
|
* Creates a new browser, returning the id.
|
|
* Call zfb_setReadyCallback and wait for it to fire before doing anything else.
|
|
*/
|
|
public delegate int Calltype_zfb_createBrowser(ZFBSettings settings);
|
|
public static Calltype_zfb_createBrowser zfb_createBrowser;
|
|
|
|
|
|
/** Reports the number of un-destroyed browsers. Slow. */
|
|
public delegate int Calltype_zfb_numBrowsers();
|
|
public static Calltype_zfb_numBrowsers zfb_numBrowsers;
|
|
|
|
|
|
/**
|
|
* Closes and cleans up a browser instance.
|
|
*/
|
|
public delegate void Calltype_zfb_destroyBrowser(int id);
|
|
public static Calltype_zfb_destroyBrowser zfb_destroyBrowser;
|
|
|
|
|
|
/** Call once per frame if the multi-threaded message loop isn't enabled. */
|
|
public delegate void Calltype_zfb_tick();
|
|
public static Calltype_zfb_tick zfb_tick;
|
|
|
|
|
|
/**
|
|
* Registers a function to call when the browser instance is ready to start taking orders.
|
|
* {cb} may be executed immediately or on any thread.
|
|
*/
|
|
public delegate void Calltype_zfb_setReadyCallback(int id, ReadyFunc cb);
|
|
public static Calltype_zfb_setReadyCallback zfb_setReadyCallback;
|
|
|
|
|
|
/** Resizes the browser. */
|
|
public delegate void Calltype_zfb_resize(int id, int w, int h);
|
|
public static Calltype_zfb_resize zfb_resize;
|
|
|
|
|
|
/**
|
|
* Adds the given browser {overlayBrowserId} as an overlay of this browser {browserId}.
|
|
* The overlaid browser will appear transparently over the top of {browser}.
|
|
* {overlayBrowser} must not have an overlay and must be sized exactly the same as {browser}.
|
|
* Remove the overlay before closing either browser.
|
|
*
|
|
* While {overlayBrowser} is overlaying another browser, do not call zfb_getImage on it.
|
|
*/
|
|
public delegate void Calltype_zfb_setOverlay(int browserId, int overlayBrowserId);
|
|
public static Calltype_zfb_setOverlay zfb_setOverlay;
|
|
|
|
|
|
/**
|
|
* Gets the image data for the current frame.
|
|
* Do not hang onto the returned data across frames or resizes.
|
|
*
|
|
* If there are no changes since last call, the pixel data will be null (unless you specify forceDirty).
|
|
*/
|
|
public delegate RenderData Calltype_zfb_getImage(int id, bool forceDirty);
|
|
public static Calltype_zfb_getImage zfb_getImage;
|
|
|
|
/**
|
|
* Registers a callback for nav state updates.
|
|
* Keep track of what it tells you to answer questions like what the current URL is and if we can go back/forward.
|
|
* (The URL overlaps a bit with CHT_FETCH_*, but this should fire earlier (when we start) as opposed to when it's done.)
|
|
*/
|
|
public delegate void Calltype_zfb_registerNavStateCallback(int id, NavStateFunc callback);
|
|
public static Calltype_zfb_registerNavStateCallback zfb_registerNavStateCallback;
|
|
|
|
/**
|
|
* Navigates to the given URL. If force it ture, it will go there right away.
|
|
* If force is false, the pages that wish to can prompt the user and possibly cancel the
|
|
* navigation.
|
|
*/
|
|
public delegate void Calltype_zfb_goToURL(int id, string url, bool force);
|
|
public static Calltype_zfb_goToURL zfb_goToURL;
|
|
|
|
/**
|
|
* Loads the given HTML string as if it were the given URL.
|
|
* Use http://-like porotocols or else things may not work right.
|
|
*/
|
|
public delegate void Calltype_zfb_goToHTML(int id, string html, string url);
|
|
public static Calltype_zfb_goToHTML zfb_goToHTML;
|
|
|
|
/** Go back (-1) or forward (1) */
|
|
public delegate void Calltype_zfb_doNav(int id, int direction);
|
|
public static Calltype_zfb_doNav zfb_doNav;
|
|
|
|
|
|
public delegate void Calltype_zfb_setZoom(int id, double zoom);
|
|
public static Calltype_zfb_setZoom zfb_setZoom;
|
|
|
|
|
|
/** Stop, refresh, or force-refresh */
|
|
public delegate void Calltype_zfb_changeLoading(int id, LoadChange what);
|
|
public static Calltype_zfb_changeLoading zfb_changeLoading;
|
|
|
|
|
|
public delegate void Calltype_zfb_showDevTools(int id, bool show);
|
|
public static Calltype_zfb_showDevTools zfb_showDevTools;
|
|
|
|
|
|
/**
|
|
* Informs the browser if it's focused for keyboard input.
|
|
* Among other things, this controls if the blinking text cursor appears in an active text field.
|
|
*/
|
|
public delegate void Calltype_zfb_setFocused(int id, bool focused);
|
|
public static Calltype_zfb_setFocused zfb_setFocused;
|
|
|
|
|
|
/**
|
|
* Reports the mouse's current location.
|
|
* x and y are in the range [0,1]. (0, 0) is top-left, (1, 1) is bottom-right
|
|
*/
|
|
public delegate void Calltype_zfb_mouseMove(int id, float x, float y);
|
|
public static Calltype_zfb_mouseMove zfb_mouseMove;
|
|
|
|
|
|
public delegate void Calltype_zfb_mouseButton(int id, MouseButton button, bool down, int clickCount);
|
|
public static Calltype_zfb_mouseButton zfb_mouseButton;
|
|
|
|
|
|
/** Reports a mouse scroll. One "tick" of a scroll wheel is generally around 120 units. */
|
|
public delegate void Calltype_zfb_mouseScroll(int id, int deltaX, int deltaY);
|
|
public static Calltype_zfb_mouseScroll zfb_mouseScroll;
|
|
|
|
|
|
/**
|
|
* Report a key down/up event. Repeated "virtual" keystrokes are simulated by repeating the down event without
|
|
* an interveneing up event.
|
|
*/
|
|
public delegate void Calltype_zfb_keyEvent(int id, bool down, int windowsKeyCode);
|
|
public static Calltype_zfb_keyEvent zfb_keyEvent;
|
|
|
|
|
|
/**
|
|
* Report a typed character. This typically interleaves with calls to zfb_keyEvent
|
|
*/
|
|
public delegate void Calltype_zfb_characterEvent(int id, int character, int windowsKeyCode);
|
|
public static Calltype_zfb_characterEvent zfb_characterEvent;
|
|
|
|
|
|
/** Register a function to call when console.log etc. is called in the browser. */
|
|
public delegate void Calltype_zfb_registerConsoleCallback(int id, ConsoleFunc callback);
|
|
public static Calltype_zfb_registerConsoleCallback zfb_registerConsoleCallback;
|
|
|
|
|
|
public delegate void Calltype_zfb_evalJS(int id, string script, string scriptURL);
|
|
public static Calltype_zfb_evalJS zfb_evalJS;
|
|
|
|
|
|
/** Registers a callback to call when window._zfb_event(int, string) is called in the browser. */
|
|
public delegate void Calltype_zfb_registerJSCallback(int id, ForwardJSCallFunc cb);
|
|
public static Calltype_zfb_registerJSCallback zfb_registerJSCallback;
|
|
|
|
|
|
/** Registers a callback that is called when something from ChangeType happens. */
|
|
public delegate void Calltype_zfb_registerChangeCallback(int id, ChangeFunc cb);
|
|
public static Calltype_zfb_registerChangeCallback zfb_registerChangeCallback;
|
|
|
|
|
|
/**
|
|
* Gets the current mouse cursor. If the type is CursorType.Custom, width and height will be filled with
|
|
* the width and height of the custom cursor.
|
|
*/
|
|
public delegate CursorType Calltype_zfb_getMouseCursor(int id, out int width, out int height);
|
|
public static Calltype_zfb_getMouseCursor zfb_getMouseCursor;
|
|
|
|
|
|
/**
|
|
* Call this if zfb_getMouseCursor tells you there's a custom cursor.
|
|
* This will fill buffer (RGBA bottom-top, 4 bytes * width * height) with the contents of the cursor.
|
|
* Use the size you got from zfb_getMouseCursor.
|
|
* If width or height don't match the results from zfb_getMouseCursor, does nothing.
|
|
*
|
|
* {hotX} and {hoyY} will be filled with the cursor's hotspot.
|
|
*/
|
|
public delegate void Calltype_zfb_getMouseCustomCursor(int id, IntPtr buffer, int width, int height, out int hotX, out int hotY);
|
|
public static Calltype_zfb_getMouseCustomCursor zfb_getMouseCustomCursor;
|
|
|
|
|
|
/** Registers a DisplayDialogFunc for this browser. */
|
|
public delegate void Calltype_zfb_registerDialogCallback(int id, DisplayDialogFunc cb);
|
|
public static Calltype_zfb_registerDialogCallback zfb_registerDialogCallback;
|
|
|
|
|
|
/** Callback for a dialog. See the docs on DisplayDialogFunc. */
|
|
public delegate void Calltype_zfb_sendDialogResults(int id, bool affirmed, string text1, string text2);
|
|
public static Calltype_zfb_sendDialogResults zfb_sendDialogResults;
|
|
|
|
|
|
/** Registers a NewWindowFunc for pop ups. */
|
|
public delegate void Calltype_zfb_registerPopupCallback(int id, NewWindowAction windowAction, ZFBSettings baseSettings, NewWindowFunc cb);
|
|
public static Calltype_zfb_registerPopupCallback zfb_registerPopupCallback;
|
|
|
|
|
|
/** Registers a ShowContextMenuFunc for the context menu. */
|
|
public delegate void Calltype_zfb_registerContextMenuCallback(int id, ShowContextMenuFunc cb);
|
|
public static Calltype_zfb_registerContextMenuCallback zfb_registerContextMenuCallback;
|
|
|
|
|
|
/**
|
|
* After your ShowContextMenuFunc has been called,
|
|
* call this to report what item the user selected.
|
|
* If the menu was canceled, send -1.
|
|
*/
|
|
public delegate void Calltype_zfb_sendContextMenuResults(int id, int commandId);
|
|
public static Calltype_zfb_sendContextMenuResults zfb_sendContextMenuResults;
|
|
|
|
|
|
/**
|
|
* Sends a command, such as copy, paste, or select to the focused frame in the given browser.
|
|
*/
|
|
public delegate void Calltype_zfb_sendCommandToFocusedFrame(int id, FrameCommand command);
|
|
public static Calltype_zfb_sendCommandToFocusedFrame zfb_sendCommandToFocusedFrame;
|
|
|
|
|
|
/** Fetches all the cookies, calling the given callback for every cookie. */
|
|
public delegate void Calltype_zfb_getCookies(int id, GetCookieFunc cb);
|
|
public static Calltype_zfb_getCookies zfb_getCookies;
|
|
|
|
|
|
/** Alters the given cookie as specified. */
|
|
public delegate void Calltype_zfb_editCookie(int id, NativeCookie cookie, CookieAction action);
|
|
public static Calltype_zfb_editCookie zfb_editCookie;
|
|
|
|
|
|
/**
|
|
* Deletes all the cookies.
|
|
* (Though it takes a browser, this will typically clear all cookies for all browsers.)
|
|
*/
|
|
public delegate void Calltype_zfb_clearCookies(int id);
|
|
public static Calltype_zfb_clearCookies zfb_clearCookies;
|
|
|
|
/**
|
|
* Take an action on a download.
|
|
* fileName is ignored except when beginning a download.
|
|
* At the outset:
|
|
* Begin: Starts the download. Saves to the given file if given. If fileName is null, the user will be prompted.
|
|
* Cancel: Does nothing with a download.
|
|
* After starting a download:
|
|
* Pause, Cancel, Resume: Does what it says on the tin.
|
|
* Once a download is finished or canceled it is not valid to call this function for that download any more.
|
|
*/
|
|
public delegate void Calltype_zfb_downloadCommand(int id, int downloadId, DownloadAction command, string fileName);
|
|
public static Calltype_zfb_downloadCommand zfb_downloadCommand;
|
|
|
|
|
|
#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
|
|
/**
|
|
* Creates a new OS-native window in this process, returning an id.
|
|
*/
|
|
public delegate int Calltype_zfb_windowCreate(String title, WindowCallbackFunc eventHandler);
|
|
public static Calltype_zfb_windowCreate zfb_windowCreate;
|
|
|
|
/**
|
|
* Renders the contents of the given browser into the given OS window.
|
|
*/
|
|
public delegate void Calltype_zfb_windowRender(int windowId, int browserId);
|
|
public static Calltype_zfb_windowRender zfb_windowRender;
|
|
|
|
/**
|
|
* Closes the given window.
|
|
* Pass -1 for the id to close all windows.
|
|
*/
|
|
public delegate void Calltype_zfb_windowClose(int windowId);
|
|
public static Calltype_zfb_windowClose zfb_windowClose;
|
|
#endif
|
|
}
|
|
|
|
}
|