summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJüri Valdmann <juri.valdmann@qt.io>2019-04-29 15:51:58 +0200
committerJüri Valdmann <juri.valdmann@qt.io>2019-05-07 07:55:32 +0000
commitefee223d7ff6e0e30fb9d9dff1536936922d4a03 (patch)
tree882cc5427a48ff3da37e3ec722ce6678d9ec274b
parentcb265ff630fdf9a6a97d83f9b3fb8ccb554f4b99 (diff)
Q(Quick)WebEngineProfile: Update list of internal schemes
Disallow installing handler for "about" and everything in kStandardURLSchemes of url/url_util.cc. Except for "gopher" which is used in tests. Suppress warning about custom schemes for "gopher" since it's not a custom scheme. Also lowercase the scheme in urlSchemeHandler() and removeUrlSchemeHandler(). Change-Id: I72b06d4fa6433882019405a0d600a593c8971bf1 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r--src/core/profile_adapter.cpp41
-rw-r--r--src/core/profile_adapter.h2
-rw-r--r--src/webengine/api/qquickwebengineprofile.cpp32
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.cpp32
-rw-r--r--tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp41
5 files changed, 84 insertions, 64 deletions
diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp
index 1b946949a..b04fa0d46 100644
--- a/src/core/profile_adapter.cpp
+++ b/src/core/profile_adapter.cpp
@@ -44,6 +44,7 @@
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/download_manager.h"
+#include "api/qwebengineurlscheme.h"
#include "content_client_qt.h"
#include "download_manager_delegate_qt.h"
#include "net/url_request_context_getter_qt.h"
@@ -440,16 +441,50 @@ bool ProfileAdapter::removeCustomUrlSchemeHandler(QWebEngineUrlSchemeHandler *ha
QWebEngineUrlSchemeHandler *ProfileAdapter::takeCustomUrlSchemeHandler(const QByteArray &scheme)
{
- QWebEngineUrlSchemeHandler *handler = m_customUrlSchemeHandlers.take(scheme);
+ QWebEngineUrlSchemeHandler *handler = m_customUrlSchemeHandlers.take(scheme.toLower());
if (handler)
updateCustomUrlSchemeHandlers();
return handler;
}
-void ProfileAdapter::addCustomUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler)
+bool ProfileAdapter::addCustomUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler)
{
- m_customUrlSchemeHandlers.insert(scheme, handler);
+ static const QSet<QByteArray> blacklist{
+ QByteArrayLiteral("about"),
+ QByteArrayLiteral("blob"),
+ QByteArrayLiteral("data"),
+ QByteArrayLiteral("javascript"),
+ QByteArrayLiteral("qrc"),
+ // See also kStandardURLSchemes in url/url_util.cc (through url::IsStandard below)
+ };
+
+ static const QSet<QByteArray> whitelist{
+ QByteArrayLiteral("gopher"),
+ };
+
+ const QByteArray canonicalScheme = scheme.toLower();
+ bool standardSyntax = url::IsStandard(canonicalScheme.data(), url::Component(0, canonicalScheme.size()));
+ bool customScheme = QWebEngineUrlScheme::schemeByName(canonicalScheme) != QWebEngineUrlScheme();
+ bool blacklisted = blacklist.contains(canonicalScheme) || (standardSyntax && !customScheme);
+ bool whitelisted = whitelist.contains(canonicalScheme);
+
+ if (blacklisted && !whitelisted) {
+ qWarning("Cannot install a URL scheme handler overriding internal scheme: %s", scheme.constData());
+ return false;
+ }
+
+ if (m_customUrlSchemeHandlers.value(canonicalScheme, handler) != handler) {
+ qWarning("URL scheme handler already installed for the scheme: %s", scheme.constData());
+ return false;
+ }
+
+ if (!whitelisted && !customScheme)
+ qWarning("Please register the custom scheme '%s' via QWebEngineUrlScheme::registerScheme() "
+ "before installing the custom scheme handler.", scheme.constData());
+
+ m_customUrlSchemeHandlers.insert(canonicalScheme, handler);
updateCustomUrlSchemeHandlers();
+ return true;
}
void ProfileAdapter::clearCustomUrlSchemeHandlers()
diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h
index 7ed5c13f5..e92fb524b 100644
--- a/src/core/profile_adapter.h
+++ b/src/core/profile_adapter.h
@@ -179,7 +179,7 @@ public:
const QHash<QByteArray, QWebEngineUrlSchemeHandler *> &customUrlSchemeHandlers() const;
const QList<QByteArray> customUrlSchemes() const;
void clearCustomUrlSchemeHandlers();
- void addCustomUrlSchemeHandler(const QByteArray &, QWebEngineUrlSchemeHandler *);
+ bool addCustomUrlSchemeHandler(const QByteArray &, QWebEngineUrlSchemeHandler *);
bool removeCustomUrlSchemeHandler(QWebEngineUrlSchemeHandler *);
QWebEngineUrlSchemeHandler *takeCustomUrlSchemeHandler(const QByteArray &);
UserResourceControllerHost *userResourceController();
diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp
index 73577a04c..f77f376aa 100644
--- a/src/webengine/api/qquickwebengineprofile.cpp
+++ b/src/webengine/api/qquickwebengineprofile.cpp
@@ -847,20 +847,7 @@ void QQuickWebEngineProfile::setRequestInterceptor(QWebEngineUrlRequestIntercept
const QWebEngineUrlSchemeHandler *QQuickWebEngineProfile::urlSchemeHandler(const QByteArray &scheme) const
{
const Q_D(QQuickWebEngineProfile);
- if (d->profileAdapter()->customUrlSchemeHandlers().contains(scheme))
- return d->profileAdapter()->customUrlSchemeHandlers().value(scheme);
- return 0;
-}
-
-static bool checkInternalScheme(const QByteArray &scheme)
-{
- static QSet<QByteArray> internalSchemes;
- if (internalSchemes.isEmpty()) {
- internalSchemes << QByteArrayLiteral("qrc") << QByteArrayLiteral("data") << QByteArrayLiteral("blob")
- << QByteArrayLiteral("http") << QByteArrayLiteral("https") << QByteArrayLiteral("ftp")
- << QByteArrayLiteral("javascript");
- }
- return internalSchemes.contains(scheme);
+ return d->profileAdapter()->customUrlSchemeHandlers().value(scheme.toLower());
}
/*!
@@ -873,23 +860,8 @@ void QQuickWebEngineProfile::installUrlSchemeHandler(const QByteArray &scheme, Q
{
Q_D(QQuickWebEngineProfile);
Q_ASSERT(handler);
- QByteArray canonicalScheme = scheme.toLower();
- if (checkInternalScheme(canonicalScheme)) {
- qWarning("Cannot install a URL scheme handler overriding internal scheme: %s", scheme.constData());
- return;
- }
-
- if (d->profileAdapter()->customUrlSchemeHandlers().contains(canonicalScheme)) {
- if (d->profileAdapter()->customUrlSchemeHandlers().value(canonicalScheme) != handler)
- qWarning("URL scheme handler already installed for the scheme: %s", scheme.constData());
+ if (!d->profileAdapter()->addCustomUrlSchemeHandler(scheme, handler))
return;
- }
-
- if (QWebEngineUrlScheme::schemeByName(canonicalScheme) == QWebEngineUrlScheme())
- qWarning("Please register the custom scheme '%s' via QWebEngineUrlScheme::registerScheme() "
- "before installing the custom scheme handler.", scheme.constData());
-
- d->profileAdapter()->addCustomUrlSchemeHandler(canonicalScheme, handler);
connect(handler, SIGNAL(_q_destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)), this, SLOT(destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)));
}
diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp
index 929c2aaa1..c8aafa0e8 100644
--- a/src/webenginewidgets/api/qwebengineprofile.cpp
+++ b/src/webenginewidgets/api/qwebengineprofile.cpp
@@ -688,20 +688,7 @@ QWebEngineSettings *QWebEngineProfile::settings() const
const QWebEngineUrlSchemeHandler *QWebEngineProfile::urlSchemeHandler(const QByteArray &scheme) const
{
const Q_D(QWebEngineProfile);
- if (d->profileAdapter()->customUrlSchemeHandlers().contains(scheme))
- return d->profileAdapter()->customUrlSchemeHandlers().value(scheme);
- return 0;
-}
-
-static bool checkInternalScheme(const QByteArray &scheme)
-{
- static QSet<QByteArray> internalSchemes;
- if (internalSchemes.isEmpty()) {
- internalSchemes << QByteArrayLiteral("qrc") << QByteArrayLiteral("data") << QByteArrayLiteral("blob")
- << QByteArrayLiteral("http") << QByteArrayLiteral("https") << QByteArrayLiteral("ftp")
- << QByteArrayLiteral("javascript");
- }
- return internalSchemes.contains(scheme);
+ return d->profileAdapter()->customUrlSchemeHandlers().value(scheme.toLower());
}
/*!
@@ -716,23 +703,8 @@ void QWebEngineProfile::installUrlSchemeHandler(const QByteArray &scheme, QWebEn
{
Q_D(QWebEngineProfile);
Q_ASSERT(handler);
- QByteArray canonicalScheme = scheme.toLower();
- if (checkInternalScheme(canonicalScheme)) {
- qWarning("Cannot install a URL scheme handler overriding internal scheme: %s", scheme.constData());
- return;
- }
-
- if (d->profileAdapter()->customUrlSchemeHandlers().contains(canonicalScheme)) {
- if (d->profileAdapter()->customUrlSchemeHandlers().value(canonicalScheme) != handler)
- qWarning("URL scheme handler already installed for the scheme: %s", scheme.constData());
+ if (!d->profileAdapter()->addCustomUrlSchemeHandler(scheme, handler))
return;
- }
-
- if (QWebEngineUrlScheme::schemeByName(canonicalScheme) == QWebEngineUrlScheme())
- qWarning("Please register the custom scheme '%s' via QWebEngineUrlScheme::registerScheme() "
- "before installing the custom scheme handler.", scheme.constData());
-
- d->profileAdapter()->addCustomUrlSchemeHandler(canonicalScheme, handler);
connect(handler, SIGNAL(_q_destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)), this, SLOT(destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)));
}
diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
index 2a4e2d533..3fc8fb45a 100644
--- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
+++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
@@ -55,6 +55,7 @@ private Q_SLOTS:
void urlSchemeHandlerFailRequest();
void urlSchemeHandlerFailOnRead();
void urlSchemeHandlerStreaming();
+ void urlSchemeHandlerInstallation();
void customUserAgent();
void httpAcceptLanguage();
void downloadItem();
@@ -466,6 +467,46 @@ void tst_QWebEngineProfile::urlSchemeHandlerStreaming()
QCOMPARE(toPlainTextSync(view.page()), QString::fromLatin1(result));
}
+void tst_QWebEngineProfile::urlSchemeHandlerInstallation()
+{
+ FailingUrlSchemeHandler handler;
+ QWebEngineProfile profile;
+
+ // Builtin schemes that *cannot* be overridden.
+ for (auto scheme : { "about", "blob", "data", "javascript", "qrc", "https", "http", "file",
+ "ftp", "wss", "ws", "filesystem", "FileSystem" }) {
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ QRegularExpression("Cannot install a URL scheme handler overriding internal scheme.*"));
+ profile.installUrlSchemeHandler(scheme, &handler);
+ QCOMPARE(profile.urlSchemeHandler(scheme), nullptr);
+ }
+
+ // Builtin schemes that *can* be overridden.
+ for (auto scheme : { "gopher", "GOPHER" }) {
+ profile.installUrlSchemeHandler(scheme, &handler);
+ QCOMPARE(profile.urlSchemeHandler(scheme), &handler);
+ profile.removeUrlScheme(scheme);
+ }
+
+ // Other schemes should be registered with QWebEngineUrlScheme first, but
+ // handler installation still succeeds to preserve backwards compatibility.
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ QRegularExpression("Please register the custom scheme.*"));
+ profile.installUrlSchemeHandler("tst", &handler);
+ QCOMPARE(profile.urlSchemeHandler("tst"), &handler);
+
+ // Existing handler cannot be overridden.
+ FailingUrlSchemeHandler handler2;
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ QRegularExpression("URL scheme handler already installed.*"));
+ profile.installUrlSchemeHandler("tst", &handler2);
+ QCOMPARE(profile.urlSchemeHandler("tst"), &handler);
+ profile.removeUrlScheme("tst");
+}
+
void tst_QWebEngineProfile::customUserAgent()
{
QString defaultUserAgent = QWebEngineProfile::defaultProfile()->httpUserAgent();