diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/webenginewidgets/webenginewidgets.pro | 3 | ||||
-rw-r--r-- | examples/webenginewidgets/webui/about.html | 129 | ||||
-rw-r--r-- | examples/webenginewidgets/webui/doc/images/webui-example.png | bin | 0 -> 28862 bytes | |||
-rw-r--r-- | examples/webenginewidgets/webui/doc/src/webui.qdoc | 165 | ||||
-rw-r--r-- | examples/webenginewidgets/webui/main.cpp | 80 | ||||
-rw-r--r-- | examples/webenginewidgets/webui/webui.pro | 16 | ||||
-rw-r--r-- | examples/webenginewidgets/webui/webui.qrc | 5 | ||||
-rw-r--r-- | examples/webenginewidgets/webui/webuihandler.cpp | 94 | ||||
-rw-r--r-- | examples/webenginewidgets/webui/webuihandler.h | 67 |
9 files changed, 558 insertions, 1 deletions
diff --git a/examples/webenginewidgets/webenginewidgets.pro b/examples/webenginewidgets/webenginewidgets.pro index eb4e1f287..20c7ead50 100644 --- a/examples/webenginewidgets/webenginewidgets.pro +++ b/examples/webenginewidgets/webenginewidgets.pro @@ -10,7 +10,8 @@ SUBDIRS += \ html2pdf \ simplebrowser \ stylesheetbrowser \ - videoplayer + videoplayer \ + webui qtConfig(webengine-geolocation): SUBDIRS += maps qtConfig(webengine-webchannel): SUBDIRS += markdowneditor diff --git a/examples/webenginewidgets/webui/about.html b/examples/webenginewidgets/webui/about.html new file mode 100644 index 000000000..7b5a58969 --- /dev/null +++ b/examples/webenginewidgets/webui/about.html @@ -0,0 +1,129 @@ +<!DOCTYPE html> +<html> + <head> + <title>Qt WebEngine WebUI Example</title> + <style> + html { + background: #f0f0f0; + color: #303030; + font: 16px system-ui; + height: 100%; + } + + body { + margin: 0; + padding: 0; + height: 100%; + display: flex; + flex-direction: column; + align-items: stretch; + } + + body > * { + padding-left: 20px; + padding-right: 20px; + } + + header { + flex: none; + display: flex; + align-items: center; + background: #f0fff0; + border-bottom: 1px solid #e0e0e0; + padding-top: 20px; + padding-bottom: 20px; + } + + header > h1 { + font: bold 20px system-ui; + margin-left: 18px; + } + + main { + flex: auto; + } + + footer { + flex: none; + display: flex; + justify-content: center; + padding-bottom: 20px; + } + + button { + background: #41cd52; + color: #f0f0f0; + font: 16px system-ui; + border: 0; + box-shadow: 0px 1px 3px rgb(0,0,0,0.5); + cursor: pointer; + margin: 0 0 1px; + padding: 10px 24px; + } + + button:hover { + background: #50dc61; + } + + button:active { + background: #50dc61; + box-shadow: 0px 1px 2px rgb(0,0,0,0.5); + margin: 1px 0 0; + } + + button:focus { + outline: 0; + } + + </style> + </head> + <body> + <header> + <img width="48px" height="48px" + src="qrc:/qt-project.org/qmessagebox/images/qtlogo-64.png"> + <h1>WebEngine Widgets<br>WebUI Example</h1> + </header> + <main> + <p> + Aside from the built-in schemes, such as <code>http</code> and + <code>qrc</code>, Qt WebEngine may be extended with <em>custom + schemes</em> by creating <em>custom scheme handlers</em>. + </p> + + <p> + This is a simple HTML page loaded from a custom scheme and + displayed by a <code>QWebEngineView</code>. Even the Quit button + below is a standard HTML <code><button></code> element. + </p> + + <p> + Read the documentation to find out + </p> + <ul> + <li> + <p> + How to create a custom scheme handler which serves HTML + and handles HTML form submissions. + </p> + </li> + <li> + <p> + How to prevent ordinary web content from accessing the + custom scheme. + </p> + </li> + <li> + <p> + How to prevent any other scheme from submitting HTML + form data. + </p> + </li> + </ul> + </main> + <footer> + <form action="" method="post"> + <button name="quit">Quit</button> + </form> + </footer> + </body> +</html> diff --git a/examples/webenginewidgets/webui/doc/images/webui-example.png b/examples/webenginewidgets/webui/doc/images/webui-example.png Binary files differnew file mode 100644 index 000000000..84e2c7fc3 --- /dev/null +++ b/examples/webenginewidgets/webui/doc/images/webui-example.png diff --git a/examples/webenginewidgets/webui/doc/src/webui.qdoc b/examples/webenginewidgets/webui/doc/src/webui.qdoc new file mode 100644 index 000000000..d5eb13d02 --- /dev/null +++ b/examples/webenginewidgets/webui/doc/src/webui.qdoc @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example webenginewidgets/webui + \title WebEngine Widgets WebUI Example + \ingroup webengine-widgetexamples + \brief Displays HTML over a custom scheme. + + \image webui-example.png + + \e {WebUI} demonstrates how to implement a custom scheme in a secure way. + + Aside from the built-in URL schemes, such as \c {http} and \c {qrc}, Qt + WebEngine may be extended with \e {custom schemes} by creating \e {custom + scheme handlers}. This example shows: + + \list + \li How to create a custom scheme handler which serves HTML and handles + HTML form submissions. + \li How to prevent ordinary web content from accessing the custom scheme. + \li How to prevent any other scheme from submitting HTML form data. + \endlist + + \include examples-run.qdocinc + + \section1 Overview + + The example program consists of a single \l {QWebEngineView} showing a + simple HTML page loaded from the URL \c {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 \c {main} function for setting + everything up, and the \c {WebUiHandler} class for implementing our custom + scheme handler. The \c {main} function is quite short: + + \quotefromfile webenginewidgets/webui/main.cpp + \skipto int main + \printuntil /^\}/ + + Aside from the relatively standard setup of widgets, two points are + noteworthy. First, we call the static method \c + {WebUiHandler::registerUrlScheme()} to register our custom scheme with the + web engine. Second, we create and install our custom scheme handler \c + {WebUiHandler} using \l + {QWebEngineProfile::installUrlSchemeHandler()}{installUrlSchemeHandler()}. + The following sections describe these aspects in more detail. + + \section1 Registering the Scheme + + 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 \l + {QWebEngineUrlScheme} object and then handing it over to \l + {QWebEngineUrlScheme::addScheme()}. The example program does exactly this in + the static method \c {WebUiHandler::registerUrlScheme()}: + + \quotefromfile webenginewidgets/webui/webuihandler.cpp + \skipto void WebUiHandler::registerUrlScheme + \printuntil /^\}/ + + A custom scheme needs a name, which can be set by passing it to + the constructor of \c {QWebEngineUrlScheme} or by calling \l + {QWebEngineUrlScheme::setName}. In the above, the name \c {webui} is set + through the constructor. Additionally, we activate the flags \l + {QWebEngineUrlScheme::Secure}{Secure}, \l + {QWebEngineUrlScheme::Local}{Local} and \l + {QWebEngineUrlScheme::LocalAccessAllowed}{LocalAccessAllowed}. Since our + custom scheme handler will not deliver resources received from insecure + network connections, we can safely mark it as \c {Secure}. The \c {Local} + flag prevents content from non-local schemes (such as \c {http}) from + interacting with our custom scheme. Without this flag it would be possible, + for example, to embed the \c {webui:about} page in an \c <iframe> element on + a remotely loaded HTML page, perhaps to attempt a phishing attack. We also + need the \c {LocalAccessAllowed} flag without which we would not be able to + access the \c {webui} scheme from our \c {webui:about} page. + + Earlier we saw that the call to \c {WebUiHandler::registerUrlScheme()} is + made already at the top of the \c {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. + + \section1 Handling Requests + + 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 \l + {QWebEngineUrlSchemeHandler}, which is just what is done by the \c + {WebUiHandler} class of the example program: + + \quotefromfile webenginewidgets/webui/webuihandler.h + \skipto class WebUiHandler + \printuntil /^\}/ + + For each request to a \c {webui} URL, the \c + {WebUiHandler::requestStarted()} method will be called: + + \quotefromfile webenginewidgets/webui/webuihandler.cpp + \skipto void WebUiHandler::requestStarted + \printuntil /^\}/ + + The \l {QWebEngineUrlRequestJob} object \c {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 \l + {QIODevice} that the application passes to \l + {QWebEngineUrlRequestJob::reply()}{reply()}. + + \warning The \c 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 \l + {QWebEngineUrlRequestJob::requestMethod()}{requestMethod} and \l + {QWebEngineUrlRequestJob::requestUrl()}{requestUrl}, there is also the \l + {QWebEngineUrlRequestJob::initiator()}{initiator}, holding the origin of the + content which initiated the request. An empty \c initiator means the request + was initiated directly by the application (via \l + {QWebEnginePage::setUrl()}, for example). The special value \c "null" + corresponds to an opaque origin (a sandboxed \c {<iframe>} element, for + example). Otherwise, the \c initiator will contain the URL scheme, hostname, + and port of the content which initiated the request. + + In this example, the \c initiator is used to ensure that \c {POST} requests + to \c {webui:about} will only trigger the application's exit if they + originate from the \c {webui} scheme. This prevents content loaded over + other schemes from triggering the application's exit. + +*/ diff --git a/examples/webenginewidgets/webui/main.cpp b/examples/webenginewidgets/webui/main.cpp new file mode 100644 index 000000000..54e0c145c --- /dev/null +++ b/examples/webenginewidgets/webui/main.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "webuihandler.h" + +#include <QApplication> +#include <QWebEnginePage> +#include <QWebEngineProfile> +#include <QWebEngineView> + +int main(int argc, char *argv[]) +{ + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + WebUiHandler::registerUrlScheme(); + + QApplication app(argc, argv); + + QWebEngineProfile profile; + + WebUiHandler handler; + profile.installUrlSchemeHandler(QByteArrayLiteral("webui"), &handler); + + QWebEnginePage page(&profile); + page.load(QStringLiteral("webui:about")); + + QWebEngineView view; + view.setPage(&page); + view.setContextMenuPolicy(Qt::NoContextMenu); + view.resize(500, 600); + view.show(); + + return app.exec(); +} diff --git a/examples/webenginewidgets/webui/webui.pro b/examples/webenginewidgets/webui/webui.pro new file mode 100644 index 000000000..714833587 --- /dev/null +++ b/examples/webenginewidgets/webui/webui.pro @@ -0,0 +1,16 @@ +TEMPLATE = app + +QT += webenginewidgets + +HEADERS += \ + webuihandler.h + +SOURCES += \ + main.cpp \ + webuihandler.cpp + +RESOURCES += \ + webui.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/webui +INSTALLS += target diff --git a/examples/webenginewidgets/webui/webui.qrc b/examples/webenginewidgets/webui/webui.qrc new file mode 100644 index 000000000..6ddf01fa2 --- /dev/null +++ b/examples/webenginewidgets/webui/webui.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>about.html</file> + </qresource> +</RCC> diff --git a/examples/webenginewidgets/webui/webuihandler.cpp b/examples/webenginewidgets/webui/webuihandler.cpp new file mode 100644 index 000000000..42446b88e --- /dev/null +++ b/examples/webenginewidgets/webui/webuihandler.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "webuihandler.h" + +#include <QApplication> +#include <QFile> +#include <QWebEngineUrlRequestJob> +#include <QWebEngineUrlScheme> + +WebUiHandler::WebUiHandler(QObject *parent) + : QWebEngineUrlSchemeHandler(parent) +{ +} + +void WebUiHandler::requestStarted(QWebEngineUrlRequestJob *job) +{ + static const QUrl webuiAboutUrl(QStringLiteral("webui:about")); + static const QUrl webUiOrigin(QStringLiteral("webui:")); + 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 == webuiAboutUrl) { + QFile *file = new QFile(QStringLiteral(":/about.html"), job); + file->open(QIODevice::ReadOnly); + job->reply(QByteArrayLiteral("text/html"), file); + } else if (method == POST && url == webuiAboutUrl && initiator == webUiOrigin) { + job->fail(QWebEngineUrlRequestJob::RequestAborted); + QApplication::exit(); + } else { + job->fail(QWebEngineUrlRequestJob::UrlNotFound); + } +} + +// static +void WebUiHandler::registerUrlScheme() +{ + QWebEngineUrlScheme webUiScheme(QByteArrayLiteral("webui")); + webUiScheme.setFlags(QWebEngineUrlScheme::Secure | + QWebEngineUrlScheme::Local | + QWebEngineUrlScheme::LocalAccessAllowed); + QWebEngineUrlScheme::addScheme(webUiScheme); +} diff --git a/examples/webenginewidgets/webui/webuihandler.h b/examples/webenginewidgets/webui/webuihandler.h new file mode 100644 index 000000000..f9d7b91df --- /dev/null +++ b/examples/webenginewidgets/webui/webuihandler.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WEBUIHANDLER_H +#define WEBUIHANDLER_H + +#include <QWebEngineUrlSchemeHandler> + +class WebUiHandler : public QWebEngineUrlSchemeHandler +{ + Q_OBJECT +public: + explicit WebUiHandler(QObject *parent = nullptr); + + void requestStarted(QWebEngineUrlRequestJob *job) override; + + static void registerUrlScheme(); +}; + +#endif // !WEBUIHANDLER_H |