diff options
author | Kirill Burtsev <kirill.burtsev@qt.io> | 2020-11-03 19:36:18 +0100 |
---|---|---|
committer | Kirill Burtsev <kirill.burtsev@qt.io> | 2021-02-08 00:09:29 +0100 |
commit | 0185f4114579c818fd50374ff1e7d8c054c01e24 (patch) | |
tree | 5fcee73fcfd93c2979c2abbea5afc7ee5565a661 /tests | |
parent | a4fce092cbd877560dd75b38a2e495aaa75f60f3 (diff) |
Resolve installed interceptors right before interception point
Ammends a05bb73747. Since request processing is asynchronous, resolve
interceptors right before actual interception point to accommodate
cases where interceptor on profile or page was replaced or uninstalled
before all instantiated InterceptedRequest's are processed.
Effectively, this doesn't send url requests to uninstalled interceptors.
Fixes: QTBUG-86286
Change-Id: Iaf55e5ef99d62b55f7304ee68a0c89a1469fd86f
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp | 127 | ||||
-rw-r--r-- | tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp | 6 |
2 files changed, 130 insertions, 3 deletions
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp index bf4acec14..4750c8d0e 100644 --- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp @@ -76,6 +76,9 @@ private Q_SLOTS: void initiator(); void jsServiceWorker_data(); void jsServiceWorker(); + void replaceInterceptor_data(); + void replaceInterceptor(); + void replaceOnIntercept(); }; tst_QWebEngineUrlRequestInterceptor::tst_QWebEngineUrlRequestInterceptor() @@ -128,6 +131,7 @@ public: QUrl redirectUrl; QMap<QUrl, QSet<QUrl>> requestInitiatorUrls; QMap<QByteArray, QByteArray> headers; + std::function<bool (QWebEngineUrlRequestInfo &)> onIntercept; void interceptRequest(QWebEngineUrlRequestInfo &info) override { @@ -139,6 +143,9 @@ public: if (info.requestUrl().scheme() == QLatin1String("blob")) return; + if (onIntercept && !onIntercept(info)) + return; + bool block = info.requestMethod() != QByteArrayLiteral("GET"); bool redirect = shouldRedirect && info.requestUrl() != redirectUrl; @@ -800,5 +807,125 @@ void tst_QWebEngineUrlRequestInterceptor::jsServiceWorker() QVERIFY(server.stop()); } +void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor_data() +{ + QTest::addColumn<bool>("firstInterceptIsInPage"); + QTest::addColumn<bool>("keepInterceptionPoint"); + QTest::newRow("page") << true << true; + QTest::newRow("page-profile") << true << false; + QTest::newRow("profile") << false << true; + QTest::newRow("profile-page") << false << false; +} + +void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor() +{ + QFETCH(bool, firstInterceptIsInPage); + QFETCH(bool, keepInterceptionPoint); + + HttpServer server; + server.setResourceDirs({ ":/resources" }); + QVERIFY(server.start()); + + QWebEngineProfile profile; + profile.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); + QWebEnginePage page(&profile); + QSignalSpy spy(&page, SIGNAL(loadFinished(bool))); + bool fetchFinished = false; + + auto setInterceptor = [&] (QWebEngineUrlRequestInterceptor *interceptor, bool interceptInPage) { + interceptInPage ? page.setUrlRequestInterceptor(interceptor) : profile.setUrlRequestInterceptor(interceptor); + }; + + std::vector<TestRequestInterceptor> interceptors(3); + std::vector<int> requestsOnReplace; + setInterceptor(&interceptors.front(), firstInterceptIsInPage); + + auto sc = connect(&page, &QWebEnginePage::loadFinished, [&] () { + auto currentInterceptorIndex = requestsOnReplace.size(); + requestsOnReplace.push_back(interceptors[currentInterceptorIndex].requestInfos.size()); + + bool isFirstReinstall = currentInterceptorIndex == 0; + bool interceptInPage = keepInterceptionPoint ? firstInterceptIsInPage : (isFirstReinstall ^ firstInterceptIsInPage); + setInterceptor(&interceptors[++currentInterceptorIndex], interceptInPage); + if (!keepInterceptionPoint) + setInterceptor(nullptr, !interceptInPage); + + if (isFirstReinstall) { + page.triggerAction(QWebEnginePage::Reload); + } else { + page.runJavaScript("fetch('http://nonexistent.invalid').catch(() => {})", [&, interceptInPage] (const QVariant &) { + requestsOnReplace.push_back(interceptors.back().requestInfos.size()); + setInterceptor(nullptr, interceptInPage); + fetchFinished = true; + }); + } + }); + + page.setUrl(server.url("/favicon.html")); + QTRY_COMPARE(spy.count(), 2); + QTRY_VERIFY(fetchFinished); + + QString s; QDebug d(&s); + for (auto i = 0u; i < interceptors.size(); ++i) { + auto &&interceptor = interceptors[i]; + auto &&requests = interceptor.requestInfos; + d << "\nInterceptor [" << i << "] with" << requestsOnReplace[i] << "requests on replace and" << requests.size() << "in the end:"; + for (int j = 0; j < requests.size(); ++j) { + auto &&r = requests[j]; + d << "\n\t" << j << "| url:" << r.requestUrl << "firstPartyUrl:" << r.firstPartyUrl; + } + QVERIFY2(!requests.isEmpty(), qPrintable(s)); + QVERIFY2(requests.size() == requestsOnReplace[i], qPrintable(s)); + } +} + +void tst_QWebEngineUrlRequestInterceptor::replaceOnIntercept() +{ + HttpServer server; + server.setResourceDirs({ ":/resources" }); + QVERIFY(server.start()); + + QWebEngineProfile profile; + profile.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); + QWebEnginePage page(&profile); + QSignalSpy spy(&page, SIGNAL(loadFinished(bool))); + + struct Interceptor : QWebEngineUrlRequestInterceptor { + Interceptor(const std::function<void ()> &a) : action(a) { } + void interceptRequest(QWebEngineUrlRequestInfo &) override { action(); } + std::function<void ()> action; + int interceptRequestReceived = 0; + }; + + TestRequestInterceptor profileInterceptor, pageInterceptor1, pageInterceptor2; + page.setUrlRequestInterceptor(&pageInterceptor1); + profile.setUrlRequestInterceptor(&profileInterceptor); + profileInterceptor.onIntercept = [&] (QWebEngineUrlRequestInfo &) { + page.setUrlRequestInterceptor(&pageInterceptor2); + return true; + }; + + page.setUrl(server.url("/favicon.html")); + QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(profileInterceptor.requestInfos.size(), 2); + + // if interceptor for page was replaced on intercept call in profile then, since request first + // comes to profile, forward to page's interceptor should land to second one + QCOMPARE(pageInterceptor1.requestInfos.size(), 0); + QCOMPARE(profileInterceptor.requestInfos.size(), pageInterceptor2.requestInfos.size()); + + page.setUrlRequestInterceptor(&pageInterceptor1); + bool fetchFinished = false; + page.runJavaScript("fetch('http://nonexistent.invalid').catch(() => {})", [&] (const QVariant &) { + page.setUrlRequestInterceptor(&pageInterceptor2); + fetchFinished = true; + }); + + QTRY_VERIFY(fetchFinished); + QCOMPARE(profileInterceptor.requestInfos.size(), 3); + QCOMPARE(pageInterceptor1.requestInfos.size(), 0); + QCOMPARE(profileInterceptor.requestInfos.size(), pageInterceptor2.requestInfos.size()); +} + QTEST_MAIN(tst_QWebEngineUrlRequestInterceptor) #include "tst_qwebengineurlrequestinterceptor.moc" diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index f4c0484eb..1b0f95064 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -514,7 +514,7 @@ void tst_QWebEngineProfile::urlSchemeHandlerStreaming() view.setPage(new QWebEnginePage(&profile, &view)); view.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); view.load(QUrl(QStringLiteral("stream://whatever"))); - QVERIFY(loadFinishedSpy.wait()); + QTRY_COMPARE_WITH_TIMEOUT(loadFinishedSpy.count(), 1, 30000); QByteArray result; result.append(1000, 'c'); QCOMPARE(toPlainTextSync(view.page()), QString::fromLatin1(result)); @@ -575,7 +575,7 @@ void tst_QWebEngineProfile::urlSchemeHandlerRequestHeaders() QWebEnginePage page(&profile); QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool))); page.load(QUrl(QStringLiteral("myscheme://whatever"))); - QVERIFY(loadFinishedSpy.wait()); + QTRY_COMPARE_WITH_TIMEOUT(loadFinishedSpy.count(), 1, 30000); } void tst_QWebEngineProfile::urlSchemeHandlerInstallation() @@ -707,7 +707,7 @@ void tst_QWebEngineProfile::urlSchemeHandlerXhrStatus() profile.installUrlSchemeHandler("aviancarrier", &handler); page.setWebChannel(&channel); page.load(QUrl("aviancarrier:/")); - QTRY_VERIFY(host.isReady()); + QTRY_VERIFY_WITH_TIMEOUT(host.isReady(), 30000); host.load(QUrl("aviancarrier:/ok")); host.load(QUrl("aviancarrier:/redirect")); host.load(QUrl("aviancarrier:/fail")); |