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