BrowserNative.cs 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139
  1. #if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && !UNITY_EDITOR)
  2. #define ZF_WINDOWS
  3. #endif
  4. #define PROXY_BROWSER_API
  5. using System;
  6. using System.Collections;
  7. using System.Collections.Generic;
  8. using System.IO;
  9. using UnityEngine;
  10. using System.Runtime.InteropServices;
  11. using System.Text;
  12. using UnityEngine.Assertions;
  13. using System.Reflection;
  14. using UnityEngine.Profiling;
  15. #if UNITY_EDITOR
  16. using UnityEditor;
  17. using System.Diagnostics;
  18. using Debug = UnityEngine.Debug;
  19. #endif
  20. // ReSharper disable InconsistentNaming
  21. namespace ZenFulcrum.EmbeddedBrowser {
  22. /**
  23. * Wrapper/native callbacks for CEF browser implementation.
  24. * When changing code in this file you may have to restart the Unity Editor for things to get working again.
  25. *
  26. * Note that callbacks given to the native side may be invoked on any thread.
  27. *
  28. * Make sure IntPtrs are pinned and callbacks are kept alive from GC while their object lives.
  29. */
  30. public static class BrowserNative {
  31. #if UNITY_EDITOR
  32. public const int DebugPort = 9848;
  33. #else
  34. public const int DebugPort = 9849;
  35. #endif
  36. public static bool NativeLoaded { get; private set; }
  37. public static bool SymbolsLoaded { get; private set; }
  38. /// <summary>
  39. /// Lock this object before touching any of the zfb_* functions outside the main thread.
  40. /// (While many of them are thread safe, the shared library can be unloaded, leading
  41. /// to a possible race condition at shutdown. For example thread A grabs the value of zfb_sendRequestData,
  42. /// the main thread unloads the shared library, then thread A tries to execute the pointer it has for
  43. /// zfb_sendRequestData, resulting in sadness.)
  44. /// </summary>
  45. public static readonly object symbolsLock = new object();
  46. #if PROXY_BROWSER_API
  47. public const bool UsingAPIProxy = true;
  48. #else
  49. public const bool UsingAPIProxy = false;
  50. #endif
  51. /**
  52. * List of command-line switches given to Chromium.
  53. * http://peter.sh/experiments/chromium-command-line-switches/
  54. *
  55. * If you want to change this, be sure to change it before LoadNative gets called.
  56. *
  57. * Adding or removing flags may lead to instability and/or insecurity.
  58. * Make sure you understand what a flag does before you use it.
  59. * Be sure to test your use cases thoroughly after changing any flags as
  60. * things are more likely to crash or break if you aren't using the default
  61. * configuration.
  62. *
  63. * Extra non-Chromium arguments:
  64. * --zf-cef-log-verbose
  65. * if enabled, we'll write a lot more CEF/Chromium logging to your editor/player log file than usual
  66. * --zf-log-internal
  67. * If enabled, some extra logs will be dumped to the current working directory.
  68. * --zf-browser-update-delay=N
  69. * N = maximum update loop delay, in milliseconds. Default = 10
  70. * Tune the message loop update speed for your preferred CPU/usage tradeoff.
  71. * Ideally this wouldn't be necessary, but CEF seems to struggle with higher rendering framerates
  72. * if you only tick it when it schedules a tick.
  73. *
  74. */
  75. public static List<string> commandLineSwitches = new List<string>() {
  76. //Smooth scrolling tends to make scrolling act wonky or break.
  77. "--disable-smooth-scrolling",
  78. //If you install the PPAPI version of Flash on your system this tells Chromium to try to use it.
  79. //(download at https://get.adobe.com/flashplayer/otherversions/)
  80. "--enable-system-flash",
  81. //getUserMedia (microphone/webcam).
  82. //Turning this on has security implications, it appears there's no
  83. //CEF API for authorizing access, it just allows it. (ergo, any website can record the user)
  84. //"--enable-media-stream",
  85. //Enable these to get a higher browser framerate at the expense of more CPU usage:
  86. // "--zf-browser-update-delay=1",
  87. // "--disable-gpu-vsync",
  88. //If you want to specify a proxy by hand:
  89. //"--proxy-server=localhost:8000",
  90. //"--zf-log-cef-verbose",
  91. //"--zf-log-internal",
  92. };
  93. /**
  94. * WebResources used to resolve local requests.
  95. *
  96. * This may be replaced with an implementation of your choice, but be sure to set it up before requesting
  97. * any URLs.
  98. */
  99. public static WebResources webResources;
  100. public static string LocalUrlPrefix { get { return "https://game.local/"; } }
  101. private static void LogCallback(string message) {
  102. Debug.Log("ZFWeb: " + message);
  103. }
  104. private static string _profilePath = null;
  105. /**
  106. * Where should we save the user's data and cookies? Leave null to not save them.
  107. * Set before the browser system initializes. Also, restart the Editor to apply changes.
  108. */
  109. public static string ProfilePath {
  110. get { return _profilePath; }
  111. set {
  112. if (NativeLoaded) throw new InvalidOperationException("ProfilePath must be set before initializing the browser system.");
  113. _profilePath = value;
  114. }
  115. }
  116. /**
  117. * Loads the shared library and the function symbols so we can call zfb_* functions.
  118. */
  119. public static void LoadSymbols() {
  120. if (SymbolsLoaded) return;
  121. var dirs = FileLocations.Dirs;
  122. HandLoadSymbols(dirs.binariesPath);
  123. }
  124. public static void LoadNative() {
  125. if (NativeLoaded) return;
  126. Profiler.BeginSample("BrowserNative.LoadNative");
  127. if (webResources == null) {
  128. //if the user hasn't given us a WebResources to use, use the default
  129. #if UNITY_EDITOR
  130. webResources = new EditorWebResources();
  131. #else
  132. var swr = new StandaloneWebResources(Application.dataPath + "/" + StandaloneWebResources.DefaultPath);
  133. swr.LoadIndex();
  134. webResources = swr;
  135. #endif
  136. }
  137. //For Editor/debug builds, we'll open a port you can just http:// to inspect pages.
  138. //Don't do this for real builds, though. It makes it really, really easy for the end user to call
  139. //random JS in the page, potentially affecting or bypassing game logic.
  140. var debugPort = Debug.isDebugBuild ? DebugPort : 0;
  141. var dirs = FileLocations.Dirs;
  142. #if UNITY_EDITOR_OSX
  143. FixProcessPermissions(dirs);
  144. #endif
  145. #if UNITY_STANDALONE_WIN && !UNITY_EDITOR
  146. //make sure the child processes can be started (their dependent .dlls are next to the main .exe, not in the Plugins folder)
  147. var loadDir = Directory.GetParent(Application.dataPath).FullName;
  148. var path = Environment.GetEnvironmentVariable("PATH");
  149. path += ";" + loadDir;
  150. Environment.SetEnvironmentVariable("PATH", path);
  151. #elif UNITY_EDITOR_WIN
  152. //help it find our .dlls
  153. var path = Environment.GetEnvironmentVariable("PATH");
  154. path += ";" + dirs.binariesPath;
  155. Environment.SetEnvironmentVariable("PATH", path);
  156. #elif UNITY_EDITOR_LINUX
  157. Environment.SetEnvironmentVariable("ZF_CEF_FORCE_EXE_DIR", Directory.GetParent(dirs.subprocessFile).FullName);
  158. #endif
  159. LoadSymbols();
  160. StandaloneShutdown.Create();
  161. //There never should be any, but just in case, destroy any existing browsers on a re-init
  162. zfb_destroyAllBrowsers();
  163. //Caution: Careful with these functions you pass to native. The Unity Editor will
  164. //reload assemblies, leaving the function pointers dangling. If any native calls try to use them
  165. //before we load back up and re-register them we can crash.
  166. //To prevent this, we call zfb_setCallbacksEnabled to disable callbacks before we get unloaded.
  167. zfb_setDebugFunc(LogCallback);
  168. zfb_setLocalRequestHandler(NewRequestCallback);
  169. zfb_setCallbacksEnabled(true);
  170. var settings = new ZFBInitialSettings() {
  171. cefPath = dirs.resourcesPath,
  172. localePath = dirs.localesPath,
  173. subprocessFile = dirs.subprocessFile,
  174. userAgent = UserAgent.GetUserAgent(),
  175. logFile = dirs.logFile,
  176. profilePath = _profilePath,
  177. debugPort = debugPort,
  178. #if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && !UNITY_EDITOR)
  179. //CEF doesn't have the multithreaded loop implemented on 'cept Windows
  180. multiThreadedMessageLoop = 1,
  181. #else
  182. multiThreadedMessageLoop = 0,
  183. #endif
  184. };
  185. foreach (var arg in commandLineSwitches) zfb_addCLISwitch(arg);
  186. var initRes = zfb_init(settings);
  187. if (!initRes) throw new Exception("Failed to initialize browser system.");
  188. NativeLoaded = true;
  189. Profiler.EndSample();
  190. AppDomain.CurrentDomain.DomainUnload += (sender, args) => {
  191. //Shutdown should happen StandaloneShutdown, but in some cases, like the Unity Editor
  192. //reloading assemblies, we don't get OnApplicationQuit because we didn't "quit", even though
  193. //everything gets shut down.
  194. //Make sure the backend shuts down, in this case, or it will crash when we try to start it again.
  195. UnloadNative();
  196. };
  197. }
  198. private static void FixProcessPermissions(FileLocations.CEFDirs dirs) {
  199. /*
  200. * The package we get from the Asset Store probably won't have the right executable permissions for
  201. * ZFGameBrowser for OS X, so let's fix that for the user right now.
  202. */
  203. var attrs = (uint)File.GetAttributes(dirs.subprocessFile);
  204. //From https://github.com/mono/mono/blob/master/mono/io-layer/io.c under SetFileAttributes() (also noted in FileAttributes.cs):
  205. //"Currently we only handle one *internal* case [...]: 0x80000000, which means `set executable bit'"
  206. //Let's use that now.
  207. attrs |= 0x80000000;
  208. //Make it executable.
  209. File.SetAttributes(dirs.subprocessFile, unchecked((FileAttributes)attrs));
  210. }
  211. private static IntPtr moduleHandle;
  212. /// <summary>
  213. /// Loads the browser symbols.
  214. ///
  215. /// We don't use DllImport for a few reasons, historically for DEEPBIND support and multiple CEF versions in the same process,
  216. /// but now mostly so we can unload the .dll whenever we want and to simplify picking and loading our shared library how we want.
  217. /// </summary>
  218. /// <param name="binariesPath"></param>
  219. private static void HandLoadSymbols(string binariesPath) {
  220. Profiler.BeginSample("BrowserNative.HandLoadSymbols");
  221. #if PROXY_BROWSER_API
  222. var coreType = "ZFProxyWeb";
  223. #else
  224. var coreType = "ZFEmbedWeb";
  225. #endif
  226. #if UNITY_EDITOR_OSX || (!UNITY_EDITOR && UNITY_STANDALONE_OSX)
  227. var libFile = binariesPath + "/lib" + coreType + ".dylib";
  228. #elif UNITY_EDITOR_LINUX || (!UNITY_EDITOR && UNITY_STANDALONE_LINUX)
  229. var libFile = binariesPath + "/lib" + coreType + ".so";
  230. #elif UNITY_EDITOR_WIN || (!UNITY_EDITOR && UNITY_STANDALONE_WIN)
  231. var libFile = binariesPath + "/" + coreType + ".dll";
  232. #else
  233. #error Unknown OS.
  234. #endif
  235. //Debug.Log("Loading " + libFile);
  236. moduleHandle = OpenLib(libFile);
  237. //Now go through and fill our functions with life.
  238. int i = 0;
  239. var fields = typeof(BrowserNative).GetFields(BindingFlags.Static | BindingFlags.Public);
  240. foreach (var field in fields) {
  241. if (!field.Name.StartsWith("zfb_")) continue;
  242. var fp = GetFunc(moduleHandle, field.Name);
  243. var func = Marshal.GetDelegateForFunctionPointer(fp, field.FieldType);
  244. field.SetValue(null, func);
  245. ++i;
  246. }
  247. //Debug.Log("Loaded " + i + " symbols");
  248. SymbolsLoaded = true;
  249. Profiler.EndSample();
  250. }
  251. /// <summary>
  252. /// Clears out the symbols so, if the shared library has been unloaded, we get null exceptions instead
  253. /// of crashes.
  254. /// </summary>
  255. private static void ClearSymbols() {
  256. SymbolsLoaded = false;
  257. var fields = typeof(BrowserNative).GetFields(BindingFlags.Static | BindingFlags.Public);
  258. foreach (var field in fields) {
  259. if (!field.Name.StartsWith("zfb_")) continue;
  260. field.SetValue(null, null);
  261. }
  262. }
  263. private static string GetLibError() {
  264. #if ZF_WINDOWS
  265. return new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()).Message;
  266. #else
  267. return Marshal.PtrToStringAnsi(dlerror());
  268. #endif
  269. }
  270. private static IntPtr OpenLib(string name) {
  271. #if ZF_WINDOWS
  272. var handle = LoadLibrary(name);
  273. if (handle == IntPtr.Zero) {
  274. // throw new DllNotFoundException("ZFBrowser failed to load " + name + ": " + Marshal.GetLastWin32Error());
  275. throw new DllNotFoundException("ZFBrowser failed to load " + name + ": " +
  276. new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()).Message
  277. );
  278. }
  279. return handle;
  280. #else
  281. //Call this now because running a DllImport method the first time will end up calling dlerror
  282. //which will clear the error we were trying to get from dlerror.
  283. dlerror();
  284. /*
  285. Linux:
  286. In the editor, we need to use RTLD_DEEPBIND so libZFEmbedWeb.so gets the symbols from zf_cef.so
  287. instead of the ones that are already loaded in the Unity editor.
  288. However, for standalone, we need to NOT use RTLD_DEEPBIND because the standlaone appers to override
  289. {operator new} and we get nasty memory crashes if we have two allocaros in use. (Also, we don't need
  290. deep binding because there's no other copy of CEF flaoting around.)
  291. */
  292. #if UNITY_EDITOR
  293. var handle = dlopen(name, (int)(DLFlags.RTLD_LAZY | DLFlags.RTLD_DEEPBIND));
  294. #else
  295. var handle = dlopen(name, (int)(DLFlags.RTLD_LAZY));
  296. #endif
  297. if (handle == IntPtr.Zero) {
  298. throw new DllNotFoundException("ZFBrowser failed to load " + name + ": " + getDlError());
  299. }
  300. return handle;
  301. #endif
  302. }
  303. private static void CloseLib() {
  304. if (moduleHandle == IntPtr.Zero) return;
  305. ClearSymbols();
  306. #if ZF_WINDOWS
  307. var success = FreeLibrary(moduleHandle);
  308. #else
  309. var success = dlclose(moduleHandle) == 0;
  310. #endif
  311. if (!success) {
  312. throw new DllNotFoundException(
  313. "Failed to unload library: " +
  314. GetLibError()
  315. );
  316. }
  317. //Debug.Log("Unloaded shared library");
  318. moduleHandle = IntPtr.Zero;
  319. }
  320. private static IntPtr GetFunc(IntPtr libHandle, string fnName) {
  321. #if ZF_WINDOWS
  322. var addr = GetProcAddress(libHandle, fnName);
  323. if (addr == IntPtr.Zero) {
  324. throw new DllNotFoundException("ZFBrowser failed to load method " + fnName + ": " + Marshal.GetLastWin32Error());
  325. }
  326. return addr;
  327. #else
  328. var fp = dlsym(libHandle, fnName);
  329. if (fp == IntPtr.Zero) {
  330. throw new DllNotFoundException("ZFBrowser failed to load method " + fnName + ": " + getDlError());
  331. }
  332. return fp;
  333. #endif
  334. }
  335. [Flags]
  336. public enum DLFlags {
  337. RTLD_LAZY = 1,
  338. RTLD_NOW = 2,
  339. RTLD_DEEPBIND = 8,
  340. }
  341. [DllImport("__Internal")] static extern IntPtr dlopen(string filename, int flags);
  342. [DllImport("__Internal")] static extern IntPtr dlsym(IntPtr handle, string symbol);
  343. [DllImport("__Internal")] static extern int dlclose(IntPtr handle);
  344. [DllImport("__Internal")] static extern IntPtr dlerror();
  345. private static string getDlError() {
  346. var err = dlerror();
  347. return Marshal.PtrToStringAnsi(err);
  348. }
  349. [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
  350. static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
  351. [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
  352. static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
  353. [DllImport("kernel32", SetLastError = true)]
  354. private static extern bool FreeLibrary(IntPtr hModule);
  355. private static void NewRequestCallback(int requestId, string url) {
  356. webResources.HandleRequest(requestId, url);
  357. }
  358. /** Shuts down the native browser library and CEF. */
  359. public static void UnloadNative() {
  360. if (!NativeLoaded) return;
  361. //Debug.Log("Stop CEF");
  362. zfb_destroyAllBrowsers();
  363. zfb_shutdown();
  364. zfb_setCallbacksEnabled(false);
  365. NativeLoaded = false;
  366. CloseLib();
  367. }
  368. /** Call this with a message to debug it to a console somewhere. */
  369. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  370. public delegate void MessageFunc(string message);
  371. /**
  372. * Callback for starting a new local request.
  373. * url is the url requested
  374. * At present only GET requests with no added headers are supported.
  375. * After this is called, you are responsible for calling zfb_sendRequestHeaders (once)
  376. * then zfb_sendRequestData (as much as needed) to finish up the request.
  377. */
  378. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  379. public delegate void NewRequestFunc(int requestId, string url);
  380. /** Called when the native backend is ready to start receiving orders. */
  381. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  382. public delegate void ReadyFunc(int browserId);
  383. /** Called on console.log, console.err, etc. */
  384. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  385. public delegate void ConsoleFunc(int browserId, string message, string source, int line);
  386. /**
  387. * Called when JS calls back to us.
  388. * callbackId is the first argument,
  389. * data (UTF-8 null-terminated string) (and its included size) are the second argument.
  390. */
  391. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  392. public delegate void ForwardJSCallFunc(int browserId, int callbackId, string data, int size);
  393. /**
  394. * Called when a browser opens a new window.
  395. * creatorBrowserId - id of the browser that cause the window to be created
  396. * newBrowserId - a newly created (as if by zfb_createBrowser) browser tab
  397. *
  398. * May be called on any thread.
  399. */
  400. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  401. public delegate void NewWindowFunc(int creatorBrowserId, int newBrowserId, IntPtr initialURL);
  402. /**
  403. * Called when an item from ChangeType happens.
  404. * See the documentation for the given ChangeType for info on what the args mean or how to get more information.
  405. */
  406. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  407. public delegate void ChangeFunc(int browserId, ChangeType changeType, string arg1);
  408. /**
  409. * This is called when the browser wants to display a dialog of some sort.
  410. * dialogType - the type, or DLT_HIDE to hide any existing dialogs.
  411. * dialogText - main text for the dialog, usually from in-page JavaScript
  412. * initialPromptText - if we are doing a JavaScript prompt(), the default text to display
  413. * sourceURL - the URL of the page that is causing the dialog
  414. *
  415. * Once the user has responded to the dialog (if we were showing one), call zfb_sendDialogResults
  416. * with the user's input.
  417. */
  418. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  419. public delegate void DisplayDialogFunc(
  420. int browserId, DialogType dialogType, IntPtr dialogText,
  421. IntPtr initialPromptText, IntPtr sourceURL
  422. );
  423. /**
  424. * Called by the backend when a context menu should be shown or hidden.
  425. * If menuJSON is null, hide the context menu.
  426. * If it's not, show the given menu and eventually call zfb_sendContextMenuResults.
  427. * For more information on the menu format, look at BrowserDialogs.html
  428. *
  429. * x and y report the position the menu was summoned, relative to the top-left of the view.
  430. * origin indicates on what type of item the context menu was created.
  431. */
  432. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  433. public delegate void ShowContextMenuFunc(int browserId, string menuJSON, int x, int y, ContextMenuOrigin origin);
  434. /**
  435. * Used with zfb_getCookies, this will be called once for each cookie.
  436. */
  437. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  438. public delegate void GetCookieFunc(NativeCookie cookie);
  439. /**
  440. * Called when nav state (can go back/forward, loaded, url) changes.
  441. */
  442. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  443. public delegate void NavStateFunc(int browserId, bool canGoBack, bool canGoForward, bool lodaing, IntPtr url);
  444. /**
  445. * Called by a native OS windows gets an event like mouse move click, etc.
  446. * data contains json details on the event
  447. */
  448. [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  449. public delegate void WindowCallbackFunc(int windowId, IntPtr data);
  450. public enum LoadChange : int {
  451. LC_STOP = 1,
  452. LC_RELOAD,
  453. LC_FORCE_RELOAD,
  454. }
  455. public enum MouseButton : int {
  456. MBT_LEFT = 0,
  457. MBT_MIDDLE,
  458. MBT_RIGHT,
  459. }
  460. public enum ChangeType : int {
  461. /** The cursor has changed. Use zfb_getMouseCursor/zfb_getMouseCustomCursor to see what it is now. */
  462. CHT_CURSOR = 0,
  463. /** The browser has been closed and can no longer receive commands. */
  464. CHT_BROWSER_CLOSE,
  465. /**
  466. * We have the HTML for the top-level page.
  467. * arg1 (JSON) contains HTTP {status} code and the {url}
  468. * Note that successfully fetching errors from a server (404, 500) are treated
  469. * as successful, CHT_FETCH_FAILED won't be triggered.
  470. */
  471. CHT_FETCH_FINISHED,
  472. /**
  473. * Failed to fetch a page (timeout, network issues, etc)
  474. * arg1 (JSON) contains an {error} code and the {url}
  475. */
  476. CHT_FETCH_FAILED,
  477. /**
  478. * The page has reached onload
  479. * arg1 (JSON) contains HTTP {status} code and the {url}
  480. */
  481. CHT_LOAD_FINISHED,
  482. /** SSL certificate error. arg1 has some JSON about the issue. Often followed by a CHT_FETCH_FAILED */
  483. CHT_CERT_ERROR,
  484. /** Renderer process crashed/was killed/etc. */
  485. CHT_SAD_TAB,
  486. /**
  487. * The user/page has initialized a download.
  488. * arg1 (JSON) contains:
  489. * download {id}
  490. * {mimeType}
  491. * {url} of the download
  492. * {originalURL} of the download before redirection
  493. * {suggestedName} you might save the file as
  494. * {size} number of bytes in the download (if known)
  495. * {contentDisposition}
  496. *
  497. * Call zfb_downloadCommand(browserId, download["id"], DownloadAction.xxyy, fileName) to cancel or save the file
  498. * (and afterward control it).
  499. */
  500. CHT_DOWNLOAD_STARTED,
  501. /**
  502. * Progress/status update on a download.
  503. * arg1 (JSON) contains:
  504. * download {id}
  505. * {speed} in bytes/sec
  506. * {percentComplete} int in [0, 100], or -1 if unknown
  507. * {received} number of bytes received
  508. * {statusStr} download status. One of: complete, canceled, working, unknown
  509. * {fullPath} we are saving to. (If you had the user pick the destination you can get it here.)
  510. *
  511. * Call zfb_downloadCommand(browserId, download["id"], DownloadAction.xxyy, null) to cancel/pause/resume the download.
  512. */
  513. CHT_DOWNLOAD_STATUS,
  514. /**
  515. * The element with keyboard focus has changed.
  516. * You can use this to show/hide a keyboard when needed.
  517. * arg1 (JSON) contains:
  518. * {tagName} of the focused node, or empty of no node is focused (focus loss)
  519. * {editable} true if it's some sort of editable text
  520. * textual {value} of the node, if it's simple (doesn't work for things like ContentEditable nodes)
  521. */
  522. CHT_FOCUSED_NODE,
  523. }
  524. public enum DownloadAction {
  525. Begin,
  526. Cancel,
  527. Pause,
  528. Resume,
  529. }
  530. /** @see cef_cursor_type_t in cef_types.h */
  531. public enum CursorType : int {
  532. Pointer = 0,
  533. Cross,
  534. Hand,
  535. IBeam,
  536. Wait,
  537. Help,
  538. EastResize,
  539. NorthResize,
  540. NorthEastResize,
  541. NorthWestResize,
  542. SouthResize,
  543. SouthEastResize,
  544. SouthWestResize,
  545. WestResize,
  546. NorthSouthResize,
  547. EastWestResize,
  548. NorthEastSouthWestResize,
  549. NorthWestSouthEastResize,
  550. ColumnResize,
  551. RowResize,
  552. MiddlePanning,
  553. EastPanning,
  554. NorthPanning,
  555. NorthEastPanning,
  556. NorthWestPanning,
  557. SouthPanning,
  558. SouthEastPanning,
  559. SouthWestPanning,
  560. WestPanning,
  561. Move,
  562. VerticalText,
  563. Cell,
  564. ContextMenu,
  565. Alias,
  566. Progress,
  567. NoDrop,
  568. Copy,
  569. None,
  570. NotAllowed,
  571. ZoomIn,
  572. ZoomOut,
  573. Grab,
  574. Grabbing,
  575. Custom,
  576. }
  577. public enum DialogType {
  578. DLT_HIDE = 0,
  579. DLT_ALERT,
  580. DLT_CONFIRM,
  581. DLT_PROMPT,
  582. DLT_PAGE_UNLOAD,
  583. DLT_PAGE_RELOAD,//like unload, but the user is just refreshing the page
  584. DLT_GET_AUTH,
  585. };
  586. public enum NewWindowAction {
  587. NWA_IGNORE = 1,
  588. NWA_REDIRECT,
  589. NWA_NEW_BROWSER,
  590. NWA_NEW_WINDOW,
  591. };
  592. [Flags]
  593. public enum ContextMenuOrigin {
  594. Editable = 1 << 1,
  595. Image = 1 << 2,
  596. Selection = 1 << 3,
  597. Other = 1 << 0,
  598. }
  599. public enum FrameCommand {
  600. Undo,
  601. Redo,
  602. Cut,
  603. Copy,
  604. Paste,
  605. Delete,
  606. SelectAll,
  607. ViewSource,
  608. };
  609. public enum CookieAction {
  610. Delete,
  611. Create,
  612. };
  613. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  614. public struct ZFBInitialSettings {
  615. public string cefPath, localePath, subprocessFile, userAgent, logFile, profilePath;
  616. public int debugPort, multiThreadedMessageLoop;
  617. }
  618. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  619. public struct ZFBSettings {
  620. public int bgR, bgG, bgB, bgA;
  621. public int offscreen;
  622. }
  623. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  624. public struct RenderData {
  625. public IntPtr pixels;
  626. public int w, h;
  627. }
  628. [StructLayout(LayoutKind.Sequential, Pack = 1)]
  629. public class NativeCookie {
  630. public string name, value, domain, path;
  631. public string creation, lastAccess, expires;
  632. public byte secure, httpOnly;
  633. }
  634. /*
  635. * See HandLoadSymbols() for an explanation of what's going on here and why we use a bunch of delegates instead
  636. * of DllImport.
  637. *
  638. * Don't use this API directly unless you want to deal with things breaking.
  639. * Though it is accessible, it's not considered part of the public API for versioning purposes.
  640. * That, and you can shoot yourself in the foot and crash your app.
  641. *
  642. * Also, if you want to call any of these functions off the main thread make sure:
  643. * - It's documented as supporting such.
  644. * - To acquire a lock on symbolsLock first. (See its docs for why.)
  645. */
  646. /** Does nothing. */
  647. public delegate void Calltype_zfb_noop();
  648. public static Calltype_zfb_noop zfb_noop;
  649. /**
  650. * Allocates and initializes a block of memory suitable for use with LoadRawTextureData to clear a texture
  651. * to the given color.
  652. * Call zfb_free on the pointer when your are done using it.
  653. * Does not require the browser system to be initialized, thread safe.
  654. */
  655. public delegate IntPtr Calltype_zfb_flatColorTexture(int pixelCount, int r, int g, int b, int a);
  656. public static Calltype_zfb_flatColorTexture zfb_flatColorTexture;
  657. /**
  658. * Copies from a zfb_getImage buffer to a Color32[] buffer.
  659. * Does not require the browser system to be initialized, thread safe.
  660. */
  661. public delegate void Calltype_zfb_copyToColor32(IntPtr src, IntPtr dest, int pixelCount);
  662. public static Calltype_zfb_copyToColor32 zfb_copyToColor32;
  663. /**
  664. * Some functions allocate memory to give you a response (see their docs). Call this to free it.
  665. * Does not require the browser system to be initialized, thread safe.
  666. */
  667. public delegate void Calltype_zfb_free(IntPtr mem);
  668. public static Calltype_zfb_free zfb_free;
  669. /**
  670. * Plain old memcpy. Because sometimes Marshal.Copy falls short of our needs.
  671. * Does not require the browser system to be initialized, thread safe.
  672. */
  673. public delegate void Calltype_zfb_memcpy(IntPtr dst, IntPtr src, int size);
  674. public static Calltype_zfb_memcpy zfb_memcpy;
  675. /**
  676. * Returns the Chrome(ium) version as a static C string.
  677. * Does not require the browser system to be initialized, thread safe.
  678. */
  679. public delegate IntPtr Calltype_zfb_getVersion();
  680. public static Calltype_zfb_getVersion zfb_getVersion;
  681. /** Sets a function to call for Debug.Log-style messages. */
  682. public delegate void Calltype_zfb_setDebugFunc(MessageFunc debugFunc);
  683. public static Calltype_zfb_setDebugFunc zfb_setDebugFunc;
  684. /** Sets callbacks for when a local (https://game.local/) request is started. */
  685. public delegate void Calltype_zfb_setLocalRequestHandler(NewRequestFunc requestFunc);
  686. public static Calltype_zfb_setLocalRequestHandler zfb_setLocalRequestHandler;
  687. /**
  688. * Sends the headers for a response.
  689. * responseLength should be the number of bytes in the response, or -1 if unknown.
  690. * headersJSON should contain a string:string map of headers, JSON encoded
  691. * - You should include a "Content-Type" header.
  692. * - You may also include a ":status:" pseudoheader to set the status to a non-200 value
  693. * - You may also include a ":statusText:" pseudoheader to set the status text
  694. * After calling this, call zfb_sendRequestData to send the actual response body.
  695. *
  696. * May be called from any thread.
  697. */
  698. public delegate void Calltype_zfb_sendRequestHeaders(int requestId, int responseLength, string headersJSON);
  699. public static Calltype_zfb_sendRequestHeaders zfb_sendRequestHeaders;
  700. /**
  701. * Sends the body for a response after calling zfb_sendRequestHeaders.
  702. *
  703. * You must always write at least one byte except as described below.
  704. *
  705. * If you sent a responseLength >= 0, make sure all calls to this function add up to exactly that value.
  706. * If you sent a responseLength < 0, call this a final time with size = 0 to signify the
  707. * end of the response.
  708. *
  709. * May be called from any thread.
  710. */
  711. public delegate void Calltype_zfb_sendRequestData(int requestId, IntPtr data, int dataSize);
  712. public static Calltype_zfb_sendRequestData zfb_sendRequestData;
  713. /** Enabled/disables user callbacks. Useful for disabling all callbacks when mono assemblies reload. */
  714. public delegate void Calltype_zfb_setCallbacksEnabled(bool enabled);
  715. public static Calltype_zfb_setCallbacksEnabled zfb_setCallbacksEnabled;
  716. /** Destroys all browser instances. */
  717. public delegate void Calltype_zfb_destroyAllBrowsers();
  718. public static Calltype_zfb_destroyAllBrowsers zfb_destroyAllBrowsers;
  719. /** Adds a command-line switch to Chromium, must call before zfb_init */
  720. public delegate void Calltype_zfb_addCLISwitch(string value);
  721. public static Calltype_zfb_addCLISwitch zfb_addCLISwitch;
  722. /** Initializes the system so we can start making browsers. */
  723. public delegate bool Calltype_zfb_init(ZFBInitialSettings settings);
  724. public static Calltype_zfb_init zfb_init;
  725. /** Shuts down the system. It cannot be re-initialized. */
  726. public delegate void Calltype_zfb_shutdown();
  727. public static Calltype_zfb_shutdown zfb_shutdown;
  728. /**
  729. * Creates a new browser, returning the id.
  730. * Call zfb_setReadyCallback and wait for it to fire before doing anything else.
  731. */
  732. public delegate int Calltype_zfb_createBrowser(ZFBSettings settings);
  733. public static Calltype_zfb_createBrowser zfb_createBrowser;
  734. /** Reports the number of un-destroyed browsers. Slow. */
  735. public delegate int Calltype_zfb_numBrowsers();
  736. public static Calltype_zfb_numBrowsers zfb_numBrowsers;
  737. /**
  738. * Closes and cleans up a browser instance.
  739. */
  740. public delegate void Calltype_zfb_destroyBrowser(int id);
  741. public static Calltype_zfb_destroyBrowser zfb_destroyBrowser;
  742. /** Call once per frame if the multi-threaded message loop isn't enabled. */
  743. public delegate void Calltype_zfb_tick();
  744. public static Calltype_zfb_tick zfb_tick;
  745. /**
  746. * Registers a function to call when the browser instance is ready to start taking orders.
  747. * {cb} may be executed immediately or on any thread.
  748. */
  749. public delegate void Calltype_zfb_setReadyCallback(int id, ReadyFunc cb);
  750. public static Calltype_zfb_setReadyCallback zfb_setReadyCallback;
  751. /** Resizes the browser. */
  752. public delegate void Calltype_zfb_resize(int id, int w, int h);
  753. public static Calltype_zfb_resize zfb_resize;
  754. /**
  755. * Adds the given browser {overlayBrowserId} as an overlay of this browser {browserId}.
  756. * The overlaid browser will appear transparently over the top of {browser}.
  757. * {overlayBrowser} must not have an overlay and must be sized exactly the same as {browser}.
  758. * Remove the overlay before closing either browser.
  759. *
  760. * While {overlayBrowser} is overlaying another browser, do not call zfb_getImage on it.
  761. */
  762. public delegate void Calltype_zfb_setOverlay(int browserId, int overlayBrowserId);
  763. public static Calltype_zfb_setOverlay zfb_setOverlay;
  764. /**
  765. * Gets the image data for the current frame.
  766. * Do not hang onto the returned data across frames or resizes.
  767. *
  768. * If there are no changes since last call, the pixel data will be null (unless you specify forceDirty).
  769. */
  770. public delegate RenderData Calltype_zfb_getImage(int id, bool forceDirty);
  771. public static Calltype_zfb_getImage zfb_getImage;
  772. /**
  773. * Registers a callback for nav state updates.
  774. * Keep track of what it tells you to answer questions like what the current URL is and if we can go back/forward.
  775. * (The URL overlaps a bit with CHT_FETCH_*, but this should fire earlier (when we start) as opposed to when it's done.)
  776. */
  777. public delegate void Calltype_zfb_registerNavStateCallback(int id, NavStateFunc callback);
  778. public static Calltype_zfb_registerNavStateCallback zfb_registerNavStateCallback;
  779. /**
  780. * Navigates to the given URL. If force it ture, it will go there right away.
  781. * If force is false, the pages that wish to can prompt the user and possibly cancel the
  782. * navigation.
  783. */
  784. public delegate void Calltype_zfb_goToURL(int id, string url, bool force);
  785. public static Calltype_zfb_goToURL zfb_goToURL;
  786. /**
  787. * Loads the given HTML string as if it were the given URL.
  788. * Use http://-like porotocols or else things may not work right.
  789. */
  790. public delegate void Calltype_zfb_goToHTML(int id, string html, string url);
  791. public static Calltype_zfb_goToHTML zfb_goToHTML;
  792. /** Go back (-1) or forward (1) */
  793. public delegate void Calltype_zfb_doNav(int id, int direction);
  794. public static Calltype_zfb_doNav zfb_doNav;
  795. public delegate void Calltype_zfb_setZoom(int id, double zoom);
  796. public static Calltype_zfb_setZoom zfb_setZoom;
  797. /** Stop, refresh, or force-refresh */
  798. public delegate void Calltype_zfb_changeLoading(int id, LoadChange what);
  799. public static Calltype_zfb_changeLoading zfb_changeLoading;
  800. public delegate void Calltype_zfb_showDevTools(int id, bool show);
  801. public static Calltype_zfb_showDevTools zfb_showDevTools;
  802. /**
  803. * Informs the browser if it's focused for keyboard input.
  804. * Among other things, this controls if the blinking text cursor appears in an active text field.
  805. */
  806. public delegate void Calltype_zfb_setFocused(int id, bool focused);
  807. public static Calltype_zfb_setFocused zfb_setFocused;
  808. /**
  809. * Reports the mouse's current location.
  810. * x and y are in the range [0,1]. (0, 0) is top-left, (1, 1) is bottom-right
  811. */
  812. public delegate void Calltype_zfb_mouseMove(int id, float x, float y);
  813. public static Calltype_zfb_mouseMove zfb_mouseMove;
  814. public delegate void Calltype_zfb_mouseButton(int id, MouseButton button, bool down, int clickCount);
  815. public static Calltype_zfb_mouseButton zfb_mouseButton;
  816. /** Reports a mouse scroll. One "tick" of a scroll wheel is generally around 120 units. */
  817. public delegate void Calltype_zfb_mouseScroll(int id, int deltaX, int deltaY);
  818. public static Calltype_zfb_mouseScroll zfb_mouseScroll;
  819. /**
  820. * Report a key down/up event. Repeated "virtual" keystrokes are simulated by repeating the down event without
  821. * an interveneing up event.
  822. */
  823. public delegate void Calltype_zfb_keyEvent(int id, bool down, int windowsKeyCode);
  824. public static Calltype_zfb_keyEvent zfb_keyEvent;
  825. /**
  826. * Report a typed character. This typically interleaves with calls to zfb_keyEvent
  827. */
  828. public delegate void Calltype_zfb_characterEvent(int id, int character, int windowsKeyCode);
  829. public static Calltype_zfb_characterEvent zfb_characterEvent;
  830. /** Register a function to call when console.log etc. is called in the browser. */
  831. public delegate void Calltype_zfb_registerConsoleCallback(int id, ConsoleFunc callback);
  832. public static Calltype_zfb_registerConsoleCallback zfb_registerConsoleCallback;
  833. public delegate void Calltype_zfb_evalJS(int id, string script, string scriptURL);
  834. public static Calltype_zfb_evalJS zfb_evalJS;
  835. /** Registers a callback to call when window._zfb_event(int, string) is called in the browser. */
  836. public delegate void Calltype_zfb_registerJSCallback(int id, ForwardJSCallFunc cb);
  837. public static Calltype_zfb_registerJSCallback zfb_registerJSCallback;
  838. /** Registers a callback that is called when something from ChangeType happens. */
  839. public delegate void Calltype_zfb_registerChangeCallback(int id, ChangeFunc cb);
  840. public static Calltype_zfb_registerChangeCallback zfb_registerChangeCallback;
  841. /**
  842. * Gets the current mouse cursor. If the type is CursorType.Custom, width and height will be filled with
  843. * the width and height of the custom cursor.
  844. */
  845. public delegate CursorType Calltype_zfb_getMouseCursor(int id, out int width, out int height);
  846. public static Calltype_zfb_getMouseCursor zfb_getMouseCursor;
  847. /**
  848. * Call this if zfb_getMouseCursor tells you there's a custom cursor.
  849. * This will fill buffer (RGBA bottom-top, 4 bytes * width * height) with the contents of the cursor.
  850. * Use the size you got from zfb_getMouseCursor.
  851. * If width or height don't match the results from zfb_getMouseCursor, does nothing.
  852. *
  853. * {hotX} and {hoyY} will be filled with the cursor's hotspot.
  854. */
  855. public delegate void Calltype_zfb_getMouseCustomCursor(int id, IntPtr buffer, int width, int height, out int hotX, out int hotY);
  856. public static Calltype_zfb_getMouseCustomCursor zfb_getMouseCustomCursor;
  857. /** Registers a DisplayDialogFunc for this browser. */
  858. public delegate void Calltype_zfb_registerDialogCallback(int id, DisplayDialogFunc cb);
  859. public static Calltype_zfb_registerDialogCallback zfb_registerDialogCallback;
  860. /** Callback for a dialog. See the docs on DisplayDialogFunc. */
  861. public delegate void Calltype_zfb_sendDialogResults(int id, bool affirmed, string text1, string text2);
  862. public static Calltype_zfb_sendDialogResults zfb_sendDialogResults;
  863. /** Registers a NewWindowFunc for pop ups. */
  864. public delegate void Calltype_zfb_registerPopupCallback(int id, NewWindowAction windowAction, ZFBSettings baseSettings, NewWindowFunc cb);
  865. public static Calltype_zfb_registerPopupCallback zfb_registerPopupCallback;
  866. /** Registers a ShowContextMenuFunc for the context menu. */
  867. public delegate void Calltype_zfb_registerContextMenuCallback(int id, ShowContextMenuFunc cb);
  868. public static Calltype_zfb_registerContextMenuCallback zfb_registerContextMenuCallback;
  869. /**
  870. * After your ShowContextMenuFunc has been called,
  871. * call this to report what item the user selected.
  872. * If the menu was canceled, send -1.
  873. */
  874. public delegate void Calltype_zfb_sendContextMenuResults(int id, int commandId);
  875. public static Calltype_zfb_sendContextMenuResults zfb_sendContextMenuResults;
  876. /**
  877. * Sends a command, such as copy, paste, or select to the focused frame in the given browser.
  878. */
  879. public delegate void Calltype_zfb_sendCommandToFocusedFrame(int id, FrameCommand command);
  880. public static Calltype_zfb_sendCommandToFocusedFrame zfb_sendCommandToFocusedFrame;
  881. /** Fetches all the cookies, calling the given callback for every cookie. */
  882. public delegate void Calltype_zfb_getCookies(int id, GetCookieFunc cb);
  883. public static Calltype_zfb_getCookies zfb_getCookies;
  884. /** Alters the given cookie as specified. */
  885. public delegate void Calltype_zfb_editCookie(int id, NativeCookie cookie, CookieAction action);
  886. public static Calltype_zfb_editCookie zfb_editCookie;
  887. /**
  888. * Deletes all the cookies.
  889. * (Though it takes a browser, this will typically clear all cookies for all browsers.)
  890. */
  891. public delegate void Calltype_zfb_clearCookies(int id);
  892. public static Calltype_zfb_clearCookies zfb_clearCookies;
  893. /**
  894. * Take an action on a download.
  895. * fileName is ignored except when beginning a download.
  896. * At the outset:
  897. * Begin: Starts the download. Saves to the given file if given. If fileName is null, the user will be prompted.
  898. * Cancel: Does nothing with a download.
  899. * After starting a download:
  900. * Pause, Cancel, Resume: Does what it says on the tin.
  901. * Once a download is finished or canceled it is not valid to call this function for that download any more.
  902. */
  903. public delegate void Calltype_zfb_downloadCommand(int id, int downloadId, DownloadAction command, string fileName);
  904. public static Calltype_zfb_downloadCommand zfb_downloadCommand;
  905. #if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
  906. /**
  907. * Creates a new OS-native window in this process, returning an id.
  908. */
  909. public delegate int Calltype_zfb_windowCreate(String title, WindowCallbackFunc eventHandler);
  910. public static Calltype_zfb_windowCreate zfb_windowCreate;
  911. /**
  912. * Renders the contents of the given browser into the given OS window.
  913. */
  914. public delegate void Calltype_zfb_windowRender(int windowId, int browserId);
  915. public static Calltype_zfb_windowRender zfb_windowRender;
  916. /**
  917. * Closes the given window.
  918. * Pass -1 for the id to close all windows.
  919. */
  920. public delegate void Calltype_zfb_windowClose(int windowId);
  921. public static Calltype_zfb_windowClose zfb_windowClose;
  922. #endif
  923. }
  924. }