-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
CefSharp 43
CefSharp 43 provides much better access to the underlying CEF API
and as such there are many changes over version 41
. A number of changes will be required when updating. This document provides some information, if you have something to add then please be aware that any registered GitHub
user an contribute.
-
Expose
IFrame
andIBrowser
interfaces. -
Access to the underlying popup browser wrappers.
-
New CEF binary files need to be included with
libcef.dll
, etc.: -
natives_blob.bin
-
snapshot_blob.bin
-
Breaking changes for many handlers
-
Built-in PDF viewer removed. See #1144 for workaround.
-
The following are now deprecated:
-
IWebBrowser.CanReload
, useIWebBrowser.IsLoading
instead (will be removed from the threeChromiumWebBrowser
instances). -
FrameLoadStartEventArgs.IsMainFrame
useFrameLoadStartEventArgs.Frame.IsMain
instead -
FrameLoadEndEventArgs.IsMainFrame
useFrameLoadEndEventArgs.Frame.IsMain
instead
-
-
PR's tagged as
breaking change
can be found at https://github.com/cefsharp/CefSharp/issues?utf8=%E2%9C%93&q=label%3Abreaking-change+is%3Amerged+milestone%3A43.0.0 -
WCF can now be disabled via
CefSharpSettings.WcfEnabled = false;
. Disables JavaScript object binding. Native ChromeIPC
used instead for allIPC
,ExecuteScriptAsync
andEvaluateScriptAsync
. -
Changed to using
process-per-tab
model (OneRender Process
perChromiumWebBrowser
instance). This is to workaround a problem with the nativeIPC
andJavascriptBinding
.
Most of the public facing API
has breaking changes, the scheme handler implementation was totally rewritten to simplify the underlying code, give you access to underlying API
. The Handler interfaces have also undergone major changes, the key concepts are outlined below. There are unfortunately too many changes to list them all.
//To upgrade: add new parameters. Code logic does not need to change.
public SchemeHandlerFactory: ISchemeHandlerFactory
{
//Old
ISchemeHandler Create()
{
return handler;
}
//New
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
{
//To read a file of disk no need to implement your own handler
if (schemeName == SchemeName && request.Url.EndsWith("CefSharp.Core.xml", System.StringComparison.OrdinalIgnoreCase))
{
//Display the CefSharp.Core.xml file in the browser
return ResourceHandler.FromFileName("CefSharp.Core.xml", ".xml");
}
return new CefSharpSchemeHandler();
}
}
//NOTE: ISchemeHandler renamed to IResourceHandler (shares code with ResourceHandler implementation)
public class CefSharpSchemeHandler : IResourceHandler
{
//Old:
public bool ProcessRequestAsync(IRequest request, ISchemeHandlerResponse response, OnRequestCompletedHandler requestCompletedCallback)
{
//Processing goes here...
return true;
}
//New:
//To upgrade: store the response stream in a class field, then call callback.Continue() instead of the old `requestCompletedCallback`.
//See here for example of new usage: https://github.com/cefsharp/CefSharp/blob/cefsharp/43/CefSharp.Example/CefSharpSchemeHandler.cs
public bool ProcessRequestAsync(IRequest request, ICallback callback)
{
Task.Run(() =>
{
// Base to dispose of callback as it wraps a managed resource
using (callback)
{
//Perform processing here
// When processing complete call continue
callback.Continue();
}
});
return true;
}
public Stream GetResponse(IResponse response, out long responseLength, out string redirectUrl)
{
//How long is your stream?
responseLength = stream.Length;
//Set to null if not redirecting to a different url
redirectUrl = null;
//Set response related stuff here
response.StatusCode = (int)HttpStatusCode.OK;
response.StatusText = "OK";
response.MimeType = mimeType;
//Return your populated stream
return stream;
}
}
Most handler interfaces, IKeyboardHandler
, IRequestHandler
, etc no provide access to the underlying CefBrowser
through the IBrowser
interface. IMenuHandler
was renamed to IContextMenuHandler
(matches the underlying CefContextMenuHandler
naming).
Whilst IBrowser
wraps a managed resource, please don't call Dispose()
, CefSharp
will take care of this.
Some handlers will also expose IFrame
interface which wraps CefFrame
, again, don't Dispose()
. You will also note the appearance of many callback
interfaces, for example IRequestCallback
. You can now perform tasks in an async operation. We do reccomend you Dispose()
of the callbacks when your finished as they wrap an unmanaged
resource. (Easiest way is a using()
block.
Example of the updated IKeyboardHandler interface
public class KeyboardHandler : IKeyboardHandler
{
//Old:
public bool OnKeyEvent(IWebBrowser browserControl, KeyType type, int windowsKeyCode, CefEventFlags modifiers, bool isSystemKey)
{
return false;
}
//New:
public bool OnPreKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut)
{
return false;
}
}
See https://github.com/cefsharp/CefSharp/blob/cefsharp/43/CefSharp.Example/RequestHandler.cs
public class RequestHandler : IRequestHandler
{
//NOTE: In some cases new methods have been added, check the interface documentation for more details.
//e.g. https://github.com/cefsharp/CefSharp/blob/cefsharp/43/CefSharp/IRequestHandler.cs#L43
bool IRequestHandler.OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture)
{
return false;
}
//NOTE: The IWebBrowser control variable is now called browserControl, you now have access to IBrowser, IFrame and in this instance IRequestCallback
CefReturnValue IRequestHandler.OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
{
//NOTE: If you do not wish to implement this method returning false is the default behaviour
// We also suggest you explicitly Dispose of the callback as it wraps an unmanaged resource.
//callback.Dispose();
//return false;
//NOTE: When executing the callback in an async fashion need to check to see if it's disposed
if (!callback.IsDisposed)
{
using (callback)
{
//Do some stuff here
//Callback in async fashion
//callback.Continue(true);
//return CefReturnValue.ContinueAsync;
}
}
return CefReturnValue.Continue;
}
}
The settings have been simplified and now closely mimic the behavior of CEF
.
browserSettings.ImageLoadingDisabled = true;
becomes
browserSettings.ImageLoading = CefState.Disabled;
(The enum has three states CefState.Default, CefState.Enabled, CefState.Disabled