using System; using System.Threading.Tasks; using Xilium.CefGlue.Common.Events; using Xilium.CefGlue.Common.Handlers; using Xilium.CefGlue.Common.Helpers.Logger; using Xilium.CefGlue.Common.Platform; namespace Xilium.CefGlue.Common { /// /// Browser interface shared among the several implementations (Avalonia, WPF, ...) /// public abstract partial class BaseCefBrowser : IDisposable { protected readonly ILogger _logger; private readonly CommonBrowserAdapter _adapter; #region Disposable public BaseCefBrowser() { if (!CefRuntimeLoader.IsLoaded) { CefRuntimeLoader.Load(); } _logger = new Logger(nameof(BaseCefBrowser)); if (CefRuntimeLoader.IsOSREnabled) { _adapter = new CommonOffscreenBrowserAdapter(this, nameof(BaseCefBrowser), CreateOffScreenControlHost(), CreatePopupHost(), _logger); } else { _adapter = new CommonBrowserAdapter(this, nameof(BaseCefBrowser), CreateControl(), _logger); } } ~BaseCefBrowser() { Dispose(false); } public void HandleOpenContextMenu(CefContextMenuParams parameters, CefMenuModel model, CefRunContextMenuCallback callback) { ((ICefBrowserHost) _adapter).HandleOpenContextMenu(parameters, model, callback); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { _adapter?.Dispose(disposing); } #endregion /// /// Creates the instance of the popup control that will host the browser popups. /// /// internal abstract IOffScreenPopupHost CreatePopupHost(); /// /// Creates the instance of the control that will host the browser. /// /// internal abstract IControl CreateControl(); /// /// Creates the instance of the control that will host the browser in the offscreen mode. /// /// internal abstract IOffScreenControlHost CreateOffScreenControlHost(); /// /// Event fired when the browser is initialized. /// public event Action BrowserInitialized { add => _adapter.Initialized += value; remove => _adapter.Initialized -= value; } /// /// Event fired when the browser starts loading a frame. /// public event LoadStartEventHandler LoadStart { add => _adapter.LoadStart += value; remove => _adapter.LoadStart -= value; } /// /// Event fired when the browser ends loading a frame. /// public event LoadEndEventHandler LoadEnd { add => _adapter.LoadEnd += value; remove => _adapter.LoadEnd -= value; } /// /// Event fired when the loading state of a frame changes. /// public event LoadingStateChangeEventHandler LoadingStateChange { add => _adapter.LoadingStateChange += value; remove => _adapter.LoadingStateChange -= value; } /// /// Event fired when the an error occurs while loading a frame. /// public event LoadErrorEventHandler LoadError { add => _adapter.LoadError += value; remove => _adapter.LoadError -= value; } /// /// Event fired when the address changes. /// public event AddressChangedEventHandler AddressChanged { add => _adapter.AddressChanged += value; remove => _adapter.AddressChanged -= value; } /// /// Event fired when a console message arrives. /// public event ConsoleMessageEventHandler ConsoleMessage { add => _adapter.ConsoleMessage += value; remove => _adapter.ConsoleMessage -= value; } /// /// Event fired when the browser receives a status message. |message| contains the text that will be displayed in the status message. /// public event StatusMessageEventHandler StatusMessage { add => _adapter.StatusMessage += value; remove => _adapter.StatusMessage -= value; } /// /// Event fired when the title changes. /// public event TitleChangedEventHandler TitleChanged { add => _adapter.TitleChanged += value; remove => _adapter.TitleChanged -= value; } /// /// Event fired when the javascript context of the specified frame is created and ready to execute. /// public event JavascriptContextLifetimeEventHandler JavascriptContextCreated { add => _adapter.JavascriptContextCreated += value; remove => _adapter.JavascriptContextCreated -= value; } /// /// Event fired when the javascript context of the specified frame is destroyed. /// public event JavascriptContextLifetimeEventHandler JavascriptContextReleased { add => _adapter.JavascriptContextReleased += value; remove => _adapter.JavascriptContextReleased -= value; } /// /// Event fired when a javascript uncaugh exception is thrown. /// public event JavascriptUncaughtExceptionEventHandler JavascriptUncaughException { add => _adapter.JavascriptUncaughtException += value; remove => _adapter.JavascriptUncaughtException -= value; } /// /// Event fired when an internal browser exception is unhandled. /// public event AsyncUnhandledExceptionEventHandler UnhandledException { add => _adapter.UnhandledException += value; remove => _adapter.UnhandledException -= value; } /// /// Return the handler for context menus. If no handler is provided the default implementation will be used. /// public ContextMenuHandler ContextMenuHandler { get => _adapter.ContextMenuHandler; set => _adapter.ContextMenuHandler = value; } /// /// Return the handler for dialogs. If no handler is provided the default implementation will be used. /// public DialogHandler DialogHandler { get => _adapter.DialogHandler; set => _adapter.DialogHandler = value; } /// /// Return the handler for download events. If no handler is returned downloads will not be allowed. /// public DownloadHandler DownloadHandler { get => _adapter.DownloadHandler; set => _adapter.DownloadHandler = value; } /// /// Return the handler for drag events. /// public DragHandler DragHandler { get => _adapter.DragHandler; set => _adapter.DragHandler = value; } /// /// Return the handler for find result events. /// public FindHandler FindHandler { get => _adapter.FindHandler; set => _adapter.FindHandler = value; } /// /// Return the handler for focus events. /// public FocusHandler FocusHandler { get => _adapter.FocusHandler; set => _adapter.FocusHandler = value; } /// /// Return the handler for keyboard events. /// public KeyboardHandler KeyboardHandler { get => _adapter.KeyboardHandler; set => _adapter.KeyboardHandler = value; } /// /// Return the handler for browser request events. /// public RequestHandler RequestHandler { get => _adapter.RequestHandler; set => _adapter.RequestHandler = value; } /// /// Return the handler for browser life span events. /// public LifeSpanHandler LifeSpanHandler { get => _adapter.LifeSpanHandler; set => _adapter.LifeSpanHandler = value; } /// /// Return the handler for browser display state events. /// public DisplayHandler DisplayHandler { get => _adapter.DisplayHandler; set => _adapter.DisplayHandler = value; } /// /// Return the handler for off-screen rendering events. /// public RenderHandler RenderHandler { get => _adapter.RenderHandler; set => _adapter.RenderHandler = value; } /// /// Return the handler for JavaScript dialogs. If no handler is provided the default implementation will be used. /// public JSDialogHandler JSDialogHandler { get => _adapter.JSDialogHandler; set => _adapter.JSDialogHandler = value; } /// /// Gets or set the url. /// public string Address { get => _adapter.Address; set => _adapter.Address = value; } /// /// Returns true when the underlying browser has been initialized. /// public bool IsBrowserInitialized => _adapter.IsInitialized; /// /// Returns true when the javascript engine of the frame. /// public bool IsJavascriptEngineInitialized => _adapter.IsJavascriptEngineInitialized; /// /// Returns true if the browser is currently loading. /// public bool IsLoading => _adapter.IsLoading; /// /// Returns the current page title. /// public string Title => _adapter.Title; /// /// Gets or sets the initial browser settings. /// Changing this property after browser becomes initialized does not have any effects. /// public CefBrowserSettings Settings => _adapter.Settings; /// /// Specifies the maximium number of calls that can be made simultaneously to native object methods. /// Defaults to the int.MaxValue. /// public int MaxNativeMethodsParallelCalls { get => _adapter.MaxNativeMethodsParallelCalls; set => _adapter.MaxNativeMethodsParallelCalls = value; } /// /// Get or set the current zoom level. The default zoom level is 0.0. /// public double ZoomLevel { get => _adapter.ZoomLevel; set => _adapter.ZoomLevel = value; } /// /// The undelying cef browser instance. Can be used for advanced functionality. /// protected CefBrowser UnderlyingBrowser => _adapter.Browser; /// /// Returns true if the browser can navigate backwards. /// /// public bool CanGoBack => _adapter.CanGoBack(); /// /// Navigate backwards. /// public void GoBack() { _adapter.GoBack(); } /// /// Returns true if the browser can navigate forward. /// /// public bool CanGoForward => _adapter.CanGoForward(); /// /// Navigate forwards. /// public void GoForward() { _adapter.GoForward(); } /// /// Reload the current page. /// public void Reload(bool ignoreCache = false) { _adapter.Reload(ignoreCache); } /// /// Executes the specified javascript snippet. /// /// The javascript snippet. /// Url where the script in question can be found. /// The base line number to use for error, if any. public void ExecuteJavaScript(string code, string url = null, int line = 1) { _adapter.ExecuteJavaScript(code, url ?? "about:blank", line); } /// /// Evaluates the specified javascript snippet. /// /// The type of the resulting object. /// The javascript snippet. /// Url where the script in question can be found. /// The base line number to use for error, if any. /// The name of the frame where the script will be executed. /// Timeout after which the evaluation is cancelled. /// The result of the evaluation. public Task EvaluateJavaScript(string code, string frameName = null, string url = null, int line = 1, TimeSpan? timeout = null) { return _adapter.EvaluateJavaScript(code, url ?? "about:blank", line, frameName, timeout); } /// /// Evaluates the specified javascript snippet. /// /// The type of the resulting object. /// The javascript snippet. /// Url where the script in question can be found. /// The base line number to use for error, if any. /// The frame where the script will be executed. /// Timeout after which the evaluation is cancelled. /// The result of the evaluation. public Task EvaluateJavaScript(string code, CefFrame frame, string url = null, int line = 1, TimeSpan? timeout = null) { return _adapter.EvaluateJavaScript(code, url ?? "about:blank", line, frame, timeout); } /// /// Opens the Developer tools. /// public void ShowDeveloperTools() { _adapter.ShowDeveloperTools(); } /// /// Closes the Developer tools (opened previously). /// public void CloseDeveloperTools() { _adapter.CloseDeveloperTools(); } /// /// Registers a Javascript object in this browser instance. /// /// The object to be made accessible to Javascript /// The name of the object. (e.g. "potatoes", if you want the object to be accessible as window.potatoes). /// Optional handler to be executed before the target object method is called. You may use this for instance to log calls. public void RegisterJavascriptObject(object targetObject, string name, JavascriptObjectMethodCallHandler methodHandler = null) { _adapter.RegisterJavascriptObject(targetObject, name, methodHandler); } /// /// Unregisters a Javascript object in this browser instance. /// /// The name of the object used to register. public void UnregisterJavascriptObject(string name) { _adapter.UnregisterJavascriptObject(name); } /// /// Returns true if an object has already beend regsisterd with the specified name. /// /// Name of the object to check. /// public bool IsJavascriptObjectRegistered(string name) { return _adapter.IsJavascriptObjectRegistered(name); } /// /// Creates the browser (if not created yet) with the specified dimensions. /// /// /// /// True if browser was created, false otherwise. protected bool CreateBrowser(int width, int height) { return _adapter.CreateBrowser(width, height); } } }