From c63afe36dbb20f515c8ddcb7565a317e56de6791 Mon Sep 17 00:00:00 2001 From: Yigit Akcay Date: Thu, 2 Feb 2023 15:21:45 +0100 Subject: Custom URL Schemes usable with HTML5 Fetch Api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change adds the QWebEngineUrlScheme::FetchApiAllowed flag and test cases to test its effect. When FetchApiAllowed flag is set a custom url scheme can be used by the HTML5 fetch api. Fixes: QTBUG-88830 Change-Id: I953dd0504bf508fd8082fae5db08b7b9fc47ea1f Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Michael BrĂ¼ning --- tests/auto/core/origins/CMakeLists.txt | 1 + tests/auto/core/origins/resources/fetchApi.html | 14 +++ tests/auto/core/origins/tst_origins.cpp | 129 +++++++++++++++++++++++- 3 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 tests/auto/core/origins/resources/fetchApi.html (limited to 'tests') diff --git a/tests/auto/core/origins/CMakeLists.txt b/tests/auto/core/origins/CMakeLists.txt index 10a185f0a..4238bc6e3 100644 --- a/tests/auto/core/origins/CMakeLists.txt +++ b/tests/auto/core/origins/CMakeLists.txt @@ -33,6 +33,7 @@ set(tst_origins_resource_files "resources/websocket.html" "resources/websocket2.html" "resources/red.png" + "resources/fetchApi.html" ) qt_internal_add_resource(tst_origins "tst_origins" diff --git a/tests/auto/core/origins/resources/fetchApi.html b/tests/auto/core/origins/resources/fetchApi.html new file mode 100644 index 000000000..7b54416fd --- /dev/null +++ b/tests/auto/core/origins/resources/fetchApi.html @@ -0,0 +1,14 @@ + + + + + + diff --git a/tests/auto/core/origins/tst_origins.cpp b/tests/auto/core/origins/tst_origins.cpp index 1d716c418..98f0f1735 100644 --- a/tests/auto/core/origins/tst_origins.cpp +++ b/tests/auto/core/origins/tst_origins.cpp @@ -150,7 +150,15 @@ void registerSchemes() scheme.setFlags(QWebEngineUrlScheme::LocalScheme | QWebEngineUrlScheme::CorsEnabled); QWebEngineUrlScheme::registerScheme(scheme); } - + { + QWebEngineUrlScheme scheme("fetchapi-allowed"); + scheme.setFlags(QWebEngineUrlScheme::CorsEnabled | QWebEngineUrlScheme::FetchApiAllowed); + QWebEngineUrlScheme::registerScheme(scheme); + } + { + QWebEngineUrlScheme scheme("fetchapi-not-allowed"); + QWebEngineUrlScheme::registerScheme(scheme); + } } Q_CONSTRUCTOR_FUNCTION(registerSchemes) @@ -323,6 +331,9 @@ private Q_SLOTS: void redirectInterceptorSecure(); void redirectInterceptorFile(); void redirectInterceptorHttp(); + void fetchApiCustomUrl_data(); + void fetchApiCustomUrl(); + void fetchApiHttpUrl(); private: bool verifyLoad(const QUrl &url) @@ -1511,5 +1522,121 @@ void tst_Origins::localMediaBlock() } +class FetchApiHandler : public QWebEngineUrlSchemeHandler +{ + Q_OBJECT +public: + FetchApiHandler(QByteArray schemeName, QObject *parent = nullptr) + : QWebEngineUrlSchemeHandler(parent), m_schemeName(schemeName) + { + } + + void requestStarted(QWebEngineUrlRequestJob *job) override + { + QCOMPARE(job->requestUrl(), QUrl(m_schemeName + ":about")); + fetchWasAllowed = true; + } + + bool fetchWasAllowed = false; + +private: + QByteArray m_schemeName; +}; + +class FetchApiPage : public QWebEnginePage +{ + Q_OBJECT + +signals: + void jsCalled(); + +public: + FetchApiPage(QWebEngineProfile *profile, QObject *parent = nullptr) + : QWebEnginePage(profile, parent) + { + } + +protected: + void javaScriptConsoleMessage(QWebEnginePage::JavaScriptConsoleMessageLevel level, + const QString &message, int lineNumber, + const QString &sourceID) override + { + qCritical() << "js:" << message; + emit jsCalled(); + } +}; + +void tst_Origins::fetchApiCustomUrl_data() +{ + QTest::addColumn("url"); + QTest::addColumn("fetchApiScheme"); + QTest::addColumn("expectedFetchWasAllowed"); + + QTest::newRow("custom url with fetch allowed flag") + << QUrl("qrc:///resources/fetchApi.html?printRes=false&url=fetchapi-allowed:about") + << QBAL("fetchapi-allowed") << true; + QTest::newRow("custom url without fetch allowed flag") + << QUrl("qrc:///resources/fetchApi.html?printRes=false&url=fetchapi-not-allowed:about") + << QBAL("fetchapi-not-allowed") << false; +} + +void tst_Origins::fetchApiCustomUrl() +{ + QFETCH(QUrl, url); + QFETCH(QByteArray, fetchApiScheme); + QFETCH(bool, expectedFetchWasAllowed); + + QWebEngineProfile profile; + FetchApiHandler handler(fetchApiScheme); + + profile.installUrlSchemeHandler(fetchApiScheme, &handler); + + FetchApiPage page(&profile); + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + QSignalSpy jsSpy(&page, SIGNAL(jsCalled())); + + if (fetchApiScheme == "fetchapi-not-allowed") { + QTest::ignoreMessage(QtCriticalMsg, QRegularExpression("Failed to fetch")); + QTest::ignoreMessage( + QtCriticalMsg, + QRegularExpression("Fetch API cannot load fetchapi-not-allowed:about.")); + } + + page.load(url); + QVERIFY(loadSpy.wait()); + QCOMPARE(handler.fetchWasAllowed, expectedFetchWasAllowed); + + if (fetchApiScheme == "fetchapi-not-allowed") { + QVERIFY(jsSpy.wait()); + } +} + +void tst_Origins::fetchApiHttpUrl() +{ + HttpServer httpServer; + QObject::connect(&httpServer, &HttpServer::newRequest, this, [](HttpReqRep *rr) { + rr->setResponseBody(QBAL("Fetch Was Allowed")); + rr->setResponseHeader(QBAL("Access-Control-Allow-Origin"), QBAL("*")); + rr->sendResponse(); + }); + QVERIFY(httpServer.start()); + + QWebEngineProfile profile; + FetchApiPage page(&profile); + + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + QSignalSpy jsSpy(&page, SIGNAL(jsCalled())); + + QTest::ignoreMessage(QtCriticalMsg, QRegularExpression("Fetch Was Allowed")); + + const QByteArray fullUrl = QByteArray("qrc:///resources/fetchApi.html?printRes=true&url=") + + httpServer.url("/somepage.html").toEncoded(); + page.load(QUrl(fullUrl)); + + QVERIFY(loadSpy.wait()); + QVERIFY(jsSpy.wait()); + QVERIFY(httpServer.stop()); +} + QTEST_MAIN(tst_Origins) #include "tst_origins.moc" -- cgit v1.2.1