从 2.4 迁移到 2.5

在 DotNetBrowser 2.5 中,Chromium 引擎已升级到 88 版本。 这个 Chromium 版本在源代码中有一些破坏性的更改,影响了产品的公共 API。 在本迁移指南中,我们将介绍 2.5 中已删除/更改的 API,以及应该使用的替代方案。

已删除的 API

Flash 支持

Chromium 88 不再支持 Flash,因此以下引擎选项已过时,并从 API 中删除:

  • EngineOptions.PpapiFlashPath
  • EngineOptions.PpapiFlashVersion

UI 语言

以下 UI 语言已被移除,因为它们不再得到 Chromium 的官方支持:

  • 南非语
  • 中文(香港)
  • 法语(加拿大)
  • 英语(澳大利亚)
  • 祖鲁语

添加或更新的 API

网络

拦截请求

v2.4

为了拦截标准的 URL 请求(例如 httphttps)和自定义协议(例如 my-app),使用了 InterceptRequestHandler。 它允许拦截请求并覆盖响应数据,就好像这些数据是从网络服务器发送的一样。

下面介绍如何在 2.4 中使用 myscheme 方案拦截请求:

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(() =>
        {
            // 请求处理在后台线程中进行
            // 以避免冻结网页。
            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()
            ' 请求处理在后台线程中进行
            ' 以避免冻结网页。
            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

以前拦截所有请求的方法存在一些安全限制和问题:

  • 被拦截的自定义方案被视为非标准方案,因此您无法拦截自定义方案并返回包含访问 LocalStorage 的 JavaScript 的 HTML。 这将导致拒绝访问错误;
  • 并非所有方案都可以被拦截。 例如,禁止拦截 chromedatachrome-extensions 等方案。 上一版本的 API 允许这样做,这可能会导致在 Chromium 中出现意外行为或崩溃;
  • 某些方案被视为本地方案,如 file。 它们无法被拦截,因为它不是网络请求。

在此版本中,我们改进了API,允许拦截 URL 请求和注册自定义方案。 新版本中没有上述安全限制和问题。

下面的示例演示了如何注册自定义 myscheme 方案并拦截所有相应的 URL 请求:

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(() =>
    {
        // 请求处理在后台线程中执行
        // 以避免冻结网页。
        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()
        ' 请求处理在后台线程中执行
        ' 以避免冻结网页。
        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")

如果无法拦截指定的方案, EngineOptions 构建器将抛出相应的异常。 例如:” “file” 方案无法被拦截。”

已知限制

在 Chromium 88 中,安全限制变得更加严格。 因此,当使用 LoadHtml 加载依赖于外部脚本的 HTML 文档时,它永远不会加载这些脚本,并记录错误信息 Failed to load resource: net::ERR_NOT_IMPLEMENTED

可能的解决方法是使用 data: 编码 URI,然后使用常规的 LoadUrl 调用加载它。 下面是一个例子:

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()

不过,使用这种解决方法时无法设置基本 URL。

另一种可行的方法是向处理程序注册 Scheme,并拦截相应的请求以提供 HTML。 请参阅相应的文章

Go Top