WebUI 演示如何以安全方式实现自定义方案。
						Aside from the built-in URL schemes, such as
						
http
						
						and
						
qrc
						
						, Qt WebEngine may be extended with
						
							custom schemes
						
						by creating
						
							custom scheme handlers
						
						. This example shows:
					
要运行范例从 Qt Creator ,打开 欢迎 模式,然后选择范例从 范例 。更多信息,拜访 构建和运行范例 .
						The example program consists of a single
						
							QWebEngineView
						
						showing a simple HTML page loaded from the URL
						
webui:about
						
						, over our custom scheme. Pressing the button at the bottom of the page will trigger an HTML form submission via POST to the same URL, at which point our custom scheme handler will cause the application to exit.
					
						The program is divided into two parts, the
						
main
						
						function for setting everything up, and the
						
WebUiHandler
						
						class for implementing our custom scheme handler. The
						
main
						
						function is quite short:
					
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(); }
						Aside from the relatively standard setup of widgets, two points are noteworthy. First, we call the static method
						
WebUiHandler::registerUrlScheme()
						
						to register our custom scheme with the web engine. Second, we create and install our custom scheme handler
						
WebUiHandler
						
						使用
						
							installUrlSchemeHandler()
						
						. The following sections describe these aspects in more detail.
						
					
As custom schemes are integrated directly into the web engine, they do not necessarily need to follow the standard security rules which apply to ordinary web content. Depending on the chosen configuration, content served over a custom scheme may be given access to local resources, be set to ignore Content-Security-Policy rules, or conversely, be denied access to any other content entirely.
						In order to take advantage of these possibilities, the custom scheme must first be registered. This means creating and configuring a
						
							QWebEngineUrlScheme
						
						object and then handing it over to
						
							QWebEngineUrlScheme::registerScheme
						
						(). The example program does exactly this in the static method
						
WebUiHandler::registerUrlScheme()
						
						:
					
void WebUiHandler::registerUrlScheme() { QWebEngineUrlScheme webUiScheme(schemeName); webUiScheme.setFlags(QWebEngineUrlScheme::SecureScheme | QWebEngineUrlScheme::LocalScheme | QWebEngineUrlScheme::LocalAccessAllowed); QWebEngineUrlScheme::registerScheme(webUiScheme); }
						A custom scheme needs a name, which can be set by passing it to the constructor of
						
QWebEngineUrlScheme
						
						or by calling
						
							QWebEngineUrlScheme::setName
						
						. In the above, the name
						
webui
						
						is set through the constructor. Additionally, we activate the flags
						
							SecureScheme
						
						,
						
							LocalScheme
						
						and
						
							LocalAccessAllowed
						
						. Since our custom scheme handler will not deliver resources received from insecure network connections, we can safely mark it as a
						
SecureScheme
						
						。
						
LocalScheme
						
						flag prevents content from non-local schemes (such as
						
http
						
						) from interacting with our custom scheme. Without this flag it would be possible, for example, to embed the
						
webui:about
						
						page in an
						
<iframe>
						
						element on a remotely loaded HTML page, perhaps to attempt a phishing attack. We also need the
						
LocalAccessAllowed
						
						flag without which we would not be able to access the
						
webui
						
						scheme from our
						
webui:about
						
						页面。
					
						Earlier we saw that the call to
						
WebUiHandler::registerUrlScheme()
						
						is made already at the top of the
						
main
						
						function. This is so because custom schemes need to be registered as early as possible so that that they can be passed to all subprocesses. Specifically, custom schemes need to be registered before any other Qt WebEngine classes are instantiated by the application.
						
					
A custom scheme handler is, broadly speaking, similar to a web application served over HTTP. However, because custom schemes are integrated directly into the web engine, they have the advantage in terms of efficiency: there's no need for generating and parsing HTTP messages or for transferring data over sockets.
						Implementing a handler means creating a subclass of
						
							QWebEngineUrlSchemeHandler
						
						, which is just what is done by the
						
WebUiHandler
						
						class of the example program:
					
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; };
						For each request to a
						
webui
						
						URL, the
						
WebUiHandler::requestStarted()
						
						method will be called:
					
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); } }
						The
						
							QWebEngineUrlRequestJob
						
						对象
						
job
						
						contains the request's attributes and provides methods for replying to the request with a response. Responses are generated asynchronously by reading them from the
						
							QIODevice
						
						that the application passes to
						
							reply()
						
						.
					
						
							警告:
						
						The
						
requestStarted()
						
						method is not called from the main thread, but from the web engine's IO thread. Care must be taken to synchronize access to any resources on the main thread.
					
						Aside from the usual fare of
						
							requestMethod
						
						and
						
							requestUrl
						
						, there is also the
						
							initiator
						
						, holding the origin of the content which initiated the request. An empty
						
initiator
						
						means the request was initiated directly by the application (via
						
							QWebEnginePage::setUrl
						
						(), for example). The special value
						
"null"
						
						corresponds to an opaque origin (a sandboxed
						
<iframe>
						
						element, for example). Otherwise, the
						
initiator
						
						will contain the URL scheme, hostname, and port of the content which initiated the request.
					
						在此范例中,
						
initiator
						
						is used to ensure that
						
POST
						
						requests to
						
webui:about
						
						will only trigger the application's exit if they originate from the
						
webui
						
						scheme. This prevents content loaded over other schemes from triggering the application's exit.