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);
}
}
}