// Copyright © 2020 The CefSharp Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
//NOTE:Classes in the CefSharp.Core namespace have been hidden from intellisnse so users don't use them directly
using System;
using System.Threading.Tasks;
using CefSharp.Internals;
namespace CefSharp
{
///
/// Global CEF methods are exposed through this class. e.g. CefInitalize maps to Cef.Initialize
/// CEF API Doc https://magpcss.org/ceforum/apidocs3/projects/(default)/(_globals).html
/// This class cannot be inherited.
///
public static class Cef
{
///
/// Event is raised when is called,
/// before the shutdown logic is executed.
///
///
/// Will be called on the same thread as
///
public static event EventHandler ShutdownStarted;
public static TaskFactory UIThreadTaskFactory
{
get { return Core.Cef.UIThreadTaskFactory; }
}
public static TaskFactory IOThreadTaskFactory
{
get { return Core.Cef.IOThreadTaskFactory; }
}
public static TaskFactory FileThreadTaskFactory
{
get { return Core.Cef.FileThreadTaskFactory; }
}
public static void AddDisposable(IDisposable item)
{
Core.Cef.AddDisposable(item);
}
public static void RemoveDisposable(IDisposable item)
{
Core.Cef.RemoveDisposable(item);
}
/// Gets a value that indicates whether CefSharp is initialized.
/// true if CefSharp is initialized; otherwise, false.
public static bool IsInitialized
{
get { return Core.Cef.IsInitialized; }
}
/// Gets a value that indicates whether CefSharp was shutdown.
/// true if CefSharp was shutdown; otherwise, false.
public static bool IsShutdown
{
get { return Core.Cef.IsShutdown; }
}
/// Gets a value that indicates the version of CefSharp currently being used.
/// The CefSharp version.
public static string CefSharpVersion
{
get { return Core.Cef.CefSharpVersion; }
}
/// Gets a value that indicates the CEF version currently being used.
/// The CEF Version
public static string CefVersion
{
get { return Core.Cef.CefVersion; }
}
/// Gets a value that indicates the Chromium version currently being used.
/// The Chromium version.
public static string ChromiumVersion
{
get { return Core.Cef.ChromiumVersion; }
}
///
/// Gets a value that indicates the Git Hash for CEF version currently being used.
///
/// The Git Commit Hash
public static string CefCommitHash
{
get { return Core.Cef.CefCommitHash; }
}
///
/// Parse the specified url into its component parts.
/// Uses a GURL to parse the Url. GURL is Google's URL parsing library.
///
/// url
/// Returns null if the URL is empty or invalid.
public static UrlParts ParseUrl(string url)
{
return Core.Cef.ParseUrl(url);
}
///
/// Initializes CefSharp with user-provided settings.
/// It's important to note that Initialize and Shutdown MUST be called on your main
/// application thread (typically the UI thread). If you call them on different
/// threads, your application will hang. See the documentation for Cef.Shutdown() for more details.
///
/// CefSharp configuration settings.
/// true if successful; otherwise, false.
public static bool Initialize(CefSettingsBase settings)
{
using (settings)
{
return Core.Cef.Initialize(settings.settings);
}
}
///
/// Initializes CefSharp with user-provided settings.
/// It's important to note that Initialize/Shutdown MUST be called on your main
/// application thread (typically the UI thread). If you call them on different
/// threads, your application will hang. See the documentation for Cef.Shutdown() for more details.
///
/// CefSharp configuration settings.
/// Check that all relevant dependencies available, throws exception if any are missing
/// true if successful; otherwise, false.
public static bool Initialize(CefSettingsBase settings, bool performDependencyCheck)
{
using (settings)
{
return Core.Cef.Initialize(settings.settings, performDependencyCheck);
}
}
///
/// Initializes CefSharp with user-provided settings.
/// It's important to note that Initialize/Shutdown MUST be called on your main
/// application thread (typically the UI thread). If you call them on different
/// threads, your application will hang. See the documentation for Cef.Shutdown() for more details.
///
/// CefSharp configuration settings.
/// Check that all relevant dependencies available, throws exception if any are missing
/// The handler for functionality specific to the browser process. Null if you don't wish to handle these events
/// true if successful; otherwise, false.
public static bool Initialize(CefSettingsBase settings, bool performDependencyCheck, IBrowserProcessHandler browserProcessHandler)
{
using (settings)
{
return Core.Cef.Initialize(settings.settings, performDependencyCheck, browserProcessHandler);
}
}
///
/// Initializes CefSharp with user-provided settings.
/// It's important to note that Initialize/Shutdown MUST be called on your main
/// application thread (typically the UI thread). If you call them on different
/// threads, your application will hang. See the documentation for Cef.Shutdown() for more details.
///
/// CefSharp configuration settings.
/// Check that all relevant dependencies available, throws exception if any are missing
/// Implement this interface to provide handler implementations. Null if you don't wish to handle these events
/// true if successful; otherwise, false.
public static bool Initialize(CefSettingsBase settings, bool performDependencyCheck, IApp cefApp)
{
using (settings)
{
return Core.Cef.Initialize(settings.settings, performDependencyCheck, cefApp);
}
}
///
/// Initializes CefSharp with user-provided settings. This method allows you to wait for
/// to be called before continuing.
/// It's important to note that Initialize and Shutdown MUST be called on your main
/// application thread (typically the UI thread). If you call them on different
/// threads, your application will hang. See the documentation for Cef.Shutdown() for more details.
///
/// CefSharp configuration settings.
/// Check that all relevant dependencies available, throws exception if any are missing
/// The handler for functionality specific to the browser process. Null if you don't wish to handle these events
/// returns a Task that can be awaited. true if successful; otherwise, false. If false check the log file for possible errors
///
/// If successful then the Task will be completed successfully when is called.
/// If successful then the continuation will happen syncrionously on the CEF UI thread.
///
public static Task InitializeAsync(CefSettingsBase settings, bool performDependencyCheck = true, IBrowserProcessHandler browserProcessHandler = null)
{
using (settings)
{
try
{
//Ignore the result, the Task will be set in Core.Cef.Initialze
Core.Cef.Initialize(settings.settings, performDependencyCheck, browserProcessHandler);
}
catch (Exception ex)
{
GlobalContextInitialized.SetException(ex);
}
}
return GlobalContextInitialized.Task;
}
///
/// Run the CEF message loop. Use this function instead of an application-
/// provided message loop to get the best balance between performance and CPU
/// usage. This function should only be called on the main application thread and
/// only if Cef.Initialize() is called with a
/// CefSettings.MultiThreadedMessageLoop value of false. This function will
/// block until a quit message is received by the system.
///
public static void RunMessageLoop()
{
Core.Cef.RunMessageLoop();
}
///
/// Quit the CEF message loop that was started by calling Cef.RunMessageLoop().
/// This function should only be called on the main application thread and only
/// if Cef.RunMessageLoop() was used.
///
public static void QuitMessageLoop()
{
Core.Cef.QuitMessageLoop();
}
///
/// Perform a single iteration of CEF message loop processing.This function is
/// provided for cases where the CEF message loop must be integrated into an
/// existing application message loop. Use of this function is not recommended
/// for most users; use CefSettings.MultiThreadedMessageLoop if possible (the default).
/// When using this function care must be taken to balance performance
/// against excessive CPU usage. It is recommended to enable the
/// CefSettings.ExternalMessagePump option when using
/// this function so that IBrowserProcessHandler.OnScheduleMessagePumpWork()
/// callbacks can facilitate the scheduling process. This function should only be
/// called on the main application thread and only if Cef.Initialize() is called
/// with a CefSettings.MultiThreadedMessageLoop value of false. This function
/// will not block.
///
public static void DoMessageLoopWork()
{
Core.Cef.DoMessageLoopWork();
}
///
/// This function should be called from the application entry point function to execute a secondary process.
/// It can be used to run secondary processes from the browser client executable (default behavior) or
/// from a separate executable specified by the CefSettings.browser_subprocess_path value.
/// If called for the browser process (identified by no "type" command-line value) it will return immediately with a value of -1.
/// If called for a recognized secondary process it will block until the process should exit and then return the process exit code.
/// The |application| parameter may be empty. The |windows_sandbox_info| parameter is only used on Windows and may be NULL (see cef_sandbox_win.h for details).
///
public static int ExecuteProcess()
{
return Core.Cef.ExecuteProcess();
}
/// Add an entry to the cross-origin whitelist.
/// The origin allowed to be accessed by the target protocol/domain.
/// The target protocol allowed to access the source origin.
/// The optional target domain allowed to access the source origin.
/// If set to true would allow a blah.example.com if the
/// was set to example.com
///
/// Returns false if is invalid or the whitelist cannot be accessed.
///
/// The same-origin policy restricts how scripts hosted from different origins
/// (scheme + domain + port) can communicate. By default, scripts can only access
/// resources with the same origin. Scripts hosted on the HTTP and HTTPS schemes
/// (but no other schemes) can use the "Access-Control-Allow-Origin" header to
/// allow cross-origin requests. For example, https://source.example.com can make
/// XMLHttpRequest requests on http://target.example.com if the
/// http://target.example.com request returns an "Access-Control-Allow-Origin:
/// https://source.example.com" response header.
///
/// Scripts in separate frames or iframes and hosted from the same protocol and
/// domain suffix can execute cross-origin JavaScript if both pages set the
/// document.domain value to the same domain suffix. For example,
/// scheme://foo.example.com and scheme://bar.example.com can communicate using
/// JavaScript if both domains set document.domain="example.com".
///
/// This method is used to allow access to origins that would otherwise violate
/// the same-origin policy. Scripts hosted underneath the fully qualified
/// URL (like http://www.example.com) will be allowed access to
/// all resources hosted on the specified and .
/// If is non-empty and if false only
/// exact domain matches will be allowed. If contains a top-
/// level domain component (like "example.com") and is
/// true sub-domain matches will be allowed. If is empty and
/// if true all domains and IP addresses will be
/// allowed.
///
/// This method cannot be used to bypass the restrictions on local or display
/// isolated schemes. See the comments on for more
/// information.
///
/// This function may be called on any thread. Returns false if
/// is invalid or the whitelist cannot be accessed.
///
public static bool AddCrossOriginWhitelistEntry(
string sourceOrigin,
string targetProtocol,
string targetDomain,
bool allowTargetSubdomains)
{
return Core.Cef.AddCrossOriginWhitelistEntry(
sourceOrigin,
targetProtocol,
targetDomain,
allowTargetSubdomains);
}
/// Remove entry from cross-origin whitelist
/// The origin allowed to be accessed by the target protocol/domain.
/// The target protocol allowed to access the source origin.
/// The optional target domain allowed to access the source origin.
/// If set to true would allow a blah.example.com if the
/// was set to example.com
///
///
/// Remove an entry from the cross-origin access whitelist. Returns false if
/// is invalid or the whitelist cannot be accessed.
///
public static bool RemoveCrossOriginWhitelistEntry(string sourceOrigin,
string targetProtocol,
string targetDomain,
bool allowTargetSubdomains)
{
return Core.Cef.RemoveCrossOriginWhitelistEntry(
sourceOrigin,
targetProtocol,
targetDomain,
allowTargetSubdomains);
}
/// Remove all entries from the cross-origin access whitelist.
///
/// Remove all entries from the cross-origin access whitelist. Returns false if
/// the whitelist cannot be accessed.
///
public static bool ClearCrossOriginWhitelist()
{
return Core.Cef.ClearCrossOriginWhitelist();
}
///
/// Returns the global cookie manager. By default data will be stored at CefSettings.CachePath if specified or in memory otherwise.
/// Using this method is equivalent to calling Cef.GetGlobalRequestContext().GetCookieManager()
/// The cookie managers storage is created in an async fashion, whilst this method may return a cookie manager instance,
/// there may be a short delay before you can Get/Write cookies.
/// To be sure the cookie manager has been initialized use one of the following
/// - Access the ICookieManager after ICompletionCallback.OnComplete has been called
/// - Access the ICookieManager instance in IBrowserProcessHandler.OnContextInitialized.
/// - Use the ChromiumWebBrowser BrowserInitialized (OffScreen) or IsBrowserInitializedChanged (WinForms/WPF) events.
///
/// If non-NULL it will be executed asynchronously on the CEF UI thread after the manager's storage has been initialized.
/// A the global cookie manager or null if the RequestContext has not yet been initialized.
public static ICookieManager GetGlobalCookieManager(ICompletionCallback callback = null)
{
return Core.Cef.GetGlobalCookieManager(callback);
}
///
/// Called prior to calling Cef.Shutdown, this disposes of any remaining
/// ChromiumWebBrowser instances. In WPF this is used from Dispatcher.ShutdownStarted
/// to release the unmanaged resources held by the ChromiumWebBrowser instances.
/// Generally speaking you don't need to call this yourself.
///
public static void PreShutdown()
{
Core.Cef.PreShutdown();
}
///
/// Shuts down CefSharp and the underlying CEF infrastructure. This method is safe to call multiple times; it will only
/// shut down CEF on the first call (all subsequent calls will be ignored).
/// This method should be called on the main application thread to shut down the CEF browser process before the application exits.
/// If you are Using CefSharp.OffScreen then you must call this explicitly before your application exits or it will hang.
/// This method must be called on the same thread as Initialize. If you don't call Shutdown explicitly then CefSharp.Wpf and CefSharp.WinForms
/// versions will do their best to call Shutdown for you, if your application is having trouble closing then call thus explicitly.
///
public static void Shutdown()
{
ShutdownStarted?.Invoke(null, EventArgs.Empty);
ShutdownStarted = null;
Core.Cef.Shutdown();
}
///
/// This method should only be used by advanced users, if you're unsure then use Cef.Shutdown().
/// This function should be called on the main application thread to shut down
/// the CEF browser process before the application exits. This method simply obtains a lock
/// and calls the native CefShutdown method, only IsInitialized is checked. All ChromiumWebBrowser
/// instances MUST be Disposed of before calling this method. If calling this method results in a crash
/// or hangs then you're likely hanging on to some unmanaged resources or haven't closed all of your browser
/// instances
///
public static void ShutdownWithoutChecks()
{
ShutdownStarted?.Invoke(null, EventArgs.Empty);
ShutdownStarted = null;
Core.Cef.ShutdownWithoutChecks();
}
///
/// Clear all scheme handler factories registered with the global request context.
/// Returns false on error. This function may be called on any thread in the browser process.
/// Using this function is equivalent to calling Cef.GetGlobalRequestContext().ClearSchemeHandlerFactories().
///
/// Returns false on error.
public static bool ClearSchemeHandlerFactories()
{
return Core.Cef.ClearSchemeHandlerFactories();
}
///
/// Call during process startup to enable High-DPI support on Windows 7 or newer.
/// Older versions of Windows should be left DPI-unaware because they do not
/// support DirectWrite and GDI fonts are kerned very badly.
///
[Obsolete("This method will be removed in M113. See https://github.com/cefsharp/CefSharp/issues/4417")]
public static void EnableHighDPISupport()
{
Core.Cef.EnableHighDPISupport();
}
///
/// Returns true if called on the specified CEF thread.
///
/// Returns true if called on the specified thread.
public static bool CurrentlyOnThread(CefThreadIds threadId)
{
return Core.Cef.CurrentlyOnThread(threadId);
}
///
/// Gets the Global Request Context. Make sure to Dispose of this object when finished.
/// The earlier possible place to access the IRequestContext is in IBrowserProcessHandler.OnContextInitialized.
/// Alternative use the ChromiumWebBrowser BrowserInitialized (OffScreen) or IsBrowserInitializedChanged (WinForms/WPF) events.
///
/// Returns the global request context or null if the RequestContext has not been initialized yet.
public static IRequestContext GetGlobalRequestContext()
{
return Core.Cef.GetGlobalRequestContext();
}
///
/// Helper function (wrapper around the CefColorSetARGB macro) which combines
/// the 4 color components into an uint32 for use with BackgroundColor property
///
/// Alpha
/// Red
/// Green
/// Blue
/// Returns the color.
public static UInt32 ColorSetARGB(UInt32 a, UInt32 r, UInt32 g, UInt32 b)
{
return Core.Cef.ColorSetARGB(a, r, g, b);
}
///
/// Crash reporting is configured using an INI-style config file named
/// crash_reporter.cfg. This file must be placed next to
/// the main application executable. File contents are as follows:
///
/// # Comments start with a hash character and must be on their own line.
///
/// [Config]
/// ProductName=<Value of the "prod" crash key; defaults to "cef">
/// ProductVersion=<Value of the "ver" crash key; defaults to the CEF version>
/// AppName=<Windows only; App-specific folder name component for storing crash
/// information; default to "CEF">
/// ExternalHandler=<Windows only; Name of the external handler exe to use
/// instead of re-launching the main exe; default to empty>
/// ServerURL=<crash server URL; default to empty>
/// RateLimitEnabled=<True if uploads should be rate limited; default to true>
/// MaxUploadsPerDay=<Max uploads per 24 hours, used if rate limit is enabled;
/// default to 5>
/// MaxDatabaseSizeInMb=<Total crash report disk usage greater than this value
/// will cause older reports to be deleted; default to 20>
/// MaxDatabaseAgeInDays=<Crash reports older than this value will be deleted;
/// default to 5>
///
/// [CrashKeys]
/// my_key1=<small|medium|large>
/// my_key2=<small|medium|large>
///
/// Config section:
///
/// If "ProductName" and/or "ProductVersion" are set then the specified values
/// will be included in the crash dump metadata.
///
/// If "AppName" is set on Windows then crash report information (metrics,
/// database and dumps) will be stored locally on disk under the
/// "C:\Users\[CurrentUser]\AppData\Local\[AppName]\User Data" folder.
///
/// If "ExternalHandler" is set on Windows then the specified exe will be
/// launched as the crashpad-handler instead of re-launching the main process
/// exe. The value can be an absolute path or a path relative to the main exe
/// directory.
///
/// If "ServerURL" is set then crashes will be uploaded as a multi-part POST
/// request to the specified URL. Otherwise, reports will only be stored locally
/// on disk.
///
/// If "RateLimitEnabled" is set to true then crash report uploads will be rate
/// limited as follows:
/// 1. If "MaxUploadsPerDay" is set to a positive value then at most the
/// specified number of crashes will be uploaded in each 24 hour period.
/// 2. If crash upload fails due to a network or server error then an
/// incremental backoff delay up to a maximum of 24 hours will be applied for
/// retries.
/// 3. If a backoff delay is applied and "MaxUploadsPerDay" is > 1 then the
/// "MaxUploadsPerDay" value will be reduced to 1 until the client is
/// restarted. This helps to avoid an upload flood when the network or
/// server error is resolved.
///
/// If "MaxDatabaseSizeInMb" is set to a positive value then crash report storage
/// on disk will be limited to that size in megabytes. For example, on Windows
/// each dump is about 600KB so a "MaxDatabaseSizeInMb" value of 20 equates to
/// about 34 crash reports stored on disk.
///
/// If "MaxDatabaseAgeInDays" is set to a positive value then crash reports older
/// than the specified age in days will be deleted.
///
/// CrashKeys section:
///
/// Any number of crash keys can be specified for use by the application. Crash
/// key values will be truncated based on the specified size (small = 63 bytes,
/// medium = 252 bytes, large = 1008 bytes). The value of crash keys can be set
/// from any thread or process using the Cef.SetCrashKeyValue function. These
/// key/value pairs will be sent to the crash server along with the crash dump
/// file. Medium and large values will be chunked for submission. For example,
/// if your key is named "mykey" then the value will be broken into ordered
/// chunks and submitted using keys named "mykey-1", "mykey-2", etc.
///
/// Returns true if crash reporting is enabled.
public static bool CrashReportingEnabled
{
get { return Core.Cef.CrashReportingEnabled; }
}
///
/// Sets or clears a specific key-value pair from the crash metadata.
///
/// key
/// value
public static void SetCrashKeyValue(string key, string value)
{
Core.Cef.SetCrashKeyValue(key, value);
}
///
/// Gets the current log level.
/// When is set to then
/// no messages will be written to the log file, but FATAL messages will still be output to stderr.
/// When logging is disabled this method will return .
///
/// Current Log Level
public static LogSeverity GetMinLogLevel()
{
var severity = Core.Cef.GetMinLogLevel();
//Manually convert the int into the enum
//Values don't match (this is a difference in CEF/Chromium) implementation
//we need to deal with it manually,
//https://github.com/chromiumembedded/cef/blob/2a64387259cf14412e24c3267c8a1eb3b99a54e3/include/base/cef_logging.h#L186
//const LogSeverity LOG_VERBOSE = -1;
//const LogSeverity LOG_INFO = 0;
//const LogSeverity LOG_WARNING = 1;
//const LogSeverity LOG_ERROR = 2;
//const LogSeverity LOG_FATAL = 3;
if (severity == -1)
{
return LogSeverity.Verbose;
}
if (severity == 0)
{
return LogSeverity.Info;
}
if (severity == 1)
{
return LogSeverity.Warning;
}
if (severity == 2)
{
return LogSeverity.Error;
}
if (severity == 3)
{
return LogSeverity.Fatal;
}
//No matching type, return the integer value as enum
return (LogSeverity)severity;
}
///
/// Returns the mime type for the specified file extension or an empty string if unknown.
///
/// file extension
/// Returns the mime type for the specified file extension or an empty string if unknown.
public static string GetMimeType(string extension)
{
return Core.Cef.GetMimeType(extension);
}
///
/// WaitForBrowsersToClose is not enabled by default, call this method
/// before Cef.Initialize to enable. If you aren't calling Cef.Initialize
/// explicitly then this should be called before creating your first
/// ChromiumWebBrowser instance.
///
public static void EnableWaitForBrowsersToClose()
{
Core.Cef.EnableWaitForBrowsersToClose();
}
///
/// Helper method to ensure all ChromiumWebBrowser instances have been
/// closed/disposed, should be called before Cef.Shutdown.
/// Disposes all remaining ChromiumWebBrowser instances
/// then waits for CEF to release its remaining CefBrowser instances.
/// Finally a small delay of 50ms to allow for CEF to finish it's cleanup.
/// Should only be called when MultiThreadedMessageLoop = true;
/// (Hasn't been tested when when CEF integrates into main message loop).
///
public static void WaitForBrowsersToClose()
{
Core.Cef.WaitForBrowsersToClose();
}
///
/// Helper method to ensure all ChromiumWebBrowser instances have been
/// closed/disposed, should be called before Cef.Shutdown.
/// Disposes all remaining ChromiumWebBrowser instances
/// then waits for CEF to release its remaining CefBrowser instances.
/// Finally a small delay of 50ms to allow for CEF to finish it's cleanup.
/// Should only be called when MultiThreadedMessageLoop = true;
/// (Hasn't been tested when when CEF integrates into main message loop).
///
/// The timeout in miliseconds.
public static void WaitForBrowsersToClose(int timeoutInMiliseconds)
{
Core.Cef.WaitForBrowsersToClose(timeoutInMiliseconds);
}
///
/// Post an action for delayed execution on the specified thread.
///
/// thread id
/// action to execute
/// delay in ms
/// bool
public static bool PostDelayedAction(CefThreadIds threadId, Action action, int delayInMs)
{
return Core.Cef.PostDelayedAction(threadId, action, delayInMs);
}
///
/// Post an action for execution on the specified thread.
///
/// thread id
/// action to execute
/// bool
public static bool PostAction(CefThreadIds threadId, Action action)
{
return Core.Cef.PostAction(threadId, action);
}
}
}