CefRuntime.cs 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196
  1. namespace Xilium.CefGlue
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Globalization;
  6. using System.Runtime.InteropServices;
  7. using System.Text;
  8. using Xilium.CefGlue.Interop;
  9. public static unsafe class CefRuntime
  10. {
  11. private static readonly CefRuntimePlatform _platform;
  12. private static bool _loaded;
  13. private static bool _initialized;
  14. static CefRuntime()
  15. {
  16. _platform = DetectPlatform();
  17. }
  18. #region Platform Detection
  19. private static CefRuntimePlatform DetectPlatform()
  20. {
  21. var platformId = Environment.OSVersion.Platform;
  22. if (platformId == PlatformID.MacOSX)
  23. return CefRuntimePlatform.MacOS;
  24. int p = (int)platformId;
  25. if ((p == 4) || (p == 128))
  26. return IsRunningOnMac() ? CefRuntimePlatform.MacOS : CefRuntimePlatform.Linux;
  27. return CefRuntimePlatform.Windows;
  28. }
  29. //From Managed.Windows.Forms/XplatUI
  30. private static bool IsRunningOnMac()
  31. {
  32. IntPtr buf = IntPtr.Zero;
  33. try
  34. {
  35. buf = Marshal.AllocHGlobal(8192);
  36. // This is a hacktastic way of getting sysname from uname ()
  37. if (uname(buf) == 0)
  38. {
  39. string os = Marshal.PtrToStringAnsi(buf);
  40. if (os == "Darwin")
  41. return true;
  42. }
  43. }
  44. catch { }
  45. finally
  46. {
  47. if (buf != IntPtr.Zero)
  48. Marshal.FreeHGlobal(buf);
  49. }
  50. return false;
  51. }
  52. [DllImport("libc")]
  53. private static extern int uname(IntPtr buf);
  54. public static CefRuntimePlatform Platform
  55. {
  56. get { return _platform; }
  57. }
  58. #endregion
  59. /// <summary>
  60. /// Gets whether the CEF runtime has been initialized;
  61. /// </summary>
  62. public static bool IsInitialized => _initialized;
  63. /// <summary>
  64. /// Loads CEF runtime.
  65. /// </summary>
  66. /// <exception cref="DllNotFoundException"></exception>
  67. /// <exception cref="CefVersionMismatchException"></exception>
  68. /// <exception cref="InvalidOperationException"></exception>
  69. public static void Load()
  70. {
  71. Load(null);
  72. }
  73. /// <summary>
  74. /// Loads CEF runtime from specified path.
  75. /// </summary>
  76. /// <exception cref="DllNotFoundException"></exception>
  77. /// <exception cref="CefVersionMismatchException"></exception>
  78. /// <exception cref="InvalidOperationException"></exception>
  79. public static void Load(string path)
  80. {
  81. if (_loaded) return;
  82. if (!string.IsNullOrEmpty(path))
  83. {
  84. if (Platform == CefRuntimePlatform.Windows)
  85. LoadLibraryWindows(path);
  86. else
  87. throw new PlatformNotSupportedException("CEF Runtime can't be initialized on altered path on this platform. Use CefRuntime.Load() instead.");
  88. }
  89. CheckVersion();
  90. _loaded = true;
  91. }
  92. private static void LoadLibraryWindows(string path)
  93. {
  94. Xilium.CefGlue.Platform.Windows.NativeMethods.LoadLibraryEx(
  95. System.IO.Path.Combine(path, "libcef.dll"),
  96. IntPtr.Zero,
  97. Xilium.CefGlue.Platform.Windows.LoadLibraryFlags.LOAD_WITH_ALTERED_SEARCH_PATH
  98. );
  99. }
  100. #region cef_version
  101. public static string ChromeVersion
  102. {
  103. get
  104. {
  105. return string.Format("{0}.{1}.{2}.{3}", libcef.CHROME_VERSION_MAJOR, libcef.CHROME_VERSION_MINOR, libcef.CHROME_VERSION_BUILD, libcef.CHROME_VERSION_PATCH);
  106. }
  107. }
  108. private static void CheckVersion()
  109. {
  110. CheckVersionByApiHash();
  111. }
  112. private static void CheckVersionByApiHash()
  113. {
  114. // get CEF_API_HASH_PLATFORM
  115. string actual;
  116. try
  117. {
  118. var n_actual = libcef.api_hash(0);
  119. actual = n_actual != null ? new string(n_actual) : null;
  120. }
  121. catch (EntryPointNotFoundException ex)
  122. {
  123. throw new NotSupportedException("cef_api_hash call is not supported.", ex);
  124. }
  125. if (string.IsNullOrEmpty(actual)) throw new NotSupportedException();
  126. string expected;
  127. switch (CefRuntime.Platform)
  128. {
  129. case CefRuntimePlatform.Windows: expected = libcef.CEF_API_HASH_PLATFORM_WIN; break;
  130. case CefRuntimePlatform.MacOS: expected = libcef.CEF_API_HASH_PLATFORM_MACOS; break;
  131. case CefRuntimePlatform.Linux: expected = libcef.CEF_API_HASH_PLATFORM_LINUX; break;
  132. default: throw new PlatformNotSupportedException();
  133. }
  134. if (string.Compare(actual, expected, StringComparison.OrdinalIgnoreCase) != 0)
  135. {
  136. var expectedVersion = libcef.CEF_VERSION;
  137. throw ExceptionBuilder.RuntimeVersionApiHashMismatch(actual, expected, expectedVersion);
  138. }
  139. }
  140. #endregion
  141. #region cef_app
  142. /// <summary>
  143. /// This function should be called from the application entry point function to
  144. /// execute a secondary process. It can be used to run secondary processes from
  145. /// the browser client executable (default behavior) or from a separate
  146. /// executable specified by the CefSettings.browser_subprocess_path value. If
  147. /// called for the browser process (identified by no "type" command-line value)
  148. /// it will return immediately with a value of -1. If called for a recognized
  149. /// secondary process it will block until the process should exit and then return
  150. /// the process exit code. The |application| parameter may be empty. The
  151. /// |windows_sandbox_info| parameter is only used on Windows and may be NULL (see
  152. /// cef_sandbox_win.h for details).
  153. /// </summary>
  154. public static int ExecuteProcess(CefMainArgs args, CefApp application, IntPtr windowsSandboxInfo)
  155. {
  156. LoadIfNeed();
  157. var n_args = args.ToNative();
  158. var n_app = application != null ? application.ToNative() : null;
  159. try
  160. {
  161. return libcef.execute_process(n_args, n_app, (void*)windowsSandboxInfo);
  162. }
  163. finally
  164. {
  165. CefMainArgs.Free(n_args);
  166. }
  167. }
  168. [Obsolete]
  169. public static int ExecuteProcess(CefMainArgs args, CefApp application)
  170. {
  171. return ExecuteProcess(args, application, IntPtr.Zero);
  172. }
  173. /// <summary>
  174. /// This function should be called on the main application thread to initialize
  175. /// the CEF browser process. The |application| parameter may be empty. A return
  176. /// value of true indicates that it succeeded and false indicates that it failed.
  177. /// The |windows_sandbox_info| parameter is only used on Windows and may be NULL
  178. /// (see cef_sandbox_win.h for details).
  179. /// </summary>
  180. public static void Initialize(CefMainArgs args, CefSettings settings, CefApp application, IntPtr windowsSandboxInfo)
  181. {
  182. LoadIfNeed();
  183. if (args == null) throw new ArgumentNullException("args");
  184. if (settings == null) throw new ArgumentNullException("settings");
  185. if (_initialized) throw ExceptionBuilder.CefRuntimeAlreadyInitialized();
  186. var n_main_args = args.ToNative();
  187. var n_settings = settings.ToNative();
  188. var n_app = application != null ? application.ToNative() : null;
  189. try
  190. {
  191. if (libcef.initialize(n_main_args, n_settings, n_app, (void*)windowsSandboxInfo) != 0)
  192. {
  193. _initialized = true;
  194. }
  195. else
  196. {
  197. throw ExceptionBuilder.CefRuntimeFailedToInitialize();
  198. }
  199. }
  200. finally
  201. {
  202. CefMainArgs.Free(n_main_args);
  203. CefSettings.Free(n_settings);
  204. }
  205. }
  206. [Obsolete]
  207. public static void Initialize(CefMainArgs args, CefSettings settings, CefApp application)
  208. {
  209. Initialize(args, settings, application, IntPtr.Zero);
  210. }
  211. /// <summary>
  212. /// This function should be called on the main application thread to shut down
  213. /// the CEF browser process before the application exits.
  214. /// </summary>
  215. public static void Shutdown()
  216. {
  217. if (!_initialized) return;
  218. GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
  219. GC.WaitForPendingFinalizers();
  220. libcef.shutdown();
  221. }
  222. /// <summary>
  223. /// Perform a single iteration of CEF message loop processing. This function is
  224. /// provided for cases where the CEF message loop must be integrated into an
  225. /// existing application message loop. Use of this function is not recommended
  226. /// for most users; use either the CefRunMessageLoop() function or
  227. /// CefSettings.multi_threaded_message_loop if possible. When using this function
  228. /// care must be taken to balance performance against excessive CPU usage. It is
  229. /// recommended to enable the CefSettings.external_message_pump option when using
  230. /// this function so that CefBrowserProcessHandler::OnScheduleMessagePumpWork()
  231. /// callbacks can facilitate the scheduling process. This function should only be
  232. /// called on the main application thread and only if CefInitialize() is called
  233. /// with a CefSettings.multi_threaded_message_loop value of false. This function
  234. /// will not block.
  235. /// </summary>
  236. public static void DoMessageLoopWork()
  237. {
  238. libcef.do_message_loop_work();
  239. }
  240. /// <summary>
  241. /// Run the CEF message loop. Use this function instead of an application-
  242. /// provided message loop to get the best balance between performance and CPU
  243. /// usage. This function should only be called on the main application thread and
  244. /// only if CefInitialize() is called with a
  245. /// CefSettings.multi_threaded_message_loop value of false. This function will
  246. /// block until a quit message is received by the system.
  247. /// </summary>
  248. public static void RunMessageLoop()
  249. {
  250. libcef.run_message_loop();
  251. }
  252. /// <summary>
  253. /// Quit the CEF message loop that was started by calling CefRunMessageLoop().
  254. /// This function should only be called on the main application thread and only
  255. /// if CefRunMessageLoop() was used.
  256. /// </summary>
  257. public static void QuitMessageLoop()
  258. {
  259. libcef.quit_message_loop();
  260. }
  261. /// <summary>
  262. /// Set to true before calling Windows APIs like TrackPopupMenu that enter a
  263. /// modal message loop. Set to false after exiting the modal message loop.
  264. /// </summary>
  265. public static void SetOSModalLoop(bool osModalLoop)
  266. {
  267. libcef.set_osmodal_loop(osModalLoop ? 1 : 0);
  268. }
  269. /// <summary>
  270. /// Call during process startup to enable High-DPI support on Windows 7 or newer.
  271. /// Older versions of Windows should be left DPI-unaware because they do not
  272. /// support DirectWrite and GDI fonts are kerned very badly.
  273. /// </summary>
  274. public static void EnableHighDpiSupport()
  275. {
  276. libcef.enable_highdpi_support();
  277. }
  278. #endregion
  279. #region cef_task
  280. /// <summary>
  281. /// CEF maintains multiple internal threads that are used for handling different
  282. /// types of tasks in different processes. See the cef_thread_id_t definitions in
  283. /// cef_types.h for more information. This function will return true if called on
  284. /// the specified thread. It is an error to request a thread from the wrong
  285. /// process.
  286. /// </summary>
  287. public static bool CurrentlyOn(CefThreadId threadId)
  288. {
  289. return libcef.currently_on(threadId) != 0;
  290. }
  291. /// <summary>
  292. /// Post a task for execution on the specified thread. This function may be
  293. /// called on any thread. It is an error to request a thread from the wrong
  294. /// process.
  295. /// </summary>
  296. public static bool PostTask(CefThreadId threadId, CefTask task)
  297. {
  298. if (task == null) throw new ArgumentNullException("task");
  299. return libcef.post_task(threadId, task.ToNative()) != 0;
  300. }
  301. /// <summary>
  302. /// Post a task for delayed execution on the specified thread. This function may
  303. /// be called on any thread. It is an error to request a thread from the wrong
  304. /// process.
  305. /// </summary>
  306. public static bool PostTask(CefThreadId threadId, CefTask task, long delay)
  307. {
  308. if (task == null) throw new ArgumentNullException("task");
  309. return libcef.post_delayed_task(threadId, task.ToNative(), delay) != 0;
  310. }
  311. #endregion
  312. #region cef_origin_whitelist
  313. /// <summary>
  314. /// Add an entry to the cross-origin access whitelist.
  315. ///
  316. /// The same-origin policy restricts how scripts hosted from different origins
  317. /// (scheme + domain + port) can communicate. By default, scripts can only access
  318. /// resources with the same origin. Scripts hosted on the HTTP and HTTPS schemes
  319. /// (but no other schemes) can use the "Access-Control-Allow-Origin" header to
  320. /// allow cross-origin requests. For example, https://source.example.com can make
  321. /// XMLHttpRequest requests on http://target.example.com if the
  322. /// http://target.example.com request returns an "Access-Control-Allow-Origin:
  323. /// https://source.example.com" response header.
  324. ///
  325. /// Scripts in separate frames or iframes and hosted from the same protocol and
  326. /// domain suffix can execute cross-origin JavaScript if both pages set the
  327. /// document.domain value to the same domain suffix. For example,
  328. /// scheme://foo.example.com and scheme://bar.example.com can communicate using
  329. /// JavaScript if both domains set document.domain="example.com".
  330. ///
  331. /// This method is used to allow access to origins that would otherwise violate
  332. /// the same-origin policy. Scripts hosted underneath the fully qualified
  333. /// |source_origin| URL (like http://www.example.com) will be allowed access to
  334. /// all resources hosted on the specified |target_protocol| and |target_domain|.
  335. /// If |target_domain| is non-empty and |allow_target_subdomains| if false only
  336. /// exact domain matches will be allowed. If |target_domain| contains a top-
  337. /// level domain component (like "example.com") and |allow_target_subdomains| is
  338. /// true sub-domain matches will be allowed. If |target_domain| is empty and
  339. /// |allow_target_subdomains| if true all domains and IP addresses will be
  340. /// allowed.
  341. ///
  342. /// This method cannot be used to bypass the restrictions on local or display
  343. /// isolated schemes. See the comments on CefRegisterCustomScheme for more
  344. /// information.
  345. ///
  346. /// This function may be called on any thread. Returns false if |source_origin|
  347. /// is invalid or the whitelist cannot be accessed.
  348. /// </summary>
  349. public static bool AddCrossOriginWhitelistEntry(string sourceOrigin, string targetProtocol, string targetDomain, bool allowTargetSubdomains)
  350. {
  351. if (string.IsNullOrEmpty("sourceOrigin")) throw new ArgumentNullException("sourceOrigin");
  352. if (string.IsNullOrEmpty("targetProtocol")) throw new ArgumentNullException("targetProtocol");
  353. fixed (char* sourceOrigin_ptr = sourceOrigin)
  354. fixed (char* targetProtocol_ptr = targetProtocol)
  355. fixed (char* targetDomain_ptr = targetDomain)
  356. {
  357. var n_sourceOrigin = new cef_string_t(sourceOrigin_ptr, sourceOrigin.Length);
  358. var n_targetProtocol = new cef_string_t(targetProtocol_ptr, targetProtocol.Length);
  359. var n_targetDomain = new cef_string_t(targetDomain_ptr, targetDomain != null ? targetDomain.Length : 0);
  360. return libcef.add_cross_origin_whitelist_entry(
  361. &n_sourceOrigin,
  362. &n_targetProtocol,
  363. &n_targetDomain,
  364. allowTargetSubdomains ? 1 : 0
  365. ) != 0;
  366. }
  367. }
  368. /// <summary>
  369. /// Remove an entry from the cross-origin access whitelist. Returns false if
  370. /// |source_origin| is invalid or the whitelist cannot be accessed.
  371. /// </summary>
  372. public static bool RemoveCrossOriginWhitelistEntry(string sourceOrigin, string targetProtocol, string targetDomain, bool allowTargetSubdomains)
  373. {
  374. if (string.IsNullOrEmpty("sourceOrigin")) throw new ArgumentNullException("sourceOrigin");
  375. if (string.IsNullOrEmpty("targetProtocol")) throw new ArgumentNullException("targetProtocol");
  376. fixed (char* sourceOrigin_ptr = sourceOrigin)
  377. fixed (char* targetProtocol_ptr = targetProtocol)
  378. fixed (char* targetDomain_ptr = targetDomain)
  379. {
  380. var n_sourceOrigin = new cef_string_t(sourceOrigin_ptr, sourceOrigin.Length);
  381. var n_targetProtocol = new cef_string_t(targetProtocol_ptr, targetProtocol.Length);
  382. var n_targetDomain = new cef_string_t(targetDomain_ptr, targetDomain != null ? targetDomain.Length : 0);
  383. return libcef.remove_cross_origin_whitelist_entry(
  384. &n_sourceOrigin,
  385. &n_targetProtocol,
  386. &n_targetDomain,
  387. allowTargetSubdomains ? 1 : 0
  388. ) != 0;
  389. }
  390. }
  391. /// <summary>
  392. /// Remove all entries from the cross-origin access whitelist. Returns false if
  393. /// the whitelist cannot be accessed.
  394. /// </summary>
  395. public static bool ClearCrossOriginWhitelist()
  396. {
  397. return libcef.clear_cross_origin_whitelist() != 0;
  398. }
  399. #endregion
  400. #region cef_scheme
  401. /// <summary>
  402. /// Register a scheme handler factory for the specified |scheme_name| and
  403. /// optional |domain_name|. An empty |domain_name| value for a standard scheme
  404. /// will cause the factory to match all domain names. The |domain_name| value
  405. /// will be ignored for non-standard schemes. If |scheme_name| is a built-in
  406. /// scheme and no handler is returned by |factory| then the built-in scheme
  407. /// handler factory will be called. If |scheme_name| is a custom scheme then
  408. /// also implement the CefApp::OnRegisterCustomSchemes() method in all processes.
  409. /// This function may be called multiple times to change or remove the factory
  410. /// that matches the specified |scheme_name| and optional |domain_name|.
  411. /// Returns false if an error occurs. This function may be called on any thread
  412. /// in the browser process.
  413. /// </summary>
  414. public static bool RegisterSchemeHandlerFactory(string schemeName, string domainName, CefSchemeHandlerFactory factory)
  415. {
  416. if (string.IsNullOrEmpty(schemeName)) throw new ArgumentNullException("schemeName");
  417. if (factory == null) throw new ArgumentNullException("factory");
  418. fixed (char* schemeName_str = schemeName)
  419. fixed (char* domainName_str = domainName)
  420. {
  421. var n_schemeName = new cef_string_t(schemeName_str, schemeName.Length);
  422. var n_domainName = new cef_string_t(domainName_str, domainName != null ? domainName.Length : 0);
  423. return libcef.register_scheme_handler_factory(&n_schemeName, &n_domainName, factory.ToNative()) != 0;
  424. }
  425. }
  426. /// <summary>
  427. /// Clear all registered scheme handler factories. Returns false on error. This
  428. /// function may be called on any thread in the browser process.
  429. /// </summary>
  430. public static bool ClearSchemeHandlerFactories()
  431. {
  432. return libcef.clear_scheme_handler_factories() != 0;
  433. }
  434. #endregion
  435. #region cef_trace
  436. /// <summary>
  437. /// Start tracing events on all processes. Tracing is initialized asynchronously
  438. /// and |callback| will be executed on the UI thread after initialization is
  439. /// complete.
  440. ///
  441. /// If CefBeginTracing was called previously, or if a CefEndTracingAsync call is
  442. /// pending, CefBeginTracing will fail and return false.
  443. ///
  444. /// |categories| is a comma-delimited list of category wildcards. A category can
  445. /// have an optional '-' prefix to make it an excluded category. Having both
  446. /// included and excluded categories in the same list is not supported.
  447. ///
  448. /// Example: "test_MyTest*"
  449. /// Example: "test_MyTest*,test_OtherStuff"
  450. /// Example: "-excluded_category1,-excluded_category2"
  451. ///
  452. /// This function must be called on the browser process UI thread.
  453. /// </summary>
  454. public static bool BeginTracing(string categories = null, CefCompletionCallback callback = null)
  455. {
  456. fixed (char* categories_str = categories)
  457. {
  458. var n_categories = new cef_string_t(categories_str, categories != null ? categories.Length : 0);
  459. var n_callback = callback != null ? callback.ToNative() : null;
  460. return libcef.begin_tracing(&n_categories, n_callback) != 0;
  461. }
  462. }
  463. /// <summary>
  464. /// Stop tracing events on all processes.
  465. ///
  466. /// This function will fail and return false if a previous call to
  467. /// CefEndTracingAsync is already pending or if CefBeginTracing was not called.
  468. ///
  469. /// |tracing_file| is the path at which tracing data will be written and
  470. /// |callback| is the callback that will be executed once all processes have
  471. /// sent their trace data. If |tracing_file| is empty a new temporary file path
  472. /// will be used. If |callback| is empty no trace data will be written.
  473. ///
  474. /// This function must be called on the browser process UI thread.
  475. /// </summary>
  476. public static bool EndTracing(string tracingFile = null, CefEndTracingCallback callback = null)
  477. {
  478. fixed (char* tracingFile_str = tracingFile)
  479. {
  480. var n_tracingFile = new cef_string_t(tracingFile_str, tracingFile != null ? tracingFile.Length : 0);
  481. var n_callback = callback != null ? callback.ToNative() : null;
  482. return libcef.end_tracing(&n_tracingFile, n_callback) != 0;
  483. }
  484. }
  485. /// <summary>
  486. /// Returns the current system trace time or, if none is defined, the current
  487. /// high-res time. Can be used by clients to synchronize with the time
  488. /// information in trace events.
  489. /// </summary>
  490. public static long NowFromSystemTraceTime()
  491. {
  492. return libcef.now_from_system_trace_time();
  493. }
  494. // TODO: functions from cef_trace_event.h (not generated automatically)
  495. #endregion
  496. #region cef_parser
  497. // Methods from cef_parser.h.
  498. /// <summary>
  499. /// Parse the specified |url| into its component parts.
  500. /// Returns false if the URL is empty or invalid.
  501. /// </summary>
  502. public static bool ParseUrl(string url, out CefUrlParts parts)
  503. {
  504. fixed (char* url_str = url)
  505. {
  506. var n_url = new cef_string_t(url_str, url != null ? url.Length : 0);
  507. var n_parts = new cef_urlparts_t();
  508. var result = libcef.parse_url(&n_url, &n_parts) != 0;
  509. parts = result ? CefUrlParts.FromNative(&n_parts) : null;
  510. cef_urlparts_t.Clear(&n_parts);
  511. return result;
  512. }
  513. }
  514. public static bool CreateUrl(CefUrlParts parts, out string url)
  515. {
  516. if (parts == null) throw new ArgumentNullException("parts");
  517. var n_parts = parts.ToNative();
  518. var n_url = new cef_string_t();
  519. var result = libcef.create_url(&n_parts, &n_url) != 0;
  520. url = result ? cef_string_t.ToString(&n_url) : null;
  521. cef_urlparts_t.Clear(&n_parts);
  522. libcef.string_clear(&n_url);
  523. return result;
  524. }
  525. /// <summary>
  526. /// Returns the mime type for the specified file extension or an empty string if
  527. /// unknown.
  528. /// </summary>
  529. public static string GetMimeType(string extension)
  530. {
  531. fixed (char* extension_str = extension)
  532. {
  533. var n_extension = new cef_string_t(extension_str, extension != null ? extension.Length : 0);
  534. var n_result = libcef.get_mime_type(&n_extension);
  535. return cef_string_userfree.ToString(n_result);
  536. }
  537. }
  538. /// <summary>
  539. /// Get the extensions associated with the given mime type. This should be passed
  540. /// in lower case. There could be multiple extensions for a given mime type, like
  541. /// "html,htm" for "text/html", or "txt,text,html,..." for "text/*". Any existing
  542. /// elements in the provided vector will not be erased.
  543. /// </summary>
  544. public static string[] GetExtensionsForMimeType(string mimeType)
  545. {
  546. fixed (char* mimeType_str = mimeType)
  547. {
  548. var n_mimeType = new cef_string_t(mimeType_str, mimeType != null ? mimeType.Length : 0);
  549. var n_list = libcef.string_list_alloc();
  550. libcef.get_extensions_for_mime_type(&n_mimeType, n_list);
  551. var result = cef_string_list.ToArray(n_list);
  552. libcef.string_list_free(n_list);
  553. return result;
  554. }
  555. }
  556. /// <summary>
  557. /// Encodes |data| as a base64 string.
  558. /// </summary>
  559. public static unsafe string Base64Encode(void* data, int size)
  560. {
  561. var n_result = libcef.base64encode(data, (UIntPtr)size);
  562. return cef_string_userfree.ToString(n_result);
  563. }
  564. public static string Base64Encode(byte[] bytes, int offset, int length)
  565. {
  566. // TODO: check bounds
  567. fixed (byte* bytes_ptr = &bytes[offset])
  568. {
  569. return Base64Encode(bytes_ptr, length);
  570. }
  571. }
  572. public static string Base64Encode(byte[] bytes)
  573. {
  574. return Base64Encode(bytes, 0, bytes.Length);
  575. }
  576. /// <summary>
  577. /// Decodes the base64 encoded string |data|. The returned value will be NULL if
  578. /// the decoding fails.
  579. /// </summary>
  580. public static CefBinaryValue Base64Decode(string data)
  581. {
  582. fixed (char* data_str = data)
  583. {
  584. var n_data = new cef_string_t(data_str, data != null ? data.Length : 0);
  585. return CefBinaryValue.FromNative(libcef.base64decode(&n_data));
  586. }
  587. }
  588. /// <summary>
  589. /// Escapes characters in |text| which are unsuitable for use as a query
  590. /// parameter value. Everything except alphanumerics and -_.!~*'() will be
  591. /// converted to "%XX". If |use_plus| is true spaces will change to "+". The
  592. /// result is basically the same as encodeURIComponent in Javacript.
  593. /// </summary>
  594. public static string UriEncode(string text, bool usePlus)
  595. {
  596. fixed (char* text_str = text)
  597. {
  598. var n_text = new cef_string_t(text_str, text != null ? text.Length : 0);
  599. var n_result = libcef.uriencode(&n_text, usePlus ? 1 : 0);
  600. return cef_string_userfree.ToString(n_result);
  601. }
  602. }
  603. /// <summary>
  604. /// Unescapes |text| and returns the result. Unescaping consists of looking for
  605. /// the exact pattern "%XX" where each X is a hex digit and converting to the
  606. /// character with the numerical value of those digits (e.g. "i%20=%203%3b"
  607. /// unescapes to "i = 3;"). If |convert_to_utf8| is true this function will
  608. /// attempt to interpret the initial decoded result as UTF-8. If the result is
  609. /// convertable into UTF-8 it will be returned as converted. Otherwise the
  610. /// initial decoded result will be returned. The |unescape_rule| parameter
  611. /// supports further customization the decoding process.
  612. /// </summary>
  613. public static string UriDecode(string text, bool convertToUtf8, CefUriUnescapeRules unescapeRule)
  614. {
  615. fixed (char* text_str = text)
  616. {
  617. var n_text = new cef_string_t(text_str, text != null ? text.Length : 0);
  618. var n_result = libcef.uridecode(&n_text, convertToUtf8 ? 1 : 0, unescapeRule);
  619. return cef_string_userfree.ToString(n_result);
  620. }
  621. }
  622. /// <summary>
  623. /// Parses the specified |json_string| and returns a dictionary or list
  624. /// representation. If JSON parsing fails this method returns NULL.
  625. /// </summary>
  626. public static CefValue ParseJson(string value, CefJsonParserOptions options)
  627. {
  628. fixed (char* value_str = value)
  629. {
  630. var n_value = new cef_string_t(value_str, value != null ? value.Length : 0);
  631. var n_result = libcef.parse_json(&n_value, options);
  632. return CefValue.FromNativeOrNull(n_result);
  633. }
  634. }
  635. public static CefValue ParseJson(IntPtr json, int jsonSize, CefJsonParserOptions options)
  636. {
  637. var n_result = libcef.parse_json_buffer((void*)json, checked((UIntPtr)jsonSize), options);
  638. return CefValue.FromNativeOrNull(n_result);
  639. }
  640. /// <summary>
  641. /// Parses the specified |json_string| and returns a dictionary or list
  642. /// representation. If JSON parsing fails this method returns NULL and populates
  643. /// |error_msg_out| with a formatted error message.
  644. /// </summary>
  645. public static CefValue ParseJsonAndReturnError(string value, CefJsonParserOptions options, out string errorMessage)
  646. {
  647. fixed (char* value_str = value)
  648. {
  649. var n_value = new cef_string_t(value_str, value != null ? value.Length : 0);
  650. cef_string_t n_error_msg;
  651. var n_result = libcef.parse_jsonand_return_error(&n_value, options, &n_error_msg);
  652. var result = CefValue.FromNativeOrNull(n_result);
  653. errorMessage = cef_string_userfree.ToString((cef_string_userfree*)&n_error_msg);
  654. return result;
  655. }
  656. }
  657. /// <summary>
  658. /// Generates a JSON string from the specified root |node| which should be a
  659. /// dictionary or list value. Returns an empty string on failure. This method
  660. /// requires exclusive access to |node| including any underlying data.
  661. /// </summary>
  662. public static string WriteJson(CefValue value, CefJsonWriterOptions options)
  663. {
  664. if (value == null) throw new ArgumentNullException("value");
  665. var n_result = libcef.write_json(value.ToNative(), options);
  666. return cef_string_userfree.ToString(n_result);
  667. }
  668. #endregion
  669. #region cef_v8
  670. /// <summary>
  671. /// Register a new V8 extension with the specified JavaScript extension code and
  672. /// handler. Functions implemented by the handler are prototyped using the
  673. /// keyword 'native'. The calling of a native function is restricted to the scope
  674. /// in which the prototype of the native function is defined. This function may
  675. /// only be called on the render process main thread.
  676. ///
  677. /// Example JavaScript extension code:
  678. /// <code>
  679. /// // create the 'example' global object if it doesn't already exist.
  680. /// if (!example)
  681. /// example = {};
  682. /// // create the 'example.test' global object if it doesn't already exist.
  683. /// if (!example.test)
  684. /// example.test = {};
  685. /// (function() {
  686. /// // Define the function 'example.test.myfunction'.
  687. /// example.test.myfunction = function() {
  688. /// // Call CefV8Handler::Execute() with the function name 'MyFunction'
  689. /// // and no arguments.
  690. /// native function MyFunction();
  691. /// return MyFunction();
  692. /// };
  693. /// // Define the getter function for parameter 'example.test.myparam'.
  694. /// example.test.__defineGetter__('myparam', function() {
  695. /// // Call CefV8Handler::Execute() with the function name 'GetMyParam'
  696. /// // and no arguments.
  697. /// native function GetMyParam();
  698. /// return GetMyParam();
  699. /// });
  700. /// // Define the setter function for parameter 'example.test.myparam'.
  701. /// example.test.__defineSetter__('myparam', function(b) {
  702. /// // Call CefV8Handler::Execute() with the function name 'SetMyParam'
  703. /// // and a single argument.
  704. /// native function SetMyParam();
  705. /// if(b) SetMyParam(b);
  706. /// });
  707. ///
  708. /// // Extension definitions can also contain normal JavaScript variables
  709. /// // and functions.
  710. /// var myint = 0;
  711. /// example.test.increment = function() {
  712. /// myint += 1;
  713. /// return myint;
  714. /// };
  715. /// })();
  716. /// </code>
  717. /// Example usage in the page:
  718. /// <code>
  719. /// // Call the function.
  720. /// example.test.myfunction();
  721. /// // Set the parameter.
  722. /// example.test.myparam = value;
  723. /// // Get the parameter.
  724. /// value = example.test.myparam;
  725. /// // Call another function.
  726. /// example.test.increment();
  727. /// </code>
  728. /// </summary>
  729. public static bool RegisterExtension(string extensionName, string javascriptCode, CefV8Handler handler)
  730. {
  731. if (string.IsNullOrEmpty(extensionName)) throw new ArgumentNullException("extensionName");
  732. if (string.IsNullOrEmpty(javascriptCode)) throw new ArgumentNullException("javascriptCode");
  733. fixed (char* extensionName_str = extensionName)
  734. fixed (char* javascriptCode_str = javascriptCode)
  735. {
  736. var n_extensionName = new cef_string_t(extensionName_str, extensionName.Length);
  737. var n_javascriptCode = new cef_string_t(javascriptCode_str, javascriptCode.Length);
  738. return libcef.register_extension(&n_extensionName, &n_javascriptCode, handler != null ? handler.ToNative() : null) != 0;
  739. }
  740. }
  741. #endregion
  742. #region cef_web_plugin
  743. // TODO: move web plugins methods to CefRuntime.WebPlugin.Xxx
  744. /// <summary>
  745. /// Visit web plugin information. Can be called on any thread in the browser
  746. /// process.
  747. /// </summary>
  748. public static void VisitWebPluginInfo(CefWebPluginInfoVisitor visitor)
  749. {
  750. if (visitor == null) throw new ArgumentNullException("visitor");
  751. libcef.visit_web_plugin_info(visitor.ToNative());
  752. }
  753. /// <summary>
  754. /// Cause the plugin list to refresh the next time it is accessed regardless
  755. /// of whether it has already been loaded. Can be called on any thread in the
  756. /// browser process.
  757. /// </summary>
  758. public static void RefreshWebPlugins()
  759. {
  760. libcef.refresh_web_plugins();
  761. }
  762. /// <summary>
  763. /// Unregister an internal plugin. This may be undone the next time
  764. /// CefRefreshWebPlugins() is called. Can be called on any thread in the browser
  765. /// process.
  766. /// </summary>
  767. public static void UnregisterInternalWebPlugin(string path)
  768. {
  769. if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
  770. fixed (char* path_str = path)
  771. {
  772. var n_path = new cef_string_t(path_str, path.Length);
  773. libcef.unregister_internal_web_plugin(&n_path);
  774. }
  775. }
  776. /// <summary>
  777. /// Register a plugin crash. Can be called on any thread in the browser process
  778. /// but will be executed on the IO thread.
  779. /// </summary>
  780. public static void RegisterWebPluginCrash(string path)
  781. {
  782. if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
  783. fixed (char* path_str = path)
  784. {
  785. var n_path = new cef_string_t(path_str, path.Length);
  786. libcef.register_web_plugin_crash(&n_path);
  787. }
  788. }
  789. /// <summary>
  790. /// Query if a plugin is unstable. Can be called on any thread in the browser
  791. /// process.
  792. /// </summary>
  793. public static void IsWebPluginUnstable(string path, CefWebPluginUnstableCallback callback)
  794. {
  795. if (string.IsNullOrEmpty(path)) throw new ArgumentNullException("path");
  796. if (callback == null) throw new ArgumentNullException("callback");
  797. fixed (char* path_str = path)
  798. {
  799. var n_path = new cef_string_t(path_str, path.Length);
  800. libcef.is_web_plugin_unstable(&n_path, callback.ToNative());
  801. }
  802. }
  803. /// <summary>
  804. /// Register the Widevine CDM plugin.
  805. ///
  806. /// The client application is responsible for downloading an appropriate
  807. /// platform-specific CDM binary distribution from Google, extracting the
  808. /// contents, and building the required directory structure on the local machine.
  809. /// The CefBrowserHost::StartDownload method and CefZipArchive class can be used
  810. /// to implement this functionality in CEF. Contact Google via
  811. /// https://www.widevine.com/contact.html for details on CDM download.
  812. ///
  813. /// |path| is a directory that must contain the following files:
  814. /// 1. manifest.json file from the CDM binary distribution (see below).
  815. /// 2. widevinecdm file from the CDM binary distribution (e.g.
  816. /// widevinecdm.dll on on Windows, libwidevinecdm.dylib on OS X,
  817. /// libwidevinecdm.so on Linux).
  818. ///
  819. /// If any of these files are missing or if the manifest file has incorrect
  820. /// contents the registration will fail and |callback| will receive a |result|
  821. /// value of CEF_CDM_REGISTRATION_ERROR_INCORRECT_CONTENTS.
  822. ///
  823. /// The manifest.json file must contain the following keys:
  824. /// A. "os": Supported OS (e.g. "mac", "win" or "linux").
  825. /// B. "arch": Supported architecture (e.g. "ia32" or "x64").
  826. /// C. "x-cdm-module-versions": Module API version (e.g. "4").
  827. /// D. "x-cdm-interface-versions": Interface API version (e.g. "8").
  828. /// E. "x-cdm-host-versions": Host API version (e.g. "8").
  829. /// F. "version": CDM version (e.g. "1.4.8.903").
  830. /// G. "x-cdm-codecs": List of supported codecs (e.g. "vp8,vp9.0,avc1").
  831. ///
  832. /// A through E are used to verify compatibility with the current Chromium
  833. /// version. If the CDM is not compatible the registration will fail and
  834. /// |callback| will receive a |result| value of
  835. /// CEF_CDM_REGISTRATION_ERROR_INCOMPATIBLE.
  836. ///
  837. /// |callback| will be executed asynchronously once registration is complete.
  838. ///
  839. /// On Linux this function must be called before CefInitialize() and the
  840. /// registration cannot be changed during runtime. If registration is not
  841. /// supported at the time that CefRegisterWidevineCdm() is called then |callback|
  842. /// will receive a |result| value of CEF_CDM_REGISTRATION_ERROR_NOT_SUPPORTED.
  843. /// </summary>
  844. public static void CefRegisterWidevineCdm(string path, CefRegisterCdmCallback callback = null)
  845. {
  846. fixed (char* path_str = path)
  847. {
  848. var n_path = new cef_string_t(path_str, path.Length);
  849. libcef.register_widevine_cdm(&n_path,
  850. callback != null ? callback.ToNative() : null);
  851. }
  852. }
  853. #endregion
  854. #region cef_path_util
  855. /// <summary>
  856. /// Retrieve the path associated with the specified |key|. Returns true on
  857. /// success. Can be called on any thread in the browser process.
  858. /// </summary>
  859. public static string GetPath(CefPathKey pathKey)
  860. {
  861. var n_value = new cef_string_t();
  862. var success = libcef.get_path(pathKey, &n_value) != 0;
  863. var value = cef_string_t.ToString(&n_value);
  864. libcef.string_clear(&n_value);
  865. if (!success)
  866. {
  867. throw new InvalidOperationException(
  868. string.Format(CultureInfo.InvariantCulture, "Failed to get path for key {0}.", pathKey)
  869. );
  870. }
  871. return value;
  872. }
  873. #endregion
  874. #region cef_process_util
  875. /// <summary>
  876. /// Launches the process specified via |command_line|. Returns true upon
  877. /// success. Must be called on the browser process TID_PROCESS_LAUNCHER thread.
  878. ///
  879. /// Unix-specific notes:
  880. /// - All file descriptors open in the parent process will be closed in the
  881. /// child process except for stdin, stdout, and stderr.
  882. /// - If the first argument on the command line does not contain a slash,
  883. /// PATH will be searched. (See man execvp.)
  884. /// </summary>
  885. public static bool LaunchProcess(CefCommandLine commandLine)
  886. {
  887. if (commandLine == null) throw new ArgumentNullException("commandLine");
  888. return libcef.launch_process(commandLine.ToNative()) != 0;
  889. }
  890. #endregion
  891. #region cef_sandbox_win
  892. // TODO: investigate using of sandbox on windows and .net
  893. #endregion
  894. #region cef_ssl_info
  895. /// <summary>
  896. /// Returns true if the certificate status represents an error.
  897. /// </summary>
  898. public static bool IsCertStatusError(CefCertStatus status)
  899. {
  900. return libcef.is_cert_status_error(status) != 0;
  901. }
  902. #endregion
  903. #region cef_crash_util
  904. /// <summary>
  905. /// Crash reporting is configured using an INI-style config file named
  906. /// "crash_reporter.cfg". On Windows and Linux this file must be placed next to
  907. /// the main application executable. On macOS this file must be placed in the
  908. /// top-level app bundle Resources directory (e.g.
  909. /// "&lt;appname&gt;.app/Contents/Resources"). File contents are as follows:
  910. ///
  911. /// # Comments start with a hash character and must be on their own line.
  912. ///
  913. /// [Config]
  914. /// ProductName=&lt;Value of the "prod" crash key; defaults to "cef"&gt;
  915. /// ProductVersion=&lt;Value of the "ver" crash key; defaults to the CEF version&gt;
  916. /// AppName=&lt;Windows only; App-specific folder name component for storing crash
  917. /// information; default to "CEF"&gt;
  918. /// ExternalHandler=&lt;Windows only; Name of the external handler exe to use
  919. /// instead of re-launching the main exe; default to empty&gt;
  920. /// BrowserCrashForwardingEnabled=&lt;macOS only; True if browser process crashes
  921. /// should be forwarded to the system crash
  922. /// reporter; default to false&gt;
  923. /// ServerURL=&lt;crash server URL; default to empty&gt;
  924. /// RateLimitEnabled=&lt;True if uploads should be rate limited; default to true&gt;
  925. /// MaxUploadsPerDay=&lt;Max uploads per 24 hours, used if rate limit is enabled;
  926. /// default to 5&gt;
  927. /// MaxDatabaseSizeInMb=&lt;Total crash report disk usage greater than this value
  928. /// will cause older reports to be deleted; default to 20&gt;
  929. /// MaxDatabaseAgeInDays=&lt;Crash reports older than this value will be deleted;
  930. /// default to 5&gt;
  931. ///
  932. /// [CrashKeys]
  933. /// my_key1=&lt;small|medium|large&gt;
  934. /// my_key2=&lt;small|medium|large&gt;
  935. ///
  936. /// Config section:
  937. ///
  938. /// If "ProductName" and/or "ProductVersion" are set then the specified values
  939. /// will be included in the crash dump metadata. On macOS if these values are set
  940. /// to empty then they will be retrieved from the Info.plist file using the
  941. /// "CFBundleName" and "CFBundleShortVersionString" keys respectively.
  942. ///
  943. /// If "AppName" is set on Windows then crash report information (metrics,
  944. /// database and dumps) will be stored locally on disk under the
  945. /// "C:\Users\[CurrentUser]\AppData\Local\[AppName]\User Data" folder. On other
  946. /// platforms the CefSettings.user_data_path value will be used.
  947. ///
  948. /// If "ExternalHandler" is set on Windows then the specified exe will be
  949. /// launched as the crashpad-handler instead of re-launching the main process
  950. /// exe. The value can be an absolute path or a path relative to the main exe
  951. /// directory. On Linux the CefSettings.browser_subprocess_path value will be
  952. /// used. On macOS the existing subprocess app bundle will be used.
  953. ///
  954. /// If "BrowserCrashForwardingEnabled" is set to true on macOS then browser
  955. /// process crashes will be forwarded to the system crash reporter. This results
  956. /// in the crash UI dialog being displayed to the user and crash reports being
  957. /// logged under "~/Library/Logs/DiagnosticReports". Forwarding of crash reports
  958. /// from non-browser processes and Debug builds is always disabled.
  959. ///
  960. /// If "ServerURL" is set then crashes will be uploaded as a multi-part POST
  961. /// request to the specified URL. Otherwise, reports will only be stored locally
  962. /// on disk.
  963. ///
  964. /// If "RateLimitEnabled" is set to true then crash report uploads will be rate
  965. /// limited as follows:
  966. /// 1. If "MaxUploadsPerDay" is set to a positive value then at most the
  967. /// specified number of crashes will be uploaded in each 24 hour period.
  968. /// 2. If crash upload fails due to a network or server error then an
  969. /// incremental backoff delay up to a maximum of 24 hours will be applied for
  970. /// retries.
  971. /// 3. If a backoff delay is applied and "MaxUploadsPerDay" is > 1 then the
  972. /// "MaxUploadsPerDay" value will be reduced to 1 until the client is
  973. /// restarted. This helps to avoid an upload flood when the network or
  974. /// server error is resolved.
  975. /// Rate limiting is not supported on Linux.
  976. ///
  977. /// If "MaxDatabaseSizeInMb" is set to a positive value then crash report storage
  978. /// on disk will be limited to that size in megabytes. For example, on Windows
  979. /// each dump is about 600KB so a "MaxDatabaseSizeInMb" value of 20 equates to
  980. /// about 34 crash reports stored on disk. Not supported on Linux.
  981. ///
  982. /// If "MaxDatabaseAgeInDays" is set to a positive value then crash reports older
  983. /// than the specified age in days will be deleted. Not supported on Linux.
  984. ///
  985. /// CrashKeys section:
  986. ///
  987. /// A maximum of 26 crash keys of each size can be specified for use by the
  988. /// application. Crash key values will be truncated based on the specified size
  989. /// (small = 64 bytes, medium = 256 bytes, large = 1024 bytes). The value of
  990. /// crash keys can be set from any thread or process using the
  991. /// CefSetCrashKeyValue function. These key/value pairs will be sent to the crash
  992. /// server along with the crash dump file.+// A maximum of 26 crash keys of each size can be specified for use by the
  993. /// application. Crash key values will be truncated based on the specified size
  994. /// (small = 64 bytes, medium = 256 bytes, large = 1024 bytes). The value of
  995. /// crash keys can be set from any thread or process using the
  996. /// CefSetCrashKeyValue function. These key/value pairs will be sent to the crash
  997. /// server along with the crash dump file.
  998. /// </summary>
  999. public static bool CrashReportingEnabled()
  1000. {
  1001. return libcef.crash_reporting_enabled() != 0;
  1002. }
  1003. /// <summary>
  1004. /// Sets or clears a specific key-value pair from the crash metadata.
  1005. /// </summary>
  1006. public static void SetCrashKeyValue(string key, string value)
  1007. {
  1008. fixed (char* key_ptr = key)
  1009. fixed (char* value_ptr = value)
  1010. {
  1011. var n_key = new cef_string_t(key_ptr, key.Length);
  1012. var n_value = new cef_string_t(value_ptr, value != null ? value.Length : 0);
  1013. libcef.set_crash_key_value(&n_key, &n_value);
  1014. }
  1015. }
  1016. #endregion
  1017. #region file_util
  1018. /// <summary>
  1019. /// Loads the existing "Certificate Revocation Lists" file that is managed by
  1020. /// Google Chrome. This file can generally be found in Chrome's User Data
  1021. /// directory (e.g. "C:\Users\[User]\AppData\Local\Google\Chrome\User Data\" on
  1022. /// Windows) and is updated periodically by Chrome's component updater service.
  1023. /// Must be called in the browser process after the context has been initialized.
  1024. /// See https://dev.chromium.org/Home/chromium-security/crlsets for background.
  1025. /// </summary>
  1026. public static void LoadCrlSetsFile(string path)
  1027. {
  1028. if (path == null) throw new ArgumentNullException(nameof(path));
  1029. fixed (char* path_ptr = path)
  1030. {
  1031. var n_path = new cef_string_t(path_ptr, path.Length);
  1032. libcef.load_crlsets_file(&n_path);
  1033. }
  1034. }
  1035. #endregion
  1036. private static void LoadIfNeed()
  1037. {
  1038. if (!_loaded) Load();
  1039. }
  1040. #region linux
  1041. /////
  1042. //// Return the singleton X11 display shared with Chromium. The display is not
  1043. //// thread-safe and must only be accessed on the browser process UI thread.
  1044. /////
  1045. //CEF_EXPORT XDisplay* cef_get_xdisplay();
  1046. #endregion
  1047. }
  1048. }