介绍
在自定义模式下显示HTML
WebUI的范例展示了如何去创建一个安全的定制窗口来显示网页
除了内置的URL方案,比如http和qrc,Qt WebEngine 可以通过创建定制
- 如何创建定制的方案句柄,可以服务于HTML,和如何从显示服务器中的HTML文件
- 在访问定制的方案如何去预防普通的网页链接
- 如何来防止任何其他从数据中提交HTML的方案
运行这个实例
打开Qt Creater来打开实例
Overview
这个简单的例子展示了一个如何通过定制的方案来使用QWebEngineView来展示简单的网页从 webui:about 地址中来加载一个HTML网页,点击页面下面的按钮将会触发一个HTML的请求,请求组是通过 POST 相同的 URL,点击了这个句柄后将会造成程序的退出
这个项目分成两个部分,主函数将把环境搭建好,另外一个WebUiHandler类来操作我么定制的方案句柄,主函数如下:
int main(int argc, char *argv[])
{
QCoreApplication::setOrganizationName("QtExamples");
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
WebUiHandler::registerUrlScheme();
QApplication app(argc, argv);
QWebEngineProfile profile;
WebUiHandler handler;
profile.installUrlSchemeHandler(WebUiHandler::schemeName, &handler);
QWebEnginePage page(&profile);
page.load(WebUiHandler::aboutUrl);
QWebEngineView view;
view.setPage(&page);
view.setContextMenuPolicy(Qt::NoContextMenu);
view.resize(500, 600);
view.show();
return app.exec();
}
这里面除了正常的关于widget的设置之外,还有两个点需要注意,首先我们调用了静态的方法WebUiHandler::registerUrlScheme()函数来登录我们定制的方法,第二,我们使用installUrlSchemeHandle()函数创建了且安装在我们定制的方法句柄WebUiHandler,下面将详细描述这两点
登录方案
一个定制的方案是直接继承在web 引擎中的,它不需要使用下面的标准的用来支持普通的网页链接的方法规则,根据选择的配置,连接将会创建一个定制的方案,来访问本地的链接,这样会避开链接安全协议的规则,相反,它拒绝访问其他的链接
为了来配置这些规则,我们可以通过QWebEngineUrlScheme::registerScheme()函数来设置他们,这个例子直接调用静态方法WebUiHandler::registerUrlScheme()函数
void WebUiHandler::registerUrlScheme()
{
QWebEngineUrlScheme webUiScheme(schemeName);
webUiScheme.setFlags(QWebEngineUrlScheme::SecureScheme |
QWebEngineUrlScheme::LocalScheme |
QWebEngineUrlScheme::LocalAccessAllowed);
QWebEngineUrlScheme::registerScheme(webUiScheme);
}
定制的方案需要一个名字,可以通过QwebEngineUrlScheme的构造函数或者调用QWebEngineUrlScheme::setName()函数来这是,在所有的开始之前,我们命名了一个名为 webui的名字,在我们的构造函数中,除此只玩,我们就激活了标志位:SercureScheme, LocalScheme 和LocalAccessAllowed的设置参数,一旦我们的定制的方法没有提交从网络连接中的源,我们可以安全的将其标记为SecureScheme,本地方案把标志位,防止任何非本地的网络请求来连接到这个定制的方案中,如果没有这些标志位,也是可行的,比如为了避免webui:about页面在在远程HTML页面中,使用 LocalAccessAllowed标志位来设置
Handling请求
一个定制的方案句柄是一个很宽泛的语言,比如一个通过HTTP来服务的网页应用程序,除此之外,因为定制的方案是继承在web引擎中的,因此它有很先进的功能,我们不需要自己去生产HTTP信息然后通过端口在发送数据
操作一个句柄意味着创建一个QWebEngineUrlSchemeHandler的子类,我们可以按照下面的方法来做
class WebUiHandler : public QWebEngineUrlSchemeHandler
{
Q_OBJECT
public:
explicit WebUiHandler(QObject *parent = nullptr);
void requestStarted(QWebEngineUrlRequestJob *job) override;
static void registerUrlScheme();
const static QByteArray schemeName;
const static QUrl aboutUrl;
};
对于每一个需要请求webui的地址,函数WebUiHandler::requestStandard()函数将会被调用
void WebUiHandler::requestStarted(QWebEngineUrlRequestJob *job)
{
static const QUrl webUiOrigin(QStringLiteral(SCHEMENAME ":"));
static const QByteArray GET(QByteArrayLiteral("GET"));
static const QByteArray POST(QByteArrayLiteral("POST"));
QByteArray method = job->requestMethod();
QUrl url = job->requestUrl();
QUrl initiator = job->initiator();
if (method == GET && url == aboutUrl) {
QFile *file = new QFile(QStringLiteral(":/about.html"), job);
file->open(QIODevice::ReadOnly);
job->reply(QByteArrayLiteral("text/html"), file);
} else if (method == POST && url == aboutUrl && initiator == webUiOrigin) {
job->fail(QWebEngineUrlRequestJob::RequestAborted);
QApplication::exit();
} else {
job->fail(QWebEngineUrlRequestJob::UrlNotFound);
}
}
QWebEngineRequestJob对象job包含请求的参数,且需要提供对于回应请求的方法,异步的生成和响应他们通过QIODevice的reply()函数
警告:函数requestStarted()不是在主函数中被执行的,而是从Webengine的IO线程,不要在主线程中同步相应任何请求