diff options
author | Yigit Akcay <yigit.akcay@qt.io> | 2023-02-15 20:43:25 +0100 |
---|---|---|
committer | Yigit Akcay <yigit.akcay@qt.io> | 2023-03-10 17:13:32 +0100 |
commit | 5e257fb57a211f95556ec387fe6f262a60cbb6fe (patch) | |
tree | 330abbb7f84f8664fbd44b80d573265da4cc2bcb /tests | |
parent | 28a2cfe4116f7218b33df811b79536c0593ddda6 (diff) | |
download | qtwebengine-5e257fb57a211f95556ec387fe6f262a60cbb6fe.tar.gz |
QWebEngineUrlResponseInterceptor: Implement new URL response interceptor
This patch adds the QWebEngineUrlResponseInterceptor abstract class,
which, when implemented, allows a user to intercept response headers and
modify them in any way they like.
A response interceptor can be set via
QWebEngineProfile::setUrlResponseInterceptor(),
QQuickWebEngineProfile::setUrlResponseInterceptor() or
QWebEnginePage::setUrlResponseInterceptor().
Also, the QWebEngineUrlResponseInfo class is implemented, which contains
the request and response data to be used with the response interceptor.
If a response interceptor is set in the profile and page, the one in the
profile takes precedence.
Fixes: QTBUG-61071
Change-Id: I484d14373ff597b1d531541c066f0102bae28c72
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'tests')
3 files changed, 153 insertions, 0 deletions
diff --git a/tests/auto/core/CMakeLists.txt b/tests/auto/core/CMakeLists.txt index 6ba6ffd92..9d131da56 100644 --- a/tests/auto/core/CMakeLists.txt +++ b/tests/auto/core/CMakeLists.txt @@ -5,6 +5,7 @@ add_subdirectory(qwebenginecookiestore) add_subdirectory(qwebengineloadinginfo) add_subdirectory(qwebenginesettings) add_subdirectory(qwebengineurlrequestinterceptor) +add_subdirectory(qwebengineurlresponseinterceptor) add_subdirectory(qwebengineurlrequestjob) add_subdirectory(origins) add_subdirectory(devtools) diff --git a/tests/auto/core/qwebengineurlresponseinterceptor/CMakeLists.txt b/tests/auto/core/qwebengineurlresponseinterceptor/CMakeLists.txt new file mode 100644 index 000000000..08a5b9699 --- /dev/null +++ b/tests/auto/core/qwebengineurlresponseinterceptor/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +include(../../httpserver/httpserver.cmake) + +qt_internal_add_test(tst_qwebengineurlresponseinterceptor + SOURCES + tst_qwebengineurlresponseinterceptor.cpp + LIBRARIES + Qt::WebEngineCore + Test::HttpServer +) diff --git a/tests/auto/core/qwebengineurlresponseinterceptor/tst_qwebengineurlresponseinterceptor.cpp b/tests/auto/core/qwebengineurlresponseinterceptor/tst_qwebengineurlresponseinterceptor.cpp new file mode 100644 index 000000000..4d08853ef --- /dev/null +++ b/tests/auto/core/qwebengineurlresponseinterceptor/tst_qwebengineurlresponseinterceptor.cpp @@ -0,0 +1,140 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include <QtTest/QtTest> +#include <QtWebEngineCore/QWebEngineUrlResponseInterceptor> +#include <QtWebEngineCore/QWebEngineProfile> +#include <QtWebEngineCore/QWebEnginePage> +#include <QtWebEngineCore/QWebEngineLoadingInfo> +#include <QtWebEngineCore/QWebEngineUrlResponseInfo> + +#include <httpserver.h> +#include <httpreqrep.h> + +class tst_QWebEngineUrlResponseInterceptor : public QObject +{ + Q_OBJECT + +public: + tst_QWebEngineUrlResponseInterceptor() { } + ~tst_QWebEngineUrlResponseInterceptor() { } + +public Q_SLOTS: + void init() { } + void cleanup() { } + +private Q_SLOTS: + void initTestCase() { } + void cleanupTestCase() { } + void interceptRequest_data(); + void interceptRequest(); +}; + +Q_LOGGING_CATEGORY(lc, "qt.webengine.tests") + +class Interceptor : public QWebEngineUrlResponseInterceptor +{ + Q_OBJECT + + QUrl m_receivedRequestUrl; + QHash<QByteArray, QByteArray> m_receivedRequestHeaders; + +public: + void interceptResponseHeaders(QWebEngineUrlResponseInfo &info) override + { + m_receivedRequestUrl = info.requestUrl(); + m_receivedRequestHeaders = info.requestHeaders(); + QHash<QByteArray, QByteArray> responseHeaders = info.responseHeaders(); + + responseHeaders.insert(QByteArrayLiteral("ADDEDHEADER"), QByteArrayLiteral("ADDEDVALUE")); + *(responseHeaders.find(QByteArrayLiteral("content-length"))) = QByteArrayLiteral("57"); + + info.setResponseHeaders(responseHeaders); + } + + void getReceivedRequest(QUrl *receivedRequestUrl, + QHash<QByteArray, QByteArray> *receivedRequestHeaders) + { + *receivedRequestUrl = m_receivedRequestUrl; + *receivedRequestHeaders = m_receivedRequestHeaders; + } +}; + +void tst_QWebEngineUrlResponseInterceptor::interceptRequest_data() +{ + QTest::addColumn<bool>("withProfileInterceptor"); + QTest::newRow("with profile interceptor") << true; + QTest::newRow("with page interceptor") << false; +} + +void tst_QWebEngineUrlResponseInterceptor::interceptRequest() +{ + QFETCH(bool, withProfileInterceptor); + + HttpServer httpServer; + QObject::connect(&httpServer, &HttpServer::newRequest, this, [&](HttpReqRep *rr) { + if (rr->requestPath() == QByteArrayLiteral("/okay.html")) { + rr->setResponseBody(QByteArrayLiteral( + "<html><script>console.log('hello world js!');</script></html>")); + rr->sendResponse(); + } + }); + QVERIFY(httpServer.start()); + + const QUrl requestUrl = httpServer.url(QStringLiteral("/okay.html")); + + Interceptor interceptor; + QWebEngineProfile profile; + QWebEnginePage page(&profile); + if (withProfileInterceptor) + profile.setUrlResponseInterceptor(&interceptor); + else + page.setUrlResponseInterceptor(&interceptor); + + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + + bool headersWereChanged = false; + QObject::connect( + &page, &QWebEnginePage::loadingChanged, this, [&](QWebEngineLoadingInfo loadingInfo) { + const QHash<QByteArray, QByteArray> responseHeaders = loadingInfo.responseHeaders(); + bool contentLengthSizeChanged = false; + bool additionalHeaderAdded = false; + for (auto it = responseHeaders.constBegin(); it != responseHeaders.constEnd(); + ++it) { + if (it.key() == QByteArrayLiteral("content-length") + && it.value() == QByteArrayLiteral("57")) + contentLengthSizeChanged = true; + if (it.key() == QByteArrayLiteral("ADDEDHEADER") + && it.value() == QByteArrayLiteral("ADDEDVALUE")) + additionalHeaderAdded = true; + } + + if (contentLengthSizeChanged && additionalHeaderAdded) + headersWereChanged = true; + }); + + page.load(requestUrl); + + QVERIFY(loadSpy.wait()); + + QUrl receivedRequestUrl; + QHash<QByteArray, QByteArray> receivedRequestHeaders; + interceptor.getReceivedRequest(&receivedRequestUrl, &receivedRequestHeaders); + + bool receivedRequestHeadersContainsQtWebEngine = false; + for (auto it = receivedRequestHeaders.cbegin(); it != receivedRequestHeaders.cend(); ++it) { + if (it.value().contains("QtWebEngine/")) { + receivedRequestHeadersContainsQtWebEngine = true; + break; + } + } + + QVERIFY(headersWereChanged); + QCOMPARE_EQ(receivedRequestUrl, requestUrl); + QVERIFY(receivedRequestHeaders.size() != 0); + QVERIFY(receivedRequestHeadersContainsQtWebEngine); + QVERIFY(httpServer.stop()); +} + +QTEST_MAIN(tst_QWebEngineUrlResponseInterceptor) +#include "tst_qwebengineurlresponseinterceptor.moc" |