Introduction
Installation
Guides
- Engine
- Profile
- Browser
- BrowserView
- Navigation
- Content
- Context menu
- DOM
- JavaScript
- Pop-ups
- Dialogs
- Downloads
- Chrome extensions
- Network
- Cache
- Cookies
- Proxy
- Authentication
- Permissions
- Plugins
- Printing
- Passwords
- User data profiles
- Credit cards
- Media
- Zoom
- Spell checker
- Deployment
- Chromium
Troubleshooting
- Logging
- Common exceptions
- Application does not terminate
- Video does not play
- Cannot sign in to Google account
- User data is not stored
- Color scheme
- Startup failure
- Slow startup on Windows
- Unresponsive .NET Application
- Unexpected Chromium process termination
- Unexpected behavior
- Windows 7/8/8.1 end of support
Migration
Migrating from 2.4 to 2.5
In DotNetBrowser 2.5 the Chromium engine has been upgraded to version 88. This Chromium version has several breaking changes in the source code that affect the public API of product. In this migration guide we describe what API has been removed/changed in 2.5 and what alternatives you should use instead.
Removed API
Flash support
In Chromium 88 the Flash support is dropped, therefore, the following engine options became obsolete and were removed from the API:
EngineOptions.PpapiFlashPath
EngineOptions.PpapiFlashVersion
UI languages
The following UI languages were removed, as they are no longer officially supported by Chromium:
- Afrikaans
- Chinese (HongKong)
- French (Canada)
- English (Australia)
- Zulu
Added or updated API
Network
Intercepting requests
v2.4
To intercept URL requests with the standard (e.g. http
, https
) and custom schemes (e.g. my-app
) the InterceptRequestHandler
was used. It allows intercepting requests and override response data as if it was sent from a web server.
Here is how to intercept requests with the myscheme
scheme in 2.4:
engine.Network.InterceptRequestHandler =
new Handler<InterceptRequestParameters, InterceptRequestResponse>(p =>
{
if(!p.UrlRequest.Url.StartsWith("myscheme"))
{
return InterceptRequestResponse.Proceed();
}
UrlRequestJobOptions options = new UrlRequestJobOptions
{
Headers = new List<HttpHeader>
{
new HttpHeader("Content-Type", "text/html", "charset=utf-8"),
}
};
UrlRequestJob job = p.Network.CreateUrlRequestJob(p.UrlRequest, options);
Task.Run(() =>
{
// The request processing is performed in a background thread
// in order to avoid freezing the web page.
job.Write(Encoding.UTF8.GetBytes("My data"));
job.Complete();
});
return InterceptRequestResponse.Intercept(job);
});
...
browser.Navigation.LoadUrl("myscheme://app/hello");
engine.Network.InterceptRequestHandler =
New Handler(Of InterceptRequestParameters, InterceptRequestResponse)(Function(p)
If Not p.UrlRequest.Url.StartsWith("myscheme") Then
Return InterceptRequestResponse.Proceed()
End If
Dim options As New UrlRequestJobOptions With {
.Headers = New List(Of HttpHeader) From {
New HttpHeader("Content-Type", "text/html", "charset=utf-8")}
}
Dim job As UrlRequestJob = p.Network.CreateUrlRequestJob(p.UrlRequest, options)
Task.Run(Sub()
' The request processing is performed in a background thread
' in order to avoid freezing the web page.
job.Write(Encoding.UTF8.GetBytes("My data"))
job.Complete()
End Sub)
Return InterceptRequestResponse.Intercept(job)
End Function)
'...
browser.Navigation.LoadUrl("myscheme://app/hello")
v2.5
The previous approach with intercepting all requests has several security limitations and issues:
- the intercepted custom schemes are treated as non-standard, so you cannot intercept a custom scheme and return HTML with JavaScript that accesses
LocalStorage
. It will lead to the access denied error; - not all schemes can be intercepted. For example, it is forbidden to intercept schemes such as
chrome
,data
, orchrome-extensions
. The previous version of the API allows doing this which might lead to unexpected behavior or crash inside Chromium; - some schemes are treated as local schemes, e.g.
file
. They cannot be intercepted because it is not a network request.
In this version, we improved the API that allows intercepting URL requests and registering custom schemes. The new version does not have the security limitations and issues described above.
The following example demonstrates how to register the custom myscheme
scheme and intercept all corresponding URL requests:
var handler = new Handler<InterceptRequestParameters, InterceptRequestResponse>(p =>
{
UrlRequestJobOptions options = new UrlRequestJobOptions
{
Headers = new List<HttpHeader>
{
new HttpHeader("Content-Type", "text/html", "charset=utf-8"),
}
};
UrlRequestJob job = p.Network.CreateUrlRequestJob(p.UrlRequest, options);
Task.Run(() =>
{
// The request processing is performed in a background thread
// in order to avoid freezing the web page.
job.Write(Encoding.UTF8.GetBytes("My data"));
job.Complete();
});
return InterceptRequestResponse.Intercept(job);
});
IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
Schemes =
{
{ Scheme.Create("myscheme"), handler }
}
}.Build());
IBrowser browser = engine.CreateBrowser();
browser.Navigation.LoadUrl("myscheme://app/hello");
Dim handler As New Handler(
Of InterceptRequestParameters, InterceptRequestResponse)(Function(p)
Dim options As New UrlRequestJobOptions With {
.Headers = New List(Of HttpHeader) From {
New HttpHeader("Content-Type", "text/html", "charset=utf-8")}
}
Dim job As UrlRequestJob = p.Network.CreateUrlRequestJob(p.UrlRequest, options)
Task.Run(Sub()
' The request processing is performed in a background thread
' in order to avoid freezing the web page.
job.Write(Encoding.UTF8.GetBytes("My data"))
job.Complete()
End Sub)
Return InterceptRequestResponse.Intercept(job)
End Function)
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With {
.Schemes = {
{ Scheme.Create("myscheme"), handler }
}
}.Build())
Dim browser As IBrowser = engine.CreateBrowser()
browser.Navigation.LoadUrl("myscheme://app/hello")
If the specified scheme cannot be intercepted, the corresponding exception will be thrown by the EngineOptions
builder. For example: “The “file” scheme cannot be intercepted.”
Known limitations
The security restrictions became more tight in Chromium 88. As a result, when an HTML document relying on external scripts is loaded using LoadHtml
, it never loads those scripts and logs errors saying Failed to load resource: net::ERR_NOT_IMPLEMENTED
.
The possible workaround is to use data:
encoded URI and then load it using the regular LoadUrl call. Here is an example:
var html = "<html><head></head><body><h1>Html Encoded in URL!</h1></body></html>";
var base64EncodedHtml = Convert.ToBase64String(Encoding.UTF8.GetBytes(html));
browser.Navigation.LoadUrl("data:text/html;base64," + base64EncodedHtml).Wait();
Dim html = "<html><head></head><body><h1>Html Encoded in URL!</h1></body></html>"
Dim base64EncodedHtml = Convert.ToBase64String(Encoding.UTF8.GetBytes(html))
browser.Navigation.LoadUrl("data:text/html;base64," & base64EncodedHtml).Wait()
However, the base URL cannot be set when using this workaround.
Another possible approach is to register a Scheme
with a handler and intercept the corresponding request to provide the HTML. See the corresponding article.