BaseCefBrowser.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. using System;
  2. using System.Threading.Tasks;
  3. using Xilium.CefGlue.Common.Events;
  4. using Xilium.CefGlue.Common.Handlers;
  5. using Xilium.CefGlue.Common.Helpers.Logger;
  6. using Xilium.CefGlue.Common.Platform;
  7. namespace Xilium.CefGlue.Common
  8. {
  9. /// <summary>
  10. /// Browser interface shared among the several implementations (Avalonia, WPF, ...)
  11. /// </summary>
  12. public abstract partial class BaseCefBrowser : IDisposable
  13. {
  14. protected readonly ILogger _logger;
  15. private readonly CommonBrowserAdapter _adapter;
  16. #region Disposable
  17. public BaseCefBrowser()
  18. {
  19. if (!CefRuntimeLoader.IsLoaded)
  20. {
  21. CefRuntimeLoader.Load();
  22. }
  23. _logger = new Logger(nameof(BaseCefBrowser));
  24. if (CefRuntimeLoader.IsOSREnabled)
  25. {
  26. _adapter = new CommonOffscreenBrowserAdapter(this, nameof(BaseCefBrowser), CreateOffScreenControlHost(), CreatePopupHost(), _logger);
  27. }
  28. else
  29. {
  30. _adapter = new CommonBrowserAdapter(this, nameof(BaseCefBrowser), CreateControl(), _logger);
  31. }
  32. }
  33. ~BaseCefBrowser()
  34. {
  35. Dispose(false);
  36. }
  37. public void HandleOpenContextMenu(CefContextMenuParams parameters, CefMenuModel model, CefRunContextMenuCallback callback)
  38. {
  39. ((ICefBrowserHost) _adapter).HandleOpenContextMenu(parameters, model, callback);
  40. }
  41. public void Dispose()
  42. {
  43. Dispose(true);
  44. GC.SuppressFinalize(this);
  45. }
  46. protected virtual void Dispose(bool disposing)
  47. {
  48. _adapter?.Dispose(disposing);
  49. }
  50. #endregion
  51. /// <summary>
  52. /// Creates the instance of the popup control that will host the browser popups.
  53. /// </summary>
  54. /// <returns></returns>
  55. internal abstract IOffScreenPopupHost CreatePopupHost();
  56. /// <summary>
  57. /// Creates the instance of the control that will host the browser.
  58. /// </summary>
  59. /// <returns></returns>
  60. internal abstract IControl CreateControl();
  61. /// <summary>
  62. /// Creates the instance of the control that will host the browser in the offscreen mode.
  63. /// </summary>
  64. /// <returns></returns>
  65. internal abstract IOffScreenControlHost CreateOffScreenControlHost();
  66. /// <summary>
  67. /// Event fired when the browser is initialized.
  68. /// </summary>
  69. public event Action BrowserInitialized { add => _adapter.Initialized += value; remove => _adapter.Initialized -= value; }
  70. /// <summary>
  71. /// Event fired when the browser starts loading a frame.
  72. /// </summary>
  73. public event LoadStartEventHandler LoadStart { add => _adapter.LoadStart += value; remove => _adapter.LoadStart -= value; }
  74. /// <summary>
  75. /// Event fired when the browser ends loading a frame.
  76. /// </summary>
  77. public event LoadEndEventHandler LoadEnd { add => _adapter.LoadEnd += value; remove => _adapter.LoadEnd -= value; }
  78. /// <summary>
  79. /// Event fired when the loading state of a frame changes.
  80. /// </summary>
  81. public event LoadingStateChangeEventHandler LoadingStateChange { add => _adapter.LoadingStateChange += value; remove => _adapter.LoadingStateChange -= value; }
  82. /// <summary>
  83. /// Event fired when the an error occurs while loading a frame.
  84. /// </summary>
  85. public event LoadErrorEventHandler LoadError { add => _adapter.LoadError += value; remove => _adapter.LoadError -= value; }
  86. /// <summary>
  87. /// Event fired when the address changes.
  88. /// </summary>
  89. public event AddressChangedEventHandler AddressChanged { add => _adapter.AddressChanged += value; remove => _adapter.AddressChanged -= value; }
  90. /// <summary>
  91. /// Event fired when a console message arrives.
  92. /// </summary>
  93. public event ConsoleMessageEventHandler ConsoleMessage { add => _adapter.ConsoleMessage += value; remove => _adapter.ConsoleMessage -= value; }
  94. /// <summary>
  95. /// Event fired when the browser receives a status message. |message| contains the text that will be displayed in the status message.
  96. /// </summary>
  97. public event StatusMessageEventHandler StatusMessage { add => _adapter.StatusMessage += value; remove => _adapter.StatusMessage -= value; }
  98. /// <summary>
  99. /// Event fired when the title changes.
  100. /// </summary>
  101. public event TitleChangedEventHandler TitleChanged { add => _adapter.TitleChanged += value; remove => _adapter.TitleChanged -= value; }
  102. /// <summary>
  103. /// Event fired when the javascript context of the specified frame is created and ready to execute.
  104. /// </summary>
  105. public event JavascriptContextLifetimeEventHandler JavascriptContextCreated { add => _adapter.JavascriptContextCreated += value; remove => _adapter.JavascriptContextCreated -= value; }
  106. /// <summary>
  107. /// Event fired when the javascript context of the specified frame is destroyed.
  108. /// </summary>
  109. public event JavascriptContextLifetimeEventHandler JavascriptContextReleased { add => _adapter.JavascriptContextReleased += value; remove => _adapter.JavascriptContextReleased -= value; }
  110. /// <summary>
  111. /// Event fired when a javascript uncaugh exception is thrown.
  112. /// </summary>
  113. public event JavascriptUncaughtExceptionEventHandler JavascriptUncaughException { add => _adapter.JavascriptUncaughtException += value; remove => _adapter.JavascriptUncaughtException -= value; }
  114. /// <summary>
  115. /// Event fired when an internal browser exception is unhandled.
  116. /// </summary>
  117. public event AsyncUnhandledExceptionEventHandler UnhandledException { add => _adapter.UnhandledException += value; remove => _adapter.UnhandledException -= value; }
  118. /// <summary>
  119. /// Return the handler for context menus. If no handler is provided the default implementation will be used.
  120. /// </summary>
  121. public ContextMenuHandler ContextMenuHandler { get => _adapter.ContextMenuHandler; set => _adapter.ContextMenuHandler = value; }
  122. /// <summary>
  123. /// Return the handler for dialogs. If no handler is provided the default implementation will be used.
  124. /// </summary>
  125. public DialogHandler DialogHandler { get => _adapter.DialogHandler; set => _adapter.DialogHandler = value; }
  126. /// <summary>
  127. /// Return the handler for download events. If no handler is returned downloads will not be allowed.
  128. /// </summary>
  129. public DownloadHandler DownloadHandler { get => _adapter.DownloadHandler; set => _adapter.DownloadHandler = value; }
  130. /// <summary>
  131. /// Return the handler for drag events.
  132. /// </summary>
  133. public DragHandler DragHandler { get => _adapter.DragHandler; set => _adapter.DragHandler = value; }
  134. /// <summary>
  135. /// Return the handler for find result events.
  136. /// </summary>
  137. public FindHandler FindHandler { get => _adapter.FindHandler; set => _adapter.FindHandler = value; }
  138. /// <summary>
  139. /// Return the handler for focus events.
  140. /// </summary>
  141. public FocusHandler FocusHandler { get => _adapter.FocusHandler; set => _adapter.FocusHandler = value; }
  142. /// <summary>
  143. /// Return the handler for keyboard events.
  144. /// </summary>
  145. public KeyboardHandler KeyboardHandler { get => _adapter.KeyboardHandler; set => _adapter.KeyboardHandler = value; }
  146. /// <summary>
  147. /// Return the handler for browser request events.
  148. /// </summary>
  149. public RequestHandler RequestHandler { get => _adapter.RequestHandler; set => _adapter.RequestHandler = value; }
  150. /// <summary>
  151. /// Return the handler for browser life span events.
  152. /// </summary>
  153. public LifeSpanHandler LifeSpanHandler { get => _adapter.LifeSpanHandler; set => _adapter.LifeSpanHandler = value; }
  154. /// <summary>
  155. /// Return the handler for browser display state events.
  156. /// </summary>
  157. public DisplayHandler DisplayHandler { get => _adapter.DisplayHandler; set => _adapter.DisplayHandler = value; }
  158. /// <summary>
  159. /// Return the handler for off-screen rendering events.
  160. /// </summary>
  161. public RenderHandler RenderHandler { get => _adapter.RenderHandler; set => _adapter.RenderHandler = value; }
  162. /// <summary>
  163. /// Return the handler for JavaScript dialogs. If no handler is provided the default implementation will be used.
  164. /// </summary>
  165. public JSDialogHandler JSDialogHandler { get => _adapter.JSDialogHandler; set => _adapter.JSDialogHandler = value; }
  166. /// <summary>
  167. /// Gets or set the url.
  168. /// </summary>
  169. public string Address { get => _adapter.Address; set => _adapter.Address = value; }
  170. /// <summary>
  171. /// Returns true when the underlying browser has been initialized.
  172. /// </summary>
  173. public bool IsBrowserInitialized => _adapter.IsInitialized;
  174. /// <summary>
  175. /// Returns true when the javascript engine of the frame.
  176. /// </summary>
  177. public bool IsJavascriptEngineInitialized => _adapter.IsJavascriptEngineInitialized;
  178. /// <summary>
  179. /// Returns true if the browser is currently loading.
  180. /// </summary>
  181. public bool IsLoading => _adapter.IsLoading;
  182. /// <summary>
  183. /// Returns the current page title.
  184. /// </summary>
  185. public string Title => _adapter.Title;
  186. /// <summary>
  187. /// Gets or sets the initial browser settings.
  188. /// Changing this property after browser becomes initialized does not have any effects.
  189. /// </summary>
  190. public CefBrowserSettings Settings => _adapter.Settings;
  191. /// <summary>
  192. /// Specifies the maximium number of calls that can be made simultaneously to native object methods.
  193. /// Defaults to the int.MaxValue.
  194. /// </summary>
  195. public int MaxNativeMethodsParallelCalls { get => _adapter.MaxNativeMethodsParallelCalls; set => _adapter.MaxNativeMethodsParallelCalls = value; }
  196. /// <summary>
  197. /// Get or set the current zoom level. The default zoom level is 0.0.
  198. /// </summary>
  199. public double ZoomLevel { get => _adapter.ZoomLevel; set => _adapter.ZoomLevel = value; }
  200. /// <summary>
  201. /// The undelying cef browser instance. Can be used for advanced functionality.
  202. /// </summary>
  203. protected CefBrowser UnderlyingBrowser => _adapter.Browser;
  204. /// <summary>
  205. /// Returns true if the browser can navigate backwards.
  206. /// </summary>
  207. /// <returns></returns>
  208. public bool CanGoBack => _adapter.CanGoBack();
  209. /// <summary>
  210. /// Navigate backwards.
  211. /// </summary>
  212. public void GoBack()
  213. {
  214. _adapter.GoBack();
  215. }
  216. /// <summary>
  217. /// Returns true if the browser can navigate forward.
  218. /// </summary>
  219. /// <returns></returns>
  220. public bool CanGoForward => _adapter.CanGoForward();
  221. /// <summary>
  222. /// Navigate forwards.
  223. /// </summary>
  224. public void GoForward()
  225. {
  226. _adapter.GoForward();
  227. }
  228. /// <summary>
  229. /// Reload the current page.
  230. /// </summary>
  231. public void Reload(bool ignoreCache = false)
  232. {
  233. _adapter.Reload(ignoreCache);
  234. }
  235. /// <summary>
  236. /// Executes the specified javascript snippet.
  237. /// </summary>
  238. /// <param name="code">The javascript snippet.</param>
  239. /// <param name="url">Url where the script in question can be found.</param>
  240. /// <param name="line">The base line number to use for error, if any.</param>
  241. public void ExecuteJavaScript(string code, string url = null, int line = 1)
  242. {
  243. _adapter.ExecuteJavaScript(code, url ?? "about:blank", line);
  244. }
  245. /// <summary>
  246. /// Evaluates the specified javascript snippet.
  247. /// </summary>
  248. /// <typeparam name="T">The type of the resulting object.</typeparam>
  249. /// <param name="code">The javascript snippet.</param>
  250. /// <param name="url">Url where the script in question can be found.</param>
  251. /// <param name="line">The base line number to use for error, if any.</param>
  252. /// <param name="frameName">The name of the frame where the script will be executed.</param>
  253. /// <param name="timeout">Timeout after which the evaluation is cancelled.</param>
  254. /// <returns>The result of the evaluation.</returns>
  255. public Task<T> EvaluateJavaScript<T>(string code, string frameName = null, string url = null, int line = 1, TimeSpan? timeout = null)
  256. {
  257. return _adapter.EvaluateJavaScript<T>(code, url ?? "about:blank", line, frameName, timeout);
  258. }
  259. /// <summary>
  260. /// Evaluates the specified javascript snippet.
  261. /// </summary>
  262. /// <typeparam name="T">The type of the resulting object.</typeparam>
  263. /// <param name="code">The javascript snippet.</param>
  264. /// <param name="url">Url where the script in question can be found.</param>
  265. /// <param name="line">The base line number to use for error, if any.</param>
  266. /// <param name="frame">The frame where the script will be executed.</param>
  267. /// <param name="timeout">Timeout after which the evaluation is cancelled.</param>
  268. /// <returns>The result of the evaluation.</returns>
  269. public Task<T> EvaluateJavaScript<T>(string code, CefFrame frame, string url = null, int line = 1, TimeSpan? timeout = null)
  270. {
  271. return _adapter.EvaluateJavaScript<T>(code, url ?? "about:blank", line, frame, timeout);
  272. }
  273. /// <summary>
  274. /// Opens the Developer tools.
  275. /// </summary>
  276. public void ShowDeveloperTools()
  277. {
  278. _adapter.ShowDeveloperTools();
  279. }
  280. /// <summary>
  281. /// Closes the Developer tools (opened previously).
  282. /// </summary>
  283. public void CloseDeveloperTools()
  284. {
  285. _adapter.CloseDeveloperTools();
  286. }
  287. /// <summary>
  288. /// Registers a Javascript object in this browser instance.
  289. /// </summary>
  290. /// <param name="targetObject">The object to be made accessible to Javascript</param>
  291. /// <param name="name">The name of the object. (e.g. "potatoes", if you want the object to be accessible as window.potatoes).</param>
  292. /// <param name="methodHandler">Optional handler to be executed before the target object method is called. You may use this for instance to log calls.</param>
  293. public void RegisterJavascriptObject(object targetObject, string name, JavascriptObjectMethodCallHandler methodHandler = null)
  294. {
  295. _adapter.RegisterJavascriptObject(targetObject, name, methodHandler);
  296. }
  297. /// <summary>
  298. /// Unregisters a Javascript object in this browser instance.
  299. /// </summary>
  300. /// <param name="name">The name of the object used to register.</param>
  301. public void UnregisterJavascriptObject(string name)
  302. {
  303. _adapter.UnregisterJavascriptObject(name);
  304. }
  305. /// <summary>
  306. /// Returns true if an object has already beend regsisterd with the specified name.
  307. /// </summary>
  308. /// <param name="name">Name of the object to check.</param>
  309. /// <returns></returns>
  310. public bool IsJavascriptObjectRegistered(string name)
  311. {
  312. return _adapter.IsJavascriptObjectRegistered(name);
  313. }
  314. /// <summary>
  315. /// Creates the browser (if not created yet) with the specified dimensions.
  316. /// </summary>
  317. /// <param name="width"></param>
  318. /// <param name="height"></param>
  319. /// <returns>True if browser was created, false otherwise.</returns>
  320. protected bool CreateBrowser(int width, int height)
  321. {
  322. return _adapter.CreateBrowser(width, height);
  323. }
  324. }
  325. }